added the game

This commit is contained in:
JHDev2006
2025-09-13 16:30:32 +01:00
parent 5ef689109b
commit 3773bdaf64
3616 changed files with 263702 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
extends Enemy
const MOVE_SPEED := 30
const BARREL_DESTRUCTION_PARTICLE = preload("res://Scenes/Prefabs/Particles/BarrelDestructionParticle.tscn")
func _physics_process(delta: float) -> void:
handle_movement(delta)
func handle_movement(delta: float) -> void:
if is_on_wall() and is_on_floor() and get_wall_normal().x == -direction:
die()
func die() -> void:
destroy()
func die_from_object(_node: Node2D) -> void:
destroy()
func summon_particle() -> void:
var node = BARREL_DESTRUCTION_PARTICLE.instantiate()
node.global_position = global_position - Vector2(0, 8)
add_sibling(node)
func destroy() -> void:
summon_particle()
AudioManager.play_sfx("block_break", global_position)
queue_free()
func bounce_up() -> void:
velocity.y = -200

View File

@@ -0,0 +1 @@
uid://dkg8usmlrm1d3

View File

@@ -0,0 +1,10 @@
extends Enemy
func _physics_process(delta: float) -> void:
handle_movement(delta)
func handle_movement(delta: float) -> void:
apply_enemy_gravity(delta)
if is_on_floor():
velocity.x = lerpf(velocity.x, 0, delta * 10)
move_and_slide()

View File

@@ -0,0 +1 @@
uid://q44gfy2ffos5

View File

@@ -0,0 +1,29 @@
extends Enemy
var falling := true
var target_player: Player = null
var can_rise := true
func _physics_process(delta: float) -> void:
target_player = get_tree().get_first_node_in_group("Players")
if falling:
global_position.y += 32 * delta
if global_position.y >= target_player.global_position.y - 24 and can_rise:
rise_tween()
$Sprite.play("Fall")
else:
$Sprite.play("Rise")
func rise_tween() -> void:
falling = false
can_rise = false
var tween = create_tween().set_trans(Tween.TRANS_CUBIC)
var dir = sign(target_player.global_position.x - global_position.x)
var target_position := Vector2(32 * dir, -32)
var final_position = global_position + target_position
final_position.y = clamp(final_position.y, -176, 64)
tween.tween_property(self, "global_position", final_position, 0.75)
await tween.finished
falling = true
await get_tree().create_timer(0.25, false).timeout
can_rise = true

View File

@@ -0,0 +1 @@
uid://coocdv3t4548x

View File

@@ -0,0 +1,23 @@
extends Enemy
@export var held_scene: PackedScene = null
func stomped_on(player: Player) -> void:
player.enemy_bounce_off()
AudioManager.play_sfx("enemy_stomp", global_position)
summon_held()
func summon_held() -> Node:
var node = held_scene.instantiate()
node.global_position = global_position
node.direction = direction
if $TrackJoint.is_attached:
get_parent().owner.add_sibling(node)
else:
add_sibling(node)
queue_free()
return node
func fireball_hit(fireball: Node2D) -> void:
var held = summon_held()
held.kick(fireball)

View File

@@ -0,0 +1 @@
uid://br4ltfynb4eqr

View File

@@ -0,0 +1,52 @@
extends Node2D
var target_player: Player = null
var velocity := Vector2.ZERO
const MOVE_SPEED := 30
const SMOKE_PARTICLE = preload("uid://d08nv4qtfouv1")
var direction := -1
signal killed
func _physics_process(delta: float) -> void:
target_player = get_tree().get_first_node_in_group("Players")
if $TrackJoint.is_attached == false:
handle_movement(delta)
$Sprite.scale.x = direction
func handle_movement(delta: float) -> void:
var target_direction = sign(target_player.global_position.x - global_position.x)
if target_direction != 0:
direction = target_direction
if target_player.direction == direction:
if $Sprite.animation != "Move":
$Sprite.play("Move")
velocity = lerp(velocity, 30 * global_position.direction_to(target_player.global_position), delta * 5)
else:
if $Sprite.animation != "Idle":
$Sprite.play("Idle")
velocity = lerp(velocity, Vector2.ZERO, delta * 5)
global_position += velocity * delta
func on_area_entered(area: Area2D) -> void:
if area.owner is Player:
if area.owner.is_invincible:
die()
else:
area.owner.damage()
func die() -> void:
summon_smoke_particle()
queue_free()
killed.emit()
func flag_die() -> void:
die()
func summon_smoke_particle() -> void:
var particle = SMOKE_PARTICLE.instantiate()
particle.global_position = global_position
add_sibling(particle)

View File

@@ -0,0 +1 @@
uid://bbp3jg7yg1700

View File

