From 4db656db1a701a310118340f7b41180ad7fae879 Mon Sep 17 00:00:00 2001
From: Latapostrophe <hyperclassic3@gmail.com>
Date: Sat, 20 Oct 2018 16:10:40 +0200
Subject: [PATCH] Midnight Channel hardcode

---
 src/dehacked.c |   4 +-
 src/info.c     | 131 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/info.h     |  28 ++++++++++
 src/p_enemy.c  | 135 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/sounds.c   |   2 +
 src/sounds.h   |   2 +
 6 files changed, 299 insertions(+), 3 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index 60d38a638..9b4ddc710 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1837,7 +1837,9 @@ static actionpointer_t actionpointers[] =
 	{{A_JawzExplode},          "A_JAWZEXPLODE"}, // SRB2kart
 	{{A_MineExplode},          "A_MINEEXPLODE"}, // SRB2kart
 	{{A_BallhogExplode},       "A_BALLHOGEXPLODE"}, // SRB2kart
-	{{A_LightningFollowPlayer}, "A_LIGHTNINGFOLLOWPLAYER"},	//SRB2kart
+	{{A_LightningFollowPlayer},"A_LIGHTNINGFOLLOWPLAYER"},	//SRB2kart
+	{{A_RandomShadowFrame},	   "A_RANDOMSHADOWFRAME"},	//SRB2kart
+	{{A_RoamingShadowThinker}, "A_ROAMINGSHADOWTHINKER"},	//SRB2kart
 	{{A_OrbitNights},          "A_ORBITNIGHTS"},
 	{{A_GhostMe},              "A_GHOSTME"},
 	{{A_SetObjectState},       "A_SETOBJECTSTATE"},
diff --git a/src/info.c b/src/info.c
index 2efa68ab8..e0a55a8a1 100644
--- a/src/info.c
+++ b/src/info.c
@@ -61,7 +61,7 @@ char sprnames[NUMSPRITES + 1][5] =
 	"DEZL","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM",
 	"SACO","CRAB","SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB",
 	"ARRO","ITEM","ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK",
-	"LZI1","LZI2","KLIT","VIEW"
+	"LZI1","LZI2","KLIT", "SPTL", "ENM1", "GARU", "MARR", "VIEW"
 };
 
 // Doesn't work with g++, needs actionf_p1 (don't modify this comment)
@@ -3064,7 +3064,24 @@ state_t states[NUMSTATES] =
 	{SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|4, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT10},	// S_KLIT9
 	{SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT11},	// S_KLIT10
 	{SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|5, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT12},	// S_KLIT11
-	{SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT1},	// S_KLIT12	
+	{SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT1},	// S_KLIT12
+	
+	// Midnight Channel stuff, yay more boring states!
+	{SPR_SPTL, 0, -1, {NULL}, 0, 0, S_SPOTLIGHT},		// S_SPOTLIGHT
+	{SPR_ENM1, 0, 1, {A_RandomShadowFrame}, 0, 0, S_RANDOMSHADOW},		// S_RANDOMSHADOW
+	
+	{SPR_GARU, 0, 2, {NULL}, 0, 0, S_GARU2},	// S_GARU1
+	{SPR_GARU, 1, 2, {NULL}, 0, 0, S_GARU3},	// S_GARU2
+	{SPR_GARU, 2, 2, {NULL}, 0, 0, S_NULL},		// S_GARU3
+	
+	{SPR_NULL, 0, 2, {NULL}, 0, 0, S_TGARU1},	// S_TGARU0
+	{SPR_GARU, FF_TRANS30, 2, {NULL}, 0, 0, S_GARU2},	// S_TGARU1
+	{SPR_GARU, 1|FF_TRANS30, 2, {NULL}, 0, 0, S_GARU3},	// S_TGARU2
+	{SPR_GARU, 2|FF_TRANS30, 2, {NULL}, 0, 0, S_NULL},		// S_TGARU3
+	
+	{SPR_ENM1, 2, 1, {A_RoamingShadowThinker}, 0, 0, S_ROAMINGSHADOW}, //S_ROAMINGSHADOW
+	
+	{SPR_MARR, 0, 1, {A_MayonakaArrow}, 0, 0, S_MAYONAKAARROW}, //S_MAYONAKAARROW
 
 #ifdef SEENAMES
 	{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
@@ -17210,6 +17227,116 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		MF_NOTHINK|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
 		S_NULL          // raisestate
 	},
