diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 120ffc55..0b885ab3 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4855,9 +4855,13 @@ static void Command_RestartAudio_f(void) I_SetSfxVolume(cv_soundvolume.value); I_SetDigMusicVolume(cv_digmusicvolume.value); //I_SetMIDIMusicVolume(cv_midimusicvolume.value); + + S_StartSound(NULL, sfx_strpst); + if (Playing()) // Gotta make sure the player is in a level P_RestoreMusic(&players[consoleplayer]); - + else + S_ChangeMusicInternal("titles", looptitle); } /** Quits a game and returns to the title screen. diff --git a/src/d_player.h b/src/d_player.h index 415ca67e..866589df 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -328,7 +328,6 @@ typedef enum k_squishedtimer, // Squished frame timer k_rocketsneakertimer, // Rocket Sneaker duration timer k_invincibilitytimer, // Invincibility timer - k_deathsentence, // 30 seconds to live... (SPB murder timer (not actually 30 sec, I just couldn't help the FF reference :p)) k_eggmanheld, // Eggman monitor held, separate from k_itemheld so it doesn't stop you from getting items k_eggmanexplode, // Fake item recieved, explode in a few seconds k_eggmanblame, // Fake item recieved, who set this fake diff --git a/src/dehacked.c b/src/dehacked.c index ef86c336..2468078d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1835,6 +1835,7 @@ static actionpointer_t actionpointers[] = {{A_ItemPop}, "A_ITEMPOP"}, // SRB2kart {{A_JawzChase}, "A_JAWZCHASE"}, // SRB2kart {{A_JawzExplode}, "A_JAWZEXPLODE"}, // SRB2kart + {{A_SPBChase}, "A_SPBCHASE"}, // SRB2kart {{A_MineExplode}, "A_MINEEXPLODE"}, // SRB2kart {{A_BallhogExplode}, "A_BALLHOGEXPLODE"}, // SRB2kart {{A_LightningFollowPlayer},"A_LIGHTNINGFOLLOWPLAYER"}, //SRB2kart @@ -6477,17 +6478,27 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_BALLHOGBOOM16", // Self-Propelled Bomb - just an explosion for now... - "S_BLUELIGHTNING1", - "S_BLUELIGHTNING2", - "S_BLUELIGHTNING3", - "S_BLUELIGHTNING4", - "S_BLUEEXPLODE", - - // Grow/shrink beams - "S_LIGHTNING1", - "S_LIGHTNING2", - "S_LIGHTNING3", - "S_LIGHTNING4", + "S_SPB1", + "S_SPB2", + "S_SPB3", + "S_SPB4", + "S_SPB5", + "S_SPB6", + "S_SPB7", + "S_SPB8", + "S_SPB9", + "S_SPB10", + "S_SPB11", + "S_SPB12", + "S_SPB13", + "S_SPB14", + "S_SPB15", + "S_SPB16", + "S_SPB17", + "S_SPB18", + "S_SPB19", + "S_SPB20", + "S_SPB_DEAD", // Thunder Shield "S_THUNDERSHIELD1", @@ -6718,7 +6729,26 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAYERARROW_WANTED6", "S_PLAYERARROW_WANTED7", - "S_PLAYERBOMB", // Player bomb overlay + "S_PLAYERBOMB1", // Player bomb overlay + "S_PLAYERBOMB2", + "S_PLAYERBOMB3", + "S_PLAYERBOMB4", + "S_PLAYERBOMB5", + "S_PLAYERBOMB6", + "S_PLAYERBOMB7", + "S_PLAYERBOMB8", + "S_PLAYERBOMB9", + "S_PLAYERBOMB10", + "S_PLAYERBOMB11", + "S_PLAYERBOMB12", + "S_PLAYERBOMB13", + "S_PLAYERBOMB14", + "S_PLAYERBOMB15", + "S_PLAYERBOMB16", + "S_PLAYERBOMB17", + "S_PLAYERBOMB18", + "S_PLAYERBOMB19", + "S_PLAYERBOMB20", "S_PLAYERITEM", // Player item overlay "S_PLAYERFAKE", // Player fake overlay @@ -7358,9 +7388,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_BALLHOG", // Ballhog "MT_BALLHOGBOOM", - "MT_BLUELIGHTNING", // Grow/shrink stuff - "MT_BLUEEXPLOSION", - "MT_LIGHTNING", + "MT_SPB", // Self-Propelled Bomb + "MT_SPBEXPLOSION", "MT_THUNDERSHIELD", // Thunder Shield stuff @@ -7827,7 +7856,6 @@ static const char *const KARTSTUFF_LIST[] = { "SQUISHEDTIMER", "ROCKETSNEAKERTIMER", "INVINCIBILITYTIMER", - "DEATHSENTENCE", "EGGMANHELD", "EGGMANEXPLODE", "EGGMANBLAME", diff --git a/src/doomstat.h b/src/doomstat.h index 48ff5f9d..83917fe4 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -458,8 +458,6 @@ extern boolean comeback; extern SINT8 battlewanted[4]; extern tic_t wantedcalcdelay; extern tic_t indirectitemcooldown; -extern tic_t spbincoming; -extern UINT8 spbplayer; extern tic_t mapreset; extern UINT8 nospectategrief; diff --git a/src/g_game.c b/src/g_game.c index 617712f7..7cf679af 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -264,8 +264,6 @@ SINT8 pickedvote; // What vote the host rolls SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points tic_t wantedcalcdelay; // Time before it recalculates WANTED tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded -tic_t spbincoming; // Timer before SPB hits, can switch targets at this point -UINT8 spbplayer; // Player num that used the last SPB tic_t mapreset; // Map reset delay when enough players have joined an empty game UINT8 nospectategrief; // How many players need to be in-game to eliminate last; for preventing spectate griefing @@ -1840,6 +1838,9 @@ boolean G_Responder(event_t *ev) if (players[displayplayer].exiting) continue; + if (players[displayplayer].pflags & PF_TIMEOVER) + continue; + // I don't know if we want this actually, but I'll humor the suggestion anyway if (G_BattleGametype()) { @@ -2356,6 +2357,7 @@ void G_PlayerReborn(INT32 player) INT32 itemamount; INT32 itemroulette; INT32 roulettetype; + INT32 growshrinktimer; INT32 bumper; INT32 comebackpoints; INT32 wanted; @@ -2368,7 +2370,7 @@ void G_PlayerReborn(INT32 player) exiting = players[player].exiting; jointime = players[player].jointime; spectator = players[player].spectator; - pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE)); + pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE|PF_WANTSTOJOIN)); // As long as we're not in multiplayer, carry over cheatcodes from map to map if (!(netgame || multiplayer)) @@ -2419,6 +2421,7 @@ void G_PlayerReborn(INT32 player) roulettetype = 0; itemtype = 0; itemamount = 0; + growshrinktimer = 0; bumper = (G_BattleGametype() ? cv_kartbumpers.value : 0); comebackpoints = 0; wanted = 0; @@ -2442,6 +2445,9 @@ void G_PlayerReborn(INT32 player) itemamount = players[player].kartstuff[k_itemamount]; } + // Keep Shrink status, remove Grow status + growshrinktimer = min(players[player].kartstuff[k_growshrinktimer], 0); + bumper = players[player].kartstuff[k_bumper]; comebackpoints = players[player].kartstuff[k_comebackpoints]; wanted = players[player].kartstuff[k_wanted]; @@ -2506,6 +2512,7 @@ void G_PlayerReborn(INT32 player) p->kartstuff[k_roulettetype] = roulettetype; p->kartstuff[k_itemtype] = itemtype; p->kartstuff[k_itemamount] = itemamount; + p->kartstuff[k_growshrinktimer] = growshrinktimer; p->kartstuff[k_bumper] = bumper; p->kartstuff[k_comebackpoints] = comebackpoints; p->kartstuff[k_comebacktimer] = comebacktime; diff --git a/src/info.c b/src/info.c index e416bff6..4507c558 100644 --- a/src/info.c +++ b/src/info.c @@ -57,11 +57,11 @@ 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","FZSM","FZBM","FPRT","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","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -2777,16 +2777,27 @@ state_t states[NUMSTATES] = {SPR_BHBM, FF_FULLBRIGHT|14, 1, {NULL}, 0, 0, S_BALLHOGBOOM16}, // S_BALLHOGBOOM15 {SPR_BHBM, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_NULL}, // S_BALLHOGBOOM16 - {SPR_BLIG, 0, 2, {NULL}, 0, 0, S_BLUELIGHTNING2}, // S_BLUELIGHTNING1 - {SPR_BLIG, 1, 2, {NULL}, 0, 0, S_BLUELIGHTNING3}, // S_BLUELIGHTNING2 - {SPR_BLIG, 2, 2, {NULL}, 0, 0, S_BLUELIGHTNING4}, // S_BLUELIGHTNING3 - {SPR_BLIG, 3, 2, {NULL}, 0, 0, S_NULL}, // S_BLUELIGHTNING4 - {SPR_SSMN, 0, 1, {A_MineExplode}, MT_BLUEEXPLOSION, 0, S_NULL}, // S_BLUEEXPLODE - - {SPR_LIGH, 0, 2, {NULL}, 0, 0, S_LIGHTNING2}, // S_LIGHTNING1 - {SPR_LIGH, 1, 2, {NULL}, 0, 0, S_LIGHTNING3}, // S_LIGHTNING2 - {SPR_LIGH, 2, 2, {NULL}, 0, 0, S_LIGHTNING4}, // S_LIGHTNING3 - {SPR_LIGH, 3, 2, {NULL}, 0, 0, S_NULL}, // S_LIGHTNING4 + {SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB2}, // S_SPB1 + {SPR_SPBM, 1, 1, {A_SPBChase}, 0, 0, S_SPB3}, // S_SPB2 + {SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB4}, // S_SPB3 + {SPR_SPBM, 2, 1, {A_SPBChase}, 0, 0, S_SPB5}, // S_SPB4 + {SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB6}, // S_SPB5 + {SPR_SPBM, 3, 1, {A_SPBChase}, 0, 0, S_SPB7}, // S_SPB6 + {SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB8}, // S_SPB7 + {SPR_SPBM, 4, 1, {A_SPBChase}, 0, 0, S_SPB9}, // S_SPB8 + {SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB10}, // S_SPB9 + {SPR_SPBM, 5, 1, {A_SPBChase}, 0, 0, S_SPB11}, // S_SPB10 + {SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB12}, // S_SPB11 + {SPR_SPBM, 6, 1, {A_SPBChase}, 0, 0, S_SPB13}, // S_SPB12 + {SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB14}, // S_SPB13 + {SPR_SPBM, 7, 1, {A_SPBChase}, 0, 0, S_SPB15}, // S_SPB14 + {SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB16}, // S_SPB15 + {SPR_SPBM, 8, 1, {A_SPBChase}, 0, 0, S_SPB17}, // S_SPB16 + {SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB18}, // S_SPB17 + {SPR_SPBM, 8, 1, {A_SPBChase}, 0, 0, S_SPB19}, // S_SPB18 + {SPR_SPBM, 0, 1, {A_SPBChase}, 0, 0, S_SPB20}, // S_SPB19 + {SPR_SPBM, 8, 1, {A_SPBChase}, 0, 0, S_SPB1}, // S_SPB20 + {SPR_SPBM, 8, 175, {NULL}, 0, 0, S_NULL}, // S_SPB_DEAD {SPR_THNS, FF_FULLBRIGHT|9, 2, {NULL}, 0, 0, S_THUNDERSHIELD2}, // S_THUNDERSHIELD1 {SPR_THNS, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_THUNDERSHIELD3}, // S_THUNDERSHIELD2 @@ -3009,11 +3020,30 @@ state_t states[NUMSTATES] = {SPR_WANT, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_PLAYERARROW_WANTED7}, // S_PLAYERARROW_WANTED6 {SPR_WANT, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_PLAYERARROW_WANTED1}, // S_PLAYERARROW_WANTED7 - {SPR_PBOM, FF_ANIMATE, -1, {NULL}, 3, 3, S_NULL}, // S_PLAYERBOMB + {SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB2}, // S_PLAYERBOMB1 + {SPR_SPBM, 1, 1, {NULL}, 0, 0, S_PLAYERBOMB3}, // S_PLAYERBOMB2 + {SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB4}, // S_PLAYERBOMB3 + {SPR_SPBM, 2, 1, {NULL}, 0, 0, S_PLAYERBOMB5}, // S_PLAYERBOMB4 + {SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB6}, // S_PLAYERBOMB5 + {SPR_SPBM, 3, 1, {NULL}, 0, 0, S_PLAYERBOMB7}, // S_PLAYERBOMB6 + {SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB8}, // S_PLAYERBOMB7 + {SPR_SPBM, 4, 1, {NULL}, 0, 0, S_PLAYERBOMB9}, // S_PLAYERBOMB8 + {SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB10}, // S_PLAYERBOMB9 + {SPR_SPBM, 5, 1, {NULL}, 0, 0, S_PLAYERBOMB11}, // S_PLAYERBOMB10 + {SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB12}, // S_PLAYERBOMB11 + {SPR_SPBM, 6, 1, {NULL}, 0, 0, S_PLAYERBOMB13}, // S_PLAYERBOMB12 + {SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB14}, // S_PLAYERBOMB13 + {SPR_SPBM, 7, 1, {NULL}, 0, 0, S_PLAYERBOMB15}, // S_PLAYERBOMB14 + {SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB16}, // S_PLAYERBOMB15 + {SPR_SPBM, 8, 1, {NULL}, 0, 0, S_PLAYERBOMB17}, // S_PLAYERBOMB16 + {SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB18}, // S_PLAYERBOMB17 + {SPR_SPBM, 8, 1, {NULL}, 0, 0, S_PLAYERBOMB19}, // S_PLAYERBOMB18 + {SPR_SPBM, 0, 1, {NULL}, 0, 0, S_PLAYERBOMB20}, // S_PLAYERBOMB19 + {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 - {SPR_PBOM, 4, -1, {NULL}, 0, 0, S_NULL}, // S_KARMAWHEEL + {SPR_PBOM, 0, -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) @@ -15166,7 +15196,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 320*FRACUNIT, // painchance + 288*FRACUNIT, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate @@ -15373,34 +15403,34 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BLUELIGHTNING + { // MT_SPB -1, // doomednum - S_BLUELIGHTNING1, // spawnstate - 1000, // spawnhealth + S_SPB1, // spawnstate + 1, // spawnhealth S_NULL, // seestate - sfx_None, // seesound + sfx_tossed, // seesound 8, // reactiontime - sfx_None, // attacksound + sfx_kc57, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_NULL, // deathstate + S_SPB_DEAD, // deathstate S_NULL, // xdeathstate - sfx_None, // deathsound - 8, // speed - 64*FRACUNIT, // radius - 64*FRACUNIT, // height + sfx_s3k5d, // deathsound + 64*FRACUNIT, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height 0, // display offset - 16, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags + 100, // mass + 1, // damage + sfx_kc64, // activesound + MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, - { // MT_BLUEEXPLOSION + { // MT_SPBEXPLOSION -1, // doomednum S_INVISIBLE, // spawnstate 1, // spawnhealth @@ -15409,7 +15439,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 256*FRACUNIT, // painchance + 288*FRACUNIT, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate @@ -15427,33 +15457,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_LIGHTNING - -1, // doomednum - S_LIGHTNING1, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 8, // speed - 64*FRACUNIT, // radius - 64*FRACUNIT, // height - 0, // display offset - 16, // mass - 0, // damage - sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags - S_NULL // raisestate - }, - { // MT_THUNDERSHIELD -1, // doomednum S_THUNDERSHIELD1, // spawnstate @@ -17184,7 +17187,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_KARMAHITBOX -1, // doomednum - S_PLAYERBOMB, // spawnstate + S_PLAYERBOMB1, // spawnstate 1000, // spawnhealth S_PLAYERITEM, // seestate sfx_kc2e, // seesound diff --git a/src/info.h b/src/info.h index 5ac86689..b4afcfaf 100644 --- a/src/info.h +++ b/src/info.h @@ -166,6 +166,7 @@ void A_ToggleFlameJet(); void A_ItemPop(); // SRB2kart void A_JawzChase(); // SRB2kart void A_JawzExplode(); // SRB2kart +void A_SPBChase(); // SRB2kart void A_MineExplode(); // SRB2kart void A_BallhogExplode(); // SRB2kart void A_LightningFollowPlayer(); // SRB2kart: Lightning shield effect player chasing @@ -607,8 +608,7 @@ typedef enum sprite SPR_KRBM, // SS Mine BOOM SPR_BHOG, // Ballhog SPR_BHBM, // Ballhog BOOM - SPR_BLIG, // Self-Propelled Bomb - SPR_LIGH, // Grow/shrink beams (Metallic Maddness) + SPR_SPBM, // Self-Propelled Bomb SPR_THNS, // Thunder Shield SPR_SINK, // Kitchen Sink SPR_SITR, // Kitchen Sink Trail @@ -3323,18 +3323,28 @@ typedef enum state S_BALLHOGBOOM15, S_BALLHOGBOOM16, - // Self-Propelled Bomb - just an explosion for now... - S_BLUELIGHTNING1, - S_BLUELIGHTNING2, - S_BLUELIGHTNING3, - S_BLUELIGHTNING4, - S_BLUEEXPLODE, - - // Grow/Shrink - S_LIGHTNING1, - S_LIGHTNING2, - S_LIGHTNING3, - S_LIGHTNING4, + // Self-Propelled Bomb + S_SPB1, + S_SPB2, + S_SPB3, + S_SPB4, + S_SPB5, + S_SPB6, + S_SPB7, + S_SPB8, + S_SPB9, + S_SPB10, + S_SPB11, + S_SPB12, + S_SPB13, + S_SPB14, + S_SPB15, + S_SPB16, + S_SPB17, + S_SPB18, + S_SPB19, + S_SPB20, + S_SPB_DEAD, // Thunder Shield S_THUNDERSHIELD1, @@ -3565,7 +3575,26 @@ typedef enum state S_PLAYERARROW_WANTED6, S_PLAYERARROW_WANTED7, - S_PLAYERBOMB, + S_PLAYERBOMB1, // Karma player overlays + S_PLAYERBOMB2, + S_PLAYERBOMB3, + S_PLAYERBOMB4, + S_PLAYERBOMB5, + S_PLAYERBOMB6, + S_PLAYERBOMB7, + S_PLAYERBOMB8, + S_PLAYERBOMB9, + S_PLAYERBOMB10, + S_PLAYERBOMB11, + S_PLAYERBOMB12, + S_PLAYERBOMB13, + S_PLAYERBOMB14, + S_PLAYERBOMB15, + S_PLAYERBOMB16, + S_PLAYERBOMB17, + S_PLAYERBOMB18, + S_PLAYERBOMB19, + S_PLAYERBOMB20, S_PLAYERITEM, S_PLAYERFAKE, @@ -4222,9 +4251,8 @@ typedef enum mobj_type MT_BALLHOG, // Ballhog MT_BALLHOGBOOM, - MT_BLUELIGHTNING, // Grow/shrink stuff - MT_BLUEEXPLOSION, - MT_LIGHTNING, + MT_SPB, // SPB stuff + MT_SPBEXPLOSION, MT_THUNDERSHIELD, // Thunder Shield stuff diff --git a/src/k_kart.c b/src/k_kart.c index 0d9e2322..ea5d10ed 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -28,8 +28,6 @@ // comeback is Battle Mode's karma comeback, also bool // battlewanted is an array of the WANTED player nums, -1 for no player in that slot // indirectitemcooldown is timer before anyone's allowed another Shrink/SPB -// spbincoming is the timer before k_deathsentence is cast on the player in 1st -// spbplayer is the last player who fired a SPB // mapreset is set when enough players fill an empty server // nospectategrief is the players in-game needed to eliminate the person in last @@ -488,28 +486,28 @@ boolean K_IsPlayerWanted(player_t *player) static INT32 K_KartItemOddsRace[NUMKARTRESULTS][9] = { //P-Odds 0 1 2 3 4 5 6 7 8 - /*Sneaker*/ {20, 0, 0, 3, 6, 6, 0, 0, 0 }, // Sneaker - /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 5, 4, 0 }, // Rocket Sneaker - /*Invincibility*/ { 0, 0, 0, 0, 0, 1, 5, 6,16 }, // Invincibility + /*Sneaker*/ {20, 0, 0, 4, 6, 6, 0, 0, 0 }, // Sneaker + /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 5, 5, 0 }, // Rocket Sneaker + /*Invincibility*/ { 0, 0, 0, 0, 0, 1, 4, 6,16 }, // Invincibility /*Banana*/ { 0, 9, 4, 2, 1, 0, 0, 0, 0 }, // Banana /*Eggman Monitor*/ { 0, 4, 3, 2, 0, 0, 0, 0, 0 }, // Eggman Monitor - /*Orbinaut*/ { 0, 6, 5, 4, 2, 0, 0, 0, 0 }, // Orbinaut - /*Jawz*/ { 0, 0, 3, 2, 2, 1, 0, 0, 0 }, // Jawz + /*Orbinaut*/ { 0, 6, 5, 3, 2, 0, 0, 0, 0 }, // Orbinaut + /*Jawz*/ { 0, 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz /*Mine*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Mine /*Ballhog*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Ballhog - /*Self-Propelled Bomb*/ { 0, 0, 1, 1, 1, 2, 2, 3, 2 }, // Self-Propelled Bomb - /*Grow*/ { 0, 0, 0, 0, 0, 1, 3, 6, 4 }, // Grow - /*Shrink*/ { 0, 0, 0, 0, 0, 0, 0, 1, 0 }, // Shrink + /*Self-Propelled Bomb*/ { 0, 0, 1, 2, 3, 4, 2, 2, 0 }, // Self-Propelled Bomb + /*Grow*/ { 0, 0, 0, 0, 0, 1, 3, 5, 4 }, // Grow + /*Shrink*/ { 0, 0, 0, 0, 0, 0, 1, 2, 0 }, // Shrink /*Thunder Shield*/ { 0, 1, 2, 0, 0, 0, 0, 0, 0 }, // Thunder Shield /*Hyudoro*/ { 0, 0, 0, 0, 1, 2, 1, 0, 0 }, // Hyudoro /*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink - /*Sneaker x3*/ { 0, 0, 0, 0, 3, 6, 5, 3, 0 }, // Sneaker x3 + /*Sneaker x3*/ { 0, 0, 0, 0, 3, 6, 6, 2, 0 }, // Sneaker x3 /*Banana x3*/ { 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3 /*Banana x10*/ { 0, 0, 0, 0, 1, 0, 0, 0, 0 }, // Banana x10 - /*Orbinaut x3*/ { 0, 0, 0, 1, 1, 0, 0, 0, 0 }, // Orbinaut x3 - /*Orbinaut x4*/ { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // Orbinaut x4 - /*Jawz x2*/ { 0, 0, 0, 1, 1, 0, 0, 0, 0 } // Jawz x2 + /*Orbinaut x3*/ { 0, 0, 0, 1, 0, 0, 0, 0, 0 }, // Orbinaut x3 + /*Orbinaut x4*/ { 0, 0, 0, 0, 1, 1, 0, 0, 0 }, // Orbinaut x4 + /*Jawz x2*/ { 0, 0, 0, 1, 2, 0, 0, 0, 0 } // Jawz x2 }; static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = @@ -1052,7 +1050,6 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) mobj_t *fx; fixed_t momdifx, momdify; fixed_t distx, disty; - //fixed_t nobumpx = 0, nobumpy = 0; fixed_t dot, p; fixed_t mass1, mass2; @@ -1101,20 +1098,28 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) momdify = FixedMul((25*mapheaderinfo[gamemap-1]->mobj_scale), normalisedy); } - /*if (mass1 == 0 && mass2 > 0) - { - nobumpx = mobj2->momx; - nobumpy = mobj2->momy; - } - else if (mass2 == 0 && mass1 > 0) - { - nobumpx = mobj1->momx; - nobumpy = mobj1->momy; - }*/ - + // Adds the OTHER player's momentum, so that it reduces the chance of you being "inside" the other object distx = (mobj1->x + mobj2->momx) - (mobj2->x + mobj1->momx); disty = (mobj1->y + mobj2->momy) - (mobj2->y + mobj1->momy); + { // Don't allow dist to get WAY too low, that it pushes you stupidly huge amounts, or backwards... + fixed_t dist = P_AproxDistance(distx, disty); + fixed_t nx = FixedDiv(distx, dist); + fixed_t ny = FixedDiv(disty, dist); + + if (P_AproxDistance(distx, disty) < (3*mobj1->radius)/4) + { + distx = FixedMul((3*mobj1->radius)/4, nx); + disty = FixedMul((3*mobj1->radius)/4, ny); + } + + if (P_AproxDistance(distx, disty) < (3*mobj2->radius)/4) + { + distx = FixedMul((3*mobj2->radius)/4, nx); + disty = FixedMul((3*mobj2->radius)/4, ny); + } + } + if (distx == 0 && disty == 0) { // if there's no distance between the 2, they're directly on top of each other, don't run this @@ -1950,7 +1955,7 @@ void K_SquishPlayer(player_t *player, mobj_t *source) return; } -void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer +void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A bit of a hack, we just throw the player up higher here and extend their spinout timer { UINT8 scoremultiply = 1; if (G_BattleGametype()) @@ -1964,8 +1969,8 @@ void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we ju if (player->health <= 0) return; - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0 - || player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 + if (/*player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0 // Explosions should combo, because of SPB and Eggman + ||*/player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) { K_DoInstashield(player); @@ -1981,7 +1986,8 @@ void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we ju player->kartstuff[k_sneakertimer] = 0; player->kartstuff[k_driftboost] = 0; - if (G_BattleGametype()) + // This is the only part that SHOULDN'T combo :VVVVV + if (G_BattleGametype() && !(player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0)) { if (source && source->player && player != source->player) { @@ -2024,6 +2030,12 @@ void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we ju player->powers[pw_flashing] = K_GetKartFlashing(player); + if (inflictor && inflictor->type == MT_SPBEXPLOSION && inflictor->extravalue1) + { + player->kartstuff[k_spinouttimer] = (3*player->kartstuff[k_spinouttimer])/2; + player->mo->momz *= 2; + } + if (player->mo->state != &states[S_KART_SPIN]) P_SetPlayerMobjState(player->mo, S_KART_SPIN); @@ -2194,9 +2206,6 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 mobj->momy = FixedMul(FixedDiv(mobjy - y, dist), FixedDiv(dist, 6*FRACUNIT)); mobj->momz = FixedMul(FixedDiv(mobjz - z, dist), FixedDiv(dist, 6*FRACUNIT)); - mobj->flags |= MF_NOCLIPTHING; - mobj->flags &= ~MF_SPECIAL; - P_SetTarget(&mobj->target, source); } } @@ -2215,7 +2224,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) height = source->height>>FRACBITS; if (!color) - color = SKINCOLOR_RED; + color = SKINCOLOR_KETCHUP; for (i = 0; i < 32; i++) { @@ -2223,7 +2232,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) dust->angle = (ANGLE_180/16) * i; P_SetScale(dust, source->scale); dust->destscale = source->scale*10; - dust->scalespeed = FixedMul(dust->scalespeed, source->scale); + dust->scalespeed = source->scale/12; P_InstaThrust(dust, dust->angle, FixedMul(20*FRACUNIT, source->scale)); truc = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT, @@ -2231,7 +2240,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) source->z + P_RandomRange(0, height)*FRACUNIT, MT_BOOMEXPLODE); P_SetScale(truc, source->scale); truc->destscale = source->scale*6; - truc->scalespeed = FixedMul(truc->scalespeed, source->scale); + truc->scalespeed = source->scale/12; speed = FixedMul(10*FRACUNIT, source->scale)>>FRACBITS; truc->momx = P_RandomRange(-speed, speed)*FRACUNIT; truc->momy = P_RandomRange(-speed, speed)*FRACUNIT; @@ -2247,7 +2256,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) source->z + P_RandomRange(0, height)*FRACUNIT, MT_SMOKE); P_SetScale(dust, source->scale); dust->destscale = source->scale*10; - dust->scalespeed = FixedMul(dust->scalespeed, source->scale); + dust->scalespeed = source->scale/12; dust->tics = 30; dust->momz = P_RandomRange(FixedMul(3*FRACUNIT, source->scale)>>FRACBITS, FixedMul(7*FRACUNIT, source->scale)>>FRACBITS)*FRACUNIT; @@ -2256,7 +2265,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) source->z + P_RandomRange(0, height)*FRACUNIT, MT_BOOMPARTICLE); P_SetScale(truc, source->scale); truc->destscale = source->scale*5; - truc->scalespeed = FixedMul(truc->scalespeed, source->scale); + truc->scalespeed = source->scale/12; speed = FixedMul(20*FRACUNIT, source->scale)>>FRACBITS; truc->momx = P_RandomRange(-speed, speed)*FRACUNIT; truc->momy = P_RandomRange(-speed, speed)*FRACUNIT; @@ -2655,7 +2664,7 @@ void K_DriftDustHandling(mobj_t *spawner) dust->momz = P_MobjFlip(spawner) * (P_RandomRange(1, 4) * (spawner->scale)); P_SetScale(dust, spawner->scale/2); dust->destscale = spawner->scale * 3; - dust->scalespeed = FixedMul(dust->scalespeed, spawner->scale); + dust->scalespeed = spawner->scale/12; if (leveltime % 6 == 0) S_StartSound(spawner, sfx_screec); @@ -2758,7 +2767,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map } else { - if (dir == -1) + if (dir == -1 && mapthing != MT_SPB) { // Shoot backward mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/4); @@ -3072,38 +3081,6 @@ static void K_DoShrink(player_t *player) } } -static void K_DoSPB(player_t *victim) -{ - //INT32 i; - S_StartSound(victim->mo, sfx_bkpoof); // Sound the BANG! - - /*for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - P_FlashPal(&players[i], PAL_NUKE, 10); - }*/ - - if (!victim->mo || !victim->mo->health || victim->spectator) - return; - - { - mobj_t *spbexplode; - - if (!victim->kartstuff[k_invincibilitytimer] && !victim->kartstuff[k_growshrinktimer]) - { - K_DropHnextList(victim); - K_StripItems(victim); - - victim->powers[pw_flashing] = 0; - } - - spbexplode = P_SpawnMobj(victim->mo->x, victim->mo->y, victim->mo->z, MT_BLUEEXPLOSION); - - if (playeringame[spbplayer] && !players[spbplayer].spectator && players[spbplayer].mo) - P_SetTarget(&spbexplode->target, players[spbplayer].mo); - } -} - void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) { const fixed_t vscale = mapheaderinfo[gamemap-1]->mobj_scale + (mo->scale - mapheaderinfo[gamemap-1]->mobj_scale); @@ -4069,13 +4046,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_justbumped]) player->kartstuff[k_justbumped]--; - if (player->kartstuff[k_deathsentence]) - { - if (player->kartstuff[k_deathsentence] == 1) - K_DoSPB(player); - player->kartstuff[k_deathsentence]--; - } - if (player->kartstuff[k_lapanimation]) player->kartstuff[k_lapanimation]--; @@ -4136,8 +4106,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_eggmanexplode] <= 0) { mobj_t *eggsexplode; - player->powers[pw_flashing] = 0; - eggsexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUEEXPLOSION); + //player->powers[pw_flashing] = 0; + eggsexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SPBEXPLOSION); if (player->kartstuff[k_eggmanblame] >= 0 && player->kartstuff[k_eggmanblame] < MAXPLAYERS && playeringame[player->kartstuff[k_eggmanblame]] @@ -4968,45 +4938,14 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { player->kartstuff[k_itemamount]--; K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0); - S_StartSound(player->mo, sfx_mario7); K_PlayAttackTaunt(player->mo); } break; case KITEM_SPB: if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) { - UINT8 ploop; - UINT8 bestrank = 0; - fixed_t dist = 0; - - for (ploop = 0; ploop < MAXPLAYERS; ploop++) - { - fixed_t thisdist; - if (!playeringame[ploop] || players[ploop].spectator) - continue; - if (&players[ploop] == player) - continue; - if (!players[ploop].mo) - continue; - if (players[ploop].exiting) - continue; - thisdist = R_PointToDist2(player->mo->x, player->mo->y, players[ploop].mo->x, players[ploop].mo->y); - if (bestrank == 0 || players[ploop].kartstuff[k_position] < bestrank) - { - bestrank = players[ploop].kartstuff[k_position]; - dist = thisdist; - } - } - - if (dist == 0) - spbincoming = 6*TICRATE; // If you couldn't find anyone, just set an abritary timer - else - spbincoming = (tic_t)max(1, FixedDiv(dist, 64*FRACUNIT)/FRACUNIT); - - spbplayer = player-players; - player->kartstuff[k_itemamount]--; - + K_ThrowKartItem(player, true, MT_SPB, 1, 0); K_PlayAttackTaunt(player->mo); } break; @@ -5015,7 +4954,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) && player->kartstuff[k_growshrinktimer] <= 0) // Grow holds the item box hostage { K_PlayPowerGloatSound(player->mo); - player->mo->scalespeed = FRACUNIT/TICRATE; + player->mo->scalespeed = mapheaderinfo[gamemap-1]->mobj_scale/TICRATE; player->mo->destscale = 3*(mapheaderinfo[gamemap-1]->mobj_scale)/2; if (cv_kartdebugshrink.value && !player->bot) player->mo->destscale = 6*player->mo->destscale/8; @@ -5119,8 +5058,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_itemtype] == KITEM_SPB || player->kartstuff[k_itemtype] == KITEM_SHRINK - || player->kartstuff[k_growshrinktimer] < 0 - || spbincoming) + || player->kartstuff[k_growshrinktimer] < 0) indirectitemcooldown = 20*TICRATE; if (player->kartstuff[k_hyudorotimer] > 0) @@ -5608,7 +5546,6 @@ static patch_t *kp_sadface[2]; static patch_t *kp_check[6]; -static patch_t *kp_spbwarning[2]; static patch_t *kp_eggnum[4]; static patch_t *kp_fpview[3]; @@ -5765,10 +5702,6 @@ void K_LoadKartHUDGraphics(void) kp_check[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } - // SPB warning - kp_spbwarning[0] = W_CachePatchName("K_SPBW1", PU_HUDGFX); - kp_spbwarning[1] = W_CachePatchName("K_SPBW2", PU_HUDGFX); - // Eggman warning numbers sprintf(buffer, "K_EGGNx"); for (i = 0; i < 4; i++) @@ -5890,7 +5823,6 @@ INT32 FACE_X, FACE_Y; // Top-four Faces INT32 STCD_X, STCD_Y; // Starting countdown INT32 CHEK_Y; // CHECK graphic INT32 MINI_X, MINI_Y; // Minimap -INT32 SPBW_X, SPBW_Y; // SPB warning INT32 WANT_X, WANT_Y; // Battle WANTED poster static void K_initKartHUD(void) @@ -5956,9 +5888,6 @@ static void K_initKartHUD(void) // Minimap MINI_X = BASEVIDWIDTH - 50; // 270 MINI_Y = (BASEVIDHEIGHT/2)-16; // 84 - // Blue Shell warning - SPBW_X = BASEVIDWIDTH/2; // 270 - SPBW_Y = BASEVIDHEIGHT- 24; // 176 // Battle WANTED poster WANT_X = BASEVIDWIDTH - 55; // 270 WANT_Y = BASEVIDHEIGHT- 71; // 176 @@ -5976,8 +5905,6 @@ static void K_initKartHUD(void) MINI_Y = (BASEVIDHEIGHT/2); - SPBW_Y = (BASEVIDHEIGHT/2)-8; - WANT_X = BASEVIDWIDTH-8; WANT_Y = (BASEVIDHEIGHT/2)-12; @@ -5996,8 +5923,6 @@ static void K_initKartHUD(void) MINI_X = (3*BASEVIDWIDTH/4); MINI_Y = (3*BASEVIDHEIGHT/4); - SPBW_X = BASEVIDWIDTH/4; - WANT_X = (BASEVIDWIDTH/2)-8; if (splitscreen > 2) // 4P-only @@ -6622,23 +6547,6 @@ static void K_drawKartBumpersOrKarma(void) } } -static void K_drawSPBWarning(void) -{ - patch_t *localpatch = kp_nodraw; - INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM); - - if (!(stplyr->kartstuff[k_deathsentence] > 0 - || (spbincoming > 0 && spbincoming < 2*TICRATE && stplyr->kartstuff[k_position] == 1))) - return; - - if (leveltime % 8 > 3) - localpatch = kp_spbwarning[1]; - else - localpatch = kp_spbwarning[0]; - - V_DrawScaledPatch(SPBW_X, SPBW_Y, splitflags, localpatch); -} - fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my) { fixed_t dist, x; @@ -7682,9 +7590,6 @@ void K_drawKartHUD(void) // Draw the input UI K_drawInput(); } - - // You're about to DIEEEEE - K_drawSPBWarning(); } else if (G_BattleGametype()) // Battle-only { diff --git a/src/k_kart.h b/src/k_kart.h index f15b51cb..671efb89 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -29,7 +29,7 @@ void K_KartPlayerAfterThink(player_t *player); void K_DoInstashield(player_t *player); void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, boolean trapitem); void K_SquishPlayer(player_t *player, mobj_t *source); -void K_ExplodePlayer(player_t *player, mobj_t *source); +void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor); void K_StealBumper(player_t *player, player_t *victim, boolean force); void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source); void K_SpawnMineExplosion(mobj_t *source, UINT8 color); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index af8d44fb..ed50d591 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2149,12 +2149,15 @@ static int lib_kExplodePlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); if (!source) return LUA_ErrInvalid(L, "mobj_t"); - K_ExplodePlayer(player, source); + if (!inflictor) + return LUA_ErrInvalid(L, "mobj_t"); + K_ExplodePlayer(player, source, inflictor); return 0; } diff --git a/src/m_menu.c b/src/m_menu.c index 2e2a79e0..6e42504b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -314,7 +314,7 @@ menu_t OP_SoundOptionsDef; static void M_ToggleSFX(INT32 choice); static void M_ToggleDigital(INT32 choice); //static void M_ToggleMIDI(INT32 choice); -static void M_RestartAudio(void); +//static void M_RestartAudio(void); //Misc menu_t /*OP_DataOptionsDef,*/ OP_ScreenshotOptionsDef, OP_EraseDataDef; @@ -1315,7 +1315,7 @@ static menuitem_t OP_SoundOptionsMenu[] = { {IT_KEYHANDLER|IT_STRING, NULL, "SFX", M_ToggleSFX, 10}, {IT_STRING|IT_CVAR|IT_CV_SLIDER, - NULL, "SFX Volume", &cv_soundvolume, 18}, + NULL, "SFX Volume", &cv_soundvolume, 18}, {IT_KEYHANDLER|IT_STRING, NULL, "Music", M_ToggleDigital, 30}, {IT_STRING|IT_CVAR|IT_CV_SLIDER, @@ -1330,16 +1330,16 @@ static menuitem_t OP_SoundOptionsMenu[] = NULL, "CD Volume", &cd_volume, 40}, #endif*/ - {IT_STRING|IT_CALL, NULL, "Restart Audio System", M_RestartAudio, 50}, + //{IT_STRING|IT_CALL, NULL, "Restart Audio System", M_RestartAudio, 50}, - {IT_STRING|IT_CVAR, NULL, "Reverse L/R Channels", &stereoreverse, 65}, - {IT_STRING|IT_CVAR, NULL, "Surround Sound", &surround, 75}, + {IT_STRING|IT_CVAR, NULL, "Reverse L/R Channels", &stereoreverse, 50}, + {IT_STRING|IT_CVAR, NULL, "Surround Sound", &surround, 60}, - {IT_STRING|IT_CVAR, NULL, "Chat sounds", &cv_chatnotifications, 90}, - {IT_STRING|IT_CVAR, NULL, "Character voices", &cv_kartvoices, 100}, - {IT_STRING|IT_CVAR, NULL, "Powerup Warning", &cv_kartinvinsfx, 110}, + {IT_STRING|IT_CVAR, NULL, "Chat sounds", &cv_chatnotifications, 75}, + {IT_STRING|IT_CVAR, NULL, "Character voices", &cv_kartvoices, 85}, + {IT_STRING|IT_CVAR, NULL, "Powerup Warning", &cv_kartinvinsfx, 95}, - {IT_KEYHANDLER|IT_STRING, NULL, "Sound Test", M_HandleSoundTest, 125}, + {IT_KEYHANDLER|IT_STRING, NULL, "Sound Test", M_HandleSoundTest, 110}, }; /*static menuitem_t OP_DataOptionsMenu[] = @@ -7421,6 +7421,7 @@ static void M_StartServer(INT32 choice) { paused = false; SV_StartSinglePlayerServer(); + multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this... D_MapChange(cv_nextmap.value, cv_newgametype.value, (boolean)cv_kartencore.value, 1, 1, false, false); } else @@ -9041,25 +9042,10 @@ static void M_ToggleDigital(INT32 choice) } }*/ -static void M_RestartAudio(void) +/*static void M_RestartAudio(void) { - S_StopMusic(); - I_ShutdownMusic(); - I_ShutdownSound(); - I_StartupSound(); - I_InitMusic(); - - I_SetSfxVolume(cv_soundvolume.value); - I_SetDigMusicVolume(cv_digmusicvolume.value); - //I_SetMIDIMusicVolume(cv_midimusicvolume.value); - - S_StartSound(NULL, sfx_strpst); - - if (Playing()) // Gotta make sure the player is in a level - P_RestoreMusic(&players[consoleplayer]); - else - S_ChangeMusicInternal("titles", looptitle); -} + COM_ImmedExecute("restartaudio"); +}*/ // =============== // VIDEO MODE MENU diff --git a/src/p_enemy.c b/src/p_enemy.c index fe23ca10..6f7e6677 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -190,6 +190,7 @@ void A_ToggleFlameJet(mobj_t *actor); void A_ItemPop(mobj_t *actor); // SRB2kart void A_JawzChase(mobj_t *actor); // SRB2kart 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 @@ -3408,7 +3409,7 @@ void A_ParticleSpawn(mobj_t *actor) P_SetScale(spawn, actor->scale); spawn->momz = speed; spawn->destscale = FixedDiv(spawn->scale<scalespeed = FixedDiv(((actor->spawnpoint->angle >> 8) & 63) << FRACBITS, 100<scalespeed = FixedDiv(((actor->spawnpoint->angle >> 8) & 63) * actor->scale, 100<tics = actor->spawnpoint->extrainfo + 1; } @@ -4016,7 +4017,7 @@ static inline boolean PIT_MineExplode(mobj_t *thing) grenade->flags2 |= MF2_DEBRIS; if (thing->player) // Looks like we're going to have to need a seperate function for this too - K_ExplodePlayer(thing->player, grenade->target); + K_ExplodePlayer(thing->player, grenade->target, grenade); else P_DamageMobj(thing, grenade, grenade->target, 1); @@ -4055,7 +4056,7 @@ void A_MineExplode(mobj_t *actor) if (actor->target && actor->target->player) K_SpawnMineExplosion(actor, actor->target->player->skincolor); else - K_SpawnMineExplosion(actor, SKINCOLOR_RED); + K_SpawnMineExplosion(actor, SKINCOLOR_KETCHUP); P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINEEXPLOSIONSOUND); } @@ -8175,7 +8176,7 @@ void A_ToggleFlameJet(mobj_t* actor) } } -//{ SRB2kart - A_ItemPop, A_JawzChase, A_JawzExplode, A_MineExplode, A_BallhogExplode, A_LightningFollowPlayer, A_FZBoomFlash, A_FZBoomSmoke +//{ SRB2kart Actions void A_ItemPop(mobj_t *actor) { mobj_t *remains; @@ -8295,7 +8296,7 @@ void A_JawzExplode(mobj_t *actor) truc = P_SpawnMobj(actor->x, actor->y, actor->z, MT_BOOMEXPLODE); truc->scale = actor->scale*2; - truc->color = SKINCOLOR_RED; + truc->color = SKINCOLOR_KETCHUP; while (shrapnel) { @@ -8313,7 +8314,7 @@ void A_JawzExplode(mobj_t *actor) speed2 = FixedMul(15*FRACUNIT, actor->scale)>>FRACBITS; truc->momz = P_RandomRange(speed, speed2)*FRACUNIT; truc->tics = TICRATE*2; - truc->color = SKINCOLOR_RED; + truc->color = SKINCOLOR_KETCHUP; shrapnel--; } @@ -8321,65 +8322,220 @@ void A_JawzExplode(mobj_t *actor) return; } -/* old A_MineExplode - see elsewhere in the file -void A_MineExplode(mobj_t *actor) +void A_SPBChase(mobj_t *actor) { - mobj_t *mo2; - thinker_t *th; - INT32 d; - INT32 locvar1 = var1; - mobjtype_t type; - fixed_t range; + player_t *player = NULL; + UINT8 i; + UINT8 bestrank = UINT8_MAX; + fixed_t dist; + angle_t hang, vang; + fixed_t wspeed, xyspeed, zspeed; #ifdef HAVE_BLUA - if (LUA_CallAction("A_MineExplode", actor)) + if (LUA_CallAction("A_SPBChase", actor)) return; #endif - type = (mobjtype_t)locvar1; - range = FixedMul(actor->info->painchance, mapheaderinfo[gamemap-1]->mobj_scale); + // Default speed + wspeed = FixedMul(actor->info->speed, mapheaderinfo[gamemap-1]->mobj_scale); + if (gamespeed == 0) + wspeed = FixedMul(wspeed, FRACUNIT-FRACUNIT/4); + else if (gamespeed == 2) + wspeed = FixedMul(wspeed, FRACUNIT+FRACUNIT/4); - for (th = thinkercap.next; th != &thinkercap; th = th->next) + if (actor->threshold) // Just fired, go straight. { - if (P_MobjWasRemoved(actor)) - return; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot - - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2 == actor || mo2->type == MT_MINEEXPLOSIONSOUND) // Don't explode yourself! Endless loop! - continue; - - if (!(mo2->flags & MF_SHOOTABLE) || (mo2->flags & MF_SCENERY)) - continue; - - if (G_BattleGametype() && actor->target && actor->target->player && actor->target->player->kartstuff[k_bumper] <= 0 && mo2 == actor->target) - continue; - - if (P_AproxDistance(P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y), mo2->z - actor->z) > range) - continue; - - actor->flags2 |= MF2_DEBRIS; - - if (mo2->player) // Looks like we're going to have to need a seperate function for this too - K_ExplodePlayer(mo2->player, actor->target); - else - P_DamageMobj(mo2, actor, actor->target, 1); + P_InstaThrust(actor, actor->angle, wspeed); + return; } - for (d = 0; d < 16; d++) - K_SpawnKartExplosion(actor->x, actor->y, actor->z, range + 32*mapheaderinfo[gamemap-1]->mobj_scale, 32, type, d*(ANGLE_45/4), true, false, actor->target); // 32 <-> 64 + if (actor->extravalue1) // MODE: TARGETING + { + if (actor->tracer && actor->tracer->health) + { + fixed_t defspeed = wspeed; + fixed_t range = (160*actor->tracer->scale); - if (actor->target && actor->target->player) - K_SpawnMineExplosion(actor, actor->target->player->skincolor); - else - K_SpawnMineExplosion(actor, SKINCOLOR_RED); + // Maybe we want SPB to target an object later? IDK lol + if (actor->tracer->player) // 7/8ths max speed for Knuckles, 3/4ths max speed for min accel, exactly max speed for max accel + { + if (!P_IsObjectOnGround(actor->tracer) && !actor->tracer->player->kartstuff[k_pogospring]) + defspeed = 7*actor->tracer->player->speed/8; // In the air you have no control; basically don't hit unless you make a near complete stop + else + defspeed = ((33 - actor->tracer->player->kartspeed) * K_GetKartSpeed(actor->tracer->player, false)) / 32; + } - P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINEEXPLOSIONSOUND); + // Play the intimidating gurgle + if (!S_SoundPlaying(actor, actor->info->activesound)) + S_StartSound(actor, actor->info->activesound); + + dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z); + + wspeed = FixedMul(defspeed, FRACUNIT + FixedDiv(dist-range, range)); + if (wspeed < defspeed) + wspeed = defspeed; + if (wspeed > (3*defspeed)/2) + wspeed = (3*defspeed)/2; + + hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); + vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z); + + { + // Smoothly rotate horz angle + angle_t input = hang - actor->angle; + boolean invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; it looks better and makes U-turns not unfair + xyspeed = FixedMul(wspeed, max(0, (((180<angle += input; + + // Smoothly rotate vert angle + input = vang - actor->movedir; + invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; might as well do it for momz, since we do it above too + zspeed = FixedMul(wspeed, max(0, (((180<movedir += input; + } + + actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); + actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); + actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); + + // Red speed lines for when it's gaining on its target. A tell for when you're starting to lose too much speed! + if (R_PointToDist2(0, 0, actor->momx, actor->momy) > (actor->tracer->player ? (16*actor->tracer->player->speed)/15 + : (16*R_PointToDist2(0, 0, actor->tracer->momx, actor->tracer->momy))/15) // Going faster than the target + && xyspeed > K_GetKartSpeed(actor->tracer->player, false)/4) // Don't display speedup lines at pitifully low speeds + { + mobj_t *fast = P_SpawnMobj(actor->x + (P_RandomRange(-24,24) * actor->scale), + actor->y + (P_RandomRange(-24,24) * actor->scale), + actor->z + (actor->height/2) + (P_RandomRange(-24,24) * actor->scale), + MT_FASTLINE); + fast->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + //fast->momx = 3*actor->momx/4; + //fast->momy = 3*actor->momy/4; + //fast->momz = 3*actor->momz/4; + fast->color = SKINCOLOR_RED; + fast->colorized = true; + } + + return; + } + else // Target's gone, return to SEEKING + { + P_SetTarget(&actor->tracer, NULL); + actor->extravalue1 = 0; // Find someone new next tic + return; + } + } + else // MODE: SEEKING + { + // Find the player with the best rank + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].exiting) + continue; // not in-game + + if (!players[i].mo) + continue; // no mobj + + if (players[i].mo->health <= 0) + continue; // dead + + if (players[i].kartstuff[k_respawn]) + continue; // respawning + + if (players[i].kartstuff[k_position] < bestrank) + { + bestrank = players[i].kartstuff[k_position]; + player = &players[i]; + } + } + + // No one there? + if (player == NULL || !player->mo) + { +#if 0 + // SELF-DESTRUCT? + mobj_t *spbexplode; + + S_StopSound(actor); // Don't continue playing the gurgle or the siren + spbexplode = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPBEXPLOSION); + P_SetTarget(&spbexplode->target, actor->target); + + P_RemoveMobj(actor); +#else + actor->momx = actor->momy = actor->momz = 0; +#endif + return; + } + + // Found someone, now get close enough to initiate the slaughter... + P_SetTarget(&actor->tracer, player->mo); + + dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z); + + hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); + vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z); + + { + // Smoothly rotate horz angle + angle_t input = hang - actor->angle; + boolean invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; it looks better and makes U-turns not unfair + xyspeed = FixedMul(wspeed, max(0, (((180<angle += input; + + // Smoothly rotate vert angle + input = vang - actor->movedir; + invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; might as well do it for momz, since we do it above too + zspeed = FixedMul(wspeed, max(0, (((180<movedir += input; + } + + actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); + actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); + actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); + + if (dist <= (3072*actor->tracer->scale)) // Close enough to target? + { + S_StartSound(actor, actor->info->attacksound); // Siren sound; might not need this anymore, but I'm keeping it for now just for debugging. + actor->extravalue1 = 1; // TARGET ACQUIRED + } + } return; -}*/ +} void A_BallhogExplode(mobj_t *actor) { diff --git a/src/p_floor.c b/src/p_floor.c index 075ad1da..3365b4b9 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -3003,6 +3003,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) fixed_t topz; fixed_t a, b, c; mobjtype_t type = MT_ROCKCRUMBLE1; + const fixed_t spacing = 48*mapheaderinfo[gamemap-1]->mobj_scale; // If the control sector has a special // of Section3:7-15, use the custom debris. @@ -3034,16 +3035,16 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) rightx = sec->lines[rightmostvertex]->v1->x; topy = sec->lines[topmostvertex]->v1->y-(16<lines[bottommostvertex]->v1->y; - topz = *rover->topheight-(16<topheight-(spacing/2); - for (a = leftx; a < rightx; a += (32< bottomy; b -= (32< bottomy; b -= spacing) { if (R_PointInSubsector(a, b)->sector == sec) { mobj_t *spawned = NULL; - for (c = topz; c > *rover->bottomheight; c -= (32< *rover->bottomheight; c -= spacing) { spawned = P_SpawnMobj(a, b, c, type); spawned->fuse = 3*TICRATE; diff --git a/src/p_inter.c b/src/p_inter.c index d200ca4b..6d9fb19c 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -490,7 +490,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->target->color) boom->color = special->target->color; else - boom->color = SKINCOLOR_RED; + boom->color = SKINCOLOR_KETCHUP; S_StartSound(boom, special->info->attacksound); if (player->kartstuff[k_bumper] == 1) // If you have only one bumper left, and see if it's a 1v1 @@ -514,7 +514,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) K_StealBumper(special->target->player, player, true); special->target->player->kartstuff[k_comebacktimer] = comebacktime; - K_ExplodePlayer(player, special->target); + K_ExplodePlayer(player, special->target, special); } } else if (special->target->player->kartstuff[k_comebackmode] == 1 && P_CanPickupItem(player, 1)) @@ -577,6 +577,39 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->target->player->kartstuff[k_eggmanblame] = -1; } return; + case MT_SPB: + if ((special->target == toucher || special->target == toucher->target) && (special->threshold > 0)) + return; + + if (special->health <= 0 || toucher->health <= 0) + return; + + if (!player->mo || player->spectator) + return; + + if (special->tracer && toucher == special->tracer) + { + mobj_t *spbexplode; + + S_StopSound(special); // Don't continue playing the gurgle or the siren + + if (!player->kartstuff[k_invincibilitytimer] && !player->kartstuff[k_growshrinktimer]) + { + K_DropHnextList(player); + K_StripItems(player); + //player->powers[pw_flashing] = 0; + } + + spbexplode = P_SpawnMobj(toucher->x, toucher->y, toucher->z, MT_SPBEXPLOSION); + spbexplode->extravalue1 = 1; // Tell K_ExplodePlayer to use extra knockback + P_SetTarget(&spbexplode->target, special->target); + + P_RemoveMobj(special); + } + else + K_SpinPlayer(player, special, 0, false); + + return; // ***************************************** // // Rings, coins, spheres, weapon panels, etc // @@ -2002,7 +2035,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) || target->type == MT_JAWZ || target->type == MT_JAWZ_DUD || target->type == MT_JAWZ_SHIELD || target->type == MT_BANANA || target->type == MT_BANANA_SHIELD || target->type == MT_FAKEITEM || target->type == MT_FAKESHIELD - || target->type == MT_BALLHOG)) // kart dead items + || target->type == MT_BALLHOG || target->type == MT_SPB)) // kart dead items target->flags |= MF_NOGRAVITY; // Don't drop Tails 03-08-2000 else target->flags &= ~MF_NOGRAVITY; // lose it if you for whatever reason have it, I'm looking at you shields @@ -3146,7 +3179,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!player->kartstuff[k_invincibilitytimer] && player->kartstuff[k_growshrinktimer] <= 0) { // Start shrinking! - player->mo->scalespeed = FRACUNIT/TICRATE; + player->mo->scalespeed = mapheaderinfo[gamemap-1]->mobj_scale/TICRATE; player->mo->destscale = 6*(mapheaderinfo[gamemap-1]->mobj_scale)/8; if (cv_kartdebugshrink.value && !player->bot) player->mo->destscale = 6*player->mo->destscale/8; @@ -3172,8 +3205,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da player->kartstuff[k_growshrinktimer] = 2; } player->kartstuff[k_sneakertimer] = 0; - // Invincible or not, we still need this. - //P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_LIGHTNING); S_StartSound(player->mo, sfx_kc59); return true; } diff --git a/src/p_map.c b/src/p_map.c index 4aed4db6..1d8a2daa 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -824,7 +824,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_PLAYER && thing->player) { if (tmthing->state == &states[S_MINEEXPLOSION1]) - K_ExplodePlayer(thing->player, tmthing->target); + K_ExplodePlayer(thing->player, tmthing->target, tmthing); else K_SpinPlayer(thing->player, tmthing->target, 0, false); } @@ -1033,7 +1033,7 @@ static boolean PIT_CheckThing(mobj_t *thing) { // Player Damage if (thing->state == &states[S_MINEEXPLOSION1]) - K_ExplodePlayer(tmthing->player, thing->target); + K_ExplodePlayer(tmthing->player, thing->target, thing); else K_SpinPlayer(tmthing->player, thing->target, 0, false); @@ -1077,7 +1077,8 @@ static boolean PIT_CheckThing(mobj_t *thing) //} - if (thing->type == MT_FALLINGROCK || tmthing->type == MT_FALLINGROCK) + if ((thing->type == MT_FALLINGROCK && (tmthing->player || tmthing->type == MT_FALLINGROCK)) + || (tmthing->type == MT_FALLINGROCK && (thing->player || thing->type == MT_FALLINGROCK))) { // see if it went over / under if (tmthing->z > thing->z + thing->height) diff --git a/src/p_mobj.c b/src/p_mobj.c index 0578dc39..ed1c0ba7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2626,12 +2626,14 @@ static boolean P_ZMovement(mobj_t *mo) mom.z /= 2; // Rocks not so bouncy - if (abs(mom.x) < FixedMul(STOPSPEED, mo->scale) - && abs(mom.y) < FixedMul(STOPSPEED, mo->scale) - && abs(mom.z) < FixedMul(STOPSPEED*3, mo->scale)) + if (!mo->fuse + && abs(mom.x) < FixedMul(STOPSPEED*2, mo->scale) + && abs(mom.y) < FixedMul(STOPSPEED*2, mo->scale) + && abs(mom.z) < FixedMul(STOPSPEED*2*3, mo->scale)) { - P_RemoveMobj(mo); - return false; + //P_RemoveMobj(mo); + //return false; + mo->fuse = TICRATE; } } else if (mo->type == MT_CANNONBALLDECOR) @@ -7401,6 +7403,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_ORBINAUT: case MT_BANANA: case MT_FAKEITEM: + case MT_SPB: if (mobj->z <= mobj->floorz) { P_RemoveMobj(mobj); @@ -7421,7 +7424,7 @@ void P_MobjThinker(mobj_t *mobj) mobj->flags2 ^= MF2_DONTDRAW; break; case MT_SSMINE: - case MT_BLUEEXPLOSION: + case MT_SPBEXPLOSION: if (mobj->health > -100) { P_SetMobjState(mobj, mobj->info->deathstate); @@ -7444,13 +7447,14 @@ void P_MobjThinker(mobj_t *mobj) { case MT_FALLINGROCK: // Despawn rocks here in case zmovement code can't do so (blame slopes) - if (!mobj->momx && !mobj->momy && !mobj->momz + if (!mobj->fuse && !mobj->momx && !mobj->momy && !mobj->momz && ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->z + mobj->height >= mobj->ceilingz : mobj->z <= mobj->floorz)) { - P_RemoveMobj(mobj); - return; + //P_RemoveMobj(mobj); + //return; + mobj->fuse = TICRATE; } P_MobjCheckWater(mobj); break; @@ -8155,6 +8159,9 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->threshold > 0) mobj->threshold--; break; + case MT_SPB: + indirectitemcooldown = 20*TICRATE; + /* FALLTHRU */ case MT_BALLHOG: P_SpawnGhostMobj(mobj)->fuse = 3; if (mobj->threshold > 0) @@ -8175,7 +8182,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->target && mobj->target->player) mobj->color = mobj->target->player->skincolor; else - mobj->color = SKINCOLOR_RED; + mobj->color = SKINCOLOR_KETCHUP; if (mobj->momx || mobj->momy) P_SpawnGhostMobj(mobj); if (P_IsObjectOnGround(mobj)) @@ -8201,7 +8208,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->threshold > 0) mobj->threshold--; break; - case MT_BLUEEXPLOSION: + case MT_SPBEXPLOSION: mobj->health--; break; case MT_MINEEXPLOSION: @@ -8265,7 +8272,7 @@ void P_MobjThinker(mobj_t *mobj) P_SetScale(smoke, mobj->target->scale/2); smoke->destscale = 3*mobj->target->scale/2; - smoke->scalespeed = FixedMul(smoke->scalespeed, mobj->target->scale); + smoke->scalespeed = mobj->target->scale/12; smoke->momx = mobj->target->momx/2; smoke->momy = mobj->target->momy/2; @@ -8383,74 +8390,80 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_KARMAHITBOX: - if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator - || (G_RaceGametype() || mobj->target->player->kartstuff[k_bumper])) { - P_RemoveMobj(mobj); - return; - } + statenum_t state = (mobj->state-states); - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); - mobj->scalespeed = mobj->target->scalespeed; - mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); - mobj->color = mobj->target->color; - mobj->colorized = (mobj->target->player->kartstuff[k_comebackmode]); - - if (mobj->target->player->kartstuff[k_comebacktimer] > 0) - { - if (mobj->state != &states[mobj->info->spawnstate]) - P_SetMobjState(mobj, mobj->info->spawnstate); - - if (mobj->target->player->kartstuff[k_comebacktimer] < TICRATE && (leveltime & 1)) - mobj->flags2 &= ~MF2_DONTDRAW; - else - mobj->flags2 |= MF2_DONTDRAW; - } - else - { - if (!mobj->target->player->kartstuff[k_comebackmode] - && mobj->state != &states[mobj->info->spawnstate]) - P_SetMobjState(mobj, mobj->info->spawnstate); - else if (mobj->target->player->kartstuff[k_comebackmode] == 1 - && mobj->state != &states[mobj->info->seestate]) - P_SetMobjState(mobj, mobj->info->seestate); - else if (mobj->target->player->kartstuff[k_comebackmode] == 2 - && mobj->state != &states[mobj->info->painstate]) - P_SetMobjState(mobj, mobj->info->painstate); - - if (mobj->target->player->powers[pw_flashing] && (leveltime & 1)) - mobj->flags2 |= MF2_DONTDRAW; - else - mobj->flags2 &= ~MF2_DONTDRAW; - } - - // Now for the wheels - { - const fixed_t rad = FixedMul(mobjinfo[MT_PLAYER].radius, mobj->target->scale); - mobj_t *cur = mobj->hnext; - - while (cur && !P_MobjWasRemoved(cur)) + if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator + || (G_RaceGametype() || mobj->target->player->kartstuff[k_bumper])) { - fixed_t offx = rad; - fixed_t offy = rad; + P_RemoveMobj(mobj); + return; + } - if (cur->lastlook == 1 || cur->lastlook == 3) - offx *= -1; - if (cur->lastlook == 2 || cur->lastlook == 3) - offy *= -1; + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + mobj->angle = mobj->target->angle; + mobj->scalespeed = mobj->target->scalespeed; + mobj->destscale = mobj->target->destscale; + P_SetScale(mobj, mobj->target->scale); + mobj->color = mobj->target->color; + mobj->colorized = true; - P_TeleportMove(cur, mobj->x + offx, mobj->y + offy, mobj->z); - cur->scalespeed = mobj->target->scalespeed; - cur->destscale = mobj->target->destscale; - P_SetScale(cur, mobj->target->scale); - - if (mobj->flags2 & MF2_DONTDRAW) - cur->flags2 |= MF2_DONTDRAW; + if (mobj->target->player->kartstuff[k_comebacktimer] > 0) + { + if (state < mobj->info->spawnstate || state > mobj->info->spawnstate+19) + P_SetMobjState(mobj, mobj->info->spawnstate); + if (mobj->target->player->kartstuff[k_comebacktimer] < TICRATE && (leveltime & 1)) + mobj->flags2 &= ~MF2_DONTDRAW; else - cur->flags2 &= ~MF2_DONTDRAW; + mobj->flags2 |= MF2_DONTDRAW; + } + else + { + if (!mobj->target->player->kartstuff[k_comebackmode] + && (state < mobj->info->spawnstate || state > mobj->info->spawnstate+19)) + P_SetMobjState(mobj, mobj->info->spawnstate); + else if (mobj->target->player->kartstuff[k_comebackmode] == 1 + && state != mobj->info->seestate) + P_SetMobjState(mobj, mobj->info->seestate); + else if (mobj->target->player->kartstuff[k_comebackmode] == 2 + && state != mobj->info->painstate) + P_SetMobjState(mobj, mobj->info->painstate); - cur = cur->hnext; + if (mobj->target->player->powers[pw_flashing] && (leveltime & 1)) + mobj->flags2 |= MF2_DONTDRAW; + else + mobj->flags2 &= ~MF2_DONTDRAW; + } + + // Now for the wheels + { + const fixed_t rad = FixedMul(mobjinfo[MT_PLAYER].radius, mobj->target->scale); + mobj_t *cur = mobj->hnext; + + while (cur && !P_MobjWasRemoved(cur)) + { + fixed_t offx = rad; + fixed_t offy = rad; + + if (cur->lastlook == 1 || cur->lastlook == 3) + offx *= -1; + if (cur->lastlook == 2 || cur->lastlook == 3) + offy *= -1; + + P_TeleportMove(cur, mobj->x + offx, mobj->y + offy, mobj->z); + cur->scalespeed = mobj->target->scalespeed; + cur->destscale = mobj->target->destscale; + P_SetScale(cur, mobj->target->scale); + cur->color = mobj->target->color; + cur->colorized = true; + + if (mobj->flags2 & MF2_DONTDRAW) + cur->flags2 |= MF2_DONTDRAW; + else + cur->flags2 &= ~MF2_DONTDRAW; + + cur = cur->hnext; + } } } break; @@ -8842,7 +8855,7 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s if (P_MobjWasRemoved(mobj)) return; } - else if (((mobj->type == MT_RANDOMITEM && mobj->threshold == 69) || mobj->type == MT_FAKEITEM) && mobj->fuse <= TICRATE) + else if (((mobj->type == MT_RANDOMITEM && mobj->threshold == 69) || mobj->type == MT_FAKEITEM || mobj->type == MT_FALLINGROCK) && mobj->fuse <= TICRATE) mobj->flags2 ^= MF2_DONTDRAW; } @@ -9176,7 +9189,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // All mobjs are created at 100% scale. mobj->scale = FRACUNIT; mobj->destscale = mobj->scale; - mobj->scalespeed = FRACUNIT/12; + mobj->scalespeed = mapheaderinfo[gamemap-1]->mobj_scale/12; if (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->mobj_scale != FRACUNIT) //&& !(mobj->type == MT_BLACKEGGMAN) mobj->destscale = mapheaderinfo[gamemap-1]->mobj_scale; @@ -9429,6 +9442,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_SSMINE: case MT_SSMINE_SHIELD: case MT_BALLHOG: case MT_SINK: case MT_THUNDERSHIELD: case MT_ROCKETSNEAKER: + case MT_SPB: P_SpawnShadowMobj(mobj); default: break; @@ -9516,7 +9530,7 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster) // All mobjs are created at 100% scale. mobj->scale = FRACUNIT; mobj->destscale = mobj->scale; - mobj->scalespeed = FRACUNIT/12; + mobj->scalespeed = mapheaderinfo[gamemap-1]->mobj_scale/12; if (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->mobj_scale != FRACUNIT) //&& !(mobj->type == MT_BLACKEGGMAN) mobj->destscale = mapheaderinfo[gamemap-1]->mobj_scale; diff --git a/src/p_saveg.c b/src/p_saveg.c index 3ba026a7..a4c1192b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1116,7 +1116,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff |= MD_SCALE; if (mobj->destscale != mobj->scale) diff |= MD_DSCALE; - if (mobj->scalespeed != FRACUNIT/12) + if (mobj->scalespeed != mapheaderinfo[gamemap-1]->mobj_scale/12) diff2 |= MD2_SCALESPEED; if (mobj == redflag) @@ -2123,7 +2123,7 @@ static void LoadMobjThinker(actionf_p1 thinker) if (diff2 & MD2_SCALESPEED) mobj->scalespeed = READFIXED(save_p); else - mobj->scalespeed = FRACUNIT/12; + mobj->scalespeed = mapheaderinfo[gamemap-1]->mobj_scale/12; if (diff2 & MD2_CUSVAL) mobj->cusval = READINT32(save_p); if (diff2 & MD2_CVMEM) @@ -3284,8 +3284,6 @@ static void P_NetArchiveMisc(void) WRITEUINT32(save_p, wantedcalcdelay); WRITEUINT32(save_p, indirectitemcooldown); - WRITEUINT32(save_p, spbincoming); - WRITEUINT8(save_p, spbplayer); WRITEUINT32(save_p, mapreset); WRITEUINT8(save_p, nospectategrief); @@ -3391,8 +3389,6 @@ static inline boolean P_NetUnArchiveMisc(void) wantedcalcdelay = READUINT32(save_p); indirectitemcooldown = READUINT32(save_p); - spbincoming = READUINT32(save_p); - spbplayer = READUINT8(save_p); mapreset = READUINT32(save_p); nospectategrief = READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index e58905a0..471bbb1c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3023,8 +3023,6 @@ boolean P_SetupLevel(boolean skipprecip) wantedcalcdelay = wantedfrequency*2; indirectitemcooldown = 0; - spbincoming = 0; - spbplayer = 0; mapreset = 0; nospectategrief = 0; diff --git a/src/p_tick.c b/src/p_tick.c index 9b59e70d..e2a1bb4b 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -678,38 +678,6 @@ void P_Ticker(boolean run) if (countdown2) countdown2--; - if (spbincoming && --spbincoming <= 0) - { - UINT8 best = 0; - SINT8 hurtthisguy = -1; - - spbincoming = 0; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (players[i].exiting) - continue; - - if (best <= 0 || players[i].kartstuff[k_position] < best) - { - best = players[i].kartstuff[k_position]; - hurtthisguy = i; - } - } - - if (hurtthisguy != -1) - { - players[hurtthisguy].kartstuff[k_deathsentence] = (2*TICRATE)+1; - S_StartSound(players[hurtthisguy].mo, sfx_kc57); - } - } - if (indirectitemcooldown) indirectitemcooldown--; diff --git a/src/p_user.c b/src/p_user.c index 19accdba..dc4bdaf5 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -7666,7 +7666,8 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) mo = (mobj_t *)think; - if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS)) + if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS + || mo->type == MT_SPB)) // Don't want to give SPB MF_SHOOTABLE, to ensure it's undamagable through other means continue; if (mo->flags & MF_MONITOR) @@ -7695,7 +7696,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) || mo->type == MT_ORBINAUT_SHIELD || mo->type == MT_JAWZ_SHIELD || mo->type == MT_BANANA || mo->type == MT_BANANA_SHIELD || mo->type == MT_FAKEITEM || mo->type == MT_FAKESHIELD - || mo->type == MT_BALLHOG) + || mo->type == MT_BALLHOG || mo->type == MT_SPB) { if (mo->eflags & MFE_VERTICALFLIP) mo->z -= mo->height; @@ -7709,6 +7710,9 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) P_InstaThrust(mo, R_PointToAngle2(inflictor->x, inflictor->y, mo->x, mo->y)+ANGLE_90, 16*FRACUNIT); } + if (mo->type == MT_SPB) // If you destroy a SPB, you don't get the luxury of a cooldown. + indirectitemcooldown = 0; + if (mo == inflictor) // Don't nuke yourself, dummy! continue; @@ -8066,11 +8070,14 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall fixed_t x, y, z, dist, height, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight; fixed_t pan, xpan, ypan; INT32 camrotate; - boolean camstill, cameranoclip, lookback; + boolean camstill, lookback; UINT8 timeover; mobj_t *mo; - subsector_t *newsubsec; fixed_t f1, f2; +#ifndef NOCLIPCAM + boolean cameranoclip; + subsector_t *newsubsec; +#endif // We probably shouldn't move the camera if there is no player or player mobj somehow if (!player || !player->mo) @@ -8078,13 +8085,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall mo = player->mo; -#ifdef NOCLIPCAM - cameranoclip = true; // We like camera noclip! -#else +#ifndef NOCLIPCAM cameranoclip = ((player->pflags & (PF_NOCLIP|PF_NIGHTSMODE)) || (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) // Noclipping player camera noclips too!! || (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 @@ -8332,6 +8338,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall else z = mo->z + pviewheight + camheight; +#ifndef NOCLIPCAM // Disable all z-clipping for noclip cam // move camera down to move under lower ceilings newsubsec = R_IsPointInSubsector(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1)); @@ -8529,6 +8536,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (thiscam->z < thiscam->floorz && !cameranoclip) thiscam->z = thiscam->floorz; +#endif // NOCLIPCAM // point viewed by the camera // this point is just 64 unit forward the player @@ -8559,7 +8567,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { thiscam->momx = x - thiscam->x; thiscam->momy = y - thiscam->y; - thiscam->momz = FixedMul(z - thiscam->z, camspeed/2); + if (splitscreen == 1) // Wide-screen needs to follow faster, due to a smaller vertical:horizontal ratio of screen space + thiscam->momz = FixedMul(z - thiscam->z, (3*camspeed)/4); + else + thiscam->momz = FixedMul(z - thiscam->z, camspeed/2); } thiscam->pan = pan;