Merge branch 'master' into item-bungus

This commit is contained in:
Sally Coolatta 2022-08-23 23:42:21 -04:00
commit 429f61966e
32 changed files with 662 additions and 448 deletions

View file

@ -301,13 +301,25 @@ target_compile_definitions(SRB2SDL2 PRIVATE -DCMAKECONFIG)
# ${SRB2_BLUA_HEADERS}
#)
## strip debug symbols into separate file when using gcc.
## to be consistent with Makefile, don't generate for OS X.
if((CMAKE_COMPILER_IS_GNUCC) AND NOT (${CMAKE_SYSTEM} MATCHES Darwin))
if((${CMAKE_BUILD_TYPE} MATCHES Debug) OR (${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo))
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
set(OBJCOPY_ONLY_KEEP_DEBUG "--only-keep-debug")
endif()
message(STATUS "Will make separate debug symbols in *.debug")
add_custom_command(TARGET SRB2SDL2 POST_BUILD
COMMAND ${OBJCOPY} ${OBJCOPY_ONLY_KEEP_DEBUG} $<TARGET_FILE:SRB2SDL2> $<TARGET_FILE:SRB2SDL2>.debug
COMMAND ${OBJCOPY} --strip-debug $<TARGET_FILE:SRB2SDL2>
COMMAND ${OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE:SRB2SDL2>.debug $<TARGET_FILE:SRB2SDL2>
)
endif()
endif()
add_subdirectory(sdl)
add_subdirectory(objects)
if(${CMAKE_SYSTEM} MATCHES Windows)
add_subdirectory(win32)
endif()
if(NOT ${SRB2_SDL2_AVAILABLE})
message(FATAL_ERROR "There are no targets available to build an SRB2Kart executable. :(")
endif()

View file

@ -1641,34 +1641,14 @@ void CV_SaveVars(UINT8 **p, boolean in_demo)
// the client will reset all netvars to default before loading
WRITEUINT16(*p, 0x0000);
for (cvar = consvar_vars; cvar; cvar = cvar->next)
if (((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) || (in_demo && cvar->netid == cv_numlaps.netid))
if ((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar))
{
if (in_demo)
WRITESTRING(*p, cvar->name);
else
WRITEUINT16(*p, cvar->netid);
// UGLY HACK: Save proper lap count in net replays
if (in_demo && cvar->netid == cv_numlaps.netid)
{
if (cv_basenumlaps.value &&
(!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value))
)
{
WRITESTRING(*p, cv_basenumlaps.string);
}
else
{
char buf[9];
sprintf(buf, "%d", mapheaderinfo[gamemap - 1]->numlaps);
WRITESTRING(*p, buf);
}
}
else
{
WRITESTRING(*p, cvar->string);
}
WRITESTRING(*p, cvar->string);
WRITEUINT8(*p, false);
++count;

View file

@ -888,7 +888,11 @@ void D_SRB2Loop(void)
if (!singletics)
{
INT64 elapsed = (INT64)(finishprecise - enterprecise);
if (elapsed > 0 && (INT64)capbudget > elapsed)
// in the case of "match refresh rate" + vsync, don't sleep at all
const boolean vsync_with_match_refresh = cv_vidwait.value && cv_fpscap.value == 0;
if (elapsed > 0 && (INT64)capbudget > elapsed && !vsync_with_match_refresh)
{
I_SleepDuration(capbudget - (finishprecise - enterprecise));
}

View file

@ -102,7 +102,6 @@ static void Got_DiscordInfo(UINT8 **cp, INT32 playernum);
static void PointLimit_OnChange(void);
static void TimeLimit_OnChange(void);
static void NumLaps_OnChange(void);
static void BaseNumLaps_OnChange(void);
static void Mute_OnChange(void);
static void AutoBalance_OnChange(void);
@ -141,7 +140,6 @@ static void Color4_OnChange(void);
static void DummyConsvar_OnChange(void);
static void SoundTest_OnChange(void);
static void BaseNumLaps_OnChange(void);
static void KartFrantic_OnChange(void);
static void KartSpeed_OnChange(void);
static void KartEncore_OnChange(void);
@ -467,10 +465,9 @@ static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"},
consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange);
static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}};
consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange);
static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
consvar_t cv_numlaps = CVAR_INIT ("numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange);
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange);
static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {MAX_LAPS, "MAX"}, {0, "Map default"}, {0, NULL}};
consvar_t cv_numlaps = CVAR_INIT ("numlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, numlaps_cons_t, NumLaps_OnChange);
// Point and time limits for every gametype
INT32 pointlimits[NUMGAMETYPES];
@ -691,7 +688,6 @@ void D_RegisterServerCommands(void)
// misc
CV_RegisterVar(&cv_pointlimit);
CV_RegisterVar(&cv_numlaps);
CV_RegisterVar(&cv_basenumlaps);
CV_RegisterVar(&cv_autobalance);
CV_RegisterVar(&cv_teamscramble);
@ -4480,24 +4476,6 @@ static void PointLimit_OnChange(void)
CONS_Printf(M_GetText("Point limit disabled\n"));
}
static void NumLaps_OnChange(void)
{
if (K_CanChangeRules() == false)
{
return;
}
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
&& (cv_numlaps.value > mapheaderinfo[gamemap - 1]->numlaps))
{
CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps);
}
// Just don't be verbose
if (gametyperules & GTR_CIRCUIT)
CONS_Printf(M_GetText("Number of laps set to %d\n"), cv_numlaps.value);
}
static void NetTimeout_OnChange(void)
{
connectiontimeout = (tic_t)cv_nettimeout.value;
@ -5759,22 +5737,24 @@ static void Command_ShowTime_f(void)
}
// SRB2Kart: On change messages
static void BaseNumLaps_OnChange(void)
static void NumLaps_OnChange(void)
{
if (K_CanChangeRules() == true)
if (K_CanChangeRules() == false)
{
const char *str = va("%d", cv_basenumlaps.value);
return;
}
if (cv_basenumlaps.value == 0)
{
str = "map defaults";
}
CONS_Printf(M_GetText("Number of laps will be changed to %s next round.\n"), str);
if (leveltime < starttime)
{
CONS_Printf(M_GetText("Number of laps have been set to %d.\n"), cv_numlaps.value);
numlaps = (UINT8)cv_numlaps.value;
}
else
{
CONS_Printf(M_GetText("Number of laps will be set to %d next round.\n"), cv_numlaps.value);
}
}
static void KartFrantic_OnChange(void)
{
if (K_CanChangeRules() == false)

View file

@ -42,7 +42,6 @@ extern consvar_t cv_itemrespawn;
extern consvar_t cv_pointlimit;
extern consvar_t cv_timelimit;
extern consvar_t cv_numlaps;
extern consvar_t cv_basenumlaps;
extern UINT32 timelimitintics;
extern consvar_t cv_allowexitlevel;

View file

@ -258,6 +258,7 @@ typedef enum
#define TRICKDELAY (TICRATE/4)
#define TUMBLEBOUNCES 3
#define TUMBLEGRAVITY (4*FRACUNIT)
#define BALLHOGINCREMENT (7)
@ -541,6 +542,7 @@ typedef struct player_s
INT16 totalring; // Total number of rings obtained for GP
tic_t realtime; // integer replacement for leveltime
UINT8 laps; // Number of laps (optional)
UINT8 latestlap;
INT32 starpostnum; // The number of the last starpost you hit
UINT8 ctfteam; // 0 == Spectator, 1 == Red, 2 == Blue

View file

@ -700,6 +700,7 @@ extern INT16 scramblecount; //for CTF team scramble
extern INT32 cheats;
// SRB2kart
extern UINT8 numlaps;
extern UINT8 gamespeed;
extern boolean franticitems;
extern boolean encoremode, prevencoremode;

View file

@ -1999,6 +1999,7 @@ void G_BeginRecording(void)
WRITEUINT8(demo_p, demoflags);
WRITEUINT8(demo_p, gametype & 0xFF);
WRITEUINT8(demo_p, numlaps);
// file list
m = demo_p;/* file count */
@ -2429,6 +2430,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
p += 16; // map md5
flags = READUINT8(p); // demoflags
p++; // gametype
p++; // numlaps
G_SkipDemoExtraFiles(&p);
aflags = flags & (DF_TIMEATTACK|DF_BREAKTHECAPSULES);
@ -2486,6 +2488,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
p += 16; // mapmd5
flags = READUINT8(p);
p++; // gametype
p++; // numlaps
G_SkipDemoExtraFiles(&p);
if (!(flags & aflags))
{
@ -2600,6 +2603,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
}
pdemo->gametype = READUINT8(info_p);
pdemo->numlaps = READUINT8(info_p);
pdemo->addonstatus = G_CheckDemoExtraFiles(&info_p, true);
info_p += 4; // RNG seed
@ -2626,20 +2630,11 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
if (!stricmp(kartspeed_cons_t[j].strvalue, svalue))
pdemo->kartspeed = kartspeed_cons_t[j].value;
}
else if (netid == cv_basenumlaps.netid && pdemo->gametype == GT_RACE)
pdemo->numlaps = atoi(svalue);
}
if (pdemoflags & DF_ENCORE)
pdemo->kartspeed |= DF_ENCORE;
/*// Temporary info until this is actually present in replays.
(void)extrainfo_p;
sprintf(pdemo->winnername, "transrights420");
pdemo->winnerskin = 1;
pdemo->winnercolor = SKINCOLOR_MOONSET;
pdemo->winnertime = 6666;*/
// Read standings!
count = 0;
@ -2835,6 +2830,7 @@ void G_DoPlayDemo(char *defdemoname)
demoflags = READUINT8(demo_p);
gametype = READUINT8(demo_p);
G_SetGametype(gametype);
numlaps = READUINT8(demo_p);
if (demo.title) // Titledemos should always play and ought to always be compatible with whatever wadlist is running.
G_SkipDemoExtraFiles(&demo_p);
@ -3258,6 +3254,7 @@ void G_AddGhost(char *defdemoname)
}
p++; // gametype
p++; // numlaps
G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts.
switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
@ -3475,7 +3472,7 @@ void G_UpdateStaffGhostName(lumpnum_t l)
}
p++; // Gametype
p++; // numlaps
G_SkipDemoExtraFiles(&p);
switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)

