Merge branch 'master' into net-screen

This commit is contained in:
TehRealSalt 2018-10-19 15:59:13 -04:00
commit 553066b48b
26 changed files with 442 additions and 361 deletions

View file

@ -1600,6 +1600,31 @@ void CV_AddValue(consvar_t *var, INT32 increment)
return; return;
} }
} }
else if (var == &cv_kartspeed)
{
INT32 maxspeed = (M_SecretUnlocked(SECRET_HARDSPEED) ? 2 : 1);
// Special case for the kartspeed variable, used only directly from the menu to prevent selecting hard mode
if (increment > 0) // Going up!
{
newvalue = var->value + 1;
if (newvalue > maxspeed)
newvalue = 0;
var->value = newvalue;
var->string = var->PossibleValue[var->value].strvalue;
var->func();
return;
}
else if (increment < 0) // Going down!
{
newvalue = var->value - 1;
if (newvalue < 0)
newvalue = maxspeed;
var->value = newvalue;
var->string = var->PossibleValue[var->value].strvalue;
var->func();
return;
}
}
#ifdef PARANOIA #ifdef PARANOIA
if (currentindice == -1) if (currentindice == -1)
I_Error("CV_AddValue: current value %d not found in possible value\n", I_Error("CV_AddValue: current value %d not found in possible value\n",

View file

@ -1633,18 +1633,18 @@ static void CL_LoadReceivedSavegame(void)
// load a base level // load a base level
if (P_LoadNetGame()) if (P_LoadNetGame())
{ {
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)); CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)));
if (strlen(mapheaderinfo[gamemap-1]->lvlttl) > 0) if (strlen(mapheaderinfo[gamemap-1]->lvlttl) > 0)
{ {
CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl); CON_LogMessage(va(": %s", mapheaderinfo[gamemap-1]->lvlttl));
if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0) if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0)
CONS_Printf(" %s", mapheaderinfo[gamemap-1]->zonttl); CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->zonttl));
else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
CONS_Printf(M_GetText(" ZONE")); CON_LogMessage(M_GetText(" ZONE"));
if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0)
CONS_Printf(" %s", mapheaderinfo[gamemap-1]->actnum); CON_LogMessage(va(" %s", mapheaderinfo[gamemap-1]->actnum));
} }
CONS_Printf("\"\n"); CON_LogMessage("\"\n");
} }
else else
{ {

View file

@ -420,9 +420,6 @@ consvar_t cv_numlaps = {"numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_con
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}}; static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL};
// log elemental hazards -- not a netvar, is local to current player
consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_forceskin = {"forceskin", "-1", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_forceskin = {"forceskin", "-1", CV_NETVAR|CV_CALL|CV_CHEAT, NULL, ForceSkin_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_downloading = {"downloading", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_downloading = {"downloading", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowexitlevel = {"allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowexitlevel = {"allowexitlevel", "No", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -595,8 +592,6 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_numlaps); CV_RegisterVar(&cv_numlaps);
CV_RegisterVar(&cv_basenumlaps); CV_RegisterVar(&cv_basenumlaps);
CV_RegisterVar(&cv_hazardlog);
CV_RegisterVar(&cv_autobalance); CV_RegisterVar(&cv_autobalance);
CV_RegisterVar(&cv_teamscramble); CV_RegisterVar(&cv_teamscramble);
CV_RegisterVar(&cv_scrambleonchange); CV_RegisterVar(&cv_scrambleonchange);
@ -2491,11 +2486,12 @@ static void Command_Suicide(void)
}*/ }*/
// Retry is quicker. Probably should force people to use it. // Retry is quicker. Probably should force people to use it.
if (!(netgame || multiplayer)) // nope, this is srb2kart - a complete retry is overkill
/*if (!(netgame || multiplayer))
{ {
CONS_Printf(M_GetText("You can't use this in Single Player! Use \"retry\" instead.\n")); CONS_Printf(M_GetText("You can't use this in Single Player! Use \"retry\" instead.\n"));
return; return;
} }*/
SendNetXCmd(XD_SUICIDE, &buf, 4); SendNetXCmd(XD_SUICIDE, &buf, 4);
} }
@ -3320,11 +3316,11 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[playernum], '\x84', M_GetText("Blue Team"), '\x80'); CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[playernum], '\x84', M_GetText("Blue Team"), '\x80');
} }
else if (NetPacket.packet.newteam == 3) else if (NetPacket.packet.newteam == 3)
/*CONS_Printf(M_GetText("%s entered the game.\n"), player_names[playernum])*/; CON_LogMessage(va(M_GetText("%s entered the game.\n"), player_names[playernum]));
else if (players[playernum].pflags & PF_WANTSTOJOIN) else if (players[playernum].pflags & PF_WANTSTOJOIN)
players[playernum].pflags &= ~PF_WANTSTOJOIN; players[playernum].pflags &= ~PF_WANTSTOJOIN;
else else
CONS_Printf(M_GetText("%s became a spectator.\n"), player_names[playernum]); CON_LogMessage(va(M_GetText("%s became a spectator.\n"), player_names[playernum]));
//reset view if you are changed, or viewing someone who was changed. //reset view if you are changed, or viewing someone who was changed.
if (playernum == consoleplayer || displayplayer == playernum) if (playernum == consoleplayer || displayplayer == playernum)
@ -4898,10 +4894,10 @@ void Command_Retry_f(void)
CONS_Printf(M_GetText("You must be in a level to use this.\n")); CONS_Printf(M_GetText("You must be in a level to use this.\n"));
else if (netgame || multiplayer) else if (netgame || multiplayer)
CONS_Printf(M_GetText("This only works in single player.\n")); CONS_Printf(M_GetText("This only works in single player.\n"));
else if (!&players[consoleplayer] || players[consoleplayer].lives <= 1) /*else if (!&players[consoleplayer] || players[consoleplayer].lives <= 1)
CONS_Printf(M_GetText("You can't retry without any lives remaining!\n")); CONS_Printf(M_GetText("You can't retry without any lives remaining!\n"));
else if (G_IsSpecialStage(gamemap)) else if (G_IsSpecialStage(gamemap))
CONS_Printf(M_GetText("You can't retry special stages!\n")); CONS_Printf(M_GetText("You can't retry special stages!\n"));*/
else else
{ {
M_ClearMenus(true); M_ClearMenus(true);
@ -5351,6 +5347,13 @@ static void KartFrantic_OnChange(void)
static void KartSpeed_OnChange(void) static void KartSpeed_OnChange(void)
{ {
if (!M_SecretUnlocked(SECRET_HARDSPEED) && cv_kartspeed.value == 2)
{
CONS_Printf(M_GetText("You haven't earned this yet.\n"));
CV_StealthSetValue(&cv_kartspeed, 1);
return;
}
if (G_RaceGametype()) if (G_RaceGametype())
{ {
if ((UINT8)cv_kartspeed.value != gamespeed && gamestate == GS_LEVEL && leveltime > starttime) if ((UINT8)cv_kartspeed.value != gamespeed && gamestate == GS_LEVEL && leveltime > starttime)

View file

@ -81,8 +81,6 @@ extern consvar_t cv_basenumlaps;
extern UINT32 timelimitintics; extern UINT32 timelimitintics;
extern consvar_t cv_allowexitlevel; extern consvar_t cv_allowexitlevel;
extern consvar_t cv_hazardlog;
extern consvar_t cv_autobalance; extern consvar_t cv_autobalance;
extern consvar_t cv_teamscramble; extern consvar_t cv_teamscramble;
extern consvar_t cv_scrambleonchange; extern consvar_t cv_scrambleonchange;

View file

@ -2430,6 +2430,8 @@ static void readunlockable(MYFILE *f, INT32 num)
unlockables[num].type = SECRET_ENCORE; unlockables[num].type = SECRET_ENCORE;
else if (fastcmp(word2, "HELLATTACK")) else if (fastcmp(word2, "HELLATTACK"))
unlockables[num].type = SECRET_HELLATTACK; unlockables[num].type = SECRET_HELLATTACK;
else if (fastcmp(word2, "HARDSPEED"))
unlockables[num].type = SECRET_HARDSPEED;
else else
unlockables[num].type = (INT16)i; unlockables[num].type = (INT16)i;
} }
@ -6311,6 +6313,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_WIPEOUTTRAIL4", "S_WIPEOUTTRAIL4",
"S_WIPEOUTTRAIL5", "S_WIPEOUTTRAIL5",
// Rocket sneaker
"S_ROCKETSNEAKER_L",
"S_ROCKETSNEAKER_R",
"S_ROCKETSNEAKER_LVIBRATE",
"S_ROCKETSNEAKER_RVIBRATE",
//{ Eggman Monitor //{ Eggman Monitor
"S_FAKEITEM1", "S_FAKEITEM1",
"S_FAKEITEM2", "S_FAKEITEM2",
@ -7294,6 +7302,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_DRIFTSPARK", "MT_DRIFTSPARK",
"MT_DRIFTDUST", "MT_DRIFTDUST",
"MT_ROCKETSNEAKER", // Rocket sneakers
"MT_FAKESHIELD", "MT_FAKESHIELD",
"MT_FAKEITEM", "MT_FAKEITEM",
@ -7305,7 +7315,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_JAWZ", // Jawz stuff "MT_JAWZ", // Jawz stuff
"MT_JAWZ_DUD", "MT_JAWZ_DUD",
"MT_JAWZ_SHIELD", "MT_JAWZ_SHIELD",
"MT_PLAYERRETICULE", // Jawz reticule "MT_PLAYERRETICULE", // Jawz reticule

View file

@ -461,6 +461,7 @@ extern tic_t indirectitemcooldown;
extern tic_t spbincoming; extern tic_t spbincoming;
extern UINT8 spbplayer; extern UINT8 spbplayer;
extern tic_t mapreset; extern tic_t mapreset;
extern UINT8 nospectategrief;
extern boolean legitimateexit; extern boolean legitimateexit;
extern boolean comebackshowninfo; extern boolean comebackshowninfo;

View file

@ -267,6 +267,7 @@ tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any othe
tic_t spbincoming; // Timer before SPB hits, can switch targets at this point tic_t spbincoming; // Timer before SPB hits, can switch targets at this point
UINT8 spbplayer; // Player num that used the last SPB UINT8 spbplayer; // Player num that used the last SPB
tic_t mapreset; // Map reset delay when enough players have joined an empty game tic_t mapreset; // Map reset delay when enough players have joined an empty game
UINT8 nospectategrief; // How many players need to be in-game to eliminate last; for preventing spectate griefing
// Client-sided, unsynched variables (NEVER use in anything that needs to be synced with other players) // Client-sided, unsynched variables (NEVER use in anything that needs to be synced with other players)
boolean legitimateexit; // Did this client actually finish the match? boolean legitimateexit; // Did this client actually finish the match?
@ -2100,10 +2101,12 @@ void G_Ticker(boolean run)
G_ClearRetryFlag(); G_ClearRetryFlag();
// Costs a life to retry ... unless the player in question is dead already. // Costs a life to retry ... unless the player in question is dead already.
if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE) /*if (G_GametypeUsesLives() && players[consoleplayer].playerstate == PST_LIVE)
players[consoleplayer].lives -= 1; players[consoleplayer].lives -= 1;
G_DoReborn(consoleplayer); G_DoReborn(consoleplayer);*/
D_MapChange(gamemap, gametype, cv_kartencore.value, true, 1, false, false);
} }
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
@ -2935,7 +2938,7 @@ void G_DoReborn(INT32 playernum)
if (oldmo) if (oldmo)
G_ChangePlayerReferences(oldmo, players[playernum].mo); G_ChangePlayerReferences(oldmo, players[playernum].mo);
} }
else if (countdowntimeup || (!multiplayer && gametype == GT_COOP)) /*else if (countdowntimeup || (!multiplayer && !modeattacking))
{ {
// reload the level from scratch // reload the level from scratch
if (countdowntimeup) if (countdowntimeup)
@ -3004,7 +3007,7 @@ void G_DoReborn(INT32 playernum)
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
} }
#endif #endif
} }*/
else else
{ {
// respawn at the start // respawn at the start
@ -3051,7 +3054,7 @@ void G_ExitLevel(void)
} }
if (netgame || multiplayer) if (netgame || multiplayer)
CONS_Printf(M_GetText("The round has ended.\n")); CON_LogMessage(M_GetText("The round has ended.\n"));
// Remove CEcho text on round end. // Remove CEcho text on round end.
HU_DoCEcho(""); HU_DoCEcho("");
@ -4339,13 +4342,13 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
{ {
char *title = G_BuildMapTitle(gamemap); char *title = G_BuildMapTitle(gamemap);
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)); CON_LogMessage(va(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)));
if (title) if (title)
{ {
CONS_Printf(": %s", title); CON_LogMessage(va(": %s", title));
Z_Free(title); Z_Free(title);
} }
CONS_Printf("\"\n"); CON_LogMessage("\"\n");
} }
} }
@ -4496,6 +4499,13 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
G_CopyTiccmd(cmd, &oldcmd, 1); G_CopyTiccmd(cmd, &oldcmd, 1);
// SRB2kart: Copy-pasted from ticcmd building, removes that crappy demo cam
if (((players[displayplayer].mo && players[displayplayer].speed > 0) // Moving
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (players[displayplayer].spectator || objectplacing)) // Not a physical player
&& !(players[displayplayer].kartstuff[k_spinouttimer] && players[displayplayer].kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout
localangle += (cmd->angleturn<<16);
if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
{ {
// end of demo data stream // end of demo data stream

View file

@ -189,7 +189,6 @@ void G_StopMetalDemo(void);
ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void);
void G_StopDemo(void); void G_StopDemo(void);
boolean G_CheckDemoStatus(void); boolean G_CheckDemoStatus(void);
char *G_DemoPlayerName(char *defdemoname);
boolean G_IsSpecialStage(INT32 mapnum); boolean G_IsSpecialStage(INT32 mapnum);
boolean G_GametypeUsesLives(void); boolean G_GametypeUsesLives(void);

View file

@ -56,12 +56,12 @@ char sprnames[NUMSPRITES + 1][5] =
"SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO", "SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO",
//SRB2kart Sprites //SRB2kart Sprites
"SPRG","BSPR","RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE", "SPRG","BSPR","RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE",
"KINV","KINF","WIPD","DRIF","DUST","FITM","BANA","ORBN","JAWZ","SSMN", "KINV","KINF","WIPD","DRIF","DUST","RSHE","FITM","BANA","ORBN","JAWZ",
"KRBM","BHOG","BHBM","BLIG","LIGH","THNS","SINK","SITR","KBLN","DEZL", "SSMN","KRBM","BHOG","BHBM","BLIG","LIGH","THNS","SINK","SITR","KBLN",
"POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO", "DEZL","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM",
"CRAB","SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO", "SACO","CRAB","SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB",
"ITEM","ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK","LZI1", "ARRO","ITEM","ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK",
"LZI2","KLIT","VIEW" "LZI1","LZI2","KLIT","VIEW"
}; };
// Doesn't work with g++, needs actionf_p1 (don't modify this comment) // Doesn't work with g++, needs actionf_p1 (don't modify this comment)
@ -2623,6 +2623,11 @@ state_t states[NUMSTATES] =
{SPR_WIPD, 3, 3, {NULL}, 0, 0, S_WIPEOUTTRAIL5}, // S_WIPEOUTTRAIL4 {SPR_WIPD, 3, 3, {NULL}, 0, 0, S_WIPEOUTTRAIL5}, // S_WIPEOUTTRAIL4
{SPR_WIPD, 4, 3, {NULL}, 0, 0, S_NULL}, // S_WIPEOUTTRAIL5 {SPR_WIPD, 4, 3, {NULL}, 0, 0, S_NULL}, // S_WIPEOUTTRAIL5
{SPR_RSHE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_ROCKETSNEAKER_L
{SPR_RSHE, 1, -1, {NULL}, 0, 0, S_NULL}, // S_ROCKETSNEAKER_R
{SPR_RSHE, 2, -1, {NULL}, 0, 0, S_NULL}, // S_ROCKETSNEAKER_LVIBRATE
{SPR_RSHE, 3, -1, {NULL}, 0, 0, S_NULL}, // S_ROCKETSNEAKER_RVIBRATE
{SPR_FITM, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM2}, // S_FAKEITEM1 {SPR_FITM, FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM2}, // S_FAKEITEM1
{SPR_FITM, 1|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM3}, // S_FAKEITEM2 {SPR_FITM, 1|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM3}, // S_FAKEITEM2
{SPR_FITM, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM4}, // S_FAKEITEM3 {SPR_FITM, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FAKEITEM4}, // S_FAKEITEM3
@ -14803,6 +14808,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_ROCKETSNEAKER
-1, // doomednum
S_ROCKETSNEAKER_L, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_tossed, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_s3k5d, // deathsound
0, // speed
16*FRACUNIT, // radius
16*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_s3kc0s, // activesound
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_FAKESHIELD { // MT_FAKESHIELD
-1, // doomednum -1, // doomednum
S_FAKEITEM1, // spawnstate S_FAKEITEM1, // spawnstate

View file

@ -596,6 +596,7 @@ typedef enum sprite
SPR_DUST, // Drift Dust SPR_DUST, // Drift Dust
// Kart Items // Kart Items
SPR_RSHE, // Rocket sneaker
SPR_FITM, // Eggman Monitor SPR_FITM, // Eggman Monitor
SPR_BANA, // Banana Peel SPR_BANA, // Banana Peel
SPR_ORBN, // Orbinaut SPR_ORBN, // Orbinaut
@ -3155,6 +3156,12 @@ typedef enum state
S_WIPEOUTTRAIL4, S_WIPEOUTTRAIL4,
S_WIPEOUTTRAIL5, S_WIPEOUTTRAIL5,
// Rocket sneaker
S_ROCKETSNEAKER_L,
S_ROCKETSNEAKER_R,
S_ROCKETSNEAKER_LVIBRATE,
S_ROCKETSNEAKER_RVIBRATE,
//{ Eggman Monitor //{ Eggman Monitor
S_FAKEITEM1, S_FAKEITEM1,
S_FAKEITEM2, S_FAKEITEM2,
@ -4155,6 +4162,8 @@ typedef enum mobj_type
MT_DRIFTSPARK, MT_DRIFTSPARK,
MT_DRIFTDUST, MT_DRIFTDUST,
MT_ROCKETSNEAKER,
MT_FAKESHIELD, MT_FAKESHIELD,
MT_FAKEITEM, MT_FAKEITEM,

View file

@ -31,6 +31,7 @@
// spbincoming is the timer before k_deathsentence is cast on the player in 1st // spbincoming is the timer before k_deathsentence is cast on the player in 1st
// spbplayer is the last player who fired a SPB // spbplayer is the last player who fired a SPB
// mapreset is set when enough players fill an empty server // mapreset is set when enough players fill an empty server
// nospectategrief is the players in-game needed to eliminate the person in last
//{ SRB2kart Color Code //{ SRB2kart Color Code
@ -2071,13 +2072,8 @@ void K_StealBumper(player_t *player, player_t *victim, boolean force)
} }
} }
if (netgame) if (netgame && player->kartstuff[k_bumper] <= 0)
{ CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]);
if (player->kartstuff[k_bumper] <= 0)
CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]);
else if (cv_hazardlog.value)
CONS_Printf(M_GetText("%s stole a bumper from %s!\n"), player_names[player-players], player_names[victim-players]);
}
newbumper = player->kartstuff[k_bumper]; newbumper = player->kartstuff[k_bumper];
if (newbumper <= 1) if (newbumper <= 1)
@ -2996,35 +2992,66 @@ static void K_DoHyudoroSteal(player_t *player)
} }
} }
void K_DoSneaker(player_t *player, boolean doPFlag) void K_DoSneaker(player_t *player, INT32 type)
{ {
const fixed_t prevboost = player->kartstuff[k_speedboost]; fixed_t intendedboost;
switch (gamespeed)
{
case 0:
intendedboost = 53740+768;
break;
case 2:
intendedboost = 17294+768;
break;
default:
intendedboost = 32768;
break;
}
if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3)
{ {
S_StartSound(player->mo, sfx_cdfm01); S_StartSound(player->mo, sfx_cdfm01);
K_SpawnDashDustRelease(player); K_SpawnDashDustRelease(player);
if (intendedboost > player->kartstuff[k_speedboost])
player->kartstuff[k_destboostcam] = FixedMul(FRACUNIT, FixedDiv((intendedboost - player->kartstuff[k_speedboost]), intendedboost));
} }
if (!player->kartstuff[k_sneakertimer]) if (!player->kartstuff[k_sneakertimer])
{ {
mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BOOSTFLAME); if (type == 2)
P_SetTarget(&overlay->target, player->mo); {
overlay->destscale = player->mo->scale; if (player->mo->hnext)
P_SetScale(overlay, player->mo->scale); {
mobj_t *cur = player->mo->hnext;
while (cur && !P_MobjWasRemoved(cur))
{
if (!cur->tracer)
{
mobj_t *overlay = P_SpawnMobj(cur->x, cur->y, cur->z, MT_BOOSTFLAME);
P_SetTarget(&overlay->target, cur);
P_SetTarget(&cur->tracer, overlay);
P_SetScale(overlay, (overlay->destscale = 3*cur->scale/4));
}
cur = cur->hnext;
}
}
}
else
{
mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BOOSTFLAME);
P_SetTarget(&overlay->target, player->mo);
P_SetScale(overlay, (overlay->destscale = player->mo->scale));
}
} }
player->kartstuff[k_sneakertimer] = sneakertime; player->kartstuff[k_sneakertimer] = sneakertime;
if (doPFlag) if (type != 0)
{ {
player->pflags |= PF_ATTACKDOWN; player->pflags |= PF_ATTACKDOWN;
K_PlayBoostTaunt(player->mo); K_PlayBoostTaunt(player->mo);
} }
K_GetKartBoostPower(player);
if (player->kartstuff[k_speedboost] > prevboost)
player->kartstuff[k_destboostcam] = FRACUNIT;
} }
static void K_DoShrink(player_t *player) static void K_DoShrink(player_t *player)
@ -3235,6 +3262,7 @@ void K_DropHnextList(player_t *player)
break; break;
// intentionally do nothing // intentionally do nothing
case MT_SINK_SHIELD: case MT_SINK_SHIELD:
case MT_ROCKETSNEAKER:
return; return;
default: default:
continue; continue;
@ -3582,6 +3610,93 @@ static void K_MoveHeldObjects(player_t *player)
} }
} }
break; break;
case MT_ROCKETSNEAKER: // Special rocket sneaker stuff
{
mobj_t *cur = player->mo->hnext;
INT32 num = 0;
while (cur && !P_MobjWasRemoved(cur))
{
const fixed_t radius = FixedHypot(player->mo->radius, player->mo->radius) + FixedHypot(cur->radius, cur->radius);
boolean vibrate = ((leveltime & 1) && !cur->tracer);
angle_t angoffset;
fixed_t targx, targy, targz;
cur->flags &= ~MF_NOCLIPTHING;
if (player->kartstuff[k_rocketsneakertimer] <= TICRATE && (leveltime & 1))
cur->flags2 |= MF2_DONTDRAW;
else
cur->flags2 &= ~MF2_DONTDRAW;
if (num & 1)
P_SetMobjStateNF(cur, (vibrate ? S_ROCKETSNEAKER_LVIBRATE : S_ROCKETSNEAKER_L));
else
P_SetMobjStateNF(cur, (vibrate ? S_ROCKETSNEAKER_RVIBRATE : S_ROCKETSNEAKER_R));
if (!player->kartstuff[k_rocketsneakertimer] || cur->extravalue2 || !cur->health)
{
num = (num+1) % 2;
cur = cur->hnext;
continue;
}
if (cur->extravalue1 < radius)
cur->extravalue1 += FixedMul(P_AproxDistance(cur->extravalue1, radius), FRACUNIT/12);
if (cur->extravalue1 > radius)
cur->extravalue1 = radius;
// Shrink your items if the player shrunk too.
P_SetScale(cur, (cur->destscale = FixedMul(FixedDiv(cur->extravalue1, radius), player->mo->scale)));
#if 1
{
angle_t input = player->mo->angle - cur->angle;
boolean invert = (input > ANGLE_180);
if (invert)
input = InvAngle(input);
input = FixedAngle(AngleFixed(input)/4);
if (invert)
input = InvAngle(input);
cur->angle = cur->angle + input;
}
#else
cur->angle = player->mo->angle;
#endif
angoffset = ANGLE_90 + (ANGLE_180 * num);
targx = player->mo->x + P_ReturnThrustX(cur, cur->angle + angoffset, cur->extravalue1);
targy = player->mo->y + P_ReturnThrustY(cur, cur->angle + angoffset, cur->extravalue1);
{ // bobbing, copy pasted from my kimokawaiii entry
const fixed_t pi = (22<<FRACBITS) / 7; // loose approximation, this doesn't need to be incredibly precise
fixed_t sine = 8 * FINESINE((((2*pi*(4*TICRATE)) * leveltime)>>ANGLETOFINESHIFT) & FINEMASK);
targz = (player->mo->z + (player->mo->height/2)) + sine;
}
if (cur->tracer)
{
fixed_t diffx, diffy, diffz;
diffx = targx - cur->x;
diffy = targy - cur->y;
diffz = targz - cur->z;
P_TeleportMove(cur->tracer, cur->tracer->x + diffx + P_ReturnThrustX(cur, cur->angle + angoffset, 6*cur->scale),
cur->tracer->y + diffy + P_ReturnThrustY(cur, cur->angle + angoffset, 6*cur->scale), cur->tracer->z + diffz);
P_SetScale(cur->tracer, (cur->tracer->destscale = 3*cur->scale/4));
}
P_TeleportMove(cur, targx, targy, targz);
num = (num+1) % 2;
cur = cur->hnext;
}
}
break;
default: default:
break; break;
} }
@ -4607,9 +4722,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
else if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO else if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO
&& player->kartstuff[k_rocketsneakertimer] > 1) && player->kartstuff[k_rocketsneakertimer] > 1)
{ {
K_DoSneaker(player, true); K_DoSneaker(player, 2);
K_PlayBoostTaunt(player->mo); K_PlayBoostTaunt(player->mo);
player->kartstuff[k_rocketsneakertimer] -= 5; player->kartstuff[k_rocketsneakertimer] -= 2*TICRATE;
if (player->kartstuff[k_rocketsneakertimer] < 1) if (player->kartstuff[k_rocketsneakertimer] < 1)
player->kartstuff[k_rocketsneakertimer] = 1; player->kartstuff[k_rocketsneakertimer] = 1;
} }
@ -4624,7 +4739,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
case KITEM_SNEAKER: case KITEM_SNEAKER:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO) if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO)
{ {
K_DoSneaker(player, true); K_DoSneaker(player, 1);
K_PlayBoostTaunt(player->mo); K_PlayBoostTaunt(player->mo);
player->kartstuff[k_itemamount]--; player->kartstuff[k_itemamount]--;
} }
@ -4633,10 +4748,33 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO
&& player->kartstuff[k_rocketsneakertimer] == 0) && player->kartstuff[k_rocketsneakertimer] == 0)
{ {
K_DoSneaker(player, true); INT32 moloop;
mobj_t *mo = NULL;
mobj_t *prev = player->mo;
K_PlayBoostTaunt(player->mo); K_PlayBoostTaunt(player->mo);
player->kartstuff[k_rocketsneakertimer] = itemtime; //player->kartstuff[k_itemheld] = 1;
S_StartSound(player->mo, sfx_s3k3a);
//K_DoSneaker(player, 2);
player->kartstuff[k_rocketsneakertimer] = (itemtime*3);
player->kartstuff[k_itemamount]--; player->kartstuff[k_itemamount]--;
K_UpdateHnextList(player, true);
for (moloop = 0; moloop < 2; moloop++)
{
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ROCKETSNEAKER);
mo->flags |= MF_NOCLIPTHING;
mo->angle = player->mo->angle;
mo->threshold = 10;
mo->movecount = moloop%2;
mo->movedir = mo->lastlook = moloop+1;
P_SetTarget(&mo->target, player->mo);
P_SetTarget(&mo->hprev, prev);
P_SetTarget(&prev->hnext, mo);
prev = mo;
}
} }
break; break;
case KITEM_INVINCIBILITY: case KITEM_INVINCIBILITY:
@ -4896,11 +5034,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
} }
break; break;
case KITEM_THUNDERSHIELD: case KITEM_THUNDERSHIELD:
if (player->kartstuff[k_curshield] <= 0) if (player->kartstuff[k_curshield] != 1)
{ {
mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THUNDERSHIELD); mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THUNDERSHIELD);
P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2)); P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2));
P_SetTarget(&shield->target, player->mo); P_SetTarget(&shield->target, player->mo);
S_StartSound(shield, sfx_s3k41);
player->kartstuff[k_curshield] = 1; player->kartstuff[k_curshield] = 1;
} }
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
@ -5144,7 +5283,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (player->kartstuff[k_boostcharge] <= 36) if (player->kartstuff[k_boostcharge] <= 36)
{ {
player->kartstuff[k_startboost] = 0; player->kartstuff[k_startboost] = 0;
K_DoSneaker(player, false); K_DoSneaker(player, 0);
player->kartstuff[k_sneakertimer] = 70; // PERFECT BOOST!! player->kartstuff[k_sneakertimer] = 70; // PERFECT BOOST!!
if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) // Let everyone hear this one if (!player->kartstuff[k_floorboost] || player->kartstuff[k_floorboost] == 3) // Let everyone hear this one
@ -5370,7 +5509,7 @@ void K_CheckSpectateStatus(void)
return; return;
if (numingame < 2 || leveltime < starttime || mapreset) // Allow if the match hasn't started yet if (numingame < 2 || leveltime < starttime || mapreset) // Allow if the match hasn't started yet
continue; continue;
if (leveltime > 20*TICRATE) // DON'T allow if the match is 20 seconds in if (leveltime > (starttime + 20*TICRATE)) // DON'T allow if the match is 20 seconds in
return; return;
if (G_RaceGametype() && players[i].laps) // DON'T allow if the race is at 2 laps if (G_RaceGametype() && players[i].laps) // DON'T allow if the race is at 2 laps
return; return;
@ -6054,9 +6193,10 @@ static void K_drawKartItem(void)
// Extensible meter, currently only used for rocket sneaker... // Extensible meter, currently only used for rocket sneaker...
if (itembar && hudtrans) if (itembar && hudtrans)
{ {
const INT32 barlength = (splitscreen > 1 ? 12 : 24); const INT32 barlength = (splitscreen > 1 ? 12 : 26);
const INT32 max = itemtime; // timer's normal highest value const INT32 maxl = (itemtime*3) - barlength; // timer's normal highest value
const INT32 length = min(barlength, (itembar * barlength) / max); const INT32 fill = ((itembar*barlength)/maxl);
const INT32 length = min(barlength, fill);
const INT32 height = (offset ? 1 : 2); const INT32 height = (offset ? 1 : 2);
const INT32 x = (offset ? 17 : 11), y = (offset ? 27 : 35); const INT32 x = (offset ? 17 : 11), y = (offset ? 27 : 35);

View file

@ -37,7 +37,7 @@ void K_SpawnBoostTrail(player_t *player);
void K_SpawnSparkleTrail(mobj_t *mo); void K_SpawnSparkleTrail(mobj_t *mo);
void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent); void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent);
void K_DriftDustHandling(mobj_t *spawner); void K_DriftDustHandling(mobj_t *spawner);
void K_DoSneaker(player_t *player, boolean doPFlag); void K_DoSneaker(player_t *player, INT32 type);
void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound); void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound);
void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source); void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source);
void K_UpdateHnextList(player_t *player, boolean clean); void K_UpdateHnextList(player_t *player, boolean clean);

