- proper actor handling in all of SOP interpolation

This commit is contained in:
Christoph Oelckers 2021-11-02 18:42:25 +01:00
parent e4e164a07f
commit 910a51b290
5 changed files with 78 additions and 85 deletions

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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));