Skip to content

Commit 2c5559a

Browse files
authored
Merge pull request #208 from DiplomacyTeam/dev
v1.2.5 release
2 parents a86689a + 9ac4a5c commit 2c5559a

30 files changed

Lines changed: 441 additions & 229 deletions

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright © 2020-2022 Diplomacy Team
3+
Copyright © 2020-2023 Diplomacy Team
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

build/common.props

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
<!--Module Version-->
44
<PropertyGroup>
5-
<Version>1.2.4</Version>
5+
<Version>1.2.5</Version>
66
<GameVersion>1.0.0</GameVersion>
77
</PropertyGroup>
88

99
<!-- Versions of Major Dependencies (For Package References & SubModule.xml Substitution) -->
1010
<PropertyGroup>
1111
<!--BuildResources Version-->
12-
<BuildResourcesVersion>1.0.1.89</BuildResourcesVersion>
12+
<BuildResourcesVersion>1.0.1.92</BuildResourcesVersion>
1313
<!--Harmony Version-->
1414
<HarmonyVersion>2.2.2</HarmonyVersion>
1515
<!--ButterLib Version-->
@@ -19,13 +19,13 @@
1919
<!--UIExtenderEx Version-->
2020
<UIExtenderExVersion>2.6.0</UIExtenderExVersion>
2121
<!--BUTRShared Version-->
22-
<BUTRSharedVersion>3.0.0.130</BUTRSharedVersion>
22+
<BUTRSharedVersion>3.0.0.134</BUTRSharedVersion>
2323
<!--BUTRModuleManager Version-->
2424
<BUTRModuleManagerVersion>5.0.198</BUTRModuleManagerVersion>
2525
<!--ModuleLoader Version-->
2626
<BUTRModuleLoaderVersion>1.0.1.44</BUTRModuleLoaderVersion>
2727
<!--Harmony Extensions Version-->
28-
<HarmonyExtensionsVersion>3.2.0.73</HarmonyExtensionsVersion>
28+
<HarmonyExtensionsVersion>3.2.0.75</HarmonyExtensionsVersion>
2929
</PropertyGroup>
3030
<PropertyGroup>
3131
<TargetFramework>net472</TargetFramework>

changelog.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
11
---------------------------------------------------------------------------------------------------
2+
Version: 1.2.5
3+
Game Versions: v1.0.0,v1.0.1,v1.0.2,v1.0.3,v1.1.0
4+
* Fixed a crash on making peace when War Exhaustion is disabled.
5+
* Fixed a crash after loading a save when attempting to fix any faulty factions (again).
6+
* Fixed a bug due to which kingdoms were sometimes not destroyed when they should have been.
7+
* Fixed a bug due to which War Exhaustion breakdowns were sometimes showing wrong values (unaffected by rates).
8+
* Making peace should now use all of the mod's enabled mechanics, no matter what interface option was used for it.
9+
* Adjusted the calculation of war reparations to make it even more lenient.
10+
* Adjusted the way war reparations are gathered by the paying kingdom to make it less stressful.
11+
* Adjusted the way war reparations are distributed among the winning faction.
12+
* Adjusted the calculation and default values for some of the War Exhaustion entries.
13+
* Adjusted War Exhaustion rates calculation.
14+
* Adjusted descriptions of some settings for clarity.
15+
* Added an option to disable the elimination of fiefless kingdoms.
16+
* Added an option to disable fief repatriation after losing a war.
17+
---------------------------------------------------------------------------------------------------
218
Version: 1.2.4
319
Game Versions: v1.0.0,v1.0.1,v1.0.2,v1.0.3,v1.1.0
420
* Fixed a crash after loading a save when attempting to fix any faulty factions.

src/Bannerlord.Diplomacy/Actions/GiveGoldToClanAction.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using Helpers;
22

3+
using System.Linq;
4+
35
using TaleWorlds.CampaignSystem;
46
using TaleWorlds.CampaignSystem.Actions;
57
using TaleWorlds.Library;
@@ -22,15 +24,15 @@ private static void ApplyInternal(Hero? giverHero, Clan? clan, int goldAmount)
2224

