diff --git a/src/command.c b/src/command.c index 8a5c5974..961dbe97 100644 --- a/src/command.c +++ b/src/command.c @@ -1447,8 +1447,8 @@ void CV_AddValue(consvar_t *var, INT32 increment) INT32 newvalue, max; // count pointlimit better - if (var == &cv_pointlimit && (gametype == GT_MATCH)) - increment *= 50; + /*if (var == &cv_pointlimit && (gametype == GT_MATCH)) + increment *= 50;*/ newvalue = var->value + increment; if (var->PossibleValue) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d185c59d..0a2c5eb2 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -43,6 +43,7 @@ #include "lzf.h" #include "lua_script.h" #include "lua_hook.h" +#include "k_kart.h" #ifdef CLIENT_LOADINGSCREEN // cl loading screen @@ -519,8 +520,6 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]); for (j = 0; j < NUMKARTSTUFF; ++j) rsp->kartstuff[j] = LONG(players[i].kartstuff[j]); // SRB2kart - for (j = 0; j < MAXPLAYERS; ++j) - rsp->collide[j] = (UINT8)players[i].collide[j]; // SRB2kart // Score is resynched in the rspfirm resync packet rsp->health = 0; // resynched with mo health @@ -576,6 +575,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->starposty = SHORT(players[i].starposty); rsp->starpostz = SHORT(players[i].starpostz); rsp->starpostnum = LONG(players[i].starpostnum); + rsp->starpostcount = LONG(players[i].starpostcount); rsp->starposttime = (tic_t)LONG(players[i].starposttime); rsp->starpostangle = (angle_t)LONG(players[i].starpostangle); @@ -653,8 +653,6 @@ static void resynch_read_player(resynch_pak *rsp) players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]); for (j = 0; j < NUMKARTSTUFF; ++j) players[i].kartstuff[j] = LONG(rsp->kartstuff[j]); // SRB2kart - for (j = 0; j < MAXPLAYERS; ++j) - players[i].collide[j] = (UINT8)rsp->collide[j]; // SRB2kart // Score is resynched in the rspfirm resync packet players[i].health = rsp->health; @@ -709,6 +707,7 @@ static void resynch_read_player(resynch_pak *rsp) players[i].starposty = SHORT(rsp->starposty); players[i].starpostz = SHORT(rsp->starpostz); players[i].starpostnum = LONG(rsp->starpostnum); + players[i].starpostcount = LONG(rsp->starpostcount); players[i].starposttime = (tic_t)LONG(rsp->starposttime); players[i].starpostangle = (angle_t)LONG(rsp->starpostangle); @@ -2427,6 +2426,8 @@ static void CL_RemovePlayer(INT32 playernum) if (G_TagGametype()) //Check if you still have a game. Location flexible. =P P_CheckSurvivors(); + else if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF) + K_CheckBalloons(); // SRB2Kart else if (gametype == GT_RACE || gametype == GT_COMPETITION) P_CheckRacers(); } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 3d7d7322..8249f1f4 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -163,7 +163,7 @@ typedef struct UINT16 powers[NUMPOWERS]; INT32 kartstuff[NUMKARTSTUFF]; // SRB2kart - UINT8 collide[MAXPLAYERS]; // SRB2kart + angle_t frameangle; // SRB2kart // Score is resynched in the confirm resync packet INT32 health; @@ -219,6 +219,7 @@ typedef struct INT16 starposty; INT16 starpostz; INT32 starpostnum; + INT32 starpostcount; tic_t starposttime; angle_t starpostangle; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a20a4b1f..ca24a998 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -313,9 +313,17 @@ consvar_t cv_jaws = {"jaws", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, consvar_t cv_fireflower = {"fireflowers", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_tripleredshell = {"tripleredshells", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_lightning = {"lightning", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_feather = {"feathers", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_karthud = {"karthud", "Default", CV_SAVE|CV_CALL, karthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartcheck = {"kartcheck", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t kartstarsfx_cons_t[] = {{0, "Music"}, {1, "SMK"}, {0, NULL}}; +consvar_t cv_kartstarsfx = {"kartstarsfx", "SMK", CV_SAVE, kartstarsfx_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // change default to "SMK"? consvar_t cv_kartcc = {"kartcc", "100cc", CV_NETVAR, kartcc_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t kartballoons_cons_t[] = {{1, "MIN"}, {12, "MAX"}, {0, NULL}}; +consvar_t cv_kartballoons = {"kartballoons", "3", CV_NETVAR, kartballoons_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t speedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}}; consvar_t cv_speedometer = {"speedometer", "Kilometers", CV_SAVE, speedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display @@ -1063,7 +1071,7 @@ UINT8 CanChangeSkin(INT32 playernum) return true; // Can change skin during initial countdown. - if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE) + if (leveltime < 4*TICRATE) return true; if (G_TagGametype()) @@ -1868,8 +1876,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) // a copy of color if (players[0].mo) players[0].mo->color = players[0].skincolor; - - CV_StealthSetValue(&cv_kartcc, 150); // srb2kart } if (metalrecording) G_BeginMetal(); @@ -1970,11 +1976,11 @@ static void Command_Suicide(void) return; } - if (!G_PlatformGametype()) + /*if (!G_PlatformGametype()) // srb2kart: not necessary, suiciding makes you lose a balloon in battle, so it's not desirable to use as a way to escape a hit { CONS_Printf(M_GetText("You may only use this in co-op, race, and competition!\n")); return; - } + }*/ // Retry is quicker. Probably should force people to use it. if (!(netgame || multiplayer)) @@ -1991,7 +1997,7 @@ static void Got_Suicide(UINT8 **cp, INT32 playernum) INT32 suicideplayer = READINT32(*cp); // You can't suicide someone else. Nice try, there. - if (suicideplayer != playernum || (!G_PlatformGametype())) + if (suicideplayer != playernum) // srb2kart: "|| (!G_PlatformGametype())" { CONS_Alert(CONS_WARNING, M_GetText("Illegal suicide command received from %s\n"), player_names[playernum]); if (server) @@ -2661,6 +2667,8 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) // In tag, check to see if you still have a game. if (G_TagGametype()) P_CheckSurvivors(); + else if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF) + K_CheckBalloons(); // SRB2Kart } // @@ -3544,9 +3552,9 @@ void D_GameTypeChanged(INT32 lastgametype) case GT_TEAMMATCH: if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits { - // default settings for match: timelimit 10 mins, no pointlimit + // default settings for match: no timelimit, no pointlimit CV_SetValue(&cv_pointlimit, 0); - CV_SetValue(&cv_timelimit, 10); + CV_SetValue(&cv_timelimit, 0); } if (!cv_itemrespawntime.changed) CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally @@ -3604,7 +3612,7 @@ void D_GameTypeChanged(INT32 lastgametype) // When swapping to a gametype that supports spectators, // make everyone a spectator initially. - if (!splitscreen && (G_GametypeHasSpectators())) + /*if (!splitscreen && (G_GametypeHasSpectators())) { INT32 i; for (i = 0; i < MAXPLAYERS; i++) @@ -3613,7 +3621,7 @@ void D_GameTypeChanged(INT32 lastgametype) players[i].ctfteam = 0; players[i].spectator = true; } - } + }*/ // don't retain teams in other modes or between changes from ctf to team match. // also, stop any and all forms of team scrambling that might otherwise take place. diff --git a/src/d_netcmd.h b/src/d_netcmd.h index cf9260ea..68dc7ed2 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -103,9 +103,15 @@ extern consvar_t cv_magnet, cv_boo, cv_mushroom, cv_triplemushroom, cv_megashroo extern consvar_t cv_goldshroom, cv_star, cv_triplebanana, cv_fakeitem, cv_banana; extern consvar_t cv_greenshell, cv_redshell, cv_laserwisp, cv_triplegreenshell, cv_bobomb; extern consvar_t cv_blueshell, cv_jaws, cv_fireflower, cv_tripleredshell, cv_lightning; +extern consvar_t cv_feather; extern consvar_t cv_karthud; +extern consvar_t cv_kartcheck; +extern consvar_t cv_kartstarsfx; extern consvar_t cv_kartcc; +extern consvar_t cv_kartballoons; +extern consvar_t cv_kartfrantic; +extern consvar_t cv_kartcomeback; extern consvar_t cv_speedometer; extern consvar_t cv_collideminimum; diff --git a/src/d_player.h b/src/d_player.h index a84c2ccd..4f043cf8 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -266,6 +266,7 @@ typedef enum // Some items use timers for their duration or effects k_magnettimer, // Duration of Magnet's item-break and item box pull + k_bootimer, // Duration of the boo offroad effect itself k_bootaketimer, // You are stealing an item, this is your timer k_boostolentimer, // You are being stolen from, this is your timer k_mushroomtimer, // Duration of the Mushroom Boost itself @@ -275,6 +276,9 @@ typedef enum k_startimer, // Invincibility timer k_spinouttimer, // Wipe-out from a banana peel or oil slick (was "pw_bananacam") k_laserwisptimer, // The duration and relative angle of the laser + k_justbumped, // Prevent players from endlessly bumping into each other + k_poweritemtimer, // Battle mode, how long before you're allowed another power item (Star, Megashroom) + k_comebacktimer, // Battle mode, how long before you become a bomb after death // Each item needs its own power slot, for the HUD and held use k_magnet, // 0x1 = Magnet in inventory @@ -301,8 +305,15 @@ typedef enum k_tripleredshell, // 0x1 = 1 Red Shell orbiting, 0x2 = 2 Red Shells orbiting // 0x4 = 3 Red Shells orbiting, 0x8 = Triple Red Shell in inventory k_lightning, // 0x1 = Lightning in inventory + k_feather, // 0x1 = Feather in inventory, 0x2 = Player is feather jumping k_kitchensink, // 0x1 = Sink in inventory + // Battle Mode vars + k_balloon, // Number of balloons left + k_comebackpoints, // Number of times you've bombed or gave an item to someone; once it's 3 it gets set back to 0 and you're given a balloon + k_comebackmode, // 0 = bomb, 1 = item + k_comebackshowninfo,// Have you already seen the info screen before? + NUMKARTSTUFF } kartstufftype_t; //} @@ -365,7 +376,6 @@ typedef struct player_s // SRB2kart stuff INT32 kartstuff[NUMKARTSTUFF]; - boolean collide[MAXPLAYERS]; angle_t frameangle; // for the player add the ability to have the sprite only face other angles // Bit flags. @@ -467,6 +477,7 @@ typedef struct player_s INT16 starposty; INT16 starpostz; INT32 starpostnum; // The number of the last starpost you hit + INT32 starpostcount; // SRB2kart: how many did you hit? tic_t starposttime; // Your time when you hit the starpost angle_t starpostangle; // Angle that the starpost is facing - you respawn facing this way diff --git a/src/dehacked.c b/src/dehacked.c index 0816d1bc..c4c8fed9 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6367,6 +6367,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SINKTRAIL2", "S_SINKTRAIL3", + // Battle Mode balloon + "S_BATTLEBALLOON1", + "S_BATTLEBALLOON2", + "S_BATTLEBALLOON3", + // Pokey "S_POKEY1", "S_POKEY2", @@ -6401,6 +6406,27 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FIREDITEM3", "S_FIREDITEM4", + "S_PLAYERARROW", // Above player arrow + "S_PLAYERARROW_MUSHROOM", + "S_PLAYERARROW_GREENSHELL", + "S_PLAYERARROW_BANANA", + "S_PLAYERARROW_FAKEITEM", + "S_PLAYERARROW_BOO", + "S_PLAYERARROW_FEATHER", + "S_PLAYERARROW_REDSHELL", + "S_PLAYERARROW_BOBOMB", + "S_PLAYERARROW_FIREFLOWER", + "S_PLAYERARROW_TRIPLEGREENSHELL", + "S_PLAYERARROW_TRIPLEBANANA", + "S_PLAYERARROW_TRIPLEREDSHELL", + "S_PLAYERARROW_STAR", + "S_PLAYERARROW_MEGASHROOM", + "S_PLAYERARROW_KITCHENSINK", + "S_PLAYERARROW_EMPTY", + "S_PLAYERARROW_ROULETTE", + + "S_PLAYERBOMB", // Player bomb overlay + #ifdef SEENAMES "S_NAMECHECK", #endif @@ -6958,6 +6984,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_SINK", // Kitchen Sink Stuff "MT_SINKTRAIL", + "MT_BATTLEBALLOON", // Battle Mode balloon + + "MT_LAKITU", + "MT_POKEY", // Huh, thought this was a default asset for some reason, guess not. "MT_ENEMYFLIP", "MT_WAYPOINT", @@ -6969,6 +6999,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_FIREDITEM", + "MT_PLAYERARROW", + #ifdef SEENAMES "MT_NAMECHECK", #endif @@ -7281,6 +7313,80 @@ static const char *const POWERS_LIST[] = { "INGOOP" // In goop }; +static const char *const KARTSTUFF_LIST[] = { + "POSITION", + "OLDPOSITION", + "POSITIONDELAY", + "PREVCHECK", + "NEXTCHECK", + "WAYPOINT", + "STARPOSTWP", + "LAKITU", + + "THROWDIR", + "CAMSPIN", + "LAPANIMATION", + "SOUNDS", + + "BOOSTING", + "FLOORBOOST", + "SPINOUT", + "SPINOUTTYPE", + + "DRIFT", + "DRIFTEND", + "DRIFTCHARGE", + "DRIFTBOOST", + "BOOSTCHARGE", + "JMP", + "OFFROAD", + + "ITEMROULETTE", + "ITEMCLOSE", + + "MAGNETTIMER", + "BOOTIMER", + "BOOTAKETIMER", + "BOOSTOLENTIMER", + "MUSHROOMTIMER", + "GROWSHRINKTIMER", + "SQUISHEDTIMER", + "GOLDSHROOMTIMER", + "STARTIMER", + "SPINOUTTIMER", + "LASERWISPTIMER", + "JUSTBUMPED", + "POWERITEMTIMER", + "COMEBACKTIMER", + + "MAGNET", + "BOO", + "MUSHROOM", + "MEGASHROOM", + "GOLDSHROOM", + "STAR", + "TRIPLEBANANA", + "FAKEITEM", + "BANANA", + "GREENSHELL", + "REDSHELL", + "LASERWISP", + "TRIPLEGREENSHELL", + "BOBOMB", + "BLUESHELL", + "JAWS", + "FIREFLOWER", + "TRIPLEREDSHELL", + "LIGHTNING", + "FEATHER", + "KITCHENSINK", + + "BALLOON", + "COMEBACKPOINTS", + "COMEBACKMODE", + "COMEBACKSHOWNINFO" +}; + static const char *const HUDITEMS_LIST[] = { "LIVESNAME", "LIVESPIC", @@ -7915,6 +8021,20 @@ static powertype_t get_power(const char *word) return pw_invulnerability; } +static kartstufftype_t get_kartstuff(const char *word) +{ // Returns the vlaue of k_ enumerations + kartstufftype_t i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("K_",word,2)) + word += 2; // take off the k_ + for (i = 0; i < NUMKARTSTUFF; i++) + if (fastcmp(word, KARTSTUFF_LIST[i])) + return i; + deh_warning("Couldn't find power named 'k_%s'",word); + return k_position; +} + /// \todo Make ANY of this completely over-the-top math craziness obey the order of operations. static fixed_t op_mul(fixed_t a, fixed_t b) { return a*b; } static fixed_t op_div(fixed_t a, fixed_t b) { return a/b; } @@ -8151,6 +8271,7 @@ void FUNCMATH DEH_Check(void) const size_t dehstates = sizeof(STATE_LIST)/sizeof(const char*); const size_t dehmobjs = sizeof(MOBJTYPE_LIST)/sizeof(const char*); const size_t dehpowers = sizeof(POWERS_LIST)/sizeof(const char*); + const size_t dehkartstuff = sizeof(KARTSTUFF_LIST)/sizeof(const char*); const size_t dehcolors = sizeof(COLOR_ENUMS)/sizeof(const char*); if (dehstates != S_FIRSTFREESLOT) @@ -8162,6 +8283,9 @@ void FUNCMATH DEH_Check(void) if (dehpowers != NUMPOWERS) I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d powers defined, versus %s in the Dehacked list)\n", NUMPOWERS, sizeu1(dehpowers)); + if (dehkartstuff != NUMKARTSTUFF) + I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d kartstuff defined, versus %s in the Dehacked list)\n", NUMKARTSTUFF, sizeu1(dehkartstuff)); + if (dehcolors != MAXTRANSLATIONS) I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", MAXTRANSLATIONS, sizeu1(dehcolors)); #endif @@ -8501,6 +8625,24 @@ static inline int lib_getenum(lua_State *L) } return luaL_error(L, "power '%s' could not be found.\n", word); } + else if (!mathlib && fastncmp("k_",word,2)) { + p = word+2; + for (i = 0; i < NUMKARTSTUFF; i++) + if (fasticmp(p, KARTSTUFF_LIST[i])) { + lua_pushinteger(L, i); + return 1; + } + return 0; + } + else if (mathlib && fastncmp("K_",word,2)) { // SOCs are ALL CAPS! + p = word+2; + for (i = 0; i < NUMKARTSTUFF; i++) + if (fastcmp(p, KARTSTUFF_LIST[i])) { + lua_pushinteger(L, i); + return 1; + } + return luaL_error(L, "kartstuff '%s' could not be found.\n", word); + } else if (fastncmp("HUD_",word,4)) { p = word+4; for (i = 0; i < NUMHUDITEMS; i++) diff --git a/src/doomstat.h b/src/doomstat.h index 8553aaec..9d4fda5e 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -329,7 +329,7 @@ extern UINT16 emeralds; #define EMERALD7 64 #define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) -extern INT32 nummaprings; //keep track of spawned rings/coins +extern INT32 nummaprings, nummapboxes, numgotboxes; //keep track of spawned rings/coins/battle mode items /** Time attack information, currently a very small structure. */ @@ -401,8 +401,10 @@ extern UINT16 extralifetics; // SRB2kart extern INT32 bootime; +extern INT32 boostealtime; extern INT32 mushroomtime; extern INT32 itemtime; +extern INT32 comebacktime; extern UINT8 introtoplay; extern UINT8 creditscutscene; diff --git a/src/g_game.c b/src/g_game.c index bc391e77..b3c4ff69 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -179,6 +179,10 @@ UINT32 bluescore, redscore; // CTF and Team Match team scores // ring count... for PERFECT! INT32 nummaprings = 0; +// box respawning in battle mode +INT32 nummapboxes = 0; +INT32 numgotboxes = 0; + // Elminates unnecessary searching. boolean CheckForBustableBlocks; boolean CheckForBouncySector; @@ -198,8 +202,10 @@ UINT16 extralifetics = 4*TICRATE; // SRB2kart INT32 bootime = 7*TICRATE; +INT32 boostealtime = TICRATE/2; INT32 mushroomtime = TICRATE + (TICRATE/3); INT32 itemtime = 8*TICRATE; +INT32 comebacktime = 10*TICRATE; INT32 gameovertics = 15*TICRATE; @@ -1784,7 +1790,7 @@ boolean G_Responder(event_t *ev) if (players[displayplayer].spectator) continue; - if (G_GametypeHasTeams()) + /*if (G_GametypeHasTeams()) { if (players[consoleplayer].ctfteam && players[displayplayer].ctfteam != players[consoleplayer].ctfteam) @@ -1806,6 +1812,12 @@ boolean G_Responder(event_t *ev) { if (!players[consoleplayer].spectator) continue; + }*/ + + if (gametype != GT_RACE) // srb2kart + { + if (players[consoleplayer].kartstuff[k_balloon] > 0) + continue; } break; @@ -2120,7 +2132,6 @@ static inline void G_PlayerFinishLevel(INT32 player) memset(p->powers, 0, sizeof (p->powers)); memset(p->kartstuff, 0, sizeof (p->kartstuff)); // SRB2kart - memset(p->collide, 0, sizeof (p->collide)); // SRB2kart p->ringweapons = 0; p->mo->flags2 &= ~MF2_SHADOW; // cancel invisibility @@ -2131,6 +2142,7 @@ static inline void G_PlayerFinishLevel(INT32 player) p->starposty = 0; p->starpostz = 0; p->starpostnum = 0; + p->starpostcount = 0; if (rendermode == render_soft) V_SetPaletteLump(GetPalette()); // Reset the palette @@ -2171,6 +2183,7 @@ void G_PlayerReborn(INT32 player) INT16 starposty; INT16 starpostz; INT32 starpostnum; + INT32 starpostcount; INT32 starpostangle; fixed_t jumpfactor; INT32 exiting; @@ -2188,6 +2201,8 @@ void G_PlayerReborn(INT32 player) // SRB2kart INT32 starpostwp; INT32 offroad; + INT32 balloon; + INT32 comebackpoints; score = players[player].score; lives = players[player].lives; @@ -2226,6 +2241,7 @@ void G_PlayerReborn(INT32 player) starposty = players[player].starposty; starpostz = players[player].starpostz; starpostnum = players[player].starpostnum; + starpostcount = players[player].starpostcount; starpostangle = players[player].starpostangle; jumpfactor = players[player].jumpfactor; thokitem = players[player].thokitem; @@ -2242,6 +2258,8 @@ void G_PlayerReborn(INT32 player) // SRB2kart starpostwp = players[player].kartstuff[k_starpostwp]; offroad = players[player].kartstuff[k_offroad]; + balloon = players[player].kartstuff[k_balloon]; + comebackpoints = players[player].kartstuff[k_comebackpoints]; p = &players[player]; memset(p, 0, sizeof (*p)); @@ -2281,6 +2299,7 @@ void G_PlayerReborn(INT32 player) p->starposty = starposty; p->starpostz = starpostz; p->starpostnum = starpostnum; + p->starpostcount = starpostcount; p->starpostangle = starpostangle; p->jumpfactor = jumpfactor; p->exiting = exiting; @@ -2297,6 +2316,9 @@ void G_PlayerReborn(INT32 player) // SRB2kart p->kartstuff[k_starpostwp] = starpostwp; // TODO: get these out of kartstuff, it causes desync p->kartstuff[k_offroad] = offroad; + p->kartstuff[k_balloon] = balloon; + p->kartstuff[k_comebackpoints] = comebackpoints; + p->kartstuff[k_comebacktimer] = comebacktime; // Don't do anything immediately p->pflags |= PF_USEDOWN; @@ -2308,7 +2330,7 @@ void G_PlayerReborn(INT32 player) p->panim = PA_IDLE; // standing animation if ((netgame || multiplayer) && !p->spectator) - p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent + p->powers[pw_flashing] = K_GetKartFlashing(p)-1; // Babysitting deterrent if (p-players == consoleplayer) { @@ -2399,6 +2421,9 @@ static boolean G_CheckSpot(INT32 playernum, mapthing_t *mthing) if (!P_CheckPosition(players[playernum].mo, x, y)) return false; + if (!K_CheckPlayersRespawnColliding(playernum, x, y)) + return false; + return true; } @@ -2644,6 +2669,7 @@ void G_DoReborn(INT32 playernum) player->starposty = 0; player->starpostz = 0; player->starpostnum = 0; + player->starpostcount = 0; } if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD)) { @@ -2801,7 +2827,8 @@ boolean G_GametypeHasTeams(void) // boolean G_GametypeHasSpectators(void) { - return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE); + return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE + && gametype != GT_MATCH); // srb2kart: temporary? } // @@ -3066,7 +3093,7 @@ static void G_DoWorldDone(void) // don't reset player between maps D_MapChange(nextmap+1, gametype, ultimatemode, false, 0, false, false); else - // resetplayer in match/chaos/tag/CTF/race for more equality + // resetplayer in match/tag/CTF for more equality D_MapChange(nextmap+1, gametype, ultimatemode, true, 0, false, false); } @@ -3692,6 +3719,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean players[i].playerstate = PST_REBORN; players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0; players[i].starpostx = players[i].starposty = players[i].starpostz = 0; + players[i].starpostcount = 0; // srb2kart if (netgame || multiplayer) { diff --git a/src/info.c b/src/info.c index 0c241613..79433ecd 100644 --- a/src/info.c +++ b/src/info.c @@ -57,8 +57,8 @@ char sprnames[NUMSPRITES + 1][5] = //SRB2kart Sprites "SPRG","BSPR","RNDM","RPOP","KFRE","DRIF","DSMO","FITM","DFAK","BANA", "DBAN","GSHE","DGSH","RSHE","DRSH","BOMB","BLIG","LIGH","SINK","SITR", - "LAKI","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM", - "SACO","CRAB","SHAD","BUMP","FLEN","CLAS","PSHW" + "KBLN","LAKI","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB", + "CHOM","SACO","CRAB","SHAD","BUMP","FLEN","CLAS","PSHW","ARRO","PBOM" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -2704,6 +2704,10 @@ state_t states[NUMSTATES] = {SPR_SITR, 1, 5, {NULL}, 0, 0, S_SINKTRAIL3}, // S_SINKTRAIL2 {SPR_SITR, 2, 3, {NULL}, 0, 0, S_NULL}, // S_SINKTRAIL3 + {SPR_KBLN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_BATTLEBALLOON1}, // S_BATTLEBALLOON1 + {SPR_KBLN, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_BATTLEBALLOON2}, // S_BATTLEBALLOON2 + {SPR_KBLN, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_BATTLEBALLOON3}, // S_BATTLEBALLOON3 + {SPR_LAKI, 0, 64, {NULL}, 1, 0, S_LAKITU2}, // S_LAKITU1 {SPR_LAKI, 1, 35, {NULL}, 0, 0, S_NULL}, // S_LAKITU2 @@ -2857,6 +2861,28 @@ state_t states[NUMSTATES] = {SPR_PSHW, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_FIREDITEM4}, // S_FIREDITEM3 {SPR_PSHW, FF_FULLBRIGHT|3, 3, {NULL}, 0, 0, S_NULL}, // S_FIREDITEM4 + // Above player arrow + {SPR_ARRO, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW + {SPR_ARRO, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_MUSHROOM + {SPR_ARRO, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_GREENSHELL + {SPR_ARRO, FF_FULLBRIGHT|3, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_BANANA + {SPR_ARRO, FF_FULLBRIGHT|4, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_FAKEITEM + {SPR_ARRO, FF_FULLBRIGHT|5, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_BOO + {SPR_ARRO, FF_FULLBRIGHT|6, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_FEATHER + {SPR_ARRO, FF_FULLBRIGHT|7, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_REDSHELL + {SPR_ARRO, FF_FULLBRIGHT|8, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_BOBOMB + {SPR_ARRO, FF_FULLBRIGHT|9, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_FIREFLOWER + {SPR_ARRO, FF_FULLBRIGHT|10, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_TRIPLEGREENSHELL + {SPR_ARRO, FF_FULLBRIGHT|11, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_TRIPLEBANANA + {SPR_ARRO, FF_FULLBRIGHT|12, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_TRIPLEREDSHELL + {SPR_ARRO, FF_FULLBRIGHT|13, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_STAR + {SPR_ARRO, FF_FULLBRIGHT|14, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_MEGASHROOM + {SPR_ARRO, FF_FULLBRIGHT|15, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_KITCHENSINK + {SPR_ARRO, FF_FULLBRIGHT|16, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW_EMPTY + {SPR_ARRO, FF_FULLBRIGHT|FF_ANIMATE|1, -1, {NULL}, 5, 3, S_NULL}, // S_PLAYERARROW_ROULETTE + + {SPR_PBOM, 0, -1, {NULL}, 1, 0, S_NULL}, // S_PLAYERBOMB + #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK #endif @@ -15112,6 +15138,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BATTLEBALLOON + -1, // doomednum + S_BATTLEBALLOON1,// 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 + 4*FRACUNIT, // speed + 8*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_LAKITU -1, // doomednum S_LAKITU1, // spawnstate @@ -16596,6 +16649,34 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY, // flags S_NULL // raisestate }, + + { // MT_PLAYERARROW + -1, // doomednum + S_PLAYERARROW, // 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 + 36*FRACUNIT, // radius + 37*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + // ============================================================================================================================// #ifdef SEENAMES diff --git a/src/info.h b/src/info.h index 9675ea89..2624f16e 100644 --- a/src/info.h +++ b/src/info.h @@ -598,6 +598,7 @@ typedef enum sprite SPR_LIGH, // Lightning SPR_SINK, // Kitchen Sink SPR_SITR, // Kitchen Sink Trail + SPR_KBLN, // Battle Mode Balloon SPR_LAKI, // Lakitu @@ -620,6 +621,10 @@ typedef enum sprite SPR_CLAS, // items clash SPR_PSHW, // thrown indicator + SPR_ARRO, // player arrows + + SPR_PBOM, // player bomb + SPR_FIRSTFREESLOT, SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1, NUMSPRITES @@ -3212,6 +3217,11 @@ typedef enum state S_SINKTRAIL2, S_SINKTRAIL3, + // Battle Mode balloons + S_BATTLEBALLOON1, + S_BATTLEBALLOON2, + S_BATTLEBALLOON3, + // Lakitu S_LAKITU1, S_LAKITU2, @@ -3373,6 +3383,27 @@ typedef enum state S_FIREDITEM3, S_FIREDITEM4, + S_PLAYERARROW, // Above player arrow + S_PLAYERARROW_MUSHROOM, + S_PLAYERARROW_GREENSHELL, + S_PLAYERARROW_BANANA, + S_PLAYERARROW_FAKEITEM, + S_PLAYERARROW_BOO, + S_PLAYERARROW_FEATHER, + S_PLAYERARROW_REDSHELL, + S_PLAYERARROW_BOBOMB, + S_PLAYERARROW_FIREFLOWER, + S_PLAYERARROW_TRIPLEGREENSHELL, + S_PLAYERARROW_TRIPLEBANANA, + S_PLAYERARROW_TRIPLEREDSHELL, + S_PLAYERARROW_STAR, + S_PLAYERARROW_MEGASHROOM, + S_PLAYERARROW_KITCHENSINK, + S_PLAYERARROW_EMPTY, + S_PLAYERARROW_ROULETTE, + + S_PLAYERBOMB, + #ifdef SEENAMES S_NAMECHECK, #endif @@ -3947,6 +3978,8 @@ typedef enum mobj_type MT_SINK, // Kitchen Sink Stuff MT_SINKTRAIL, + MT_BATTLEBALLOON, // Battle Mode balloons + MT_LAKITU, MT_POKEY, // Huh, thought this was a default asset for some reason, guess not. @@ -4017,6 +4050,8 @@ typedef enum mobj_type MT_FIREDITEM, + MT_PLAYERARROW, + #ifdef SEENAMES MT_NAMECHECK, #endif diff --git a/src/k_kart.c b/src/k_kart.c index a6afef1e..8e576fb7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -18,6 +18,7 @@ #include "z_zone.h" #include "m_misc.h" #include "k_kart.h" +#include "f_finale.h" //{ SRB2kart Color Code @@ -300,8 +301,14 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_fireflower); CV_RegisterVar(&cv_tripleredshell); CV_RegisterVar(&cv_lightning); + CV_RegisterVar(&cv_feather); + CV_RegisterVar(&cv_kartcheck); + CV_RegisterVar(&cv_kartstarsfx); CV_RegisterVar(&cv_kartcc); + CV_RegisterVar(&cv_kartballoons); + CV_RegisterVar(&cv_kartfrantic); + CV_RegisterVar(&cv_kartcomeback); CV_RegisterVar(&cv_speedometer); CV_RegisterVar(&cv_collideminimum); CV_RegisterVar(&cv_collidesoundnum); @@ -310,9 +317,19 @@ void K_RegisterKartStuff(void) //} +UINT8 K_GetKartCC(void) +{ + if (gametype == GT_MATCH) + return 50; + else if (modeattacking) + return 150; + else + return cv_kartcc.value; +} + //{ SRB2kart Roulette Code - Position Based -#define NUMKARTITEMS 18 +#define NUMKARTITEMS 19 #define NUMKARTODDS 40 // Ugly ol' 3D arrays @@ -674,28 +691,30 @@ static INT32 K_KartItemOddsPosition_Retro[MAXPLAYERS][NUMKARTITEMS][MAXPLAYERS] */ // Less ugly 2D arrays -static INT32 K_KartItemOddsDistance_Retro[NUMKARTITEMS][9] = +static INT32 K_KartItemOddsDistance_Retro[NUMKARTITEMS][10] = { - //P-Odds 0 1 2 3 4 5 6 7 8 - /*Magnet*/ { 0, 1, 2, 0, 0, 0, 0, 0, 0 }, // Magnet - /*Boo*/ { 0, 0, 2, 2, 1, 0, 0, 0, 0 }, // Boo - /*Mushroom*/ { 1, 0, 0, 3, 7, 5, 0, 0, 0 }, // Mushroom - /*Triple Mushroom*/ { 0, 0, 0, 0, 3,10, 6, 4, 0 }, // Triple Mushroom - /*Mega Mushroom*/ { 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // Mega Mushroom - /*Gold Mushroom*/ { 0, 0, 0, 0, 0, 1, 6, 8,12 }, // Gold Mushroom - /*Star*/ { 0, 0, 0, 0, 0, 0, 4, 6, 8 }, // Star + //P-Odds 0 1 2 3 4 5 6 7 8 9 + /*Magnet*/ { 0, 0, 1, 2, 0, 0, 0, 0, 0, 0 }, // Magnet + /*Boo*/ { 3, 0, 0, 2, 2, 1, 0, 0, 0, 0 }, // Boo + /*Mushroom*/ { 5, 1, 0, 0, 3, 7, 5, 0, 0, 0 }, // Mushroom + /*Triple Mushroom*/ { 0, 0, 0, 0, 0, 3,10, 6, 4, 0 }, // Triple Mushroom + /*Mega Mushroom*/ { 1, 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // Mega Mushroom + /*Gold Mushroom*/ { 0, 0, 0, 0, 0, 0, 1, 6, 8,12 }, // Gold Mushroom + /*Star*/ { 1, 0, 0, 0, 0, 0, 0, 4, 6, 8 }, // Star - /*Triple Banana*/ { 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // Triple Banana - /*Fake Item*/ { 0, 4, 2, 1, 0, 0, 0, 0, 0 }, // Fake Item - /*Banana*/ { 0, 9, 4, 2, 1, 0, 0, 0, 0 }, // Banana - /*Green Shell*/ { 0, 6, 4, 3, 2, 0, 0, 0, 0 }, // Green Shell - /*Red Shell*/ { 0, 0, 3, 2, 2, 1, 0, 0, 0 }, // Red Shell - /*Triple Green Shell*/ { 0, 0, 0, 1, 1, 1, 0, 0, 0 }, // Triple Green Shell - /*Bob-omb*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Bob-omb - /*Blue Shell*/ { 0, 0, 0, 0, 0, 1, 2, 0, 0 }, // Blue Shell - /*Fire Flower*/ { 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Fire Flower - /*Triple Red Shell*/ { 0, 0, 0, 1, 1, 0, 0, 0, 0 }, // Triple Red Shell - /*Lightning*/ { 0, 0, 0, 0, 0, 0, 1, 2, 0 } // Lightning + /*Triple Banana*/ { 3, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, // Triple Banana + /*Fake Item*/ { 5, 0, 4, 2, 1, 0, 0, 0, 0, 0 }, // Fake Item + /*Banana*/ { 5, 0, 9, 4, 2, 1, 0, 0, 0, 0 }, // Banana + /*Green Shell*/ { 5, 0, 6, 4, 3, 2, 0, 0, 0, 0 }, // Green Shell + /*Red Shell*/ { 3, 0, 0, 3, 2, 2, 1, 0, 0, 0 }, // Red Shell + /*Triple Green Shell*/ { 3, 0, 0, 0, 1, 1, 1, 0, 0, 0 }, // Triple Green Shell + /*Bob-omb*/ { 3, 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Bob-omb + /*Blue Shell*/ { 0, 0, 0, 0, 0, 0, 1, 2, 0, 0 }, // Blue Shell + /*Fire Flower*/ { 3, 0, 0, 1, 2, 1, 0, 0, 0, 0 }, // Fire Flower + /*Triple Red Shell*/ { 1, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, // Triple Red Shell + /*Lightning*/ { 0, 0, 0, 0, 0, 0, 0, 1, 2, 0 }, // Lightning + + /*Feather*/ { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Feather }; /** \brief Item Roulette for Kart @@ -776,6 +795,9 @@ static void K_KartGetItemResult(player_t *player, fixed_t getitem, boolean retro case 18: // Lightning player->kartstuff[k_lightning] = 1; break; + case 19: // Feather + player->kartstuff[k_feather] |= 1; + break; default: // Mushroom - Doing it here as a fail-safe if (getitem != 3) CONS_Printf("ERROR: P_KartGetItemResult - Item roulette gave bad item (%d), giving Mushroom instead.\n", getitem); @@ -917,6 +939,16 @@ static void K_KartItemRouletteByPosition(player_t *player, ticcmd_t *cmd) //} +static INT32 K_KartGetItemOdds(INT32 pos, INT32 itemnum) +{ + INT32 newodds = (K_KartItemOddsDistance_Retro[itemnum-1][pos]); + if ((cv_kartfrantic.value) && (itemnum == 1 || itemnum == 4 || itemnum == 5 || itemnum == 6 + || itemnum == 7 || itemnum == 8 || itemnum == 12 || itemnum == 13 || itemnum == 14 || itemnum == 15 + || itemnum == 16 || itemnum == 17 || itemnum == 18)) + newodds *= 2; + return newodds; +} + //{ SRB2kart Roulette Code - Distance Based, no waypoints static void K_KartItemRouletteByDistance(player_t *player, ticcmd_t *cmd) @@ -976,40 +1008,51 @@ static void K_KartItemRouletteByDistance(player_t *player, ticcmd_t *cmd) player->kartstuff[k_itemclose] = 0; // Reset the item window closer. - if (pingame == 1) useodds = 0; - else if (pdis <= distvar * 0) useodds = 1; // (64*14) * 0 = 0 - else if (pdis <= distvar * 1) useodds = 2; // (64*14) * 1 = 896 - else if (pdis <= distvar * 2) useodds = 3; // (64*14) * 2 = 1792 - else if (pdis <= distvar * 4) useodds = 4; // (64*14) * 4 = 3584 - else if (pdis <= distvar * 6) useodds = 5; // (64*14) * 6 = 5376 - else if (pdis <= distvar * 9) useodds = 6; // (64*14) * 9 = 8064 - else if (pdis <= distvar * 12) useodds = 7; // (64*14) * 12 = 10752 - else useodds = 8; + if (cv_kartfrantic.value) // Stupid items + { + pdis = (15*pdis/14); // multiply... + pdis += distvar; // set everyone back another place... + } + + if (gametype == GT_MATCH + || gametype == GT_TEAMMATCH + || gametype == GT_CTF) useodds = 0; // Battle Mode + else if (pingame == 1) useodds = 1; // Record Attack, or just alone + else if (pdis <= distvar * 0) useodds = 2; // (64*14) * 0 = 0 + else if (pdis <= distvar * 1) useodds = 3; // (64*14) * 1 = 896 + else if (pdis <= distvar * 2) useodds = 4; // (64*14) * 2 = 1792 + else if (pdis <= distvar * 4) useodds = 5; // (64*14) * 4 = 3584 + else if (pdis <= distvar * 6) useodds = 6; // (64*14) * 6 = 5376 + else if (pdis <= distvar * 9) useodds = 7; // (64*14) * 9 = 8064 + else if (pdis <= distvar * 12) useodds = 8; // (64*14) * 12 = 10752 + else useodds = 9; #define SETITEMRESULT(pos, itemnum) \ - for (chance = 0; chance < K_KartItemOddsDistance_Retro[itemnum-1][pos]; chance++) spawnchance[numchoices++] = itemnum + for (chance = 0; chance < K_KartGetItemOdds(pos, itemnum); chance++) \ + spawnchance[numchoices++] = itemnum // Check the game type to differentiate odds. //if (gametype == GT_RETRO) //{ - if (cv_magnet.value) SETITEMRESULT(useodds, 1); // Magnet - if (cv_boo.value) SETITEMRESULT(useodds, 2); // Boo - if (cv_mushroom.value) SETITEMRESULT(useodds, 3); // Mushroom - if (cv_mushroom.value) SETITEMRESULT(useodds, 4); // Triple Mushroom - if (cv_megashroom.value) SETITEMRESULT(useodds, 5); // Mega Mushroom - if (cv_goldshroom.value) SETITEMRESULT(useodds, 6); // Gold Mushroom - if (cv_star.value) SETITEMRESULT(useodds, 7); // Star - if (cv_triplebanana.value) SETITEMRESULT(useodds, 8); // Triple Banana - if (cv_fakeitem.value) SETITEMRESULT(useodds, 9); // Fake Item - if (cv_banana.value) SETITEMRESULT(useodds, 10); // Banana - if (cv_greenshell.value) SETITEMRESULT(useodds, 11); // Green Shell - if (cv_redshell.value) SETITEMRESULT(useodds, 12); // Red Shell - if (cv_triplegreenshell.value) SETITEMRESULT(useodds, 13); // Triple Green Shell - if (cv_bobomb.value) SETITEMRESULT(useodds, 14); // Bob-omb - if (cv_blueshell.value && pexiting == 0) SETITEMRESULT(useodds, 15); // Blue Shell - if (cv_fireflower.value) SETITEMRESULT(useodds, 16); // Fire Flower - if (cv_tripleredshell.value) SETITEMRESULT(useodds, 17); // Triple Red Shell - if (cv_lightning.value && pingame > pexiting) SETITEMRESULT(useodds, 18); // Lightning + if (cv_magnet.value) SETITEMRESULT(useodds, 1); // Magnet + if (cv_boo.value) SETITEMRESULT(useodds, 2); // Boo + if (cv_mushroom.value) SETITEMRESULT(useodds, 3); // Mushroom + if (cv_mushroom.value) SETITEMRESULT(useodds, 4); // Triple Mushroom + if (cv_megashroom.value && !player->kartstuff[k_poweritemtimer]) SETITEMRESULT(useodds, 5); // Mega Mushroom + if (cv_goldshroom.value) SETITEMRESULT(useodds, 6); // Gold Mushroom + if (cv_star.value && !player->kartstuff[k_poweritemtimer]) SETITEMRESULT(useodds, 7); // Star + if (cv_triplebanana.value) SETITEMRESULT(useodds, 8); // Triple Banana + if (cv_fakeitem.value) SETITEMRESULT(useodds, 9); // Fake Item + if (cv_banana.value) SETITEMRESULT(useodds, 10); // Banana + if (cv_greenshell.value) SETITEMRESULT(useodds, 11); // Green Shell + if (cv_redshell.value) SETITEMRESULT(useodds, 12); // Red Shell + if (cv_triplegreenshell.value) SETITEMRESULT(useodds, 13); // Triple Green Shell + if (cv_bobomb.value) SETITEMRESULT(useodds, 14); // Bob-omb + if (cv_blueshell.value && pexiting == 0) SETITEMRESULT(useodds, 15); // Blue Shell + if (cv_fireflower.value) SETITEMRESULT(useodds, 16); // Fire Flower + if (cv_tripleredshell.value) SETITEMRESULT(useodds, 17); // Triple Red Shell + if (cv_lightning.value && pingame > pexiting) SETITEMRESULT(useodds, 18); // Lightning + if (cv_feather.value) SETITEMRESULT(useodds, 19); // Feather prandom = P_RandomKey(numchoices); @@ -1039,84 +1082,34 @@ static void K_KartItemRouletteByDistance(player_t *player, ticcmd_t *cmd) //{ SRB2kart p_user.c Stuff -boolean K_IsTouching(mobj_t *mobj1, mobj_t *mobj2) +void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce) { - if (mobj1 == NULL || mobj2 == NULL) - return false; - fixed_t absx = abs(mobj1->x - mobj2->x); - fixed_t absy = abs(mobj1->y - mobj2->y); - fixed_t absz = abs(mobj1->z - mobj2->z); - - if (absx < 32*FRACUNIT && absy < 32*FRACUNIT && absz < 32*FRACUNIT) - return true; - else - return false; -} - -void K_SwapMomentum(mobj_t *mobj1, mobj_t *mobj2, boolean bounce) -{ - fixed_t newx, newy; mobj_t *fx; + fixed_t momdifx, momdify; + fixed_t distx, disty; + fixed_t dot, p; + fixed_t mass1, mass2; - if (mobj1 == NULL || mobj2 == NULL) + if (!mobj1 || !mobj2) + return; + + // Don't bump when you're being reborn + if ((mobj1->player && mobj1->player->playerstate != PST_LIVE) + || (mobj2->player && mobj2->player->playerstate != PST_LIVE)) return; - fixed_t meanX = (mobj1->momx + mobj2->momx) / 2; - fixed_t meanY = (mobj1->momy + mobj2->momy) / 2; - fixed_t deltaV1 = P_AproxDistance((mobj1->momx - meanX), (mobj1->momy - meanY)); - fixed_t deltaV2 = P_AproxDistance((mobj2->momx - meanX), (mobj2->momy - meanY)); - //fixed_t clashvolume = (deltaV1 / FRACUNIT) * 8; // In case you want to do a scaling bump sound volume. if (cv_collidesounds.value == 1) { S_StartSound(mobj1, cv_collidesoundnum.value); - //S_StartSound(mobj2, cv_collidesoundnum.value); } - fx = P_SpawnMobj((mobj1->x + mobj2->x)/2, (mobj1->y + mobj2->y)/2, (mobj1->z + mobj2->z)/2, MT_BUMP); + fx = P_SpawnMobj(mobj1->x/2 + mobj2->x/2, mobj1->y/2 + mobj2->y/2, mobj1->z/2 + mobj2->z/2, MT_BUMP); if (mobj1->eflags & MFE_VERTICALFLIP) fx->eflags |= MFE_VERTICALFLIP; else fx->eflags &= ~MFE_VERTICALFLIP; fx->scale = mobj1->scale; - - if (deltaV1 < (cv_collideminimum.value * FRACUNIT / 2)) - { - fixed_t a = 0; - if (deltaV1 != 0) - a = FixedDiv((cv_collideminimum.value * FRACUNIT / 2), deltaV1); - else if (deltaV2 != 0) - a = FixedDiv((cv_collideminimum.value * FRACUNIT / 2), deltaV2); - else - a = 0; - fixed_t deltax1 = (mobj1->momx - meanX); - fixed_t deltax2 = (mobj2->momx - meanX); - fixed_t deltay1 = (mobj1->momy - meanY); - fixed_t deltay2 = (mobj2->momy - meanY); - mobj1->momx = meanX + FixedMul(deltax1, a); - mobj1->momy = meanY + FixedMul(deltay1, a); - mobj2->momx = meanX + FixedMul(deltax2, a); - mobj2->momy = meanY + FixedMul(deltay2, a); - } - /* - if (mobj1->player && mobj2->player) // Weight is applicable if both are players - { - fixed_t m1w = 15 + mobj1->player->kartweight; - fixed_t m2w = 15 + mobj2->player->kartweight; - newx = FixedMul(mobj1->momx, FixedDiv(m1w*FRACUNIT, m2w*FRACUNIT)); - newy = FixedMul(mobj1->momy, FixedDiv(m1w*FRACUNIT, m2w*FRACUNIT)); - mobj1->momx = FixedMul(mobj2->momx, FixedDiv(m2w*FRACUNIT, m1w*FRACUNIT)); - mobj1->momy = FixedMul(mobj2->momy, FixedDiv(m2w*FRACUNIT, m1w*FRACUNIT)); - } - else*/ - //{ - newx = mobj1->momx; - newy = mobj1->momy; - mobj1->momx = mobj2->momx; - mobj1->momy = mobj2->momy; - //} - mobj2->momx = newx; - mobj2->momy = newy; if (bounce == true) // Perform a Goomba Bounce. mobj1->momz = -mobj1->momz; else @@ -1125,54 +1118,64 @@ void K_SwapMomentum(mobj_t *mobj1, mobj_t *mobj2, boolean bounce) mobj1->momz = mobj2->momz; mobj2->momz = newz; } -} -void K_KartBouncer(void) -{ - fixed_t i, j; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) - for (j = 0; j < MAXPLAYERS; j++) - players[i].collide[j] = false; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo) - && !players[i].kartstuff[k_growshrinktimer] - && !players[i].kartstuff[k_squishedtimer] - && !players[i].kartstuff[k_bootaketimer] - && !players[i].kartstuff[k_spinouttimer] - && !players[i].kartstuff[k_startimer]) - { - for (j = i+1; j < MAXPLAYERS; j++) - if (playeringame[j] && players[j].mo && !P_MobjWasRemoved(players[j].mo) - && !players[j].kartstuff[k_squishedtimer] - && !players[j].kartstuff[k_growshrinktimer] - && !players[j].kartstuff[k_bootaketimer] - && !players[j].kartstuff[k_spinouttimer] - && !players[j].kartstuff[k_startimer]) - { - if (players[j].mo == players[i].mo) - break; - if (K_IsTouching(players[i].mo, players[j].mo)) - { - if (!players[i].collide[j] && !players[j].collide[i]) - { - if (P_IsObjectOnGround(players[j].mo) && players[i].mo->momz < 0) - K_SwapMomentum(players[i].mo, players[j].mo, true); - else if (P_IsObjectOnGround(players[i].mo) && players[j].mo->momz < 0) - K_SwapMomentum(players[j].mo, players[i].mo, true); - else - K_SwapMomentum(players[i].mo, players[j].mo, false); - players[i].collide[j] = true; - players[j].collide[i] = true; - } - } - else - { - players[i].collide[j] = false; - players[j].collide[i] = false; - } - } - } + mass1 = mass2 = 5*FRACUNIT; + if (mobj1->player) + mass1 = (mobj1->player->kartweight)*FRACUNIT; + if (mobj2->player) + mass2 = (mobj2->player->kartweight)*FRACUNIT; + + momdifx = mobj1->momx - mobj2->momx; + momdify = mobj1->momy - mobj2->momy; + + // if the speed difference is less than this let's assume they're going proportionately faster from each other + if (P_AproxDistance(momdifx, momdify) < 25*FRACUNIT) + { + fixed_t momdiflength = P_AproxDistance(momdifx, momdify); + fixed_t normalisedx = FixedDiv(momdifx, momdiflength); + fixed_t normalisedy = FixedDiv(momdify, momdiflength); + momdifx = FixedMul(25*FRACUNIT, normalisedx); + momdify = FixedMul(25*FRACUNIT, normalisedy); + } + + distx = mobj1->x - mobj2->x; + disty = mobj1->y - mobj2->y; + + 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 + return; + } + + dot = FixedMul(momdifx, distx) + FixedMul(momdify, disty); + + if (dot >= 0) + { + // They're moving away from each other + return; + } + + p = FixedDiv(dot, FixedMul(distx, distx)+FixedMul(disty, disty)); + + mobj1->momx = mobj1->momx - FixedMul(FixedMul(FixedDiv(2*mass2, mass1 + mass2), p), distx); + mobj1->momy = mobj1->momy - FixedMul(FixedMul(FixedDiv(2*mass2, mass1 + mass2), p), disty); + + mobj2->momx = mobj2->momx - FixedMul(FixedMul(FixedDiv(2*mass1, mass1 + mass2), p), -distx); + mobj2->momy = mobj2->momy - FixedMul(FixedMul(FixedDiv(2*mass1, mass1 + mass2), p), -disty); + + // Because this is done during collision now, rmomx and rmomy need to be recalculated + // so that friction doesn't immediately decide to stop the player if they're at a standstill + if (mobj1->player) + { + mobj1->player->rmomx = mobj1->momx - mobj1->player->cmomx; + mobj1->player->rmomy = mobj1->momy - mobj1->player->cmomy; + } + + if (mobj2->player) + { + mobj2->player->rmomx = mobj2->momx - mobj2->player->cmomx; + mobj2->player->rmomy = mobj2->momy - mobj2->player->cmomy; + } } /** \brief Checks that the player is on an offroad subsector for realsies @@ -1387,8 +1390,16 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_spinouttimer]) player->kartstuff[k_spinouttimer]--; + else if (!cv_kartcomeback.value) + player->kartstuff[k_comebacktimer] = comebacktime; + else if (player->kartstuff[k_comebacktimer]) + { + player->kartstuff[k_comebacktimer]--; + if (player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer] <= 0) + player->kartstuff[k_comebackshowninfo] = 1; + } - if (player->kartstuff[k_spinout] == 0 && player->kartstuff[k_spinouttimer] == 0 && player->powers[pw_flashing] == flashingtics) + if (player->kartstuff[k_spinout] == 0 && player->kartstuff[k_spinouttimer] == 0 && player->powers[pw_flashing] == K_GetKartFlashing(player)) player->powers[pw_flashing]--; if (player->kartstuff[k_magnettimer]) @@ -1422,6 +1433,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) && player->kartstuff[k_goldshroomtimer]) player->kartstuff[k_goldshroomtimer]--; + if (player->kartstuff[k_bootimer]) + player->kartstuff[k_bootimer]--; + if (player->kartstuff[k_bootaketimer]) player->kartstuff[k_bootaketimer]--; @@ -1434,6 +1448,12 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_laserwisptimer]) player->kartstuff[k_laserwisptimer]--; + if (player->kartstuff[k_justbumped]) + player->kartstuff[k_justbumped]--; + + if (player->kartstuff[k_poweritemtimer]) + player->kartstuff[k_poweritemtimer]--; + if (player->kartstuff[k_lapanimation]) player->kartstuff[k_lapanimation]--; @@ -1449,7 +1469,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->mo->momz *= player->kartstuff[k_jmp]; player->kartstuff[k_jmp] = 0; } - */ + */ + + if (player->kartstuff[k_comebacktimer]) + player->kartstuff[k_comebackmode] = 0; + + if (P_IsObjectOnGround(player->mo) && !(player->mo->momz) + && player->kartstuff[k_feather] & 2) + player->kartstuff[k_feather] &= ~2; if (cmd->buttons & BT_JUMP) player->kartstuff[k_jmp] = 1; @@ -1479,6 +1506,16 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) S_StopSoundByID(player->mo, sfx_mega); // Stop it } + // AAAAAAND handle the SMK star alarm + if (player->mo->health > 0 && (player->mo->player->kartstuff[k_startimer] > 0 + || player->mo->player->kartstuff[k_growshrinktimer] > 0)) + { + if (leveltime % 13 == 0 && cv_kartstarsfx.value && !P_IsLocalPlayer(player)) + S_StartSound(player->mo, sfx_smkinv); + } + else if (S_SoundPlaying(player->mo, sfx_smkinv)) + S_StopSoundByID(player->mo, sfx_smkinv); + // Plays the music after the starting countdown. if (P_IsLocalPlayer(player) && leveltime == 158) S_ChangeMusicInternal(mapmusname, true); @@ -1526,7 +1563,7 @@ static fixed_t K_GetKartBoostPower(player_t *player, boolean speed) fixed_t boostvalue = 0; // Offroad is separate, it's difficult to factor it in with a variable value anyway. - if (!(player->kartstuff[k_startimer] || player->kartstuff[k_bootaketimer] || player->kartstuff[k_mushroomtimer]) + if (!(player->kartstuff[k_startimer] || player->kartstuff[k_bootimer] || player->kartstuff[k_mushroomtimer]) && player->kartstuff[k_offroad] >= 0 && speed) boostpower = FixedDiv(boostpower, player->kartstuff[k_offroad] + FRACUNIT); @@ -1565,7 +1602,7 @@ static fixed_t K_GetKartBoostPower(player_t *player, boolean speed) { // Mushroom if (speed) { - switch (cv_kartcc.value) + switch (K_GetKartCC()) { case 50: boostvalue = max(boostvalue, 53740+768); @@ -1592,9 +1629,10 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) fixed_t k_speed = 150; fixed_t g_cc = FRACUNIT; fixed_t xspd = 3072; // 4.6875 aka 3/64 + UINT8 kartspeed = player->kartspeed; fixed_t finalspeed; - switch (cv_kartcc.value) + switch (K_GetKartCC()) { case 50: g_cc = 53248 + xspd; // 50cc = 81.25 + 4.69 = 85.94% @@ -1607,7 +1645,10 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) break; } - k_speed += player->kartspeed*3; // 153 - 177 + if (gametype != GT_RACE && player->kartstuff[k_balloon] <= 0) + kartspeed = 1; + + k_speed += kartspeed*3; // 153 - 177 finalspeed = FixedMul(FixedMul(k_speed<<14, g_cc), player->mo->scale); @@ -1616,16 +1657,31 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) return finalspeed; } -static fixed_t K_GetKartAccel(player_t *player) +fixed_t K_GetKartAccel(player_t *player) { fixed_t k_accel = 32; // 36; + UINT8 kartspeed = player->kartspeed; - //k_accel += 3 * (9 - player->kartspeed); // 36 - 60 - k_accel += 4 * (9 - player->kartspeed); // 32 - 64 + if (gametype != GT_RACE && player->kartstuff[k_balloon] <= 0) + kartspeed = 1; + + //k_accel += 3 * (9 - kartspeed); // 36 - 60 + k_accel += 4 * (9 - kartspeed); // 32 - 64 return FixedMul(k_accel, K_GetKartBoostPower(player, false)); } +UINT16 K_GetKartFlashing(player_t *player) +{ + UINT16 tics = flashingtics; + if (gametype != GT_RACE) + { + tics *= 2; + //tics += (3*TICRATE/8) * (player->kartspeed-1); + } + return tics; +} + fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove) { fixed_t accelmax = 4000; @@ -1633,7 +1689,7 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove fixed_t p_speed = K_GetKartSpeed(player, true); fixed_t p_accel = K_GetKartAccel(player); - if (!onground) return 0; // If the player isn't on the ground, there is no change in speed + if (!onground && !(player->kartstuff[k_feather] & 2)) return 0; // If the player isn't on the ground, there is no change in speed // ACCELCODE!!!1!11! oldspeed = R_PointToDist2(0, 0, player->rmomx, player->rmomy); // FixedMul(P_AproxDistance(player->rmomx, player->rmomy), player->mo->scale); @@ -1666,10 +1722,11 @@ void K_SpinPlayer(player_t *player, mobj_t *source) return; if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinout] > 0) - || player->kartstuff[k_startimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootaketimer] > 0) + || player->kartstuff[k_startimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootimer] > 0 + || (gametype != GT_RACE && ((player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) return; - if (source && source->player && !source->player->kartstuff[k_sounds]) + if (source && source != player->mo && source->player && !source->player->kartstuff[k_sounds]) { S_StartSound(source, sfx_hitem); source->player->kartstuff[k_sounds] = 50; @@ -1678,6 +1735,23 @@ void K_SpinPlayer(player_t *player, mobj_t *source) player->kartstuff[k_mushroomtimer] = 0; player->kartstuff[k_driftboost] = 0; + if (gametype != GT_RACE) + { + if (player->kartstuff[k_balloon] > 0) + { + if (player->kartstuff[k_balloon] == 1) + CONS_Printf(M_GetText("%s lost all of their balloons!\n"), player_names[player-players]); + player->kartstuff[k_balloon]--; + } + + if (source && source->player && player != source->player) + P_AddPlayerScore(source->player, 1); + + K_CheckBalloons(); + } + + player->kartstuff[k_comebacktimer] = comebacktime; + if (player->kartstuff[k_spinouttype] <= 0) { if (player->kartstuff[k_spinouttype] == 0) @@ -1694,7 +1768,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source) else player->kartstuff[k_spinouttimer] = 1*TICRATE; // ? Whipeout - player->powers[pw_flashing] = flashingtics; + player->powers[pw_flashing] = K_GetKartFlashing(player); player->kartstuff[k_spinout] = player->kartstuff[k_spinouttimer]; @@ -1708,20 +1782,37 @@ void K_SpinPlayer(player_t *player, mobj_t *source) void K_SquishPlayer(player_t *player, mobj_t *source) { - (void) source; if (player->health <= 0) return; - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 - || player->kartstuff[k_startimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootaketimer] > 0) + if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_startimer] > 0 + || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootimer] > 0 + || (gametype != GT_RACE && ((player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) return; player->kartstuff[k_mushroomtimer] = 0; player->kartstuff[k_driftboost] = 0; + if (gametype != GT_RACE) + { + if (player->kartstuff[k_balloon] > 0) + { + if (player->kartstuff[k_balloon] == 1) + CONS_Printf(M_GetText("%s lost all of their balloons!\n"), player_names[player-players]); + player->kartstuff[k_balloon]--; + } + + if (source && source->player && player != source->player) + P_AddPlayerScore(source->player, 1); + + K_CheckBalloons(); + } + + player->kartstuff[k_comebacktimer] = comebacktime; + player->kartstuff[k_squishedtimer] = 1*TICRATE; - player->powers[pw_flashing] = flashingtics; + player->powers[pw_flashing] = K_GetKartFlashing(player); player->mo->flags |= MF_NOCLIP; @@ -1735,12 +1826,12 @@ void K_SquishPlayer(player_t *player, mobj_t *source) 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) source; if (player->health <= 0) return; if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinout] > 0) - || player->kartstuff[k_startimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootaketimer] > 0) + || player->kartstuff[k_startimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootimer] > 0 + || (gametype != GT_RACE && ((player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) return; player->mo->momz = 18*FRACUNIT; @@ -1749,11 +1840,28 @@ void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we ju player->kartstuff[k_mushroomtimer] = 0; player->kartstuff[k_driftboost] = 0; + if (gametype != GT_RACE) + { + if (player->kartstuff[k_balloon] > 0) + { + if (player->kartstuff[k_balloon] == 1) + CONS_Printf(M_GetText("%s lost all of their balloons!\n"), player_names[player-players]); + player->kartstuff[k_balloon]--; + } + + if (source && source->player && player != source->player) + P_AddPlayerScore(source->player, 1); + + K_CheckBalloons(); + } + + player->kartstuff[k_comebacktimer] = comebacktime; + player->kartstuff[k_spinouttype] = 1; player->kartstuff[k_spinouttimer] = 2*TICRATE+(TICRATE/2); player->kartstuff[k_spinout] = player->kartstuff[k_spinouttimer]; - player->powers[pw_flashing] = flashingtics; + player->powers[pw_flashing] = K_GetKartFlashing(player); if (player->mo->state != &states[S_KART_SPIN]) P_SetPlayerMobjState(player->mo, S_KART_SPIN); @@ -1771,7 +1879,71 @@ void K_ExplodePlayer(player_t *player, mobj_t *source) // A bit of a hack, we ju return; } -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) +void K_StealBalloon(player_t *player, player_t *victim, boolean force) +{ + INT32 newballoon; + angle_t newangle, diff; + fixed_t newx, newy; + mobj_t *newmo; + + if (gametype == GT_RACE) + return; + + if (player->health <= 0 || victim->health <= 0) + return; + + if (force) + ; + else + { + if (victim->kartstuff[k_balloon] <= 0) // || player->kartstuff[k_balloon] >= cv_kartballoons.value+2 + return; + + if ((player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinout] > 0) + || player->kartstuff[k_startimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_bootimer] > 0 + || (player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer])) + || (victim->powers[pw_flashing] > 0 || victim->kartstuff[k_squishedtimer] > 0 || (victim->kartstuff[k_spinouttimer] > 0 && victim->kartstuff[k_spinout] > 0) + || victim->kartstuff[k_startimer] > 0 || victim->kartstuff[k_growshrinktimer] > 0 || victim->kartstuff[k_bootimer] > 0)) + return; + } + + if (player->kartstuff[k_balloon] <= 0) + CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]); + else + CONS_Printf(M_GetText("%s stole a balloon from %s!\n"), player_names[player-players], player_names[victim-players]); + + newballoon = player->kartstuff[k_balloon]; + if (newballoon <= 1) + diff = 0; + else + diff = FixedAngle(360*FRACUNIT/newballoon); + + newangle = player->mo->angle; + newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); + newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, 64*FRACUNIT); + + newmo = P_SpawnMobj(newx, newy, player->mo->z, MT_BATTLEBALLOON); + newmo->threshold = newballoon; + P_SetTarget(&newmo->tracer, victim->mo); + P_SetTarget(&newmo->target, player->mo); + newmo->angle = (diff * (newballoon-1)); + newmo->color = victim->skincolor; + + if (newballoon+1 < 2) + P_SetMobjState(newmo, S_BATTLEBALLOON3); + else if (newballoon+1 < 3) + P_SetMobjState(newmo, S_BATTLEBALLOON2); + else + P_SetMobjState(newmo, S_BATTLEBALLOON1); + + player->kartstuff[k_balloon]++; + player->kartstuff[k_comebackpoints] = 0; + player->powers[pw_flashing] = K_GetKartFlashing(player); + return; +} + +// source is the mobj that originally threw the bomb that exploded etc. +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) { mobj_t *mobj; mobj_t *ghost = NULL; @@ -1851,6 +2023,7 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 mobj->flags |= MF_NOCLIPTHING; mobj->flags &= ~MF_SPECIAL; + P_SetTarget(&mobj->target, source); } } @@ -1871,7 +2044,12 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t angle x = source->x + source->momx; y = source->y + source->momy; - z = source->z + source->height/3; + z = source->z; // spawn on the ground please + + if (P_MobjFlip(source) < 0) + { + z = source->z+source->height - mobjinfo[type].height; + } th = P_SpawnMobj(x, y, z, type); @@ -1891,6 +2069,21 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t angle P_SetTarget(&th->target, source); + if (P_IsObjectOnGround(source)) + { + // floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn + // This should set it for FOFs + P_TeleportMove(th, th->x, th->y, th->z); + // spawn on the ground if the player is on the ground + if (P_MobjFlip(source) < 0) + { + th->z = th->ceilingz - th->height; + th->eflags |= MFE_VERTICALFLIP; + } + else + th->z = th->floorz; + } + th->angle = an; th->momx = FixedMul(speed, FINECOSINE(an>>ANGLETOFINESHIFT)); th->momy = FixedMul(speed, FINESINE(an>>ANGLETOFINESHIFT)); @@ -1930,7 +2123,7 @@ void K_SpawnDriftTrail(player_t *player) for (i = 0; i < 2; i++) { - if (player->kartstuff[k_bootaketimer] != 0) + if (player->kartstuff[k_bootimer] != 0 || (gametype != GT_RACE && player->kartstuff[k_balloon] <= 0 && player->kartstuff[k_comebacktimer])) continue; newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale)); @@ -1982,16 +2175,16 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map return NULL; // Figure out projectile speed by CC - switch (cv_kartcc.value) + switch (K_GetKartCC()) { case 50: - PROJSPEED = 85*FRACUNIT; // Avg Speed is 34 + PROJSPEED = 68*FRACUNIT; // Avg Speed is 34 break; case 150: - PROJSPEED = 120*FRACUNIT; // Avg Speed is 48 + PROJSPEED = 96*FRACUNIT; // Avg Speed is 48 break; default: - PROJSPEED = 102*FRACUNIT+FRACUNIT/2; // Avg Speed is 41 + PROJSPEED = 82*FRACUNIT; // Avg Speed is 41 break; } @@ -2016,51 +2209,23 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map { if (mapthing == MT_FIREBALL) // Messy { - mobj_t *mo2; - mobj_t *mo3; - mobj_t *mo4; - mobj_t *mo5; if (dir == -1) { // Shoot backward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x06000000, 0, PROJSPEED/2); - mo2 = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x03000000, 0, PROJSPEED/2); - mo3 = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/2); - mo4 = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x03000000, 0, PROJSPEED/2); - mo5 = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x06000000, 0, PROJSPEED/2); - - if (mo) - { - if (player->mo->eflags & MFE_VERTICALFLIP) - { - mo->eflags |= MFE_VERTICALFLIP; - mo2->eflags |= MFE_VERTICALFLIP; - mo3->eflags |= MFE_VERTICALFLIP; - mo4->eflags |= MFE_VERTICALFLIP; - mo5->eflags |= MFE_VERTICALFLIP; - } - } + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x06000000, 0, PROJSPEED/2); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 - 0x03000000, 0, PROJSPEED/2); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/2); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x03000000, 0, PROJSPEED/2); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180 + 0x06000000, 0, PROJSPEED/2); } else { // Shoot forward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle - 0x06000000, 0, PROJSPEED); - mo2 = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle - 0x03000000, 0, PROJSPEED); - mo3 = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle, 0, PROJSPEED); - mo4 = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + 0x03000000, 0, PROJSPEED); - mo5 = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + 0x06000000, 0, PROJSPEED); - - if (mo) - { - if (player->mo->eflags & MFE_VERTICALFLIP) - { - mo->eflags |= MFE_VERTICALFLIP; - mo2->eflags |= MFE_VERTICALFLIP; - mo3->eflags |= MFE_VERTICALFLIP; - mo4->eflags |= MFE_VERTICALFLIP; - mo5->eflags |= MFE_VERTICALFLIP; - } - } + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle - 0x06000000, 0, PROJSPEED); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle - 0x03000000, 0, PROJSPEED); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle, 0, PROJSPEED); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + 0x03000000, 0, PROJSPEED); + K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + 0x06000000, 0, PROJSPEED); } } else // Shells @@ -2069,23 +2234,11 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map { // Shoot backward mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + ANGLE_180, 0, PROJSPEED/2); - - if (mo) - { - if (player->mo->eflags & MFE_VERTICALFLIP) - mo->eflags |= MFE_VERTICALFLIP; - } } else { // Shoot forward mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle, 0, PROJSPEED + player->speed); - - if (mo) - { - if (player->mo->eflags & MFE_VERTICALFLIP) - mo->eflags |= MFE_VERTICALFLIP; - } } } } @@ -2094,10 +2247,9 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map if (dir == 1 || dir == 2) { // Shoot forward - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + 80*FRACUNIT, mapthing); + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, mapthing); mo->threshold = 10; - P_SetTarget(&mo->target, player->mo); S_StartSound(player->mo, mo->info->seesound); @@ -2108,41 +2260,61 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map INT32 HEIGHT; if (dir == 2) - HEIGHT = 16*FRACUNIT + player->mo->momz; + HEIGHT = 40*FRACUNIT + player->mo->momz; else - HEIGHT = 8*FRACUNIT + player->mo->momz; + HEIGHT = 30*FRACUNIT + player->mo->momz; - if (HEIGHT > 64*FRACUNIT) - HEIGHT = 64*FRACUNIT; - - mo->momx = FixedMul(FINECOSINE(fa), PROJSPEED); - mo->momy = FixedMul(FINESINE(fa), PROJSPEED); - mo->momz = HEIGHT; + mo->momx = player->mo->momx + FixedMul(FINECOSINE(fa), PROJSPEED); + mo->momy = player->mo->momy + FixedMul(FINESINE(fa), PROJSPEED); + mo->momz = P_MobjFlip(player->mo) * HEIGHT; if (player->mo->eflags & MFE_VERTICALFLIP) mo->eflags |= MFE_VERTICALFLIP; } - mobj_t *throwmo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + 80*FRACUNIT, MT_FIREDITEM); + mobj_t *throwmo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_FIREDITEM); P_SetTarget(&throwmo->target, player->mo); throwmo->movecount = 0; // above player } else { + fixed_t dropradius = FixedHypot(player->mo->radius, player->mo->radius) + FixedHypot(mobjinfo[mapthing].radius, mobjinfo[mapthing].radius); + // Drop it directly behind you. newangle = player->mo->angle; - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, mapthing); + newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, dropradius); + newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, dropradius); + + mo = P_SpawnMobj(newx, newy, player->mo->z, mapthing); + + if (P_MobjFlip(player->mo) < 0) + mo->z = player->mo->z + player->mo->height - mo->height; mo->threshold = 10; - P_SetTarget(&mo->target, player->mo); - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, player->mo->radius*2 + mo->radius*3); - newy = player->mo->y + P_ReturnThrustY(player->mo, newangle + ANGLE_180, player->mo->radius*2 + mo->radius*3); + if (P_IsObjectOnGround(player->mo)) + { + // floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn + // This should set it for FOFs + P_TeleportMove(mo, mo->x, mo->y, mo->z); - mo->x = newx; - mo->y = newy; + if (P_MobjFlip(mo) > 0) + { + if (mo->floorz > mo->target->z - mo->height) + { + mo->z = mo->floorz; + } + } + else + { + if (mo->ceilingz < mo->target->z + mo->target->height + mo->height) + { + mo->z = mo->ceilingz - mo->height; + } + } + } if (mo) { @@ -2168,14 +2340,15 @@ static void K_DoBooSteal(player_t *player) INT32 stealplayer = 0; // The player that's getting stolen from INT32 prandom = 0; - if (!multiplayer) + if (!multiplayer || (gametype == GT_MATCH && player->kartstuff[k_balloon] <= 0)) return; for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE - && !players[i].exiting && !players[i].powers[pw_super] && !((netgame || multiplayer) && players[i].spectator) - && players[i].kartstuff[k_position] < player->kartstuff[k_position] && player != &players[i] + && player != &players[i] && !players[i].exiting && !players[i].powers[pw_super] && !(players[i].spectator) + && ((gametype == GT_RACE && players[i].kartstuff[k_position] < player->kartstuff[k_position]) + || (gametype != GT_RACE && players[i].kartstuff[k_balloon] > 0)) && (players[i].kartstuff[k_star] || players[i].kartstuff[k_mushroom] || players[i].kartstuff[k_goldshroom] || players[i].kartstuff[k_megashroom] || players[i].kartstuff[k_lightning] || players[i].kartstuff[k_blueshell] @@ -2194,7 +2367,8 @@ static void K_DoBooSteal(player_t *player) if (player->kartstuff[k_position] == 1 || numplayers < 1) // No-one can be stolen from? Get longer invisibility for nothing { - player->kartstuff[k_bootaketimer] = bootime; + player->kartstuff[k_bootimer] = bootime; + player->kartstuff[k_bootaketimer] = boostealtime; player->kartstuff[k_boo] = 0; return; } @@ -2211,9 +2385,10 @@ static void K_DoBooSteal(player_t *player) { stealplayer -= 1; // stealplayer is +1 so we know if it found there actually WAS a player - player->kartstuff[k_bootaketimer] = bootime; + player->kartstuff[k_bootimer] = bootime; + player->kartstuff[k_bootaketimer] = boostealtime; player->kartstuff[k_boo] = 0; - players[stealplayer].kartstuff[k_boostolentimer] = bootime; + players[stealplayer].kartstuff[k_boostolentimer] = boostealtime; if (players[stealplayer].kartstuff[k_star]) { @@ -2348,6 +2523,73 @@ static void K_DoLightning(player_t *player, boolean bluelightning) player->kartstuff[k_sounds] = 50; } +void K_DoBouncePad(mobj_t *mo, fixed_t vertispeed) +{ + if (mo->player && mo->player->spectator) + return; + + if (mo->eflags & MFE_SPRUNG) + return; + +#ifdef ESLOPE + mo->standingslope = NULL; +#endif + + mo->eflags |= MFE_SPRUNG; + + if (mo->eflags & MFE_VERTICALFLIP) + vertispeed *= -1; + + if (vertispeed == 0) + { + fixed_t thrust; + + if (mo->player) + { + thrust = 3*mo->player->speed/2; + if (thrust < 48<momx,mo->momy); + if (thrust < 8< 72<momz = FixedMul(FINESINE(ANGLE_22h>>ANGLETOFINESHIFT), thrust); + } + else + mo->momz = FixedMul(vertispeed, mo->scale); + + S_StartSound(mo, sfx_boing); +} + +// Returns false if this player being placed here causes them to collide with any other player +// Used in g_game.c for match etc. respawning +// This does not check along the z because the z is not correctly set for the spawnee at this point +boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y) +{ + INT32 i; + fixed_t p1radius = players[playernum].mo->radius; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playernum == i || !playeringame[i] || players[i].spectator || !players[i].mo || players[i].mo->health <= 0 + || players[i].playerstate != PST_LIVE || (players[i].mo->flags & MF_NOCLIP) || (players[i].mo->flags & MF_NOCLIPTHING)) + continue; + + if (abs(x - players[i].mo->x) < (p1radius + players[i].mo->radius) + && abs(y - players[i].mo->y) < (p1radius + players[i].mo->radius)) + { + return false; + } + } + return true; +} + // countersteer is how strong the controls are telling us we are turning // turndir is the direction the controls are telling us to turn, -1 if turning right and 1 if turning left static INT16 K_GetKartDriftValue(player_t *player, fixed_t countersteer) @@ -2402,9 +2644,15 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) static void K_KartDrift(player_t *player, boolean onground) { + UINT8 kartspeed = player->kartspeed; + fixed_t dsone, dstwo; + + if (gametype != GT_RACE && player->kartstuff[k_balloon] <= 0) + kartspeed = 1; + // IF YOU CHANGE THESE: MAKE SURE YOU UPDATE THE SAME VALUES IN p_mobjc, "case MT_DRIFT:" - fixed_t dsone = 26*4 + player->kartspeed*2 + (9 - player->kartweight); - fixed_t dstwo = dsone*2; + dsone = 26*4 + kartspeed*2 + (9 - player->kartweight); + dstwo = dsone*2; // Drifting is actually straffing + automatic turning. // Holding the Jump button will enable drifting. @@ -2626,6 +2874,63 @@ static boolean K_CheckForHoldItem(player_t *player) ) return true; return false; } + +static void K_StripItems(player_t *player) +{ + if ( player->kartstuff[k_kitchensink] + || player->kartstuff[k_feather] & 1 + || player->kartstuff[k_lightning] + || player->kartstuff[k_tripleredshell] + || player->kartstuff[k_fireflower] + || player->kartstuff[k_blueshell] + || player->kartstuff[k_bobomb] + || player->kartstuff[k_triplegreenshell] + || player->kartstuff[k_redshell] + || player->kartstuff[k_greenshell] + || player->kartstuff[k_banana] + || player->kartstuff[k_fakeitem] & 2 + || player->kartstuff[k_triplebanana] + || player->kartstuff[k_star] + || player->kartstuff[k_goldshroom] + || player->kartstuff[k_megashroom] + || player->kartstuff[k_mushroom] + || player->kartstuff[k_boo] + || player->kartstuff[k_magnet] + || player->kartstuff[k_bootimer] + || player->kartstuff[k_bootaketimer] + || player->kartstuff[k_boostolentimer] + || player->kartstuff[k_goldshroomtimer] + || player->kartstuff[k_growshrinktimer] + || player->kartstuff[k_itemroulette] + ) player->kartstuff[k_itemclose] = 10; + player->kartstuff[k_kitchensink] = 0; + player->kartstuff[k_feather] = 0; + player->kartstuff[k_lightning] = 0; + player->kartstuff[k_tripleredshell] = 0; + player->kartstuff[k_fireflower] = 0; + player->kartstuff[k_blueshell] = 0; + player->kartstuff[k_bobomb] = 0; + player->kartstuff[k_triplegreenshell] = 0; + player->kartstuff[k_redshell] = 0; + player->kartstuff[k_greenshell] = 0; + player->kartstuff[k_banana] = 0; + player->kartstuff[k_fakeitem] = 0; + player->kartstuff[k_triplebanana] = 0; + player->kartstuff[k_star] = 0; + player->kartstuff[k_goldshroom] = 0; + player->kartstuff[k_megashroom] = 0; + player->kartstuff[k_mushroom] = 0; + player->kartstuff[k_boo] = 0; + player->kartstuff[k_magnet] = 0; + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_bootimer] = 0; + player->kartstuff[k_bootaketimer] = 0; + player->kartstuff[k_boostolentimer] = 0; + player->kartstuff[k_goldshroomtimer] = 0; + player->kartstuff[k_growshrinktimer] = 0; + player->kartstuff[k_magnettimer] = 0; + player->kartstuff[k_startimer] = 0; +} // // K_MoveKartPlayer // @@ -2636,7 +2941,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) boolean HOLDING_ITEM = K_CheckForHoldItem(player); boolean NO_BOO = (player->kartstuff[k_boostolentimer] == 0 && player->kartstuff[k_bootaketimer] == 0); - K_KartUpdatePosition(player); + if (gametype == GT_RACE) + K_KartUpdatePosition(player); // Position Taunt // If you were behind someone but just passed them, taunt at them! @@ -2728,11 +3034,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (P_IsLocalPlayer(player) && !player->exiting) S_ChangeMusicInternal("minvnc", true); - if (!P_IsLocalPlayer(player)) + if (!cv_kartstarsfx.value && !P_IsLocalPlayer(player)) S_StartSound(player->mo, sfx_star); player->kartstuff[k_startimer] = itemtime; // Activate it K_PlayTauntSound(player->mo); player->kartstuff[k_star] = 0; + if (gametype != GT_RACE) + player->kartstuff[k_poweritemtimer] = 10*TICRATE; player->kartstuff[k_itemclose] = 10; player->pflags |= PF_ATTACKDOWN; } @@ -3041,13 +3349,15 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { if (P_IsLocalPlayer(player) && !player->exiting) S_ChangeMusicInternal("mega", true); - if (!P_IsLocalPlayer(player)) + if (!cv_kartstarsfx.value && !P_IsLocalPlayer(player)) S_StartSound(player->mo, sfx_mega); K_PlayTauntSound(player->mo); player->kartstuff[k_growshrinktimer] = itemtime + TICRATE*2; S_StartSound(player->mo, sfx_mario3); player->pflags |= PF_ATTACKDOWN; player->kartstuff[k_megashroom] = 0; + if (gametype != GT_RACE) + player->kartstuff[k_poweritemtimer] = 10*TICRATE; player->kartstuff[k_itemclose] = 10; } // Boo @@ -3064,6 +3374,18 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->pflags |= PF_ATTACKDOWN; player->kartstuff[k_magnet] = 0; } + // Feather + else if (ATTACK_IS_DOWN && !HOLDING_ITEM && player->kartstuff[k_feather] & 1 && NO_BOO) + { + K_PlayTauntSound(player->mo); + K_DoBouncePad(player->mo, 32<pflags |= PF_ATTACKDOWN; + player->kartstuff[k_feather] |= 2; + player->kartstuff[k_feather] &= ~1; + + player->kartstuff[k_itemclose] = 10; + } // Mushroom Boost if (((player->kartstuff[k_mushroomtimer] > 0 && player->kartstuff[k_boosting] == 0) @@ -3097,11 +3419,16 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->kartstuff[k_growshrinktimer] == 26) S_StartSound(player->mo, sfx_mario8); - if (player->kartstuff[k_bootaketimer] > 0) + if ((gametype != GT_RACE) + && (player->kartstuff[k_star] || player->kartstuff[k_megashroom] + || player->kartstuff[k_startimer] || player->kartstuff[k_growshrinktimer] > 0)) + player->kartstuff[k_poweritemtimer] = 10*TICRATE; + + if (player->kartstuff[k_bootimer] > 0) { if ((player == &players[displayplayer] || (splitscreen && player == &players[secondarydisplayplayer])) || (!(player == &players[displayplayer] || (splitscreen && player == &players[secondarydisplayplayer])) - && (player->kartstuff[k_bootaketimer] < 1*TICRATE/2 || player->kartstuff[k_bootaketimer] > bootime-(1*TICRATE/2)))) + && (player->kartstuff[k_bootimer] < 1*TICRATE/2 || player->kartstuff[k_bootimer] > bootime-(1*TICRATE/2)))) { if (leveltime & 1) player->mo->flags2 |= MF2_DONTDRAW; @@ -3111,12 +3438,45 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else player->mo->flags2 |= MF2_DONTDRAW; - player->powers[pw_flashing] = player->kartstuff[k_bootaketimer]; // We'll do this for now, let's people know about the invisible people through subtle hints + player->powers[pw_flashing] = player->kartstuff[k_bootimer]; // We'll do this for now, let's people know about the invisible people through subtle hints } - else if (player->kartstuff[k_bootaketimer] == 0) + else if (player->kartstuff[k_bootimer] == 0) { player->mo->flags2 &= ~MF2_DONTDRAW; } + + if (gametype != GT_RACE && player->kartstuff[k_balloon] <= 0) // dead in match? you da bomb + { + K_StripItems(player); + player->mo->flags2 |= MF2_SHADOW; + + if (!(player->mo->tracer)) + player->mo->tracer = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_OVERLAY); + + P_SetTarget(&player->mo->tracer->target, player->mo); + P_SetMobjState(player->mo->tracer, S_PLAYERBOMB); + player->mo->tracer->color = player->mo->color; + + if (player->kartstuff[k_comebacktimer] > 0) + { + if (player->kartstuff[k_comebacktimer] < TICRATE && (leveltime & 1)) + player->mo->tracer->flags2 &= ~MF2_DONTDRAW; + else + player->mo->tracer->flags2 |= MF2_DONTDRAW; + + player->powers[pw_flashing] = player->kartstuff[k_comebacktimer]; + } + else if (player->kartstuff[k_comebackmode] != 0) + player->mo->tracer->flags2 |= MF2_DONTDRAW; + else + player->mo->tracer->flags2 &= ~MF2_DONTDRAW; + } + else if (gametype == GT_RACE || player->kartstuff[k_balloon] > 0) + { + player->mo->flags2 &= ~MF2_SHADOW; + if (player->mo->tracer && player->mo->tracer->state == &states[S_PLAYERBOMB]) + P_RemoveMobj(player->mo->tracer); + } } if (player->kartstuff[k_growshrinktimer] > 1) @@ -3124,9 +3484,28 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Friction if (player->speed > 0 && cmd->forwardmove == 0 && player->mo->friction == 59392) - player->mo->friction += 4608; + player->mo->friction += 4608; if (player->speed > 0 && cmd->forwardmove < 0 && player->mo->friction == 59392) - player->mo->friction += 1608; + player->mo->friction += 1608; + if (gametype != GT_RACE && player->kartstuff[k_balloon] <= 0) + { + player->mo->friction += 1228; + + if (player->mo->friction > FRACUNIT) + player->mo->friction = FRACUNIT; + if (player->mo->friction < 0) + player->mo->friction = 0; + + player->mo->movefactor = FixedDiv(ORIG_FRICTION, player->mo->friction); + + if (player->mo->movefactor < FRACUNIT) + player->mo->movefactor = 19*player->mo->movefactor - 18*FRACUNIT; + else + player->mo->movefactor = FRACUNIT; //player->mo->movefactor = ((player->mo->friction - 0xDB34)*(0xA))/0x80; + + if (player->mo->movefactor < 32) + player->mo->movefactor = 32; + } K_KartDrift(player, onground); @@ -3187,6 +3566,56 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } } +void K_CheckBalloons(void) +{ + UINT8 i; + UINT8 numingame = 0; + INT8 winnernum = -1; + +// Set to 1 if you need to test comeback in splitscreen +#if 0 + return; +#endif + + if (!(multiplayer || netgame)) + return; + + if (gametype == GT_RACE) + return; + + if (gameaction == ga_completed) + return; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) // not even in-game + continue; + + if (players[i].exiting) // we're already exiting! stop! + return; + + numingame++; + + if (players[i].kartstuff[k_balloon] <= 0) // if you don't have any balloons, you're probably not a winner + continue; + else if (winnernum > -1) // TWO winners? that's dumb :V + return; + winnernum = i; + } + + if (numingame <= 1) + return; + + if (playeringame[winnernum]) + { + P_AddPlayerScore(&players[winnernum], numingame); + CONS_Printf(M_GetText("%s recieved %d points for winning!\n"), player_names[winnernum], numingame); // numingame/2 == 1 ? "" : "s" + } + + for (i = 0; i < MAXPLAYERS; i++) + P_DoPlayerExit(&players[i]); +} + //} //{ SRB2kart HUD Code @@ -3202,14 +3631,23 @@ static patch_t *kp_timesticker; static patch_t *kp_timestickerwide; static patch_t *kp_lapsticker; static patch_t *kp_lapstickernarrow; +static patch_t *kp_balloonsticker; +static patch_t *kp_balloonstickerwide; +static patch_t *kp_karmasticker; +static patch_t *kp_timeoutsticker; static patch_t *kp_lakitustart[NUMLAKIFRAMES]; static patch_t *kp_lakitulaps[17]; static patch_t *kp_positionnum[NUMPOSNUMS][NUMPOSFRAMES]; +static patch_t *kp_winnernum[NUMPOSFRAMES]; static patch_t *kp_facenull; static patch_t *kp_facefirst; static patch_t *kp_facesecond; static patch_t *kp_facethird; static patch_t *kp_facefourth; +static patch_t *kp_battlewin; +static patch_t *kp_battlelose; +static patch_t *kp_battlewait; +static patch_t *kp_battleinfo; static patch_t *kp_magnet; static patch_t *kp_boo; static patch_t *kp_boosteal; @@ -3230,6 +3668,7 @@ static patch_t *kp_blueshell; static patch_t *kp_fireflower; static patch_t *kp_tripleredshell; static patch_t *kp_lightning; +static patch_t *kp_feather; static patch_t *kp_kitchensink; static patch_t *kp_itemused1; static patch_t *kp_itemused2; @@ -3245,6 +3684,12 @@ static patch_t *kp_triplegreenshellicon; static patch_t *kp_singleredshellicon; static patch_t *kp_doubleredshellicon; static patch_t *kp_tripleredshellicon; +static patch_t *kp_check; +static patch_t *kp_checkw; +static patch_t *kp_checkstar; +static patch_t *kp_checkstarw; +static patch_t *kp_checkmega; +static patch_t *kp_checkmegaw; /* static patch_t *kp_neonoitem; static patch_t *kp_electroshield; @@ -3289,6 +3734,10 @@ void K_LoadKartHUDGraphics(void) kp_timestickerwide = W_CachePatchName("K_STTIMW", PU_HUDGFX); kp_lapsticker = W_CachePatchName("K_STLAPS", PU_HUDGFX); kp_lapstickernarrow = W_CachePatchName("K_STLAPN", PU_HUDGFX); + kp_balloonsticker = W_CachePatchName("K_STBALN", PU_HUDGFX); + kp_balloonstickerwide = W_CachePatchName("K_STBALW", PU_HUDGFX); + kp_karmasticker = W_CachePatchName("K_STKARM", PU_HUDGFX); + kp_timeoutsticker = W_CachePatchName("K_STTOUT", PU_HUDGFX); // Lakitu Start-up Frames kp_lakitustart[0] = W_CachePatchName("K_LAKISA", PU_HUDGFX); @@ -3334,12 +3783,25 @@ void K_LoadKartHUDGraphics(void) kp_positionnum[i][j] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } } + + for (i = 0; i < NUMPOSFRAMES; i++) + { + sprintf(buffer, "K_POSNW%d", i); + kp_winnernum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + } + kp_facenull = W_CachePatchName("K_PFACE0", PU_HUDGFX); kp_facefirst = W_CachePatchName("K_PFACE1", PU_HUDGFX); kp_facesecond = W_CachePatchName("K_PFACE2", PU_HUDGFX); kp_facethird = W_CachePatchName("K_PFACE3", PU_HUDGFX); kp_facefourth = W_CachePatchName("K_PFACE4", PU_HUDGFX); + // Battle graphics + kp_battlewin = W_CachePatchName("K_BWIN", PU_HUDGFX); + kp_battlelose = W_CachePatchName("K_BLOSE", PU_HUDGFX); + kp_battlewait = W_CachePatchName("K_BWAIT", PU_HUDGFX); + kp_battleinfo = W_CachePatchName("K_BINFO", PU_HUDGFX); + // Kart Item Windows kp_magnet = W_CachePatchName("K_ITMAGN", PU_HUDGFX); kp_boo = W_CachePatchName("K_ITBOO1", PU_HUDGFX); @@ -3361,6 +3823,7 @@ void K_LoadKartHUDGraphics(void) kp_fireflower = W_CachePatchName("K_ITFIRE", PU_HUDGFX); kp_tripleredshell = W_CachePatchName("K_ITTRED", PU_HUDGFX); kp_lightning = W_CachePatchName("K_ITLIGH", PU_HUDGFX); + kp_feather = W_CachePatchName("K_ITFETH", PU_HUDGFX); kp_kitchensink = W_CachePatchName("K_ITSINK", PU_HUDGFX); // Item-used - Closing the item window after an item is used @@ -3381,6 +3844,14 @@ void K_LoadKartHUDGraphics(void) kp_doubleredshellicon = W_CachePatchName("K_TRRED2", PU_HUDGFX); kp_tripleredshellicon = W_CachePatchName("K_TRRED3", PU_HUDGFX); + // CHECK indicators + kp_check = W_CachePatchName("K_CHECK1", PU_HUDGFX); + kp_checkw = W_CachePatchName("K_CHECK2", PU_HUDGFX); + kp_checkstar = W_CachePatchName("K_CHECK3", PU_HUDGFX); + kp_checkstarw = W_CachePatchName("K_CHECK4", PU_HUDGFX); + kp_checkmega = W_CachePatchName("K_CHECK5", PU_HUDGFX); + kp_checkmegaw = W_CachePatchName("K_CHECK6", PU_HUDGFX); + /* // Neo-Kart item windows kp_electroshield = W_CachePatchName("KNITELEC", PU_HUDGFX); @@ -3426,19 +3897,21 @@ static INT32 STRINGY(INT32 y) return y; } -static INT32 SCX(INT32 x) +/*static INT32 SCX(INT32 x) { return FixedInt(FixedMul(x<kartstuff[k_bootaketimer] > 0 - || stplyr->kartstuff[k_boostolentimer] > 0) && (leveltime & 2)) localpatch = kp_boosteal; - else if (stplyr->kartstuff[k_boostolentimer] > 0 && !(leveltime & 2)) localpatch = kp_noitem; + if ((stplyr->kartstuff[k_bootaketimer] > 0 || stplyr->kartstuff[k_boostolentimer] > 0) + && (leveltime & 2)) localpatch = kp_boosteal; + else if (stplyr->kartstuff[k_boostolentimer] > 0 && !(leveltime & 2)) localpatch = kp_noitem; else if (stplyr->kartstuff[k_kitchensink] == 1) localpatch = kp_kitchensink; - else if (stplyr->kartstuff[k_lightning] == 1) localpatch = kp_lightning; - else if (stplyr->kartstuff[k_tripleredshell]) localpatch = kp_tripleredshell; // &8 + else if (stplyr->kartstuff[k_feather] & 1) localpatch = kp_feather; + else if (stplyr->kartstuff[k_lightning] == 1) localpatch = kp_lightning; + else if (stplyr->kartstuff[k_tripleredshell]) localpatch = kp_tripleredshell; // &8 else if (stplyr->kartstuff[k_fireflower] == 1) localpatch = kp_fireflower; - else if (stplyr->kartstuff[k_blueshell] == 1) localpatch = kp_blueshell; - else if (stplyr->kartstuff[k_bobomb]) localpatch = kp_bobomb; // &2 + else if (stplyr->kartstuff[k_blueshell] == 1) localpatch = kp_blueshell; + else if (stplyr->kartstuff[k_bobomb]) localpatch = kp_bobomb; // &2 else if (stplyr->kartstuff[k_triplegreenshell]) localpatch = kp_triplegreenshell; // &8 else if (stplyr->kartstuff[k_redshell]) localpatch = kp_redshell; // &2 - else if (stplyr->kartstuff[k_greenshell]) localpatch = kp_greenshell; // &2 - else if (stplyr->kartstuff[k_banana]) localpatch = kp_banana; // &2 + else if (stplyr->kartstuff[k_greenshell]) localpatch = kp_greenshell; // &2 + else if (stplyr->kartstuff[k_banana]) localpatch = kp_banana; // &2 else if (stplyr->kartstuff[k_fakeitem] & 2) localpatch = kp_fakeitem; else if (stplyr->kartstuff[k_triplebanana]) localpatch = kp_triplebanana; // &8 - else if (stplyr->kartstuff[k_star] == 1) localpatch = kp_star; + else if (stplyr->kartstuff[k_star] == 1) localpatch = kp_star; else if (stplyr->kartstuff[k_goldshroom] == 1 - || (stplyr->kartstuff[k_goldshroomtimer] > 1 && (leveltime & 1))) localpatch = kp_goldshroom; + || (stplyr->kartstuff[k_goldshroomtimer] > 1 && (leveltime & 1))) localpatch = kp_goldshroom; else if (stplyr->kartstuff[k_goldshroomtimer] > 1 && !(leveltime & 1)) localpatch = kp_noitem; else if (stplyr->kartstuff[k_megashroom] == 1 - || (stplyr->kartstuff[k_growshrinktimer] > 1 && (leveltime & 1))) localpatch = kp_megashroom; + || (stplyr->kartstuff[k_growshrinktimer] > 1 && (leveltime & 1))) localpatch = kp_megashroom; else if (stplyr->kartstuff[k_growshrinktimer] > 1 && !(leveltime & 1)) localpatch = kp_noitem; else if (stplyr->kartstuff[k_mushroom] & 4) localpatch = kp_triplemushroom; else if (stplyr->kartstuff[k_mushroom] & 2) localpatch = kp_doublemushroom; - else if (stplyr->kartstuff[k_mushroom] == 1) localpatch = kp_mushroom; + else if (stplyr->kartstuff[k_mushroom] == 1) localpatch = kp_mushroom; else if (stplyr->kartstuff[k_boo] == 1) localpatch = kp_boo; else if (stplyr->kartstuff[k_magnet] == 1) localpatch = kp_magnet; - V_DrawScaledPatch(ITEM_X, STRINGY(ITEM_Y), V_SNAPTORIGHT|V_SNAPTOTOP, localpatch); + if (splitscreen) + flags = 0; + V_DrawScaledPatch(ITEM_X, STRINGY(ITEM_Y), flags, localpatch); } /* @@ -3777,8 +4274,12 @@ static void K_drawKartTimestamp(void) // TIME_Y = 6; // 6 INT32 TIME_XB; + INT32 flags = V_SNAPTORIGHT|V_SNAPTOTOP; + + if (splitscreen) + flags = 0; - V_DrawScaledPatch(TIME_X, STRINGY(TIME_Y), 0, kp_timestickerwide); + V_DrawScaledPatch(TIME_X, STRINGY(TIME_Y), flags, kp_timestickerwide); TIME_XB = TIME_X+33; @@ -3787,44 +4288,44 @@ static void K_drawKartTimestamp(void) // zero minute if (stplyr->realtime/(60*TICRATE) < 10) { - V_DrawKartString(TIME_XB, STRINGY(TIME_Y+3), 0, va("0")); + V_DrawKartString(TIME_XB, STRINGY(TIME_Y+3), flags, va("0")); // minutes time 0 __ __ - V_DrawKartString(TIME_XB+12, STRINGY(TIME_Y+3), 0, va("%d", stplyr->realtime/(60*TICRATE))); + V_DrawKartString(TIME_XB+12, STRINGY(TIME_Y+3), flags, va("%d", stplyr->realtime/(60*TICRATE))); } // minutes time 0 __ __ else - V_DrawKartString(TIME_XB, STRINGY(TIME_Y+3), 0, va("%d", stplyr->realtime/(60*TICRATE))); + V_DrawKartString(TIME_XB, STRINGY(TIME_Y+3), flags, va("%d", stplyr->realtime/(60*TICRATE))); // apostrophe location _'__ __ - V_DrawKartString(TIME_XB+24, STRINGY(TIME_Y+3), 0, va("'")); + V_DrawKartString(TIME_XB+24, STRINGY(TIME_Y+3), flags, va("'")); // zero second _ 0_ __ if ((stplyr->realtime/TICRATE % 60) < 10) { - V_DrawKartString(TIME_XB+36, STRINGY(TIME_Y+3), 0, va("0")); + V_DrawKartString(TIME_XB+36, STRINGY(TIME_Y+3), flags, va("0")); // seconds time _ _0 __ - V_DrawKartString(TIME_XB+48, STRINGY(TIME_Y+3), 0, va("%d", stplyr->realtime/TICRATE % 60)); + V_DrawKartString(TIME_XB+48, STRINGY(TIME_Y+3), flags, va("%d", stplyr->realtime/TICRATE % 60)); } // zero second _ 00 __ else - V_DrawKartString(TIME_XB+36, STRINGY(TIME_Y+3), 0, va("%d", stplyr->realtime/TICRATE % 60)); + V_DrawKartString(TIME_XB+36, STRINGY(TIME_Y+3), flags, va("%d", stplyr->realtime/TICRATE % 60)); // quotation mark location _ __"__ - V_DrawKartString(TIME_XB+60, STRINGY(TIME_Y+3), 0, va("\"")); + V_DrawKartString(TIME_XB+60, STRINGY(TIME_Y+3), flags, va("\"")); // zero tick _ __ 0_ if (G_TicsToCentiseconds(stplyr->realtime) < 10) { - V_DrawKartString(TIME_XB+72, STRINGY(TIME_Y+3), 0, va("0")); + V_DrawKartString(TIME_XB+72, STRINGY(TIME_Y+3), flags, va("0")); // tics _ __ _0 - V_DrawKartString(TIME_XB+84, STRINGY(TIME_Y+3), 0, va("%d", G_TicsToCentiseconds(stplyr->realtime))); + V_DrawKartString(TIME_XB+84, STRINGY(TIME_Y+3), flags, va("%d", G_TicsToCentiseconds(stplyr->realtime))); } // zero tick _ __ 00 if (G_TicsToCentiseconds(stplyr->realtime) >= 10) - V_DrawKartString(TIME_XB+72, STRINGY(TIME_Y+3), 0, va("%d", G_TicsToCentiseconds(stplyr->realtime))); + V_DrawKartString(TIME_XB+72, STRINGY(TIME_Y+3), flags, va("%d", G_TicsToCentiseconds(stplyr->realtime))); } else - V_DrawKartString(TIME_XB, STRINGY(TIME_Y+3), 0, va("99'59\"99")); + V_DrawKartString(TIME_XB, STRINGY(TIME_Y+3), flags, va("99'59\"99")); } static void K_DrawKartPositionNum(INT32 num) @@ -3832,14 +4333,18 @@ static void K_DrawKartPositionNum(INT32 num) // POSI_X = BASEVIDWIDTH - 51; // 269 // POSI_Y = BASEVIDHEIGHT- 64; // 136 - INT32 X = POSI_X+SCX(43); // +43 to offset where it's being drawn if there are more than one + INT32 X = POSI_X+43; // +43 to offset where it's being drawn if there are more than one INT32 W = SHORT(kp_positionnum[0][0]->width); + INT32 flags = V_TRANSLUCENT|V_SNAPTORIGHT|V_SNAPTOBOTTOM; patch_t *localpatch = kp_positionnum[0][0]; + if (splitscreen) + flags = V_TRANSLUCENT; + // Special case for 0 if (!num) { - V_DrawTranslucentPatch(X-(W*vid.dupx), POSI_Y, V_NOSCALESTART|V_TRANSLUCENT|V_SNAPTORIGHT|V_SNAPTOBOTTOM, kp_positionnum[0][0]); + V_DrawTranslucentPatch(X-W, STRINGY(POSI_Y), flags, kp_positionnum[0][0]); return; } @@ -3848,28 +4353,58 @@ static void K_DrawKartPositionNum(INT32 num) // Draw the number while (num) { - X -= (W*vid.dupx); + X -= W; - // Check for the final lap - if (stplyr->laps+1 == cv_numlaps.value) + if (stplyr->exiting && num == 1) // 1st place winner? You get rainbows!! + { + // Alternate frame every three frames + switch (leveltime % 21) + { + case 1: case 2: case 3: + localpatch = kp_winnernum[0]; + break; + case 4: case 5: case 6: + localpatch = kp_winnernum[1]; + break; + case 7: case 8: case 9: + localpatch = kp_winnernum[2]; + break; + case 10: case 11: case 12: + localpatch = kp_winnernum[3]; + break; + case 13: case 14: case 15: + localpatch = kp_winnernum[4]; + break; + case 16: case 17: case 18: + localpatch = kp_winnernum[5]; + break; + case 19: case 20: case 21: + localpatch = kp_winnernum[6]; + break; + default: + localpatch = kp_positionnum[1][0]; + break; + } + } + else if (stplyr->laps+1 == cv_numlaps.value || stplyr->exiting) // Check for the final lap, or won { // Alternate frame every three frames switch (leveltime % 9) { case 1: case 2: case 3: - if (stplyr->kartstuff[k_position] >= 4) + if (stplyr->kartstuff[k_position] >= 4 || (splitscreen && stplyr->kartstuff[k_position] >= 2)) localpatch = kp_positionnum[num % 10][4]; else localpatch = kp_positionnum[num % 10][1]; break; case 4: case 5: case 6: - if (stplyr->kartstuff[k_position] >= 4) + if (stplyr->kartstuff[k_position] >= 4 || (splitscreen && stplyr->kartstuff[k_position] >= 2)) localpatch = kp_positionnum[num % 10][5]; else localpatch = kp_positionnum[num % 10][2]; break; case 7: case 8: case 9: - if (stplyr->kartstuff[k_position] >= 4) + if (stplyr->kartstuff[k_position] >= 4 || (splitscreen && stplyr->kartstuff[k_position] >= 2)) localpatch = kp_positionnum[num % 10][6]; else localpatch = kp_positionnum[num % 10][3]; @@ -3882,7 +4417,7 @@ static void K_DrawKartPositionNum(INT32 num) else localpatch = kp_positionnum[num % 10][0]; - V_DrawTranslucentPatch(X, POSI_Y, V_NOSCALESTART|V_TRANSLUCENT|V_SNAPTORIGHT|V_SNAPTOBOTTOM, localpatch); + V_DrawTranslucentPatch(X, STRINGY(POSI_Y), flags, localpatch); num /= 10; } } @@ -3940,17 +4475,17 @@ static void K_drawKartPositionFaces(void) { colormap = colormaps; if (rankplayer[i] != myplayer) - V_DrawSmallTranslucentPatch(FACE_X, Y, 0, faceprefix[players[rankplayer[i]].skin]); + V_DrawSmallTranslucentPatch(FACE_X, STRINGY(Y), V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin]); else - V_DrawSmallScaledPatch(FACE_X, Y, 0, faceprefix[players[rankplayer[i]].skin]); + V_DrawSmallScaledPatch(FACE_X, STRINGY(Y), V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin]); } else { colormap = R_GetTranslationColormap(players[rankplayer[i]].skin, players[rankplayer[i]].mo->color, GTC_CACHE); if (rankplayer[i] != myplayer) - V_DrawSmallTranslucentMappedPatch(FACE_X, Y, 0, faceprefix[players[rankplayer[i]].skin], colormap); + V_DrawSmallTranslucentMappedPatch(FACE_X, STRINGY(Y), V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin], colormap); else - V_DrawSmallMappedPatch(FACE_X, Y, 0, faceprefix[players[rankplayer[i]].skin], colormap); + V_DrawSmallMappedPatch(FACE_X, STRINGY(Y), V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin], colormap); } // Draws the little number over the face switch (players[rankplayer[i]].kartstuff[k_position]) @@ -3962,30 +4497,200 @@ static void K_drawKartPositionFaces(void) default: break; } if (rankplayer[i] != myplayer) - V_DrawSmallTranslucentPatch(FACE_X, Y, 0, localpatch); + V_DrawSmallTranslucentPatch(FACE_X, STRINGY(Y), V_SNAPTOLEFT, localpatch); else - V_DrawSmallScaledPatch(FACE_X, Y, 0, localpatch); + V_DrawSmallScaledPatch(FACE_X, STRINGY(Y), V_SNAPTOLEFT, localpatch); Y += 18; } } +static void K_drawKartLaps(void) +{ + INT32 flags = V_SNAPTOLEFT|V_SNAPTOBOTTOM; + if (splitscreen) + flags = 0; + + V_DrawScaledPatch(LAPS_X, STRINGY(LAPS_Y), flags, kp_lapsticker); + + if (stplyr->exiting) + V_DrawKartString(LAPS_X+33, STRINGY(LAPS_Y+3), flags, "FIN"); + else + V_DrawKartString(LAPS_X+33, STRINGY(LAPS_Y+3), flags, va("%d/%d", stplyr->laps+1, cv_numlaps.value)); +} + static void K_drawKartSpeedometer(void) { fixed_t convSpeed; + INT32 flags = V_SNAPTOLEFT|V_SNAPTOBOTTOM; + if (splitscreen) + flags = 0; if (cv_speedometer.value == 1) { convSpeed = FixedMul(stplyr->speed, 142371)/FRACUNIT; // 2.172409058 - V_DrawKartString(9, STRINGY(155), 0, va("%3d km/h", convSpeed)); + V_DrawKartString(SPDM_X, STRINGY(SPDM_Y), flags, va("%3d km/h", convSpeed)); } else if (cv_speedometer.value == 2) { convSpeed = FixedMul(stplyr->speed, 88465)/FRACUNIT; // 1.349868774 - V_DrawKartString(9, STRINGY(155), 0, va("%3d mph", convSpeed)); + V_DrawKartString(SPDM_X, STRINGY(SPDM_Y), flags, va("%3d mph", convSpeed)); } else if (cv_speedometer.value == 3) { convSpeed = stplyr->speed/FRACUNIT; - V_DrawKartString(9, STRINGY(155), 0, va("%3d Fracunits/s", convSpeed)); + V_DrawKartString(SPDM_X, STRINGY(SPDM_Y), flags, va("%3d fu/s", convSpeed)); + } +} + +static void K_drawKartBalloonsOrKarma(void) +{ + UINT8 *colormap = R_GetTranslationColormap(-1, stplyr->skincolor, 0); + INT32 flags = V_SNAPTOLEFT|V_SNAPTOBOTTOM; + if (splitscreen) + flags = 0; + + if (stplyr->kartstuff[k_balloon] <= 0) + { + V_DrawScaledPatch(LAPS_X, STRINGY(LAPS_Y), flags, kp_karmasticker); + V_DrawKartString(LAPS_X+58, STRINGY(LAPS_Y+3), flags, va("%d", stplyr->kartstuff[k_comebackpoints])); + V_DrawKartString(LAPS_X+85, STRINGY(LAPS_Y+3), flags, va("3")); + } + else + { + if (cv_kartballoons.value > 9) + { + V_DrawMappedPatch(LAPS_X, STRINGY(LAPS_Y), flags, kp_balloonstickerwide, colormap); + V_DrawKartString(LAPS_X+46, STRINGY(LAPS_Y+3), flags, va("%2d", stplyr->kartstuff[k_balloon])); + V_DrawKartString(LAPS_X+83, STRINGY(LAPS_Y+3), flags, va("%2d", cv_kartballoons.value)); + } + else + { + V_DrawMappedPatch(LAPS_X, STRINGY(LAPS_Y), flags, kp_balloonsticker, colormap); + V_DrawKartString(LAPS_X+46, STRINGY(LAPS_Y+3), flags, va("%d", stplyr->kartstuff[k_balloon])); + V_DrawKartString(LAPS_X+73, STRINGY(LAPS_Y+3), flags, va("%d", cv_kartballoons.value)); + } + } +} + +fixed_t K_FindCheckX(fixed_t px, fixed_t py, angle_t ang, fixed_t mx, fixed_t my) +{ + fixed_t dist, x; + fixed_t range = RING_DIST/3; + angle_t diff; + + range *= (K_GetKartCC()/50); + + dist = abs(R_PointToDist2(px, py, mx, my)); + if (dist > range) + return -320; + + diff = R_PointToAngle2(px, py, mx, my) - ang; + + if (diff < ANGLE_90 || diff > ANGLE_270) + return -320; + else + x = (FixedMul(FINETANGENT(((diff+ANGLE_90)>>ANGLETOFINESHIFT) & 4095), 160<>FRACBITS); +} + +static void K_drawKartPlayerCheck(void) +{ + INT32 i; + UINT8 *colormap; + INT32 x; + patch_t *localpatch; + + if (!(stplyr->mo)) + return; + + if (stplyr->awayviewtics) + return; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (&players[i] == stplyr) + continue; + if (!(players[i].mo)) + continue; + + if ((players[i].kartstuff[k_startimer] <= 0) && (leveltime & 2)) + { + if (players[i].kartstuff[k_megashroom] || players[i].kartstuff[k_growshrinktimer] > 0) + localpatch = kp_checkmegaw; + else if (players[i].kartstuff[k_star] || players[i].kartstuff[k_startimer]) + localpatch = kp_checkstarw; + else + localpatch = kp_checkw; + } + else + { + if (players[i].kartstuff[k_megashroom] || players[i].kartstuff[k_growshrinktimer] > 0) + localpatch = kp_checkmega; + else if (players[i].kartstuff[k_star] || players[i].kartstuff[k_startimer]) + localpatch = kp_checkstar; + else + localpatch = kp_check; + } + + x = K_FindCheckX(stplyr->mo->x, stplyr->mo->y, stplyr->mo->angle, players[i].mo->x, players[i].mo->y); + if (x <= 320 && x >= 0) + { + if (x < 14) + x = 14; + else if (x > 306) + x = 306; + + colormap = R_GetTranslationColormap(-1, players[i].mo->color, 0); + V_DrawMappedPatch(x, STRINGY(CHEK_Y), V_SNAPTOBOTTOM, localpatch, colormap); + } + } +} + +static void K_drawBattleFullscreen(void) +{ + if (!WipeInAction && !menuactive && !splitscreen) + V_DrawFadeScreen(); + + if (stplyr->exiting) + { + if (splitscreen) + { + if (stplyr->kartstuff[k_balloon]) + V_DrawScaledPatch(96, STRINGY(100), 0, kp_battlewin); + else + V_DrawScaledPatch(BASEVIDWIDTH-96, STRINGY(100), 0, kp_battlelose); + } + else + { + if (stplyr->kartstuff[k_balloon]) + V_DrawScaledPatch(BASEVIDWIDTH/2, STRINGY(100), 0, kp_battlewin); + else + V_DrawScaledPatch(BASEVIDWIDTH/2, STRINGY(100), 0, kp_battlelose); + } + } + else if (stplyr->kartstuff[k_balloon] <= 0 && stplyr->kartstuff[k_comebacktimer] && cv_kartcomeback.value) + { + INT32 t = stplyr->kartstuff[k_comebacktimer]/TICRATE; + INT32 X = BASEVIDWIDTH/2; + + while (t) + { + X -= 8; + t /= 10; + } + + if (!stplyr->kartstuff[k_comebackshowninfo]) + { + V_DrawScaledPatch(BASEVIDWIDTH/2, STRINGY(BASEVIDHEIGHT/2), 0, kp_battleinfo); + V_DrawScaledPatch(BASEVIDWIDTH/2, STRINGY((BASEVIDHEIGHT/2) + 66), 0, kp_timeoutsticker); + V_DrawKartString(X, STRINGY((BASEVIDHEIGHT/2) + 66), 0, va("%d", stplyr->kartstuff[k_comebacktimer]/TICRATE)); + } + else + { + V_DrawScaledPatch(BASEVIDWIDTH/2, STRINGY(BASEVIDHEIGHT/2), 0, kp_battlewait); + V_DrawScaledPatch(BASEVIDWIDTH/2, STRINGY((BASEVIDHEIGHT/2) + 30), 0, kp_timeoutsticker); + V_DrawKartString(X, STRINGY((BASEVIDHEIGHT/2) + 30), 0, va("%d", stplyr->kartstuff[k_comebacktimer]/TICRATE)); + } } } @@ -4100,6 +4805,13 @@ void K_drawKartHUD(void) // This is handled by console/menu values K_initKartHUD(); + // Draw full screen stuff that turns off the rest of the HUD + if ((gametype != GT_RACE) && (stplyr->exiting || (stplyr->kartstuff[k_balloon] <= 0 && stplyr->kartstuff[k_comebacktimer] && cv_kartcomeback.value))) + { + K_drawBattleFullscreen(); + return; + } + // Draw Lakitu // This is done first so that regardless of HUD layers, // he'll appear to be in the 'real world' @@ -4110,6 +4822,10 @@ void K_drawKartHUD(void) if (stplyr->kartstuff[k_lapanimation]) K_drawLapLakitu(); + + // Draw the CHECK indicator before the other items too, so it's overlapped by everything else + if (cv_kartcheck.value) + K_drawKartPlayerCheck(); } // If the item window is closing, draw it closing! @@ -4125,32 +4841,36 @@ void K_drawKartHUD(void) else K_drawKartRetroItem(); - // If not splitscreen, draw... - // The little triple-item icons at the bottom - // The top-four faces on the left - if (!(splitscreen || modeattacking)) - { - //K_DrawKartTripleItem(); - K_drawKartPositionFaces(); - } - + //K_DrawKartTripleItem(); + // Draw the timestamp K_drawKartTimestamp(); - // Draw the lap counter - V_DrawScaledPatch(LAPS_X, STRINGY(LAPS_Y), 0, kp_lapsticker); - if (stplyr->exiting) - V_DrawKartString(LAPS_X+33, STRINGY(LAPS_Y+3), 0, "FIN"); - else - V_DrawKartString(LAPS_X+33, STRINGY(LAPS_Y+3), 0, va("%d/%d", stplyr->laps+1, cv_numlaps.value)); + if (gametype == GT_RACE) // Race-only elements + { + if (!(splitscreen || modeattacking)) + { + // If not splitscreen, draw... + // The little triple-item icons at the bottom + // The top-four faces on the left + K_drawKartPositionFaces(); + } - // Draw the numerical position - if (!modeattacking) + // Draw the numerical position K_DrawKartPositionNum(stplyr->kartstuff[k_position]); - // Draw the speedometer - // TODO: Make a better speedometer. - K_drawKartSpeedometer(); + // Draw the speedometer + // TODO: Make a better speedometer. + K_drawKartSpeedometer(); + + // Draw the lap counter + K_drawKartLaps(); + } + else if (gametype == GT_MATCH) // Battle-only + { + // Draw the hits left! + K_drawKartBalloonsOrKarma(); + } } //} diff --git a/src/k_kart.h b/src/k_kart.h index 9319a227..394e4d61 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -15,20 +15,27 @@ UINT8 K_GetKartColorByName(const char *name); void K_RegisterKartStuff(void); -void K_KartBouncer(void); +UINT8 K_GetKartCC(void); +void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce); void K_KartMoveAnimation(player_t *player); void K_KartPlayerThink(player_t *player, ticcmd_t *cmd); void K_SpinPlayer(player_t *player, mobj_t *source); void K_SquishPlayer(player_t *player, mobj_t *source); void K_ExplodePlayer(player_t *player, mobj_t *source); -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); +void K_StealBalloon(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_SpawnDriftTrail(player_t *player); void K_DoMushroom(player_t *player, boolean doPFlag, boolean startboost); +void K_DoBouncePad(mobj_t *mo, fixed_t vertispeed); +boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); void K_MomentumToFacing(player_t *player); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); +fixed_t K_GetKartAccel(player_t *player); +UINT16 K_GetKartFlashing(player_t *player); fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove); void K_MoveKartPlayer(player_t *player, boolean onground); +void K_CheckBalloons(void); void K_LoadKartHUDGraphics(void); void K_drawKartHUD(void); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e8e8fd02..f24cf27b 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -20,6 +20,7 @@ #include "m_random.h" #include "s_sound.h" #include "g_game.h" +#include "k_kart.h" #include "lua_script.h" #include "lua_libs.h" @@ -1009,10 +1010,11 @@ static int lib_pTeleportMove(lua_State *L) static int lib_pSlideMove(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + boolean forceslide = luaL_checkboolean(L, 2); NOHUD if (!mo) return LUA_ErrInvalid(L, "mobj_t"); - P_SlideMove(mo); + P_SlideMove(mo, forceslide); return 0; } @@ -1980,6 +1982,184 @@ static int lib_gTicsToMilliseconds(lua_State *L) return 1; } +// K_KART +//////////// + +static int lib_kGetKartColorByName(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + //HUDSAFE + lua_pushinteger(L, K_GetKartColorByName(name)); + return 1; +} + +static int lib_kGetKartCC(lua_State *L) +{ + //HUDSAFE + lua_pushinteger(L, K_GetKartCC()); + return 1; +} + +static int lib_kKartBouncing(lua_State *L) +{ + mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + boolean bounce = luaL_checkboolean(L, 3); + NOHUD + if (!mobj1) + return LUA_ErrInvalid(L, "mobj_t"); + if (!mobj2) + return LUA_ErrInvalid(L, "mobj_t"); + K_KartBouncing(mobj1, mobj2, bounce); + return 0; +} + +static int lib_kSpinPlayer(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)); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (!source) + return LUA_ErrInvalid(L, "mobj_t"); + K_SpinPlayer(player, source); + return 0; +} + +static int lib_kSquishPlayer(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)); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (!source) + return LUA_ErrInvalid(L, "mobj_t"); + K_SquishPlayer(player, source); + return 0; +} + +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)); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (!source) + return LUA_ErrInvalid(L, "mobj_t"); + K_ExplodePlayer(player, source); + return 0; +} + +static int lib_kStealBalloon(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + player_t *victim = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); + boolean force = luaL_checkboolean(L, 3); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (!victim) + return LUA_ErrInvalid(L, "player_t"); + K_StealBalloon(player, victim, force); + return 0; +} + +static int lib_kSpawnKartExplosion(lua_State *L) +{ + fixed_t x = luaL_checkfixed(L, 1); + fixed_t y = luaL_checkfixed(L, 2); + fixed_t z = luaL_checkfixed(L, 3); + fixed_t radius = luaL_checkfixed(L, 4); + INT32 number = (INT32)luaL_checkinteger(L, 5); + mobjtype_t type = luaL_checkinteger(L, 6); + angle_t rotangle = luaL_checkangle(L, 7); + boolean spawncenter = luaL_checkboolean(L, 8); + boolean ghostit = luaL_checkboolean(L, 9); + mobj_t *source = *((mobj_t **)luaL_checkudata(L, 10, META_MOBJ)); + NOHUD + if (!source) + return LUA_ErrInvalid(L, "mobj_t"); + K_SpawnKartExplosion(x, y, z, radius, number, type, rotangle, spawncenter, ghostit, source); + return 0; +} + +static int lib_kSpawnDriftTrail(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + K_SpawnDriftTrail(player); + return 0; +} + +static int lib_kDoMushroom(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + boolean doPFlag = luaL_checkboolean(L, 2); + boolean startboost = luaL_checkboolean(L, 3); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + K_DoMushroom(player, doPFlag, startboost); + return 0; +} + +static int lib_kDoBouncePad(lua_State *L) +{ + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + fixed_t vertispeed = luaL_checkfixed(L, 2); + NOHUD + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + K_DoBouncePad(mo, vertispeed); + return 0; +} + +static int lib_kMomentumToFacing(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + K_MomentumToFacing(player); + return 0; +} + +static int lib_kGetKartSpeed(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + boolean doboostpower = luaL_checkboolean(L, 2); + //HUDSAFE + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushinteger(L, K_GetKartSpeed(player, doboostpower)); + return 0; +} + +static int lib_kGetKartAccel(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + //HUDSAFE + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushinteger(L, K_GetKartAccel(player)); + return 0; +} + +static int lib_kGetKartFlashing(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + //HUDSAFE + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushinteger(L, K_GetKartFlashing(player)); + return 0; +} + static luaL_Reg lib[] = { {"print", lib_print}, {"EvalMath", lib_evalMath}, @@ -2153,6 +2333,23 @@ static luaL_Reg lib[] = { {"G_TicsToCentiseconds",lib_gTicsToCentiseconds}, {"G_TicsToMilliseconds",lib_gTicsToMilliseconds}, + // k_kart + {"K_GetKartColorByName",lib_kGetKartColorByName}, + {"K_GetKartCC",lib_kGetKartCC}, + {"K_KartBouncing",lib_kKartBouncing}, + {"K_SpinPlayer",lib_kSpinPlayer}, + {"K_SquishPlayer",lib_kSquishPlayer}, + {"K_ExplodePlayer",lib_kExplodePlayer}, + {"K_StealBalloon",lib_kStealBalloon}, + {"K_SpawnKartExplosion",lib_kSpawnKartExplosion}, + {"K_SpawnDriftTrail",lib_kSpawnDriftTrail}, + {"K_DoMushroom",lib_kDoMushroom}, + {"K_DoBouncePad",lib_kDoBouncePad}, + {"K_MomentumToFacing",lib_kMomentumToFacing}, + {"K_GetKartSpeed",lib_kGetKartSpeed}, + {"K_GetKartAccel",lib_kGetKartAccel}, + {"K_GetKartFlashing",lib_kGetKartFlashing}, + {NULL, NULL} }; diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 55ceaa18..a58892d3 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -130,8 +130,6 @@ static int player_get(lua_State *L) LUA_PushUserdata(L, plr->powers, META_POWERS); else if (fastcmp(field,"kartstuff")) LUA_PushUserdata(L, plr->kartstuff, META_KARTSTUFF); - else if (fastcmp(field,"collide")) - LUA_PushUserdata(L, plr->collide, META_COLLIDE); else if (fastcmp(field,"frameangle")) lua_pushangle(L, plr->frameangle); else if (fastcmp(field,"pflags")) @@ -248,6 +246,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->starpostz); else if (fastcmp(field,"starpostnum")) lua_pushinteger(L, plr->starpostnum); + else if (fastcmp(field,"starpostcount")) + lua_pushinteger(L, plr->starpostcount); else if (fastcmp(field,"starposttime")) lua_pushinteger(L, plr->starposttime); else if (fastcmp(field,"starpostangle")) @@ -414,10 +414,14 @@ static int player_set(lua_State *L) else if (fastcmp(field,"dashtime")) plr->dashtime = (INT32)luaL_checkinteger(L, 3); // SRB2kart + else if (fastcmp(field,"kartstuff")) + return NOSET; + else if (fastcmp(field,"frameangle")) + plr->frameangle = luaL_checkangle(L, 3); else if (fastcmp(field,"kartspeed")) - plr->kartspeed = (UINT8)luaL_checkfixed(L, 3); + plr->kartspeed = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"kartweight")) - plr->kartweight = (UINT8)luaL_checkfixed(L, 3); + plr->kartweight = (UINT8)luaL_checkinteger(L, 3); // else if (fastcmp(field,"normalspeed")) plr->normalspeed = luaL_checkfixed(L, 3); @@ -511,6 +515,8 @@ static int player_set(lua_State *L) plr->starpostz = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"starpostnum")) plr->starpostnum = (INT32)luaL_checkinteger(L, 3); + else if (fastcmp(field,"starpostcount")) + plr->starpostcount = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"starposttime")) plr->starposttime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"starpostangle")) @@ -672,6 +678,38 @@ static int power_len(lua_State *L) return 1; } +// kartstuff, ks -> kartstuff[ks] +static int kartstuff_get(lua_State *L) +{ + INT32 *kartstuff = *((INT32 **)luaL_checkudata(L, 1, META_KARTSTUFF)); + kartstufftype_t ks = luaL_checkinteger(L, 2); + if (ks >= NUMKARTSTUFF) + return luaL_error(L, LUA_QL("kartstufftype_t") " cannot be %u", ks); + lua_pushinteger(L, kartstuff[ks]); + return 1; +} + +// kartstuff, ks, value -> kartstuff[ks] = value +static int kartstuff_set(lua_State *L) +{ + INT32 *kartstuff = *((INT32 **)luaL_checkudata(L, 1, META_KARTSTUFF)); + kartstufftype_t ks = luaL_checkinteger(L, 2); + INT32 i = (INT32)luaL_checkinteger(L, 3); + if (ks >= NUMKARTSTUFF) + return luaL_error(L, LUA_QL("kartstufftype_t") " cannot be %u", ks); + if (hud_running) + return luaL_error(L, "Do not alter player_t in HUD rendering code!"); + kartstuff[ks] = i; + return 0; +} + +// #kartstuff -> NUMKARTSTUFF +static int kartstuff_len(lua_State *L) +{ + lua_pushinteger(L, NUMKARTSTUFF); + return 1; +} + #define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field) static int ticcmd_get(lua_State *L) @@ -749,6 +787,17 @@ int LUA_PlayerLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L,1); + luaL_newmetatable(L, META_KARTSTUFF); + lua_pushcfunction(L, kartstuff_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, kartstuff_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, kartstuff_len); + lua_setfield(L, -2, "__len"); + lua_pop(L,1); + luaL_newmetatable(L, META_TICCMD); lua_pushcfunction(L, ticcmd_get); lua_setfield(L, -2, "__index"); diff --git a/src/lua_script.c b/src/lua_script.c index 9ba7ce7f..aafabbb9 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -435,7 +435,6 @@ void LUA_InvalidatePlayer(player_t *player) LUA_InvalidateUserdata(player); LUA_InvalidateUserdata(player->powers); LUA_InvalidateUserdata(player->kartstuff); - LUA_InvalidateUserdata(player->collide); LUA_InvalidateUserdata(&player->cmd); } diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 85e029e6..a267d998 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -165,10 +165,10 @@ static int skin_get(lua_State *L) break; // SRB2kart case skin_kartspeed: - lua_pushfixed(L, skin->kartspeed); + lua_pushinteger(L, skin->kartspeed); break; case skin_kartweight: - lua_pushfixed(L, skin->kartweight); + lua_pushinteger(L, skin->kartweight); break; // case skin_normalspeed: diff --git a/src/m_cheat.c b/src/m_cheat.c index cad35431..69e691a5 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -33,6 +33,8 @@ #include "z_zone.h" #include "p_slopes.h" +#include "k_kart.h" // srb2kart + #include "lua_script.h" #include "lua_hook.h" @@ -1348,7 +1350,7 @@ void Command_ObjectPlace_f(void) players[0].mo->color = op_oldcolor; // This is necessary for recovery of dying players. - if (players[0].powers[pw_flashing] >= flashingtics) - players[0].powers[pw_flashing] = flashingtics - 1; + if (players[0].powers[pw_flashing] >= K_GetKartFlashing(&players[0])) + players[0].powers[pw_flashing] = K_GetKartFlashing(&players[0]) - 1; } } diff --git a/src/p_enemy.c b/src/p_enemy.c index 6ab7d79b..2b010327 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -850,7 +850,7 @@ void A_Look(mobj_t *actor) if (!P_LookForPlayers(actor, locvar1 & 65535, false , FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale))) return; - if (leveltime < 4*TICRATE && gametype == GT_RACE) // SRB2kart - no looking before race starts + if (leveltime < 4*TICRATE) // SRB2kart - no looking before race starts return; // go into chase state @@ -3627,12 +3627,16 @@ void A_AttractChase(mobj_t *actor) P_LookForShield(actor); // Go find 'em, boy! - if (!actor->tracer + if (actor->tracer && actor->tracer->player && actor->tracer->player->kartstuff[k_comebackmode] == 1) + ; + else if (!actor->tracer || !actor->tracer->player || !actor->tracer->health || !P_CheckSight(actor, actor->tracer)) // You have to be able to SEE it...sorta { // Lost attracted rings don't through walls anymore. + if (actor->tracer && actor->tracer->player) + actor->tracer->player->kartstuff[k_comebackmode] = 0; actor->flags &= ~MF_NOCLIP; P_SetTarget(&actor->tracer, NULL); return; @@ -3921,10 +3925,11 @@ static inline boolean PIT_GrenadeRing(mobj_t *thing) if (thing == grenade->target && !(grenade->threshold == 0)) // Don't blow up at your owner. return true; - if (thing->player && thing->player->kartstuff[k_bootaketimer]) + if (thing->player && (thing->player->kartstuff[k_bootimer] + || (thing->player->kartstuff[k_balloon] <= 0 && thing->player->kartstuff[k_comebacktimer]))) return true; - if ((gametype == GT_CTF || gametype == GT_MATCH) + if ((gametype == GT_CTF || gametype == GT_TEAMMATCH) && !cv_friendlyfire.value && grenade->target->player && thing->player && grenade->target->player->ctfteam == thing->player->ctfteam) // Don't blow up at your teammates, unless friendlyfire is on return true; @@ -8090,6 +8095,13 @@ void A_ItemPop(mobj_t *actor) { mobj_t *remains; + if (!(actor->target && actor->target->player)) + { + if (cv_debug && !(actor->target && actor->target->player)) + CONS_Printf("ERROR: Powerup has no target!\n"); + return; + } + // de-solidify //P_UnsetThingPosition(actor); //actor->flags &= ~MF_SOLID; @@ -8123,26 +8135,13 @@ void A_ItemPop(mobj_t *actor) return; } - if (actor->target && actor->target->player // These used to be &2's and &8's for box only, but are now universal. - && !(actor->target->player->kartstuff[k_greenshell] || actor->target->player->kartstuff[k_triplegreenshell] - || actor->target->player->kartstuff[k_redshell] || actor->target->player->kartstuff[k_tripleredshell] - || actor->target->player->kartstuff[k_banana] || actor->target->player->kartstuff[k_triplebanana] - || actor->target->player->kartstuff[k_fakeitem] & 2 || actor->target->player->kartstuff[k_magnet] - || actor->target->player->kartstuff[k_bobomb] || actor->target->player->kartstuff[k_blueshell] - || actor->target->player->kartstuff[k_mushroom] || actor->target->player->kartstuff[k_fireflower] - || actor->target->player->kartstuff[k_star] || actor->target->player->kartstuff[k_goldshroom] - || actor->target->player->kartstuff[k_lightning] || actor->target->player->kartstuff[k_megashroom] - || actor->target->player->kartstuff[k_itemroulette] - || actor->target->player->kartstuff[k_boo] || actor->target->player->kartstuff[k_bootaketimer] - || actor->target->player->kartstuff[k_boostolentimer] - || actor->target->player->kartstuff[k_growshrinktimer] > 1 - || actor->target->player->kartstuff[k_goldshroomtimer])) - actor->target->player->kartstuff[k_itemroulette] = 1; - else if (cv_debug && !(actor->target && actor->target->player)) - CONS_Printf("ERROR: Powerup has no target!\n"); + actor->target->player->kartstuff[k_itemroulette] = 1; remains->flags2 &= ~MF2_AMBUSH; + if (gametype != GT_RACE) + numgotboxes++; + P_RemoveMobj(actor); } @@ -8213,8 +8212,11 @@ void A_RedShellChase(mobj_t *actor) continue; } - if (!(gametype == GT_RACE)) + if (gametype != GT_RACE) { + if (player->kartstuff[k_balloon] <= 0) + continue; + if (P_AproxDistance(P_AproxDistance(player->mo->x-actor->x, player->mo->y-actor->y), player->mo->z-actor->z) > RING_DIST) continue; @@ -8223,7 +8225,8 @@ void A_RedShellChase(mobj_t *actor) if ((gametype == GT_RACE) || (gametype != GT_RACE // If in match etc. only home in when you get close enough, in race etc. home in all the time && P_AproxDistance(P_AproxDistance(player->mo->x-actor->x, - player->mo->y-actor->y), player->mo->z-actor->z) < RING_DIST)) + player->mo->y-actor->y), player->mo->z-actor->z) < RING_DIST + && player->kartstuff[k_balloon] > 0)) P_SetTarget(&actor->tracer, player->mo); return; @@ -8253,7 +8256,7 @@ void A_BobombExplode(mobj_t *actor) type = (mobjtype_t)locvar1; for (d = 0; d < 16; d++) - K_SpawnKartExplosion(actor->x, actor->y, actor->z, actor->info->painchance + 32*FRACUNIT, 32, type, d*(ANGLE_45/4), false, false); // 32 <-> 64 + K_SpawnKartExplosion(actor->x, actor->y, actor->z, actor->info->painchance + 32*FRACUNIT, 32, type, d*(ANGLE_45/4), false, false, actor->target); // 32 <-> 64 P_SpawnMobj(actor->x, actor->y, actor->z, MT_BOMBEXPLOSIONSOUND); @@ -8269,6 +8272,9 @@ void A_BobombExplode(mobj_t *actor) if (mo2 == actor || mo2->type == MT_BOMBEXPLOSIONSOUND) // Don't explode yourself! Endless loop! continue; + if (actor->target && actor->target->player && actor->target->player->kartstuff[k_balloon] <= 0 && mo2 == actor->target) + continue; + if (P_AproxDistance(P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y), mo2->z - actor->z) > actor->info->painchance) continue; diff --git a/src/p_inter.c b/src/p_inter.c index bcf7a8ef..bff3a030 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -150,6 +150,28 @@ boolean P_CanPickupItem(player_t *player, boolean weapon) //if (player->powers[pw_flashing] > (flashingtics/4)*3 && player->powers[pw_flashing] <= flashingtics) // return false; + if (gametype != GT_RACE && player->kartstuff[k_balloon] <= 0) // No balloons in Match + return false; + + if (player->kartstuff[k_magnettimer]) // You should probably collect stuff when you're attracting it :V + return true; + + if (player->kartstuff[k_bootaketimer] || player->kartstuff[k_boostolentimer] + || player->kartstuff[k_growshrinktimer] > 1 || player->kartstuff[k_goldshroomtimer]) // Item-specific timer going off + return false; + + if (player->kartstuff[k_itemroulette] + || player->kartstuff[k_greenshell] || player->kartstuff[k_triplegreenshell] + || player->kartstuff[k_redshell] || player->kartstuff[k_tripleredshell] + || player->kartstuff[k_banana] || player->kartstuff[k_triplebanana] + || player->kartstuff[k_fakeitem] & 2 || player->kartstuff[k_magnet] + || player->kartstuff[k_bobomb] || player->kartstuff[k_blueshell] + || player->kartstuff[k_mushroom] || player->kartstuff[k_fireflower] + || player->kartstuff[k_star] || player->kartstuff[k_goldshroom] + || player->kartstuff[k_lightning] || player->kartstuff[k_megashroom] + || player->kartstuff[k_boo] || player->kartstuff[k_feather] & 1) // Item slot already taken up + return false; + return true; } @@ -388,8 +410,34 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { case MT_RANDOMITEM: // SRB2kart case MT_FLINGRANDOMITEM: - if (!(P_CanPickupItem(player, false))) + if (gametype != GT_RACE && player->kartstuff[k_balloon] <= 0) + { + if (player->kartstuff[k_comebackmode] == 0 && !player->kartstuff[k_comebacktimer]) + { + if (special->tracer && special->tracer->player) + special->tracer->player->kartstuff[k_comebackmode] = 0; + P_SetTarget(&special->tracer, toucher); + player->kartstuff[k_comebackmode] = 1; + } return; + } + + if (!P_CanPickupItem(player, false) && special->tracer != toucher) + return; + + if (gametype != GT_RACE && special->tracer && special->tracer->player) + { + special->tracer->player->kartstuff[k_comebackmode] = 0; + + special->tracer->player->kartstuff[k_comebackpoints]++; + CONS_Printf(M_GetText("%s gave an item to %s.\n"), player_names[special->tracer->player-players], player_names[player-players]); + + if (special->tracer->player->kartstuff[k_comebackpoints] >= 3) + K_StealBalloon(special->tracer->player, player, true); + + special->tracer->player->kartstuff[k_comebacktimer] = comebacktime; + } + special->momx = special->momy = special->momz = 0; P_SetTarget(&special->target, toucher); P_SetMobjState(special, special->info->deathstate); @@ -1165,9 +1213,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; } // - // In circuit, player must have touched all previous starposts + // SRB2kart: make sure the player will have enough checkpoints to touch if (circuitmap - && special->health - player->starpostnum > 1) + && special->health >= (numstarposts/2 + player->starpostnum)) { // blatant reuse of a variable that's normally unused in circuit if (!player->tossdelay) @@ -1194,6 +1242,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) player->starpostz = special->z>>FRACBITS; player->starpostangle = special->angle; player->starpostnum = special->health; + player->starpostcount++; P_ClearStarPost(special->health); // Find all starposts in the level with this value. @@ -2004,6 +2053,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) target->target->player->kartstuff[k_triplebanana] &= ~2; else if (target->type == MT_TRIPLEBANANASHIELD3 && target->target->player->kartstuff[k_triplebanana] & 4) target->target->player->kartstuff[k_triplebanana] &= ~4; + /*else if (target->type == MT_BATTLEBALLOON && target->target->player->kartstuff[k_balloon] > target->threshold-1) + target->target->player->kartstuff[k_balloon] = target->threshold-1;*/ } // @@ -2066,7 +2117,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) P_SetTarget(&target->target, source); source->player->numboxes++; if ((cv_itemrespawn.value && gametype != GT_COOP && (modifiedgame || netgame || multiplayer))) + { target->fuse = cv_itemrespawntime.value*TICRATE + 2; // Random box generation + } } // Award Score Tails @@ -2214,7 +2267,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) for (w=0; w < MAXPLAYERS; w++) { if (players[w].pflags & PF_TAGIT) - P_AddPlayerScore(&players[w], 100); + P_AddPlayerScore(&players[w], 1); } target->player->pflags |= PF_TAGGED; @@ -2224,6 +2277,10 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) } } } + else if (gametype == GT_MATCH) + { + K_CheckBalloons(); + } } if (source && target && target->player && source->player) @@ -2535,7 +2592,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) target->momy = FixedMul(FINESINE(fa),target->target->radius); } - player->powers[pw_flashing] = flashingtics; + player->powers[pw_flashing] = K_GetKartFlashing(player); P_SetMobjState(target->tracer, S_NIGHTSHURT1); S_StartSound(target, sfx_nghurt); @@ -2580,7 +2637,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou // The tag occurs so long as you aren't shooting another tagger with friendlyfire on. if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT)) { - P_AddPlayerScore(source->player, 100); //award points to tagger. + P_AddPlayerScore(source->player, 1); //award points to tagger. P_HitDeathMessages(player, inflictor, source); if (gametype == GT_TAG) //survivor @@ -2694,21 +2751,21 @@ 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))) + /*if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) { P_PlayerFlagBurst(player, false); if (source && source->player) { // Award no points when players shoot each other when cv_friendlyfire is on. if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, 25); + P_AddPlayerScore(source->player, 1); } } if (source && source->player && !player->powers[pw_super]) //don't score points against super players { // Award no points when players shoot each other when cv_friendlyfire is on. if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, 100); + P_AddPlayerScore(source->player, 1); } // If the player was super, tell them he/she ain't so super nomore. @@ -2718,6 +2775,18 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) HU_SetCEchoFlags(0); HU_SetCEchoDuration(5); HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players])); + }*/ + + if (gametype != GT_RACE) + { + if (player->kartstuff[k_balloon] > 0) + { + if (player->kartstuff[k_balloon] == 1) + CONS_Printf(M_GetText("%s lost all of their balloons!\n"), player_names[player-players]); + player->kartstuff[k_balloon]--; + } + + K_CheckBalloons(); } } @@ -2854,11 +2923,11 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN S_StartSound(player->mo, sfx_spkdth); } - if (source && source->player && !player->powers[pw_super]) //don't score points against super players + /*if (source && source->player && !player->powers[pw_super]) //don't score points against super players { // Award no points when players shoot each other when cv_friendlyfire is on. if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, 50); + P_AddPlayerScore(source->player, 1); } if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) @@ -2868,9 +2937,9 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN { // Award no points when players shoot each other when cv_friendlyfire is on. if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) - P_AddPlayerScore(source->player, 25); + P_AddPlayerScore(source->player, 1); } - } + }*/ // Ring loss sound plays despite hitting spikes P_PlayRinglossSound(player->mo); // Ringledingle! @@ -3092,7 +3161,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da { // Just need to do this now! Being thrown upwards is done by the explosion. P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUELIGHTNING); - P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUEEXPLOSION); + mobj_t *blueexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BLUEEXPLOSION); + P_SetTarget(&blueexplode->target, source); return true; } else if (damage == 65 && player->kartstuff[k_position] > 1) @@ -3124,17 +3194,29 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; else { - player->kartstuff[k_spinouttype] = 1; - K_SpinPlayer(player, source); - damage = player->mo->health - 1; - P_RingDamage(player, inflictor, source, damage); - if (inflictor && (inflictor->type == MT_GREENITEM || inflictor->type == MT_REDITEM || inflictor->type == MT_REDITEMDUD)) - P_PlayerRingBurst(player, 5); - player->mo->momx = player->mo->momy = 0; - if (P_IsLocalPlayer(player)) + if (inflictor && (inflictor->type == MT_GREENITEM || inflictor->type == MT_GREENSHIELD + || inflictor->type == MT_REDITEM || inflictor->type == MT_REDSHIELD || inflictor->type == MT_REDITEMDUD + || inflictor->type == MT_FAKEITEM || inflictor->type == MT_FAKESHIELD + || inflictor->type == MT_TRIPLEGREENSHIELD1 || inflictor->type == MT_TRIPLEGREENSHIELD2 || inflictor->type == MT_TRIPLEGREENSHIELD3 + || inflictor->type == MT_TRIPLEREDSHIELD1 || inflictor->type == MT_TRIPLEREDSHIELD2 || inflictor->type == MT_TRIPLEREDSHIELD3 + || inflictor->player)) { - quake.intensity = 32*FRACUNIT; - quake.time = 5; + player->kartstuff[k_spinouttype] = 1; + K_SpinPlayer(player, source); + damage = player->mo->health - 1; + P_RingDamage(player, inflictor, source, damage); + P_PlayerRingBurst(player, 5); + player->mo->momx = player->mo->momy = 0; + if (P_IsLocalPlayer(player)) + { + quake.intensity = 32*FRACUNIT; + quake.time = 5; + } + } + else + { + player->kartstuff[k_spinouttype] = -1; + K_SpinPlayer(player, source); } return true; } @@ -3227,7 +3309,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da player->health -= damage; // mirror mobj health here if (damage < 10000) { - target->player->powers[pw_flashing] = flashingtics; + target->player->powers[pw_flashing] = K_GetKartFlashing(target->player); if (damage > 0) // don't spill emeralds/ammo/panels for shield damage P_PlayerRingBurst(player, damage); } diff --git a/src/p_local.h b/src/p_local.h index c86256ae..8d27d69e 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -153,7 +153,7 @@ void P_DoJumpShield(player_t *player); void P_BlackOw(player_t *player); void P_ElementalFireTrail(player_t *player); -void P_DoPityCheck(player_t *player); +//void P_DoPityCheck(player_t *player); void P_PlayerThink(player_t *player); void P_PlayerAfterThink(player_t *player); void P_DoPlayerExit(player_t *player); @@ -201,6 +201,7 @@ extern size_t iquehead, iquetail; extern consvar_t cv_gravity, cv_viewheight; void P_RespawnSpecials(void); +void P_RespawnBattleSpecials(void); mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); @@ -326,7 +327,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam); boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); boolean P_Move(mobj_t *actor, fixed_t speed); boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); -void P_SlideMove(mobj_t *mo); +void P_SlideMove(mobj_t *mo, boolean forceslide); void P_BounceMove(mobj_t *mo); boolean P_CheckSight(mobj_t *t1, mobj_t *t2); void P_CheckHoopPosition(mobj_t *hoopthing, fixed_t x, fixed_t y, fixed_t z, fixed_t radius); diff --git a/src/p_map.c b/src/p_map.c index bf7ad90d..982d544e 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -320,6 +320,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) } } +#if 0 static void P_DoTailsCarry(player_t *sonic, player_t *tails) { INT32 p; @@ -400,6 +401,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) sonic->pflags &= ~PF_CARRIED; } } +#endif // // PIT_CheckThing @@ -673,6 +675,10 @@ static boolean PIT_CheckThing(mobj_t *thing) && (tmthing->target == thing->target)) // Don't hit each other if you have the same target return true; + if (thing->player && thing->player->powers[pw_flashing] + && !(tmthing->type == MT_GREENITEM || tmthing->type == MT_REDITEM || tmthing->type == MT_REDITEMDUD)) + return true; + if (thing->type == MT_PLAYER) { // Player Damage @@ -808,6 +814,9 @@ static boolean PIT_CheckThing(mobj_t *thing) if (((tmthing->target == thing) || (tmthing->target == thing->target)) && (tmthing->threshold > 0 || (thing->type != MT_PLAYER && thing->threshold > 0))) return true; + if (thing->player && thing->player->powers[pw_flashing]) + return true; + if (thing->type == MT_PLAYER) { S_StartSound(NULL, sfx_cgot); //let all players hear it. @@ -832,6 +841,9 @@ static boolean PIT_CheckThing(mobj_t *thing) if (!(thing->type == MT_PLAYER)) return true; + if (thing->player && thing->player->powers[pw_flashing]) + return true; + if (thing->type == MT_PLAYER) { K_SpinPlayer(thing->player, tmthing->target); @@ -863,6 +875,9 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->type == MT_FIREBALL && thing->type == MT_FIREBALL) return true; // Fireballs don't collide with eachother + if (thing->player && thing->player->powers[pw_flashing]) + return true; + if (thing->type == MT_PLAYER) { // Player Damage @@ -960,6 +975,9 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->health <= 0 || thing->health <= 0) return true; + if (thing->player && thing->player->powers[pw_flashing]) + return true; + if (thing->type == MT_GREENITEM // When these items collide with the fake item, just the fake item is destroyed || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD || thing->type == MT_BOMBITEM @@ -1043,6 +1061,9 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->health <= 0 || thing->health <= 0) return true; + if (thing->player && thing->player->powers[pw_flashing]) + return true; + if (thing->type == MT_PLAYER) { P_KillMobj(tmthing, thing, thing); @@ -1087,6 +1108,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath + if (tmthing->player && tmthing->player->powers[pw_flashing] + && !(thing->type == MT_GREENITEM || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD)) + return true; + if (thing->type == MT_GREENSHIELD || thing->type == MT_TRIPLEGREENSHIELD1 || thing->type == MT_TRIPLEGREENSHIELD2 || thing->type == MT_TRIPLEGREENSHIELD3 || thing->type == MT_REDSHIELD || thing->type == MT_TRIPLEREDSHIELD1 || thing->type == MT_TRIPLEREDSHIELD2 || thing->type == MT_TRIPLEREDSHIELD3 || thing->type == MT_GREENITEM || thing->type == MT_REDITEM || thing->type == MT_REDITEMDUD @@ -1534,7 +1559,8 @@ static boolean PIT_CheckThing(mobj_t *thing) } // Force solid players in hide and seek to avoid corner stacking. - if (cv_tailspickup.value && gametype != GT_HIDEANDSEEK) + // Kart: No Tailspickup ever, players are always solid + /*if (cv_tailspickup.value && gametype != GT_HIDEANDSEEK) { if (tmthing->player && thing->player) { @@ -1546,7 +1572,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->player-players == consoleplayer && botingame) CV_SetValue(&cv_analog2, true); thing->player->pflags &= ~PF_CARRIED; - } + }*/ if (thing->player) { @@ -1592,6 +1618,101 @@ static boolean PIT_CheckThing(mobj_t *thing) && tmthing->z <= thing->z + thing->height) iwassprung = P_DoSpring(thing, tmthing); } + else if (thing->player) // bounce when players collide + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + if (thing->player->kartstuff[k_growshrinktimer] || thing->player->kartstuff[k_squishedtimer] + || thing->player->kartstuff[k_bootimer] || thing->player->kartstuff[k_spinouttimer] + || thing->player->kartstuff[k_startimer] || thing->player->kartstuff[k_justbumped] + || (gametype != GT_RACE && (thing->player->kartstuff[k_balloon] <= 0 + && (thing->player->kartstuff[k_comebacktimer] || thing->player->kartstuff[k_comebackmode] == 1))) + || tmthing->player->kartstuff[k_growshrinktimer] || tmthing->player->kartstuff[k_squishedtimer] + || tmthing->player->kartstuff[k_bootimer] || tmthing->player->kartstuff[k_spinouttimer] + || tmthing->player->kartstuff[k_startimer] || tmthing->player->kartstuff[k_justbumped] + || (gametype != GT_RACE && (tmthing->player->kartstuff[k_balloon] <= 0 + && (tmthing->player->kartstuff[k_comebacktimer] || tmthing->player->kartstuff[k_comebackmode] == 1)))) + { + return true; + } + + if (gametype != GT_RACE) + { + if ((thing->player->kartstuff[k_balloon] <= 0 || tmthing->player->kartstuff[k_balloon] <= 0) + && (thing->player->kartstuff[k_comebackmode] == 0 && tmthing->player->kartstuff[k_comebackmode] == 0)) + { + if (tmthing->player->kartstuff[k_balloon] > 0) + { + thing->player->kartstuff[k_comebackpoints] += 2; + CONS_Printf(M_GetText("%s bombed %s!\n"), player_names[thing->player-players], player_names[tmthing->player-players]); + + if (thing->player->kartstuff[k_comebackpoints] >= 3) + K_StealBalloon(thing->player, tmthing->player, true); + + K_ExplodePlayer(tmthing->player, thing); + + thing->player->kartstuff[k_comebacktimer] = comebacktime; + return true; + } + else if (thing->player->kartstuff[k_balloon] > 0) + { + tmthing->player->kartstuff[k_comebackpoints] += 2; + CONS_Printf(M_GetText("%s bombed %s!\n"), player_names[tmthing->player-players], player_names[thing->player-players]); + + if (tmthing->player->kartstuff[k_comebackpoints] >= 3) + K_StealBalloon(tmthing->player, thing->player, true); + + K_ExplodePlayer(thing->player, tmthing); + + tmthing->player->kartstuff[k_comebacktimer] = comebacktime; + return true; + } + } + } + + if (P_IsObjectOnGround(thing) && tmthing->momz < 0) + { + K_KartBouncing(tmthing, thing, true); + if (gametype != GT_RACE && tmthing->player->kartstuff[k_feather] & 2) + { + K_StealBalloon(tmthing->player, thing->player, false); + K_SpinPlayer(thing->player, tmthing); + } + } + else if (P_IsObjectOnGround(tmthing) && thing->momz < 0) + { + K_KartBouncing(thing, tmthing, true); + if (gametype != GT_RACE && thing->player->kartstuff[k_feather] & 2) + { + K_StealBalloon(thing->player, tmthing->player, false); + K_SpinPlayer(tmthing->player, thing); + } + } + else + K_KartBouncing(tmthing, thing, false); + + if (gametype != GT_RACE) + { + if (thing->player->kartstuff[k_mushroomtimer] && !(tmthing->player->kartstuff[k_mushroomtimer])) + { + K_StealBalloon(thing->player, tmthing->player, false); + K_SpinPlayer(tmthing->player, thing); + } + else if (tmthing->player->kartstuff[k_mushroomtimer] && !(thing->player->kartstuff[k_mushroomtimer])) + { + K_StealBalloon(tmthing->player, thing->player, false); + K_SpinPlayer(thing->player, tmthing); + } + } + + thing->player->kartstuff[k_justbumped] = 6; + tmthing->player->kartstuff[k_justbumped] = 6; + return true; + } // Are you touching the side of the object you're interacting with? else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height && thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) >= tmthing->z) @@ -2613,7 +2734,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (!(thing->flags & MF_NOCLIP)) { //All things are affected by their scale. - fixed_t maxstep = FixedMul(MAXSTEPMOVE, thing->scale); + fixed_t maxstep = MAXSTEPMOVE; //FixedMul(MAXSTEPMOVE, thing->scale); if (thing->player) { @@ -3522,7 +3643,7 @@ stairstep: // // This is a kludgy mess. // -void P_SlideMove(mobj_t *mo) +void P_SlideMove(mobj_t *mo, boolean forceslide) { fixed_t leadx, leady, trailx, traily, newx, newy; INT16 hitcount = 0; @@ -3600,7 +3721,7 @@ retry: PT_ADDLINES, PTR_SlideTraverse); // Some walls are bouncy even if you're not - if (bestslideline && !(bestslideline->flags & ML_BOUNCY)) // SRB2kart - All walls are bouncy unless specified otherwise + if (!forceslide && bestslideline && !(bestslideline->flags & ML_BOUNCY)) // SRB2kart - All walls are bouncy unless specified otherwise { P_BounceMove(mo); return; diff --git a/src/p_mobj.c b/src/p_mobj.c index db812519..a0295f4d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -216,11 +216,11 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) } } // You were in pain state after taking a hit, and you're moving out of pain state now? - else */if (mobj->state == &states[mobj->info->painstate] && player->powers[pw_flashing] == flashingtics && state != mobj->info->painstate) + else */if (mobj->state == &states[mobj->info->painstate] && player->powers[pw_flashing] == K_GetKartFlashing(player) && state != mobj->info->painstate) { // Start flashing, since you've landed. - player->powers[pw_flashing] = flashingtics-1; - P_DoPityCheck(player); + player->powers[pw_flashing] = K_GetKartFlashing(player)-1; + //P_DoPityCheck(player); } // Set animation state @@ -1331,6 +1331,8 @@ fixed_t P_GetMobjGravity(mobj_t *mo) } if (wasflip == !(mo->eflags & MFE_VERTICALFLIP)) // note!! == ! is not equivalent to != here - turns numeric into bool this way P_PlayerFlip(mo); + if (mo->player->kartstuff[k_feather] & 2) + gravityadd = FixedMul(gravityadd, 5*FRACUNIT/2); } else { @@ -1378,6 +1380,10 @@ fixed_t P_GetMobjGravity(mobj_t *mo) break; case MT_WATERDROP: gravityadd >>= 1; + case MT_BANANAITEM: + case MT_FAKEITEM: + case MT_BOMBITEM: + gravityadd = FixedMul(gravityadd, 5*FRACUNIT/2); default: break; } @@ -1809,7 +1815,7 @@ void P_XYMovement(mobj_t *mo) } else if (player || mo->flags & (MF_SLIDEME|MF_PUSHABLE)) { // try to slide along it - P_SlideMove(mo); + P_SlideMove(mo, false); xmove = ymove = 0; } else if (mo->type == MT_SPINFIRE) @@ -1990,7 +1996,7 @@ static void P_RingXYMovement(mobj_t *mo) I_Assert(!P_MobjWasRemoved(mo)); if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) - P_SlideMove(mo); + P_SlideMove(mo, false); } static void P_SceneryXYMovement(mobj_t *mo) @@ -2004,7 +2010,7 @@ static void P_SceneryXYMovement(mobj_t *mo) oldy = mo->y; if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) - P_SlideMove(mo); + P_SlideMove(mo, false); if ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z > mo->floorz) || (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height < mo->ceilingz)) return; // no friction when airborne @@ -2299,6 +2305,14 @@ static boolean P_ZMovement(mobj_t *mo) case MT_BIGTUMBLEWEED: case MT_LITTLETUMBLEWEED: case MT_SHELL: + // SRB2kart stuff that should die in pits + // Shouldn't stop moving along the Z if there's no speed though! + case MT_FAKEITEM: + case MT_BANANAITEM: + case MT_GREENITEM: + case MT_REDITEM: + case MT_REDITEMDUD: + case MT_FIREBALL: // Remove stuff from death pits. if (P_CheckDeathPitCollide(mo)) { @@ -2325,13 +2339,6 @@ static boolean P_ZMovement(mobj_t *mo) case MT_FLINGCOIN: case MT_FLINGRANDOMITEM: case MT_FLINGEMERALD: - // SRB2kart stuff that should die in pits - case MT_RANDOMITEM: - case MT_BANANAITEM: - case MT_GREENITEM: - case MT_REDITEM: - case MT_REDITEMDUD: - case MT_FIREBALL: // Remove flinged stuff from death pits. if (P_CheckDeathPitCollide(mo)) { @@ -6452,19 +6459,30 @@ void P_MobjThinker(mobj_t *mobj) //{ SRB2kart mobs case MT_DRIFT: { - fixed_t dsone = 26*4 + mobj->target->player->kartspeed*2 + (9 - mobj->target->player->kartweight); - fixed_t dstwo = dsone*2; - if ((mobj->target && mobj->target->player && mobj->target->player->mo && mobj->target->player->health > 0 && !mobj->target->player->spectator) - && (mobj->type == MT_DRIFT && mobj->target->player->kartstuff[k_driftcharge] >= dsone)) + if (mobj->target && mobj->target->player && mobj->target->player->mo && mobj->target->player->health > 0 && !mobj->target->player->spectator) { + UINT8 kartspeed = mobj->target->player->kartspeed; + fixed_t dsone, dstwo; INT32 HEIGHT; fixed_t radius; - if (mobj->target->player->kartstuff[k_bootaketimer] > 0) + if (gametype != GT_RACE && mobj->target->player->kartstuff[k_balloon] <= 0) + kartspeed = 1; + + dsone = 26*4 + kartspeed*2 + (9 - mobj->target->player->kartweight); + dstwo = dsone*2; + + if (mobj->target->player->kartstuff[k_driftcharge] < dsone) + { + P_RemoveMobj(mobj); + return; + } + + if (mobj->target->player->kartstuff[k_bootimer] > 0) { if ((mobj->target->player == &players[displayplayer] || (splitscreen && mobj->target->player == &players[secondarydisplayplayer])) || (!(mobj->target->player == &players[displayplayer] || (splitscreen && mobj->target->player == &players[secondarydisplayplayer])) - && (mobj->target->player->kartstuff[k_bootaketimer] < 1*TICRATE/2 || mobj->target->player->kartstuff[k_bootaketimer] > bootime-(1*TICRATE/2)))) + && (mobj->target->player->kartstuff[k_bootimer] < 1*TICRATE/2 || mobj->target->player->kartstuff[k_bootimer] > bootime-(1*TICRATE/2)))) { if (leveltime & 1) mobj->flags2 |= MF2_DONTDRAW; @@ -6474,7 +6492,7 @@ void P_MobjThinker(mobj_t *mobj) else mobj->flags2 |= MF2_DONTDRAW; } - else if (mobj->target->player->kartstuff[k_bootaketimer] == 0) + else if (mobj->target->player->kartstuff[k_bootimer] == 0) { mobj->flags2 &= ~MF2_DONTDRAW; } @@ -6540,15 +6558,8 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->health > 0 && mobj->target && mobj->target->player && mobj->target->player->mo && mobj->target->player->health > 0 && !mobj->target->player->spectator) { - INT32 zfixds = 56; - INT32 DIST = FixedMul(zfixds, mobj->target->scale); - INT32 HEIGHT; - const fixed_t radius = DIST*FRACUNIT; // mobj's distance from its Target, or Radius. - - if (mobj->type == MT_BANANASHIELD || mobj->type == MT_TRIPLEBANANASHIELD1 || mobj->type == MT_TRIPLEBANANASHIELD2 || mobj->type == MT_TRIPLEBANANASHIELD3) - zfixds = 64; - else - zfixds = 56; + fixed_t z; + const fixed_t radius = FixedHypot(mobj->target->radius, mobj->target->radius) + FixedHypot(mobj->radius, mobj->radius); // mobj's distance from its Target, or Radius. //mobj->angle += FixedAngle(12*FRACUNIT); // mobj's actual speed. if (mobj->type == MT_TRIPLEGREENSHIELD1 || mobj->type == MT_TRIPLEGREENSHIELD2 || mobj->type == MT_TRIPLEGREENSHIELD3 @@ -6565,26 +6576,51 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->target->player && mobj->target->eflags & MFE_VERTICALFLIP) { mobj->eflags |= MFE_VERTICALFLIP; - HEIGHT = mobj->target->height / 2; } else { mobj->eflags &= ~MFE_VERTICALFLIP; - HEIGHT = mobj->target->height / 5; } // Shrink your items if the player shrunk too. if (mobj->target->player) mobj->scale = mobj->target->scale; - P_UnsetThingPosition(mobj); + if (P_MobjFlip(mobj) > 0) { - const angle_t fa = mobj->angle>>ANGLETOFINESHIFT; - mobj->x = mobj->target->x + FixedMul(FINECOSINE(fa),radius); - mobj->y = mobj->target->y + FixedMul(FINESINE(fa), radius); - mobj->z = mobj->target->z + HEIGHT; - P_SetThingPosition(mobj); + z = mobj->target->z; } + else + { + z = mobj->target->z + mobj->target->height - mobj->height; + } + + mobj->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, z); + mobj->momx = FixedMul(FINECOSINE(mobj->angle>>ANGLETOFINESHIFT),radius); + mobj->momy = FixedMul(FINESINE(mobj->angle>>ANGLETOFINESHIFT), radius); + mobj->flags &= ~MF_NOCLIPTHING; + if (!P_TryMove(mobj, mobj->target->x + mobj->momx, mobj->target->y + mobj->momy, true)) + P_SlideMove(mobj, true); + if (P_IsObjectOnGround(mobj->target)) + { + if (P_MobjFlip(mobj) > 0) + { + if (mobj->floorz > mobj->target->z - mobj->height) + { + z = mobj->floorz; + } + } + else + { + if (mobj->ceilingz < mobj->target->z + mobj->target->height + mobj->height) + { + z = mobj->ceilingz - mobj->height; + } + } + } + mobj->z = z; + mobj->momx = mobj->momy = 0; // Was this so hard? if ((mobj->type == MT_GREENSHIELD && !(mobj->target->player->kartstuff[k_greenshell] & 1)) @@ -6615,6 +6651,163 @@ void P_MobjThinker(mobj_t *mobj) return; } break; + case MT_BATTLEBALLOON: + if (mobj->health > 0 && mobj->target && mobj->target->player && mobj->target->player->mo + && mobj->target->player->health > 0 && !mobj->target->player->spectator) + { + fixed_t rad = 32*mobj->target->scale; + fixed_t offz; + angle_t ang, diff; + + if (!((mobj->target->player-players) & 1)) + ang = (FixedAngle(mobj->info->speed) * -1); + else + ang = FixedAngle(mobj->info->speed); + + if (mobj->target->player->kartstuff[k_balloon] <= 1) + diff = 0; + else + diff = FixedAngle(360*FRACUNIT/mobj->target->player->kartstuff[k_balloon]); + + ang = (ang*leveltime) + (diff * (mobj->threshold-1)); + + // If the player is on the ceiling, then flip your items as well. + if (mobj->target->eflags & MFE_VERTICALFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + offz = mobj->target->height / 2; + } + else + { + mobj->eflags &= ~MFE_VERTICALFLIP; + offz = mobj->target->height / 5; + } + + if (mobj->target->flags2 & MF2_DONTDRAW) + mobj->flags2 |= MF2_DONTDRAW; + else + mobj->flags2 &= ~MF2_DONTDRAW; + + if (mobj->target->eflags & MFE_VERTICALFLIP) + offz += 4*FRACUNIT; + else + offz -= 4*FRACUNIT; + + if (mobj->tracer && mobj->tracer->player && mobj->tracer->player->mo + && mobj->tracer->player->health > 0 && !mobj->tracer->player->spectator) // STOLEN + mobj->color = mobj->tracer->player->skincolor; // don't do star flashing for stolen balloons + else + mobj->color = mobj->target->color; // but do so if it belongs to you :B + + if (mobj->target->player->kartstuff[k_balloon] < 2) + P_SetMobjState(mobj, S_BATTLEBALLOON3); + else if (mobj->target->player->kartstuff[k_balloon] < 3) + P_SetMobjState(mobj, S_BATTLEBALLOON2); + else + P_SetMobjState(mobj, S_BATTLEBALLOON1); + + // Shrink your items if the player shrunk too. + mobj->scale = mobj->target->scale; + + P_UnsetThingPosition(mobj); + { + const angle_t fa = ang>>ANGLETOFINESHIFT; + mobj->x = mobj->target->x + FixedMul(FINECOSINE(fa), rad); + mobj->y = mobj->target->y + FixedMul(FINESINE(fa), rad); + mobj->z = mobj->target->z + offz; + P_SetThingPosition(mobj); + } + + // Was this so hard? + if (mobj->target->player->kartstuff[k_balloon] <= mobj->threshold) + { + P_RemoveMobj(mobj); + return; + } + } + else if ((mobj->health > 0 + && (!mobj->target || !mobj->target->player || !mobj->target->player->mo || mobj->target->player->health <= 0 || mobj->target->player->spectator)) + || (mobj->health <= 0 && mobj->z <= mobj->floorz) + || P_CheckDeathPitCollide(mobj)) // When in death state + { + P_RemoveMobj(mobj); + return; + } + break; + case MT_PLAYERARROW: + if (mobj->target && mobj->target->health + && mobj->target->player && mobj->target->player->mo + && mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD) + { + fixed_t scale = mobj->target->scale; + mobj->color = mobj->target->color; + + if ((splitscreen || !netgame) + || gametype == GT_RACE + || mobj->target->player == &players[displayplayer] + || mobj->target->player->kartstuff[k_balloon] <= 0 + || (mobj->target->player->mo->flags2 & MF2_DONTDRAW)) + mobj->flags2 |= MF2_DONTDRAW; + else + mobj->flags2 &= ~MF2_DONTDRAW; + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + + if (!(mobj->target->eflags & MFE_VERTICALFLIP)) + { + mobj->z = mobj->target->z + P_GetPlayerHeight(mobj->target->player)+16*FRACUNIT; + mobj->eflags &= ~MFE_VERTICALFLIP; + } + else + { + mobj->z = mobj->target->z - P_GetPlayerHeight(mobj->target->player)+16*FRACUNIT; + mobj->eflags |= MFE_VERTICALFLIP; + } + P_SetThingPosition(mobj); + + // Set it to use the correct states for its condition + if (mobj->target->player->kartstuff[k_itemroulette]) + { + if (mobj->state != &states[S_PLAYERARROW_ROULETTE]) // don't reset FF_ANIMATE + P_SetMobjState(mobj, S_PLAYERARROW_ROULETTE); + } + else if (mobj->target->player->kartstuff[k_kitchensink]) P_SetMobjState(mobj, S_PLAYERARROW_KITCHENSINK); + else if (mobj->target->player->kartstuff[k_megashroom] == 1 + || (mobj->target->player->kartstuff[k_growshrinktimer] > 1 + && (leveltime & 1))) P_SetMobjState(mobj, S_PLAYERARROW_MEGASHROOM); + else if (mobj->target->player->kartstuff[k_growshrinktimer] > 1 + && !(leveltime & 1)) P_SetMobjState(mobj, S_PLAYERARROW_EMPTY); // S_INVISIBLE + else if (mobj->target->player->kartstuff[k_star] == 1) P_SetMobjState(mobj, S_PLAYERARROW_STAR); + else if (mobj->target->player->kartstuff[k_tripleredshell]) P_SetMobjState(mobj, S_PLAYERARROW_TRIPLEREDSHELL); + else if (mobj->target->player->kartstuff[k_triplebanana]) P_SetMobjState(mobj, S_PLAYERARROW_TRIPLEBANANA); + else if (mobj->target->player->kartstuff[k_triplegreenshell]) P_SetMobjState(mobj, S_PLAYERARROW_TRIPLEGREENSHELL); + else if (mobj->target->player->kartstuff[k_fireflower]) P_SetMobjState(mobj, S_PLAYERARROW_FIREFLOWER); + else if (mobj->target->player->kartstuff[k_bobomb]) P_SetMobjState(mobj, S_PLAYERARROW_BOBOMB); + else if (mobj->target->player->kartstuff[k_redshell]) P_SetMobjState(mobj, S_PLAYERARROW_REDSHELL); + else if (mobj->target->player->kartstuff[k_feather] & 1) P_SetMobjState(mobj, S_PLAYERARROW_FEATHER); + else if (mobj->target->player->kartstuff[k_boo] == 1) P_SetMobjState(mobj, S_PLAYERARROW_BOO); + else if (mobj->target->player->kartstuff[k_fakeitem] & 2) P_SetMobjState(mobj, S_PLAYERARROW_FAKEITEM); + else if (mobj->target->player->kartstuff[k_banana]) P_SetMobjState(mobj, S_PLAYERARROW_BANANA); + else if (mobj->target->player->kartstuff[k_greenshell]) P_SetMobjState(mobj, S_PLAYERARROW_GREENSHELL); + else if (mobj->target->player->kartstuff[k_mushroom]) P_SetMobjState(mobj, S_PLAYERARROW_MUSHROOM); + else P_SetMobjState(mobj, S_PLAYERARROW); // S_INVISIBLE + + scale += FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayer].mo->x-mobj->target->x, + players[displayplayer].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale); + if (scale > 16*FRACUNIT) + { + scale = 16*FRACUNIT; + } + mobj->destscale = scale; + } + else if (mobj->health > 0) + { + P_KillMobj(mobj, NULL, NULL); + return; + } + break; //} case MT_WATERDROP: P_SceneryCheckWater(mobj); @@ -7486,15 +7679,16 @@ void P_MobjThinker(mobj_t *mobj) break; case MT_GREENITEM: { + sector_t *sec2; fixed_t finalspeed = mobj->info->speed; P_SpawnGhostMobj(mobj); - if (cv_kartcc.value == 50) + if (K_GetKartCC() == 50) { finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); } - else if (cv_kartcc.value == 150) + else if (K_GetKartCC() == 150) { finalspeed = FixedMul(finalspeed, FRACUNIT+FRACUNIT/4); } @@ -7513,14 +7707,21 @@ void P_MobjThinker(mobj_t *mobj) { P_InstaThrust(mobj, mobj->angle, finalspeed); } + + sec2 = P_ThingOnSpecial3DFloor(mobj); + if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) || (P_IsObjectOnGround(mobj) && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) + K_DoBouncePad(mobj, 0); + if (mobj->threshold > 0) mobj->threshold--; + if (leveltime % 6 == 0) S_StartSound(mobj, mobj->info->activesound); break; } case MT_REDITEM: { + sector_t *sec2; fixed_t topspeed = 64*FRACUNIT; fixed_t distbarrier = 512*FRACUNIT; fixed_t distaway; @@ -7532,18 +7733,18 @@ void P_MobjThinker(mobj_t *mobj) if (leveltime % 7 == 0) S_StartSound(mobj, mobj->info->activesound); - if (cv_kartcc.value == 50) + if (K_GetKartCC() == 50) { topspeed = FixedMul(topspeed, FRACUNIT-FRACUNIT/4); distbarrier = FixedMul(distbarrier, FRACUNIT-FRACUNIT/4); } - else if (cv_kartcc.value == 150) + else if (K_GetKartCC() == 150) { topspeed = FixedMul(topspeed, FRACUNIT+FRACUNIT/4); distbarrier = FixedMul(distbarrier, FRACUNIT+FRACUNIT/4); } - if (mobj->tracer) + if (gametype == GT_RACE && mobj->tracer) { distaway = P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y); if (distaway < distbarrier) @@ -7557,17 +7758,33 @@ void P_MobjThinker(mobj_t *mobj) } P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), topspeed); + + sec2 = P_ThingOnSpecial3DFloor(mobj); + if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) || (P_IsObjectOnGround(mobj) && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) + K_DoBouncePad(mobj, 0); + break; } case MT_REDITEMDUD: + { + sector_t *sec2; + P_SpawnGhostMobj(mobj); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->x+mobj->momx, mobj->y+mobj->momy); P_InstaThrust(mobj, mobj->angle, mobj->info->speed); + + sec2 = P_ThingOnSpecial3DFloor(mobj); + if ((sec2 && GETSECSPECIAL(sec2->special, 3) == 1) || (P_IsObjectOnGround(mobj) && GETSECSPECIAL(mobj->subsector->sector->special, 3) == 1)) + K_DoBouncePad(mobj, 0); + if (mobj->threshold > 0) mobj->threshold--; + if (leveltime % 7 == 0) S_StartSound(mobj, mobj->info->activesound); + break; + } case MT_BANANAITEM: case MT_FAKEITEM: if (mobj->momx || mobj->momy) @@ -8387,6 +8604,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_COIN: case MT_BLUEBALL: nummaprings++; + break; default: break; } @@ -8401,10 +8619,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_GREENITEM: case MT_GREENSHIELD: case MT_TRIPLEGREENSHIELD1: case MT_TRIPLEGREENSHIELD2: case MT_TRIPLEGREENSHIELD3: case MT_REDITEM: case MT_REDSHIELD: case MT_REDITEMDUD: - case MT_TRIPLEREDSHIELD1: case MT_TRIPLEREDSHIELD2: case MT_TRIPLEREDSHIELD3: + case MT_TRIPLEREDSHIELD1: case MT_TRIPLEREDSHIELD2: case MT_TRIPLEREDSHIELD3: + case MT_BATTLEBALLOON: case MT_FIREBALL: case MT_FAKEITEM: case MT_FAKESHIELD: case MT_BOMBITEM: case MT_BOMBSHIELD: - case MT_FIREBALL: P_SpawnShadowMobj(mobj); default: break; @@ -8978,6 +9196,12 @@ void P_RespawnSpecials(void) mobj_t *mo = NULL; mapthing_t *mthing = NULL; + if (gametype != GT_RACE) // Battle Mode vers + { + P_RespawnBattleSpecials(); + return; + } + // only respawn items when cv_itemrespawn is on if (!cv_itemrespawn.value) return; @@ -9059,6 +9283,97 @@ void P_RespawnSpecials(void) iquetail = (iquetail+1)&(ITEMQUESIZE-1); } +// +// P_RespawnBattleSpecials +// +void P_RespawnBattleSpecials(void) +{ + fixed_t x, y, z; + subsector_t *ss; + mobj_t *mo = NULL; + mapthing_t *mthing = NULL; + + // only respawn items when cv_itemrespawn is on + if (!cv_itemrespawn.value) + return; + + // Didn't collect enough boxes + if (numgotboxes < (4*nummapboxes/5)) + return; + + // wait a teeeensy bit after collecting everything + if (leveltime - itemrespawntime[iquehead-1] < (tic_t)cv_itemrespawntime.value*(5*TICRATE)) + return; + + while (iquehead != iquetail) // respawn EVERYTHING in que! + { + mthing = itemrespawnque[iquetail]; + +#ifdef PARANOIA + if (!mthing) + I_Error("itemrespawnque[iquetail] is NULL!"); +#endif + + if (mthing) + { + mobjtype_t i; + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + ss = R_PointInSubsector(x, y); + + // find which type to spawn + for (i = 0; i < NUMMOBJTYPES; i++) + if (mthing->type == mobjinfo[i].doomednum) + break; + + //CTF rings should continue to respawn as normal rings outside of CTF. + if (gametype != GT_CTF) + { + if (i == MT_REDTEAMRING || i == MT_BLUETEAMRING) + i = MT_RING; + } + + if (mthing->options & MTF_OBJECTFLIP) + { + z = ( +#ifdef ESLOPE + ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : +#endif + ss->sector->ceilingheight) - (mthing->options >> ZSHIFT) * FRACUNIT; + if (mthing->options & MTF_AMBUSH + && (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN || P_WeaponOrPanel(i))) + z -= 24*FRACUNIT; + z -= mobjinfo[i].height; // Don't forget the height! + } + else + { + z = ( +#ifdef ESLOPE + ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : +#endif + ss->sector->floorheight) + (mthing->options >> ZSHIFT) * FRACUNIT; + if (mthing->options & MTF_AMBUSH + && (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN || P_WeaponOrPanel(i))) + z += 24*FRACUNIT; + } + + mo = P_SpawnMobj(x, y, z, i); + mo->spawnpoint = mthing; + mo->angle = ANGLE_45 * (mthing->angle/45); + + if (mthing->options & MTF_OBJECTFLIP) + { + mo->eflags |= MFE_VERTICALFLIP; + mo->flags2 |= MF2_OBJECTFLIP; + } + } + // pull it from the que + iquetail = (iquetail+1)&(ITEMQUESIZE-1); + } + + numgotboxes = 0; +} + // // P_SpawnPlayer // Called when a player is spawned on the level. @@ -9068,6 +9383,7 @@ void P_SpawnPlayer(INT32 playernum) { player_t *p = &players[playernum]; mobj_t *mobj; + mobj_t *overheadarrow; if (p->playerstate == PST_REBORN) G_PlayerReborn(playernum); @@ -9077,13 +9393,13 @@ void P_SpawnPlayer(INT32 playernum) { // Special case for (NiGHTS) special stages! // if stage has already started, force players to become spectators until the next stage - if (multiplayer && netgame && G_IsSpecialStage(gamemap) && useNightsSS && leveltime > 0) + /*if (multiplayer && netgame && G_IsSpecialStage(gamemap) && useNightsSS && leveltime > 0) p->spectator = true; - else + else*/ p->spectator = false; } else if (netgame && p->jointime < 1) - p->spectator = true; + /*p->spectator = true*/; else if (multiplayer && !netgame) { // If you're in a team game and you don't have a team assigned yet... @@ -9153,7 +9469,62 @@ void P_SpawnPlayer(INT32 playernum) P_FlashPal(p, 0, 0); // Resets // Spawn with a pity shield if necessary. - P_DoPityCheck(p); + //P_DoPityCheck(p); + + overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + P_GetPlayerHeight(p)+16*FRACUNIT, MT_PLAYERARROW); + P_SetTarget(&overheadarrow->target, mobj); + overheadarrow->flags2 |= MF2_DONTDRAW; + P_SetScale(overheadarrow, mobj->destscale); + + if (gametype != GT_RACE) + { + /*INT32 i; + INT32 pcount = 0; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || &players[i] == p) + continue; + if (players[i].jointime > 0) + continue; + pcount++; + }*/ + + if (p->kartstuff[k_balloon] > 0 || leveltime < 1/* || pcount <= 1*/) // srb2kart + { + INT32 i; + angle_t newangle; + angle_t diff; + fixed_t newx; + fixed_t newy; + mobj_t *mo; + + if (leveltime < 1 /*|| pcount <= 1*/) // Start of the map? + p->kartstuff[k_balloon] = cv_kartballoons.value; // Reset those balloons! + + if (p->kartstuff[k_balloon] <= 1) + diff = 0; + else + diff = FixedAngle(360*FRACUNIT/p->kartstuff[k_balloon]); + + newangle = mobj->angle; + newx = mobj->x + P_ReturnThrustX(mobj, newangle + ANGLE_180, 64*FRACUNIT); + newy = mobj->y + P_ReturnThrustY(mobj, newangle + ANGLE_180, 64*FRACUNIT); + + for (i = 0; i < p->kartstuff[k_balloon]; i++) + { + mo = P_SpawnMobj(newx, newy, mobj->z, MT_BATTLEBALLOON); + mo->threshold = i; + P_SetTarget(&mo->target, mobj); + mo->angle = (diff * (i-1)); + mo->color = mobj->color; + if (mobj->flags2 & MF2_DONTDRAW) + mo->flags2 |= MF2_DONTDRAW; + else + mo->flags2 &= ~MF2_DONTDRAW; + } + } + } } void P_AfterPlayerSpawn(INT32 playernum) diff --git a/src/p_saveg.c b/src/p_saveg.c index d5a84136..847ba1a9 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -138,8 +138,6 @@ static void P_NetArchivePlayers(void) WRITEUINT16(save_p, players[i].powers[j]); for (j = 0; j < NUMKARTSTUFF; j++) WRITEINT32(save_p, players[i].kartstuff[j]); - for (j = 0; j < MAXPLAYERS; j++) - WRITEUINT8(save_p, players[i].collide[j]); WRITEANGLE(save_p, players[i].frameangle); @@ -323,8 +321,6 @@ static void P_NetUnArchivePlayers(void) players[i].powers[j] = READUINT16(save_p); for (j = 0; j < NUMKARTSTUFF; j++) players[i].kartstuff[j] = READINT32(save_p); - for (j = 0; j < MAXPLAYERS; j++) - players[i].collide[j] = (boolean)READUINT8(save_p); players[i].frameangle = READANGLE(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index e91acab6..c272464f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -983,6 +983,9 @@ static void P_LoadThings(void) || mt->type == 1702) // MT_AXISTRANSFERLINE continue; // These were already spawned + if (mt->type == 2000) // MT_RANDOMITEM + nummapboxes++; + mt->mobj = NULL; P_SpawnMapThing(mt); } @@ -2154,6 +2157,8 @@ static void P_LevelInitStuff(void) tokenbits = 0; runemeraldmanager = false; nummaprings = 0; + nummapboxes = 0; + numgotboxes = 0; // emerald hunt hunt1 = hunt2 = hunt3 = NULL; @@ -2566,8 +2571,7 @@ boolean P_SetupLevel(boolean skipprecip) // chasecam on in chaos, race, coop // chasecam off in match, tag, capture the flag - chase = (gametype == GT_RACE || gametype == GT_COMPETITION || gametype == GT_COOP) - || (maptol & TOL_2D); + chase = true; // srb2kart: always on if (!dedicated) { diff --git a/src/p_spec.c b/src/p_spec.c index a1e2a843..6ebeb466 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3728,7 +3728,18 @@ DoneSection2: // Process Section 3 switch (special) { - case 1: // Unused (was "Ice/Sludge") + case 1: // SRB2kart: bounce pad + if (!P_IsObjectOnGround(player->mo)) + break; + + if (player->speed < K_GetKartSpeed(player, true)/16 && !(player->mo->eflags & MFE_SPRUNG)) // Push forward to prevent getting stuck + P_InstaThrust(player->mo, player->mo->angle, FixedMul(K_GetKartSpeed(player, true)/16, player->mo->scale)); + + player->kartstuff[k_feather] |= 2; + K_DoBouncePad(player->mo, 0); + + break; + case 2: // Wind/Current case 3: // Unused (was "Ice/Sludge and Wind/Current") case 4: // Conveyor Belt @@ -3878,7 +3889,7 @@ DoneSection2: mo->spawnpoint = bflagpoint; mo->flags2 |= MF2_JUSTATTACKED; redscore += 1; - P_AddPlayerScore(player, 250); + P_AddPlayerScore(player, 5); } } break; @@ -3911,7 +3922,7 @@ DoneSection2: mo->spawnpoint = rflagpoint; mo->flags2 |= MF2_JUSTATTACKED; bluescore += 1; - P_AddPlayerScore(player, 250); + P_AddPlayerScore(player, 5); } } break; @@ -4099,12 +4110,12 @@ DoneSection2: case 10: // Finish Line // SRB2kart - 150117 - if (gametype == GT_RACE && (player->starpostnum == numstarposts || player->exiting)) + if (gametype == GT_RACE && (player->starpostcount >= numstarposts/2 || player->exiting)) player->kartstuff[k_starpostwp] = player->kartstuff[k_waypoint] = 0; // if (gametype == GT_RACE && !player->exiting) { - if (player->starpostnum == numstarposts) // Must have touched all the starposts + if (player->starpostcount >= numstarposts/2) // srb2kart: must have touched *enough* starposts (was originally "(player->starpostnum == numstarposts)") { player->laps++; player->kartstuff[k_lapanimation] = 80; @@ -4123,6 +4134,7 @@ DoneSection2: // SRB2kart 200117 player->starpostangle = player->starpostnum = 0; player->starpostx = player->starposty = player->starpostz = 0; + player->starpostcount = 0; //except the time! player->starposttime = player->realtime; @@ -7140,7 +7152,7 @@ void T_Friction(friction_t *f) // friction works for all mobj's // (or at least MF_PUSHABLEs, which is all I care about anyway) if ((!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && thing->z == thing->floorz) && (thing->player - && (thing->player->kartstuff[k_startimer] == 0 && thing->player->kartstuff[k_bootaketimer] == 0 + && (thing->player->kartstuff[k_startimer] == 0 && thing->player->kartstuff[k_bootimer] == 0 && thing->player->kartstuff[k_mushroomtimer] == 0 && thing->player->kartstuff[k_growshrinktimer] <= 0))) { if (f->roverfriction) @@ -7537,7 +7549,7 @@ void T_Pusher(pusher_t *p) if (thing->player && thing->player->pflags & PF_ROPEHANG) continue; - if (thing->player && (thing->state == &states[thing->info->painstate]) && (thing->player->powers[pw_flashing] > (flashingtics/4)*3 && thing->player->powers[pw_flashing] <= flashingtics)) + if (thing->player && (thing->state == &states[thing->info->painstate]) && (thing->player->powers[pw_flashing] > (K_GetKartFlashing(thing->player)/4)*3 && thing->player->powers[pw_flashing] <= K_GetKartFlashing(thing->player))) continue; inFOF = touching = moved = false; diff --git a/src/p_tick.c b/src/p_tick.c index 71bd3594..7ea98435 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -625,9 +625,6 @@ void P_Ticker(boolean run) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); - // SRB2kart - runs bounce collision for players - K_KartBouncer(); - #ifdef HAVE_BLUA LUAh_ThinkFrame(); #endif @@ -743,9 +740,6 @@ void P_PreTicker(INT32 frames) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); - // SRB2kart - runs bounce collision for players - K_KartBouncer(); - #ifdef HAVE_BLUA LUAh_ThinkFrame(); #endif diff --git a/src/p_user.c b/src/p_user.c index f70d589b..583a0547 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -853,17 +853,17 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) // Point penalty for hitting a hazard during tag. // Discourages players from intentionally hurting themselves to avoid being tagged. - if (gametype == GT_TAG && (!(player->pflags & PF_TAGGED) && !(player->pflags & PF_TAGIT))) + /*if (gametype == GT_TAG && (!(player->pflags & PF_TAGGED) && !(player->pflags & PF_TAGIT))) { - //if (player->score >= 50) - // player->score -= 50; - //else - // player->score = 0; - } + if (player->score >= 50) + player->score -= 50; + else + player->score = 0; + }*/ P_ResetPlayer(player); P_SetPlayerMobjState(player->mo, player->mo->info->painstate); - player->powers[pw_flashing] = flashingtics; + player->powers[pw_flashing] = K_GetKartFlashing(player); if (player->timeshit != UINT8_MAX) ++player->timeshit; @@ -1007,12 +1007,12 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) { UINT32 oldscore; - return; // SRB2kart - no score. - // This will probably be temporary until we do battle modes? - if (player->bot) player = &players[consoleplayer]; + if (player->exiting) // srb2kart + return; + // NiGHTS does it different! if (gamestate == GS_LEVEL && mapheaderinfo[gamemap-1]->typeoflevel & TOL_NIGHTS) { @@ -1607,9 +1607,7 @@ void P_DoPlayerExit(player_t *player) if (player->exiting) return; - if (cv_allowexitlevel.value == 0 && !G_PlatformGametype()) - return; - else if (gametype == GT_RACE || gametype == GT_COMPETITION) // If in Race Mode, allow + if (gametype == GT_RACE || gametype == GT_COMPETITION) // If in Race Mode, allow { // SRB2kart 120217 if (!countdown && !(netgame || multiplayer)) @@ -1652,6 +1650,8 @@ void P_DoPlayerExit(player_t *player) if (P_CheckRacers()) player->exiting = (14*TICRATE)/5 + 1; } + else if (gametype != GT_RACE) + player->exiting = 10*TICRATE + 2; // Accidental death safeguard??? else player->exiting = (14*TICRATE)/5 + 2; // Accidental death safeguard??? @@ -1668,8 +1668,8 @@ void P_DoPlayerExit(player_t *player) player->powers[pw_spacetime] = 0; P_RestoreMusic(player); - if (playeringame[player-players] && netgame && !circuitmap) - CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]); + /*if (playeringame[player-players] && netgame && !circuitmap) + CONS_Printf(M_GetText("%s has completed the level.\n"), player_names[player-players]);*/ } #define SPACESPECIAL 12 @@ -3557,7 +3557,7 @@ static void P_DoSuperStuff(player_t *player) } if (gametype != GT_COOP) - player->powers[pw_flashing] = flashingtics-1; + player->powers[pw_flashing] = K_GetKartFlashing(player)-1; /* if (player->mo->health > 0) @@ -5842,7 +5842,7 @@ static void P_NiGHTSMovement(player_t *player) } // Currently reeling from being hit. - if (player->powers[pw_flashing] > (2*flashingtics)/3) + if (player->powers[pw_flashing] > (2*K_GetKartFlashing(player))/3) { { const angle_t fa = (FixedAngle(player->flyangle*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; @@ -6499,7 +6499,7 @@ static void P_MovePlayer(player_t *player) */ cmd = &player->cmd; - runspd = FixedMul(player->runspeed, player->mo->scale); + runspd = 14*player->mo->scale; //srb2kart // Let's have some movement speed fun on low-friction surfaces, JUST for players... // (high friction surfaces shouldn't have any adjustment, since the acceleration in @@ -6700,10 +6700,12 @@ static void P_MovePlayer(player_t *player) { K_KartMoveAnimation(player); - player->frameangle = player->mo->angle; + if (player->kartstuff[k_feather] & 2) + player->frameangle += ANGLE_22h; + else + player->frameangle = player->mo->angle; } - player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame. // If you are stopped and are still walking, stand still! @@ -7935,13 +7937,8 @@ static void P_DeathThink(player_t *player) } //player->kartstuff[k_lakitu] = 48; // See G_PlayerReborn in g_game.c - // SRB2kart - spawn automatically after 1.5 seconds - if (player->deadtimer > (TICRATE + TICRATE/2) && (gametype == GT_RACE || player->spectator)) - player->playerstate = PST_REBORN; - - // SRB2kart - spawn after 1.5 seconds & Button press - if ((cmd->buttons & BT_JUMP || cmd->buttons & BT_ACCELERATE) && player->deadtimer > (TICRATE + TICRATE/2) - && (gametype == GT_RACE || player->spectator)) + // SRB2kart - spawn automatically after 1 second + if (player->deadtimer > TICRATE) player->playerstate = PST_REBORN; // Single player auto respawn @@ -8000,41 +7997,33 @@ static void P_DeathThink(player_t *player) } } - if (gametype == GT_RACE || gametype == GT_COMPETITION || (gametype == GT_COOP && (multiplayer || netgame))) + // Keep time rolling + if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_TIMEOVER)) + { + if (leveltime >= 4*TICRATE) + player->realtime = leveltime - 4*TICRATE; + else + player->realtime = 0; + } + + if ((gametype == GT_RACE || gametype == GT_COMPETITION || (gametype == GT_COOP && (multiplayer || netgame))) && (player->lives <= 0)) { - // Keep time rolling in race mode - if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_TIMEOVER)) - { - if (gametype == GT_RACE || gametype == GT_COMPETITION) - { - if (leveltime >= 4*TICRATE) - player->realtime = leveltime - 4*TICRATE; - else - player->realtime = 0; - } - else - player->realtime = leveltime; - } - // Return to level music - if (player->lives <= 0) + if (netgame) { - 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 other player's music once we're dead for long enough - // -- that is, as long as they aren't dead too - else if (player == &players[displayplayer] && players[secondarydisplayplayer].lives > 0) - P_RestoreMusic(&players[secondarydisplayplayer]); - else if (player == &players[secondarydisplayplayer] && players[displayplayer].lives > 0) - P_RestoreMusic(&players[displayplayer]); - } + if (player->deadtimer == gameovertics && P_IsLocalPlayer(player)) + S_ChangeMusic(mapmusname, mapmusflags, true); + } + else if (multiplayer) // local multiplayer only + { + if (player->deadtimer != gameovertics) + ; + // Restore the other player's music once we're dead for long enough + // -- that is, as long as they aren't dead too + else if (player == &players[displayplayer] && players[secondarydisplayplayer].lives > 0) + P_RestoreMusic(&players[secondarydisplayplayer]); + else if (player == &players[secondarydisplayplayer] && players[displayplayer].lives > 0) + P_RestoreMusic(&players[displayplayer]); } } @@ -8707,7 +8696,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } // Make player translucent if camera is too close (only in single player). - if (!(multiplayer || netgame) && !splitscreen) + /*if (!(multiplayer || netgame) && !splitscreen) { fixed_t vx = 0, vy = 0; if (player->awayviewtics) { @@ -8726,7 +8715,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall player->mo->flags2 &= ~MF2_SHADOW; } else - player->mo->flags2 &= ~MF2_SHADOW; + player->mo->flags2 &= ~MF2_SHADOW;*/ /* if (!resetcalled && (player->pflags & PF_NIGHTSMODE && player->exiting)) { @@ -8969,7 +8958,7 @@ static void P_CalcPostImg(player_t *player) #endif } -void P_DoPityCheck(player_t *player) +/*void P_DoPityCheck(player_t *player) { // No pity outside of match or CTF. if (player->spectator @@ -8986,7 +8975,7 @@ void P_DoPityCheck(player_t *player) player->powers[pw_shield] = SH_PITY; P_SpawnShieldOrb(player); } -} +}*/ // // P_PlayerThink @@ -9131,7 +9120,7 @@ void P_PlayerThink(player_t *player) // If it is set, start subtracting // Don't allow it to go back to 0 - if (player->exiting > 1 && player->exiting < 3*TICRATE && player->exiting > 1) // SRB2kart - " && player->exiting > 1" + if (player->exiting > 1 && (player->exiting < 3*TICRATE || gametype != GT_RACE)) // SRB2kart - "&& player->exiting > 1" player->exiting--; if (player->exiting && countdown2) @@ -9214,7 +9203,7 @@ void P_PlayerThink(player_t *player) playerdeadview = false; // SRB2kart 010217 - if (gametype == GT_RACE && leveltime < 4*TICRATE) + if (leveltime < 4*TICRATE) player->powers[pw_nocontrol] = 2; /* if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE) @@ -9228,15 +9217,10 @@ void P_PlayerThink(player_t *player) // Synchronizes the "real" amount of time spent in the level. if (!player->exiting) { - if (gametype == GT_RACE || gametype == GT_COMPETITION) - { - if (leveltime >= 4*TICRATE) - player->realtime = leveltime - 4*TICRATE; - else - player->realtime = 0; - } + if (leveltime >= 4*TICRATE) + player->realtime = leveltime - 4*TICRATE; else - player->realtime = leveltime; + player->realtime = 0; } if ((netgame || splitscreen) && player->spectator && cmd->buttons & BT_ATTACK && !player->powers[pw_flashing]) @@ -9391,7 +9375,7 @@ void P_PlayerThink(player_t *player) if (player->powers[pw_invulnerability] && player->powers[pw_invulnerability] < UINT16_MAX) player->powers[pw_invulnerability]--; - if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && ((player->pflags & PF_NIGHTSMODE) || player->powers[pw_flashing] < flashingtics)) + if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && ((player->pflags & PF_NIGHTSMODE) || player->powers[pw_flashing] < K_GetKartFlashing(player))) player->powers[pw_flashing]--; if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX && player->charability != CA_SWIM && !(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) // tails fly counter @@ -9480,9 +9464,10 @@ void P_PlayerThink(player_t *player) { // SRB2kart - fixes boo not flashing when it should. Mega doesn't flash either. Flashing is local. if ((player == &players[displayplayer] || (splitscreen && player == &players[secondarydisplayplayer])) - && player->kartstuff[k_bootaketimer] == 0 && player->kartstuff[k_growshrinktimer] <= 0) + && player->kartstuff[k_bootimer] == 0 && player->kartstuff[k_growshrinktimer] <= 0 + && (player->kartstuff[k_comebacktimer] == 0 || (gametype == GT_RACE || player->kartstuff[k_balloon] > 0))) { - if (player->powers[pw_flashing] > 0 && player->powers[pw_flashing] < flashingtics && (leveltime & 1)) + if (player->powers[pw_flashing] > 0 && player->powers[pw_flashing] < K_GetKartFlashing(player) && (leveltime & 1)) player->mo->flags2 |= MF2_DONTDRAW; else player->mo->flags2 &= ~MF2_DONTDRAW; diff --git a/src/r_things.c b/src/r_things.c index e370476c..d67a66ad 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1262,7 +1262,7 @@ static void R_ProjectSprite(mobj_t *thing) offset2 = FixedMul(spritecachedinfo[lump].width, this_scale); tx += FixedMul(offset2, ang_scale); - x2 = ((centerxfrac + FixedMul (tx,xscale)) >>FRACBITS) - 1; + x2 = ((centerxfrac + FixedMul (tx,xscale)) >> FRACBITS) - (papersprite ? 2 : 1); // off the left side if (x2 < 0) diff --git a/src/r_things.h b/src/r_things.h index 80c3d38c..6fd65c9b 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -91,8 +91,8 @@ typedef struct fixed_t maxdash; // SRB2kart - UINT8 kartspeed; // Normal ground - UINT8 kartweight; // Normal ground + UINT8 kartspeed; + UINT8 kartweight; // fixed_t normalspeed; // Normal ground diff --git a/src/sounds.c b/src/sounds.c index 75b5e259..22f966ee 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -498,10 +498,12 @@ sfxinfo_t S_sfx[NUMSFX] = {"mkitm7", true, 72, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"mkitm8", true, 72, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"mkitmF", true, 72, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"clash", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"tossed", false,150, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"shelit", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR}, - {"vroom", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"clash", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"tossed", false, 150, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"shelit", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR}, + {"vroom", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"boing", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"smkinv", false, 140, 16, -1, NULL, 0, -1, -1, LUMPERROR}, // SRB2kart - Skin sounds {"kwin", false, 64, 0, -1, NULL, 0, SKSWIN, -1, LUMPERROR}, diff --git a/src/sounds.h b/src/sounds.h index 20084985..9ffc3a87 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -574,6 +574,8 @@ typedef enum sfx_tossed, sfx_shelit, sfx_vroom, + sfx_boing, + sfx_smkinv, sfx_kwin, sfx_klose, diff --git a/src/st_stuff.c b/src/st_stuff.c index a05bb686..15343adc 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1922,14 +1922,14 @@ static void ST_overlayDrawer(void) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(116), 0, M_GetText("You cannot move while hiding.")); V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press F12 to watch another player.")); } - else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text. + /*else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text. { INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; if (respawntime > 0 && !stplyr->spectator) V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, va(M_GetText("Respawn in: %d second%s."), respawntime, respawntime == 1 ? "" : "s")); else V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Jump to respawn.")); - } + }*/ else if (stplyr->spectator #ifdef HAVE_BLUA && LUA_HudEnabled(hud_textspectator)