--Hey! What you´re doing here pal! It´s okay if you want to use my code, just remember to credit me! Unless you just want to see it... local WSS_DEFAULT = { stretchstyle = 0, stretchlimit = 22, squashstyle = 0, squashlimit = 22, returnstyle = 0, returnspd = 2, stretchheight = 10, squashwidth = 10 } local StretchNames = { [0] = "Classic", [1] = "Airflow" } local SquashNames = { [0] = "Landing", [1] = "State", [2] = "Speed" } local ReturnNames = { [0] = "Sharp", [1] = "Smooth", [2] = "Jelly" } local function WSS_CopyTable(t) local new = {} for k,v in pairs(t) do new[k] = v end return new end local WSS_CONFIG = WSS_CopyTable(WSS_DEFAULT) local function WSS_LoadConfig() local file = io.openlocal("wss_config.cfg") if not file then return end local data = {} for i = 1,8 data[i] = tonumber(file:read("*l")) end file:close() if data[1] then WSS_CONFIG.stretchstyle = data[1] end if data[2] then WSS_CONFIG.stretchlimit = data[2] end if data[3] then WSS_CONFIG.squashstyle = data[3] end if data[4] then WSS_CONFIG.squashlimit = data[4] end if data[5] then WSS_CONFIG.returnstyle = data[5] end if data[6] then WSS_CONFIG.returnspd = data[6] end if data[7] then WSS_CONFIG.stretchheight = data[7] end if data[8] then WSS_CONFIG.squashwidth = data[8] end end local function WSS_SaveConfig(p) local file = io.openlocal("wss_config.cfg", "w") if not file CONS_Printf(p, "\x85Failed to create config file.") else file:write(WSS_CONFIG.stretchstyle, "\n") file:write(WSS_CONFIG.stretchlimit, "\n") file:write(WSS_CONFIG.squashstyle, "\n") file:write(WSS_CONFIG.squashlimit, "\n") file:write(WSS_CONFIG.returnstyle, "\n") file:write(WSS_CONFIG.returnspd, "\n") file:write(WSS_CONFIG.stretchheight, "\n") file:write(WSS_CONFIG.squashwidth, "\n") file:close() end end local function WSS_Reset(p) WSS_CONFIG = WSS_CopyTable(WSS_DEFAULT) WSS_SaveConfig(p) CONS_Printf(p, "\x82WSS configuration reset to default.") end local function ApplyConfigToPlayer(p) p.wss_stretchstyle = WSS_CONFIG.stretchstyle p.wss_stretchlimit = WSS_CONFIG.stretchlimit * FU p.wss_squashstyle = WSS_CONFIG.squashstyle p.wss_squashlimit = WSS_CONFIG.squashlimit * FU p.wss_returnstyle = WSS_CONFIG.returnstyle p.wss_returnspd = WSS_CONFIG.returnspd * FU / 10 p.wss_stretchheight = WSS_CONFIG.stretchheight p.wss_squashwidth = WSS_CONFIG.squashwidth end local function WSS_UpdateConfig(p, msg) ApplyConfigToPlayer(p) WSS_SaveConfig(p) CONS_Printf(p, "\x83"..msg) end COM_AddCommand("wss", function(p, z, a, b) if z == "stretch" if a == "style" if b == "0" or b == "classic" WSS_CONFIG.stretchstyle = 0 WSS_UpdateConfig(p, "Stretch style set to: Classic.") elseif b == "1" or b == "airflow" WSS_CONFIG.stretchstyle = 1 WSS_UpdateConfig(p, "Stretch style set to: Airflow.") else CONS_Printf(p, "0 = Classic (stretchs once player's mid-air).") CONS_Printf(p, "1 = Airflow (stretchs based on vertical speed).") end elseif a == "limit" if b local num = tonumber(b) if num == nil CONS_Printf(p, "\x85Please enter a valid number.") else if num <= 0 WSS_CONFIG.stretchlimit = 0 WSS_UpdateConfig(p, "Stretch disabled.") else local value = min(num, 30) WSS_CONFIG.stretchlimit = value WSS_UpdateConfig(p, "Stretch limit set to: "..value..".") end end else CONS_Printf(p, "Default: 29 | Type 0 to disable stretching.") end elseif a == "height" if b local num = tonumber(b) if num == nil or num < 0 CONS_Printf(p, "\x85Please enter a valid number and above -1.") else local value = min(num, 30) WSS_CONFIG.stretchheight = value WSS_UpdateConfig(p, "Stretch height set to: "..value..".") end else CONS_Printf(p, "Default: 10") end else CONS_Printf(p, "(wss stretch style <0/1>) Stretch algorithm.") CONS_Printf(p, "(wss stretch limit ) Maximum stretch.") CONS_Printf(p, "(wss stretch height ) Vertical stretch intensity.") end elseif z == "squash" if a == "style" if b == "0" or b == "landing" WSS_CONFIG.squashstyle = 0 WSS_UpdateConfig(p, "\x83Squash style set to: Landing.") elseif b == "1" or b == "state" WSS_CONFIG.squashstyle = 1 WSS_UpdateConfig(p, "Squash style set to: State.") elseif b == "2" or b == "speed" WSS_CONFIG.squashstyle = 2 WSS_UpdateConfig(p, "Squash style set to: Speed.") else CONS_Printf(p, "0 = Landing (when player lands).") CONS_Printf(p, "1 = State (when player's state changes).") CONS_Printf(p, "2 = Speed (based on player's ground speed).") end elseif a == "limit" if b local num = tonumber(b) if num == nil CONS_Printf(p, "\x85Please enter a valid number.") else if num <= 0 WSS_CONFIG.squashlimit = 0 WSS_UpdateConfig(p, "Squash disabled.") else local value = min(num, 30) WSS_CONFIG.squashlimit = value WSS_UpdateConfig(p, "Squash limit set to: "..value..".") end end else CONS_Printf(p, "Default: 18 | Type 0 to disable squashing.") end elseif a == "width" if b local num = tonumber(b) if num == nil or num < 0 CONS_Printf(p, "\x85Please enter a valid number and above -1.") else local value = min(num, 30) WSS_CONFIG.squashwidth = value WSS_UpdateConfig(p, "Squash width set to: "..value..".") end else CONS_Printf(p, "Default: 10") end else CONS_Printf(p, "(wss squash style <0/1/2>) Squash algorithm.") CONS_Printf(p, "(wss squash limit ) Maximum squash.") CONS_Printf(p, "(wss squash width ) Horizontal squash intensity.") end elseif z == "returnscale" if a == "style" if b == "0" or b == "sharp" WSS_CONFIG.returnstyle = 0 WSS_UpdateConfig (p, "Return style set to: Sharp.") elseif b == "1" or b == "smooth" WSS_CONFIG.returnstyle = 1 WSS_UpdateConfig (p, "Return style set to: Smooth.") elseif b == "2" or b == "jelly" WSS_CONFIG.returnstyle = 2 WSS_UpdateConfig (p, "Return style set to: Jelly.") else CONS_Printf(p, "0 = Sharp (linear return).") CONS_Printf(p, "1 = Smooth (exponential return).") CONS_Printf(p, "2 = Jelly (overshoots slightly before settling).") end elseif a == "speed" if b local num = tonumber(b) if num == nil or num <= 0 CONS_Printf(p, "\x85Please enter a valid number and above 0.") else local value = min(num, 10) WSS_CONFIG.returnspd = value WSS_UpdateConfig (p, "\x83Return speed set to: "..value..".") end else CONS_Printf(p, "Current return speed: "..(p.wss_returnspd or 1)..".") CONS_Printf(p, "Default: 1") end else CONS_Printf(p, "(wss returnscale style <0/1/2>) Returning sprite scale animation.") CONS_Printf(p, "(wss returnscale speed ) Returning sprite animation speed.") end elseif z == "reset" WSS_Reset(p) ApplyConfigToPlayer(p) elseif z == "info" CONS_Printf(p, "\x82Stretch") CONS_Printf(p, " Style : "..StretchNames[p.wss_stretchstyle or 0]) CONS_Printf(p, " Limit : "..(p.wss_stretchlimit or 29*FU) / FU) CONS_Printf(p, " Height: "..(p.wss_stretchheight or 10)) CONS_Printf(p, "\x82Squash") CONS_Printf(p, " Style : "..SquashNames[p.wss_squashstyle or 0]) CONS_Printf(p, " Limit : "..(p.wss_squashlimit or 18*FU) / FU) CONS_Printf(p, " Width : "..(p.wss_squashwidth or 10)) CONS_Printf(p, "\x82Return Scale") CONS_Printf(p, " Style : "..ReturnNames[p.wss_returnstyle or 0]) CONS_Printf(p, " Speed : "..(p.wss_returnspd or 2*FU) / FU) else CONS_Printf(p, "(wss stretch) Configure stretching.") CONS_Printf(p, "(wss squash) Configure squashing.") CONS_Printf(p, "(wss returnscale) Configure return animation.") CONS_Printf(p, "(wss reset) Reset all settings.") CONS_Printf(p, "(wss info) Show current settings.") CONS_Printf(p, "(wss ) Show info about command.") end end, COM_LOCAL) local function WSS_Main(p) if not p or not p.valid or not p.mo or not p.mo.valid then return end if p.wss_oldstate == nil p.wss_oldstate = p.mo.state end if p.wss_fallspeed == nil p.wss_fallspeed = p.mo.momz end if p.wss_stretchstyle == nil p.wss_stretchstyle = 0 end if p.wss_stretchlimit == nil p.wss_stretchlimit = 29*FU end if p.wss_stretchheight == nil p.wss_stretchheight = 10*FU end if p.wss_squashstyle == nil p.wss_squashstyle = 0 end if p.wss_squashlimit == nil p.wss_squashlimit = 18*FU end if p.wss_squashwidth == nil p.wss_squashwidth = 10*FU end if p.wss_returnspd == nil p.wss_returnspd = FU/10 end if p.wss_returnstyle == nil p.wss_returnstyle = 0 end if p.wss_spritescale == nil p.wss_spritescale = 0 end if p.wss_landed == nil p.wss_landed = false end if p.wss_spritescale >= 0 if p.wss_stretchheight == 0 p.mo.spriteyscale = FU p.mo.spritexscale = FU - p.wss_spritescale/34 else p.mo.spriteyscale = FU + (p.wss_spritescale/(44 - p.wss_stretchheight)) p.mo.spritexscale = FU - p.wss_spritescale/34 end else if p.wss_squashwidth == 0 p.mo.spriteyscale = FU + p.wss_spritescale/34 p.mo.spritexscale = FU else p.mo.spriteyscale = FU + p.wss_spritescale/34 p.mo.spritexscale = FU - (p.wss_spritescale/(44 - p.wss_squashwidth)) end end end local function WSS_Stretch(p) if not p or not p.valid or not p.mo or not p.mo.valid then return end local grounded = P_IsObjectOnGround(p.mo) if p.wss_midair == nil p.wss_midair = false end if not grounded local dist = p.mo.z - p.mo.floorz if p.wss_stretchstyle == 0 if p.mo.momz > 0 and p.wss_midair == false and (p.mo.state ~= S_PLAY_BOUNCE_LANDING and dist > 1*FU) p.wss_oldstate = p.mo.state p.wss_spritescale = p.mo.momz if p.wss_stretchstyle == 0 p.wss_midair = true if p.mo.momz > p.wss_stretchlimit p.wss_spritescale = p.wss_stretchlimit else p.wss_spritescale = p.mo.momz end end end elseif p.wss_stretchstyle == 1 if p.mo.momz > 0 if p.mo.momz > p.wss_stretchlimit*2 p.wss_spritescale = p.wss_stretchlimit else p.wss_spritescale = p.mo.momz/2 end else if p.mo.momz < -p.wss_stretchlimit*2 p.wss_spritescale = p.wss_stretchlimit else p.wss_spritescale = -p.mo.momz/2 end end end end end local function WSS_Squash(p) if not p or not p.valid or not p.mo or not p.mo.valid then return end local grounded = P_IsObjectOnGround(p.mo) if (p.wss_oldstate ~= p.mo.state and not grounded) or p.mo.momz <= 0 p.wss_midair = false end if p.mo.eflags & MFE_JUSTHITFLOOR p.wss_landed = true p.wss_oldstate = p.mo.state end if p.wss_squashstyle == 0 if not grounded then p.wss_fallspeed = p.mo.momz end if p.mo.eflags & MFE_JUSTHITFLOOR then local impact = abs(p.wss_fallspeed or 0) p.wss_spritescale = -min(impact*2, p.wss_squashlimit) end if p.mo.state == S_PLAY_BOUNCE_LANDING p.wss_spritescale = -p.wss_squashlimit end elseif p.wss_squashstyle == 1 if p.wss_oldstate ~= p.mo.state and grounded and p.wss_landed == false p.wss_spritescale = -p.wss_squashlimit p.wss_oldstate = p.mo.state end elseif p.wss_squashstyle == 2 and grounded local speed = FixedHypot(p.mo.momx, p.mo.momy) if speed ~= 0 local squash = FixedMul(FixedDiv(speed, 100*FU), p.wss_squashlimit) p.wss_spritescale = -min(squash, 32*FU) else p.wss_spritescale = 0 end end p.wss_landed = false end local function WSS_ReturnScale(p) if not p or not p.valid or not p.mo or not p.mo.valid then return end if (p.wss_squashstyle == 2 and P_IsObjectOnGround(p.mo)) or (p.wss_stretchstyle == 1 and not P_IsObjectOnGround(p.mo)) then return end if p.wss_spritescale ~= 0 local spd = (p.wss_returnspd / 2) if p.wss_returnstyle == 0 if p.wss_spritescale > 0 p.wss_spritescale = max(0, $ - spd*10) else p.wss_spritescale = min(0, $ + spd*10) end elseif p.wss_returnstyle == 1 local strength = min(FU-1, spd) p.wss_spritescale = FixedMul($, FU - strength) else if p.wss_scalevel == nil p.wss_scalevel = 0 end if p.wss_spritescale == 0 and abs(p.wss_scalevel) < FU/100 p.wss_scalevel = 0 end local spring = FixedMul(FU/8, spd*8) local force = -p.wss_spritescale p.wss_scalevel = $ + FixedMul(force, spring) p.wss_scalevel = FixedMul($, 4*FU/5) p.wss_spritescale = $ + p.wss_scalevel if abs(p.wss_spritescale) < FU/100 and abs(p.wss_scalevel) < FU/100 p.wss_spritescale = 0 p.wss_scalevel = 0 end end end end local function OverlayThinker(mo) if mo.tracer and mo.tracer.valid and mo.tracer.player and mo.tracer.player.valid mo.spritexscale = mo.tracer.spritexscale mo.spriteyscale = mo.tracer.spriteyscale end if mo.target and mo.target.valid and mo.target.player and mo.target.player.valid mo.spritexscale = mo.target.spritexscale mo.spriteyscale = mo.target.spriteyscale end end WSS_LoadConfig() addHook("PlayerSpawn", function(p) ApplyConfigToPlayer(p) p.wss_spritescale = 0 end) addHook("PlayerQuit", function(p) WSS_SaveConfig(p) end) addHook("PreThinkFrame", function() for player in players.iterate do WSS_Main(player); WSS_Stretch(player); WSS_Squash(player); WSS_ReturnScale(player); end end); addHook("MobjThinker", OverlayThinker, MT_THOK) addHook("MobjThinker", OverlayThinker, MT_TAILSOVERLAY) addHook("MobjThinker", OverlayThinker, MT_METALJETFUME)