@@ -0,0 +1,18 @@
extends Node2D
@export_range(25, 180) var length := 80
@export_enum("Clockwise", "C-Clockwise") var direction := 0
@export_range(4, 12) var boo_amount := 10
@export var spread_boos := false
func _physics_process(delta: float) -> void:
%RotationJoint.global_rotation_degrees = wrap(%RotationJoint.global_rotation_degrees + (45 * [1, -1][direction]) * delta, 0, 360)
for i in $Boos.get_children():
i.get_node("Sprite").scale.x = sign(get_tree().get_first_node_in_group("Players").global_position.x + 1 - i.global_position.x)
func on_area_entered(area: Area2D) -> void:
if area.owner is Player:
area.owner.damage()
func flag_die() -> void:
queue_free()

View File

@@ -0,0 +1 @@
uid://djdtghrjbpv2i

View File

@@ -0,0 +1,144 @@
extends Enemy
const BOWSER_FLAME = preload("res://Scenes/Prefabs/Entities/Enemies/BowserFlame.tscn")
const HAMMER = preload("res://Scenes/Prefabs/Entities/Items/Hammer.tscn")
@onready var sprite: BetterAnimatedSprite2D = $SpriteScaleJoint/Sprite
@export var can_hammer := false
@export var can_fire := true
@export var music_enabled := true
var target_player: Player = null
var can_move := true
var can_fall := true
var health := 5
var move_dir := -1
func _ready() -> void:
for i in [$JumpTimer, $HammerTime, $FlameTimer]:
i.start()
func _physics_process(delta: float) -> void:
target_player = get_tree().get_nodes_in_group("Players")[0]
if is_on_floor():
direction = sign(target_player.global_position.x - global_position.x)
velocity.x = 0
sprite.scale.x = direction
if can_fall:
apply_enemy_gravity(delta)
move_and_slide()
if Input.is_action_just_pressed("editor_move_player") and Global.debug_mode:
die()
func jump() -> void:
if is_on_floor():
velocity.y = -100
$JumpTimer.start(randf_range(1, 2.5))
func apply_enemy_gravity(delta: float) -> void:
velocity.y += (2.5 / delta) * delta
velocity.y = clamp(velocity.y, -INF, Global.entity_max_fall_speed)
func get_target_y(player: Player) -> float:
if player.global_position.y + 16 < global_position.y:
return player.global_position.y - 32
else:
return player.global_position.y - 8
func show_smoke() -> void:
if has_meta("is_real"):
return
var smoke = preload("res://Scenes/Prefabs/Particles/SmokeParticle.tscn").instantiate()
smoke.scale = Vector2(2, 2)
smoke.global_position =global_position
AudioManager.play_sfx("magic", global_position)
add_sibling(smoke)
func breathe_fire() -> void:
if can_fire == false:
return
sprite.play("FireCharge")
await get_tree().create_timer(1, false).timeout
var flame = BOWSER_FLAME.instantiate()
flame.global_position = global_position + Vector2(18 * direction, -20)
flame.mode = 1
flame.direction = direction
flame.target_y = get_target_y(target_player)
if $TrackJoint.is_attached:
get_parent().owner.add_sibling(flame)
else:
add_sibling(flame)
sprite.play("FireBreathe")
if is_instance_valid(get_node_or_null("FlameTimer")):
$FlameTimer.start(randf_range(1.5, 4.5))
await get_tree().create_timer(0.5, false).timeout
sprite.play("Idle")
func bridge_fall() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
direction = 1
$FlameTimer.queue_free()
$HammerTime.queue_free()
$JumpTimer.queue_free()
sprite.play("Fall")
sprite.reset_physics_interpolation()
$MoveAnimation.queue_free()
can_fall = false
velocity.y = 0
await get_tree().create_timer(2).timeout
$FallSFX.play()
can_fall = true
$Collision.queue_free()
await get_tree().create_timer(2).timeout
queue_free()
func throw_hammers() -> void:
if can_hammer == false:
return
$Hammer.show()
await get_tree().create_timer(0.5, false).timeout
for i in randi_range(3, 6):
$Hammer.show()
await get_tree().create_timer(0.1, false).timeout
var node = HAMMER.instantiate()
node.velocity.y = -200
node.global_position = $Hammer.global_position
node.direction = direction
if $TrackJoint.is_attached:
get_parent().owner.add_sibling(node)
else:
add_sibling(node)
sprite.play("Idle")
$Hammer.hide()
await get_tree().create_timer(0.1, false).timeout
if get_node_or_null("HammerTime") != null:
$HammerTime.start()
func fireball_hit() -> void:
health -= 1
AudioManager.play_sfx("bump", global_position)
if health <= 0:
die()
else:
$SpriteScaleJoint/HurtAnimation.stop()
$SpriteScaleJoint/HurtAnimation.play("Hurt")
AudioManager.play_sfx("kick", global_position)
func play_music() -> void:
for i: EntityGenerator in get_tree().get_nodes_in_group("EntityGenerators"):
if i.entity_scene != null:
if i.entity_scene.resource_path == "res://Scenes/Prefabs/Entities/Enemies/BowserFlame.tscn":
i.queue_free()
if Settings.file.audio.extra_bgm == 0: return
if Global.level_editor != null:
return
if music_enabled:
AudioManager.set_music_override(AudioManager.MUSIC_OVERRIDES.BOWSER, 5, false)
func on_timeout() -> void:
move_dir = [-1, 1].pick_random()

