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
Fix lm cache movement #17159
Fix lm cache movement #17159
Conversation
@@ -214,8 +214,6 @@ public int Facing | |||
{ | |||
if (FromCell == ToCell) | |||
return new[] { Pair.New(FromCell, FromSubCell) }; | |||
if (CanEnterCell(ToCell)) | |||
return new[] { Pair.New(ToCell, ToSubCell) }; | |||
|
|||
return new[] { Pair.New(FromCell, FromSubCell), Pair.New(ToCell, ToSubCell) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be return new[] { Pair.New(ToCell, ToSubCell) };
now if we want the unit behaviour to remain the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the idea behind the old code was that units occupied both the cell they were leaving and the cell they were entering while moving. This avoids units stacking on top of eachother if the movement is stopped (e.g. EMP) before it has left the starting cell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is obvious that that was the idea. I'm just pointing out that that is not how units have been behaving all this time—probably never have—because CanEnterCell(ToCell)
is always true. It only gets set after checking whether the next cell in the path is accessible and then the actor immediately lays claim to it so no other actor can block it anymore.
The idea was also probably a bad one to begin with. It has no effect on the case where units stop before it has left the starting cell, because such a window doesn't exist in the first place. The new mobile.ToCell
is set in the same tick as the MovePart
is queued (which is not interruptible and always the first childactivity when it is queued) so an EMPed unit will always end up in ToCell
no matter when the movement was stopped. If it hasn't started moving yet, ToCell
is equal to FromCell
.
What this will affect is movement of groups of units. Because units in a column will have to wait till the unit in front of it has completely finished moving to the next cell before starting its move, it means tight formations are no longer possible. There will be odd gaps in the formation and starting a movement will be slow and chaotic.
In any case, this doesn't seem like the kind of behavioural change you would want to do this short before a release as part of a simple bugfix that is not, on the face of it, really related. And since it is just half a line difference to keep the status quo behaviour (intentional or not) while still fixing the bug, it seems prudent to do so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we don't allow changing subcells while remaining in the same cell, (FromCell == ToCell) => (FromSubCell == ToSubCell)
right? In that case this entire method can simplify down to return new[] { Pair.New(ToCell, ToSubCell) };
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we don't allow changing subcells while remaining in the same cell,
(FromCell == ToCell) => (FromSubCell == ToSubCell)
right? In that case this entire method can simplify down toreturn new[] { Pair.New(ToCell, ToSubCell) };
.
Looks like it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That means that CanEnterCell(ToCell) is not always true
Correct. This has always had the definition quirk of “I can’t enter if I’m already in it”, and things break when this is changed. IIRC CanExistInCell was added to handle the “already in or can move into cell” case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The transition of OccupiedCells
when moving between two cells looks like this on the previous release (20190314). Imo it was best to look at it before we added the locomotor cache in case of any regressions.
FromCell
ToCell
FromCell-ToCell
FromCell
It only spends a short time on ToCell
and the majority on FromCell-ToCell
while the move happens. I.e. in only got one line of ToCell
logged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you update the transition list to note where the values of fromcell and tocell are the same or different?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only time the fromcell and tocell are the same is when FromCell
is printed.
This is how the code looks:
public Pair<CPos, SubCell>[] OccupiedCells()
{
if (FromCell == ToCell)
{
Debug.WriteLine("FromCell");
return new[] { Pair.New(FromCell, FromSubCell) };
}
if (CanEnterCell(ToCell))
{
Debug.WriteLine("ToCell");
return new[] { Pair.New(ToCell, ToSubCell) };
}
Debug.WriteLine("FromCell-ToCell");
return new[] { Pair.New(FromCell, FromSubCell), Pair.New(ToCell, ToSubCell) };
}
Complete log for a move, only one actor on the map and dev visibility (for enabling radar).
...
FromCell
FromCell
FromCell
ToCell
FromCell-ToCell
FromCell-ToCell
FromCell-ToCell
FromCell-ToCell
FromCell-ToCell
FromCell-ToCell
FromCell-ToCell
FromCell-ToCell
FromCell-ToCell
FromCell-ToCell
FromCell
FromCell
FromCell
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we aware of all the possible downstream affects from changing the fundamental definition of what cells a mobile unit occupies to consuming code? It feels like asking for regressions.
→ #17290
8cb211e
to
435d3db
Compare
435d3db
to
6e02d13
Compare
FWIW I have tested this in RA and TS without experiencing any de-sync crashes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code changes here now look sensible, so we are probably best with merging this and letting it be tested by a wider audience.
The if (CanEnterCell(ToCell))
branch this removes has been present since the very early days, and doesn't make a lot of sense - actors should either be in a single cell (when ToCell == FromCell
) or spanning both cells - I can't think of a logically valid case where we would want to return only the ToCell
when FromCell
is different. Removing this may actually fix some hidden bugs.
@@ -270,6 +270,7 @@ public interface IActorMap | |||
WDist LargestActorRadius { get; } | |||
WDist LargestBlockingActorRadius { get; } | |||
|
|||
void MarkAsDirty(IOccupySpace ios); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MarkAsDirty
isn't very descriptive. How about something like (Dirty|Update|Refresh)OccupiedCells
?
6e02d13
to
03f5e5c
Compare
updated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good and I didn't experience any desyncs or other crashes.
Fixes #17089