From 598047ae8b97f525728878ff9e4ece85ed7311a4 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 29 Sep 2019 10:39:09 +0200
Subject: [PATCH] Hardcoded the Pterabyte (without the grabbing mechanic)

---
 src/dehacked.c          | 15 +++++++
 src/hardware/hw_light.c |  1 +
 src/info.c              | 92 +++++++++++++++++++++++++++++++++++++++++
 src/info.h              | 16 +++++++
 src/p_enemy.c           | 76 +++++++++++++++++++++++++++++++++-
 src/p_mobj.c            | 70 +++++++++++++++++++++++++++++++
 src/sounds.c            |  1 +
 src/sounds.h            |  1 +
 8 files changed, 271 insertions(+), 1 deletion(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index 1664c6cb2..b2a0239c6 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -2435,6 +2435,8 @@ static actionpointer_t actionpointers[] =
 	{{A_LavafallLava},           "A_LAVAFALLLAVA"},
 	{{A_FallingLavaCheck},       "A_FALLINGLAVACHECK"},
 	{{A_FireShrink},             "A_FIRESHRINK"},
+	{{A_SpawnPterabytes},        "A_SPAWNPTERABYTES"},
+	{{A_PterabyteHover},         "A_PTERABYTEHOVER"},
 	{{NULL},                     "NONE"},
 
 	// This NULL entry must be the last in the list
@@ -4582,6 +4584,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_PYREFIRE1",
 	"S_PYREFIRE2",
 
+	// Pterabyte
+	"S_PTERABYTESPAWNER",
+	"S_PTERABYTEWAYPOINT",
+	"S_PTERABYTE_FLY1",
+	"S_PTERABYTE_FLY2",
+	"S_PTERABYTE_FLY3",
+	"S_PTERABYTE_FLY4",
+	"S_PTERABYTE_SWOOPDOWN",
+	"S_PTERABYTE_SWOOPUP",
+
 	// Boss Explosion
 	"S_BOSSEXPLODE",
 
@@ -7232,6 +7244,9 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_CANARIVORE_GAS", // Canarivore gas
 	"MT_PYREFLY", // Pyre Fly
 	"MT_PYREFLY_FIRE", // Pyre Fly fire
+	"MT_PTERABYTESPAWNER", // Pterabyte spawner
+	"MT_PTERABYTEWAYPOINT", // Pterabyte waypoint
+	"MT_PTERABYTE", // Pterabyte
 
 	// Generic Boss Items
 	"MT_BOSSEXPLODE",
diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c
index 57dfc57ab..f3b2b4f87 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -181,6 +181,7 @@ light_t *t_lspr[NUMSPRITES] =
 	&lspr[NOLIGHT],     // SPR_CANA
 	&lspr[NOLIGHT],     // SPR_CANG
 	&lspr[NOLIGHT],     // SPR_PYRE
+	&lspr[NOLIGHT],     // SPR_PTER
 
 	// Generic Boos Items
 	&lspr[JETLIGHT_L],     // SPR_JETF // Boss jet fumes
diff --git a/src/info.c b/src/info.c
index b82c64e52..6800ba4be 100644
--- a/src/info.c
+++ b/src/info.c
@@ -69,6 +69,7 @@ char sprnames[NUMSPRITES + 1][5] =
 	"CANA", // Canarivore
 	"CANG", // Canarivore gas
 	"PYRE", // Pyre Fly
+	"PTER", // Pterabyte
 
 	// Generic Boss Items
 	"JETF", // Boss jet fumes
@@ -1178,6 +1179,16 @@ state_t states[NUMSTATES] =
 	{SPR_FLAM, FF_FULLBRIGHT, 10, {NULL}, 0, 0, S_PYREFIRE2}, // S_PYREFIRE1
 	{SPR_FLAM, 1|FF_FULLBRIGHT, 10, {A_FireShrink}, 0, 16, S_NULL}, // S_PYREFIRE2
 
+	// Pterabyte
+	{SPR_NULL, 0, -1, {A_SpawnPterabytes}, 0, 0, S_PTERABYTESPAWNER},    // S_PTERABYTESPAWNER
+	{SPR_NULL, 0,  1, {A_PterabyteHover},  0, 0, S_PTERABYTEWAYPOINT},   // S_PTERABYTEWAYPOINT
+	{SPR_PTER, 0,  6, {NULL},              0, 0, S_PTERABYTE_FLY2},      // S_PTERABYTE_FLY1
+	{SPR_PTER, 1,  2, {NULL},              0, 0, S_PTERABYTE_FLY3},      // S_PTERABYTE_FLY2
+	{SPR_PTER, 2,  6, {NULL},              0, 0, S_PTERABYTE_FLY4},      // S_PTERABYTE_FLY3
+	{SPR_PTER, 3,  2, {NULL},              0, 0, S_PTERABYTE_FLY1},      // S_PTERABYTE_FLY4
+	{SPR_PTER, 4,  1, {NULL},              0, 0, S_PTERABYTE_SWOOPDOWN}, // S_PTERABYTE_SWOOPDOWN
+	{SPR_PTER, 0,  1, {NULL},              0, 0, S_PTERABYTE_SWOOPUP},   // S_PTERABYTE_SWOOPUP
+
 	// Boss Explosion
 	{SPR_BOM2, FF_FULLBRIGHT|FF_ANIMATE, (5*7), {NULL}, 6, 5, S_NULL}, // S_BOSSEXPLODE
 
@@ -5064,6 +5075,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
+	{           // MT_PTERABYTESPAWNER
+		135,            // doomednum
+		S_PTERABYTESPAWNER, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		0,              // 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
+		16*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOGRAVITY|MF_NOCLIPTHING|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags
+		S_NULL          // raisestate
+	},
+
+	{           // MT_PTERABYTEWAYPOINT
+		-1,             // doomednum
+		S_PTERABYTEWAYPOINT, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		0,              // 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
+		4*FRACUNIT,     // speed
+		24*FRACUNIT,    // radius
+		48*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOGRAVITY|MF_NOCLIPTHING|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags
+		S_NULL          // raisestate
+	},
+
+	{           // MT_PTERABYTE
+		-1,             // doomednum
+		S_PTERABYTE_FLY1, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		0,              // reactiontime
+		sfx_pscree,     // attacksound
+		S_NULL,         // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_XPLD_FLICKY,  // deathstate
+		S_NULL,         // xdeathstate
+		sfx_pop,        // deathsound
+		4*FRACUNIT,     // speed
+		24*FRACUNIT,    // radius
+		48*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_NOGRAVITY|MF_SLIDEME, // flags
+		S_NULL          // raisestate
+	},
+
 	{           // MT_BOSSEXPLODE
 		-1,             // doomednum
 		S_BOSSEXPLODE,  // spawnstate
diff --git a/src/info.h b/src/info.h
index 8d2023c3d..98a5db4ca 100644
--- a/src/info.h
+++ b/src/info.h
@@ -270,6 +270,8 @@ void A_LavafallRocks();
 void A_LavafallLava();
 void A_FallingLavaCheck();
 void A_FireShrink();
+void A_SpawnPterabytes();
+void A_PterabyteHover();
 
 // ratio of states to sprites to mobj types is roughly 6 : 1 : 1
 #define NUMMOBJFREESLOTS 512
@@ -319,6 +321,7 @@ typedef enum sprite
 	SPR_CANA, // Canarivore
 	SPR_CANG, // Canarivore gas
 	SPR_PYRE, // Pyre Fly
+	SPR_PTER, // Pterabyte
 
 	// Generic Boss Items
 	SPR_JETF, // Boss jet fumes
@@ -1335,6 +1338,16 @@ typedef enum state
 	S_PYREFIRE1,
 	S_PYREFIRE2,
 
+	// Pterabyte
+	S_PTERABYTESPAWNER,
+	S_PTERABYTEWAYPOINT,
+	S_PTERABYTE_FLY1,
+	S_PTERABYTE_FLY2,
+	S_PTERABYTE_FLY3,
+	S_PTERABYTE_FLY4,
+	S_PTERABYTE_SWOOPDOWN,
+	S_PTERABYTE_SWOOPUP,
+
 	// Boss Explosion
 	S_BOSSEXPLODE,
 
@@ -4007,6 +4020,9 @@ typedef enum mobj_type
 	MT_CANARIVORE_GAS, // Canarivore gas
 	MT_PYREFLY, // Pyre Fly
 	MT_PYREFLY_FIRE, // Pyre Fly fire
+	MT_PTERABYTESPAWNER, // Pterabyte spawner
+	MT_PTERABYTEWAYPOINT, // Pterabyte waypoint
+	MT_PTERABYTE, // Pterabyte
 
 	// Generic Boss Items
 	MT_BOSSEXPLODE,
diff --git a/src/p_enemy.c b/src/p_enemy.c
index e37eea19d..894bd3090 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -300,6 +300,8 @@ void A_LavafallRocks(mobj_t *actor);
 void A_LavafallLava(mobj_t *actor);
 void A_FallingLavaCheck(mobj_t *actor);
 void A_FireShrink(mobj_t *actor);
+void A_SpawnPterabytes(mobj_t *actor);
+void A_PterabyteHover(mobj_t *actor);
 
 //for p_enemy.c
 
@@ -13784,6 +13786,8 @@ void A_LavafallRocks(mobj_t *actor)
 //
 void A_LavafallLava(mobj_t *actor)
 {
+	mobj_t *lavafall;
+
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_LavafallLava", actor))
 		return;
@@ -13792,7 +13796,7 @@ void A_LavafallLava(mobj_t *actor)
 	if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS)))
 		return;
 