View File

@@ -0,0 +1 @@
uid://wtypg4d0l6j2

View File

@@ -0,0 +1,29 @@
class_name BowserFlame
extends Node2D
@export_enum("Straight", "Aimed") var mode := 0
var target_y := 0
var direction := -1
func _ready() -> void:
pass
func _physics_process(delta: float) -> void:
movement(delta)
func movement(delta: float) -> void:
if mode == 1:
global_position.y = move_toward(global_position.y, target_y, delta * 50)
global_position.x += (100 * direction) * delta
$Sprite.scale.x = direction
func flag_die() -> void:
queue_free()
func on_area_entered(area: Area2D) -> void:
if area.owner is Player:
area.owner.damage()
func play_sfx() -> void:
AudioManager.play_sfx("bowser_flame", global_position)

View File

@@ -0,0 +1 @@
uid://btstbvjk6e6aw

View File

@@ -0,0 +1,29 @@
class_name BulletBill
extends Enemy
static var amount := 0
var can_despawn := false
const MOVE_SPEED := 96
var cannon := false
func _ready() -> void:
amount += 1
$Sprite.scale.x = direction
if cannon:
await get_tree().create_timer(0.2, false).timeout
z_index = 0
func _physics_process(delta: float) -> void:
global_position.x += (90 * delta) * direction
func _exit_tree() -> void:
amount -= 1
func on_screen_entered() -> void:
if Global.level_editor != null:
if Global.level_editor.current_state == LevelEditor.EditorState.PLAYTESTING or Global.current_game_mode == Global.GameMode.CUSTOM_LEVEL:
AudioManager.play_sfx("cannon", global_position)
else:
AudioManager.play_sfx("cannon", global_position)

View File

@@ -0,0 +1 @@
uid://7b27p232kp7w

View File

@@ -0,0 +1,8 @@
extends Enemy
var direction_vector := Vector2.UP
const MOVE_SPEED := 70.0
func _physics_process(delta: float) -> void:
global_position += direction_vector * MOVE_SPEED * delta

View File

@@ -0,0 +1 @@
uid://bfdtqldkrv4dn

View File

@@ -0,0 +1,36 @@
extends Enemy
const MOVE_SPEED := 32
var can_move := true
const DRY_BONES_DESTRUCTION_PARTICLES = preload("uid://bhs5ly6bbaahk")
func _physics_process(_delta: float) -> void:
$Sprite.scale.x = direction
func stomped_on(player: Player) -> void:
player.enemy_bounce_off(false)
$Sprite.play("Crumble")
AudioManager.play_sfx("dry_bones_crumble", global_position)
$BasicEnemyMovement.can_move = false
set_collision_layer_value(5, false)
set_collision_mask_value(5, false)
set_collision_mask_value(6, false)
$Hitbox/Shape.set_deferred("disabled", true)
await get_tree().create_timer(3, false).timeout
$ShakeAnimation.play("Shake")
await get_tree().create_timer(1, false).timeout
$Sprite.play("GetUp")
$ShakeAnimation.play("RESET")
await $Sprite.animation_finished
$BasicEnemyMovement.can_move = true
$Hitbox/Shape.set_deferred("disabled", false)
set_collision_layer_value(5, true)
set_collision_mask_value(5, true)
set_collision_mask_value(6, true)
$Sprite.play("Walk")
func summon_particle() -> void:
var particle = DRY_BONES_DESTRUCTION_PARTICLES.instantiate()
particle.global_position = global_position + Vector2(0, -10)
add_sibling(particle)
AudioManager.play_sfx("dry_bones_crumble", global_position)

View File

@@ -0,0 +1 @@
uid://n123x5yuqpjd

View File

@@ -0,0 +1,28 @@
extends Enemy
const BUZZY_BEETLE = preload("res://Scenes/Prefabs/Entities/Enemies/BuzzyBeetle.tscn")
var jump_meter := 0.0
func _physics_process(delta: float) -> void:
jump_meter += delta
$Sprite.play(["Fly", "Idle"][int(is_on_floor())])
if jump_meter >= 0.5:
$BasicEnemyMovement.bounce_on_land = true
$BasicEnemyMovement.move_speed = 30
jump_meter = 0
elif is_on_floor():
$BasicEnemyMovement.bounce_on_land = false
$BasicEnemyMovement.move_speed = 0
func stomped_on(player: Player) -> void:
AudioManager.play_sfx("enemy_stomp", global_position)
$BasicEnemyMovement.can_move = false
Global.combo_amount += 1
player.enemy_bounce_off()
$Sprite.play("Stomped")
$Hitbox.queue_free()
await get_tree().create_timer(0.5, false).timeout
queue_free()