+	
+	// Midnight Channel stuff:
+	
+	{           // MT_SPOTLIGHT
+		3124,           // doomednum
+		S_SPOTLIGHT,   	// spawnstate
+		1000,           // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_NULL,         // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		0,              // speed
+		8*FRACUNIT,     // radius
+		16*FRACUNIT,    // height
+		0,              // display offset
+		0,              // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOTHINK|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
+		S_NULL          // raisestate
+	},
+	
+	{           // MT_RANDOMSHADOW
+		3120,           // doomednum
+		S_RANDOMSHADOW, // spawnstate
+		1000,           // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_NULL,         // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		0,              // speed
+		16*FRACUNIT,     // radius
+		32*FRACUNIT,    // height
+		0,              // display offset
+		0,              // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_SCENERY|MF_PAIN, // flags
+		S_NULL          // raisestate
+	},
+	
+	{           // MT_ROAMINGSHADOW
+		3121,           // doomednum
+		S_ROAMINGSHADOW, // spawnstate
+		1000,           // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_NULL,         // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		0,              // speed
+		16*FRACUNIT,     // radius
+		32*FRACUNIT,    // height
+		0,              // display offset
+		0,              // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_SOLID|MF_PAIN|MF_SPECIAL|MF_RUNSPAWNFUNC, // flags
+		S_NULL          // raisestate
+	},
+	
+	{           // MT_MAYONAKAARROW
+		3122,           // doomednum
+		S_MAYONAKAARROW, // spawnstate
+		1000,           // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_NULL,         // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		0,              // speed
+		64*FRACUNIT,     // radius
+		128*FRACUNIT,    // height
+		0,              // display offset
+		0,              // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags
+		S_NULL          // raisestate
+	},
 
 	// ============================================================================================================================//
 
diff --git a/src/info.h b/src/info.h
index f14d21212..5dbc68d85 100644
--- a/src/info.h
+++ b/src/info.h
@@ -169,6 +169,9 @@ void A_JawzExplode(); // SRB2kart
 void A_MineExplode(); // SRB2kart
 void A_BallhogExplode(); // SRB2kart
 void A_LightningFollowPlayer();	// SRB2kart: Lightning shield effect player chasing
+void A_RandomShadowFrame();	//SRB2kart: Shadow spawner frame randomizer
+void A_RoamingShadowThinker();	// SRB2kart: Roaming Shadow moving + attacking players.
+void A_MayonakaArrow();	//SRB2kart: midnight channel arrow sign
 void A_OrbitNights();
 void A_GhostMe();
 void A_SetObjectState();
@@ -652,6 +655,12 @@ typedef enum sprite
 	SPR_LZI1, // Lightning that falls on the player for lightning shield
 	SPR_LZI2, // ditto
 	SPR_KLIT, // You have a twisted mind. But this actually is for the diagonal lightning.
+	
+	// Midnight Channel stuff:
+	SPR_SPTL,	// Spotlight
+	SPR_ENM1,	// Shadows (Roaming and static)
+	SPR_GARU,	// Wind attack roaming shadows use.
+	SPR_MARR,	// Mayonaka Arrow
 
 	SPR_VIEW, // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw!
 	
@@ -3612,6 +3621,19 @@ typedef enum state
 	S_KLIT10,
 	S_KLIT11,
 	S_KLIT12,
+	
+	// Midnight Channel stuff:
+	S_SPOTLIGHT,	// Spotlight decoration
+	S_RANDOMSHADOW,	// Random Shadow. They're static and don't do nothing.
+	S_GARU1,
+	S_GARU2,
+	S_GARU3,
+	S_TGARU0,	
+	S_TGARU1,
+	S_TGARU2,
+	S_TGARU3,	// Wind attack used by Roaming Shadows on Players.
+	S_ROAMINGSHADOW,	// Roaming Shadow (the one that uses above's wind attack or smth)
+	S_MAYONAKAARROW,	// Arrow sign
 
 #ifdef SEENAMES
 	S_NAMECHECK,