View file

@ -2235,11 +2235,11 @@ static int lib_kDriftDustHandling(lua_State *L)
static int lib_kDoSneaker(lua_State *L) static int lib_kDoSneaker(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean doPFlag = luaL_checkboolean(L, 2); INT32 type = luaL_checkinteger(L, 2);
NOHUD NOHUD
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
K_DoSneaker(player, doPFlag); K_DoSneaker(player, type);
return 0; return 0;
} }

View file

@ -101,10 +101,11 @@ unlockable_t unlockables[MAXUNLOCKABLES] =
/* 02 */ {"SMK Cup", "", -1, 2, SECRET_NONE, 0, false, false, 0}, /* 02 */ {"SMK Cup", "", -1, 2, SECRET_NONE, 0, false, false, 0},
/* 03 */ {"Chao Cup", "", -1, 3, SECRET_NONE, 0, false, false, 0}, /* 03 */ {"Chao Cup", "", -1, 3, SECRET_NONE, 0, false, false, 0},
/* 04 */ {"Encore Mode", "", 3, 4, SECRET_ENCORE, 0, false, false, 0}, /* 04 */ {"Hard Game Speed", "", -1, 4, SECRET_HARDSPEED, 0, false, false, 0},
/* 05 */ {"Hell Attack", "", 5, 5, SECRET_HELLATTACK, 0, false, false, 0}, /* 05 */ {"Encore Mode", "", 4, 5, SECRET_ENCORE, 0, false, false, 0},
/* 06 */ {"Hell Attack", "", 6, 6, SECRET_HELLATTACK, 0, false, false, 0},
/* 06 */ {"Record Attack", "", -1, -1, SECRET_RECORDATTACK, 0, true, true, 0}, /* 07 */ {"Record Attack", "", -1, -1, SECRET_RECORDATTACK, 0, true, true, 0},
}; };
// Default number of emblems and extra emblems // Default number of emblems and extra emblems
@ -120,23 +121,27 @@ void M_SetupDefaultConditionSets(void)
M_AddRawCondition(1, 1, UC_TOTALEMBLEMS, 5, 0, 0); M_AddRawCondition(1, 1, UC_TOTALEMBLEMS, 5, 0, 0);
M_AddRawCondition(1, 2, UC_MATCHESPLAYED, 10, 0, 0); M_AddRawCondition(1, 2, UC_MATCHESPLAYED, 10, 0, 0);
// -- 2: Collect 15 emblems OR play 25 matches // -- 2: Collect 10 emblems OR play 25 matches
M_AddRawCondition(2, 1, UC_TOTALEMBLEMS, 15, 0, 0); M_AddRawCondition(2, 1, UC_TOTALEMBLEMS, 10, 0, 0);
M_AddRawCondition(2, 2, UC_MATCHESPLAYED, 25, 0, 0); M_AddRawCondition(2, 2, UC_MATCHESPLAYED, 25, 0, 0);
// -- 3: Collect 30 emblems OR play 50 matches // -- 3: Collect 20 emblems OR play 50 matches
M_AddRawCondition(3, 1, UC_TOTALEMBLEMS, 30, 0, 0); M_AddRawCondition(3, 1, UC_TOTALEMBLEMS, 20, 0, 0);
M_AddRawCondition(3, 2, UC_MATCHESPLAYED, 50, 0, 0); M_AddRawCondition(3, 2, UC_MATCHESPLAYED, 50, 0, 0);
// -- 4: Collect 40 emblems OR play 150 matches // -- 4: Collect 30 emblems OR play 100 matches
M_AddRawCondition(4, 1, UC_TOTALEMBLEMS, 40, 0, 0); M_AddRawCondition(4, 1, UC_TOTALEMBLEMS, 30, 0, 0);
M_AddRawCondition(4, 2, UC_MATCHESPLAYED, 150, 0, 0); M_AddRawCondition(4, 2, UC_MATCHESPLAYED, 100, 0, 0);
// -- 5: Collect 50 emblems ONLY // -- 5: Collect 40 emblems OR play 150 matches
M_AddRawCondition(5, 1, UC_TOTALEMBLEMS, 50, 0, 0); M_AddRawCondition(5, 1, UC_TOTALEMBLEMS, 40, 0, 0);
M_AddRawCondition(5, 2, UC_MATCHESPLAYED, 150, 0, 0);
// -- 10: Play 100 matches // -- 6: Collect 50 emblems ONLY
M_AddRawCondition(10, 1, UC_MATCHESPLAYED, 100, 0, 0); M_AddRawCondition(6, 1, UC_TOTALEMBLEMS, 50, 0, 0);
// -- 10: Play 300 matches
M_AddRawCondition(10, 1, UC_MATCHESPLAYED, 300, 0, 0);
} }
void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2) void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2)

