From 6d16d577ab5046c71c64d8bafc054840b2f087e6 Mon Sep 17 00:00:00 2001 From: laochailan Date: Wed, 2 Jun 2021 08:15:26 +0200 Subject: [PATCH] fix a replay desync in the reimu_b code between clang and gcc The desync was caused by implementation specific behavior with complex numbers. Depending on the compiler, multiplying a complex-type number 1+0*I by -1 will either yield -1-0*I (gcc) or -1+0*I (clang). Complex functions with a branch cut along the negative real axis, such as carg will respond drastically to such a difference in zero sign. In the case of carg, the difference incurred by this is exactly M_TAU, which is irrelevant in most applications. In reimu_b, however there was one instance where the branch cut of carg was not handled (carg(a/b) != carg(a) - carg(b)). Even without the zero-sign inconsistency, this was a bug causing bullets to be absorbed by gaps that should not have been. This commit fixes said bug (and simplifies two instances of unproblematic but needlessly complicated math). The result is that (i) the gaps now function properly, and (ii) new replays do not desync between gcc and clang anymore. Note, that this change slightly breaks replay compatibility to older replays that showed the buggy behavior of the gaps. --- src/plrmodes/reimu_b.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/plrmodes/reimu_b.c b/src/plrmodes/reimu_b.c index c89087cd..8889cf47 100644 --- a/src/plrmodes/reimu_b.c +++ b/src/plrmodes/reimu_b.c @@ -330,7 +330,7 @@ static void reimu_dream_bullet_warp(ReimuBController *ctrl, Projectile *p, int * for(int i = 0; i < NUM_GAPS; ++i) { ReimuBGap *gap = ctrl->gaps.array + i; - real a = (carg(-gap->orientation) - carg(p->move.velocity)); + real a = carg(-gap->orientation/p->move.velocity); if(fabs(a) < M_TAU/3) { continue; @@ -359,11 +359,10 @@ static void reimu_dream_bullet_warp(ReimuBController *ctrl, Projectile *p, int * reimu_dream_spawn_warp_effect(gap->pos + gap->parallel_axis * GAP_LENGTH * (fract - 0.5), false); reimu_dream_spawn_warp_effect(o, true); - cmplx new_vel = -cabs(p->move.velocity) * ngap->orientation; - real angle_diff = carg(new_vel) - carg(p->move.velocity); + cmplx new_vel = cabs(p->move.velocity) * -ngap->orientation; - p->move.velocity *= cdir(angle_diff); - p->move.acceleration *= cdir(angle_diff); + p->move.acceleration *= cnormalize(new_vel/p->move.velocity); + p->move.velocity = new_vel; p->pos = o - p->move.velocity; --*warp_count; @@ -578,7 +577,7 @@ TASK(reimu_dream_shot_forward, { ReimuBController *ctrl; }) { for(int i = -1; i < 2; i += 2) { cmplx shot_dir = i * ((plr->inputflags & INFLAG_FOCUS) ? 1 : I); - cmplx spread_dir = shot_dir * cexp(I*M_PI*0.5); + cmplx spread_dir = shot_dir * I; for(int j = -1; j < 2; j += 2) { INVOKE_TASK(reimu_dream_ofuda,