From 910a51b290ee60da5f482f1892e1f59a8ea52bf0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 2 Nov 2021 18:42:25 +0100 Subject: [PATCH] - proper actor handling in all of SOP interpolation --- source/games/sw/src/interpso.cpp | 113 +++++++++++++++---------------- source/games/sw/src/interpso.h | 4 +- source/games/sw/src/sprite.cpp | 2 +- source/games/sw/src/track.cpp | 33 +++++---- source/games/sw/src/weapon.cpp | 11 +-- 5 files changed, 78 insertions(+), 85 deletions(-) diff --git a/source/games/sw/src/interpso.cpp b/source/games/sw/src/interpso.cpp index 451c39b5b..eac8e1215 100644 --- a/source/games/sw/src/interpso.cpp +++ b/source/games/sw/src/interpso.cpp @@ -71,11 +71,11 @@ static struct so_interp bool hasvator; } so_interpdata[MAX_SECTOR_OBJECTS]; -static int &getvalue(int element, bool write) +static int &getvalue(so_interp::interp_data& element, bool write) { static int scratch; - int index = element & soi_base; - int type = element & ~soi_base; + int index = element.curelement & soi_base; + int type = element.curelement & ~soi_base; switch (type) { case soi_wallx: @@ -95,17 +95,21 @@ static int &getvalue(int element, bool write) case soi_soz: return SectorObject[index].zmid; case soi_sprx: - return sprite[index].x; + if (element.actorofang) + return element.actorofang->s().x; case soi_spry: - return sprite[index].y; + if (element.actorofang) + return element.actorofang->s().y; case soi_sprz: - return sprite[index].z; + if (element.actorofang) + return element.actorofang->s().z; default: - return scratch; + break; } + return scratch; } -static void so_setpointinterpolation(so_interp *interp, int element) +static void so_setpointinterpolation(so_interp *interp, int element, DSWActor* actor = nullptr) { int32_t i; if (interp->numinterpolations >= SO_MAXINTERPOLATIONS) @@ -113,27 +117,27 @@ static void so_setpointinterpolation(so_interp *interp, int element) for (i = 0; i < interp->numinterpolations; i++) { - if (interp->data[i].curelement == element) + if (interp->data[i].curelement == element && interp->data[i].actorofang == actor) return; } so_interp::interp_data *data = &interp->data[interp->numinterpolations++]; data->curelement = element; + data->actorofang = actor; data->oldipos = data->lastipos = - data->lastoldipos = getvalue(element, false); - data->actorofang = nullptr; + data->lastoldipos = getvalue(*data, false); } -static void so_setspriteanginterpolation(so_interp *interp, int32_t spritenum) +static void so_setspriteanginterpolation(so_interp *interp, DSWActor* actor) { int32_t i; if (interp->numinterpolations >= SO_MAXINTERPOLATIONS) return; for (i = 0; i < interp->numinterpolations; i++) - if (interp->data[i].curelement == soi_sprang && interp->data[i].actorofang->GetSpriteIndex() == spritenum) + if (interp->data[i].curelement == soi_sprang && interp->data[i].actorofang == actor) return; so_interp::interp_data *data = &interp->data[interp->numinterpolations++]; @@ -141,31 +145,22 @@ static void so_setspriteanginterpolation(so_interp *interp, int32_t spritenum) data->curelement = soi_sprang; data->oldipos = data->lastipos = - data->lastoldipos = sprite[spritenum].ang; + data->lastoldipos = actor->s().ang; data->lastangdiff = 0; - data->actorofang = &swActors[spritenum]; + data->actorofang = actor; } // Covers points and angles altogether -static void so_stopdatainterpolation(so_interp *interp, int element) +static void so_stopdatainterpolation(so_interp *interp, int element, DSWActor* actor) { - int32_t i; - - for (i = 0; i < interp->numinterpolations; i++) - { - if (interp->data[i].curelement == -1) - { - if (interp->data[i].actorofang->GetSpriteIndex() == element) break; - } - else if (interp->data[i].curelement == element) - break; - - } - - if (i == interp->numinterpolations) - return; - - interp->data[i] = interp->data[--(interp->numinterpolations)]; + for (int i = 0; i < interp->numinterpolations; i++) + { + if (interp->data[i].curelement == element && interp->data[i].actorofang == actor) + { + interp->data[i] = interp->data[--(interp->numinterpolations)]; + break; + } + } } void so_addinterpolation(SECTOR_OBJECTp sop) @@ -197,10 +192,10 @@ void so_addinterpolation(SECTOR_OBJECTp sop) } } - int i; - SectIterator it(int(*sectp - sector)); - while ((i = it.NextIndex()) >= 0) - if (sprite[i].statnum == STAT_VATOR && SP_TAG1(sprite+i) == SECT_VATOR) + + SWSectIterator it(int(*sectp - sector)); + while (auto actor = it.Next()) + if (actor->s().statnum == STAT_VATOR && SP_TAG1(&actor->s()) == SECT_VATOR) break; interp->hasvator |= (i >= 0); } @@ -221,28 +216,26 @@ void so_addinterpolation(SECTOR_OBJECTp sop) interp->lasttic = synctics; } -void so_setspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp) +void so_setspriteinterpolation(SECTOR_OBJECTp sop, DSWActor* actor) { so_interp *interp = &so_interpdata[sop - SectorObject]; - int snum = int(sp - sprite); - - so_setpointinterpolation(interp, snum | soi_sprx); - so_setpointinterpolation(interp, snum | soi_spry); + + so_setpointinterpolation(interp, soi_sprx, actor); + so_setpointinterpolation(interp, soi_spry, actor); if (!interp->hasvator) - so_setpointinterpolation(interp, snum | soi_sprz); - so_setspriteanginterpolation(interp, snum); + so_setpointinterpolation(interp, soi_sprz, actor); + so_setspriteanginterpolation(interp, actor); } -void so_stopspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp) +void so_stopspriteinterpolation(SECTOR_OBJECTp sop, DSWActor *actor) { so_interp *interp = &so_interpdata[sop - SectorObject]; - int snum = int(sp - sprite); - so_stopdatainterpolation(interp, snum | soi_sprx); - so_stopdatainterpolation(interp, snum | soi_spry); + so_stopdatainterpolation(interp, soi_sprx, actor); + so_stopdatainterpolation(interp, soi_spry, actor); if (!interp->hasvator) - so_stopdatainterpolation(interp, snum | soi_sprz); - so_stopdatainterpolation(interp, -1); + so_stopdatainterpolation(interp, soi_sprz, actor); + so_stopdatainterpolation(interp, soi_sprang, actor); } void so_setinterpolationtics(SECTOR_OBJECTp sop, int16_t locktics) @@ -281,7 +274,7 @@ void so_updateinterpolations(void) // Stick at beginning of domovethings data->oldipos = data->actorofang->s().ang; } else - data->oldipos = getvalue(data->curelement, false); + data->oldipos = getvalue(*data, false); if (!interpolating) data->lastipos = data->lastoldipos = data->oldipos; @@ -310,7 +303,7 @@ void so_dointerpolations(int32_t smoothratio) // Stick at b for (i = 0; i < interp->numinterpolations; i++) interp->data[i].bakipos = (interp->data[i].curelement == soi_sprang) ? interp->data[i].actorofang->s().ang : - getvalue(interp->data[i].curelement, false); + getvalue(interp->data[i], false); if (interp->tic == 0) // Only if the SO has just moved { @@ -359,13 +352,13 @@ void so_dointerpolations(int32_t smoothratio) // Stick at b // TODO: It could be better. In particular, it could be better // to conditionally disable the interpolation from analyzesprites // instead, using TSPRITE info if possible. - if (data->curelement >= soi_sprx) + if (data->curelement >= soi_sprx && data->curelement <= soi_sprz) { - int32_t sprnum = data->curelement & soi_base; - USERp u = User[sprnum].Data(); - if (u && (sprite[sprnum].statnum != STAT_DEFAULT) && - ((TEST(u->Flags, SPR_SKIP4) && (sprite[sprnum].statnum <= STAT_SKIP4_INTERP_END)) || - (TEST(u->Flags, SPR_SKIP2) && (sprite[sprnum].statnum <= STAT_SKIP2_INTERP_END)))) + auto actor = data->actorofang; + USERp u = actor->u(); + if (u && (actor->s().statnum != STAT_DEFAULT) && + ((TEST(u->Flags, SPR_SKIP4) && (actor->s().statnum <= STAT_SKIP4_INTERP_END)) || + (TEST(u->Flags, SPR_SKIP2) && (actor->s().statnum <= STAT_SKIP2_INTERP_END)))) continue; } @@ -374,7 +367,7 @@ void so_dointerpolations(int32_t smoothratio) // Stick at b else { delta = data->lastipos - data->lastoldipos; - getvalue(data->curelement, true) = data->lastoldipos + MulScale(delta, ratio, 16); + getvalue(*data, true) = data->lastoldipos + MulScale(delta, ratio, 16); } } } @@ -398,7 +391,7 @@ void so_restoreinterpolations(void) // Stick at end of drawscree if (data->curelement == soi_sprang) data->actorofang->s().ang = data->bakipos; else - getvalue(data->curelement, true) = data->bakipos; + getvalue(*data, true) = data->bakipos; } } diff --git a/source/games/sw/src/interpso.h b/source/games/sw/src/interpso.h index 616efe59e..0ca0bd8ca 100644 --- a/source/games/sw/src/interpso.h +++ b/source/games/sw/src/interpso.h @@ -32,8 +32,8 @@ BEGIN_SW_NS extern int32_t so_numinterpolations; void so_addinterpolation(SECTOR_OBJECTp sop); -void so_setspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp); -void so_stopspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp); +void so_setspriteinterpolation(SECTOR_OBJECTp sop, DSWActor *sp); +void so_stopspriteinterpolation(SECTOR_OBJECTp sop, DSWActor *sp); void so_setinterpolationangdiff(SECTOR_OBJECTp sop, int16_t angdiff); void so_setinterpolationtics(SECTOR_OBJECTp sop, int16_t locktics); void so_updateinterpolations(void); diff --git a/source/games/sw/src/sprite.cpp b/source/games/sw/src/sprite.cpp index 88efcc730..afabc277b 100644 --- a/source/games/sw/src/sprite.cpp +++ b/source/games/sw/src/sprite.cpp @@ -688,7 +688,7 @@ void KillSprite(int16_t SpriteNum) sn--; ASSERT(sop->sp_num[sn] >= 0); - so_stopspriteinterpolation(sop, sp); + so_stopspriteinterpolation(sop, actor); // replace the one to be deleted with the last ndx sop->sp_num[FoundSpriteNdx] = sop->sp_num[sn]; // the last ndx is not -1 diff --git a/source/games/sw/src/track.cpp b/source/games/sw/src/track.cpp index 617a3bdac..27af1349f 100644 --- a/source/games/sw/src/track.cpp +++ b/source/games/sw/src/track.cpp @@ -884,14 +884,12 @@ SectorObjectSetupBounds(SECTOR_OBJECTp sop) for (i = 0; i < (int)SIZ(StatList); i++) { - StatIterator it(StatList[i]); - while ((sp_num = it.NextIndex()) >= 0) + SWStatIterator it(StatList[i]); + while (auto itActor = it.Next()) { - SPRITEp sp = &sprite[sp_num]; + SPRITEp sp = &itActor->s(); USERp u; - ASSERT(sp_num != -1); - if (sp->x > xlow && sp->x < xhigh && sp->y > ylow && sp->y < yhigh) { // some delete sprites ride others don't @@ -901,10 +899,10 @@ SectorObjectSetupBounds(SECTOR_OBJECTp sop) continue; } - if (User[sp_num].Data() == nullptr) - u = SpawnUser(sp_num, 0, nullptr); + if (!itActor->hasU()) + u = SpawnUser(itActor, 0, nullptr); else - u = User[sp_num].Data(); + u = itActor->u(); u->RotNum = 0; @@ -934,14 +932,14 @@ SectorObjectSetupBounds(SECTOR_OBJECTp sop) sop->clipbox_ang[sop->clipbox_num] = getincangle(ang2, sop->ang); sop->clipbox_num++; - KillSprite(sp_num); + KillActor(itActor); goto cont; } case SO_SHOOT_POINT: - sp->owner = -1; - change_sprite_stat(sp_num, STAT_SO_SHOOT_POINT); + ClearOwner(itActor); + change_actor_stat(itActor, STAT_SO_SHOOT_POINT); RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN); break; default: @@ -973,8 +971,8 @@ SectorObjectSetupBounds(SECTOR_OBJECTp sop) ASSERT(sn < (int)SIZ(sop->sp_num) - 1); - sop->sp_num[sn] = sp_num; - so_setspriteinterpolation(sop, sp); + sop->sp_num[sn] = itActor->GetSpriteIndex(); + so_setspriteinterpolation(sop, itActor); if (!TEST(sop->flags, SOBJ_SPRITE_OBJ)) @@ -2030,8 +2028,9 @@ void KillSectorObjectSprites(SECTOR_OBJECTp sop) for (i = 0; sop->sp_num[i] != -1; i++) { - sp = &sprite[sop->sp_num[i]]; - u = User[sop->sp_num[i]].Data(); + auto actor = &swActors[sop->sp_num[i]]; + sp = &actor->s(); + u = actor->u(); // not a part of the so anymore RESET(u->Flags, SPR_SO_ATTACHED); @@ -2039,8 +2038,8 @@ void KillSectorObjectSprites(SECTOR_OBJECTp sop) if (sp->picnum == ST1 && sp->hitag == SPAWN_SPOT) continue; - so_stopspriteinterpolation(sop, sp); - KillSprite(sop->sp_num[i]); + so_stopspriteinterpolation(sop, actor); + KillActor(actor); } // clear the list diff --git a/source/games/sw/src/weapon.cpp b/source/games/sw/src/weapon.cpp index b3fe0eddf..2d24f8693 100644 --- a/source/games/sw/src/weapon.cpp +++ b/source/games/sw/src/weapon.cpp @@ -11323,8 +11323,9 @@ SpawnMicroExp(int16_t Weapon) int AddSpriteToSectorObject(short SpriteNum, SECTOR_OBJECTp sop) { - SPRITEp sp = &sprite[SpriteNum]; - USERp u = User[SpriteNum].Data(); + auto actor = &swActors[SpriteNum]; + SPRITEp sp = &actor->s(); + USERp u = actor->u(); unsigned sn; // make sure it has a user @@ -11341,8 +11342,8 @@ AddSpriteToSectorObject(short SpriteNum, SECTOR_OBJECTp sop) } ASSERT(sn < SIZ(sop->sp_num) - 1); - sop->sp_num[sn] = SpriteNum; - so_setspriteinterpolation(sop, sp); + sop->sp_num[sn] = actor->GetSpriteIndex(); + so_setspriteinterpolation(sop, actor); SET(u->Flags, SPR_ON_SO_SECTOR|SPR_SO_ATTACHED); @@ -11409,7 +11410,7 @@ SpawnBigGunFlames(int16_t Weapon, int16_t Operator, SECTOR_OBJECTp sop) ASSERT(sn < SIZ(sop->sp_num) - 1); sop->sp_num[sn] = explosion; - so_setspriteinterpolation(sop, exp); + so_setspriteinterpolation(sop, &swActors[explosion]); SET(eu->Flags, TEST(u->Flags, SPR_ON_SO_SECTOR|SPR_SO_ATTACHED));