-	mobj_t *lavafall = P_SpawnMobjFromMobj(actor, 0, 0, -8*FRACUNIT, MT_LAVAFALL_LAVA);
+	lavafall = P_SpawnMobjFromMobj(actor, 0, 0, -8*FRACUNIT, MT_LAVAFALL_LAVA);
 	lavafall->momz = -P_MobjFlip(actor)*25*FRACUNIT;
 }
 
@@ -13838,4 +13842,74 @@ void A_FireShrink(mobj_t *actor)
 
 	actor->destscale = locvar1;
 	actor->scalespeed = FRACUNIT/locvar2;
+}
+
+// Function: A_SpawnPterabytes
+//
+// Description: Spawn Pterabytes around the actor in a circle.
+//
+// var1 = unused
+// var2 = unused
+//
+void A_SpawnPterabytes(mobj_t *actor)
+{
+	mobj_t *waypoint, *ptera;
+	fixed_t c, s;
+	fixed_t rad = 280*FRACUNIT;
+	angle_t ang = 0;
+	angle_t interval, fa;
+	UINT8 amount = 1;
+	UINT8 i;
+
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_SpawnPterabytes", actor))
+		return;
+#endif
+
+	if (actor->spawnpoint)
+	{
+		amount = actor->spawnpoint->extrainfo + 1;
+		if (actor->spawnpoint->angle)
+			rad = actor->spawnpoint->angle*FRACUNIT;
+	}
+
+	interval = FixedAngle(FRACUNIT*360/amount);
+
+	for (i = 0; i < amount; i++)
+	{
+		fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
+		c = FINECOSINE(fa);
+		s = FINESINE(fa);
+		waypoint = P_SpawnMobjFromMobj(actor, FixedMul(c, rad), FixedMul(s, rad), 0, MT_PTERABYTEWAYPOINT);
+		waypoint->angle = ang + ANGLE_90;
+		ptera = P_SpawnMobjFromMobj(waypoint, 0, 0, 0, MT_PTERABYTE);
+		ptera->angle = waypoint->angle;
+		P_SetTarget(&ptera->tracer, waypoint);
+		ptera->extravalue1 = 0;
+		ang += interval;
+	}
+}
+
+// Function: A_PterabyteHover
+//
+// Description: Hover in a circular fashion, bobbing up and down slightly.
+//
+// var1 = unused
+// var2 = unused
+//
+void A_PterabyteHover(mobj_t *actor)
+{
+	angle_t ang, fa;
+
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_PterabyteHover", actor))
+		return;
+#endif
+
+	P_InstaThrust(actor, actor->angle, actor->info->speed);
+	actor->angle += ANG1;
+	actor->extravalue1 = (actor->extravalue1 + 3) % 360;
+	ang = actor->extravalue1*ANG1;
+	fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
+	actor->z += FINESINE(fa);
 }
\ No newline at end of file
diff --git a/src/p_mobj.c b/src/p_mobj.c
index bb86df067..4258ac402 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -9076,6 +9076,76 @@ void P_MobjThinker(mobj_t *mobj)
 					}
 					break;
 				}
+			case MT_PTERABYTE:
+				{
+					if (mobj->extravalue1 == 0) // Hovering
+					{
+						fixed_t vdist, hdist, time;
+						fixed_t hspeed = 3*mobj->info->speed;
+						angle_t fa;
+
+						var1 = 1;
+						var2 = 0;
+						A_CapeChase(mobj);
+						P_LookForPlayers(mobj, true, false, 256*FRACUNIT);
+
+						if (!mobj->target)
+							break;
+
+						vdist = mobj->z - mobj->target->z;
+						if (vdist <= 0)
+							break;
+
+						hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
+						if (hdist > 450*FRACUNIT)
+							break;
+
+						P_SetMobjState(mobj, S_PTERABYTE_SWOOPDOWN);
+						mobj->extravalue1 = 1;
+						S_StartSound(mobj, mobj->info->attacksound);
+						time = FixedDiv(hdist, hspeed);
+						mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
+						fa = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK;
+						mobj->momx = FixedMul(FINECOSINE(fa), hspeed);
+						mobj->momy = FixedMul(FINESINE(fa), hspeed);
+						mobj->momz = -2*FixedDiv(vdist, time);
+						mobj->extravalue2 = -FixedDiv(mobj->momz, time); //Z accel
+						mobj->movecount = time >> FRACBITS;
+						mobj->reactiontime = mobj->movecount;
+					}
+					else if (mobj->extravalue1 == 1) // Swooping
+					{
+						mobj->reactiontime--;
+						mobj->momz += mobj->extravalue2;
+						if (mobj->reactiontime)
+							break;
+
+						if (mobj->state - states == S_PTERABYTE_SWOOPDOWN)
+						{
+							P_SetMobjState(mobj, S_PTERABYTE_SWOOPUP);
+							mobj->reactiontime = mobj->movecount;
+						}
+						else if (mobj->state - states == S_PTERABYTE_SWOOPUP)
+						{
+							P_SetMobjState(mobj, S_PTERABYTE_FLY1);
+							mobj->extravalue1 = 2;
+							P_SetTarget(&mobj->target, NULL);
+							mobj->momx = mobj->momy = mobj->momz = 0;
+						}
+					}
+					else // Returning
+					{
+						var1 = 2*mobj->info->speed;
+						var2 = 1;
+						A_HomingChase(mobj);
+						if (P_AproxDistance(mobj->x - mobj->tracer->x, mobj->y - mobj->tracer->y) <= mobj->info->speed)
+						{
+							mobj->extravalue1 = 0;
+							mobj->momx = mobj->momy = mobj->momz = 0;
+						}
+					}
+					break;
+				}
 			case MT_SPINFIRE:
 				if (mobj->flags & MF_NOGRAVITY)
 				{
diff --git a/src/sounds.c b/src/sounds.c
index 5a498b358..c2b9a09d7 100644
--- a/src/sounds.c
+++ b/src/sounds.c
@@ -200,6 +200,7 @@ sfxinfo_t S_sfx[NUMSFX] =
   {"bsnipe", false, 200,  0, -1, NULL, 0,        -1,  -1, LUMPERROR, "Home-run smash"},
   {"sprong", false, 112,  0, -1, NULL, 0,        -1,  -1, LUMPERROR, "Power spring"},
   {"lvfal1",  true,  64,  0, -1, NULL, 0,        -1,  -1, LUMPERROR, "Rumble"},
+  {"pscree", false,  64,  0, -1, NULL, 0,        -1,  -1, LUMPERROR, "SCREE!"},
 
   // Menu, interface
   {"chchng", false, 120,  0, -1, NULL, 0,        -1,  -1, LUMPERROR, "Score"},
diff --git a/src/sounds.h b/src/sounds.h
index f1221e6fe..be6969e56 100644
--- a/src/sounds.h
+++ b/src/sounds.h
@@ -266,6 +266,7 @@ typedef enum
 	sfx_bsnipe,
 	sfx_sprong,
 	sfx_lvfal1,
+	sfx_pscree,
 
 	// Menu, interface
 	sfx_chchng,