Beta Patch Notes e1.8.0

Users who are viewing this thread

As I said, it is not the only factor there but one of them. I didn't claim this is the cause of defection bug. Flesson said clans get different defection chances when you give different settlements to them, I checked the code why.
Here is how game calculates geographical advantage of a settlement for a faction
C#:
private float GeographicalAdvantageForFaction(Settlement settlement, IFaction faction)
{
    Settlement factionMidSettlement = faction.FactionMidSettlement;
    float distance = Campaign.Current.Models.MapDistanceModel.GetDistance(settlement, factionMidSettlement);
    float distanceToClosestNonAllyFortification = faction.DistanceToClosestNonAllyFortification;
    if (faction.FactionMidSettlement.MapFaction != faction)
    {
        return Campaign.AverageDistanceBetweenTwoFortifications / (distance + 0.1f);
    }
    if (settlement.MapFaction == faction && distance < distanceToClosestNonAllyFortification)
    {
        return MathF.Clamp(Campaign.AverageDistanceBetweenTwoFortifications / (distanceToClosestNonAllyFortification - distance), 1f, 4f);
    }
    float num = (distance - distanceToClosestNonAllyFortification) / Campaign.AverageDistanceBetweenTwoFortifications;
    return 1f / (1f + num);
}
This calculation is used for every settlement the clan owns when game is calculating which faction is better for the clan. For the relevant code, you can check DefaultDiplomacyModel class, specifically GetScoreOfClanToJoinKingdom, GetScoreOfClanToLeaveKingdom and GetScoreOfKingdomToGetClan methods.

To further explain this part while at it, game basically checks how far away the settlement is from faction's middle settlement. So when you give a clan settlements all on Battania border lets say, you have higher chances that Battania's value will be higher for that clan. This becomes even more significant as your size grows. If you give clans settlements on the opposite sides of your kingdom, your faction's score will stay roughly same for the clan but no other faction will get much better scores than you either if any better.

Speaking of this being changed, in fact it is different from 1.7.2. I don't know if it was mentioned in patch notes as I started playing again after beta 1.8.0 was released, I didn't read patch notes.
C#:
private float GeographicalAdvantageForFaction(Settlement settlement, IFaction faction)
{
    float num = this._settlementDistances.GetSixNearestSettlementDistanceWithSameFaction(settlement, faction) / 5f;
    float num2 = (faction != null) ? Campaign.Current.Models.MapDistanceModel.GetDistance(settlement, faction.FactionMidSettlement) : 0f;
    float num3 = MathF.Pow(1f - num2 / Campaign.MapDiagonal, 0.1f);
    float num4 = Campaign.AverageDistanceBetweenTwoTowns * 1.5f;
    float num5 = (Campaign.AverageDistanceBetweenTwoTowns < num4) ? 1f : MathF.Max(0.5f, MathF.Min(1f, MathF.Pow(num4 / num, 0.25f)));
    return num3 * num5;
}

Quite a bit different calculation but to me most important part seems that "six nearest settlement distance with same faction" is gone. (Speculation) This is probably what was helping huge kingdoms. Although new fief is quite far away from midpoint, it can still have close 6 other settlements.
There are some other changes in other factors as well. For example having same original map faction and culture has less effect on 1.8.0 compared to 1.7.2

And while talking about this, I couldn't check it since it is on the engine side (C++) but I really hope distances between settlements calculated considering factors like forests/snow etc. cause otherwise factions like Aserai that has pretty big but empty lands will innately be in disadvantage because settlements will be calculated too far away while in reality forest/snow etc. makes it similar times to travel between factions in other parts of the world.

EDIT: I should have paid more attention to 1.7.2 code before making speculations 😅 `num5` will always be 1 because `num4` is guaranteed to be higher than `Campaign.AverageDistanceBetweenTwoTowns` (uhm, maybe it was a bug?) removing six nearest settlement calculation from equation completely. Considering this new discovery, old code used to compare every faction to map size BUT thanks to that power to tiny tiny 0.1, the difference between a faction half the size of map and only 1/10th of the map will only be 0.1 :smile: While in new code the difference can be as high as 3-4 it seems. There you go, there is your big difference.
Thank you, very interesting read
 
