From 6a969c163b4f72b98c5d24d1eafe30e02045c044 Mon Sep 17 00:00:00 2001
From: spherallic <spherallic@gmail.com>
Date: Wed, 6 Apr 2022 15:31:25 +0200
Subject: [PATCH] Make boss 3's shockwave into a customizable action.

---
 src/deh_tables.c |  1 +
 src/info.h       |  2 ++
 src/p_enemy.c    | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

diff --git a/src/deh_tables.c b/src/deh_tables.c
index 8dbe314cc1..bed81e60c9 100644
--- a/src/deh_tables.c
+++ b/src/deh_tables.c
@@ -198,6 +198,7 @@ actionpointer_t actionpointers[] =
 	{{A_Boss3TakeDamage},        "A_BOSS3TAKEDAMAGE"},
 	{{A_Boss3Path},              "A_BOSS3PATH"},
 	{{A_Boss3ShockThink},        "A_BOSS3SHOCKTHINK"},
+	{{A_Shockwave},              "A_SHOCKWAVE"},
 	{{A_LinedefExecute},         "A_LINEDEFEXECUTE"},
 	{{A_PlaySeeSound},           "A_PLAYSEESOUND"},
 	{{A_PlayAttackSound},        "A_PLAYATTACKSOUND"},
diff --git a/src/info.h b/src/info.h
index 1b7a201cea..04c048dd8a 100644
--- a/src/info.h
+++ b/src/info.h
@@ -151,6 +151,7 @@ enum actionnum
 	A_BOSS3TAKEDAMAGE,
 	A_BOSS3PATH,
 	A_BOSS3SHOCKTHINK,
+	A_SHOCKWAVE,
 	A_LINEDEFEXECUTE,
 	A_PLAYSEESOUND,
 	A_PLAYATTACKSOUND,
@@ -414,6 +415,7 @@ void A_Boss1Spikeballs();
 void A_Boss3TakeDamage();
 void A_Boss3Path();
 void A_Boss3ShockThink();
+void A_Shockwave();
 void A_LinedefExecute();
 void A_PlaySeeSound();
 void A_PlayAttackSound();
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 87aa5ff2f8..efa413a444 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -173,6 +173,7 @@ void A_Boss1Spikeballs(mobj_t *actor);
 void A_Boss3TakeDamage(mobj_t *actor);
 void A_Boss3Path(mobj_t *actor);
 void A_Boss3ShockThink(mobj_t *actor);
+void A_Shockwave(mobj_t *actor);
 void A_LinedefExecute(mobj_t *actor);
 void A_PlaySeeSound(mobj_t *actor);
 void A_PlayAttackSound(mobj_t *actor);
@@ -8326,6 +8327,56 @@ void A_Boss3ShockThink(mobj_t *actor)
 	}
 }
 
+// Function: A_Shockwave
+//
+// Description: Spawns a shockwave of objects. Best used to spawn objects that call A_Boss3ShockThink.
+//
+// var1 = object spawned
+// var2 = amount of objects spawned
+//
+void A_Shockwave(mobj_t *actor)
+{
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
+	INT32 i;
+
+	angle_t ang = 0, interval;
+	mobj_t *shock = NULL, *sfirst = NULL, *sprev = NULL;
+
+	if (LUA_CallAction(A_SHOCKWAVE, actor))
+		return;
+
+	if (locvar2 == 0)
+		locvar2 = 24; // a sensible default, just in case
+
+	interval = FixedAngle((360 << FRACBITS) / locvar2);
+
+	for (i = 0; i < locvar2; i++)
+	{
+		shock = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1);
+		P_SetTarget(&shock->target, actor);
+		shock->fuse = shock->info->painchance;
+
+		if (i % 2 == 0)
+			P_SetMobjState(shock, shock->state->nextstate);
+
+		if (!sprev)
+			sfirst = shock;
+		else
+		{
+			if (i == locvar2 - 1)
+				P_SetTarget(&shock->hnext, sfirst);
+			P_SetTarget(&sprev->hnext, shock);
+		}
+
+		P_Thrust(shock, ang, shock->info->speed);
+		ang += interval;
+		sprev = shock;
+	}
+	
+	S_StartSound(actor, shock->info->seesound);
+}
+
 // Function: A_LinedefExecute
 //
 // Description: Object's location is used to set the calling sector. The tag used is var1. Optionally, if var2 is set, the actor's angle (multiplied by var2) is added to the tag number as well.
-- 
GitLab