View File

@@ -0,0 +1 @@
uid://cemetiu57dblq

View File

@@ -0,0 +1,37 @@
extends Enemy
var can_move := true
var angry := false
var can_turn := false
func _ready() -> void:
$Sprite.play("Walk")
func _physics_process(_delta: float) -> void:
if can_turn:
$Sprite.scale.x = direction
func stomped_on(player: Player) -> void:
AudioManager.play_sfx("enemy_stomp", global_position)
can_move = false
DiscoLevel.combo_amount += 1
$BasicEnemyMovement.can_move = false
player.enemy_bounce_off()
$Sprite.play("Stomped")
$Hitbox.queue_free()
await get_tree().create_timer(0.5, false).timeout
queue_free()
func damage(object: Node2D) -> void:
if angry:
die_from_object(object)
$ScoreNoteSpawner.spawn_note(200)
return
AudioManager.play_sfx("kick", global_position)
velocity.y = -150
direction = sign(global_position.x - object.global_position.x)
angry = true
$Sprite.play("Angry")
$BasicEnemyMovement.move_speed *= 2

View File

@@ -0,0 +1 @@
uid://dv18do583a3x0

View File

@@ -0,0 +1,93 @@
extends Enemy
var jumping := false
var jump_direction := 0
@export var auto_charge := false
var charging := false
var wall_jump := false
var target_player: Player = null
const HAMMER = preload("res://Scenes/Prefabs/Entities/Items/Hammer.tscn")
func _ready() -> void:
$MovementAnimations.play("Movement")
$Timer.start()
$JumpTimer.start()
$HammerTimer.start()
func _process(delta: float) -> void:
target_player = get_tree().get_first_node_in_group("Players")
direction = sign(target_player.global_position.x - global_position.x)
$Sprite.scale.x = direction
if $TrackJoint.is_attached: $MovementAnimations.play("RESET")
func _physics_process(delta: float) -> void:
apply_enemy_gravity(delta)
if charging and target_player != null:
if is_on_wall() and is_on_floor():
jump(true)
velocity.x = 50 * direction
else:
velocity.x = 0
move_and_slide()
handle_collision()
func handle_collision() -> void:
var can_pass_block := false
if jump_direction == -1:
can_pass_block = velocity.y < -50
elif jump_direction == 1:
can_pass_block = velocity.y <= 250
$Collision.set_deferred("disabled", can_pass_block and jumping and not wall_jump)
if is_on_floor() and jumping:
jumping = false
func jump(wall := false) -> void:
if is_on_floor() == false:
return
wall_jump = wall
jumping = true
jump_direction = [-1, 1].pick_random()
if jump_direction == -1 and $UpBlock.is_colliding() == false:
jump_direction = 1
if jump_direction == 1 and ($BlockDetect.is_colliding() or global_position.y >= -1):
jump_direction = -1
if jump_direction == -1:
velocity.y = -300
else:
velocity.y = -140
$JumpTimer.start(randf_range(1, 5))
func do_hammer_throw() -> void:
for i in randi_range(1, 6):
await throw_hammer()
await get_tree().create_timer(0.25, false).timeout
$HammerTimer.start(randf_range(2, 5))
func throw_hammer() -> void:
$Sprite/Hammer.show()
$Sprite.play("Hammer")
await get_tree().create_timer(0.5, false).timeout
spawn_hammer()
$Sprite.play("Idle")
$Sprite/Hammer.hide()
func spawn_hammer() -> void:
var node = HAMMER.instantiate()
node.global_position = $Sprite/Hammer.global_position
node.direction = direction
if $TrackJoint.is_attached:
get_parent().owner.add_sibling(node)
else:
add_sibling(node)
func charge() -> void:
charging = true
$MovementAnimations.play("RESET")
func on_screen_entered() -> void:
if auto_charge:
charge()

View File

@@ -0,0 +1 @@
uid://b8gdlotx0at6x

View File

