- MoveMissile + actExplodeSprite.

# Conflicts:
#	source/games/blood/src/actor.cpp
This commit is contained in:
Christoph Oelckers 2020-12-05 12:17:28 +01:00
parent 29c2e68270
commit ddcb12a8b2
6 changed files with 196 additions and 210 deletions

View file

@ -4010,12 +4010,12 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode)
int nDamage = (50 + Random(50)) << 4; int nDamage = (50 + Random(50)) << 4;
actDamageSprite(missileOwner, actorHit, kDamageBullet, nDamage); actDamageSprite(missileOwner, actorHit, kDamageBullet, nDamage);
} }
actExplodeSprite(pMissile); actExplodeSprite(missileActor);
break; break;
case kMissileFlareAlt: case kMissileFlareAlt:
sfxKill3DSound(pMissile, -1, -1); sfxKill3DSound(pMissile, -1, -1);
actExplodeSprite(pMissile); actExplodeSprite(missileActor);
break; break;
case kMissileFlareRegular: case kMissileFlareRegular:
@ -4072,7 +4072,7 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode)
break; break;
case kMissileFireballCerberus: case kMissileFireballCerberus:
actExplodeSprite(pMissile); actExplodeSprite(missileActor);
if (hitCode == 3 && actorHit && actorHit->hasX()) if (hitCode == 3 && actorHit && actorHit->hasX())
{ {
if ((pSpriteHit->statnum == kStatThing || pSpriteHit->statnum == kStatDude) && pXSpriteHit->burnTime == 0) if ((pSpriteHit->statnum == kStatThing || pSpriteHit->statnum == kStatDude) && pXSpriteHit->burnTime == 0)
@ -4083,11 +4083,11 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode)
int nDamage = (25 + Random(10)) << 4; int nDamage = (25 + Random(10)) << 4;
actDamageSprite(missileOwner, actorHit, kDamageBullet, nDamage); actDamageSprite(missileOwner, actorHit, kDamageBullet, nDamage);
} }
actExplodeSprite(pMissile); actExplodeSprite(missileActor);
break; break;
case kMissileFireballTchernobog: case kMissileFireballTchernobog:
actExplodeSprite(pMissile); actExplodeSprite(missileActor);
if (hitCode == 3 && actorHit && actorHit->hasX()) if (hitCode == 3 && actorHit && actorHit->hasX())
{ {
if ((pSpriteHit->statnum == kStatThing || pSpriteHit->statnum == kStatDude) && pXSpriteHit->burnTime == 0) if ((pSpriteHit->statnum == kStatThing || pSpriteHit->statnum == kStatDude) && pXSpriteHit->burnTime == 0)
@ -4098,7 +4098,7 @@ static void actImpactMissile(DBloodActor* missileActor, int hitCode)
int nDamage = (25 + Random(10)) << 4; int nDamage = (25 + Random(10)) << 4;
actDamageSprite(missileOwner, actorHit, kDamageBullet, nDamage); actDamageSprite(missileOwner, actorHit, kDamageBullet, nDamage);
} }
actExplodeSprite(pMissile); actExplodeSprite(missileActor);
break; break;
case kMissileEctoSkull: case kMissileEctoSkull:
@ -5331,63 +5331,53 @@ void MoveDude(DBloodActor* actor)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int MoveMissile(spritetype *pSprite) int MoveMissile(DBloodActor* actor)
{ {
int nXSprite = pSprite->extra; auto pSprite = &actor->s();
XSPRITE *pXSprite = &xsprite[nXSprite]; auto pXSprite = &actor->x();
int vdi = -1; auto Owner = actor->GetOwner();
spritetype *pOwner = NULL; int cliptype = -1;
int bakCstat = 0; int bakCstat = 0;
if (pSprite->owner >= 0) spritetype* pOwner = nullptr;
if (Owner && Owner->IsDudeActor())
{ {
int nOwner = pSprite->owner; pOwner = &Owner->s();
pOwner = &sprite[nOwner];
if (IsDudeSprite(pOwner))
{
bakCstat = pOwner->cstat; bakCstat = pOwner->cstat;
pOwner->cstat &= ~257; pOwner->cstat &= ~257;
} }
else
pOwner = NULL;
}
gHitInfo.hitsect = -1; gHitInfo.hitsect = -1;
gHitInfo.hitwall = -1; gHitInfo.hitwall = -1;
gHitInfo.hitsprite = -1; gHitInfo.hitsprite = -1;
if (pSprite->type == kMissileFlameSpray) if (pSprite->type == kMissileFlameSpray) actAirDrag(actor, 0x1000);
actAirDrag(&bloodActors[pSprite->index], 0x1000);
int nSprite = pSprite->index; if (pXSprite->target != -1 && (actor->xvel() || actor->yvel() || actor->zvel()))
if (pXSprite->target != -1 && (xvel[nSprite] || yvel[nSprite] || zvel[nSprite]))
{ {
spritetype *pTarget = &sprite[pXSprite->target]; auto target = actor->GetTarget();
XSPRITE *pXTarget; spritetype* pTarget = &target->s();
if (pTarget->extra > 0) XSPRITE* pXTarget = target->hasX() ? &target->x() : nullptr;
pXTarget = &xsprite[pTarget->extra];
else
pXTarget = NULL;
if (pTarget->statnum == kStatDude && pXTarget && pXTarget->health > 0) if (pTarget->statnum == kStatDude && pXTarget && pXTarget->health > 0)
{ {
int nTargetAngle = getangle(-(pTarget->y-pSprite->y), pTarget->x-pSprite->x); int nTargetAngle = getangle(-(pTarget->y - pSprite->y), pTarget->x - pSprite->x);
int vx = missileInfo[pSprite->type - kMissileBase].velocity; int vx = missileInfo[pSprite->type - kMissileBase].velocity;
int vy = 0; int vy = 0;
RotatePoint(&vx, &vy, (nTargetAngle+1536)&2047, 0, 0); RotatePoint(&vx, &vy, (nTargetAngle + 1536) & 2047, 0, 0);
xvel[nSprite] = vx; actor->xvel() = vx;
yvel[nSprite] = vy; actor->yvel() = vy;
int dx = pTarget->x-pSprite->x; int dx = pTarget->x - pSprite->x;
int dy = pTarget->y-pSprite->y; int dy = pTarget->y - pSprite->y;
int dz = pTarget->z-pSprite->z; int dz = pTarget->z - pSprite->z;
// Inlined
int vax = dz/10; int deltaz = dz / 10;
if (pTarget->z < pSprite->z) if (pTarget->z < pSprite->z) deltaz = -deltaz;
vax = -vax; actor->zvel() += deltaz;
zvel[nSprite] += vax;
ksqrt(dx*dx+dy*dy+dz*dz);
} }
} }
int vx = xvel[nSprite]>>12; int vx = actor->xvel() >> 12;
int vy = yvel[nSprite]>>12; int vy = actor->yvel() >> 12;
int vz = zvel[nSprite]>>8; int vz = actor->zvel() >> 8;
int top, bottom; int top, bottom;
GetSpriteExtents(pSprite, &top, &bottom); GetActorExtents(actor, &top, &bottom);
int i = 1; int i = 1;
const int bakCompat = enginecompatibility_mode; const int bakCompat = enginecompatibility_mode;
const bool isFlameSprite = (pSprite->type == kMissileFlameSpray || pSprite->type == kMissileFlameHound); // do not use accurate clipmove for flame based sprites (changes damage too much) const bool isFlameSprite = (pSprite->type == kMissileFlameSpray || pSprite->type == kMissileFlameHound); // do not use accurate clipmove for flame based sprites (changes damage too much)
@ -5404,95 +5394,88 @@ int MoveMissile(spritetype *pSprite)
enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy enginecompatibility_mode = ENGINECOMPATIBILITY_NONE; // improved clipmove accuracy
pSprite->cstat &= ~257; // remove self collisions for accurate clipmove pSprite->cstat &= ~257; // remove self collisions for accurate clipmove
} }
int vdx = ClipMove(&x, &y, &z, &nSector2, vx, vy, pSprite->clipdist<<2, (z-top)/4, (bottom-z)/4, CLIPMASK0); Collision clipmoveresult = ClipMove(&x, &y, &z, &nSector2, vx, vy, pSprite->clipdist << 2, (z - top) / 4, (bottom - z) / 4, CLIPMASK0);
enginecompatibility_mode = bakCompat; // restore enginecompatibility_mode = bakCompat; // restore
pSprite->cstat = bakSpriteCstat; pSprite->cstat = bakSpriteCstat;
clipmoveboxtracenum = 3; clipmoveboxtracenum = 3;
short nSector = nSector2; short nSector = nSector2;
if (nSector2 < 0) if (nSector2 < 0)
{ {
vdi = -1; cliptype = -1;
break; break;
} }
if (vdx) if (clipmoveresult.type == kHitSprite)
{ {
int nHitSprite = vdx & 0x3fff; gHitInfo.hitsprite = clipmoveresult.legacyVal;
if ((vdx&0xc000) == 0xc000) cliptype = 3;
{
gHitInfo.hitsprite = nHitSprite;
vdi = 3;
} }
else if ((vdx & 0xc000) == 0x8000) else if (clipmoveresult.type == kHitWall)
{ {
gHitInfo.hitwall = nHitSprite; gHitInfo.hitwall = clipmoveresult.index;
if (wall[nHitSprite].nextsector == -1) if (wall[clipmoveresult.index].nextsector == -1) cliptype = 0;
vdi = 0;
else else
{ {
int32_t fz, cz; int32_t fz, cz;
getzsofslope(wall[nHitSprite].nextsector, x, y, &cz, &fz); getzsofslope(wall[clipmoveresult.index].nextsector, x, y, &cz, &fz);
if (z <= cz || z >= fz) if (z <= cz || z >= fz) cliptype = 0;
vdi = 0; else cliptype = 4;
else
vdi = 4;
} }
} }
} if (cliptype == 4)
if (vdi == 4)
{ {
walltype *pWall = &wall[gHitInfo.hitwall]; walltype* pWall = &wall[gHitInfo.hitwall];
if (pWall->extra > 0) if (pWall->extra > 0)
{ {
XWALL *pXWall = &xwall[pWall->extra]; XWALL* pXWall = &xwall[pWall->extra];
if (pXWall->triggerVector) if (pXWall->triggerVector)
{ {
trTriggerWall(gHitInfo.hitwall, pXWall, kCmdWallImpact); trTriggerWall(gHitInfo.hitwall, pXWall, kCmdWallImpact);
if (!(pWall->cstat&64)) if (!(pWall->cstat & 64))
{ {
vdi = -1; cliptype = -1;
if (i-- > 0) if (i-- > 0)
continue; continue;
vdi = 0; cliptype = 0;
break; break;
} }
} }
} }
} }
if (vdi >= 0 && vdi != 3) if (cliptype >= 0 && cliptype != 3)
{ {
int nAngle = getangle(xvel[nSprite], yvel[nSprite]); int nAngle = getangle(actor->xvel(), actor->yvel());
x -= MulScale(Cos(nAngle), 16, 30); x -= MulScale(Cos(nAngle), 16, 30);
y -= MulScale(Sin(nAngle), 16, 30); y -= MulScale(Sin(nAngle), 16, 30);
int nVel = approxDist(xvel[nSprite], yvel[nSprite]); int nVel = approxDist(actor->xvel(), actor->yvel());
vz -= scale(0x100, zvel[nSprite], nVel); vz -= scale(0x100, actor->zvel(), nVel);
updatesector(x, y, &nSector); updatesector(x, y, &nSector);
nSector2 = nSector; nSector2 = nSector;
} }
int ceilZ, ceilHit, floorZ, floorHit; int ceilZ, ceilHit, floorZ, floorHit;
GetZRangeAtXYZ(x, y, z, nSector2, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist<<2, CLIPMASK0); GetZRangeAtXYZ(x, y, z, nSector2, &ceilZ, &ceilHit, &floorZ, &floorHit, pSprite->clipdist << 2, CLIPMASK0);
GetSpriteExtents(pSprite, &top, &bottom); GetActorExtents(actor, &top, &bottom);
top += vz; top += vz;
bottom += vz; bottom += vz;
if (bottom >= floorZ) if (bottom >= floorZ)
{ {
gSpriteHit[nXSprite].florhit = floorHit; actor->hit().florhit = floorHit;
vz += floorZ-bottom; vz += floorZ - bottom;
vdi = 2; cliptype = 2;
} }
if (top <= ceilZ) if (top <= ceilZ)
{ {
gSpriteHit[nXSprite].ceilhit = ceilHit; actor->hit().ceilhit = ceilHit;
vz += ClipLow(ceilZ-top, 0); vz += ClipLow(ceilZ - top, 0);
vdi = 1; cliptype = 1;
} }
pSprite->x = x; pSprite->x = x;
pSprite->y = y; pSprite->y = y;
pSprite->z = z+vz; pSprite->z = z + vz;
updatesector(x, y, &nSector); updatesector(x, y, &nSector);
if (nSector >= 0 && nSector != pSprite->sectnum) if (nSector >= 0 && nSector != pSprite->sectnum)
{ {
assert(nSector >= 0 && nSector < kMaxSectors); assert(nSector >= 0 && nSector < kMaxSectors);
ChangeSpriteSect(nSprite, nSector); ChangeSpriteSect(pSprite->index, nSector);
} }
CheckLink(pSprite); CheckLink(pSprite);
gHitInfo.hitsect = pSprite->sectnum; gHitInfo.hitsect = pSprite->sectnum;
@ -5501,110 +5484,120 @@ int MoveMissile(spritetype *pSprite)
gHitInfo.hitz = pSprite->z; gHitInfo.hitz = pSprite->z;
break; break;
} }
if (pOwner) if (pOwner) pOwner->cstat = bakCstat;
pOwner->cstat = bakCstat;
return vdi; return cliptype;
} }
void actExplodeSprite(spritetype *pSprite) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void actExplodeSprite(DBloodActor* actor)
{ {
int nXSprite = pSprite->extra; if (!actor->hasX()) return;
if (nXSprite <= 0 || nXSprite >= kMaxXSprites) auto pSprite = &actor->s();
return; auto pXSprite = &actor->x();
if (pSprite->statnum == kStatExplosion) //auto Owner = actor->GetOwner();
return;
if (pSprite->statnum == kStatExplosion) return;
sfxKill3DSound(pSprite, -1, -1); sfxKill3DSound(pSprite, -1, -1);
evKill(pSprite->index, 3); evKill(pSprite->index, 3);
int nType = kExplosionStandard; int nType = kExplosionStandard;
switch (pSprite->type) switch (pSprite->type)
{ {
case kMissileFireballNapalm: case kMissileFireballNapalm:
nType = kExplosionNapalm; nType = kExplosionNapalm;
seqSpawn(4, 3, nXSprite, -1); seqSpawn(4, actor, -1);
if (Chance(0x8000)) if (Chance(0x8000)) pSprite->cstat |= 4;
pSprite->cstat |= 4;
sfxPlay3DSound(pSprite, 303, -1, 0); sfxPlay3DSound(pSprite, 303, -1, 0);
GibSprite(pSprite, GIBTYPE_5, NULL, NULL); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr);
break; break;
case kMissileFlareAlt: case kMissileFlareAlt:
nType = kExplosionFireball; nType = kExplosionFireball;
seqSpawn(9, 3, nXSprite, -1); seqSpawn(9, actor, -1);
if (Chance(0x8000)) if (Chance(0x8000)) pSprite->cstat |= 4;
pSprite->cstat |= 4; sfxPlay3DSound(pSprite, 306, 24 + (pSprite->index & 3), FX_GlobalChannel); // ouch...
sfxPlay3DSound(pSprite, 306, 24+(pSprite->index&3), 1); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr);
GibSprite(pSprite, GIBTYPE_5, NULL, NULL);
break; break;
case kMissileFireballCerberus: case kMissileFireballCerberus:
case kMissileFireballTchernobog: case kMissileFireballTchernobog:
nType = kExplosionFireball; nType = kExplosionFireball;
seqSpawn(5, 3, nXSprite, -1); seqSpawn(5, actor, -1);
sfxPlay3DSound(pSprite, 304, -1, 0); sfxPlay3DSound(pSprite, 304, -1, 0);
GibSprite(pSprite, GIBTYPE_5, NULL, NULL); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr);
break; break;
case kThingArmedTNTStick: case kThingArmedTNTStick:
nType = kExplosionSmall; nType = kExplosionSmall;
if (gSpriteHit[nXSprite].florhit == 0) seqSpawn(4,3,nXSprite,-1); if (actor->hit().florhit == 0) seqSpawn(4, actor, -1);
else seqSpawn(3,3,nXSprite,-1); else seqSpawn(3, actor, -1);
sfxPlay3DSound(pSprite, 303, -1, 0); sfxPlay3DSound(pSprite, 303, -1, 0);
GibSprite(pSprite, GIBTYPE_5, NULL, NULL); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr);
break; break;
case kThingArmedProxBomb: case kThingArmedProxBomb:
case kThingArmedRemoteBomb: case kThingArmedRemoteBomb:
case kThingArmedTNTBundle: case kThingArmedTNTBundle:
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
case kModernThingTNTProx: case kModernThingTNTProx:
#endif #endif
nType = kExplosionStandard; nType = kExplosionStandard;
if (gSpriteHit[nXSprite].florhit == 0) if (actor->hit().florhit == 0) seqSpawn(4, actor, -1);
seqSpawn(4,3,nXSprite,-1);
else else
seqSpawn(3,3,nXSprite,-1); seqSpawn(3, actor, -1);
sfxPlay3DSound(pSprite, 304, -1, 0); sfxPlay3DSound(pSprite, 304, -1, 0);
GibSprite(pSprite, GIBTYPE_5, NULL, NULL); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr);
break; break;
case kThingArmedSpray: case kThingArmedSpray:
nType = kExplosionSpray; nType = kExplosionSpray;
seqSpawn(5, 3, nXSprite, -1); seqSpawn(5, actor, -1);
sfxPlay3DSound(pSprite, 307, -1, 0); sfxPlay3DSound(pSprite, 307, -1, 0);
GibSprite(pSprite, GIBTYPE_5, NULL, NULL); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr);
break; break;
case kThingTNTBarrel: case kThingTNTBarrel:
{ {
spritetype *pSprite2 = actSpawnSprite_(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0, 1); auto spawned = actSpawnSprite(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0, 1);
pSprite2->owner = pSprite->owner; spawned->SetOwner(actor->GetOwner());
if (actCheckRespawn(pSprite)) if (actCheckRespawn(pSprite))
{ {
XSPRITE *pXSprite = &xsprite[nXSprite];
pXSprite->state = 1; pXSprite->state = 1;
pXSprite->health = thingInfo[0].startHealth<<4; pXSprite->health = thingInfo[0].startHealth << 4;
} }
else else actPostSprite(actor, kStatFree);
actPostSprite(pSprite->index, kStatFree);
nType = kExplosionLarge; nType = kExplosionLarge;
nXSprite = pSprite2->extra; seqSpawn(4, spawned, -1);
seqSpawn(4, 3, nXSprite, -1); actor = spawned;
sfxPlay3DSound(pSprite2, 305, -1, 0); pSprite = &spawned->s();
GibSprite(pSprite2, GIBTYPE_14, NULL, NULL); pXSprite = &spawned->x();
pSprite = pSprite2;
sfxPlay3DSound(pSprite, 305, -1, 0);
GibSprite(pSprite, GIBTYPE_14, nullptr, nullptr);
break; break;
} }
case kTrapExploder: case kTrapExploder:
{ {
// Defaults for exploder // Defaults for exploder
nType = 1; int nSnd = 304; int nSeq = 4; nType = 1;
int nSnd = 304;
int nSeq = 4;
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
// allow to customize hidden exploder trap // allow to customize hidden exploder trap
if (gModernMap) { if (gModernMap)
// Temp variables for override via data fields {
int tSnd = 0; int tSeq = 0; nType = pXSprite->data1; // Explosion type
int tSeq = pXSprite->data2; // SEQ id
int tSnd = pXSprite->data3; // Sound Id
XSPRITE* pXSPrite = &xsprite[nXSprite];
nType = pXSPrite->data1; // Explosion type
tSeq = pXSPrite->data2; // SEQ id
tSnd = pXSPrite->data3; // Sound Id
if (nType <= 1 || nType > kExplodeMax) { nType = 1; nSeq = 4; nSnd = 304; } if (nType <= 1 || nType > kExplodeMax) { nType = 1; nSeq = 4; nSnd = 304; }
else if (nType == 2) { nSeq = 4; nSnd = 305; } else if (nType == 2) { nSeq = 4; nSnd = 305; }
@ -5618,77 +5611,73 @@ void actExplodeSprite(spritetype *pSprite)
if (tSeq > 0) nSeq = tSeq; if (tSeq > 0) nSeq = tSeq;
if (tSnd > 0) nSnd = tSnd; if (tSnd > 0) nSnd = tSnd;
} }
#endif #endif
if (getSequence(nSeq))
seqSpawn(nSeq, 3, nXSprite, -1);
if (getSequence(nSeq)) seqSpawn(nSeq, actor, -1);
sfxPlay3DSound(pSprite, nSnd, -1, 0); sfxPlay3DSound(pSprite, nSnd, -1, 0);
break;
} }
break;
case kThingPodFireBall: case kThingPodFireBall:
nType = kExplosionFireball; nType = kExplosionFireball;
seqSpawn(9, 3, nXSprite, -1); seqSpawn(9, actor, -1);
sfxPlay3DSound(pSprite, 307, -1, 0); sfxPlay3DSound(pSprite, 307, -1, 0);
GibSprite(pSprite, GIBTYPE_5, NULL, NULL); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr);
sub_746D4(pSprite, 240); sub_746D4(pSprite, 240);
break; break;
default: default:
nType = kExplosionStandard; nType = kExplosionStandard;
seqSpawn(4, 3, nXSprite, -1); seqSpawn(4, actor, -1);
if (Chance(0x8000)) if (Chance(0x8000)) pSprite->cstat |= 4;
pSprite->cstat |= 4;
sfxPlay3DSound(pSprite, 303, -1, 0); sfxPlay3DSound(pSprite, 303, -1, 0);
GibSprite(pSprite, GIBTYPE_5, NULL, NULL); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr);
break; break;
} }
int nSprite = pSprite->index; actor->xvel() = actor->yvel() = actor->zvel() = 0;
xvel[nSprite] = yvel[nSprite] = zvel[nSprite] = 0; actPostSprite(actor, kStatExplosion);
actPostSprite(nSprite, kStatExplosion);
pSprite->xrepeat = pSprite->yrepeat = explodeInfo[nType].repeat; pSprite->xrepeat = pSprite->yrepeat = explodeInfo[nType].repeat;
pSprite->flags &= ~3; pSprite->flags &= ~3;
pSprite->type = nType; pSprite->type = nType;
const EXPLOSION *pExplodeInfo = &explodeInfo[nType]; const EXPLOSION* pExplodeInfo = &explodeInfo[nType];
xsprite[nXSprite].target = 0; pXSprite->target = 0;
xsprite[nXSprite].data1 = pExplodeInfo->ticks; pXSprite->data1 = pExplodeInfo->ticks;
xsprite[nXSprite].data2 = pExplodeInfo->quakeEffect; pXSprite->data2 = pExplodeInfo->quakeEffect;
xsprite[nXSprite].data3 = pExplodeInfo->flashEffect; pXSprite->data3 = pExplodeInfo->flashEffect;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void actActivateGibObject(DBloodActor* actor) void actActivateGibObject(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
int vdx = ClipRange(pXSprite->data1, 0, 31);
int vc = ClipRange(pXSprite->data2, 0, 31);
int v4 = ClipRange(pXSprite->data3, 0, 31);
int vbp = pXSprite->data4;
int v8 = pXSprite->dropMsg;
if (vdx > 0)
GibSprite(pSprite, (GIBTYPE)(vdx-1), NULL, NULL);
if (vc > 0)
GibSprite(pSprite, (GIBTYPE)(vc-1), NULL, NULL);
if (v4 > 0 && pXSprite->burnTime > 0)
GibSprite(pSprite, (GIBTYPE)(v4-1), NULL, NULL);
if (vbp > 0)
sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, vbp, pSprite->sectnum);
if (v8 > 0)
actDropObject(pSprite, v8);
if (!(pSprite->cstat&32768) && !(pSprite->flags&kHitagRespawn)) int gib1 = ClipRange(pXSprite->data1, 0, 31);
actPostSprite(pSprite->index, kStatFree); int gib2 = ClipRange(pXSprite->data2, 0, 31);
int gib3 = ClipRange(pXSprite->data3, 0, 31);
int sound = pXSprite->data4;
int dropmsg = pXSprite->dropMsg;
if (gib1 > 0) GibSprite(pSprite, (GIBTYPE)(gib1 - 1), nullptr, nullptr);
if (gib2 > 0) GibSprite(pSprite, (GIBTYPE)(gib2 - 1), nullptr, nullptr);
if (gib3 > 0 && pXSprite->burnTime > 0) GibSprite(pSprite, (GIBTYPE)(gib3 - 1), nullptr, nullptr);
if (sound > 0) sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, sound, pSprite->sectnum);
if (dropmsg > 0) actDropObject(pSprite, dropmsg);
if (!(pSprite->cstat & 32768) && !(pSprite->flags & kHitagRespawn))
actPostSprite(actor, kStatFree);
} }
bool IsUnderWater(spritetype *pSprite) //---------------------------------------------------------------------------
{ //
int nSector = pSprite->sectnum; //
int nXSector = sector[nSector].extra; //
if (nXSector > 0 && nXSector < kMaxXSectors) //---------------------------------------------------------------------------
if (xsector[nXSector].Underwater)
return 1;
return 0;
}
void MakeSplash(DBloodActor *actor); void MakeSplash(DBloodActor *actor);
@ -5922,7 +5911,7 @@ void actProcessSprites(void)
if ((hit&0xc000) != 0xc000 && (nObject < 0 || nObject >= 4096)) if ((hit&0xc000) != 0xc000 && (nObject < 0 || nObject >= 4096))
break; break;
assert(nObject >= 0 && nObject < kMaxSprites); assert(nObject >= 0 && nObject < kMaxSprites);
actExplodeSprite(pSprite); actExplodeSprite(&bloodActors[pSprite->index]);
break; break;
} }
} }
@ -5939,7 +5928,7 @@ void actProcessSprites(void)
if (pSprite->flags & 32) if (pSprite->flags & 32)
continue; continue;
viewBackupSpriteLoc(nSprite, pSprite); viewBackupSpriteLoc(nSprite, pSprite);
int hit = MoveMissile(pSprite); int hit = MoveMissile(&bloodActors[nSprite]);
if (hit >= 0) if (hit >= 0)
actImpactMissile(&bloodActors[pSprite->index], hit); actImpactMissile(&bloodActors[pSprite->index], hit);
} }