View file

@ -113,7 +113,7 @@ typedef struct
} unlockable_t; } unlockable_t;
// I have NO idea why these are going negative, but whatever. // I have NO idea why these are going negative, but whatever.
#define SECRET_NONE -6 // Does nil. Use with levels locked by UnlockRequired #define SECRET_NONE -6 // Does nil. Use with levels locked by UnlockRequired
#define SECRET_ITEMFINDER -5 // Enables Item Finder/Emblem Radar #define SECRET_ITEMFINDER -5 // Enables Item Finder/Emblem Radar
#define SECRET_EMBLEMHINTS -4 // Enables Emblem Hints #define SECRET_EMBLEMHINTS -4 // Enables Emblem Hints
#define SECRET_PANDORA -3 // Enables Pandora's Box #define SECRET_PANDORA -3 // Enables Pandora's Box
@ -124,8 +124,9 @@ typedef struct
#define SECRET_WARP 2 // Selectable warp #define SECRET_WARP 2 // Selectable warp
#define SECRET_SOUNDTEST 3 // Sound Test #define SECRET_SOUNDTEST 3 // Sound Test
#define SECRET_CREDITS 4 // Enables Credits #define SECRET_CREDITS 4 // Enables Credits
#define SECRET_ENCORE 5 // Enables Encore mode cvar #define SECRET_ENCORE 5 // Enables Encore mode cvar
#define SECRET_HELLATTACK 6 // Map Hell in record attack #define SECRET_HELLATTACK 6 // Map Hell in record attack
#define SECRET_HARDSPEED 7 // Enables Hard gamespeed
// If you have more secrets than these variables allow in your game, // If you have more secrets than these variables allow in your game,
// you seriously need to get a life. // you seriously need to get a life.

