local movement = { MODULE_ID = "movement"; initialized = false; } local tick =os.clock function movement.initialize() print("Loading movement module") do type _raycastResult = { hit:Instance, pos:Vector3, normal:Vector3, material:string, origin:CFrame, length:number, alpha:number } -- shortcuts local localPlayer:Player = game.Players.LocalPlayer local players = {[localPlayer]=localPlayer} local characters = {} local mouse = localPlayer:GetMouse() local isa = game.IsA local wfc = game.WaitForChild local root_wfd = nil local ffc = function(instance,name,recursive) return instance:FindFirstChild(name,recursive) end local findDescendant = function(instance:Instance,...) local target = instance local path = {...} for _,name in pairs(path) do target = target:FindFirstChild(name) if not target then return end end return target end local getchildren = game.GetChildren local cf = CFrame.new local cfzero = CFrame.identity local angles = CFrame.Angles local tos = cfzero.toObjectSpace local v2 = function(x:number|Vector3,y:number|boolean) if typeof(x) == "Vector3" then --convert Vector3 into Vector2, x:Vector3, y:bool, if y is true, then it will use a different axis return Vector2.new(x.X,y and x.Y or x.Z) else return Vector2.new(x,y) end end local printOut = print local print = print if not (game["Run Service"]:IsStudio() or game.PlaceId == 17653179714) then print = function() end end local loadingCameraCF = cf(3316.62622, 453.794464, -123.563583, -0.764629662, 0.240535319, -0.597899914, -0, 0.927738965, 0.373229682, 0.644469976, 0.285382479, -0.709376693) local v3 = Vector3.new local v3zero = Vector3.zero local v3one = v3(1,1,1) local function unit(vector) return vector.magnitude > 0 and vector.unit or v3(0,1,0) end local function unitv3(x,y,z) local vector = v3(x,y,z) return unit(vector) end local function v3flat(vector) return v3(vector.X,0,vector.Z) end local clamp = math.clamp local ray = Ray.new local debris = game.Debris local ud2 = UDim2.new local destroy = game.Destroy local remove = table.remove local abs = math.abs local rad = math.rad local deg = math.deg local min = math.min local max = math.max local contentProvider = game:GetService("ContentProvider") local replicated = game:GetService("ReplicatedStorage") local pui = wfc(localPlayer,"PlayerGui") local physicsService = game:GetService("PhysicsService") local http = game:GetService("HttpService") local validQueueNames = { heartbeat = true, logs = true, metrics = true, security = true, UserSecurity = true, UserMetrics = true, FrameworkErrors = true, } local defaultRJC = cf(0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 1, -0) local mapBounds = {v2(1149.8,-2048),v2(7293.8,3072)} local function useNonZeroV3(...) local vectors = {...} for i, v in pairs(vectors) do if v.magnitude > 0 then return v end end -- Print a WARN message as well warn("could not find nonzero vector with vectors",...) end local signedRandom = function(number) return (math.random()-.5)*(number or 1)*2 end local function lerp(a:number,b:number,t:number) return a*(1-t)+(b*t) end local modules = game.ReplicatedFirst["Modules"] local event = require(script.Parent.Event).event local events = require(script.Parent.Event).event local camera = require(script.Parent.Camera) local utility = require(script.Parent.Utility) local ui = require(script.Parent.UI) local engine = require(script.Parent.Engine) local actor = require(script.Parent.Actor) local input = require(script.Parent.Input) local network = require(script.Parent.Network) local sound = require(script.Parent.Sound) local music = sound.music local hitbox = require(script.Parent.Hitbox) local score = require(script.Parent.Score) local gear = require(script.Parent.Gear) local debugger = require(script.Parent.Debugger) local raycast = require(script.Parent.Raycast) local objective = require(script.Parent.Objective) local world = require(script.Parent.World) local data = require(script.Parent.Data) local tween = require(script.Parent.Tween) local props = require(script.Parent.Props) local logic = require(script.Parent.Logic) local dialog = require(script.Parent.Dialog) local alphaFromRange = function(value:number,min:number,max:number,scaleLower:number,scaleUpper:number,easingStyle:Enum.EasingStyle,easingDirection:Enum.EasingDirection) return utility.alphaFromRange(value,min,max,scaleLower,scaleUpper,easingStyle,easingDirection) end local function getDistance(a1:Vector3,a2:Vector3):number if not a2 then a2 = actor.character and actor.character.WorldPivot.Position or (camera.cam and camera.cam.Focus.p or a1) end if typeof(a1) == "CFrame" then a1 = a1.Position end if typeof(a2) == "CFrame" then a2 = a2.Position end return (a1-a2).Magnitude end local function withinEqual(number,min,max) return number >= min and number <= max end local function normalToOrientedCFrame(normal:Vector3) return cf(v3zero,normal) end local function augmentVelocity(vel) local force = vel.magnitude local adjustedMag = max(0,actor.velocity.magnitude-force) local added = (unit(actor.velocity)*adjustedMag) + vel local mag = math.max(force,actor.velocity.magnitude) return added.unit*mag end local function getOffsetFromPlane(point,planePoint,planeNormal) return planeNormal:Dot(point-planePoint) end local function getUpVector(v) return normalToOrientedCFrame(v).UpVector end local animation = require(script.Parent.Animation) --defaults movement.pipeDebounce = {} movement.highJumping = false movement.lastJumpBuffer = 0 movement.lastSlideBuffer = 0 --constants movement.floatPower = 3 movement.floatDecay = 64 movement.baseJumpPower = 6 movement.speedToJumpPowerRatio = .4 movement.leapMultiplier = 1/.725 movement.parkourFallingThreshold = -75 movement.doubleJumpStrength = 35 movement.doubleJumpDashStrength = 30 movement.jumpBufferTime = .075 movement.slideBufferTime = .025 movement.parkour = { is = false, last = nil, lastTick = tick(), land = { covert = true, --if true this ability being active doesnt count as parkouring = true --defaults last = 0, type = nil, --constants debounce = .5, fatalDistance = 65, minLandingHeight = 8, minDamageHeight = 20, minDamage = 20, ms = { roll = 175, precise = 90, perfect = 50, }, multipliers = { unprepared = .58, bad = .75, normal = .8, imperfect = .95, } }, vault = { --defaults active=false, enabled = true, --constants minSpeed = 16, }, wallrun = { --defaults active=false, enabled = true, casted = nil, normal=v3(0,1,0), velocity=v2(), start=0, lateral=false, lateralDirection=0, timeHanging=0, pushFuel=0, speed=0, hookTime=0, lastRunNormal=v3(0,1,0), lastClimbNormal=v3(0,1,0), left=false, accumulator=0, horizontalDuration=0, verticalDuration=0, maxLateralFallDistance=0, maxVerticalFallDistance=0, coyoteBudget=0, --constants FPS=120, transitionResponses = { vault = true, wallclimb = true, mantle = true, climb = true }, horizontalGravity = 20, verticalGravity = 90, defaultHorizontalDuration=1, defaultVerticalDuration=4, defaultLateralFallDistance=30, defaultVerticalFallDistance=5, clutchSpeed=-10, maxHangTime=1, basePush=22.75, --25 maxExtraPush=0, hookDuration=.5, maxPushTime=.4, minPushTime=.3125, minAngleChange=math.cos(math.rad(5)), angleCutoff=math.cos(math.rad(60)), bounceWindow=.2, coyoteTime=1/20, --time in seconds player will wallrun on air in attempt to find another surface or receive input before falling + 1 frame timeToWallBoostMax = .25, -- maximum time in seconds after starting a wall clutch the player will be able to wall boost timeToWallBoostMin = .06, -- time in seconds angle concessions will be at their maximum for fast-boosting players }, cornerhook = {active=false}, dropdown = { covert=true, --if true this ability being active doesnt count as parkouring = true --defaults active=false, enabled = true, dir=v3(0,0,-1), did=false }, climb = {active=false,enabled=true}, pipeclimb = {active=false,cancel=false}, powerslide = { covert=true, --if true this ability being active doesnt count as parkouring = true --defaults active=false, enabled = true, velocity=v3zero, last=0, entrySpeed=0, --constants frictionFactor=2, --factor of speed loss as a divisor (speed =/ 1 + frictionFactor) frictionlessWindow=.2, --time before friction begins applying boost=1.25, --multiplies current velocity upon entry into powerslide cooldown=1, minSpeed=8, }, slide = { covert=true, --if true this ability being active doesnt count as parkouring = true --defaults active=false, enabled = true, lastSlide=0, --constants minSpeed=12, speedBoost=4, boostCooldown=.5, }, dash = { covert=true, --if true this ability being active doesnt count as parkouring = true --defaults enabled = true, active=false, afterboosted=false, holdForLanding=false, --[[wallKickExhaust=false,]] query=false, airQuery=false, totalChainJumps=0, elapsed=0, lastUse=0, lastRelease=0, lastAirUse=0, lastLongJump=0, doors={}, obstacles={}, --constants length=2, chargeTime=.5, cooldown=1, airCooldown=.5, wallKickWindow=.2, afterboostWindow=.2, afterboostDuration=.2, }, zipline = { --defaults active=false, debounce={model=nil,time=0}, --constants mechanizedSpeed=50, maxSpeed=90, grabDistance=10, friction=5 --deceleration in studs/s/s }, wallkick = { --defaults did=false, enabled = true, --constants minSpeed=12, --speed at which the momentum range floors maxSpeed=24, --speed at which the momentum range caps minMomentum=18, --lower momentum range maxMomentum=30, --upper momentum range upMomentum=28, --amount of upward momentum given }, dropkick = { covert = true; enabled = true; active = false; last = 0; cooldown = 1; maxVertical = 16; verticalDivisor = 5; maxBoost = 12; recoveryTime = 0.85; } } movement.abilities = require(modules:WaitForChild("Abilities")) event.new("parkour") event.new("land") event.new("jump") event.new("wallJump") function movement.parkour.wallrun:getAnimSpeed() return 1--clamp(movement.parkour.wallrun.speed/20,.75,1.75) end function movement.parkour.zipline:canGrab(model:Model) local db = movement.parkour.zipline.debounce return ((model ~= db.model or tick()-db.time > 1.5) and not movement.parkour.is) end local movementFunctable = {__call = function(_,move) movement.parkour.last = move movement.parkour.lastTick = tick() --print("performed",move) events.parkour:Fire(move) end} setmetatable(movement,movementFunctable) local function lerpRootUp(height,length) local totalAdded = 0 local alpha = height / math.abs(height) height = math.abs(height) while true do local delta = engine.wait() local toAdd = delta / length if totalAdded+toAdd >= height then actor.rootpart.CFrame += v3(0,height-totalAdded,0) * alpha break else totalAdded += toAdd actor.rootpart.CFrame += v3(0,toAdd,0) * alpha end end end function movement:crash(speed) --print("crash",speed) local gravity = actor.defaultGravity local studsFallenEquivalent = 0.5*gravity*(speed/gravity)^2 local damage = (studsFallenEquivalent/movement.parkour.land.fatalDistance)*200 if game.ReplicatedStorage.PlayerData[localPlayer.Name].Mods.ToggleFallDamage.Value == false then actor:inchealth(-damage) else end end function movement:isParkouring() movement.parkour.is = false for i,v in pairs(movement.parkour) do if typeof(v) == "table" and v.active and not v.covert then movement.parkour.is = true break end end return movement.parkour.is end function movement:updatePhysicsEnabled() movement:isParkouring() if movement.parkour.wallrun.active or movement.parkour.climb.active then actor.physics.Disabled = true else actor.physics.Disabled = false end end function movement:setMovementActive(index,bool) movement.parkour[index].active = bool --movement:isParkouring() -- unnecessary, :updatePhysicsEnabled already calls this movement:updatePhysicsEnabled() end function movement:stopAll() if movement.parkour.powerslide.active then movement:stopPowerslide() end for i,v in pairs(movement.parkour) do if type(v) == "table" and v.active ~= nil then v.active = false end end movement:updatePhysicsEnabled() end function movement:stopWallrunAnimations(...) animation.wallclimbL:SafeStop(...) animation.wallclimbR:SafeStop(...) animation.wallstepL:SafeStop(...) animation.wallstepR:SafeStop(...) animation.wallclimbLastL:SafeStop(...) animation.wallclimbLastR:SafeStop(...) if not movement.parkour.cornerhook.active then animation.cornerhangleft:SafeStop(...) animation.cornerhangright:SafeStop(...) end end function movement:isWallrunClutching() local wallrun = movement.parkour.wallrun local duration = tick()-wallrun.start return duration > wallrun.verticalDuration or wallrun.velocity.Y < 0 or input.stickyBinds.downmove end function movement:TweenRootToCFrame(targetcf,duration) local startcf = actor.rootpart.CFrame local tweenStart = tick() local lastAlpha = 0 actor.humanoid:SetVelocity(v3zero) local yield = true local bindID = "rootTween"..os.time() network:bounce("rootPartTween",actor.character,startcf,targetcf,duration) game["Run Service"]:BindToRenderStep(bindID,Enum.RenderPriority.Camera.Value-1,function() local alpha = math.min(1,(tick()-tweenStart)/duration) if lastAlpha < 1 then actor.humanoid:SetVelocity(v3zero) actor.rootpart.CFrame = startcf:Lerp(targetcf,alpha) end lastAlpha = alpha if tick()-tweenStart > duration then yield = false --print("pls stop (this should only appear once)") game["Run Service"]:UnbindFromRenderStep(bindID) end end) while yield do engine.wait() end end -- MOVESET DEFINITION function movement:getOrigin() local rootcf = actor.rootpart.CFrame if camera:IsLocked() then return cf(rootcf.p,rootcf.p+v3flat(camera.rawlook)) else if actor.localInputVector.Magnitude > 0 then return cf(rootcf.p,rootcf.p+actor.inputVector) else return rootcf end end end function movement:jump(jumpType) actor:SwapJumpPhase() jumpType = jumpType or actor.jumpPhase if jumpType == "doublejump" and actor.ammo.doublejump > 0 and actor.velocity.Y < movement.doubleJumpStrength and not actor.frozen then local newVel = actor.velocity local dash = gear:hasUpgrade("Compound","BoostBelt",2) local upgraded = gear.equipped.Compound.level >= 2 if dash then local upStrength = 10 * (upgraded and 1.5 or 1) local strength = movement.doubleJumpDashStrength * (upgraded and 1.25 or 1) local input = useNonZeroV3(actor.inputVector,v3flat(actor.velocity),v3flat(actor.rootlook)).unit local force = input*strength force = force.unit * math.max(force.magnitude,v3flat(actor.velocity).magnitude) newVel = v3(force.X,math.min(upStrength,actor.velocity.Y+upStrength*3),force.Z) else local strength = movement.doubleJumpStrength * (upgraded and 1.5 or 1) newVel = v3(actor.velocity.X,math.min(strength,actor.velocity.Y+strength*1),actor.velocity.Z) end actor.velocity = newVel actor.humanoid:SetVelocity(newVel) actor.ammo.doublejump -= 1 elseif actor.character and actor.humanoid and actor.rootpart and actor.alive and require(script.Parent.Objective).timetrials.state ~= "countdown" and jumpType ~= "doublejump" then local wasOnGround = actor.onground(true) local wasSliding = actor.sliding actor.humanoid:SetState("Jumping") actor.physics.Grounded = false events.jump:fire() actor.ground = false actor.landed = false actor.jumping = tick() actor.ammo.jump = false local horizMultiplier = 1 local verticalAdd = 0 local down = raycast.raycast(ray(actor.rootpart.Position+actor.rootlook*2,v3(0,-4,0))) animation.roll:Stop() --animation.crouchRoll:Stop() animation.slideRoll:Stop() local dash = movement.parkour.dash local edgeJumpMult = dash.afterboosted and 1 or .65 local dashing = dash.active or dash.holdForLanding or tick()-dash.lastRelease < .2 if wasSliding then actor.lastSlideJump = tick() end if down.hit or wasSliding or not dashing then camera.jumpTilt.up = true if jumpType == "left" then animation.jumpL:Play() else animation.jumpR:Play() end if dash.holdForLanding then dash.active = false end dash.holdForLanding = false ui.hud.Momentum.Overcharge.Visible = false dash.totalChainJumps = 0 ui.hud.Chain.Text = "x"..dash.totalChainJumps ui.hud.Chain.Highlight.Text = dash.totalChainJumps ui.hud.Chain.Visible = false elseif (not down.hit or actor.velocity.Y > 8) and dashing then camera.jumpTilt.up = true movement(dash.afterboosted and "longjump" or "edgejump") horizMultiplier = 1 + (movement.leapMultiplier-1) * edgeJumpMult if dash.totalChainJumps > 0 then local factor = .5 horizMultiplier += (factor - factor / dash.totalChainJumps) end verticalAdd = 2 * edgeJumpMult if dash.afterboosted then dash.totalChainJumps += 1 if data:hasAbility("Chain") then local any_ToHSV_result1_5_upvr, any_ToHSV_result2_3_upvr, any_ToHSV_result3_2_upvr = ui.hud.Chain.Highlight.TextColor3:ToHSV() dash.holdForLanding = true network:send("chainJump",dash.totalChainJumps) ui.hud.Chain.Text = "x"..dash.totalChainJumps ui.hud.Chain.Highlight.Text = dash.totalChainJumps if dash.totalChainJumps >= 3 then ui.hud.Chain.Visible = true end --local Shortcut_upvr = require(Modules_upvr.Core.Shortcut) --function spawnFlash(arg1, arg2, arg3) -- Line 3174 -- local any_new_result1_upvr_6 = Shortcut_upvr.new(var2091_upvr, "_flash", nil, { -- ZIndex = var2091_upvr.ZIndex - 1; -- }) -- local seed = math.random() -- local var2099 = (-math.pi*2) * seed -- local var2100 = Vector2.new(math.cos(var2099), math.sin(var2099)).Unit * arg2 -- local Position_upvr_2 = any_new_result1_upvr_6.Position -- any_new_result1_upvr_6.TextTransparency = 0.75 -- local var2103_upvr = arg2 / 16 / (arg3 / 10 + 1) -- local Color3_fromHSV_result1_upvr_2 = Color3.fromHSV(Shortcut_upvr.lerp(any_ToHSV_result1_5_upvr, seed + Shortcut_upvr.signedRandom(0.05), math.max(0, arg3 ^ 1.3 / 50 - 0.15)) % 1, any_ToHSV_result2_3_upvr, any_ToHSV_result3_2_upvr) -- local var2105_upvr = Position_upvr_2 + UDim2.fromOffset(var2100.X, var2100.Y) -- task.spawn(function() -- Line 3195 -- any_new_result1_upvr_6.Parent = var2090_upvr -- Tween_upvr_2.play(any_new_result1_upvr_6, var2103_upvr, "Exponential", "In", { -- TextTransparency = 1; -- }) -- Tween_upvr_2.play(any_new_result1_upvr_6, var2103_upvr, "Exponential", "Out", { -- TextColor3 = Color3_fromHSV_result1_upvr_2; -- }) -- Tween_upvr_2.custom(var2103_upvr, "Exponential", "Out", function(arg1_45, arg2_11) -- Line 3199 -- local var2109 = arg3 * (1 - arg2_11) -- local var2110 = (-math.pi*2) * math.random() -- local var2111 = Vector2.new(math.cos(var2110), math.sin(var2110)) * var2109 -- any_new_result1_upvr_6.Position = Position_upvr_2:Lerp(var2105_upvr, arg2_11) + UDim2.fromOffset(var2111.X, var2111.Y) -- any_new_result1_upvr_6.Rotation = Shortcut_upvr.signedRandom(var2109 * 2) -- end) -- any_new_result1_upvr_6:Destroy() -- end) --end ----local var2090_upvr_result1_upvw, var2090_result2_upvw, var2090_upvr_result3_upvr = var2090_upvr(ui.hud.Chain.Highlight) --for _, v_34 in pairs(any_ToHSV_result1_5_upvr.getDescendantsOfType(any_ToHSV_result1_5_upvr, any_ToHSV_result2_3_upvr)) do -- handleConnection(v_34) --end end ui.hud.Momentum.Overcharge.Visible = true if actor.velocity.magnitude > actor.baseSpeed then local newHoriz = v3flat(actor.velocity).Unit*actor.speed actor.velocity = v3(newHoriz.X,actor.velocity.Y,newHoriz.Z) end animation.flailjump:Play(.75) if jumpType == "left" then animation.edgeJumpL:Play(.1,1,1) else animation.edgeJumpR:Play(.1,1,1) end dash.lastLongJump = tick() data.stats:increment("LongJumps",1) actor:speedboost() else animation.flailjump:Play(.2) end end local hasBoostBelt = gear:hasUpgrade("Compound","BoostBelt") local activeJumpPower = actor.jumpPower*movement.floatPower * (hasBoostBelt and 1.2 or 1) local inputtingMovement = actor.inputVector.magnitude > input.inputVectorZeroThreshold local horizontalSpeed = actor.horizontalVelocity.magnitude local useTheoreticalSpeed = (inputtingMovement and horizontalSpeed < actor.baseSpeed) local theoSpeed = actor.inputVector*actor.speed local targetHorizontal = useTheoreticalSpeed and theoSpeed*horizMultiplier or actor.horizontalVelocity*horizMultiplier local newSpeed if dashing then newSpeed = actor.speed else newSpeed = min(inputtingMovement and actor.maxSpeed or 0,actor.speed,actor.maxSpeed) end local targetMagnitude = max(newSpeed * horizMultiplier,horizontalSpeed) --print(totalSpeed,actor.speed,horizSpeed) targetHorizontal = unit(targetHorizontal) * targetMagnitude local powerslide = movement.parkour.powerslide if powerslide.active then local targetDir if inputtingMovement then local clamped = utility.clampVectorWithinCone(v2(actor.inputVector.Unit),v2(powerslide.velocity.Unit),120).unit targetDir = v3(clamped.X,0,clamped.Y).Unit else targetDir = powerslide.velocity.Unit end if targetDir.Magnitude ~= targetDir.Magnitude then targetDir = powerslide.velocity.Unit end targetHorizontal = targetDir * powerslide.entrySpeed movement:stopPowerslide() end local dropdown = movement.parkour.dropdown if dropdown.active then movement:setMovementActive("dropdown",false) end local charY = actor.velocity.Y local jumpStrength = max(0,charY) + actor.jumpPower + verticalAdd local maxAdditively = 42 local targetY = clamp(jumpStrength, 0, max(maxAdditively,charY)) -- RIP wumpy 2023 - 2023 --[[ if targetY > maxAdditively then --print(targetY) print("you just got wumpy nerf'd! your jump had ".. floor(((targetY-maxAdditively)/maxAdditively)*100) .."% less power than it would have had!") end --]] actor.humanoid:SetVelocity(v3( targetHorizontal.X, targetY, targetHorizontal.Z )) --print("jump") if score.combo.score.base > 0 then task.spawn(function() score.combo:attemptAdvanceCoverage() end) end sound:PlayStep("jump") movement.highJumping = tick() while not actor.ground and actor.jumping and movement.highJumping and actor.jumping < movement.highJumping do local delta = engine.wait() if activeJumpPower > 0 then --actor.humanoid:Nudge(v3(0,activeJumpPower*delta,0)) actor.gravity = actor.defaultGravity - activeJumpPower activeJumpPower = max(0,activeJumpPower - engine.delta*movement.floatDecay) --print(activeJumpPower) if not input.bindsDown.upmove and movement.highJumping --[[and tick()-movement.highJumping > .05]] then --print("no longer holding space",print(input.bindsDown.upmove)) activeJumpPower = 0 movement.highJumping = false end else movement.highJumping = false actor.gravity = actor.defaultGravity end end --print("end jump") actor.gravity = actor.defaultGravity actor.jumping = false movement.highJumping = false actor.humanoid:SetState("Falling") end end function movement:land(overrideAirVelocity) --print("landing") actor.airVelocity = overrideAirVelocity or actor.airVelocity actor.landing = true local allowBufferJump = true local allowBufferSlide = true local damage = 0 local district:Folder = utility.getDistrictAtPosition(actor.position) if district == false then actor:revertPosition() end local landingType local landData = movement.parkour.land if actor.rootpart and actor.humanoid and actor.velocity.Y < 10 and actor.alive and not movement.parkour.is and tick()-movement.parkour.land.last >= movement.parkour.land.debounce and actor.airTime > .1 then landData.last = tick() actor.landed = true actor.air = false actor.lastLandedTick = tick() local wasMoving = actor.inputVector.magnitude > input.inputVectorZeroThreshold local didDropdown = movement.parkour.dropdown.did if not actor.air then events.land:fire() end local dropkick_8 = movement.parkour.dropkick if dropkick_8.active then dropkick_8.last = tick() animation.dropKick_land:Play() movement:setMovementActive("dropkick", false) end local prepms = actor.preparing and math.max(0,tick()-actor.preparing-engine.delta)*1000 or math.huge local gravity = actor.defaultGravity --local fallSpeed = utility.velocityFromStudsFallen(studsFallen,actor.humanoid.Gravity,0,actor.terminalVelocity) local airSpeed = actor.airVelocity local angleAlpha = actor.physics.GroundNormal and -actor.physics.GroundNormal:Dot(actor.airVelocity.unit) or 1 local movementAngleAlpha = actor.rootlook:Dot(actor.inputVector) local fallSpeed = angleAlpha*actor.airVelocity.magnitude local studsFallen = 0.5*gravity*(fallSpeed/gravity)^2 --velocity based local damageMult = actor.preparing and (prepms < landData.ms.precise and 0 or alphaFromRange(prepms,landData.ms.precise,500,.35,1)) or 1 local criticalDistance = 0 if actor.preparing then if prepms > landData.ms.roll then criticalDistance = landData.fatalDistance*landData.multipliers.bad elseif prepms > landData.ms.precise then criticalDistance = landData.fatalDistance*landData.multipliers.normal elseif prepms > landData.ms.perfect then criticalDistance = landData.fatalDistance*landData.multipliers.imperfect else criticalDistance = landData.fatalDistance end else criticalDistance = landData.fatalDistance*landData.multipliers.unprepared end --local criticalSpeed = utility.velocityFromStudsFallen(criticalDistance,actor.humanoid.Gravity) local damageAlpha = tween.service:GetValue((studsFallen-landData.minDamageHeight-(didDropdown and 5 or 0))/(criticalDistance-landData.minDamageHeight),Enum.EasingStyle.Circular,Enum.EasingDirection.In) damage = landData.minDamage + damageAlpha*(actor.maxhealth-landData.minDamage) local rawDamage = damage --this is marking what the damage was before any changes were made down the line --actor:stopJumpAnimations() local cushioned = raycast.raycast.whitelist(ray(actor.rootpart.Position,v3(0,-10,0)),actor.pillows) cushioned = raycast.raycast.whitelist(ray(actor.rootpart.Position,v3(0,-10,0)),actor.pillows) -- why must i do this local breakthrough = raycast.raycast.whitelist(ray(actor.rootpart.Position,v3(0,-10,0)),{workspace.World.Props.Dynamics.FallStoppers}) --if didDropdown then -- damage = damage * .75 --end print(landData) if studsFallen > landData.minLandingHeight then if actor.preparing then if movementAngleAlpha < .45 and prepms >= landData.ms.roll then landingType = "straight" elseif wasMoving and angleAlpha < actor.maxSlideSlope/90 then landingType = "slide" elseif wasMoving and prepms < landData.ms.precise and studsFallen > landData.minDamageHeight-4 then landingType = "roll" elseif wasMoving then landingType = "fours" elseif not wasMoving then landingType = "straight" end if game.ReplicatedStorage.PlayerData:WaitForChild(localPlayer.Name).Mods.ToggleAlwaysFall.Value then landingType = "roll" end end if studsFallen < landData.minDamageHeight + (didDropdown and 10 or 0) then damageMult = 1 damage = 0 if not actor.preparing then actor:speedboost() animation.land:Play(.25) landingType = "stumble" end elseif not actor.preparing then landingType = "hard" end else damageMult = 1 damage = 0 end --print(damage,damageMult,rawDamage) damage = damage * damageMult if cushioned.hit and (studsFallen > landData.fatalDistance or damage > 0) then if actor.airVelocity.Y < -actor.terminalVelocity+10 then if prepms < landData.ms.precise and actor.stabilization >= .5 then damage = 0 landingType = "hard" movement("hardCushion") else damage = rawDamage end else damage = 0 if prepms < landData.ms.precise then landingType = "fours" else landingType = "hard" end end sound:PlayHybridSound("Cushion","game",{PlaybackSpeed=1+signedRandom(.1) }) elseif breakthrough.hit and (studsFallen > landData.fatalDistance or damage >= actor.health) then landingType = nil props.fallStopperFunctions[breakthrough.hit.Parent.Name].destroy(breakthrough.hit.Parent,actor.cframe,actor.airVelocity.Y) network:bounce("destroyFallStopper",breakthrough.hit.Parent,actor.cframe,actor.airVelocity.Y) damage = math.min(90,damage/2) actor.humanoid:SetState("Falling") actor.physics.Grounded = false actor.humanoid:SetVelocity(actor.airVelocity/(3.5-2*(abs(actor.airVelocity.Y)/actor.terminalVelocity))) landData.last = 0 actor.lastLandedTick = 0 actor.landed = false actor.lastBreakthrough = tick() elseif rawDamage >= 100 then damage = rawDamage end if damage > 0 then actor:incspeed(-3) end if damage >= actor.health and require(script.Parent.Objective).timetrials.state then landingType = "restartTrial" allowBufferJump = false allowBufferSlide = false else if game.ReplicatedStorage.PlayerData[localPlayer.Name].Mods.ToggleFallDamage.Value == false then actor:inchealth(-damage) else end end landData.type = landingType if studsFallen > 2 and landingType ~= "restartTrial" then local eq sound:PlayHybridGroupSound("Land","game") if studsFallen > 40 then sound:PlayHybridGroupSound("Hard","game") end end ui.dev.Debug.ms.Text = "ms: " .. math.floor(prepms) .. "\ndist: " .. math.floor(studsFallen) .. " / " .. math.floor(criticalDistance) .. "\ndmg: " .. math.floor(damage) .. " / " .. math.floor(rawDamage) actor:checkIfDead() if actor.alive then if data:hasAbility("Powerslide") then if landingType == "slide" then movement("slideLand") movement:powerslide() elseif actor.coiling and input.bindsDown.downmove then movement("slideLand") movement:slide() animation.coil:Stop() landingType = nil end end if didDropdown and landingType then movement("landDropdown") end if landingType == "roll" then local speed = max(1,actor.speed/actor.runAnimMultiplier) --[[local locked = camera:IsLocked() if locked and math.abs(actor.localInputVector.X) > 0.5 and actor.localInputVector.Z > -.5 then if actor.localInputVector.X < 0 then animation.rollR:Play(.1,1,speed) else animation.rollL:Play(.1,1,speed) end elseif locked and actor.localInputVector.Z > 0 then animation.rollB:Play(.1,1,speed) else animation.roll:Play(.1,1,speed) end]] animation.roll:Play(.1,1,speed) --[[ weighted if locked then local input:Vector3 = actor.localInputVector.unit animation.roll:Play(.1,max(0,(-input.Z))^2,speed) animation.rollB:Play(.1,max(0,input.Z)^2,speed) animation.rollR:Play(.1,max(0,-input.X)^2,speed) animation.rollL:Play(.1,max(0,input.X)^2,speed) else animation.roll:Play(.1,1,speed) end ]] sound:PlayHybridSound("Roll","game") movement("roll") elseif landingType == "straight" then animation.landstraight:Play() movement("landStraight") elseif landingType == "fours" then local speed = max(1,actor.speed/actor.runAnimMultiplier) * 1.25 animation.land4s:Play(.05,1,speed) sound:PlayHybridGroupSound("Cloth","game",{Volume=2,PlaybackSpeed=1+signedRandom(.1)}) task.spawn(function() engine.wait((animation.land4s.raw.Length*.75)/speed) animation.land4s:Stop(.4) end) movement("landFours") elseif landingType == "hard" then local anim = utility.checkPlane(unit(actor.velocity),v3zero,actor.rootlook) and "landhard" or "landhard_backwards" -- if var.flipping and (anims.frontflip.TimePosition >= 0.16 or anims.backflip.TimePosition >= 0.16) then -- anim = anims.frontflip.IsPlaying and anims.landhard_backwards or anims.landhard -- end actor:setspeed(actor.baseSpeed) animation[anim]:Play() movement("landHard") actor:Freeze("land") elseif landingType == "restartTrial" then objective.timetrials.current.restart(true) else if studsFallen > 4 then --animation.land:Play(.25) end end end if landingType == "hard" or actor.health <= 0 then if not cushioned.hit then score.combo:reset() sound:PlayHybridSound("LandHard","game") end elseif actor.health > 0 and landingType ~= "restartTrial" then if landingType and landingType ~= "stumble" then data.stats:increment("Landings",1) end if prepms < landData.ms.precise and studsFallen > landData.minLandingHeight then data.stats:increment("PreciseLandings",1) if prepms < landData.ms.perfect or movement.preparedLastFrame then sound:PlayHybridSound("PerfectLanding","interface") local distanceScore = ((fallSpeed/110)*1.25)^5 actor:incspeed(distanceScore) local healthDistanceScore = ((fallSpeed/110)*3)^3 actor:inchealth(healthDistanceScore) movement:dashReset() else sound:PlayHybridSound("PreciseLanding","interface") end end end end task.spawn(function() local last = landData.last engine.wait(.1) if last == landData.last then actor.landing = false landData.type = nil end end) local bufferjumpTime = input.bindsDown.upmove and .2 or movement.jumpBufferTime if allowBufferJump and landingType ~= "hard" and landingType ~= "restartTrial" and damage < actor.health and tick()-movement.lastJumpBuffer <= max(bufferjumpTime,engine.delta) then task.spawn(function() movement.lastJumpBuffer = 0 --print("buffer jump") actor.step(1/240) movement:jump() end) end --[[local bufferslideTime = input.bindsDown.downmove and .2 or movement.slideBufferTime if allowBufferSlide and landingType ~= "hard" and landingType ~= "restartTrial" and damage < actor.health and tick()-movement.lastSlideBuffer <= max(bufferslideTime,engine.delta) then task.spawn(function() movement.lastSlideBuffer = 0 print("buffer slide") actor.step(1/240) movement:powerslide() end) end ]] end function movement:coil() actor.coiling = true animation.coil:Play(.1) lerpRootUp(1.5,.1) repeat engine.wait() until not animation.coil.raw.IsPlaying or not actor.air actor.coiling = false if actor.air then lerpRootUp(-1.5,.1) end end function movement:getPipeData(pipe:BasePart) : (number,number,number,number,number) local minHeight,maxHeight = -(pipe.Size.Y/2)+3,(pipe.Size.Y/2)-3 local top:Vector3,bottom:Vector3 = (pipe.CFrame*cf(0,pipe.Size.Y/2,0)).Position,(pipe.CFrame*cf(0,-pipe.Size.Y/2,0)).Position local height = math.clamp(pipe.CFrame:PointToObjectSpace(actor.rootpart.Position).Y,minHeight+.1,maxHeight-.1) return height,minHeight,maxHeight,top,bottom end function movement:climbPipe(pipe:BasePart,isLadder:boolean) local moveData = movement.parkour.pipeclimb moveData.cancel = false if pipe.Name == "LadderClimb" then isLadder = true end local slideSpeed = -2.25 local zoopSpeed = 3.5 local start = tick() local height,minHeight,maxHeight,top,bottom = movement:getPipeData(pipe) actor:AutoRotate("pipeclimb",false) movement:setMovementActive("pipeclimb",true) actor:resetAmmo() movement:endWallrun() sound:PlayHybridGroupSound("PipeGrab","game") animation.pipeclimb:Play(.1,1,0) local climbAnim = animation.pipeclimb.raw climbAnim.TimePosition = .25 actor.humanoid:SetState("NoPhysics") actor.humanoid:SetState("Falling") local climbSpeed = 16 local acceleration = 1 local climbAlpha = -actor.localInputVector.Z if input.bindsDown.downmove and actor.velocity.Y < 0 then animation.pipeslide:SafePlay(.065,1,1) climbAlpha = slideSpeed end local space = nil local jump = 0 local jumpStartHeight = 0 local jumpHeight = 16 local jumpDuration = 1.5 input.stickyBinds.upmove = false local function stopAnims() animation.pipeclimb:SafeStop() animation.pipeleft:SafeStop() animation.piperight:SafeStop() animation.pipejumpleft:SafeStop() animation.pipejumpright:SafeStop() animation.pipeslide:SafeStop() end local verticalSpeed = actor.airVelocity.Y local autoClimbBuffer = 0 if verticalSpeed < -15 or actor.position.Y > top.Y - 1 then autoClimbBuffer = tick()+.3 end local graspL = (1/24) * 20 local graspR = (1/24) * 8 local tweenDuration = .1 local slowingDown = false if verticalSpeed < movement.parkourFallingThreshold then slowingDown = true climbAlpha = verticalSpeed / climbSpeed tweenDuration = .05 end height += verticalSpeed * tweenDuration movement:TweenRootToCFrame(pipe.CFrame * CFrame.new(0,height,1.5),tweenDuration) --local hitTop = raycast(Ray.new(pipe.Position+v3(0,2,0)+v3(0,pipe.Size.Y/2,0),pipe.CFrame.lookVector*3)) --local canClimb = hitTop.hit == nil local lastSoundPlay = 0 while true do local delta = engine.wait() local slidingDown = input.bindsDown.downmove if slowingDown then climbAlpha += delta * climbSpeed * max(.5,abs(climbAlpha/5)) local targetSpeed = slidingDown and slideSpeed or min(0,actor.localInputVector.Z) if climbAlpha > targetSpeed then slowingDown = false continue end slidingDown = true elseif moveData.zoop then climbAlpha = zoopSpeed else climbAlpha = lerp(climbAlpha,slidingDown and slideSpeed or -actor.localInputVector.Z,delta*15) end if slidingDown then animation.pipeslide:SafePlay() else animation.pipeslide:SafeStop() end local isJumping = tick()-jump < jumpDuration local jumpAlpha = (tick()-jump) / jumpDuration acceleration = if (actor.localInputVector.Z < 0 and not slidingDown and not isJumping and not moveData.zoop) then min(1.15,acceleration + delta/12) else 1 local prevHeight = height local climbDelta = clamp(climbAlpha*climbSpeed*acceleration,height == minHeight and 0 or -1000,height == maxHeight and 0 or 1000) if isJumping then local jumpTweenedAlpha = jumpAlpha >= 1 and 1 or 1 - 2.5^(-10*jumpAlpha) jumpStartHeight += climbDelta*delta*tween.service:GetValue(jumpAlpha,Enum.EasingStyle.Sine,Enum.EasingDirection.In) --print(jumpStartHeight) height = jumpStartHeight+jumpHeight*jumpTweenedAlpha else animation.pipejumpleft:SafeStop(.2) animation.pipejumpright:SafeStop(.2) height += climbDelta * delta end height = math.clamp(height,minHeight,maxHeight) local climbStudsDelta = height-prevHeight local lastTimePos = climbAnim.TimePosition climbAnim.TimePosition = slidingDown and lerp(climbAnim.TimePosition,climbAnim.TimePosition>.5 and .75 or .25,delta*10) or (climbAnim.TimePosition + (climbStudsDelta*.15)%1) local timePos = climbAnim.TimePosition local timeMin,timeMax = min(lastTimePos,timePos),max(lastTimePos,timePos) local diff = climbAnim.TimePosition-lastTimePos local didntLoop = abs(diff) < .5 local passed = (timeMin < graspL and timeMax > graspL) or (timeMin < graspR and timeMax > graspR) if passed and didntLoop and tick()-lastSoundPlay > .1 and abs(climbAlpha) > .35 and not isJumping then sound:PlayHybridGroupSound("PipeStep","game") end if not moveData.cancel then actor.rootpart.CFrame = pipe.CFrame * CFrame.new(0,height,1.5) actor.humanoid:SetVelocity(v3zero) end local backVectorL = (pipe.CFrame*CFrame.Angles(0,math.rad(150),0)).LookVector local backVectorR = (pipe.CFrame*CFrame.Angles(0,math.rad(-150),0)).LookVector local sideVector = (pipe.CFrame*CFrame.Angles(0,math.rad(-90),0)).LookVector local camLook = camera.rawlook local lookingBack = camLook:Dot(backVectorL) > 0 or camLook:Dot(backVectorR) > 0 local targetLook = lookingBack and (camLook:Dot(sideVector) > 0 and "right" or "left") or "" if targetLook == "left" and math.abs(climbAlpha) < .2 then animation.pipeleft:Play(.1) animation.piperight:Stop() elseif targetLook == "right" and math.abs(climbAlpha) < .2 then animation.piperight:Play(.1) animation.pipeleft:Stop() else animation.pipeleft:Stop() animation.piperight:Stop() end if moveData.zoop and height >= maxHeight then break elseif input.stickyBinds.upmove then input.stickyBinds.upmove = false if lookingBack or height >= maxHeight then sound:PlayHybridGroupSound("PipeJump","game") movement:wallJump{ normal = camLook, overrideWalkSpeed = 16 } actor.lastPipeJump = tick() break elseif tick()-jump > jumpDuration + 1 then actor:SwapJumpPhase() sound:PlayHybridGroupSound("PipeJump","game") if climbAnim.TimePosition < 3/30 or climbAnim.TimePosition > 16/30 then animation.pipejumpright:Play() else animation.pipejumpleft:Play() end jump = tick() jumpStartHeight = height end elseif height >= maxHeight and (input.bindsDown.upmove or tick() > autoClimbBuffer) then local dir = pipe.CFrame.LookVector local pos = (pipe.CFrame*cf(0,pipe.Size.Y/2,pipe.Size.Z/2-.5)).p local up = raycast.raycast(ray(pos-dir*.6,v3(0,5,0)),raycast.raycast.ignore) local front = raycast.raycast(ray(pos-dir*.4+v3(0,2,0),dir*2),raycast.raycast.ignore) if not front.hit and not up.hit then stopAnims() local climbType = "Narrow"--isLadder and "Wide" or "Narrow" movement:ledgeClimb(pos,unitv3(dir.X,0,dir.Z),climbType) break else height = maxHeight - .000001 climbAlpha = 0 end elseif (height <= minHeight and climbAlpha < -.25 or slowingDown) or moveData.cancel or actor.dead then moveData.cancel = false actor.humanoid:SetVelocity(v3(0,climbDelta,0)) break end end movement("pipe") stopAnims() actor:resetAmmo() movement.pipeDebounce = {pipe=pipe,t=tick()} actor.humanoid:SetState((actor.velocity.Y > 0 and not moveData.zoop) and "Jumping" or "Falling") actor:AutoRotate("pipeclimb",true) movement:setMovementActive("pipeclimb",false) task.spawn(logic.retryAutoParkour) if moveData.zoop then actor.humanoid:SetVelocity(v3(0,climbSpeed * zoopSpeed,0)) moveData.zoop = false end end function movement:attemptPipeClimb(pipe) local frontness = actor.rootlook:Dot(pipe.Position-actor.position) local intendsToGrab = (data.settings.AutoClimbPipe or input.stickyBinds.upmove or input.stickyBinds.downmove or input.bindsDown.interact) local restrictedByCurrentAction = (movement.parkour.vault.active or movement.parkour.climb.active) local restrictedByVelocity = (actor.velocity.magnitude <= 2 or actor.velocity.Y < movement.parkourFallingThreshold*2) local height = movement:getPipeData(pipe) local targetPos = (pipe.CFrame * CFrame.new(0,height,1.5)).Position local collisionRay = ray(actor.position,targetPos-actor.position) local collisionCheck:_raycastResult = raycast.raycast(collisionRay) if not movement.parkour.pipeclimb.active and not gear.using and frontness > 1/3 and intendsToGrab and not restrictedByCurrentAction and not restrictedByVelocity and not collisionCheck.hit and (movement.pipeDebounce.pipe ~= pipe or tick()>movement.pipeDebounce.t+.5) then return true end end function movement:findZipline() local debounce = movement.parkour.zipline.debounce for i,data in pairs(world.ziplines.active) do local origin:CFrame,length = data.cf,data.length local offset = origin:ToObjectSpace(actor.cframe) local pos = (origin*cf(0,0,clamp(offset.Z,-length/2,length/2))).p if getDistance(actor.position,pos) < movement.parkour.zipline.grabDistance and not movement.parkour.is then return data.model end end end function movement:zipline(model) if actor.alive and model:FindFirstChild("Line") and model.Line:FindFirstChild("Start") then local zipliningData = movement.parkour.zipline movement:setMovementActive("zipline",true) actor:resetAmmo() movement("ziplineGrab") local line:BasePart = model.Line local startAttachment:Attachment = line.Start local endAttachment:Attachment = line.End animation:StopAll() animation.zipline:SafePlay(.2) local animSpeed = max(1,actor.speed/actor.runAnimMultiplier) local left = startAttachment.WorldCFrame.RightVector:Dot(actor.position-startAttachment.WorldPosition) < 0 if left then animation.ziplineenterleft:Play(.1,1,animSpeed) else animation.ziplineenterright:Play(.1,1,animSpeed) end local dir = startAttachment.WorldCFrame.LookVector local dir2d = v3(dir.X,0,dir.Z).Unit local dist = getDistance(startAttachment.WorldPosition,endAttachment.WorldPosition) local offset = line.CFrame:ToObjectSpace(actor.cframe) local alpha = clamp(-offset.Z+dist/2,0,dist)/dist local function currentCFrame(alphaOverride) local a = alphaOverride or alpha return startAttachment.WorldCFrame*cf(0,0,-a*dist) end local maxspeed = zipliningData.maxSpeed local speed = actor.velocity:Dot(dir) if alpha == 0 and speed < 0 then speed = 0 end local startTick = tick() local startPos = actor.position local lerpAlpha = .1 local angle = abs(dir.Y) local friction = zipliningData.friction local canSpeedControl = gear:hasUpgrade("Compound","ZiplineHook",1,1) local isPowered = gear:hasUpgrade("Compound","ZiplineHook",1,2) local flipCharacter = speed < 0 local flipThreshold = 2 input.stickyBinds.upmove = false input.stickyBinds.downmove = false while zipliningData.active and (not actor.ground or tick()-startTick < .25) and withinEqual(alpha,0,1) and not (input.stickyBinds.upmove or input.stickyBinds.downmove) and model.Parent ~= nil and actor.alive do local delta = engine.delta local abSpeed = abs(speed) local powerSpeed = zipliningData.mechanizedSpeed local dirAlpha = speed > 0 and 1 or -1 local inputDot = actor.inputVector:Dot(dir2d) local isInputting = actor.inputVector.magnitude > 0 local targetFlip = speed < 0 if abSpeed > flipThreshold then flipCharacter = targetFlip end friction = zipliningData.friction * (2-(inputDot*dirAlpha + 1)) actor.humanoid:SetVelocity(v3zero) local cframe = actor.rootpart.CFrame:lerp(currentCFrame()*cf(0,-3,0)*angles(0,flipCharacter and pi or 0,0),lerpAlpha) actor.rootpart.CFrame = cframe lerpAlpha = min(1,lerpAlpha+delta) actor:setspeed(max(actor.rootSpeed,abSpeed/3)) if speed < maxspeed and (not isPowered or (isPowered and speed > 0 and inputDot > -.05) or (isPowered and speed < 0 and inputDot > .05)) then speed = clamp(speed+(angle*actor.defaultGravity-friction*dirAlpha)*delta,-math.huge,maxspeed) end if canSpeedControl then if isInputting and inputDot*dirAlpha < abs(inputDot) then speed = speed-(max(20,speed*2)*dirAlpha)*delta elseif abSpeed < powerSpeed and isPowered then speed = speed+(25*dirAlpha)*delta end end if abs(speed) < friction*delta*2 then speed = 0 end alpha = alpha+speed/dist*delta engine.wait() end local velToSet = dir*speed if input.stickyBinds.upmove then local target = startAttachment.WorldCFrame.UpVector * 25 local right = startAttachment.WorldCFrame.RightVector local lookDot = camera.rawlook:Dot(right) local lookIntensity = abs(lookDot) * 10 target += (if lookDot > 0 then right else -right) * (5+lookIntensity) velToSet += target.Unit * 25 end actor.humanoid:SetVelocity(velToSet) movement("ziplineDrop") zipliningData.debounce = {model=model,time=tick()} animation.ziplineenterright:Stop(0) animation.ziplineenterleft:Stop(0) animation.zipline:Stop(.2) movement:setMovementActive("zipline",false) end end function movement:ledgeClimb(pos,normal,climbType,originDir,result:_raycastResult) --Wide, Narrow, Vault, Mantle movement:setMovementActive("climb",true) if movement.parkour.wallrun.active then movement:endWallrun() end local start = tick() actor:Freeze("climb") local floor = raycast.raycast(ray(pos+v3(0,2.5,0)+normal*.75,v3(0,-5,0))) local isVault = floor.hit == nil if isVault then climbType = "Vault" else climbType = climbType or "Wide" end if climbType == "Vault" and actor.localInputVector.magnitude == 0 then local ceiling = raycast.raycast(ray(pos+v3(0,1,0)+normal*.25,v3(0,4,0))) if not ceiling.hit then climbType = "Wide" end end local targetPos,vel,endState,length,anim,animSpeed,fadeIn,fadeOut,stopOnlyOnLand,skipTime,minAnimDuration local climbSpeed = tween.service:GetValue( alphaFromRange(actor.speed,actor.baseSpeed,actor.maxSpeed), Enum.EasingStyle.Sine, Enum.EasingDirection.In ) if climbType == "Wide" or climbType == "Narrow" then targetPos = (pos - normal*.25 + v3(0,2.5,0)) vel = normal*actor.speed length = 19/30 anim = climbType == "Narrow" and animation.ledgeclimb2 or animation.ledgeclimb animSpeed = 1.25 + climbSpeed*.75 endState = "Running" fadeIn = .1 fadeOut = .2 elseif climbType == "Vault" then targetPos = (pos + normal*3.5) vel = unitv3(normal.X,-.25,normal.Z)*actor.speed length = 16/30 anim = animation.barriervault animSpeed = 1.1 + climbSpeed*.35 endState = "Falling" fadeIn = .1 fadeOut = .15 stopOnlyOnLand = true minAnimDuration = 20/30 elseif climbType == "Mantle" then targetPos = (pos + normal*1.5 + v3(0,2.5,0)) vel = normal*actor.speed length = 8/30 anim = animation.mantle animSpeed = 1 + climbSpeed*.3 endState = "Running" fadeIn = .1 fadeOut = .1 elseif climbType == "FastMantle" then targetPos = (pos + normal*3 + v3(0,2.5,0)) vel = normal*actor.speed length = 12/30 anim = animation.fastmantle animSpeed = 1 + climbSpeed*.6 endState = "Running" fadeIn = .1 fadeOut = .1 if result then --fadeIn = .025 + result.alpha*.075 skipTime = (1-result.alpha) * .2 end end --print(climbType) anim:SafeStop() anim:Play(fadeIn,1,animSpeed) anim.raw.TimePosition = skipTime or 0 sound:PlayHybridSound("Grab1","game",{PlaybackSpeed=1+signedRandom(.05)}) sound:PlayHybridSound("Grab2","game",{PlaybackSpeed=1.1+signedRandom(.05)}) task.spawn(function() engine.wait(.075) sound:PlayHybridGroupSound("Cloth","game",{PlaybackSpeed=1+signedRandom(.1)}) end) actor:speedboost() actor:resetAmmo() local targetcf = cf(targetPos,targetPos+v3flat(originDir or actor.rootlook)) movement:TweenRootToCFrame(targetcf,fadeIn) --movement:updatePhysicsEnabled() movement("climb") local toSpringboard = false local st = tick() repeat engine.wait() toSpringboard = (climbType == "Mantle" or climbType == "FastMantle") and input.bindsDown.upmove and tick()-start > .175 and actor.localInputVector.magnitude == 0 until not anim.raw.IsPlaying or anim.raw.TimePosition > length or toSpringboard or tick()-st > 2 actor:Unfreeze("climb") movement:setMovementActive("climb",false) --movement:updatePhysicsEnabled() actor.humanoid:SetState(endState) if endState == "Running" and not toSpringboard then sound:PlayStep() end if actor.localInputVector.magnitude > input.inputVectorZeroThreshold then actor.humanoid:SetVelocity(vel) end if stopOnlyOnLand then repeat engine.wait() until not actor.air or movement.parkour.is end if not movement.parkour.climb.active then if minAnimDuration then repeat engine.wait() until anim.raw.TimePosition > minAnimDuration end if climbType == "Vault" and actor.ground then sound:PlayStep() end anim:Stop(fadeOut) end end function movement:attemptClimb(pos,normal,climbType,originDir) --utility.visualizePosition(pos) if actor.velocity.Y > movement.parkourFallingThreshold then local marginBack,marginFront = 1.5,.6 local minThickness = .025 local resolution = .025 local height = 5 local upVector = getUpVector(normal) if climbType == "Mantle" then marginFront = 1.5 elseif climbType == "FastMantle" then marginFront = 3 end pos = pos + normal*marginBack --print(debug.traceback()) --local up = raycast(ray(pos,upVector*height+1.5)) local overlap = OverlapParams.new() overlap.FilterDescendantsInstances = raycast.raycast.ignore overlap.RespectCanCollide = true overlap.CollisionGroup = "Player" local upBoxHeight = height + .5 local upBoxPos = pos+(upVector*upBoxHeight/2) local upPart = utility.newInstance("Part") upPart.CFrame = cf(upBoxPos,upBoxPos-normal) upPart.Size = v3(.05,upBoxHeight,.05) local upParts = workspace:GetPartsInPart(upPart,overlap) upPart:destroy() local front = raycast.raycast(ray(pos + upVector*height,-normal*(marginBack+minThickness))) if #upParts == 0 and not front.hit then local down local floorSpace local offset = 0 for i = 0,marginFront/resolution do offset = i*resolution down = raycast.raycast(ray(pos + upVector*height - normal*(marginBack+minThickness+offset),-upVector*(height+.5))) if down.hit then floorSpace = raycast.raycast(ray(down.pos + v3(0,.5,0) + normal*offset,-normal*marginFront)) if not floorSpace.hit then break end end end if down.hit and down.hit.Name ~= "Barrier" and not floorSpace.hit then local climbType = climbType or (actor.velocity.Y > 0 and "Narrow" or "Wide") return {down.pos+normal*(minThickness),-normal,climbType,originDir} end end end return false end function movement.canWallclimb(raycastResult) local hit = raycastResult.hit if hit then local wallrun = movement.parkour.wallrun local aboveParkourFallThreshold = actor.velocity.Y > movement.parkourFallingThreshold local withinFallGracePeriod = actor.timeFalling <= actor.maxTimeFallingToWallClimb local enoughAmmo = actor.ammo.wallclimb > 0 local canWallBoost = movement.parkour.dash.airActive local surfaceClimbable = hit:HasTag("Climbable") local notBarrier = hit.Name ~= "Barrier" and not hit:HasTag("Barrier") local withinAngle = raycastResult.normal.Y < .25 and raycastResult.normal.Y > -.05 local isDifferentWall = (raycastResult.normal:Dot(wallrun.lastClimbNormal) < wallrun.minAngleChange or wallrun.lastClimbNormal.Magnitude == 0) return enoughAmmo and aboveParkourFallThreshold and (canWallBoost or withinFallGracePeriod or surfaceClimbable) and notBarrier and withinAngle and isDifferentWall end end function movement:wallrun(lateral,pos,normal) local wallrun = movement.parkour.wallrun sound:PlayHybridGroupSound("Cloth","game",{PlaybackSpeed=1+signedRandom(.1)}) --gear stuff local equipped = gear:getEquipped("Core","Glove") wallrun.maxLateralFallDistance = wallrun.defaultLateralFallDistance * (gear:hasUpgrade("Core","Glove",2,1) and 16 or 1) wallrun.maxVerticalFallDistance = wallrun.defaultVerticalFallDistance wallrun.horizontalDuration = wallrun.defaultHorizontalDuration * (equipped and (gear:hasUpgrade("Core","Glove",2,1) and 2.25 or 1.5) or 1) wallrun.horizontalDuration = wallrun.horizontalDuration * ((gear:getEquipped("Augment","MagRail") and wallrun.left) and 1.25 or 1) wallrun.verticalDuration = wallrun.defaultVerticalDuration wallrun.float = gear:hasUpgrade("Core","Glove",2,2) wallrun.canPushBoost = gear:hasUpgrade("Core","Glove",1,1) wallrun.pushBoosted = false --- local chosenVelocity = actor.lastVelocity.magnitude > actor.velocity.magnitude and actor.lastVelocity or actor.velocity local localVelocity = cf(v3zero,normal):PointToObjectSpace(chosenVelocity) local velocity = v2(localVelocity.X,localVelocity.Y).unit*chosenVelocity.magnitude if velocity.magnitude ~= velocity.magnitude then velocity = Vector2.zero warn("wallrun velocity NAN avoided, local velocity:",localVelocity) end wallrun.velocity = v2(lateral and velocity.X or velocity.X/4,lateral and min(0,velocity.Y)+12 or min(10,velocity.Y/2+40)) wallrun.startPos = actor.position wallrun.startVelocity = velocity wallrun.entryCharacterVelocity = actor.velocity wallrun.snapInterpolationMultiplier = 1 + alphaFromRange(actor.velocity.magnitude,20,50,0,2) wallrun.maxHeight = -math.huge wallrun.targetRootCFrame = cf(pos+normal*2) * actor.rootpart.CFrame.Rotation --movement.bodypos.Position = pos+normal*2 movement:setMovementActive("wallrun",true) movement("wallrun") wallrun.casted = nil wallrun.pos = pos wallrun.hit = nil wallrun.normal = normal wallrun.start = tick() wallrun.last = tick() wallrun.lateral = lateral wallrun.timeHanging = 0 wallrun.speed = actor.speed wallrun.lateralDirection = 0 wallrun.hookTime = 0 wallrun.stepPhase = actor.jumpPhase wallrun.accumulator = 0 wallrun.totalSteps = 0 wallrun.topPos = nil wallrun.coyoteBudget = wallrun.coyoteTime wallrun.timeColliding = 0 wallrun.climbing = false if not wallrun.lateral then if not gear:getEquipped("Core","Glove") then wallrun.speed = min(26,wallrun.speed) wallrun.extendedClimb = false else wallrun.extendedClimb = true end end wallrun.pushSpeed = wallrun.maxPushTime-alphaFromRange(wallrun.speed,actor.baseSpeed,actor.maxSpeed)*(wallrun.maxPushTime-wallrun.minPushTime) wallrun.pushFuel = wallrun.pushSpeed*1.25 wallrun.wallboostAttempt = not wallrun.lateral and movement.parkour.dash.airActive and data:hasAbility("WallBoost") input.stickyBinds.upmove = false input.stickyBinds.downmove = false actor.humanoid:SetVelocity(v3(actor.velocity.X,0,actor.velocity.Z)) actor.humanoid:SetState("Jumping") actor.physics.Grounded = false --movement:updatePhysicsEnabled() actor.ammo[wallrun.lateral and "wallrun" or "wallclimb"] -= 1 data.stats:increment(wallrun.lateral and "WallRuns" or "WallClimbs",1) animation:SafeStopType("air") end function movement:endWallrun() local wallrun = movement.parkour.wallrun local rotatedVel = (cf(v3zero,wallrun.normal)*cf(wallrun.velocity.X,wallrun.velocity.Y,0)).p --print(wallrun.maxHeight-wallrun.startPos.Y) actor.humanoid:SetVelocity(rotatedVel) movement:setMovementActive("wallrun",false) movement:stopWallrunAnimations() task.spawn(logic.retryAutoParkour) --movement:updatePhysicsEnabled() end type wallJumpQuery = { normal:Vector3, jumpType:string?, overrideWalkSpeed:number?, overrideSpeedAlpha:number?, toAddFromVelocity:Vector3?, clampCone:number?, } function movement:wallJump(query:wallJumpQuery) --print("wall jump") movement:endWallrun() events.wallJump:fire() sound:PlayStep("jump") actor.lastLandedTick = 0 local normal = query.normal local lastAir = tick()-movement.parkour.dash.lastAirUse if query.jumpType == "boost" then movement.parkour.dash.lastAirUse = tick()-.75 local speedAlpha = alphaFromRange(query.overrideWalkSpeed or actor.speed,actor.baseSpeed,actor.maxSpeed,0,1) local height = 0 if gear:hasUpgrade("Core","Glove",1,1) then height = 18 + 6*speedAlpha else height = 11 + 6*speedAlpha end actor.humanoid:SetVelocity(v3(0,math.sqrt(2*actor.defaultGravity*height),0)) actor.humanoid:SetState("Falling") animation.wallboost:Play() movement("wallboost") data.stats:increment("WallBoosts",1) else local wallrun = movement.parkour.wallrun local dir = v3(0,0,-1) if true then local localDesired = cf(v3zero,normal):toObjectSpace(cf(camera.rawlook)).p local z = (actor.inputVector.magnitude > input.inputVectorZeroThreshold) and localDesired.Z or -abs(localDesired.Z) dir = unit((cf(v3zero,normal)*cf(unitv3(localDesired.X,localDesired.Y,z))).Position) end local aimDot = dir:Dot(wallrun.normal) if wallrun.bounced then animation.wallbounce:Play() wallrun.bounced = false elseif wallrun.lateral then if wallrun.lateralDirection < 0 then if aimDot < math.sqrt(.5) then animation.wallrunLjumpShallow:Play() else animation.wallrunLjump:Play() end else if aimDot < math.sqrt(.5) then animation.wallrunRjumpShallow:Play() else animation.wallrunRjump:Play() end end end local jumpPower = 26 local speedMagnitude = 42 local speedAlpha = query.overrideSpeedAlpha or alphaFromRange(query.overrideWalkSpeed or actor.speed,0,actor.sprintThreshold,0,1) local targetVelocity = v3(dir.X,0,dir.Z)*speedMagnitude*speedAlpha + v3(0,jumpPower,0) local add = query.toAddFromVelocity if add then targetVelocity = (targetVelocity+add).unit * math.max(add.magnitude,targetVelocity.magnitude) end actor.humanoid:SetVelocity(targetVelocity)--max(0,dir.Y)*35 movement("walljump") data.stats:increment("WallJumps",1) end end function movement.parkour.wallrun:jumpOut() local wallrun = movement.parkour.wallrun local currentTick = tick()-wallrun.start local overrideWallJumpSpeed,add local jumpType = nil if wallrun.lateral then overrideWallJumpSpeed = wallrun.speed/42 elseif currentTick > wallrun.bounceWindow then overrideWallJumpSpeed = .35 elseif currentTick <= wallrun.bounceWindow then add = (cf(v3zero,wallrun.normal)*cf(wallrun.startVelocity.X,math.clamp(wallrun.startVelocity.Y,0,100),0)).p wallrun.bounced = true end movement:wallJump{ normal = wallrun.normal, jumpType = jumpType, overrideSpeedAlpha = overrideWallJumpSpeed, toAddFromVelocity = add } movement.parkour.dash.airActive = false end function movement:cornerHook(pos,normal,left) -- scrapped probably, or use on a gear? local wallrun = movement.parkour.wallrun movement:setMovementActive("cornerhook",true) actor:AutoRotate("cornerhook",false) actor:Freeze("cornerhook") if left then animation.cornerhangleft:Play(.1,1,.8) else animation.cornerhangright:Play(.1,1,.8) end movement:TweenRootToCFrame(cf(pos,pos+normal),.1) while input.bindsDown.upmove and wallrun.hookTime < wallrun.hookDuration do local delta = engine.wait() wallrun.hookTime += delta end actor:AutoRotate("cornerhook",true) actor:thaw("cornerhook") movement:setMovementActive("cornerhook",false) movement:wallJump{ normal = normal } end function movement:endSlide() local slide = movement.parkour.slide if slide.active and (actor.air or not actor.physics.CurrentAngle or actor.physics.CurrentAngle < actor.maxSlideSlope) then movement:setMovementActive("slide",false) actor:stopSlideAnimations() end end function movement:slide(speed,doNotPlayEnterAnimation) local slide = movement.parkour.slide local velocity = actor.velocity.unit * (speed or actor.velocity.magnitude) --print("slide",speed) if velocity.magnitude > slide.minSpeed and actor.physics.GroundNormal:Dot(actor.horizontalVelocity.unit) > -.25 and not actor.sliding then actor.humanoid:SetVelocity(velocity) if not doNotPlayEnterAnimation then animation.slide_enter:Play(.25,1,1) end if tick()-movement.parkour.powerslide.last > .15 then sound:PlayHybridGroupSound("Slide","game") end slide.lastSlide = tick() movement:setMovementActive("slide",true) end end function movement:stopPowerslide(source) local powerslide = movement.parkour.powerslide if powerslide.active then --print("stop powerslide:",source) animation.powerslide_in:Stop() animation.powerslide_slow:Stop() animation.powerslide:Stop() powerslide.last = tick() movement:setMovementActive("powerslide",false) actor:AutoRotate("powerslide",true) end end local lastPowerslide = tick() function movement:powerslide() local powerslide = movement.parkour.powerslide if actor.ground and not powerslide.active and tick()-powerslide.last > powerslide.cooldown then local mult = 1 + (.5*math.clamp((tick()-lastPowerslide-1/30)*2,0,1)) lastPowerslide = tick() movement:setMovementActive("powerslide",true) powerslide.entrySpeed = actor.velocity.magnitude powerslide.velocity = actor.velocity * mult powerslide.last = tick() animation.powerslide_in:Play(.05) actor:AutoRotate("powerslide",false) sound:PlayHybridGroupSound("Slide","game") actor.rootpart.CFrame = cf(actor.rootpart.Position,actor.rootpart.Position + v3flat(powerslide.velocity)) end end function movement:dashReset() local dash = movement.parkour.dash dash.active = false dash.lastUse = 0 dash.lastRelease = 0 --[[dash.wallKickExhaust = false]] dash.lastAirUse = 0 dash.airActive = false end function movement:dashRelease(automatic) local dash = movement.parkour.dash local lastUse = tick()-dash.lastUse local lastAirUse = tick()-dash.lastAirUse dash.query = false dash.airQuery = false if dash.active and (not dash.afterboosted or automatic) then dash.active = false dash.lastRelease = tick() end if dash.airActive and lastAirUse >= dash.wallKickWindow then dash.airActive = false dash.lastAirUse = tick() end end function movement:updateBashables() local dash = movement.parkour.dash dash.doors = {} dash.obstacles = {} local function insertIfObjectInRange(object,pos) local dist = getDistance(actor.position,pos) if dist < 64 then table.insert(dash.obstacles,object) end end for _,model in pairs(workspace.World.Props.Dynamics.Destructibles.Generic:GetChildren()) do local pos = model.Bounds.Position if not props.destroyed[model] then insertIfObjectInRange(model,pos) end end for _,glass in pairs(workspace.World.Props.Dynamics.Destructibles.Glass:GetChildren()) do local pos = glass.Pane.Position if not props.destroyed[glass] then insertIfObjectInRange(glass,pos) end end local doorsToOpen = {} for _,model in pairs(workspace.World.Props.Dynamics.Doors:GetChildren()) do local origincf = model.Part.CFrame local door = props.doors[model] if not door.locked then local dist = getDistance(actor.position,origincf.p) if dist < 64 then --prompt.KeyboardKeyCode = input.binds.dash.Keyboard.Value --prompt.GamepadKeyCode = input.binds.dash.Gamepad.Value table.insert(dash.doors,model) end end end end function movement:dash() local dash = movement.parkour.dash --obstacle bashing portion movement:updateBashables() actor.bashStep(engine.delta,true) --- --actual dash portion if not data:hasAbility("Dash") then return end local lastAirUse = tick()-dash.lastAirUse local lastUse = tick()-dash.lastUse local lastRelease = tick()-dash.lastRelease if dash.query or (not actor.air or (tick()-actor.lastLandedTick < .1 and not actor.jumping) or (lastRelease < dash.afterboostWindow and not dash.afterboosted)) and actor.localInputVector.Magnitude > 0 and not dash.active and (actor.speed < actor.maxSpeed-.05 or data:hasAbility("Afterboost")) then dash.query = false if data:hasAbility("Afterboost") and lastUse > dash.chargeTime and lastRelease < dash.afterboostWindow and not dash.afterboosted then dash.afterboosted = true dash.active = true dash.lastUse = tick() actor.humanoid:SetVelocity(actor.velocity*1.15) movement("afterboost") --print("boost") elseif lastRelease > dash.cooldown then dash.afterboosted = false dash.active = true dash.lastUse = tick() -- hi this is jasper i added this okay carry on :thumbs_up: if actor.sliding then animation.roll:Play(.1,1,max(1,actor.speed/actor.runAnimMultiplier)) actor:stopSlideAnimations() sound:PlayHybridSound("Roll","game") movement:setMovementActive("slide",false) end --print("dash") else dash.query = true end elseif dash.airQuery or (data:hasAbility("WallBoost") or data:hasAbility("WallKick")) and not movement.parkour.is and actor.air then dash.airQuery = false if lastAirUse > dash.airCooldown then dash.lastAirUse = tick() dash.airActive = true --print("air dash hold") else dash.airQuery = true end end end function movement:dropdown(pos:CFrame,partsToPhase) if not data:hasAbility("Dropdown") then return end movement:setMovementActive("dropdown",true) local dropdown = movement.parkour.dropdown local humanoid = actor.humanoid local dir = pos.LookVector dropdown.dir = dir local start = tick() local startPos = actor.position humanoid.Physics.DisableGrounding = true animation.dropdown:Play() humanoid:SetState("Falling") actor.ground = false dropdown.did = true task.spawn(function() repeat engine.wait() until (actor.ground or actor.velocity.Y > 10) if dropdown.active then movement:setMovementActive("dropdown",false) end animation.dropdown:SafeStop() end) local duration = .5 local dist = getDistance(actor.position,v3(pos.X,actor.cframe.Y,pos.Z)) if actor.velocity.magnitude < dist/duration then humanoid:SetVelocity(dir*dist/duration) end repeat local dT = engine.wait() if not dropdown.active then break end local vel = humanoid.Velocity humanoid:SetVelocity(vel.X,0,vel.Z) local alpha = getDistance(actor.rootpart.Position,pos) / getDistance(startPos,pos) local y = lerp(startPos.Y-2,startPos.Y,alpha) actor.rootpart.CFrame = cf(actor.rootpart.CFrame.X,y,actor.rootpart.CFrame.Z) * actor.rootpart.CFrame.Rotation until tick()-start > duration or dir:Dot(actor.position-pos.Position) > 0 if dropdown.active then humanoid:SetVelocity(nil,-8,nil) humanoid:SetState("Falling") local start = tick() repeat engine.wait() until actor.cframe.Y < pos.Y or tick()-start > .2 movement:setMovementActive("dropdown",false) end humanoid.Physics.DisableGrounding = false end function movement.dropkick(arg1) local var283 if not data:hasAbility("Dropkick") then else local dropkick_3 = movement.parkour.dropkick movement:setMovementActive("dropkick", true) dropkick_3.last = tick() animation:SafeStopAll() animation.dropKick_loop:Play() animation.dropKick:Play() local tbl_3 = {} var283 = signedRandom(0.1) tbl_3.PlaybackSpeed = 1 + var283 --sound:PlayHybridGroupSound("Cloth", "game", tbl_3) engine.wait(0.16666666666666666) gear.grappler.swinging = false local tbl_18 = {} var283 = 1 tbl_18.PlaybackSpeed = var283 + signedRandom(0.1) --sound:PlayHybridGroupSound("Cloth", "game", tbl_18) --sound:PlayHybridSound("DropkickWhoosh", "game") movement:updateBashables() actor.bashStep(engine.delta, true) local velocity = actor.velocity local vector3 = Vector3.new(velocity.X, 0, velocity.Z) local Unit = vector3.Unit local Magnitude = vector3.Magnitude if gear.grappler.swinging then var283 = Magnitude * 1.1 Magnitude = math.max(Magnitude + 12, var283) var283 = actor Unit = var283.rootpart.CFrame.LookVector var283 = actor var283.grappler.jrap:Detach() end local Y = velocity.Y local maxVertical = dropkick_3.maxVertical if maxVertical < Y then var283 = maxVertical + (Y - maxVertical) / dropkick_3.verticalDivisor else var283 = Y end local var293_upvr = Unit * math.max(Magnitude, math.min(actor.maxSpeed, math.max(0, Y), vector3.Magnitude) + math.min(math.max(0, Y - var283), dropkick_3.maxBoost)) + Vector3.new(0, math.min(maxVertical, var283), 0) actor.humanoid:SetVelocity(var293_upvr) --if not data.settings.Peaceful then print("runhitbox") hitbox:runHitbox({ Origin = actor.rootpart; Offset = CFrame.new(0, -2.5, -2); Size = Vector3.new(3, 4, 6); FPS = 120; Duration = 0.25; FirstCallback = function() -- Line 2662, Named "FirstCallback" --[[ Upvalues[2]: [1]: Actor_upvr (copied, readonly) [2]: var293_upvr (readonly) ]] actor.humanoid:SetVelocity(var293_upvr.Unit * Vector3.new(var293_upvr.X / 16, var293_upvr.Y, var293_upvr.Z / 16)) end; HitCallback = function(arg1_6) -- Line 2666, Named "HitCallback" --[[ Upvalues[4]: [1]: Sound_upvr (copied, readonly) [2]: Network_upvr (copied, readonly) [3]: Actor_upvr (copied, readonly) [4]: var293_upvr (readonly) ]] --sound:PlayHybridSound("DropkickHit", "game") local tbl_6 = {} tbl_6[1] = arg1_6 network:send("dropkick", tbl_6, actor.rootpart.CFrame.LookVector, var293_upvr) end; Debug = false; }) --end end end network:add("dropkickHit", function(arg1) -- Line 2678 --[[ Upvalues[3]: [1]: Data_upvr (readonly) [2]: Races_upvr (readonly) [3]: Actor_upvr (readonly) ]] if not data.settings.Peaceful and not actor.currentAnimSpot then actor.humanoid:SetState("Jumping") actor.humanoid:Nudge(arg1) end end, "server") function movement.dropkickRecovery(arg1) -- Line 2685 --[[ Upvalues[2]: [1]: module_7_upvr (copied, readonly) [2]: Animation_upvr (readonly) ]] local dropkick_5 = movement.parkour.dropkick if dropkick_5.active then dropkick_5.last = tick() animation.dropKick_loop:SafeStop() animation.dropKick:SafeStop() animation.dropKick_recover:Play() movement:setMovementActive("dropkick", false) end end function movement:vaultJump(dir,speed) local humanoid = actor.humanoid local longVel = dir*max(actor.speed*movement.leapMultiplier,speed) + v3(0,32,0) local upVel = dir*max(10,speed/3.2) + v3(0,45,0) movement("vaultJump") humanoid:SetVelocity(actor.inputVector.Magnitude > input.inputVectorZeroThreshold and longVel or upVel) humanoid:SetState("Jumping") actor.jumping = tick() actor.lastVaultJump = tick() animation.mantle:SafeStop(.35) animation.fastmantle:SafeStop(.35) animation.monkeyvault:SafeStop(.35) actor:speedboost() actor.lastLandedTick = 0 --fix for super springboarding/coyote springboard/frog jump, uncomment when people start figuring it out lol sound:PlayStep("jump") animation.springboard:Play(.2) end ------ do -- parkour sub-module i gues local origin = cfzero local dir = -Vector3.zAxis local allowPrecisionClimb = true local rayLength = 5 local movementDependencies = {} do function movementDependencies:reset() for i,v in pairs(movementDependencies) do if typeof(v) == "table" then v.value = nil end end end function movementDependencies:invoke(...) local indexes = {...} local values = {} for i,v in pairs(indexes) do local target = movementDependencies[v] local value = target.value or target.get() target.value = value values[i] = value end return unpack(values) end movementDependencies.rootpart = { get = function() return actor.rootpart end,} movementDependencies.intentDot = { get = function() return logic.autoParkouring and dir:Dot(actor.inputVector.magnitude > input.inputVectorZeroThreshold and actor.inputVector or dir) or 1 end,} movementDependencies.ground = { get = function() return actor.onground() end,} movementDependencies.hipsRay = { get = function() local rootpart = movementDependencies:invoke("rootpart") return ray(rootpart.Position+v3(0,-1.2,0),dir*(6+max(0,(v3flat(actor.velocity).magnitude-64)/64))) end,} movementDependencies.hips = { get = function() return raycast.raycast(movementDependencies:invoke("hipsRay")) end,} movementDependencies.head = { get = function() local rootpart,hips = movementDependencies:invoke("rootpart","hips") return raycast.raycast(ray(rootpart.Position+v3(0,1.5,0),dir*math.max(5,hips.length+3))) end,} movementDependencies.shortHead = { get = function() local rootpart,hips = movementDependencies:invoke("rootpart","hips") return raycast.raycast(ray(rootpart.Position+v3(0,1.5,0),dir*(hips.length+1))) end,} movementDependencies.behind = { get = function() local rootpart = movementDependencies:invoke("rootpart") return raycast.raycast(ray(rootpart.Position+v3(0,-2,0),-dir*6)) end,} movementDependencies.front = { get = function() local rootpart = movementDependencies:invoke("rootpart") return raycast.raycast(ray(rootpart.Position,dir*rayLength)) end,} movementDependencies.left = { get = function() local rootpart = movementDependencies:invoke("rootpart") return raycast.raycast(ray(rootpart.Position,(origin*CFrame.Angles(0,math.rad(45),0)).LookVector*rayLength)) end,} movementDependencies.right = { get = function() local rootpart = movementDependencies:invoke("rootpart") return raycast.raycast(ray(rootpart.Position,(origin*CFrame.Angles(0,math.rad(-45),0)).LookVector*rayLength)) end,} end local function invoke(...) return movementDependencies:invoke(...) end local function wallrunBase(disableType) local wallrun = movement.parkour.wallrun local front local left,right local sideWall local isLeft local prioritizeClimb local dotAngle local autoCont = (not logic.autoParkouring or (movement.parkour.last and tick()-movement.parkour.lastTick > .5) or actor.velocity.Y < 20) local intentDot = invoke("intentDot") local function wallclimbRayDataCheck(data) return data.hit and data.normal.Y > -.4 and data.normal.Y < .2 end ----- front = invoke("front") dotAngle = front.normal:Dot(dir) if disableType ~= "wallrun" then left,right = invoke("left","right") if getDistance(right.pos,actor.rootpart.Position) < getDistance(left.pos,actor.rootpart.Position) then sideWall = right else sideWall = left isLeft = true end end ----- if not disableType then if not front.hit or (sideWall and sideWall.hit and getDistance(sideWall.normal,front.normal) < .1 and dotAngle > -wallrun.angleCutoff) then prioritizeClimb = false else prioritizeClimb = true end end if movement.parkour.climb.enabled and not gear.using and intentDot > -.1 then if wallclimbRayDataCheck(front) then local args = movement:attemptClimb(front.pos,-dir,nil,dir) if args then return "climb",args end elseif allowPrecisionClimb then --precision climb local height,current = 5,0 local resolution = 20--per stud for i = 1,height*resolution do local front = raycast.raycast(ray(actor.position+v3(0,current,0),dir*rayLength)) if wallclimbRayDataCheck(front) then local args = movement:attemptClimb(front.pos-v3(0,current,0),-dir,"Wide",dir) if args then return "climb",args end end current += 1/resolution end end end local allowWallClimb = (prioritizeClimb == nil or prioritizeClimb) local allowWallRun = (prioritizeClimb == nil or not prioritizeClimb) if wallrun.enabled and intentDot > .35 and allowWallClimb and autoCont and movement.canWallclimb(front) then return "wallclimb",{front} elseif wallrun.enabled and abs(intentDot) > .35 and allowWallRun and sideWall and sideWall.hit and sideWall.hit.Name ~= "Barrier" and actor.ammo.wallrun > 0 and actor.velocity.Y > movement.parkourFallingThreshold then local dotAngle = sideWall.normal:Dot(dir) if sideWall.normal.Y < .3 and sideWall.normal.Y > -.15 and dotAngle > -.5 and (sideWall.normal:Dot(wallrun.lastRunNormal) < wallrun.minAngleChange or wallrun.lastRunNormal.Magnitude == 0) then return "wallrun",{sideWall,isLeft} end end end movement.conditions = { up = { jump = function() if (movement.parkour.dropdown.active or actor.landed or actor.canCoyoteJump()) and tick()-actor.lastBreakthrough > .5 and (not actor.sliding or tick()-actor.lastSlideJump > 1) then return "jump" end end, doublejump = function() if (gear:hasUpgrade("Compound","BoostBelt",1) or gear:hasUpgrade("Compound","BoostBelt",2)) and not input.bindsDown.downmove then return "jump",{"doubleJump"} end end, wallrun = function() return wallrunBase("wallclimb") end, wallclimb = function() return wallrunBase("wallrun") end, wallrunclimb = function() return wallrunBase() end, climbpipe = function() local currentPipe = movement.parkour.pipeclimb.current if currentPipe and movement:attemptPipeClimb(currentPipe) then return "climbpipe",{currentPipe} end end, wallkick = function() local behind = invoke("behind") local dash = movement.parkour.dash if data:hasAbility("WallKick") and actor.air and behind.hit and actor.velocity.Y > -75 and dash.airActive and actor.ammo.wallkick > 0 and tick()-dash.lastAirUse < dash.wallKickWindow then --(tick()-dash.lastUse > dash.chargeTime and (tick()-dash.lastRelease < dash.afterboostWindow and not dash.afterboosted)) return "wallkick",{dir} end end, mantlevault = function() local intentDot,hips,head,shortHead = invoke("intentDot","hips","head","shortHead") local minVaultSpeed = movement.parkour.vault.minSpeed if intentDot > -.1 and hips.hit and hips.hit.Name ~= "Barrier" and (actor.speed >= minVaultSpeed or hips.length < 4) and (not head.hit or not shortHead.hit) and hips.normal.Y < .3 and actor.velocity.Y > -actor.terminalVelocity+100 then local hipsRay = invoke("hipsRay") local floor = raycast.raycast(ray(hips.pos+v3(0,2.7,0)+dir*5,v3(0,-2.7,0))) local backside = raycast.raycast(ray(hips.pos+dir*5,-dir*5)) local vaultSpeed = math.max(actor.baseSpeed,max(v3(actor.velocity.X,max(0,actor.velocity.Y),actor.velocity.Z).magnitude,actor.speed,24)) if (floor.hit or not backside.hit or (actor.speed < minVaultSpeed and hips.length < 4)) and not shortHead.hit then local climbType = actor.speed > 20 and "FastMantle" or "Mantle" if head.hit then climbType = "Mantle" end local args = movement:attemptClimb(hips.pos,-dir,climbType,dir) if args then return "mantle",{dir,vaultSpeed,args,hips} end elseif not head.hit and actor.speed >= minVaultSpeed then return "vault",{vaultSpeed,hipsRay,hips} end end end, } } local upConditions = movement.conditions.up movement.conditions.ordered = { up = { ground = { upConditions.mantlevault, upConditions.climbpipe, upConditions.jump }, disable = { upConditions.jump, upConditions.doublejump }, air = { upConditions.mantlevault, upConditions.climbpipe, upConditions.jump, upConditions.wallrunclimb, upConditions.doublejump }, airdash = { upConditions.wallclimb, upConditions.wallkick, upConditions.wallrun, upConditions.mantlevault, upConditions.climbpipe, upConditions.jump, upConditions.doublejump }, dialog = { upConditions.jump }, } } movement.queries = { up = function(a,b) if actor.currentAnimSpot then actor:exitLoiterSpot() return "getUp" end local rootpart = actor.rootpart local humanoid = actor.humanoid if not actor.alive or not rootpart or not humanoid or actor.frozen or movement.parkour.pipeclimb.active or movement.parkour.zipline.active then return end origin = movement:getOrigin() dir = a or origin.LookVector allowPrecisionClimb = b movementDependencies:reset() if true then local conditions = movement.conditions.ordered.up local selected if dialog.isOpen then selected = conditions.dialog elseif movement.parkour.dash.airActive then selected = conditions.airdash elseif actor.air then selected = conditions.air --[[ if actor.lastVaultJump and tick()-actor.lastVaultJump < .4 and actor.velocity.Y > 0 and input.bindsDown.upmove and actor.lastVaultJump > input.bindsDown.upmove then selected = conditions.disable end --]] else selected = conditions.ground end for _,condition in pairs(selected) do local target,args = condition() if target then return target,args end end end end, down = function() actor.preparing = tick() local onGround = actor.onground() if not onGround then -- jasper code i apologize if (not movement.parkour.is) and actor.velocity.Y <= -15 then --? elseif data:hasAbility("Coil") and not actor.coiling and not movement.parkour.is and not shared.freecaming then return "coil" end elseif onGround then if data:hasAbility("Powerslide") and actor.velocity.magnitude > movement.parkour.powerslide.minSpeed then return "powerslide" end end end, } movement.responseFunctions = { jump = function(...) movement:jump(...) end, wallclimb = function(front) movement:wallrun(false,front.pos,front.normal) end, wallrun = function(wall,isLeft) movement.parkour.wallrun.left = isLeft movement:wallrun(true,wall.pos,wall.normal) if isLeft then animation.wallrunL:Play() --animation.wallrunLenter:Play() else animation.wallrunR:Play() --animation.wallrunRenter:Play() end end, climb = function(...) movement:ledgeClimb(...) end, mantle = function(dir,vaultSpeed,args,hips) table.insert(args,hips) movement:ledgeClimb(unpack(args)) if input.bindsDown.upmove and actor.inputVector.Magnitude <= input.inputVectorZeroThreshold then movement:vaultJump(dir,vaultSpeed) else input.bindsDown.upmove = false end end, vault = function(speed,hipsRay,hips) local humanoid = actor.humanoid local rootpart = actor.rootpart if hips.hit and (world.district == "Tutorial" or not hips.hit:GetAttribute("TutorialOnly")) then local override = hips.hit:GetAttribute("VaultSpeed") speed = override or speed if override then actor:setspeed(speed) end end movement:setMovementActive("vault",true) animation.monkeyvault:Play(.1,1,2) movement("vault") humanoid:SetState("Jumping") actor.ammo.jump = false actor:speedboost() actor:resetAmmo() sound:PlayHybridSound("Grab2","game") sound:PlayHybridGroupSound("Cloth","game",{PlaybackSpeed=1+signedRandom(.1)}) local _,_,_,vaultParts = raycast.raycast.recursive("none",hipsRay) for i,v in pairs(vaultParts) do if v.Anchored and v.CanCollide then --v.CanCollide = false else table.remove(vaultParts,i) end end --actor.humanoid:ChangeState(Enum.HumanoidStateType.Freefall) local dir = origin.lookVector rootpart.CFrame = cf(rootpart.Position,rootpart.Position+dir) local st = tick() local passed = false while tick()-st < .175 or not passed do engine.wait() humanoid:SetState("Jumping") humanoid:SetVelocity(v3(0,7,0)+dir*speed) passed = getOffsetFromPlane(rootpart.Position,hips.pos,dir) > .5 end sound:PlayHybridGroupSound("Cloth","game",{PlaybackSpeed=1+signedRandom(.1)}) for i,v in pairs(vaultParts) do --v.CanCollide = true end movement:setMovementActive("vault",false) actor.jumping = false if input.bindsDown.upmove and hips.hit and (not hips.hit:GetAttribute("DisableVaultJump") or (hips.hit:GetAttribute("TutorialOnly") and world.district ~= "Tutorial")) then movement:vaultJump(dir,speed) end end, wallkick = function(dir) local dash = movement.parkour.dash local wallkick = movement.parkour.wallkick actor.ammo.wallkick -= 1 wallkick.did = true dash.lastRelease = 0 dash.lastAirUse = tick() dash.airActive = false --[[if actor.ammo.wallkick == 0 then dash.wallKickExhaust = true end]] sound:PlayStep("WallKick") movement("wallkick") animation:SafeStopType("air") animation.wallkick_back:Play(.1) local speed = alphaFromRange(actor.speed,wallkick.minSpeed,wallkick.maxSpeed,wallkick.minMomentum,wallkick.maxMomentum) local vel = dir*speed local finalvel = augmentVelocity(vel) actor.humanoid:SetVelocity(v3(finalvel.X,wallkick.upMomentum,finalvel.Z)) actor:speedboost() data.stats:increment("WallKicks",1) end, climbpipe = function(pipe) movement:climbPipe(pipe) end, powerslide = function() movement:powerslide() end, coil = function() movement:coil() end, } function movement:queryMovementType(movementType,...) local query = movement.queries[movementType] if query then return query(...) --send response args else warn("couldn't find query for movement type",movementType) end end function movement:executeMovementResponse(response,args) local responseFunction = movement.responseFunctions[response] if responseFunction then return responseFunction(unpack(args or {})) else --warn("no response function for response",response) end end end --[[local debugbrick = new("Part",workspace.RaycastIgnore) debugbrick.Material = Enum.Material.ForceField debugbrick.Color = Color3.new(0,1,0) debugbrick.Anchored = true debugbrick.CanCollide = false]] events.parkour:connect(function(move) --print(move) network:send("parkour",move) end) local wallrun = movement.parkour.wallrun local dash = movement.parkour.dash movement.wallrunStep = function(delta) delta = math.min(delta,.1) --wallrun logic if wallrun.active and wallrun.normal.Magnitude > 0 then local marginBack,marginFront = 3,(wallrun.lateral and 1.5 or .6) local fullMargin = marginBack+marginFront local upReach = 4 local rayPos = wallrun.pos+wallrun.normal*marginBack local rayCF = cf(rayPos,rayPos-wallrun.normal) local casted = raycast.raycast(ray(rayPos,-wallrun.normal*fullMargin)) wallrun.casted = casted local upCast = raycast.raycast(ray(rayPos+v3(0,upReach,0),-wallrun.normal*fullMargin)) --local downShift = raycast(ray(rayPos+v3(0,-3,0),-wallrun.normal*fullMargin)) local collision = { upEx = raycast.raycast(ray(rayPos-wallrun.normal*.5,v3(0,upReach,0))), up = raycast.raycast(ray(rayPos-wallrun.normal*.5,v3(0,3,0))), left = raycast.raycast(ray(rayPos-wallrun.normal*.5,-rayCF.RightVector*.75)), right = raycast.raycast(ray(rayPos-wallrun.normal*.5,rayCF.RightVector*.75)), } local adjustDistance = marginBack-upCast.length local animSpeed = wallrun:getAnimSpeed() animation.wallrunL:AdjustSpeed(animSpeed) animation.wallrunR:AdjustSpeed(animSpeed) local distanceOffWall = wallrun.lateral and 1.85 or (wallrun.speed > 26 and 1.5 or 1) if not wallrun.lateral then distanceOffWall += adjustDistance end local physicalPos = actor.rootpart.Position+wallrun.normal*(marginBack-distanceOffWall) local physicalCast = raycast.raycast(ray(physicalPos,-wallrun.normal*fullMargin)) local currentTick = tick()-wallrun.start local duration = (wallrun.lateral and wallrun.horizontalDuration or wallrun.verticalDuration) wallrun.timeColliding += (if wallrun.left then collision.right.hit~=nil else collision.left.hit~=nil) and delta or -wallrun.timeColliding local sinceLastAirDash = tick()-dash.lastAirUse local wallDashing = wallrun.lateral and dash.airActive local isClear = if wallrun.lateral then wallrun.timeColliding < .2 else collision.upEx.hit or upCast.hit local notTooTilted = casted.normal.Y < .3 and casted.normal.Y > -.15 local tooSlow = (not wallrun.lateral or abs(wallrun.velocity.X) < 1) and wallrun.velocity.Magnitude < 5 and currentTick > .2 local withinDuration = currentTick < duration local clutching = not wallrun.lateral and wallrun.timeHanging < wallrun.maxHangTime local notFallenTooFar = wallrun.pos.Y > wallrun.startPos.Y-(wallrun.lateral and wallrun.maxLateralFallDistance or wallrun.maxVerticalFallDistance) local blocked = (casted.hit and casted.hit.Name == "Barrier") or (upCast.hit and upCast.hit.Name == "Barrier") local desiresToContinue = true if blocked then casted.hit = false physicalCast.hit = false isClear = false wallrun.coyoteBudget = 0 elseif not notTooTilted then casted.hit = false end local surfaceClimbable = casted.hit and casted.hit:HasTag("Climbable") local usableSurface = (casted.hit or physicalCast.hit or wallrun.coyoteBudget > 0) and isClear local upPressed = input.bindsDown.upmove local downPressed = input.bindsDown.downmove local toWallboost = false local wantsToWallBoost = movement.parkour.dash.airActive and data:hasAbility("WallBoost") if not wallrun.lateral then if wantsToWallBoost and input.stickyBinds.upmove then desiresToContinue = false toWallboost = true elseif not wantsToWallBoost and ((data.settings.HoldToWallClimb and not upPressed) or (not data.settings.HoldToWallClimb and input.stickyBinds.upmove)) then desiresToContinue = false end else if (data.settings.HoldToWallRun and not upPressed) or (not data.settings.HoldToWallRun and input.stickyBinds.upmove) then desiresToContinue = false end end local desiresToJumpOut = false if not wallrun.lateral then if data.settings.HoldToWallClimb and not upPressed then desiresToJumpOut = true elseif not data.settings.HoldToWallClimb and input.stickyBinds.upmove then desiresToJumpOut = true end else if data.settings.HoldToWallRun and not upPressed then desiresToJumpOut = true elseif not data.settings.HoldToWallRun and input.stickyBinds.upmove then desiresToJumpOut = true end end if data.settings.AutoParkour and currentTick > duration-.75 then desiresToJumpOut = true end local minVx,maxVx = -math.huge,math.huge if collision.left.hit and not collision.right.hit then maxVx = -2*(1-collision.left.alpha) elseif collision.right.hit and not collision.left.hit then minVx = 2*(1-collision.right.alpha) elseif collision.left.hit and collision.right.hit then minVx,maxVx = 0,0 end local blocked local downHit = raycast.raycast(ray(actor.rootpart.Position,v3(0,-3,0))) if usableSurface and not actor.ground and (not tooSlow and withinDuration or clutching) and notFallenTooFar and desiresToContinue and not downHit.hit then wallrun.accumulator += delta if casted.hit then wallrun.coyoteBudget = wallrun.coyoteTime wallrun.pos = casted.pos wallrun.hit = casted.hit wallrun.normal = casted.normal elseif not physicalCast.hit then if wallrun.coyoteBudget > 0 then wallrun.coyoteBudget = math.max(wallrun.coyoteBudget - delta,0) else wallrun.coyoteBudget -= delta end --print(wallrun.coyoteBudget) end currentTick = tick()-wallrun.start wallrun.last = tick() wallrun.lateralDirection = wallrun.velocity.X / abs(wallrun.velocity.X) local desireInput = normalToOrientedCFrame(wallrun.normal):PointToObjectSpace(actor.inputVector) local desired = desireInput.X -- direction and speed on the wall's normal the player wishes to move in if wallrun.lateral then if camera:IsLocked() then desired = wallrun.left and actor.localInputVector.Z or -actor.localInputVector.Z else desired = desireInput.X end if desireInput.magnitude == 0 then desired = wallrun.left and -1 or 1 end end local nextChange = v2() local stepped = false if wallrun.lateral then wallrun.speed = max(abs(wallrun.velocity.X),actor.speed) end while wallrun.accumulator > 0 do local delta = min(wallrun.accumulator,1/wallrun.FPS) wallrun.accumulator -= delta currentTick += delta local distanceFromTarget = getDistance(actor.rootpart.Position,wallrun.targetRootCFrame.Position) local entrySpeed = max(wallrun.entryCharacterVelocity.magnitude,16) if distanceFromTarget > .1 and entrySpeed < 64 then local lerpAccelAlpha = 1 + min(1,currentTick/.25) local nextCFrameStepAlpha = clamp((entrySpeed*delta*lerpAccelAlpha) / distanceFromTarget,0,1) actor.rootpart.CFrame = actor.rootpart.CFrame:Lerp( wallrun.targetRootCFrame, nextCFrameStepAlpha ) else actor.rootpart.CFrame = wallrun.targetRootCFrame end --velocity --local targetVx = clamp( lerp(wallrun.velocity.X,(wallrun.lateral and (localDesired.X > 0 and 1 or (localDesired.X < 0 and -1)) or localDesired.X)*wallrun.speed*(wallrun.lateral and 1 or .2),delta*5) , minVx , maxVx) local targetVx = clamp( lerp(wallrun.velocity.X,(wallrun.lateral and (desired > 0 and 1 or (desired < 0 and -1) or 0) or desired)*wallrun.speed*(wallrun.lateral and 1 or .2),delta*5) , minVx , maxVx) local targetVy = wallrun.lateral and max(-25,wallrun.velocity.Y-wallrun.horizontalGravity*delta) or max(-25,wallrun.velocity.Y-wallrun.verticalGravity*delta/((movement:isWallrunClutching() and wallrun.velocity.Y < 0) and 3 or 1)) wallrun.velocity = v2( targetVx, min(collision.up.hit and 0 or math.huge,targetVy) ) --- if wallrun.float and wallrun.velocity.Y < -10 and abs(wallrun.velocity.X) >= actor.speed -1 and wallrun.lateral then local change = (wallrun.horizontalGravity+15/2)*delta local horizInherit = (wallrun.velocity.Y < -15 and (wallrun.velocity.X > 0 and change or -change) * .75 or 0) wallrun.velocity += v2(horizInherit,change) end if not wallrun.lateral and not wallrun.pushBoosted then wallrun.pushFuel += delta local clutching = movement:isWallrunClutching() if wallrun.pushFuel >= wallrun.pushSpeed and not clutching then wallrun.pushFuel -= wallrun.pushSpeed if surfaceClimbable then wallrun.velocity = v2(0,1+wallrun.verticalGravity*wallrun.pushSpeed) wallrun.climbing = true else wallrun.velocity += v2(0,wallrun.basePush) end stepped = true elseif (wallrun.canPushBoost and clutching) or wallrun.wallboostAttempt then wallrun.pushBoosted = true --print("boost") stepped = true wallrun.velocity = v2(wallrun.velocity.X,wallrun.basePush*1.5) end end nextChange += wallrun.velocity*delta end if not wallrun.lateral and movement:isWallrunClutching() then distanceOffWall = 1 animation.wallclutch:SafePlay(.35) end local charPos = wallrun.pos + wallrun.normal*distanceOffWall if wallrun.lateral then wallrun.lastRunNormal = wallrun.normal local sideVector = cf(v3zero,wallrun.normal).RightVector if wallrun.left then sideVector = -sideVector end wallrun.targetRootCFrame = cf(charPos, charPos + v3(sideVector.X,0,sideVector.Z-.0001)) if duration-currentTick < 2/3 then if wallrun.left then animation.wallrunLend:SafePlay(.3) else animation.wallrunRend:SafePlay(.3) end end if data.settings.AutoWallClimb then local dir = rayCF.RightVector * (wallrun.left and 1 or -1) local response,args = movement:queryMovementType("up",dir,false) --print(response , wallrun.transitionResponses[response] , (data.settings.AutoWallClimb or response == "climb")) if response and wallrun.transitionResponses[response] and (data.settings.AutoWallClimb or response == "climb") then movement:endWallrun() movement:executeMovementResponse(response,args) end end else wallrun.lastClimbNormal = wallrun.normal wallrun.targetRootCFrame = cf(charPos, charPos - wallrun.normal) if wallrun.velocity.Magnitude <= 5 or currentTick > wallrun.verticalDuration then wallrun.timeHanging += delta end if stepped then sound:PlayStep("wallrun") movement:stopWallrunAnimations(wallrun.pushSpeed) if wallrun.stepPhase == "left" then if wallrun.pushBoosted then animation.wallclimbLastL:Play() elseif wallrun.speed > 26 then if wallrun.totalSteps == 0 then animation.wallstepL:Play(.075,.75,1.25) animation.wallclimbL:Play(.075,.25,1) else animation.wallstepL:Play() end else animation.wallclimbL:Play() end wallrun.stepPhase = "right" else if wallrun.pushBoosted then animation.wallclimbLastR:Play() elseif wallrun.speed > 26 then if wallrun.totalSteps == 0 then animation.wallstepR:Play(.075,.75,1.25) animation.wallclimbR:Play(.075,.25,1) else animation.wallstepR:Play() end else animation.wallclimbR:Play() end wallrun.stepPhase = "left" end wallrun.totalSteps += 1 end if casted.hit then local args = movement:attemptClimb(casted.pos,casted.normal,nil,-wallrun.normal) if args then movement:endWallrun() movement:ledgeClimb(unpack(args)) return end end end wallrun.maxHeight = math.max(wallrun.maxHeight,actor.rootpart.CFrame.Y) wallrun.pos += (cf(v3zero,wallrun.normal)*cf(nextChange.X,nextChange.Y,0)).Position wallrun.topPos = upCast.hit and upCast.pos or wallrun.topPos --movement.bodypos.Position = (wallrun.pos + wallrun.normal*distanceOffWall) --print(velocity.Magnitude) --[[local relative = (actor.position-movement.bodypos.Position) if relative.magnitude > 8 then movement.bodypos.Position = actor.position + relative.unit*8 end]] if input.stickyBinds.downmove and not input.bindsDown.downmove then movement:endWallrun() end elseif toWallboost then local flatLook = v3flat(camera.rawlook) local wbFront = raycast.raycast(ray(wallrun.pos+wallrun.normal*1,flatLook*3)) local angleConcessionAlpha = alphaFromRange(currentTick,wallrun.timeToWallBoostMin,wallrun.timeToWallBoostMin,0,1) local angleCorrect = v3flat(wallrun.normal):Dot(flatLook) > -(.2 + angleConcessionAlpha * .5) or not wbFront.hit or input.usingGamepad local success = camera.rawlook.Y > 0 and angleCorrect and currentTick < wallrun.timeToWallBoostMax if success then movement:wallJump{ normal = v3zero, jumpType = "boost" } movement.parkour.dash.lastAirUse = tick() else animation.boostfail:Play() movement:endWallrun() movement:dashRelease(true) end elseif desiresToJumpOut or (data.settings.AutoParkour and currentTick >= duration) then wallrun:jumpOut() elseif actor.ground then movement:endWallrun() else movement:endWallrun() end if (sinceLastAirDash >= dash.wallKickWindow and wallDashing) then wallrun:jumpOut() end else animation.wallclutch:SafeStop() animation.wallrunL:SafeStop() animation.wallrunR:SafeStop() animation.wallrunLend:SafeStop() animation.wallrunRend:SafeStop() end ----- end movement.step = function(delta) delta = min(delta,.1) movement:isParkouring() --[[local debugspace = movement.bodypos.Position-actor.position debugbrick.Size = v3(.2,.2,debugspace.magnitude) debugbrick.CFrame = cf(actor.position,movement.bodypos.Position)*cf(0,0,-debugspace.magnitude/2) debugbrick.Color = movement.bodypos.MaxForce.magnitude > 0 and Color3.new(0,1,0) or Color3.new(1,0,0)]] local slide = movement.parkour.slide if slide.active then actor.humanoid.SlideSlope = 0 else actor.humanoid.SlideSlope = actor.maxSlideSlope end if slide.active or actor.sliding then if not animation.slide_enter.raw.IsPlaying or animation.slide_enter.raw.TimePosition > .2 then actor:playSlideAnimations() end --// justyn code, NaN prevention, it's trying to get the unit of a vector thats 0 thank u hudzell --print(actor.physicalVelocity) if actor.physicalVelocity == Vector3.new(0,0,0) then --print("naned here") actor.physicalVelocity = Vector3.new(1,1,1) end --\\ bad code til someone else fixes it actor.humanoid.SlidingDrag = v2(.1+.7*clamp(actor.physicalVelocity.unit.Y*2+.5,0,1),0) if tick()-actor.lastLandedTick > .3 or actor.jumping or not input.bindsDown.downmove or actor.velocity.magnitude < slide.minSpeed/1.5 then movement:endSlide() end else actor:stopSlideAnimations() end local powerslide = movement.parkour.powerslide if powerslide.active then actor.rootpart.CFrame = cf(actor.rootpart.Position,actor.rootpart.Position + v3flat(powerslide.velocity)) animation.powerslide_slow:SafePlay(.15) animation.powerslide:SafePlay(.15) local speedWeight = alphaFromRange(powerslide.velocity.Magnitude,powerslide.minSpeed,32,0,1) animation.powerslide_slow:AdjustWeight(1-speedWeight) animation.powerslide:AdjustWeight(speedWeight) local animSpeed = clamp(powerslide.velocity.Magnitude/32,.1,2) animation.powerslide_slow:AdjustSpeed(clamp(powerslide.velocity.Magnitude/32,.1,2)) animation.powerslide:AdjustSpeed(clamp(powerslide.velocity.Magnitude/32,.1,2)) --print("POWERSLIDE!!") if (not actor.ground and not actor.withinCoyote()) or powerslide.velocity.Magnitude < powerslide.minSpeed or actor.physics.Velocity.Magnitude < powerslide.minSpeed or (not input.bindsDown.downmove and tick()-powerslide.last > .5) or movement.parkour.is then --print("powersliden't :(") movement:stopPowerslide(":)") end else movement:stopPowerslide() end actor.humanoid.Camera.AllowLock = -- to prevent root from locking to cam while in first person/shift lock not slide.active and not actor.sliding and not wallrun.active and not movement.parkour.climb.active and not movement.parkour.zipline.active and not movement.parkour.pipeclimb.active and not movement.parkour.powerslide.active and actor.currentAnimSpot == nil --movement:updatePhysicsEnabled() local dropkick_11 = movement.parkour.dropkick if dropkick_11.active and dropkick_11.recoveryTime < tick() - dropkick_11.last then movement:dropkickRecovery() end end movement.powerslideStep = function(delta) local powerslide = movement.parkour.powerslide if powerslide.active then local currentTick = tick()-powerslide.last if currentTick > powerslide.frictionlessWindow then powerslide.velocity /= 1 + powerslide.frictionFactor * delta end if data:hasAbility("Dropdown") then local hit,pos local maxLength = 0 local parts = {} local step = 1/3 for length = 1,alphaFromRange(actor.velocity.magnitude,0,powerslide.minSpeed,4,8)/step do local casted = raycast.raycast(ray(actor.position+actor.rootlook*length*step,v3(0,-5.5,0))) if not casted.hit then break else parts[casted.hit] = casted.hit maxLength = length*step hit,pos = casted.hit,casted.pos end end local forward = raycast.raycast(ray(actor.position+v3(0,-2.5,0),actor.rootlook*(maxLength+1))) local farDown = raycast.raycast(ray(forward.pos,v3(0,-4.5,0))) --print(hit,not forward.hit,not farDown.hit,not movement.parkour.is) if hit and not forward.hit and not farDown.hit and not movement.parkour.is then local dropPos = pos + actor.rootlook*.5 + v3(0,-1.5,0) movement:stopPowerslide() movement:dropdown(cf(dropPos,dropPos+actor.rootlook),parts) end end local velocity = powerslide.velocity --[[ local wall:_raycastResult = raycast(ray( actor.rootpart.Position, velocity*.1 )) --]] local params = RaycastParams.new() params.FilterType = Enum.RaycastFilterType.Exclude params.FilterDescendantsInstances = raycast.raycast.ignore params.CollisionGroup = "Player" params.RespectCanCollide = true local obstruction:RaycastResult = workspace:Blockcast( actor.rootpart.CFrame, v3(1,4,1), velocity * .25, params ) local underpass:RaycastResult = workspace:Blockcast( actor.rootpart.CFrame - v3(0,2,0), v3(1,1,1), velocity * .25, params ) local slideUnder = (obstruction and obstruction.Instance and not underpass) --[[ local hit,pos if wall.hit then local hasHit = false for offset = 0, 2, 1/3 do local casted:_raycastResult = raycast(ray( wall.pos - velocity.Unit*.1 - v3(0,offset,0), velocity.Unit * 5 )) if not casted.hit then slideUnder = true else hasHit = true if slideUnder then slideUnder = false break end end end end --]] local sloost = --[[(actor.groundTime < 1/30 and actor.airVelocity.Y < -32)]] false --print(add) if slideUnder or sloost or (actor.physics.CurrentAngle and actor.physics.CurrentAngle > actor.slideTransitionAngle) then movement:stopPowerslide("slide") movement.parkour.powerslide.last = 0 --reset cooldown animation.powerslide_transition:Play() local targetSpeed if sloost then targetSpeed = min(64,(actor.airVelocity*v3(1,.75,1)).magnitude) else local baseSpeed = if slideUnder then powerslide.velocity.magnitude else powerslide.entrySpeed local add = if slideUnder then 4 else 0--math.clamp(currentTick/.125-0.1,0,4) local boostedSpeed = min(powerslide.entrySpeed+add, actor.maxSpeed) targetSpeed = max(boostedSpeed, baseSpeed) end movement("slideUnder") movement:slide(targetSpeed) end end end end --- end return movement