Compare commits

...

42 commits

Author SHA1 Message Date
Eidolon
c2c3ae63a7 Merge branch 'wallspike-crash-fix' into 'master'
Add player pointer check in wall spike bounce

Closes #397

See merge request kart-krew-dev/ring-racers!78
2025-10-26 20:59:39 -05:00
Eidolon
721d5630a1 Add player pointer check in wall spike bounce 2025-10-26 20:37:51 -05:00
Eidolon
200e7b4014 Update modversion for RC9/final just in case 2025-10-26 19:48:56 -05:00
Eidolon
d4c2235e92 Update hashes 2025-10-26 19:26:36 -05:00
Ashnal
b9df8963cd Merge branch 'tally-idle-exp-grade-fix' into 'master'
Fixes grading for 0 EXP finishes

See merge request kart-krew-dev/ring-racers-internal!2973
2025-10-27 00:20:23 +00:00
Ashnal
719923e0cf Fixes grading for 0 EXP finishes 2025-10-27 00:20:22 +00:00
Eidolon
e864ba5255 Merge branch 'team-assist' into 'master'
Significantly more active Speed Assist in teamplay

See merge request kart-krew-dev/ring-racers-internal!2969
2025-10-26 18:51:49 -05:00
Eidolon
b0e1b14c9b Merge remote-tracking branch 'public/master' 2025-10-26 18:07:56 -05:00
Eidolon
15f66de4af Merge branch 'battle-exp-queue' into 'master'
Implement score-to-EXP scaling for Battle and Duel Race when Mobiums are not enabled.

See merge request kart-krew-dev/ring-racers!69
2025-10-26 18:00:03 -05:00
Freaky Mutant Man
6d344ad118 Implement score-to-EXP scaling for Battle and Duel Race when Mobiums are not enabled. 2025-10-26 18:00:03 -05:00
Eidolon
5f0121cca8 Merge branch 'eid-sonic-boom-color' into 'master'
Fix sonic boom colorization

Closes ring-racers#378

See merge request kart-krew-dev/ring-racers-internal!2971
2025-10-26 16:50:22 -05:00
Eidolon
36de3285bd Merge branch 'eid-battle-crash-fix' into 'master'
Use a different patch for striking levels in duel vote

Closes ring-racers#388

See merge request kart-krew-dev/ring-racers-internal!2972
2025-10-26 16:50:16 -05:00
Eidolon
ecb1927cf8 Merge branch 'shorter-caltrops' into 'master'
Set short fuse on "ring burn" caltrops

See merge request kart-krew-dev/ring-racers-internal!2970
2025-10-26 15:11:04 -05:00
Antonio Martinez
c28733f2f5 Speed Assist: Store team multiplier up front 2025-10-26 15:57:23 -04:00
Eidolon
e63ad4a681 Use a different patch for striking levels in duel vote 2025-10-26 14:17:38 -05:00
Eidolon
c087c8bacc Fix sonic boom colorization 2025-10-25 21:08:23 -05:00
Eidolon
8ce90ff211 Merge public master 2025-10-25 20:43:09 -05:00
Eidolon
b4c597161b Merge branch 'node0Bot' into 'master'
Fix node 0 being occupied by a bot in dedicated servers for clients

Closes #385

See merge request kart-krew-dev/ring-racers!77
2025-10-25 20:40:00 -05:00
JugadorXEI
2b7e1384ed Fix node 0 being occupied by a bot in dedicated servers for clients 2025-10-25 20:39:59 -05:00
Eidolon
176713d243 Merge branch 'cachedlevels-lua-why-broke' into 'master'
Fix cup->cachedlevels Lua getter to return entire cachedlevels list.