View file

@ -229,12 +229,8 @@ int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE a3, int a4);
int actDamageSprite(DBloodActor* pSource, DBloodActor* pTarget, DAMAGE_TYPE damageType, int damage); int actDamageSprite(DBloodActor* pSource, DBloodActor* pTarget, DAMAGE_TYPE damageType, int damage);
void actHitcodeToData(int a1, HITINFO *pHitInfo, DBloodActor **actor, walltype **a7 = nullptr); void actHitcodeToData(int a1, HITINFO *pHitInfo, DBloodActor **actor, walltype **a7 = nullptr);
void actAirDrag(DBloodActor *pSprite, int a2); void actAirDrag(DBloodActor *pSprite, int a2);
int MoveThing(spritetype *pSprite); void actExplodeSprite(DBloodActor *pSprite);
void MoveDude(spritetype *pSprite);
int MoveMissile(spritetype *pSprite);
void actExplodeSprite(spritetype *pSprite);
void actActivateGibObject(DBloodActor *actor); void actActivateGibObject(DBloodActor *actor);
bool IsUnderWater(spritetype *pSprite);
void actProcessSprites(void); void actProcessSprites(void);
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);
DBloodActor* actSpawnSprite(int nSector, int x, int y, int z, int nStat, bool a6); DBloodActor* actSpawnSprite(int nSector, int x, int y, int z, int nStat, bool a6);