View file

@ -2851,18 +2851,18 @@ void M_StartControlPanel(void)
} }
else if (!(netgame || multiplayer)) // Single Player else if (!(netgame || multiplayer)) // Single Player
{ {
if (gamestate != GS_LEVEL || ultimatemode) // intermission, so gray out stuff. if (gamestate != GS_LEVEL /*|| ultimatemode*/) // intermission, so gray out stuff.
{ {
SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA)) ? (IT_GRAYEDOUT) : (IT_DISABLED); SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA)) ? (IT_GRAYEDOUT) : (IT_DISABLED);
SPauseMenu[spause_retry].status = IT_GRAYEDOUT; SPauseMenu[spause_retry].status = IT_GRAYEDOUT;
} }
else else
{ {
INT32 numlives = 2; //INT32 numlives = 2;
SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); SPauseMenu[spause_pandora].status = (M_SecretUnlocked(SECRET_PANDORA)) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
if (&players[consoleplayer]) /*if (&players[consoleplayer])
{ {
numlives = players[consoleplayer].lives; numlives = players[consoleplayer].lives;
if (players[consoleplayer].playerstate != PST_LIVE) if (players[consoleplayer].playerstate != PST_LIVE)
@ -2873,7 +2873,7 @@ void M_StartControlPanel(void)
// for me to want to use the short if statement syntax // for me to want to use the short if statement syntax
if (numlives <= 1 || G_IsSpecialStage(gamemap)) if (numlives <= 1 || G_IsSpecialStage(gamemap))
SPauseMenu[spause_retry].status = (IT_GRAYEDOUT); SPauseMenu[spause_retry].status = (IT_GRAYEDOUT);
else else*/
SPauseMenu[spause_retry].status = (IT_STRING | IT_CALL); SPauseMenu[spause_retry].status = (IT_STRING | IT_CALL);
} }
@ -5001,7 +5001,7 @@ static void M_RetryResponse(INT32 ch)
static void M_Retry(INT32 choice) static void M_Retry(INT32 choice)
{ {
(void)choice; (void)choice;
M_StartMessage(M_GetText("Retry this act from the last starpost?\n\n(Press 'Y' to confirm)\n"),M_RetryResponse,MM_YESNO); M_StartMessage(M_GetText("Start this race over?\n\n(Press 'Y' to confirm)\n"),M_RetryResponse,MM_YESNO);
} }
static void M_SelectableClearMenus(INT32 choice) static void M_SelectableClearMenus(INT32 choice)
@ -5135,7 +5135,7 @@ static void M_DrawChecklist(void)
{ {
if (unlockables[i].name[0] == 0 || unlockables[i].nochecklist if (unlockables[i].name[0] == 0 || unlockables[i].nochecklist
|| !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS || !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS
|| !M_Achieved(unlockables[i].showconditionset - 1)) || (!M_Achieved(unlockables[i].showconditionset - 1) && !unlockables[i].unlocked))
continue; continue;
++line; ++line;

View file

@ -510,8 +510,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
special->target->player->kartstuff[k_comebackpoints] += 2 * (K_IsPlayerWanted(player) ? 2 : 1); special->target->player->kartstuff[k_comebackpoints] += 2 * (K_IsPlayerWanted(player) ? 2 : 1);
if (netgame && cv_hazardlog.value)
CONS_Printf(M_GetText("%s bombed %s!\n"), player_names[special->target->player-players], player_names[player-players]);
if (special->target->player->kartstuff[k_comebackpoints] >= 3) if (special->target->player->kartstuff[k_comebackpoints] >= 3)
K_StealBumper(special->target->player, player, true); K_StealBumper(special->target->player, player, true);
special->target->player->kartstuff[k_comebacktimer] = comebacktime; special->target->player->kartstuff[k_comebacktimer] = comebacktime;
@ -527,8 +525,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->player->kartstuff[k_comebackmode] = 0; special->target->player->kartstuff[k_comebackmode] = 0;
special->target->player->kartstuff[k_comebackpoints]++; special->target->player->kartstuff[k_comebackpoints]++;
if (netgame && cv_hazardlog.value)
CONS_Printf(M_GetText("%s gave an item to %s.\n"), player_names[special->target->player-players], player_names[player-players]);
if (special->target->player->kartstuff[k_comebackpoints] >= 3) if (special->target->player->kartstuff[k_comebackpoints] >= 3)
K_StealBumper(special->target->player, player, true); K_StealBumper(special->target->player, player, true);
special->target->player->kartstuff[k_comebacktimer] = comebacktime; special->target->player->kartstuff[k_comebacktimer] = comebacktime;
@ -560,8 +556,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->player->kartstuff[k_comebackmode] = 0; special->target->player->kartstuff[k_comebackmode] = 0;
special->target->player->kartstuff[k_comebackpoints]++; special->target->player->kartstuff[k_comebackpoints]++;
if (netgame && cv_hazardlog.value)
CONS_Printf(M_GetText("%s gave an \"item\" to %s.\n"), player_names[special->target->player-players], player_names[player-players]);
if (special->target->player->kartstuff[k_comebackpoints] >= 3) if (special->target->player->kartstuff[k_comebackpoints] >= 3)
K_StealBumper(special->target->player, player, true); K_StealBumper(special->target->player, player, true);
special->target->player->kartstuff[k_comebacktimer] = comebacktime; special->target->player->kartstuff[k_comebacktimer] = comebacktime;
@ -1667,199 +1661,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
} }
//
/** Prints death messages relating to a dying or hit player.
*
* \param player Affected player.
* \param inflictor The attack weapon used, can be NULL.
* \param source The attacker, can be NULL.
*/
static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *source)
{
const char *str = NULL;
boolean deathonly = false;
boolean deadsource = false;
boolean deadtarget = false;
// player names complete with control codes
char targetname[MAXPLAYERNAME+4];
char sourcename[MAXPLAYERNAME+4];
if (G_RaceGametype())
return; // Not in coop, etc.
if (!player)
return; // Impossible!
if (player->spectator)
return; // No messages for dying (crushed) spectators.
if (!netgame)
return; // Presumably it's obvious what's happening in splitscreen.
#ifdef HAVE_BLUA
if (LUAh_HurtMsg(player, inflictor, source))
return;
#endif
deadtarget = (player->health <= 0);
// Target's name
snprintf(targetname, sizeof(targetname), "%s%s%s",
CTFTEAMCODE(player),
player_names[player - players],
CTFTEAMENDCODE(player));
if (source)
{
// inflictor shouldn't be NULL if source isn't
I_Assert(inflictor != NULL);
if (source->player)
{
// Source's name (now that we know there is one)
snprintf(sourcename, sizeof(sourcename), "%s%s%s",
CTFTEAMCODE(source->player),
player_names[source->player - players],
CTFTEAMENDCODE(source->player));
// We don't care if it's us.
// "Player 1's [redacted] killed Player 1."
if (source->player->playerstate == PST_DEAD && source->player != player &&
(inflictor->flags2 & MF2_BEYONDTHEGRAVE))
deadsource = true;
if (inflictor->flags & MF_PUSHABLE)
{
str = M_GetText("%s%s's playtime with heavy objects %s %s.\n");
}
else switch (inflictor->type)
{
case MT_PLAYER:
if ((inflictor->player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB)
str = M_GetText("%s%s's armageddon blast %s %s.\n");
else if (inflictor->player->powers[pw_invulnerability])
str = M_GetText("%s%s's invincibility aura %s %s.\n");
else if (inflictor->player->powers[pw_super])
str = M_GetText("%s%s's super aura %s %s.\n");
else
str = M_GetText("%s%s's tagging hand %s %s.\n");
break;
case MT_SPINFIRE:
str = M_GetText("%s%s's elemental fire trail %s %s.\n");
break;
case MT_THROWNBOUNCE:
str = M_GetText("%s%s's bounce ring %s %s.\n");
break;
case MT_THROWNINFINITY:
str = M_GetText("%s%s's infinity ring %s %s.\n");
break;
case MT_THROWNAUTOMATIC:
str = M_GetText("%s%s's automatic ring %s %s.\n");
break;
case MT_THROWNSCATTER:
str = M_GetText("%s%s's scatter ring %s %s.\n");
break;
// TODO: For next two, figure out how to determine if it was a direct hit or splash damage. -SH
case MT_THROWNEXPLOSION:
str = M_GetText("%s%s's explosion ring %s %s.\n");
break;
case MT_THROWNGRENADE:
str = M_GetText("%s%s's grenade ring %s %s.\n");
break;
case MT_REDRING:
if (inflictor->flags2 & MF2_RAILRING)
str = M_GetText("%s%s's rail ring %s %s.\n");
else
str = M_GetText("%s%s's thrown ring %s %s.\n");
break;
default:
str = M_GetText("%s%s %s %s.\n");
break;
}
CONS_Printf(str,
deadsource ? M_GetText("The late ") : "",
sourcename,
deadtarget ? M_GetText("killed") : M_GetText("hit"),
targetname);
return;
}
else switch (source->type)
{
case MT_NULL:
switch(source->threshold)
{
case 42:
deathonly = true;
str = M_GetText("%s drowned.\n");
break;
case 43:
str = M_GetText("%s was %s by spikes.\n");
break;
case 44:
deathonly = true;
str = M_GetText("%s was crushed.\n");
break;
}
break;
case MT_EGGMANICO:
case MT_EGGMANBOX:
str = M_GetText("%s was %s by Eggman's nefarious TV magic.\n");
break;
case MT_SPIKE:
str = M_GetText("%s was %s by spikes.\n");
break;
default:
str = M_GetText("%s was %s by an environmental hazard.\n");
break;
}
}
else
{
// null source, environment kills
// TERRIBLE HACK for hit damage because P_DoPlayerPain moves the player...
// I'll put it back, I promise!
player->mo->z -= player->mo->momz+1;
if (P_PlayerTouchingSectorSpecial(player, 1, 2))
str = M_GetText("%s was %s by chemical water.\n");
else if (P_PlayerTouchingSectorSpecial(player, 1, 3))
str = M_GetText("%s was %s by molten lava.\n");
else if (P_PlayerTouchingSectorSpecial(player, 1, 4))
str = M_GetText("%s was %s by electricity.\n");
else if (deadtarget)
{
deathonly = true;
if (P_PlayerTouchingSectorSpecial(player, 1, 6)
|| P_PlayerTouchingSectorSpecial(player, 1, 7))
str = M_GetText("%s fell into a bottomless pit.\n");
else if (P_PlayerTouchingSectorSpecial(player, 1, 12))
str = M_GetText("%s asphyxiated in space.\n");
else
str = M_GetText("%s died.\n");
}
if (!str)
str = M_GetText("%s was %s by an environmental hazard.\n");
player->mo->z += player->mo->momz+1;
}
if (!str) // Should not happen! Unless we missed catching something above.
return;
// Don't log every hazard hit if they don't want us to.
if (!deadtarget && !cv_hazardlog.value)
return;
if (deathonly)
{
if (!deadtarget)
return;
CONS_Printf(str, targetname);
}
else
CONS_Printf(str, targetname, deadtarget ? M_GetText("killed") : M_GetText("hit"));
}
/** Checks if the level timer is over the timelimit and the round should end, /** Checks if the level timer is over the timelimit and the round should end,
* unless you are in overtime. In which case leveltime may stretch out beyond * unless you are in overtime. In which case leveltime may stretch out beyond
* timelimitintics and overtime's status will be checked here each tick. * timelimitintics and overtime's status will be checked here each tick.
@ -2150,7 +1951,7 @@ boolean P_CheckRacers(void)
numplayersingame++; numplayersingame++;
} }
if (numplayersingame > 1) // if there's more than one player in-game, this is safe to do if (numplayersingame >= nospectategrief) // prevent spectate griefing
{ {
// check if we just got unlucky and there was only one guy who was a problem // check if we just got unlucky and there was only one guy who was a problem
for (j = i+1; j < MAXPLAYERS; j++) for (j = i+1; j < MAXPLAYERS; j++)
@ -2819,7 +2620,6 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
/*if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT)) /*if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT))
{ {
P_AddPlayerScore(source->player, 1); //award points to tagger. P_AddPlayerScore(source->player, 1); //award points to tagger.
P_HitDeathMessages(player, inflictor, source);
if (gametype == GT_TAG) //survivor if (gametype == GT_TAG) //survivor
{ {
@ -3509,8 +3309,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (player->health < 0) if (player->health < 0)
player->health = 0; player->health = 0;
P_HitDeathMessages(player, inflictor, source);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
} }

View file

@ -6639,20 +6639,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_SSMINE_SHIELD: case MT_SSMINE_SHIELD:
case MT_FAKESHIELD: case MT_FAKESHIELD:
case MT_SINK_SHIELD: case MT_SINK_SHIELD:
/*if (mobj->health > 0 && mobj->target && mobj->target->player if ((mobj->health > 0
&& mobj->target->player->health > 0 && !mobj->target->player->spectator)
{
// Was this so hard? -- Handled this with K_UpdateHnextList instead of thinking it away...
if ((mobj->type == MT_ORBINAUT_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_ORBINAUT)
|| (mobj->type == MT_JAWZ_SHIELD && mobj->target->player->kartstuff[k_itemtype] != KITEM_JAWZ)
|| (mobj->movedir > 0 && ((UINT16)mobj->target->player->kartstuff[k_itemamount] < mobj->movedir))
|| (!mobj->target->player->kartstuff[k_itemheld]))
{
P_RemoveMobj(mobj);
return;
}
}
else*/ if ((mobj->health > 0
&& (!mobj->target || !mobj->target->player || mobj->target->player->health <= 0 || mobj->target->player->spectator)) && (!mobj->target || !mobj->target->player || mobj->target->player->health <= 0 || mobj->target->player->spectator))
|| (mobj->health <= 0 && mobj->z <= mobj->floorz) || (mobj->health <= 0 && mobj->z <= mobj->floorz)
|| P_CheckDeathPitCollide(mobj)) // When in death state || P_CheckDeathPitCollide(mobj)) // When in death state
@ -8250,16 +8237,24 @@ void P_MobjThinker(mobj_t *mobj)
return; return;
} }
P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->target->angle+ANGLE_180, mobj->target->radius),
mobj->target->y + P_ReturnThrustY(mobj, mobj->target->angle+ANGLE_180, mobj->target->radius), mobj->target->z);
mobj->angle = mobj->target->angle; mobj->angle = mobj->target->angle;
P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius),
mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z);
P_SetScale(mobj, mobj->target->scale); P_SetScale(mobj, mobj->target->scale);
if (mobj->target->player)
{ {
if (mobj->target->player->kartstuff[k_sneakertimer] > mobj->movecount) player_t *p = NULL;
P_SetMobjState(mobj, S_BOOSTFLAME); if (mobj->target->target && mobj->target->target->player)
mobj->movecount = mobj->target->player->kartstuff[k_sneakertimer]; p = mobj->target->target->player;
else if (mobj->target->player)
p = mobj->target->player;
if (p)
{
if (p->kartstuff[k_sneakertimer] > mobj->movecount)
P_SetMobjState(mobj, S_BOOSTFLAME);
mobj->movecount = p->kartstuff[k_sneakertimer];
}
} }
if (mobj->state == &states[S_BOOSTSMOKESPAWNER]) if (mobj->state == &states[S_BOOSTSMOKESPAWNER])
@ -8274,7 +8269,7 @@ void P_MobjThinker(mobj_t *mobj)
smoke->momy = mobj->target->momy/2; smoke->momy = mobj->target->momy/2;
smoke->momz = mobj->target->momz/2; smoke->momz = mobj->target->momz/2;
P_Thrust(smoke, mobj->target->angle+FixedAngle(P_RandomRange(135, 225)<<FRACBITS), P_RandomRange(0, 8) * mobj->target->scale); P_Thrust(smoke, mobj->angle+FixedAngle(P_RandomRange(135, 225)<<FRACBITS), P_RandomRange(0, 8) * mobj->target->scale);
} }
break; break;
case MT_SPARKLETRAIL: case MT_SPARKLETRAIL:
@ -8352,6 +8347,39 @@ void P_MobjThinker(mobj_t *mobj)
P_TeleportMove(mobj, destx, desty, mobj->target->z); P_TeleportMove(mobj, destx, desty, mobj->target->z);
break; break;
} }
case MT_ROCKETSNEAKER:
if (!mobj->target || !mobj->target->health)
{
P_RemoveMobj(mobj);
return;
}
if (mobj->target->player && !mobj->target->player->kartstuff[k_rocketsneakertimer])
{
mobj->flags &= ~MF_NOGRAVITY;
mobj->angle += ANGLE_45;
if (!mobj->extravalue2)
{
if (mobj->eflags & MFE_VERTICALFLIP)
mobj->z -= mobj->height;
else
mobj->z += mobj->height;
S_StartSound(mobj, mobj->info->deathsound);
P_SetObjectMomZ(mobj, 8*FRACUNIT, false);
P_InstaThrust(mobj, R_PointToAngle2(mobj->target->x, mobj->target->y, mobj->x, mobj->y)+ANGLE_90, 16*FRACUNIT);
mobj->momx += mobj->target->momx;
mobj->momy += mobj->target->momy;
mobj->momz += mobj->target->momz;
mobj->extravalue2 = 1;
}
else if (P_IsObjectOnGround(mobj))
{
P_RemoveMobj(mobj);
return;
}
}
break;
case MT_KARMAHITBOX: case MT_KARMAHITBOX:
if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator
|| (G_RaceGametype() || mobj->target->player->kartstuff[k_bumper])) || (G_RaceGametype() || mobj->target->player->kartstuff[k_bumper]))
@ -9340,7 +9368,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
case MT_JAWZ: case MT_JAWZ_DUD: case MT_JAWZ_SHIELD: case MT_JAWZ: case MT_JAWZ_DUD: case MT_JAWZ_SHIELD:
case MT_SSMINE: case MT_SSMINE_SHIELD: case MT_SSMINE: case MT_SSMINE_SHIELD:
case MT_BALLHOG: case MT_SINK: case MT_BALLHOG: case MT_SINK:
case MT_THUNDERSHIELD: case MT_THUNDERSHIELD: case MT_ROCKETSNEAKER:
P_SpawnShadowMobj(mobj); P_SpawnShadowMobj(mobj);
default: default:
break; break;
@ -11236,7 +11264,7 @@ ML_NOCLIMB : Direction not controllable
void P_SpawnHoopsAndRings(mapthing_t *mthing) void P_SpawnHoopsAndRings(mapthing_t *mthing)
{ {
mobj_t *mobj = NULL; mobj_t *mobj = NULL;
INT32 r, i; INT32 /*r,*/ i;
fixed_t x, y, z, finalx, finaly, finalz; fixed_t x, y, z, finalx, finaly, finalz;
sector_t *sec; sector_t *sec;
TVector v, *res; TVector v, *res;
@ -11310,8 +11338,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP); mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP);
if (maptol & TOL_XMAS) //if (maptol & TOL_XMAS)
P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); //P_SetMobjState(mobj, mobj->info->seestate + (i & 1));
mobj->z -= mobj->height/2; mobj->z -= mobj->height/2;
P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center.
@ -11320,8 +11348,10 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
// Link all the sprites in the hoop together // Link all the sprites in the hoop together
if (nextmobj) if (nextmobj)
{ {
mobj->hprev = nextmobj; P_SetTarget(&mobj->hprev, nextmobj);
mobj->hprev->hnext = mobj; P_SetTarget(&mobj->hprev->hnext, mobj);
//mobj->hprev = nextmobj;
//mobj->hprev->hnext = mobj;
} }
else else
mobj->hprev = mobj->hnext = NULL; mobj->hprev = mobj->hnext = NULL;
@ -11351,8 +11381,10 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
// Link all the collision sprites together. // Link all the collision sprites together.
mobj->hnext = NULL; mobj->hnext = NULL;
mobj->hprev = nextmobj; P_SetTarget(&mobj->hprev, nextmobj);
mobj->hprev->hnext = mobj; P_SetTarget(&mobj->hprev->hnext, mobj);
//mobj->hprev = nextmobj;
//mobj->hprev->hnext = mobj;
nextmobj = mobj; nextmobj = mobj;
} }
@ -11378,8 +11410,10 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
// Link all the collision sprites together. // Link all the collision sprites together.
mobj->hnext = NULL; mobj->hnext = NULL;
mobj->hprev = nextmobj; P_SetTarget(&mobj->hprev, nextmobj);
mobj->hprev->hnext = mobj; P_SetTarget(&mobj->hprev->hnext, mobj);
//mobj->hprev = nextmobj;
//mobj->hprev->hnext = mobj;
nextmobj = mobj; nextmobj = mobj;
} }
@ -11452,8 +11486,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP); mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP);
if (maptol & TOL_XMAS) //if (maptol & TOL_XMAS)
P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); //P_SetMobjState(mobj, mobj->info->seestate + (i & 1));
mobj->z -= mobj->height/2; mobj->z -= mobj->height/2;
P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center.
@ -11462,8 +11496,10 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
// Link all the sprites in the hoop together // Link all the sprites in the hoop together
if (nextmobj) if (nextmobj)
{ {
mobj->hprev = nextmobj; P_SetTarget(&mobj->hprev, nextmobj);
mobj->hprev->hnext = mobj; P_SetTarget(&mobj->hprev->hnext, mobj);
//mobj->hprev = nextmobj;
//mobj->hprev->hnext = mobj;
} }
else else
mobj->hprev = mobj->hnext = NULL; mobj->hprev = mobj->hnext = NULL;
@ -11504,8 +11540,10 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
// Link all the collision sprites together. // Link all the collision sprites together.
mobj->hnext = NULL; mobj->hnext = NULL;
mobj->hprev = nextmobj; P_SetTarget(&mobj->hprev, nextmobj);
mobj->hprev->hnext = mobj; P_SetTarget(&mobj->hprev->hnext, mobj);
//mobj->hprev = nextmobj;
//mobj->hprev->hnext = mobj;
nextmobj = mobj; nextmobj = mobj;
} }
@ -11513,6 +11551,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
return; return;
} }
else return; // srb2kart - no rings or ring-like objects in R1
/*
// Wing logo item. // Wing logo item.
else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum) else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum)
{ {
@ -11806,7 +11846,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
} }
} }
return; return;
} }*/
} }
// //

