From 351dabdb90cf989d35af3b2fab7fa03949cf901b Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Sat, 5 Dec 2020 21:23:53 +0100
Subject: [PATCH] - actFireMissile.

---
 source/games/blood/src/actor.cpp     | 184 ++++++++++++++-------------
 source/games/blood/src/actor.h       |   4 +-
 source/games/blood/src/aicerber.cpp  |  12 +-
 source/games/blood/src/aicult.cpp    |   2 +-
 source/games/blood/src/aigarg.cpp    |   8 +-
 source/games/blood/src/aighost.cpp   |   4 +-
 source/games/blood/src/aihound.cpp   |   2 +-
 source/games/blood/src/aitchern.cpp  |   8 +-
 source/games/blood/src/aiunicult.cpp |   9 +-
 source/games/blood/src/aizombf.cpp   |   4 +-
 source/games/blood/src/nnexts.cpp    |   9 +-
 source/games/blood/src/player.cpp    |   6 +-
 source/games/blood/src/triggers.cpp  |  20 +--
 13 files changed, 145 insertions(+), 127 deletions(-)

diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp
index a85955e30..330ab7099 100644
--- a/source/games/blood/src/actor.cpp
+++ b/source/games/blood/src/actor.cpp
@@ -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)
 {
diff --git a/source/games/blood/src/actor.h b/source/games/blood/src/actor.h
index f6d3c0825..b89652933 100644
--- a/source/games/blood/src/actor.h
+++ b/source/games/blood/src/actor.h
@@ -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[];
 
diff --git a/source/games/blood/src/aicerber.cpp b/source/games/blood/src/aicerber.cpp
index 81a01b34e..d130f985f 100644
--- a/source/games/blood/src/aicerber.cpp
+++ b/source/games/blood/src/aicerber.cpp
@@ -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;
 	}
 }
diff --git a/source/games/blood/src/aicult.cpp b/source/games/blood/src/aicult.cpp
index 2eaddf2ad..8ffece960 100644
--- a/source/games/blood/src/aicult.cpp
+++ b/source/games/blood/src/aicult.cpp
@@ -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);
 	}
 }
diff --git a/source/games/blood/src/aigarg.cpp b/source/games/blood/src/aigarg.cpp
index ffb7da04a..17719adc7 100644
--- a/source/games/blood/src/aigarg.cpp
+++ b/source/games/blood/src/aigarg.cpp
@@ -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
 
diff --git a/source/games/blood/src/aighost.cpp b/source/games/blood/src/aighost.cpp
index 12f7e2f9a..65ba703da 100644
--- a/source/games/blood/src/aighost.cpp
+++ b/source/games/blood/src/aighost.cpp
@@ -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
 }
diff --git a/source/games/blood/src/aihound.cpp b/source/games/blood/src/aihound.cpp
index 4765144f4..3d78a2b86 100644
--- a/source/games/blood/src/aihound.cpp
+++ b/source/games/blood/src/aihound.cpp
@@ -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)
diff --git a/source/games/blood/src/aitchern.cpp b/source/games/blood/src/aitchern.cpp
index 51325efcf..65eba2da7 100644
--- a/source/games/blood/src/aitchern.cpp
+++ b/source/games/blood/src/aitchern.cpp
@@ -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)
diff --git a/source/games/blood/src/aiunicult.cpp b/source/games/blood/src/aiunicult.cpp
index e1159d038..bba35d1d0 100644
--- a/source/games/blood/src/aiunicult.cpp
+++ b/source/games/blood/src/aiunicult.cpp
@@ -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);
diff --git a/source/games/blood/src/aizombf.cpp b/source/games/blood/src/aizombf.cpp
index af6150c22..2dcf412d8 100644
--- a/source/games/blood/src/aizombf.cpp
+++ b/source/games/blood/src/aizombf.cpp
@@ -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)
diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp
index 4db668fd1..856b75a41 100644
--- a/source/games/blood/src/nnexts.cpp
+++ b/source/games/blood/src/nnexts.cpp
@@ -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;
diff --git a/source/games/blood/src/player.cpp b/source/games/blood/src/player.cpp
index cd717fa59..e5ac25729 100644
--- a/source/games/blood/src/player.cpp
+++ b/source/games/blood/src/player.cpp
@@ -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)
diff --git a/source/games/blood/src/triggers.cpp b/source/games/blood/src/triggers.cpp
index ce2a8605e..a7dd84a26 100644
--- a/source/games/blood/src/triggers.cpp
+++ b/source/games/blood/src/triggers.cpp
@@ -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);
 }