Explosion_der_Spiele/scripts/levels/dressler_boss.gd
copilot 1cc8aa9b9d Add village 3D wiring, voice lines, and 1.74 m world scale.
Houses ~8.5 m; chimps capped ~0.85 m with safer axis fitting. Large GLB/PBR packs stay local until Git LFS (Forgejo HTTP 413).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 12:02:57 +02:00

88 lines
3.2 KiB
GDScript

extends Node3D
## Dresslermeister: Augen auf, Mähdrescher hijacken, Apfel dreschen (DESIGN.md §10).
var _hijacked: int = 0
var _eyes_open: bool = false
func _ready() -> void:
GameState.current_scene_id = "dressler_boss"
GameState.heal_full()
var dressler := get_node_or_null("Dressler")
if dressler:
dressler.set("ai_enabled", false) # sleeps until eyes open
dressler.set("max_hp", 18)
dressler.set("hp", 18)
dressler.set("billboard_height", SpriteFit.WORLD_BOSS_HEIGHT)
dressler.set("death_cause_key", "death_mower")
if dressler.has_signal("defeated"):
dressler.defeated.connect(_on_dressler_defeated)
var ui := get_node_or_null("/root/UIRoot")
if ui and ui.has_method("show_dialog"):
ui.show_dialog("Ein riesiger Apfel auf dem Feld…", 2.5)
for name in ["Mower1", "Mower2", "Mower3"]:
var m := get_node_or_null(name)
if m:
_make_hijackable(m)
func _physics_process(delta: float) -> void:
_try_open_eyes()
if Input.is_action_just_pressed("interact") or Input.is_action_just_pressed("attack"):
_try_hijack()
# Moving mowers slowly toward player if not hijacked
var player := get_tree().get_first_node_in_group("player")
if player is Node3D:
for mower in get_tree().get_nodes_in_group("hijackable_mower"):
if mower is Node3D and not bool(mower.get_meta("hijacked", false)):
var to_p: Vector3 = (player as Node3D).global_position - mower.global_position
to_p.y = 0.0
if to_p.length() > 0.2:
mower.global_position += to_p.normalized() * 1.6 * delta
func _try_open_eyes() -> void:
if _eyes_open:
return
var player := get_tree().get_first_node_in_group("player")
var dressler := get_node_or_null("Dressler")
if player is Node3D and dressler is Node3D:
if player.global_position.distance_to(dressler.global_position) < 6.0:
_eyes_open = true
dressler.set("ai_enabled", true)
dressler.set("move_speed", 1.2)
dressler.set("attack_damage", 1)
dressler.set("shout_key", "dialog_dressler")
dressler.set("shout_interval", 6.0)
var ui := get_node_or_null("/root/UIRoot")
if ui and ui.has_method("show_dialog"):
ui.show_dialog_key("dialog_dressler", 3.0)
func _make_hijackable(mower: Node) -> void:
mower.set_meta("hijacked", false)
mower.add_to_group("hijackable_mower")
func _try_hijack() -> void:
var player := get_tree().get_first_node_in_group("player")
if player == null:
return
for mower in get_tree().get_nodes_in_group("hijackable_mower"):
if mower is Node3D and player.global_position.distance_to(mower.global_position) <= 2.5:
if bool(mower.get_meta("hijacked", false)):
continue
mower.set_meta("hijacked", true)
_hijacked += 1
if mower is Area3D:
(mower as Area3D).monitoring = false
var ui := get_node_or_null("/root/UIRoot")
if ui and ui.has_method("show_dialog"):
ui.show_dialog("Fahrer rausgeworfen! Dresche den Apfel! (%d)" % _hijacked)
var dressler := get_node_or_null("Dressler")
if dressler and dressler.has_method("take_hit"):
dressler.take_hit(4)
return
func _on_dressler_defeated() -> void:
Achievements.unlock("dressler_apples")
Inventory.add_item("dressler_apple", 1)
var ui := get_node_or_null("/root/UIRoot")
if ui and ui.has_method("show_dialog"):
ui.show_dialog_key("dialog_dressler_drop", 4.0)
GameState.set_flag("dressler_defeated", true)