@@ -0,0 +1,46 @@
class_name Icicle
extends Enemy
var falling := false
const ICICLE_DESTRUCTION = preload("res://Scenes/Parts/Particles/IcicleDestruction.tscn")
func _physics_process(delta: float) -> void:
if falling:
handle_movement(delta)
else:
detect_player()
func detect_player() -> void:
var shaking := false
for i in get_tree().get_nodes_in_group("Players"):
var distance = abs(i.global_position.x - global_position.x)
if i.global_position.y > global_position.y:
if distance <= 32:
fall()
elif distance <= 64:
shaking = true
if shaking:
$AnimationPlayer.play("Shake")
else:
$AnimationPlayer.play("RESET")
func handle_movement(delta: float) -> void:
apply_enemy_gravity(delta)
apply_enemy_gravity(delta / 2)
if is_on_floor():
destroy()
move_and_slide()
func destroy() -> void:
AudioManager.play_sfx("icicle_break", global_position)
summon_particles()
queue_free()
func summon_particles() -> void:
var node = ICICLE_DESTRUCTION.instantiate()
node.global_position = global_position - Vector2(0, 8)
add_sibling(node)
func fall() -> void:
AudioManager.play_sfx("icicle_fall", global_position)
falling = true

View File

@@ -0,0 +1 @@
uid://cx0ak5ctcg0mi

View File

@@ -0,0 +1,76 @@
extends Enemy
const MOVE_SPEED := 32
@export var winged := false
@export_file("*.tscn") var shell_scene = ""
@onready var starting_position := global_position
var fly_wave := PI
var dead := false
func _ready() -> void:
if has_meta("fly_2"):
fly_wave = 0
func _physics_process(delta: float) -> void:
if winged and (has_meta("is_red") or has_meta("fly_2")):
handle_fly_movement(delta)
else:
$BasicEnemyMovement.bounce_on_land = winged
$BasicEnemyMovement.handle_movement(delta)
$Sprite.play("Walk")
%Wing.visible = winged
$Sprite.scale.x = direction
func handle_fly_movement(delta: float) -> void:
velocity = Vector2.ZERO
fly_wave += delta
var old_x = global_position.x
if has_meta("fly_2"):
global_position.x = starting_position.x + (cos(fly_wave) * 48) - 48
global_position.y = starting_position.y + (sin(fly_wave * 4) * 2)
direction = sign(global_position.x - old_x + 0.001)
else:
global_position.y = starting_position.y + (cos(fly_wave) * 48) + 48
func stomped_on(player: Player) -> void:
if dead:
return
player.enemy_bounce_off()
AudioManager.play_sfx("enemy_stomp", global_position)
if winged:
DiscoLevel.combo_meter = 100
DiscoLevel.combo_amount += 1
velocity.y = 0
winged = false
var direction_to_change = sign(player.global_position.x - global_position.x)
if direction_to_change != 0:
direction = direction_to_change
return
dead = true
await get_tree().physics_frame
summon_shell(not is_on_floor(), false)
queue_free()
func block_bounced() -> void:
summon_shell(true, true)
queue_free()
func summon_shell(flipped := false, launch := false) -> void:
if is_queued_for_deletion():
return
DiscoLevel.combo_amount += 1
var shell = load(shell_scene).instantiate()
shell.flipped = flipped
shell.old_entity = self.duplicate()
if launch:
AudioManager.play_sfx("kick", global_position)
shell.can_air_kick = true
shell.velocity = Vector2(50 * direction, -150)
shell.global_position = global_position
if $TrackJoint.is_attached:
get_parent().owner.add_sibling(shell)
else:
add_sibling(shell)

View File

@@ -0,0 +1 @@
uid://q8gx0l64pcjh

View File

@@ -0,0 +1,97 @@
class_name Lakitu
extends Enemy
static var present := false:
set(value):
if value == true:
pass
present = value
var screen_center := Vector2.ZERO
var lakitu_point := Vector2.ZERO
const BLOCK_DISTANCE := 64
static var fixed_throw := true
var player: Player = null
var retreat := false
var can_enter := false
static var spiny_amount := 0
@export var item: PackedScene = null
@export var retreat_x := 3072
func _ready() -> void:
can_enter = false
$ThrowTimer.start()
lakitu_point = to_local(global_position)
fixed_throw = Settings.file.difficulty.lakitu_style == 1
get_parent().move_child(self, 0)
func _process(_delta: float) -> void:
screen_center = get_viewport().get_camera_2d().get_screen_center_position()
func _physics_process(delta: float) -> void:
player = get_tree().get_first_node_in_group("Players")
handle_movement(delta)
func handle_movement(_delta: float) -> void:
retreat = get_viewport().get_camera_2d().get_screen_center_position().x >= retreat_x
var player_x = player.global_position.x + ((player.velocity.x))
var distance = abs(global_position.x - player_x)
get_direction(player_x)
if direction == 1:
velocity.x = int(clamp((distance - 16) * 2, 48, INF))
else:
velocity.x = -48
$Cloud.scale.x = direction
move_and_slide()
func get_direction(player_x := 0.0) -> void:
if retreat:
present = false
direction = -1
return
if direction == -1 and global_position.x < player_x - BLOCK_DISTANCE:
direction = 1
elif direction == 1 and global_position.x > player_x + BLOCK_DISTANCE:
direction = -1
func summon_cloud_particle() -> void:
var node = preload("res://Scenes/Prefabs/Particles/LakituCloudBurst.tscn").instantiate()
node.global_position = $Cloud.global_position
add_sibling(node)
func on_timeout() -> void:
if spiny_amount >= 3 or retreat or $WallCheck.is_colliding():
return
$Cloud/Sprite.play("Throw")
await get_tree().create_timer(0.5, false).timeout
if $WallCheck.is_colliding() == false:
throw_spiny()
$Cloud/Sprite.play("Idle")
func throw_spiny() -> void:
var node = item.instantiate()
spiny_amount += 1
node.set("in_egg", true)
node.global_position = $Cloud/Sprite.global_position
node.velocity = Vector2(0, -150)
if fixed_throw:
node.velocity.x = 50 * (sign(player.global_position.x - global_position.x))
node.set("direction", sign(node.velocity.x))
add_sibling(node)
if Settings.file.audio.extra_sfx == 1:
AudioManager.play_sfx("lakitu_throw", global_position)
node.tree_exited.connect(func(): spiny_amount -= 1)
func on_screen_entered() -> void:
if Global.level_editor != null:
if Global.level_editor.playing_level == false:
return
add_to_group("Lakitus")
if get_tree().get_node_count_in_group("Lakitus") >= 2:
queue_free()

