Implemented simple quest system
This commit is contained in:
@@ -1,11 +1,51 @@
|
||||
extends Node
|
||||
signal new_day
|
||||
|
||||
var raycasts_count = 100
|
||||
var raycast_queue = []
|
||||
var astar: AStar
|
||||
|
||||
func _ready():
|
||||
set_save_slot(0)
|
||||
|
||||
enum periods {MORNING, DAY, EVENING, NIGHT}
|
||||
var game_day: int = 0
|
||||
var day_period: int = periods.MORNING
|
||||
var game_hour: int = 0
|
||||
var game_minute: int = 0
|
||||
|
||||
var acc_time:float = 0.0
|
||||
var time_active = false
|
||||
|
||||
func _process(delta):
|
||||
if time_active:
|
||||
update_time(delta)
|
||||
|
||||
func update_time(delta):
|
||||
acc_time += delta
|
||||
if acc_time >= 1.0:
|
||||
game_minute += 1
|
||||
acc_time -= 1.0
|
||||
if game_minute == 60:
|
||||
game_minute = 0
|
||||
game_hour += 1
|
||||
if game_hour == 24:
|
||||
game_hour = 0
|
||||
game_day += 1
|
||||
match(game_hour):
|
||||
23,0,1,2,3:
|
||||
day_period = periods.NIGHT
|
||||
4,5,6,7,8,9,10,11:
|
||||
day_period = periods.MORNING
|
||||
12,13,14,15,16:
|
||||
day_period = periods.DAY
|
||||
17,18,19,20,21,22:
|
||||
day_period = periods.EVENING
|
||||
func start_time():
|
||||
time_active = true
|
||||
func stop_time():
|
||||
time_active = false
|
||||
|
||||
func visibility_check(ch1, ch2):
|
||||
var direction: Vector3 = -ch1.global_transform.basis[2].normalized()
|
||||
var to_ch2: Vector3 = (ch2.global_transform.origin - ch1.global_transform.origin).normalized()
|
||||
@@ -38,6 +78,10 @@ func save_characters():
|
||||
spawner.set_meta("stats", stats)
|
||||
|
||||
func save_game():
|
||||
print("save game")
|
||||
save_data.game_day = game_day
|
||||
save_data.game_hour = game_hour
|
||||
save_data.day_period = day_period
|
||||
assert(save_slot.length() > 0)
|
||||
var fd = File.new()
|
||||
fd.open(save_slot, File.WRITE)
|
||||
@@ -51,4 +95,7 @@ func load_game():
|
||||
var data = fd.get_as_text()
|
||||
var parse: = JSON.parse(data)
|
||||
save_data = parse.result
|
||||
game_day = save_data.game_day
|
||||
game_hour = save_data.game_hour
|
||||
day_period = save_data.day_period
|
||||
fd.close()
|
||||
|
||||
213
proto3/godot/autoloads/quests.gd
Normal file
213
proto3/godot/autoloads/quests.gd
Normal file
@@ -0,0 +1,213 @@
|
||||
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()
|
||||
|
||||
22
proto3/godot/autoloads/world.gd
Normal file
22
proto3/godot/autoloads/world.gd
Normal file
@@ -0,0 +1,22 @@
|
||||
extends Node
|
||||
signal level_up
|
||||
signal new_quest
|
||||
|
||||
var money: int = 2000
|
||||
var master_node
|
||||
var current_room
|
||||
var team = {}
|
||||
var line = {}
|
||||
var training = false
|
||||
# warning-ignore:unused_class_variable
|
||||
var quests : = []
|
||||
# warning-ignore:unused_class_variable
|
||||
var team_train_count : = 0
|
||||
# warning-ignore:unused_class_variable
|
||||
var arrow: Spatial
|
||||
# warning-ignore:unused_class_variable
|
||||
var next_scene: String
|
||||
var player_visual = {
|
||||
"gender": "male"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user