diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 3ee92edd0..2f1fdbb80 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -613,7 +613,12 @@ 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_GUARD, CV_YesNo, KartAirDrop_OnChange); +static CV_PossibleValue_t airdrop_cons_t[] = {{AIRDROP_NONE, "Off"}, + {AIRDROP_LIGHT, "Light"}, + {AIRDROP_HEAVY, "Heavy"}, + {AIRDROP_FUSION, "Fusion"}, + {0, NULL}}; +consvar_t cv_kartairdrop = CVAR_INIT ("kartairdrop", "Off", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, airdrop_cons_t, KartAirDrop_OnChange); consvar_t cv_kartairthrust = CVAR_INIT ("kartairthrust", "No", CV_NETVAR|CV_CALL|CV_NOINIT|CV_GUARD, CV_YesNo, KartAirThrust_OnChange); consvar_t cv_kartairthrust_reductionrate = CVAR_INIT ("kartairthrust_reductionrate", "0.5", CV_NETVAR|CV_FLOAT|CV_CHEAT|CV_GUARD, CV_Unsigned, NULL); @@ -8469,29 +8474,14 @@ static void KartAirDrop_OnChange(void) return; } - if (!K_AirDropActive() && cv_kartairdrop.value) + if (leveltime < starttime) { - 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")); - } + CONS_Printf(M_GetText("Air Drop has been set to \"%s\".\n"), cv_kartairdrop.string); + airdropactive = (UINT8)cv_kartairdrop.value; } - else if (K_AirDropActive() && !cv_kartairdrop.value) + else { - if (leveltime < starttime) - { - airdropactive = false; - CONS_Printf(M_GetText("Air Drop has been turned \"Off\".\n")); - } - else - { - CONS_Printf(M_GetText("Air Drop will be turned \"Off\" next round.\n")); - } + CONS_Printf(M_GetText("Air Drop will be set to \"%s\" next round.\n"), cv_kartairdrop.string); } } diff --git a/src/d_player.h b/src/d_player.h index 49820f06d..fce7c6db8 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -71,8 +71,8 @@ typedef enum // TODO: Is there a better way to track this? PF_GAINAX = 1<<3, PF_KICKSTARTACCEL = 1<<4, // Accessibility feature: Is accelerate in kickstart mode? - // 1<<5 free - // 1<<6 free + + // free: 1<<5 and 1<<6 PF_WANTSTOJOIN = 1<<7, // Spectator that wants to join @@ -111,6 +111,16 @@ typedef enum PF_SLIDING = 1<<31, // For lua compat, don't use! } pflags_t; +typedef enum +{ + PAF_AIRDROPINPUT = 1<<0, // Air drop input held + PAF_WANTSAIRDROP = 1<<1, // Wants Air drop (input pressed and buffered) + PAF_AIRDROP_LIGHT = 1<<2, // Is in Light Air Drop + PAF_AIRDROP_HEAVY = 1<<3, // Is in Heavy Air Drop + + PAF_AIRDROP_MASK = (PAF_AIRDROP_LIGHT|PAF_AIRDROP_HEAVY), // Is in any Air Drop state +} p_airdropflags_t; + typedef enum { // Are animation frames playing? @@ -199,6 +209,8 @@ typedef enum khud_boostcam, // Camera push forward on boost khud_destboostcam, // Ditto khud_timeovercam, // Camera timer for leaving behind or not + khud_heavydropcam, // Camera timer for heavy air drop + khud_postdropcam, // Camera timer for landing after heavy air drop (both timers superposition for feel) // Sounds khud_enginesnd, // Engine sound offset this player is using. @@ -676,8 +688,10 @@ struct player_t 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 airdroptime; // Tracks how long airdrop has been active, used for delay before airdrop kicks in. - //boolean ringdrop; // Set when having ringdrop applied. + INT32 airdroppredelay; // In light airdrop, handles the delay before it can be activated once going airborne. + INT32 airdroptime; // Tracks how long the player has been in airdrop. + INT32 airdropbuffer; // Time during which heavy air drop will instantly trigger upon going airborne. + p_airdropflags_t airdropflags; // Airdrop-exclusive bitflags. mobj_t *shieldtracer; // Blankart: Shield mobj diff --git a/src/deh_lua.c b/src/deh_lua.c index 56fc35502..023a08958 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -178,6 +178,18 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) if (mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word); return 0; } + else if (fastncmp("PAF_", word, 4)) { + p = word+4; + for (i = 0; AIRDROPFLAG_LIST[i]; i++) + { + if (fastcmp(p, AIRDROPFLAG_LIST[i])) { + CacheAndPushConstant(L, word, ((lua_Integer)1< 0, true}, {"Drafting", 0, NULL, K_DraftingActive() > 0, true}, - {"Air Drop", 0, NULL, K_AirDropActive() > 0, true}, + {"Light AirDrop", 0, NULL, K_AirDropActive() == AIRDROP_LIGHT, true}, + {"Heavy AirDrop", 0, NULL, K_AirDropActive() == AIRDROP_HEAVY, true}, + {"Fus. AirDrop", 0, NULL, K_AirDropActive() == AIRDROP_FUSION, true}, {"Air Thrust", 0, NULL, K_AirThrustActive() > 0, true}, {"Recovery Dash", 0, NULL, K_RecoveryDashActive() > 0, true}, {"Bump Spark", 0, &cv_kartbumpspark, -1, true}, diff --git a/src/k_kart.c b/src/k_kart.c index 5f6f6faa4..7f8ab99f0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6995,65 +6995,148 @@ static void K_SpawnFallLines(player_t *player, boolean ringdrop) static void K_AirDrop(player_t *player, ticcmd_t *cmd) { + const INT32 heavydrophi = TICRATE/3; + const INT32 airbrakedelay = TICRATE/3; + + if (player->airdropbuffer > 0) + { + player->airdropbuffer--; + } + + if ((cmd->buttons & BT_BRAKE)) + { + if (!(player->airdropflags & PAF_AIRDROPINPUT)) + { + player->airdropflags |= PAF_WANTSAIRDROP|PAF_AIRDROPINPUT; + if (P_IsObjectOnGround(player->mo)) + player->airdropbuffer = 2; + } + } + else + { + player->airdropflags &= ~PAF_AIRDROPINPUT; + if (airdropactive == AIRDROP_LIGHT || airdropactive == AIRDROP_FUSION) + { + player->airdropflags &= ~PAF_WANTSAIRDROP; + } + } + + if (P_IsObjectOnGround(player->mo) && player->airdropbuffer == 0) + { + player->airdropflags &= ~PAF_WANTSAIRDROP; + } + + if (!(player->airdropflags & PAF_AIRDROP_HEAVY)) + { + if (player->karthud[khud_heavydropcam] > 0) + { + player->karthud[khud_heavydropcam] = max(player->karthud[khud_heavydropcam] - 5, 0); + } + } + if (player->karthud[khud_postdropcam] > 0) + { + player->karthud[khud_postdropcam]--; + } + + if (K_AirDropActive() && P_IsObjectOnGround(player->mo)) + { + if ((player->airdropflags & PAF_AIRDROP_HEAVY)) + { + if (player->rings > 0 && player->airdroptime > TICRATE/4) + { + P_PlayerRingBurst(player, min(2, player->rings)); + } + if (player->airdroptime > 1) + { + player->startboost = TICRATE/4 + min(TICRATE, ((FixedDiv(player->airdroptime, TICRATE) * TICRATE) / FRACUNIT)); + + // Take off! + S_StartSound(player->mo, sfx_shrpgo); + } + + // POOMP! + S_StartSound(player->mo, sfx_doord2); + + player->karthud[khud_postdropcam] = min(2*player->karthud[khud_heavydropcam], TICRATE/4); + } + } + if (!K_AirDropActive() || P_IsObjectOnGround(player->mo) || P_PlayerInPain(player) || player->loop.radius || (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) || player->respawn ) { - // Conditions! player->airdroptime = 0; - //player->ringdrop = false; + player->airdroppredelay = 0; + player->airdropflags &= ~PAF_AIRDROP_MASK; return; } - if (cmd->buttons & BT_BRAKE) + if (player->airdropflags & PAF_WANTSAIRDROP) { - SINT8 airbrakedelay = TICRATE/3; - if (player->airdroptime < airbrakedelay) + if ((airdropactive == AIRDROP_LIGHT) || (airdropactive == AIRDROP_FUSION && (cmd->buttons & BT_ACCELERATE))) { - /*if (player->rings > 0) - { - player->ringlock = 6; - } - - player->ringdrop = false;*/ + player->airdropflags |= PAF_AIRDROP_LIGHT; } - else + else if (!(player->airdropflags & (PAF_AIRDROP_HEAVY))) // in fusion, fires if brake is held but not accel { - /*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); + player->airdropflags |= PAF_AIRDROP_HEAVY; + player->airdroptime = 0; + player->airdropbuffer = 0; - ring->renderflags |= RF_ADD; - ring->renderflags |= RF_TRANS60; - ring->colorized = true; - ring->color = SKINCOLOR_SILVER; + // TODO: heavy air drop should allow keeping current boost stack + S_StartSound(player->mo, sfx_s3k77); + S_StartSound(player->mo, sfx_s3k51); - ring->extravalue1 = 17; // 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 = 7; - player->ringlock = 6; - } - - if (player->rings <= 0) - { - player->ringdrop = false; - }*/ - - K_SpawnFallLines(player, /*player->ringdrop*/ false); - K_SpawnAirdropTrail(player); - player->mo->momz -= FixedMul(gravity, mapobjectscale)*P_MobjFlip(player->mo); + player->mo->momx = FixedMul(player->mo->momx, 90*FRACUNIT/100); + player->mo->momy = FixedMul(player->mo->momy, 90*FRACUNIT/100); + player->mo->momz -= 12*P_MobjFlip(player->mo)*mapobjectscale; + } + } + else + { + if (airdropactive == AIRDROP_LIGHT || airdropactive == AIRDROP_FUSION) + { + player->airdropflags &= ~PAF_AIRDROP_LIGHT; + if (!(player->airdropflags & PAF_AIRDROP_HEAVY)) + player->airdroptime = 0; } } - if (player->airdroptime < UINT8_MAX) + // heavy air drop always overrides light air drop + if (player->airdropflags & PAF_AIRDROP_HEAVY) + { + K_SpawnFallLines(player, false); + if (player->airdroptime <= heavydrophi) + { + player->mo->momz -= FixedMul(5*gravity, mapobjectscale)*P_MobjFlip(player->mo); + K_SpawnAirdropTrail(player); + } + else + { + player->mo->momz -= FixedMul(2*gravity, mapobjectscale)*P_MobjFlip(player->mo); + } + + if (player->karthud[khud_heavydropcam] < TICRATE) + player->karthud[khud_heavydropcam]++; + player->airdroptime++; + } + else if (player->airdropflags & PAF_AIRDROP_LIGHT) + { + if (player->airdroppredelay >= airbrakedelay) + { + player->mo->momz -= FixedMul(gravity, mapobjectscale)*P_MobjFlip(player->mo); + K_SpawnFallLines(player, false); + K_SpawnAirdropTrail(player); + } + + player->airdroptime++; + } + + if (K_AirDropActive() && !P_IsObjectOnGround(player->mo)) + player->airdroppredelay++; } // Returns the bumpspark value as an enum. @@ -11720,15 +11803,9 @@ boolean K_DraftingActive(void) return false; } -boolean K_AirDropActive(void) +SINT8 K_AirDropActive(void) { - if (airdropactive) - { - // Air Drop is enabled! - return true; - } - - return false; + return airdropactive; } boolean K_AirThrustActive(void) @@ -11948,6 +12025,11 @@ void K_QuiteSaltyHop(player_t *player) boolean K_CheckWaterskipLockout(player_t *player) { + if (player->airdropflags & PAF_AIRDROP_HEAVY) + { + return false; + } + if (K_WaterskipBricksActive()) { return (player->cmd.buttons & BT_ACCELERATE) == BT_ACCELERATE; diff --git a/src/k_kart.h b/src/k_kart.h index 08f24b159..c0a829122 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -381,7 +381,7 @@ boolean K_ChainingActive(void); boolean K_SlipdashActive(void); boolean K_SlopeBoostActive(void); boolean K_DraftingActive(void); -boolean K_AirDropActive(void); +SINT8 K_AirDropActive(void); boolean K_AirThrustActive(void); boolean K_RecoveryDashActive(void); boolean K_WaterskipBricksActive(void); @@ -419,6 +419,14 @@ typedef enum BUMPSPARK_ALL } bumpsparktype_t; +typedef enum +{ + AIRDROP_NONE = 0, + AIRDROP_LIGHT, + AIRDROP_HEAVY, + AIRDROP_FUSION, +} airdroptype_t; + boolean K_NullDriftTiltEnalbed(); #ifdef __cplusplus diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 791efe442..593f6cb0d 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -10,6 +10,7 @@ /// \file lua_baselib.c /// \brief basic functions for Lua scripting +#include "blua/lua.h" #include "doomdef.h" #include "p_local.h" #include "p_setup.h" // So we can have P_SetupLevelSky @@ -4406,7 +4407,7 @@ static int lib_kDraftingActive(lua_State *L) // Checks if Air Drop is active. static int lib_kAirDropActive(lua_State *L) { - lua_pushboolean(L, K_AirDropActive()); + lua_pushinteger(L, K_AirDropActive()); return 1; } diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index c00611b9d..04173ad7c 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1507,6 +1507,17 @@ static int libd_getDrawInfo(lua_State *L) drawinfo_t info = {0}; rouletteinfo_t rinfo = {0}; + // Initialize the extra values that might not get used. + info.hudScale = 0; + info.hudScaleFloat = 0.0f; + + rinfo.crop.x = 0; + rinfo.crop.y = 0; + rinfo.flags = 0; + rinfo.offset = 0; + rinfo.spacing = 0; + rinfo.intSpacing = 0; + switch(option) { case huddrawinfo_item: K_getItemBoxDrawinfo(&info, &rinfo);break; case huddrawinfo_gametypeinfo: K_getLapsDrawinfo(&info); break; diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 328feef5d..29ae5fdb5 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -390,7 +390,10 @@ static int lib_lenLocalplayers(lua_State *L) X(nextringaward) \ X(ringvolume) \ X(ringtransparency) \ + X(airdroppredelay) \ X(airdroptime) \ + X(airdropbuffer) \ + X(airdropflags) \ X(ringdrop) \ X(shieldtracer) \ X(bubblecool) \ @@ -829,9 +832,18 @@ static int player_get(lua_State *L) case player_ringtransparency: lua_pushinteger(L, plr->ringtransparency); break; + case player_airdroppredelay: + lua_pushinteger(L, plr->airdroppredelay); + break; case player_airdroptime: lua_pushinteger(L, plr->airdroptime); break; + case player_airdropbuffer: + lua_pushinteger(L, plr->airdropbuffer); + break; + case player_airdropflags: + lua_pushinteger(L, plr->airdropflags); + break; /*case player_ringdrop: lua_pushinteger(L, plr->ringdrop); break;*/ @@ -1610,9 +1622,18 @@ static int player_set(lua_State *L) case player_ringtransparency: plr->ringtransparency = luaL_checkinteger(L, 3); break; + case player_airdroppredelay: + plr->airdroppredelay = luaL_checkinteger(L, 3); + break; case player_airdroptime: plr->airdroptime = luaL_checkinteger(L, 3); break; + case player_airdropbuffer: + plr->airdropbuffer = luaL_checkinteger(L, 3); + break; + case player_airdropflags: + plr->airdropflags = luaL_checkinteger(L, 3); + break; /*case player_ringdrop: plr->ringdrop = luaL_checkinteger(L, 3); break;*/ diff --git a/src/m_cheat.c b/src/m_cheat.c index 8dcd8d068..308356218 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -1190,6 +1190,7 @@ void Command_ObjectPlace_f(void) // Remove ALL flags and motion. P_UnsetThingPosition(players[0].mo); players[0].pflags = 0; + players[0].airdropflags = 0; players[0].mo->flags2 = 0; players[0].mo->eflags = 0; players[0].mo->flags = (MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP); diff --git a/src/p_mobj.h b/src/p_mobj.h index 80f0447ba..01bab7ad1 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -617,7 +617,7 @@ extern boolean slipdashactive; extern boolean purpledriftactive; extern boolean slopeboostactive; extern boolean draftingactive; -extern boolean airdropactive; +extern UINT8 airdropactive; extern boolean airthrustactive; extern boolean recoverydashactive; extern boolean waterskipbricks; diff --git a/src/p_saveg.c b/src/p_saveg.c index f9f7fb7da..828502779 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -501,6 +501,7 @@ static void P_NetSyncPlayers(savebuffer_t *save) SYNC(players[i].playerstate); SYNC(players[i].pflags); + SYNC(players[i].airdropflags); SYNC(players[i].panim); SYNCBOOLEAN(players[i].spectator); SYNC(players[i].spectatewait); @@ -711,8 +712,10 @@ static void P_NetSyncPlayers(savebuffer_t *save) SYNC(players[i].ringvolume); SYNC(players[i].ringtransparency); + SYNC(players[i].airdroppredelay); SYNC(players[i].airdroptime); - //SYNCBOOLEAN(players[i].ringdrop); + SYNC(players[i].airdropbuffer); + SYNC(players[i].airdropflags); RSYNC(players[i].shieldtracer); @@ -4266,13 +4269,13 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) SYNCBOOLEAN(purpledriftactive); SYNCBOOLEAN(slopeboostactive); SYNCBOOLEAN(draftingactive); - SYNCBOOLEAN(airdropactive); SYNCBOOLEAN(airthrustactive); SYNCBOOLEAN(recoverydashactive); SYNCBOOLEAN(waterskipbricks); SYNCBOOLEAN(itemlittering); SYNCBOOLEAN(itempushing); SYNCBOOLEAN(itemlistactive); + SYNC(airdropactive); SYNC(bumpsparkactive); SYNC(antibumptime); diff --git a/src/p_setup.c b/src/p_setup.c index 4999279fd..c55604b9d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -161,7 +161,7 @@ boolean slipdashactive; boolean purpledriftactive; boolean slopeboostactive; boolean draftingactive; -boolean airdropactive; +UINT8 airdropactive; boolean airthrustactive; boolean recoverydashactive; boolean waterskipbricks; @@ -8185,7 +8185,7 @@ static void P_InitLevelSettings(boolean reloadinggamestate) purpledriftactive = false; slopeboostactive = false; draftingactive = false; - airdropactive = false; + airdropactive = 0; airthrustactive = false; recoverydashactive = false; waterskipbricks = false; @@ -8216,8 +8216,7 @@ static void P_InitLevelSettings(boolean reloadinggamestate) if (cv_kartdrafting.value) draftingactive = true; - if (cv_kartairdrop.value) - airdropactive = true; + airdropactive = (UINT8)cv_kartairdrop.value; if (cv_kartairthrust.value) airthrustactive = true; diff --git a/src/p_user.c b/src/p_user.c index 9991ca2b2..ceb178419 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3364,6 +3364,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } z += player->cameraOffset; + z -= 2*(player->karthud[khud_heavydropcam] + player->karthud[khud_postdropcam])*FRACUNIT*P_MobjFlip(mo); // point viewed by the camera // this point is just 64 unit forward the player @@ -3415,13 +3416,13 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (mo->eflags & MFE_VERTICALFLIP) { - angle = R_PointToAngle2(0, thiscam->z + thiscam->height, dist, mo->z + mo->height - player->mo->height + player->cameraOffset); + angle = R_PointToAngle2(0, thiscam->z + thiscam->height, dist, mo->z + mo->height - player->mo->height + player->cameraOffset + 2*player->karthud[khud_heavydropcam]*FRACUNIT); if (thiscam->pitch < ANGLE_180 && thiscam->pitch > angle) angle += (thiscam->pitch - angle)/2; } else { - angle = R_PointToAngle2(0, thiscam->z, dist, mo->z + player->mo->height + player->cameraOffset); + angle = R_PointToAngle2(0, thiscam->z, dist, mo->z + player->mo->height + player->cameraOffset - 2*player->karthud[khud_heavydropcam]*FRACUNIT); if (thiscam->pitch >= ANGLE_180 && thiscam->pitch < angle) angle -= (angle - thiscam->pitch)/2; }