Fix: A queuing guest can ignore the next guest in the queue in certain circumstances (RCT2 bug)#19068
Conversation
| auto queueTileCentre = CoordsXY{ CoordsXY{ guest->NextLoc } + CoordsDirectionDelta[guest->PeepDirection] } | ||
| .ToTileCentre(); | ||
| guest->SetDestination(queueTileCentre); | ||
|
|
There was a problem hiding this comment.
The reason of adding this was for two reason, the first reason is that I have see that in RCT2 guests are aligned to the center of the queue after joining to the queue, but in OpenRCT2 guests are not aligned to the center of the queue after joining to the queue, instead guests are aligned when they reaches the second queue tile.
The second reason was that without this change, I have see that a guest can still ignore the next guest in the queue if a queue is configured in this way (tested with maximum game speed), but with the change I was unable to replicate the issue.
I think that aligning guests to the center after joining to the queue will ensure that PeepDirection always have a consistent state between the current guest and the next guest in the queue.
Edit: See my comment below, I have done more research and finally found the reason of why this is needed to be changed.
There was a problem hiding this comment.
This does direct the guest the middle of the tile, in both x and y direction. But if the first queue tile has peeps standing on it, that location will be occupied by other. I don’t know if this is a problem?
There was a problem hiding this comment.
I do not think that it should be a problem, the logic to update the queue position of a guest takes care about the distance of the next guest in the queue: guest will wait if the distance to the next guest in both axis (X,Y) is less or equals than 7 units no matters if both guests does not have the same direction, I think that this should not interfere with the guest AI (please see my explanation below).
I have done more research and I think that now I have the answer of why guests should be aligned to the middle of the first queue tile.
Sorry for my long text, but I prefer to explain all of my research in order to get more feedback if this issue can be solved in another way or if I have forgot something.
When a guest is walking, every time that guest reaches his destination, pathfinding is used to calculate the next tile that guest should walk (it is done by the CalculateNextDestination() method at GuestPathfinding.cpp) and the destination and direction of the guest is changed to the next tile.
CalculateNextDestination() always ends calling peep_move_one_tile() and peep_move_one_tile() will set the destination of the guest to the middle of the next tile, also peep_move_one_tile() will add an offset to the destination to make a spread effect along walking guests that are not queuing.
When a guest joins a queue, his destination will remain having the spread offset because at this point the guest has not yet reached his destination (remember that CalculateNextDestination() is only called when a guest reaches his destination), when guest finally reaches his destination pathfinding will change the destination of the guest to the middle of the second queue tile (because guest have the queuing state). [also this is the reason of why guests are aligned to the middle of the second queue tile instead of doing it at the first queue tile]
The spread offset added by peep_move_one_tile() is done within a square from the middle of the tile

Reason of why guests should always be aligned to the middle of the first queue tile:
If you configures a queue in this way:
There is a low chance that a guest can ignore the next guest in queue if certain conditions are meet:

Demonstration in-game, the next guest of brown guest is the purple guest:

