- actImpactMissile.

This commit is contained in:
Christoph Oelckers 2020-12-03 18:00:07 +01:00
parent f96521a7f4
commit a7572bca0a
11 changed files with 372 additions and 371 deletions

View file

@ -2742,7 +2742,7 @@ static void actNapalmMove(DBloodActor* actor)
if (pXSprite->data4 > 1) if (pXSprite->data4 > 1)
{ {
GibSprite(pSprite, GIBTYPE_5, NULL, NULL); GibSprite(pSprite, GIBTYPE_5, nullptr, nullptr);
int spawnparam[2]; int spawnparam[2];
spawnparam[0] = pXSprite->data4 >> 1; spawnparam[0] = pXSprite->data4 >> 1;
spawnparam[1] = pXSprite->data4 - spawnparam[0]; spawnparam[1] = pXSprite->data4 - spawnparam[0];
@ -2880,7 +2880,7 @@ static DBloodActor* actDropFlag(DBloodActor* actor, int nType)
auto act2 = actDropItem(actor, nType); auto act2 = actDropItem(actor, nType);
if (act2 && gGameOptions.nGameType == 3) if (act2 && gGameOptions.nGameType == 3)
{ {
evPost(act2->s().index, 3, 1800, kCallbackReturnFlag); evPost(act2, 1800, kCallbackReturnFlag);
} }
return act2; return act2;
} }
@ -2949,7 +2949,7 @@ static bool actKillModernDude(DBloodActor* actor, DAMAGE_TYPE damageType)
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); GENDUDEEXTRA* pExtra = genDudeExtra(pSprite);
removeDudeStuff(pSprite); removeDudeStuff(pSprite);
if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == NULL) if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == nullptr)
{ {
if (pExtra->weaponType == kGenDudeWeaponKamikaze && Chance(0x4000) && damageType != DAMAGE_TYPE_5 && damageType != DAMAGE_TYPE_4) if (pExtra->weaponType == kGenDudeWeaponKamikaze && Chance(0x4000) && damageType != DAMAGE_TYPE_5 && damageType != DAMAGE_TYPE_4)
{ {
@ -3280,7 +3280,7 @@ static void zombieAxeNormalDeath(DBloodActor* actor, int nSeq)
else if (nSeq == 1 && Chance(0x4000)) else if (nSeq == 1 && Chance(0x4000))
{ {
seqSpawn(dudeInfo[nType].seqStartID + 7, actor, nDudeToGibClient1); seqSpawn(dudeInfo[nType].seqStartID + 7, actor, nDudeToGibClient1);
evPost(pSprite->index, 3, 0, kCallbackFXZombieSpurt); evPost(actor, 0, kCallbackFXZombieSpurt);
sfxPlay3DSound(pSprite, 362, -1, 0); sfxPlay3DSound(pSprite, 362, -1, 0);
actor->x().data1 = 35; actor->x().data1 = 35;
actor->x().data2 = 5; actor->x().data2 = 5;
@ -3308,7 +3308,7 @@ static void burningCultistDeath(DBloodActor* actor, int nSeq)
if (Chance(0x8000)) if (Chance(0x8000))
{ {
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
GibSprite(pSprite, GIBTYPE_7, NULL, NULL); GibSprite(pSprite, GIBTYPE_7, nullptr, nullptr);
seqSpawn(dudeInfo[nType].seqStartID + 16 - Random(1), actor, nDudeToGibClient1); seqSpawn(dudeInfo[nType].seqStartID + 16 - Random(1), actor, nDudeToGibClient1);
} }
else else
@ -3454,7 +3454,7 @@ void actKillDude(DBloodActor* killerActor, DBloodActor* actor, DAMAGE_TYPE damag
gPlayer[p].setFragger(nullptr); gPlayer[p].setFragger(nullptr);
} }
if (pSprite->type != kDudeCultistBeast) if (pSprite->type != kDudeCultistBeast)
trTriggerSprite(pSprite->index, pXSprite, kCmdOff); trTriggerSprite(actor, kCmdOff);
pSprite->flags |= 7; pSprite->flags |= 7;
checkAddFrag(killerActor, actor); checkAddFrag(killerActor, actor);
@ -3735,7 +3735,7 @@ static int actDamageThing(DBloodActor* source, DBloodActor* actor, int damage, D
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
case kModernThingEnemyLifeLeech: case kModernThingEnemyLifeLeech:
#endif #endif
GibSprite(pSprite, GIBTYPE_14, NULL, NULL); GibSprite(pSprite, GIBTYPE_14, nullptr, nullptr);
pXSprite->data1 = pXSprite->data2 = pXSprite->data3 = pXSprite->DudeLockout = 0; pXSprite->data1 = pXSprite->data2 = pXSprite->data3 = pXSprite->DudeLockout = 0;
pXSprite->stateTimer = pXSprite->data4 = pXSprite->isTriggered = 0; pXSprite->stateTimer = pXSprite->data4 = pXSprite->isTriggered = 0;
@ -3751,7 +3751,7 @@ static int actDamageThing(DBloodActor* source, DBloodActor* actor, int damage, D
break; break;
} }
trTriggerSprite(pSprite->index, pXSprite, kCmdOff); trTriggerSprite(actor, kCmdOff);
switch (pSprite->type) switch (pSprite->type)
{ {
@ -3772,7 +3772,7 @@ static int actDamageThing(DBloodActor* source, DBloodActor* actor, int damage, D
case kThingFluorescent: case kThingFluorescent:
seqSpawn(12, 3, pSprite->extra, -1); seqSpawn(12, 3, pSprite->extra, -1);
GibSprite(pSprite, GIBTYPE_6, NULL, NULL); GibSprite(pSprite, GIBTYPE_6, nullptr, nullptr);
break; break;
case kThingSpiderWeb: case kThingSpiderWeb:
@ -3781,14 +3781,14 @@ static int actDamageThing(DBloodActor* source, DBloodActor* actor, int damage, D
case kThingMetalGrate: case kThingMetalGrate:
seqSpawn(21, 3, pSprite->extra, -1); seqSpawn(21, 3, pSprite->extra, -1);
GibSprite(pSprite, GIBTYPE_4, NULL, NULL); GibSprite(pSprite, GIBTYPE_4, nullptr, nullptr);
break; break;
case kThingFlammableTree: case kThingFlammableTree:
switch (pXSprite->data1) switch (pXSprite->data1)
{ {
case -1: case -1:
GibSprite(pSprite, GIBTYPE_14, NULL, NULL); GibSprite(pSprite, GIBTYPE_14, nullptr, nullptr);
sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, 312, pSprite->sectnum); sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, 312, pSprite->sectnum);
actPostSprite(actor, kStatFree); actPostSprite(actor, kStatFree);
break; break;
@ -3828,7 +3828,7 @@ int actDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE damageT
if (source == nullptr) source = actor; if (source == nullptr) source = actor;
PLAYER* pSourcePlayer = NULL; PLAYER* pSourcePlayer = nullptr;
if (source->IsPlayerActor()) pSourcePlayer = &gPlayer[source->s().type - kDudePlayer1]; if (source->IsPlayerActor()) pSourcePlayer = &gPlayer[source->s().type - kDudePlayer1];
if (!gGameOptions.bFriendlyFire && IsTargetTeammate(pSourcePlayer, pSprite)) return 0; if (!gGameOptions.bFriendlyFire && IsTargetTeammate(pSourcePlayer, pSprite)) return 0;
@ -3847,86 +3847,60 @@ int actDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE damageT
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// // this was condensed to the parts actually in use.
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void actHitcodeToData(int a1, HITINFO *pHitInfo, int *a3, spritetype **a4, XSPRITE **a5, int *a6, walltype **a7, XWALL **a8, int *a9, sectortype **a10, XSECTOR **a11) void actHitcodeToData(int a1, HITINFO* pHitInfo, DBloodActor** pActor, walltype** a7)
{ {
assert(pHitInfo != NULL); assert(pHitInfo != nullptr);
int nSprite = -1; int nSprite = -1;
spritetype *pSprite = NULL;
XSPRITE *pXSprite = NULL;
int nWall = -1; int nWall = -1;
walltype *pWall = NULL; walltype* pWall = nullptr;
XWALL *pXWall = NULL;
int nSector = -1;
sectortype *pSector = NULL;
XSECTOR *pXSector = NULL;
switch (a1) switch (a1)
{ {
case 3: case 3:
case 5: case 5:
nSprite = pHitInfo->hitsprite; nSprite = pHitInfo->hitsprite;
assert(nSprite >= 0 && nSprite < kMaxSprites);
pSprite = &sprite[nSprite];
if (pSprite->extra > 0)
pXSprite = &xsprite[pSprite->extra];
break; break;
case 0: case 0:
case 4: case 4:
nWall = pHitInfo->hitwall; nWall = pHitInfo->hitwall;
assert(nWall >= 0 && nWall < kMaxWalls); if (nWall >= 0 && nWall < kMaxWalls) pWall = &wall[nWall];
pWall = &wall[nWall];
if (pWall->extra > 0)
pXWall = &xwall[pWall->extra];
break; break;
case 1: default:
case 2:
case 6:
nSector = pHitInfo->hitsect;
assert(nSector >= 0 && nSector < kMaxSectors);
pSector = &sector[nSector];
if (pSector->extra > 0)
pXSector = &xsector[pSector->extra];
break; break;
} }
if (a3) if (pActor) *pActor = nSprite == -1 ? nullptr : &bloodActors[nSprite];
*a3 = nSprite; if (a7) *a7 = pWall;
if (a4)
*a4 = pSprite;
if (a5)
*a5 = pXSprite;
if (a6)
*a6 = nWall;
if (a7)
*a7 = pWall;
if (a8)
*a8 = pXWall;
if (a9)
*a9 = nSector;
if (a10)
*a10 = pSector;
if (a11)
*a11 = pXSector;
} }
void actImpactMissile(spritetype *pMissile, int hitCode) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void actImpactMissile(DBloodActor* missileActor, int hitCode)
{ {
int nXMissile = pMissile->extra; auto pMissile = &missileActor->s();
assert(nXMissile > 0 && nXMissile < kMaxXSprites); XSPRITE* pXMissile = &missileActor->x();
XSPRITE *pXMissile = &xsprite[pMissile->extra]; auto missileOwner = missileActor->GetOwner();
int nSpriteHit = -1; int nWallHit = -1; int nSectorHit = -1; DBloodActor* actorHit = nullptr;
spritetype *pSpriteHit = NULL; XSPRITE *pXSpriteHit = NULL; walltype* pWallHit = nullptr;
walltype *pWallHit = NULL; XWALL *pXWallHit = NULL;
sectortype *pSectorHit = NULL; XSECTOR *pXSectorHit = NULL;
actHitcodeToData(hitCode, &gHitInfo, &nSpriteHit, &pSpriteHit, &pXSpriteHit, &nWallHit, &pWallHit, &pXWallHit, &nSectorHit, &pSectorHit, &pXSectorHit); actHitcodeToData(hitCode, &gHitInfo, &actorHit, &pWallHit);
const THINGINFO *pThingInfo = NULL; DUDEINFO *pDudeInfo = NULL; spritetype* pSpriteHit = actorHit ? &actorHit->s() : nullptr;
XSPRITE* pXSpriteHit = actorHit && actorHit->hasX() ? &actorHit->x() : nullptr;
if (hitCode == 3 && pSpriteHit) { const THINGINFO* pThingInfo = nullptr;
switch (pSpriteHit->statnum) { DUDEINFO* pDudeInfo = nullptr;
if (hitCode == 3 && pSpriteHit)
{
switch (pSpriteHit->statnum)
{
case kStatThing: case kStatThing:
pThingInfo = &thingInfo[pSpriteHit->type - kThingBase]; pThingInfo = &thingInfo[pSpriteHit->type - kThingBase];
break; break;
@ -3935,127 +3909,143 @@ void actImpactMissile(spritetype *pMissile, int hitCode)
break; break;
} }
} }
switch (pMissile->type) { switch (pMissile->type)
{
case kMissileLifeLeechRegular: case kMissileLifeLeechRegular:
if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo)) { if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo))
int nOwner = pMissile->owner; {
DAMAGE_TYPE rand1 = (DAMAGE_TYPE)Random(7); DAMAGE_TYPE rand1 = (DAMAGE_TYPE)Random(7);
int rand2 = (7 + Random(7)) << 4; int rand2 = (7 + Random(7)) << 4;
int nDamage = actDamageSprite(nOwner, pSpriteHit, rand1, rand2); int nDamage = actDamageSprite(missileOwner, actorHit, rand1, rand2);
if ((pThingInfo && pThingInfo->dmgControl[DAMAGE_TYPE_1] != 0) || (pDudeInfo && pDudeInfo->damageVal[DAMAGE_TYPE_1] != 0)) if ((pThingInfo && pThingInfo->dmgControl[DAMAGE_TYPE_1] != 0) || (pDudeInfo && pDudeInfo->damageVal[DAMAGE_TYPE_1] != 0))
actBurnSprite(pMissile->owner, pXSpriteHit, 360); actBurnSprite(missileActor->GetOwner(), actorHit, 360);
// by NoOne: make Life Leech heal user, just like it was in 1.0x versions // by NoOne: make Life Leech heal user, just like it was in 1.0x versions
if (gGameOptions.weaponsV10x && !VanillaMode() && !DemoRecordStatus() && pDudeInfo != NULL) { if (gGameOptions.weaponsV10x && !VanillaMode() && !DemoRecordStatus() && pDudeInfo != nullptr)
spritetype* pSource = &sprite[nOwner]; {
XSPRITE* pXSource = (pSource->extra >= 0) ? &xsprite[pSource->extra] : NULL; if (missileOwner->IsDudeActor() && missileOwner->hasX() && missileOwner->x().health != 0)
actHealDude(missileOwner, nDamage >> 2, getDudeInfo(missileOwner->s().type)->startHealth);
if (IsDudeSprite(pSource) && pXSource != NULL && pXSource->health != 0)
actHealDude(pXSource, nDamage >> 2, getDudeInfo(pSource->type)->startHealth);
} }
} }
if (pMissile->extra > 0) { if (pMissile->extra > 0)
actPostSprite(pMissile->index, kStatDecoration); {
actPostSprite(missileActor, kStatDecoration);
if (pMissile->ang == 1024) sfxPlay3DSound(pMissile, 307, -1, 0); if (pMissile->ang == 1024) sfxPlay3DSound(pMissile, 307, -1, 0);
pMissile->type = kSpriteDecoration; pMissile->type = kSpriteDecoration;
seqSpawn(9, 3, pMissile->extra, -1); seqSpawn(9, missileActor, -1);
} else { }
else
{
actPostSprite(pMissile->index, kStatFree); actPostSprite(pMissile->index, kStatFree);
} }
break; break;
case kMissileTeslaAlt: case kMissileTeslaAlt:
teslaHit(pMissile, hitCode); teslaHit(pMissile, hitCode);
switch (hitCode) { switch (hitCode)
{
case 0: case 0:
case 4: case 4:
if (pWallHit) { if (pWallHit)
{
spritetype* pFX = gFX.fxSpawn(FX_52, pMissile->sectnum, pMissile->x, pMissile->y, pMissile->z, 0); spritetype* pFX = gFX.fxSpawn(FX_52, pMissile->sectnum, pMissile->x, pMissile->y, pMissile->z, 0);
if (pFX) pFX->ang = (GetWallAngle(nWallHit) + 512) & 2047; if (pFX) pFX->ang = (GetWallAngle(pWallHit) + 512) & 2047;
} }
break; break;
} }
GibSprite(pMissile, GIBTYPE_24, NULL, NULL); GibSprite(pMissile, GIBTYPE_24, NULL, NULL);
actPostSprite(pMissile->index, kStatFree); actPostSprite(missileActor, kStatFree);
break; break;
case kMissilePukeGreen: case kMissilePukeGreen:
seqKill(3, nXMissile); seqKill(missileActor);
if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo)) if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo))
{ {
int nOwner = pMissile->owner; int nOwner = pMissile->owner;
int nDamage = (15+Random(7))<<4; int nDamage = (15 + Random(7)) << 4;
actDamageSprite(nOwner, pSpriteHit, DAMAGE_TYPE_2, nDamage); actDamageSprite(nOwner, pSpriteHit, DAMAGE_TYPE_2, nDamage);
} }
actPostSprite(pMissile->index, kStatFree); actPostSprite(missileActor, kStatFree);
break; break;
case kMissileArcGargoyle: case kMissileArcGargoyle:
sfxKill3DSound(pMissile, -1, -1); sfxKill3DSound(pMissile, -1, -1);
sfxPlay3DSound(pMissile->x, pMissile->y, pMissile->z, 306, pMissile->sectnum); sfxPlay3DSound(pMissile->x, pMissile->y, pMissile->z, 306, pMissile->sectnum);
GibSprite(pMissile, GIBTYPE_6, NULL, NULL); GibSprite(pMissile, GIBTYPE_6, NULL, NULL);
if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo)) if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo))
{ {
int nOwner = pMissile->owner; int nDamage = (25 + Random(20)) << 4;
int nDamage = (25+Random(20))<<4; actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_5, nDamage);
actDamageSprite(nOwner, pSpriteHit, DAMAGE_TYPE_5, nDamage);
} }
actPostSprite(pMissile->index, kStatFree); actPostSprite(missileActor, kStatFree);
break; break;
case kMissileLifeLeechAltNormal: case kMissileLifeLeechAltNormal:
case kMissileLifeLeechAltSmall: case kMissileLifeLeechAltSmall:
sfxKill3DSound(pMissile, -1, -1); sfxKill3DSound(pMissile, -1, -1);
sfxPlay3DSound(pMissile->x, pMissile->y, pMissile->z, 306, pMissile->sectnum); sfxPlay3DSound(pMissile->x, pMissile->y, pMissile->z, 306, pMissile->sectnum);
if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo)) {
int nOwner = pMissile->owner; if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo))
{
int nDmgMul = (pMissile->type == kMissileLifeLeechAltSmall) ? 6 : 3; int nDmgMul = (pMissile->type == kMissileLifeLeechAltSmall) ? 6 : 3;
int nDamage = (nDmgMul+Random(nDmgMul))<<4; int nDamage = (nDmgMul + Random(nDmgMul)) << 4;
actDamageSprite(nOwner, pSpriteHit, DAMAGE_TYPE_5, nDamage); actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_5, nDamage);
} }
actPostSprite(pMissile->index, kStatFree); actPostSprite(missileActor, kStatFree);
break; break;
case kMissileFireball: case kMissileFireball:
case kMissileFireballNapam: case kMissileFireballNapam:
if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo)) if (hitCode == 3 && pSpriteHit && (pThingInfo || pDudeInfo))
{ {
if (pThingInfo && pSpriteHit->type == kThingTNTBarrel && pXSpriteHit->burnTime == 0) if (pThingInfo && pSpriteHit->type == kThingTNTBarrel && actorHit->x().burnTime == 0)
evPost(nSpriteHit, 3, 0, kCallbackFXFlameLick); evPost(actorHit, 0, kCallbackFXFlameLick);
int nOwner = pMissile->owner;
int nDamage = (50+Random(50))<<4; int nDamage = (50 + Random(50)) << 4;
actDamageSprite(nOwner, pSpriteHit, DAMAGE_TYPE_2, nDamage); actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_2, nDamage);
} }
actExplodeSprite(pMissile); actExplodeSprite(pMissile);
break; break;
case kMissileFlareAlt: case kMissileFlareAlt:
sfxKill3DSound(pMissile, -1, -1); sfxKill3DSound(pMissile, -1, -1);
actExplodeSprite(pMissile); actExplodeSprite(pMissile);
break; break;
case kMissileFlareRegular: case kMissileFlareRegular:
sfxKill3DSound(pMissile, -1, -1); sfxKill3DSound(pMissile, -1, -1);
if ((hitCode == 3 && pSpriteHit) && (pThingInfo || pDudeInfo)) { if ((hitCode == 3 && pSpriteHit) && (pThingInfo || pDudeInfo))
int nOwner = pMissile->owner; {
if ((pThingInfo && pThingInfo->dmgControl[DAMAGE_TYPE_1] != 0) || (pDudeInfo && pDudeInfo->damageVal[DAMAGE_TYPE_1] != 0)) { if ((pThingInfo && pThingInfo->dmgControl[DAMAGE_TYPE_1] != 0) || (pDudeInfo && pDudeInfo->damageVal[DAMAGE_TYPE_1] != 0))
if (pThingInfo && pSpriteHit->type == kThingTNTBarrel && pXSpriteHit->burnTime == 0) {
evPost(nSpriteHit, 3, 0, kCallbackFXFlameLick); if (pThingInfo && pSpriteHit->type == kThingTNTBarrel && actorHit->x().burnTime == 0)
evPost(actorHit, 0, kCallbackFXFlameLick);
actBurnSprite(pMissile->owner, pXSpriteHit, 480); actBurnSprite(missileOwner, actorHit, 480);
actRadiusDamage(&bloodActors[nOwner], pMissile->x, pMissile->y, pMissile->z, pMissile->sectnum, 16, 20, 10, DAMAGE_TYPE_2, 6, 480); actRadiusDamage(missileOwner, pMissile->x, pMissile->y, pMissile->z, pMissile->sectnum, 16, 20, 10, DAMAGE_TYPE_2, 6, 480);
// by NoOne: allow additional bullet damage for Flare Gun // by NoOne: allow additional bullet damage for Flare Gun
if (gGameOptions.weaponsV10x && !VanillaMode() && !DemoRecordStatus()) { if (gGameOptions.weaponsV10x && !VanillaMode() && !DemoRecordStatus())
{
int nDamage = (20 + Random(10)) << 4; int nDamage = (20 + Random(10)) << 4;
actDamageSprite(nOwner, pSpriteHit, DAMAGE_TYPE_2, nDamage); actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_2, nDamage);
} }
} else { }
int nDamage = (20+Random(10))<<4; else
actDamageSprite(nOwner, pSpriteHit, DAMAGE_TYPE_2, nDamage); {
int nDamage = (20 + Random(10)) << 4;
actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_2, nDamage);
} }
if (surfType[pSpriteHit->picnum] == kSurfFlesh) { if (surfType[pSpriteHit->picnum] == kSurfFlesh)
{
pMissile->picnum = 2123; pMissile->picnum = 2123;
pXMissile->target = nSpriteHit; missileActor->SetTarget(actorHit);
pXMissile->targetZ = pMissile->z-pSpriteHit->z; pXMissile->targetZ = pMissile->z - pSpriteHit->z;
pXMissile->goalAng = getangle(pMissile->x-pSpriteHit->x, pMissile->y-pSpriteHit->y)-pSpriteHit->ang; pXMissile->goalAng = getangle(pMissile->x - pSpriteHit->x, pMissile->y - pSpriteHit->y) - pSpriteHit->ang;
pXMissile->state = 1; pXMissile->state = 1;
actPostSprite(pMissile->index, kStatFlare); actPostSprite(pMissile->index, kStatFlare);
pMissile->cstat &= ~257; pMissile->cstat &= ~257;
@ -4063,145 +4053,113 @@ void actImpactMissile(spritetype *pMissile, int hitCode)
} }
} }
GibSprite(pMissile, GIBTYPE_17, NULL, NULL); GibSprite(pMissile, GIBTYPE_17, NULL, NULL);
actPostSprite(pMissile->index, kStatFree); actPostSprite(missileActor, kStatFree);
break; break;
case kMissileFlameSpray: case kMissileFlameSpray:
case kMissileFlameHound: case kMissileFlameHound:
if (hitCode == 3) if (hitCode == 3 && actorHit && actorHit->hasX())
{ {
int nObject = gHitInfo.hitsprite; if ((pSpriteHit->statnum == kStatThing || pSpriteHit->statnum == kStatDude) && pXSpriteHit->burnTime == 0)
assert(nObject >= 0 && nObject < kMaxSprites); evPost(actorHit, 0, kCallbackFXFlameLick);
spritetype *pObject = &sprite[nObject];
if (pObject->extra > 0) actBurnSprite(missileOwner, actorHit, (4 + gGameOptions.nDifficulty) << 2);
{ actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_1, 8);
XSPRITE *pXObject = &xsprite[pObject->extra];
if ((pObject->statnum == kStatThing || pObject->statnum == kStatDude) && pXObject->burnTime == 0)
evPost(nObject, 3, 0, kCallbackFXFlameLick);
int nOwner = pMissile->owner;
actBurnSprite(pMissile->owner, pXObject, (4+gGameOptions.nDifficulty)<<2);
actDamageSprite(nOwner, pObject, DAMAGE_TYPE_1, 8);
}
} }
break; break;
case kMissileFireballCerberus: case kMissileFireballCerberus:
actExplodeSprite(pMissile); actExplodeSprite(pMissile);
if (hitCode == 3) if (hitCode == 3 && actorHit && actorHit->hasX())
{ {
int nObject = gHitInfo.hitsprite; if ((pSpriteHit->statnum == kStatThing || pSpriteHit->statnum == kStatDude) && pXSpriteHit->burnTime == 0)
assert(nObject >= 0 && nObject < kMaxSprites); evPost(actorHit, 0, kCallbackFXFlameLick);
spritetype *pObject = &sprite[nObject];
if (pObject->extra > 0) actBurnSprite(missileOwner, actorHit, (4 + gGameOptions.nDifficulty) << 2);
{ actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_1, 8);
XSPRITE *pXObject = &xsprite[pObject->extra]; int nDamage = (25 + Random(10)) << 4;
if ((pObject->statnum == kStatThing || pObject->statnum == kStatDude) && pXObject->burnTime == 0) actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_2, nDamage);
evPost(nObject, 3, 0, kCallbackFXFlameLick);
int nOwner = pMissile->owner;
actBurnSprite(pMissile->owner, pXObject, (4+gGameOptions.nDifficulty)<<2);
actDamageSprite(nOwner, pObject, DAMAGE_TYPE_1, 8);
int nDamage = (25+Random(10))<<4;
actDamageSprite(nOwner, pObject, DAMAGE_TYPE_2, nDamage);
}
} }
actExplodeSprite(pMissile); actExplodeSprite(pMissile);
break; break;
case kMissileFireballTchernobog: case kMissileFireballTchernobog:
actExplodeSprite(pMissile); actExplodeSprite(pMissile);
if (hitCode == 3) if (hitCode == 3 && actorHit && actorHit->hasX())
{ {
int nObject = gHitInfo.hitsprite; if ((pSpriteHit->statnum == kStatThing || pSpriteHit->statnum == kStatDude) && pXSpriteHit->burnTime == 0)
assert(nObject >= 0 && nObject < kMaxSprites); evPost(actorHit, 0, kCallbackFXFlameLick);
spritetype *pObject = &sprite[nObject];
if (pObject->extra > 0) actBurnSprite(missileOwner, actorHit, 32);
{ actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_5, 12);
XSPRITE *pXObject = &xsprite[pObject->extra]; int nDamage = (25 + Random(10)) << 4;
if ((pObject->statnum == kStatThing || pObject->statnum == kStatDude) && pXObject->burnTime == 0) actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_2, nDamage);
evPost(nObject, 3, 0, kCallbackFXFlameLick);
int nOwner = pMissile->owner;
actBurnSprite(pMissile->owner, pXObject, 32);
actDamageSprite(nOwner, pObject, DAMAGE_TYPE_5, 12);
int nDamage = (25+Random(10))<<4;
actDamageSprite(nOwner, pObject, DAMAGE_TYPE_2, nDamage);
}
} }
actExplodeSprite(pMissile); actExplodeSprite(pMissile);
break; break;
case kMissileEctoSkull: case kMissileEctoSkull:
sfxKill3DSound(pMissile, -1, -1); sfxKill3DSound(pMissile, -1, -1);
sfxPlay3DSound(pMissile->x, pMissile->y, pMissile->z, 522, pMissile->sectnum); sfxPlay3DSound(pMissile->x, pMissile->y, pMissile->z, 522, pMissile->sectnum);
actPostSprite(pMissile->index, kStatDebris); actPostSprite(pMissile->index, kStatDebris);
seqSpawn(20, 3, pMissile->extra, -1); seqSpawn(20, 3, pMissile->extra, -1);
if (hitCode == 3) if (hitCode == 3 && actorHit && actorHit->hasX())
{ {
int nObject = gHitInfo.hitsprite; if (pSpriteHit->statnum == kStatDude)
assert(nObject >= 0 && nObject < kMaxSprites);
spritetype *pObject = &sprite[nObject];
if (pObject->statnum == kStatDude)
{ {
int nOwner = pMissile->owner; int nDamage = (25 + Random(10)) << 4;
int nDamage = (25+Random(10))<<4; actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_5, nDamage);
actDamageSprite(nOwner, pObject, DAMAGE_TYPE_5, nDamage);
} }
} }
break; break;
case kMissileButcherKnife: case kMissileButcherKnife:
actPostSprite(pMissile->index, kStatDebris); actPostSprite(missileActor, kStatDebris);
pMissile->cstat &= ~16; pMissile->cstat &= ~16;
pMissile->type = kSpriteDecoration; pMissile->type = kSpriteDecoration;
seqSpawn(20, 3, pMissile->extra, -1); seqSpawn(20, 3, pMissile->extra, -1);
if (hitCode == 3) if (hitCode == 3 && actorHit && actorHit->hasX())
{ {
int nObject = gHitInfo.hitsprite; if (pSpriteHit->statnum == kStatDude)
assert(nObject >= 0 && nObject < kMaxSprites);
spritetype *pObject = &sprite[nObject];
if (pObject->statnum == kStatDude)
{ {
int nOwner = pMissile->owner; int nDamage = (10 + Random(10)) << 4;
int nDamage = (10+Random(10))<<4; actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_5, nDamage);
actDamageSprite(nOwner, pObject, DAMAGE_TYPE_5, nDamage); int nType = missileOwner->s().type - kDudeBase;
spritetype *pOwner = &sprite[nOwner]; if (missileOwner->x().health > 0)
XSPRITE *pXOwner = &xsprite[pOwner->extra]; actHealDude(missileOwner, 10, getDudeInfo(nType + kDudeBase)->startHealth);
int nType = pOwner->type-kDudeBase;
if (pXOwner->health > 0)
actHealDude(pXOwner, 10, getDudeInfo(nType+kDudeBase)->startHealth);
} }
} }
break; break;
case kMissileTeslaRegular: case kMissileTeslaRegular:
sfxKill3DSound(pMissile, -1, -1); sfxKill3DSound(pMissile, -1, -1);
sfxPlay3DSound(pMissile->x, pMissile->y, pMissile->z, 518, pMissile->sectnum); sfxPlay3DSound(pMissile->x, pMissile->y, pMissile->z, 518, pMissile->sectnum);
GibSprite(pMissile, (hitCode == 2) ? GIBTYPE_23 : GIBTYPE_22, NULL, NULL); GibSprite(pMissile, (hitCode == 2) ? GIBTYPE_23 : GIBTYPE_22, NULL, NULL);
evKill(pMissile->index, 3); evKill(missileActor);
seqKill(3, nXMissile); seqKill(missileActor);
actPostSprite(pMissile->index, kStatFree); actPostSprite(missileActor, kStatFree);
if (hitCode == 3) if (hitCode == 3 && actorHit)
{ {
int nObject = gHitInfo.hitsprite; int nDamage = (15 + Random(10)) << 4;
assert(nObject >= 0 && nObject < kMaxSprites); actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_6, nDamage);
spritetype *pObject = &sprite[nObject];
int nOwner = pMissile->owner;
int nDamage = (15+Random(10))<<4;
actDamageSprite(nOwner, pObject, DAMAGE_TYPE_6, nDamage);
} }
break; break;
default: default:
seqKill(3, nXMissile); seqKill(missileActor);
actPostSprite(pMissile->index, kStatFree); actPostSprite(missileActor, kStatFree);
if (hitCode == 3) if (hitCode == 3 && actorHit)
{ {
int nObject = gHitInfo.hitsprite; int nDamage = (10 + Random(10)) << 4;
assert(nObject >= 0 && nObject < kMaxSprites); actDamageSprite(missileOwner, actorHit, DAMAGE_TYPE_0, nDamage);
spritetype *pObject = &sprite[nObject];
int nOwner = pMissile->owner;
int nDamage = (10+Random(10))<<4;
actDamageSprite(nOwner, pObject, DAMAGE_TYPE_0, nDamage);
} }
break; break;
} }
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
if (gModernMap && pXSpriteHit && pXSpriteHit->state != pXSpriteHit->restState && pXSpriteHit->Impact) if (gModernMap && pXSpriteHit && pXSpriteHit->state != pXSpriteHit->restState && pXSpriteHit->Impact)
trTriggerSprite(nSpriteHit, pXSpriteHit, kCmdSpriteImpact); trTriggerSprite(actorHit, kCmdSpriteImpact);
#endif #endif
pMissile->cstat &= ~257; pMissile->cstat &= ~257;
} }
@ -4825,7 +4783,7 @@ void MoveDude(spritetype *pSprite)
{ {
HITINFO hitInfo = gHitInfo; HITINFO hitInfo = gHitInfo;
gHitInfo.hitsprite = nSprite; gHitInfo.hitsprite = nSprite;
actImpactMissile(pHitSprite, 3); actImpactMissile(&bloodActors[nHitSprite], 3);
gHitInfo = hitInfo; gHitInfo = hitInfo;
} }
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
@ -5893,7 +5851,7 @@ void actProcessSprites(void)
viewBackupSpriteLoc(nSprite, pSprite); viewBackupSpriteLoc(nSprite, pSprite);
int hit = MoveMissile(pSprite); int hit = MoveMissile(pSprite);
if (hit >= 0) if (hit >= 0)
actImpactMissile(pSprite, hit); actImpactMissile(&bloodActors[pSprite->index], hit);
} }
it.Reset(kStatExplosion); it.Reset(kStatExplosion);
while ((nSprite = it.NextIndex()) >= 0) while ((nSprite = it.NextIndex()) >= 0)
@ -6597,7 +6555,7 @@ spritetype* actFireMissile(spritetype *pSprite, int a2, int a3, int a4, int a5,
if (v4) if (v4)
{ {
actImpactMissile(pMissile, hit); actImpactMissile(&bloodActors[pMissile->index], hit);
pMissile = NULL; pMissile = NULL;
} }
return pMissile; return pMissile;

View file

@ -221,8 +221,7 @@ void actKillDude(DBloodActor* a1, DBloodActor* pSprite, DAMAGE_TYPE a3, int a4);
void actKillDude(int a1, spritetype *pSprite, DAMAGE_TYPE a3, int a4); void actKillDude(int a1, spritetype *pSprite, DAMAGE_TYPE a3, int a4);
int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE a3, int a4); 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, int *a3, spritetype **a4, XSPRITE **a5, int *a6, walltype **a7, XWALL **a8, int *a9, sectortype **a10, XSECTOR **a11); void actHitcodeToData(int a1, HITINFO *pHitInfo, DBloodActor **actor, walltype **a7 = nullptr);
void actImpactMissile(spritetype *pMissile, int hitCode);
void actKickObject(spritetype *pSprite1, spritetype *pSprite2); void actKickObject(spritetype *pSprite1, spritetype *pSprite2);
void actTouchFloor(spritetype *pSprite, int nSector); void actTouchFloor(spritetype *pSprite, int nSector);
void ProcessTouchObjects(spritetype *pSprite, int nXSprite); void ProcessTouchObjects(spritetype *pSprite, int nXSprite);

