Added P_MobjTouchingTeamBase, P_TeamHasFlagAtBase, sector.teambase

This commit is contained in:
Lactozilla 2023-08-06 21:13:00 -03:00
parent 0021fd1680
commit f6f5dcef1c
9 changed files with 312 additions and 67 deletions

View file

@ -3947,7 +3947,7 @@ UINT8 G_GetTeamFromTeamFlag(UINT32 flag)
{ {
for (UINT16 i = 1; i < teamsingame; i++) for (UINT16 i = 1; i < teamsingame; i++)
{ {
UINT32 otherflag = 1 << (i - 1); UINT32 otherflag = teams[G_GetTeam(i)].flag;
if (flag == otherflag) if (flag == otherflag)
return i; return i;
} }
@ -3961,7 +3961,7 @@ UINT8 G_GetTeamListFromTeamFlags(UINT8 *teamlist, UINT32 flags)
for (UINT16 i = 1; i < teamsingame; i++) for (UINT16 i = 1; i < teamsingame; i++)
{ {
UINT32 otherflag = 1 << (i - 1); UINT32 otherflag = teams[G_GetTeam(i)].flag;
if ((flags & otherflag) != 0) if ((flags & otherflag) != 0)
{ {
teamlist[count++] = i; teamlist[count++] = i;

View file

@ -2340,6 +2340,19 @@ static int lib_pPlayerTouchingSectorSpecialFlag(lua_State *L)
return 1; return 1;
} }
static int lib_pMobjTouchingTeamBase(lua_State *L)
{
mobj_t *mo = *((mobj_t**)luaL_checkudata(L, 1, META_MOBJ));
INT32 team = (INT32)luaL_checkinteger(L, 2);
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
if (team <= 0 || team >= teamsingame)
luaL_error(L, "team index %d out of range (1 - %d)", team, teamsingame-1);
LUA_PushUserdata(L, P_MobjTouchingTeamBase(mo, team), META_SECTOR);
return 1;
}
static int lib_pFindLowestFloorSurrounding(lua_State *L) static int lib_pFindLowestFloorSurrounding(lua_State *L)
{ {
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
@ -2481,11 +2494,29 @@ static int lib_pFadeLight(lua_State *L)
static int lib_pIsFlagAtBase(lua_State *L) static int lib_pIsFlagAtBase(lua_State *L)
{ {
mobjtype_t flag = luaL_checkinteger(L, 1); mobjtype_t flag = luaL_checkinteger(L, 1);
//HUDSAFE
INLEVEL INLEVEL
if (flag >= NUMMOBJTYPES) if (flag >= NUMMOBJTYPES)
return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1); return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1);
lua_pushboolean(L, P_IsFlagAtBase(flag)); for (UINT8 i = 1; i < teamsingame; i++)
{
UINT8 team = G_GetTeam(i);
if (teams[team].flag_mobj_type == flag)
{
lua_pushboolean(L, P_TeamHasFlagAtBase(team));
return 1;
}
}
lua_pushboolean(L, false);
return 1;
}
static int lib_pTeamHasFlagAtBase(lua_State *L)
{
INT32 team = luaL_checkinteger(L, 1);
INLEVEL
if (team <= 0 || team >= teamsingame)
luaL_error(L, "team index %d out of range (1 - %d)", team, teamsingame-1);
lua_pushboolean(L, P_TeamHasFlagAtBase(team));
return 1; return 1;
} }
@ -4281,6 +4312,7 @@ static luaL_Reg lib[] = {
{"P_MobjTouchingSectorSpecialFlag",lib_pMobjTouchingSectorSpecialFlag}, {"P_MobjTouchingSectorSpecialFlag",lib_pMobjTouchingSectorSpecialFlag},
{"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial}, {"P_PlayerTouchingSectorSpecial",lib_pPlayerTouchingSectorSpecial},
{"P_PlayerTouchingSectorSpecialFlag",lib_pPlayerTouchingSectorSpecialFlag}, {"P_PlayerTouchingSectorSpecialFlag",lib_pPlayerTouchingSectorSpecialFlag},
{"P_MobjTouchingTeamBase",lib_pMobjTouchingTeamBase},
{"P_FindLowestFloorSurrounding",lib_pFindLowestFloorSurrounding}, {"P_FindLowestFloorSurrounding",lib_pFindLowestFloorSurrounding},
{"P_FindHighestFloorSurrounding",lib_pFindHighestFloorSurrounding}, {"P_FindHighestFloorSurrounding",lib_pFindHighestFloorSurrounding},
{"P_FindNextHighestFloor",lib_pFindNextHighestFloor}, {"P_FindNextHighestFloor",lib_pFindNextHighestFloor},
@ -4293,6 +4325,7 @@ static luaL_Reg lib[] = {
{"P_SpawnLightningFlash",lib_pSpawnLightningFlash}, {"P_SpawnLightningFlash",lib_pSpawnLightningFlash},
{"P_FadeLight",lib_pFadeLight}, {"P_FadeLight",lib_pFadeLight},
{"P_IsFlagAtBase",lib_pIsFlagAtBase}, {"P_IsFlagAtBase",lib_pIsFlagAtBase},
{"P_TeamHasFlagAtBase",lib_pTeamHasFlagAtBase},
{"P_SetupLevelSky",lib_pSetupLevelSky}, {"P_SetupLevelSky",lib_pSetupLevelSky},
{"P_SetSkyboxMobj",lib_pSetSkyboxMobj}, {"P_SetSkyboxMobj",lib_pSetSkyboxMobj},
{"P_StartQuake",lib_pStartQuake}, {"P_StartQuake",lib_pStartQuake},

View file

@ -60,6 +60,7 @@ enum sector_e {
sector_flags, sector_flags,
sector_specialflags, sector_specialflags,
sector_damagetype, sector_damagetype,
sector_teambase,
sector_triggertag, sector_triggertag,
sector_triggerer, sector_triggerer,
sector_friction, sector_friction,
@ -98,6 +99,7 @@ static const char *const sector_opt[] = {
"flags", "flags",
"specialflags", "specialflags",
"damagetype", "damagetype",
"teambase",
"triggertag", "triggertag",
"triggerer", "triggerer",
"friction", "friction",
@ -760,6 +762,9 @@ static int sector_get(lua_State *L)
case sector_damagetype: // damagetype case sector_damagetype: // damagetype
lua_pushinteger(L, (UINT8)sector->damagetype); lua_pushinteger(L, (UINT8)sector->damagetype);
return 1; return 1;
case sector_teambase: // teambase
lua_pushinteger(L, (UINT8)sector->teambase);
return 1;
case sector_triggertag: // triggertag case sector_triggertag: // triggertag
lua_pushinteger(L, (INT16)sector->triggertag); lua_pushinteger(L, (INT16)sector->triggertag);
return 1; return 1;
@ -893,6 +898,9 @@ static int sector_set(lua_State *L)
case sector_damagetype: case sector_damagetype:
sector->damagetype = (UINT8)luaL_checkinteger(L, 3); sector->damagetype = (UINT8)luaL_checkinteger(L, 3);
break; break;
case sector_teambase:
sector->teambase = (UINT8)luaL_checkinteger(L, 3);
break;
case sector_triggertag: case sector_triggertag:
sector->triggertag = (INT16)luaL_checkinteger(L, 3); sector->triggertag = (INT16)luaL_checkinteger(L, 3);
break; break;

View file

@ -566,7 +566,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (special->extravalue1 > TEAM_NONE && special->extravalue1 < numteams) if (special->extravalue1 > TEAM_NONE && special->extravalue1 < numteams)
{ {
UINT8 flagteam = special->extravalue1; UINT8 flagteam = special->extravalue1;
sectorspecialflags_t specialflag = flagteam == TEAM_RED ? SSF_REDTEAMBASE : SSF_BLUETEAMBASE;
const char *flagtext; const char *flagtext;
const char *flagcolor; const char *flagcolor;
char plname[MAXPLAYERNAME+4]; char plname[MAXPLAYERNAME+4];
@ -588,7 +587,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->fuse = 1; special->fuse = 1;
special->flags2 |= MF2_JUSTATTACKED; special->flags2 |= MF2_JUSTATTACKED;
if (!P_PlayerTouchingSectorSpecialFlag(player, specialflag)) if (!P_PlayerTouchingTeamBase(player, flagteam))
CONS_Printf(M_GetText("%s returned the %s%s%c to base.\n"), plname, flagcolor, flagtext, 0x80); CONS_Printf(M_GetText("%s returned the %s%s%c to base.\n"), plname, flagcolor, flagtext, 0x80);
} }
return; return;
@ -4381,14 +4380,28 @@ void P_PlayerFlagBurst(player_t *player, boolean toss)
if (!player->gotflag) if (!player->gotflag)
return; return;
for (UINT8 i = 1; i < numteams; i++) UINT8 totalcaptured = 0;
UINT8 teamscaptured[MAXTEAMS];
memset(teamscaptured, 0, sizeof(teamscaptured));
for (UINT8 i = 1; i < teamsingame; i++)
{ {
UINT8 team = G_GetTeam(i); UINT8 otherteam = G_GetTeam(i);
UINT32 flagflag = 1 << (team - 1); UINT32 flagflag = teams[otherteam].flag;
if (!(player->gotflag & flagflag)) if (!(player->gotflag & flagflag) || otherteam == player->ctfteam)
continue;
if (teams[otherteam].flag_mobj_type == 0)
continue; continue;
mobj_t *flag = P_SpawnTeamFlag(team, player->mo->x, player->mo->y, player->mo->z); teamscaptured[totalcaptured++] = otherteam;
}
for (UINT8 i = 0; i < totalcaptured; i++)
{
UINT8 otherteam = teamscaptured[i];
mobj_t *flag = P_SpawnTeamFlag(otherteam, player->mo->x, player->mo->y, player->mo->z);
if (flag == NULL) if (flag == NULL)
continue; continue;
@ -4402,7 +4415,12 @@ void P_PlayerFlagBurst(player_t *player, boolean toss)
P_InstaThrust(flag, player->mo->angle, FixedMul(6*FRACUNIT, player->mo->scale)); P_InstaThrust(flag, player->mo->angle, FixedMul(6*FRACUNIT, player->mo->scale));
else else
{ {
angle_t fa = P_RandomByte()*FINEANGLES/256; angle_t fa;
if (totalcaptured == 1)
fa = P_RandomByte()*FINEANGLES/256;
else
fa = ((255 / totalcaptured) * i) * FINEANGLES/256;
flag->momx = FixedMul(FINECOSINE(fa), FixedMul(6*FRACUNIT, player->mo->scale)); flag->momx = FixedMul(FINECOSINE(fa), FixedMul(6*FRACUNIT, player->mo->scale));
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
flag->momy = FixedMul(FINESINE(fa), FixedMul(6*FRACUNIT, player->mo->scale)); flag->momy = FixedMul(FINESINE(fa), FixedMul(6*FRACUNIT, player->mo->scale));
@ -4412,37 +4430,34 @@ void P_PlayerFlagBurst(player_t *player, boolean toss)
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
flag->momz = -flag->momz; flag->momz = -flag->momz;
flag->spawnpoint = flagpoints[team]; flag->spawnpoint = flagpoints[otherteam];
flag->fuse = cv_flagtime.value * TICRATE; flag->fuse = cv_flagtime.value * TICRATE;
P_SetTarget(&flag->target, player->mo); P_SetTarget(&flag->target, player->mo);
// Take out the flag from the player
player->gotflag &= ~teams[otherteam].flag;
// Flag text // Flag text
{
char plname[MAXPLAYERNAME+4]; char plname[MAXPLAYERNAME+4];
const char *flagtext;
const char *flagcolor;
snprintf(plname, sizeof(plname), "%s%s%s", snprintf(plname, sizeof(plname), "%s%s%s",
CTFTEAMCODE(player), CTFTEAMCODE(player),
player_names[player - players], player_names[player - players],
CTFTEAMENDCODE(player)); CTFTEAMENDCODE(player));
flagtext = G_GetTeamFlagName(team); const char *flagtext = G_GetTeamFlagName(otherteam);
flagcolor = GetChatColorForSkincolor(G_GetTeamColor(team)); const char *flagcolor = GetChatColorForSkincolor(G_GetTeamColor(otherteam));
if (toss) if (toss)
CONS_Printf(M_GetText("%s tossed the %s%s%c.\n"), plname, flagcolor, flagtext, 0x80); CONS_Printf(M_GetText("%s tossed the %s%s%c.\n"), plname, flagcolor, flagtext, 0x80);
else else
CONS_Printf(M_GetText("%s dropped the %s%s%c.\n"), plname, flagcolor, flagtext, 0x80); CONS_Printf(M_GetText("%s dropped the %s%s%c.\n"), plname, flagcolor, flagtext, 0x80);
}
// Pointers set for displaying time value and for consistency restoration. // Pointers set for displaying time value and for consistency restoration.
P_SetTarget(&flagmobjs[team], flag); P_SetTarget(&flagmobjs[otherteam], flag);
} }
player->gotflag = 0;
if (toss) if (toss)
player->tossdelay = 2*TICRATE; player->tossdelay = 2*TICRATE;
} }

View file

@ -867,6 +867,7 @@ static void P_NetUnArchiveWaypoints(void)
#define SD_TRIGGERTAG 0x02 #define SD_TRIGGERTAG 0x02
#define SD_TRIGGERER 0x04 #define SD_TRIGGERER 0x04
#define SD_GRAVITY 0x08 #define SD_GRAVITY 0x08
#define SD_TEAMBASE 0x10
#define LD_FLAG 0x01 #define LD_FLAG 0x01
#define LD_SPECIAL 0x02 #define LD_SPECIAL 0x02
@ -1064,6 +1065,8 @@ static void ArchiveSectors(void)
diff4 |= SD_TRIGGERER; diff4 |= SD_TRIGGERER;
if (ss->gravity != spawnss->gravity) if (ss->gravity != spawnss->gravity)
diff4 |= SD_GRAVITY; diff4 |= SD_GRAVITY;
if (ss->teambase != spawnss->teambase)
diff4 |= SD_TEAMBASE;
if (ss->ffloors && CheckFFloorDiff(ss)) if (ss->ffloors && CheckFFloorDiff(ss))
diff |= SD_FFLOORS; diff |= SD_FFLOORS;
@ -1145,6 +1148,8 @@ static void ArchiveSectors(void)
WRITEUINT8(save_p, ss->triggerer); WRITEUINT8(save_p, ss->triggerer);
if (diff4 & SD_GRAVITY) if (diff4 & SD_GRAVITY)
WRITEFIXED(save_p, ss->gravity); WRITEFIXED(save_p, ss->gravity);
if (diff4 & SD_TEAMBASE)
WRITEUINT8(save_p, ss->teambase);
if (diff & SD_FFLOORS) if (diff & SD_FFLOORS)
ArchiveFFloors(ss); ArchiveFFloors(ss);
} }
@ -1265,6 +1270,8 @@ static void UnArchiveSectors(void)
sectors[i].triggerer = READUINT8(save_p); sectors[i].triggerer = READUINT8(save_p);
if (diff4 & SD_GRAVITY) if (diff4 & SD_GRAVITY)
sectors[i].gravity = READFIXED(save_p); sectors[i].gravity = READFIXED(save_p);
if (diff4 & SD_TEAMBASE)
sectors[i].teambase = READUINT8(save_p);
if (diff & SD_FFLOORS) if (diff & SD_FFLOORS)
UnArchiveFFloors(&sectors[i]); UnArchiveFFloors(&sectors[i]);

View file

@ -1801,9 +1801,28 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char
else if (fastcmp(param, "returnflag") && fastcmp("true", val)) else if (fastcmp(param, "returnflag") && fastcmp("true", val))
sectors[i].specialflags |= SSF_RETURNFLAG; sectors[i].specialflags |= SSF_RETURNFLAG;
else if (fastcmp(param, "redteambase") && fastcmp("true", val)) else if (fastcmp(param, "redteambase") && fastcmp("true", val))
{
sectors[i].specialflags |= SSF_REDTEAMBASE; sectors[i].specialflags |= SSF_REDTEAMBASE;
sectors[i].teambase = G_GetTeam(TEAM_RED);
}
else if (fastcmp(param, "blueteambase") && fastcmp("true", val)) else if (fastcmp(param, "blueteambase") && fastcmp("true", val))
{
sectors[i].specialflags |= SSF_BLUETEAMBASE; sectors[i].specialflags |= SSF_BLUETEAMBASE;
sectors[i].teambase = G_GetTeam(TEAM_BLUE);
}
else if (fastcmp(param, "teambase"))
{
sectors[i].teambase = TEAM_NONE;
for (UINT8 j = 0; j < numteams; j++)
{
if (fastcmp(val, teamnames[j]))
{
sectors[j].teambase = j;
break;
}
}
}
else if (fastcmp(param, "fan") && fastcmp("true", val)) else if (fastcmp(param, "fan") && fastcmp("true", val))
sectors[i].specialflags |= SSF_FAN; sectors[i].specialflags |= SSF_FAN;
else if (fastcmp(param, "supertransform") && fastcmp("true", val)) else if (fastcmp(param, "supertransform") && fastcmp("true", val))
@ -2711,6 +2730,22 @@ static void P_WriteTextmap(void)
fprintf(f, "redteambase = true;\n"); fprintf(f, "redteambase = true;\n");
if (wsectors[i].specialflags & SSF_BLUETEAMBASE) if (wsectors[i].specialflags & SSF_BLUETEAMBASE)
fprintf(f, "blueteambase = true;\n"); fprintf(f, "blueteambase = true;\n");
if (wsectors[i].teambase != TEAM_NONE && (wsectors[i].specialflags & (SSF_REDTEAMBASE | SSF_BLUETEAMBASE)) == 0)
{
// We DON'T write the teambase if the sector has (SSF_REDTEAMBASE | SSF_BLUETEAMBASE) because
// these flags get the team bases for the current gametype's team 1 and team 2, rather than the
// actual teams TEAM_RED and TEAM_BLUE.
UINT8 team = wsectors[i].teambase;
if (team != TEAM_NONE && team < numteams)
{
char *teambase = Z_StrDup(teamnames[team]);
strlwr(teambase);
fprintf(f, "teambase = \"%s\";\n", teambase);
Z_Free(teambase);
}
else
fprintf(f, "teambase = \"%s\";\n", "unknown");
}
if (wsectors[i].specialflags & SSF_FAN) if (wsectors[i].specialflags & SSF_FAN)
fprintf(f, "fan = true;\n"); fprintf(f, "fan = true;\n");
if (wsectors[i].specialflags & SSF_SUPERTRANSFORM) if (wsectors[i].specialflags & SSF_SUPERTRANSFORM)
@ -6201,9 +6236,11 @@ static void P_ConvertBinarySectorTypes(void)
break; break;
case 3: //Red team base case 3: //Red team base
sectors[i].specialflags |= SSF_REDTEAMBASE; sectors[i].specialflags |= SSF_REDTEAMBASE;
sectors[i].teambase = G_GetTeam(TEAM_RED);
break; break;
case 4: //Blue team base case 4: //Blue team base
sectors[i].specialflags |= SSF_BLUETEAMBASE; sectors[i].specialflags |= SSF_BLUETEAMBASE;
sectors[i].teambase = G_GetTeam(TEAM_BLUE);
break; break;
case 5: //Fan sector case 5: //Fan sector
sectors[i].specialflags |= SSF_FAN; sectors[i].specialflags |= SSF_FAN;

View file

@ -3941,15 +3941,18 @@ void P_SetupSignExit(player_t *player)
} }
// //
// P_IsFlagAtBase // P_TeamHasFlagAtBase
// //
// Checks to see if a flag is at its base. // Checks to see if a team has its flag at its base.
// //
boolean P_IsFlagAtBase(mobjtype_t flag) boolean P_TeamHasFlagAtBase(UINT8 team)
{ {
if (team == TEAM_NONE || team >= teamsingame)
return false;
thinker_t *think; thinker_t *think;
mobj_t *mo; mobj_t *mo;
sectorspecialflags_t specialflag = (flag == teams[TEAM_RED].flag_mobj_type) ? SSF_REDTEAMBASE : SSF_BLUETEAMBASE; mobjtype_t flag = teams[team].flag_mobj_type;
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{ {
@ -3961,7 +3964,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
if (mo->type != flag) if (mo->type != flag)
continue; continue;
if (mo->subsector->sector->specialflags & specialflag) if (mo->subsector->sector->teambase == team)
return true; return true;
else if (mo->subsector->sector->ffloors) // Check the 3D floors else if (mo->subsector->sector->ffloors) // Check the 3D floors
{ {
@ -3972,7 +3975,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
if (!(rover->fofflags & FOF_EXISTS)) if (!(rover->fofflags & FOF_EXISTS))
continue; continue;
if (!(rover->master->frontsector->specialflags & specialflag)) if (rover->master->frontsector->teambase != team)
continue; continue;
if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector)
@ -4238,6 +4241,97 @@ sector_t *P_MobjTouchingSectorSpecialFlag(mobj_t *mo, sectorspecialflags_t flag)
return NULL; return NULL;
} }
static sector_t *P_MobjTouching3DFloorTeamBase(mobj_t *mo, sector_t *sector, UINT8 team)
{
ffloor_t *rover;
for (rover = sector->ffloors; rover; rover = rover->next)
{
if (rover->master->frontsector->teambase != team)
continue;
if (!(rover->fofflags & FOF_EXISTS))
continue;
if (!P_IsMobjTouching3DFloor(mo, rover, sector))
continue;
// This FOF has the special we're looking for, but are we allowed to touch it?
if (sector == mo->subsector->sector
|| (rover->master->frontsector->flags & MSF_TRIGGERSPECIAL_TOUCH))
return rover->master->frontsector;
}
return NULL;
}
static sector_t *P_MobjTouchingPolyobjTeamBase(mobj_t *mo, UINT8 team)
{
polyobj_t *po;
sector_t *polysec;
boolean touching = false;
boolean inside = false;
for (po = mo->subsector->polyList; po; po = (polyobj_t *)(po->link.next))
{
if (po->flags & POF_NOSPECIALS)
continue;
polysec = po->lines[0]->backsector;
if (polysec->teambase != team)
continue;
touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, mo);
inside = P_MobjInsidePolyobj(po, mo);
if (!(inside || touching))
continue;
if (!P_IsMobjTouchingPolyobj(mo, po, polysec))
continue;
return polysec;
}
return NULL;
}
sector_t *P_MobjTouchingTeamBase(mobj_t *mo, UINT8 team)
{
msecnode_t *node;
sector_t *result;
result = P_MobjTouching3DFloorTeamBase(mo, mo->subsector->sector, team);
if (result)
return result;
result = P_MobjTouchingPolyobjTeamBase(mo, team);
if (result)
return result;
if (mo->subsector->sector->teambase == team)
return mo->subsector->sector;
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
if (node->m_sector == mo->subsector->sector) // Don't duplicate
continue;
result = P_MobjTouching3DFloorTeamBase(mo, node->m_sector, team);
if (result)
return result;
if (!(node->m_sector->flags & MSF_TRIGGERSPECIAL_TOUCH))
continue;
if (node->m_sector->teambase == team)
return node->m_sector;
}
return NULL;
}
// //
// P_PlayerTouchingSectorSpecial // P_PlayerTouchingSectorSpecial
// //
@ -4265,6 +4359,14 @@ sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags
return P_MobjTouchingSectorSpecialFlag(player->mo, flag); return P_MobjTouchingSectorSpecialFlag(player->mo, flag);
} }
sector_t *P_PlayerTouchingTeamBase(player_t *player, UINT8 base)
{
if (!player->mo)
return NULL;
return P_MobjTouchingTeamBase(player->mo, base);
}
static sector_t *P_CheckPlayer3DFloorTrigger(player_t *player, sector_t *sector, line_t *sourceline) static sector_t *P_CheckPlayer3DFloorTrigger(player_t *player, sector_t *sector, line_t *sourceline)
{ {
ffloor_t *rover; ffloor_t *rover;
@ -4637,38 +4739,47 @@ static void P_ProcessExitSector(player_t *player, mtag_t sectag)
static void P_ProcessTeamBase(player_t *player, UINT8 team) static void P_ProcessTeamBase(player_t *player, UINT8 team)
{ {
mobj_t *mo; if (team == TEAM_NONE || team >= teamsingame)
return;
if (!(gametyperules & GTR_TEAMFLAGS)) if (!(gametyperules & GTR_TEAMFLAGS))
return; return;
// Make sure the team still has their own flag at their base so they can score.
if (!P_TeamHasFlagAtBase(team))
return;
if (!P_IsObjectOnGround(player->mo)) if (!P_IsObjectOnGround(player->mo))
return; return;
if (player->ctfteam != team) if (!player->gotflag || player->ctfteam != team)
return; return;
UINT8 otherteam = team == TEAM_RED ? TEAM_BLUE : TEAM_RED; UINT8 totalcaptured = 0;
UINT32 teamflag = teams[otherteam].flag; UINT8 teamscaptured[MAXTEAMS];
if (!(player->gotflag & teamflag)) memset(teamscaptured, 0, sizeof(teamscaptured));
return;
// Make sure the team still has their own for (UINT8 i = 1; i < teamsingame; i++)
// flag at their base so they can score. {
if (!P_IsFlagAtBase(teams[team].flag_mobj_type)) UINT8 otherteam = G_GetTeam(i);
return; UINT32 flagflag = teams[otherteam].flag;
if (!(player->gotflag & flagflag) || otherteam == player->ctfteam)
continue;
HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE); teamscaptured[totalcaptured++] = otherteam;
HU_SetCEchoDuration(5); teamscores[team]++;
HU_DoCEcho(va(M_GetText("%s%s\200\\captured the %s%s\200.\\\\\\\\"), GetChatColorForSkincolor(G_GetTeamColor(team)), player_names[player-players], GetChatColorForSkincolor(G_GetTeamColor(otherteam)), G_GetTeamFlagName(otherteam)));
player->gotflag &= ~flagflag;
P_AddPlayerScore(player, 250);
if (splitscreen || players[consoleplayer].ctfteam == team) if (splitscreen || players[consoleplayer].ctfteam == team)
S_StartSound(NULL, sfx_flgcap); S_StartSound(NULL, sfx_flgcap);
else if (players[consoleplayer].ctfteam != team) else if (players[consoleplayer].ctfteam != team)
S_StartSound(NULL, sfx_lose); S_StartSound(NULL, sfx_lose);
mo = P_SpawnTeamFlag(otherteam, player->mo->x, player->mo->y, player->mo->z); mobj_t *mo = P_SpawnTeamFlag(otherteam, player->mo->x, player->mo->y, player->mo->z);
if (mo) if (mo)
{ {
mo->flags &= ~MF_SPECIAL; mo->flags &= ~MF_SPECIAL;
@ -4676,9 +4787,42 @@ static void P_ProcessTeamBase(player_t *player, UINT8 team)
mo->spawnpoint = flagpoints[otherteam]; mo->spawnpoint = flagpoints[otherteam];
mo->flags2 |= MF2_JUSTATTACKED; mo->flags2 |= MF2_JUSTATTACKED;
} }
player->gotflag &= ~teamflag; }
teamscores[team]++;
P_AddPlayerScore(player, 250); HU_SetCEchoFlags(V_AUTOFADEOUT|V_ALLOWLOWERCASE);
HU_SetCEchoDuration(5);
if (totalcaptured == 1)
{
UINT8 otherteam = teamscaptured[0];
HU_DoCEcho(va(M_GetText("%s%s\200\\captured the %s%s\200.\\\\\\\\"), GetChatColorForSkincolor(G_GetTeamColor(team)), player_names[player-players], GetChatColorForSkincolor(G_GetTeamColor(otherteam)), G_GetTeamFlagName(otherteam)));
}
else
{
char *buffer = NULL;
size_t buffer_size = 0;
const char *text = va(M_GetText("%s%s\200 captured the:\\"), GetChatColorForSkincolor(G_GetTeamColor(team)), player_names[player-players]);
buffer_size += strlen(text) + 1;
buffer = Z_Realloc(buffer, buffer_size, PU_STATIC, NULL);
strcpy(buffer, text);
for (UINT8 i = 0; i < totalcaptured; i++)
{
UINT8 otherteam = teamscaptured[i];
text = va(M_GetText("%s%s\200\\"), GetChatColorForSkincolor(G_GetTeamColor(otherteam)), G_GetTeamFlagName(otherteam));
buffer_size += strlen(text) + 1;
buffer = Z_Realloc(buffer, buffer_size, PU_STATIC, NULL);
strcat(buffer, text);
}
HU_DoCEcho(buffer);
Z_Free(buffer);
}
} }
static void P_ProcessZoomTube(player_t *player, mtag_t sectag, boolean end) static void P_ProcessZoomTube(player_t *player, mtag_t sectag, boolean end)
@ -4999,10 +5143,8 @@ static void P_EvaluateSpecialFlags(player_t *player, sector_t *sector, sector_t
P_ProcessExitSector(player, sectag); P_ProcessExitSector(player, sectag);
if ((sector->specialflags & SSF_SPECIALSTAGEPIT) && isTouching) if ((sector->specialflags & SSF_SPECIALSTAGEPIT) && isTouching)
P_ProcessSpecialStagePit(player); P_ProcessSpecialStagePit(player);
if ((sector->specialflags & SSF_REDTEAMBASE) && isTouching) if ((sector->teambase != TEAM_NONE) && isTouching)
P_ProcessTeamBase(player, TEAM_RED); P_ProcessTeamBase(player, sector->teambase);
if ((sector->specialflags & SSF_BLUETEAMBASE) && isTouching)
P_ProcessTeamBase(player, TEAM_BLUE);
if (sector->specialflags & SSF_FAN) if (sector->specialflags & SSF_FAN)
{ {
player->mo->momz += mobjinfo[MT_FAN].mass/4; player->mo->momz += mobjinfo[MT_FAN].mass/4;

View file

@ -506,6 +506,8 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline);
boolean P_IsPlayerValid(size_t playernum); boolean P_IsPlayerValid(size_t playernum);
boolean P_CanPlayerTrigger(size_t playernum); boolean P_CanPlayerTrigger(size_t playernum);
void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector); void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector);
sector_t *P_MobjTouchingTeamBase(mobj_t *mo, UINT8 team);
sector_t *P_PlayerTouchingTeamBase(player_t *player, UINT8 team);
fixed_t P_FindLowestFloorSurrounding(sector_t *sec); fixed_t P_FindLowestFloorSurrounding(sector_t *sec);
fixed_t P_FindHighestFloorSurrounding(sector_t *sec); fixed_t P_FindHighestFloorSurrounding(sector_t *sec);
@ -519,7 +521,7 @@ fixed_t P_FindHighestCeilingSurrounding(sector_t *sec);
INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max); INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max);
void P_SetupSignExit(player_t *player); void P_SetupSignExit(player_t *player);
boolean P_IsFlagAtBase(mobjtype_t flag); boolean P_TeamHasFlagAtBase(UINT8 team);
boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec); boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec);
boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *ffloor, sector_t *sec); boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *ffloor, sector_t *sec);

View file

@ -467,6 +467,7 @@ typedef struct sector_s
sectorflags_t flags; sectorflags_t flags;
sectorspecialflags_t specialflags; sectorspecialflags_t specialflags;
UINT8 damagetype; UINT8 damagetype;
UINT8 teambase;
// Linedef executor triggering // Linedef executor triggering
mtag_t triggertag; // tag to call upon triggering mtag_t triggertag; // tag to call upon triggering