Skip to content

Commit

Permalink
Merge pull request #208 from DiplomacyTeam/dev
Browse files Browse the repository at this point in the history
v1.2.5 release
  • Loading branch information
artifixer authored Feb 26, 2023
2 parents a86689a + 9ac4a5c commit 2c5559a
Show file tree
Hide file tree
Showing 30 changed files with 441 additions and 229 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright © 2020-2022 Diplomacy Team
Copyright © 2020-2023 Diplomacy Team

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
8 changes: 4 additions & 4 deletions build/common.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

<!--Module Version-->
<PropertyGroup>
<Version>1.2.4</Version>
<Version>1.2.5</Version>
<GameVersion>1.0.0</GameVersion>
</PropertyGroup>

<!-- Versions of Major Dependencies (For Package References & SubModule.xml Substitution) -->
<PropertyGroup>
<!--BuildResources Version-->
<BuildResourcesVersion>1.0.1.89</BuildResourcesVersion>
<BuildResourcesVersion>1.0.1.92</BuildResourcesVersion>
<!--Harmony Version-->
<HarmonyVersion>2.2.2</HarmonyVersion>
<!--ButterLib Version-->
Expand All @@ -19,13 +19,13 @@
<!--UIExtenderEx Version-->
<UIExtenderExVersion>2.6.0</UIExtenderExVersion>
<!--BUTRShared Version-->
<BUTRSharedVersion>3.0.0.130</BUTRSharedVersion>
<BUTRSharedVersion>3.0.0.134</BUTRSharedVersion>
<!--BUTRModuleManager Version-->
<BUTRModuleManagerVersion>5.0.198</BUTRModuleManagerVersion>
<!--ModuleLoader Version-->
<BUTRModuleLoaderVersion>1.0.1.44</BUTRModuleLoaderVersion>
<!--Harmony Extensions Version-->
<HarmonyExtensionsVersion>3.2.0.73</HarmonyExtensionsVersion>
<HarmonyExtensionsVersion>3.2.0.75</HarmonyExtensionsVersion>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
Expand Down
16 changes: 16 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
---------------------------------------------------------------------------------------------------
Version: 1.2.5
Game Versions: v1.0.0,v1.0.1,v1.0.2,v1.0.3,v1.1.0
* Fixed a crash on making peace when War Exhaustion is disabled.
* Fixed a crash after loading a save when attempting to fix any faulty factions (again).
* Fixed a bug due to which kingdoms were sometimes not destroyed when they should have been.
* Fixed a bug due to which War Exhaustion breakdowns were sometimes showing wrong values (unaffected by rates).
* Making peace should now use all of the mod's enabled mechanics, no matter what interface option was used for it.
* Adjusted the calculation of war reparations to make it even more lenient.
* Adjusted the way war reparations are gathered by the paying kingdom to make it less stressful.
* Adjusted the way war reparations are distributed among the winning faction.
* Adjusted the calculation and default values for some of the War Exhaustion entries.
* Adjusted War Exhaustion rates calculation.
* Adjusted descriptions of some settings for clarity.
* Added an option to disable the elimination of fiefless kingdoms.
* Added an option to disable fief repatriation after losing a war.
---------------------------------------------------------------------------------------------------
Version: 1.2.4
Game Versions: v1.0.0,v1.0.1,v1.0.2,v1.0.3,v1.1.0
* Fixed a crash after loading a save when attempting to fix any faulty factions.
Expand Down
6 changes: 4 additions & 2 deletions src/Bannerlord.Diplomacy/Actions/GiveGoldToClanAction.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Helpers;

using System.Linq;

using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.Library;
Expand All @@ -22,15 +24,15 @@ private static void ApplyInternal(Hero? giverHero, Clan? clan, int goldAmount)

private static void GiveGoldToClan(int gold, Clan clan)
{
foreach ((var recipientHero, var amount) in MBMath.DistributeShares(gold, clan.Lords, CalculateShare))
foreach ((var recipientHero, var amount) in MBMath.DistributeShares(gold, clan.Lords.Where(l => l.IsAlive && l.IsCommander), CalculateShare))
{
GiveGoldAction.ApplyBetweenCharacters(null, recipientHero, amount);
}
}