As I said, it is not the only factor there but one of them. I didn't claim this is the cause of defection bug. Flesson said clans get different defection chances when you give different settlements to them, I checked the code why.
Here is how game calculates geographical advantage of a settlement for a faction
C#:
private float GeographicalAdvantageForFaction(Settlement settlement, IFaction faction)
{
    Settlement factionMidSettlement = faction.FactionMidSettlement;
    float distance = Campaign.Current.Models.MapDistanceModel.GetDistance(settlement, factionMidSettlement);
    float distanceToClosestNonAllyFortification = faction.DistanceToClosestNonAllyFortification;
    if (faction.FactionMidSettlement.MapFaction != faction)
    {
        return Campaign.AverageDistanceBetweenTwoFortifications / (distance + 0.1f);
    }
    if (settlement.MapFaction == faction && distance < distanceToClosestNonAllyFortification)
    {
        return MathF.Clamp(Campaign.AverageDistanceBetweenTwoFortifications / (distanceToClosestNonAllyFortification - distance), 1f, 4f);
    }
    float num = (distance - distanceToClosestNonAllyFortification) / Campaign.AverageDistanceBetweenTwoFortifications;
    return 1f / (1f + num);
}
This calculation is used for every settlement the clan owns when game is calculating which faction is better for the clan. For the relevant code, you can check DefaultDiplomacyModel class, specifically GetScoreOfClanToJoinKingdom, GetScoreOfClanToLeaveKingdom and GetScoreOfKingdomToGetClan methods.

To further explain this part while at it, game basically checks how far away the settlement is from faction's middle settlement. So when you give a clan settlements all on Battania border lets say, you have higher chances that Battania's value will be higher for that clan. This becomes even more significant as your size grows. If you give clans settlements on the opposite sides of your kingdom, your faction's score will stay roughly same for the clan but no other faction will get much better scores than you either if any better.

Speaking of this being changed, in fact it is different from 1.7.2. I don't know if it was mentioned in patch notes as I started playing again after beta 1.8.0 was released, I didn't read patch notes.
C#:
private float GeographicalAdvantageForFaction(Settlement settlement, IFaction faction)
{
    float num = this._settlementDistances.GetSixNearestSettlementDistanceWithSameFaction(settlement, faction) / 5f;
    float num2 = (faction != null) ? Campaign.Current.Models.MapDistanceModel.GetDistance(settlement, faction.FactionMidSettlement) : 0f;
    float num3 = MathF.Pow(1f - num2 / Campaign.MapDiagonal, 0.1f);
    float num4 = Campaign.AverageDistanceBetweenTwoTowns * 1.5f;
    float num5 = (Campaign.AverageDistanceBetweenTwoTowns < num4) ? 1f : MathF.Max(0.5f, MathF.Min(1f, MathF.Pow(num4 / num, 0.25f)));
    return num3 * num5;
}

Quite a bit different calculation but to me most important part seems that "six nearest settlement distance with same faction" is gone. (Speculation) This is probably what was helping huge kingdoms. Although new fief is quite far away from midpoint, it can still have close 6 other settlements.
There are some other changes in other factors as well. For example having same original map faction and culture has less effect on 1.8.0 compared to 1.7.2

And while talking about this, I couldn't check it since it is on the engine side (C++) but I really hope distances between settlements calculated considering factors like forests/snow etc. cause otherwise factions like Aserai that has pretty big but empty lands will innately be in disadvantage because settlements will be calculated too far away while in reality forest/snow etc. makes it similar times to travel between factions in other parts of the world.

EDIT: I should have paid more attention to 1.7.2 code before making speculations 😅 `num5` will always be 1 because `num4` is guaranteed to be higher than `Campaign.AverageDistanceBetweenTwoTowns` (uhm, maybe it was a bug?) removing six nearest settlement calculation from equation completely. Considering this new discovery, old code used to compare every faction to map size BUT thanks to that power to tiny tiny 0.1, the difference between a faction half the size of map and only 1/10th of the map will only be 0.1 :smile: While in new code the difference can be as high as 3-4 it seems. There you go, there is your big difference.
thanks a lot for the detailed reply and explanation, very intersting. yes i wasnt referring directly to your reply to flesson, iam sorry for that.

so there has been a big change on 1.8.0 which is somewhat affecting the defection and there is defenitly a link to the issue visible in that code.
problem is, that this is only happening to you as a player and not affecting the ai in a way that they would loose settlements (only the vassals as defection is happening while peace) and even if it would work correctly, getting all the settlements would be more or less impossible or at least tedious as hell. i dont like that approach either. its not really making logic sense.
 
problem is, that this is only happening to you as a player and not affecting the ai in a way that they would loose settlements
I will check further to see if there are parts directly checking if it is player kingdom. But that only doesn't prove it is not a thing, could be side effect of some other part/bug. Still, might find something relevant.
 
