Closed ryzom-pipeline closed 7 years ago
Original comment by Guillaume DUPUY (Bitbucket: [Guillaume DUPUY](https://bitbucket.org/Guillaume DUPUY), ).
https://bitbucket.org/ryzom/ryzomcore/pull-requests/143/fix-a-bug-where-a-monster-could-be-stuck/diff contains the fix
Original comment by Cédric Ochs (Bitbucket: [Cédric OCHS](https://bitbucket.org/Cédric OCHS), ).
Nice catch :p I proposed a little change for the pull request to avoid twice the same code :)
Original comment by Guillaume DUPUY (Bitbucket: [Guillaume DUPUY](https://bitbucket.org/Guillaume DUPUY), ).
Fixed by PR 143
Original report by Guillaume DUPUY (Bitbucket: [Guillaume DUPUY](https://bitbucket.org/Guillaume DUPUY), ).
If a monster is under a root / sleep (mezz) / stun effect at the moment he drops agro on the player, he will never come back to his original spawn (unless if attacked). In the case of an aggressive monster, he'll never attack anything ever again (and since nothing will attack him, he'll freeze there for eternity).
Steps to reproduce :
What happens is fairly simple : after the aggro is dropped, the monster profile is switched to a CBotProfileReturnAfterFightFauna, who calls CMovementMagnet::update(waitTime = 0);
This function is responsible for finding a path to original spawn point and moving the bot back to the point. On first call, whether we are in state Movement_Anim / Movement_Wait_Anim, we immediately go to BeginMove, who sets _Speed to the current walkSpeed().
After that, the state is now Movement_Move, who calculates the distance the bot has been able to travel since last call, and move him accordingly. To calculate the distance, it simply does :
The problem is simple : _Speed is only set during BeginMove, and when we drop aggro (so, at first call of this function), our current walkSpeed() is 0, because we are rooted, stunned, or sleeping. After the first call, we calculate a dist of 0, and try to move accordingly. Obviously, this doesn't do anything, so we are stuck in an infinite loop.
Note that there is a way to go back to BeginAnim (who will go to BeginMove, and reset the _Speed), but we need for that
distToDest<=0
, which is never true (assuming we aren't at dest the first time, since we don't move we will never be at dest), orlastPos.quickDistTo(_BotFauna.pos())<(dist*0.5f)
. The left operand will be 0 (since lastPos = _BotFauna.pos() because we don't move), and right operand will be 0 (since dist is 0), and it's a strict compare.My fix is easy, simply update the _Speed at each call.
Note : if you want to test on a ryzomcore server, i've recreated a stun brick (well, modified the acid damage brick to be a stun brick because i'm lazy) thanks to trial and error (& looking at the parsing code), you can find it here : http://pastebin.com/WRGevn0B
Note 2 : This does not happens with spawned monster because they use a CBotProfileReturnAfterFightNpc (because they are an eventNpcGroup), which use a CBotProfileFollowPos instead of a CMagnetMovement, which does use the current walkSpeed() to calculate dist :