Vestige
Member
Lua:
freeslot("VEST_SPRT", "BAR_SPRT") local button = BT_CUSTOM1 local bounceButton = BT_SPIN local skin = "vestige" local starttimer = 200 local max_dash_energy = 400 local dash_drain_per_tick = 2 local bounce_scale = {stretch = 14/10, squash = 6/10, duration = 10} local bounce_force = 15 * FRACUNIT local bounce_cooldown_max = 12 -- Helper Functions local function SpeedBoost_Reset(p) local mo = p.mo if mo and mo.skin == skin then p.normalspeed = skins[skin].normalspeed p.jumpfactor = skins[skin].jumpfactor p.charflags = p.charflags & ~SF_RUNONWATER p.camerascale = skins[skin].camerascale p.acceleration = skins[skin].acceleration mo.blendmode = AST_COPY mo.colorized = false mo.color = p.skincolor mo.scale = FRACUNIT p.accelstart = skins[skin].accelstart end end local function SpeedBoost_start(p, overcharge) local mo = p.mo if mo and mo.skin == skin then p.charflags = p.charflags | SF_RUNONWATER p.normalspeed = skins[skin].normalspeed + 10 + overcharge p.jumpfactor = skins[skin].jumpfactor + (p.jumpfactor / 3) + overcharge p.acceleration = skins[skin].acceleration - 20 p.camerascale = skins[skin].camerascale + (p.camerascale / 4) + overcharge mo.blendmode = overcharge >= 1 and AST_REVERSESUBTRACT or AST_SUBTRACT mo.colorized = true p.accelstart = 400 mo.color = SKINCOLOR_POWER end end local function afterimage(p) local mo = p.mo local trail = P_SpawnGhostMobj(mo) trail.flags = $|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY trail.angle = mo.angle trail.color = mo.color trail.scale = mo.scale trail.blendmode = AST_ADD trail.colorized = true trail.fuse = 6 end local function dashParticleBurst(p) local mo = p.mo for i = 0, 31 do local angle = i * ANG1 * 11 local px = P_SpawnMobj(mo.x, mo.y, mo.z + 8*FRACUNIT, MT_THOK) px.momx = FixedMul(cos(angle), 5*FRACUNIT) px.momy = FixedMul(sin(angle), 5*FRACUNIT) px.momz = P_RandomRange(-2, 2)*FRACUNIT px.fuse = 10 px.scale = FRACUNIT/2 px.color = mo.color px.state = S_THOK end end addHook("PlayerThink", function(p) local mo = p.mo if not mo or mo.skin ~= skin then return end if not p.vestige then p.vestige = {} end local data = p.vestige if (p.cmd.buttons & bounceButton) and not P_IsObjectOnGround(mo) and not data.dashing and not (p.pflags & PF_THOKKED) and (data.bounce_cooldown or 0) <= 0 then bounce_force = min(((p.speed / 100000 / 4) + 3 + abs(mo.momz / 10000) / 4), 30) P_SetObjectMomZ(mo, bounce_force * FRACUNIT * -2) mo.state = S_PLAY_JUMP p.pflags = $ | PF_THOKKED S_StartSound(mo, sfx_bnce2, p) data.dash_energy = max(0, data.dash_energy - 20) data.want_to_bounce = true end if data.want_to_bounce and P_IsObjectOnGround(mo) then P_SetObjectMomZ(mo, bounce_force * FRACUNIT) mo.state = S_PLAY_JUMP p.pflags = $ | PF_SPINNING P_StartQuake(10 * FRACUNIT, TICRATE / 2) S_StartSound(mo, sfx_bnce2) data.want_to_bounce = false data.bounce_cooldown = bounce_cooldown_max end if data.bounce_cooldown and data.bounce_cooldown > 0 then data.bounce_cooldown = $ - 1 end end) -- Main Logic addHook("PlayerThink", function(player) if not player.mo or player.mo.skin ~= skin then return end if not player.vestige then player.vestige = { dash_energy = 0, notdashingtimer = 20, dashing = false, can_dash = true, combo = 0, combo_timer = 0, combo_score = 0, energy_force = 0, bounce_cooldown = 0 } end local data = player.vestige local mo = player.mo if (player.mo.eflags & MFE_UNDERWATER) then data.energy_force = 30 else data.energy_force = 60 end data.dash_energy = tonumber(data.dash_energy) or 0 data.combo = data.combo or 0 data.combo_timer = data.combo_timer or 0 data.combo_score = data.combo_score or 0 data.notdashingtimer = data.notdashingtimer or 20 data.energy_force = data.energy_force or 0 data.bounce_cooldown = data.bounce_cooldown or 0 if data.bounce_cooldown and data.bounce_cooldown > 0 then end local dash_energy = data.dash_energy local overcharged = (dash_energy > starttimer) and (dash_energy - starttimer) or 0 if not data.dashing then data.notdashingtimer = data.notdashingtimer - 1 player.mo.dashtime = 0 end if dash_energy < starttimer / 2 then data.dash_energy = $1 + 1 SpeedBoost_Reset(player) else SpeedBoost_start(player, overcharged) if dash_energy < starttimer then data.dash_energy = $1 + 1 end end if data.dashing then data.dash_energy = dash_energy - dash_drain_per_tick if data.dash_energy <= 0 or (not (player.cmd.buttons & button) and player.playerstate == PST_LIVE) and not P_PlayerInPain(player) then data.dashing = false player.mo.dashtime = 0 player.charflags = player.charflags & ~SF_CANBUSTWALLS else player.mo.dashtime = player.mo.dashtime + 1 afterimage(player) player.charflags = player.charflags | SF_CANBUSTWALLS player.pflags = player.pflags & ~PF_SPINNING P_InstaThrust(player.mo, player.drawangle, data.energy_force * FRACUNIT) player.pflags = $ & ~PF_SPINNING if P_IsObjectOnGround(player.mo) then player.mo.state = S_PLAY_RUN if player.mo.speed == 0 then player.mo.speed = Player.mo.speed + 1 end P_SpawnSkidDust(player, player.mo.radius, true) player.mo.state = S_PLAY_RUN elseif player.pflags & PF_JUMPED and player.mo.dashtime <= 9 then player.mo.momz = ((player.speed + (player.speed / 2)) / FRACUNIT) + sin(player.mo.angle) + 4 * FRACUNIT end end end if not (player.cmd.buttons & button) then if not data.dashing and data.notdashingtimer <= 0 then data.can_dash = true data.notdashingtimer = 20 end else if not data.dashing and data.can_dash and dash_energy >= 20 then data.dashing = true data.can_dash = false player.mo.dashtime = 1 // P_RadiusAttack(player.mo, player.mo, 100*FRACUNIT, DMG_INSTAKILL, player) afterimage(player) S_StartSound(player.mo, sfx_vboost, player) P_StartQuake(10*FRACUNIT, TICRATE / 2) dashParticleBurst(player) end end end) -- Award dash energy for killing enemies addHook("MobjDeath", function(mo, inflictor, source) if not source or not source.player then return end local player = source.player if not player.mo or player.mo.skin ~= skin then return end if not player.vestige then return end player.vestige.dash_energy = min(max_dash_energy, (player.vestige.dash_energy or 0) + 25) player.pflags = $ & ~PF_THOKKED end) addHook("MobjDamage", function(target, inf, src, dmg, dmgType) if target.player and target.player.vestige and target.skin == skin then local data = target.player.vestige if data.dashing == true then if dmgType == DMG_FIRE or dmgType == DMG_WATER or dmgType == DMG_ELECTRIC or dmgType == DMG_SPIKE or dmgType == DMG_NUKE or dmgType == DMG_DROWNED or dmgType == DMG_CRUSHED or dmgType == DMG_CANHURTSELF then return true end end end end, MT_PLAYER) for _, spike in ipairs({MT_SPIKE, MT_WALLSPIKE}) do addHook("MobjCollide", function(mobj, playermobj) if playermobj.player and playermobj.player.vestige and playermobj.skin == skin then local data = playermobj.player.vestige if data.dashing == true then P_KillMobj(mobj, playermobj, playermobj) data.dash_energy = data.dash_energy + 10 end end end, spike) end addHook("MobjCollide", function(mobj, playermobj) if playermobj.player and playermobj.player.vestige and playermobj.skin == skin then local data = playermobj.player.vestige if playermobj.player and playermobj.player.vestige and playermobj.skin == skin and mobj.flags & MF_ENEMY and data.dashing == true then P_KillMobj(mobj, playermobj, playermobj) end end end) addHook("MobjCollide", function(mobj, playermobj) if playermobj.player and playermobj.player.vestige and playermobj.skin == skin then local data = playermobj.player.vestige if playermobj.player and playermobj.player.vestige and playermobj.skin == skin and mobj.flags & MF_MONITOR and data.dashing == true then P_KillMobj(mobj, playermobj, playermobj) end end end) addHook("PlayerSpawn", function(player) if player.mo and player.mo.skin == skin then player.vestige = { dash_energy = 0, dash_penalty = 0, dashed_once = false, } end end)