Wire all twelve levels with billboard prefabs, autoload systems (inventory, achievements, mock shop, DE/EN/BY), and satire audio locks so the Title→End flow is playable with placeholder assets.
43 lines
1.4 KiB
GDScript
43 lines
1.4 KiB
GDScript
extends Node3D
|
|
class_name InteractableNPC
|
|
## Billboard NPC with dialog key and optional quest hook.
|
|
|
|
signal interacted(npc: InteractableNPC)
|
|
|
|
@export var dialog_key: String = "dialog_hongkong_npc"
|
|
@export var texture_path: String = "res://assets/sprites/placeholders/npc.png"
|
|
@export var give_item_id: String = ""
|
|
@export var require_item_id: String = ""
|
|
@export var consume_required: bool = false
|
|
@export var quest_flag: String = ""
|
|
@export var achievement_id: String = ""
|
|
@export var on_success_goto: String = ""
|
|
|
|
@onready var _billboard: BillboardSprite = $BillboardSprite
|
|
|
|
func _ready() -> void:
|
|
add_to_group("interactable")
|
|
if _billboard:
|
|
var tex: Texture2D = load(texture_path)
|
|
if tex:
|
|
_billboard.set_texture(tex)
|
|
|
|
func on_interact(_player: Node) -> void:
|
|
interacted.emit(self)
|
|
var ui := get_node_or_null("/root/UIRoot")
|
|
if ui and ui.has_method("show_dialog"):
|
|
ui.show_dialog(Locale.tr_key(dialog_key))
|
|
if require_item_id != "" and not Inventory.has_item(require_item_id):
|
|
return
|
|
if require_item_id != "" and consume_required:
|
|
Inventory.remove_item(require_item_id, 1)
|
|
if give_item_id != "":
|
|
Inventory.add_item(give_item_id, 1)
|
|
if quest_flag != "":
|
|
GameState.set_flag(quest_flag, true)
|
|
if quest_flag == "house_built":
|
|
GameState.house_built = true
|
|
if achievement_id != "":
|
|
Achievements.unlock(achievement_id)
|
|
if on_success_goto != "":
|
|
GameState.goto_scene(on_success_goto)
|