View File

@@ -0,0 +1 @@
uid://bohpv3almqrvg

View File

@@ -0,0 +1,27 @@
extends Enemy
func _ready() -> void:
direction = sign(get_viewport().get_camera_2d().get_screen_center_position().x - global_position.x)
velocity.x = randf_range(50, 200) * direction
velocity.y = randf_range(-250, -350)
$Sprite.scale.x = direction
setup_line()
if Settings.file.audio.extra_sfx == 1:
AudioManager.play_sfx("cheep_cheep", global_position)
func setup_line() -> void:
$Line2D.clear_points()
var line_velocity = velocity
var line_position = $Sprite.global_position
for i in 200:
line_position += line_velocity * 0.016
line_velocity.y += (5 / 0.016) * 0.016
$Line2D.add_point(line_position)
func _physics_process(delta: float) -> void:
velocity.y += (5 / delta) * delta
$Line2D.remove_point(0)
if global_position.y > 64 and velocity.y > 0:
queue_free()
move_and_slide()

View File

@@ -0,0 +1 @@
uid://mshpvsyuw15j

View File

@@ -0,0 +1,20 @@
extends Enemy
var target_player: Player = null
const MOVE_SPEED := 100.0
const ACCEL := 1.0
func _physics_process(delta: float) -> void:
target_player = get_tree().get_first_node_in_group("Players")
direction = sign(target_player.global_position.x - global_position.x)
$Sprite.scale.x = direction
handle_movement(delta)
func handle_movement(delta: float) -> void:
apply_enemy_gravity(delta)
if is_on_wall():
velocity.x = (MOVE_SPEED / 2) * get_wall_normal().x
velocity.y = -100
velocity.x = lerpf(velocity.x, MOVE_SPEED * direction, delta * ACCEL)
move_and_slide()

View File

@@ -0,0 +1 @@
uid://dw05x347cr8jj

View File

@@ -0,0 +1,17 @@
extends Enemy
@export var player_range := 24
func _enter_tree() -> void:
$Animation.play("Hide")
func _ready() -> void:
print(abs(global_rotation_degrees))
if is_equal_approx(abs(global_rotation_degrees), 180) == false:
$Sprite/Hitbox/UpsideDownExtension.queue_free()
$Timer.start()
func on_timeout() -> void:
var player = get_tree().get_first_node_in_group("Players")
if abs(player.global_position.x - global_position.x) >= player_range:
$Animation.play("Rise")

View File

@@ -0,0 +1 @@
uid://d23hoj2qc2whq

View File

@@ -0,0 +1,55 @@
extends Node2D
var velocity := 5.0
var play_sfx := false
@onready var starting_y := global_position.y
@export_range(0, 3) var jump_delay := 1
var can_jump := true
signal killed
const BASE_LINE := 48
func _ready() -> void:
if Global.current_game_mode != Global.GameMode.LEVEL_EDITOR and global_position.y > -32:
Global.log_warning("Podoboo is too low! Forgot to update!")
func _physics_process(delta: float) -> void:
velocity += (5 / delta) * delta
velocity = clamp(velocity, -INF, 280)
global_position.y += velocity * delta
global_position.y = clamp(global_position.y, -INF, BASE_LINE)
if global_position.y >= BASE_LINE and can_jump:
can_jump = false
do_jump()
$Sprite.flip_v = velocity > 0
func do_jump() -> void:
if jump_delay > 0:
$Timer.start(jump_delay)
await $Timer.timeout
if play_sfx:
AudioManager.play_sfx("podoboo", global_position)
velocity = calculate_jump_height()
print(velocity)
await get_tree().physics_frame
can_jump = true
func damage_player(player: Player) -> void:
player.damage()
func calculate_jump_height() -> float:
global_position.y = BASE_LINE
return -sqrt(2 * 5 * abs(starting_y - (global_position.y))) * 8
const SMOKE_PARTICLE = preload("uid://d08nv4qtfouv1")
func flag_die() -> void:
die()
func die() -> void:
killed.emit()
queue_free()