View file

@ -303,6 +303,7 @@ INT32 cheats; //for multiplayer cheat commands
// SRB2Kart
// Cvars that we don't want changed mid-game
UINT8 numlaps; // Removed from Cvar hell
UINT8 gamespeed; // Game's current speed (or difficulty, or cc, or etc); 0 for easy, 1 for normal, 2 for hard
boolean encoremode = false; // Encore Mode currently enabled?
boolean prevencoremode;
@ -2198,6 +2199,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
INT32 khudcardanimation;
INT16 totalring;
UINT8 laps;
UINT8 latestlap;
UINT16 skincolor;
INT32 skin;
UINT32 availabilities;
@ -2284,6 +2286,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
khudfault = 0;
nocontrol = 0;
laps = 0;
latestlap = 0;
totalring = 0;
roundscore = 0;
exiting = 0;
@ -2324,6 +2327,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
nocontrol = players[player].nocontrol;
laps = players[player].laps;
latestlap = players[player].latestlap;
totalring = players[player].totalring;
roundscore = players[player].roundscore;
@ -2380,6 +2385,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->karthud[khud_cardanimation] = khudcardanimation;
p->laps = laps;
p->latestlap = latestlap;
p->totalring = totalring;
p->bot = bot;
@ -3610,11 +3616,14 @@ static void G_DoCompleted(void)
wipegamestate = GS_NULL;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
{
// SRB2Kart: exitlevel shouldn't get you the points
if (!players[i].exiting && !(players[i].pflags & PF_NOCONTEST))
{
clientPowerAdd[i] = 0;
if (players[i].bot)
{
K_FakeBotResults(&players[i]);
@ -3632,6 +3641,7 @@ static void G_DoCompleted(void)
G_PlayerFinishLevel(i); // take away cards and stuff
}
}
// play some generic music if there's no win/cool/lose music going on (for exitlevel commands)
if ((gametyperules & GTR_CIRCUIT) && ((multiplayer && demo.playback) || j == r_splitscreen+1) && (cv_inttime.value > 0))

View file

@ -2421,7 +2421,7 @@ static void HU_DrawRankings(void)
if (circuitmap)
{
V_DrawCenteredString(64, 8, 0, "LAP COUNT");
V_DrawCenteredString(64, 16, hilicol, va("%d", cv_numlaps.value));
V_DrawCenteredString(64, 16, hilicol, va("%d", numlaps));
}
V_DrawCenteredString(256, 8, 0, "GAME SPEED");

View file

@ -675,6 +675,12 @@ static inline BlockItReturn_t PIT_LightningShieldAttack(mobj_t *thing)
return BMIT_ABORT;
}
if (thing == NULL || P_MobjWasRemoved(thing))
{
// Invalid?
return BMIT_ABORT;
}
if (thing == lightningSource)
{
// Don't explode yourself!!

View file

@ -1716,7 +1716,7 @@ static void K_DrawKartPositionNum(INT32 num)
{
localpatch = kp_winnernum[(leveltime % (NUMWINFRAMES*3)) / 3];
}
else if (stplyr->laps >= cv_numlaps.value || stplyr->exiting) // Check for the final lap, or won
else if (stplyr->laps >= numlaps || stplyr->exiting) // Check for the final lap, or won
{
boolean useRedNums = K_IsPlayerLosing(stplyr);
@ -2347,7 +2347,7 @@ static void K_drawKartLapsAndRings(void)
V_DrawScaledPatch(fx, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_splitlapflag);
V_DrawScaledPatch(fx+22, fy, V_HUDTRANS|V_SLIDEIN|splitflags, frameslash);
if (cv_numlaps.value >= 10)
if (numlaps >= 10)
{
UINT8 ln[2];
ln[0] = ((stplyr->laps / 10) % 10);
@ -2356,8 +2356,8 @@ static void K_drawKartLapsAndRings(void)
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
ln[0] = ((abs(cv_numlaps.value) / 10) % 10);
ln[1] = (abs(cv_numlaps.value) % 10);
ln[0] = ((numlaps / 10) % 10);
ln[1] = (numlaps % 10);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
@ -2365,7 +2365,7 @@ static void K_drawKartLapsAndRings(void)
else
{
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(stplyr->laps) % 10]);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(cv_numlaps.value) % 10]);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(numlaps) % 10]);
}
// Rings
@ -2403,7 +2403,7 @@ static void K_drawKartLapsAndRings(void)
{
// Laps
V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_lapsticker);
V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", min(stplyr->laps, cv_numlaps.value), cv_numlaps.value));
V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", min(stplyr->laps, numlaps), numlaps));
// Rings
if (!uselives)
@ -4377,7 +4377,7 @@ static void K_drawLapStartAnim(void)
kp_lapanim_hand[stplyr->karthud[khud_laphand]-1], NULL);
}
if (stplyr->laps == (UINT8)(cv_numlaps.value))
if (stplyr->laps == (UINT8)(numlaps))
{
newval = (62 - (32 * max(0, progress - 76))) * FRACUNIT;
oldval = (62 - (32 * max(0, progressOld - 76))) * FRACUNIT;

View file

@ -357,15 +357,15 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
/*Invincibility*/ { 0, 0, 0, 0, 3, 4, 6, 9 }, // Invincibility
/*Banana*/ { 2, 3, 1, 0, 0, 0, 0, 0 }, // Banana
/*Eggman Monitor*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor
/*Orbinaut*/ { 5, 4, 2, 2, 0, 0, 0, 0 }, // Orbinaut
/*Jawz*/ { 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz
/*Mine*/ { 0, 2, 3, 1, 0, 0, 0, 0 }, // Mine
/*Orbinaut*/ { 5, 5, 2, 2, 0, 0, 0, 0 }, // Orbinaut
/*Jawz*/ { 0, 4, 2, 1, 0, 0, 0, 0 }, // Jawz
/*Mine*/ { 0, 3, 3, 1, 0, 0, 0, 0 }, // Mine
/*Land Mine*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine
/*Ballhog*/ { 0, 0, 2, 2, 0, 0, 0, 0 }, // Ballhog
/*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 2, 4, 0 }, // Self-Propelled Bomb
/*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow
/*Shrink*/ { 0, 0, 0, 0, 0, 0, 2, 0 }, // Shrink
/*Lightning Shield*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Lightning Shield
/*Lightning Shield*/ { 1, 0, 0, 0, 0, 0, 0, 0 }, // Lightning Shield
/*Bubble Shield*/ { 0, 1, 2, 1, 0, 0, 0, 0 }, // Bubble Shield
/*Flame Shield*/ { 0, 0, 0, 0, 0, 1, 3, 5 }, // Flame Shield
/*Hyudoro*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Hyudoro
@ -373,13 +373,13 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
/*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring
/*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink
/*Drop Target*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Drop Target
/*Sneaker x2*/ { 0, 0, 2, 2, 1, 0, 0, 0 }, // Sneaker x2
/*Sneaker x3*/ { 0, 0, 0, 2, 6,10, 5, 0 }, // Sneaker x3
/*Sneaker x2*/ { 0, 0, 2, 2, 2, 0, 0, 0 }, // Sneaker x2
/*Sneaker x3*/ { 0, 0, 0, 1, 6,10, 5, 0 }, // Sneaker x3
/*Banana x3*/ { 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3
/*Banana x10*/ { 0, 0, 0, 1, 0, 0, 0, 0 }, // Banana x10
/*Orbinaut x3*/ { 0, 0, 1, 0, 0, 0, 0, 0 }, // Orbinaut x3
/*Orbinaut x4*/ { 0, 0, 0, 1, 1, 0, 0, 0 }, // Orbinaut x4
/*Jawz x2*/ { 0, 0, 1, 2, 0, 0, 0, 0 } // Jawz x2
/*Orbinaut x4*/ { 0, 0, 0, 2, 0, 0, 0, 0 }, // Orbinaut x4
/*Jawz x2*/ { 0, 0, 1, 2, 1, 0, 0, 0 } // Jawz x2
};
static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][2] =
@ -1704,9 +1704,13 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur
UINT8 c;
if (maxdist == 0)
c = 0;
{
c = leveltime % CHAOTIXBANDCOLORS;
}
else
{
c = FixedMul(CHAOTIXBANDCOLORS<<FRACBITS, FixedDiv(curdist-minimumdist, maxdist-minimumdist)) >> FRACBITS;
}
stepx = (victim->mo->x - player->mo->x) / CHAOTIXBANDLEN;
stepy = (victim->mo->y - player->mo->y) / CHAOTIXBANDLEN;
@ -1725,8 +1729,16 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur
curz + (P_RandomRange(24,48)*mapobjectscale),
MT_SIGNSPARKLE);
P_SetMobjState(band, S_SIGNSPARK1 + (leveltime % 11));
P_SetScale(band, (band->destscale = (3*player->mo->scale)/2));
if (maxdist == 0)
{
P_SetMobjState(band, S_KSPARK1 + (leveltime % 8));
P_SetScale(band, (band->destscale = player->mo->scale));
}
else
{
P_SetMobjState(band, S_SIGNSPARK1 + (leveltime % 11));
P_SetScale(band, (band->destscale = (3*player->mo->scale)/2));
}
band->color = colors[c];
band->colorized = true;
@ -1896,9 +1908,14 @@ static void K_UpdateDraft(player_t *player)
}
// No one to draft off of? Then you can knock that off.
if (player->draftleeway) // Prevent small disruptions from stopping your draft.
if (player->draftleeway > 0) // Prevent small disruptions from stopping your draft.
{
player->draftleeway--;
if (P_IsObjectOnGround(player->mo) == true)
{
// Allow maintaining tether in air setpieces.
player->draftleeway--;
}
if (player->lastdraft >= 0
&& player->lastdraft < MAXPLAYERS
&& playeringame[player->lastdraft]
@ -2979,15 +2996,14 @@ INT16 K_GetSpindashChargeTime(player_t *player)
fixed_t K_GetSpindashChargeSpeed(player_t *player)
{
// more speed for higher weight & speed
// Tails = +6.25%, Fang = +20.31%, Mighty = +20.31%, Metal = +25%
// Tails = +18.75%, Fang = +46.88%, Mighty = +46.88%, Metal = +56.25%
// (can be higher than this value when overcharged)
const fixed_t val = (player->kartspeed + player->kartweight) * (FRACUNIT/32);
const fixed_t val = ((player->kartspeed + player->kartweight) + 2) * (FRACUNIT/32);
// TODO: gametyperules
return (gametype == GT_BATTLE) ? (4 * val) : val;
}
// sets boostpower, speedboost, accelboost, and handleboost to whatever we need it to be
static void K_GetKartBoostPower(player_t *player)
{
@ -3072,7 +3088,7 @@ static void K_GetKartBoostPower(player_t *player)
if (player->startboost) // Startup Boost
{
ADDBOOST(FRACUNIT/2, 4*FRACUNIT, 0); // + 50% top speed, + 400% acceleration, +0% handling
ADDBOOST(FRACUNIT, 4*FRACUNIT, sliptidehandling/2); // + 100% top speed, + 400% acceleration, +25% handling
}
if (player->driftboost) // Drift Boost
@ -3113,6 +3129,12 @@ static void K_GetKartBoostPower(player_t *player)
draftspeed *= 2;
}
if (player->itemtype == KITEM_LIGHTNINGSHIELD)
{
// infinite tether
draftspeed *= 2;
}
speedboost += FixedMul(draftspeed, player->draftpower); // (Drafting suffers no boost stack penalty.)
numboosts++;
}
@ -3616,9 +3638,25 @@ static void K_RemoveGrowShrink(player_t *player)
P_RestoreMusic(player);
}
static fixed_t K_TumbleZ(mobj_t *mo, fixed_t input)
{
// Scales base tumble gravity to FRACUNIT
const fixed_t baseGravity = FixedMul(DEFAULT_GRAVITY, TUMBLEGRAVITY);
// Adapt momz w/ gravity
fixed_t gravityAdjust = FixedDiv(P_GetMobjGravity(mo), baseGravity);
if (mo->eflags & MFE_UNDERWATER)
{
// Reverse doubled falling speed.
gravityAdjust /= 2;
}
return FixedMul(input, -gravityAdjust);
}
void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source)
{
fixed_t gravityadjust;
(void)source;
K_DirectorFollowAttack(player, inflictor, source);
@ -3647,16 +3685,7 @@ void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source)
S_StartSound(player->mo, sfx_s3k9b);
// adapt momz w/ gravity?
// as far as kart goes normal gravity is 2 (FRACUNIT*2)
gravityadjust = P_GetMobjGravity(player->mo)/2; // so we'll halve it for our calculations.
if (player->mo->eflags & MFE_UNDERWATER)
gravityadjust /= 2; // halve "gravity" underwater
// and then modulate momz like that...
player->mo->momz = -gravityadjust * player->tumbleHeight;
player->mo->momz = K_TumbleZ(player->mo, player->tumbleHeight * FRACUNIT);
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
@ -3671,8 +3700,6 @@ static boolean K_LastTumbleBounceCondition(player_t *player)
static void K_HandleTumbleBounce(player_t *player)
{
fixed_t gravityadjust;
player->tumbleBounces++;
player->tumbleHeight = (player->tumbleHeight * ((player->tumbleHeight > 100) ? 3 : 4)) / 5;
player->pflags &= ~PF_TUMBLESOUND;
@ -3705,7 +3732,7 @@ static void K_HandleTumbleBounce(player_t *player)
// A bit of damage hitlag.
// This gives a window for DI!!
K_AddHitLag(player->mo, 6, true);
K_AddHitLag(player->mo, 3, true);
if (P_IsDisplayPlayer(player) && player->tumbleHeight >= 40)
P_StartQuake((player->tumbleHeight*3/2)<<FRACBITS, 6); // funny earthquakes for the FEEL
@ -3715,16 +3742,8 @@ static void K_HandleTumbleBounce(player_t *player)
player->mo->momx = player->mo->momx / 2;
player->mo->momy = player->mo->momy / 2;
// adapt momz w/ gravity?
// as far as kart goes normal gravity is 2 (FRACUNIT*2)
gravityadjust = P_GetMobjGravity(player->mo)/2; // so we'll halve it for our calculations.
if (player->mo->eflags & MFE_UNDERWATER)
gravityadjust /= 2; // halve "gravity" underwater
// and then modulate momz like that...
player->mo->momz = -gravityadjust * player->tumbleHeight;
player->mo->momz = K_TumbleZ(player->mo, player->tumbleHeight * FRACUNIT);
}
// Play a falling sound when you start falling while tumbling and you're nowhere near done bouncing
@ -3741,6 +3760,21 @@ static void K_HandleTumbleSound(player_t *player)
}
}
void K_TumbleInterrupt(player_t *player)
{
// If player was tumbling, set variables so that they don't tumble like crazy after they're done respawning
if (player->tumbleBounces > 0)
{
player->tumbleBounces = 0; // MAXBOUNCES-1;
player->pflags &= ~PF_TUMBLELASTBOUNCE;
//players->tumbleHeight = 20;
players->mo->rollangle = 0;
player->spinouttype = KSPIN_WIPEOUT;
player->spinouttimer = player->wipeoutslow = TICRATE+2;
}
}
void K_ApplyTripWire(player_t *player, tripwirestate_t state)
{
if (state == TRIP_PASSED)
@ -7243,6 +7277,8 @@ static void K_LookForRings(mobj_t *pmo)
*/
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
{
const boolean onground = P_IsObjectOnGround(player->mo);
K_UpdateOffroad(player);
K_UpdateDraft(player);
K_UpdateEngineSounds(player); // Thanks, VAda!
@ -7514,8 +7550,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->strongdriftboost)
player->strongdriftboost--;
if (player->startboost)
if (player->startboost > 0 && onground == true)
{
player->startboost--;
}
if (player->spindashboost)
{
@ -8248,7 +8286,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
// distance calculation to work easily
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) == 0U)
{
const UINT8 numfulllapsleft = ((UINT8)cv_numlaps.value - player->laps);
const UINT8 numfulllapsleft = ((UINT8)numlaps - player->laps);
player->distancetofinish += numfulllapsleft * K_GetCircuitLength();

View file

@ -73,6 +73,7 @@ void K_DoPowerClash(player_t *t1, player_t *t2);
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved);
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type);
void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_TumbleInterrupt(player_t *player);
INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_DebtStingPlayer(player_t *player, mobj_t *source);
void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers);