View file

@ -3287,6 +3287,7 @@ static void P_NetArchiveMisc(void)
WRITEUINT32(save_p, spbincoming); WRITEUINT32(save_p, spbincoming);
WRITEUINT8(save_p, spbplayer); WRITEUINT8(save_p, spbplayer);
WRITEUINT32(save_p, mapreset); WRITEUINT32(save_p, mapreset);
WRITEUINT8(save_p, nospectategrief);
// Is it paused? // Is it paused?
if (paused) if (paused)
@ -3393,6 +3394,7 @@ static inline boolean P_NetUnArchiveMisc(void)
spbincoming = READUINT32(save_p); spbincoming = READUINT32(save_p);
spbplayer = READUINT8(save_p); spbplayer = READUINT8(save_p);
mapreset = READUINT32(save_p); mapreset = READUINT32(save_p);
nospectategrief = READUINT8(save_p);
// Is it paused? // Is it paused?
if (READUINT8(save_p) == 0x2f) if (READUINT8(save_p) == 0x2f)

View file

@ -2209,7 +2209,7 @@ static void P_LevelInitStuff(void)
players[i].lives = cv_startinglives.value; players[i].lives = cv_startinglives.value;
} }
#else #else
players[i].lives = 1; players[i].lives = 1; // SRB2Kart
#endif #endif
players[i].realtime = countdown = countdown2 = 0; players[i].realtime = countdown = countdown2 = 0;
@ -3026,6 +3026,7 @@ boolean P_SetupLevel(boolean skipprecip)
spbincoming = 0; spbincoming = 0;
spbplayer = 0; spbplayer = 0;
mapreset = 0; mapreset = 0;
nospectategrief = 0;
// clear special respawning que // clear special respawning que
iquehead = iquetail = 0; iquehead = iquetail = 0;

