extends Node signal new_quest var quests = [] func save(): var data = [] for k in quests: data.push_back(k.save()) global.save_data.quests = data func restore_quest(d): var q = Quest.new(d.title, d.desc) func restore(): for k in global.save_data.quests: quests.push_back(restore_quest(k)) var quest_triggers = [ { "title": "Something is not right.", "desc": "You wake up from noise. Explore the building to find the source.", "trigger": ["once", 0, 0, 10], "objectives": [ ["walkto_room", "Check enterance.", "Check enterance room.", "exit_room", 8.0] ] } ] class QuestObjective extends Reference: var _title var _desc var quest var complete = false var active = false func update(): pass func activate(): active = true func finish(): active = false func set_quest(q): quest = q func _init(title, desc): _title = title _desc = desc func save(): var save_data = {} save_data.create = ["obj", _desc, _title] save_data.active = active save_data.complete = complete return save_data class Quest extends Reference: signal quest_complete var _title var _description var objectives = [] var children = [] var complete = false var cur_objective: int = -1 func _init(title, desc): _title = title _description = desc func add_objective(obj): objectives.push_back(obj) func remove_objective(obj): objectives.erase(obj) func add_child(obj): children.push_back(obj) func remove_child(obj: Quest): children.erase(obj) func save(): var save_data = {} save_data.title = _title save_data.desc = _description return save_data func update(): for k in children: k.update() for k in objectives: k.update() var old_objective:int = cur_objective complete = true for k in range(objectives.size()): if !objectives[k].complete: cur_objective = k complete = false break for k in children: if !k.complete: complete = false if complete: emit_signal("quest_complete", self) if cur_objective != old_objective: if old_objective >= 0: objectives[old_objective].finish() objectives[cur_objective].activate() func get_title(): return _title func get_description(): return _title class ObjectiveWalkto extends QuestObjective: var where = Vector3() var meta = "" var radius = 0.0 var indicator = preload("res://ui/quest_indicator.tscn") var ind_i: Node2D var old_pos = Vector3() func _init(t, d, w, r).(t, d): meta = w radius = r func activate(): active = true ind_i = indicator.instance() var player_pos: Vector3 = global.player.global_transform.origin var base = global.astar.get_closest_point(player_pos) var tgt = global.astar.get_closest_point(where) var path = global.astar.get_point_path(base, tgt) if path.size() > 1: ind_i.target = path[1] + Vector3(0, 1, 0) * 0.3 else: ind_i.target = where + Vector3(0, 1, 0) * 0.3 global.get_viewport().add_child(ind_i) print(_title, "ACTIVATED") old_pos = player_pos func finish(): active = false ind_i.queue_free() func update(): if !active: return var player_pos: Vector3 = global.player.global_transform.origin if old_pos.distance_to(player_pos) > 0.5: var base = global.astar.get_closest_point(player_pos) var tgt = global.astar.get_closest_point(where) var path = global.astar.get_point_path(base, tgt) if path.size() > 1: var ind = 0 var pt = path[ind] while ind < path.size() - 1: pt = path[ind] if pt.distance_to(player_pos) > 2.0: ind_i.target = pt + Vector3(0, 1, 0) * 0.3 break ind += 1 else: ind_i.target = where + Vector3(0, 1, 0) * 0.3 old_pos = player_pos func save(): var save_data = {} save_data.create = ["walkto_room", _title, _desc, meta, radius] save_data.active = active save_data.complete = complete return save_data func _ready(): pass func check_trigger(t): var t_type = t[0] match(t_type): "once": var t_day = t[1] var t_hour = t[2] var t_minute = t[3] if global.game_day != t_day: return false if global.game_hour != t_hour: return false if int(global.game_minute / 10) != int(t_minute / 10): return false return true return false func create_objective(v): var o_type = v[0] match(o_type): "walkto_room": var o_title = v[1] var o_desc = v[2] var o_meta = v[3] var o_radius = v[4] var obj = ObjectiveWalkto.new(o_title, o_desc, o_meta, o_radius) return obj return null var up_time = 0.0 var state: int = 0 func _process(delta): up_time += delta if up_time > 1000.0: up_time = 0.0 if int(up_time * 10.0) % 10 == 1: var processed = [] while quest_triggers.size() > 0: var k = quest_triggers.pop_front() if check_trigger(k.trigger): print("quest triggered: ", k.title) var q = Quest.new(k.title, k.desc) quests.push_back(q) for r in k.objectives: var obj = create_objective(r) if obj: q.add_objective(obj) emit_signal("new_quest", q) else: processed.push_back(k) quest_triggers = processed for k in quests: k.update()