extends CharacterBody2D const SPEED = 500.0 const ACCEL = 7.0 var direction = 0 var addedveloc = 0 var forcedVeloc = 0 const JUMP_VELOCITY = -450.0 const MAX_JUMPS = 1 var jumps = MAX_JUMPS var wallKayote = 0 const FALL_SPEED = -JUMP_VELOCITY var falling = false var floorTime = 0 var kayote = 0 var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") var checkpointPos = Vector2.ZERO @export var ghostMode = false var ghostFrame = 0 var startPos = Vector2.ZERO var can_move = true var camera : Camera2D @export var savedInputsPath : String @onready var sceneReload = load(get_tree().current_scene.scene_file_path) var savedInputs = [] var wallPower = 0 var squishers = -1 func actionPressed(inp): if ghostMode: if inp in savedInputs[ghostFrame]: return true return false else: return Input.is_action_pressed(inp) func actionJustPressed(inp): if ghostMode: if inp in savedInputs[ghostFrame] and not inp in savedInputs[ghostFrame - 1]: return true return false else: return Input.is_action_just_pressed(inp) func getAxis(inp1, inp2): if ghostMode: var dir = 0 if actionPressed("left"): dir -= 1 if actionPressed("right"): dir += 1 return clamp(dir, -1, 1) else: return Input.get_axis(inp1, inp2) func isWallSliding(): for collisionNumb in get_slide_collision_count(): var collision = get_slide_collision(collisionNumb) var object = collision.get_collider() if object is TileMap: var tileMap : TileMap = object var tilePos = tileMap.get_coords_for_body_rid(collision.get_collider_rid()) var tileData = tileMap.get_cell_tile_data(0, tilePos) if tileData and not tileData.get_custom_data("Slidable") == true: return false return is_on_wall_only() and direction func getGravMulti(): var axis = (gen.boolToNumb(actionPressed("up") or forceLowGrav, 1)) if velocity.y < 0: return axis return 1 func launch(veloc): addedveloc = veloc velocity.x = veloc func forceLaunch(veloc): forcedVeloc = veloc velocity.x = veloc signal Jumped signal Died var deathParticles = preload("res://Particles/Player/deathParticles.tscn") var doubleWallJumped = false var forceLowGrav = true var landed = false func die(): Died.emit() var parti = deathParticles.instantiate() parti.modulate = $Sprite.self_modulate add_child(parti) can_move = false $Sprite.visible = false gen.savedPos = checkpointPos await Camera.deathAnim().finished get_tree().change_scene_to_packed(sceneReload) func _ready(): RenderingServer.set_default_clear_color(Color8(0, 0, 0)) if find_child("Camera"): camera = $Camera if ghostMode: startPos = global_position var rc = load(savedInputsPath) if rc: var inputKeyRaw = rc["actions"] var frameDataRaw = rc["data"] var inputKey = [] var frameData = {} for action in inputKeyRaw: inputKey.append(action) for frame in frameDataRaw: frameData[frame] = {} for x in frameDataRaw[frame]: frameData[frame][x] = frameDataRaw[frame][x] var frameCount = gen.getRecordingFrameCount(frameData) var held = [] for frame in range(frameCount): savedInputs.append([]) if frameData.has(frame): for actID in frameData[frame]: var pressed = frameData[frame][actID] var inputName = inputKey[actID] if pressed == 1: held.append(inputName) elif inputName in held: held.remove_at(held.find(inputName)) savedInputs[frame] += held else: Camera.player = self var parti = deathParticles.instantiate() parti.modulate = $Sprite.self_modulate add_child(parti) $Sprite.visible = true $"../Smoother".reset_node(self) #camera.position_smoothing_enabled = true if gen.savedPos != Vector2.ZERO: global_position = gen.savedPos gen.savedPos = Vector2.ZERO velocity = Vector2(0, 0) #camera.reset_smoothing() @onready var trail = $"Sprite/Trail" var ghosting = true var ghostParti = preload("res://Particles/Ghosts/spawnParticles.tscn") var lastFloor = null func spawnParti(): var parti = ghostParti.instantiate() add_child(parti) parti.top_level = true parti.global_position = global_position func _physics_process(delta): if ghostFrame + 1 >= savedInputs.size() and ghostMode: ghostFrame = 0 trail.points = [] $Sprite.visible = false ghosting = false spawnParti() global_position = startPos velocity = Vector2.ZERO await get_tree().create_timer(3).timeout spawnParti() ghosting = true $Sprite.visible = true if (ghosting or !ghostMode) and can_move: var space_state = get_world_2d().direct_space_state if ghostFrame == 0: spawnParti() ghostFrame += 1 direction = round(getAxis("left", "right")) wallKayote -= delta if is_on_floor() and !landed: velocity.y = 0 if not is_on_floor(): if velocity.y < 2000: velocity.y += gravity * delta / getGravMulti() floorTime = 0 kayote -= delta if lastFloor: if "velocity" in lastFloor: velocity += lastFloor.velocity lastFloor = null else: #velocity.y = 0 doubleWallJumped = false kayote = 0.3 floorTime += delta jumps = MAX_JUMPS falling = false for collisionNumb in get_slide_collision_count(): var collision = get_slide_collision(collisionNumb) var object = collision.get_collider() if abs(collision.get_angle()) <= floor_max_angle: lastFloor = object if velocity.y <= 0: forceLowGrav = false if isWallSliding(): wallKayote = 0.3 falling = false if actionJustPressed("respawn") or position.y > 5000: die() if actionJustPressed("jump"): if wallKayote > 0 and not is_on_floor(): if doubleWallJumped: wallKayote = 0 else: doubleWallJumped = true wallKayote += 0.1 if actionPressed("down"): launch(get_wall_normal().x * SPEED * 1.75) velocity.y = clamp((velocity.y / 2) + JUMP_VELOCITY / 1.8, -INF, JUMP_VELOCITY / 1.8) else: launch(get_wall_normal().x * SPEED * 1.4) velocity.y = clamp(velocity.y + JUMP_VELOCITY, -INF, JUMP_VELOCITY) Jumped.emit() #if result and "velocity" in result.collider: #velocity.x += result.collider.velocity.x elif jumps > 0: velocity.y = clamp(velocity.y + JUMP_VELOCITY, -INF, JUMP_VELOCITY) doubleWallJumped = false if kayote < 0: jumps -= 1 else: var query = PhysicsRayQueryParameters2D.create(global_position + (Vector2.UP * 32), global_position + (Vector2.DOWN * 64)) query.exclude = [self] var result = space_state.intersect_ray(query) if result and "velocity" in result.collider: velocity += result.collider.velocity falling = false if actionPressed("down") and kayote > 0 and abs(velocity.x) < SPEED * 1.5: launch(direction * SPEED * 1.5) kayote = 0 Jumped.emit() if actionJustPressed("down") and not falling and not isWallSliding(): falling = true velocity.y = clamp(velocity.y + FALL_SPEED, FALL_SPEED, INF) if isWallSliding(): var upDown = clamp(getAxis("up", "down"), -0.5, 1) var holdMulti = (upDown * 2) + 1 var query = PhysicsRayQueryParameters2D.create(global_position + (get_wall_normal() * 32), global_position + (get_wall_normal() * -64)) query.exclude = [self] var result = space_state.intersect_ray(query) if result and "velocity" in result.collider and abs(result.collider.velocity.x) > 50: velocity.y = lerpf(velocity.y, 0, delta * 30) else: velocity.y = lerpf(velocity.y, clamp(velocity.y, JUMP_VELOCITY, 100 * holdMulti), delta * 10) var finalSpeed = clamp(abs(velocity.x), SPEED, INF) if floorTime > 0.05: finalSpeed = clamp(lerp(finalSpeed, SPEED, delta * 20), SPEED, INF) velocity.x = lerp(velocity.x, direction * finalSpeed, delta * ACCEL) if abs(velocity.x) < abs(addedveloc): addedveloc = lerp(addedveloc, velocity.x, ACCEL * 2 * delta) velocity.x += addedveloc * delta * 15 if abs(velocity.x) < abs(forcedVeloc): forcedVeloc = lerp(forcedVeloc, velocity.x, ACCEL * 2 * delta) velocity.x += forcedVeloc * delta * 35 addedveloc = lerpf(addedveloc, 0, delta * 6) if not is_on_floor(): forcedVeloc = lerpf(forcedVeloc, 0, delta) else: forcedVeloc = lerpf(forcedVeloc, 0, delta * 5) landed = is_on_floor() move_and_slide() func _process(_delta): if ghostMode: if velocity.length() > 5: trail.add_point(global_position) elif trail.get_point_count() > 0: trail.remove_point(0) if trail.get_point_count() > 100: trail.remove_point(0) func _on_squish_detection_body_shape_entered(_body_rid, _body, _body_shape_index, _local_shape_index): squishers += 1 if squishers >= 2: die() func _on_squish_detection_body_shape_exited(_body_rid, _body, _body_shape_index, _local_shape_index): squishers -= 1