View file

@ -36,6 +36,7 @@
#include "lua_hook.h" // LUAh_LinedefExecute #include "lua_hook.h" // LUAh_LinedefExecute
#include "k_kart.h" // SRB2kart #include "k_kart.h" // SRB2kart
#include "console.h" // CON_LogMessage
#ifdef HW3SOUND #ifdef HW3SOUND
#include "hardware/hw3sound.h" #include "hardware/hw3sound.h"
@ -4022,7 +4023,7 @@ DoneSection2:
player->kartstuff[k_floorboost] = 3; player->kartstuff[k_floorboost] = 3;
else else
player->kartstuff[k_floorboost] = 2; player->kartstuff[k_floorboost] = 2;
K_DoSneaker(player, false); K_DoSneaker(player, 0);
} }
break; break;
@ -4201,15 +4202,8 @@ DoneSection2:
if (player->pflags & PF_NIGHTSMODE) if (player->pflags & PF_NIGHTSMODE)
player->drillmeter += 48*20; player->drillmeter += 48*20;
if (netgame) if (netgame && player->laps >= (UINT8)cv_numlaps.value)
{ CON_LogMessage(va(M_GetText("%s has finished the race.\n"), player_names[player-players]));
if (player->laps >= (UINT8)cv_numlaps.value)
CONS_Printf(M_GetText("%s has finished the race.\n"), player_names[player-players]);
else if (player->laps == (UINT8)(cv_numlaps.value - 1))
CONS_Printf("%s started the final lap\n", player_names[player-players]);
else
CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1);
}
// SRB2Kart: save best lap for record attack // SRB2Kart: save best lap for record attack
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
@ -4235,12 +4229,23 @@ DoneSection2:
S_StartSound(NULL, sfx_s221); S_StartSound(NULL, sfx_s221);
} }
//
//player->starpostangle = player->starposttime = player->starpostnum = 0; //player->starpostangle = player->starposttime = player->starpostnum = 0;
//player->starpostx = player->starposty = player->starpostz = 0; //player->starpostx = player->starposty = player->starpostz = 0;
// Play the starpost sound for 'consistency' // Play the starpost sound for 'consistency'
// S_StartSound(player->mo, sfx_strpst); // S_StartSound(player->mo, sfx_strpst);
// Figure out how many are playing on the last lap, to prevent spectate griefing
if (!nospectategrief && player->laps >= (UINT8)(cv_numlaps.value - 1))
{
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
nospectategrief++;
}
}
} }
else if (player->starpostnum) else if (player->starpostnum)
{ {

View file

@ -45,6 +45,7 @@
// SRB2kart // SRB2kart
#include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems #include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems
#include "k_kart.h" #include "k_kart.h"
#include "console.h" // CON_LogMessage
#ifdef HW3SOUND #ifdef HW3SOUND
#include "hardware/hw3sound.h" #include "hardware/hw3sound.h"
@ -8238,7 +8239,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
// if (leveltime > 0 && timeinmap <= 0) // if (leveltime > 0 && timeinmap <= 0)
// return true; // return true;
if (player->pflags & PF_NIGHTSMODE) if (demoplayback)
{ {
focusangle = mo->angle; focusangle = mo->angle;
focusaiming = 0; focusaiming = 0;
@ -8345,9 +8346,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
input = InvAngle(input); input = InvAngle(input);
angle = thiscam->angle + input; angle = thiscam->angle + input;
if (demoplayback && player == &players[consoleplayer])
localangle = angle;
} }
if (!resetcalled && (leveltime > starttime) if (!resetcalled && (leveltime > starttime)
@ -8753,7 +8751,7 @@ boolean P_SpectatorJoinGame(player_t *player)
if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) if (P_IsLocalPlayer(player) && displayplayer != consoleplayer)
displayplayer = consoleplayer; displayplayer = consoleplayer;
CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); CON_LogMessage(va(M_GetText("%s entered the game.\n"), player_names[player-players]));
return true; // no more player->mo, cannot continue. return true; // no more player->mo, cannot continue.
} }
return false; return false;
@ -9173,7 +9171,7 @@ void P_PlayerThink(player_t *player)
if ((netgame || multiplayer) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing]) if ((netgame || multiplayer) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing])
{ {
player->pflags ^= PF_WANTSTOJOIN; player->pflags ^= PF_WANTSTOJOIN;
//player->powers[pw_flashing] = TICRATE + 1; player->powers[pw_flashing] = TICRATE/2 + 1;
/*if (P_SpectatorJoinGame(player)) /*if (P_SpectatorJoinGame(player))
return; // player->mo was removed.*/ return; // player->mo was removed.*/
} }

