diff --git a/src/d_player.h b/src/d_player.h index 8600d61d3..866589dfb 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -306,6 +306,7 @@ typedef enum k_accelboost, // Boost value smoothing for acceleration k_boostcam, // Camera push forward on boost k_destboostcam, // Ditto + k_timeovercam, // Camera timer for leaving behind or not k_aizdriftstrat, // Let go of your drift while boosting? Helper for the SICK STRATZ you have just unlocked k_itemroulette, // Used for the roulette when deciding what item to give you (was "pw_kartitem") diff --git a/src/dehacked.c b/src/dehacked.c index 33e65c4be..77663ccda 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1838,11 +1838,13 @@ static actionpointer_t actionpointers[] = {{A_SPBChase}, "A_SPBCHASE"}, // SRB2kart {{A_MineExplode}, "A_MINEEXPLODE"}, // SRB2kart {{A_BallhogExplode}, "A_BALLHOGEXPLODE"}, // SRB2kart - {{A_LightningFollowPlayer},"A_LIGHTNINGFOLLOWPLAYER"}, //SRB2kart - {{A_RandomShadowFrame}, "A_RANDOMSHADOWFRAME"}, //SRB2kart - {{A_RoamingShadowThinker}, "A_ROAMINGSHADOWTHINKER"}, //SRB2kart - {{A_ReaperThinker}, "A_REAPERTHINKER"}, //SRB2kart - {{A_MementosTPParticles}, "A_MEMENTOSTPPARTICLES"}, //SRB2kart + {{A_LightningFollowPlayer},"A_LIGHTNINGFOLLOWPLAYER"}, //SRB2kart + {{A_FZBoomFlash}, "A_FZBOOMFLASH"}, //SRB2kart + {{A_FZBoomSmoke}, "A_FZBOOMSMOKE"}, //SRB2kart + {{A_RandomShadowFrame}, "A_RANDOMSHADOWFRAME"}, //SRB2kart + {{A_RoamingShadowThinker}, "A_ROAMINGSHADOWTHINKER"}, //SRB2kart + {{A_ReaperThinker}, "A_REAPERTHINKER"}, //SRB2kart + {{A_MementosTPParticles}, "A_MEMENTOSTPPARTICLES"}, //SRB2kart {{A_OrbitNights}, "A_ORBITNIGHTS"}, {{A_GhostMe}, "A_GHOSTME"}, {{A_SetObjectState}, "A_SETOBJECTSTATE"}, @@ -6804,6 +6806,31 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_KLIT11", "S_KLIT12", + "S_FZEROSMOKE1", // F-Zero NO CONTEST explosion + "S_FZEROSMOKE2", + "S_FZEROSMOKE3", + "S_FZEROSMOKE4", + "S_FZEROSMOKE5", + + "S_FZEROBOOM1", + "S_FZEROBOOM2", + "S_FZEROBOOM3", + "S_FZEROBOOM4", + "S_FZEROBOOM5", + "S_FZEROBOOM6", + "S_FZEROBOOM7", + "S_FZEROBOOM8", + "S_FZEROBOOM9", + "S_FZEROBOOM10", + "S_FZEROBOOM11", + "S_FZEROBOOM12", + + "S_FZSLOWSMOKE1", + "S_FZSLOWSMOKE2", + "S_FZSLOWSMOKE3", + "S_FZSLOWSMOKE4", + "S_FZSLOWSMOKE5", + // Midnight Channel stuff: "S_SPOTLIGHT", // Spotlight decoration "S_RANDOMSHADOW", // Random Shadow. They're static and don't do nothing. @@ -7488,6 +7515,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_KARMAHITBOX", "MT_KARMAWHEEL", + "MT_FZEROBOOM", + // Midnight Channel stuff: "MT_SPOTLIGHT", // Spotlight Object "MT_RANDOMSHADOW", // Random static Shadows. @@ -7507,7 +7536,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_CDBUSH", "MT_CDTREEA", "MT_CDTREEB", - + #ifdef SEENAMES "MT_NAMECHECK", #endif @@ -7864,6 +7893,7 @@ static const char *const KARTSTUFF_LIST[] = { "ACCELBOOST", "BOOSTCAM", "DESTBOOSTCAM", + "TIMEOVERCAM", "AIZDRIFTSTRAT", "ITEMROULETTE", diff --git a/src/info.c b/src/info.c index f8ffb632f..3366e5df0 100644 --- a/src/info.c +++ b/src/info.c @@ -57,12 +57,12 @@ char sprnames[NUMSPRITES + 1][5] = //SRB2kart Sprites "SPRG","BSPR","RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE", "KINV","KINF","WIPD","DRIF","DUST","RSHE","FITM","BANA","ORBN","JAWZ", - "SSMN","KRBM","BHOG","BHBM","BLIG","LIGH","THNS","SINK","SITR","KBLN", - "DEZL","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM", - "SACO","CRAB","SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB", - "ARRO","ITEM","ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK", - "LZI1","LZI2","KLIT", "SPTL", "ENM1", "GARU", "MARR", "REAP", "JITB", - "CDMO", "CDBU", "VIEW" + "SSMN","KRBM","BHOG","BHBM","SPBM","THNS","SINK","SITR","KBLN","DEZL", + "POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO", + "CRAB","SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO", + "ITEM","ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK","LZI1", + "LZI2","KLIT","FZSM","FZBM","FPRT","SPTL","ENM1","GARU","MARR","REAP", + "JITB","CDMO","CDBU","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -3043,13 +3043,8 @@ state_t states[NUMSTATES] = {SPR_SPBM, 8, 1, {NULL}, 0, 0, S_PLAYERBOMB1}, // S_PLAYERBOMB20 {SPR_RNDM, FF_ANIMATE, -1, {NULL}, 23, 3, S_NULL}, // S_PLAYERITEM {SPR_FITM, FF_ANIMATE, -1, {NULL}, 23, 3, S_NULL}, // S_PLAYERFAKE -<<<<<<< HEAD -======= {SPR_PBOM, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KARMAWHEEL ->>>>>>> master - - {SPR_PBOM, 4, -1, {NULL}, 0, 0, S_NULL}, // S_KARMAWHEEL // Oh no it's annoying lightning states....... // Lightning Sparks (it's the ones we'll use for the radius) @@ -3089,18 +3084,43 @@ state_t states[NUMSTATES] = {SPR_LZI2, FF_TRANS70|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_LZIO29 // The slanted bolt. Man these states are boring as all heck to do. - {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT2}, // S_KLIT1 - {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT3}, // S_KLIT2 + {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT2}, // S_KLIT1 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT3}, // S_KLIT2 {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|1, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT4}, // S_KLIT3 - {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT5}, // S_KLIT4 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT5}, // S_KLIT4 {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|2, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT6}, // S_KLIT5 - {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT7}, // S_KLIT6 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT7}, // S_KLIT6 {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|3, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT8}, // S_KLIT7 - {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT9}, // S_KLIT8 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT9}, // S_KLIT8 {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|4, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT10}, // S_KLIT9 {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT11}, // S_KLIT10 {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|5, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT12}, // S_KLIT11 - {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT1}, // S_KLIT12 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT1}, // S_KLIT12 + + {SPR_FZSM, 0, 4, {NULL}, 0, 0, S_FZEROSMOKE2}, // S_FZEROSMOKE1 + {SPR_FZSM, 1, 4, {NULL}, 0, 0, S_FZEROSMOKE3}, // S_FZEROSMOKE2 + {SPR_FZSM, 2, 4, {NULL}, 0, 0, S_FZEROSMOKE4}, // S_FZEROSMOKE3 + {SPR_FZSM, 3, 4, {NULL}, 0, 0, S_FZEROSMOKE5}, // S_FZEROSMOKE4 + {SPR_FZSM, 4, 4, {NULL}, 0, 0, S_NULL}, // S_FZEROSMOKE5 + + {SPR_FZBM, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_FZEROBOOM2}, // S_FZEROBOOM1 + {SPR_FZBM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_FZEROBOOM3}, // S_FZEROBOOM2 + {SPR_FZBM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_FZEROBOOM4}, // S_FZEROBOOM3 + {SPR_FZBM, FF_FULLBRIGHT|3, 2, {A_FZBoomFlash}, 0, 0, S_FZEROBOOM5}, // S_FZEROBOOM4 + {SPR_FZBM, FF_FULLBRIGHT|2, 1, {A_FZBoomSmoke}, 0, 0, S_FZEROBOOM6}, // S_FZEROBOOM5 + {SPR_FZBM, FF_FULLBRIGHT|1, 1, {A_FZBoomSmoke}, 0, 0, S_FZEROBOOM7}, // S_FZEROBOOM6 + {SPR_NULL, 0, 1, {A_FZBoomSmoke}, 1, 0, S_FZEROBOOM8}, // S_FZEROBOOM7 + {SPR_NULL, 0, 1, {A_FZBoomSmoke}, 2, 0, S_FZEROBOOM9}, // S_FZEROBOOM8 + {SPR_NULL, 0, 1, {A_FZBoomSmoke}, 3, 0, S_FZEROBOOM10}, // S_FZEROBOOM9 + {SPR_NULL, 0, 1, {A_FZBoomSmoke}, 2, 0, S_FZEROBOOM11}, // S_FZEROBOOM10 + {SPR_NULL, 0, 1, {A_FZBoomSmoke}, 1, 0, S_FZEROBOOM12}, // S_FZEROBOOM11 + {SPR_NULL, 0, 1, {A_FZBoomSmoke}, 0, 0, S_NULL}, // S_FZEROBOOM12 + + {SPR_SMOK, FF_TRANS30, 30, {NULL}, 0, 0, S_FZSLOWSMOKE2}, // S_FZSLOWSMOKE1 + {SPR_SMOK, FF_TRANS30|1, 30, {NULL}, 0, 0, S_FZSLOWSMOKE3}, // S_FZSLOWSMOKE2 + {SPR_SMOK, FF_TRANS30|2, 30, {NULL}, 0, 0, S_FZSLOWSMOKE4}, // S_FZSLOWSMOKE3 + {SPR_SMOK, FF_TRANS30|3, 30, {NULL}, 0, 0, S_FZSLOWSMOKE5}, // S_FZSLOWSMOKE4 + {SPR_SMOK, FF_TRANS30|4, 30, {NULL}, 0, 0, S_NULL}, // S_FZSLOWSMOKE5 // Midnight Channel stuff, yay more boring states! {SPR_SPTL, 0, -1, {NULL}, 0, 0, S_SPOTLIGHT}, // S_SPOTLIGHT @@ -17256,8 +17276,34 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - // Midnight Channel stuff: + { // MT_FZEROBOOM + -1, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_kc31, // seesound + 8, // reactiontime + sfx_kc51, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + FRACUNIT, // radius + FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + // Midnight Channel stuff: { // MT_SPOTLIGHT 3124, // doomednum S_SPOTLIGHT, // spawnstate @@ -17602,10 +17648,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16<kartstuff[k_boostcam], player->kartstuff[k_destboostcam]); } + player->kartstuff[k_timeovercam] = 0; + if (player->kartstuff[k_spinouttimer]) { if ((P_IsObjectOnGround(player->mo) || player->kartstuff[k_spinouttype] == 1) diff --git a/src/p_enemy.c b/src/p_enemy.c index f25922be2..0e8066bee 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -193,7 +193,9 @@ void A_JawzExplode(mobj_t *actor); // SRB2kart void A_SPBChase(mobj_t *actor); // SRB2kart void A_MineExplode(mobj_t *actor); // SRB2kart void A_BallhogExplode(mobj_t *actor); // SRB2kart -void A_LightningFollowPlayer(mobj_t *actor); // SRB2kart +void A_LightningFollowPlayer(mobj_t *actor); // SRB2kart +void A_FZBoomFlash(mobj_t *actor); // SRB2kart +void A_FZBoomSmoke(mobj_t *actor); // SRB2kart void A_RandomShadowFrame(mobj_t *actor); // SRB2kart void A_RoamingShadowThinker(mobj_t *actor); //SRB2kart void A_MayonakaArrow(mobj_t *actor); //SRB2kart @@ -8179,7 +8181,7 @@ void A_ToggleFlameJet(mobj_t* actor) } } -//{ SRB2kart - A_ItemPop, A_JawzChase, A_JawzExplode, A_SPBChase, A_MineExplode, and A_BallhogExplode +//{ SRB2kart Actions void A_ItemPop(mobj_t *actor) { mobj_t *remains; @@ -8582,6 +8584,50 @@ void A_LightningFollowPlayer(mobj_t *actor) return; } +// A_FZBoomFlash: +// Flash everyone close enough to the boom +void A_FZBoomFlash(mobj_t *actor) +{ + UINT8 i; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FZBoomFlash", actor)) + return; +#endif + for (i = 0; i < MAXPLAYERS; i++) + { + fixed_t dist; + if (!playeringame[i] || !players[i].mo) + continue; + dist = P_AproxDistance(P_AproxDistance(actor->x-players[i].mo->x, actor->y-players[i].mo->y), actor->z-players[i].mo->z); + if (dist < 1536<x + (P_RandomRange(-rad, rad)*actor->scale), actor->y + (P_RandomRange(-rad, rad)*actor->scale), + actor->z + (P_RandomRange(0, 72)*actor->scale), MT_THOK); + + P_SetMobjState(smoke, S_FZEROSMOKE1); + smoke->tics += P_RandomRange(-3, 4); + smoke->scale = actor->scale*3; + } + return; +} + // A_RandomShadowFrame // Gives a random sprite for the Mayonaka static shadows. Dumb and simple. void A_RandomShadowFrame(mobj_t *actor) diff --git a/src/p_inter.c b/src/p_inter.c index 0c3c46897..01abb2160 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1994,7 +1994,7 @@ boolean P_CheckRacers(void) numplayersingame++; } - if (numplayersingame >= nospectategrief) // prevent spectate griefing + if (numplayersingame > 1 && nospectategrief > 0 && numplayersingame >= nospectategrief) // prevent spectate griefing { // check if we just got unlucky and there was only one guy who was a problem for (j = i+1; j < MAXPLAYERS; j++) @@ -2398,8 +2398,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) break; case MT_PLAYER: - target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player) target->momx = target->momy = target->momz = 0; + + if (target->player && target->player->pflags & PF_TIMEOVER) + break; + + target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player) if (!(source && source->type == MT_NULL && source->threshold == 42)) // Don't jump up when drowning P_SetObjectMomZ(target, 14*FRACUNIT, false); @@ -2766,6 +2770,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) // Get rid of shield player->powers[pw_shield] = SH_NONE; player->mo->color = player->skincolor; + player->mo->colorized = false; // Get rid of emeralds player->powers[pw_emeralds] = 0; @@ -2775,6 +2780,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) P_ResetPlayer(player); P_SetPlayerMobjState(player->mo, player->mo->info->deathstate); + /*if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) { P_PlayerFlagBurst(player, false); @@ -2801,6 +2807,17 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players])); }*/ + if (player->pflags & PF_TIMEOVER) + { + mobj_t *boom; + player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP); + player->mo->flags2 |= MF2_DONTDRAW; + boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM); + boom->scale = player->mo->scale; + boom->angle = player->mo->angle; + P_SetTarget(&boom->target, player->mo); + } + if (G_BattleGametype()) { if (player->kartstuff[k_bumper] > 0) diff --git a/src/p_map.c b/src/p_map.c index 3bc9521e1..1d8a2daa6 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2382,6 +2382,11 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) || (thiscam == &camera3 && (players[thirddisplayplayer].pflags & PF_NOCLIP)) || (thiscam == &camera4 && (players[fourthdisplayplayer].pflags & PF_NOCLIP)) || (leveltime < introtime)) +#else + if ((thiscam == &camera && !(players[displayplayer].pflags & PF_TIMEOVER)) + || (thiscam == &camera2 && !(players[secondarydisplayplayer].pflags & PF_TIMEOVER)) + || (thiscam == &camera3 && !(players[thirddisplayplayer].pflags & PF_TIMEOVER)) + || (thiscam == &camera4 && !(players[fourthdisplayplayer].pflags & PF_TIMEOVER))) #endif { // Noclipping player camera noclips too!! floatok = true; diff --git a/src/p_mobj.c b/src/p_mobj.c index 0ba943120..da0af87bf 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3711,6 +3711,8 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled dummy.y = thiscam->y; dummy.z = thiscam->z; dummy.height = thiscam->height; + if (player->pflags & PF_TIMEOVER) + player->kartstuff[k_timeovercam] = (2*TICRATE)+1; if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. P_ResetCamera(player, thiscam); else @@ -8494,6 +8496,64 @@ void P_MobjThinker(mobj_t *mobj) } } break; + case MT_FZEROBOOM: // F-Zero explosion + if (!mobj->extravalue1) + { + fixed_t mx = P_ReturnThrustX(NULL, mobj->angle, 32<angle, 32<x + (2*mx), mobj->y + (2*my), mobj->z+(mobj->height/2), MT_THOK); + + P_SetMobjState(explosion, S_FZEROBOOM1); + explosion->scale = mobj->scale*2; + explosion->momx = mx; + explosion->momy = my; + + S_StartSound(mobj, mobj->info->seesound); + mobj->extravalue1 = 1; + } + + if (!S_SoundPlaying(mobj, mobj->info->attacksound)) + S_StartSound(mobj, mobj->info->attacksound); + + if (mobj->extravalue2 > 70) // fire + smoke pillar + { + UINT8 i; + mobj_t *fire = P_SpawnMobj(mobj->x + (P_RandomRange(-32, 32)*mobj->scale), mobj->y + (P_RandomRange(-32, 32)*mobj->scale), mobj->z, MT_THOK); + + fire->sprite = SPR_FPRT; + fire->frame = FF_FULLBRIGHT|FF_TRANS30; + fire->scale = mobj->scale*4; + fire->momz = P_RandomRange(2, 3)*mobj->scale; + fire->scalespeed = mobj->scale/12; + fire->destscale = 1; + fire->tics = TICRATE; + + for (i = 0; i < 2; i++) + { + mobj_t *smoke = P_SpawnMobj(mobj->x + (P_RandomRange(-16, 16)*mobj->scale), mobj->y + (P_RandomRange(-16, 16)*mobj->scale), mobj->z, MT_SMOKE); + + P_SetMobjState(smoke, S_FZSLOWSMOKE1); + smoke->scale = mobj->scale; + smoke->momz = P_RandomRange(3, 10)*mobj->scale; + smoke->destscale = mobj->scale*4; + smoke->scalespeed = mobj->scale/24; + } + } + else + { + mobj->extravalue2++; // flametimer + + if (mobj->extravalue2 > 8) + { + mobj_t *smoke = P_SpawnMobj(mobj->x + (P_RandomRange(-31, 31)*mobj->scale), mobj->y + (P_RandomRange(-31, 31)*mobj->scale), + mobj->z + (P_RandomRange(0, 48)*mobj->scale), MT_THOK); + + P_SetMobjState(smoke, S_FZEROSMOKE1); + smoke->tics += P_RandomRange(-3, 4); + smoke->scale = mobj->scale*2; + } + } + break; //} case MT_TURRET: P_MobjCheckWater(mobj); diff --git a/src/p_user.c b/src/p_user.c index e5893754b..dc4bdaf56 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1181,7 +1181,7 @@ boolean P_EndingMusic(player_t *player) } if (G_RaceGametype() && bestlocalpos == MAXPLAYERS+1) - sprintf(buffer, "k*lose"); // krfail, for eventual F-Zero death results theme + sprintf(buffer, "k*fail"); // F-Zero death results theme else { if (bestlocalpos == 1) @@ -7887,25 +7887,22 @@ void P_FindEmerald(void) // static void P_DeathThink(player_t *player) { - //ticcmd_t *cmd = &player->cmd; - //player->deltaviewheight = 0; + if (player->pflags & PF_TIMEOVER) + { + player->kartstuff[k_timeovercam]++; + if (player->mo) + { + player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP); + player->mo->flags2 |= MF2_DONTDRAW; + } + } + else + player->kartstuff[k_timeovercam] = 0; if (player->deadtimer < INT32_MAX) player->deadtimer++; - // continue logic - /*if (!(netgame || multiplayer) && player->lives <= 0) - { - if (player->deadtimer > TICRATE && (cmd->buttons & BT_BRAKE || cmd->buttons & BT_ACCELERATE || cmd->buttons & BT_DRIFT) && player->continues > 0) - G_UseContinue(); - else if (player->deadtimer >= gameovertics) - G_UseContinue(); // Even if we don't have one this handles ending the game - }*/ - // Force respawn if idle for more than 30 seconds in shooter modes. - /*if (player->deadtimer > 30*TICRATE && !G_RaceGametype()) - player->playerstate = PST_REBORN; - else if (player->lives > 0 && !G_IsSpecialStage(gamemap)*/ if (player->lives > 0 /*&& leveltime >= starttime*/) // *could* you respawn? { // SRB2kart - spawn automatically after 1 second @@ -7914,55 +7911,6 @@ static void P_DeathThink(player_t *player) : TICRATE)) // don't let them change it in record attack player->playerstate = PST_REBORN; } - /*else if ((netgame || multiplayer) && player->deadtimer == 8*TICRATE) - { - // In a net/multiplayer game, and out of lives - if (gametype == GT_COMPETITION) - { - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && !players[i].exiting && players[i].lives > 0) - break; - - if (i == MAXPLAYERS) - { - // Everyone's either done with the race, or dead. - if (!countdown2 || countdown2 > 1*TICRATE) - countdown2 = 1*TICRATE; - } - } - - // In a coop game, and out of lives - if (gametype == GT_COOP) - { - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (players[i].exiting || players[i].lives > 0)) - break; - - if (i == MAXPLAYERS) - { - // They're dead, Jim. - //nextmapoverride = spstage_start; - nextmapoverride = gamemap; - countdown2 = 1*TICRATE; - skipstats = true; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - players[i].score = 0; - } - - //emeralds = 0; - tokenbits = 0; - tokenlist = 0; - token = 0; - } - } - }*/ // Keep time rolling if (!(countdown2 && !countdown) && !(player->exiting || mapreset) && !(player->pflags & PF_TIMEOVER)) @@ -7986,50 +7934,6 @@ static void P_DeathThink(player_t *player) } } - /*if (G_RaceGametype() && (player->lives <= 0)) - { - // to the lose music! - if (player->deadtimer == 4*TICRATE) - P_EndingMusic(player); - // stuff below isn't for kart - // Return to level music - if (netgame) - { - if (player->deadtimer == gameovertics && P_IsLocalPlayer(player)) - S_ChangeMusic(mapmusname, mapmusflags, true); - } - else if (multiplayer) // local multiplayer only - { - if (player->deadtimer != gameovertics) - ; - // Restore the first available player's music once we're dead for long enough - // -- that is, as long as they aren't dead too - else - { - INT32 i; - - for (i = 0; i < 4; i++) - { - if (i > splitscreen) - break; - - if (i == 0 && player != &players[displayplayer] && players[displayplayer].lives > 0) - P_RestoreMusic(&players[displayplayer]); - else if (i == 1 && player != &players[secondarydisplayplayer] && players[secondarydisplayplayer].lives > 0) - P_RestoreMusic(&players[secondarydisplayplayer]); - else if (i == 2 && player != &players[thirddisplayplayer] && players[thirddisplayplayer].lives > 0) - P_RestoreMusic(&players[thirddisplayplayer]); - else if (i == 3 && player != &players[fourthdisplayplayer] && players[fourthdisplayplayer].lives > 0) - P_RestoreMusic(&players[fourthdisplayplayer]); - else - continue; - - break; - } - } - } - }*/ - if (!player->mo) return; @@ -8167,6 +8071,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall fixed_t pan, xpan, ypan; INT32 camrotate; boolean camstill, lookback; + UINT8 timeover; mobj_t *mo; fixed_t f1, f2; #ifndef NOCLIPCAM @@ -8186,6 +8091,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall || (leveltime < introtime)); // Kart intro cam #endif + if (player->pflags & PF_TIMEOVER) // 1 for momentum keep, 2 for turnaround + timeover = (player->kartstuff[k_timeovercam] > 2*TICRATE ? 2 : 1); + else + timeover = 0; + if (!(player->playerstate == PST_DEAD || player->exiting)) { if (player->spectator) // force cam off for spectators @@ -8315,7 +8225,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall lookback = camspin4; } - if (leveltime < introtime) // Whoooshy camera! + if (timeover) + { + const INT32 timeovercam = max(0, min(180, (player->kartstuff[k_timeovercam] - 2*TICRATE)*15)); + camrotate += timeovercam; + } + else if (leveltime < introtime) // Whoooshy camera! { const INT32 introcam = (introtime - leveltime); camrotate += introcam*5; @@ -8335,10 +8250,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (mo->eflags & MFE_VERTICALFLIP) camheight += thiscam->height; - if (camstill || resetcalled || player->playerstate == PST_DEAD) - angle = thiscam->angle; + if (timeover) + angle = mo->angle + FixedAngle(camrotate*FRACUNIT); else if (leveltime < starttime) angle = focusangle + FixedAngle(camrotate*FRACUNIT); + else if (camstill || resetcalled || player->playerstate == PST_DEAD) + angle = thiscam->angle; else { angle_t input = focusangle + FixedAngle(camrotate<angle; @@ -8353,7 +8270,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall angle = thiscam->angle + input; } - if (!resetcalled && (leveltime > starttime) + if (!resetcalled && (leveltime > starttime && timeover != 2) && ((thiscam == &camera && t_cam_rotate != -42) || (thiscam == &camera2 && t_cam2_rotate != -42) || (thiscam == &camera3 && t_cam3_rotate != -42) @@ -8389,25 +8306,30 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall y = mo->y - FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); // SRB2Kart: set camera panning - if (player->kartstuff[k_drift] != 0) - { - fixed_t panmax = (dist/5); - pan = FixedDiv(FixedMul(min((fixed_t)player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)), panmax), K_GetKartDriftSparkValue(player)); - if (pan > panmax) - pan = panmax; - if (player->kartstuff[k_drift] < 0) - pan *= -1; - } + if (camstill || resetcalled || player->playerstate == PST_DEAD) + pan = xpan = ypan = 0; else - pan = 0; + { + if (player->kartstuff[k_drift] != 0) + { + fixed_t panmax = (dist/5); + pan = FixedDiv(FixedMul(min((fixed_t)player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)), panmax), K_GetKartDriftSparkValue(player)); + if (pan > panmax) + pan = panmax; + if (player->kartstuff[k_drift] < 0) + pan *= -1; + } + else + pan = 0; - pan = thiscam->pan + FixedMul(pan - thiscam->pan, camspeed/4); + pan = thiscam->pan + FixedMul(pan - thiscam->pan, camspeed/4); - xpan = FixedMul(FINECOSINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan); - ypan = FixedMul(FINESINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan); + xpan = FixedMul(FINECOSINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan); + ypan = FixedMul(FINESINE(((angle+ANGLE_90)>>ANGLETOFINESHIFT) & FINEMASK), pan); - x += xpan; - y += ypan; + x += xpan; + y += ypan; + } pviewheight = FixedMul(32<scale); @@ -8622,15 +8544,19 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall viewpointx = mo->x + FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist) + xpan; viewpointy = mo->y + FixedMul(FINESINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist) + ypan; - if (!camstill && !resetcalled && !paused) + if (timeover) + thiscam->angle = angle; + else if (!camstill && !resetcalled && !paused && timeover != 1) thiscam->angle = R_PointToAngle2(thiscam->x, thiscam->y, viewpointx, viewpointy); - if (player->exiting) + if (timeover == 1) { - thiscam->momx = 0; - thiscam->momy = 0; + thiscam->momx = P_ReturnThrustX(NULL, mo->angle, 32<momy = P_ReturnThrustY(NULL, mo->angle, 32<momz = 0; } + else if (player->exiting || timeover == 2) + thiscam->momx = thiscam->momy = thiscam->momz = 0; else if (leveltime < starttime) { thiscam->momx = FixedMul(x - thiscam->x, camspeed); @@ -8659,10 +8585,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall else angle = R_PointToAngle2(0, thiscam->z, dist, mo->z + P_GetPlayerHeight(player)); - if (player->playerstate != PST_DEAD && !(player->pflags & PF_NIGHTSMODE && player->exiting)) + if (player->playerstate != PST_DEAD && !((player->pflags & PF_NIGHTSMODE) && player->exiting)) angle += (focusaiming < ANGLE_180 ? focusaiming/2 : InvAngle(InvAngle(focusaiming)/2)); // overcomplicated version of '((signed)focusaiming)/2;' - if (twodlevel || (mo->flags2 & MF2_TWOD) || !camstill) // Keep the view still... + if (twodlevel || (mo->flags2 & MF2_TWOD) || (!camstill && !timeover)) // Keep the view still... { G_ClipAimingPitch((INT32 *)&angle); dist = thiscam->aiming - angle; @@ -8923,15 +8849,13 @@ void P_DoTimeOver(player_t *player) S_StopSound(player->mo); P_DamageMobj(player->mo, NULL, NULL, 10000); } + player->lives = 0; P_EndingMusic(player); -#if 0 - // sal, when you do the f-zero explosion, this is how you make sure the map doesn't end before it's done ^u^ ~toast if (!countdown2) countdown2 = 5*TICRATE; -#endif } // @@ -9429,6 +9353,7 @@ void P_PlayerThink(player_t *player) player->kartstuff[k_hyudorotimer] // SRB2kart - fixes Hyudoro not flashing when it should. || player->kartstuff[k_growshrinktimer] > 0 // Grow doesn't flash either. || player->kartstuff[k_respawn] // Respawn timer (for drop dash effect) + || (player->pflags & PF_TIMEOVER) // NO CONTEST explosion || (G_BattleGametype() && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || leveltime < starttime)) // Level intro { diff --git a/src/sounds.c b/src/sounds.c index e1bf870be..94c659932 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -705,7 +705,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kc2e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc2f", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Pogo Spring use {"kc30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc31", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"kc31", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, // NO CONTEST explosion {"kc32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -737,7 +737,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"kc51", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, // NO CONTEST debris ambience {"kc52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"kc54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, diff --git a/src/y_inter.c b/src/y_inter.c index 6a7e305c2..9361dbe3c 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -275,6 +275,8 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) for (j = 0; j < numplayersingame; j++) { + INT32 nump = ((G_RaceGametype() && nospectategrief > 0) ? nospectategrief : numplayersingame); + for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i] || players[i].spectator || completed[i]) @@ -296,9 +298,9 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) else data.match.pos[data.match.numplayers] = data.match.numplayers+1; - if (!rankingsmode && !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] < nospectategrief)) + if (!rankingsmode && !(players[i].pflags & PF_TIMEOVER) && (data.match.pos[data.match.numplayers] < nump)) { - data.match.increase[i] = nospectategrief - data.match.pos[data.match.numplayers]; + data.match.increase[i] = nump - data.match.pos[data.match.numplayers]; players[i].score += data.match.increase[i]; }