-
Notifications
You must be signed in to change notification settings - Fork 87
Fix stuck soldiers leading to crashes in drawing code #1706
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Flow86
merged 22 commits into
Return-To-The-Roots:master
from
Flamefire:fix-soldier-crash
Nov 19, 2024
Merged
Fix stuck soldiers leading to crashes in drawing code #1706
Flow86
merged 22 commits into
Return-To-The-Roots:master
from
Flamefire:fix-soldier-crash
Nov 19, 2024
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
We usually want to browse the map anyway so just combine showing the window and revealing the map.
For debugging we often want to view a specific position. Make this easy by specifying the position as X-Y and Go-To with RETURN. TAB can be used to change between the edits which also clears the newly activated one such that new coordinates can be entered.
As we store GameObject references by pointer we must not copy them. The only exception is for soldiers where we convert a passive soldier to an attacker or defender by copying the base attributes. Mark any copy constructor we don't need as deleted and the others as explicit and protected.
In some cases we need to start at e.g. 1 not 0. Also make use of C++17 CTAD and remove the factory method.
391cdd6 to
7d400f6
Compare
Flow86
reviewed
Oct 16, 2024
Allow to easier understand the soldier logic by translating the comments and docstrings improving the wording while doing that. Also small (mostly syntactical) changes to follow the logic more easily
Better capture meaning as it implies an action not just a search.
`CancelSeaAttack` already calls `Abrogate`
Easier to understand and validate. Also refactor one use site a bit translating the comments.
Make the decisions clearer by showing the symmetries and the few different cases.
Translate all remaining comments.
Refactor code of type
```
if(arrived) {
//handle arrived
return
}
// handle not arrived
```
to
```
if(arrived) {
// handle arrived
} else {
// handle not arrived
}
```
Especially for small or similar code it emphasizes the either-or logic.
Communicate that those must not be NULL
The method is called when a free fight cannot be started not after it has ended, so reflect this in the name.
In some places we need e.g. "any water" terrain or in general a single or all descriptors matching a condition. Add `find` and `findAll` methods to the containers and add and use the explicit bool operator. Both in combination avoid using the raw `value` member of the `DescIdx` in most cases.
Also use the bool operator of `DescIdx` for invalid edge-indices.
Create 2 tests for free fights aborted by either the attacker or defender. This reproduces issue Return-To-The-Roots#1668
When one soldier involved in an upcoming free fight is waiting for the other and that aborts the free fight for any reason, e.g. when the spot becomes unreachable, the waiting soldier changes state but doesn't start moving and as he isn't moving already there is no event queued that would make it handle the new (moving) state. This leads to it being stuck there forever and also crashes the draw code which doesn't expect a supposedly walking soldier not having a walk event. Split the `AbortFreeFight` method in 2: - virtual method to determine the next state - base method to reset the free fight state for both soldiers and let them continue For the aborting soldier effectively nothing is changed. The other soldier gets a simulated walk event if he was waiting to handle the new state. As the 2 soldiers might get involved in another fight with each other both their "fight states" are cleaned up first to establish a valid state before the other soldier gets triggered.
7d400f6 to
3782e20
Compare
Member
|
rebase necessary, but other than that, lgtm |
Member
Author
|
Done. IIRC you can approve which stays active after the update/rebase such that it can be merged right away. |
Member
Author
|
@Flow86 ? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #1695
Fixes #1668
The cause is in both issues the same:
One soldier involved in an upcoming free fight is waiting for the other. That aborts the free fight as the spot becomes unreachable due to a removed road over water (either manually or by a captured building)
The waiting soldier changes state but doesn't start moving and as he isn't moving already there is no event queued that would make it handle the new (moving) state.
This leads to it being stuck there forever and also crashes the draw code which doesn't expect a supposedly walking soldier not having a walk-event.
Implemented solution:
Split the
AbortFreeFightmethod in 2:For the aborting soldier effectively nothing is changed.
The other soldier gets a simulated walk event if he was waiting to handle the new state.
As the 2 soldiers might get involved in another fight with each other both their "fight states" are cleaned up first to establish a valid state before the other soldier gets triggered.
As this was a bit tricky to find and create a test case to reproduce this I added quite a bit refactoring:
General:
rangeclass start iterating not only from zero but any valueDescIdxmatching conditions (useful especially for tests to quickly find e.g. water)DescriptionVectorto have astd::vectorbut indexed only byDescIdxTo understand what is happening with (fighting) soldiers I translated and fixed comments and documentation and some smaller refactoring to make it easier to read. Especially use of an enum instead of
uint8and references where NULL isn't allowed.