-- Script written by Blip<<. -- for all those people who miss the good-ol days where kart maker just squished the normal sprites i guess. -- Tbh i just wish there were no insta-kill hazards in this game lol --[[ HEY YOU!! Want your skin to have a special flattened sprite? Well here's how you do it. Create a frame named "FLAT", and give it L/R frames only. Boom! Your skin will now have a proper flattened sprite unlike the base cast! ]]-- -- why are you adding me multiple times. if(rawget(_G,"flattening_lua") ~= nil)then return end -- FREESLOT!!!!!!!! freeslot( "SPR2_FLAT", -- For custom animations "S_PLAY_FLAT") spr2defaults[SPR2_FLAT] = SPR2_DEAD -- namespace. local _flat = { hooks = {}, api = {} } -- Dunno why you would want to disable it if you're adding it, but ya never know the case. local cvar_flattened_enabled = CV_RegisterVar({ name = "flattening.enabled", defaultvalue = "On", flags = CV_NETVAR, PossibleValue = CV_OnOff }) -- Customizability local cvar_flattened_time = CV_RegisterVar({ name = "flattening.pancaketime", defaultvalue = tostring(TICRATE/2), flags = CV_NETVAR, PossibleValue = CV_Natural }) local cvar_unflattened_jank = CV_RegisterVar({ name = "flattening.recoverjanktime", defaultvalue = tostring(TICRATE*2), flags = CV_NETVAR, PossibleValue = CV_Natural }) local cvar_mean_mode = CV_RegisterVar({ name = "flattening.wombopain", defaultvalue = "Off", flags = CV_NETVAR, PossibleValue = CV_OnOff }) local cvar_explode_death = CV_RegisterVar({ name = "flattening.explodeonstuck", defaultvalue = "On", flags = CV_NETVAR, PossibleValue = CV_OnOff }) local cvar_grow_flattens = CV_RegisterVar({ name = "flattening.growflattens", defaultvalue = "On", flags = CV_NETVAR, PossibleValue = CV_OnOff }) local cvar_grow_stronger_inv = CV_RegisterVar({ name = "flattening.growoverpowersinvincible", defaultvalue = "Off", flags = CV_NETVAR, PossibleValue = CV_OnOff }) local cvar_stone_shoe_flattens = CV_RegisterVar({ name = "flattening.stoneshoeflattens", defaultvalue = "On", flags = CV_NETVAR, PossibleValue = CV_OnOff }) local cvar_stomp_flatten = CV_RegisterVar({ name = "flattening.stompflatten", defaultvalue = "On", flags = CV_NETVAR, PossibleValue = CV_OnOff }) local cvar_amps_given_to_flattener = CV_RegisterVar({ name = "flattening.ampsgiven", defaultvalue = tostring(10), flags = CV_NETVAR, PossibleValue = CV_Natural }) -- Yes i see you, i know of your existance, and i will ruin your fun >:3 local cvar_prevent_mean_assholes = CV_RegisterVar({ name = "flattening.preventcamping", defaultvalue = "On", flags = CV_NETVAR, PossibleValue = CV_OnOff }) local cvar_mean_fling_units = CV_RegisterVar({ name = "flattening.meanflingunits", defaultvalue = tostring(16), flags = CV_NETVAR, PossibleValue = CV_Natural }) -- Let's add some funnies local cvar_explode_anyways = CV_RegisterVar({ name = "flattening.funny.explodeanyways", defaultvalue = "Off", flags = CV_NETVAR, PossibleValue = CV_OnOff }) -- Local commands local cvar_local_no_custom_sprites = CV_RegisterVar({ name = "flattening.local.flatstyle", defaultvalue = "Auto", flags = 0, PossibleValue = { Auto = 0, Off = 1, On = 2 } }) local MF_CRUSHED = MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_NOCLIP local PF_CRUSHED = PF_STASIS local sfx_squish = sfx_tppop local sfx_unsquish = sfx_sprong local sfx_hitonhead = sfx_s3k8b -- https://easings.net was referenced when making this function. -- Simply returns a modified version of t local function easeInElastic(t) local c4 = 120< (mo.radius + co.radius))then continue end if(abs(mo.y-co.y) > (mo.radius + co.radius))then continue end -- Overhead if(co.z > mo.z + mo.height)then continue end -- Underneath if(co.z + co.height < mo.z)then continue end -- Are we larger? local required_diff = (mapobjectscale/4) if((mo.scale > co.scale + required_diff) and boolonly)then continue end subjects[#subjects+1] = { mo = co, is_bigger = (mo.scale <= co.scale + required_diff) } if(boolonly)then return true end end if(boolonly)then return false end return subjects end local function mobj_handle_flatten(self) if(not cvar_flattened_enabled.value)then return end if(self.player.playerstate ~= PST_LIVE)then self.flattened_timer = nil self.get_unstuck_please = nil self.unflattened_jank = nil return end if(self.unflattened_jank)then -- Getting unflattened gets special jank! self.unflattened_jank = $-1 self.player.defenselockout = 2 -- Prevent the player from spindashing and drifting while unflattening. self.player.cmd.buttons = $&~(BT_DRIFT) if(not self.unflattened_jank)then -- Play funny sound S_StartSound(self,sfx_unsquish) self.spritexscale = FU/3*2 self.spriteyscale = FU/3*4 end end if(not self.flattened_timer)then return end -- Purely visual shit self.flags = $|MF_CRUSHED self.player.pflags = $|PF_CRUSHED -- Stop momentum and other actions self.momx = 0 self.momy = 0 self.z = self.floorz -- Prevent the player from doing much of anything. self.player.cmd.buttons = $&(BT_LOOKBACK|BT_VOTE) -- HEY GUYS GUESS WHA- (respawn replaced with ring bail) -- Countdown local is_being_crushed = mobj_being_crushed(self) if(not (is_being_crushed or cvar_prevent_mean_assholes.value or cvar_explode_anyways.value))then is_being_crushed = big_mobj_over_mobj(self.player,true) end if(not is_being_crushed)then self.flattened_timer = $-1 else -- You're still being flattened! self.flattened_timer = cvar_flattened_time.value if(not self.get_unstuck_please)then self.get_unstuck_please = 0 end self.get_unstuck_please = $+1 -- Make sure we aren't stuck forever by FUCKING KILLING YOU LOL if(self.get_unstuck_please > (TICRATE*2) and mobj_being_crushed(self))then self.state = S_KART_STILL if(cvar_explode_death.value)then P_KillMobj(self,nil,nil,DMG_INSTAKILL) else P_DamageMobj(self,nil,nil,1,DMG_DEATHPIT) end self.flattened_timer = nil self.get_unstuck_please = nil self.flags = $&~MF_CRUSHED self.player.pflags = $&~PF_CRUSHED return end end self.player.stunned = cvar_unflattened_jank.value -- End if(self.flattened_timer <= 0)then -- Be really mean to really mean people.. or funny if(cvar_prevent_mean_assholes.value or cvar_explode_anyways.value)then local mean_people = big_mobj_over_mobj(self.player) for _,p in ipairs(mean_people) do P_DamageMobj(p.mo,nil,nil,10,DMG_STUMBLE|DMG_WOMBO) P_Thrust(p.mo,R_PointToAngle2(self.x,self.y,p.mo.x,p.mo.y),cvar_mean_fling_units.value*self.scale) end end -- sike fuck you actually if(cvar_explode_anyways.value)then P_KillMobj(self,nil,nil,DMG_INSTAKILL) self.flattened_timer = nil self.get_unstuck_please = nil self.flags = $&~MF_CRUSHED self.player.pflags = $&~PF_CRUSHED return end -- Real stuff self.flattened_timer = nil self.get_unstuck_please = nil self.state = S_KART_STILL self.flags = $&~MF_CRUSHED self.player.pflags = $&~PF_CRUSHED self.player.flashing = cvar_unflattened_jank.value self.unflattened_jank = cvar_unflattened_jank.value -- Set scale self.spritexscale = 2<:( function _flat.hooks.ShouldDamage(self,inflictor,source,damage,type) if(not cvar_flattened_enabled.value)then return end if(not self.player or self.player.playerstate ~= PST_LIVE or self.player.respawn.state ~= 0x00)then return end if((type&(DMG_DEATHMASK|DMG_TYPEMASK)) ~= DMG_CRUSHED)then return end mobj_flatten(self) return false end -- Main handling. function _flat.hooks.PreThink() for self in players.iterate() do if(self.mo)then mobj_handle_flatten(self.mo) end end end -- Visuals are done in post due to lots of things messing with it. function _flat.hooks.PostThink() for self in players.iterate() do if(self.mo)then mobj_handle_visual(self.mo) end end end function _flat.hooks.MobjCollide(self,collidee) -- We don't need to do this. if(not cvar_grow_flattens.value)then return end if(not cvar_flattened_enabled.value)then return end -- Not who we need. if(not self.player)then return end if(not collidee.player)then return end -- Respawn states if(self.player.playerstate ~= PST_LIVE or self.player.respawn.state ~= 0x00)then return end if(collidee.player.playerstate ~= PST_LIVE or collidee.player.respawn.state ~= 0x00)then return end -- Overhead if(collidee.z > self.z + self.height)then return end -- Underneath if(collidee.z + collidee.height < self.z)then return end -- Ghosted if(self.player.hyudorotimer or collidee.player.hyudorotimer)then return end -- If they're flashing, don't. if(collidee.player.flashing)then return end -- If they're invincible, check. (optional, if you like grow being stronger then you can change that :) if(not cvar_grow_stronger_inv.value)then if(collidee.player.invincibilitytimer > 0)then return end end -- Falling really fast onto your enemy? yeah here you go local fast_speed_check = cvar_stomp_flatten.value if(fast_speed_check)then fast_speed_check = ((self.momz - collidee.momz) < (-32*collidee.scale * P_MobjFlip(collidee))) and abs(self.momz) > abs(collidee.momz) and P_IsObjectOnGround(collidee) end -- Are we larger? local required_diff = (mapobjectscale/4) if(self.scale <= collidee.scale + required_diff and not fast_speed_check)then return end -- Using current abilities (fling instead of squash) if(self.player.invincibilitytimer > 0)then return end if(self.player.flamedash > 0 and self.player.curshield == KSHIELD_FLAME)then return end if(self.player.curshield == KSHIELD_TOP and (self.player.cmd.buttons & BT_DRIFT) ~= BT_DRIFT)then return end if(self.player.bubbleblowup > 0)then return end -- Same team? if(G_GametypeHasTeams() and self.player.team == collidee.team)then return end -- We'll just call that good. mobj_flatten(collidee,self,self,(gametyperules>R_BUMPERS) ~= GTR_BUMPERS) -- funny coconut sound if(fast_speed_check)then S_StartSound(collidee,sfx_hitonhead) end return false end function _flat.hooks.StoneShoeCollide(self,collidee) if(not cvar_flattened_enabled.value)then return end if(not cvar_stone_shoe_flattens.value)then return end if(not self.player)then return end if(collidee.type ~= MT_STONESHOE)then return end local other_player = nil if(collidee.owner and collidee.owner.player)then other_player = collidee.owner.player end -- Respawn states if(self.player.playerstate ~= PST_LIVE or self.player.respawn.state ~= 0x00)then return end -- Overhead if(collidee.z > self.z + self.height)then return end -- Underneath if(collidee.z + collidee.height < self.z)then return end -- Actually moving if(abs(collidee.momx) + abs(collidee.momy) < 8*self.scale)then return end -- Ghosted if(self.player.hyudorotimer)then return end -- If they're flashing, don't. if(self.player.flashing)then return end -- We'll just call that good. mobj_flatten(self,collidee,collidee.owner,(gametyperules>R_BUMPERS) ~= GTR_BUMPERS) end addHook("ShouldDamage",_flat.hooks.ShouldDamage,MT_PLAYER) addHook("PreThinkFrame",_flat.hooks.PreThink) addHook("PostThinkFrame",_flat.hooks.PostThink) addHook("MobjCollide",_flat.hooks.MobjCollide,MT_PLAYER) addHook("MobjCollide",_flat.hooks.StoneShoeCollide,MT_PLAYER) addHook("MobjMoveCollide",_flat.hooks.MobjCollide,MT_PLAYER) -- API ---@function Allows the flatten, and restored sounds to be replaced by different sounds. The only reason this is provided is because this is a lua script only, and I want to avoid making this a wad. Allows you to make a sound mod for this mod. ---@param name Either "flattened", "restored" or "headflattened", otherwise will throw an error. ---@param sfxid The sfx_ constant to play when squished. ---@return namespace, for chaining functions. function _flat.api.changeSound(name,sfxid) if(name:lower() == "flattened")then sfx_squish = sfxid return _flat elseif(name:lower() == "restored")then sfx_unsquish = sfxid return _flat elseif(name:lower() == "headflattened")then sfx_hitonhead = sfxid return _flat end print("[flattened.lua][ERROR][changeSound]: Sound name '"..name.."' not recognised! Name can only be 'flattened', 'restored', or 'headflattened'!") return _flat end ---@function Flatten a mobj. Only works on MT_PLAYER. ---@param mobj The object to flatten. Should only be type MT_PLAYER. ---@param no_damage If true, will not deal damage to the object. ---@param inflictor What did it? Can be nil. ---@param source Who did it? Can be nil. ---@return namespace, for chaining functions. function _flat.api.mobjFlatten(mobj,inflictor,source,no_damage) if(userdataType(mobj) ~= "mobj_t")then print("[flattened.lua][ERROR][mobjFlatten]: mobj is not a mobj_t!") return _flat end mobj_flatten(mobj,inflictor,source,no_damage) return _flat end -- dont mind me im just clogging up globalspace lol rawset(_G,"flattening_lua",_flat)