View File

@@ -0,0 +1 @@
uid://bha5utvbhxppl

View File

@@ -0,0 +1,26 @@
extends Enemy
@export_range(1, 10, 1) var length := 3
var wave := 0.0
func _physics_process(delta: float) -> void:
handle_collision()
handle_part_animation(delta)
func handle_collision() -> void:
$HeadHitbox.position.y = (-length * 16) + 8
$Collision.shape.size.y = (length * 16)
$Collision.position.y = (-length * 8)
$BodyHitbox.position.y = $Collision.position.y
func handle_part_animation(delta: float) -> void:
wave += delta
for i in $Parts.get_children():
if i.get_index() > 0:
i.offset.x = sin(wave * 8) * 1 * [-1, 1][i.get_index() % 2]
func summon_part_gibs() -> void:
for i in $Parts.get_children():
if i.visible:
i.get_node("GibSpawner").summon_gib([-1, 1][i.get_index() % 2])

View File

@@ -0,0 +1 @@
uid://b1b6aiai213ci

View File

@@ -0,0 +1,71 @@
extends Node2D
var moving := false
@export var path: PathFollow2D = null
@export var time_needed := [60, 45, 30]
const COLOURS := ["White", "Green", "Red", "Black", "Gold"]
var last_position := global_position
var tween: Tween = null
@export var force_colour := -1
func play_laugh_animation() -> void:
if get_tree().get_nodes_in_group("BooSwitchBlocks").is_empty() == false:
$Warning.show()
$Sprite.play("Laugh")
await get_tree().create_timer(1, false).timeout
$Warning.hide()
if moving:
$Sprite.play("Idle")
func _ready() -> void:
if force_colour != -1:
BooRaceHandler.boo_colour = force_colour
$Sprite.play("Lose")
$OffScreenIcon.frame = BooRaceHandler.boo_colour
$GoldParticles.visible = BooRaceHandler.boo_colour == 4
get_tree().get_first_node_in_group("Players").dead.connect(func(): $Sprite.play("Win"))
func _process(_delta: float) -> void:
if Global.current_game_mode == Global.GameMode.BOO_RACE:
handle_off_screen_icon()
func handle_off_screen_icon() -> void:
$OffScreenIcon.visible = $Sprite/VisibleOnScreenNotifier2D.is_on_screen() == false and moving
var sprite_position = $Sprite.global_position
var screen_center = get_viewport().get_camera_2d().get_screen_center_position()
var screen_size = get_viewport().get_visible_rect().size
sprite_position.x = clamp(sprite_position.x, (screen_center.x - (screen_size.x / 2)) + 8, (screen_center.x + (screen_size.x / 2)) - 8)
sprite_position.y = clamp(sprite_position.y, (screen_center.y - (screen_size.y / 2)) + 8, (screen_center.y + (screen_size.y / 2)) - 8)
$OffScreenIcon.global_position = sprite_position
if global_position.x > get_tree().get_first_node_in_group("Players").global_position.x and path.progress_ratio >= 0.8:
$OffScreenIcon/Animation.play("CloseFlash")
$Sprite.play("Win")
func _physics_process(_delta: float) -> void:
var dir = sign(global_position.x - last_position.x)
if moving and dir != 0:
$Sprite.scale.x = dir
last_position = global_position
func flag_die() -> void:
tween.kill()
$Sprite.play("Lose")
moving = false
func move_tween() -> void:
if path == null:
return
moving = true
$Sprite.play("Idle")
tween = create_tween()
tween.tween_property(path, "progress_ratio", 1, time_needed[BooRaceHandler.boo_colour])
await tween.finished
boo_win()
func boo_win() -> void:
$Sprite.play("Win")
get_tree().call_group("Players", "time_up")

View File

@@ -0,0 +1 @@
uid://b43onpjaw542l

View File

@@ -0,0 +1,35 @@
extends Enemy
@export var can_stomp := false
const WRENCH_PROJECTILE = preload("uid://p42vcj0qmhxl")
var count := 0
func _ready() -> void:
$Timer.start()
func on_player_stomped_on(player: Player) -> void:
if can_stomp:
$GibSpawner.stomp_die(player)
func on_timeout() -> void:
if is_on_floor() == false:
return
direction = sign(get_tree().get_first_node_in_group("Players").global_position.x - global_position.x + 1)
$Sprite.scale.x = direction
if count == 0:
$Animations.play("PeekOut")
$Sprite.play("Idle")
else:
count = -1
$Sprite.play("Aim")
$Animations.play("Throw")
await $Animations.animation_finished
$Timer.start()
count += 1
func throw_wrench() -> void:
$Sprite.play("Throw")
var node = WRENCH_PROJECTILE.instantiate()
node.global_position = $Sprite/Wrench.global_position
node.direction = direction
add_sibling(node)