@@ -4282,6 +4304,12 @@ typedef enum mobj_type
 
 	MT_KARMAHITBOX,
 	MT_KARMAWHEEL,
+	
+	// Midnight Channel stuff:
+	MT_SPOTLIGHT,		// Spotlight Object
+	MT_RANDOMSHADOW,	// Random static Shadows.
+	MT_ROAMINGSHADOW,	// Roaming Shadows.
+	MT_MAYONAKAARROW,	// Arrow static signs for Mayonaka
 
 #ifdef SEENAMES
 	MT_NAMECHECK,
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 37dd58998..969a32829 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -193,6 +193,9 @@ void A_JawzExplode(mobj_t *actor); // SRB2kart
 void A_MineExplode(mobj_t *actor); // SRB2kart
 void A_BallhogExplode(mobj_t *actor); // SRB2kart
 void A_LightningFollowPlayer(mobj_t *actor);	// SRB2kart
+void A_RandomShadowFrame(mobj_t *actor);	// SRB2kart
+void A_RoamingShadowThinker(mobj_t *actor);	//SRB2kart
+void A_MayonakaArrow(mobj_t *actor);	//SRB2kart
 void A_OrbitNights(mobj_t *actor);
 void A_GhostMe(mobj_t *actor);
 void A_SetObjectState(mobj_t *actor);
@@ -8421,6 +8424,138 @@ void A_LightningFollowPlayer(mobj_t *actor)
 	return;
 }
 