Thats the problem with sandbox games that arent scripted, you change one part and it ****s up a completely different part due to unforeseen consequences.
I understand the sentiment and the generosity behind this statement, combined with the fact that this is the beta branch...
But at the same time simply foresee the consequences 💩

If it were I don’t know, say my job to develop a video game amongst a team I might want a large colour coded flowchart showing dependencies of different aspects of the simulation and each of their inputs etc.
Such a diagram would be decently complex (complexity that could be made more readable by visual design) but nonetheless it would be finite.

Then if for a design development reason I wanted to make a change to an area of the game, I could easily track down what other factors may be affected by my intended change and how I might have to compensate for my intended changes. The diagram could also indicate the staff most knowledgeable and responsible for the area that I intended to effect with my changes so that I may confer and collaborate with them. Then after my changes are made harmonious enough to satisfy the team, I can add any new dependencies and links to the diagram for the whole team to see.
Sounds like a lot of work but its a lot less work than everytime I attempt to improve something I make something else worse or break 3 other things creating a cluster ****, stalling development for a month as we reassemble humpty dumpty into a gut renching hommunculous who now feeds on human flesh.

But I'm sure Taleworlds has an equivalent thing in their process and all issues are caused by understandable human error in the foreign to me syntax of coding.
 
But I'm sure Taleworlds has an equivalent thing in their process and all issues are caused by understandable human error in the foreign to me syntax of coding.
Meanwhile TW explaining their systems internally in meetings:

1arqp8.jpg
 
As I said, it is not the only factor there but one of them. I didn't claim this is the cause of defection bug. Flesson said clans get different defection chances when you give different settlements to them, I checked the code why.
Here is how game calculates geographical advantage of a settlement for a faction
C#:
private float GeographicalAdvantageForFaction(Settlement settlement, IFaction faction)
{
    Settlement factionMidSettlement = faction.FactionMidSettlement;
    float distance = Campaign.Current.Models.MapDistanceModel.GetDistance(settlement, factionMidSettlement);
    float distanceToClosestNonAllyFortification = faction.DistanceToClosestNonAllyFortification;
    if (faction.FactionMidSettlement.MapFaction != faction)
    {
        return Campaign.AverageDistanceBetweenTwoFortifications / (distance + 0.1f);
    }
    if (settlement.MapFaction == faction && distance < distanceToClosestNonAllyFortification)
    {
        return MathF.Clamp(Campaign.AverageDistanceBetweenTwoFortifications / (distanceToClosestNonAllyFortification - distance), 1f, 4f);
    }
    float num = (distance - distanceToClosestNonAllyFortification) / Campaign.AverageDistanceBetweenTwoFortifications;
    return 1f / (1f + num);
}
This calculation is used for every settlement the clan owns when game is calculating which faction is better for the clan. For the relevant code, you can check DefaultDiplomacyModel class, specifically GetScoreOfClanToJoinKingdom, GetScoreOfClanToLeaveKingdom and GetScoreOfKingdomToGetClan methods.

To further explain this part while at it, game basically checks how far away the settlement is from faction's middle settlement. So when you give a clan settlements all on Battania border lets say, you have higher chances that Battania's value will be higher for that clan. This becomes even more significant as your size grows. If you give clans settlements on the opposite sides of your kingdom, your faction's score will stay roughly same for the clan but no other faction will get much better scores than you either if any better.

Speaking of this being changed, in fact it is different from 1.7.2. I don't know if it was mentioned in patch notes as I started playing again after beta 1.8.0 was released, I didn't read patch notes.
C#:
private float GeographicalAdvantageForFaction(Settlement settlement, IFaction faction)
{
    float num = this._settlementDistances.GetSixNearestSettlementDistanceWithSameFaction(settlement, faction) / 5f;
    float num2 = (faction != null) ? Campaign.Current.Models.MapDistanceModel.GetDistance(settlement, faction.FactionMidSettlement) : 0f;
    float num3 = MathF.Pow(1f - num2 / Campaign.MapDiagonal, 0.1f);
    float num4 = Campaign.AverageDistanceBetweenTwoTowns * 1.5f;
    float num5 = (Campaign.AverageDistanceBetweenTwoTowns < num4) ? 1f : MathF.Max(0.5f, MathF.Min(1f, MathF.Pow(num4 / num, 0.25f)));
    return num3 * num5;
}

Quite a bit different calculation but to me most important part seems that "six nearest settlement distance with same faction" is gone. (Speculation) This is probably what was helping huge kingdoms. Although new fief is quite far away from midpoint, it can still have close 6 other settlements.
There are some other changes in other factors as well. For example having same original map faction and culture has less effect on 1.8.0 compared to 1.7.2

