diff --git a/src/cvars.cpp b/src/cvars.cpp index 0f818f64a..63b1f7f90 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -561,7 +561,9 @@ static constexpr const char* kNetDemoRecordDefault = consvar_t cv_recordmultiplayerdemos = Server("netdemo_record", kNetDemoRecordDefault).values({{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}}); -consvar_t cv_reducevfx = Server("reducevfx", "No").yes_no(); +void ReduceVFX_OnChange(void); +consvar_t cv_reducevfx = Server("reducevfx", "No").yes_no().onchange(ReduceVFX_OnChange); + consvar_t cv_screenshake = Server("screenshake", "Full").values({{0, "Off"}, {1, "Half"}, {2, "Full"}}); consvar_t cv_rendezvousserver = Server("holepunchserver", "relay.kartkrew.org"); @@ -919,6 +921,7 @@ consvar_t cv_devmode_screen = PlayerCheat("devmode_screen", "1").min_max(1, 4).d consvar_t cv_drawpickups = PlayerCheat("drawpickups", "Yes").yes_no().description("Hide rings, spheres, item capsules, prison capsules (visual only)"); consvar_t cv_drawtimer = PlayerCheat("drawtimer", "No").yes_no().description("Always draw the timer (race checkpoint timing, etc)"); consvar_t cv_debugfonts = PlayerCheat("debugfonts", "No").yes_no().description("Draw font bounding boxes (integer precision, beware centered text!)"); +consvar_t cv_vorpal = ServerCheat("vorpal", "No").yes_no().description("Show real EXP odds modification"); void lua_profile_OnChange(void); consvar_t cv_lua_profile = PlayerCheat("lua_profile", "0").values(CV_Unsigned).onchange(lua_profile_OnChange).description("Show hook timings over an average of N tics"); diff --git a/src/deh_tables.c b/src/deh_tables.c index 21e950abc..19c5f3ddb 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -372,7 +372,17 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_KART_LEFTOVER", "S_KART_LEFTOVER_NOTIRES", - "S_KART_LEFTOVER_CUSTOM", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_A", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_B", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_C", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_D", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_E", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_F", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_G", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_H", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_I", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_J", + "S_KART_LEFTOVER_PARTICLE_CUSTOM_K", "S_KART_TIRE1", "S_KART_TIRE2", diff --git a/src/info.c b/src/info.c index dca797a0e..f71c0ad72 100644 --- a/src/info.c +++ b/src/info.c @@ -848,7 +848,17 @@ char spr2names[NUMPLAYERSPRITES][5] = "SIGN", "SIGL", "SSIG", // Finish signpost "XTRA", // Three Faces of Darkness "TALK", // Dialogue - "DKRT", // Kart husk + "DKRA", // Kart husk particle (A) + "DKRB", // Kart husk particle (B) + "DKRC", // Kart husk particle (C) + "DKRD", // Kart husk particle (D) + "DKRE", // Kart husk particle (E) + "DKRF", // Kart husk particle (F) AKA The kart husk itself + "DKRG", // Kart husk particle (G) + "DKRH", // Kart husk particle (H) + "DKRI", // Kart husk particle (I) + "DKRJ", // Kart husk particle (J) + "DKRK", // Kart husk particle (K) }; playersprite_t free_spr2 = SPR2_FIRSTFREESLOT; @@ -893,7 +903,17 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_SIGN, // SPR2_SSIG 0, // SPR2_XTRA 0, // SPR2_TALK - 0, // SPR2_DKRT + 0, // SPR2_DKRA + 0, // SPR2_DKRB + 0, // SPR2_DKRC + 0, // SPR2_DKRD + 0, // SPR2_DKRE + 0, // SPR2_DKRF + 0, // SPR2_DKRG + 0, // SPR2_DKRH + 0, // SPR2_DKRI + 0, // SPR2_DKRJ + 0, // SPR2_DKRK }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -958,7 +978,17 @@ state_t states[NUMSTATES] = {SPR_KART, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER {SPR_DIEF, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER_NOTIRES - {SPR_PLAY, SPR2_DKRT,3,{NULL},0,0,S_KART_LEFTOVER_CUSTOM},// S_KART_LEFTOVER_CUSTOM + {SPR_PLAY, SPR2_DKRA, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_A}, // S_KART_LEFTOVER_PARTICLE_CUSTOM_A + {SPR_PLAY, SPR2_DKRB, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_B}, // S_KART_LEFTOVER_PARTICLE_CUSTOM_B + {SPR_PLAY, SPR2_DKRC, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_C}, // S_KART_LEFTOVER_PARTICLE_CUSTOM_C + {SPR_PLAY, SPR2_DKRD, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_D}, // S_KART_LEFTOVER_PARTICLE_CUSTOM_D + {SPR_PLAY, SPR2_DKRE, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_E}, // S_KART_LEFTOVER_PARTICLE_CUSTOM_E + {SPR_PLAY, SPR2_DKRF, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_F},// S_KART_LEFTOVER_PARTICLE_CUSTOM_F + {SPR_PLAY, SPR2_DKRG, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_G}, // S_KART_LEFTOVER_PARTICLE_CUSTOM_G + {SPR_PLAY, SPR2_DKRH, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_H}, // S_KART_LEFTOVER_PARTICLE_CUSTOM_H + {SPR_PLAY, SPR2_DKRI, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_I}, // S_KART_LEFTOVER_PARTICLE_CUSTOM_I + {SPR_PLAY, SPR2_DKRJ, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_J}, // S_KART_LEFTOVER_PARTICLE_CUSTOM_J + {SPR_PLAY, SPR2_DKRK, 3, {NULL}, 0, 0, S_KART_LEFTOVER_PARTICLE_CUSTOM_K}, // S_KART_LEFTOVER_PARTICLE_CUSTOM_K {SPR_TIRE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_TIRE1 {SPR_TIRE, 1, -1, {NULL}, 0, 0, S_NULL}, // S_KART_TIRE2 diff --git a/src/info.h b/src/info.h index fc27b881c..70391a3f8 100644 --- a/src/info.h +++ b/src/info.h @@ -1384,7 +1384,17 @@ typedef enum playersprite SPR2_SIGN, SPR2_SIGL, SPR2_SSIG, SPR2_XTRA, SPR2_TALK, - SPR2_DKRT, + SPR2_DKRA, + SPR2_DKRB, + SPR2_DKRC, + SPR2_DKRD, + SPR2_DKRE, + SPR2_DKRF, + SPR2_DKRG, + SPR2_DKRH, + SPR2_DKRI, + SPR2_DKRJ, + SPR2_DKRK, SPR2_FIRSTFREESLOT, SPR2_LASTFREESLOT = 0x7f, @@ -1445,7 +1455,17 @@ typedef enum state S_KART_LEFTOVER, S_KART_LEFTOVER_NOTIRES, - S_KART_LEFTOVER_CUSTOM, + S_KART_LEFTOVER_PARTICLE_CUSTOM_A, + S_KART_LEFTOVER_PARTICLE_CUSTOM_B, + S_KART_LEFTOVER_PARTICLE_CUSTOM_C, + S_KART_LEFTOVER_PARTICLE_CUSTOM_D, + S_KART_LEFTOVER_PARTICLE_CUSTOM_E, + S_KART_LEFTOVER_PARTICLE_CUSTOM_F, + S_KART_LEFTOVER_PARTICLE_CUSTOM_G, + S_KART_LEFTOVER_PARTICLE_CUSTOM_H, + S_KART_LEFTOVER_PARTICLE_CUSTOM_I, + S_KART_LEFTOVER_PARTICLE_CUSTOM_J, + S_KART_LEFTOVER_PARTICLE_CUSTOM_K, S_KART_TIRE1, S_KART_TIRE2, diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 4f91c412f..c1aaf1642 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -3315,12 +3315,22 @@ static void K_drawKartEmeralds(void) } } -INT32 K_GetTransFlagFromFixed(fixed_t value) +INT32 K_GetTransFlagFromFixed(fixed_t value, boolean midrace) { - value = std::clamp(value, FRACUNIT/2, FRACUNIT*3/2); + fixed_t base = midrace ? GRADINGFACTORSOFTCAP : FRACUNIT; - // Calculate distance from 1.0 - fixed_t distance = abs(FRACUNIT - value); + value = std::clamp(value, base - FRACUNIT/2, base + FRACUNIT/2); + + // Calculate distance from "base"" + fixed_t distance = abs(base - value); + + if (midrace) + { + if (value > base) + distance = FixedMul(distance, GRADINGFACTORCAPSTRENGTH); + } + + distance = std::clamp(distance, 0, FRACUNIT/2); // Map the distance to 0-10 range (10 = closest to 1.0, 0 = farthest from 1.0) INT32 transLevel = 10 - ((distance * 10) / (FRACUNIT/2)); @@ -4090,6 +4100,13 @@ static boolean K_drawKartLaps(void) UINT16 displayEXP = stplyr->karthud[khud_exp]; + // Odds debugger + if (cv_vorpal.value) + { + displayEXP = 100 * K_EffectiveGradingFactor(stplyr) / FRACUNIT; + } + + // Jesus Christ. // I do not understand the way this system of offsets is laid out at all, // so it's probably going to be pretty bad to maintain. Sorry. @@ -4213,7 +4230,7 @@ static boolean K_drawKartLaps(void) // WHAT IS THIS? // WHAT ARE YOU FUCKING TALKING ABOUT? V_DrawMappedPatch(fr, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_exp[1], R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MUSTARD, GTC_CACHE)); - auto transflag = K_GetTransFlagFromFixed(K_EffectiveGradingFactor(stplyr)); + auto transflag = K_GetTransFlagFromFixed(K_EffectiveGradingFactor(stplyr), true); skincolornum_t overlaycolor = K_EffectiveGradingFactor(stplyr) < FRACUNIT ? SKINCOLOR_RUBY : SKINCOLOR_ULTRAMARINE ; auto colormap = R_GetTranslationColormap(TC_RAINBOW, overlaycolor, GTC_CACHE); V_DrawMappedPatch(fr, fy, transflag|V_SLIDEIN|splitflags, kp_exp[1], colormap); @@ -4236,7 +4253,7 @@ static boolean K_drawKartLaps(void) V_DrawMappedPatch(LAPS_X+bump, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_exp[0], R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MUSTARD, GTC_CACHE)); - auto transflag = K_GetTransFlagFromFixed(K_EffectiveGradingFactor(stplyr)); + auto transflag = K_GetTransFlagFromFixed(K_EffectiveGradingFactor(stplyr), true); skincolornum_t overlaycolor = K_EffectiveGradingFactor(stplyr) < FRACUNIT ? SKINCOLOR_RUBY : SKINCOLOR_ULTRAMARINE ; auto colormap = R_GetTranslationColormap(TC_RAINBOW, overlaycolor, GTC_CACHE); V_DrawMappedPatch(LAPS_X+bump, LAPS_Y, transflag|V_SLIDEIN|splitflags, kp_exp[0], colormap); diff --git a/src/k_hud.h b/src/k_hud.h index c251fc137..d0b5ba81a 100644 --- a/src/k_hud.h +++ b/src/k_hud.h @@ -67,7 +67,7 @@ void K_drawButton(fixed_t x, fixed_t y, INT32 flags, patch_t *button[2], boolean void K_drawButtonAnim(INT32 x, INT32 y, INT32 flags, patch_t *button[2], tic_t animtic); void K_DrawSticker(INT32 x, INT32 y, INT32 width, INT32 flags, boolean isSmall); void K_DrawMarginSticker(INT32 x, INT32 y, INT32 width, INT32 flags, boolean isSmall, boolean leftedge); -INT32 K_GetTransFlagFromFixed(fixed_t value); +INT32 K_GetTransFlagFromFixed(fixed_t value, boolean midrace); void K_DrawKartPositionNumXY( UINT8 num, diff --git a/src/k_kart.c b/src/k_kart.c index ead1570f0..dbc50a360 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -151,7 +151,13 @@ fixed_t K_EffectiveGradingFactor(const player_t *player) fixed_t min = (franticitems) ? MINFRANTICFACTOR : MINGRADINGFACTOR; if (grandprixinfo.gp && grandprixinfo.masterbots && !K_PlayerUsesBotMovement(player)) return min; - return max(min, player->gradingfactor); + + fixed_t gf = player->gradingfactor; + + if (gf > GRADINGFACTORSOFTCAP) + gf = GRADINGFACTORSOFTCAP + FixedDiv(gf - GRADINGFACTORSOFTCAP, GRADINGFACTORCAPSTRENGTH); + + return max(min, gf); } player_t *K_DuelOpponent(player_t *player) @@ -497,7 +503,7 @@ boolean K_IsPlayerLosing(player_t *player) } // Some behavior should change if the player approaches the frontrunner unusually fast. -fixed_t K_PlayerScamPercentage(player_t *player, UINT8 mult) +fixed_t K_PlayerScamPercentage(const player_t *player, UINT8 mult) { if (!M_NotFreePlay()) return 0; @@ -3146,15 +3152,9 @@ fixed_t K_PlayerTripwireSpeedThreshold(const player_t *player) if (modeattacking && !(gametyperules & GTR_CATCHER)) required_speed = 4 * K_GetKartSpeed(player, false, false); - UINT32 distance = K_GetItemRouletteDistance(player, 8); - if ((gametyperules & GTR_CIRCUIT) && !K_Cooperative() && M_NotFreePlay() && !modeattacking) { - if (distance < SCAMDIST) // Players near 1st need more speed! - { - fixed_t percentscam = FixedDiv(FRACUNIT*(SCAMDIST - distance), FRACUNIT*SCAMDIST); - required_speed += FixedMul(required_speed, percentscam); - } + required_speed += FixedMul(required_speed, K_PlayerScamPercentage(player, 2)); // Proration: Players near 1st need more speed! } @@ -4690,6 +4690,15 @@ void K_CheckpointCrossAward(player_t *player) else { K_AddMessage("Margin Boost!", true, false); + S_StartSound(NULL, sfx_duelmb); // Duel announcer call, we only do this on the first margin boost + + // fade out the song for a bit + g_musicfade.start = leveltime; + g_musicfade.end = g_musicfade.start + 70; + g_musicfade.fade = 6; + g_musicfade.ticked = false; + + // epic lighting g_darkness.start = leveltime; g_darkness.end = INT32_MAX; for (UINT8 i = 0; i < MAXSPLITSCREENPLAYERS; i++) @@ -4698,7 +4707,12 @@ void K_CheckpointCrossAward(player_t *player) } } - S_StartSound(NULL, sfx_gsha6); + player_t *foeplayer = K_DuelOpponent(player); + + if (!(player->duelscore - foeplayer->duelscore == DUELWINNINGSCORE)) // Avoid playing margin boost sfx when someone wins + { + S_StartSound(NULL, sfx_gsha6); // Gunstar chk-ching noise + } } player_t *opp = K_DuelOpponent(player); @@ -11550,14 +11564,21 @@ void K_KartResetPlayerColor(player_t *player) goto finalise; } - if (player->overdrive && (leveltime & 1)) + boolean allowflashing = true; + if (demo.playback && cv_reducevfx.value && !R_CanShowSkinInDemo(player->skin)) + { + // messy condition stack for, specifically, disabling flashing effects when viewing a staff ghost replay of a currently hidden character + allowflashing = false; + } + + if (player->overdrive && (leveltime & 1) && allowflashing) { player->mo->colorized = true; fullbright = true; player->mo->color = player->skincolor; goto finalise; } - else if (player->overdrive) + else if (player->overdrive && allowflashing) { player->mo->colorized = true; fullbright = true; @@ -11565,7 +11586,7 @@ void K_KartResetPlayerColor(player_t *player) goto finalise; } - if (player->ringboost && (leveltime & 1)) // ring boosting + if (player->ringboost && (leveltime & 1) && allowflashing) // ring boosting { player->mo->colorized = true; fullbright = true; diff --git a/src/k_kart.h b/src/k_kart.h index 63b61a53d..a1639ec66 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -135,6 +135,8 @@ player_t *K_DuelOpponent(player_t *player); fixed_t K_EffectiveGradingFactor(const player_t *player); #define MINGRADINGFACTOR (FRACUNIT/2) #define MINFRANTICFACTOR (8*FRACUNIT/10) +#define GRADINGFACTORSOFTCAP (FRACUNIT) +#define GRADINGFACTORCAPSTRENGTH (3*FRACUNIT) void K_TimerReset(void); void K_TimerInit(void); @@ -143,7 +145,7 @@ UINT32 K_GetPlayerDontDrawFlag(player_t *player); void K_ReduceVFXForEveryone(mobj_t *mo); boolean K_IsPlayerLosing(player_t *player); -fixed_t K_PlayerScamPercentage(player_t *player, UINT8 mult); +fixed_t K_PlayerScamPercentage(const player_t *player, UINT8 mult); fixed_t K_GetKartGameSpeedScalar(SINT8 value); INT32 K_GetShieldFromItem(INT32 item); diff --git a/src/k_podium.cpp b/src/k_podium.cpp index 564155315..b18ec7211 100644 --- a/src/k_podium.cpp +++ b/src/k_podium.cpp @@ -745,7 +745,7 @@ void podiumData_s::Draw(void) factor = FRACUNIT - FixedDiv(factor, bluemaxoffset); } - auto transflag = K_GetTransFlagFromFixed(factor); + auto transflag = K_GetTransFlagFromFixed(factor, false); drawer_gametype .xy(0, 1) .colorize(static_cast(overlaycolor)) @@ -915,7 +915,7 @@ void podiumData_s::Draw(void) factor = FRACUNIT - FixedDiv(factor, bluemaxoffset); } - auto transflag = K_GetTransFlagFromFixed(factor); + auto transflag = K_GetTransFlagFromFixed(factor, false); drawer_totals_right .colorize(static_cast(overlaycolor)) .flags(transflag) diff --git a/src/k_roulette.c b/src/k_roulette.c index 8a734688a..6c5aad085 100644 --- a/src/k_roulette.c +++ b/src/k_roulette.c @@ -1426,7 +1426,7 @@ void K_FillItemRouletteData(player_t *player, itemroulette_t *const roulette, bo // 5: Skim any items that are much weaker than the reel's average out of the roulette // 6: Cram it all in - fixed_t largegamescaler = roulette->playing * 6 + 100; // Spread out item odds in large games for a less insane experience. + fixed_t largegamescaler = roulette->playing * 10 + 100; // Spread out item odds in large games for a less insane experience. UINT32 targetpower = 100 * roulette->dist / largegamescaler; // fill roulette with items around this value! UINT32 powers[NUMKARTRESULTS]; // how strong is each item? think of this as a "target distance" for this item to spawn at @@ -1642,7 +1642,7 @@ void K_FillItemRouletteData(player_t *player, itemroulette_t *const roulette, bo // Conversely, if we're lonely, try not to reselect an item that wouldn't be useful to us // without any players to use it on. if (K_IsItemUselessAlone(bestitem)) - deltapenalty = Easing_InCubic(loneliness, deltapenalty, 3*deltapenalty); + deltapenalty = Easing_Linear(loneliness, deltapenalty, 5*deltapenalty); // Draw complex odds debugger. This one breaks down all the calcs in order. if (cv_kartdebugdistribution.value > 1) diff --git a/src/objects/destroyed-kart.cpp b/src/objects/destroyed-kart.cpp index 14643c5c9..0db43836e 100644 --- a/src/objects/destroyed-kart.cpp +++ b/src/objects/destroyed-kart.cpp @@ -55,16 +55,32 @@ struct Particle : Mobj bool is_shrapnel() const { return sprite == SPR_KRBM; } - static void spew(Mobj* source) + static void spew(Mobj* source,int pskin) { - auto generic = [&](spritenum_t sprite, int degr, Fixed scale, int momx, const Vec2& momz) + auto generic = [&](spritenum_t sprite, int pskinn, statenum_t spr2state, int degr, Fixed scale, int momx, const Vec2& momz) { Particle* x = source->spawn_from({}, MT_KART_PARTICLE); if (x) { - x->sprite = sprite; + if(pskinn >= 0 && pskinn < numskins + && spr2state > S_NULL && spr2state < NUMSTATES && + states[spr2state].frame >= 0 && states[spr2state].frame < NUMPLAYERSPRITES * 2 && //'NUMPLAYERSPRITES * 2' being the length of the 'skin_t.sprites' array member + skins[pskinn]->sprites[states[spr2state].frame].numframes > 0) + { + + x->skin = (void*)(&skins[pskinn]); + x->state(spr2state); + //frame will be set by state() + } + else{ + //state will be set by mapthing definition + x->sprite = sprite; + x->frame = 0; + } + + x->frame |=FF_SEMIBRIGHT; + x->color = source->color; - x->frame = FF_SEMIBRIGHT; x->lightlevel = 112; x->scale(scale * x->scale()); @@ -79,34 +95,34 @@ struct Particle : Mobj return x; }; - auto part = [&](spritenum_t sprite, int degr, Fixed scale) + auto part = [&](spritenum_t sprite, int pskinn, statenum_t spr2state, int degr, Fixed scale) { - return generic(sprite, degr, scale, 2, {8, 16}); + return generic(sprite, pskinn, spr2state, degr, scale, 2, {8, 16}); }; - auto radial = [&](spritenum_t sprite, int ofs, int spokes, Fixed scale) + auto radial = [&](spritenum_t sprite, int pskinn, statenum_t spr2state, int ofs, int spokes, Fixed scale) { - radial_generic(ofs, spokes, [&](int ang) { part(sprite, ang, scale); }); + radial_generic(ofs, spokes, [&](int ang) { part(sprite, pskinn, spr2state, ang, scale); }); }; constexpr Fixed kSmall = 3*FRACUNIT/2; constexpr Fixed kMedium = 7*FRACUNIT/4; constexpr Fixed kLarge = 2*FRACUNIT; - part(SPR_DIEE, 0, kLarge); // steering wheel - part(SPR_DIEK, 180 + 45, kLarge); // engine + part(SPR_DIEE, pskin, S_KART_LEFTOVER_PARTICLE_CUSTOM_E, 0, kLarge); // steering wheel + part(SPR_DIEK, pskin, S_KART_LEFTOVER_PARTICLE_CUSTOM_K, 180 + 45, kLarge); // engine - part(SPR_DIEG, 90, kLarge); // left pedal base - part(SPR_DIED, -90, kLarge); // right pedal base + part(SPR_DIEG, pskin, S_KART_LEFTOVER_PARTICLE_CUSTOM_G, 90, kLarge); // left pedal base + part(SPR_DIED, pskin, S_KART_LEFTOVER_PARTICLE_CUSTOM_D, -90, kLarge); // right pedal base - radial(SPR_DIEI, 90, 2, kLarge); // wheel axle bars - radial(SPR_DIEC, 90, 2, kLarge); // pedal tips - radial(SPR_DIEA, 45, 4, kMedium); // tires - radial(SPR_DIEH, 45, 4, kMedium); // struts / springs - radial(SPR_DIEB, 360/12, 6, kSmall); // pipeframe bars - radial(SPR_DIEJ, 360/16, 8, kSmall); // screws + radial(SPR_DIEI, pskin, S_KART_LEFTOVER_PARTICLE_CUSTOM_I, 90, 2, kLarge); // wheel axle bars + radial(SPR_DIEC, pskin, S_KART_LEFTOVER_PARTICLE_CUSTOM_C, 90, 2, kLarge); // pedal tips + radial(SPR_DIEA, pskin, S_KART_LEFTOVER_PARTICLE_CUSTOM_A, 45, 4, kMedium); // tires + radial(SPR_DIEH, pskin, S_KART_LEFTOVER_PARTICLE_CUSTOM_H, 45, 4, kMedium); // struts / springs + radial(SPR_DIEB, pskin, S_KART_LEFTOVER_PARTICLE_CUSTOM_B, 360/12, 6, kSmall); // pipeframe bars + radial(SPR_DIEJ, pskin, S_KART_LEFTOVER_PARTICLE_CUSTOM_J, 360/16, 8, kSmall); // screws - radial_generic(0, 6, [&](int degr) { generic(SPR_KRBM, degr, kSmall, 8, {22, 28}); }); // shrapnel + radial_generic(0, 6, [&](int degr) { generic(SPR_KRBM, -1, S_NULL, degr, kSmall, 8, {22, 28}); }); // shrapnel // explosion radial_generic( @@ -320,15 +336,15 @@ struct Kart : Mobj Mobj* p = player(); bool pValid = Mobj::valid(p) && p->player; - bool hasCustomHusk = pValid && skins[p->player->skin]->sprites[SPR2_DKRT].numframes; + int pSkin = pValid ? p->player->skin : -1; //rip lyman lineface :-1 + bool hasCustomHusk = pSkin >=0 && pSkin < numskins && skins[pSkin]->sprites[SPR2_DKRF].numframes; if(hasCustomHusk) { - skin = (void*)(skins[p->player->skin]); - frame = 0; + skin = (void*)(skins[pSkin]); } - Particle::spew(this); + Particle::spew(this,pSkin); scale(3*scale()/2); if(hasCustomHusk){ @@ -339,7 +355,7 @@ struct Kart : Mobj } health = 1; - state(!hasCustomHusk ? S_KART_LEFTOVER_NOTIRES : S_KART_LEFTOVER_CUSTOM); + state(!hasCustomHusk ? S_KART_LEFTOVER_NOTIRES : S_KART_LEFTOVER_PARTICLE_CUSTOM_F); cooldown(20); burning(burn_duration()); diff --git a/src/p_inter.c b/src/p_inter.c index 8151a2c2d..a9ba1f151 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -697,6 +697,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (K_TryPickMeUp(special, toucher, false)) return; + if (special->target && !P_MobjWasRemoved(special->target) && toucher->player && (toucher->player != (special->target->player))) // Last condition here is so you can't get your own amps + { + K_SpawnAmps(special->target->player, K_PvPAmpReward(20, special->target->player, toucher->player), toucher); + } + // attach to player! P_SetTarget(&special->tracer, toucher); toucher->flags |= MF_NOGRAVITY; @@ -3457,6 +3462,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da case DMG_EXPLODE: type = DMG_TUMBLE; downgraded = true; + softenTumble = true; break; case DMG_TUMBLE: softenTumble = true; diff --git a/src/p_maputl.c b/src/p_maputl.c index 1388f4b6c..dca379e83 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -452,7 +452,11 @@ P_GetMidtextureTopBottom { side_t *side = &sides[linedef->sidenum[0]]; fixed_t textop, texbottom, texheight; - INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid + //Attempt to decouple collision from animation + INT32 texnum = side->midtexture; // make sure the texture is actually valid + //Sanity check on toaster's suggestion + if (texnum < 0 || texnum >= numtextures) + texnum = 0; sector_t *front = linedef->frontsector; sector_t *back = linedef->backsector; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index e011031e0..e3a19a57a 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -9772,3 +9772,21 @@ boolean P_MultiSetupWadFiles(boolean fullsetup) partadd_stage++; return false; } + +// +// Let's see if this works +// +void P_ReduceVFXTextureReload(void) +{ + P_InitPicAnims(); +} + +// Let's see if *this* works +extern "C" void ReduceVFX_OnChange(void); +void ReduceVFX_OnChange(void) +{ + if (con_startup_loadprogress < LOADED_CONFIG) + return; + P_ReduceVFXTextureReload(); +} + diff --git a/src/p_setup.h b/src/p_setup.h index 820f039fa..a9839e3f8 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -142,6 +142,7 @@ boolean P_MultiSetupWadFiles(boolean fullsetup); SINT8 P_PartialAddGetStage(void); extern UINT16 partadd_earliestfile; +void P_ReduceVFXTextureReload(void); boolean P_RunSOC(const char *socfilename); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); diff --git a/src/p_spec.c b/src/p_spec.c index d312b6d1f..acd67477b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -153,8 +153,8 @@ static void GrowAnimDefs(void) } // A prototype; here instead of p_spec.h, so they're "private" -void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum); -void P_ParseAnimationDefintion(void); +void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum, boolean photosens); +void P_ParseAnimationDefintion(boolean photosens); /** Sets up texture and flat animations. * @@ -181,12 +181,24 @@ void P_InitPicAnims(void) { UINT16 animdefsLumpNum; + if (cv_reducevfx.value) + { + // Find RVFXANIM lump in the WAD *first* + animdefsLumpNum = W_CheckNumForNamePwad("RVFXANIM", w, 0); + + while (animdefsLumpNum != INT16_MAX) + { + P_ParseANIMDEFSLump(w, animdefsLumpNum, true); + animdefsLumpNum = W_CheckNumForNamePwad("RVFXANIM", (UINT16)w, animdefsLumpNum + 1); + } + } + // Find ANIMDEFS lump in the WAD animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); while (animdefsLumpNum != INT16_MAX) { - P_ParseANIMDEFSLump(w, animdefsLumpNum); + P_ParseANIMDEFSLump(w, animdefsLumpNum, false); animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1); } } @@ -238,7 +250,7 @@ void P_InitPicAnims(void) animdefs = NULL; } -void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum) +void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum, boolean photosens) { char *animdefsLump; size_t animdefsLumpLength; @@ -271,7 +283,7 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum) if (stricmp(animdefsToken, "TEXTURE") == 0) { Z_Free(animdefsToken); - P_ParseAnimationDefintion(); + P_ParseAnimationDefintion(photosens); } else if (stricmp(animdefsToken, "FLAT") == 0) { @@ -286,16 +298,20 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum) { I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\", got \"%s\"",animdefsToken); } - // parse next line - while (*p != '\0' && *p != '\n') ++p; - if (*p == '\n') ++p; + + do // get next content line to parse + { + while (*p != '\0' && *p != '\n') ++p; // skips content of evaluated line + while (*p == '\n') ++p; // skips extra blank lines + } while (*p == '/' && *(p+1) == '/'); // skips comments + animdefsToken = M_GetToken(p); } Z_Free(animdefsToken); Z_Free((void *)animdefsText); } -void P_ParseAnimationDefintion(void) +void P_ParseAnimationDefintion(boolean photosens) { char *animdefsToken; size_t animdefsTokenLength; @@ -436,6 +452,12 @@ void P_ParseAnimationDefintion(void) { I_Error("Error parsing ANIMDEFS lump: Expected a positive integer for \"%s\"'s animation speed, got \"%s\"", animdefs[i].startname, animdefsToken); } + // Not letting anyone mess up a photosensitivity feature like this. + if ((photosens) && animSpeed < 8) + { + CONS_Alert(CONS_WARNING, M_GetText("RVFXANIM: Animation speed of \"%s\" is less than 8 - automatically set to 8\n"), animdefs[i].startname); + animSpeed = 8; + } animdefs[i].speed = animSpeed; Z_Free(animdefsToken); } diff --git a/src/r_main.h b/src/r_main.h index 79005f7cc..f17ef9551 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -139,6 +139,7 @@ extern consvar_t cv_debugfinishline; extern consvar_t cv_drawinput; extern consvar_t cv_drawtimer; extern consvar_t cv_debugfonts; +extern consvar_t cv_vorpal; // debugging diff --git a/src/r_spritefx.cpp b/src/r_spritefx.cpp index dea525c11..7c00321a0 100644 --- a/src/r_spritefx.cpp +++ b/src/r_spritefx.cpp @@ -46,8 +46,7 @@ INT32 R_ThingLightLevel(mobj_t* thing) } if (!R_CanShowSkinInDemo(((skin_t*)thing->skin)->skinnum) - && !thing->colorized - && !thing->hitlag) + && ((cv_reducevfx.value) || (!thing->colorized && !thing->hitlag))) { lightlevel -= 128; } diff --git a/src/sounds.c b/src/sounds.c index a2268630b..6c092bf3d 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1284,6 +1284,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"bpwrue", false, 255, 16, -1, NULL, 0, -1, -1, LUMPERROR, "Super Flicky"}, {"bpwruf", false, 255, 16, -1, NULL, 0, -1, -1, LUMPERROR, "Bonus"}, + // Misc announcer calls + {"duelmb", false, 255, 16, -1, NULL, 0, -1, -1, LUMPERROR, "Margin Boost"}, + // SRB2Kart - Engine sounds // Engine class A {"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, diff --git a/src/sounds.h b/src/sounds.h index 2dd034866..7d87f1e85 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1360,6 +1360,9 @@ typedef enum sfx_bpwrue, // Super Flicky sfx_bpwruf, // Bonus + // Misc announcer calls + sfx_duelmb, // Margin Boost + // Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy... // Engine class A - Low Speed, Low Weight sfx_krta00, diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 47f48a0af..972b99af8 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -2421,6 +2421,7 @@ int W_VerifyNMUSlumps(const char *filename, FILE *handle, boolean exit_on_error) {"MKFNT", 5}, // Kart font changes {"K_", 2}, // Kart graphic changes {"MUSICDEF", 8}, // Kart song definitions + {"RVFXANIM", 8}, // Photosensitivity texture animation changes {"TLG_", 4}, // Generic button legends