View file

@ -80,12 +80,12 @@ void SlashSeqCallback(int, DBloodActor* actor)
sfxPlay3DSound(pSprite, 9012+Random(2), -1, 0); sfxPlay3DSound(pSprite, 9012+Random(2), -1, 0);
} }
void StompSeqCallback(int, DBloodActor* actor) void StompSeqCallback(int, DBloodActor* actor1)
{ {
uint8_t vb8[(kMaxSectors+7)>>3]; uint8_t vb8[(kMaxSectors+7)>>3];
XSPRITE* pXSprite = &actor->x(); XSPRITE* pXSprite = &actor1->x();
int nSprite = pXSprite->reference; int nSprite = pXSprite->reference;
spritetype *pSprite = &actor->s(); spritetype *pSprite = &actor1->s();
int dx = CosScale16(pSprite->ang); int dx = CosScale16(pSprite->ang);
int dy = SinScale16(pSprite->ang); int dy = SinScale16(pSprite->ang);
int x = pSprite->x; int x = pSprite->x;
@ -97,12 +97,12 @@ void StompSeqCallback(int, DBloodActor* actor)
int v10 = 25+30*gGameOptions.nDifficulty; int v10 = 25+30*gGameOptions.nDifficulty;
GetClosestSpriteSectors(nSector, x, y, vc, vb8); GetClosestSpriteSectors(nSector, x, y, vc, vb8);
char v4 = 0; char v4 = 0;
int v34 = -1;
int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0); int hit = HitScan(pSprite, pSprite->z, dx, dy, 0, CLIPMASK1, 0);
actHitcodeToData(hit, &gHitInfo, &v34, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); DBloodActor* actor2 = nullptr;
if (hit == 3 && v34 >= 0) actHitcodeToData(hit, &gHitInfo, &actor2);
if (hit == 3 && actor2)
{ {
if (sprite[v34].statnum == kStatDude) if (actor2->s().statnum == kStatDude)
v4 = 0; v4 = 0;
} }
vc <<= 4; vc <<= 4;
@ -178,7 +178,7 @@ static void MorphToBeast(DBloodActor* actor)
{ {
auto pXSprite = &actor->x(); auto pXSprite = &actor->x();
auto pSprite = &actor->s(); auto pSprite = &actor->s();
actHealDude(pXSprite, dudeInfo[51].startHealth, dudeInfo[51].startHealth); actHealDude(actor, dudeInfo[51].startHealth, dudeInfo[51].startHealth);
pSprite->type = kDudeBeast; pSprite->type = kDudeBeast;
} }

View file

@ -50,6 +50,17 @@ public:
return base() + s().owner; return base() + s().owner;
} }
void SetTarget(DBloodActor* own)
{
x().target = own ? own->s().index : -1;
}
DBloodActor* GetTarget()
{
if (x().target == -1 || x().target == kMaxSprites - 1) return nullptr;
return base() + x().target;
}
void SetSpecialOwner() // nnext hackery void SetSpecialOwner() // nnext hackery
{ {
s().owner = kMaxSprites - 1; s().owner = kMaxSprites - 1;

View file

@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "blood.h" #include "blood.h"
#include "secrets.h" #include "secrets.h"
#include "serializer.h" #include "serializer.h"
#include "bloodactor.h"
BEGIN_BLD_NS BEGIN_BLD_NS
@ -525,6 +526,16 @@ void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback)
} }
void evPost(DBloodActor* actor, unsigned int nDelta, COMMAND_ID command)
{
evPost(actor->s().index, 3, nDelta, command);
}
void evPost(DBloodActor* actor, unsigned int nDelta, CALLBACK_ID callback)
{
evPost(actor->s().index, 3, nDelta, callback);
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// //
@ -549,6 +560,11 @@ void evKill(int index, int type, CALLBACK_ID cb)
} }
} }
void evKill(DBloodActor* actor)
{
evKill(actor->s().index, 3);
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// //

View file

@ -158,8 +158,12 @@ void evInit(void);
void evSend(int nIndex, int nType, int rxId, COMMAND_ID command); void evSend(int nIndex, int nType, int rxId, COMMAND_ID command);
void evPost(int nIndex, int nType, unsigned int nDelta, COMMAND_ID command); void evPost(int nIndex, int nType, unsigned int nDelta, COMMAND_ID command);
void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback); void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback);
void evPost(DBloodActor*, unsigned int nDelta, COMMAND_ID command);
void evPost(DBloodActor*, unsigned int nDelta, CALLBACK_ID callback);
void evProcess(unsigned int nTime); void evProcess(unsigned int nTime);
void evKill(int a1, int a2); void evKill(int a1, int a2);
void evKill(int a1, int a2, CALLBACK_ID a3); void evKill(int a1, int a2, CALLBACK_ID a3);
void evKill(DBloodActor*);
END_BLD_NS END_BLD_NS