View file

@ -1,5 +1,12 @@
/// \file k_pwrlv.c
/// \brief SRB2Kart Power Levels
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2018-2022 by Sally Cochenour
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
// \brief Power Level system
#include "k_pwrlv.h"
#include "d_netcmd.h"
@ -19,9 +26,12 @@ UINT16 vspowerlevel[PWRLV_NUMTYPES];
// This is done so that clients will never be able to hack someone else's score over the server.
UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES];
// Which players spec-scummed, and their power level before scumming.
// On race finish, everyone is considered to have "won" against these people.
INT16 nospectategrief[MAXPLAYERS];
// Total calculated power add during the match,
// totalled at the end of the round.
INT16 clientPowerAdd[MAXPLAYERS];
// Players who spectated mid-race
UINT8 spectateGriefed = 0;
// Game setting scrambles based on server Power Level
SINT8 speedscramble = -1;
@ -52,8 +62,14 @@ void K_ClearClientPowerLevels(void)
{
UINT8 i, j;
for (i = 0; i < MAXPLAYERS; i++)
{
clientPowerAdd[i] = 0;
for (j = 0; j < PWRLV_NUMTYPES; j++)
{
clientpowerlevels[i][j] = 0;
}
}
}
// Adapted from this: http://wiki.tockdom.com/wiki/Player_Rating
@ -71,7 +87,7 @@ INT16 K_CalculatePowerLevelInc(INT16 diff)
diff = -MAXDIFF;
#undef MAXDIFF
x = ((diff-2)<<FRACBITS) / PWRLVRECORD_START;
x = ((diff-2)<<FRACBITS) / PWRLVRECORD_MEDIAN;
for (j = 3; j < 10; j++) // Just skipping to 3 since 0 thru 2 will always just add 0...
{
@ -98,6 +114,23 @@ INT16 K_CalculatePowerLevelInc(INT16 diff)
return (INT16)(increment >> FRACBITS);
}
INT16 K_PowerLevelPlacementScore(player_t *player)
{
if ((player->pflags & PF_NOCONTEST) || (player->spectator))
{
return 0;
}
if (gametyperules & GTR_CIRCUIT)
{
return MAXPLAYERS - player->position;
}
else
{
return player->score;
}
}
INT16 K_CalculatePowerLevelAvg(void)
{
fixed_t avg = 0;
@ -143,7 +176,269 @@ INT16 K_CalculatePowerLevelAvg(void)
return (INT16)(avg >> FRACBITS);
}
// -- K_UpdatePowerLevels could not be moved here due to usage of y_data, unfortunately. --
void K_UpdatePowerLevels(player_t *player, UINT8 lap, boolean forfeit)
{
const UINT8 playerNum = player - players;
const boolean exitBonus = ((lap > numlaps) || (player->pflags & PF_NOCONTEST));
SINT8 powerType = K_UsingPowerLevels();
INT16 yourScore = 0;
UINT16 yourPower = 0;
UINT8 i;
// Compare every single player against each other for power level increases.
// Every player you won against gives you more points, and vice versa.
// The amount of points won per match-up depends on the difference between the loser's power and the winner's power.
// See K_CalculatePowerLevelInc for more info.
if (powerType == PWRLV_DISABLED)
{
return;
}
if (!playeringame[playerNum] || player->spectator)
{
return;
}
//CONS_Printf("\n========\n");
//CONS_Printf("* Power Level change for player %s (LAP %d) *\n", player_names[playerNum], lap);
//CONS_Printf("========\n");
yourPower = clientpowerlevels[playerNum][powerType];
if (yourPower == 0)
{
// Guests don't record power level changes.
return;
}
//CONS_Printf("%s's PWR.LV: %d\n", player_names[playerNum], yourPower);
yourScore = K_PowerLevelPlacementScore(player);
//CONS_Printf("%s's gametype score: %d\n", player_names[playerNum], yourScore);
//CONS_Printf("========\n");
for (i = 0; i < MAXPLAYERS; i++)
{
UINT16 theirScore = 0;
INT16 theirPower = 0;
INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV
INT16 inc = 0; // Total pt increment
boolean won = false;
if (i == playerNum) // Same person
{
continue;
}
if (!playeringame[i] || players[i].spectator)
{
continue;
}
//CONS_Printf("%s VS %s:\n", player_names[playerNum], player_names[i]);
theirPower = clientpowerlevels[i][powerType];
if (theirPower == 0)
{
// No power level (splitscreen guests, bots)
continue;
}
//CONS_Printf("%s's PWR.LV: %d\n", player_names[i], theirPower);
theirScore = K_PowerLevelPlacementScore(&players[i]);
//CONS_Printf("%s's gametype score: %d\n", player_names[i], theirScore);
if (yourScore == theirScore && forfeit == false) // Tie -- neither get any points for this match up.
{
//CONS_Printf("TIE, no change.\n");
continue;
}
won = (yourScore > theirScore);
if (won == true && forfeit == false) // This player won!
{
diff = theirPower - yourPower;
inc += K_CalculatePowerLevelInc(diff);
//CONS_Printf("WON! Diff is %d, increment is %d\n", diff, inc);
}
else // This player lost...
{
diff = yourPower - theirPower;
inc -= K_CalculatePowerLevelInc(diff);
//CONS_Printf("LOST... Diff is %d, increment is %d\n", diff, inc);
}
if (exitBonus == false)
{
INT16 prevInc = inc;
inc /= max(numlaps-1, 1);
if (inc == 0)
{
if (prevInc > 0)
{
inc = 1;
}
else if (prevInc < 0)
{
inc = -1;
}
}
//CONS_Printf("Reduced (%d / %d = %d) because it's not the end of the race\n", prevInc, numlaps, inc);
}
//CONS_Printf("========\n");
if (inc == 0)
{
CONS_Printf("Total Result: No increment, no change.\n");
continue;
}
//CONS_Printf("Total Result:\n");
//CONS_Printf("Increment: %d\n", inc);
//CONS_Printf("%s current: %d\n", player_names[playerNum], clientPowerAdd[playerNum]);
clientPowerAdd[playerNum] += inc;
//CONS_Printf("%s final: %d\n", player_names[playerNum], clientPowerAdd[playerNum]);
//CONS_Printf("%s current: %d\n", player_names[i], clientPowerAdd[i]);
clientPowerAdd[i] -= inc;
//CONS_Printf("%s final: %d\n", player_names[i], clientPowerAdd[i]);
//CONS_Printf("========\n");
}
}
void K_UpdatePowerLevelsOnFailure(player_t *player)
{
// Update upon spectate / quit / NO CONTEST
INT16 lapsLeft = 0;
UINT8 i;
lapsLeft = (numlaps - player->latestlap) + 1;
if (lapsLeft <= 0)
{
return;
}
for (i = 0; i < lapsLeft; i++)
{
K_UpdatePowerLevels(player, player->latestlap + (i + 1), true);
}
player->latestlap = numlaps+1;
}
INT16 K_FinalPowerIncrement(player_t *player, INT16 yourPower, INT16 baseInc)
{
INT16 inc = baseInc;
UINT8 numPlayers = 0;
UINT8 i;
if (yourPower == 0)
{
// Guests don't record power level changes.
return 0;
}
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
{
continue;
}
numPlayers++;
}
if (inc <= 0)
{
if (player->position == 1)
{
// Won the whole match?
// Get at least one point.
inc = 1;
}
else
{
// You trade points in 1v1s,
// but is more lenient in bigger lobbies.
inc /= max(1, numPlayers-1);
if (inc == 0)
{
if (baseInc > 0)
{
inc = 1;
}
else if (baseInc < 0)
{
inc = -1;
}
}
}
}
if (yourPower + inc > PWRLVRECORD_MAX)
{
inc -= ((yourPower + inc) - PWRLVRECORD_MAX);
}
if (yourPower + inc < PWRLVRECORD_MIN)
{
inc -= ((yourPower + inc) - PWRLVRECORD_MIN);
}
return inc;
}
void K_CashInPowerLevels(void)
{
SINT8 powerType = K_UsingPowerLevels();
UINT8 i;
//CONS_Printf("\n========\n");
//CONS_Printf("Cashing in power level changes...\n");
//CONS_Printf("========\n");
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] == true && powerType != PWRLV_DISABLED)
{
INT16 inc = K_FinalPowerIncrement(&players[i], clientpowerlevels[i][powerType], clientPowerAdd[i]);
clientpowerlevels[i][powerType] += inc;
//CONS_Printf("%s: %d -> %d (%d)\n", player_names[i], clientpowerlevels[i][powerType] - inc, clientpowerlevels[i][powerType], inc);
if (!demo.playback && i == consoleplayer && inc != 0)
{
vspowerlevel[powerType] = clientpowerlevels[i][powerType];
if (M_UpdateUnlockablesAndExtraEmblems())
{
S_StartSound(NULL, sfx_ncitem);
}
G_SaveGameData();
}
}
clientPowerAdd[i] = 0;
}
//CONS_Printf("========\n");
}
void K_SetPowerLevelScrambles(SINT8 powertype)
{
@ -227,7 +522,7 @@ void K_SetPowerLevelScrambles(SINT8 powertype)
{
case 5:
speed = KARTSPEED_HARD;
encore = true;
encore = P_RandomChance(FRACUNIT>>1);
break;
case 4:
speed = P_RandomChance((7<<FRACBITS)/10) ? KARTSPEED_HARD : KARTSPEED_NORMAL;
@ -238,7 +533,7 @@ void K_SetPowerLevelScrambles(SINT8 powertype)
encore = P_RandomChance(FRACUNIT>>2);
break;
case 2:
speed = 1;
speed = KARTSPEED_NORMAL;
encore = P_RandomChance(FRACUNIT>>3);
break;
case 1: default:
@ -254,7 +549,7 @@ void K_SetPowerLevelScrambles(SINT8 powertype)
CONS_Debug(DBG_GAMELOGIC, "Rolled speed: %d\n", speed);
CONS_Debug(DBG_GAMELOGIC, "Rolled encore: %s\n", (encore ? "true" : "false"));
if (cv_kartspeed.value == -1)
if (cv_kartspeed.value == KARTSPEED_AUTO)
speedscramble = speed;
else
speedscramble = -1;
@ -270,88 +565,89 @@ void K_SetPowerLevelScrambles(SINT8 powertype)
}
}
void K_PlayerForfeit(UINT8 playernum, boolean pointloss)
void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss)
{
UINT8 p = 0;
INT32 powertype = PWRLV_DISABLED;
UINT16 yourpower = PWRLVRECORD_DEF;
UINT16 theirpower = PWRLVRECORD_DEF;
INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV
SINT8 powerType = PWRLV_DISABLED;
UINT16 yourPower = 0;
INT16 inc = 0;
UINT8 i;
// power level & spectating is netgames only
if (!netgame)
{
return;
// This server isn't using power levels anyway!
if (!cv_kartusepwrlv.value)
return;
}
// Hey, I just got here!
if (players[playernum].jointime <= 1)
if (players[playerNum].jointime <= 1)
{
return;
}
// 20 sec into the match counts as a forfeit -- automatic loss against every other player in the match.
// 20 sec into a match counts as a forfeit -- automatic loss against every other player in the match.
if (gamestate != GS_LEVEL || leveltime <= starttime+(20*TICRATE))
{
return;
}
spectateGriefed++;
// This server isn't using power levels, so don't mess with them.
if (!cv_kartusepwrlv.value)
{
return;
}
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
if ((playeringame[i] && !players[i].spectator)
|| (i == playerNum))
{
p++;
}
}
if (p < 2) // no players
return;
if ((gametyperules & GTR_CIRCUIT))
powertype = PWRLV_RACE;
else if ((gametyperules & GTR_BUMPERS))
powertype = PWRLV_BATTLE;
if (powertype == PWRLV_DISABLED) // No power type?!
return;
if (clientpowerlevels[playernum][powertype] == 0) // splitscreen guests don't record power level changes
return;
yourpower = clientpowerlevels[playernum][powertype];
// Set up the point compensation.
nospectategrief[playernum] = yourpower;
if (!pointloss) // This is set for stuff like sync-outs, which shouldn't be so harsh on the victim!
return;
for (i = 0; i < MAXPLAYERS; i++)
{
if (i == playernum)
continue;
if (clientpowerlevels[i][powertype] == 0) // No power level (splitscreen guests, bots)
continue;
theirpower = clientpowerlevels[i][powertype];
diff = yourpower - theirpower;
inc -= K_CalculatePowerLevelInc(diff);
return;
}
if (inc == 0) // No change.
return;
powerType = K_UsingPowerLevels();
if (yourpower + inc > PWRLVRECORD_MAX) // I mean... we're subtracting... but y'know how it is :V
inc -= ((yourpower + inc) - PWRLVRECORD_MAX);
if (yourpower + inc < PWRLVRECORD_MIN)
inc -= ((yourpower + inc) - PWRLVRECORD_MIN);
clientpowerlevels[playernum][powertype] += inc;
if (!demo.playback && playernum == consoleplayer)
if (powerType == PWRLV_DISABLED) // No power type?!
{
vspowerlevel[powertype] = clientpowerlevels[playernum][powertype];
return;
}
yourPower = clientpowerlevels[playerNum][powerType];
if (yourPower == 0) // splitscreen guests don't record power level changes
{
return;
}
K_UpdatePowerLevelsOnFailure(&players[playerNum]);
inc = K_FinalPowerIncrement(&players[playerNum], yourPower, clientPowerAdd[playerNum]);
if (inc >= 0)
{
// Don't record no change or increases.
return;
}
// pointLoss isn't set for stuff like sync-outs,
// which shouldn't be so harsh on the victim!
if (!demo.playback && pointLoss == true && playerNum == consoleplayer)
{
vspowerlevel[powerType] = yourPower + inc;
if (M_UpdateUnlockablesAndExtraEmblems())
{
S_StartSound(NULL, sfx_ncitem);
G_SaveGameData(); // save your punishment!
}
G_SaveGameData();
}
}