And while talking about this, I couldn't check it since it is on the engine side (C++) but I really hope distances between settlements calculated considering factors like forests/snow etc. cause otherwise factions like Aserai that has pretty big but empty lands will innately be in disadvantage because settlements will be calculated too far away while in reality forest/snow etc. makes it similar times to travel between factions in other parts of the world.

EDIT: I should have paid more attention to 1.7.2 code before making speculations 😅 `num5` will always be 1 because `num4` is guaranteed to be higher than `Campaign.AverageDistanceBetweenTwoTowns` (uhm, maybe it was a bug?) removing six nearest settlement calculation from equation completely. Considering this new discovery, old code used to compare every faction to map size BUT thanks to that power to tiny tiny 0.1, the difference between a faction half the size of map and only 1/10th of the map will only be 0.1 :smile: While in new code the difference can be as high as 3-4 it seems. There you go, there is your big difference.
Great insight azakhi! Its very clear now that this issue is directly due to this code change. Also I can say that this defection issue is absolutely impacting AI kingdoms, it was super apparent in my snowball testing which only involves AI kingdoms.


@SadShogun sorry if you guys already know this but seems like the new code needs to be scaled down if we want it to be comparable to previous versions.
 
Have you even bothered to look at Bannerlord's API documentation? https://apidoc.bannerlord.com/v/1.8.0/
I dont have great comprehension of what I am looking at because I'm not code familiar, even this simplified api stuff. But I gather its a large number of inter-related variables.
Is your point that its too complex to simplify or make more readable?
I'm not sure maybe this stuff reads like a book to someone fluent in the syntax, and wouldnt be aided by visual simplification?
I am genuinely asking by the way.
 
I dont have great comprehension of what I am looking at because I'm not code familiar, even this simplified api stuff. But I gather its a large number of inter-related variables.
Is your point that its too complex to simplify or make more readable?
I'm not sure maybe this stuff reads like a book to someone fluent in the syntax, and wouldnt be aided by visual simplification?
I am genuinely asking by the way.
The API document is a reference dictionary. Flowcharts are more normally used in procedural programming where instructions follow each other in a logical sequence. Bannerlord's game code is written in C#, which is an object orientated language as opposed to a procedural one. It's more focused on defining data and behaviours into reusable objects.
 
Great insight azakhi! Its very clear now that this issue is directly due to this code change. Also I can say that this defection issue is absolutely impacting AI kingdoms, it was super apparent in my snowball testing which only involves AI kingdoms.


@SadShogun sorry if you guys already know this but seems like the new code needs to be scaled down if we want it to be comparable to previous versions.
I really need a save with defection issue to make a conclusion. There are lots of other factors still there. However I decided to write a little mod to compare old calculation with new one.
First of all map for reference:
f0hdtxj.png

The City we are checking for comparison is "Amprela" and we will be comparing Northern Empire to Southern Empire.
Note that this calculation is only for settlement's value for a faction! It is NOT total calculated score.
1.7.2 values:
  • Northern Empire: 1 626 857
  • Southern Empire: 1 330 563
1.8.0 values:
  • Northern Empire: 6 026 393
  • Southern Empire: 339 896
I should note this includes some other changes as well. So to compare I also made same calculation changing only geographical advantage part.
1.7.2 geographical calculation, rest 1.8.0:
  • Northern Empire: 1 491 286
  • Southern Empire: 1 330 563
I think I can conclude the geography is playing much bigger role in 1.8.0. Is this cause of the defection bug? I prefer to have a save and check values to make that conclusion. If I were to make a speculation, I would say there is an issue with this part of the code:
C#:
if (settlement.MapFaction == faction && distance < distanceToClosestNonAllyFortification)
{
    return MathF.Clamp(Campaign.AverageDistanceBetweenTwoFortifications / (distanceToClosestNonAllyFortification - distance), 1f, 4f);
}
float num = (distance - distanceToClosestNonAllyFortification) / Campaign.AverageDistanceBetweenTwoFortifications;
return 1f / (1f + num);
If the settlement's original faction is same with the faction being checked and if it is closer to that faction's middle point (distance variable) than a non-ally settlement, this part can return as high as 4. While a border settlement in a big faction will return less than 1. Considering this value is used as a multiplier, that is a big difference.