2325
private static void GiveGoldToClan(int gold, Clan clan)
2426
{
25-
foreach ((var recipientHero, var amount) in MBMath.DistributeShares(gold, clan.Lords, CalculateShare))
27+
foreach ((var recipientHero, var amount) in MBMath.DistributeShares(gold, clan.Lords.Where(l => l.IsAlive && l.IsCommander), CalculateShare))
2628
{
2729
GiveGoldAction.ApplyBetweenCharacters(null, recipientHero, amount);
2830
}
2931
}
3032

3133
private static int CalculateShare(Hero member)
3234
{
33-
return HeroHelper.CalculateTotalStrength(member) + (member == member.Clan?.Leader ? 100 : 10);
35+
return HeroHelper.CalculateTotalStrength(member) + (member == member.Clan?.Leader ? 500 : 10);
3436
}
3537

3638
public static void ApplyFromHeroToClan(Hero giverHero, Clan clan, int amount)
Lines changed: 106 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,121 @@
1-
using TaleWorlds.CampaignSystem;
1+
using System;
2+
using System.Linq;
3+
4+
using TaleWorlds.CampaignSystem;
25
using TaleWorlds.CampaignSystem.Actions;
6+
using TaleWorlds.CampaignSystem.Settlements;
37
using TaleWorlds.Library;
48

