Moved everything into a file system. Links broken.
This commit is contained in:
74
scripts/adventurer.gd
Normal file
74
scripts/adventurer.gd
Normal file
@@ -0,0 +1,74 @@
|
||||
class_name Adventurer extends Npc
|
||||
|
||||
func _ready() -> void:
|
||||
nav_agent.navigation_finished.connect(_on_nav_agent_finished)
|
||||
pass
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if nav_agent.is_navigation_finished():
|
||||
if interaction_target:
|
||||
try_interact(interaction_target)
|
||||
#If they have an interaction target within range
|
||||
#clear the target
|
||||
#try_interact
|
||||
return
|
||||
var curr_pos: Vector2 = global_position
|
||||
var next_path_pos: Vector2 = nav_agent.get_next_path_position()
|
||||
|
||||
velocity = curr_pos.direction_to(next_path_pos) * movement_speed
|
||||
move_and_slide()
|
||||
#If they virtually didn't move
|
||||
if !stuck:
|
||||
if (global_position - last_position).length_squared() < 5:
|
||||
stuck = true
|
||||
stuck_time_remaining = 1
|
||||
else:
|
||||
if stuck_time_remaining > 0:
|
||||
stuck_time_remaining -= delta
|
||||
if stuck_time_remaining <= 0:
|
||||
nav_agent.target_position = global_position
|
||||
navigation_failed.emit()
|
||||
last_position = global_position
|
||||
|
||||
func approach(pos : Vector2) -> void:
|
||||
stuck = false
|
||||
var rid = get_world_2d().get_navigation_map()
|
||||
var point : Vector2 = NavigationServer2D.map_get_closest_point(rid, pos)
|
||||
set_movement_target(point)
|
||||
|
||||
func approach_and_interact(obj : Interactable) -> void:
|
||||
set_movement_target(obj.global_position)
|
||||
nav_agent.target_desired_distance = interaction_range - 5
|
||||
interaction_target = obj
|
||||
|
||||
func try_interact(obj : Interactable) -> void:
|
||||
var df = obj.global_position - global_position
|
||||
if df.length() > interaction_range:
|
||||
approach_and_interact(obj)
|
||||
else:
|
||||
interact(obj)
|
||||
interaction_target = null
|
||||
|
||||
func interact(obj : Interactable) -> void:
|
||||
obj.interact(self)
|
||||
|
||||
func set_movement_target(target : Vector2) -> void:
|
||||
nav_agent.target_position = target
|
||||
|
||||
func show_speech_bubble(bubble_type : String) -> void:
|
||||
bubble.try_show_speech(bubble_type)
|
||||
|
||||
|
||||
|
||||
func _on_nav_agent_finished() -> void:
|
||||
navigation_finished.emit()
|
||||
|
||||
|
||||
func _on_mouse_entered() -> void:
|
||||
profile_popup = popup_template.instantiate()
|
||||
add_child(profile_popup)
|
||||
profile_popup.setup(data.name, data.level, data.job.name, activity)
|
||||
|
||||
|
||||
func _on_mouse_exited() -> void:
|
||||
profile_popup.queue_free()
|
||||
1
scripts/adventurer.gd.uid
Normal file
1
scripts/adventurer.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cjqumk0kw2vte
|
||||
60
scripts/adventurer_data.gd
Normal file
60
scripts/adventurer_data.gd
Normal file
@@ -0,0 +1,60 @@
|
||||
class_name AdventurerData extends Node
|
||||
|
||||
class StatBlock:
|
||||
var STR : int = 1
|
||||
var DEX : int = 1
|
||||
var INT : int = 1
|
||||
var CHA : int = 1
|
||||
var FAI : int = 1
|
||||
var LUK : int = 1
|
||||
|
||||
enum Gender{
|
||||
MASC,
|
||||
FEMME,
|
||||
NONBINARY
|
||||
}
|
||||
|
||||
var given_name : String = "Test"
|
||||
var surname : String = "Testing"
|
||||
var gender : Gender = Gender.MASC
|
||||
var life : int = 1
|
||||
var max_life : int = 1
|
||||
var energy : int = 1
|
||||
var max_energy : int = 1
|
||||
var level : int = 1
|
||||
var exp : int = 0
|
||||
var job : JobData
|
||||
var stats : StatBlock
|
||||
var gold : int = 0
|
||||
var quest : Quest
|
||||
|
||||
func _init() -> void:
|
||||
stats = StatBlock.new()
|
||||
|
||||
func generate() -> void:
|
||||
if job == null:
|
||||
return
|
||||
stats.STR = randi_range(job.min_STR, job.max_STR)
|
||||
stats.DEX = randi_range(job.min_DEX, job.max_DEX)
|
||||
stats.INT = randi_range(job.min_INT, job.max_INT)
|
||||
stats.CHA = randi_range(job.min_CHA, job.max_CHA)
|
||||
stats.FAI = randi_range(job.min_FAI, job.max_FAI)
|
||||
stats.LUK = randi_range(job.min_LUK, job.max_LUK)
|
||||
|
||||
max_life = stats.STR * 10 + stats.CHA * 10
|
||||
max_energy = stats.INT * 10 + stats.FAI * 10
|
||||
life = max_life
|
||||
energy = max_energy
|
||||
|
||||
func assign_quest(quest : Quest) -> void:
|
||||
self.quest = quest
|
||||
quest.initiate(self)
|
||||
|
||||
func full_name() -> String:
|
||||
return given_name + " " + surname
|
||||
|
||||
func get_tnl() -> int:
|
||||
if job:
|
||||
return job.get_tnl(level)
|
||||
else:
|
||||
return level * 10
|
||||
1
scripts/adventurer_data.gd.uid
Normal file
1
scripts/adventurer_data.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://0jl2qbvtmsik
|
||||
10
scripts/end_shift_confirmation.gd
Normal file
10
scripts/end_shift_confirmation.gd
Normal file
@@ -0,0 +1,10 @@
|
||||
extends ConfirmationDialog
|
||||
|
||||
|
||||
func _on_confirmed() -> void:
|
||||
Game.end_shift()
|
||||
hide()
|
||||
|
||||
|
||||
func _on_canceled() -> void:
|
||||
hide()
|
||||
1
scripts/end_shift_confirmation.gd.uid
Normal file
1
scripts/end_shift_confirmation.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dopd01h4q2uu8
|
||||
22
scripts/endpoint.gd
Normal file
22
scripts/endpoint.gd
Normal file
@@ -0,0 +1,22 @@
|
||||
class_name Endpoint extends Control
|
||||
|
||||
@export var percent : float = 0
|
||||
var filled: bool
|
||||
var fill: bool :
|
||||
get:
|
||||
return filled
|
||||
set(value):
|
||||
if value != filled:
|
||||
set_fill(value)
|
||||
|
||||
|
||||
func set_fill(value : bool) -> void:
|
||||
filled = value
|
||||
if value:
|
||||
$Dot.visible = true
|
||||
$Fill.modulate = Color.SEA_GREEN
|
||||
else:
|
||||
$Dot.visible = false
|
||||
$Fill.modulate = Color.BLACK
|
||||
|
||||
|
||||
1
scripts/endpoint.gd.uid
Normal file
1
scripts/endpoint.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cf0pt0ty4uaas
|
||||
52
scripts/game_manager.gd
Normal file
52
scripts/game_manager.gd
Normal file
@@ -0,0 +1,52 @@
|
||||
extends Node
|
||||
|
||||
var player : Player = null
|
||||
var panel : GamePanel = null
|
||||
var quest_log : QuestLog = null
|
||||
var top_menu : TopMenu = null
|
||||
var active : bool = true
|
||||
var end_shift_confirmation : ConfirmationDialog
|
||||
var end_shift_confirm_template = preload("res://end_shift_confirmation.tscn")
|
||||
func _ready() -> void:
|
||||
DisplayServer.register_additional_output(self)
|
||||
end_shift_confirmation = end_shift_confirm_template.instantiate()
|
||||
add_child(end_shift_confirmation)
|
||||
#var file =FileAccess.open("res://name.txt",FileAccess.READ)
|
||||
#var text =file.get_line()
|
||||
#var nmnames = text.remove_chars(" ").split(",")
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if active and Input.is_action_just_pressed("switch modes"):
|
||||
confirm_end_shift()
|
||||
|
||||
func add_quest_progress_bar(quest : Quest) -> void:
|
||||
panel.add_quest_progress_bar(quest)
|
||||
|
||||
func confirm_end_shift() -> void:
|
||||
end_shift_confirmation.popup_centered()
|
||||
|
||||
func setup_visitor_ui(spawner: VisitorSpawner)-> void:
|
||||
if panel:
|
||||
panel.connect_visitor_spawner(spawner)
|
||||
|
||||
func end_shift() -> void:
|
||||
active = false
|
||||
panel.switch_panel(active)
|
||||
var window = get_window()
|
||||
window.mode = Window.MODE_WINDOWED
|
||||
var size = DisplayServer.screen_get_size()
|
||||
window.content_scale_size = Vector2i(345,500)
|
||||
var wsize = window.get_size_with_decorations()
|
||||
window.position = Vector2i(size.x - 345, 25)
|
||||
window.transparent = true
|
||||
window.transparent_bg = true
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_BORDERLESS, true)
|
||||
DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_TRANSPARENT, true)
|
||||
Guild.hall.process_mode = Node.PROCESS_MODE_DISABLED
|
||||
top_menu.hide()
|
||||
panel.get_parent().global_position = Vector2i(5,5)
|
||||
window.size = Vector2i(345,500)
|
||||
panel.populate_quest_bars()
|
||||
|
||||
func notice(msg : String, time : float = 1) -> void:
|
||||
panel.notice(msg, time)
|
||||
1
scripts/game_manager.gd.uid
Normal file
1
scripts/game_manager.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cr421faioc8cf
|
||||
48
scripts/generate_quest_dialog.gd
Normal file
48
scripts/generate_quest_dialog.gd
Normal file
@@ -0,0 +1,48 @@
|
||||
extends Control
|
||||
|
||||
|
||||
var quest : Quest
|
||||
|
||||
|
||||
func generate_quest() -> void:
|
||||
quest = Quest.new()
|
||||
quest.name = "A Test Quest"
|
||||
quest.location = "Nestor Woods"
|
||||
quest.difficulty = 1
|
||||
quest.length = 60
|
||||
quest.rewards = {"exp":100,"gold":1}
|
||||
|
||||
func update_quest_window() -> void:
|
||||
if quest:
|
||||
%NameField.text = quest.name
|
||||
match(quest.difficulty):
|
||||
1: %DifficultyField.text = "Trivial"
|
||||
%LocationField.text = quest.location
|
||||
#for reward in quest.rewards.:
|
||||
|
||||
func reset() -> void:
|
||||
quest = null
|
||||
%DifficultyOptions.select(0)
|
||||
%LocationOptions.select(0)
|
||||
#TODO: Clear bonus rewards
|
||||
|
||||
func _on_generate_button_pressed() -> void:
|
||||
generate_quest()
|
||||
update_quest_window()
|
||||
%GenerateQuest.hide()
|
||||
%PostQuest.show()
|
||||
|
||||
func _on_post_button_pressed() -> void:
|
||||
Guild.add_quest(quest)
|
||||
quest = null
|
||||
%GenerateQuest.show()
|
||||
%PostQuest.hide()
|
||||
hide()
|
||||
|
||||
func _on_post_back_button_pressed() -> void:
|
||||
%GenerateQuest.show()
|
||||
%PostQuest.hide()
|
||||
|
||||
func _on_generate_back_button_pressed() -> void:
|
||||
hide()
|
||||
reset()
|
||||
1
scripts/generate_quest_dialog.gd.uid
Normal file
1
scripts/generate_quest_dialog.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ep03avmd4jbc
|
||||
101
scripts/guild.gd
Normal file
101
scripts/guild.gd
Normal file
@@ -0,0 +1,101 @@
|
||||
extends Node
|
||||
|
||||
|
||||
const visitors = {
|
||||
"test": {
|
||||
"data":preload("res://test_adventurer.tscn"),
|
||||
"sprite":preload("res://test_adventurer_sprite.tscn")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var surnames : Array[String] = []
|
||||
var masc_names : Array[String] = []
|
||||
var femme_names : Array[String] = []
|
||||
|
||||
const job_list = [
|
||||
preload("res://data/jobs/farmer.tres"),
|
||||
preload("res://data/jobs/rookie.tres")
|
||||
]
|
||||
|
||||
var jobs : Dictionary[String, JobData] = {}
|
||||
|
||||
var members : Array[AdventurerData] = []
|
||||
var quests : Dictionary[Quest,bool] = {}
|
||||
var hall : Guildhall = null
|
||||
var visitor_spawner : VisitorSpawner = null
|
||||
var gold : int
|
||||
var level : int
|
||||
var reputation : int
|
||||
var rep_tnl : int
|
||||
var vault : Array = []
|
||||
|
||||
signal changed()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var file = FileAccess.open("res://data/names/surnames.txt", FileAccess.READ)
|
||||
while !file.eof_reached():
|
||||
var line = file.get_line().strip_edges()
|
||||
surnames.append(line)
|
||||
file.close()
|
||||
|
||||
file = FileAccess.open("res://data/names/masc_names.txt", FileAccess.READ)
|
||||
while !file.eof_reached():
|
||||
var line = file.get_line().strip_edges()
|
||||
masc_names.append(line)
|
||||
file.close()
|
||||
|
||||
file = FileAccess.open("res://data/names/femme_names.txt", FileAccess.READ)
|
||||
while !file.eof_reached():
|
||||
var line = file.get_line().strip_edges()
|
||||
femme_names.append(line)
|
||||
file.close()
|
||||
|
||||
for job : JobData in job_list:
|
||||
jobs[job.name] = job
|
||||
|
||||
func register_guild_member(member : AdventurerData, first : bool = false) -> void:
|
||||
members.append(member)
|
||||
Game.top_menu.add_member(member)
|
||||
changed.emit()
|
||||
if first:
|
||||
Game.notice("%s has joined the guild!" % member.name, 5)
|
||||
|
||||
func has_guild_member(member : AdventurerData) -> bool:
|
||||
if member == null:
|
||||
return false
|
||||
return members.has(member)
|
||||
|
||||
func add_quest(quest : Quest) -> void:
|
||||
quests[quest] = false
|
||||
Game.top_menu.add_quest(quest)
|
||||
#Game.quest_log.add_entry(quest)
|
||||
|
||||
func assign_quest(member : AdventurerData, quest : Quest) -> void:
|
||||
member.assign_quest(quest)
|
||||
quests[quest] = true #Mark it as active
|
||||
|
||||
func spawn_visitor(pos : Vector2) -> void:
|
||||
var data : AdventurerData = visitors["test"].data.instantiate()
|
||||
var sprite : Adventurer = visitors["test"].sprite.instantiate()
|
||||
var r = randf()
|
||||
if r > 0.8:
|
||||
data.gender = 2 #Nonbinary
|
||||
if randf() > 0.5:
|
||||
data.given_name = femme_names.pick_random()
|
||||
else:
|
||||
data.given_name = masc_names.pick_random()
|
||||
elif r > 0.4:
|
||||
data.gender = 1 #Female presenting
|
||||
data.given_name = femme_names.pick_random()
|
||||
else:
|
||||
data.gender = 0 #Male presenting
|
||||
data.given_name = masc_names.pick_random()
|
||||
data.surname = surnames.pick_random()
|
||||
data.name = data.given_name + " " + data.surname
|
||||
data.job = jobs["Farmer"]
|
||||
data.generate()
|
||||
sprite.data = data
|
||||
hall.add_sprite(sprite)
|
||||
sprite.global_position = pos
|
||||
1
scripts/guild.gd.uid
Normal file
1
scripts/guild.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c7ymru8doa4a8
|
||||
12
scripts/guild_employee.gd
Normal file
12
scripts/guild_employee.gd
Normal file
@@ -0,0 +1,12 @@
|
||||
class_name GuildEmployee extends Adventurer
|
||||
|
||||
@export var speech :String
|
||||
@onready var queue : GuildQueue = $Queue
|
||||
|
||||
signal service_provided()
|
||||
|
||||
func interact(interactor, type : String = "") -> void:
|
||||
if type == "register":
|
||||
Guild.register_guild_member(interactor.data, true)
|
||||
#interactor.advance_
|
||||
service_provided.emit()
|
||||
1
scripts/guild_employee.gd.uid
Normal file
1
scripts/guild_employee.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b2unuudq5qfl
|
||||
26
scripts/guild_information_window.gd
Normal file
26
scripts/guild_information_window.gd
Normal file
@@ -0,0 +1,26 @@
|
||||
extends Window
|
||||
|
||||
@onready var levelLabel : Label = %LevelLabel
|
||||
@onready var reputationLabel : Label = %ReputationLabel
|
||||
@onready var membersLabel : Label = %MembersLabel
|
||||
@onready var goldLabel : Label = %GoldLabel
|
||||
|
||||
func _ready() -> void:
|
||||
refresh()
|
||||
Guild.changed.connect(_on_guild_change)
|
||||
|
||||
func refresh() -> void:
|
||||
levelLabel.text = str(Guild.level)
|
||||
reputationLabel.text = "%d (%d to next level)" % [Guild.reputation, Guild.rep_tnl]
|
||||
membersLabel.text = str(len(Guild.members))
|
||||
goldLabel.text = str(Guild.gold)
|
||||
|
||||
func _on_guild_change() -> void:
|
||||
refresh()
|
||||
|
||||
func _on_close_requested() -> void:
|
||||
queue_free()
|
||||
|
||||
|
||||
func _on_focus_exited() -> void:
|
||||
queue_free()
|
||||
1
scripts/guild_information_window.gd.uid
Normal file
1
scripts/guild_information_window.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dj5e81dgkpww8
|
||||
42
scripts/guild_queue.gd
Normal file
42
scripts/guild_queue.gd
Normal file
@@ -0,0 +1,42 @@
|
||||
class_name GuildQueue extends Node2D
|
||||
|
||||
var length : int :
|
||||
get:
|
||||
return len(members)
|
||||
@export var direction : Vector2 = Vector2.ZERO
|
||||
var members : Array[Adventurer] = []
|
||||
|
||||
var front : Adventurer :
|
||||
get: return null if len(members) == 0 else members[0]
|
||||
|
||||
signal advanced()
|
||||
|
||||
func add_member(member : Adventurer) -> void:
|
||||
members.append(member)
|
||||
|
||||
func remove_member(member : Adventurer) -> void:
|
||||
members.erase(member)
|
||||
|
||||
|
||||
func try_advance() -> Adventurer:
|
||||
if length > 0:
|
||||
return advance()
|
||||
else:
|
||||
return null
|
||||
|
||||
func advance() -> Adventurer:
|
||||
advanced.emit()
|
||||
return front
|
||||
|
||||
func get_last_position() -> Vector2:
|
||||
return get_index_position(length - 1)
|
||||
|
||||
func get_index_position(idx : int) -> Vector2:
|
||||
return global_position + idx * 100 * direction
|
||||
|
||||
func get_member_position(member) -> Vector2:
|
||||
var idx = members.find(member)
|
||||
if idx == -1:
|
||||
return Vector2.ZERO
|
||||
else:
|
||||
return get_index_position(idx)
|
||||
1
scripts/guild_queue.gd.uid
Normal file
1
scripts/guild_queue.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b0q2233msdtgo
|
||||
23
scripts/guildhall.gd
Normal file
23
scripts/guildhall.gd
Normal file
@@ -0,0 +1,23 @@
|
||||
class_name Guildhall extends Node2D
|
||||
|
||||
var employees : Dictionary[String, GuildEmployee] = {}
|
||||
var interactables : Dictionary[String, Interactable] = {}
|
||||
var board : QuestBoard
|
||||
@onready var sprite_node : Node2D = $Sprites
|
||||
@onready var nav_region : NavigationRegion2D = $RoomRegion
|
||||
|
||||
func _ready() -> void:
|
||||
Guild.hall = self
|
||||
for child in sprite_node.get_children():
|
||||
if child is GuildEmployee:
|
||||
register_employee(child)
|
||||
|
||||
|
||||
func register_employee(employee: GuildEmployee) -> void:
|
||||
employees[employee.name] = employee
|
||||
|
||||
func register_interactables(equipment: Interactable) -> void:
|
||||
interactables[equipment.name] = equipment
|
||||
|
||||
func add_sprite(sprite : Adventurer) -> void:
|
||||
sprite_node.add_child(sprite)
|
||||
1
scripts/guildhall.gd.uid
Normal file
1
scripts/guildhall.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ccorfvcfa84gf
|
||||
5
scripts/hero_icon.gd
Normal file
5
scripts/hero_icon.gd
Normal file
@@ -0,0 +1,5 @@
|
||||
class_name HeroIcon extends Sprite2D
|
||||
|
||||
|
||||
func move(pos : Vector2) -> void:
|
||||
pass
|
||||
1
scripts/hero_icon.gd.uid
Normal file
1
scripts/hero_icon.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cxqkvnv4rwots
|
||||
12
scripts/interactable.gd
Normal file
12
scripts/interactable.gd
Normal file
@@ -0,0 +1,12 @@
|
||||
class_name Interactable extends StaticBody2D
|
||||
|
||||
var busy : bool = false
|
||||
var queue : GuildQueue
|
||||
|
||||
signal interaction_complete()
|
||||
|
||||
func _ready() -> void:
|
||||
queue = $Queue
|
||||
|
||||
func interact(interactor, service : String = ""):
|
||||
interaction_complete.emit()
|
||||
1
scripts/interactable.gd.uid
Normal file
1
scripts/interactable.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dek37dgkvktjb
|
||||
61
scripts/main_panel.gd
Normal file
61
scripts/main_panel.gd
Normal file
@@ -0,0 +1,61 @@
|
||||
class_name GamePanel extends MarginContainer
|
||||
|
||||
const notice_template = preload("res://notice_panel.tscn")
|
||||
const quest_progress_bar_template = preload("res://quest_progress_bar.tscn")
|
||||
|
||||
signal time_changed(time : float)
|
||||
|
||||
@onready var timer : Timer = $Timer
|
||||
|
||||
func _ready() -> void:
|
||||
Game.panel = self
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
time_changed.emit(timer.time_left)
|
||||
|
||||
func add_quest_progress_bar(quest : Quest) -> void:
|
||||
var qpb : QuestProgressBar = quest_progress_bar_template.instantiate()
|
||||
qpb.setup(quest)
|
||||
%QuestList.add_child(qpb)
|
||||
#TODO: Change the hero portrait to match
|
||||
if quest.steps > 1:
|
||||
for i in range(quest.steps-1):
|
||||
qpb.add_waypoint(float(i) / quest.steps, quest.step_messages[i])
|
||||
|
||||
|
||||
func switch_panel(active : bool) -> void:
|
||||
%OpenShift.visible = active
|
||||
%WorkingShift.visible = !active
|
||||
%Timer.start(300 if active else 1500)
|
||||
|
||||
func _on_show_quests_pressed() -> void:
|
||||
%QuestProgressList.visible = !%QuestProgressList.visible
|
||||
|
||||
func _on_end_shift_pressed() -> void:
|
||||
Game.confirm_end_shift()
|
||||
|
||||
func _on_visitor_spawned(remaining : int, total : int) -> void:
|
||||
update_visitor_count(total - remaining, total)
|
||||
|
||||
func connect_visitor_spawner(spawner : VisitorSpawner) -> void:
|
||||
spawner.visitor_spawned.connect(_on_visitor_spawned)
|
||||
update_visitor_count(spawner.total_visitors - spawner.visitors_remaining, spawner.total_visitors)
|
||||
|
||||
func update_visitor_count(current : int, total : int) -> void:
|
||||
%OpenList/VisitorsLabel.text = "Visitors: %d/%d" % [current, total]
|
||||
|
||||
func populate_quest_bars() -> void:
|
||||
|
||||
var count : int = 0
|
||||
for quest in Guild.quests:
|
||||
if quest.is_taken():
|
||||
count+=1
|
||||
add_quest_progress_bar(quest)
|
||||
%ShowQuestsButton.disabled = (count == 0)
|
||||
|
||||
func notice(msg : String, time : float) -> void:
|
||||
var ntc : NoticePanel = notice_template.instantiate()
|
||||
%Notices.add_child(ntc)
|
||||
ntc.message = msg
|
||||
ntc.duration = time
|
||||
|
||||
1
scripts/main_panel.gd.uid
Normal file
1
scripts/main_panel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dhw85vqlvw33s
|
||||
36
scripts/member_panel_entry.gd
Normal file
36
scripts/member_panel_entry.gd
Normal file
@@ -0,0 +1,36 @@
|
||||
extends PanelContainer
|
||||
|
||||
const npc_profile_window_template = preload("res://npc_profile_window.tscn")
|
||||
var _enabled: bool
|
||||
var enabled: bool:
|
||||
get:
|
||||
return _enabled
|
||||
set(value):
|
||||
enable(value)
|
||||
|
||||
var data : AdventurerData
|
||||
|
||||
|
||||
func enable(en: bool) -> void:
|
||||
_enabled = en
|
||||
if en:
|
||||
mouse_filter=Control.MOUSE_FILTER_STOP
|
||||
else:
|
||||
mouse_filter=Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
func setup(member : AdventurerData) -> void:
|
||||
data = member
|
||||
%NameLabel.text = data.given_name + " " + data.surname
|
||||
%LevelLabel.text = str(data.level)
|
||||
if data.job:
|
||||
%JobLabel.text = data.job.name
|
||||
#TODO: Change portrait
|
||||
|
||||
func _on_gui_input(event: InputEvent) -> void:
|
||||
var evt = event as InputEventMouseButton
|
||||
if evt and evt.button_index == MOUSE_BUTTON_LEFT and evt.pressed:
|
||||
var window : Window = npc_profile_window_template.instantiate()
|
||||
Game.add_child(window)
|
||||
window.setup(data)
|
||||
window.popup_centered()
|
||||
window.grab_focus()
|
||||
1
scripts/member_panel_entry.gd.uid
Normal file
1
scripts/member_panel_entry.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b5v1r3u5gbpfw
|
||||
18
scripts/notice_panel.gd
Normal file
18
scripts/notice_panel.gd
Normal file
@@ -0,0 +1,18 @@
|
||||
class_name NoticePanel extends PanelContainer
|
||||
|
||||
|
||||
var message : String :
|
||||
get:
|
||||
return %Label.text
|
||||
set(value):
|
||||
%Label.text = value
|
||||
|
||||
var duration : float :
|
||||
get:
|
||||
return %Timer.wait_time
|
||||
set(value):
|
||||
%Timer.wait_time = value
|
||||
%Timer.start()
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
queue_free()
|
||||
1
scripts/notice_panel.gd.uid
Normal file
1
scripts/notice_panel.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bqah2tc3d5otk
|
||||
31
scripts/npc.gd
Normal file
31
scripts/npc.gd
Normal file
@@ -0,0 +1,31 @@
|
||||
class_name Npc extends Person
|
||||
|
||||
const popup_template = preload("res://profile_popup.tscn")
|
||||
var profile_popup
|
||||
|
||||
@export var is_player : bool = false
|
||||
@onready var bt_player : BTPlayer = $BTPlayer
|
||||
@export var movement_speed : float = 400.0
|
||||
@onready var movement_target_position : Vector2 = global_position
|
||||
@onready var nav_agent : NavigationAgent2D = $NavigationAgent2D
|
||||
|
||||
var data : AdventurerData = null
|
||||
var interaction_target = null
|
||||
var last_position : Vector2 = Vector2.ZERO
|
||||
var stuck : bool = false
|
||||
var stuck_time_remaining : float = 0
|
||||
var busy : bool = false
|
||||
var _activity : String = ""
|
||||
var activity : String :
|
||||
get:
|
||||
return _activity
|
||||
set(value):
|
||||
_activity = value
|
||||
if profile_popup:
|
||||
profile_popup.change_activity(_activity)
|
||||
@onready var bubble : SpeechBubble = $SpeechBubble
|
||||
@export var interaction_range : float = 75
|
||||
@export var stop_range : float = 25
|
||||
|
||||
signal navigation_finished()
|
||||
signal navigation_failed()
|
||||
1
scripts/npc.gd.uid
Normal file
1
scripts/npc.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bh54wpqgau8hc
|
||||
38
scripts/npc_profile_window.gd
Normal file
38
scripts/npc_profile_window.gd
Normal file
@@ -0,0 +1,38 @@
|
||||
extends Window
|
||||
|
||||
var data : AdventurerData
|
||||
@onready var jobLabel = %JobLabel
|
||||
@onready var expLabel : Label = %ExpLabel
|
||||
@onready var levelLabel :Label = %LevelLabel
|
||||
@onready var lifeLabel :Label = %LifeLabel
|
||||
@onready var energyLabel :Label = %EnergyLabel
|
||||
|
||||
@onready var strLabel :Label = %STRLabel
|
||||
@onready var dexLabel :Label = %DEXLabel
|
||||
@onready var intLabel :Label = %INTLabel
|
||||
@onready var chaLabel :Label = %CHALabel
|
||||
@onready var faiLabel :Label = %FAILabel
|
||||
@onready var lukLabel :Label = %LUKLabel
|
||||
|
||||
|
||||
func setup(adv : AdventurerData) -> void:
|
||||
data = adv
|
||||
title = data.full_name()
|
||||
if data.job:
|
||||
jobLabel.text = data.job.name
|
||||
else:
|
||||
jobLabel.text = "ERROR"
|
||||
levelLabel.text = str(data.level)
|
||||
expLabel.text = "Exp: %d/%d" % [data.exp, data.get_tnl()]
|
||||
lifeLabel.text = "Life: " + str(data.life) + "/" + str(data.max_life)
|
||||
energyLabel.text = "Energy: " + str(data.energy) + "/" + str(data.max_energy)
|
||||
strLabel.text = "STR: " + str(data.stats.STR)
|
||||
dexLabel.text = "DEX: " + str(data.stats.DEX)
|
||||
intLabel.text = "INT: " + str(data.stats.INT)
|
||||
chaLabel.text = "CHA: " + str(data.stats.CHA)
|
||||
faiLabel.text = "FAI: " + str(data.stats.FAI)
|
||||
lukLabel.text = "LUK: " + str(data.stats.LUK)
|
||||
#TODO: Show equipment
|
||||
|
||||
func _on_close_requested() -> void:
|
||||
queue_free()
|
||||
1
scripts/npc_profile_window.gd.uid
Normal file
1
scripts/npc_profile_window.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ccsiubi5y75qg
|
||||
1
scripts/person.gd
Normal file
1
scripts/person.gd
Normal file
@@ -0,0 +1 @@
|
||||
class_name Person extends CharacterBody2D
|
||||
1
scripts/person.gd.uid
Normal file
1
scripts/person.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cr3kvsepqabgt
|
||||
73
scripts/player.gd
Normal file
73
scripts/player.gd
Normal file
@@ -0,0 +1,73 @@
|
||||
class_name Player extends Person
|
||||
|
||||
@onready var movement_speed : float = 400.0
|
||||
@onready var movement_target_position : Vector2 = global_position
|
||||
@onready var nav_agent : NavigationAgent2D = $NavigationAgent2D
|
||||
|
||||
var interaction_target = null
|
||||
@export var interaction_range : float = 75
|
||||
@export var stop_range : float = 25
|
||||
var data : AdventurerData
|
||||
|
||||
func _ready() -> void:
|
||||
Game.player = self
|
||||
data = AdventurerData.new()
|
||||
data.name = "Player"
|
||||
setup.call_deferred()
|
||||
|
||||
|
||||
func setup():
|
||||
await get_tree().physics_frame
|
||||
set_movement_target(movement_target_position)
|
||||
|
||||
|
||||
func set_movement_target(target : Vector2) -> void:
|
||||
nav_agent.target_position = target
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
|
||||
if nav_agent.is_navigation_finished():
|
||||
if interaction_target:
|
||||
try_interact(interaction_target)
|
||||
#If they have an interaction target within range
|
||||
#clear the target
|
||||
#try_interact
|
||||
return
|
||||
|
||||
var curr_pos: Vector2 = global_position
|
||||
var next_path_pos: Vector2 = nav_agent.get_next_path_position()
|
||||
|
||||
velocity = curr_pos.direction_to(next_path_pos) * movement_speed
|
||||
|
||||
move_and_slide()
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
var evt : InputEventMouseButton = event as InputEventMouseButton
|
||||
if evt and evt.pressed:
|
||||
approach(evt.global_position)
|
||||
nav_agent.target_desired_distance = stop_range
|
||||
interaction_target = null
|
||||
|
||||
func approach(pos : Vector2) -> void:
|
||||
var rid = get_world_2d().get_navigation_map()
|
||||
var point : Vector2 = NavigationServer2D.map_get_closest_point(rid, pos)
|
||||
set_movement_target(point)
|
||||
|
||||
func approach_and_interact(obj : Interactable) -> void:
|
||||
var t : Vector2 = obj.global_position
|
||||
if "queue" in obj and obj.queue != null:
|
||||
t = obj.queue.global_position
|
||||
set_movement_target(obj.global_position)
|
||||
nav_agent.target_desired_distance = interaction_range - 5
|
||||
interaction_target = obj
|
||||
|
||||
func try_interact(obj : Interactable) -> void:
|
||||
var df = obj.global_position - global_position
|
||||
if df.length() > interaction_range:
|
||||
approach_and_interact(obj)
|
||||
else:
|
||||
interact(obj)
|
||||
interaction_target = null
|
||||
|
||||
func interact(obj : Interactable) -> void:
|
||||
obj.interact(self)
|
||||
1
scripts/player.gd.uid
Normal file
1
scripts/player.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dolqtw1ye4ras
|
||||
16
scripts/profile_popup.gd
Normal file
16
scripts/profile_popup.gd
Normal file
@@ -0,0 +1,16 @@
|
||||
extends Control
|
||||
|
||||
@onready var name_label = %NameLabel
|
||||
@onready var level_label = %LevelLabel
|
||||
@onready var job_label = %JobLabel
|
||||
@onready var activity_label = %ActivityLabel
|
||||
|
||||
|
||||
func setup(new_name : String, level : int, job : String, activity : String) -> void:
|
||||
name_label.text = new_name
|
||||
level_label.text = "Lv " + str(level)
|
||||
job_label.text = job
|
||||
activity_label.text = activity
|
||||
|
||||
func change_activity(activity : String) -> void:
|
||||
activity_label.text = activity
|
||||
1
scripts/profile_popup.gd.uid
Normal file
1
scripts/profile_popup.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b0obax7efrsy1
|
||||
1
scripts/profile_window.gd
Normal file
1
scripts/profile_window.gd
Normal file
@@ -0,0 +1 @@
|
||||
extends Window
|
||||
1
scripts/profile_window.gd.uid
Normal file
1
scripts/profile_window.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dpws8rq811nt8
|
||||
77
scripts/quest.gd
Normal file
77
scripts/quest.gd
Normal file
@@ -0,0 +1,77 @@
|
||||
class_name Quest extends Object
|
||||
|
||||
|
||||
enum Status{
|
||||
OPEN,
|
||||
TAKEN,
|
||||
IN_PROGRESS,
|
||||
COMPLETED,
|
||||
FAILED
|
||||
}
|
||||
|
||||
|
||||
var name : String = "A Basic Quest"
|
||||
var desc : String = "The default quest, with no special anything."
|
||||
var difficulty : int = 1
|
||||
var location : String
|
||||
var steps : int = 1
|
||||
var rewards : Dictionary
|
||||
var length : float = 10
|
||||
var step_outcomes : Array = [
|
||||
{"pass":"I succeeded!", "fail":"I failed!"}
|
||||
]
|
||||
|
||||
|
||||
|
||||
var progress : float = 0
|
||||
var current_step : int = 0
|
||||
var taken : bool = false
|
||||
var status : Status = Status.OPEN
|
||||
|
||||
var questor : AdventurerData = null
|
||||
signal status_changed(status : Status)
|
||||
|
||||
func _init() -> void:
|
||||
pass
|
||||
|
||||
func initiate(member : AdventurerData) -> void:
|
||||
questor = member
|
||||
status = Status.TAKEN
|
||||
status_changed.emit(Status.TAKEN)
|
||||
|
||||
func fail() -> void:
|
||||
status = Status.FAILED
|
||||
status_changed.emit(Status.FAILED)
|
||||
|
||||
func complete() -> void:
|
||||
status = Status.COMPLETED
|
||||
status_changed.emit(Status.COMPLETED)
|
||||
for reward in rewards.keys():
|
||||
if reward == "gold":
|
||||
questor.gain_gold(rewards[reward])
|
||||
elif reward == "exp":
|
||||
questor.gain_exp(rewards[reward])
|
||||
#TODO: Implement other reward types
|
||||
#elif rewards[reward] is Item:
|
||||
# questor.gain_item()
|
||||
#else it's a guild item they'll bring back for us
|
||||
Game.notice("%s completed the quest '%s'!" % [questor.full_name(), name])
|
||||
|
||||
#TODO: Put in quest requirements
|
||||
func is_eligible(member : AdventurerData) -> bool:
|
||||
return !taken
|
||||
|
||||
func is_taken() -> bool:
|
||||
return status == Status.TAKEN
|
||||
|
||||
|
||||
|
||||
func difficulty_name() -> String:
|
||||
match(difficulty):
|
||||
0: return "None"
|
||||
1: return "Trivial"
|
||||
2: return "Moderate"
|
||||
3: return "Severe"
|
||||
4: return "Extreme"
|
||||
5: return "Legendary"
|
||||
_: return "Unknown"
|
||||
1
scripts/quest.gd.uid
Normal file
1
scripts/quest.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bowt76gfx40pv
|
||||
44
scripts/quest_board.gd
Normal file
44
scripts/quest_board.gd
Normal file
@@ -0,0 +1,44 @@
|
||||
class_name QuestBoard extends Interactable
|
||||
|
||||
|
||||
@onready var polygon : CollisionPolygon2D = $CollisionPolygon2D
|
||||
@onready var window : QuestBoardWindow = $QuestBoardWindow
|
||||
@onready var btplayer : BTPlayer = $BTPlayer
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
register_board.call_deferred()
|
||||
super._ready()
|
||||
|
||||
func register_board() -> void:
|
||||
Guild.hall.register_interactables(self)
|
||||
|
||||
func _input(event : InputEvent) -> void:
|
||||
var evt : InputEventMouseButton = event as InputEventMouseButton
|
||||
if evt and evt.button_index == MOUSE_BUTTON_LEFT and evt.pressed:
|
||||
if Geometry2D.is_point_in_polygon(evt.position - polygon.global_position, polygon.polygon):
|
||||
Game.player.try_interact(self)
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
func interact(interactor, type : String = "") -> void:
|
||||
if interactor is Player:
|
||||
window.populate(Guild.quests.keys())
|
||||
window.popup_centered()
|
||||
elif type == "quest":
|
||||
var viable_quests : Dictionary[Quest,int] = {}
|
||||
#Go through all quests and create a list of open quests suitable for their level
|
||||
for quest in Guild.quests:
|
||||
if quest.is_eligible(interactor.data):
|
||||
#TODO: Make them weight different quests differently.
|
||||
viable_quests[quest] = 1
|
||||
#If that list is zero, return without giving them a quest
|
||||
if viable_quests.size() != 0:
|
||||
var rnd_quest = []
|
||||
for quest in viable_quests.keys():
|
||||
for i in range(viable_quests[quest]):
|
||||
rnd_quest.append(quest)
|
||||
var quest = rnd_quest.pick_random()
|
||||
Guild.assign_quest(interactor.data, quest)
|
||||
interaction_complete.emit()
|
||||
#Else pick a random quest from the list and assign it to them
|
||||
1
scripts/quest_board.gd.uid
Normal file
1
scripts/quest_board.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://blo7tb5135vfm
|
||||
34
scripts/quest_board_entry.gd
Normal file
34
scripts/quest_board_entry.gd
Normal file
@@ -0,0 +1,34 @@
|
||||
class_name QuestBoardEntry extends Button
|
||||
|
||||
|
||||
const quest_window_template = preload("res://quest_window.tscn")
|
||||
var quest : Quest = null
|
||||
@onready var tex_icon : TextureRect = %Icon
|
||||
@onready var name_label : Label = %NameLabel
|
||||
@onready var status_label : Label = %StatusLabel
|
||||
var board_window : QuestBoardWindow = null
|
||||
|
||||
func setup(quest : Quest) -> void:
|
||||
self.quest = quest
|
||||
quest.status_changed.connect(_on_quest_status_changed)
|
||||
name_label.text = quest.name
|
||||
status_label.text = "Available" if !quest.taken else "Unavailable"
|
||||
|
||||
func update() -> void:
|
||||
status_label.text = "Available" if !quest.taken else "Unavailable"
|
||||
|
||||
|
||||
func _on_quest_status_changed(status: Quest.Status) -> void:
|
||||
match(status):
|
||||
Quest.Status.OPEN: status_label.text = "Available"
|
||||
Quest.Status.TAKEN:queue_free()
|
||||
Quest.Status.COMPLETED: queue_free()
|
||||
_: status_label.text = "Unavailable"
|
||||
|
||||
func _on_pressed() -> void:
|
||||
var window = quest_window_template.instantiate()
|
||||
window.setup(quest, true)
|
||||
window.quest_accepted.connect(board_window._on_quest_accepted)
|
||||
add_child(window)
|
||||
window.popup_centered()
|
||||
|
||||
1
scripts/quest_board_entry.gd.uid
Normal file
1
scripts/quest_board_entry.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://hsks1qah12sh
|
||||
25
scripts/quest_board_window.gd
Normal file
25
scripts/quest_board_window.gd
Normal file
@@ -0,0 +1,25 @@
|
||||
class_name QuestBoardWindow extends Popup
|
||||
|
||||
const entry_template = preload("res://quest_board_entry.tscn")
|
||||
|
||||
@onready var entry_list : VBoxContainer = %Entries
|
||||
|
||||
|
||||
func populate(quests : Array[Quest]) -> void:
|
||||
for entry : QuestBoardEntry in entry_list.get_children():
|
||||
entry.queue_free()
|
||||
for quest in quests:
|
||||
if !quest.is_taken():
|
||||
add_entry(quest)
|
||||
|
||||
func add_entry(quest : Quest) -> void:
|
||||
var qle : QuestBoardEntry = entry_template.instantiate()
|
||||
entry_list.add_child(qle)
|
||||
qle.setup(quest)
|
||||
qle.board_window = self
|
||||
|
||||
func _on_quest_accepted() -> void:
|
||||
hide()
|
||||
|
||||
func _on_close_requested() -> void:
|
||||
hide()
|
||||
1
scripts/quest_board_window.gd.uid
Normal file
1
scripts/quest_board_window.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://de4lnikqqk7b4
|
||||
15
scripts/quest_log.gd
Normal file
15
scripts/quest_log.gd
Normal file
@@ -0,0 +1,15 @@
|
||||
class_name QuestLog extends Control
|
||||
|
||||
const entry_template = preload("res://quest_log_entry.tscn")
|
||||
|
||||
@onready var entry_list : VBoxContainer = %Entries
|
||||
var entries : Array[QuestLogEntry] = []
|
||||
|
||||
func _ready() -> void:
|
||||
Game.quest_log = self
|
||||
|
||||
func add_entry(quest : Quest) -> void:
|
||||
var qle : QuestLogEntry = entry_template.instantiate()
|
||||
entries.append(qle)
|
||||
entry_list.add_child(qle)
|
||||
qle.setup(quest)
|
||||
1
scripts/quest_log.gd.uid
Normal file
1
scripts/quest_log.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://opy1kwcgsh70
|
||||
21
scripts/quest_log_entry.gd
Normal file
21
scripts/quest_log_entry.gd
Normal file
@@ -0,0 +1,21 @@
|
||||
class_name QuestLogEntry extends Panel
|
||||
|
||||
var quest : Quest = null
|
||||
@onready var icon : TextureRect = %Icon
|
||||
@onready var name_label : Label = %NameLabel
|
||||
@onready var status_label : Label = %StatusLabel
|
||||
|
||||
func setup(quest : Quest) -> void:
|
||||
self.quest = quest
|
||||
name_label.text = quest.name
|
||||
status_label.text = "Available" if !quest.taken else "Unavailable"
|
||||
quest.status_changed.connect(_on_quest_status_changed)
|
||||
|
||||
func update() -> void:
|
||||
status_label.text = "Available" if !quest.taken else "Unavailable"
|
||||
|
||||
func _on_quest_status_changed(status : Quest.Status) -> void:
|
||||
match(status):
|
||||
Quest.Status.OPEN: status_label.text = "Available"
|
||||
Quest.Status.COMPLETED: queue_free()
|
||||
_: status_label.text = "Unavailable"
|
||||
1
scripts/quest_log_entry.gd.uid
Normal file
1
scripts/quest_log_entry.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dfn0507e4nccu
|
||||
40
scripts/quest_panel_entry.gd
Normal file
40
scripts/quest_panel_entry.gd
Normal file
@@ -0,0 +1,40 @@
|
||||
extends PanelContainer
|
||||
|
||||
|
||||
var _enabled: bool
|
||||
var enabled: bool:
|
||||
get:
|
||||
return _enabled
|
||||
set(value):
|
||||
enable(value)
|
||||
|
||||
var quest : Quest
|
||||
@onready var status_label = %StatusLabel
|
||||
|
||||
func enable(en: bool) -> void:
|
||||
_enabled = en
|
||||
if en:
|
||||
mouse_filter=Control.MOUSE_FILTER_STOP
|
||||
else:
|
||||
mouse_filter=Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
func setup(qst : Quest) -> void:
|
||||
quest = qst
|
||||
quest.status_changed.connect(_on_quest_status_changed)
|
||||
%NameLabel.text = quest.name
|
||||
#TODO: Add star rating
|
||||
#%LevelLabel.text = str(data.level)
|
||||
%StatusLabel.text = ("Taken ()" % [quest.questor.full_name()]) if quest.taken else "OPEN"
|
||||
#TODO: Change portrait
|
||||
|
||||
func _on_gui_input(event: InputEvent) -> void:
|
||||
var evt = event as InputEventMouseButton
|
||||
if evt and evt.button_index == MOUSE_BUTTON_LEFT and evt.pressed:
|
||||
print("Quest clicked!")
|
||||
|
||||
func _on_quest_status_changed(status: Quest.Status) -> void:
|
||||
match(status):
|
||||
Quest.Status.OPEN: status_label.text = "OPEN"
|
||||
Quest.Status.COMPLETED: queue_free()
|
||||
Quest.Status.IN_PROGRESS: status_label.text = "IN PROGRESS"
|
||||
_: status_label.text = "Taken"
|
||||
1
scripts/quest_panel_entry.gd.uid
Normal file
1
scripts/quest_panel_entry.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://qv10wys8xel3
|
||||
71
scripts/quest_progress_bar.gd
Normal file
71
scripts/quest_progress_bar.gd
Normal file
@@ -0,0 +1,71 @@
|
||||
class_name QuestProgressBar extends Control
|
||||
|
||||
const waypoint_template = preload("res://waypoint.tscn")
|
||||
var length : float
|
||||
var waypoints : Array = []
|
||||
@onready var hero_offset : Vector2 = %Hero.position
|
||||
@onready var hero : HeroIcon = %Hero
|
||||
@onready var startpoint : Endpoint = %Start
|
||||
@onready var endpoint : Endpoint = %End
|
||||
@onready var bar : TextureProgressBar = $ProgressBar
|
||||
@onready var path : Control = %Path
|
||||
var quest : Quest = null
|
||||
var time_elapsed : float = 0
|
||||
#signal value_changed(value : float)
|
||||
#var min_value
|
||||
#var max_value
|
||||
#var step
|
||||
#var page
|
||||
#var value
|
||||
#var exp_edit
|
||||
#var rounded
|
||||
#var allow_greater
|
||||
func _ready() -> void:
|
||||
length = path.size.x
|
||||
if quest:
|
||||
#Generate the waypoints
|
||||
generate_waypoints()
|
||||
#TODO: Change the hero's portrait
|
||||
bar.value = quest.progress
|
||||
hero.position = hero_offset + Vector2(length * bar.value / bar.max_value, 0)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if time_elapsed < quest.length:
|
||||
time_elapsed += delta
|
||||
progress_quest()
|
||||
|
||||
func generate_waypoints():
|
||||
if len(waypoints) > 0:
|
||||
for wp in waypoints:
|
||||
wp.queue_free()
|
||||
waypoints = []
|
||||
|
||||
for i in range(1,quest.steps):
|
||||
var pct : float = i / float(quest.steps)
|
||||
add_waypoint( pct, quest.step_outcomes[i])
|
||||
|
||||
func add_waypoint(pct : float, msgs : Dictionary):
|
||||
var wp = waypoint_template.instantiate()
|
||||
waypoints.append(wp)
|
||||
wp.percent = pct
|
||||
%Waypoints.add_child(wp)
|
||||
wp.global_position = global_position + Vector2(pct * length - 16, -9)
|
||||
if bar.value / bar.max_value >= pct:
|
||||
wp.fill = true
|
||||
|
||||
func update_waypoints(value : float) -> void:
|
||||
startpoint.fill = (bar.value / bar.max_value >= startpoint.percent)
|
||||
for wp : Waypoint in waypoints:
|
||||
wp.fill = (bar.value / bar.max_value >= wp.percent)
|
||||
endpoint.fill = (bar.value / bar.max_value >= endpoint.percent)
|
||||
|
||||
func setup(quest : Quest) -> void:
|
||||
self.quest = quest
|
||||
time_elapsed = 0
|
||||
|
||||
func progress_quest() -> void:
|
||||
bar.value = clampf(time_elapsed / quest.length, 0, bar.max_value)
|
||||
hero.position = hero_offset + Vector2(length * bar.value / bar.max_value, 0)
|
||||
if time_elapsed >= quest.length:
|
||||
quest.complete()
|
||||
update_waypoints(bar.value)
|
||||
1
scripts/quest_progress_bar.gd.uid
Normal file
1
scripts/quest_progress_bar.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cgi3tu0ussfk0
|
||||
39
scripts/quest_window.gd
Normal file
39
scripts/quest_window.gd
Normal file
@@ -0,0 +1,39 @@
|
||||
extends Window
|
||||
|
||||
var quest : Quest
|
||||
signal quest_accepted()
|
||||
|
||||
func setup(qst : Quest, board : bool) -> void:
|
||||
quest = qst
|
||||
quest.status_changed.connect(_on_quest_status_changed)
|
||||
%NameField.text = quest.name
|
||||
%DifficultyField.text = quest.difficulty_name()
|
||||
%LocationField.text = quest.location
|
||||
if !board:
|
||||
%AcceptButton.hide()
|
||||
|
||||
if quest.is_taken():
|
||||
%StatusField.text = "Taken"
|
||||
%AcceptButton.disabled = true
|
||||
else:
|
||||
%StatusField.text = "OPEN"
|
||||
%AcceptButton.disabled = false
|
||||
|
||||
|
||||
func _on_quest_status_changed(status : Quest.Status) -> void:
|
||||
if status == Quest.Status.COMPLETED:
|
||||
queue_free()
|
||||
if quest.is_taken():
|
||||
%StatusField.text = "Taken"
|
||||
%AcceptButton.disabled = true
|
||||
else:
|
||||
%StatusField.text = "OPEN"
|
||||
%AcceptButton.disabled = false
|
||||
|
||||
func _on_accept_pressed() -> void:
|
||||
Guild.assign_quest(Game.player.data, quest)
|
||||
quest_accepted.emit()
|
||||
queue_free()
|
||||
|
||||
func _on_close_button_pressed() -> void:
|
||||
queue_free()
|
||||
1
scripts/quest_window.gd.uid
Normal file
1
scripts/quest_window.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b3flxu0sduc1
|
||||
14
scripts/speech_bubble.gd
Normal file
14
scripts/speech_bubble.gd
Normal file
@@ -0,0 +1,14 @@
|
||||
class_name SpeechBubble extends Sprite2D
|
||||
|
||||
@onready var anim_player : AnimationPlayer = $AnimationPlayer
|
||||
|
||||
func try_show_speech(type : String = ""):
|
||||
if type != "":
|
||||
if anim_player.has_animation(type):
|
||||
visible = true
|
||||
anim_player.play(type)
|
||||
else:
|
||||
printerr("Tried to show speech bubble %s but speech bubble does not have that type!" % type)
|
||||
visible = false
|
||||
else:
|
||||
visible = false
|
||||
1
scripts/speech_bubble.gd.uid
Normal file
1
scripts/speech_bubble.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://w57riwplc00t
|
||||
5
scripts/start_menu.gd
Normal file
5
scripts/start_menu.gd
Normal file
@@ -0,0 +1,5 @@
|
||||
extends Control
|
||||
|
||||
|
||||
func _on_button_pressed() -> void:
|
||||
get_tree().change_scene_to_file()
|
||||
1
scripts/start_menu.gd.uid
Normal file
1
scripts/start_menu.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dco3n63irwntu
|
||||
4
scripts/test_limbo.gd
Normal file
4
scripts/test_limbo.gd
Normal file
@@ -0,0 +1,4 @@
|
||||
extends CharacterBody2D
|
||||
|
||||
|
||||
var busy : bool = false
|
||||
1
scripts/test_limbo.gd.uid
Normal file
1
scripts/test_limbo.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cgsnqeb1dg23d
|
||||
8
scripts/test_scene.gd
Normal file
8
scripts/test_scene.gd
Normal file
@@ -0,0 +1,8 @@
|
||||
extends Node2D
|
||||
|
||||
var test_adv = preload("res://test_adventurer.tscn")
|
||||
func _ready() -> void:
|
||||
#var adv : AdventurerData = test_adv.instantiate() as AdventurerData
|
||||
#Guild.register_guild_member(adv)
|
||||
var quest : Quest = Quest.new()
|
||||
Guild.add_quest(quest)
|
||||
1
scripts/test_scene.gd.uid
Normal file
1
scripts/test_scene.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cci652umkym1f
|
||||
12
scripts/timer_label.gd
Normal file
12
scripts/timer_label.gd
Normal file
@@ -0,0 +1,12 @@
|
||||
extends Label
|
||||
|
||||
|
||||
func _on_time_changed(time : float) -> void:
|
||||
var t : int = int(time)
|
||||
var ms = time - t
|
||||
var s = t % 60
|
||||
t = (t - s) / 60
|
||||
var m = t % 60
|
||||
t = (t - m) / 60
|
||||
var h = t
|
||||
text = "%02d:%02d:%02d.%02d" % [h,m,s,int(ms * 100) % 100]
|
||||
1
scripts/timer_label.gd.uid
Normal file
1
scripts/timer_label.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://4jrp67ckp7vt
|
||||
51
scripts/top_menu.gd
Normal file
51
scripts/top_menu.gd
Normal file
@@ -0,0 +1,51 @@
|
||||
class_name TopMenu extends Control
|
||||
|
||||
const member_panel_entry_template = preload("res://member_panel_entry.tscn")
|
||||
const quest_panel_entry_template = preload("res://quest_panel_entry.tscn")
|
||||
const guild_info_window_template = preload("res://guild_info_window.tscn")
|
||||
|
||||
@onready var members_list = %MembersList
|
||||
@onready var members = %Members
|
||||
@onready var quest_list = %QuestList
|
||||
@onready var quests = %Quests
|
||||
func _ready() -> void:
|
||||
Game.top_menu = self
|
||||
|
||||
func hide_submenus() -> void:
|
||||
members.visible = false
|
||||
quests.visible = false
|
||||
|
||||
func _on_members_button_pressed() -> void:
|
||||
if !members.visible:
|
||||
hide_submenus()
|
||||
members.visible = !members.visible
|
||||
for child in members_list.get_children():
|
||||
child.enabled = members.visible
|
||||
|
||||
func _on_quests_button_pressed() -> void:
|
||||
if !quests.visible:
|
||||
hide_submenus()
|
||||
quests.visible = !quests.visible
|
||||
for child in quest_list.get_children():
|
||||
child.enabled = quests.visible
|
||||
|
||||
func add_member(member : AdventurerData) -> void:
|
||||
var entry = member_panel_entry_template.instantiate()
|
||||
entry.setup(member)
|
||||
members_list.add_child(entry)
|
||||
|
||||
func add_quest(quest : Quest) -> void:
|
||||
var entry = quest_panel_entry_template.instantiate()
|
||||
entry.setup(quest)
|
||||
quest_list.add_child(entry)
|
||||
|
||||
|
||||
func _on_quest_generate_button_pressed() -> void:
|
||||
%GenerateQuestDialog.show()
|
||||
|
||||
|
||||
func _on_guild_button_pressed() -> void:
|
||||
var wnd = guild_info_window_template.instantiate()
|
||||
add_child(wnd)
|
||||
wnd.popup_centered()
|
||||
wnd.grab_focus()
|
||||
1
scripts/top_menu.gd.uid
Normal file
1
scripts/top_menu.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://wyv0gt0ww6fp
|
||||
27
scripts/update_bubble.gd
Normal file
27
scripts/update_bubble.gd
Normal file
@@ -0,0 +1,27 @@
|
||||
extends NinePatchRect
|
||||
|
||||
@onready var label : Label = %Label
|
||||
@onready var timer : Timer = %Timer
|
||||
|
||||
func _ready() -> void:
|
||||
show_message("TESTING, 1 2 3\nTESTING!!!!")
|
||||
|
||||
|
||||
func show_message(msg : String, show_time : float = 1.0) -> void:
|
||||
label.text = msg
|
||||
appear.call(show_time)
|
||||
|
||||
func appear(show_time : float):
|
||||
var size : Vector2 = label.get_size()
|
||||
size += get_minimum_size() / 2
|
||||
print(size)
|
||||
var tween = create_tween()
|
||||
tween.tween_property(self, "size", size, .25)
|
||||
#tween.parallel().tween_property(self, "pivot_offset", Vector2(0, size.y), .5)
|
||||
tween.parallel().tween_property(self, "position", Vector2(position.x, position.y-size.y/2), 0.25)
|
||||
timer.start(show_time + .25)
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
var tween = create_tween()
|
||||
tween.tween_property(self, "modulate", Color(1,1,1,0), .5)
|
||||
tween.tween_callback(queue_free)
|
||||
1
scripts/update_bubble.gd.uid
Normal file
1
scripts/update_bubble.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c23pbcmig5v3s
|
||||
31
scripts/visitor_spawner.gd
Normal file
31
scripts/visitor_spawner.gd
Normal file
@@ -0,0 +1,31 @@
|
||||
class_name VisitorSpawner extends Node2D
|
||||
|
||||
@onready var timer : Timer = $Timer
|
||||
@export var total_visitors : int = 0
|
||||
@export var min_time : float = 5
|
||||
@export var max_time : float = 10
|
||||
var visitors_remaining : int
|
||||
signal visitor_spawned(current : int, total : int)
|
||||
|
||||
func _ready() -> void:
|
||||
Guild.visitor_spawner = self
|
||||
visitors_remaining = total_visitors
|
||||
if visitors_remaining > 0:
|
||||
timer.start(randf_range(min_time, max_time))
|
||||
setup_ui.call_deferred()
|
||||
|
||||
func setup_ui():
|
||||
Game.setup_visitor_ui(self)
|
||||
|
||||
|
||||
func spawn_visitor() -> void:
|
||||
Guild.spawn_visitor(global_position)
|
||||
visitors_remaining-=1
|
||||
visitor_spawned.emit(visitors_remaining, total_visitors)
|
||||
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
if visitors_remaining > 0:
|
||||
spawn_visitor()
|
||||
else:
|
||||
timer.stop()
|
||||
1
scripts/visitor_spawner.gd.uid
Normal file
1
scripts/visitor_spawner.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bnbljf6u2d3kh
|
||||
22
scripts/waypoint.gd
Normal file
22
scripts/waypoint.gd
Normal file
@@ -0,0 +1,22 @@
|
||||
class_name Waypoint extends Control
|
||||
|
||||
var percent : float = 0
|
||||
var filled: bool
|
||||
var fill: bool :
|
||||
get:
|
||||
return filled
|
||||
set(value):
|
||||
if value != filled:
|
||||
set_fill(value)
|
||||
|
||||
|
||||
func set_fill(value : bool) -> void:
|
||||
filled = value
|
||||
if value:
|
||||
$Dot.visible = true
|
||||
$Fill.modulate = Color.SEA_GREEN
|
||||
else:
|
||||
$Dot.visible = false
|
||||
$Fill.modulate = Color.BLACK
|
||||
|
||||
|
||||
1
scripts/waypoint.gd.uid
Normal file
1
scripts/waypoint.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dnytdxwuk6b7x
|
||||
Reference in New Issue
Block a user