View file

@ -5042,7 +5042,7 @@ bool modernTypeOperateSprite(int nSprite, spritetype* pSprite, XSPRITE* pXSprite
pXSprite->Proximity = 1; pXSprite->Proximity = 1;
break; break;
default: default:
actExplodeSprite(pSprite); actExplodeSprite(&bloodActors[pSprite->index]);
break; break;
} }
} }

View file

@ -169,14 +169,7 @@ void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector)
if (chan) chan->UserData = nSector; if (chan) chan->UserData = nSector;
} }
enum EPlayFlags void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int playchannel, int playflags, int pitch, int volume)
{
FX_GlobalChannel = 1,
FX_SoundMatch = 2,
FX_ChannelMatch = 4,
};
void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitch, int volume)
{ {
if (!SoundEnabled() || soundId < 0 || !pSprite) return; if (!SoundEnabled() || soundId < 0 || !pSprite) return;
auto sid = soundEngine->FindSoundByResID(soundId); auto sid = soundEngine->FindSoundByResID(soundId);
@ -188,17 +181,17 @@ void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitc
sid = getSfx(sid, attenuation, pitch, volume); sid = getSfx(sid, attenuation, pitch, volume);
if (volume == -1) volume = 80; if (volume == -1) volume = 80;
if (a3 >= 0) if (playchannel >= 0)
{ {
a3++; // This is to make 0 a valid channel value. playchannel++; // This is to make 0 a valid channel value.
if (soundEngine->EnumerateChannels([=](FSoundChan* chan) -> int if (soundEngine->EnumerateChannels([=](FSoundChan* chan) -> int
{ {
if (chan->SourceType != SOURCE_Actor) return false; // other source types are not our business. if (chan->SourceType != SOURCE_Actor) return false; // other source types are not our business.
if (chan->EntChannel == a3 && (chan->Source == pSprite || (a4 & FX_GlobalChannel) != 0)) if (chan->EntChannel == playchannel && (chan->Source == pSprite || (playflags & FX_GlobalChannel) != 0))
{ {
if ((a4 & FX_ChannelMatch) != 0 && chan->EntChannel == a3) if ((playflags & FX_ChannelMatch) != 0 && chan->EntChannel == playchannel)
return true; return true;
if ((a4 & FX_SoundMatch) != 0 && chan->OrgID == sid) if ((playflags & FX_SoundMatch) != 0 && chan->OrgID == sid)
return true; return true;
soundEngine->StopChannel(chan); soundEngine->StopChannel(chan);
return -1; return -1;
@ -209,10 +202,10 @@ void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitc
} }
auto sfx = soundEngine->GetSfx(sid); auto sfx = soundEngine->GetSfx(sid);
EChanFlags flags = a3 == -1 ? CHANF_OVERLAP : CHANF_NONE; EChanFlags flags = playchannel == -1 ? CHANF_OVERLAP : CHANF_NONE;
if (sfx && sfx->LoopStart >= 0) flags |= CHANF_LOOP; if (sfx && sfx->LoopStart >= 0) flags |= CHANF_LOOP;
soundEngine->StartSound(SOURCE_Actor, pSprite, &svec, a3, flags, sid, volume * (0.8f / 80.f), attenuation, nullptr, pitch / 65536.f); soundEngine->StartSound(SOURCE_Actor, pSprite, &svec, playchannel, flags, sid, volume * (0.8f / 80.f), attenuation, nullptr, pitch / 65536.f);
} }
void sfxPlay3DSound(spritetype* pSprite, int soundId, int a3, int a4) void sfxPlay3DSound(spritetype* pSprite, int soundId, int a3, int a4)

View file

@ -62,4 +62,12 @@ void ambProcess(void);
void ambKillAll(void); void ambKillAll(void);
void ambInit(void); void ambInit(void);
enum EPlayFlags
{
FX_GlobalChannel = 1,
FX_SoundMatch = 2,
FX_ChannelMatch = 4,
};
END_BLD_NS END_BLD_NS

View file

@ -495,7 +495,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
case kThingArmedTNTStick: case kThingArmedTNTStick:
case kThingArmedTNTBundle: case kThingArmedTNTBundle:
case kThingArmedSpray: case kThingArmedSpray:
actExplodeSprite(pSprite); actExplodeSprite(&bloodActors[pSprite->index]);
break; break;
case kTrapExploder: case kTrapExploder:
switch (event.cmd) { switch (event.cmd) {
@ -504,13 +504,13 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
break; break;
default: default:
pSprite->cstat &= (unsigned short)~CSTAT_SPRITE_INVISIBLE; pSprite->cstat &= (unsigned short)~CSTAT_SPRITE_INVISIBLE;
actExplodeSprite(pSprite); actExplodeSprite(&bloodActors[pSprite->index]);
break; break;
} }
break; break;
case kThingArmedRemoteBomb: case kThingArmedRemoteBomb:
if (pSprite->statnum != kStatRespawn) { if (pSprite->statnum != kStatRespawn) {
if (event.cmd != kCmdOn) actExplodeSprite(pSprite); if (event.cmd != kCmdOn) actExplodeSprite(&bloodActors[pSprite->index]);
else { else {
sfxPlay3DSound(pSprite, 454, 0, 0); sfxPlay3DSound(pSprite, 454, 0, 0);
evPost(nSprite, 3, 18, kCmdOff); evPost(nSprite, 3, 18, kCmdOff);
@ -531,7 +531,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
pXSprite->Proximity = 1; pXSprite->Proximity = 1;
break; break;
default: default:
actExplodeSprite(pSprite); actExplodeSprite(&bloodActors[pSprite->index]);
break; break;
} }
} }