- actFireMissile.

This commit is contained in:
Christoph Oelckers 2020-12-05 21:23:53 +01:00
parent 7eac8b71d5
commit 351dabdb90
13 changed files with 145 additions and 127 deletions

View file

@ -6654,11 +6654,92 @@ DBloodActor* actFireThing(DBloodActor* actor, int a2, int a3, int a4, int thingT
//
//---------------------------------------------------------------------------
spritetype* actFireMissile(spritetype* pSprite, int a2, int a3, int a4, int a5, int a6, int nType)
void actBuildMissile(DBloodActor* spawned, DBloodActor* actor)
{
auto pMissile = &spawned->s();
int nMissile = pMissile->index;
switch (pMissile->type)
{
case kMissileLifeLeechRegular:
evPost(nMissile, 3, 0, kCallbackFXFlameLick);
break;
case kMissileTeslaAlt:
evPost(nMissile, 3, 0, kCallbackFXTeslaAlt);
break;
case kMissilePukeGreen:
seqSpawn(29, spawned, -1);
break;
case kMissileButcherKnife:
pMissile->cstat |= 16;
break;
case kMissileTeslaRegular:
sfxPlay3DSound(pMissile, 251, 0, 0);
break;
case kMissileEctoSkull:
seqSpawn(2, spawned, -1);
sfxPlay3DSound(pMissile, 493, 0, 0);
break;
case kMissileFireballNapalm:
seqSpawn(61, spawned, nNapalmClient);
sfxPlay3DSound(pMissile, 441, 0, 0);
break;
case kMissileFireball:
seqSpawn(22, spawned, nFireballClient);
sfxPlay3DSound(pMissile, 441, 0, 0);
break;
case kMissileFlameHound:
seqSpawn(27, spawned, -1);
spawned->xvel() += actor->xvel() / 2 + Random2(0x11111);
spawned->yvel() += actor->yvel() / 2 + Random2(0x11111);
spawned->zvel() += actor->zvel() / 2 + Random2(0x11111);
break;
case kMissileFireballCerberus:
seqSpawn(61, spawned, dword_2192E0);
sfxPlay3DSound(pMissile, 441, 0, 0);
break;
case kMissileFireballTchernobog:
seqSpawn(23, spawned, dword_2192D8);
spawned->xvel() += actor->xvel() / 2 + Random2(0x11111);
spawned->yvel() += actor->yvel() / 2 + Random2(0x11111);
spawned->zvel() += actor->zvel() / 2 + Random2(0x11111);
break;
case kMissileFlameSpray:
if (Chance(0x8000)) seqSpawn(0, spawned, -1);
else seqSpawn(1, spawned, -1);
spawned->xvel() += actor->xvel() / 2 + Random2(0x11111);
spawned->yvel() += actor->yvel() / 2 + Random2(0x11111);
spawned->zvel() += actor->zvel() / 2 + Random2(0x11111);
break;
case kMissileFlareAlt:
evPost(spawned, 30, kCallbackFXFlareBurst);
evPost(spawned, 0, kCallbackFXFlareSpark);
sfxPlay3DSound(pMissile, 422, 0, 0);
break;
case kMissileFlareRegular:
evPost(spawned, 0, kCallbackFXFlareSpark);
sfxPlay3DSound(pMissile, 422, 0, 0);
break;
case kMissileLifeLeechAltSmall:
evPost(spawned, 0, kCallbackFXArcSpark);
break;
case kMissileArcGargoyle:
sfxPlay3DSound(pMissile, 252, 0, 0);
break;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
DBloodActor* actFireMissile(DBloodActor* actor, int a2, int a3, int a4, int a5, int a6, int nType)
{
assert(nType >= kMissileBase && nType < kMissileMax);
char v4 = 0;
auto pSprite = &actor->s();
int nSprite = pSprite->index;
const MissileType* pMissileInfo = &missileInfo[nType - kMissileBase];
int x = pSprite->x + MulScale(a2, Cos(pSprite->ang + 512), 30);
@ -6682,8 +6763,8 @@ spritetype* actFireMissile(spritetype* pSprite, int a2, int a3, int a4, int a5,
y = gHitInfo.hity - MulScale(pMissileInfo->clipDist << 1, Sin(pSprite->ang), 28);
}
}
auto actor = actSpawnSprite(pSprite->sectnum, x, y, z, 5, 1);
spritetype* pMissile = &actor->s();
auto spawned = actSpawnSprite(pSprite->sectnum, x, y, z, 5, 1);
spritetype* pMissile = &spawned->s();
int nMissile = pMissile->index;
show2dsprite.Set(nMissile);
pMissile->type = nType;
@ -6695,98 +6776,29 @@ spritetype* actFireMissile(spritetype* pSprite, int a2, int a3, int a4, int a5,
pMissile->yrepeat = pMissileInfo->yrepeat;
pMissile->picnum = pMissileInfo->picnum;
pMissile->ang = (pSprite->ang + pMissileInfo->angleOfs) & 2047;
xvel[nMissile] = MulScale(pMissileInfo->velocity, a4, 14);
yvel[nMissile] = MulScale(pMissileInfo->velocity, a5, 14);
zvel[nMissile] = MulScale(pMissileInfo->velocity, a6, 14);
spawned->xvel() = MulScale(pMissileInfo->velocity, a4, 14);
spawned->yvel() = MulScale(pMissileInfo->velocity, a5, 14);
spawned->zvel() = MulScale(pMissileInfo->velocity, a6, 14);
pMissile->owner = pSprite->index;
pMissile->cstat |= 1;
int nXSprite = pMissile->extra;
assert(nXSprite > 0 && nXSprite < kMaxXSprites);
xsprite[nXSprite].target_i = -1;
evPost(nMissile, 3, 600, kCallbackRemove);
spawned->SetTarget(nullptr);
evPost(spawned, 600, kCallbackRemove);
actBuildMissile(pMissile, nXSprite, nSprite);
actBuildMissile(spawned, actor);
if (v4)
{
actImpactMissile(&bloodActors[pMissile->index], hit);
pMissile = NULL;
actImpactMissile(spawned, hit);
return nullptr;
}
return pMissile;
return spawned;
}
void actBuildMissile(spritetype* pMissile, int nXSprite, int nSprite) {
int nMissile = pMissile->index;
switch (pMissile->type) {
case kMissileLifeLeechRegular:
evPost(nMissile, 3, 0, kCallbackFXFlameLick);
break;
case kMissileTeslaAlt:
evPost(nMissile, 3, 0, kCallbackFXTeslaAlt);
break;
case kMissilePukeGreen:
seqSpawn(29, 3, nXSprite, -1);
break;
case kMissileButcherKnife:
pMissile->cstat |= 16;
break;
case kMissileTeslaRegular:
sfxPlay3DSound(pMissile, 251, 0, 0);
break;
case kMissileEctoSkull:
seqSpawn(2, 3, nXSprite, -1);
sfxPlay3DSound(pMissile, 493, 0, 0);
break;
case kMissileFireballNapalm:
seqSpawn(61, 3, nXSprite, nNapalmClient);
sfxPlay3DSound(pMissile, 441, 0, 0);
break;
case kMissileFireball:
seqSpawn(22, 3, nXSprite, nFireballClient);
sfxPlay3DSound(pMissile, 441, 0, 0);
break;
case kMissileFlameHound:
seqSpawn(27, 3, nXSprite, -1);
xvel[nMissile] += xvel[nSprite] / 2 + Random2(0x11111);
yvel[nMissile] += yvel[nSprite] / 2 + Random2(0x11111);
zvel[nMissile] += zvel[nSprite] / 2 + Random2(0x11111);
break;
case kMissileFireballCerberus:
seqSpawn(61, 3, nXSprite, dword_2192E0);
sfxPlay3DSound(pMissile, 441, 0, 0);
break;
case kMissileFireballTchernobog:
seqSpawn(23, 3, nXSprite, dword_2192D8);
xvel[nMissile] += xvel[nSprite] / 2 + Random2(0x11111);
yvel[nMissile] += yvel[nSprite] / 2 + Random2(0x11111);
zvel[nMissile] += zvel[nSprite] / 2 + Random2(0x11111);
break;
case kMissileFlameSpray:
if (Chance(0x8000))
seqSpawn(0, 3, nXSprite, -1);
else
seqSpawn(1, 3, nXSprite, -1);
xvel[nMissile] += xvel[nSprite] + Random2(0x11111);
yvel[nMissile] += yvel[nSprite] + Random2(0x11111);
zvel[nMissile] += zvel[nSprite] + Random2(0x11111);
break;
case kMissileFlareAlt:
evPost(nMissile, 3, 30, kCallbackFXFlareBurst);
evPost(nMissile, 3, 0, kCallbackFXFlareSpark);
sfxPlay3DSound(pMissile, 422, 0, 0);
break;
case kMissileFlareRegular:
evPost(nMissile, 3, 0, kCallbackFXFlareSpark);
sfxPlay3DSound(pMissile, 422, 0, 0);
break;
case kMissileLifeLeechAltSmall:
evPost(nMissile, 3, 0, kCallbackFXArcSpark);
break;
case kMissileArcGargoyle:
sfxPlay3DSound(pMissile, 252, 0, 0);
break;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int actGetRespawnTime(DBloodActor* actor)
{

View file

@ -233,8 +233,8 @@ DBloodActor* actSpawnSprite(int nSector, int x, int y, int z, int nStat, bool a6
DBloodActor* actSpawnDude(DBloodActor* pSource, short nType, int a3, int a4);
DBloodActor * actSpawnSprite(DBloodActor *pSource, int nStat);
DBloodActor * actSpawnThing(int nSector, int x, int y, int z, int nThingType);
spritetype * actFireThing_(spritetype *pSprite, int a2, int a3, int a4, int thingType, int a6);
DBloodActor* actFireThing(DBloodActor* pSprite, int a2, int a3, int a4, int thingType, int a6);
DBloodActor* actFireMissile(DBloodActor *pSprite, int a2, int a3, int a4, int a5, int a6, int nType);
int actGetRespawnTime(DBloodActor *pSprite);
bool actCheckRespawn(DBloodActor *pSprite);
@ -244,7 +244,7 @@ void actPostSprite(int nSprite, int nStatus);
void actPostSprite(DBloodActor* actor, int status);
void actPostProcess(void);
void MakeSplash(DBloodActor *actor);
void actBuildMissile(spritetype* pMissile, int nXSprite, int nSprite);
void actBuildMissile(DBloodActor* spawned, DBloodActor* actor);
extern const int DudeDifficulty[];

View file

@ -144,11 +144,11 @@ void cerberusBurnSeqCallback(int, DBloodActor* actor)
}
switch (pSprite->type) {
case kDudeCerberusTwoHead:
actFireMissile(pSprite, -350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
actFireMissile(actor, -350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
actFireMissile(actor, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
break;
case kDudeCerberusOneHead:
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
actFireMissile(actor, 350, -100, aim.dx, aim.dy, aim.dz, kMissileFireballCerberus);
break;
}
}
@ -226,11 +226,11 @@ void cerberusBurnSeqCallback2(int, DBloodActor* actor)
}
switch (pSprite->type) {
case kDudeCerberusTwoHead:
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound);
actFireMissile(pSprite, -350, 0, ax, ay, az, kMissileFlameHound);
actFireMissile(actor, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound);
actFireMissile(actor, -350, 0, ax, ay, az, kMissileFlameHound);
break;
case kDudeCerberusOneHead:
actFireMissile(pSprite, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound);
actFireMissile(actor, 350, -100, aim.dx, aim.dy, -aim.dz, kMissileFlameHound);
break;
}
}

View file

@ -99,7 +99,7 @@ void TeslaSeqCallback(int, DBloodActor* actor)
dx += Random3((5 - gGameOptions.nDifficulty) * 1000);
dy += Random3((5 - gGameOptions.nDifficulty) * 1000);
dz += Random3((5 - gGameOptions.nDifficulty) * 500);
actFireMissile(pSprite, 0, 0, dx, dy, dz, kMissileTeslaRegular);
actFireMissile(actor, 0, 0, dx, dy, dz, kMissileTeslaRegular);
sfxPlay3DSound(actor, 470, -1, 0);
}
}

View file

@ -188,13 +188,13 @@ void BlastSSeqCallback(int, DBloodActor* actor)
#ifdef NOONE_EXTENSIONS
// allow to fire missile in non-player targets
if (IsPlayerSprite(pTarget) || gModernMap) {
actFireMissile(pSprite, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
actFireMissile(pSprite, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
actFireMissile(actor, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
actFireMissile(actor, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
}
#else
if (IsPlayerSprite(pTarget)) {
actFireMissile(pSprite, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
actFireMissile(pSprite, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
actFireMissile(actor, -120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
actFireMissile(actor, 120, 0, aim.dx, aim.dy, aim.dz, kMissileArcGargoyle);
}
#endif

View file

@ -172,12 +172,12 @@ void ghostBlastSeqCallback(int, DBloodActor* actor)
// allow fire missile in non-player targets if not a demo
if (IsPlayerSprite(pTarget) || gModernMap) {
sfxPlay3DSound(actor, 489, 0, 0);
actFireMissile(pSprite, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull);
actFireMissile(actor, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull);
}
#else
if (IsPlayerSprite(pTarget)) {
sfxPlay3DSound(actor, 489, 0, 0);
actFireMissile(pSprite, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull);
actFireMissile(actor, 0, 0, aim.dx, aim.dy, aim.dz, kMissileEctoSkull);
}
#endif
}

View file

@ -69,7 +69,7 @@ void houndBiteSeqCallback(int, DBloodActor* actor)
void houndBurnSeqCallback(int, DBloodActor* actor)
{
spritetype* pSprite = &actor->s();
actFireMissile(pSprite, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileFlameHound);
actFireMissile(actor, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileFlameHound);
}
static void houndThinkSearch(DBloodActor* actor)

View file

@ -128,8 +128,8 @@ void sub_71BD4(int, DBloodActor* actor)
}
}
}
actFireMissile(pSprite, -350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballTchernobog);
actFireMissile(pSprite, 350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballTchernobog);
actFireMissile(actor, -350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballTchernobog);
actFireMissile(actor, 350, 0, aim.dx, aim.dy, aim.dz, kMissileFireballTchernobog);
}
void sub_720AC(int, DBloodActor* actor)
@ -203,8 +203,8 @@ void sub_720AC(int, DBloodActor* actor)
}
}
}
actFireMissile(pSprite, 350, 0, aim.dx, aim.dy, -aim.dz, kMissileFireballTchernobog);
actFireMissile(pSprite, -350, 0, ax, ay, az, kMissileFireballTchernobog);
actFireMissile(actor, 350, 0, aim.dx, aim.dy, -aim.dz, kMissileFireballTchernobog);
actFireMissile(actor, -350, 0, ax, ay, az, kMissileFireballTchernobog);
}
static void sub_72580(DBloodActor* actor)

View file

@ -288,7 +288,7 @@ void genDudeAttack1(int, DBloodActor* actor)
// dispersal modifiers here
dx += Random3(dispersion); dy += Random3(dispersion); dz += Random3(dispersion >> 1);
actFireMissile(pSprite, 0, 0, dx, dy, dz, pExtra->curWeapon);
actFireMissile(actor, 0, 0, dx, dy, dz, pExtra->curWeapon);
if (!playGenDudeSound(pSprite, kGenDudeSndAttackNormal))
sfxPlayMissileSound(pSprite, pExtra->curWeapon);
}
@ -1648,6 +1648,7 @@ void dudeLeechOperate(spritetype* pSprite, XSPRITE* pXSprite, EVENT event)
actPostSprite(pSprite->index, kStatFree);
return;
}
auto actor = &bloodActors[pSprite->index];
int nTarget = pXSprite->target_i;
if (spriRangeIsFine(nTarget) && nTarget != pSprite->owner) {
@ -1682,10 +1683,10 @@ void dudeLeechOperate(spritetype* pSprite, XSPRITE* pXSprite, EVENT event)
if (!pXSprite->data3) t2 = 120 / 10;
else t2 = (3 * 120) / 10;
spritetype * pMissile = actFireMissile(pSprite, 0, z1, dx, dy, dz, nMissileType);
if (pMissile)
auto missile = actFireMissile(actor, 0, z1, dx, dy, dz, nMissileType);
if (missile)
{
pMissile->owner = pSprite->owner;
missile->SetOwner(actor);
pXSprite->stateTimer = 1;
evPost(pSprite->index, 3, t2, kCallbackLeechStateTimer);
pXSprite->data3 = ClipLow(pXSprite->data3 - 1, 0);

View file

@ -77,13 +77,13 @@ void PukeSeqCallback(int, DBloodActor* actor)
int dx = CosScale16(nAngle);
int dy = SinScale16(nAngle);
sfxPlay3DSound(pSprite, 1203, 1, 0);
actFireMissile(pSprite, 0, -(height - height2), dx, dy, 0, kMissilePukeGreen);
actFireMissile(actor, 0, -(height - height2), dx, dy, 0, kMissilePukeGreen);
}
void ThrowSeqCallback(int, DBloodActor* actor)
{
spritetype* pSprite = &actor->s();
actFireMissile(pSprite, 0, -getDudeInfo(pSprite->type)->eyeHeight, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileButcherKnife);
actFireMissile(actor, 0, -getDudeInfo(pSprite->type)->eyeHeight, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileButcherKnife);
}
static void zombfThinkSearch(DBloodActor* actor)

View file

@ -5482,6 +5482,7 @@ void useUniMissileGen(XSPRITE* pXSource, spritetype* pSprite) {
spritetype* pSource = &sprite[pXSource->reference];
if (pSprite == NULL)
pSprite = pSource;
auto actor = &bloodActors[pSprite->index];
if (pXSource->data1 < kMissileBase || pXSource->data1 >= kMissileMax)
return;
@ -5497,9 +5498,9 @@ void useUniMissileGen(XSPRITE* pXSource, spritetype* pSprite) {
else if (dz < -0x10000) dz = -0x10000;
}
spritetype* pMissile = NULL;
if ((pMissile = actFireMissile(pSprite, 0, 0, dx, dy, dz, pXSource->data1)) != NULL) {
auto missile = actFireMissile(actor, 0, 0, dx, dy, dz, actor->x().data1);
if (missile != NULL) {
auto pMissile = &missile->s();
int from; // inherit some properties of the generator
if ((from = (pSource->flags & kModernTypeFlag3)) > 0) {
@ -7832,7 +7833,7 @@ void callbackUniMissileBurst(int nSprite) // 22
pBurst->ang = ((pSprite->ang + missileInfo[pSprite->type - kMissileBase].angleOfs) & 2047);
pBurst->owner = pSprite->owner;
actBuildMissile(pBurst, pBurst->extra, pSprite->index);
actBuildMissile(&bloodActors[pBurst->index], &bloodActors[pSprite->index]);
int nAngle2 = (i << 11) / 8;
int dx = 0;

View file

@ -1780,13 +1780,15 @@ void playerProcess(PLAYER *pPlayer)
spritetype *playerFireMissile(PLAYER *pPlayer, int a2, int a3, int a4, int a5, int a6)
{
return actFireMissile(pPlayer->pSprite, a2, pPlayer->zWeapon-pPlayer->pSprite->z, a3, a4, a5, a6);
auto misl = actFireMissile(&bloodActors[pPlayer->pSprite->index], a2, pPlayer->zWeapon-pPlayer->pSprite->z, a3, a4, a5, a6);
return misl ? &misl->s() : nullptr;
}
spritetype * playerFireThing(PLAYER *pPlayer, int a2, int a3, int thingType, int a5)
{
assert(thingType >= kThingBase && thingType < kThingMax);
return &actFireThing(&bloodActors[pPlayer->pSprite->index], a2, pPlayer->zWeapon-pPlayer->pSprite->z, pPlayer->slope+a3, thingType, a5)->s();
auto misl = actFireThing(&bloodActors[pPlayer->pSprite->index], a2, pPlayer->zWeapon-pPlayer->pSprite->z, pPlayer->slope+a3, thingType, a5);
return misl ? &misl->s() : nullptr;
}
void playerFrag(PLAYER *pKiller, PLAYER *pVictim)

View file

@ -198,6 +198,8 @@ unsigned int GetSourceBusy(EVENT a1)
void LifeLeechOperate(spritetype *pSprite, XSPRITE *pXSprite, EVENT event)
{
auto actor = &bloodActors[pSprite->index];
switch (event.cmd) {
case kCmdSpritePush:
{
@ -257,10 +259,10 @@ void LifeLeechOperate(spritetype *pSprite, XSPRITE *pXSprite, EVENT event)
t2 = 120 / 10;
else
t2 = (3*120) / 10;
spritetype *pMissile = actFireMissile(pSprite, 0, z1, dx, dy, dz, nMissileType);
if (pMissile)
auto missile = actFireMissile(actor, 0, z1, dx, dy, dz, nMissileType);
if (missile)
{
pMissile->owner = pSprite->owner;
missile->SetOwner(actor);
pXSprite->stateTimer = 1;
evPost(pSprite->index, 3, t2, kCallbackLeechStateTimer);
pXSprite->data3 = ClipLow(pXSprite->data3-1, 0);
@ -459,9 +461,9 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
if (gGameOptions.nMonsterSettings && pXSprite->data1 >= kDudeBase && pXSprite->data1 < kDudeMax)
{
auto actor = &bloodActors[pSprite->index];
spritetype* pSpawn = &actSpawnDude(actor, pXSprite->data1, -1, 0)->s();
if (pSpawn) {
XSPRITE *pXSpawn = &xsprite[pSpawn->extra];
auto spawned = actSpawnDude(actor, pXSprite->data1, -1, 0);
if (spawned) {
XSPRITE *pXSpawn = &spawned->x();
gKillMgr.AddNewKill(1);
switch (pXSprite->data1) {
case kDudeBurningInnocent:
@ -472,7 +474,7 @@ void OperateSprite(int nSprite, XSPRITE *pXSprite, EVENT event)
pXSpawn->health = getDudeInfo(pXSprite->data1)->startHealth << 4;
pXSpawn->burnTime = 10;
pXSpawn->target_i = -1;
aiActivateDude(&bloodActors[pXSpawn->reference]);
aiActivateDude(spawned);
break;
default:
break;
@ -2255,9 +2257,9 @@ void FireballTrapSeqCallback(int, DBloodActor* actor)
{
spritetype* pSprite = &actor->s();
if (pSprite->cstat&32)
actFireMissile(pSprite, 0, 0, 0, 0, (pSprite->cstat&8) ? 0x4000 : -0x4000, kMissileFireball);
actFireMissile(actor, 0, 0, 0, 0, (pSprite->cstat&8) ? 0x4000 : -0x4000, kMissileFireball);
else
actFireMissile(pSprite, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileFireball);
actFireMissile(actor, 0, 0, CosScale16(pSprite->ang), SinScale16(pSprite->ang), 0, kMissileFireball);
}