Fix wrongly shown soldiers & Refactor HQ start wares and inventory handling#1910
Conversation
This is especially important during skipping which expects that each gameframe is actually executed.
When soldiers in the leave queue get canceled, e.g. because a fight started so we re-add all leaving aggressive defenders, the counts of soldiers gets off: - Adding a soldier to leave queue will remove it from the real count only, not the visual count: He is still in there - When he is removed from the queue after going out the visual count is decreased - When adding it back before he left we must not increase the visual count Currently it checked if the soldier is in the leave queue but at that point he isn't anymore so the check never succeeds. Add new callback to notify when a figure has left the queue.
When we clear the inventory or start with an empty one there is no need to call this.
`GoodsAndPeopleCounts` is now both a `GoodCounts` and `PeopleCounts` allowing them to be used as required. Refactor the misnamed `AddGoods` to 3 `AddToInventory` methods to avoid parts of the work if only people or goods are added. Ensure visibility of write-accessors for `Inventory` is protecting against mistakes e.g. with armored soldier counts.
270380f to
d9a95b2
Compare
This is not always desired, especially in the tests. So add an extra method for that to allow adding only wares/people when desired.
…roops When a defender is requested then a) Leaving agg. defenders are stopped b) A defender is chosen from remaining troops This might "convert" and agg. defender to a defender. As this is kind of a sub-case of the existing one, merge them with a data-param. Similar the handling for warehouses and military buildings needs to be checked, so make that another param.
Soldiers are stopped when a defender is coming out. If no defender is found the leaving soldiers are checked. So it is better to first stop the leaving soldiers and then choose from all of them. Also remove `nofAggressiveDefender::NeedForHomeDefence` which is a wrapper to `InformTargetsAboutCancelling` only used in a single place which is now redundant.
The check assumes only active soldiers start in "Job-state". This state is set when a figure arrived at its goal, and immediately for those not having a "fixed" goal, like attacking soldiers. But it also applies to e.g. trade-donkeys. So check for soldiers directly. Also rename `NoDefender` to `ResetDefender` to clarify meaning and remove the check for leaving defenders which cannot be met: The method is called before the defender is called.
This is so specific to the call site that it should be inline which explains the reasoning better.
d9a95b2 to
8d86aac
Compare
- Pin used actions - Add explicit permissions - Update actions where required & possible for Node 20 deprecation
| std::vector<MapPoint> hqPositions = hqPositions_; | ||
| if(world_.GetGGS().randomStartPosition) | ||
| RANDOM_SHUFFLE2(hqPositions, 0); | ||
| if(!PlaceHQs()) |
There was a problem hiding this comment.
that RANDOM_SHUFFLE2 only changes the copy of the hqPoisitions - not the ones used then in PlaceHQs?
There was a problem hiding this comment.
Oh, that was supposed to go one method deeper, yes.
Fixed
There was a problem hiding this comment.
I still have one question here. hqPositions_ is now not "in sync" with the positions "used" by PlaceHQs later.
I know its initialized via PlaceObjects and then read here in PlaceHQs. I only ask since its maybe "later" used and creates weirdness since they're not the positions used to place?
There was a problem hiding this comment.
That method is static and accepts the HQ positions as a parameter, so it doesn't care about the member variable.
If this was an issue it would already have been: We didn't shuffle the member variable before either, only a copy (the parameter passed to the static method)
There was a problem hiding this comment.
I renamed the method to get HQ positions from the loader to reflect what it actually returns and added a test which would have detected the shuffle issue
2f50d23 to
667b4b3
Compare
667b4b3 to
4c001d1
Compare
4c001d1 to
a411a93
Compare
When soldiers in the leave queue get cancelled, e.g. because a fight
started so we re-add all leaving aggressive defenders, the counts of
soldiers gets off:
only, not the visual count: He is still in there
Currently it checked if the soldier is in the leave queue but at that
point he isn't anymore so the check never succeeds.
Add new callback to notify when a figure has left the queue.
Fixes #1907
I added tests for this issue and possible related issues I could see by inspecting the called code.
For that some additional changes were required:
InventoryviaAddGoods. So you needed to create an "inventory" of soldiers to pass toAddGoods?GoodsAndPeopleCounts
is now both aGoodCountsandPeopleCountsallowing them to be used as required. RenamedAddGoodsto 3AddToInventory` methods to avoid parts of the work if only people or goods are added.Factory functions for adding single job/people types
The additional tests yielded further changes to address this:
When a defender is called it stops leaving attackers and aggressive defenders (interception enemy attackers) from leaving the house.
The callback to provide a defender will use leaving soldiers if necessary. So we can stop them first to always have those we will stop anyway.
As that method to stop them was hard to name and was now only called in a single place with assumptions at both sides I eventually just inlined it.
And it turns out the check for
figureState == jobStateisn't enough: It would also trigger for trade donkeys.So check for (active) soldiers directly.
WEIRD: When we call a defender we cancel all attacking soldiers (normal attackers and aggressive defenders) but when a defender is called it is still possible that new aggressive defenders are called and leaving. But it seems this is the original behavior. cc @Spikeone after Discord discussion