mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-18 07:22:28 +00:00
Merge remote-tracking branch 'origin/next' into next-newcontrols
This commit is contained in:
commit
f8a3e3b898
32 changed files with 1061 additions and 442 deletions
48
src/b_bot.c
48
src/b_bot.c
|
@ -339,27 +339,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
jump_last = jump;
|
||||
spin_last = spin;
|
||||
|
||||
// ********
|
||||
// Thinkfly overlay
|
||||
if (thinkfly)
|
||||
{
|
||||
if (!tails->hnext)
|
||||
{
|
||||
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
|
||||
if (tails->hnext)
|
||||
{
|
||||
P_SetTarget(&tails->hnext->target, tails);
|
||||
P_SetTarget(&tails->hnext->hprev, tails);
|
||||
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR)
|
||||
{
|
||||
P_RemoveMobj(tails->hnext);
|
||||
P_SetTarget(&tails->hnext, NULL);
|
||||
}
|
||||
|
||||
// Turn the virtual keypresses into ticcmd_t.
|
||||
B_KeysToTiccmd(tails, cmd, forward, backward, left, right, false, false, jump, spin);
|
||||
|
||||
|
@ -569,3 +548,30 @@ void B_RespawnBot(INT32 playernum)
|
|||
P_SetScale(tails, sonic->scale);
|
||||
tails->destscale = sonic->destscale;
|
||||
}
|
||||
|
||||
void B_HandleFlightIndicator(player_t *player)
|
||||
{
|
||||
mobj_t *tails = player->mo;
|
||||
|
||||
if (!tails)
|
||||
return;
|
||||
|
||||
if (thinkfly && player->bot == 1 && tails->health)
|
||||
{
|
||||
if (!tails->hnext)
|
||||
{
|
||||
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
|
||||
if (tails->hnext)
|
||||
{
|
||||
P_SetTarget(&tails->hnext->target, tails);
|
||||
P_SetTarget(&tails->hnext->hprev, tails);
|
||||
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR)
|
||||
{
|
||||
P_RemoveMobj(tails->hnext);
|
||||
P_SetTarget(&tails->hnext, NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,3 +15,4 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward
|
|||
boolean B_CheckRespawn(player_t *player);
|
||||
void B_MoveBlocked(player_t *player);
|
||||
void B_RespawnBot(INT32 playernum);
|
||||
void B_HandleFlightIndicator(player_t *player);
|
||||
|
|
|
@ -54,7 +54,7 @@ static void COM_Add_f(void);
|
|||
static void CV_EnforceExecVersion(void);
|
||||
static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr);
|
||||
static boolean CV_Command(void);
|
||||
static consvar_t *CV_FindVar(const char *name);
|
||||
consvar_t *CV_FindVar(const char *name);
|
||||
static const char *CV_StringValue(const char *var_name);
|
||||
static consvar_t *consvar_vars; // list of registered console variables
|
||||
|
||||
|
@ -1106,7 +1106,7 @@ static const char *cv_null_string = "";
|
|||
* \return Pointer to the variable if found, or NULL.
|
||||
* \sa CV_FindNetVar
|
||||
*/
|
||||
static consvar_t *CV_FindVar(const char *name)
|
||||
consvar_t *CV_FindVar(const char *name)
|
||||
{
|
||||
consvar_t *cvar;
|
||||
|
||||
|
|
|
@ -149,6 +149,9 @@ void CV_ToggleExecVersion(boolean enable);
|
|||
// register a variable for use at the console
|
||||
void CV_RegisterVar(consvar_t *variable);
|
||||
|
||||
// returns a console variable by name
|
||||
consvar_t *CV_FindVar(const char *name);
|
||||
|
||||
// sets changed to 0 for every console variable
|
||||
void CV_ClearChangedFlags(void);
|
||||
|
||||
|
|
|
@ -1293,7 +1293,8 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
|||
|
||||
netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers();
|
||||
netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value;
|
||||
netbuffer->u.serverinfo.gametype = (UINT8)gametype;
|
||||
strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype],
|
||||
sizeof netbuffer->u.serverinfo.gametypename);
|
||||
netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
|
||||
netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();
|
||||
netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated;
|
||||
|
@ -2122,13 +2123,10 @@ static void CL_ConnectToServer(boolean viams)
|
|||
|
||||
if (i != -1)
|
||||
{
|
||||
UINT16 num = serverlist[i].info.gametype;
|
||||
const char *gametypestr = NULL;
|
||||
char *gametypestr = serverlist[i].info.gametypename;
|
||||
CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername);
|
||||
if (num < gametypecount)
|
||||
gametypestr = Gametype_Names[num];
|
||||
if (gametypestr)
|
||||
CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr);
|
||||
gametypestr[sizeof serverlist[i].info.gametypename - 1] = '\0';
|
||||
CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr);
|
||||
CONS_Printf(M_GetText("Version: %d.%d.%u\n"), serverlist[i].info.version/100,
|
||||
serverlist[i].info.version%100, serverlist[i].info.subversion);
|
||||
}
|
||||
|
@ -3656,6 +3654,8 @@ static void HandleServerInfo(SINT8 node)
|
|||
netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0;
|
||||
netbuffer->u.serverinfo.application
|
||||
[sizeof netbuffer->u.serverinfo.application - 1] = '\0';
|
||||
netbuffer->u.serverinfo.gametypename
|
||||
[sizeof netbuffer->u.serverinfo.gametypename - 1] = '\0';
|
||||
|
||||
SL_InsertServer(&netbuffer->u.serverinfo, node);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ This version is independent of the mod name, and standard
|
|||
version and subversion. It should only account for the
|
||||
basic fields of the packet, and change infrequently.
|
||||
*/
|
||||
#define PACKETVERSION 0
|
||||
#define PACKETVERSION 1
|
||||
|
||||
// Network play related stuff.
|
||||
// There is a data struct that stores network
|
||||
|
@ -361,7 +361,7 @@ typedef struct
|
|||
UINT8 subversion;
|
||||
UINT8 numberofplayer;
|
||||
UINT8 maxplayer;
|
||||
UINT8 gametype;
|
||||
char gametypename[24];
|
||||
UINT8 modifiedgame;
|
||||
UINT8 cheatsenabled;
|
||||
UINT8 isdedicated;
|
||||
|
|
|
@ -766,7 +766,7 @@ void D_StartTitle(void)
|
|||
|
||||
if (netgame)
|
||||
{
|
||||
if (gametype == GT_COOP)
|
||||
if (gametyperules & GTR_CAMPAIGN)
|
||||
{
|
||||
G_SetGamestate(GS_WAITINGPLAYERS); // hack to prevent a command repeat
|
||||
|
||||
|
|
|
@ -3726,7 +3726,7 @@ static void CoopStarposts_OnChange(void)
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
if (!(netgame || multiplayer) || gametype != GT_COOP)
|
||||
if (!(netgame || multiplayer) || !G_GametypeUsesCoopStarposts())
|
||||
return;
|
||||
|
||||
switch (cv_coopstarposts.value)
|
||||
|
@ -3781,7 +3781,7 @@ static void CoopLives_OnChange(void)
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
if (!(netgame || multiplayer) || gametype != GT_COOP)
|
||||
if (!(netgame || multiplayer) || !G_GametypeUsesCoopLives())
|
||||
return;
|
||||
|
||||
switch (cv_cooplives.value)
|
||||
|
|
|
@ -8906,32 +8906,35 @@ static const char *const GAMETYPERULE_LIST[] = {
|
|||
"CAMPAIGN",
|
||||
"RINGSLINGER",
|
||||
"SPECTATORS",
|
||||
"FRIENDLYFIRE",
|
||||
"LIVES",
|
||||
"TEAMS",
|
||||
"FIRSTPERSON",
|
||||
"POWERSTONES",
|
||||
"TEAMFLAGS",
|
||||
"FRIENDLY",
|
||||
"SPECIALSTAGES",
|
||||
"EMERALDTOKENS",
|
||||
"EMERALDHUNT",
|
||||
"RACE",
|
||||
"TAG",
|
||||
"POINTLIMIT",
|
||||
"TIMELIMIT",
|
||||
"HIDETIME",
|
||||
"OVERTIME",
|
||||
"HURTMESSAGES",
|
||||
"FRIENDLYFIRE",
|
||||
"STARTCOUNTDOWN",
|
||||
"HIDEFROZEN",
|
||||
"BLINDFOLDED",
|
||||
"FIRSTPERSON",
|
||||
"MATCHEMERALDS",
|
||||
"TEAMFLAGS",
|
||||
"RESPAWNDELAY",
|
||||
"PITYSHIELD",
|
||||
"DEATHPENALTY",
|
||||
"NOSPECTATORSPAWN",
|
||||
"DEATHMATCHSTARTS",
|
||||
"SPECIALSTAGES",
|
||||
"EMERALDTOKENS",
|
||||
"EMERALDHUNT",
|
||||
"SPAWNINVUL",
|
||||
"SPAWNENEMIES",
|
||||
"ALLOWEXIT",
|
||||
"NOTITLECARD",
|
||||
"OVERTIME",
|
||||
"HURTMESSAGES",
|
||||
"SPAWNINVUL",
|
||||
"CUTSCENES",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -464,6 +464,8 @@ extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL;
|
|||
char *va(const char *format, ...) FUNCPRINTF;
|
||||
char *M_GetToken(const char *inputString);
|
||||
void M_UnGetToken(void);
|
||||
UINT32 M_GetTokenPos(void);
|
||||
void M_SetTokenPos(UINT32 newPos);
|
||||
char *sizeu1(size_t num);
|
||||
char *sizeu2(size_t num);
|
||||
char *sizeu3(size_t num);
|
||||
|
|
|
@ -397,32 +397,35 @@ enum GameTypeRules
|
|||
GTR_CAMPAIGN = 1, // Linear Co-op map progression, don't allow random maps
|
||||
GTR_RINGSLINGER = 1<<1, // Outside of Co-op, Competition, and Race (overriden by cv_ringslinger)
|
||||
GTR_SPECTATORS = 1<<2, // Outside of Co-op, Competition, and Race
|
||||
GTR_FRIENDLYFIRE = 1<<3, // Always allow friendly fire
|
||||
GTR_LIVES = 1<<4, // Co-op and Competition
|
||||
GTR_TEAMS = 1<<5, // Team Match, CTF
|
||||
GTR_RACE = 1<<6, // Race and Competition
|
||||
GTR_TAG = 1<<7, // Tag and Hide and Seek
|
||||
GTR_POINTLIMIT = 1<<8, // Ringslinger point limit
|
||||
GTR_TIMELIMIT = 1<<9, // Ringslinger time limit
|
||||
GTR_HIDETIME = 1<<10, // Hide time (Tag and Hide and Seek)
|
||||
GTR_HIDEFROZEN = 1<<11, // Frozen after hide time (Hide and Seek, but not Tag)
|
||||
GTR_BLINDFOLDED = 1<<12, // Blindfolded view (Tag and Hide and Seek)
|
||||
GTR_FIRSTPERSON = 1<<13, // First person camera
|
||||
GTR_MATCHEMERALDS = 1<<14, // Ringslinger emeralds (Match and CTF)
|
||||
GTR_TEAMFLAGS = 1<<15, // Gametype has team flags (CTF)
|
||||
GTR_PITYSHIELD = 1<<16, // Award pity shield
|
||||
GTR_DEATHPENALTY = 1<<17, // Death score penalty
|
||||
GTR_NOSPECTATORSPAWN = 1<<18, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators
|
||||
GTR_DEATHMATCHSTARTS = 1<<19, // Use deathmatch starts
|
||||
GTR_SPECIALSTAGES = 1<<20, // Allow special stages
|
||||
GTR_EMERALDTOKENS = 1<<21, // Spawn emerald tokens
|
||||
GTR_EMERALDHUNT = 1<<22, // Emerald Hunt
|
||||
GTR_SPAWNENEMIES = 1<<23, // Spawn enemies
|
||||
GTR_ALLOWEXIT = 1<<24, // Allow exit sectors
|
||||
GTR_NOTITLECARD = 1<<25, // Don't show the title card
|
||||
GTR_OVERTIME = 1<<26, // Allow overtime
|
||||
GTR_HURTMESSAGES = 1<<27, // Hit and death messages
|
||||
GTR_SPAWNINVUL = 1<<28, // Babysitting deterrent
|
||||
GTR_LIVES = 1<<3, // Co-op and Competition
|
||||
GTR_TEAMS = 1<<4, // Team Match, CTF
|
||||
GTR_FIRSTPERSON = 1<<5, // First person camera
|
||||
GTR_POWERSTONES = 1<<6, // Power stones (Match and CTF)
|
||||
GTR_TEAMFLAGS = 1<<7, // Gametype has team flags (CTF)
|
||||
GTR_FRIENDLY = 1<<8, // Co-op
|
||||
GTR_SPECIALSTAGES = 1<<9, // Allow special stages
|
||||
GTR_EMERALDTOKENS = 1<<10, // Spawn emerald tokens
|
||||
GTR_EMERALDHUNT = 1<<11, // Emerald Hunt
|
||||
GTR_RACE = 1<<12, // Race and Competition
|
||||
GTR_TAG = 1<<13, // Tag and Hide and Seek
|
||||
GTR_POINTLIMIT = 1<<14, // Ringslinger point limit
|
||||
GTR_TIMELIMIT = 1<<15, // Ringslinger time limit
|
||||
GTR_OVERTIME = 1<<16, // Allow overtime
|
||||
GTR_HURTMESSAGES = 1<<17, // Hit and death messages
|
||||
GTR_FRIENDLYFIRE = 1<<18, // Always allow friendly fire
|
||||
GTR_STARTCOUNTDOWN = 1<<19, // Hide time countdown (Tag and Hide and Seek)
|
||||
GTR_HIDEFROZEN = 1<<20, // Frozen after hide time (Hide and Seek, but not Tag)
|
||||
GTR_BLINDFOLDED = 1<<21, // Blindfolded view (Tag and Hide and Seek)
|
||||
GTR_RESPAWNDELAY = 1<<22, // Respawn delay
|
||||
GTR_PITYSHIELD = 1<<23, // Award pity shield
|
||||
GTR_DEATHPENALTY = 1<<24, // Death score penalty
|
||||
GTR_NOSPECTATORSPAWN = 1<<25, // Use with GTR_SPECTATORS, spawn in the map instead of with the spectators
|
||||
GTR_DEATHMATCHSTARTS = 1<<26, // Use deathmatch starts
|
||||
GTR_SPAWNINVUL = 1<<27, // Babysitting deterrent
|
||||
GTR_SPAWNENEMIES = 1<<28, // Spawn enemies
|
||||
GTR_ALLOWEXIT = 1<<29, // Allow exit sectors
|
||||
GTR_NOTITLECARD = 1<<30, // Don't show the title card
|
||||
GTR_CUTSCENES = 1<<31, // Play cutscenes, ending, credits, and evaluation
|
||||
};
|
||||
|
||||
// String names for gametypes
|
||||
|
|
164
src/g_game.c
164
src/g_game.c
|
@ -1617,6 +1617,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver
|
||||
B_BuildTiccmd(player, cmd);
|
||||
}
|
||||
B_HandleFlightIndicator(player);
|
||||
}
|
||||
else if (player->bot == 2)
|
||||
*myangle = localangle; // Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Legacy
|
||||
|
@ -2676,8 +2677,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
|
|||
|
||||
// -- DM/Tag/CTF-spectator/etc --
|
||||
// Order: DM->CTF->Coop
|
||||
else if ((gametyperules & GTR_DEATHMATCHSTARTS) || gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF
|
||||
|| ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT)))
|
||||
else if ((gametyperules & GTR_DEATHMATCHSTARTS) && !(players[playernum].pflags & PF_TAGIT))
|
||||
{
|
||||
if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
|
||||
&& !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start
|
||||
|
@ -2878,11 +2878,11 @@ void G_DoReborn(INT32 playernum)
|
|||
|
||||
if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP))
|
||||
resetlevel = true;
|
||||
else if (gametype == GT_COOP && (netgame || multiplayer) && !G_IsSpecialStage(gamemap))
|
||||
else if ((G_GametypeUsesCoopLives() || G_GametypeUsesCoopStarposts()) && (netgame || multiplayer) && !G_IsSpecialStage(gamemap))
|
||||
{
|
||||
boolean notgameover = true;
|
||||
|
||||
if (cv_cooplives.value != 0 && player->lives <= 0) // consider game over first
|
||||
if (G_GametypeUsesCoopLives() && (cv_cooplives.value != 0 && player->lives <= 0)) // consider game over first
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -2917,7 +2917,7 @@ void G_DoReborn(INT32 playernum)
|
|||
}
|
||||
}
|
||||
|
||||
if (notgameover && cv_coopstarposts.value == 2)
|
||||
if (G_GametypeUsesCoopStarposts() && (notgameover && cv_coopstarposts.value == 2))
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -2993,7 +2993,7 @@ void G_DoReborn(INT32 playernum)
|
|||
}
|
||||
|
||||
// restore time in netgame (see also p_setup.c)
|
||||
if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2)
|
||||
if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2)
|
||||
{
|
||||
// is this a hack? maybe
|
||||
tic_t maxstarposttime = 0;
|
||||
|
@ -3064,7 +3064,7 @@ void G_AddPlayer(INT32 playernum)
|
|||
if (!players[i].exiting)
|
||||
notexiting++;
|
||||
|
||||
if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum)))
|
||||
if (!(cv_coopstarposts.value && G_GametypeUsesCoopStarposts() && (p->starpostnum < players[i].starpostnum)))
|
||||
continue;
|
||||
|
||||
p->starpostscale = players[i].starpostscale;
|
||||
|
@ -3181,24 +3181,24 @@ const char *Gametype_ConstantNames[NUMGAMETYPES] =
|
|||
UINT32 gametypedefaultrules[NUMGAMETYPES] =
|
||||
{
|
||||
// Co-op
|
||||
GTR_CAMPAIGN|GTR_LIVES|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES,
|
||||
GTR_CAMPAIGN|GTR_LIVES|GTR_FRIENDLY|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES|GTR_CUTSCENES,
|
||||
// Competition
|
||||
GTR_RACE|GTR_LIVES|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_SPAWNINVUL|GTR_ALLOWEXIT,
|
||||
// Race
|
||||
GTR_RACE|GTR_SPAWNENEMIES|GTR_SPAWNINVUL|GTR_ALLOWEXIT,
|
||||
|
||||
// Match
|
||||
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD|GTR_DEATHPENALTY,
|
||||
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD|GTR_DEATHPENALTY,
|
||||
// Team Match
|
||||
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_SPAWNINVUL|GTR_PITYSHIELD,
|
||||
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD,
|
||||
|
||||
// Tag
|
||||
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL,
|
||||
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY,
|
||||
// Hide and Seek
|
||||
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL,
|
||||
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_STARTCOUNTDOWN|GTR_BLINDFOLDED|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY,
|
||||
|
||||
// CTF
|
||||
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD,
|
||||
GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_POWERSTONES|GTR_DEATHMATCHSTARTS|GTR_SPAWNINVUL|GTR_RESPAWNDELAY|GTR_PITYSHIELD,
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -3239,50 +3239,68 @@ INT16 G_AddGametype(UINT32 rules)
|
|||
//
|
||||
void G_AddGametypeConstant(INT16 gtype, const char *newgtconst)
|
||||
{
|
||||
char *gtconst = Z_Malloc(strlen(newgtconst) + 3, PU_STATIC, NULL);
|
||||
// Copy GT_ and the gametype name.
|
||||
strcpy(gtconst, "GT_");
|
||||
strcat(gtconst, newgtconst);
|
||||
size_t r = 0; // read
|
||||
size_t w = 0; // write
|
||||
char *gtconst = Z_Calloc(strlen(newgtconst) + 3, PU_STATIC, NULL);
|
||||
char *tmpconst = Z_Calloc(strlen(newgtconst), PU_STATIC, NULL);
|
||||
|
||||
// Copy the gametype name.
|
||||
strcpy(tmpconst, newgtconst);
|
||||
|
||||
// Make uppercase.
|
||||
strupr(gtconst);
|
||||
// Remove characters.
|
||||
#define REMOVECHAR(chr) \
|
||||
{ \
|
||||
char *chrfind = strchr(gtconst, chr); \
|
||||
while (chrfind) \
|
||||
{ \
|
||||
*chrfind = '_'; \
|
||||
chrfind = strchr(chrfind, chr); \
|
||||
} \
|
||||
strupr(tmpconst);
|
||||
|
||||
// Prepare to write the new constant string now.
|
||||
strcpy(gtconst, "GT_");
|
||||
|
||||
// Remove characters that will not be allowed in the constant string.
|
||||
for (; r < strlen(tmpconst); r++)
|
||||
{
|
||||
boolean writechar = true;
|
||||
char rc = tmpconst[r];
|
||||
switch (rc)
|
||||
{
|
||||
// Space, at sign and question mark
|
||||
case ' ':
|
||||
case '@':
|
||||
case '?':
|
||||
// Used for operations
|
||||
case '+':
|
||||
case '-':
|
||||
case '*':
|
||||
case '/':
|
||||
case '%':
|
||||
case '^':
|
||||
case '&':
|
||||
case '!':
|
||||
// Part of Lua's syntax
|
||||
case '#':
|
||||
case '=':
|
||||
case '~':
|
||||
case '<':
|
||||
case '>':
|
||||
case '(':
|
||||
case ')':
|
||||
case '{':
|
||||
case '}':
|
||||
case '[':
|
||||
case ']':
|
||||
case ':':
|
||||
case ';':
|
||||
case ',':
|
||||
case '.':
|
||||
writechar = false;
|
||||
break;
|
||||
}
|
||||
if (writechar)
|
||||
{
|
||||
gtconst[3 + w] = rc;
|
||||
w++;
|
||||
}
|
||||
}
|
||||
|
||||
// Space
|
||||
REMOVECHAR(' ')
|
||||
// Used for operations
|
||||
REMOVECHAR('+')
|
||||
REMOVECHAR('-')
|
||||
REMOVECHAR('*')
|
||||
REMOVECHAR('/')
|
||||
REMOVECHAR('%')
|
||||
REMOVECHAR('^')
|
||||
// Part of Lua's syntax
|
||||
REMOVECHAR('#')
|
||||
REMOVECHAR('=')
|
||||
REMOVECHAR('~')
|
||||
REMOVECHAR('<')
|
||||
REMOVECHAR('>')
|
||||
REMOVECHAR('(')
|
||||
REMOVECHAR(')')
|
||||
REMOVECHAR('{')
|
||||
REMOVECHAR('}')
|
||||
REMOVECHAR('[')
|
||||
REMOVECHAR(']')
|
||||
REMOVECHAR(':')
|
||||
REMOVECHAR(';')
|
||||
REMOVECHAR(',')
|
||||
REMOVECHAR('.')
|
||||
|
||||
#undef REMOVECHAR
|
||||
// Free the temporary string.
|
||||
Z_Free(tmpconst);
|
||||
|
||||
// Finally, set the constant string.
|
||||
Gametype_ConstantNames[gtype] = gtconst;
|
||||
|
@ -3427,6 +3445,28 @@ boolean G_GametypeUsesLives(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// G_GametypeUsesCoopLives
|
||||
//
|
||||
// Returns true if the current gametype uses
|
||||
// the cooplives CVAR. False otherwise.
|
||||
//
|
||||
boolean G_GametypeUsesCoopLives(void)
|
||||
{
|
||||
return (gametyperules & (GTR_LIVES|GTR_FRIENDLY)) == (GTR_LIVES|GTR_FRIENDLY);
|
||||
}
|
||||
|
||||
//
|
||||
// G_GametypeUsesCoopStarposts
|
||||
//
|
||||
// Returns true if the current gametype uses
|
||||
// the coopstarposts CVAR. False otherwise.
|
||||
//
|
||||
boolean G_GametypeUsesCoopStarposts(void)
|
||||
{
|
||||
return (gametyperules & GTR_FRIENDLY);
|
||||
}
|
||||
|
||||
//
|
||||
// G_GametypeHasTeams
|
||||
//
|
||||
|
@ -3480,6 +3520,16 @@ boolean G_TagGametype(void)
|
|||
return (gametyperules & GTR_TAG);
|
||||
}
|
||||
|
||||
//
|
||||
// G_CompetitionGametype
|
||||
//
|
||||
// For gametypes that are race gametypes, and have lives.
|
||||
//
|
||||
boolean G_CompetitionGametype(void)
|
||||
{
|
||||
return ((gametyperules & GTR_RACE) && (gametyperules & GTR_LIVES));
|
||||
}
|
||||
|
||||
/** Get the typeoflevel flag needed to indicate support of a gametype.
|
||||
* In single-player, this always returns TOL_SP.
|
||||
* \param gametype The gametype for which support is desired.
|
||||
|
@ -3721,7 +3771,7 @@ void G_AfterIntermission(void)
|
|||
|
||||
HU_ClearCEcho();
|
||||
|
||||
if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene.
|
||||
if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene.
|
||||
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false);
|
||||
else
|
||||
{
|
||||
|
@ -3831,7 +3881,7 @@ static void G_DoContinued(void)
|
|||
void G_EndGame(void)
|
||||
{
|
||||
// Only do evaluation and credits in coop games.
|
||||
if (gametype == GT_COOP)
|
||||
if (gametyperules & GTR_CUTSCENES)
|
||||
{
|
||||
if (nextmap == 1103-1) // end game with ending
|
||||
{
|
||||
|
@ -4534,7 +4584,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
|
|||
automapactive = false;
|
||||
imcontinuing = false;
|
||||
|
||||
if (!skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene.
|
||||
if ((gametyperules & GTR_CUTSCENES) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene.
|
||||
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer);
|
||||
else
|
||||
G_DoLoadLevel(resetplayer);
|
||||
|
|
|
@ -245,11 +245,14 @@ void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolo
|
|||
INT32 G_GetGametypeByName(const char *gametypestr);
|
||||
boolean G_IsSpecialStage(INT32 mapnum);
|
||||
boolean G_GametypeUsesLives(void);
|
||||
boolean G_GametypeUsesCoopLives(void);
|
||||
boolean G_GametypeUsesCoopStarposts(void);
|
||||
boolean G_GametypeHasTeams(void);
|
||||
boolean G_GametypeHasSpectators(void);
|
||||
boolean G_RingSlingerGametype(void);
|
||||
boolean G_PlatformGametype(void);
|
||||
boolean G_TagGametype(void);
|
||||
boolean G_CompetitionGametype(void);
|
||||
boolean G_EnoughPlayersFinished(void);
|
||||
void G_ExitLevel(void);
|
||||
void G_NextLevel(void);
|
||||
|
|
|
@ -2445,7 +2445,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
|
|||
}
|
||||
}
|
||||
|
||||
if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
|
||||
if (G_GametypeUsesLives() && !(G_GametypeUsesCoopLives() && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
|
||||
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives));
|
||||
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
|
||||
{
|
||||
|
@ -2754,7 +2754,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
|
|||
| (greycheck ? V_TRANSLUCENT : 0)
|
||||
| V_ALLOWLOWERCASE, name);
|
||||
|
||||
if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
|
||||
if (G_GametypeUsesLives() && !(G_GametypeUsesCoopLives() && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
|
||||
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives));
|
||||
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
|
||||
V_DrawSmallScaledPatch(x-28, y-4, 0, tagico);
|
||||
|
|
|
@ -2854,6 +2854,22 @@ static int lib_gGametypeUsesLives(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_gGametypeUsesCoopLives(lua_State *L)
|
||||
{
|
||||
//HUDSAFE
|
||||
INLEVEL
|
||||
lua_pushboolean(L, G_GametypeUsesCoopLives());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_gGametypeUsesCoopStarposts(lua_State *L)
|
||||
{
|
||||
//HUDSAFE
|
||||
INLEVEL
|
||||
lua_pushboolean(L, G_GametypeUsesCoopStarposts());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_gGametypeHasTeams(lua_State *L)
|
||||
{
|
||||
//HUDSAFE
|
||||
|
@ -2894,6 +2910,14 @@ static int lib_gTagGametype(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_gCompetitionGametype(lua_State *L)
|
||||
{
|
||||
//HUDSAFE
|
||||
INLEVEL
|
||||
lua_pushboolean(L, G_CompetitionGametype());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_gTicsToHours(lua_State *L)
|
||||
{
|
||||
tic_t rtic = luaL_checkinteger(L, 1);
|
||||
|
@ -3139,11 +3163,14 @@ static luaL_Reg lib[] = {
|
|||
{"G_ExitLevel",lib_gExitLevel},
|
||||
{"G_IsSpecialStage",lib_gIsSpecialStage},
|
||||
{"G_GametypeUsesLives",lib_gGametypeUsesLives},
|
||||
{"G_GametypeUsesCoopLives",lib_gGametypeUsesCoopLives},
|
||||
{"G_GametypeUsesCoopStarposts",lib_gGametypeUsesCoopStarposts},
|
||||
{"G_GametypeHasTeams",lib_gGametypeHasTeams},
|
||||
{"G_GametypeHasSpectators",lib_gGametypeHasSpectators},
|
||||
{"G_RingSlingerGametype",lib_gRingSlingerGametype},
|
||||
{"G_PlatformGametype",lib_gPlatformGametype},
|
||||
{"G_TagGametype",lib_gTagGametype},
|
||||
{"G_CompetitionGametype",lib_gCompetitionGametype},
|
||||
{"G_TicsToHours",lib_gTicsToHours},
|
||||
{"G_TicsToMinutes",lib_gTicsToMinutes},
|
||||
{"G_TicsToSeconds",lib_gTicsToSeconds},
|
||||
|
|
|
@ -427,6 +427,26 @@ static int lib_cvRegisterVar(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_cvFindVar(lua_State *L)
|
||||
{
|
||||
consvar_t *cv;
|
||||
if (( cv = CV_FindVar(luaL_checkstring(L,1)) ))
|
||||
{
|
||||
lua_settop(L,1);/* We only want one argument in the stack. */
|
||||
lua_pushlightuserdata(L, cv);/* Now the second value on stack. */
|
||||
luaL_getmetatable(L, META_CVAR);
|
||||
/*
|
||||
The metatable is the last value on the stack, so this
|
||||
applies it to the second value, which is the cvar.
|
||||
*/
|
||||
lua_setmetatable(L,2);
|
||||
lua_pushvalue(L,2);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CONS_Printf for a single player
|
||||
// Use 'print' in baselib for a global message.
|
||||
static int lib_consPrintf(lua_State *L)
|
||||
|
@ -466,6 +486,7 @@ static luaL_Reg lib[] = {
|
|||
{"COM_BufAddText", lib_comBufAddText},
|
||||
{"COM_BufInsertText", lib_comBufInsertText},
|
||||
{"CV_RegisterVar", lib_cvRegisterVar},
|
||||
{"CV_FindVar", lib_cvFindVar},
|
||||
{"CONS_Printf", lib_consPrintf},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
|
|
@ -53,6 +53,7 @@ enum hook {
|
|||
hook_IntermissionThinker,
|
||||
hook_TeamSwitch,
|
||||
hook_ViewpointSwitch,
|
||||
hook_SeenPlayer,
|
||||
|
||||
hook_MAX // last hook
|
||||
};
|
||||
|
@ -97,5 +98,8 @@ void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting
|
|||
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
|
||||
boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh....
|
||||
UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode
|
||||
#ifdef SEENAMES
|
||||
boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -64,6 +64,7 @@ const char *const hookNames[hook_MAX+1] = {
|
|||
"IntermissionThinker",
|
||||
"TeamSwitch",
|
||||
"ViewpointSwitch",
|
||||
"SeenPlayer",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -207,6 +208,7 @@ static int lib_addHook(lua_State *L)
|
|||
case hook_PlayerCanDamage:
|
||||
case hook_TeamSwitch:
|
||||
case hook_ViewpointSwitch:
|
||||
case hook_SeenPlayer:
|
||||
case hook_ShieldSpawn:
|
||||
case hook_ShieldSpecial:
|
||||
lastp = &playerhooks;
|
||||
|
@ -1412,7 +1414,7 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean
|
|||
return 0;
|
||||
|
||||
lua_settop(gL, 0);
|
||||
hud_running = true;
|
||||
hud_running = true; // local hook
|
||||
|
||||
for (hookp = playerhooks; hookp; hookp = hookp->next)
|
||||
{
|
||||
|
@ -1453,4 +1455,49 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean
|
|||
return canSwitchView;
|
||||
}
|
||||
|
||||
// Hook for MT_NAMECHECK
|
||||
#ifdef SEENAMES
|
||||
boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend)
|
||||
{
|
||||
hook_p hookp;
|
||||
boolean hasSeenPlayer = true;
|
||||
if (!gL || !(hooksAvailable[hook_SeenPlayer/8] & (1<<(hook_SeenPlayer%8))))
|
||||
return 0;
|
||||
|
||||
lua_settop(gL, 0);
|
||||
hud_running = true; // local hook
|
||||
|
||||
for (hookp = playerhooks; hookp; hookp = hookp->next)
|
||||
{
|
||||
if (hookp->type != hook_SeenPlayer)
|
||||
continue;
|
||||
|
||||
if (lua_gettop(gL) == 0)
|
||||
{
|
||||
LUA_PushUserdata(gL, player, META_PLAYER);
|
||||
LUA_PushUserdata(gL, seenfriend, META_PLAYER);
|
||||
}
|
||||
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
|
||||
lua_gettable(gL, LUA_REGISTRYINDEX);
|
||||
lua_pushvalue(gL, -3);
|
||||
lua_pushvalue(gL, -3);
|
||||
if (lua_pcall(gL, 2, 1, 0)) {
|
||||
if (!hookp->error || cv_debug & DBG_LUA)
|
||||
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
|
||||
lua_pop(gL, 1);
|
||||
hookp->error = true;
|
||||
continue;
|
||||
}
|
||||
if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1))
|
||||
hasSeenPlayer = false; // Hasn't seen player
|
||||
lua_pop(gL, 1);
|
||||
}
|
||||
|
||||
lua_settop(gL, 0);
|
||||
hud_running = false;
|
||||
|
||||
return hasSeenPlayer;
|
||||
}
|
||||
#endif // SEENAMES
|
||||
|
||||
#endif
|
||||
|
|
|
@ -299,9 +299,7 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
// See the above.
|
||||
int LUA_CheckGlobals(lua_State *L, const char *word)
|
||||
{
|
||||
if (fastcmp(word, "gametyperules"))
|
||||
gametyperules = (UINT32)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word, "redscore"))
|
||||
if (fastcmp(word, "redscore"))
|
||||
redscore = (UINT32)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word, "bluescore"))
|
||||
bluescore = (UINT32)luaL_checkinteger(L, 2);
|
||||
|
|
27
src/m_menu.c
27
src/m_menu.c
|
@ -4966,7 +4966,7 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt)
|
|||
if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE))
|
||||
return true;
|
||||
|
||||
if (gt > 0 && gt < gametypecount && (mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt]))
|
||||
if (gt >= 0 && gt < gametypecount && (mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -10202,7 +10202,7 @@ static void M_DrawRoomMenu(void)
|
|||
static void M_DrawConnectMenu(void)
|
||||
{
|
||||
UINT16 i;
|
||||
const char *gt = "Unknown";
|
||||
char *gt;
|
||||
INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE;
|
||||
|
||||
for (i = FIRSTSERVERLINE; i < min(localservercount, SERVERS_PER_PAGE)+FIRSTSERVERLINE; i++)
|
||||
|
@ -10246,14 +10246,17 @@ static void M_DrawConnectMenu(void)
|
|||
V_DrawSmallString(currentMenu->x, S_LINEY(i)+8, globalflags,
|
||||
va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time)));
|
||||
|
||||
gt = "Unknown";
|
||||
if (serverlist[slindex].info.gametype < gametypecount)
|
||||
gt = Gametype_Names[serverlist[slindex].info.gametype];
|
||||
gt = serverlist[slindex].info.gametypename;
|
||||
|
||||
V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags,
|
||||
va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer));
|
||||
|
||||
V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, va("Gametype: %s", gt));
|
||||
if (strlen(gt) > 11)
|
||||
gt = va("Gametype: %.11s...", gt);
|
||||
else
|
||||
gt = va("Gametype: %s", gt);
|
||||
|
||||
V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, gt);
|
||||
|
||||
MP_ConnectMenu[i+FIRSTSERVERLINE].status = IT_STRING | IT_CALL;
|
||||
}
|
||||
|
@ -10294,7 +10297,15 @@ SERVER_LIST_ENTRY_COMPARATOR(time)
|
|||
SERVER_LIST_ENTRY_COMPARATOR(numberofplayer)
|
||||
SERVER_LIST_ENTRY_COMPARATOR_REVERSE(numberofplayer)
|
||||
SERVER_LIST_ENTRY_COMPARATOR_REVERSE(maxplayer)
|
||||
SERVER_LIST_ENTRY_COMPARATOR(gametype)
|
||||
|
||||
static int ServerListEntryComparator_gametypename(const void *entry1, const void *entry2)
|
||||
{
|
||||
const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2;
|
||||
int c;
|
||||
if (( c = strcasecmp(sa->info.gametypename, sb->info.gametypename) ))
|
||||
return c;
|
||||
return strcmp(sa->info.servername, sb->info.servername); \
|
||||
}
|
||||
|
||||
// Special one for modified state.
|
||||
static int ServerListEntryComparator_modified(const void *entry1, const void *entry2)
|
||||
|
@ -10334,7 +10345,7 @@ void M_SortServerList(void)
|
|||
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_maxplayer_reverse);
|
||||
break;
|
||||
case 5: // Gametype.
|
||||
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametype);
|
||||
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
|
14
src/m_misc.c
14
src/m_misc.c
|
@ -1908,6 +1908,20 @@ void M_UnGetToken(void)
|
|||
endPos = oldendPos;
|
||||
}
|
||||
|
||||
/** Returns the current token's position.
|
||||
*/
|
||||
UINT32 M_GetTokenPos(void)
|
||||
{
|
||||
return endPos;
|
||||
}
|
||||
|
||||
/** Sets the current token's position.
|
||||
*/
|
||||
void M_SetTokenPos(UINT32 newPos)
|
||||
{
|
||||
endPos = newPos;
|
||||
}
|
||||
|
||||
/** Count bits in a number.
|
||||
*/
|
||||
UINT8 M_CountBits(UINT32 num, UINT8 size)
|
||||
|
|
|
@ -1451,7 +1451,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (player->starpostnum >= special->health)
|
||||
return; // Already hit this post
|
||||
|
||||
if (cv_coopstarposts.value && gametype == GT_COOP && (netgame || multiplayer))
|
||||
if (cv_coopstarposts.value && G_GametypeUsesCoopStarposts() && (netgame || multiplayer))
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -1807,7 +1807,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
return;
|
||||
|
||||
case MT_MINECARTSPAWNER:
|
||||
if (!player->bot && (special->fuse < TICRATE || player->powers[pw_carry] != CR_MINECART))
|
||||
if (!player->bot && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART)
|
||||
{
|
||||
mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART);
|
||||
P_SetTarget(&mcart->target, toucher);
|
||||
|
@ -2521,7 +2521,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
target->colorized = false;
|
||||
G_GhostAddColor(GHC_NORMAL);
|
||||
|
||||
if ((target->player->lives <= 1) && (netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value == 0))
|
||||
if ((target->player->lives <= 1) && (netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value == 0))
|
||||
;
|
||||
else if (!target->player->bot && !target->player->spectator && (target->player->lives != INFLIVES)
|
||||
&& G_GametypeUsesLives())
|
||||
|
@ -2531,7 +2531,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
if (target->player->lives <= 0) // Tails 03-14-2000
|
||||
{
|
||||
boolean gameovermus = false;
|
||||
if ((netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value != 1))
|
||||
if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && (cv_cooplives.value != 1))
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
@ -3199,10 +3199,12 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
|
|||
player->powers[pw_carry] = CR_NONE;
|
||||
|
||||
// Burst weapons and emeralds in Match/CTF only
|
||||
if (source && (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF))
|
||||
if (source)
|
||||
{
|
||||
P_PlayerRingBurst(player, player->rings);
|
||||
P_PlayerEmeraldBurst(player, false);
|
||||
if ((gametyperules & GTR_RINGSLINGER) && !(gametyperules & GTR_TAG))
|
||||
P_PlayerRingBurst(player, player->rings);
|
||||
if (gametyperules & GTR_POWERSTONES)
|
||||
P_PlayerEmeraldBurst(player, false);
|
||||
}
|
||||
|
||||
// Get rid of shield
|
||||
|
|
11
src/p_map.c
11
src/p_map.c
|
@ -745,9 +745,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
// So that NOTHING ELSE can see MT_NAMECHECK because it is client-side.
|
||||
if (tmthing->type == MT_NAMECHECK)
|
||||
{
|
||||
// Ignore things that aren't players, ignore spectators, ignore yourself.
|
||||
// (also don't bother to check that tmthing->target->player is non-NULL because we're not actually using it here.)
|
||||
if (!thing->player || thing->player->spectator || (tmthing->target && thing->player == tmthing->target->player))
|
||||
// Ignore things that aren't players, ignore spectators, ignore yourself.
|
||||
if (!thing->player || !(tmthing->target && tmthing->target->player) || thing->player->spectator || (tmthing->target && thing->player == tmthing->target->player))
|
||||
return true;
|
||||
|
||||
// Now check that you actually hit them.
|
||||
|
@ -760,6 +759,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
// REX HAS SEEN YOU
|
||||
if (!LUAh_SeenPlayer(tmthing->target->player, thing->player))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
seenplayer = thing->player;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -11823,7 +11823,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i)
|
|||
if (!cv_powerstones.value)
|
||||
return false;
|
||||
|
||||
if (!(gametyperules & GTR_MATCHEMERALDS))
|
||||
if (!(gametyperules & GTR_POWERSTONES))
|
||||
return false;
|
||||
|
||||
runemeraldmanager = true;
|
||||
|
|
695
src/p_setup.c
695
src/p_setup.c
|
@ -83,6 +83,8 @@
|
|||
#include "p_slopes.h"
|
||||
#endif
|
||||
|
||||
#include "fastcmp.h" // textmap parsing
|
||||
|
||||
//
|
||||
// Map MD5, calculated on level load.
|
||||
// Sent to clients in PT_SERVERINFO.
|
||||
|
@ -863,11 +865,6 @@ static void P_InitializeSector(sector_t *ss)
|
|||
ss->lightingdata = NULL;
|
||||
ss->fadecolormapdata = NULL;
|
||||
|
||||
ss->floor_xoffs = ss->floor_yoffs = 0;
|
||||
ss->ceiling_xoffs = ss->ceiling_yoffs = 0;
|
||||
|
||||
ss->floorpic_angle = ss->ceilingpic_angle = 0;
|
||||
|
||||
ss->heightsec = -1;
|
||||
ss->camsec = -1;
|
||||
|
||||
|
@ -943,6 +940,11 @@ static void P_LoadSectors(UINT8 *data)
|
|||
ss->special = SHORT(ms->special);
|
||||
ss->tag = SHORT(ms->tag);
|
||||
|
||||
ss->floor_xoffs = ss->floor_yoffs = 0;
|
||||
ss->ceiling_xoffs = ss->ceiling_yoffs = 0;
|
||||
|
||||
ss->floorpic_angle = ss->ceilingpic_angle = 0;
|
||||
|
||||
P_InitializeSector(ss);
|
||||
}
|
||||
}
|
||||
|
@ -1012,16 +1014,34 @@ static void P_InitializeLinedef(line_t *ld)
|
|||
{
|
||||
sides[ld->sidenum[0]].special = ld->special;
|
||||
sides[ld->sidenum[0]].line = ld;
|
||||
|
||||
}
|
||||
if (ld->sidenum[1] != 0xffff)
|
||||
{
|
||||
sides[ld->sidenum[1]].special = ld->special;
|
||||
sides[ld->sidenum[1]].line = ld;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void P_SetLinedefV1(size_t i, UINT16 vertex_num)
|
||||
{
|
||||
if (vertex_num >= numvertexes)
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "P_SetLinedefV1: linedef %s has out-of-range v1 num %u\n", sizeu1(i), vertex_num);
|
||||
vertex_num = 0;
|
||||
}
|
||||
lines[i].v1 = &vertexes[vertex_num];
|
||||
}
|
||||
|
||||
static void P_SetLinedefV2(size_t i, UINT16 vertex_num)
|
||||
{
|
||||
if (vertex_num >= numvertexes)
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "P_SetLinedefV2: linedef %s has out-of-range v2 num %u\n", sizeu1(i), vertex_num);
|
||||
vertex_num = 0;
|
||||
}
|
||||
lines[i].v2 = &vertexes[vertex_num];
|
||||
}
|
||||
|
||||
static void P_LoadLinedefs(UINT8 *data)
|
||||
{
|
||||
maplinedef_t *mld = (maplinedef_t *)data;
|
||||
|
@ -1033,8 +1053,8 @@ static void P_LoadLinedefs(UINT8 *data)
|
|||
ld->flags = SHORT(mld->flags);
|
||||
ld->special = SHORT(mld->special);
|
||||
ld->tag = SHORT(mld->tag);
|
||||
ld->v1 = &vertexes[SHORT(mld->v1)];
|
||||
ld->v2 = &vertexes[SHORT(mld->v2)];
|
||||
P_SetLinedefV1(i, SHORT(mld->v1));
|
||||
P_SetLinedefV2(i, SHORT(mld->v2));
|
||||
|
||||
ld->sidenum[0] = SHORT(mld->sidenum[0]);
|
||||
ld->sidenum[1] = SHORT(mld->sidenum[1]);
|
||||
|
@ -1043,6 +1063,30 @@ static void P_LoadLinedefs(UINT8 *data)
|
|||
}
|
||||
}
|
||||
|
||||
static void P_SetSidedefSector(size_t i, UINT16 sector_num)
|
||||
{
|
||||
// cph 2006/09/30 - catch out-of-range sector numbers; use sector 0 instead
|
||||
if (sector_num >= numsectors)
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "P_SetSidedefSector: sidedef %s has out-of-range sector num %u\n", sizeu1(i), sector_num);
|
||||
sector_num = 0;
|
||||
}
|
||||
sides[i].sector = §ors[sector_num];
|
||||
}
|
||||
|
||||
static void P_InitializeSidedef(side_t *sd)
|
||||
{
|
||||
if (!sd->line)
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "P_LoadSidedefs: Sidedef %s is not used by any linedef\n", sizeu1((size_t)(sd - sides)));
|
||||
sd->line = &lines[0];
|
||||
sd->special = sd->line->special;
|
||||
}
|
||||
|
||||
sd->text = NULL;
|
||||
sd->colormap_data = NULL;
|
||||
}
|
||||
|
||||
static void P_LoadSidedefs(UINT8 *data)
|
||||
{
|
||||
mapsidedef_t *msd = (mapsidedef_t*)data;
|
||||
|
@ -1051,22 +1095,28 @@ static void P_LoadSidedefs(UINT8 *data)
|
|||
|
||||
for (i = 0; i < numsides; i++, sd++, msd++)
|
||||
{
|
||||
UINT16 sector_num;
|
||||
boolean isfrontside = !sd->line || sd->line->sidenum[0] == i;
|
||||
INT16 textureoffset = SHORT(msd->textureoffset);
|
||||
boolean isfrontside;
|
||||
|
||||
sd->textureoffset = SHORT(msd->textureoffset)<<FRACBITS;
|
||||
P_InitializeSidedef(sd);
|
||||
|
||||
isfrontside = sd->line->sidenum[0] == i;
|
||||
|
||||
// Repeat count for midtexture
|
||||
if (((sd->line->flags & (ML_TWOSIDED|ML_EFFECT5)) == (ML_TWOSIDED|ML_EFFECT5))
|
||||
&& !(sd->special >= 300 && sd->special < 500)) // exempt linedef exec specials
|
||||
{
|
||||
sd->repeatcnt = (INT16)(((unsigned)textureoffset) >> 12);
|
||||
sd->textureoffset = (((unsigned)textureoffset) & 2047) << FRACBITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
sd->repeatcnt = 0;
|
||||
sd->textureoffset = textureoffset << FRACBITS;
|
||||
}
|
||||
sd->rowoffset = SHORT(msd->rowoffset)<<FRACBITS;
|
||||
|
||||
// cph 2006/09/30 - catch out-of-range sector numbers; use sector 0 instead
|
||||
sector_num = SHORT(msd->sector);
|
||||
if (sector_num >= numsectors)
|
||||
{
|
||||
CONS_Debug(DBG_SETUP, "P_LoadSidedefs: sidedef %s has out-of-range sector num %u\n", sizeu1(i), sector_num);
|
||||
sector_num = 0;
|
||||
}
|
||||
sd->sector = §ors[sector_num];
|
||||
|
||||
sd->colormap_data = NULL;
|
||||
P_SetSidedefSector(i, SHORT(msd->sector));
|
||||
|
||||
// Special info stored in texture fields!
|
||||
switch (sd->special)
|
||||
|
@ -1233,29 +1283,400 @@ static void P_LoadThings(UINT8 *data)
|
|||
mt->z = mt->options; // NiGHTS Hoops use the full flags bits to set the height.
|
||||
else
|
||||
mt->z = mt->options >> ZSHIFT;
|
||||
|
||||
mt->mobj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void P_LoadMapData(const virtres_t *virt)
|
||||
// Stores positions for relevant map data spread through a TEXTMAP.
|
||||
UINT32 mapthingsPos[UINT16_MAX];
|
||||
UINT32 linesPos[UINT16_MAX];
|
||||
UINT32 sidesPos[UINT16_MAX];
|
||||
UINT32 vertexesPos[UINT16_MAX];
|
||||
UINT32 sectorsPos[UINT16_MAX];
|
||||
|
||||
// Determine total amount of map data in TEXTMAP.
|
||||
static boolean TextmapCount(UINT8 *data, size_t size)
|
||||
{
|
||||
virtlump_t* virtvertexes = NULL, * virtsectors = NULL, * virtsidedefs = NULL, * virtlinedefs = NULL, * virtthings = NULL;
|
||||
#ifdef UDMF
|
||||
virtlump_t* textmap = vres_Find(virt, "TEXTMAP");
|
||||
char *tkn = M_GetToken((char *)data);
|
||||
UINT8 brackets = 0;
|
||||
|
||||
nummapthings = 0;
|
||||
numlines = 0;
|
||||
numsides = 0;
|
||||
numvertexes = 0;
|
||||
numsectors = 0;
|
||||
|
||||
// Look for namespace at the beginning.
|
||||
if (!fastcmp(tkn, "namespace"))
|
||||
{
|
||||
Z_Free(tkn);
|
||||
CONS_Alert(CONS_ERROR, "No namespace at beginning of lump!\n");
|
||||
return false;
|
||||
}
|
||||
Z_Free(tkn);
|
||||
|
||||
// Check if namespace is valid.
|
||||
tkn = M_GetToken(NULL);
|
||||
if (!fastcmp(tkn, "srb2"))
|
||||
CONS_Alert(CONS_WARNING, "Invalid namespace '%s', only 'srb2' is supported.\n", tkn);
|
||||
Z_Free(tkn);
|
||||
|
||||
tkn = M_GetToken(NULL);
|
||||
while (tkn && M_GetTokenPos() < size)
|
||||
{
|
||||
// Avoid anything inside bracketed stuff, only look for external keywords.
|
||||
if (brackets)
|
||||
{
|
||||
if (fastcmp(tkn, "}"))
|
||||
brackets--;
|
||||
}
|
||||
else if (fastcmp(tkn, "{"))
|
||||
brackets++;
|
||||
// Check for valid fields.
|
||||
else if (fastcmp(tkn, "thing"))
|
||||
mapthingsPos[nummapthings++] = M_GetTokenPos();
|
||||
else if (fastcmp(tkn, "linedef"))
|
||||
linesPos[numlines++] = M_GetTokenPos();
|
||||
else if (fastcmp(tkn, "sidedef"))
|
||||
sidesPos[numsides++] = M_GetTokenPos();
|
||||
else if (fastcmp(tkn, "vertex"))
|
||||
vertexesPos[numvertexes++] = M_GetTokenPos();
|
||||
else if (fastcmp(tkn, "sector"))
|
||||
sectorsPos[numsectors++] = M_GetTokenPos();
|
||||
else
|
||||
CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn);
|
||||
|
||||
Z_Free(tkn);
|
||||
tkn = M_GetToken(NULL);
|
||||
}
|
||||
|
||||
Z_Free(tkn);
|
||||
|
||||
if (brackets)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Unclosed brackets detected in textmap lump.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ParseTextmapVertexParameter(UINT32 i, char *param, char *val)
|
||||
{
|
||||
if (fastcmp(param, "x"))
|
||||
vertexes[i].x = FLOAT_TO_FIXED(atof(val));
|
||||
else if (fastcmp(param, "y"))
|
||||
vertexes[i].y = FLOAT_TO_FIXED(atof(val));
|
||||
}
|
||||
|
||||
static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
|
||||
{
|
||||
if (fastcmp(param, "heightfloor"))
|
||||
sectors[i].floorheight = atol(val) << FRACBITS;
|
||||
else if (fastcmp(param, "heightceiling"))
|
||||
sectors[i].ceilingheight = atol(val) << FRACBITS;
|
||||
if (fastcmp(param, "texturefloor"))
|
||||
sectors[i].floorpic = P_AddLevelFlat(val, foundflats);
|
||||
else if (fastcmp(param, "textureceiling"))
|
||||
sectors[i].ceilingpic = P_AddLevelFlat(val, foundflats);
|
||||
else if (fastcmp(param, "lightlevel"))
|
||||
sectors[i].lightlevel = atol(val);
|
||||
else if (fastcmp(param, "special"))
|
||||
sectors[i].special = atol(val);
|
||||
else if (fastcmp(param, "id"))
|
||||
sectors[i].tag = atol(val);
|
||||
else if (fastcmp(param, "xpanningfloor"))
|
||||
sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val));
|
||||
else if (fastcmp(param, "ypanningfloor"))
|
||||
sectors[i].floor_yoffs = FLOAT_TO_FIXED(atof(val));
|
||||
else if (fastcmp(param, "xpanningceiling"))
|
||||
sectors[i].ceiling_xoffs = FLOAT_TO_FIXED(atof(val));
|
||||
else if (fastcmp(param, "ypanningceiling"))
|
||||
sectors[i].ceiling_yoffs = FLOAT_TO_FIXED(atof(val));
|
||||
else if (fastcmp(param, "rotationfloor"))
|
||||
sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
|
||||
else if (fastcmp(param, "rotationceiling"))
|
||||
sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
|
||||
}
|
||||
|
||||
static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val)
|
||||
{
|
||||
if (fastcmp(param, "offsetx"))
|
||||
sides[i].textureoffset = atol(val)<<FRACBITS;
|
||||
else if (fastcmp(param, "offsety"))
|
||||
sides[i].rowoffset = atol(val)<<FRACBITS;
|
||||
else if (fastcmp(param, "texturetop"))
|
||||
sides[i].toptexture = R_TextureNumForName(val);
|
||||
else if (fastcmp(param, "texturebottom"))
|
||||
sides[i].bottomtexture = R_TextureNumForName(val);
|
||||
else if (fastcmp(param, "texturemiddle"))
|
||||
sides[i].midtexture = R_TextureNumForName(val);
|
||||
else if (fastcmp(param, "sector"))
|
||||
P_SetSidedefSector(i, atol(val));
|
||||
else if (fastcmp(param, "repeatcnt"))
|
||||
sides[i].repeatcnt = atol(val);
|
||||
}
|
||||
|
||||
static void ParseTextmapLinedefParameter(UINT32 i, char *param, char *val)
|
||||
{
|
||||
if (fastcmp(param, "id"))
|
||||
lines[i].tag = atol(val);
|
||||
else if (fastcmp(param, "special"))
|
||||
lines[i].special = atol(val);
|
||||
else if (fastcmp(param, "v1"))
|
||||
P_SetLinedefV1(i, atol(val));
|
||||
else if (fastcmp(param, "v2"))
|
||||
P_SetLinedefV2(i, atol(val));
|
||||
else if (fastcmp(param, "sidefront"))
|
||||
lines[i].sidenum[0] = atol(val);
|
||||
else if (fastcmp(param, "sideback"))
|
||||
lines[i].sidenum[1] = atol(val);
|
||||
|
||||
// Flags
|
||||
else if (fastcmp(param, "blocking") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_IMPASSIBLE;
|
||||
else if (fastcmp(param, "blockmonsters") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_BLOCKMONSTERS;
|
||||
else if (fastcmp(param, "twosided") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_TWOSIDED;
|
||||
else if (fastcmp(param, "dontpegtop") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_DONTPEGTOP;
|
||||
else if (fastcmp(param, "dontpegbottom") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_DONTPEGBOTTOM;
|
||||
else if (fastcmp(param, "skewtd") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_EFFECT1;
|
||||
else if (fastcmp(param, "noclimb") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_NOCLIMB;
|
||||
else if (fastcmp(param, "noskew") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_EFFECT2;
|
||||
else if (fastcmp(param, "midpeg") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_EFFECT3;
|
||||
else if (fastcmp(param, "midsolid") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_EFFECT4;
|
||||
else if (fastcmp(param, "wrapmidtex") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_EFFECT5;
|
||||
else if (fastcmp(param, "effect6") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_EFFECT6;
|
||||
else if (fastcmp(param, "nonet") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_NONET;
|
||||
else if (fastcmp(param, "netonly") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_NETONLY;
|
||||
else if (fastcmp(param, "bouncy") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_BOUNCY;
|
||||
else if (fastcmp(param, "transfer") && fastcmp("true", val))
|
||||
lines[i].flags |= ML_TFERLINE;
|
||||
}
|
||||
|
||||
static void ParseTextmapThingParameter(UINT32 i, char *param, char *val)
|
||||
{
|
||||
if (fastcmp(param, "x"))
|
||||
mapthings[i].x = atol(val);
|
||||
else if (fastcmp(param, "y"))
|
||||
mapthings[i].y = atol(val);
|
||||
else if (fastcmp(param, "height"))
|
||||
mapthings[i].z = atol(val);
|
||||
else if (fastcmp(param, "angle"))
|
||||
mapthings[i].angle = atol(val);
|
||||
else if (fastcmp(param, "type"))
|
||||
mapthings[i].type = atol(val);
|
||||
|
||||
// Flags
|
||||
else if (fastcmp(param, "extra") && fastcmp("true", val))
|
||||
mapthings[i].options |= MTF_EXTRA;
|
||||
else if (fastcmp(param, "flip") && fastcmp("true", val))
|
||||
mapthings[i].options |= MTF_OBJECTFLIP;
|
||||
else if (fastcmp(param, "special") && fastcmp("true", val))
|
||||
mapthings[i].options |= MTF_OBJECTSPECIAL;
|
||||
else if (fastcmp(param, "ambush") && fastcmp("true", val))
|
||||
mapthings[i].options |= MTF_AMBUSH;
|
||||
}
|
||||
|
||||
/** From a given position table, run a specified parser function through a {}-encapsuled text.
|
||||
*
|
||||
* \param Position of the data to parse, in the textmap.
|
||||
* \param Structure number (mapthings, sectors, ...).
|
||||
* \param Parser function pointer.
|
||||
*/
|
||||
static void TextmapParse(UINT32 dataPos, size_t num, void (*parser)(UINT32, char *, char *))
|
||||
{
|
||||
char *param, *val;
|
||||
|
||||
M_SetTokenPos(dataPos);
|
||||
param = M_GetToken(NULL);
|
||||
if (!fastcmp(param, "{"))
|
||||
{
|
||||
Z_Free(param);
|
||||
CONS_Alert(CONS_WARNING, "Invalid UDMF data capsule!\n");
|
||||
return;
|
||||
}
|
||||
Z_Free(param);
|
||||
|
||||
while (true)
|
||||
{
|
||||
param = M_GetToken(NULL);
|
||||
if (fastcmp(param, "}"))
|
||||
{
|
||||
Z_Free(param);
|
||||
break;
|
||||
}
|
||||
val = M_GetToken(NULL);
|
||||
parser(num, param, val);
|
||||
Z_Free(param);
|
||||
Z_Free(val);
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides a fix to the flat alignment coordinate transform from standard Textmaps.
|
||||
*/
|
||||
static void TextmapFixFlatOffsets(sector_t *sec)
|
||||
{
|
||||
if (sec->floorpic_angle)
|
||||
{
|
||||
fixed_t pc = FINECOSINE(sec->floorpic_angle>>ANGLETOFINESHIFT);
|
||||
fixed_t ps = FINESINE (sec->floorpic_angle>>ANGLETOFINESHIFT);
|
||||
fixed_t xoffs = sec->floor_xoffs;
|
||||
fixed_t yoffs = sec->floor_yoffs;
|
||||
sec->floor_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE);
|
||||
sec->floor_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE);
|
||||
}
|
||||
|
||||
if (sec->ceilingpic_angle)
|
||||
{
|
||||
fixed_t pc = FINECOSINE(sec->ceilingpic_angle>>ANGLETOFINESHIFT);
|
||||
fixed_t ps = FINESINE (sec->ceilingpic_angle>>ANGLETOFINESHIFT);
|
||||
fixed_t xoffs = sec->ceiling_xoffs;
|
||||
fixed_t yoffs = sec->ceiling_yoffs;
|
||||
sec->ceiling_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE);
|
||||
sec->ceiling_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/** Loads the textmap data, after obtaining the elements count and allocating their respective space.
|
||||
*/
|
||||
static void P_LoadTextmap(void)
|
||||
{
|
||||
UINT32 i;
|
||||
|
||||
vertex_t *vt;
|
||||
sector_t *sc;
|
||||
line_t *ld;
|
||||
side_t *sd;
|
||||
mapthing_t *mt;
|
||||
|
||||
CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n");
|
||||
|
||||
/// Given the UDMF specs, some fields are given a default value.
|
||||
/// If an element's field has a default value set, it is omitted
|
||||
/// from the textmap, and therefore we have to account for it by
|
||||
/// preemptively setting that value beforehand.
|
||||
|
||||
for (i = 0, vt = vertexes; i < numvertexes; i++, vt++)
|
||||
{
|
||||
// Defaults.
|
||||
vt->x = vt->y = INT32_MAX;
|
||||
vt->z = 0;
|
||||
|
||||
TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter);
|
||||
|
||||
if (vt->x == INT32_MAX)
|
||||
I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i));
|
||||
if (vt->y == INT32_MAX)
|
||||
I_Error("P_LoadTextmap: vertex %s has no y value set!\n", sizeu1(i));
|
||||
}
|
||||
|
||||
for (i = 0, sc = sectors; i < numsectors; i++, sc++)
|
||||
{
|
||||
// Defaults.
|
||||
sc->floorheight = 0;
|
||||
sc->ceilingheight = 0;
|
||||
|
||||
sc->floorpic = 0;
|
||||
sc->ceilingpic = 0;
|
||||
|
||||
sc->lightlevel = 255;
|
||||
|
||||
sc->special = 0;
|
||||
sc->tag = 0;
|
||||
|
||||
sc->floor_xoffs = sc->floor_yoffs = 0;
|
||||
sc->ceiling_xoffs = sc->ceiling_yoffs = 0;
|
||||
|
||||
sc->floorpic_angle = sc->ceilingpic_angle = 0;
|
||||
|
||||
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
|
||||
P_InitializeSector(sc);
|
||||
TextmapFixFlatOffsets(sc);
|
||||
}
|
||||
|
||||
for (i = 0, ld = lines; i < numlines; i++, ld++)
|
||||
{
|
||||
// Defaults.
|
||||
ld->v1 = ld->v2 = NULL;
|
||||
ld->flags = 0;
|
||||
ld->special = 0;
|
||||
ld->tag = 0;
|
||||
ld->sidenum[0] = 0xffff;
|
||||
ld->sidenum[1] = 0xffff;
|
||||
|
||||
TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter);
|
||||
|
||||
if (!ld->v1)
|
||||
I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i));
|
||||
if (!ld->v2)
|
||||
I_Error("P_LoadTextmap: linedef %s has no v2 value set!\n", sizeu1(i));
|
||||
if (ld->sidenum[0] == 0xffff)
|
||||
I_Error("P_LoadTextmap: linedef %s has no sidefront value set!\n", sizeu1(i));
|
||||
|
||||
P_InitializeLinedef(ld);
|
||||
}
|
||||
|
||||
for (i = 0, sd = sides; i < numsides; i++, sd++)
|
||||
{
|
||||
// Defaults.
|
||||
sd->textureoffset = 0;
|
||||
sd->rowoffset = 0;
|
||||
sd->toptexture = R_TextureNumForName("-");
|
||||
sd->midtexture = R_TextureNumForName("-");
|
||||
sd->bottomtexture = R_TextureNumForName("-");
|
||||
sd->sector = NULL;
|
||||
sd->repeatcnt = 0;
|
||||
|
||||
TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter);
|
||||
|
||||
if (!sd->sector)
|
||||
I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i));
|
||||
|
||||
P_InitializeSidedef(sd);
|
||||
}
|
||||
|
||||
for (i = 0, mt = mapthings; i < nummapthings; i++, mt++)
|
||||
{
|
||||
// Defaults.
|
||||
mt->x = mt->y = 0;
|
||||
mt->angle = 0;
|
||||
mt->type = 0;
|
||||
mt->options = 0;
|
||||
mt->z = 0;
|
||||
mt->extrainfo = 0;
|
||||
mt->mobj = NULL;
|
||||
|
||||
TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean P_LoadMapData(const virtres_t *virt)
|
||||
{
|
||||
virtlump_t *virtvertexes = NULL, *virtsectors = NULL, *virtsidedefs = NULL, *virtlinedefs = NULL, *virtthings = NULL;
|
||||
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
|
||||
|
||||
// Count map data.
|
||||
if (textmap)
|
||||
if (textmap) // Count how many entries for each type we got in textmap.
|
||||
{
|
||||
nummapthings = 0;
|
||||
numlines = 0;
|
||||
numsides = 0;
|
||||
numvertexes = 0;
|
||||
numsectors = 0;
|
||||
|
||||
// Count how many entries for each type we got in textmap.
|
||||
//TextmapCount(vtextmap->data, vtextmap->size);
|
||||
if (!TextmapCount(textmap->data, textmap->size))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
virtthings = vres_Find(virt, "THINGS");
|
||||
virtvertexes = vres_Find(virt, "VERTEXES");
|
||||
|
@ -1305,15 +1726,11 @@ static void P_LoadMapData(const virtres_t *virt)
|
|||
|
||||
numlevelflats = 0;
|
||||
|
||||
#ifdef UDMF
|
||||
// Load map data.
|
||||
if (textmap)
|
||||
{
|
||||
|
||||
}
|
||||
P_LoadTextmap();
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Strict map data
|
||||
P_LoadVertices(virtvertexes->data);
|
||||
P_LoadSectors(virtsectors->data);
|
||||
P_LoadLinedefs(virtlinedefs->data);
|
||||
|
@ -1341,6 +1758,8 @@ static void P_LoadMapData(const virtres_t *virt)
|
|||
memcpy(spawnsectors, sectors, numsectors * sizeof (*sectors));
|
||||
memcpy(spawnlines, lines, numlines * sizeof (*lines));
|
||||
memcpy(spawnsides, sides, numsides * sizeof (*sides));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void P_InitializeSubsector(subsector_t *ss)
|
||||
|
@ -1421,10 +1840,13 @@ static inline float P_SegLengthFloat(seg_t *seg)
|
|||
|
||||
static void P_InitializeSeg(seg_t *seg)
|
||||
{
|
||||
seg->sidedef = &sides[seg->linedef->sidenum[seg->side]];
|
||||
if (seg->linedef)
|
||||
{
|
||||
seg->sidedef = &sides[seg->linedef->sidenum[seg->side]];
|
||||
|
||||
seg->frontsector = seg->sidedef->sector;
|
||||
seg->backsector = (seg->linedef->flags & ML_TWOSIDED) ? sides[seg->linedef->sidenum[seg->side ^ 1]].sector : NULL;
|
||||
seg->frontsector = seg->sidedef->sector;
|
||||
seg->backsector = (seg->linedef->flags & ML_TWOSIDED) ? sides[seg->linedef->sidenum[seg->side ^ 1]].sector : NULL;
|
||||
}
|
||||
|
||||
#ifdef HWRENDER
|
||||
seg->pv1 = seg->pv2 = NULL;
|
||||
|
@ -1607,20 +2029,21 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
|
|||
case NT_XGL3:
|
||||
for (m = 0; m < subsectors[i].numlines; m++, k++)
|
||||
{
|
||||
UINT32 vertexnum = READUINT32((*data));
|
||||
UINT16 linenum;
|
||||
UINT32 vert = READUINT32((*data));
|
||||
|
||||
segs[k].v1 = &vertexes[vert];
|
||||
if (m == 0)
|
||||
segs[k + subsectors[i].numlines - 1].v2 = &vertexes[vert];
|
||||
else
|
||||
segs[k - 1].v2 = segs[k].v1;
|
||||
if (vertexnum >= numvertexes)
|
||||
I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid vertex %d!\n", sizeu1(k), m, vertexnum);
|
||||
|
||||
(*data) += 4; // partner, can be ignored by software renderer
|
||||
segs[k - 1 + ((m == 0) ? subsectors[i].numlines : 0)].v2 = segs[k].v1 = &vertexes[vertexnum];
|
||||
|
||||
READUINT32((*data)); // partner, can be ignored by software renderer
|
||||
if (nodetype == NT_XGL3)
|
||||
(*data) += 2; // Line number is 32-bit in XGL3, but we're limited to 16 bits.
|
||||
READUINT16((*data)); // Line number is 32-bit in XGL3, but we're limited to 16 bits.
|
||||
|
||||
linenum = READUINT16((*data));
|
||||
if (linenum != 0xFFFF && linenum >= numlines)
|
||||
I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid linedef %d!\n", sizeu1(k), m, linenum);
|
||||
segs[k].glseg = (linenum == 0xFFFF);
|
||||
segs[k].linedef = (linenum == 0xFFFF) ? NULL : &lines[linenum];
|
||||
segs[k].side = READUINT8((*data));
|
||||
|
@ -1630,9 +2053,20 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
|
|||
case NT_XNOD:
|
||||
for (m = 0; m < subsectors[i].numlines; m++, k++)
|
||||
{
|
||||
segs[k].v1 = &vertexes[READUINT32((*data))];
|
||||
segs[k].v2 = &vertexes[READUINT32((*data))];
|
||||
segs[k].linedef = &lines[READUINT16((*data))];
|
||||
UINT32 v1num = READUINT32((*data));
|
||||
UINT32 v2num = READUINT32((*data));
|
||||
UINT16 linenum = READUINT16((*data));
|
||||
|
||||
if (v1num >= numvertexes)
|
||||
I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid v1 %d!\n", sizeu1(k), m, v1num);
|
||||
if (v2num >= numvertexes)
|
||||
I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid v2 %d!\n", sizeu1(k), m, v2num);
|
||||
if (linenum >= numlines)
|
||||
I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid linedef %d!\n", sizeu1(k), m, linenum);
|
||||
|
||||
segs[k].v1 = &vertexes[v1num];
|
||||
segs[k].v2 = &vertexes[v2num];
|
||||
segs[k].linedef = &lines[linenum];
|
||||
segs[k].side = READUINT8((*data));
|
||||
segs[k].glseg = false;
|
||||
}
|
||||
|
@ -1649,7 +2083,8 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
|
|||
vertex_t *v2 = seg->v2;
|
||||
P_InitializeSeg(seg);
|
||||
seg->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y);
|
||||
seg->offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y);
|
||||
if (seg->linedef)
|
||||
segs[i].offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2091,16 +2526,6 @@ static void P_ProcessLinedefsWithSidedefs(void)
|
|||
ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here
|
||||
ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0;
|
||||
|
||||
// Repeat count for midtexture
|
||||
if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != 0xffff)
|
||||
&& !(ld->special >= 300 && ld->special < 500)) // exempt linedef exec specials
|
||||
{
|
||||
sides[ld->sidenum[0]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) >> 12);
|
||||
sides[ld->sidenum[0]].textureoffset = (((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) & 2047) << FRACBITS;
|
||||
sides[ld->sidenum[1]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[1]].textureoffset >> FRACBITS) >> 12);
|
||||
sides[ld->sidenum[1]].textureoffset = (((unsigned)sides[ld->sidenum[1]].textureoffset >> FRACBITS) & 2047) << FRACBITS;
|
||||
}
|
||||
|
||||
// Compile linedef 'text' from both sidedefs 'text' for appropriate specials.
|
||||
switch(ld->special)
|
||||
{
|
||||
|
@ -2123,69 +2548,6 @@ static void P_ProcessLinedefsWithSidedefs(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void P_CompressSidedefs(void)
|
||||
{
|
||||
side_t *newsides;
|
||||
size_t numnewsides = 0;
|
||||
size_t z;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < numsides; i++)
|
||||
{
|
||||
size_t j, k;
|
||||
line_t *ld;
|
||||
|
||||
if (!sides[i].sector)
|
||||
continue;
|
||||
|
||||
for (k = numlines, ld = lines; k--; ld++)
|
||||
{
|
||||
if (ld->sidenum[0] == i)
|
||||
ld->sidenum[0] = (UINT16)numnewsides;
|
||||
|
||||
if (ld->sidenum[1] == i)
|
||||
ld->sidenum[1] = (UINT16)numnewsides;
|
||||
}
|
||||
|
||||
for (j = i + 1; j < numsides; j++)
|
||||
{
|
||||
if (!sides[j].sector)
|
||||
continue;
|
||||
|
||||
if (!memcmp(&sides[i], &sides[j], sizeof(side_t)))
|
||||
{
|
||||
// Find the linedefs that belong to this one
|
||||
for (k = numlines, ld = lines; k--; ld++)
|
||||
{
|
||||
if (ld->sidenum[0] == j)
|
||||
ld->sidenum[0] = (UINT16)numnewsides;
|
||||
|
||||
if (ld->sidenum[1] == j)
|
||||
ld->sidenum[1] = (UINT16)numnewsides;
|
||||
}
|
||||
sides[j].sector = NULL; // Flag for deletion
|
||||
}
|
||||
}
|
||||
numnewsides++;
|
||||
}
|
||||
|
||||
// We're loading crap into this block anyhow, so no point in zeroing it out.
|
||||
newsides = Z_Malloc(numnewsides*sizeof(*newsides), PU_LEVEL, NULL);
|
||||
|
||||
// Copy the sides to their new block of memory.
|
||||
for (i = 0, z = 0; i < numsides; i++)
|
||||
{
|
||||
if (sides[i].sector)
|
||||
M_Memcpy(&newsides[z++], &sides[i], sizeof(side_t));
|
||||
}
|
||||
|
||||
CONS_Debug(DBG_SETUP, "P_CompressSidedefs: Old sides is %s, new sides is %s\n", sizeu1(numsides), sizeu1(numnewsides));
|
||||
|
||||
Z_Free(sides);
|
||||
sides = newsides;
|
||||
numsides = numnewsides;
|
||||
}
|
||||
|
||||
//
|
||||
// P_LinkMapData
|
||||
// Builds sector line lists and subsector sector numbers.
|
||||
|
@ -2310,47 +2672,54 @@ static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock)
|
|||
|
||||
static void P_MakeMapMD5(virtres_t *virt, void *dest)
|
||||
{
|
||||
unsigned char linemd5[16];
|
||||
unsigned char sectormd5[16];
|
||||
unsigned char thingmd5[16];
|
||||
unsigned char sidedefmd5[16];
|
||||
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
|
||||
unsigned char resmd5[16];
|
||||
UINT8 i;
|
||||
|
||||
// Create a hash for the current map
|
||||
// get the actual lumps!
|
||||
virtlump_t *virtlines = vres_Find(virt, "LINEDEFS");
|
||||
virtlump_t *virtsectors = vres_Find(virt, "SECTORS");
|
||||
virtlump_t *virtmthings = vres_Find(virt, "THINGS");
|
||||
virtlump_t *virtsides = vres_Find(virt, "SIDEDEFS");
|
||||
if (textmap)
|
||||
P_MakeBufferMD5((char*)textmap->data, textmap->size, resmd5);
|
||||
else
|
||||
{
|
||||
unsigned char linemd5[16];
|
||||
unsigned char sectormd5[16];
|
||||
unsigned char thingmd5[16];
|
||||
unsigned char sidedefmd5[16];
|
||||
UINT8 i;
|
||||
|
||||
P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5);
|
||||
P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5);
|
||||
P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5);
|
||||
P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5);
|
||||
// Create a hash for the current map
|
||||
// get the actual lumps!
|
||||
virtlump_t* virtlines = vres_Find(virt, "LINEDEFS");
|
||||
virtlump_t* virtsectors = vres_Find(virt, "SECTORS");
|
||||
virtlump_t* virtmthings = vres_Find(virt, "THINGS");
|
||||
virtlump_t* virtsides = vres_Find(virt, "SIDEDEFS");
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF;
|
||||
P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5);
|
||||
P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5);
|
||||
P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5);
|
||||
P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF;
|
||||
}
|
||||
|
||||
M_Memcpy(dest, &resmd5, 16);
|
||||
}
|
||||
|
||||
static void P_LoadMapFromFile(void)
|
||||
static boolean P_LoadMapFromFile(void)
|
||||
{
|
||||
virtres_t *virt = vres_GetMap(lastloadedmaplumpnum);
|
||||
|
||||
P_LoadMapData(virt);
|
||||
if (!P_LoadMapData(virt))
|
||||
return false;
|
||||
P_LoadMapBSP(virt);
|
||||
P_LoadMapLUT(virt);
|
||||
|
||||
P_ProcessLinedefsWithSidedefs();
|
||||
if (M_CheckParm("-compress"))
|
||||
P_CompressSidedefs();
|
||||
P_LinkMapData();
|
||||
|
||||
P_MakeMapMD5(virt, &mapmd5);
|
||||
|
||||
vres_Free(virt);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2446,7 +2815,7 @@ static void P_InitLevelSettings(void)
|
|||
// earthquake camera
|
||||
memset(&quake,0,sizeof(struct quake));
|
||||
|
||||
if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2)
|
||||
if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -2464,7 +2833,7 @@ static void P_InitLevelSettings(void)
|
|||
{
|
||||
G_PlayerReborn(i, true);
|
||||
|
||||
if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0))
|
||||
if (canresetlives && (netgame || multiplayer) && playeringame[i] && (G_CompetitionGametype() || players[i].lives <= 0))
|
||||
{
|
||||
// In Co-Op, replenish a user's lives if they are depleted.
|
||||
players[i].lives = cv_startinglives.value;
|
||||
|
@ -2754,17 +3123,10 @@ static void P_SetupCamera(void)
|
|||
{
|
||||
mapthing_t *thing;
|
||||
|
||||
switch (gametype)
|
||||
{
|
||||
case GT_MATCH:
|
||||
case GT_TAG:
|
||||
if (gametyperules & GTR_DEATHMATCHSTARTS)
|
||||
thing = deathmatchstarts[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
else
|
||||
thing = playerstarts[0];
|
||||
break;
|
||||
}
|
||||
|
||||
if (thing)
|
||||
{
|
||||
|
@ -2979,7 +3341,7 @@ static void P_InitGametype(void)
|
|||
P_InitPlayers();
|
||||
|
||||
// restore time in netgame (see also g_game.c)
|
||||
if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2)
|
||||
if ((netgame || multiplayer) && G_GametypeUsesCoopStarposts() && cv_coopstarposts.value == 2)
|
||||
{
|
||||
// is this a hack? maybe
|
||||
tic_t maxstarposttime = 0;
|
||||
|
@ -3023,6 +3385,7 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
|
||||
// This is needed. Don't touch.
|
||||
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
|
||||
gametyperules = gametypedefaultrules[gametype];
|
||||
|
||||
CON_Drawer(); // let the user know what we are going to do
|
||||
I_FinishUpdate(); // page flip or blit buffer
|
||||
|
@ -3189,7 +3552,7 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
// internal game map
|
||||
maplumpname = G_BuildMapName(gamemap);
|
||||
lastloadedmaplumpnum = W_CheckNumForName(maplumpname);
|
||||
if (lastloadedmaplumpnum == INT16_MAX)
|
||||
if (lastloadedmaplumpnum == LUMPERROR)
|
||||
I_Error("Map %s not found.\n", maplumpname);
|
||||
|
||||
R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette);
|
||||
|
@ -3202,8 +3565,8 @@ boolean P_LoadLevel(boolean fromnetsave)
|
|||
|
||||
P_MapStart();
|
||||
|
||||
if (lastloadedmaplumpnum)
|
||||
P_LoadMapFromFile();
|
||||
if (!P_LoadMapFromFile())
|
||||
return false;
|
||||
|
||||
// init gravity, tag lists,
|
||||
// anything that P_ResetDynamicSlopes/P_LoadThings needs to know
|
||||
|
|
|
@ -52,9 +52,6 @@ mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs
|
|||
// Amount (dx, dy) vector linedef is shifted right to get scroll amount
|
||||
#define SCROLL_SHIFT 5
|
||||
|
||||
// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize.
|
||||
#define MAXFLATSIZE (2048<<FRACBITS)
|
||||
|
||||
/** Animated texture descriptor
|
||||
* This keeps track of an animated texture or an animated flat.
|
||||
* \sa P_UpdateSpecials, P_InitPicAnims, animdef_t
|
||||
|
|
|
@ -27,6 +27,9 @@ extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs
|
|||
//
|
||||
#define GETSECSPECIAL(i,j) ((i >> ((j-1)*4))&15)
|
||||
|
||||
// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize.
|
||||
#define MAXFLATSIZE (2048<<FRACBITS)
|
||||
|
||||
// at game start
|
||||
void P_InitPicAnims(void);
|
||||
|
||||
|
|
58
src/p_user.c
58
src/p_user.c
|
@ -349,6 +349,11 @@ void P_GiveEmerald(boolean spawnObj)
|
|||
continue;
|
||||
P_SetTarget(&emmo->target, players[i].mo);
|
||||
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
|
||||
|
||||
// Make sure we're not being carried before our tracer is changed
|
||||
if (players[i].powers[pw_carry] != CR_NIGHTSMODE)
|
||||
players[i].powers[pw_carry] = CR_NONE;
|
||||
|
||||
P_SetTarget(&players[i].mo->tracer, emmo);
|
||||
|
||||
if (pnum == 255)
|
||||
|
@ -1232,13 +1237,13 @@ void P_GivePlayerLives(player_t *player, INT32 numlives)
|
|||
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
if (player->lives == INFLIVES || (gametype != GT_COOP && gametype != GT_COMPETITION))
|
||||
if (player->lives == INFLIVES || !(gametyperules & GTR_LIVES))
|
||||
{
|
||||
P_GivePlayerRings(player, 100*numlives);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0)
|
||||
if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0)
|
||||
{
|
||||
P_GivePlayerRings(player, 100*numlives);
|
||||
if (player->lives - prevlives >= numlives)
|
||||
|
@ -1269,7 +1274,7 @@ docooprespawn:
|
|||
|
||||
void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound)
|
||||
{
|
||||
if (!((netgame || multiplayer) && gametype == GT_COOP))
|
||||
if (!((netgame || multiplayer) && G_GametypeUsesCoopLives()))
|
||||
{
|
||||
P_GivePlayerLives(player, numlives);
|
||||
if (sound)
|
||||
|
@ -1397,7 +1402,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
|
|||
player->score = MAXSCORE;
|
||||
|
||||
// check for extra lives every 50000 pts
|
||||
if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametype == GT_COMPETITION || gametype == GT_COOP))
|
||||
if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametyperules & GTR_LIVES))
|
||||
{
|
||||
P_GivePlayerLives(player, (player->score/50000) - (oldscore/50000));
|
||||
P_PlayLivesJingle(player);
|
||||
|
@ -7791,6 +7796,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle)
|
|||
flame->fuse = TICRATE*7; // takes about an extra second to hit the ground
|
||||
flame->destscale = player->mo->scale;
|
||||
P_SetScale(flame, player->mo->scale);
|
||||
flame->flags2 = (flame->flags2 & ~MF2_OBJECTFLIP)|(player->mo->flags2 & MF2_OBJECTFLIP);
|
||||
flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP);
|
||||
P_InstaThrust(flame, flame->angle, FixedMul(3*FRACUNIT, flame->scale));
|
||||
P_SetObjectMomZ(flame, 3*FRACUNIT, false);
|
||||
|
@ -9460,7 +9466,7 @@ boolean P_GetLives(player_t *player)
|
|||
{
|
||||
INT32 i, maxlivesplayer = -1, livescheck = 1;
|
||||
if (!(netgame || multiplayer)
|
||||
|| (gametype != GT_COOP)
|
||||
|| !G_GametypeUsesCoopLives()
|
||||
|| (player->lives == INFLIVES))
|
||||
return true;
|
||||
|
||||
|
@ -9609,7 +9615,7 @@ static void P_DeathThink(player_t *player)
|
|||
player->playerstate = PST_REBORN;
|
||||
else if ((player->lives > 0 || j != MAXPLAYERS) && !(!(netgame || multiplayer) && G_IsSpecialStage(gamemap))) // Don't allow "click to respawn" in special stages!
|
||||
{
|
||||
if (gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2)
|
||||
if (G_GametypeUsesCoopStarposts() && (netgame || multiplayer) && cv_coopstarposts.value == 2)
|
||||
{
|
||||
P_ConsiderAllGone();
|
||||
if ((player->deadtimer > TICRATE<<1) || ((cmd->buttons & BT_JUMP) && (player->deadtimer > TICRATE)))
|
||||
|
@ -9624,19 +9630,22 @@ static void P_DeathThink(player_t *player)
|
|||
// Respawn with jump button, force respawn time (3 second default, cheat protected) in shooter modes.
|
||||
if (cmd->buttons & BT_JUMP)
|
||||
{
|
||||
if (gametype != GT_COOP && player->spectator)
|
||||
// You're a spectator, so respawn right away.
|
||||
if ((gametyperules & GTR_SPECTATORS) && player->spectator)
|
||||
player->playerstate = PST_REBORN;
|
||||
else switch(gametype) {
|
||||
case GT_COOP:
|
||||
case GT_COMPETITION:
|
||||
case GT_RACE:
|
||||
if (player->deadtimer > TICRATE)
|
||||
player->playerstate = PST_REBORN;
|
||||
break;
|
||||
default:
|
||||
if (player->deadtimer > cv_respawntime.value*TICRATE)
|
||||
player->playerstate = PST_REBORN;
|
||||
break;
|
||||
else
|
||||
{
|
||||
// Give me one second.
|
||||
INT32 respawndelay = TICRATE;
|
||||
|
||||
// Non-platform gametypes
|
||||
if (gametyperules & GTR_RESPAWNDELAY)
|
||||
respawndelay = (cv_respawntime.value*TICRATE);
|
||||
|
||||
// You've been dead for enough time.
|
||||
// You may now respawn.
|
||||
if (player->deadtimer > respawndelay)
|
||||
player->playerstate = PST_REBORN;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9650,7 +9659,7 @@ static void P_DeathThink(player_t *player)
|
|||
INT32 i, deadtimercheck = INT32_MAX;
|
||||
|
||||
// In a net/multiplayer game, and out of lives
|
||||
if (gametype == GT_COMPETITION)
|
||||
if (G_CompetitionGametype())
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -11477,7 +11486,10 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume)
|
|||
if (panim == PA_WALK)
|
||||
{
|
||||
if (stat != fume->info->spawnstate)
|
||||
{
|
||||
fume->threshold = 0;
|
||||
P_SetMobjState(fume, fume->info->spawnstate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -11508,6 +11520,12 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume)
|
|||
if (underwater)
|
||||
{
|
||||
fume->frame = (fume->frame & FF_FRAMEMASK) | FF_ANIMATE | (P_RandomRange(0, 9) * FF_TRANS10);
|
||||
fume->threshold = 1;
|
||||
}
|
||||
else if (fume->threshold)
|
||||
{
|
||||
fume->frame = (fume->frame & FF_FRAMEMASK) | fume->state->frame;
|
||||
fume->threshold = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11767,7 +11785,7 @@ void P_PlayerThink(player_t *player)
|
|||
#else
|
||||
if (player->spectator &&
|
||||
#endif
|
||||
gametype == GT_COOP && (netgame || multiplayer) && cv_coopstarposts.value == 2)
|
||||
G_GametypeUsesCoopStarposts() && (netgame || multiplayer) && cv_coopstarposts.value == 2)
|
||||
P_ConsiderAllGone();
|
||||
|
||||
if (player->playerstate == PST_DEAD)
|
||||
|
|
42
src/sounds.c
42
src/sounds.c
|
@ -187,6 +187,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"shield", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pity Shield"}, // generic GET!
|
||||
{"wirlsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Whirlwind Shield"}, // Whirlwind GET!
|
||||
{"forcsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Force Shield"}, // Force GET!
|
||||
{"frcssg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Weak Force Shield"}, // Force GET...? (consider making a custom shield with this instead of a single-hit force shield!)
|
||||
{"elemsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Elemental Shield"}, // Elemental GET!
|
||||
{"armasg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon Shield"}, // Armaggeddon GET!
|
||||
{"attrsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction Shield"}, // Attract GET!
|
||||
|
@ -220,6 +221,9 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"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!"},
|
||||
{"iceb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ice crack"},
|
||||
{"shattr", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Shattering"},
|
||||
{"antiri", true, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Depletion"},
|
||||
|
||||
// Menu, interface
|
||||
{"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"},
|
||||
|
@ -233,6 +237,9 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"wepchg", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Weapon change"}, // Weapon switch is identical to menu for now
|
||||
{"wtrdng", true, 212, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, // make sure you can hear the DING DING! Tails 03-08-2000
|
||||
{"zelda", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"},
|
||||
{"adderr", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Error"},
|
||||
{"notadd", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Reject"},
|
||||
{"addfil", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accept"},
|
||||
|
||||
// NiGHTS
|
||||
{"ideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Success"},
|
||||
|
@ -427,24 +434,9 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"s25e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s25f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s260", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s261", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s262", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s263", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s264", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s265", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s266", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s267", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s268", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s269", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s26a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s26b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s26c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s26d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s26e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s26f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"s270", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
|
||||
// S3&K sounds
|
||||
{"s3k2b", true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Emerald"}, // Got Emerald!
|
||||
{"s3k33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // stereo in original game, identical to latter
|
||||
{"s3k34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // mono in original game, identical to previous
|
||||
{"s3k35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"},
|
||||
|
@ -566,6 +558,21 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"s3ka9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"},
|
||||
{"s3kaa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"},
|
||||
{"s3kab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kab1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kab2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kab3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kab4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kab5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kab6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kab7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kab8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kab9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kaba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kabb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kabc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kabd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kabe", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kabf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"},
|
||||
{"s3kac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Continue"},
|
||||
{"s3kad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "GO!"},
|
||||
{"s3kae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pinball flipper"},
|
||||
|
@ -604,7 +611,8 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Revving up"}, // ditto
|
||||
{"s3kc6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"},
|
||||
{"s3kc6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, // ditto
|
||||
{"s3kc7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"},
|
||||
{"s3kc7s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"},
|
||||
{"s3kc7l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, // ditto
|
||||
{"s3kc8s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding"},
|
||||
{"s3kc8l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding"}, // ditto
|
||||
{"s3kc9s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Swinging"},
|
||||
|
|
42
src/sounds.h
42
src/sounds.h
|
@ -236,6 +236,7 @@ typedef enum
|
|||
sfx_shield,
|
||||
sfx_wirlsg,
|
||||
sfx_forcsg,
|
||||
sfx_frcssg,
|
||||
sfx_elemsg,
|
||||
sfx_armasg,
|
||||
sfx_attrsg,
|
||||
|
@ -269,6 +270,9 @@ typedef enum
|
|||
sfx_sprong,
|
||||
sfx_lvfal1,
|
||||
sfx_pscree,
|
||||
sfx_iceb,
|
||||
sfx_shattr,
|
||||
sfx_antiri,
|
||||
|
||||
// Menu, interface
|
||||
sfx_chchng,
|
||||
|
@ -282,6 +286,9 @@ typedef enum
|
|||
sfx_wepchg,
|
||||
sfx_wtrdng,
|
||||
sfx_zelda,
|
||||
sfx_adderr,
|
||||
sfx_notadd,
|
||||
sfx_addfil,
|
||||
|
||||
// NiGHTS
|
||||
sfx_ideya,
|
||||
|
@ -476,24 +483,9 @@ typedef enum
|
|||
sfx_s25e,
|
||||
sfx_s25f,
|
||||
sfx_s260,
|
||||
sfx_s261,
|
||||
sfx_s262,
|
||||
sfx_s263,
|
||||
sfx_s264,
|
||||
sfx_s265,
|
||||
sfx_s266,
|
||||
sfx_s267,
|
||||
sfx_s268,
|
||||
sfx_s269,
|
||||
sfx_s26a,
|
||||
sfx_s26b,
|
||||
sfx_s26c,
|
||||
sfx_s26d,
|
||||
sfx_s26e,
|
||||
sfx_s26f,
|
||||
sfx_s270,
|
||||
|
||||
// S3&K sounds
|
||||
sfx_s3k2b,
|
||||
sfx_s3k33,
|
||||
sfx_s3k34,
|
||||
sfx_s3k35,
|
||||
|
@ -615,6 +607,21 @@ typedef enum
|
|||
sfx_s3ka9,
|
||||
sfx_s3kaa,
|
||||
sfx_s3kab,
|
||||
sfx_s3kab1,
|
||||
sfx_s3kab2,
|
||||
sfx_s3kab3,
|
||||
sfx_s3kab4,
|
||||
sfx_s3kab5,
|
||||
sfx_s3kab6,
|
||||
sfx_s3kab7,
|
||||
sfx_s3kab8,
|
||||
sfx_s3kab9,
|
||||
sfx_s3kaba,
|
||||
sfx_s3kabb,
|
||||
sfx_s3kabc,
|
||||
sfx_s3kabd,
|
||||
sfx_s3kabe,
|
||||
sfx_s3kabf,
|
||||
sfx_s3kac,
|
||||
sfx_s3kad,
|
||||
sfx_s3kae,
|
||||
|
@ -653,7 +660,8 @@ typedef enum
|
|||
sfx_s3kc5l,
|
||||
sfx_s3kc6s,
|
||||
sfx_s3kc6l,
|
||||
sfx_s3kc7,
|
||||
sfx_s3kc7s,
|
||||
sfx_s3kc7l,
|
||||
sfx_s3kc8s,
|
||||
sfx_s3kc8l,
|
||||
sfx_s3kc9s,
|
||||
|
|
148
src/st_stuff.c
148
src/st_stuff.c
|
@ -694,7 +694,7 @@ static void ST_drawTime(void)
|
|||
else
|
||||
{
|
||||
// Counting down the hidetime?
|
||||
if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime <= (hidetime*TICRATE)))
|
||||
if ((gametyperules & GTR_STARTCOUNTDOWN) && (stplyr->realtime <= (hidetime*TICRATE)))
|
||||
{
|
||||
tics = (hidetime*TICRATE - stplyr->realtime);
|
||||
if (tics < 3*TICRATE)
|
||||
|
@ -705,7 +705,7 @@ static void ST_drawTime(void)
|
|||
else
|
||||
{
|
||||
// Hidetime finish!
|
||||
if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime < ((hidetime+1)*TICRATE)))
|
||||
if ((gametyperules & GTR_STARTCOUNTDOWN) && (stplyr->realtime < ((hidetime+1)*TICRATE)))
|
||||
ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime);
|
||||
|
||||
// Time limit?
|
||||
|
@ -723,7 +723,7 @@ static void ST_drawTime(void)
|
|||
downwards = true;
|
||||
}
|
||||
// Post-hidetime normal.
|
||||
else if (gametyperules & GTR_TAG)
|
||||
else if (gametyperules & GTR_STARTCOUNTDOWN)
|
||||
tics = stplyr->realtime - hidetime*TICRATE;
|
||||
// "Shadow! What are you doing? Hurry and get back here
|
||||
// right now before the island blows up with you on it!"
|
||||
|
@ -845,69 +845,13 @@ static void ST_drawLivesArea(void)
|
|||
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, faceprefix[stplyr->skin], colormap);
|
||||
}
|
||||
|
||||
// Lives number
|
||||
// Metal Sonic recording
|
||||
if (metalrecording)
|
||||
{
|
||||
if (((2*leveltime)/TICRATE) & 1)
|
||||
V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8,
|
||||
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_REDMAP|V_HUDTRANS, "REC");
|
||||
}
|
||||
else if (G_GametypeUsesLives() || gametype == GT_RACE)
|
||||
{
|
||||
// x
|
||||
V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10,
|
||||
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, stlivex);
|
||||
|
||||
// lives number
|
||||
if (gametype == GT_RACE)
|
||||
{
|
||||
livescount = INFLIVES;
|
||||
notgreyedout = true;
|
||||
}
|
||||
else if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 3)
|
||||
{
|
||||
INT32 i;
|
||||
livescount = 0;
|
||||
notgreyedout = (stplyr->lives > 0);
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].lives < 1)
|
||||
continue;
|
||||
|
||||
if (players[i].lives > 1)
|
||||
notgreyedout = true;
|
||||
|
||||
if (players[i].lives == INFLIVES)
|
||||
{
|
||||
livescount = INFLIVES;
|
||||
break;
|
||||
}
|
||||
else if (livescount < 99)
|
||||
livescount += (players[i].lives);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
livescount = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives);
|
||||
notgreyedout = true;
|
||||
}
|
||||
|
||||
if (livescount == INFLIVES)
|
||||
V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8,
|
||||
'\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false);
|
||||
else
|
||||
{
|
||||
if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1)))
|
||||
livescount++;
|
||||
if (livescount > 99)
|
||||
livescount = 99;
|
||||
V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8,
|
||||
hudinfo[HUD_LIVES].f|V_PERPLAYER|(notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF), va("%d",livescount));
|
||||
}
|
||||
}
|
||||
// Spectator
|
||||
else if (stplyr->spectator)
|
||||
v_colmap = V_GRAYMAP;
|
||||
|
@ -934,11 +878,89 @@ static void ST_drawLivesArea(void)
|
|||
v_colmap = V_BLUEMAP;
|
||||
}
|
||||
}
|
||||
// Lives number
|
||||
else
|
||||
{
|
||||
boolean candrawlives = true;
|
||||
|
||||
// Co-op and Competition, normal life counter
|
||||
if (G_GametypeUsesLives())
|
||||
{
|
||||
// Handle cooplives here
|
||||
if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 3)
|
||||
{
|
||||
INT32 i;
|
||||
livescount = 0;
|
||||
notgreyedout = (stplyr->lives > 0);
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].lives < 1)
|
||||
continue;
|
||||
|
||||
if (players[i].lives > 1)
|
||||
notgreyedout = true;
|
||||
|
||||
if (players[i].lives == INFLIVES)
|
||||
{
|
||||
livescount = INFLIVES;
|
||||
break;
|
||||
}
|
||||
else if (livescount < 99)
|
||||
livescount += (players[i].lives);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
livescount = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives);
|
||||
notgreyedout = true;
|
||||
}
|
||||
}
|
||||
// Infinity symbol (Race)
|
||||
else if (G_PlatformGametype() && !(gametyperules & GTR_LIVES))
|
||||
{
|
||||
livescount = INFLIVES;
|
||||
notgreyedout = true;
|
||||
}
|
||||
// Otherwise nothing, sorry.
|
||||
// Special Stages keep not showing lives,
|
||||
// as G_GametypeUsesLives() returns false in
|
||||
// Special Stages, and the infinity symbol
|
||||
// cannot show up because Special Stages
|
||||
// still have the GTR_LIVES gametype rule
|
||||
// by default.
|
||||
else
|
||||
candrawlives = false;
|
||||
|
||||
// Draw the lives counter here.
|
||||
if (candrawlives)
|
||||
{
|
||||
// x
|
||||
V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, stlivex);
|
||||
if (livescount == INFLIVES)
|
||||
V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8,
|
||||
'\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false);
|
||||
else
|
||||
{
|
||||
if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1)))
|
||||
livescount++;
|
||||
if (livescount > 99)
|
||||
livescount = 99;
|
||||
V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8,
|
||||
hudinfo[HUD_LIVES].f|V_PERPLAYER|(notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF), va("%d",livescount));
|
||||
}
|
||||
}
|
||||
#undef ST_drawLivesX
|
||||
}
|
||||
|
||||
// name
|
||||
v_colmap |= (V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER);
|
||||
if (strlen(skins[stplyr->skin].hudname) <= 5)
|
||||
V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);
|
||||
else if (V_StringWidth(skins[stplyr->skin].hudname, v_colmap) <= 48)
|
||||
V_DrawString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);
|
||||
else if (V_ThinStringWidth(skins[stplyr->skin].hudname, v_colmap) <= 40)
|
||||
V_DrawRightAlignedThinString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);
|
||||
else
|
||||
|
@ -2212,7 +2234,7 @@ static void ST_drawTextHUD(void)
|
|||
donef12 = true;
|
||||
}
|
||||
}
|
||||
else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) // Death overrides spectator text.
|
||||
else if ((gametyperules & GTR_RESPAWNDELAY) && stplyr->playerstate == PST_DEAD && stplyr->lives) // Death overrides spectator text.
|
||||
{
|
||||
INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE;
|
||||
|
||||
|
@ -2236,7 +2258,7 @@ static void ST_drawTextHUD(void)
|
|||
textHUDdraw(M_GetText("\x82""Wait for the stage to end..."))
|
||||
else if (G_PlatformGametype())
|
||||
{
|
||||
if (gametype == GT_COOP)
|
||||
if (G_GametypeUsesCoopLives())
|
||||
{
|
||||
if (stplyr->lives <= 0
|
||||
&& cv_cooplives.value == 2
|
||||
|
@ -2647,7 +2669,7 @@ static void ST_overlayDrawer(void)
|
|||
INT32 i = MAXPLAYERS;
|
||||
INT32 deadtimer = stplyr->spectator ? TICRATE : (stplyr->deadtimer-(TICRATE<<1));
|
||||
|
||||
if ((gametype == GT_COOP)
|
||||
if (G_GametypeUsesCoopLives()
|
||||
&& (netgame || multiplayer)
|
||||
&& (cv_cooplives.value != 1))
|
||||
{
|
||||
|
|
|
@ -1997,7 +1997,7 @@ static void Y_AwardCoopBonuses(void)
|
|||
|
||||
if (i == consoleplayer)
|
||||
{
|
||||
data.coop.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives);
|
||||
data.coop.gotlife = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? 0 : ptlives);
|
||||
M_Memcpy(&data.coop.bonuses, &localbonuses, sizeof(data.coop.bonuses));
|
||||
}
|
||||
}
|
||||
|
@ -2052,7 +2052,7 @@ static void Y_AwardSpecialStageBonus(void)
|
|||
|
||||
if (i == consoleplayer)
|
||||
{
|
||||
data.spec.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives);
|
||||
data.spec.gotlife = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? 0 : ptlives);
|
||||
M_Memcpy(&data.spec.bonuses, &localbonuses, sizeof(data.spec.bonuses));
|
||||
|
||||
// Continues related
|
||||
|
|
Loading…
Reference in a new issue