View File

@@ -0,0 +1 @@
uid://bfsh8bhcmknkh

View File

@@ -0,0 +1,39 @@
extends Enemy
const SPIKE_BALL = preload("uid://c7il83r4ab05d")
@export var can_move := false
func _ready() -> void:
$ThrowTimer.start()
if can_move:
$TurnTimer.start()
func _physics_process(delta: float) -> void:
if can_move:
$Movement.handle_movement(delta)
else:
$StaticMovement.handle_movement(delta)
var target_player = get_tree().get_first_node_in_group("Players")
var target_direction = sign(target_player.global_position.x - global_position.x)
if target_direction != 0:
direction = target_direction
func throw_ball() -> void:
$Movement.can_move = false
%Animations.play("BallSpawn")
await %Animations.animation_finished
summon_ball()
%Animations.play("Idle")
$Movement.can_move = true
func summon_ball() -> void:
var ball = SPIKE_BALL.instantiate()
ball.global_position = %Ball.global_position
add_sibling(ball)
ball.velocity.x = 100 * direction
func on_timeout() -> void:
if not $Movement.can_move: return
var target_player = get_tree().get_first_node_in_group("Players")
direction = sign(target_player.global_position.x - global_position.x)

View File

@@ -0,0 +1 @@
uid://4isgtypd8yqc

View File

@@ -0,0 +1,20 @@
extends Enemy
var in_egg := false
const MOVE_SPEED := 40
func _physics_process(delta: float) -> void:
handle_movement(delta)
func handle_movement(_delta: float) -> void:
if in_egg:
if is_on_floor():
var player = get_tree().get_first_node_in_group("Players")
direction = sign(player.global_position.x - global_position.x)
in_egg = false
$Sprite.play("Egg")
else:
$Sprite.play("Walk")
$Sprite.scale.x = direction

View File

@@ -0,0 +1 @@
uid://bds7rntb0btee

View File

@@ -0,0 +1,19 @@
extends Enemy
@export var move_speed := 20
@export_enum ("Straight", "Wavey", "Random") var movement_type := 2
func _ready() -> void:
if movement_type == 2:
if [0, 1].pick_random() == 1:
$WaveAnimations.play("Wave")
else:
$WaveAnimations.play("RESET")
elif movement_type == 1:
$WaveAnimations.play("Wave")
else:
$WaveAnimations.play("RESET")
func _physics_process(delta: float) -> void:
global_position.x += (move_speed * direction) * delta

View File

@@ -0,0 +1 @@
uid://b475vfhcp2f30

View File

@@ -0,0 +1,65 @@
class_name Thwomp
extends Enemy
enum States{IDLE, FALLING, LANDED, RISING}
var current_state := States.IDLE
@onready var starting_y := global_position.y
var can_fall := true
func _physics_process(delta: float) -> void:
velocity.x = move_toward(velocity.x, 0, 20)
match current_state:
States.IDLE:
handle_idle(delta)
States.FALLING:
handle_falling(delta)
States.RISING:
handle_rising(delta)
_:
pass
move_and_slide()
func handle_idle(delta: float) -> void:
var target_player = get_tree().get_first_node_in_group("Players")
var x_distance = abs(target_player.global_position.x - global_position.x)
velocity = Vector2.ZERO
if x_distance < 24 and can_fall:
can_fall = false
current_state = States.FALLING
$TrackJoint.detach()
elif x_distance < 48:
%Sprite.play("Look")
else:
%Sprite.play("Idle")
func handle_falling(delta: float) -> void:
%Sprite.play("Fall")
velocity.y += (15 / delta) * delta
velocity.y = clamp(velocity.y, -INF, Global.entity_max_fall_speed)
handle_block_breaking()
if is_on_floor():
land()
func handle_block_breaking() -> void:
for i in %BlockBreakingHitbox.get_overlapping_bodies():
if i is Block and i.get("destructable") == true:
i.destroy()
func land() -> void:
AudioManager.play_sfx("cannon", global_position)
current_state = States.LANDED
await get_tree().create_timer(1, false).timeout
current_state = States.RISING
func handle_rising(delta: float) -> void:
velocity.y = -50
%Sprite.play("Idle")
if global_position.y <= starting_y:
global_position.y = starting_y
if global_position.y <= starting_y or is_on_ceiling():
current_state = States.IDLE
await get_tree().create_timer(0.5, false).timeout
can_fall = true

View File

@@ -0,0 +1 @@
uid://bxfc7hxw13s6q