59
namespace Diplomacy.Actions
610
{
711
public static class GiveGoldToKingdomAction
812
{
13+
private const int MinRequiredBudgetWalletSize = 2000000;
14+
private const int MaxRequiredClanGold = 50000;
15+
private const int MinRequiredShortfall = 100000;
16+
private const int GoldPerProsperity = 1000;
17+
private const int MaxRevenuePerMercenaryTier = 10000;
18+
919
private static void ApplyInternal(Kingdom? giverKingdom, Kingdom? receiverKingdom, int amount, WalletType giverWallet, WalletType receiverWallet)
1020
{
1121
if (amount == 0)
1222
return;
1323

1424
if (giverKingdom != null)
1525
{
16-
switch (giverWallet)
17-
{
18-
case WalletType.TributeWallet:
19-
giverKingdom.TributeWallet -= amount;
20-
break;
21-
case WalletType.BudgetWallet:
22-
//Leaders should benefit from those payments too
23-
var leaderAmount = amount < 0 ? amount / 3 : 0;
24-
if (leaderAmount > 0) GiveGoldAction.ApplyBetweenCharacters(null, giverKingdom.Leader, leaderAmount);
25-
giverKingdom.KingdomBudgetWallet -= (amount - leaderAmount);
26-
break;
27-
default:
28-
break;
29-
}
26+
GetMoneyFromGiver(giverKingdom, amount, giverWallet);
3027
}
3128
if (receiverKingdom != null)
3229
{
33-
switch (receiverWallet)
34-
{
35-
case WalletType.TributeWallet:
36-
receiverKingdom.TributeWallet += amount;
37-
break;
38-
case WalletType.BudgetWallet:
39-
//Leaders should benefit from those payments too
40-
var leaderAmount = amount > 0 ? amount / 3 : 0;
41-
if (leaderAmount > 0) GiveGoldAction.ApplyBetweenCharacters(null, receiverKingdom.Leader, leaderAmount);
42-
receiverKingdom.KingdomBudgetWallet += (amount - leaderAmount);
43-
break;
44-
default:
45-
break;
46-
}
30+
GiveMoneyToReceiver(receiverKingdom, amount, receiverWallet);
31+
}
32+
}
33+
34+
private static void GetMoneyFromGiver(Kingdom giverKingdom, int amount, WalletType giverWallet)
35+
{
36+
switch (giverWallet)
37+
{
38+
case WalletType.TributeWallet:
39+
giverKingdom.TributeWallet -= amount;
40+
return;
41+
case WalletType.BudgetWallet:
42+
giverKingdom.KingdomBudgetWallet -= amount;
43+
return;
44+
case WalletType.ReparationsWallet:
45+
//Cover from the kingdom budget
46+
var availableBudgetAmount = Math.Max(giverKingdom.KingdomBudgetWallet - MinRequiredBudgetWalletSize, 0);
47+
if (availableBudgetAmount > 0)
48+
{
49+
var budgetCoveredAmount = Math.Min(availableBudgetAmount, amount);
50+
giverKingdom.KingdomBudgetWallet -= budgetCoveredAmount;
51+
amount -= budgetCoveredAmount;
52+
}
53+
if (amount <= 0)
54+
return;
55+
56+
//Cover from the kingdom prosperity
57+
var tolerableAmount = giverKingdom.Clans.Where(c => !c.IsUnderMercenaryService && !c.IsEliminated).Sum(c => c.Gold - Math.Min(c.Gold / 4, MaxRequiredClanGold));
58+
if (tolerableAmount < amount)
59+
{
60+
var amountToCover = amount - tolerableAmount;
61+
if (amountToCover >= MinRequiredShortfall)
62+
{
63+
foreach ((var settlement, var amountToCoverBySettlement) in MBMath.DistributeShares(amountToCover, giverKingdom.Settlements.Where(s => s.IsCastle || s.IsTown), CalculateSettlementShare))
64+
{
65+
settlement.Prosperity -= amountToCoverBySettlement / GoldPerProsperity;
66+
}
67+
amount = tolerableAmount;
68+
}
69+
}
70+
71+
giverKingdom.TributeWallet -= amount;
72+
return;
73+
default:
74+
return;
75+
}
76+
}
77+
78+
private static void GiveMoneyToReceiver(Kingdom receiverKingdom, int amount, WalletType receiverWallet)
79+
{
80+
switch (receiverWallet)
81+
{
82+
case WalletType.TributeWallet:
83+
receiverKingdom.TributeWallet += amount;
84+
return;
85+
case WalletType.BudgetWallet:
86+
receiverKingdom.KingdomBudgetWallet += amount;
87+
return;
88+
case WalletType.ReparationsWallet:
89+
//Leaders should benefit from those payments too
90+
var leaderAmount = amount / 3;
91+
if (leaderAmount > 0) GiveGoldAction.ApplyBetweenCharacters(null, receiverKingdom.Leader, leaderAmount);
92+
//Mercenaries
93+
var mercenaryAmount = amount / 6;
94+
int mercenaryAmountFact = 0;
95+
foreach ((var recipientMercClan, var amountForMercClan) in MBMath.DistributeShares(mercenaryAmount, receiverKingdom.Clans.Where(c => c.IsUnderMercenaryService && !c.IsEliminated), CalculateMercenaryShare))
96+
{
97+
var amountForMercClanFact = Math.Min(amountForMercClan, recipientMercClan.Tier * MaxRevenuePerMercenaryTier);
98+
GiveGoldAction.ApplyBetweenCharacters(null, recipientMercClan.Leader, amountForMercClanFact);
99+
mercenaryAmountFact += amountForMercClanFact;
100+
}
101+
//Reassess
102+
amount = amount - leaderAmount - mercenaryAmountFact;
103+
//Player
104+
var playerClan = Clan.PlayerClan;
105+
if (playerClan.Kingdom == receiverKingdom && !playerClan.IsUnderMercenaryService && playerClan.Leader != receiverKingdom.Leader)
106+
{
107+
var playerAmount = MBMath.DistributeShares(amount, receiverKingdom.Clans.Where(c => !c.IsUnderMercenaryService && !c.IsEliminated), CalculateShare).FirstOrDefault(x => x.Item1 == playerClan);
108+
if (playerAmount != default && playerAmount.Item2 > 0)
109+
{
110+
GiveGoldAction.ApplyBetweenCharacters(null, playerClan.Leader, playerAmount.Item2);
111+
amount -= playerAmount.Item2;
112+
}
113+
}
114+
115+
receiverKingdom.KingdomBudgetWallet += amount;
116+
return;
117+
default:
118+
return;
47119
}
48120
}
49121

@@ -61,16 +133,15 @@ private static void ApplyInternal(Hero? giverHero, Kingdom? kingdom, int goldAmo
61133

62134
private static void GiveGoldToKingdom(int gold, Kingdom kingdom)
63135
{
64-
foreach ((var recipientClan, var amount) in MBMath.DistributeShares(gold, kingdom.Clans, CalculateShare))
136+
foreach ((var recipientClan, var amount) in MBMath.DistributeShares(gold, kingdom.Clans.Where(c => !c.IsUnderMercenaryService && !c.IsEliminated), CalculateShare))
65137
{
66138
GiveGoldToClanAction.ApplyToClan(recipientClan, amount);
67139
}
68140
}
69141

70-
private static int CalculateShare(Clan clan)
71-
{
72-
return (int) clan.TotalStrength + (clan == clan.Kingdom?.Leader?.Clan ? 1000 : 10);
73-
}
142+
private static int CalculateShare(Clan clan) => Math.Max(clan.Tier / 2, 1) + (clan == clan.Kingdom?.Leader?.Clan ? 1 : 0);
143+
private static int CalculateMercenaryShare(Clan clan) => Math.Max((int) clan.Influence, 1);
144+
private static int CalculateSettlementShare(Settlement settlement) => Math.Max((int) settlement.Prosperity, 1);
74145

75146
public static void ApplyFromHeroToKingdom(Hero giverHero, Kingdom kingdom, int amount)
76147
{
@@ -88,6 +159,7 @@ public enum WalletType : byte
88159
MercenaryWallet = 1,
89160
TributeWallet = 2,
90161
BudgetWallet = 3,
162+
ReparationsWallet = 4
91163
}
92164
}
93165
}

src/Bannerlord.Diplomacy/Actions/DestroyKingdomSoftlyAction.cs renamed to src/Bannerlord.Diplomacy/Actions/SoftlyDestroyKingdomAction.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace Diplomacy.Actions
77
{
8-
public static class DestroyKingdomSoftlyAction
8+
public static class SoftlyDestroyKingdomAction
99
{
1010
public static void Apply(Kingdom kingdomToDestroy)
1111
{

src/Bannerlord.Diplomacy/CampaignBehaviors/CivilWarBehavior.cs

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ private void ResolveCivilWar(IFaction factionMakingPeace, IFaction otherFaction)
9292
private void ResolveCivilWar(IFaction factionMakingPeace, IFaction otherFaction, MakePeaceAction.MakePeaceDetail makePeaceDetail)
9393
#endif
9494
{
95+
//Need to check if this runs before or after WarExhaustionBehavior
9596
if (factionMakingPeace is Kingdom kingdomMakingPeace && otherFaction is Kingdom otherKingdom)
9697
{
9798
var kingdomMakingPeaceIsRebel = kingdomMakingPeace.IsRebelKingdomOf(otherKingdom);
@@ -100,43 +101,8 @@ private void ResolveCivilWar(IFaction factionMakingPeace, IFaction otherFaction,
100101
var rebelKingdom = kingdomMakingPeaceIsRebel ? kingdomMakingPeace : otherKingdom;
101102
var parentKingdom = kingdomMakingPeaceIsRebel ? otherKingdom : kingdomMakingPeace;
102103
var rebelFaction = RebelFactionManager.GetRebelFaction(parentKingdom).First(x => x.RebelKingdom == rebelKingdom);
103-
104-
if (!Settings.Instance!.EnableWarExhaustion)
105-
{
106-
ResolveLoss(factionMakingPeace, rebelKingdom, rebelFaction);
107-
}
108-
else
109-
{
110-
var warResult = WarExhaustionManager.Instance.GetWarResult(kingdomMakingPeace, otherKingdom);
111-
switch (warResult)
112-
{
113-
case WarExhaustionManager.WarResult.Tie when factionMakingPeace.Fiefs.Any():
114-
{
115-
var peaceBarterable = new PeaceBarterable(kingdomMakingPeace.Leader, kingdomMakingPeace, otherKingdom, CampaignTime.Years(1f));
116-
var valueForOtherKingdom = -peaceBarterable.GetValueForFaction(otherKingdom);
117-
foreach (Clan clan in otherKingdom.Clans)
118-
{
119-
var valueForClan = -peaceBarterable.GetValueForFaction(clan);
120-
if (valueForClan > valueForOtherKingdom)
121-
valueForOtherKingdom = valueForClan;
122-
}
123-
if (valueForOtherKingdom > -5000 && valueForOtherKingdom < 5000)
124-
valueForOtherKingdom = 0;
125-
126-
if (valueForOtherKingdom < 0)
127-
ResolveLoss(otherKingdom, rebelKingdom, rebelFaction);
128-
else
129-
ResolveLoss(factionMakingPeace, rebelKingdom, rebelFaction);
130-
break;
131-
}
132-
case >= WarExhaustionManager.WarResult.PyrrhicVictory:
133-
ResolveLoss(otherKingdom, rebelKingdom, rebelFaction);
134-
break;
135-
default:
136-
ResolveLoss(factionMakingPeace, rebelKingdom, rebelFaction);
137-
break;
138-
}
139-
}
104+
var loserKingdom = RebelFactionManager.GetCivilWarLoser(kingdomMakingPeace, otherKingdom);
105+
ResolveLoss(loserKingdom, rebelKingdom, rebelFaction);
140106
}
141107
}
142108

@@ -148,6 +114,7 @@ static void ResolveLoss(IFaction loser, Kingdom rebelKingdom, RebelFaction rebel
148114
rebelFaction.EnforceSuccess();
149115
}
150116
}
117+
151118
private void RemoveClanFromRebelFaction(Clan clan, Kingdom oldKingdom, Kingdom newKingdom)
152119
{
153120
var rebelFactions = RebelFactionManager.GetRebelFaction(oldKingdom).ToList();

src/Bannerlord.Diplomacy/Cheats.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ private static string SetWarExhaustion(List<string> strings)
166166
if (!CampaignCheats.CheckCheatUsage(ref CampaignCheats.ErrorType))
167167
return CampaignCheats.ErrorType;
168168

169+
if (!Settings.Instance!.EnableWarExhaustion)
170+
return "War exhaustion is disabled!";
171+
169172
var isNumeric = int.TryParse(strings[2], out var targetWarExhaustion);
170173

171174
if (!CampaignCheats.CheckParameters(strings, 3) || CampaignCheats.CheckHelp(strings) || !isNumeric)
@@ -199,7 +202,7 @@ private static string SetWarExhaustion(List<string> strings)
199202
if (kingdom2 is null)
200203
return "2nd kingdom ID not found: " + b2;
201204

202-
WarExhaustionManager.Instance.AddDivineWarExhaustion(kingdom1, kingdom2, targetWarExhaustion);
205+
WarExhaustionManager.Instance!.AddDivineWarExhaustion(kingdom1, kingdom2, targetWarExhaustion);
203206
return "done!";
204207
}
205208

src/Bannerlord.Diplomacy/CivilWar/Actions/StartRebellionAction.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public static void Apply(RebelFaction rebelFaction)
5151

5252
ChangeKingdomBannerAction.Apply(rebelFaction.RebelKingdom!, true);
5353

54-
foreach (var clan in rebelFaction.Clans)
54+
foreach (var clan in rebelFaction.Clans.ToList())
5555
{
5656
if (clan.IsEliminated)
5757
{

src/Bannerlord.Diplomacy/CivilWar/Factions/AbdicationFaction.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public AbdicationFaction(Clan sponsorClan) : base(sponsorClan) { }
2525

2626
public override float MemberInfluenceOnFailure => -100f;
2727

28+
public override bool ConsolidateOnSuccess => true;
29+
2830
protected override void ApplyDemand()
2931
{
3032
var strVars = new Dictionary<string, object>

0 commit comments

Comments
 (0)