For the interested, here are Amprela's calculated values for all factions. Note though these calculations include some other factors like factions being the same. However you can still get an idea.
1.8.0 Values:
  • Northern Empire: 6 026 393
  • Khuzait: 630 149
  • Western Empire: 314 538
  • Battania: 194 734
  • Southern Empire: 339 896
  • Aserai: 187 690
  • Sturgia: 350 528
  • Vlandia: 154 135
1.8.0 with 1.7.2 Geographical Values:
  • Northern Empire: 1 491 286
  • Khuzait: 1 221 339
  • Western Empire: 1 312 798
  • Battania: 1 176 015
  • Southern Empire: 1 330 563
  • Aserai: 1 143 351
  • Sturgia: 1 206 887
  • Vlandia: 1 140 252
1.7.2 Values:
  • Northern Empire: 1 626 857
  • Khuzait: 1 099 205
  • Western Empire: 1 312 798
  • Battania: 1 058 414
  • Southern Empire: 1 330 563
  • Aserai: 1 029 016
  • Sturgia: 1 086 198
  • Vlandia: 1 026 227
 
Last edited:
I really need a save with defection issue to make a conclusion. There are lots of other factors still there. However I decided to write a little mod to compare old calculation with new one.
First of all map for reference:
f0hdtxj.png

The City we are checking for comparison is "Amprela" and we will be comparing Northern Empire to Southern Empire.
Note that this calculation is only for settlement's value for a faction! It is NOT total calculated score.
1.7.2 values:
  • Northern Empire: 1 626 857
  • Southern Empire: 1 330 563
1.8.0 values:
  • Northern Empire: 6 026 393
  • Southern Empire: 339 896
I should note this includes some other changes as well. So to compare I also made same calculation changing only geographical advantage part.
1.7.2 geographical calculation, rest 1.8.0:
  • Northern Empire: 1 491 286
  • Southern Empire: 1 330 563
I think I can conclude the geography is playing much bigger role in 1.8.0. Is this cause of the defection bug? I prefer to have a save and check values to make that conclusion. If I were to make a speculation, I would say there is an issue with this part of the code:
C#:
if (settlement.MapFaction == faction && distance < distanceToClosestNonAllyFortification)
{
    return MathF.Clamp(Campaign.AverageDistanceBetweenTwoFortifications / (distanceToClosestNonAllyFortification - distance), 1f, 4f);
}
float num = (distance - distanceToClosestNonAllyFortification) / Campaign.AverageDistanceBetweenTwoFortifications;
return 1f / (1f + num);
If the settlement's original faction is same with the faction being checked and if it is closer to that faction's middle point (distance variable) than a non-ally settlement, this part can return as high as 4. While a border settlement in a big faction will return less than 1. Considering this value is used as a multiplier, that is a big difference.

For the interested, here are Amprela's calculated values for all factions. Note though these calculations include some other factors like factions being the same. However you can still get an idea.
1.8.0 Values:
  • Northern Empire: 6 026 393
  • Khuzait: 630 149
  • Western Empire: 314 538
  • Battania: 194 734
  • Southern Empire: 339 896
  • Aserai: 187 690
  • Sturgia: 350 528
  • Vlandia: 154 135
1.8.0 with 1.7.2 Geographical Values:
  • Northern Empire: 1 491 286
  • Khuzait: 1 221 339
  • Western Empire: 1 312 798
  • Battania: 1 176 015
  • Southern Empire: 1 330 563
  • Aserai: 1 143 351
  • Sturgia: 1 206 887
  • Vlandia: 1 140 252
1.7.2 Values:
  • Northern Empire: 1 626 857
  • Khuzait: 1 099 205
  • Western Empire: 1 312 798
  • Battania: 1 058 414
  • Southern Empire: 1 330 563
  • Aserai: 1 029 016
  • Sturgia: 1 086 198
  • Vlandia: 1 026 227
I was able to test values with the defection bug thanks to saves provided by @Blood Gryphon (thanks!).
TLDR: `DefaultSettlementValueModel.GeographicalAdvantageForFaction` method is very broken, needs to be fixed.

If you would like to read further explanation, here it is.
First of all lets see the defection on map for reference:
ZFH0AdQ.png

The clan that defected here is Dolentos, taking cities Diathma and Amprela from Southern Empire and joining Northern Empire, which had no settlements at the time.
Here is the values my mod logged regarding this defection decision:
KGvImRG.png


Base Settlement Value: This is calculated value of all of the settlements the clan has. It also checks geographical position to current faction's middle point. Since this calculation was before defection, it was calculated for Southern Empire. 618k for 2 cities is pretty normal as we can see from my previous message considering both cities are far from Southern Empire's middle point.