View file

@ -1,16 +1,30 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2018-2022 by Sally Cochenour
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
// \brief Power Level system
#ifndef __K_PWRLV__
#define __K_PWRLV__
#include "doomtype.h"
#include "doomdef.h"
#include "d_player.h"
#define PWRLV_DISABLED -1
#define PWRLV_RACE 0
#define PWRLV_BATTLE 1
#define PWRLV_NUMTYPES 2
typedef enum
{
PWRLV_DISABLED = -1,
PWRLV_RACE = 0,
PWRLV_BATTLE = 1,
PWRLV_NUMTYPES = 2,
} pwrlv_type_t;
#define PWRLVRECORD_START 1000
#define PWRLVRECORD_DEF 5000
#define PWRLVRECORD_MEDIAN 5000
#define PWRLVRECORD_MIN 1
#define PWRLVRECORD_MAX 9999
@ -19,13 +33,18 @@ extern SINT8 encorescramble;
extern UINT16 vspowerlevel[PWRLV_NUMTYPES];
extern UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES];
extern INT16 nospectategrief[MAXPLAYERS];
extern INT16 clientPowerAdd[MAXPLAYERS];
extern UINT8 spectateGriefed;
SINT8 K_UsingPowerLevels(void);
void K_ClearClientPowerLevels(void);
INT16 K_CalculatePowerLevelInc(INT16 diff);
INT16 K_PowerLevelPlacementScore(player_t *player);
INT16 K_CalculatePowerLevelAvg(void);
//void K_UpdatePowerLevels(void);
void K_UpdatePowerLevels(player_t *player, UINT8 lap, boolean forfeit);
void K_UpdatePowerLevelsOnFailure(player_t *player);
INT16 K_FinalPowerIncrement(player_t *player, INT16 yourPower, INT16 increment);
void K_CashInPowerLevels(void);
void K_SetPowerLevelScrambles(SINT8 powertype);
void K_PlayerForfeit(UINT8 playernum, boolean nopointloss);

