--Tweaks a few minor things in the game that annoy me, inspired by L_ManyMinorTweaks-v5.3.1 by EeveeEuphoria-- --Created by Kamen Laudo (aka A Dev's Diary). Feel free to reuse it and/or modify it-- --Function to check if player is valid-- local function isPlayerValid(player) return player and player.valid and player.mo and player.mo.valid and player.playerstate == PST_LIVE end --Function to check if player is in NiGHTS mode-- local function isPlayerNights(player) return (player.powers[pw_carry] == CR_NIGHTSMODE or player.powers[pw_carry] == CR_NIGHTSFALL) or (maptol & TOL_NIGHTS) or (maptol & TOL_XMAS) end --Function to check if object is valid-- local function isMobjValid(mobj) return mobj and mobj.valid end --Function to update states without reseting them every frame-- local function setNewState(actor, newstate) if actor.state ~= newstate then actor.state = newstate end end --Function to count how many players alive there are in the Special Stage-- local function getSStagePlayersRemaining() local players_alive = 0 for player in players.iterate do if player.nightstime > 0 then players_alive = $ + 1 end end return players_alive end --General gameplay tweaks-- addHook("PlayerThink", function(player) --Check if player is, well, playing!-- if isPlayerValid(player) and not isPlayerNights(player) then ----Ability tweaks---- --Characters with Homing Attack cannot use it more the once in the same jump-- if (player.charability == CA_HOMINGTHOK) then player.charflags = $ & ~SF_MULTIABILITY --Ensure the Homing Attack doesn't conflict with the Attraction Shield-- if (player.powers[pw_shield] == SH_ATTRACT) then player.charflags = $|SF_NOSHIELDABILITY elseif not (skins[player.mo.skin].flags & SF_NOSHIELDABILITY) then player.charflags = $ & ~SF_NOSHIELDABILITY end --Allow gliding characters to glide multiple times consecutively-- elseif (player.charability == CA_GLIDEANDCLIMB) then player.charflags = $|SF_MULTIABILITY end --Characters in Dash Mode emit ghosts-- if player.charflags & SF_DASHMODE and player.dashmode >= 3 * TICRATE then --Prevent Metal from spawning too many ghost objects-- if player.mo.skin ~= "metalsonic" or player.normalspeed < skins[player.skin].normalspeed * 2 then local ghost = P_SpawnGhostMobj(player.mo) ghost.fuse = 4 if ghost.tracer then ghost.tracer.fuse = ghost.fuse end end end --Prevent machine type characters from drowning or suffocating (dude, seriously, why???)-- if player.charflags & SF_MACHINE then player.powers[pw_underwater] = 100 * TICRATE --Just some arbitrary number player.powers[pw_spacetime] = 100 * TICRATE --Same here end ----Character tweaks---- --Enables Dash Mode for the vanilla trio-- if player.mo.skin == "sonic" or player.mo.skin == "tails" or player.mo.skin == "knuckles" then player.charflags = $|SF_DASHMODE end --Give Sonic and Metal Sonic the Homing Attack-- if player.mo.skin == "sonic" or player.mo.skin == "metalsonic" then player.charability = CA_HOMINGTHOK --Fix Knuckles's jump height (for the love of Kami, WHY???)-- elseif player.mo.skin == "knuckles" then player.jumpfactor = 1 * FRACUNIT end --Slope launch animation (doesn't apply to SA Sonic, X Sonic and Modern Sonic, they don't need it)-- if player.mo.skin ~= "adventuresonic" and player.mo.skin ~= "xsonic" and player.mo.skin ~= "modernsonic" and not P_IsObjectOnGround(player.mo) and not (player.pflags & (PF_JUMPED|PF_THOKKED)) and player.powers[pw_justlaunched] and not P_PlayerInPain(player) then setNewState(player.mo, S_PLAY_SPRING) end end end) --Allow players to respawn in coop special stages ;)-- addHook("ThinkFrame", do for player in players.iterate do if multiplayer and gametype == GT_COOP and G_IsSpecialStage(gamemap) and player.spectator and getSStagePlayersRemaining() > 0 then G_DoReborn(#player) --I got tired of trying to figure out what flags or variables I had to reset for this to work, so I simply reset all of them!-- player.spectator = false player.exiting = 0 player.nightstime = sstimer - leveltime player.powers[pw_nocontrol] = 0 player.pflags = $ & ~PF_FULLSTASIS & ~PF_FINISHED end end end) --Allow players to exit minecarts (except for X Sonic and Modern Sonic, they don't need it)-- addHook("PreThinkFrame", function() for player in players.iterate do if isPlayerValid(player) and not isPlayerNights(player) then if player.powers[pw_carry] == CR_MINECART and isMobjValid(player.mo.tracer) and player.mo.tracer.type == MT_MINECART and player.mo.skin ~= "xsonic" and player.mo.skin ~= "modernsonic" then local minecart = player.mo.tracer if (player.cmd.buttons & BT_SPIN) and not (player.pflags & PF_SPINDOWN) then player.powers[pw_carry] = CR_NONE player.mo.momx = minecart.momx player.mo.momy = minecart.momy P_SetObjectMomZ(player.mo, 8 * FRACUNIT, true) player.mo.state = S_PLAY_FALL minecart.target = nil end end end end end)