private static int CalculateShare(Hero member)
{
return HeroHelper.CalculateTotalStrength(member) + (member == member.Clan?.Leader ? 100 : 10);
return HeroHelper.CalculateTotalStrength(member) + (member == member.Clan?.Leader ? 500 : 10);
}

public static void ApplyFromHeroToClan(Hero giverHero, Clan clan, int amount)
Expand Down
140 changes: 106 additions & 34 deletions src/Bannerlord.Diplomacy/Actions/GiveGoldToKingdomAction.cs
Original file line number Diff line number Diff line change
@@ -1,49 +1,121 @@
using TaleWorlds.CampaignSystem;
using System;
using System.Linq;

using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.Settlements;
using TaleWorlds.Library;

namespace Diplomacy.Actions
{
public static class GiveGoldToKingdomAction
{
private const int MinRequiredBudgetWalletSize = 2000000;
private const int MaxRequiredClanGold = 50000;
private const int MinRequiredShortfall = 100000;
private const int GoldPerProsperity = 1000;
private const int MaxRevenuePerMercenaryTier = 10000;

private static void ApplyInternal(Kingdom? giverKingdom, Kingdom? receiverKingdom, int amount, WalletType giverWallet, WalletType receiverWallet)
{
if (amount == 0)
return;

if (giverKingdom != null)
{
switch (giverWallet)
{
case WalletType.TributeWallet:
giverKingdom.TributeWallet -= amount;
break;
case WalletType.BudgetWallet:
//Leaders should benefit from those payments too
var leaderAmount = amount < 0 ? amount / 3 : 0;
if (leaderAmount > 0) GiveGoldAction.ApplyBetweenCharacters(null, giverKingdom.Leader, leaderAmount);
giverKingdom.KingdomBudgetWallet -= (amount - leaderAmount);
break;
default:
break;
}
GetMoneyFromGiver(giverKingdom, amount, giverWallet);
}
if (receiverKingdom != null)
{
switch (receiverWallet)
{
case WalletType.TributeWallet:
receiverKingdom.TributeWallet += amount;
break;
case WalletType.BudgetWallet:
//Leaders should benefit from those payments too
var leaderAmount = amount > 0 ? amount / 3 : 0;
if (leaderAmount > 0) GiveGoldAction.ApplyBetweenCharacters(null, receiverKingdom.Leader, leaderAmount);
receiverKingdom.KingdomBudgetWallet += (amount - leaderAmount);
break;
default:
break;
}
GiveMoneyToReceiver(receiverKingdom, amount, receiverWallet);
}
}

private static void GetMoneyFromGiver(Kingdom giverKingdom, int amount, WalletType giverWallet)
{
switch (giverWallet)
{
case WalletType.TributeWallet:
giverKingdom.TributeWallet -= amount;
return;
case WalletType.BudgetWallet:
giverKingdom.KingdomBudgetWallet -= amount;
return;
case WalletType.ReparationsWallet:
//Cover from the kingdom budget
var availableBudgetAmount = Math.Max(giverKingdom.KingdomBudgetWallet - MinRequiredBudgetWalletSize, 0);
if (availableBudgetAmount > 0)
{
var budgetCoveredAmount = Math.Min(availableBudgetAmount, amount);
giverKingdom.KingdomBudgetWallet -= budgetCoveredAmount;
amount -= budgetCoveredAmount;
}
if (amount <= 0)
return;

//Cover from the kingdom prosperity
var tolerableAmount = giverKingdom.Clans.Where(c => !c.IsUnderMercenaryService && !c.IsEliminated).Sum(c => c.Gold - Math.Min(c.Gold / 4, MaxRequiredClanGold));
if (tolerableAmount < amount)
{
var amountToCover = amount - tolerableAmount;
if (amountToCover >= MinRequiredShortfall)
{
foreach ((var settlement, var amountToCoverBySettlement) in MBMath.DistributeShares(amountToCover, giverKingdom.Settlements.Where(s => s.IsCastle || s.IsTown), CalculateSettlementShare))
{
settlement.Prosperity -= amountToCoverBySettlement / GoldPerProsperity;
}
amount = tolerableAmount;
}
}

giverKingdom.TributeWallet -= amount;
return;
default:
return;
}
}

private static void GiveMoneyToReceiver(Kingdom receiverKingdom, int amount, WalletType receiverWallet)
{
switch (receiverWallet)
{
case WalletType.TributeWallet:
receiverKingdom.TributeWallet += amount;
return;
case WalletType.BudgetWallet:
receiverKingdom.KingdomBudgetWallet += amount;
return;
case WalletType.ReparationsWallet:
//Leaders should benefit from those payments too
var leaderAmount = amount / 3;
if (leaderAmount > 0) GiveGoldAction.ApplyBetweenCharacters(null, receiverKingdom.Leader, leaderAmount);
//Mercenaries
var mercenaryAmount = amount / 6;
int mercenaryAmountFact = 0;
foreach ((var recipientMercClan, var amountForMercClan) in MBMath.DistributeShares(mercenaryAmount, receiverKingdom.Clans.Where(c => c.IsUnderMercenaryService && !c.IsEliminated), CalculateMercenaryShare))
{
var amountForMercClanFact = Math.Min(amountForMercClan, recipientMercClan.Tier * MaxRevenuePerMercenaryTier);
GiveGoldAction.ApplyBetweenCharacters(null, recipientMercClan.Leader, amountForMercClanFact);
mercenaryAmountFact += amountForMercClanFact;
}
//Reassess
amount = amount - leaderAmount - mercenaryAmountFact;
//Player
var playerClan = Clan.PlayerClan;
if (playerClan.Kingdom == receiverKingdom && !playerClan.IsUnderMercenaryService && playerClan.Leader != receiverKingdom.Leader)
{
var playerAmount = MBMath.DistributeShares(amount, receiverKingdom.Clans.Where(c => !c.IsUnderMercenaryService && !c.IsEliminated), CalculateShare).FirstOrDefault(x => x.Item1 == playerClan);
if (playerAmount != default && playerAmount.Item2 > 0)
{
GiveGoldAction.ApplyBetweenCharacters(null, playerClan.Leader, playerAmount.Item2);
amount -= playerAmount.Item2;
}
}

receiverKingdom.KingdomBudgetWallet += amount;
return;
default:
return;
}
}

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

private static void GiveGoldToKingdom(int gold, Kingdom kingdom)
{
foreach ((var recipientClan, var amount) in MBMath.DistributeShares(gold, kingdom.Clans, CalculateShare))
foreach ((var recipientClan, var amount) in MBMath.DistributeShares(gold, kingdom.Clans.Where(c => !c.IsUnderMercenaryService && !c.IsEliminated), CalculateShare))
{
GiveGoldToClanAction.ApplyToClan(recipientClan, amount);
}
}

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

public static void ApplyFromHeroToKingdom(Hero giverHero, Kingdom kingdom, int amount)
{
Expand All @@ -88,6 +159,7 @@ public enum WalletType : byte
MercenaryWallet = 1,
TributeWallet = 2,
BudgetWallet = 3,
ReparationsWallet = 4
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Diplomacy.Actions
{
public static class DestroyKingdomSoftlyAction
public static class SoftlyDestroyKingdomAction
{
public static void Apply(Kingdom kingdomToDestroy)
{
Expand Down
41 changes: 4 additions & 37 deletions src/Bannerlord.Diplomacy/CampaignBehaviors/CivilWarBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ private void ResolveCivilWar(IFaction factionMakingPeace, IFaction otherFaction)
private void ResolveCivilWar(IFaction factionMakingPeace, IFaction otherFaction, MakePeaceAction.MakePeaceDetail makePeaceDetail)
#endif
{
//Need to check if this runs before or after WarExhaustionBehavior
if (factionMakingPeace is Kingdom kingdomMakingPeace && otherFaction is Kingdom otherKingdom)
{
var kingdomMakingPeaceIsRebel = kingdomMakingPeace.IsRebelKingdomOf(otherKingdom);
Expand All @@ -100,43 +101,8 @@ private void ResolveCivilWar(IFaction factionMakingPeace, IFaction otherFaction,
var rebelKingdom = kingdomMakingPeaceIsRebel ? kingdomMakingPeace : otherKingdom;
var parentKingdom = kingdomMakingPeaceIsRebel ? otherKingdom : kingdomMakingPeace;
var rebelFaction = RebelFactionManager.GetRebelFaction(parentKingdom).First(x => x.RebelKingdom == rebelKingdom);

if (!Settings.Instance!.EnableWarExhaustion)
{
ResolveLoss(factionMakingPeace, rebelKingdom, rebelFaction);
}
else
{
var warResult = WarExhaustionManager.Instance.GetWarResult(kingdomMakingPeace, otherKingdom);
switch (warResult)
{
case WarExhaustionManager.WarResult.Tie when factionMakingPeace.Fiefs.Any():
{
var peaceBarterable = new PeaceBarterable(kingdomMakingPeace.Leader, kingdomMakingPeace, otherKingdom, CampaignTime.Years(1f));
var valueForOtherKingdom = -peaceBarterable.GetValueForFaction(otherKingdom);
foreach (Clan clan in otherKingdom.Clans)
{
var valueForClan = -peaceBarterable.GetValueForFaction(clan);
if (valueForClan > valueForOtherKingdom)
valueForOtherKingdom = valueForClan;
}
if (valueForOtherKingdom > -5000 && valueForOtherKingdom < 5000)
valueForOtherKingdom = 0;

if (valueForOtherKingdom < 0)
ResolveLoss(otherKingdom, rebelKingdom, rebelFaction);
else
ResolveLoss(factionMakingPeace, rebelKingdom, rebelFaction);
break;
}
case >= WarExhaustionManager.WarResult.PyrrhicVictory:
ResolveLoss(otherKingdom, rebelKingdom, rebelFaction);
break;
default:
ResolveLoss(factionMakingPeace, rebelKingdom, rebelFaction);
break;
}
}
var loserKingdom = RebelFactionManager.GetCivilWarLoser(kingdomMakingPeace, otherKingdom);
ResolveLoss(loserKingdom, rebelKingdom, rebelFaction);
}
}

Expand All @@ -148,6 +114,7 @@ static void ResolveLoss(IFaction loser, Kingdom rebelKingdom, RebelFaction rebel
rebelFaction.EnforceSuccess();
}
}

private void RemoveClanFromRebelFaction(Clan clan, Kingdom oldKingdom, Kingdom newKingdom)
{
var rebelFactions = RebelFactionManager.GetRebelFaction(oldKingdom).ToList();
Expand Down
5 changes: 4 additions & 1 deletion src/Bannerlord.Diplomacy/Cheats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ private static string SetWarExhaustion(List<string> strings)
if (!CampaignCheats.CheckCheatUsage(ref CampaignCheats.ErrorType))
return CampaignCheats.ErrorType;

if (!Settings.Instance!.EnableWarExhaustion)
return "War exhaustion is disabled!";

var isNumeric = int.TryParse(strings[2], out var targetWarExhaustion);

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

WarExhaustionManager.Instance.AddDivineWarExhaustion(kingdom1, kingdom2, targetWarExhaustion);
WarExhaustionManager.Instance!.AddDivineWarExhaustion(kingdom1, kingdom2, targetWarExhaustion);
return "done!";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public static void Apply(RebelFaction rebelFaction)

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

foreach (var clan in rebelFaction.Clans)
foreach (var clan in rebelFaction.Clans.ToList())
{
if (clan.IsEliminated)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public AbdicationFaction(Clan sponsorClan) : base(sponsorClan) { }

public override float MemberInfluenceOnFailure => -100f;

public override bool ConsolidateOnSuccess => true;

protected override void ApplyDemand()
{
var strVars = new Dictionary<string, object>
Expand Down
2 changes: 2 additions & 0 deletions src/Bannerlord.Diplomacy/CivilWar/Factions/RebelFaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public abstract class RebelFaction

public abstract RebelDemandType RebelDemandType { get; }

public abstract bool ConsolidateOnSuccess { get; }

public float FactionStrength
{
get { return _participatingClans.Select(c => c.TotalStrength).Sum(); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public SecessionFaction(Clan sponsorClan) : base(sponsorClan) { }

public override float MemberInfluenceOnFailure => -100f;

public override bool ConsolidateOnSuccess => false;

protected override void ApplyDemand()
{
var kingdomName = FactionNameGenerator.GenerateKingdomName(this);
Expand Down
Loading

0 comments on commit 2c5559a

Please sign in to comment.