Settlement Value For Southern Empire: This is calculated value of all of the settlements the clan has from the viewpoint of Southern Empire. The difference from the above calculation comes from the fact that the two geographical advantage calculations are different. Now here 1.5m is a little higher but still normal for 2 cities.

Settlement Value For Northern Empire: Same calculation above done from the viewpoint of Northern Empire this time. However this time the value is 821m. About 500 times the Southern Empire. Very odd.
Before I go into checking if this crazy value has an effect on defection, first lets see why this happens.
Here is the geographical advantage code:
C#:
private float GeographicalAdvantageForFaction(Settlement settlement, IFaction faction)
{
    Settlement factionMidSettlement = faction.FactionMidSettlement;
    float distance = Campaign.Current.Models.MapDistanceModel.GetDistance(settlement, factionMidSettlement);
    float distanceToClosestNonAllyFortification = faction.DistanceToClosestNonAllyFortification;
    if (faction.FactionMidSettlement.MapFaction != faction)
    {
        return Campaign.AverageDistanceBetweenTwoFortifications / (distance + 0.1f);
    }
    if (settlement.MapFaction == faction && distance < distanceToClosestNonAllyFortification)
    {
        return MathF.Clamp(Campaign.AverageDistanceBetweenTwoFortifications / (distanceToClosestNonAllyFortification - distance), 1f, 4f);
    }
    float num = (distance - distanceToClosestNonAllyFortification) / Campaign.AverageDistanceBetweenTwoFortifications;
    return 1f / (1f + num);
}

Now my personal opinion is this method, even ignoring the bug I am going to explain, is not well thought. The result of this method is used as a multiplier, which means you can get 10-40 times the values due to calculation difference thanks to `if` conditions here. But for the moment lets focus on the bug in this particular situation.
Remember that before defection, Northern Empire didn't have any settlements. So in that case what is the `FactionMidSettlement` for it? It is definitely not `null` (meaning nothing) because the code assumes it is not. So they know for sure it can't be `null`. My guess is that it still uses the old one. And in this particular situation, that old one must be either Diathma or Amprela.
Keeping that in mind, lets check first condition. Game executes first `return` line if faction's middle settlement is not part of the faction. Since Northern Empire has no settlements, we know for sure this is true. And the distance variable must be 0 for either Diathma or Amprela. Which means our result is `Campaign.AverageDistanceBetweenTwoFortifications / 0.1`. If the average distance between two fortifications in the game is calculated as 50 for example, we are returning 500. Considering rest of the code seems to be around 0-4 as value, you can see this is an unintentional result. And the reason why Northern Empire gets about 500 times more settlement value than Southern Empire.

Now lets check if this values actually have an effect on defection. The game calls 2 methods while calculating defection scores, `GetScoreOfClanToJoinKingdom` and `GetScoreOfKingdomToGetClan`. First one is the score of how much the clan wants to join the given kingdom and second one is the score of how much the given kingdom wants to get the clan.
As you can see from the values my mod logged, these are 820m and 48m in order.
Lets how much of these values come from the settlement values we have seen above. Since these 2 methods are quite complicated, I removed irrelevant parts.
First method:
C#:
public override float GetScoreOfClanToJoinKingdom(Clan clan, Kingdom kingdom)
{
    //...
    float num7 = clan.CalculateTotalSettlementBaseValue();
    float num8 = clan.CalculateTotalSettlementValueForFaction(kingdom);
    //...
    return num9 * MathF.Sqrt((float)commanderLimit) * num14 * 0.2f * (num5 * num6) + (clan.MapFaction.IsAtWarWith(kingdom) ? (num8 - num7) : 0f) + num10;
}
Southern Empire and Northern Empire are at war so we get `num8 - num7`, which can be seen from logs as 600k and 821m in order. So the first method returned 820m all thanks to settlement values.
Second method:
C#:
public override float GetScoreOfKingdomToGetClan(Kingdom kingdom, Clan clan)
{
    //..
    return (clan.CalculateTotalSettlementValueForFaction(kingdom) * 0.1f + num3) * num * num2 * num4;
}
In here I removed everything else but that is fine because as you can see almost all values are multiplied by each other. We know settlement value is 821m, which becomes 82m before being part of multiplication. `num3` here is total strength of the clan and checking other logs I can safely say it is well under 1m. So once again, majority of score comes from settlement values.

