- actProcessSprites done.

# Conflicts:
#	source/games/blood/src/actor.cpp

# Conflicts:
#	source/games/blood/src/actor.cpp

# Conflicts:
#	source/games/blood/src/actor.cpp
This commit is contained in:
Christoph Oelckers 2020-12-05 16:23:01 +01:00
parent 7faebdcbf1
commit 2cfb4f908e
3 changed files with 258 additions and 204 deletions

View file

@ -5903,167 +5903,165 @@ static void actCheckThings()
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void MakeSplash(DBloodActor *actor); static void actCheckProjectiles()
void actProcessSprites(void)
{ {
#ifdef NOONE_EXTENSIONS
if (gModernMap) nnExtProcessSuperSprites();
#endif
actCheckProximity();
actCheckThings();
int nSprite;
BloodStatIterator it(kStatProjectile); BloodStatIterator it(kStatProjectile);
while ((nSprite = it.NextIndex()) >= 0) while (auto actor = it.Next())
{ {
spritetype *pSprite = &sprite[nSprite]; spritetype* pSprite = &actor->s();
if (pSprite->flags & 32) if (pSprite->flags & 32)
continue; continue;
viewBackupSpriteLoc(nSprite, pSprite); viewBackupSpriteLoc(actor);
int hit = MoveMissile(&bloodActors[nSprite]); int hit = MoveMissile(actor);
if (hit >= 0) if (hit >= 0) actImpactMissile(&bloodActors[pSprite->index], hit);
actImpactMissile(&bloodActors[pSprite->index], hit);
} }
it.Reset(kStatExplosion); }
while ((nSprite = it.NextIndex()) >= 0)
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void actCheckExplosion()
{
BloodStatIterator it(kStatExplosion);
while (auto actor = it.Next())
{ {
uint8_t sectmap[(kMaxSectors+7)>>3]; spritetype* pSprite = &actor->s();
spritetype *pSprite = &sprite[nSprite];
if (pSprite->flags & 32) if (pSprite->flags & 32)
continue; continue;
int nOwner = pSprite->owner;
auto pOwner = nOwner == -1? nullptr : &bloodActors[pSprite->owner]; if (!actor->hasX()) continue;
XSPRITE* pXSprite = &actor->x();
auto Owner = actor->GetOwner();
auto pOwner = Owner ? &Owner->s() : nullptr;
int nType = pSprite->type; int nType = pSprite->type;
assert(nType >= 0 && nType < kExplodeMax); assert(nType >= 0 && nType < kExplodeMax);
const EXPLOSION *pExplodeInfo = &explodeInfo[nType]; const EXPLOSION* pExplodeInfo = &explodeInfo[nType];
int nXSprite = pSprite->extra;
assert(nXSprite > 0 && nXSprite < kMaxXSprites);
XSPRITE *pXSprite = &xsprite[nXSprite];
int x = pSprite->x; int x = pSprite->x;
int y = pSprite->y; int y = pSprite->y;
int z = pSprite->z; int z = pSprite->z;
int nSector = pSprite->sectnum; int nSector = pSprite->sectnum;
int radius = pExplodeInfo->radius; int radius = pExplodeInfo->radius;
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
// Allow to override explosion radius by data4 field of any sprite which have statnum 2 set in editor // Allow to override explosion radius by data4 field of any sprite which have statnum 2 set in editor
// or of Hidden Exploder. // or of Hidden Exploder.
if (gModernMap && pXSprite->data4 > 0) if (gModernMap && pXSprite->data4 > 0)
radius = pXSprite->data4; radius = pXSprite->data4;
#endif #endif
uint8_t sectormap[(kMaxSectors + 7) >> 3];
// GetClosestSpriteSectors() has issues checking some sectors due to optimizations // GetClosestSpriteSectors() has issues checking some sectors due to optimizations
// the new flag newSectCheckMethod for GetClosestSpriteSectors() does rectify these issues, but this may cause unintended side effects for level scripted explosions // the new flag newSectCheckMethod for GetClosestSpriteSectors() does rectify these issues, but this may cause unintended side effects for level scripted explosions
// so only allow this new checking method for dude spawned explosions // so only allow this new checking method for dude spawned explosions
short gAffectedXWalls[kMaxXWalls]; short gAffectedXWalls[kMaxXWalls];
const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode(); // use new sector checking logic const bool newSectCheckMethod = !cl_bloodvanillaexplosions && pOwner && pOwner->IsDudeActor() && !VanillaMode(); // use new sector checking logic
GetClosestSpriteSectors(nSector, x, y, radius, sectmap, gAffectedXWalls, newSectCheckMethod); GetClosestSpriteSectors(nSector, x, y, radius, sectormap, gAffectedXWalls, newSectCheckMethod);
for (int i = 0; i < kMaxXWalls; i++) for (int i = 0; i < kMaxXWalls; i++)
{ {
int nWall = gAffectedXWalls[i]; int nWall = gAffectedXWalls[i];
if (nWall == -1) if (nWall == -1)
break; break;
XWALL *pXWall = &xwall[wall[nWall].extra]; XWALL* pXWall = &xwall[wall[nWall].extra];
trTriggerWall(nWall, pXWall, kCmdWallImpact); trTriggerWall(nWall, pXWall, kCmdWallImpact);
} }
int nSprite2;
StatIterator it1(kStatDude);
while ((nSprite2 = it1.NextIndex()) >= 0)
{
DBloodActor* act2 = &bloodActors[nSprite2];
spritetype *pDude = &act2->s();
if (pDude->flags & 32) BloodStatIterator it1(kStatDude);
continue; while (auto dudeactor = it1.Next())
if (TestBitString(sectmap, pDude->sectnum)) {
spritetype* pDude = &dudeactor->s();
if (pDude->flags & 32) continue;
if (TestBitString(sectormap, pDude->sectnum))
{ {
if (pXSprite->data1 && CheckProximity(pDude, x, y, z, nSector, radius)) if (pXSprite->data1 && CheckProximity(pDude, x, y, z, nSector, radius))
{ {
if (pExplodeInfo->dmg && pXSprite->target == 0) if (pExplodeInfo->dmg && pXSprite->target == 0)
{ {
pXSprite->target = 1; pXSprite->target = 1;
actDamageSprite(nOwner, pDude, kDamageFall, (pExplodeInfo->dmg+Random(pExplodeInfo->dmgRng))<<4); actDamageSprite(Owner, dudeactor, kDamageFall, (pExplodeInfo->dmg + Random(pExplodeInfo->dmgRng)) << 4);
} }
if (pExplodeInfo->dmgType) if (pExplodeInfo->dmgType) ConcussSprite(actor, dudeactor, x, y, z, pExplodeInfo->dmgType);
ConcussSprite(pOwner, act2, x, y, z, pExplodeInfo->dmgType);
if (pExplodeInfo->burnTime) if (pExplodeInfo->burnTime)
{ {
assert(pDude->extra > 0 && pDude->extra < kMaxXSprites); assert(dudeactor->hasX());
XSPRITE *pXDude = &xsprite[pDude->extra]; XSPRITE* pXDude = &xsprite[pDude->extra];
if (!pXDude->burnTime) if (!pXDude->burnTime) evPost(dudeactor, 0, kCallbackFXFlameLick);
evPost(nSprite2, 3, 0, kCallbackFXFlameLick); actBurnSprite(Owner, dudeactor, pExplodeInfo->burnTime << 2);
actBurnSprite(pSprite->owner, pXDude, pExplodeInfo->burnTime<<2);
} }
} }
} }
} }
it1.Reset(kStatThing);
while ((nSprite2 = it1.NextIndex()) >= 0)
{
auto act2 = &bloodActors[nSprite2];
spritetype *pThing = &sprite[nSprite2];
if (pThing->flags & 32) it1.Reset(kStatThing);
continue; while (auto thingactor = it1.Next())
if (TestBitString(sectmap, pThing->sectnum)) {
spritetype* pThing = &thingactor->s();
if (pThing->flags & 32) continue;
if (TestBitString(sectormap, pThing->sectnum))
{ {
if (pXSprite->data1 && CheckProximity(pThing, x, y, z, nSector, radius)) if (pXSprite->data1 && CheckProximity(pThing, x, y, z, nSector, radius) && thingactor->hasX())
{ {
XSPRITE *pXSprite2 = &xsprite[pThing->extra]; XSPRITE* pXThing = &thingactor->x();
if (!pXSprite2->locked) if (!pXThing->locked)
{ {
if (pExplodeInfo->dmgType) if (pExplodeInfo->dmgType) ConcussSprite(Owner, thingactor, x, y, z, pExplodeInfo->dmgType);
ConcussSprite(pOwner, act2, x, y, z, pExplodeInfo->dmgType);
if (pExplodeInfo->burnTime) if (pExplodeInfo->burnTime)
{ {
assert(pThing->extra > 0 && pThing->extra < kMaxXSprites);
XSPRITE *pXThing = &xsprite[pThing->extra];
if (pThing->type == kThingTNTBarrel && !pXThing->burnTime) if (pThing->type == kThingTNTBarrel && !pXThing->burnTime)
evPost(nSprite2, 3, 0, kCallbackFXFlameLick); evPost(thingactor, 0, kCallbackFXFlameLick);
actBurnSprite(pSprite->owner, pXThing, pExplodeInfo->burnTime<<2); actBurnSprite(Owner, thingactor, pExplodeInfo->burnTime << 2);
} }
} }
} }
} }
} }
for (int p = connecthead; p >= 0; p = connectpoint2[p]) for (int p = connecthead; p >= 0; p = connectpoint2[p])
{ {
spritetype *pSprite2 = gPlayer[p].pSprite; spritetype* pSprite2 = gPlayer[p].pSprite;
int dx = (x - pSprite2->x)>>4; int dx = (x - pSprite2->x) >> 4;
int dy = (y - pSprite2->y)>>4; int dy = (y - pSprite2->y) >> 4;
int dz = (z - pSprite2->z)>>8; int dz = (z - pSprite2->z) >> 8;
int nDist = dx*dx+dy*dy+dz*dz+0x40000; int nDist = dx * dx + dy * dy + dz * dz + 0x40000;
int t = DivScale(pXSprite->data2, nDist, 16); int t = DivScale(pXSprite->data2, nDist, 16);
gPlayer[p].flickerEffect += t; gPlayer[p].flickerEffect += t;
} }
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
if (pXSprite->data1 != 0) { if (pXSprite->data1 != 0)
{
// add impulse for sprites from physics list // add impulse for sprites from physics list
if (gPhysSpritesCount > 0 && pExplodeInfo->dmgType != 0) { if (gPhysSpritesCount > 0 && pExplodeInfo->dmgType != 0)
for (int i = 0; i < gPhysSpritesCount; i++) { {
for (int i = 0; i < gPhysSpritesCount; i++)
{
if (gPhysSpritesList[i] == -1) continue; if (gPhysSpritesList[i] == -1) continue;
else if (sprite[gPhysSpritesList[i]].sectnum < 0 || (sprite[gPhysSpritesList[i]].flags & kHitagFree) != 0) auto physactor = &bloodActors[gPhysSpritesList[i]];
continue; spritetype* pDebris = &physactor->s();
if (pDebris->sectnum < 0 || (pDebris->flags & kHitagFree) != 0) continue;
spritetype* pDebris = &sprite[gPhysSpritesList[i]]; if (!TestBitString(sectormap, pDebris->sectnum) || !CheckProximity(pDebris, x, y, z, nSector, radius)) continue;
if (!TestBitString(sectmap, pDebris->sectnum) || !CheckProximity(pDebris, x, y, z, nSector, radius)) continue; else debrisConcuss(Owner ? Owner->s().index : -1, i, x, y, z, pExplodeInfo->dmgType);
else debrisConcuss(nOwner, i, x, y, z, pExplodeInfo->dmgType);
} }
} }
// trigger sprites from impact list // trigger sprites from impact list
if (gImpactSpritesCount > 0) { if (gImpactSpritesCount > 0) {
for (int i = 0; i < gImpactSpritesCount; i++) { for (int i = 0; i < gImpactSpritesCount; i++)
{
if (gImpactSpritesList[i] == -1) continue; if (gImpactSpritesList[i] == -1) continue;
else if (sprite[gImpactSpritesList[i]].sectnum < 0 || (sprite[gImpactSpritesList[i]].flags & kHitagFree) != 0) else if (sprite[gImpactSpritesList[i]].sectnum < 0 || (sprite[gImpactSpritesList[i]].flags & kHitagFree) != 0)
continue; continue;
@ -6072,87 +6070,105 @@ void actProcessSprites(void)
if (pImpact->extra <= 0) if (pImpact->extra <= 0)
continue; continue;
XSPRITE* pXImpact = &xsprite[pImpact->extra]; XSPRITE* pXImpact = &xsprite[pImpact->extra];
if (/*pXImpact->state == pXImpact->restState ||*/ !TestBitString(sectmap, pImpact->sectnum) || !CheckProximity(pImpact, x, y, z, nSector, radius)) if (/*pXImpact->state == pXImpact->restState ||*/ !TestBitString(sectormap, pImpact->sectnum) || !CheckProximity(pImpact, x, y, z, nSector, radius))
continue; continue;
trTriggerSprite(pImpact->index, pXImpact, kCmdSpriteImpact); trTriggerSprite(pImpact->index, pXImpact, kCmdSpriteImpact);
} }
} }
} }
if (!gModernMap || !(pSprite->flags & kModernTypeFlag1)) { if (!gModernMap || !(pSprite->flags & kModernTypeFlag1))
// if data4 > 0, do not remove explosion. This can be useful when designer wants put explosion generator in map manually {
// via sprite statnum 2. // if data4 > 0, do not remove explosion. This can be useful when designer wants put explosion generator in map manually via sprite statnum 2.
pXSprite->data1 = ClipLow(pXSprite->data1 - 4, 0); pXSprite->data1 = ClipLow(pXSprite->data1 - 4, 0);
pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0); pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0);
pXSprite->data3 = ClipLow(pXSprite->data3 - 4, 0); pXSprite->data3 = ClipLow(pXSprite->data3 - 4, 0);
} }
#else #else
pXSprite->data1 = ClipLow(pXSprite->data1 - 4, 0); pXSprite->data1 = ClipLow(pXSprite->data1 - 4, 0);
pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0); pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0);
pXSprite->data3 = ClipLow(pXSprite->data3 - 4, 0); pXSprite->data3 = ClipLow(pXSprite->data3 - 4, 0);
#endif #endif
if (pXSprite->data1 == 0 && pXSprite->data2 == 0 && pXSprite->data3 == 0 && seqGetStatus(3, nXSprite) < 0) if (pXSprite->data1 == 0 && pXSprite->data2 == 0 && pXSprite->data3 == 0 && seqGetStatus(actor) < 0)
actPostSprite(nSprite, kStatFree); actPostSprite(actor, kStatFree);
} }
}
it.Reset(kStatTraps);
while ((nSprite = it.NextIndex()) >= 0)
{
spritetype *pSprite = &sprite[nSprite];
if (pSprite->flags & 32) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void actCheckTraps()
{
BloodStatIterator it(kStatTraps);
while (auto actor = it.Next())
{
spritetype* pSprite = &actor->s();
if ((pSprite->flags & 32) || !actor->hasX())
continue; continue;
int nXSprite = pSprite->extra;
//assert(nXSprite > 0 && nXSprite < kMaxXSprites); XSPRITE* pXSprite = &actor->x();
if (nXSprite <= 0 || nXSprite >= kMaxXSprites)
continue;
XSPRITE *pXSprite = &xsprite[nXSprite];
switch (pSprite->type) { switch (pSprite->type) {
case kTrapSawCircular: case kTrapSawCircular:
pXSprite->data2 = ClipLow(pXSprite->data2-4, 0); pXSprite->data2 = ClipLow(pXSprite->data2 - 4, 0);
break; break;
case kTrapFlame: case kTrapFlame:
if (pXSprite->state && seqGetStatus(3, nXSprite) < 0) { if (pXSprite->state && seqGetStatus(actor) < 0)
{
int x = pSprite->x; int x = pSprite->x;
int y = pSprite->y; int y = pSprite->y;
int z = pSprite->z; int z = pSprite->z;
int t = (pXSprite->data1<<23)/120; int t = (pXSprite->data1 << 23) / 120;
int dx = MulScale(t, Cos(pSprite->ang), 30); int dx = MulScale(t, Cos(pSprite->ang), 30);
int dy = MulScale(t, Sin(pSprite->ang), 30); int dy = MulScale(t, Sin(pSprite->ang), 30);
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
spritetype *pFX = gFX.fxSpawn(FX_32, pSprite->sectnum, x, y, z, 0); auto pFX = gFX.fxSpawnActor(FX_32, pSprite->sectnum, x, y, z, 0);
if (pFX) if (pFX)
{ {
xvel[pFX->index] = dx + Random2(0x8888); pFX->xvel() = dx + Random2(0x8888);
yvel[pFX->index] = dy + Random2(0x8888); pFX->yvel() = dy + Random2(0x8888);
zvel[pFX->index] = Random2(0x8888); pFX->zvel() = Random2(0x8888);
} }
x += (dx/2)>>12; x += (dx / 2) >> 12;
y += (dy/2)>>12; y += (dy / 2) >> 12;
} }
dy = SinScale16(pSprite->ang); dy = SinScale16(pSprite->ang);
dx = CosScale16(pSprite->ang); dx = CosScale16(pSprite->ang);
gVectorData[kVectorTchernobogBurn].maxDist = pXSprite->data1<<9; gVectorData[kVectorTchernobogBurn].maxDist = pXSprite->data1 << 9;
actFireVector(pSprite, 0, 0, dx, dy, Random2(0x8888), kVectorTchernobogBurn); actFireVector(pSprite, 0, 0, dx, dy, Random2(0x8888), kVectorTchernobogBurn);
} }
break; break;
} }
} }
it.Reset(kStatDude); }
while ((nSprite = it.NextIndex()) >= 0)
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void actCheckDudes()
{
BloodStatIterator it(kStatDude);
while (auto actor = it.Next())
{ {
spritetype *pSprite = &sprite[nSprite]; spritetype* pSprite = &actor->s();
if (pSprite->flags & 32) if (pSprite->flags & 32)
continue; continue;
int nXSprite = pSprite->extra;
if (nXSprite > 0) if (actor->hasX())
{ {
XSPRITE *pXSprite = &xsprite[nXSprite]; XSPRITE* pXSprite = &actor->x();
const bool fixBurnGlitch = !cl_bloodvanillaenemies && IsBurningDude(pSprite) && !VanillaMode(); // if enemies are burning, always apply burning damage per tick const bool fixBurnGlitch = !cl_bloodvanillaenemies && IsBurningDude(pSprite) && !VanillaMode(); // if enemies are burning, always apply burning damage per tick
if ((pXSprite->burnTime > 0) || fixBurnGlitch) if ((pXSprite->burnTime > 0) || fixBurnGlitch)
{ {
@ -6162,104 +6178,105 @@ void actProcessSprites(void)
case kDudeBurningCultist: case kDudeBurningCultist:
case kDudeBurningZombieAxe: case kDudeBurningZombieAxe:
case kDudeBurningZombieButcher: case kDudeBurningZombieButcher:
actDamageSprite(pXSprite->burnSource, pSprite, kDamageBurn, 8); actDamageSprite(actor->GetBurnSource(), actor, kDamageBurn, 8);
break; break;
default: default:
pXSprite->burnTime = ClipLow(pXSprite->burnTime-4, 0); pXSprite->burnTime = ClipLow(pXSprite->burnTime - 4, 0);
actDamageSprite(pXSprite->burnSource, pSprite, kDamageBurn, 8); actDamageSprite(actor->GetBurnSource(), actor, kDamageBurn, 8);
break; break;
} }
} }
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
// handle incarnations of custom dude // handle incarnations of custom dude
if (pSprite->type == kDudeModernCustom && pXSprite->txID > 0 && pXSprite->sysData1 == kGenDudeTransformStatus) { if (pSprite->type == kDudeModernCustom && pXSprite->txID > 0 && pXSprite->sysData1 == kGenDudeTransformStatus)
xvel[pSprite->index] = yvel[pSprite->index] = 0; {
if (seqGetStatus(3, nXSprite) < 0) actor->xvel() = actor->yvel() = 0;
genDudeTransform(pSprite); if (seqGetStatus(actor) < 0) genDudeTransform(pSprite);
} }
#endif #endif
if (pSprite->type == kDudeCerberusTwoHead) if (pSprite->type == kDudeCerberusTwoHead)
{ {
if (pXSprite->health <= 0 && seqGetStatus(3, nXSprite) < 0) if (pXSprite->health <= 0 && seqGetStatus(actor) < 0)
{ {
pXSprite->health = dudeInfo[28].startHealth<<4; pXSprite->health = dudeInfo[28].startHealth << 4;
pSprite->type = kDudeCerberusOneHead; pSprite->type = kDudeCerberusOneHead;
if (pXSprite->target != -1) if (pXSprite->target != -1) aiSetTarget(pXSprite, pXSprite->target);
aiSetTarget(pXSprite, pXSprite->target); aiActivateDude(actor);
aiActivateDude(&bloodActors[pXSprite->reference]);
} }
} }
if (pXSprite->Proximity && !pXSprite->isTriggered) if (pXSprite->Proximity && !pXSprite->isTriggered)
{ {
int nSprite2; BloodStatIterator it1(kStatDude);
StatIterator it1(kStatDude); while (auto actor2 = it1.Next())
while ((nSprite2 = it1.NextIndex()) >= 0)
{ {
spritetype *pSprite2 = &sprite[nSprite2]; spritetype* pSprite2 = &actor->s();
if (pSprite2->flags & 32) continue;
if (pSprite2->flags&32) XSPRITE* pXSprite2 = &actor->x();
continue;
XSPRITE *pXSprite2 = &xsprite[pSprite2->extra]; if ((unsigned int)pXSprite2->health > 0 && IsPlayerSprite(pSprite2))
if ((unsigned int)pXSprite2->health > 0 && IsPlayerSprite(pSprite2)) { {
if (CheckProximity(pSprite2, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 128)) if (CheckProximity(pSprite2, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 128))
trTriggerSprite(nSprite, pXSprite, kCmdSpriteProximity); trTriggerSprite(actor, kCmdSpriteProximity);
} }
} }
} }
if (IsPlayerSprite(pSprite)) if (actor->IsPlayerActor())
{ {
PLAYER *pPlayer = &gPlayer[pSprite->type-kDudePlayer1]; PLAYER* pPlayer = &gPlayer[pSprite->type - kDudePlayer1];
if (pPlayer->voodooTargets) if (pPlayer->voodooTargets) voodooTarget(pPlayer);
voodooTarget(pPlayer); if (pPlayer->hand && Chance(0x8000)) actDamageSprite(actor, actor, kDamageDrown, 12);
if (pPlayer->hand && Chance(0x8000))
actDamageSprite(nSprite, pSprite, kDamageDrown, 12);
if (pPlayer->isUnderwater) if (pPlayer->isUnderwater)
{ {
char bActive = packItemActive(pPlayer, 1); char bActive = packItemActive(pPlayer, 1);
if (bActive || pPlayer->godMode)
pPlayer->underwaterTime = 1200; if (bActive || pPlayer->godMode) pPlayer->underwaterTime = 1200;
else else pPlayer->underwaterTime = ClipLow(pPlayer->underwaterTime - 4, 0);
pPlayer->underwaterTime = ClipLow(pPlayer->underwaterTime-4, 0);
if (pPlayer->underwaterTime < 1080 && packCheckItem(pPlayer, 1) && !bActive) if (pPlayer->underwaterTime < 1080 && packCheckItem(pPlayer, 1) && !bActive)
packUseItem(pPlayer, 1); packUseItem(pPlayer, 1);
if (!pPlayer->underwaterTime) if (!pPlayer->underwaterTime)
{ {
pPlayer->chokeEffect += 4; pPlayer->chokeEffect += 4;
if (Chance(pPlayer->chokeEffect)) if (Chance(pPlayer->chokeEffect))
actDamageSprite(nSprite, pSprite, kDamageDrown, 3<<4); actDamageSprite(actor, actor, kDamageDrown, 3 << 4);
} }
else else
pPlayer->chokeEffect = 0; pPlayer->chokeEffect = 0;
if (xvel[nSprite] || yvel[nSprite])
if (actor->xvel() || actor->yvel())
sfxPlay3DSound(pSprite, 709, 100, 2); sfxPlay3DSound(pSprite, 709, 100, 2);
pPlayer->bubbleTime = ClipLow(pPlayer->bubbleTime-4, 0);
pPlayer->bubbleTime = ClipLow(pPlayer->bubbleTime - 4, 0);
} }
else if (gGameOptions.nGameType == 0) else if (gGameOptions.nGameType == 0)
{ {
if (pPlayer->pXSprite->health > 0 && pPlayer->restTime >= 1200 && Chance(0x200)) if (pPlayer->pXSprite->health > 0 && pPlayer->restTime >= 1200 && Chance(0x200))
{ {
pPlayer->restTime = -1; pPlayer->restTime = -1;
sfxPlay3DSound(pSprite, 3100+Random(11), 0, 2); sfxPlay3DSound(pSprite, 3100 + Random(11), 0, 2);
} }
} }
} }
ProcessTouchObjects(&bloodActors[pSprite->index]); ProcessTouchObjects(actor);
} }
} }
it.Reset(kStatDude);
while ((nSprite = it.NextIndex()) >= 0)
{
spritetype *pSprite = &sprite[nSprite];
if (pSprite->flags & 32) it.Reset(kStatDude);
continue; while (auto actor = it.Next())
int nXSprite = pSprite->extra; {
assert(nXSprite > 0 && nXSprite < kMaxXSprites); spritetype* pSprite = &actor->s();
if (pSprite->flags & 32 || !actor->hasX()) continue;
int nSector = pSprite->sectnum; int nSector = pSprite->sectnum;
viewBackupSpriteLoc(nSprite, pSprite); viewBackupSpriteLoc(actor);
int nXSector = sector[nSector].extra; int nXSector = sector[nSector].extra;
XSECTOR *pXSector = NULL; XSECTOR* pXSector = NULL;
if (nXSector > 0) if (nXSector > 0)
{ {
assert(nXSector > 0 && nXSector < kMaxXSectors); assert(nXSector > 0 && nXSector < kMaxXSectors);
@ -6269,7 +6286,7 @@ void actProcessSprites(void)
if (pXSector) if (pXSector)
{ {
int top, bottom; int top, bottom;
GetSpriteExtents(pSprite, &top, &bottom); GetActorExtents(actor, &top, &bottom);
if (getflorzofslope(nSector, pSprite->x, pSprite->y) <= bottom) if (getflorzofslope(nSector, pSprite->x, pSprite->y) <= bottom)
{ {
int angle = pXSector->panAngle; int angle = pXSector->panAngle;
@ -6280,64 +6297,95 @@ void actProcessSprites(void)
if (!pXSector->panAlways && pXSector->busy) if (!pXSector->panAlways && pXSector->busy)
speed = MulScale(speed, pXSector->busy, 16); speed = MulScale(speed, pXSector->busy, 16);
} }
if (sector[nSector].floorstat&64) if (sector[nSector].floorstat & 64)
angle = (angle+GetWallAngle(sector[nSector].wallptr)+512)&2047; angle = (angle + GetWallAngle(sector[nSector].wallptr) + 512) & 2047;
int dx = MulScale(speed, Cos(angle), 30); int dx = MulScale(speed, Cos(angle), 30);
int dy = MulScale(speed, Sin(angle), 30); int dy = MulScale(speed, Sin(angle), 30);
xvel[nSprite] += dx; actor->xvel() += dx;
yvel[nSprite] += dy; actor->yvel() += dy;
} }
} }
if (pXSector && pXSector->Underwater) if (pXSector && pXSector->Underwater) actAirDrag(actor, 5376);
actAirDrag(&bloodActors[pSprite->index], 5376); else actAirDrag(actor, 128);
else
actAirDrag(&bloodActors[pSprite->index], 128);
if ((pSprite->flags&4) || xvel[nSprite] || yvel[nSprite] || zvel[nSprite] || if ((pSprite->flags & 4) || actor->xvel() || actor->yvel() || actor->zvel() || velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum])
velFloor[pSprite->sectnum] || velCeil[pSprite->sectnum]) MoveDude(actor);
MoveDude(&bloodActors[pSprite->index]);
} }
it.Reset(kStatFlare); }
while ((nSprite = it.NextIndex()) >= 0)
{
spritetype *pSprite = &sprite[nSprite];
if (pSprite->flags & 32) //---------------------------------------------------------------------------
continue; //
int nXSprite = pSprite->extra; //
assert(nXSprite > 0 && nXSprite < kMaxXSprites); //
XSPRITE *pXSprite = &xsprite[nXSprite]; //---------------------------------------------------------------------------
int nTarget = pXSprite->target;
assert(nTarget >= 0); void actCheckFlares()
viewBackupSpriteLoc(nSprite, pSprite); {
assert(nTarget < kMaxSprites); BloodStatIterator it(kStatFlare);
spritetype *pTarget = &sprite[nTarget]; while (auto actor = it.Next())
{
spritetype* pSprite = &actor->s();
if ((pSprite->flags & 32) || !actor->hasX()) continue;
XSPRITE* pXSprite = &actor->x();
auto target = actor->GetTarget();
if (!target) continue;
viewBackupSpriteLoc(actor);
spritetype* pTarget = &target->s();
if (pTarget->statnum == kMaxStatus) if (pTarget->statnum == kMaxStatus)
{ {
GibSprite(pSprite, GIBTYPE_17, NULL, NULL); GibSprite(pSprite, GIBTYPE_17, NULL, NULL);
actPostSprite(pSprite->index, kStatFree); actPostSprite(actor, kStatFree);
} }
if (pTarget->extra > 0 && xsprite[pTarget->extra].health > 0) if (pTarget->extra > 0 && xsprite[pTarget->extra].health > 0)
{ {
int x = pTarget->x+mulscale30r(Cos(pXSprite->goalAng+pTarget->ang), pTarget->clipdist*2); int x = pTarget->x + mulscale30r(Cos(pXSprite->goalAng + pTarget->ang), pTarget->clipdist * 2);
int y = pTarget->y+mulscale30r(Sin(pXSprite->goalAng+pTarget->ang), pTarget->clipdist*2); int y = pTarget->y + mulscale30r(Sin(pXSprite->goalAng + pTarget->ang), pTarget->clipdist * 2);
int z = pTarget->z+pXSprite->targetZ; int z = pTarget->z + pXSprite->targetZ;
vec3_t pos = { x, y, z }; vec3_t pos = { x, y, z };
setsprite(nSprite,&pos); setsprite(pSprite->index, &pos);
xvel[nSprite] = xvel[nTarget]; actor->xvel() = target->xvel();
yvel[nSprite] = yvel[nTarget]; actor->yvel() = target->yvel();
zvel[nSprite] = zvel[nTarget]; actor->zvel() = target->zvel();
} }
else else
{ {
GibSprite(pSprite, GIBTYPE_17, NULL, NULL); GibSprite(pSprite, GIBTYPE_17, NULL, NULL);
actPostSprite(pSprite->index, kStatFree); actPostSprite(actor, kStatFree);
} }
} }
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void actProcessSprites(void)
{
#ifdef NOONE_EXTENSIONS
if (gModernMap) nnExtProcessSuperSprites();
#endif
actCheckProximity();
actCheckThings();
actCheckProjectiles();
actCheckExplosion();
actCheckTraps();
actCheckDudes();
actCheckFlares();
aiProcessDudes(); aiProcessDudes();
gFX.fxProcess(); gFX.fxProcess();
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
spritetype * actSpawnSprite_(int nSector, int x, int y, int z, int nStat, char a6) spritetype * actSpawnSprite_(int nSector, int x, int y, int z, int nStat, char a6)
{ {
int nSprite = InsertSprite(nSector, nStat); int nSprite = InsertSprite(nSector, nStat);

View file

@ -482,6 +482,11 @@ SEQINST* GetInstance(DBloodActor* actor)
return activeList.get(3, actor->s().index); return activeList.get(3, actor->s().index);
} }
int seqGetStatus(DBloodActor* actor)
{
return seqGetStatus(3, actor->s().index);
}
void seqKill(int type, int nXIndex) void seqKill(int type, int nXIndex)
{ {
activeList.remove(type, nXIndex); activeList.remove(type, nXIndex);

View file

@ -107,6 +107,7 @@ void seqKill(int a1, int a2);
void seqKill(DBloodActor* actor); void seqKill(DBloodActor* actor);
void seqKillAll(void); void seqKillAll(void);
int seqGetStatus(int a1, int a2); int seqGetStatus(int a1, int a2);
int seqGetStatus(DBloodActor*);
int seqGetID(int a1, int a2); int seqGetID(int a1, int a2);
void seqProcess(int a1); void seqProcess(int a1);