+// A_RandomShadowFrame
+// Gives a random sprite for the Mayonaka static shadows. Dumb and simple.
+void A_RandomShadowFrame(mobj_t *actor)
+{
+	mobj_t *fire;
+	mobj_t *fake;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_RandomShadowFrame", (actor)))
+		return;
+#endif
+
+	if (!actor->extravalue1)	// Hack that spawns thoks that look like random shadows. Otherwise the state would overwrite our frame and that's a pain.
+	{	
+		fake = P_SpawnMobj(actor->x, actor->y, actor->z, MT_THOK);
+		fake->sprite = SPR_ENM1;
+		fake->frame = P_RandomRange(0, 6);
+		P_SetScale(fake, FRACUNIT*3/2);
+		fake->scale = FRACUNIT*3/2;
+		fake->destscale = FRACUNIT*3/2;
+		fake->angle = actor->angle;
+		fake->tics = -1;
+		actor->flags2 |= MF2_DONTDRAW;
+		actor->extravalue1 = 1;
+	}
+	
+	P_SetScale(actor, FRACUNIT*3/2);
+	
+	// I have NO CLUE how to hardcode all of that fancy Linedef Executor shit so the fire spinout will be done by these entities directly.
+	if (P_LookForPlayers(actor, false, false, 512<<FRACBITS))	// got target
+	{
+		if (actor->target && !actor->target->player->powers[pw_flashing]
+		&& !actor->target->player->kartstuff[k_invincibilitytimer]
+		&& !actor->target->player->kartstuff[k_growshrinktimer]
+		&& !actor->target->player->kartstuff[k_spinouttimer]
+		&& P_IsObjectOnGround(actor->target)
+		&& actor->z == actor->target->z)
+		{
+			P_DamageMobj(actor->target, actor, actor, 1);
+			P_InstaThrust(actor->target, actor->angle, 16<<FRACBITS);
+			fire = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_THOK);
+			P_SetMobjStateNF(fire, S_QUICKBOOM1);
+			P_SetScale(fire, 4<<FRACBITS);
+			fire->color = SKINCOLOR_RED;
+			S_StartSound(actor->target, sfx_fire2);
+		}
+	}
+	return;
+}
+
+// A_RoamingShadowThinker
+// Thinker for Midnight Channel's Roaming Shadows:
+void A_RoamingShadowThinker(mobj_t *actor)
+{
+	mobj_t *wind;
+
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_RoamingShadowThinker", (actor)))
+		return;
+#endif
+	// extravalue1 replaces "movetimer"
+	// extravalue2 replaces "stoptimer"
+	
+	P_SetScale(actor, FRACUNIT*3/2);
+	if (!actor->extravalue2)
+	{
+		P_InstaThrust(actor, actor->angle, 8<<FRACBITS);	// move at 8 fracs / sec
+		actor->extravalue1 = ((actor->extravalue1) ? (actor->extravalue1-1) : (TICRATE*5+1));	// deplete timer if set, set to 5 ticrate otherwise.
+		if (actor->extravalue1 == 1)	// if timer reaches 1, do a u-turn.
+		{
+			actor->extravalue1 = 0;
+			actor->extravalue2 = 60;
+		}
+		// Search for and attack Players venturing too close in front of us.
+		
+		if (P_LookForPlayers(actor, false, false, 256<<FRACBITS))	// got target
+		{
+			if (actor->target && !actor->target->player->powers[pw_flashing]
+			&& !actor->target->player->kartstuff[k_invincibilitytimer]
+			&& !actor->target->player->kartstuff[k_growshrinktimer]
+			&& !actor->target->player->kartstuff[k_spinouttimer])
+			{
+				// send them flying and spawn the WIND!
+				P_InstaThrust(actor->target, 0, 0);
+				P_DamageMobj(actor->target, actor, actor, 1);
+				P_SetObjectMomZ(actor->target, 16<<FRACBITS, false);
+				S_StartSound(actor->target, sfx_wind1);
+
+				// Spawn the WIND:
+				wind = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_THOK);	// Opaque layer:
+				P_SetMobjState(wind, S_GARU1);
+				P_SetScale(wind, FRACUNIT*3/2);
+				wind = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_THOK);	// Translucent layer:
+				P_SetMobjState(wind, S_TGARU0);
+				P_SetScale(wind, FRACUNIT*3/2);
+				wind->destscale = 30<<FRACBITS;
+			}
+		}
+	}
+	else	// Handle U-Turn
+	{
+		actor->angle += ANG1*3;
+		actor->extravalue2--;
+	}
+	return;
+}
+
+// A_MayonakaArrow
+// Used for the arrow sprite animations in Mayonaka. It's only extra visual bullshit to make em more random.
+
+void A_MayonakaArrow(mobj_t *actor)
+{
+	INT32 flip = 0;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_MayonakaArrow", (actor)))
+		return;
+#endif	
+	// "animtimer" is replaced by "extravalue1" here.
+	actor->extravalue1 = ((actor->extravalue1) ? (actor->extravalue1+1) : (P_RandomRange(0, TICRATE*3)));
+	flip = ((actor->spawnpoint->options & 1) ? (3) : (0));	// flip adds 3 frames, which is the flipped version of the sign.
+	
+	actor->frame = flip;
+	if (actor->extravalue1 >= TICRATE*7/2)
+		actor->extravalue1 = 0;	// reset to 0 and start a new cycle.
+	else if (actor->extravalue1 > TICRATE*7/2 -4)
+		actor->frame = flip+2;
+	else if (actor->extravalue1 > TICRATE*3 && leveltime%2 > 0)
+		actor->frame = flip+1;
+	
+	actor->frame |= FF_PAPERSPRITE;
+	actor->momz = 0;
+	return;	
+}
 //}
 
 // Function: A_OrbitNights
diff --git a/src/sounds.c b/src/sounds.c
index 02ad0853c..625522be5 100644
--- a/src/sounds.c
+++ b/src/sounds.c
@@ -813,6 +813,8 @@ sfxinfo_t S_sfx[NUMSFX] =
   {"kpogos", false, 110,  8, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"ddash",  false,  64,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"zio3", 	 false, 110,  8, -1, NULL, 0,        -1,  -1, LUMPERROR},
+  {"wind1",  false, 110,  8, -1, NULL, 0,        -1,  -1, LUMPERROR},
+  {"fire2",  false, 110,  8, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"mcitm1", false, 110,  8, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"chaooo", false, 110,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"itfree", false,  64,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
diff --git a/src/sounds.h b/src/sounds.h
index 2516b6464..ccd99e994 100644
--- a/src/sounds.h
+++ b/src/sounds.h
@@ -888,6 +888,8 @@ typedef enum
 	sfx_kpogos,
 	sfx_ddash,
 	sfx_zio3,
+	sfx_wind1,
+	sfx_fire2,
 	sfx_mcitm1,
 	sfx_chaooo,
 	sfx_itfree,
-- 
GitLab