mirror of
https://github.com/ZDoom/Raze.git
synced 2025-02-20 18:42:26 +00:00
- proper actor handling in all of SOP interpolation
This commit is contained in:
parent
e4e164a07f
commit
910a51b290
5 changed files with 78 additions and 85 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
Loading…
Reference in a new issue