diff --git a/scripts/Enemy.gd b/scripts/Enemy.gd index bbf575b..4ad481c 100644 --- a/scripts/Enemy.gd +++ b/scripts/Enemy.gd @@ -29,6 +29,9 @@ var stun_time: float = 0.5 var base_scale: float = 1.0 var wave_num: int = 1 var damage_modifier: float = 0.75 +var enemy_kick_timer: float = 0.0 +const ENEMY_KICK_COOLDOWN := 1.2 +const ENEMY_KICK_RANGE := 2.2 var state: State = State.CHASING var fly_vel: Vector3 = Vector3.ZERO @@ -98,6 +101,7 @@ func _chase(delta: float) -> void: if not is_instance_valid(target): return contact_timer = max(0.0, contact_timer - delta) + enemy_kick_timer = max(0.0, enemy_kick_timer - delta) var diff := target.global_position - global_position diff.y = 0.0 var dist := diff.length() @@ -105,6 +109,8 @@ func _chase(delta: float) -> void: contact_timer = CONTACT_CD if target.has_method("take_damage"): target.take_damage(damage_to_player) + if tier > 0 and enemy_kick_timer <= 0.0: + _try_enemy_kick() if dist > 0.05: var dir := diff.normalized() dir = _avoid_rocks(dir) @@ -114,6 +120,38 @@ func _chase(delta: float) -> void: velocity.y = 0.0 move_and_slide() +func _try_enemy_kick() -> void: + var kicked := false + for node in get_tree().get_nodes_in_group("enemies"): + var en := node as Node3D + if en == null or en == self or not is_instance_valid(en): + continue + var other_tier: int = en.get("tier") if en.get("tier") != null else 0 + if other_tier >= tier: + continue + var away := en.global_position - global_position + away.y = 0.0 + if away.length() > ENEMY_KICK_RANGE: + continue + var dir := away.normalized() + var player_pos := target.global_position if is_instance_valid(target) else global_position + var to_player := (player_pos - global_position) + to_player.y = 0.0 + if to_player.length() > 0.01: + dir = to_player.normalized() + en.call("receive_kick", dir, 40.0 + tier * 10.0) + kicked = true + if not kicked and is_instance_valid(target): + var to_player := target.global_position - global_position + to_player.y = 0.0 + if to_player.length() < ENEMY_KICK_RANGE: + var player_tier: int = target.get("tier") if target.get("tier") != null else 0 + if player_tier < tier: + target.call("receive_kick", to_player.normalized(), 35.0 + tier * 8.0) + kicked = true + if kicked: + enemy_kick_timer = ENEMY_KICK_COOLDOWN + const AVOID_RADIUS := 1.6 const AVOID_STRENGTH := 2.2 diff --git a/scripts/Player.gd b/scripts/Player.gd index 272d5bd..2672aa6 100644 --- a/scripts/Player.gd +++ b/scripts/Player.gd @@ -189,6 +189,13 @@ func _squish_effect() -> void: tw.tween_property(mesh_node, "scale", Vector3(1.3, 0.55, 1.3), 0.07) tw.tween_property(mesh_node, "scale", Vector3(1.0, 1.0, 1.0), 0.18) +func receive_kick(direction: Vector3, force: float) -> void: + if not is_alive or invincible_timer > 0.0: + return + velocity.x = direction.x * force + velocity.z = direction.z * force + invincible_timer = IFRAMES_DURATION * 0.5 + func take_damage(amount: int) -> void: if not is_alive or invincible_timer > 0.0: return