See merge request kart-krew-dev/ring-racers!73
2025-10-25 20:26:31 -05:00
Freaky Mutant Man
d363c71007 Fix cup->cachedlevels Lua getter to return entire cachedlevels list. 2025-10-25 20:26:31 -05:00
Eidolon
fd27994c48 Merge branch 'unarchiveLuaVarsAfterMapLoad' into 'master'
Unarchive Lua variables *after* loading a level in a demo (fixes #284)

Closes #284

See merge request kart-krew-dev/ring-racers!72
2025-10-25 20:16:52 -05:00
JugadorXEI
9244b9148e Unarchive Lua variables *after* loading a level in a demo (fixes #284) 2025-10-25 20:16:52 -05:00
Eidolon
5d697e378f Merge branch 'fix-long-message-crash' into 'master'
Fixed crash when sending a max character message

See merge request kart-krew-dev/ring-racers!68
2025-10-25 20:01:35 -05:00
Eidolon
0e431cd334 Merge branch 'reducevfx-battle' into 'master'
Disable overtime barrier animation/flashing when reducevfx is enabled.

See merge request kart-krew-dev/ring-racers!74
2025-10-25 19:57:12 -05:00
Eidolon
21a3489bcb Merge branch 'jesus-christ-music-remap-still-broke' into 'master'
Fix anti-Stereo Mode remap check in Lua music remapping function.

See merge request kart-krew-dev/ring-racers!75
2025-10-25 19:46:00 -05:00
Freaky Mutant Man
039ba6c3dc Fix anti-Stereo Mode remap check in Lua music remapping function. 2025-10-25 19:46:00 -05:00
Eidolon
de0fc7d3be Merge branch 'ring-bail-gp-life-loss' into 'master'
Fix unintended life loss in GP when finishing a race with -20 rings.

See merge request kart-krew-dev/ring-racers!76
2025-10-25 19:38:14 -05:00
Freaky Mutant Man
fcb7d38dce Fix unintended life loss in GP when finishing a race with -20 rings. 2025-10-25 19:38:13 -05:00
Eidolon
f984ecc5d7 Merge branch 'queue-cup-crash-fix-please' into 'master'
Fix crash when trying to queue cup while highlighting an empty square.

Closes #377

See merge request kart-krew-dev/ring-racers!71
2025-10-25 19:07:30 -05:00
Eidolon
4c2e540451 Merge branch 'chatclosefix' into 'master'
Fix softlocks surrounding chat input changes

Closes #373

See merge request kart-krew-dev/ring-racers!70
2025-10-25 19:06:27 -05:00
zander3312
59830a4ff0 Fix softlocks surrounding chat input changes 2025-10-25 19:06:26 -05:00
Antonio Martinez
af61408029 Set short fuse on "ring burn" caltrops 2025-10-25 20:03:56 -04:00
Antonio Martinez
668072c285 Significantly more active Speed Assist in teamplay 2025-10-25 19:56:38 -04:00
FreakyMutantMan
687bfb0e1d Disable overtime barrier animation/flashing when reducevfx is enabled. 2025-10-23 23:12:36 -07:00
Oni VelocitOni
121ac80b43 Merge branch 'fix-eggmark-burst' into 'master'
Fix eggmark bail occuring when last roulette was eggmark

Closes ring-racers#379 and ring-racers#384

See merge request kart-krew-dev/ring-racers-internal!2968
2025-10-24 04:11:58 +00:00
Oni VelocitOni
c9dce813e3 Merge branch 'tripwire-speed-reflect' into 'master'
Lower tripwire unstuck threshold (faster)

See merge request kart-krew-dev/ring-racers-internal!2967
2025-10-24 04:11:23 +00:00
Antonio Martinez
e6b21388bd Fix eggmark bail occuring when last roulette was eggmark 2025-10-22 18:35:31 -04:00
Antonio Martinez
7ac5a45979 Lower tripwire unstuck threshold (faster) 2025-10-22 17:52:13 -04:00
FreakyMutantMan
ea8acf33aa Fix crash when trying to queue cup while highlighting an empty square. 2025-10-22 11:20:32 -07:00
Eidolon
add76b17aa Update modversion for rc8/2.4 final 2025-10-21 20:47:53 -05:00
Skirlez
4bb035c7a5 Fixed crash when sending a max character message 2025-10-20 22:54:26 +03:00
21 changed files with 183 additions and 66 deletions

View file

@ -105,6 +105,7 @@ boolean server = true; // true or false but !server == client
#define client (!server)
boolean nodownload = false;
boolean serverrunning = false;
boolean connectedtodedicated = false;
INT32 serverplayer = 0;
char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support)
@ -1271,6 +1272,7 @@ static boolean SV_SendServerConfig(INT32 node)
netbuffer->u.servercfg.gamestate = (UINT8)gamestate;
netbuffer->u.servercfg.gametype = (UINT8)gametype;
netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame;
netbuffer->u.servercfg.dedicated = (boolean)dedicated;
netbuffer->u.servercfg.maxplayer = (UINT8)(min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxconnections.value));
netbuffer->u.servercfg.allownewplayer = cv_allownewplayer.value;
@ -2502,6 +2504,7 @@ static void Command_connect(void)
// we don't request a restart unless the filelist differs
server = false;
connectedtodedicated = false;
// Get the server node.
if (netgame)
@ -2761,6 +2764,7 @@ void CL_Reset(void)
multiplayer = false;
servernode = 0;
server = true;
connectedtodedicated = false;
doomcom->numnodes = 1;
doomcom->numslots = 1;
SV_StopServer();
@ -4274,6 +4278,11 @@ boolean Playing(void)
return (server && serverrunning) || (client && cl_mode == CL_CONNECTED);
}
boolean InADedicatedServer(void)
{
return Playing() && (dedicated || connectedtodedicated);
}
boolean SV_SpawnServer(void)
{
#ifdef TESTERS
@ -4376,6 +4385,7 @@ void SV_StartSinglePlayerServer(INT32 dogametype, boolean donetgame)
{
INT32 lastgametype = gametype;
server = true;
connectedtodedicated = false;
multiplayer = (modeattacking == ATTACKING_NONE);
joinedIP[0] = '\0'; // Make sure to empty this so that we don't save garbage when we start our own game. (because yes we use this for netgames too....)
@ -5002,6 +5012,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
G_SetGametype(netbuffer->u.servercfg.gametype);
modifiedgame = netbuffer->u.servercfg.modifiedgame;
connectedtodedicated = netbuffer->u.servercfg.dedicated;
memcpy(server_context, netbuffer->u.servercfg.server_context, 8);

View file

@ -231,6 +231,7 @@ struct serverconfig_pak
UINT8 gametype;
UINT8 modifiedgame;
boolean dedicated;
char server_context[8]; // Unique context id, generated at server startup.
@ -407,7 +408,7 @@ struct resultsall_pak
struct say_pak
{
char message[HU_MAXMSGLEN];
char message[HU_MAXMSGLEN + 1];
UINT8 target;
UINT8 flags;
UINT8 source;
@ -465,7 +466,7 @@ struct doomdata_t
client3cmd_pak client3pak; // 264 bytes(?)
client4cmd_pak client4pak; // 324 bytes(?)
servertics_pak serverpak; // 132495 bytes (more around 360, no?)
serverconfig_pak servercfg; // 773 bytes
serverconfig_pak servercfg; // 777 bytes
UINT8 textcmd[MAXTEXTCMD+2]; // 66049 bytes (wut??? 64k??? More like 258 bytes...)
char filetxpak[sizeof (filetx_pak)];// 139 bytes
char fileack[sizeof (fileack_pak)];
@ -558,6 +559,7 @@ extern boolean server;
extern boolean serverrunning;
#define client (!server)
extern boolean dedicated; // For dedicated server
extern boolean connectedtodedicated; // Client that is connected to a dedicated server.
extern UINT16 software_MAXPACKETLENGTH;
extern boolean acceptnewnode;
extern SINT8 servernode;
@ -670,6 +672,7 @@ void CL_UpdateServerList(void);
void CL_TimeoutServerList(void);
// Is there a game running
boolean Playing(void);
boolean InADedicatedServer(void);
// Advance client-to-client pubkey verification flow
void UpdateChallenges(void);

View file

@ -109,13 +109,13 @@ extern "C" consvar_t cv_lua_profile, cv_menuframeskip;
#define ASSET_HASH_BIOS_PK3 "36201c4690256d133dff7d3879436dff"
#define ASSET_HASH_SCRIPTS_PK3 "56be3c47192870c3265f19cf024e860e"
#define ASSET_HASH_GFX_PK3 "24a59ebaa74f253dbec55b00328accb9"
#define ASSET_HASH_TEXTURES_GENERAL_PK3 "55c5634c769b07a594dd4f309381c0df"
#define ASSET_HASH_TEXTURES_SEGAZONES_PK3 "9c39dfc868680ffd5f44a7269971e419"
#define ASSET_HASH_GFX_PK3 "9e91306851cb6619124b37533cfbf029"
#define ASSET_HASH_TEXTURES_GENERAL_PK3 "3b81c0645b9e0580c1675f2eb70c4250"
#define ASSET_HASH_TEXTURES_SEGAZONES_PK3 "2e87cb9dddae7d32656932fdad32b22f"
#define ASSET_HASH_TEXTURES_ORIGINALZONES_PK3 "f15f974dbd17c9ce1b60bf31cf12d246"
#define ASSET_HASH_CHARS_PK3 "5c8c34c5623acf984e3f654da4509126"
#define ASSET_HASH_FOLLOWERS_PK3 "4b61428e5f2ec806de398de8a5fba5f0"
#define ASSET_HASH_MAPS_PK3 "197c587c1e7fe38f327daa9b9baa0dcf"
#define ASSET_HASH_MAPS_PK3 "d744ac9747e078220a986ab295721182"
#define ASSET_HASH_UNLOCKS_PK3 "a4de35ba9f83829ced44dfc1316ba33e"
#define ASSET_HASH_STAFFGHOSTS_PK3 "4248d1fb6eb14c6b359f739c118249cc"
#define ASSET_HASH_SHADERS_PK3 "bc0b47744d457956db2ee9ea00f59eff"
@ -864,6 +864,7 @@ void D_SRB2Loop(void)
if (dedicated)
server = true;
connectedtodedicated = dedicated;
// Pushing of + parameters is now done back in D_SRB2Main, not here.
@ -1597,6 +1598,7 @@ void D_SRB2Main(void)
// for dedicated server
dedicated = M_CheckParm("-dedicated") != 0;
connectedtodedicated = dedicated;
if (dedicated)
{
usedTourney = true;

View file

@ -3517,15 +3517,7 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
}
// end of player read (the 0xFF marker)
// so this is where we are to read our lua variables (if possible!)
if (demoflags & DF_LUAVARS) // again, used for compability, lua shit will be saved to replays regardless of if it's even been loaded
{
if (!gL) // No Lua state! ...I guess we'll just start one...
LUA_ClearState();
// No modeattacking check, DF_LUAVARS won't be present here.
LUA_UnArchive(&demobuf, false);
}
// see the DF_LUAVARS if later, though.
splitscreen = 0;
@ -3547,6 +3539,18 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
G_InitNew((demoflags & DF_ENCORE) != 0, gamemap, true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer.
// so this is where we are to read our lua variables (if possible!)
// we read it here because Lua player variables can have mobj references,
// and not having the map loaded causes crashes if that's the case.
if (demoflags & DF_LUAVARS) // again, used for compability, lua shit will be saved to replays regardless of if it's even been loaded
{
if (!gL) // No Lua state! ...I guess we'll just start one...
LUA_ClearState();
// No modeattacking check, DF_LUAVARS won't be present here.
LUA_UnArchive(&demobuf, false);
}
for (i = 0; i < numslots; i++)
{
UINT8 j;

View file

@ -1229,6 +1229,7 @@ boolean I_InitTcpNetwork(void)
if (M_CheckParm("-server") || dedicated)
{
server = true;
connectedtodedicated = dedicated;
// If a number of clients (i.e. nodes) is specified, the server will wait for the clients
// to connect before starting.

View file

@ -740,8 +740,11 @@ static void K_SpawnOvertimeLaser(fixed_t x, fixed_t y, fixed_t scale)
case 0:
P_SetMobjState(mo, S_OVERTIME_BULB1);
if (leveltime & 1)
mo->frame += 1;
if (!cv_reducevfx.value)
{
if (leveltime & 1)
mo->frame += 1;
}
//P_SetScale(mo, mapobjectscale);
zpos += 35 * mo->scale * flip;
@ -749,10 +752,13 @@ static void K_SpawnOvertimeLaser(fixed_t x, fixed_t y, fixed_t scale)
case 1:
P_SetMobjState(mo, S_OVERTIME_LASER);
if (leveltime & 1)
mo->frame += 3;
else
mo->frame += (leveltime / 2) % 3;
if (!cv_reducevfx.value)
{
if (leveltime & 1)
mo->frame += 3;
else
mo->frame += (leveltime / 2) % 3;
}
//P_SetScale(mo, scale);
zpos += 346 * mo->scale * flip;
@ -763,8 +769,11 @@ static void K_SpawnOvertimeLaser(fixed_t x, fixed_t y, fixed_t scale)
case 2:
P_SetMobjState(mo, S_OVERTIME_BULB2);
if (leveltime & 1)
mo->frame += 1;
if (!cv_reducevfx.value)
{
if (leveltime & 1)
mo->frame += 1;
}
//P_SetScale(mo, mapobjectscale);
break;
@ -1029,6 +1038,8 @@ boolean K_EndBattleRound(player_t *victor)
// exiting, the round has already ended.
return false;
}
UINT32 topscore = 0;
if (gametyperules & GTR_POINTLIMIT)
{
@ -1037,7 +1048,27 @@ boolean K_EndBattleRound(player_t *victor)
// TODO: a "won the round" bool used for sorting
// position / intermission, so we aren't completely
// clobbering the individual scoring.
victor->roundscore = 100;
// This isn't quite the above TODO but it's something?
// For purposes of score-to-EXP conversion, we need to not lock the winner to an arbitrarily high score.
// Instead, let's find the highest score, and if they're not the highest scoring player,
// give them a bump so they *are* the highest scoring player.
for (INT32 i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
{
continue;
}
if ((&players[i])->roundscore > topscore)
{
topscore = (&players[i])->roundscore;
}
}
if (victor->roundscore <= topscore)
{
victor->roundscore = topscore + 3;
}
if (G_GametypeHasTeams() == true && victor->team != TEAM_UNASSIGNED)
{

View file

@ -227,7 +227,7 @@ void K_UpdateMatchRaceBots(void)
{
const UINT16 defaultbotskin = R_BotDefaultSkin();
UINT8 difficulty;
UINT8 pmax = (dedicated ? MAXPLAYERS-1 : MAXPLAYERS);
UINT8 pmax = (InADedicatedServer() ? MAXPLAYERS-1 : MAXPLAYERS);
UINT8 numplayers = 0;
UINT8 numbots = 0;
UINT8 numwaiting = 0;
@ -343,12 +343,7 @@ void K_UpdateMatchRaceBots(void)
if (numbots < wantedbots)
{
// We require MORE bots!
UINT8 newplayernum = 0;
if (dedicated)
{
newplayernum = 1;
}
UINT8 newplayernum = InADedicatedServer() ? 1 : 0;
// Rearrange usable bot skins list to prevent gaps for randomised selection
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)

View file

@ -1275,7 +1275,7 @@ boolean K_KartSolidBounce(mobj_t *bounceMobj, mobj_t *solidMobj)
if (solidMobj->type == MT_WALLSPIKE)
{
if (bounceMobj->hitlag)
if (bounceMobj->player && bounceMobj->hitlag)
{
bounceMobj->player->justbumped = bumptime;
return false;
@ -10510,12 +10510,18 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
UINT8 counted = 0;
UINT32 firstRaw = 0;
// We want the average position of the back quarter...
UINT32 requiredPosition = ((D_NumPlayersInRace()*3)/4) - 1;
// ...except in teamplay, where we want the true average.
if (g_teamplay)
requiredPosition = 1;
for (UINT8 i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] == false || players[i].spectator == true || players[i].exiting)
continue;
if (players[i].position != 1 && players[i].position >= ((D_NumPlayersInRace()*3)/4) - 1) // Not in 1st, but also back quarter of the average (-1 guy, for leeway)
if (players[i].position != 1 && players[i].position >= requiredPosition)
{
counted++;
average += K_UndoMapScaling(players[i].distancetofinish);
@ -10537,6 +10543,15 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
UINT32 TOO_CLOSE = average + 6500; // Start gaining here, lose if closer
UINT32 WAY_TOO_CLOSE = average + 5500; // Lose at max rate here
fixed_t comeback = K_TeamComebackMultiplier(player);
if (comeback > FRACUNIT)
{
REALLY_FAR = FixedDiv(REALLY_FAR, comeback);
TOO_CLOSE = FixedDiv(TOO_CLOSE, comeback);
WAY_TOO_CLOSE = FixedDiv(WAY_TOO_CLOSE, comeback);
}
fixed_t MAX_GAIN_PER_SEC = FRACUNIT/20; // % assist to gain per sec when REALLY_FAR
fixed_t MAX_LOSS_PER_SEC = FRACUNIT/5; // % assist to lose per sec when WAY_TOO_CLOSE
@ -11043,7 +11058,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAIL);
P_SetTarget(&bail->target, player->mo);
if (player->itemRoulette.eggman || player->eggmanexplode)
if ((player->itemRoulette.active && player->itemRoulette.eggman) || player->eggmanexplode > 0)
{
player->markedfordeath = true;
player->eggmanexplode = 1;
@ -11125,7 +11140,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->preventfailsafe)
player->preventfailsafe--;
if (player->tripwireUnstuck > 150)
UINT8 unstuckthreshold = (onground) ? 80 : 40;
if (player->tripwireUnstuck > unstuckthreshold)
{
player->tripwireUnstuck = 0;
K_DoIngameRespawn(player);
@ -15318,7 +15335,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
{
player->momentboost += 3;
angle_t flingangle = player->mo->angle + ((P_RandomByte(PR_ITEM_RINGS) & 1) ? -ANGLE_90 : ANGLE_90);
P_FlingBurst(player, flingangle, MT_DEBTSPIKE, 0, 3 * FRACUNIT / 2, 20, 4*FRACUNIT);
P_FlingBurst(player, flingangle, MT_DEBTSPIKE, TICRATE/2, 3 * FRACUNIT / 2, 20, 4*FRACUNIT);
S_StartSound(player->mo, sfx_gshae);
}

View file

@ -1098,7 +1098,7 @@ void M_UpdateMenuCMD(UINT8 i, boolean bailrequired, boolean chat_open)
menucmd[i].buttons = 0;
// Eat inputs made when chat is open
if (chat_open)
if (chat_open && pausemenu.closing)
return;
if (G_PlayerInputDown(i, gc_screenshot, mp)) { menucmd[i].buttons |= MBT_SCREENSHOT; }

View file

@ -345,13 +345,10 @@ void level_tally_t::Init(player_t *player)
}
}
if ((gametypes[gt]->rules & GTR_CIRCUIT) == GTR_CIRCUIT)
if ((gametypes[gt]->rules & GTR_CIRCUIT) == GTR_CIRCUIT && K_GetNumGradingPoints() > 0) // EXP should be a rule type, but here we are
{
if (player->exp)
{
exp = player->exp;
totalExp = EXP_TARGET;
}
exp = static_cast<UINT16>(std::max<fixed_t>(player->exp, 0)); // The scoring calc doesn't subtract anymore, so using 0 is okay and will not wrap
totalExp = EXP_TARGET;
}
if (battleprisons)

View file

@ -2094,7 +2094,7 @@ static void Y_InitVoteDrawing(void)
INT32 i = 0, j = 0;
vote_draw.ruby_icon = W_CachePatchName("RUBYICON", PU_STATIC);
vote_draw.strike_icon = W_CachePatchName("K_NOBLNS", PU_STATIC);
vote_draw.strike_icon = W_CachePatchName("VT_LSTRK", PU_STATIC);
for (i = 0; i < PLANET_FRAMES; i++)
{

View file

@ -489,7 +489,8 @@ static int lib_mMusicRemap(lua_State *L)
}
// Do not allow Lua to remap Stereo Mode tunes.
if (strncmp("stere", tune_id, 5))
if (strlen(tune_id) > 5
&& toupper(tune_id[0]) == 'S' && toupper(tune_id[1]) == 'T' && toupper(tune_id[2]) == 'E' && toupper(tune_id[3]) == 'R' && toupper(tune_id[4]) == 'E')
{
return LUA_ErrStereo(L, tune_id);
}

View file

@ -351,13 +351,12 @@ static int cup_get(lua_State *L)
lua_pushstring(L, cup->levellist[i]);
lua_rawseti(L, -2, 1 + i);
}
//return UNIMPLEMENTED;
break;
case cup_cachedlevels:
lua_createtable(L, ((cup->numlevels) + (cup->numbonus)), 0);
for (size_t i = 0; i < ((cup->numlevels) + (cup->numbonus)); i++)
for (size_t i = 0; i < CUPCACHE_MAX; i++)
{
lua_pushnumber(L, cup->cachedlevels[i]);
lua_pushnumber(L, (cup->cachedlevels[i])+1);
lua_rawseti(L, -2, 1 + i);
}
break;

View file

@ -525,7 +525,7 @@ void M_CupSelectHandler(INT32 choice)
{
M_SetMenuDelay(pid);
if (cupgrid.builtgrid[CUPMENU_CURSORID] == &dummy_lostandfound)
if ((cupgrid.builtgrid[CUPMENU_CURSORID] == &dummy_lostandfound) || (cupgrid.builtgrid[CUPMENU_CURSORID] == NULL))
S_StartSound(NULL, sfx_gshe7);
else if (!M_IsCupQueueable(cupgrid.builtgrid[CUPMENU_CURSORID]))

View file

@ -15,6 +15,7 @@
#include "../../d_netcmd.h"
#include "../../i_time.h"
#include "../../k_menu.h"
#include "../../hu_stuff.h"
#include "../../k_grandprix.h" // K_CanChangeRules
#include "../../m_cond.h"
#include "../../s_sound.h"
@ -125,6 +126,9 @@ void M_OpenPauseMenu(void)
pausemenu.openoffset.dist = 0;
pausemenu.closing = false;
// Fix specific input error regarding closing netgame chat with escape while a controller is connected (only on Windows?)
chat_keydown = false;
itemOn = currentMenu->lastOn = mpause_continue; // Make sure we select "RESUME GAME" by default
// Now the hilarious balancing act of deciding what options should be enabled and which ones shouldn't be!

View file

@ -8208,6 +8208,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
invinc_rotation_delay = 8;
}
boolean updatecolor = false;
if ((trans >= NUMTRANSMAPS) || mobj->target->player->flamedash || mobj->target->player->tripwirePass < TRIPWIRE_BOOST)
{
// never show for flameshield dash, below tripwire minimum or transparency invalid
@ -8227,6 +8228,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
// < 150% flickering normally
mobj->renderflags |= RF_DONTDRAW;
}
updatecolor = true;
}
else
{
@ -8239,6 +8241,24 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
}
mobj->renderflags |= (mobj->target->renderflags & RF_DONTDRAW);
updatecolor = true;
if (blastermode == !(mobj->flags2 & MF2_AMBUSH))
{
mobj->flags2 ^= MF2_AMBUSH;
if (blastermode)
{
P_SetMobjState(mobj, (mobj->extravalue1) ? S_TRIPWIREBOOST_BLAST_BOTTOM : S_TRIPWIREBOOST_BLAST_TOP);
}
else
{
P_SetMobjState(mobj, (mobj->extravalue1) ? S_TRIPWIREBOOST_BOTTOM : S_TRIPWIREBOOST_TOP);
}
}
}
if (updatecolor)
{
if (mobj->target->player->invincibilitytimer > 0)
{
if (mobj->target->player->invincibilitytimer > itemtime+(2*TICRATE))
@ -8261,19 +8281,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->color = SKINCOLOR_NONE;
mobj->colorized = false;
}
if (blastermode == !(mobj->flags2 & MF2_AMBUSH))
{
mobj->flags2 ^= MF2_AMBUSH;
if (blastermode)
{
P_SetMobjState(mobj, (mobj->extravalue1) ? S_TRIPWIREBOOST_BLAST_BOTTOM : S_TRIPWIREBOOST_BLAST_TOP);
}
else
{
P_SetMobjState(mobj, (mobj->extravalue1) ? S_TRIPWIREBOOST_BOTTOM : S_TRIPWIREBOOST_TOP);
}
}
}
}

View file

@ -1330,7 +1330,7 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
if (grandprixinfo.gp == true
&& grandprixinfo.eventmode != GPEVENT_SPECIAL
&& player->bot == false && losing == false)
&& player->bot == false && losing == false && player->hudrings > 0)
{
const UINT8 lifethreshold = 20;

View file

@ -358,6 +358,7 @@ boolean I_InitNetwork(void)
if (M_CheckParm("-server") || dedicated)
{
server = true;
connectedtodedicated = dedicated;
// If a number of clients (i.e. nodes) is specified, the server will wait for the clients
// to connect before starting.

View file

@ -4,7 +4,7 @@
// it's only for detection of the version the player is using so the MS can alert them of an update.
// Only set it higher, not lower, obviously.
// Note that we use this to help keep internal testing in check; this is why v2.0 is not version "2".
#define MODVERSION 10
#define MODVERSION 12
// Define this as a prerelease version suffix
#define BETAVERSION "RC7"
#define BETAVERSION "RC9"

View file

@ -260,6 +260,7 @@ static inline VOID OpenTextConsole(void)
HANDLE ci, co;
const BOOL tco = M_CheckParm("-console") != 0;
dedicated = M_CheckParm("-dedicated") != 0;
connectedtodedicated = dedicated;
if (!(dedicated || tco))
return;
FreeConsole();

View file

@ -162,6 +162,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
boolean completed[MAXPLAYERS];
INT32 numplayersingame = 0;
boolean getmainplayer = false;
UINT32 topscore = 0, btopemeralds = 0;
// Initialize variables
if (rankingsmode > 1)
@ -190,6 +191,27 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
data.increase[i] = INT16_MIN;
continue;
}
// for getting the proper maximum value for score-to-EXP conversion
if (gametype == GT_BATTLE)
{
if ((&players[i])->roundscore > topscore)
{
topscore = (&players[i])->roundscore;
}
if (K_NumEmeralds(&players[i]) > btopemeralds)
{
btopemeralds = K_NumEmeralds(&players[i]); // necessary so non-emerald wins can still get max EXP if no one else is holding more emeralds
}
}
if (K_InRaceDuel() == true)
{
if (((UINT32)(&players[i])->duelscore) > topscore)
{
topscore = (&players[i])->duelscore;
}
}
if (!rankingsmode)
data.increase[i] = INT16_MIN;
@ -294,12 +316,33 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
if (powertype == PWRLV_DISABLED)
{
UINT8 pointgetters = numplayersingame + spectateGriefed;
UINT32 scoreconversion = 0;
UINT32 pscore = 0;
// accept players that nocontest, but not bots
if (data.pos[data.numplayers] <= pointgetters &&
!((players[i].pflags & PF_NOCONTEST) && players[i].bot))
{
data.increase[i] = K_CalculateGPRankPoints((&players[i])->exp, data.pos[data.numplayers], pointgetters);
if (gametype == GT_BATTLE)
{
pscore = (&players[i])->roundscore + K_NumEmeralds(&players[i]);
scoreconversion = FixedRescale(pscore, 0, topscore + btopemeralds, Easing_Linear, EXP_MIN, EXP_MAX);
data.increase[i] = K_CalculateGPRankPoints(scoreconversion, data.pos[data.numplayers], pointgetters);
}
else
{
// For Duel scoring, convert duelscore into EXP.
if (K_InRaceDuel())
{
pscore = (&players[i])->duelscore;
scoreconversion = FixedRescale(pscore, 0, topscore, Easing_Linear, EXP_MIN, EXP_MAX);
data.increase[i] = K_CalculateGPRankPoints(scoreconversion, data.pos[data.numplayers], pointgetters);
}
else
{
data.increase[i] = K_CalculateGPRankPoints((&players[i])->exp, data.pos[data.numplayers], pointgetters);
}
}
if (data.winningteam != TEAM_UNASSIGNED)
{