View file

@ -151,18 +151,8 @@ void K_DoIngameRespawn(player_t *player)
player->ringboost = 0;
player->driftboost = player->strongdriftboost = 0;
// If player was tumbling, set variables so that they don't tumble like crazy after they're done respawning
if (player->tumbleBounces > 0)
{
player->tumbleBounces = 0; // MAXBOUNCES-1;
player->pflags &= ~PF_TUMBLELASTBOUNCE;
//players->tumbleHeight = 20;
players->mo->rollangle = 0;
player->spinouttype = KSPIN_WIPEOUT;
player->spinouttimer = player->wipeoutslow = (3*TICRATE/2)+2;
}
K_TumbleInterrupt(player);
P_ResetPlayer(player);
// Set up respawn position if invalid

View file

@ -448,6 +448,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->realtime);
else if (fastcmp(field,"laps"))
lua_pushinteger(L, plr->laps);
else if (fastcmp(field,"latestlap"))
lua_pushinteger(L, plr->latestlap);
else if (fastcmp(field,"ctfteam"))
lua_pushinteger(L, plr->ctfteam);
else if (fastcmp(field,"checkskip"))
@ -790,6 +792,8 @@ static int player_set(lua_State *L)
plr->realtime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"laps"))
plr->laps = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"latestlap"))
plr->latestlap = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"ctfteam"))
plr->ctfteam = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"checkskip"))