View file

@ -321,6 +321,12 @@ int GetWallAngle(int nWall)
return getangle(wall[nWall2].x - wall[nWall].x, wall[nWall2].y - wall[nWall].y); return getangle(wall[nWall2].x - wall[nWall].x, wall[nWall2].y - wall[nWall].y);
} }
int GetWallAngle(walltype* pWall)
{
int nWall2 = pWall->point2;
return getangle(wall[nWall2].x - pWall->x, wall[nWall2].y - pWall->y);
}
void GetWallNormal(int nWall, int *pX, int *pY) void GetWallNormal(int nWall, int *pX, int *pY)
{ {
assert(nWall >= 0 && nWall < kMaxWalls); assert(nWall >= 0 && nWall < kMaxWalls);

View file

@ -72,6 +72,7 @@ bool CheckProximity(spritetype *pSprite, int nX, int nY, int nZ, int nSector, in
bool CheckProximityPoint(int nX1, int nY1, int nZ1, int nX2, int nY2, int nZ2, int nDist); bool CheckProximityPoint(int nX1, int nY1, int nZ1, int nX2, int nY2, int nZ2, int nDist);
bool CheckProximityWall(int nWall, int x, int y, int nDist); bool CheckProximityWall(int nWall, int x, int y, int nDist);
int GetWallAngle(int nWall); int GetWallAngle(int nWall);
int GetWallAngle(walltype* pWall);
void GetWallNormal(int nWall, int *pX, int *pY); void GetWallNormal(int nWall, int *pX, int *pY);
bool IntersectRay(int wx, int wy, int wdx, int wdy, int x1, int y1, int z1, int x2, int y2, int z2, int *ix, int *iy, int *iz); bool IntersectRay(int wx, int wy, int wdx, int wdy, int x1, int y1, int z1, int x2, int y2, int z2, int *ix, int *iy, int *iz);
int HitScan(spritetype *pSprite, int z, int dx, int dy, int dz, unsigned int nMask, int a8); int HitScan(spritetype *pSprite, int z, int dx, int dy, int dz, unsigned int nMask, int a8);

View file

@ -1802,6 +1802,10 @@ void trTriggerSprite(unsigned int nSprite, XSPRITE *pXSprite, int command) {
} }
} }
void trTriggerSprite(DBloodActor* actor, int command) {
trTriggerSprite(actor->s().index, &actor->x(), command);
}
void trMessageSector(unsigned int nSector, EVENT event) { void trMessageSector(unsigned int nSector, EVENT event) {
assert(nSector < (unsigned int)numsectors); assert(nSector < (unsigned int)numsectors);

View file

@ -35,6 +35,7 @@ void trMessageSector(unsigned int nSector, EVENT event);
void trTriggerWall(unsigned int nWall, XWALL *pXWall, int command); void trTriggerWall(unsigned int nWall, XWALL *pXWall, int command);
void trMessageWall(unsigned int nWall, EVENT event); void trMessageWall(unsigned int nWall, EVENT event);
void trTriggerSprite(unsigned int nSprite, XSPRITE *pXSprite, int command); void trTriggerSprite(unsigned int nSprite, XSPRITE *pXSprite, int command);
void trTriggerSprite(DBloodActor* actor, int command);
void trMessageSprite(unsigned int nSprite, EVENT event); void trMessageSprite(unsigned int nSprite, EVENT event);
void trProcessBusy(void); void trProcessBusy(void);
void trInit(void); void trInit(void);

View file

@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "build.h" #include "build.h"
#include "blood.h" #include "blood.h"
#include "bloodactor.h"
BEGIN_BLD_NS BEGIN_BLD_NS
@ -2591,9 +2592,9 @@ void teslaHit(spritetype *pMissile, int a2)
int nOwner = pMissile->owner; int nOwner = pMissile->owner;
GetClosestSpriteSectors(nSector, x, y, nDist, va4); GetClosestSpriteSectors(nSector, x, y, nDist, va4);
bool v4 = true; bool v4 = true;
int v24 = -1; DBloodActor* actor = nullptr;
actHitcodeToData(a2, &gHitInfo, &v24, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); actHitcodeToData(a2, &gHitInfo, &actor);
if (a2 == 3 && v24 >= 0 && sprite[v24].statnum == kStatDude) if (a2 == 3 && actor && actor->s().statnum == kStatDude)
v4 = false; v4 = false;
int nSprite; int nSprite;
StatIterator it(kStatDude); StatIterator it(kStatDude);