I'm posting this here on advice from RayBo. I believe I have located the reason why the numbers in the HUD resources panel are way off what they should be for the totals.
I'm going to reference my decompiled code here. I assume the function names line up with the actual code, although of course the line numbers won't. So when I refer to line numbers, I am referring to the code snippets pasted here.
Firstly, in the DailyUpdate function, the plot costs do not seem to be taken into account at all.
EDIT : I have discovered that this is intentional, as the plot costs are handled the by the plots themselves (although a little inconsistently it seems). This explains why people see their resource totals go down even when there is a surplus of that resource. I have discussed the problems with this in post 10.
The second issue is in the AdjustSettlementVirtualResource function.
In the following, I'll refer to Scrap as Level 1, Building Materials, Organic Materials, Machine Parts and Rare Materials as Level 2 and the rest as Level 3.
The DailyUpdate code runs through all resources, including the Level 2 and 3 resources. For each one it works out the production amount by getting the amount produced and subtracting the costs (though not the plot costs currently). It does that for each settlement. Then it deals with deficits by taking from the production value of other resources. So we end up with a ProductionRates array with how much of the current resource is produced in each settlement (after costs have been paid). This production is then added to the virtual resource storage, by calling ProduceSettlementVirtualResource, which checks for capacity and in turn calls AdjustSettlementVirtualResource to make the necessary change.
Here is the relevant code from AdjustSettlementVirtualResource
abBypassGroupHandling is always passed as false from ProduceResource.
First Scrap (Level 1) is passed through. It does use use Base Value as Capacity, so 1526 and 1527 are not run. In 1532 it's iCategoryIndex is -1, which is the iVRCategory flag. AdjustValue is true, and AjustMax is not, so 1535 is run and this is key - it tells it not to change that virtual resource. Line 1541 is not run because my scrap category is set to complex, so bMakeChange stays false. ICategoryIndex is still -1, so 1546 does not run. Since bMakeChange is false, the rest does not run and the resource is not added. This is all CORRECT for Scrap (Level 1).
Next, Building Materials (Level 2) is passed through. When passed, abAdjustValue is true and abAdjustMax is false, but for BuildingMaterials DoesUseBaseValueAsCapacity is true, so 1526 runs, setting abAdjustMax to true. This means bMakeChange stays true for Building Materials. Building Materials also has iCategoryIndex of 0, so it runs the HandleAdjustSettlementVirtualResourceForGroupedStorage.
This function is designed to add the resource to the parent groupings as well. So when it is run on the Building Materials pass, it adds the value to scrap as well. This is INCORRECT. Building Materials then has bMakeChange as true, so the amount is added to the Building Materials virtual storage. This is also INCORRECT.
The other Level 2 materials are passed through with the same problem. By now, Scrap Level 3 has had the full amount added to it, as have all Level 2 materials. Actually, it's not quite the full amount because the function GetSpecificDailyCosts returns 0 for level 2 materials and scrap, so the full production amount without any costs has been added.
Now the Level 1 materials get passed through (one at a time). Their abAdjustValue and abAdjustMax are both true, so bMakeChange is set to true. Their iCategoryIndex is also greater than 0, so HandleAdjustSettlementVirtualResourceForGroupedStorage is run as well. This function adds the amount to the levels above the Level 3 resource, so for Wood it adds it to Building Materials and Scrap as well. This is actually CORRECT, but because Scrap and Building Materials were also incorrectly added to on the Building Materials pass, both scrap and Building Materials have had it added twice (actually, a little more the first time because costs are not taken into account).
So, my conclusion is when level 2 materials are passed through, they should not have bMakeChange set as true and should not run HandleAdjustSettlementVirtualResourceForGroupedStorage. This will mean when a Level 3 resource goes through, it will correctly add it to that resource, the level above it, and the scrap resource, only once, taking costs into account. I believe this was the intended function. This could be achieved by firstly having iCategoryIndex test for > 0, not >= 0 in line 1545, as Level 2 resources will return a iCategoryIndex of 0 at that stage. That means the Handle function will not run for them. We also need the Level 2 categories to be set to false. If it were changed to have the DoesUseBaseValueAsCapacity return true for them, that would fix the problem. But I don't know if that causes problems, because I don't know how that value is used elsewhere.
I have tested these fixes by copying the relevant functions so I can modify them and call my modified ones. The fixes make the DailyUpdate add resources work as intended (including not going over the virtual limit). The resource numbers are then correct on the HUD.
I think correcting this could fix quite a few problems people have been having with resources, because currently the numbers for Level 2 and Level 1 resources aren't accurate, which probably messes up other calculations the code is doing.
This is all with scrap category set to complex. I'm not totally sure yet how the other categories are supposed to work. My guess is when it is set to moderate, none of the Level 3 resources are recorded and when it is set as Simple, nothing below level 3 is recorded and when you switch between them it changes all the values. However, this isn't what actually happens, so I don't know if it's a bug or I don't understand the intention.
EDIT : I should mention here that for simplicity I have only been testing this using one settlement. I know each settlement stores its own values,but I'm not sure if the HUD gets the caravan network values by adding them all up, or if that number is stored somewhere as well. FURTHER EDIT : the caravan network values are obtained by adding the individual settlement values.
ALSO, see post 7 for another potential fix for a different HUD problem.
I'm going to reference my decompiled code here. I assume the function names line up with the actual code, although of course the line numbers won't. So when I refer to line numbers, I am referring to the code snippets pasted here.
EDIT : I have discovered that this is intentional, as the plot costs are handled the by the plots themselves (although a little inconsistently it seems). This explains why people see their resource totals go down even when there is a surplus of that resource. I have discussed the problems with this in post 10.
The second issue is in the AdjustSettlementVirtualResource function.
In the following, I'll refer to Scrap as Level 1, Building Materials, Organic Materials, Machine Parts and Rare Materials as Level 2 and the rest as Level 3.
The DailyUpdate code runs through all resources, including the Level 2 and 3 resources. For each one it works out the production amount by getting the amount produced and subtracting the costs (though not the plot costs currently). It does that for each settlement. Then it deals with deficits by taking from the production value of other resources. So we end up with a ProductionRates array with how much of the current resource is produced in each settlement (after costs have been paid). This production is then added to the virtual resource storage, by calling ProduceSettlementVirtualResource, which checks for capacity and in turn calls AdjustSettlementVirtualResource to make the necessary change.
Here is the relevant code from AdjustSettlementVirtualResource
abBypassGroupHandling is always passed as false from ProduceResource.
First Scrap (Level 1) is passed through. It does use use Base Value as Capacity, so 1526 and 1527 are not run. In 1532 it's iCategoryIndex is -1, which is the iVRCategory flag. AdjustValue is true, and AjustMax is not, so 1535 is run and this is key - it tells it not to change that virtual resource. Line 1541 is not run because my scrap category is set to complex, so bMakeChange stays false. ICategoryIndex is still -1, so 1546 does not run. Since bMakeChange is false, the rest does not run and the resource is not added. This is all CORRECT for Scrap (Level 1).
Next, Building Materials (Level 2) is passed through. When passed, abAdjustValue is true and abAdjustMax is false, but for BuildingMaterials DoesUseBaseValueAsCapacity is true, so 1526 runs, setting abAdjustMax to true. This means bMakeChange stays true for Building Materials. Building Materials also has iCategoryIndex of 0, so it runs the HandleAdjustSettlementVirtualResourceForGroupedStorage.
This function is designed to add the resource to the parent groupings as well. So when it is run on the Building Materials pass, it adds the value to scrap as well. This is INCORRECT. Building Materials then has bMakeChange as true, so the amount is added to the Building Materials virtual storage. This is also INCORRECT.
The other Level 2 materials are passed through with the same problem. By now, Scrap Level 3 has had the full amount added to it, as have all Level 2 materials. Actually, it's not quite the full amount because the function GetSpecificDailyCosts returns 0 for level 2 materials and scrap, so the full production amount without any costs has been added.
Now the Level 1 materials get passed through (one at a time). Their abAdjustValue and abAdjustMax are both true, so bMakeChange is set to true. Their iCategoryIndex is also greater than 0, so HandleAdjustSettlementVirtualResourceForGroupedStorage is run as well. This function adds the amount to the levels above the Level 3 resource, so for Wood it adds it to Building Materials and Scrap as well. This is actually CORRECT, but because Scrap and Building Materials were also incorrectly added to on the Building Materials pass, both scrap and Building Materials have had it added twice (actually, a little more the first time because costs are not taken into account).
So, my conclusion is when level 2 materials are passed through, they should not have bMakeChange set as true and should not run HandleAdjustSettlementVirtualResourceForGroupedStorage. This will mean when a Level 3 resource goes through, it will correctly add it to that resource, the level above it, and the scrap resource, only once, taking costs into account. I believe this was the intended function. This could be achieved by firstly having iCategoryIndex test for > 0, not >= 0 in line 1545, as Level 2 resources will return a iCategoryIndex of 0 at that stage. That means the Handle function will not run for them. We also need the Level 2 categories to be set to false. If it were changed to have the DoesUseBaseValueAsCapacity return true for them, that would fix the problem. But I don't know if that causes problems, because I don't know how that value is used elsewhere.
I have tested these fixes by copying the relevant functions so I can modify them and call my modified ones. The fixes make the DailyUpdate add resources work as intended (including not going over the virtual limit). The resource numbers are then correct on the HUD.
I think correcting this could fix quite a few problems people have been having with resources, because currently the numbers for Level 2 and Level 1 resources aren't accurate, which probably messes up other calculations the code is doing.
This is all with scrap category set to complex. I'm not totally sure yet how the other categories are supposed to work. My guess is when it is set to moderate, none of the Level 3 resources are recorded and when it is set as Simple, nothing below level 3 is recorded and when you switch between them it changes all the values. However, this isn't what actually happens, so I don't know if it's a bug or I don't understand the intention.
EDIT : I should mention here that for simplicity I have only been testing this using one settlement. I know each settlement stores its own values,
ALSO, see post 7 for another potential fix for a different HUD problem.
Attachments
Last edited: