From cafe7a68b98f4193924df650a4ecf029198630ed Mon Sep 17 00:00:00 2001
From: Lactozilla <jp6781615@gmail.com>
Date: Sun, 6 Aug 2023 23:34:06 -0300
Subject: [PATCH] Add weapon_mobj_type and missile_mobj_type

---
 src/deh_soc.c     | 22 ++++++++++++++++++++++
 src/doomstat.h    |  8 +++++---
 src/g_game.c      | 20 ++++++++++++++++++++
 src/g_game.h      |  2 ++
 src/lua_infolib.c | 32 ++++++++++++++++++++++++++++++++
 src/p_enemy.c     |  4 ++--
 src/p_inter.c     | 33 ++++++++++++++++++++-------------
 src/p_mobj.c      | 13 ++++++++++---
 src/p_user.c      |  9 ++++++++-
 9 files changed, 121 insertions(+), 22 deletions(-)

diff --git a/src/deh_soc.c b/src/deh_soc.c
index 9ebec77b6e..09213331a5 100644
--- a/src/deh_soc.c
+++ b/src/deh_soc.c
@@ -1457,6 +1457,28 @@ void readteam(MYFILE *f, INT32 num)
 					deh_warning("readteam %d: Thing %d out of range (1 - %d)", num, i, NUMMOBJTYPES-1);
 				}
 			}
+			else if (fastcmp(word, "WEAPON"))
+			{
+				if (i == 0 && word2[0] != '0') // If word2 isn't a number
+					i = get_mobjtype(word2); // find a thing by name
+				if (i < NUMMOBJTYPES && i > 0)
+					team->weapon_mobj_type = i;
+				else
+				{
+					deh_warning("readteam %d: Thing %d out of range (1 - %d)", num, i, NUMMOBJTYPES-1);
+				}
+			}
+			else if (fastcmp(word, "MISSILE"))
+			{
+				if (i == 0 && word2[0] != '0') // If word2 isn't a number
+					i = get_mobjtype(word2); // find a thing by name
+				if (i < NUMMOBJTYPES && i > 0)
+					team->missile_mobj_type = i;
+				else
+				{
+					deh_warning("readteam %d: Thing %d out of range (1 - %d)", num, i, NUMMOBJTYPES-1);
+				}
+			}
 			else if (fastcmp(word, "COLOR"))
 			{
 				if (i == 0 && word2[0] != '0') // If word2 isn't a number
diff --git a/src/doomstat.h b/src/doomstat.h
index 044c46dc12..25fe4b15dd 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -406,12 +406,14 @@ enum {
 typedef struct
 {
 	char *name;
-	char *flag_name;
-	UINT16 flag;
-	UINT32 flag_mobj_type;
 	UINT16 color;
+	UINT32 weapon_mobj_type;
+	UINT32 missile_mobj_type;
 	UINT16 weapon_color;
 	UINT16 missile_color;
+	char *flag_name;
+	UINT16 flag;
+	UINT32 flag_mobj_type;
 	char *icons[TEAM_ICON_MAX];
 } team_t;
 
diff --git a/src/g_game.c b/src/g_game.c
index 987a5faccf..447624d238 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -3512,6 +3512,7 @@ team_t teams[MAXTEAMS] = {
 		.color = SKINCOLOR_RED,
 		.weapon_color = SKINCOLOR_RED,
 		.missile_color = SKINCOLOR_SALMON,
+		.weapon_mobj_type = MT_BLUETEAMRING,
 		.flag = GF_REDFLAG,
 		.flag_mobj_type = MT_REDFLAG,
 	},
@@ -3520,6 +3521,7 @@ team_t teams[MAXTEAMS] = {
 		.color = SKINCOLOR_BLUE,
 		.weapon_color = SKINCOLOR_BLUE,
 		.missile_color = SKINCOLOR_CORNFLOWER,
+		.weapon_mobj_type = MT_REDTEAMRING,
 		.flag = GF_BLUEFLAG,
 		.flag_mobj_type = MT_BLUEFLAG,
 	}
@@ -3936,6 +3938,8 @@ void G_InitTeam(UINT8 team)
 
 	memset(&teams[team], 0, sizeof(team_t));
 
+	teams[team].weapon_mobj_type = MT_RING;
+	teams[team].missile_mobj_type = MT_REDRING;
 	teams[team].flag = 1 << (team - 1);
 }
 
@@ -4013,6 +4017,22 @@ const char *G_GetTeamFlagName(UINT8 team)
 	return teams[team].flag_name;
 }
 
+UINT32 G_GetTeamWeaponMobjtype(UINT8 team)
+{
+	if (team >= numteams || !teams[team].weapon_mobj_type)
+		return MT_RING;
+
+	return teams[team].weapon_mobj_type;
+}
+
+UINT32 G_GetTeamMissileMobjtype(UINT8 team)
+{
+	if (team >= numteams || !teams[team].missile_mobj_type)
+		return MT_REDRING;
+
+	return teams[team].missile_mobj_type;
+}
+
 UINT16 G_GetTeamColor(UINT8 team)
 {
 	if (team >= numteams)
diff --git a/src/g_game.h b/src/g_game.h
index 7bd9ded323..cc44fd053e 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -231,6 +231,8 @@ UINT8 G_GetTeamFromTeamFlag(UINT32 flag);
 UINT8 G_GetTeamListFromTeamFlags(UINT8 *teamlist, UINT32 flags);
 const char *G_GetTeamName(UINT8 team);
 const char *G_GetTeamFlagName(UINT8 team);
+UINT32 G_GetTeamWeaponMobjtype(UINT8 team);
+UINT32 G_GetTeamMissileMobjtype(UINT8 team);
 UINT16 G_GetTeamColor(UINT8 team);
 UINT16 G_GetTeamWeaponColor(UINT8 team);
 UINT16 G_GetTeamMissileColor(UINT8 team);
diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index 46ad64672f..5ae0c2ddb7 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -2104,6 +2104,8 @@ enum team_e
 	team_flag_name,
 	team_flag,
 	team_flag_mobj_type,
+	team_weapon_mobj_type,
+	team_missile_mobj_type,
 	team_color,
 	team_weapon_color,
 	team_missile_color,
@@ -2118,6 +2120,8 @@ const char *const team_opt[] = {
 	"flag_name",
 	"flag",
 	"flag_mobj_type",
+	"weapon_mobj_type",
+	"missile_mobj_type",
 	"color",
 	"weapon_color",
 	"missile_color",
@@ -2169,6 +2173,28 @@ static int set_team_field(lua_State *L, team_t *team, enum team_e field)
 		team->flag_mobj_type = type;
 		break;
 	}
+	case team_weapon_mobj_type:
+	{
+		mobjtype_t type = luaL_checkinteger(L, 3);
+		if (type >= NUMMOBJTYPES)
+		{
+			luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
+			return 0;
+		}
+		team->weapon_mobj_type = type;
+		break;
+	}
+	case team_missile_mobj_type:
+	{
+		mobjtype_t type = luaL_checkinteger(L, 3);
+		if (type >= NUMMOBJTYPES)
+		{
+			luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
+			return 0;
+		}
+		team->missile_mobj_type = type;
+		break;
+	}
 	case team_color:
 	{
 		UINT16 newcolor = (UINT16)luaL_checkinteger(L, 3);
@@ -2298,6 +2324,12 @@ static int team_get(lua_State *L)
 	case team_flag_mobj_type:
 		lua_pushinteger(L, team->flag_mobj_type);
 		break;
+	case team_weapon_mobj_type:
+		lua_pushinteger(L, team->weapon_mobj_type);
+		break;
+	case team_missile_mobj_type:
+		lua_pushinteger(L, team->missile_mobj_type);
+		break;
 	case team_color:
 		lua_pushinteger(L, team->color);
 		break;
diff --git a/src/p_enemy.c b/src/p_enemy.c
index d3a1a5f481..318a9e9746 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -824,8 +824,8 @@ static boolean P_LookForShield(mobj_t *actor)
 			continue; // dead
 
 		//When in CTF, don't pull rings that you cannot pick up.
-		if ((actor->type == MT_REDTEAMRING && player->ctfteam != TEAM_RED) ||
-			(actor->type == MT_BLUETEAMRING && player->ctfteam != TEAM_BLUE))
+		if ((actor->type == MT_REDTEAMRING && player->ctfteam != G_GetTeam(TEAM_RED)) ||
+			(actor->type == MT_BLUETEAMRING && player->ctfteam != G_GetTeam(TEAM_BLUE)))
 			continue;
 
 		if ((player->powers[pw_shield] & SH_PROTECTELECTRIC)
diff --git a/src/p_inter.c b/src/p_inter.c
index 3201bd453d..84da2a437d 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -334,6 +334,18 @@ void P_DoMatchSuper(player_t *player)
 			}
 }
 
+static void P_CollectRing(player_t *player, mobj_t *special)
+{
+	if (!(P_CanPickupItem(player, false)) && !(special->flags2 & MF2_NIGHTSPULL))
+		return;
+
+	special->momx = special->momy = special->momz = 0;
+	P_GivePlayerRings(player, 1);
+
+	if ((maptol & TOL_NIGHTS) && special->type != MT_FLINGRING && special->type != MT_FLINGCOIN)
+		P_DoNightsScore(player);
+}
+
 /** Takes action based on a ::MF_SPECIAL thing touched by a player.
   * Actually, this just checks a few things (heights, toucher->player, no
   * objectplace, no dead or disappearing things)
@@ -615,26 +627,21 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 // Rings, coins, spheres, weapon panels, etc //
 // ***************************************** //
 		case MT_REDTEAMRING:
-			if (player->ctfteam != TEAM_RED)
+			if (player->ctfteam != G_GetTeam(TEAM_RED))
 				return;
-			/* FALLTHRU */
-		case MT_BLUETEAMRING: // Yes, I'm lazy. Oh well, deal with it.
-			if (special->type == MT_BLUETEAMRING && player->ctfteam != TEAM_BLUE)
+			P_CollectRing(player, special);
+			break;
+		case MT_BLUETEAMRING:
+			if (player->ctfteam != G_GetTeam(TEAM_BLUE))
 				return;
-			/* FALLTHRU */
+			P_CollectRing(player, special);
+			break;
 		case MT_RING:
 		case MT_FLINGRING:
 		case MT_COIN:
 		case MT_FLINGCOIN:
 		case MT_NIGHTSSTAR:
-			if (!(P_CanPickupItem(player, false)) && !(special->flags2 & MF2_NIGHTSPULL))
-				return;
-
-			special->momx = special->momy = special->momz = 0;
-			P_GivePlayerRings(player, 1);
-
-			if ((maptol & TOL_NIGHTS) && special->type != MT_FLINGRING && special->type != MT_FLINGCOIN)
-				P_DoNightsScore(player);
+			P_CollectRing(player, special);
 			break;
 		case MT_BLUESPHERE:
 		case MT_FLINGBLUESPHERE:
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 56c7d4cb6e..b7559437c7 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -10914,10 +10914,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 			 mobj->lastlook = mobj->extravalue2 = -1;
 			break;
 		case MT_REDTEAMRING:
-			mobj->color = G_GetTeamWeaponColor(TEAM_RED);
+			mobj->color = G_GetTeamWeaponColor(G_GetTeam(TEAM_RED));
 			break;
 		case MT_BLUETEAMRING:
-			mobj->color = G_GetTeamWeaponColor(TEAM_BLUE);
+			mobj->color = G_GetTeamWeaponColor(G_GetTeam(TEAM_BLUE));
 			break;
 		case MT_RING:
 		case MT_COIN:
@@ -12186,7 +12186,14 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i)
 		return teams[team].flag_mobj_type;
 	}
 
-	if (!(gametyperules & GTR_TEAMS))
+	if (gametyperules & GTR_TEAMS)
+	{
+		if (i == MT_REDTEAMRING)
+			i = G_GetTeamWeaponMobjtype(G_GetTeam(TEAM_RED));
+		else if (i == MT_BLUETEAMRING)
+			i = G_GetTeamWeaponMobjtype(G_GetTeam(TEAM_BLUE));
+	}
+	else
 	{
 		if (i == MT_BLUETEAMRING || i == MT_REDTEAMRING)
 			return MT_RING;
diff --git a/src/p_user.c b/src/p_user.c
index fa634c5ccd..72b098c149 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -4221,7 +4221,14 @@ firenormal:
 				return;
 			P_SetWeaponDelay(player, TICRATE/4);
 
-			mo = P_SpawnPlayerMissile(player->mo, MT_REDRING, 0);
+			mobjtype_t missile_type;
+
+			if (G_GametypeHasTeams())
+				missile_type = G_GetTeamMissileMobjtype(player->ctfteam);
+			else
+				missile_type = MT_REDRING;
+
+			mo = P_SpawnPlayerMissile(player->mo, missile_type, 0);
 
 			if (mo)
 				P_ColorTeamMissile(mo, player);
-- 
GitLab