This particular situation seems to be a bug and will cause odd situations every now and then. However my personal opinion is whole method needs improvement. Settlement values are a big part of calculation for defection scores. Current calculation puts huge emphasis on geographical position and faction middle settlements. If your kingdom gets quite big and Vlandia has only couple settlements on the left side of the map, any settlement on the Vlandian border will get huge settlement values for Vlandia compare to you. Doesn't make any sense. Vlandia's middle settlement being closer doesn't mean Vlandia is closer. You can have 10 settlements closer than Vlandian ones.

So fingers crossed this will be addressed soon. In the mean time if anyone is interested, I can replace geographical advantage calculation with 1.7.2 one and release as a mod.
 
I was able to test values with the defection bug thanks to saves provided by @Blood Gryphon (thanks!).
TLDR: `DefaultSettlementValueModel.GeographicalAdvantageForFaction` method is very broken, needs to be fixed.

If you would like to read further explanation, here it is.
First of all lets see the defection on map for reference:
ZFH0AdQ.png

The clan that defected here is Dolentos, taking cities Diathma and Amprela from Southern Empire and joining Northern Empire, which had no settlements at the time.
Here is the values my mod logged regarding this defection decision:
KGvImRG.png


Base Settlement Value: This is calculated value of all of the settlements the clan has. It also checks geographical position to current faction's middle point. Since this calculation was before defection, it was calculated for Southern Empire. 618k for 2 cities is pretty normal as we can see from my previous message considering both cities are far from Southern Empire's middle point.

Settlement Value For Southern Empire: This is calculated value of all of the settlements the clan has from the viewpoint of Southern Empire. The difference from the above calculation comes from the fact that the two geographical advantage calculations are different. Now here 1.5m is a little higher but still normal for 2 cities.

Settlement Value For Northern Empire: Same calculation above done from the viewpoint of Northern Empire this time. However this time the value is 821m. About 500 times the Southern Empire. Very odd.
Before I go into checking if this crazy value has an effect on defection, first lets see why this happens.
Here is the geographical advantage code:
C#:
private float GeographicalAdvantageForFaction(Settlement settlement, IFaction faction)
{
    Settlement factionMidSettlement = faction.FactionMidSettlement;
    float distance = Campaign.Current.Models.MapDistanceModel.GetDistance(settlement, factionMidSettlement);
    float distanceToClosestNonAllyFortification = faction.DistanceToClosestNonAllyFortification;
    if (faction.FactionMidSettlement.MapFaction != faction)
    {
        return Campaign.AverageDistanceBetweenTwoFortifications / (distance + 0.1f);
    }
    if (settlement.MapFaction == faction && distance < distanceToClosestNonAllyFortification)
    {
        return MathF.Clamp(Campaign.AverageDistanceBetweenTwoFortifications / (distanceToClosestNonAllyFortification - distance), 1f, 4f);
    }
    float num = (distance - distanceToClosestNonAllyFortification) / Campaign.AverageDistanceBetweenTwoFortifications;
    return 1f / (1f + num);
}

Now my personal opinion is this method, even ignoring the bug I am going to explain, is not well thought. The result of this method is used as a multiplier, which means you can get 10-40 times the values due to calculation difference thanks to `if` conditions here. But for the moment lets focus on the bug in this particular situation.
Remember that before defection, Northern Empire didn't have any settlements. So in that case what is the `FactionMidSettlement` for it? It is definitely not `null` (meaning nothing) because the code assumes it is not. So they know for sure it can't be `null`. My guess is that it still uses the old one. And in this particular situation, that old one must be either Diathma or Amprela.
Keeping that in mind, lets check first condition. Game executes first `return` line if faction's middle settlement is not part of the faction. Since Northern Empire has no settlements, we know for sure this is true. And the distance variable must be 0 for either Diathma or Amprela. Which means our result is `Campaign.AverageDistanceBetweenTwoFortifications / 0.1`. If the average distance between two fortifications in the game is calculated as 50 for example, we are returning 500. Considering rest of the code seems to be around 0-4 as value, you can see this is an unintentional result. And the reason why Northern Empire gets about 500 times more settlement value than Southern Empire.