View file

@ -391,7 +391,7 @@ int LUA_PushGlobals(lua_State *L, const char *word)
lua_pushinteger(L, mapobjectscale);
return 1;
} else if (fastcmp(word,"numlaps")) {
lua_pushinteger(L, cv_numlaps.value);
lua_pushinteger(L, numlaps);
return 1;
} else if (fastcmp(word,"racecountdown")) {
lua_pushinteger(L, racecountdown);

View file

@ -1478,17 +1478,17 @@ static menuitem_t OP_GameOptionsMenu[] =
{IT_STRING | IT_SUBMENU, NULL, "Random Item Toggles...", {.submenu = &OP_MonitorToggleDef}, 10},
{IT_STRING | IT_CVAR, NULL, "Game Speed", {.cvar = &cv_kartspeed}, 30},
{IT_STRING | IT_CVAR, NULL, "Frantic Items", {.cvar = &cv_kartfrantic}, 40},
{IT_STRING | IT_CVAR, NULL, "Frantic Items", {.cvar = &cv_kartfrantic}, 40},
{IT_SECRET, NULL, "Encore Mode", {.cvar = &cv_kartencore}, 50},
{IT_STRING | IT_CVAR, NULL, "Number of Laps", {.cvar = &cv_basenumlaps}, 70},
{IT_STRING | IT_CVAR, NULL, "Number of Laps", {.cvar = &cv_numlaps}, 70},
{IT_STRING | IT_CVAR, NULL, "Exit Countdown Timer", {.cvar = &cv_countdowntime}, 80},
{IT_STRING | IT_CVAR, NULL, "Time Limit", {.cvar = &cv_timelimit}, 100},
{IT_STRING | IT_CVAR, NULL, "Starting Bumpers", {.cvar = &cv_kartbumpers}, 110},
{IT_STRING | IT_CVAR, NULL, "Karma Comeback", {.cvar = &cv_kartcomeback}, 120},
{IT_STRING | IT_CVAR, NULL, "Starting Bumpers", {.cvar = &cv_kartbumpers}, 110},
{IT_STRING | IT_CVAR, NULL, "Karma Comeback", {.cvar = &cv_kartcomeback}, 120},
{IT_STRING | IT_CVAR, NULL, "Track Power Levels", {.cvar = &cv_kartusepwrlv}, 140},
{IT_STRING | IT_CVAR, NULL, "Track Power Levels", {.cvar = &cv_kartusepwrlv}, 140},
};
static menuitem_t OP_ServerOptionsMenu[] =

View file

@ -0,0 +1 @@
target_sourcefile(c)

View file

@ -14032,21 +14032,21 @@ void A_LightningFollowPlayer(mobj_t *actor)
if (!actor->target)
return;
if (actor->extravalue1) // Make the radius also follow the player somewhat accuratly
{
if (actor->extravalue1) // Make the radius also follow the player somewhat accuratly
{
sx = actor->target->x + FixedMul((actor->target->scale*actor->extravalue1), FINECOSINE((actor->angle)>>ANGLETOFINESHIFT));
sy = actor->target->y + FixedMul((actor->target->scale*actor->extravalue1), FINESINE((actor->angle)>>ANGLETOFINESHIFT));
P_MoveOrigin(actor, sx, sy, actor->target->z);
}
else // else just teleport to player directly
P_MoveOrigin(actor, actor->target->x, actor->target->y, actor->target->z);
K_MatchGenericExtraFlags(actor, actor->target); // copy our target for graviflip
actor->momx = actor->target->momx;
actor->momy = actor->target->momy;
actor->momz = actor->target->momz; // Give momentum since we don't teleport to our player literally every frame.
sx = actor->target->x + FixedMul((actor->target->scale*actor->extravalue1), FINECOSINE((actor->angle)>>ANGLETOFINESHIFT));
sy = actor->target->y + FixedMul((actor->target->scale*actor->extravalue1), FINESINE((actor->angle)>>ANGLETOFINESHIFT));
P_MoveOrigin(actor, sx, sy, actor->target->z);
}
else // else just teleport to player directly
{
P_MoveOrigin(actor, actor->target->x, actor->target->y, actor->target->z);
}
K_MatchGenericExtraFlags(actor, actor->target); // copy our target for graviflip
actor->momx = actor->target->momx;
actor->momy = actor->target->momy;
actor->momz = actor->target->momz; // Give momentum since we don't teleport to our player literally every frame.
}
// A_FZBoomFlash:

View file