These conditions cannot occurrs if guests are aligned to the middle of the first queue tile because both guests will have the same destination, and due to that, guest will not be able to reach the destination before the next guest in the queue because as I mentioned before, guest will wait if is too nearby to the next guest in the queue.
Thank you for reading this! I hope that this explanation can provide more context of the issue.
There was a problem hiding this comment.
This is some excellent work. Could you provide a super brief summary in a comment in the code at this point. Something like:
// Force set centre of tile to prevent issues with guests accidentally skipping the queue
51a4fcb to
383dc94
Compare
|
Hello! 👋 I rebased and tested with latest changes from develop, @Gymnasiast this PR is ready for review but I do not know what members of the dev team are more familiar with the AI logic, so I tagged you :( , can you please help me reviewing this PR and also requesting a review from another member of the dev team if necessary? Thank you! Also this PR needs a replay update but I do not know how I can achieve this, I will appreciate if someone can help me with this point. |
383dc94 to
7ed1b2e
Compare
| return false; | ||
|
|
||
| switch (guestNext->sprite_direction / 8) | ||
| switch (guestNext->PeepDirection) |
There was a problem hiding this comment.
Could you explain why the / 8 was dropped?
There was a problem hiding this comment.
I'm not too sure about this, but I have see in other parts of the code that sprite_direction >> 3 is used to set/calculate PeepDirection, and PeepDirection << 3 to set sprite_direction. If I am not wrong, sprite_direction / 8 is equivalent to sprite_direction >> 3. I do not know much about the logic of sprite_direction but I have see that a walking guest can have a sprite_direction of 0, 8, 16 and 24 (depending of the direction that guest is looking), and divide it by 8 will result in 0, 1, 2 and 3, comparing this with PeepDirection I see that both have the same value:
The reason of why I no use sprite_direction / 8 here is due to the issue that I explained before: a queuing guest can wait in the queue looking at another direction different from the real direction that guest is currently following, and because of that, sprite_direction may not always reflect the real direction of a queuing guest. In other hand, PeepDirection always have the real direction of a queuing guest.
I have made some tests to test the switch in all directions.
The purpose of the switch is to allow a guest to walk along the queue if the guest is before to the next guest.
To trigger the switch, both guests must have a distance greater than 7 units from any axis (X,Y), if distance from both guests is also greater than 13 units then both guest must be on the same tile. Also both guests must have the same direction.
I have aligned guests to the side of the queue instead of to the middle to accomplish with this condition.
-
Test
#2usingswitch(guestNext->PeepDirection)(same result as Test#1):

-
Test
#3simulating that the switch is not implemented correctly:

I have inverted all cases of the switch to do this test:
switch(...)
{
case 3:
...
break;
case 2:
...
break;
case 1:
...
break;
case 0:
...
break;
}There was a problem hiding this comment.
PeepDirection is the direction that the peep is travelling on the tile. sprite_direction is used for the actual sprite that is drawn. sprite_direction has much higher granularity as it is also used for vehicles but for peeps it is always just * 8, <<3 of the cardinal directions. So this change does make sense I think.
7ed1b2e to
61c6a33
Compare
|
You said it partially fixes #17814. Which bits does it fix and which bits doesn't it fix? |
61c6a33 to
b8229dd
Compare
duncanspumpkin
left a comment
There was a problem hiding this comment.
Could you add the comment mentioned and bump the network version in NetworkBase.cpp. I'll have to rerecord replays to get the tests to pass.
b8229dd to
a790c84
Compare
|
Sure, thank you @duncanspumpkin 🙂 . I have increased the network version and added the comment. |
- Feature: [#11269] Add properties for speed and length of vehicle animations. - Feature: [#15849] Objectives can now be set for up to 50000 guests. - Feature: [#18537] Add shift/control modifiers to window close buttons, closing all but the given window or all windows of the same type, respectively. - Feature: [#18732] [Plugin] API to get the guests thoughts. - Feature: [#18744] Cheat to allow using a regular path as a queue path. - Feature: [#19023] Add Canadian French translation. - Feature: [#19341] Add “All Scenery” tab to scenery window. - Feature: [#19378] Add command to combine CSG1i.DAT and CSG1.DAT. - Feature: [objects#226] Port RCT1 Corkscrew Coaster train. - Feature: [objects#229] Port RCT1 go karts with helmets. - Feature: [OpenMusic#20, OpenMusic#21] Added Blizzard and Extraterresterial ride music styles. - Improved: [#11473] Hot reload for plug-ins now works on macOS. - Improved: [#12466] RCT1 parks now use RCT1’s interest calculation algorithm. - Improved: [#14635] Scenery window now shows up to 255 scenery groups. - Improved: [#17288] Reorganise the order of shortcut keys in the Shortcut Keys window. - Improved: [#18706] Ability to view the list of contributors in-game. - Improved: [#18749] Ability to have 4 active awards for more than one month in a row. - Improved: [#18826] [Plugin] Added all actions and their documentation to plugin API. - Improved: [#18945] Languages can now fall back to other languages than English. - Improved: [#18970] Trying to load a non-park save will now display a context error. - Improved: [#18975] Add lift sprites for steep hills on the wooden roller coaster. - Improved: [#19044] Added special thanks to RMC and Wiegand to the About page. - Improved: [#19131] Track missing objects when selecting scenery groups in console. - Improved: [#19253] Queue junctions drawn properly when using regular paths as queue. Note: Requires using tile inspector to indicate railings can be used at T or X junctions. - Improved: [#19067] New Ride window now allows filtering similarly to Object Selection. - Improved: [#19272] Scenery window now allows filtering similarly to Object Selection. - Improved: [#19447] The control key now enables word jumping in text input fields. - Improved: [#19463] Added ‘W’ and ‘Y’ with circumflex to sprite font (for Welsh). - Improved: [#19549] Enable large address awareness for 32 bit Windows builds allowing to use 4 GiB of virtual memory. - Improved: [#19668] Decreased the minimum map size from 13 to 3. - Improved: [#19683] The delays for ride ratings to appear has been reduced drastically. - Improved: [#19697] “Show guest purchases” will now work in multiplayer. - Change: [#19018] Renamed actions to fit the naming scheme. - Change: [#19091] [Plugin] Add game action information to callback arguments of custom actions. - Change: [#19233] Reduce lift speed minimum and maximum values for “Classic Wooden Coaster”. - Removed: [#19520] Support for Windows Vista systems. - Fix: [#474] Mini golf window shows more players than there actually are (original bug). - Fix: [#592] Window scrollbar not able to navigate to the end of large lists. - Fix: [#7210] Land tile smoothing occurs with edge tiles (original bug). - Fix: [#17996] Finances window not cleared when starting some .park scenarios. - Fix: [#18260] Crash opening parks that have multiple tiles referencing the same banner entry. - Fix: [#18467] “Selected only” Object Selection filter is active in Track Designs Manager, and cannot be toggled. - Fix: [#18904] OpenRCT2 audio object accidentally exported in saves. - Fix: [#18905] Ride Construction window theme is not applied correctly. - Fix: [#18911] Mini Golf station does not draw correctly from all angles. - Fix: [#18971] New Game does not prompt for save before quitting. - Fix: [#18986] [Plugin] Sending remote scripts larger than 63KiB crashing all clients. - Fix: [#18994] Title music doesn’t start after enabling master volume. - Fix: [#19025] Park loan behaves inconsistently with non-round and out-of-bounds values. - Fix: [#19026] Park loan is clamped to a 32-bit integer. - Fix: [#19068] Guests may not join queues correctly. - Fix: [#19091] [Plugin] Remote plugins in multiplayer servers do not unload properly. - Fix: [#19112] Clearing the last character in the Object Selection filter does not properly reset it. - Fix: [#19112] Text boxes not updated with empty strings in Track List, Server List, and Start Server windows. - Fix: [#19114] [Plugin] ‘GameActionResult’ does not comply to API specification. - Fix: [#19136] SV6 saves with experimental RCT1 paths not imported correctly. - Fix: [#19243] .park scenarios don’t complete properly. - Fix: [#19250] MusicObjects do not free their preview images. - Fix: [#19292] Overflow in ‘totalRideValue’. - Fix: [#19339] Incorrect import of crashed particles from SV4. - Fix: [#19379] “No platforms” station style shows platforms on the Junior Roller Coaster. - Fix: [#19380] Startup crash when no sequences are installed and random sequences are enabled. - Fix: [#19391] String corruption caused by an improper buffer handling in ‘GfxWrapString’. - Fix: [#19434, #19509] Object types added by OpenRCT2 do not get removed when executing ‘remove_unused_objects’. - Fix: [#19475] Cannot increase loan when more than £1000 in debt. - Fix: [#19493] SV4 saves not importing the correct vehicle colours. - Fix: [#19517] Crash when peeps try to exit or enter hacked rides that have no waypoints specified. - Fix: [#19524] Staff counter shows incorrect values if there are more than 32767 staff members. - Fix: [#19574] Handle exits in null locations. - Fix: [#19641, #19643] Missing water tile in Infernal Views’ and Six Flags Holland’s river.
- Feature: [OpenRCT2#11269] Add properties for speed and length of vehicle animations. - Feature: [OpenRCT2#15849] Objectives can now be set for up to 50000 guests. - Feature: [OpenRCT2#18537] Add shift/control modifiers to window close buttons, closing all but the given window or all windows of the same type, respectively. - Feature: [OpenRCT2#18732] [Plugin] API to get the guests thoughts. - Feature: [OpenRCT2#18744] Cheat to allow using a regular path as a queue path. - Feature: [OpenRCT2#19023] Add Canadian French translation. - Feature: [OpenRCT2#19341] Add “All Scenery” tab to scenery window. - Feature: [OpenRCT2#19378] Add command to combine CSG1i.DAT and CSG1.DAT. - Feature: [objects#226] Port RCT1 Corkscrew Coaster train. - Feature: [objects#229] Port RCT1 go karts with helmets. - Feature: [OpenMusic#20, OpenMusic#21] Added Blizzard and Extraterresterial ride music styles. - Improved: [OpenRCT2#11473] Hot reload for plug-ins now works on macOS. - Improved: [OpenRCT2#12466] RCT1 parks now use RCT1’s interest calculation algorithm. - Improved: [OpenRCT2#14635] Scenery window now shows up to 255 scenery groups. - Improved: [OpenRCT2#17288] Reorganise the order of shortcut keys in the Shortcut Keys window. - Improved: [OpenRCT2#18706] Ability to view the list of contributors in-game. - Improved: [OpenRCT2#18749] Ability to have 4 active awards for more than one month in a row. - Improved: [OpenRCT2#18826] [Plugin] Added all actions and their documentation to plugin API. - Improved: [OpenRCT2#18945] Languages can now fall back to other languages than English. - Improved: [OpenRCT2#18970] Trying to load a non-park save will now display a context error. - Improved: [OpenRCT2#18975] Add lift sprites for steep hills on the wooden roller coaster. - Improved: [OpenRCT2#19044] Added special thanks to RMC and Wiegand to the About page. - Improved: [OpenRCT2#19131] Track missing objects when selecting scenery groups in console. - Improved: [OpenRCT2#19253] Queue junctions drawn properly when using regular paths as queue. Note: Requires using tile inspector to indicate railings can be used at T or X junctions. - Improved: [OpenRCT2#19067] New Ride window now allows filtering similarly to Object Selection. - Improved: [OpenRCT2#19272] Scenery window now allows filtering similarly to Object Selection. - Improved: [OpenRCT2#19447] The control key now enables word jumping in text input fields. - Improved: [OpenRCT2#19463] Added ‘W’ and ‘Y’ with circumflex to sprite font (for Welsh). - Improved: [OpenRCT2#19549] Enable large address awareness for 32 bit Windows builds allowing to use 4 GiB of virtual memory. - Improved: [OpenRCT2#19668] Decreased the minimum map size from 13 to 3. - Improved: [OpenRCT2#19683] The delays for ride ratings to appear has been reduced drastically. - Improved: [OpenRCT2#19697] “Show guest purchases” will now work in multiplayer. - Change: [OpenRCT2#19018] Renamed actions to fit the naming scheme. - Change: [OpenRCT2#19091] [Plugin] Add game action information to callback arguments of custom actions. - Change: [OpenRCT2#19233] Reduce lift speed minimum and maximum values for “Classic Wooden Coaster”. - Removed: [OpenRCT2#19520] Support for Windows Vista systems. - Fix: [OpenRCT2#474] Mini golf window shows more players than there actually are (original bug). - Fix: [OpenRCT2#592] Window scrollbar not able to navigate to the end of large lists. - Fix: [OpenRCT2#7210] Land tile smoothing occurs with edge tiles (original bug). - Fix: [OpenRCT2#17996] Finances window not cleared when starting some .park scenarios. - Fix: [OpenRCT2#18260] Crash opening parks that have multiple tiles referencing the same banner entry. - Fix: [OpenRCT2#18467] “Selected only” Object Selection filter is active in Track Designs Manager, and cannot be toggled. - Fix: [OpenRCT2#18904] OpenRCT2 audio object accidentally exported in saves. - Fix: [OpenRCT2#18905] Ride Construction window theme is not applied correctly. - Fix: [OpenRCT2#18911] Mini Golf station does not draw correctly from all angles. - Fix: [OpenRCT2#18971] New Game does not prompt for save before quitting. - Fix: [OpenRCT2#18986] [Plugin] Sending remote scripts larger than 63KiB crashing all clients. - Fix: [OpenRCT2#18994] Title music doesn’t start after enabling master volume. - Fix: [OpenRCT2#19025] Park loan behaves inconsistently with non-round and out-of-bounds values. - Fix: [OpenRCT2#19026] Park loan is clamped to a 32-bit integer. - Fix: [OpenRCT2#19068] Guests may not join queues correctly. - Fix: [OpenRCT2#19091] [Plugin] Remote plugins in multiplayer servers do not unload properly. - Fix: [OpenRCT2#19112] Clearing the last character in the Object Selection filter does not properly reset it. - Fix: [OpenRCT2#19112] Text boxes not updated with empty strings in Track List, Server List, and Start Server windows. - Fix: [OpenRCT2#19114] [Plugin] ‘GameActionResult’ does not comply to API specification. - Fix: [OpenRCT2#19136] SV6 saves with experimental RCT1 paths not imported correctly. - Fix: [OpenRCT2#19243] .park scenarios don’t complete properly. - Fix: [OpenRCT2#19250] MusicObjects do not free their preview images. - Fix: [OpenRCT2#19292] Overflow in ‘totalRideValue’. - Fix: [OpenRCT2#19339] Incorrect import of crashed particles from SV4. - Fix: [OpenRCT2#19379] “No platforms” station style shows platforms on the Junior Roller Coaster. - Fix: [OpenRCT2#19380] Startup crash when no sequences are installed and random sequences are enabled. - Fix: [OpenRCT2#19391] String corruption caused by an improper buffer handling in ‘GfxWrapString’. - Fix: [OpenRCT2#19434, OpenRCT2#19509] Object types added by OpenRCT2 do not get removed when executing ‘remove_unused_objects’. - Fix: [OpenRCT2#19475] Cannot increase loan when more than £1000 in debt. - Fix: [OpenRCT2#19493] SV4 saves not importing the correct vehicle colours. - Fix: [OpenRCT2#19517] Crash when peeps try to exit or enter hacked rides that have no waypoints specified. - Fix: [OpenRCT2#19524] Staff counter shows incorrect values if there are more than 32767 staff members. - Fix: [OpenRCT2#19574] Handle exits in null locations. - Fix: [OpenRCT2#19641, OpenRCT2#19643] Missing water tile in Infernal Views’ and Six Flags Holland’s river.
|
I just got round to reading the comments and investigation here today, but it is great work! |










After some research I think that I have found the issue that I have seen in the original game (and also present in OpenRCT2) while testing my previous PR, this is related to the logic to update the queue position of a guest.
Explanation:
The logic to update the queue position of a guest uses the direction of the next guest in the queue to determine if there is space available to walk and also to check if the current guest is still before the next guest in the queue, and according to what I understand, this logic uses the
sprite_directionto determine if both guests have the same direction:OpenRCT2/src/openrct2/entity/Guest.cpp
Lines 7328 to 7331 in 8495dbf
If both guests have the same direction, then the next part of the code is used to ensure that the current guest is always before the next guest in the queue:
OpenRCT2/src/openrct2/entity/Guest.cpp
Lines 7332 to 7350 in 8495dbf
The issue here is, when the next guest is looking at another direction different from the current guest, and the next guest is not too nearby to the current guest, the condition
sprite_direction != guestNext->sprite_directionwill be true and method will return with false, allowing the current guest to walk ignoring the next guest in the queue because the logic to ensure that a guest is always before to the next guest in the queue will not be reached.Circumstances needed to reproduce this
Gif:

How I fixed it:
I have used
PeepDirectionto compare directions between both guests instead of usingsprite_directionI do not know much about the game logic and I may be wrong, but after digging some methods used by the AI, I have found the method
CalculateNextDestinationinGuestPathfinding.cppand as I understood, this calculates the next queue tile that guest should move in, and after thatpeep_move_one_tileis called with the direction that guest should move to the next tile.The important thing here is inside the
peep_move_one_tilemethod, this set thePeepDirectionwith the direction that guest is currently following.OpenRCT2/src/openrct2/peep/GuestPathfinding.cpp
Lines 137 to 138 in 8495dbf
I think that this variable should always have the real direction that guest is following, and it can be used to check the direction of a guest.Edit: After more research, I am now sure that
PeepDirectionalways have the real direction that guest is currently following.I have made some tests and confirmed that using
PeepDirectionfixes the issue.You can use this save game to reproduce this:
bug-guest-ignore-next-guest.zip
This partially fixes #17814 , but there is some remaining things that should be fixed and I will make another PR later to try to address remaining things.
If something is needed to be changed please let me know, thank you!