gcsim icon indicating copy to clipboard operation
gcsim copied to clipboard

animation delay plays twice when buffs expire

Open kurt22i opened this issue 2 years ago • 4 comments

image

https://gcsim.app/viewer/share/perm_fj5xZjz-8DIyVgRn1jEY0

kurt22i avatar Apr 18 '22 02:04 kurt22i

Specifically, the issue I think is with https://github.com/genshinsim/gcsim/blob/2fa6d62f942589b81606e5107be8cae5943df947/pkg/simulation/run.go#L131

This if statement prevents delay from being added when the delay has already been done. However, the way it does this is by calling the delay function every frame - so when the delay function suddenly returns something different (say, paramita expired, and tao's frames changed), this statement no longer works correctly.

This can be fixed two ways: 1. "snapshot" the delay or 2. Prevent any and all delay from being added more than 1 frame after the last action, since this should never happen anyway (to my knowledge)

kurt22i avatar Apr 18 '22 02:04 kurt22i

AnimationCancelDelay function does not get called every frame though.

You can see here: https://github.com/genshinsim/gcsim/blob/2fa6d62f942589b81606e5107be8cae5943df947/pkg/simulation/run.go#L80-L84

If delay is valid, it sets s.skip and on the next frame if s.skip > 0 it will skip the rest of the block of code

Or did you mean something else?

srliao avatar Apr 18 '22 02:04 srliao

AnimationCancelDelay function does not get called every frame though.

You can see here:

https://github.com/genshinsim/gcsim/blob/2fa6d62f942589b81606e5107be8cae5943df947/pkg/simulation/run.go#L80-L84

If delay is valid, it sets s.skip and on the next frame if s.skip > 0 it will skip the rest of the block of code

Or did you mean something else?

You're right, it does not get called every frame like I'd thought.

It is still the problem statement though. I looked through debug mode (in gcsim and vscode), and what happens is this: reference config: https://gcsim.app/viewer/share/perm_g_8uOXDb8CF5cgJngLTc9

  • Frame 1056: Hu Tao executes a Charge Attack.
  • Frame 1058: Hu Tao's charge attack is able to be cancelled - this is the first "actionable" frame. s.lastActionUsedAt is set to 1058.
  • Frame 1059: Animation delay is triggered. The next action in queue is Burst, and s.C.AnimationCancelDelay(act.Typ, act.Param) returns 33, which is set as delay. A 33 frame delay begins.
  • Frame 1063: Paramita status expires.
  • Frame 1092: The 33 frame delay is complete. The code block is entered again, and delay is once again set to s.C.AnimationCancelDelay(act.Typ, act.Param). This time, however, it returns 41, since Paramita is no longer active. So, delay now = 41. Now, the problematic if statement is reached. Current frame - LastActionFrame = 1092-1058 = 34. If delay was still 33, it would return true and delay would be set to 0. However, since delay is 41, the if returns false, and delay is allowed to remain at 41. A second, incorrect animation delay of 41 frames begins.

kurt22i avatar Apr 18 '22 15:04 kurt22i

Putting this here, since it should be resolved by the refactor.

The animation delay gets triggered late when doing x -> burst cancels, but it only happens if the char doesn't have enough energy, so the delay is added after/when the particle is received.

In this config the 2nd burst should happen at 1503 regardless of how late the particle is. https://gcsim.app/viewer/share/perm_oIS3c4E4oOt7FClmgo12V

shizukayuki avatar May 01 '22 10:05 shizukayuki