@ -792,16 +792,11 @@ boolean P_CheckRacers(void)
boolean eliminatelast = cv_karteliminatelast.value;
boolean everyonedone = true;
boolean eliminatebots = false;
boolean griefed = false;
const boolean griefed = (spectateGriefed > 0);
// Check if all the players in the race have finished. If so, end the level.
for (i = 0; i < MAXPLAYERS; i++)
{
if (nospectategrief[i] != -1) // prevent spectate griefing
{
griefed = true;
}
if (!playeringame[i] || players[i].spectator || players[i].lives <= 0) // Not playing
{
// Y'all aren't even playing
@ -922,7 +917,7 @@ boolean P_CheckRacers(void)
// We're still playing, but no one else is, so we need to reset spectator griefing.
if (numplayersingame <= 1)
{
memset(nospectategrief, -1, sizeof (nospectategrief));
spectateGriefed = 0;
}
// Turns out we're still having a good time & playing the game, we didn't have to do anything :)

View file

@ -28,6 +28,9 @@
//#define VIEWHEIGHTS "41"
// Maximum laps per map.
#define MAX_LAPS 99
// Maximum player score.
#define MAXSCORE 99999990 // 999999990

View file

@ -417,6 +417,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
P_SetTarget(&spring->target, object);
}
K_TumbleInterrupt(object->player);
P_ResetPlayer(object->player);
object->player->springstars = max(vertispeed, horizspeed) / FRACUNIT / 2;

View file

@ -1130,7 +1130,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
if (mo->player->tumbleBounces > 0)
{
gravityadd = (5*gravityadd)/2;
gravityadd = FixedMul(TUMBLEGRAVITY, gravityadd);
}
}
else
@ -11011,16 +11011,20 @@ void P_RespawnSpecials(void)
else
{
if (pcount == 1) // No respawn when alone
{
return;
}
else if (pcount > 1)
{
time = (120 - ((pcount-2) * 10)) * TICRATE;
time = (120 - ((pcount-2) * 20)) * TICRATE;
// If the map is longer or shorter than 3 laps, then adjust ring respawn to account for this.
// 5 lap courses would have more retreaded ground, while 2 lap courses would have less.
if ((mapheaderinfo[gamemap-1]->numlaps != 3)
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_SECTIONRACE))
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_SECTIONRACE))
{
time = (time * 3) / max(1, mapheaderinfo[gamemap-1]->numlaps);
}
if (time < 10*TICRATE)
{

View file

@ -106,6 +106,7 @@ static void P_NetArchivePlayers(void)
{
WRITEINT16(save_p, clientpowerlevels[i][j]);
}
WRITEINT16(save_p, clientPowerAdd[i]);
if (!playeringame[i])
continue;
@ -167,6 +168,7 @@ static void P_NetArchivePlayers(void)
WRITEINT16(save_p, players[i].totalring);
WRITEUINT32(save_p, players[i].realtime);
WRITEUINT8(save_p, players[i].laps);
WRITEUINT8(save_p, players[i].latestlap);
WRITEINT32(save_p, players[i].starpostnum);
WRITEUINT8(save_p, players[i].ctfteam);
@ -406,6 +408,7 @@ static void P_NetUnArchivePlayers(void)
{
clientpowerlevels[i][j] = READINT16(save_p);
}
clientPowerAdd[i] = READINT16(save_p);
// Do NOT memset player struct to 0
// other areas may initialize data elsewhere
@ -468,6 +471,7 @@ static void P_NetUnArchivePlayers(void)
players[i].totalring = READINT16(save_p); // Total number of rings obtained for GP
players[i].realtime = READUINT32(save_p); // integer replacement for leveltime
players[i].laps = READUINT8(save_p); // Number of laps (optional)
players[i].latestlap = READUINT8(save_p);
players[i].starpostnum = READINT32(save_p);
players[i].ctfteam = READUINT8(save_p); // 1 == Red, 2 == Blue
@ -4499,6 +4503,7 @@ static void P_NetArchiveMisc(boolean resending)
WRITEUINT8(save_p, battlecapsules);
WRITEUINT8(save_p, gamespeed);
WRITEUINT8(save_p, numlaps);
WRITEUINT8(save_p, franticitems);
WRITEUINT8(save_p, comeback);
@ -4519,8 +4524,7 @@ static void P_NetArchiveMisc(boolean resending)
WRITEUINT32(save_p, indirectitemcooldown);
WRITEUINT32(save_p, mapreset);
for (i = 0; i < MAXPLAYERS; i++)
WRITEINT16(save_p, nospectategrief[i]);
WRITEUINT8(save_p, spectateGriefed);
WRITEUINT8(save_p, thwompsactive);
WRITEUINT8(save_p, lastLowestLap);
@ -4648,6 +4652,7 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
battlecapsules = (boolean)READUINT8(save_p);
gamespeed = READUINT8(save_p);
numlaps = READUINT8(save_p);
franticitems = (boolean)READUINT8(save_p);
comeback = (boolean)READUINT8(save_p);
@ -4668,8 +4673,7 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
indirectitemcooldown = READUINT32(save_p);
mapreset = READUINT32(save_p);
for (i = 0; i < MAXPLAYERS; i++)
nospectategrief[i] = READINT16(save_p);
spectateGriefed = READUINT8(save_p);
thwompsactive = (boolean)READUINT8(save_p);
lastLowestLap = READUINT8(save_p);

View file

@ -4063,25 +4063,37 @@ static void P_InitPlayers(void)
static void P_InitGametype(void)
{
spectateGriefed = 0;
K_CashInPowerLevels(); // Pushes power level changes even if intermission was skipped
P_InitPlayers();
if (modeattacking && !demo.playback)
P_LoadRecordGhosts();
if ((gametyperules & GTR_CIRCUIT) && server)
numlaps = 0;
if (gametyperules & GTR_CIRCUIT)
{
if ((netgame || multiplayer) && cv_basenumlaps.value
if ((netgame || multiplayer) && cv_numlaps.value
&& (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value)))
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_numlaps.value)))
{
CV_StealthSetValue(&cv_numlaps, cv_basenumlaps.value);
numlaps = cv_numlaps.value;
}
else
{
CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps);
numlaps = mapheaderinfo[gamemap - 1]->numlaps;
}
}
wantedcalcdelay = wantedfrequency*2;
indirectitemcooldown = 0;
mapreset = 0;
thwompsactive = false;
lastLowestLap = 0;
spbplace = -1;
// Start recording replay in multiplayer with a temp filename
//@TODO I'd like to fix dedis crashing when recording replays for the future too...
if (!demo.playback && multiplayer && !dedicated)
@ -4117,6 +4129,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Map header should always be in place at this point
INT32 i, ranspecialwipe = 0;
sector_t *ss;
levelloading = true;
// This is needed. Don't touch.
@ -4430,17 +4443,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
K_InitDirector();
}
wantedcalcdelay = wantedfrequency*2;
indirectitemcooldown = 0;
mapreset = 0;
for (i = 0; i < MAXPLAYERS; i++)
nospectategrief[i] = -1;
thwompsactive = false;
lastLowestLap = 0;
spbplace = -1;
// clear special respawning que
iquehead = iquetail = 0;

View file

