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>
88 lines
3.2 KiB
GDScript
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)
|