diff --git a/CMakeLists.txt b/CMakeLists.txt index 567ab0ee2..aac038881 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,7 @@ option(SRB2_CONFIG_TRACY "Compile with Tracy profiling enabled" OFF) option(SRB2_CONFIG_ASAN "Compile with AddressSanitizer (libasan)." OFF) set(SRB2_CONFIG_ASSET_DIRECTORY "" CACHE PATH "Path to directory that contains all asset files for the installer. If set, assets will be part of installation and cpack.") option(SRB2_CONFIG_LTO "Enable link time optimizations, improves performance at the cost of longer link times." ON) +option(SRB2_CONFIG_TIDY "Enable clang tiny, checks compiled code for issues at the cost of longer compile times." OFF) if(SRB2_CONFIG_ENABLE_TESTS) # https://github.com/catchorg/Catch2 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 07fc40d33..03cc0cb96 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,10 @@ if(SRB2_CONFIG_ASAN) target_link_options(SRB2SDL2 PRIVATE -fsanitize=address) endif() +if(SRB2_CONFIG_TIDY) + set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=*") +endif() + add_subdirectory(blua) add_subdirectory(blan) add_subdirectory(sdl) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index e98e1ddde..f779fdf41 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -160,6 +160,7 @@ static void KartChaining_OnChange(void); static void KartSlipdash_OnChange(void); static void KartSlopeBoost_OnChange(void); static void KartDrafting_OnChange(void); +static void KartAirDrop_OnChange(void); static void KartItemBreaker_OnChange(void); static void KartInvinType_OnChange(void); static void KartBumpSpark_OnChange(void); @@ -548,6 +549,8 @@ consvar_t cv_kartdrafting_closedraft = CVAR_INIT ("kartdrafting_closedraft", "Of consvar_t cv_kartdrafting_closedeadzone = CVAR_INIT ("kartdrafting_closedeadzone", "640", CV_NETVAR|CV_CHEAT, CV_Unsigned, NULL); consvar_t cv_kartdrafting_basedistance = CVAR_INIT ("kartdrafting_basedistance", "2560", CV_NETVAR|CV_CHEAT, CV_Unsigned, NULL); +consvar_t cv_kartairdrop = CVAR_INIT ("kartairdrop", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartAirDrop_OnChange); + // Invincibility modifiers static CV_PossibleValue_t invintype_cons_t[] = {{0, "Legacy"}, {1, "Alternative"}, {0, NULL}}; consvar_t cv_kartinvintype = CVAR_INIT ("kartinvintype", "Legacy", CV_NETVAR|CV_CALL, invintype_cons_t, KartInvinType_OnChange); @@ -7595,6 +7598,40 @@ static void KartDrafting_OnChange(void) } } + +static void KartAirDrop_OnChange(void) +{ + if (K_CanChangeRules() == false) + { + return; + } + + if (!K_AirDropActive() && cv_kartairdrop.value) + { + if (leveltime < starttime) + { + airdropactive = true; + CONS_Printf(M_GetText("Air Drop has been turned \"On\".\n")); + } + else + { + CONS_Printf(M_GetText("Air Drop will be turned \"On\" Next Round.\n")); + } + } + else if (K_AirDropActive() && !cv_kartairdrop.value) + { + if (leveltime < starttime) + { + airdropactive = false; + CONS_Printf(M_GetText("Drafting has been turned \"Off\".\n")); + } + else + { + CONS_Printf(M_GetText("Drafting will be turned \"Off\" next round.\n")); + } + } +} + static void KartItemBreaker_OnChange(void) { if (K_CanChangeRules() == false) diff --git a/src/d_netcmd.h b/src/d_netcmd.h index a0d2ea124..4fb975046 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -198,6 +198,8 @@ extern consvar_t cv_kartinvindistmul; extern consvar_t cv_kartinvin_maxtime; extern consvar_t cv_kartinvin_midtime; +extern consvar_t cv_kartairdrop; + extern consvar_t cv_encorevotes; extern consvar_t cv_votetime; diff --git a/src/d_player.h b/src/d_player.h index 04436637b..69bea329f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -683,12 +683,16 @@ struct player_t SINT8 ringmax; // maximum rings UINT8 pickuprings; // Number of rings being picked up before added to the counter (prevents rings from being deleted forever over 20) UINT8 ringdelay; // (0 to 3) - 3 tic delay between every ring usage + UINT8 ringlock; // Timer for automatic handeling of ringlock UINT16 ringboost; // Ring boost timer UINT16 ringtime; // The current Ring boost timer if it wasn't capped. Used for spam prevention measures. UINT16 superring; // Spawn rings on top of you every tic! UINT8 nextringaward; // When should we spawn our next superring ring? UINT8 ringvolume; // When consuming lots of rings, lower the sound a little. - UINT8 ringtransparency; // When consuming lots of rings, fade out the rings again. + UINT8 ringtransparency; // When consuming lots of rings, fade out the rings again. + + UINT8 airdroptime; // Tracks how long airdrop has been active, used for delay before airdrop kicks in. + boolean ringdrop; // Set when having ringdrop applied. UINT8 curshield; // see kartshields_t UINT8 bubblecool; // Bubble Shield use cooldown diff --git a/src/deh_soc.c b/src/deh_soc.c index 763bebb8f..e3f81a938 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1859,6 +1859,7 @@ static struct { const char *name; consvar_t *var; } HIDDENVARS[] = { { "DUMMYATTACKINGSLIPDASH", &cv_dummyattackingslipdash }, { "DUMMYATTACKINGPURPLEDRIFT", &cv_dummyattackingpurpledrift }, { "DUMMYATTACKINGSLOPEBOOST", &cv_dummyattackingslopeboost }, + { "DUMMYATTACKINGAIRDROP", &cv_dummyattackingairdrop }, { "DUMMYATTACKINGBUMPSPARK", &cv_dummyattackingbumpspark }, { "DUMMYSTAFF", &cv_dummystaff }, { "DUMMYMULTIPLAYER", &cv_dummymultiplayer }, diff --git a/src/deh_tables.c b/src/deh_tables.c index 73d87d268..4d13434bc 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1597,7 +1597,8 @@ struct int_const_s const INT_CONST[] = { {"TMBOT_NORUBBERBAND",TMBOT_NORUBBERBAND}, {"TMBOT_NOCONTROL",TMBOT_NOCONTROL}, {"TMBOT_FORCEDIR",TMBOT_FORCEDIR}, - //{"TMBOT_FASTFALL",TMBOT_FASTFALL}, + {"TMBOT_AIRDROP",TMBOT_AIRDROP}, + {"TMBOT_FASTFALL",TMBOT_AIRDROP}, // textmapbottrick_t /* diff --git a/src/doomdef.h b/src/doomdef.h index 7d85d7b85..02a2bfd1e 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -103,7 +103,7 @@ extern "C" { // Special Hashing. //#define NOFILEHASH -//#define NOVERIFYIWADS +#define NOVERIFYIWADS // Uncheck this to compile debugging code //#define RANGECHECK diff --git a/src/g_demo.c b/src/g_demo.c index 98bb7155a..caf7ff05d 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -112,7 +112,7 @@ demoghost *ghosts = NULL; // DEMO RECORDING // -#define DEMOVERSION 0x000B +#define DEMOVERSION 0x000C #define DEMOHEADER "\xF0" "BlanReplay" "\x0F" #define DF_GHOST 0x01 // This demo contains ghost data too! @@ -2740,6 +2740,8 @@ void G_BeginRecording(void) raflags |= RAF_PURPLEDRIFT; if (cv_dummyattackingslopeboost.value) raflags |= RAF_SLOPEBOOST; + if (cv_dummyattackingairdrop.value) + raflags |= RAF_AIRDROP; if (cv_dummyattackingbumpspark.value == BUMPSPARK_ALL) raflags |= RAF_BUMPSPARK; if (cv_dummyattackingbumpspark.value == BUMPSPARK_NOCHARGE) @@ -3832,6 +3834,7 @@ void G_AddGhost(char *defdemoname) CLEANUP(Z_Pfree) char *pdemoname = NULL; const char *n; UINT64 demohash; + UINT32 raflags; demoghost *gh; UINT8 flags; CLEANUP(Z_Pfree) UINT8 *buffer = NULL; @@ -3895,6 +3898,7 @@ void G_AddGhost(char *defdemoname) flags = header.demoflags; + raflags = header.raflags; if (!(flags & DF_GHOST)) { CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname); @@ -3913,6 +3917,40 @@ void G_AddGhost(char *defdemoname) return; } + // Check RA flags. + { + UINT32 ourraflags = 0; + UINT16 demoversion = header.demoversion; + + if (cv_dummyattackingrings.value) + ourraflags |= RAF_RINGS; + if (cv_dummyattackingstacking.value) + ourraflags |= RAF_STACKING; + if (cv_dummyattackingchaining.value) + ourraflags |= RAF_CHAINING; + if (cv_dummyattackingslipdash.value) + ourraflags |= RAF_SLIPDASH; + if (cv_dummyattackingpurpledrift.value) + ourraflags |= RAF_PURPLEDRIFT; + if (cv_dummyattackingslopeboost.value) + ourraflags |= RAF_SLOPEBOOST; + if (cv_dummyattackingairdrop.value) + ourraflags |= RAF_AIRDROP; + + if (demoversion <= 0x000B) + { + ourraflags &= ~RAF_AIRDROP; + ourraflags &= ~RAF_BUMPDRIFT; + ourraflags &= ~RAF_BUMPSPARK; + } + + if (ourraflags != raflags) + { + CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay doesn't match current RA mode.\n"), pdemoname); + return; + } + } + demoplayer_t *plr = &header.playerdata[0]; // any invalidating flags? diff --git a/src/g_demo.h b/src/g_demo.h index 77667fc99..6bc536c04 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -41,8 +41,9 @@ typedef enum RAF_SLIPDASH = 1<<3, RAF_PURPLEDRIFT = 1<<4, RAF_SLOPEBOOST = 1<<5, - RAF_BUMPDRIFT = 1<<6, - RAF_BUMPSPARK = 1<<7, + RAF_AIRDROP = 1<<6, + RAF_BUMPDRIFT = 1<<7, + RAF_BUMPSPARK = 1<<8, // up to 1<<31 is free } raflags_t; diff --git a/src/g_game.c b/src/g_game.c index 329e4bded..14ed674fd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -483,12 +483,13 @@ SINT8 G_RecordPresetIndex(void) boolean slipdash = cv_dummyattackingslipdash.value; boolean purpledrift = cv_dummyattackingpurpledrift.value; boolean slopeboost = cv_dummyattackingslopeboost.value; - boolean bumpspark = cv_dummyattackingbumpspark.value; + boolean airdrop = cv_dummyattackingairdrop.value; + UINT8 bumpspark = cv_dummyattackingbumpspark.value; - if (!rings && !stacking && !chaining && !slipdash && !purpledrift && !slopeboost && !bumpspark) + if (!rings && !stacking && !chaining && !slipdash && !purpledrift && !slopeboost && !airdrop && (bumpspark == BUMPSPARK_NONE)) return RP_KART; - if (stacking && chaining && slopeboost && !rings && !slipdash && !purpledrift && (bumpspark == BUMPSPARK_ALL)) + if (stacking && chaining && slopeboost && airdrop && !rings && !slipdash && !purpledrift && (bumpspark == BUMPSPARK_ALL)) return RP_TECH; if (rings && stacking && chaining && slipdash && purpledrift && slopeboost && (bumpspark == BUMPSPARK_NOCHARGE)) diff --git a/src/k_bot.cpp b/src/k_bot.cpp index 747dbf15a..6b4d6edb1 100644 --- a/src/k_bot.cpp +++ b/src/k_bot.cpp @@ -1640,6 +1640,26 @@ void K_BotTicker(const player_t *player) forcedDir = true; } + if (P_IsObjectOnGround(player->mo) == false) + { + if (player->airdroptime == 0 + && K_AirDropActive() + && !P_PlayerInPain(player) + && !player->loop.radius + && !(player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) + && !player->respawn) + { + if (botController != nullptr && (botController->flags & TMBOT_AIRDROP) == TMBOT_AIRDROP) + { + // Air Drop! + bd->brakedown = true; + return; + } + } + + //return; // Don't allow bots to turn in the air. + } + if (forcedDir == true) { destangle = R_PointToAngle2(player->mo->x, player->mo->y, bd->predict.x, bd->predict.y); diff --git a/src/k_hud.c b/src/k_hud.c index d63322a17..8fa89505a 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2363,7 +2363,7 @@ void K_SetScoreboardModStatus(const char *name, SINT8 active) CONS_Alert(CONS_WARNING, "Server mod '%s' does not exist so status cannot be changed.\n", name); } -#define BASEMODS 12 +#define BASEMODS 14 static void K_DrawServerMods(INT32 x, INT32 y) { UINT8 i, j; @@ -2380,6 +2380,8 @@ static void K_DrawServerMods(INT32 x, INT32 y) {"Chain Offroad", 0, &cv_kartchainingoffroad, -1, true}, {"Slope Boost", 0, NULL, K_PurpleDriftActive() > 0, true}, {"Drafting", 0, NULL, K_DraftingActive() > 0, true}, + {"Air Drop", 0, NULL, K_AirDropActive() > 0, true}, + {"Bump Spark", 0, &cv_kartbumpspark, -1, true}, {"Bump Drift", 0, NULL, K_GetBumpSpark() > 0, true}, {"Bump Spark", 0, NULL, K_GetBumpSpark() == BUMPSPARK_ALL, true}, {"Bump Spring", 0, &cv_kartbumpspring, -1, true}, diff --git a/src/k_kart.c b/src/k_kart.c index d4ee9fc34..0e8de3377 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -364,6 +364,8 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartchainingoffroad); CV_RegisterVar(&cv_kartchainingsound); + CV_RegisterVar(&cv_kartairdrop); + CV_RegisterVar(&cv_kartitembreaker); //CV_RegisterVar(&cv_kartwalltransfer); @@ -6602,11 +6604,7 @@ static void K_HandleRingDeincrement(player_t *player, boolean chainnerf) finalringtimer += subring; } - if (player->ringboost - finalringtimer > player->chaintimer) - { - // Cap this to prevent displacement between chaintimer and ringtimer. - player->chaintimer = min(player->ringboost, (TICRATE - TICRATE/4)); - } + player->chaintimer = max(player->ringboost, player->chaintimer); } player->ringboost = max(0, player->ringboost - finalringtimer); @@ -6643,6 +6641,103 @@ void K_AwardScaledPlayerRings(player_t *player, SINT8 mode) K_AwardPlayerRings(player, awardamount, (mode == ASR_SUPERRING) ? true : false); } +void K_SpawnFallLines(player_t *player, boolean ringdrop) +{ + fixed_t rand_x; + fixed_t rand_y; + fixed_t rand_z; + + rand_z = player->mo->z + player->mo->height + (16 * player->mo->scale) + (P_RandomRange(-15,15) * player->mo->scale); + rand_y = player->mo->y + (P_RandomRange(-25,25) * player->mo->scale); + rand_x = player->mo->x + (P_RandomRange(-25,25) * player->mo->scale); + + mobj_t *fast = P_SpawnMobj(rand_x, rand_y, rand_z, MT_FASTLINE); + + P_SetTarget(&fast->target, player->mo); + fast->momx = 3*player->mo->momx/4; + fast->momy = 3*player->mo->momy/4; + fast->momz = 3*P_GetMobjZMovement(player->mo)/4; + + P_SetScale(fast, fast->scale/4); + fast->angle = player->mo->angle+ANGLE_90; + fast->rollangle = ANGLE_90; + + fast->colorized = true; + + if (ringdrop) + { + fast->color = SKINCOLOR_CROCODILE; + fast->renderflags |= RF_TRANS10; + } + else + fast->color = SKINCOLOR_IVORY; + + fast->renderflags |= RF_ADD; + + K_MatchGenericExtraFlags(fast, player->mo); +} + +void K_AirDrop(player_t *player, ticcmd_t *cmd) +{ + if ((player->cmd.buttons & BT_BRAKE) + && K_AirDropActive() + && !P_IsObjectOnGround(player->mo) + && !P_PlayerInPain(player) + && !player->loop.radius + && !(player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) + && !player->respawn) + { + SINT8 airbrakedelay = (player->rings > 0) ? TICRATE/4 : TICRATE/3; + if (player->airdroptime < airbrakedelay) + { + if (player->rings > 0) + { + player->ringlock = 6; + } + + player->ringdrop = false; + } + else + { + if (!player->ringdelay && player->rings > 0) + { + mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); + P_SetMobjState(ring, S_FASTRING1); + + ring->renderflags |= RF_ADD; + ring->renderflags |= RF_TRANS60; + ring->colorized = true; + ring->color = SKINCOLOR_SILVER; + + ring->extravalue1 = 18; // Ring use animation timer + ring->extravalue2 = 1; // Ring use animation flag + ring->extravalue3 = 1; // Ring airdrop use flag + ring->shadowscale = 0; + P_SetTarget(&ring->target, player->mo); // user + player->rings--; + player->ringdelay = 5; + player->ringlock = 6; + } + + if (player->rings <= 0) + { + player->ringdrop = false; + } + + K_SpawnFallLines(player, player->ringdrop); + player->mo->momz -= FixedMul(gravity, mapobjectscale)*P_MobjFlip(player->mo); + } + + if (player->airdroptime < UINT8_MAX) + player->airdroptime++; + } + else + { + player->airdroptime = 0; + player->ringdrop = false; + } +} + // Returns the bumpspark value as an enum. INT32 K_GetBumpSpark(void) { @@ -6875,6 +6970,19 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_HandleRingDeincrement(player, chainingactive); } + K_AirDrop(player, cmd); + + if (player->ringlock) + { + player->chaintimer = max(player->chaintimer, player->ringboost); + player->ringlock--; + + if (!player->ringlock) + player->pflags &= ~PF_RINGLOCK; + else + player->pflags |= PF_RINGLOCK; + } + if (!player->ringboost && !player->chaintimer) player->ringtime = 0; @@ -9848,7 +9956,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground) || ((K_GetKartInvinType() == KARTINVIN_ALTERN) && player->invincibilitytimer) || (player->growshrinktimer > 0) || player->flametimer - || (leveltime < starttime))) + || (leveltime < starttime) + || (player->pflags & PF_RINGLOCK))) player->itemflags |= IF_USERINGS; else player->itemflags &= ~IF_USERINGS; @@ -10975,6 +11084,17 @@ boolean K_DraftingActive(void) return false; } +boolean K_AirDropActive(void) +{ + if (airdropactive) + { + // Air Drop is enabled! + return true; + } + + return false; +} + boolean K_GetKartInvinType(void) { return invintype; diff --git a/src/k_kart.h b/src/k_kart.h index a9d794d7f..aa250d075 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -322,6 +322,7 @@ boolean K_ChainingActive(void); boolean K_SlipdashActive(void); boolean K_SlopeBoostActive(void); boolean K_DraftingActive(void); +boolean K_AirDropActive(void); boolean K_GetKartInvinType(void); INT32 K_GetBumpSpark(void); boolean K_BoostChain(player_t *player, INT32 timer, boolean chainsound); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 24316e21d..361b466c8 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -4170,6 +4170,13 @@ static int lib_kDraftingActive(lua_State *L) return 1; } +// Checks if Air Drop is active. +static int lib_kAirDropActive(lua_State *L) +{ + lua_pushboolean(L, K_AirDropActive()); + return 1; +} + // Grabs the currently active invintype. static int lib_kGetKartInvinType(lua_State *L) { @@ -5273,6 +5280,7 @@ static luaL_Reg lib[] = { {"K_SlipdashActive",lib_kSlipdashActive}, {"K_SlopeBoostActive",lib_kSlopeBoostActive}, {"K_DraftingActive",lib_kDraftingActive}, + {"K_AirDropActive",lib_kAirDropActive}, {"K_GetBumpSpark",lib_kGetBumpSpark}, {"K_GetKartInvinType",lib_kGetKartInvinType}, {"K_UsingLegacyCheckpoints",lib_kUsingLegacyCheckpoints}, diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index ee90e99b0..ac764112a 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -256,12 +256,15 @@ enum player_e player_ringmax, player_pickuprings, player_ringdelay, + player_ringlock, player_ringboost, player_ringtime, player_superring, player_nextringaward, player_ringvolume, player_ringtransparency, + player_airdroptime, + player_ringdrop, player_curshield, player_bubblecool, player_bubbleblowup, @@ -453,12 +456,15 @@ static const char *const player_opt[] = { "ringmax", "pickuprings", "ringdelay", + "ringlock", "ringboost", "ringtime", "superring", "nextringaward", "ringvolume", "ringtransparency", + "airdroptime", + "ringdrop", "curshield", "bubblecool", "bubbleblowup", @@ -854,6 +860,9 @@ static int player_get(lua_State *L) case player_ringdelay: lua_pushinteger(L, plr->ringdelay); break; + case player_ringlock: + lua_pushinteger(L, plr->ringlock); + break; case player_ringboost: lua_pushinteger(L, plr->ringboost); break; @@ -872,6 +881,12 @@ static int player_get(lua_State *L) case player_ringtransparency: lua_pushinteger(L, plr->ringtransparency); break; + case player_airdroptime: + lua_pushinteger(L, plr->airdroptime); + break; + case player_ringdrop: + lua_pushinteger(L, plr->ringdrop); + break; case player_curshield: lua_pushinteger(L, plr->curshield); break; @@ -1534,6 +1549,9 @@ static int player_set(lua_State *L) case player_ringdelay: plr->ringdelay = luaL_checkinteger(L, 3); break; + case player_ringlock: + plr->ringlock = luaL_checkinteger(L, 3); + break; case player_ringboost: plr->ringboost = luaL_checkinteger(L, 3); break; @@ -1552,6 +1570,12 @@ static int player_set(lua_State *L) case player_ringtransparency: plr->ringtransparency = luaL_checkinteger(L, 3); break; + case player_airdroptime: + plr->airdroptime = luaL_checkinteger(L, 3); + break; + case player_ringdrop: + plr->ringdrop = luaL_checkinteger(L, 3); + break; case player_curshield: plr->curshield = luaL_checkinteger(L, 3); break; diff --git a/src/lua_script.c b/src/lua_script.c index 36d1b3a25..dc524aa75 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -397,6 +397,8 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"draftingactive")) { lua_pushinteger(L, draftingactive); return 1; + } else if (fastcmp(word,"airdropactive")) { + lua_pushinteger(L, airdropactive); } else if (fastcmp(word,"bumpsparkactive")) { lua_pushinteger(L, bumpsparkactive); return 1; diff --git a/src/m_menu.c b/src/m_menu.c index 180b75896..a0ceccc36 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -455,8 +455,10 @@ consvar_t cv_dummyattackingchaining = CVAR_INIT ("dummyattackingchaining", "Off" consvar_t cv_dummyattackingslipdash = CVAR_INIT ("dummyattackingslipdash", "Off", CV_HIDEN|CV_CALL|CV_NOINIT, CV_OnOff, Nextmap_OnChange); consvar_t cv_dummyattackingpurpledrift = CVAR_INIT ("dummyattackingpurpledrift", "Off", CV_HIDEN|CV_CALL|CV_NOINIT, CV_OnOff, Nextmap_OnChange); consvar_t cv_dummyattackingslopeboost = CVAR_INIT ("dummyattackingslopeboost", "Off", CV_HIDEN|CV_CALL|CV_NOINIT, CV_OnOff, Nextmap_OnChange); +consvar_t cv_dummyattackingairdrop = CVAR_INIT ("dummyattackingairdrop", "Off", CV_HIDEN|CV_CALL|CV_NOINIT, CV_OnOff, Nextmap_OnChange); -static CV_PossibleValue_t dummybumpspark_cons_t[] = {{BUMPSPARK_NONE, "Off"}, {BUMPSPARK_NOCHARGE, "NoCharge"}, {BUMPSPARK_ALL, "On"}}; + +static CV_PossibleValue_t dummybumpspark_cons_t[] = {{BUMPSPARK_NONE, "Off"}, {BUMPSPARK_NOCHARGE, "NoCharge"}, {BUMPSPARK_ALL, "On"}, {0, NULL}}; consvar_t cv_dummyattackingbumpspark = CVAR_INIT ("dummyattackingbumpspark", "Off", CV_HIDEN|CV_CALL|CV_NOINIT, dummybumpspark_cons_t, Nextmap_OnChange); static CV_PossibleValue_t dummygpdifficulty_cons_t[] = {{KARTSPEED_EASY, "Easy"}, {KARTSPEED_NORMAL, "Normal"}, {KARTSPEED_HARD, "Hard"}, {KARTSPEED_EXPERT, "Expert"}, {KARTGP_MASTER, "Master"}, {KARTGP_NIGHTMARE, "Nightmare"}, {0, NULL}}; @@ -660,6 +662,7 @@ char *M_AppendGametypeAndModName(void) ADD(cv_dummyattackingslipdash, "SD-") ADD(cv_dummyattackingpurpledrift, "PD-") ADD(cv_dummyattackingslopeboost, "SB-") + ADD(cv_dummyattackingairdrop, "AD-") ADDEQUALS(cv_dummyattackingbumpspark, "BD-", BUMPSPARK_NOCHARGE) ADDEQUALS(cv_dummyattackingbumpspark, "BS-", BUMPSPARK_ALL) @@ -2174,6 +2177,7 @@ void M_Init(void) CV_RegisterVar(&cv_dummyattackingslipdash); CV_RegisterVar(&cv_dummyattackingpurpledrift); CV_RegisterVar(&cv_dummyattackingslopeboost); + CV_RegisterVar(&cv_dummyattackingairdrop); CV_RegisterVar(&cv_dummyattackingbumpspark); CV_RegisterVar(&cv_dummygpdifficulty); @@ -5741,7 +5745,7 @@ void MD_DrawTimeAttackMenu(void) // Draw current RA preset mode. { - const char *mode = "Unkown mode"; + const char *mode = "Unknown mode"; if (preset == 0) { mode = "SRB2Kart Mode"; @@ -5861,11 +5865,11 @@ INT32 MR_ReplayStaff(INT32 choice) } #define NUMPRESETS 3 -static INT32 presets[NUMPRESETS][7] = { - //rings stacking chaining slipdash purpledrift slopeboost bumpspark - { 0, 0, 0, 0, 0, 0, BUMPSPARK_NONE}, // SRB2Kart - { 0, 1, 1, 0, 0, 1, BUMPSPARK_ALL}, // Tech - { 1, 1, 1, 1, 1, 1, BUMPSPARK_NOCHARGE}, // BlanKart +static INT32 presets[NUMPRESETS][8] = { + //rings stacking chaining slipdash purpledrift slopeboost airdrop bumpspark + { 0, 0, 0, 0, 0, 0, 0, BUMPSPARK_NONE }, // SRB2Kart + { 0, 1, 1, 0, 0, 1, 1, BUMPSPARK_ALL }, // Tech + { 1, 1, 1, 1, 1, 1, 1, BUMPSPARK_NOCHARGE }, // BlanKart }; INT32 MR_TimeAttackPreset(INT32 arg) @@ -5880,8 +5884,9 @@ INT32 MR_TimeAttackPreset(INT32 arg) CV_Set(&cv_dummyattackingslipdash, (boolean)preset[3] ? "On" : "Off"); CV_Set(&cv_dummyattackingpurpledrift, (boolean)preset[4] ? "On" : "Off"); CV_Set(&cv_dummyattackingslopeboost, (boolean)preset[5] ? "On" : "Off"); + CV_Set(&cv_dummyattackingairdrop, preset[6] ? "On" : "Off"); - switch(preset[6]) + switch(preset[7]) { case BUMPSPARK_ALL: CV_Set(&cv_dummyattackingbumpspark, "On"); diff --git a/src/m_menu.h b/src/m_menu.h index e6ed89e38..4942956b7 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -422,7 +422,7 @@ extern consvar_t cv_dummygpdifficulty, cv_dummygpencore, cv_dummygpcup; extern consvar_t cv_dummymenuplayer, cv_dummyteam, cv_dummyspectate, cv_dummyscramble; extern consvar_t cv_dummyattackingrings, cv_dummyattackingstacking, cv_dummyattackingchaining; extern consvar_t cv_dummyattackingslipdash, cv_dummyattackingpurpledrift, cv_dummyattackingslopeboost; -extern consvar_t cv_dummyattackingbumpspark; +extern consvar_t cv_dummyattackingairdrop, cv_dummyattackingbumpspark; extern consvar_t cv_dummystaff; extern consvar_t cv_dummymultiplayer, cv_dummyip, cv_dummyname, cv_dummyfollower, cv_dummycolor; extern consvar_t cv_dummyserverpage; diff --git a/src/p_enemy.c b/src/p_enemy.c index 82566adf1..96a566a7c 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3170,11 +3170,27 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 21) { - // Base add is 4 tics for 9,9, adds 1 tic for each point closer to the 1,1 end - actor->target->player->ringboost += K_GetKartRingPower(actor->target->player, true); - actor->target->player->ringtime += K_GetKartRingPower(actor->target->player, true); + if (actor->extravalue3 && !P_IsObjectOnGround(actor->target)) + { + actor->target->momz -= (FixedMul(gravity, mapobjectscale))*P_MobjFlip(actor->target); + actor->target->player->ringboost += 5; + actor->target->player->ringtime += 5; + actor->target->player->ringdrop = true; + } + else + { + // Base add is 4 tics for 9,9, adds 1 tic for each point closer to the 1,1 end + actor->target->player->ringboost += K_GetKartRingPower(actor->target->player, true); + actor->target->player->ringtime += K_GetKartRingPower(actor->target->player, true); + } + S_StartSoundAtVolume(actor->target, sfx_s1b5, actor->target->player->ringvolume); + if (actor->extravalue3 && !P_IsObjectOnGround(actor->target)) + { + actor->target->momz -= (FixedMul(gravity, mapobjectscale)/2)*P_MobjFlip(actor->target); + } + if (actor->target->player->rings <= 10) { S_StartSoundAtVolume(actor->target, sfx_ringlw, 255 - actor->target->player->rings*10); @@ -3199,6 +3215,7 @@ void A_AttractChase(mobj_t *actor) ( actor->target->height + offz )* P_MobjFlip(actor)); actor->extravalue1++; } + } else // Collecting { diff --git a/src/p_mobj.h b/src/p_mobj.h index 4dab13a4b..9f2df3307 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -407,6 +407,7 @@ struct mobj_t // Extra values are for internal use for whatever you want INT32 extravalue1; INT32 extravalue2; + INT32 extravalue3; // Custom values are not to be altered by us! // They are for SOCs to store things in. @@ -606,6 +607,7 @@ extern boolean slipdashactive; extern boolean purpledriftactive; extern boolean slopeboostactive; extern boolean draftingactive; +extern boolean airdropactive; extern UINT8 bumpsparkactive; extern UINT16 bossdisabled; extern boolean stoppedclock; diff --git a/src/p_saveg.c b/src/p_saveg.c index 452c03a18..fd5cfe258 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -327,6 +327,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITESINT8(save->p, players[i].ringmax); WRITEUINT8(save->p, players[i].pickuprings); WRITEUINT8(save->p, players[i].ringdelay); + WRITEUINT8(save->p, players[i].ringlock); WRITEUINT16(save->p, players[i].ringboost); WRITEUINT16(save->p, players[i].ringtime); WRITEUINT16(save->p, players[i].superring); @@ -334,6 +335,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].ringvolume); WRITEUINT8(save->p, players[i].ringtransparency); + WRITEUINT8(save->p, players[i].airdroptime); + WRITEUINT8(save->p, players[i].ringdrop); + WRITEUINT8(save->p, players[i].curshield); WRITEUINT8(save->p, players[i].bubblecool); WRITEUINT8(save->p, players[i].bubbleblowup); @@ -680,6 +684,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].ringmax = READSINT8(save->p); players[i].pickuprings = READUINT8(save->p); players[i].ringdelay = READUINT8(save->p); + players[i].ringlock = READUINT8(save->p); players[i].ringboost = READUINT16(save->p); players[i].ringtime = READUINT16(save->p);; players[i].superring = READUINT16(save->p); @@ -687,6 +692,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].ringvolume = READUINT8(save->p); players[i].ringtransparency = READUINT8(save->p); + players[i].airdroptime = READUINT8(save->p); + players[i].ringdrop = READUINT8(save->p); + players[i].curshield = READUINT8(save->p); players[i].bubblecool = READUINT8(save->p); players[i].bubbleblowup = READUINT8(save->p); @@ -2095,6 +2103,7 @@ typedef enum MD3_GRAVITY = 1, MD3_MISCCAP = 1<<1, MD3_BAKEDOFFSET = 1<<2, + MD3_EXTVAL3 = 1<<3, } mobj_diff3_t; typedef enum @@ -2410,6 +2419,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 if (mobj->bakexoff || mobj->bakeyoff || mobj->bakezoff || mobj->bakexpiv || mobj->bakeypiv || mobj->bakezpiv) diff3 |= MD3_BAKEDOFFSET; + if (mobj->extravalue3) + diff3 |= MD3_EXTVAL3; if (diff3 != 0) diff2 |= MD2_MORE; @@ -2696,6 +2707,10 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 WRITEFIXED(save->p, mobj->bakeypiv); WRITEFIXED(save->p, mobj->bakezpiv); } + if (diff3 & MD3_EXTVAL3) + { + WRITEINT32(save->p, mobj->extravalue3); + } WRITEUINT32(save->p, mobj->mobjnum); } @@ -3995,6 +4010,10 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker, UINT8 mobj->bakexoff = mobj->bakeyoff = mobj->bakezoff = 0; mobj->bakexpiv = mobj->bakeypiv = mobj->bakezpiv = 0; } + if (diff3 & MD3_EXTVAL3) + { + mobj->extravalue3 = READINT32(save->p); + } // Reset some non-synch values mobj->sloperoll = 0; @@ -5298,6 +5317,7 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITEUINT8(save->p, purpledriftactive); WRITEUINT8(save->p, slopeboostactive); WRITEUINT8(save->p, draftingactive); + WRITEUINT8(save->p, airdropactive); WRITEUINT8(save->p, bumpsparkactive); for (i = 0; i < 12; i++) @@ -5686,6 +5706,7 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool purpledriftactive = READUINT8(save->p); slopeboostactive = READUINT8(save->p); draftingactive = READUINT8(save->p); + airdropactive = READUINT8(save->p); bumpsparkactive = READUINT8(save->p); for (i = 0; i < 12; i++) diff --git a/src/p_setup.c b/src/p_setup.c index aa5b17b89..ef6e70942 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -154,6 +154,7 @@ boolean slipdashactive; boolean purpledriftactive; boolean slopeboostactive; boolean draftingactive; +boolean airdropactive; UINT8 bumpsparkactive; UINT16 bossdisabled; boolean stoppedclock; @@ -8035,6 +8036,7 @@ static void P_InitLevelSettings(boolean reloadinggamestate) purpledriftactive = false; slopeboostactive = false; draftingactive = false; + airdropactive = false; bumpsparkactive = 0; if (cv_kartrings.value) @@ -8058,8 +8060,10 @@ static void P_InitLevelSettings(boolean reloadinggamestate) if (cv_kartdrafting.value) draftingactive = true; - bumpsparkactive = (UINT8)cv_kartbumpspark.value; + if (cv_kartairdrop.value) + airdropactive = true; + bumpsparkactive = (UINT8)cv_kartbumpspark.value; invintype = (UINT8)cv_kartinvintype.value; // emerald hunt @@ -8150,6 +8154,8 @@ static void P_InitLevelSettings(boolean reloadinggamestate) purpledriftactive = true; if (raflags & RAF_SLOPEBOOST) slopeboostactive = true; + if (raflags & RAF_AIRDROP) + airdropactive = true; if (raflags & RAF_BUMPSPARK) bumpsparkactive = BUMPSPARK_ALL; if (raflags & RAF_BUMPDRIFT) @@ -8163,7 +8169,7 @@ static void P_InitLevelSettings(boolean reloadinggamestate) chainingactive = cv_dummyattackingchaining.value; slipdashactive = cv_dummyattackingslipdash.value; slopeboostactive = cv_dummyattackingslopeboost.value; - + airdropactive = cv_dummyattackingairdrop.value; bumpsparkactive = (UINT8)(cv_dummyattackingbumpspark.value); } } diff --git a/src/p_spec.h b/src/p_spec.h index af15e96de..0386b3866 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -541,6 +541,7 @@ typedef enum TMBOT_NORUBBERBAND = 1, TMBOT_NOCONTROL = 1<<1, TMBOT_FORCEDIR = 1<<2, + TMBOT_AIRDROP = 1<<3, } textmapbotcontroller_t; typedef enum