@ -1917,14 +1917,6 @@ static void K_HandleLapIncrement(player_t *player)
player->karthud[khud_laphand] = 0; // No hands in FREE PLAY
player->karthud[khud_lapanimation] = 80;
// save best lap for record attack
if (player == &players[consoleplayer])
{
if (curlap < bestlap || bestlap == 0)
bestlap = curlap;
curlap = 0;
}
}
if (rainbowstartavailable == true)
@ -1938,18 +1930,18 @@ static void K_HandleLapIncrement(player_t *player)
rainbowstartavailable = false;
}
if (netgame && player->laps >= (UINT8)cv_numlaps.value)
if (netgame && player->laps >= numlaps)
CON_LogMessage(va(M_GetText("%s has finished the race.\n"), player_names[player-players]));
player->starpostnum = 0;
if (P_IsDisplayPlayer(player))
{
if (player->laps == (UINT8)(cv_numlaps.value)) // final lap
if (player->laps == numlaps) // final lap
S_StartSound(NULL, sfx_s3k68);
else if ((player->laps > 1) && (player->laps < (UINT8)(cv_numlaps.value))) // non-final lap
else if ((player->laps > 1) && (player->laps < numlaps)) // non-final lap
S_StartSound(NULL, sfx_s221);
else if (player->laps > (UINT8)(cv_numlaps.value))
else if (player->laps > numlaps)
{
// finished
S_StartSound(NULL, sfx_s3k6a);
@ -1958,7 +1950,7 @@ static void K_HandleLapIncrement(player_t *player)
}
else
{
if ((player->laps > (UINT8)(cv_numlaps.value)) && (player->position == 1))
if ((player->laps > numlaps) && (player->position == 1))
{
// opponent finished
S_StartSound(NULL, sfx_s253);
@ -1966,12 +1958,34 @@ static void K_HandleLapIncrement(player_t *player)
}
// finished race exit setup
if (player->laps > (unsigned)cv_numlaps.value)
if (player->laps > numlaps)
{
P_DoPlayerExit(player);
P_SetupSignExit(player);
}
if (player->laps > player->latestlap)
{
if (player->laps > 1)
{
// save best lap for record attack
if (modeattacking && player == &players[consoleplayer])
{
if (curlap < bestlap || bestlap == 0)
{
bestlap = curlap;
}
curlap = 0;
}
// Update power levels for this lap.
K_UpdatePowerLevels(player, player->laps, false);
}
player->latestlap = player->laps;
}
thwompsactive = true; // Lap 2 effects
lowestLap = P_FindLowestLap();

View file

@ -873,7 +873,7 @@ void P_RestoreMusic(player_t *player)
#if 0
// Event - Final Lap
// Still works for GME, but disabled for consistency
if ((gametyperules & GTR_CIRCUIT) && player->laps >= (UINT8)(cv_numlaps.value))
if ((gametyperules & GTR_CIRCUIT) && player->laps >= numlaps)
S_SpeedMusic(1.2f);
#endif
if (mapmusresume && cv_resume.value)
@ -3851,6 +3851,7 @@ void P_DoTimeOver(player_t *player)
}
player->pflags |= PF_NOCONTEST;
K_UpdatePowerLevelsOnFailure(player);
if (G_GametypeUsesLives())
{

View file

@ -79,11 +79,11 @@ if(${SDL2_FOUND})
endif()
if(${CMAKE_SYSTEM} MATCHES Windows)
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2win)
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2kart)
elseif(${CMAKE_SYSTEM} MATCHES Linux)
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME lsdlsrb2)
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME lsdlsrb2kart)
else()
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2)
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2kart)
endif()
if(${CMAKE_SYSTEM} MATCHES Darwin)
@ -124,6 +124,14 @@ if(${SDL2_FOUND})
endif()
endif()
if(${CMAKE_SYSTEM} MATCHES Windows AND ${CMAKE_C_COMPILER_ID} MATCHES "GNU" AND ${SRB2_SYSTEM_BITS} EQUAL 32)
target_link_libraries(SRB2SDL2 PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/../../libs/drmingw/lib/win32/libexchndl.a"
"${CMAKE_CURRENT_SOURCE_DIR}/../../libs/drmingw/lib/win32/libmgwhelp.a"
)
target_include_directories(SRB2SDL2 PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../libs/drmingw/include")
endif()
#target_link_libraries(SRB2SDL2 PRIVATE SRB2Core)
if(${SRB2_USEASM})
@ -168,24 +176,9 @@ if(${SDL2_FOUND})
target_compile_definitions(SRB2SDL2 PRIVATE
-DDIRECTFULLSCREEN -DHAVE_SDL
-DHAVE_THREADS
)
## strip debug symbols into separate file when using gcc.
## to be consistent with Makefile, don't generate for OS X.
if((CMAKE_COMPILER_IS_GNUCC) AND NOT (${CMAKE_SYSTEM} MATCHES Darwin))
if((${CMAKE_BUILD_TYPE} MATCHES Debug) OR (${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo))
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
set(OBJCOPY_ONLY_KEEP_DEBUG "--only-keep-debug")
endif()
message(STATUS "Will make separate debug symbols in *.debug")
add_custom_command(TARGET SRB2SDL2 POST_BUILD
COMMAND ${OBJCOPY} ${OBJCOPY_ONLY_KEEP_DEBUG} $<TARGET_FILE:SRB2SDL2> $<TARGET_FILE:SRB2SDL2>.debug
COMMAND ${OBJCOPY} --strip-debug $<TARGET_FILE:SRB2SDL2>
COMMAND ${OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE:SRB2SDL2>.debug $<TARGET_FILE:SRB2SDL2>
)
endif()
endif()
#### Installation ####
if(${CMAKE_SYSTEM} MATCHES Darwin)
install(TARGETS SRB2SDL2

View file

@ -214,7 +214,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
{
INT32 i, j;
boolean completed[MAXPLAYERS];
INT32 numplayersingame = 0, numgriefers = 0;
INT32 numplayersingame = 0;
// Initialize variables
if (rankingsmode > 1)
@ -273,9 +273,6 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
{
data.val[i] = UINT32_MAX;
if (nospectategrief[i] != -1)
numgriefers++;
if (!playeringame[i] || players[i].spectator)
{
data.increase[i] = INT16_MIN;
@ -324,10 +321,10 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
{
if ((powertype == PWRLV_DISABLED)
&& !(players[i].pflags & PF_NOCONTEST)
&& (data.pos[data.numplayers] < (numplayersingame + numgriefers)))
&& (data.pos[data.numplayers] < (numplayersingame + spectateGriefed)))
{
// Online rank is handled further below in this file.
data.increase[i] = K_CalculateGPRankPoints(data.pos[data.numplayers], numplayersingame + numgriefers);
data.increase[i] = K_CalculateGPRankPoints(data.pos[data.numplayers], numplayersingame + spectateGriefed);
players[i].score += data.increase[i];
}
@ -890,157 +887,6 @@ void Y_Ticker(void)
}
}
static void K_UpdatePowerLevels(void)
{
INT32 i, j;
INT32 numplayersingame = 0, numgriefers = 0;
INT16 increment[MAXPLAYERS];
// Compare every single player against each other for power level increases.
// Every player you won against gives you more points, and vice versa.
// The amount of points won per match-up depends on the difference between the loser's power and the winner's power.
// See K_CalculatePowerLevelInc for more info.
for (i = 0; i < MAXPLAYERS; i++)
{
increment[i] = 0;
if (nospectategrief[i] != -1)
numgriefers++;
if (!playeringame[i] || players[i].spectator)
continue;
numplayersingame++;
}
for (i = 0; i < numplayersingame; i++)
{
UINT16 yourpower = PWRLVRECORD_DEF;
UINT16 theirpower = PWRLVRECORD_DEF;
INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV
INT16 inc = 0; // Total pt increment
UINT8 ipnum = data.num[i];
UINT8 jpnum;
CONS_Debug(DBG_GAMELOGIC, "Power Level Gain for player %d:\n", ipnum);
if (clientpowerlevels[ipnum][powertype] == 0) // splitscreen guests don't record power level changes
continue;
yourpower = clientpowerlevels[ipnum][powertype];
CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", ipnum, yourpower);
for (j = 0; j < numplayersingame; j++)
{
boolean won = false;
jpnum = data.num[j];
if (i == j || ipnum == jpnum) // Same person
continue;
CONS_Debug(DBG_GAMELOGIC, "Player %d VS Player %d:\n", ipnum, jpnum);
if (data.val[i] == data.val[j]) // Tie -- neither get any points for this match up.
{
CONS_Debug(DBG_GAMELOGIC, "TIE, no change.\n");
continue;
}
if (clientpowerlevels[jpnum][powertype] == 0) // No power level (splitscreen guests, bots)
continue;
theirpower = clientpowerlevels[jpnum][powertype];
CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", jpnum, theirpower);
if ((gametyperules & GTR_CIRCUIT))
{
if (data.val[i] < data.val[j])
won = true;
}
else
{
if (data.val[i] > data.val[j])
won = true;
}
if (won) // This player won!
{
diff = theirpower - yourpower;
inc += K_CalculatePowerLevelInc(diff);
CONS_Debug(DBG_GAMELOGIC, "WON! Diff is %d, total increment is %d\n", diff, inc);
}
else // This player lost...
{
diff = yourpower - theirpower;
inc -= K_CalculatePowerLevelInc(diff);
CONS_Debug(DBG_GAMELOGIC, "LOST... Diff is %d, total increment is %d\n", diff, inc);
}
}
if (numgriefers != 0) // Automatic win against quitters.
{
for (jpnum = 0; jpnum < MAXPLAYERS; jpnum++)
{
if (nospectategrief[jpnum] == -1) // Empty slot
continue;
if (ipnum == jpnum) // Same person
continue;
CONS_Debug(DBG_GAMELOGIC, "Player %d VS Player %d (griefer):\n", ipnum, jpnum);
if (nospectategrief[jpnum] == 0) // No power level (splitscreen guests, bots)
continue;
theirpower = nospectategrief[jpnum];
CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", jpnum, theirpower);
diff = theirpower - yourpower;
inc += K_CalculatePowerLevelInc(diff);
CONS_Debug(DBG_GAMELOGIC, "AUTO-WON! Diff is %d, total increment is %d\n", diff, inc);
}
}
if (inc == 0)
{
data.increase[ipnum] = INT16_MIN;
CONS_Debug(DBG_GAMELOGIC, "Total Result: No increment, no change.\n");
continue;
}
if (yourpower + inc > PWRLVRECORD_MAX)
inc -= ((yourpower + inc) - PWRLVRECORD_MAX);
if (yourpower + inc < PWRLVRECORD_MIN)
inc -= ((yourpower + inc) - PWRLVRECORD_MIN);
CONS_Debug(DBG_GAMELOGIC, "Total Result: Increment of %d.\n", inc);
increment[ipnum] = inc;
}
CONS_Debug(DBG_GAMELOGIC, "Setting final power levels...\n");
for (i = 0; i < MAXPLAYERS; i++)
{
if (increment[i] == 0)
continue;
data.increase[i] = increment[i];
clientpowerlevels[i][powertype] += data.increase[i];
if (!demo.playback && i == consoleplayer)
{
CONS_Debug(DBG_GAMELOGIC, "Player %d is you! Saving...\n", i);
vspowerlevel[powertype] = clientpowerlevels[i][powertype];
if (M_UpdateUnlockablesAndExtraEmblems())
S_StartSound(NULL, sfx_ncitem);
G_SaveGameData();
}
}
}
//
// Y_DetermineIntermissionType
//
@ -1121,7 +967,7 @@ void Y_StartIntermission(void)
//if (dedicated) return;
// This should always exist, but just in case...
if(!mapheaderinfo[prevmap])
if (!mapheaderinfo[prevmap])
P_AllocMapHeader(prevmap);
switch (intertype)
@ -1157,7 +1003,18 @@ void Y_StartIntermission(void)
if (powertype != PWRLV_DISABLED)
{
K_UpdatePowerLevels();
for (i = 0; i < MAXPLAYERS; i++)
{
// Kind of a hack to do this here,
// but couldn't think of a better way.
data.increase[i] = K_FinalPowerIncrement(
&players[i],
clientpowerlevels[i][powertype],
clientPowerAdd[i]
);
}
K_CashInPowerLevels();
}
//if (intertype == int_race || intertype == int_battle)