View file

@ -851,7 +851,7 @@ void R_SkyboxFrame(player_t *player)
{ {
aimingangle = player->aiming; aimingangle = player->aiming;
viewangle = player->mo->angle; viewangle = player->mo->angle;
if (!demoplayback && player->playerstate != PST_DEAD) if (/*!demoplayback && */player->playerstate != PST_DEAD)
{ {
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
{ {
@ -1128,7 +1128,7 @@ void R_SetupFrame(player_t *player, boolean skybox)
aimingangle = player->aiming; aimingangle = player->aiming;
viewangle = viewmobj->angle; viewangle = viewmobj->angle;
if (!demoplayback && player->playerstate != PST_DEAD) if (/*!demoplayback && */player->playerstate != PST_DEAD)
{ {
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
{ {

View file

@ -2699,7 +2699,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
player->jumpfactor = skin->jumpfactor; player->jumpfactor = skin->jumpfactor;
if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback || modeattacking)) /*if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback || modeattacking))
{ {
if (playernum == consoleplayer) if (playernum == consoleplayer)
CV_StealthSetValue(&cv_playercolor, skin->prefcolor); CV_StealthSetValue(&cv_playercolor, skin->prefcolor);
@ -2712,7 +2712,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
player->skincolor = skin->prefcolor; player->skincolor = skin->prefcolor;
if (player->mo) if (player->mo)
player->mo->color = player->skincolor; player->mo->color = player->skincolor;
} }*/
if (player->mo) if (player->mo)
P_SetScale(player->mo, player->mo->scale); P_SetScale(player->mo, player->mo->scale);

View file

@ -1955,18 +1955,22 @@ static void ST_overlayDrawer(void)
if (splitscreen) if (splitscreen)
{ {
INT32 splitflags = K_calcSplitFlags(0); INT32 splitflags = K_calcSplitFlags(0);
V_DrawThinString(2, (BASEVIDHEIGHT/2)-20, V_YELLOWMAP|V_HUDTRANSHALF|V_6WIDTHSPACE|splitflags, M_GetText("- SPECTATING -")); V_DrawThinString(2, (BASEVIDHEIGHT/2)-20, V_YELLOWMAP|V_HUDTRANSHALF|splitflags, M_GetText("- SPECTATING -"));
if (stplyr->pflags & PF_WANTSTOJOIN) if (stplyr->powers[pw_flashing])
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|V_6WIDTHSPACE|splitflags, M_GetText("Item - Cancel Join")); V_DrawString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - . . ."));
else if (stplyr->pflags & PF_WANTSTOJOIN)
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Cancel Join"));
/*else if (G_GametypeHasTeams()) /*else if (G_GametypeHasTeams())
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|V_6WIDTHSPACE|splitflags, M_GetText("Item - Join Team"));*/ V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Join Team"));*/
else else
V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|V_6WIDTHSPACE|splitflags, M_GetText("Item - Join Game")); V_DrawThinString(2, (BASEVIDHEIGHT/2)-10, V_HUDTRANSHALF|splitflags, M_GetText("Item - Join Game"));
} }
else else
{ {
V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -")); V_DrawString(2, BASEVIDHEIGHT-40, V_HUDTRANSHALF|V_YELLOWMAP, M_GetText("- SPECTATING -"));
if (stplyr->pflags & PF_WANTSTOJOIN) if (stplyr->powers[pw_flashing])
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - . . ."));
else if (stplyr->pflags & PF_WANTSTOJOIN)
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Cancel Join")); V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Cancel Join"));
/*else if (G_GametypeHasTeams()) /*else if (G_GametypeHasTeams())
V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Team"));*/ V_DrawString(2, BASEVIDHEIGHT-30, V_HUDTRANSHALF, M_GetText("Item - Join Team"));*/

View file

@ -296,9 +296,9 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
else else
data.match.pos[data.match.numplayers] = data.match.numplayers+1; data.match.pos[data.match.numplayers] = data.match.numplayers+1;
if (!rankingsmode && !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] != numplayersingame)) if (!rankingsmode && !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] < nospectategrief))
{ {
data.match.increase[i] = numplayersingame - data.match.pos[data.match.numplayers]; data.match.increase[i] = nospectategrief - data.match.pos[data.match.numplayers];
players[i].score += data.match.increase[i]; players[i].score += data.match.increase[i];
} }