From 92c900f28468e058fbcd17701ff88967b6c0a83b Mon Sep 17 00:00:00 2001
From: lachwright <lachlanwright17@gmail.com>
Date: Mon, 4 May 2020 00:35:57 +0800
Subject: [PATCH] New GFZ3 laser

---
 src/dehacked.c |  5 ++++-
 src/info.c     | 13 ++++++++-----
 src/info.h     |  5 ++++-
 src/p_enemy.c  | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index e9d029be0..daf578007 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -6224,7 +6224,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 
 	"S_ROCKET",
 
-	"S_LASER",
+	"S_LASER1",
+	"S_LASER2",
+	"S_LASERFLASH",
+	"S_LASERSPARK",
 
 	"S_TORPEDO",
 
diff --git a/src/info.c b/src/info.c
index bd6ccb527..2944c53b1 100644
--- a/src/info.c
+++ b/src/info.c
@@ -2058,7 +2058,10 @@ state_t states[NUMSTATES] =
 
 	{SPR_MISL, FF_FULLBRIGHT, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_ROCKET}, // S_ROCKET
 
-	{SPR_MISL, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LASER
+	{SPR_MISL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_NULL}, // S_LASER1
+	{SPR_MISL, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_NULL}, // S_LASER2
+	{SPR_MISL, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_NULL}, // S_LASERFLASH
+	{SPR_MISL, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_LASERSPARK}, // S_LASERSPARK
 
 	{SPR_TORP, 0, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_TORPEDO}, // S_TORPEDO
 
@@ -9628,17 +9631,17 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_LASER
 		-1,             // doomednum
-		S_LASER,        // spawnstate
+		S_LASER1,       // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_rlaunc,     // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
-		S_NULL,         // painstate
+		S_LASERSPARK,   // painstate
 		0,              // painchance
 		sfx_None,       // painsound
-		S_NULL,         // meleestate
-		S_NULL,         // missilestate
+		S_LASERFLASH,   // meleestate
+		S_LASER2,       // missilestate
 		S_NULL,         // deathstate
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
diff --git a/src/info.h b/src/info.h
index 586209ff9..1d1400aba 100644
--- a/src/info.h
+++ b/src/info.h
@@ -2219,7 +2219,10 @@ typedef enum state
 
 	S_ROCKET,
 
-	S_LASER,
+	S_LASER1,
+	S_LASER2,
+	S_LASERFLASH,
+	S_LASERSPARK,
 
 	S_TORPEDO,
 
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 2341be6d3..ec7445f9f 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -2990,6 +2990,19 @@ void A_Boss1Laser(mobj_t *actor)
 	angle_t angle;
 	mobj_t *point;
 	tic_t dur;
+	static const UINT8 LASERCOLORS[] =
+	{
+		SKINCOLOR_SUPERRED3,
+		SKINCOLOR_SUPERRED4,
+		SKINCOLOR_SUPERRED5,
+		SKINCOLOR_FLAME,
+		SKINCOLOR_RED,
+		SKINCOLOR_RED,
+		SKINCOLOR_FLAME,
+		SKINCOLOR_SUPERRED5,
+		SKINCOLOR_SUPERRED4,
+		SKINCOLOR_SUPERRED3,
+	};
 
 	if (LUA_CallAction("A_Boss1Laser", actor))
 		return;
@@ -3064,7 +3077,7 @@ void A_Boss1Laser(mobj_t *actor)
 	point = P_SpawnMobj(x, y, z, locvar1);
 	P_SetTarget(&point->target, actor);
 	point->angle = actor->angle;
-	speed = point->radius*2;
+	speed = point->radius;
 	point->momz = FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT), speed);
 	point->momx = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(point->angle>>ANGLETOFINESHIFT), speed));
 	point->momy = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINESINE(point->angle>>ANGLETOFINESHIFT), speed));
@@ -3073,10 +3086,26 @@ void A_Boss1Laser(mobj_t *actor)
 	{
 		mobj_t *mo = P_SpawnMobj(point->x, point->y, point->z, point->type);
 		mo->angle = point->angle;
+		mo->color = LASERCOLORS[((UINT8)(i - 3*leveltime) >> 2) % sizeof(LASERCOLORS)]; // codeing
 		P_UnsetThingPosition(mo);
 		mo->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY;
 		P_SetThingPosition(mo);
 
+		if (leveltime & 1 && mo->info->missilestate)
+		{
+			P_SetMobjState(mo, mo->info->missilestate);
+			if (mo->info->meleestate)
+			{
+				mobk_t *mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_PARTICLE);
+				mo2->flags2 |= MF2_LINKDRAW;
+				P_SetTarget(&mo2->tracer, actor);
+				P_SetMobjState(mo2, mo->info->meleestate);
+			}
+		}
+
+		if (leveltime % 4 == 0)
+			P_SpawnGhostMobj(mo);
+
 		x = point->x, y = point->y, z = point->z;
 		if (P_RailThinker(point))
 			break;
@@ -3085,6 +3114,20 @@ void A_Boss1Laser(mobj_t *actor)
 	floorz = P_FloorzAtPos(x, y, z, mobjinfo[MT_EGGMOBILE_FIRE].height);
 	if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1)
 	{
+		for (i = 0; point->info->painstate && i < 3; i++)
+		{
+			mobj_t *spark = P_SpawnMobj(x, y, floorz+1, MT_PARTICLE);
+			spark->flags &= ~MF_NOGRAVITY;
+			spark->angle = FixedAngle(P_RandomKey(360)*FRACUNIT);
+			spark->rollangle = FixedAngle(P_RandomKey(360)*FRACUNIT);
+			spark->color = LASERCOLORS[P_RandomKey(sizeof(LASERCOLORS)/sizeof(UINT8))];
+			spark->colorized = true;
+			spark->fuse = 12;
+			spark->destscale = point->scale >> 3;
+			P_SetObjectMomZ(spark, 8*FRACUNIT, true);
+			P_InstaThrust(spark, spark->angle, 6*FRACUNIT);
+			P_SetMobjState(spark, point->info->painstate);
+		}
 		point = P_SpawnMobj(x, y, floorz+1, MT_EGGMOBILE_FIRE);
 		P_SetTarget(&point->target, actor);
 		point->destscale = 3*FRACUNIT;