Now lets check if this values actually have an effect on defection. The game calls 2 methods while calculating defection scores, `GetScoreOfClanToJoinKingdom` and `GetScoreOfKingdomToGetClan`. First one is the score of how much the clan wants to join the given kingdom and second one is the score of how much the given kingdom wants to get the clan.
As you can see from the values my mod logged, these are 820m and 48m in order.
Lets how much of these values come from the settlement values we have seen above. Since these 2 methods are quite complicated, I removed irrelevant parts.
First method:
C#:
public override float GetScoreOfClanToJoinKingdom(Clan clan, Kingdom kingdom)
{
    //...
    float num7 = clan.CalculateTotalSettlementBaseValue();
    float num8 = clan.CalculateTotalSettlementValueForFaction(kingdom);
    //...
    return num9 * MathF.Sqrt((float)commanderLimit) * num14 * 0.2f * (num5 * num6) + (clan.MapFaction.IsAtWarWith(kingdom) ? (num8 - num7) : 0f) + num10;
}
Southern Empire and Northern Empire are at war so we get `num8 - num7`, which can be seen from logs as 600k and 821m in order. So the first method returned 820m all thanks to settlement values.
Second method:
C#:
public override float GetScoreOfKingdomToGetClan(Kingdom kingdom, Clan clan)
{
    //..
    return (clan.CalculateTotalSettlementValueForFaction(kingdom) * 0.1f + num3) * num * num2 * num4;
}
In here I removed everything else but that is fine because as you can see almost all values are multiplied by each other. We know settlement value is 821m, which becomes 82m before being part of multiplication. `num3` here is total strength of the clan and checking other logs I can safely say it is well under 1m. So once again, majority of score comes from settlement values.

This particular situation seems to be a bug and will cause odd situations every now and then. However my personal opinion is whole method needs improvement. Settlement values are a big part of calculation for defection scores. Current calculation puts huge emphasis on geographical position and faction middle settlements. If your kingdom gets quite big and Vlandia has only couple settlements on the left side of the map, any settlement on the Vlandian border will get huge settlement values for Vlandia compare to you. Doesn't make any sense. Vlandia's middle settlement being closer doesn't mean Vlandia is closer. You can have 10 settlements closer than Vlandian ones.

So fingers crossed this will be addressed soon. In the mean time if anyone is interested, I can replace geographical advantage calculation with 1.7.2 one and release as a mod.
Awesome analysis Azakhi, glad you were able to pinpoint the bug in the code. Also i'm definitely interested to test out 1.8 with the mod to change the code to 1.7.2 geographical calc, would be good to check if the defection issue was the major drive in snowballing going way up in 1.8.

@SadShogun please review this analysis, Azakhi very clearly lays out the issue in the code and I think this is the path to the solution for defections.
 
I think I can conclude the geography is playing much bigger role in 1.8.0. Is this cause of the defection bug? I prefer to have a save and check values to make that conclusion. If I were to make a speculation, I would say there is an issue with this part of the c
This is indeed correct, while there are other contributing factors to defection the geographical advantage calculation affects the defection scores most. It is a simplified method to measure empire "expanse" i.e. if an empire is spread too thin / if it has "enclaves" etc. but it's simplicity creates some wild values in many unwanted cases.
We are looking into tweaking the geographical advantage modifier to something more stable.
 
This is indeed correct, while there are other contributing factors to defection the geographical advantage calculation affects the defection scores most. It is a simplified method to measure empire "expanse" i.e. if an empire is spread too thin / if it has "enclaves" etc. but it's simplicity creates some wild values in many unwanted cases.
We are looking into tweaking the geographical advantage modifier to something more stable.
Thanks for the reply. I get the idea behind it but I am not sure if looking at faction middle settlement is a good idea. IMHO if you guys want to keep it, at least its effect should be decreased. From my observations it seems a settlement very close to middle settlement can get values as high as 4-6 million. While a faction big enough will get less than 1m. This difference is quite big enough to completely wipe out all the other considerations.
 
@SadShogun
I think it would be 10000X better if the vassal just gets mad when they don't have a fief and after a certain amount of time they leave the faction, say 30 days. No % chances. Just make them leave the defeated faction and stay in the healthy factions, until they have no fief. Or if you must have some other means of defection, make it 100% transparent, interactive and preventable.
 
@SadShogun
I think it would be 10000X better if the vassal just gets mad when they don't have a fief and after a certain amount of time they leave the faction, say 30 days. No % chances. Just make them leave the defeated faction and stay in the healthy factions, until they have no fief. Or if you must have some other means of defection, make it 100% transparent, interactive and preventable.
+1
 
@SadShogun
I think it would be 10000X better if the vassal just gets mad when they don't have a fief and after a certain amount of time they leave the faction, say 30 days. No % chances. Just make them leave the defeated faction and stay in the healthy factions, until they have no fief. Or if you must have some other means of defection, make it 100% transparent, interactive and preventable.
Or, just an idea, do what Total War games do when you expand without a proper investment, corruption mechanic. Forcing AI lords to go back to patrolling their settlements can help with snowballing too.
 
Back
Top Bottom