aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/gui_bottom_bar.gd41
-rw-r--r--scripts/gui_picker.gd49
-rw-r--r--scripts/gui_top_bar.gd31
-rw-r--r--scripts/gui_turret.gd60
-rw-r--r--scripts/load_map.gd113
-rw-r--r--scripts/load_scenes.gd7
-rw-r--r--scripts/load_turrets.gd52
-rw-r--r--scripts/placer.gd210
-rw-r--r--scripts/resources.gd27
-rw-r--r--scripts/saveload.gd26
10 files changed, 616 insertions, 0 deletions
diff --git a/scripts/gui_bottom_bar.gd b/scripts/gui_bottom_bar.gd
new file mode 100644
index 0000000..0a7b7b8
--- /dev/null
+++ b/scripts/gui_bottom_bar.gd
@@ -0,0 +1,41 @@
+extends Control
+
+var _in_editor : bool
+var voxel_picker : Control
+var map_tool_picker : Control
+var turret_picker : Control
+
+var _load_turrets : Node
+
+var gui : Control
+
+func _fetch ():
+ if gui == null: gui = get_parent()
+ if voxel_picker == null: voxel_picker = $voxels
+ if map_tool_picker == null: map_tool_picker = $map_tools
+ if turret_picker == null: turret_picker = $turrets
+
+ var root = get_tree().root.get_child(0)
+ if _load_turrets == null:
+ _load_turrets = root.get_node("saveload").get_node("load_turrets")
+
+func build ():
+ _fetch()
+ turret_picker.build(_load_turrets.get_base_turrets())
+ voxel_picker.build()
+ map_tool_picker.build()
+
+func refresh (in_editor : bool):
+ _fetch()
+ _in_editor = in_editor
+
+ if _in_editor:
+ voxel_picker.visible = true
+ map_tool_picker.visible = true
+ else:
+ voxel_picker.visible = false
+ map_tool_picker.visible = false
+
+ turret_picker.refresh(gui.player.sel)
+ voxel_picker.refresh(gui.player.sel)
+ map_tool_picker.refresh(gui.player.sel)
diff --git a/scripts/gui_picker.gd b/scripts/gui_picker.gd
new file mode 100644
index 0000000..df4ee9b
--- /dev/null
+++ b/scripts/gui_picker.gd
@@ -0,0 +1,49 @@
+extends Panel
+
+var _hbox : HBoxContainer
+var _gui_button : Resource = load("res://scenes/gui/gui_turret.tscn")
+
+var _options = []
+
+var gui : Control
+
+func _fetch ():
+ if gui == null: gui = get_parent().gui
+ if _hbox == null: _hbox = $ScrollContainer/Hbox
+
+func build (options : Array = []):
+ _fetch()
+
+ if options.size() > 0:
+ for n in _hbox.get_children(): n.queue_free()
+
+ _options = options
+ for t in _options:
+ var gt : TextureButton = _gui_button.instance()
+ gt.name = t.name
+ _hbox.add_child(gt)
+ gt.init(t)
+
+ for child in _hbox.get_children():
+ if child.get_signal_connection_list("pressed").size() == 0:
+ child.connect("mouse_entered", self, "_on_gui_turret_mouse_entered", [child.name])
+ child.connect("mouse_exited", self, "_on_gui_turret_mouse_entered", [child.name])
+ child.connect("pressed", self, "_on_gui_turret_pressed", [child.name])
+
+func refresh (sel = ""):
+ _fetch()
+ if sel.type == "":
+ for child in _hbox.get_children(): child.picked = false
+ if sel.type == name:
+ for child in _hbox.get_children():
+ child.picked = child.name == sel.name
+
+func _on_gui_turret_mouse_entered(name : String):
+ print(name + " entered from " + self.name)
+
+func _on_gui_turret_mouse_exited(name : String):
+ print(name + " exited from " + self.name)
+
+func _on_gui_turret_pressed(name : String):
+ print(name + " pressed from " + self.name)
+ gui.player.selected_event(name, self.name)
diff --git a/scripts/gui_top_bar.gd b/scripts/gui_top_bar.gd
new file mode 100644
index 0000000..a002e87
--- /dev/null
+++ b/scripts/gui_top_bar.gd
@@ -0,0 +1,31 @@
+extends Control
+
+var _in_editor : bool
+var _editor_button : Button
+var _hbox : HBoxContainer
+
+var _resources : Node
+var _gui : Control
+
+func refresh (in_editor : bool):
+ _in_editor = in_editor
+
+ var root = get_tree().root.get_child(0)
+ _resources = root.get_node("player").get_node("resources")
+
+ if _gui == null: _gui = get_parent()
+ if _hbox == null: _hbox = $panel/resources/HBoxContainer
+ if _editor_button == null: _editor_button = $panel/editor_button
+
+ if _in_editor: _editor_button.text = "Editor"
+ else: _editor_button.text = "Playmode"
+
+func _process (_delta):
+ for r in _resources.get_names():
+ _hbox.get_node(r).text = str(_resources[r]) + r
+
+func _on_editor_button_down():
+ _gui.player.gui_editor_toggle_event()
+
+func _on_wave_button_pressed():
+ _gui.player.gui_start_wave_event()
diff --git a/scripts/gui_turret.gd b/scripts/gui_turret.gd
new file mode 100644
index 0000000..9faeb7a
--- /dev/null
+++ b/scripts/gui_turret.gd
@@ -0,0 +1,60 @@
+extends TextureButton
+
+var _turret : Dictionary
+
+var _color_rect : ColorRect
+var _name_label : Label
+var _cash_label : Label
+
+var _viewport : Viewport
+var _spinner : Node
+var _mesh : Node
+
+var _resources : Node
+
+var picked : bool
+var enabled : bool = false
+
+var _rotate_timer : float
+
+func init (turret : Dictionary):
+ _turret = turret
+ _color_rect = $ColorRect
+ _name_label = $hbox/name_label
+ _cash_label = $cash_label
+ _viewport = $viewport
+ _spinner = $viewport/spinner
+
+ var root = get_tree().root.get_child(0)
+ _resources = root.get_node("player").get_node("resources")
+
+ _name_label.text = turret.name
+ _cash_label.text = _resources.dict_to_str(turret.cost)
+
+ var load_turrets = root.get_node("saveload").get_node("load_turrets")
+ if !load_turrets.loaded: yield(load_turrets, "done_loading")
+ var model = load_turrets.models[turret.model_name]
+ _mesh = model.instance()
+ _spinner.add_child(_mesh)
+
+ texture_normal = _viewport.get_texture()
+
+func _process(delta):
+ if !has_node("viewport"): return
+ if _spinner == null: _spinner = $viewport/spinner
+ if _spinner != null:
+ if _resources == null:
+ var root = get_tree().root.get_child(0)
+ _resources = root.get_node("player").get_node("resources")
+
+ var afforded = _resources.greater_than(_turret.cost)
+ if afforded: _color_rect.color = Color(0,0,0,0)
+ else: _color_rect.color = Color(0,0,0,0.5)
+
+ if afforded and (is_hovered() or picked):
+ _spinner.transform.basis = _spinner.transform.rotated(Vector3.UP, delta).basis
+ _rotate_timer = 0
+ else:
+ _rotate_timer = min(1, _rotate_timer + delta * 5)
+ var idle_rot = Transform.rotated(Vector3.UP, PI-PI/4).basis
+ _spinner.transform.basis = _spinner.transform.basis.slerp(idle_rot, _rotate_timer)
diff --git a/scripts/load_map.gd b/scripts/load_map.gd
new file mode 100644
index 0000000..8130997
--- /dev/null
+++ b/scripts/load_map.gd
@@ -0,0 +1,113 @@
+extends Node
+
+var _world : VoxelMesh = null
+var _path_holder : Node = null
+var _attach_point_holder : Node = null
+
+var _load_scenes : Node = null
+
+func _ready():
+ map_load()
+
+func fetch ():
+ var root = get_tree().root.get_child(0)
+ if _world == null:
+ _world = root.get_node("world")
+ if _path_holder == null:
+ _path_holder = root.get_node("path")
+ if _attach_point_holder == null:
+ _attach_point_holder = root.get_node("attach")
+ if _load_scenes == null:
+ _load_scenes = root.get_node("saveload").get_node("load_scenes")
+
+func get_map_state ():
+ fetch()
+ var state = {}
+
+ state["voxels"] = []
+ for pos in _world.get_voxels():
+ var vox = { "pos": [pos.x, pos.y, pos.z], "id":_world.get_voxel_id(pos) }
+ state["voxels"] += [vox]
+
+ state["path"] = []
+ for node in _path_holder.get_children():
+ var pos = node.transform.origin;
+ var rot = node.transform.basis.get_rotation_quat();
+ var pobj = {
+ "pos": [pos.x, pos.y, pos.z],
+ "rot": [rot.x, rot.y, rot.z, rot.w],
+ "id": node.name
+ }
+ state["path"] += [pobj]
+
+ state["attach"] = []
+ for node in _attach_point_holder.get_children():
+ var pos = node.transform.origin;
+ var rot = node.transform.basis.get_rotation_quat();
+ var pobj = {
+ "pos": [pos.x, pos.y, pos.z],
+ "rot": [rot.x, rot.y, rot.z, rot.w],
+ "id": node.name
+ }
+ state["attach"] += [pobj]
+
+ return state
+
+func set_map_state (state):
+ fetch()
+ _world.erase_voxels()
+ for vox in state["voxels"]:
+ var vecpos = Vector3(vox.pos[0], vox.pos[1], vox.pos[2]);
+ _world.set_voxel(vecpos, vox.id)
+ _world.update_mesh()
+
+ for n in _path_holder.get_children(): n.queue_free()
+
+ for pobj in state["path"]:
+ var blue = _load_scenes.path
+ if "start" in pobj.id:
+ blue = _load_scenes.path_start
+ if "end" in pobj.id:
+ blue = _load_scenes.path_end
+ var instance = blue.instance()
+ _path_holder.add_child(instance)
+ var vecpos = Vector3(pobj.pos[0], pobj.pos[1], pobj.pos[2]);
+ instance.transform.origin = vecpos;
+ var quat = Quat(pobj.rot[0], pobj.rot[1], pobj.rot[2], pobj.rot[3]);
+ instance.transform.basis = Basis(quat);
+
+ for n in _attach_point_holder.get_children(): n.queue_free()
+
+ for pobj in state["attach"]:
+ var blue = _load_scenes.attach_point
+ var instance = blue.instance()
+ _attach_point_holder.add_child(instance)
+ var vecpos = Vector3(pobj.pos[0], pobj.pos[1], pobj.pos[2]);
+ instance.transform.origin = vecpos;
+ var quat = Quat(pobj.rot[0], pobj.rot[1], pobj.rot[2], pobj.rot[3]);
+ instance.transform.basis = Basis(quat);
+
+
+func map_save():
+ var save_game = File.new()
+ save_game.open("user://map0.json", File.WRITE)
+ save_game.store_string(to_json(get_map_state()))
+ save_game.close()
+ print("saved")
+
+func map_load():
+ var save_game = File.new()
+ save_game.open("user://map0.json", File.READ)
+ var raw = save_game.get_as_text()
+ save_game.close()
+
+ var state = parse_json(raw)
+ set_map_state(state)
+ print("loaded")
+
+
+func _process(_delta):
+ if Input.is_action_just_released("save"):
+ map_save()
+ if Input.is_action_just_released("load"):
+ map_load()
diff --git a/scripts/load_scenes.gd b/scripts/load_scenes.gd
new file mode 100644
index 0000000..fe237a4
--- /dev/null
+++ b/scripts/load_scenes.gd
@@ -0,0 +1,7 @@
+extends Node
+
+var turret : PackedScene = load("res://scenes/turret.tscn")
+var path_start : PackedScene = load("res://scenes/path_start.tscn")
+var path : PackedScene = load("res://scenes/path.tscn")
+var path_end : PackedScene= load("res://scenes/path_end.tscn")
+var attach_point : PackedScene = load("res://scenes/attach_point.tscn")
diff --git a/scripts/load_turrets.gd b/scripts/load_turrets.gd
new file mode 100644
index 0000000..3c9f378
--- /dev/null
+++ b/scripts/load_turrets.gd
@@ -0,0 +1,52 @@
+extends Node
+
+var saveload : Node
+
+var info : Dictionary
+var models : Dictionary
+var thumbs : Dictionary
+
+var loaded : bool = false
+signal done_loading
+
+func _ready():
+ get_saveload()
+ load_models()
+ load_info()
+ emit_signal("done_loading")
+ loaded = true
+
+func get_saveload():
+ if saveload == null: saveload = get_tree().root.get_child(0).get_node("saveload")
+
+func get_base_turrets():
+ var results = []
+ for turr in info.values():
+ var flag = true
+ for oth in info.values():
+ if oth.name == turr.name: continue
+ if turr.name in oth.upgrades:
+ flag = false
+ if flag: results.append(turr)
+ return results
+
+func load_info():
+ info.clear()
+ var files = saveload.parse_dir("res://assets", ".json")
+ for turr in files:
+ var parsed = saveload.load_parse_json("res://assets/" + turr)
+ if parsed != null:
+ for tin in parsed:
+ info[tin.name] = tin
+
+func load_models():
+ models.clear()
+ var files = saveload.parse_dir("res://models/turrets", ".glb")
+ for turr in files:
+ models[turr] = load("res://models/turrets/" + turr)
+
+func load_thumbs():
+ thumbs.clear()
+ var files = saveload.parse_dir("res://textures/thumbnails", ".png")
+ for turr in files:
+ thumbs[turr] = load("res://textures/thumbnails/" + turr)
diff --git a/scripts/placer.gd b/scripts/placer.gd
new file mode 100644
index 0000000..f06944e
--- /dev/null
+++ b/scripts/placer.gd
@@ -0,0 +1,210 @@
+extends Spatial
+
+var player : Spatial
+var world : VoxelMesh
+var turret_holder : Node
+var path_holder : Node
+var attach_point_holder : Node
+var load_turrets : Node
+var saveload_map : Node
+var load_scenes : Node
+var ptr : Spatial
+var resources : Node
+
+var normal = Vector3.ZERO
+var colliding = false
+var colliding_group = []
+var colliding_node : Spatial
+var collision_point : Vector3
+
+func _ready ():
+ player = get_parent()
+ resources = get_parent().get_node("resources")
+
+ var root = get_tree().root.get_child(0)
+ world = root.get_node("world")
+ turret_holder = root.get_node("turrets")
+ attach_point_holder = root.get_node("attach")
+ path_holder = root.get_node("path")
+ ptr = root.find_node("pointer");
+
+ var saveload = root.get_node("saveload")
+ load_turrets = saveload.get_node("load_turrets")
+ saveload_map = saveload.get_node("saveload_map")
+ load_scenes = saveload.get_node("load_scenes")
+
+ if !load_turrets.loaded: yield(load_turrets, "done_loading")
+
+func _physics_process(_delta):
+ _pointer()
+
+func check_overlap_pointer():
+ var overlap = false
+ var space = get_world().direct_space_state
+
+ var center = ptr.transform.origin + normal*0.25
+
+ var shape: = BoxShape.new()
+ shape.extents = Vector3(0.24, 0.24, 0.24)
+
+ var params: = PhysicsShapeQueryParameters.new()
+ params.set_shape(shape)
+ params.collision_mask = 3
+ params.transform = Transform.IDENTITY
+ params.transform.origin = center
+
+ var result = space.intersect_shape(params)
+ for body in result:
+ if !body.collider.get_parent().is_in_group("attach"):
+ overlap = true
+ break
+
+ for pos in world.get_voxels():
+ var wpos = pos * 0.5
+ wpos += Vector3.ONE * (0.5 / 2)
+ var dist = (wpos - center).length_squared()
+ if dist < 0.1:
+ overlap = true
+ break
+
+ for node in path_holder.get_children():
+ var pos = node.transform.origin
+ var dist = (pos - center).length_squared()
+ if dist < 0.1:
+ overlap = true
+ break
+
+ return overlap
+
+func _inst_turret (pos, rot):
+ var instance = load_scenes.turret.instance()
+ turret_holder.add_child(instance)
+ instance.transform.origin = pos;
+ instance.transform.basis = Basis(rot);
+ instance.refresh_normal()
+
+ var info = load_turrets.info[player.sel.name]
+ var model = load_turrets.models[info.model_name]
+ var instance_model = model.instance()
+ instance_model.name = "model"
+ instance.add_child(instance_model)
+ instance.refresh_model()
+
+ instance.refresh_info(info)
+
+func _inst_path_start (pos, rot):
+ var instance = load_scenes.path_start.instance()
+ path_holder.add_child(instance)
+ instance.transform.origin = pos + normal * 0.25;
+ instance.transform.basis = Basis(rot);
+
+func _inst_path (pos, rot):
+ var instance = load_scenes.path.instance()
+ path_holder.add_child(instance)
+ instance.transform.origin = pos + normal * 0.25;
+ instance.transform.basis = Basis(rot);
+ instance.set_name("path")
+ colliding_node.transform.basis = Basis(rot);
+
+func _inst_path_end (pos, rot):
+ var instance = load_scenes.path_end.instance()
+ path_holder.add_child(instance)
+ instance.transform.origin = pos + normal * 0.25
+ instance.transform.basis = Basis(rot);
+
+func _inst_attach (pos, rot):
+ var instance = load_scenes.attach_point.instance()
+ attach_point_holder.add_child(instance)
+ instance.transform.origin = pos;
+ instance.transform.basis = Basis(rot);
+
+func place (group, inst : FuncRef):
+ if Input.is_action_just_pressed("use"):
+ if colliding && group in colliding_group:
+ if !check_overlap_pointer():
+ inst.call_func(ptr.transform.origin, ptr.transform.basis.get_rotation_quat())
+ return "ok"
+
+func delete (group):
+ if Input.is_action_just_pressed("cancel"):
+ if colliding && group in colliding_group:
+ colliding_node.queue_free()
+
+func select ():
+ pass
+
+func _pointer ():
+ if player.sel.name == "" or player.sel.type == "": ptr.visible = false
+ else: ptr.visible = true
+
+ var space: PhysicsDirectSpaceState = get_world().direct_space_state as PhysicsDirectSpaceState
+ var mouse2d = get_viewport().get_mouse_position()
+ var from = player.camera.project_ray_origin(mouse2d)
+ var to = (from + player.camera.project_ray_normal(mouse2d) * 100)
+
+ ptr.transform.origin = to
+
+ var mask = 1
+ if player.sel.name.find("path") != -1: mask = 3
+
+ var result = space.intersect_ray(from, to, [], mask)
+ if result.size() > 0:
+ ptr.visible = true
+
+ colliding = true
+ normal = result.normal;
+ collision_point = result.position
+
+ var node = result.collider.get_parent()
+ colliding_node = node
+ colliding_group = node.get_groups()
+
+ if ("voxels" in colliding_group or "path" in colliding_group):
+ var cpos = result.position - normal * (0.5 / 2)
+ var cursor_position = (cpos / 0.5).floor() * 0.5
+ cursor_position += Vector3.ONE * (0.5 / 2) + normal * (0.5 / 2)
+ collision_point = cursor_position
+
+ if ("attach" in colliding_group):
+ collision_point = node.global_transform.origin;
+ normal = (node.global_transform.basis.get_rotation_quat() * Vector3.UP).normalized();
+
+ ptr.transform.basis = Basis(Utils.quat_look(normal, Vector3.UP))
+ ptr.transform.origin = collision_point
+ else:
+ colliding = false
+ colliding_group = []
+ ptr.visible = false
+
+ var placed = ""
+ match player.sel.type:
+ "map_tools":
+ match player.sel.name:
+ "start path":
+ place("path", funcref(self, "_inst_path_start"))
+ delete("path")
+ "path":
+ place("path", funcref(self, "_inst_path"))
+ delete("path")
+ "end path":
+ place("path", funcref(self, "_inst_path_end"))
+ delete("path")
+ "attach":
+ place("voxels", funcref(self, "_inst_attach"))
+ delete("attach")
+ "voxels":
+ pass
+ "turrets":
+ placed = place("attach", funcref(self, "_inst_turret"))
+ if placed == "ok" and !player.in_editor:
+ resources.sub(load_turrets.info[player.sel.name].cost)
+ delete("turret")
+
+ if placed == "ok":
+ player.sel.name = ""
+ player.sel.type = ""
+ if ptr.has_node("preview"):
+ ptr.get_node("preview").queue_free()
+ player.refresh_gui()
+ else:
+ select()
diff --git a/scripts/resources.gd b/scripts/resources.gd
new file mode 100644
index 0000000..1fc50c5
--- /dev/null
+++ b/scripts/resources.gd
@@ -0,0 +1,27 @@
+extends Node
+
+var T : float = 500
+var k : float = 0
+var a : float = 0
+var d : float = 0
+var s : float = 0
+
+func get_names(): return "Tkads"
+
+func dict_to_str (cost):
+ var st = ""
+ for n in cost.keys():
+ st += str(cost[n]) + n
+ return st
+
+func add (cost):
+ for n in cost.keys(): self[n] += cost[n]
+
+func sub (cost):
+ for n in cost.keys(): self[n] -= cost[n]
+
+func greater_than (cost):
+ for n in cost.keys():
+ if self[n] < cost[n]:
+ return false
+ return true
diff --git a/scripts/saveload.gd b/scripts/saveload.gd
new file mode 100644
index 0000000..9f7a203
--- /dev/null
+++ b/scripts/saveload.gd
@@ -0,0 +1,26 @@
+extends Node
+
+
+func load_parse_json (path):
+ var data_file = File.new()
+ if data_file.open(path, File.READ) != OK:
+ return
+ var data_text = data_file.get_as_text()
+ data_file.close()
+ var data_parse = JSON.parse(data_text)
+ if data_parse.error != OK:
+ return
+ var data = data_parse.result
+ return data
+
+func parse_dir (path : String, extension : String = ""):
+ var files = []
+ var dir = Directory.new()
+ dir.open(path)
+ dir.list_dir_begin(true)
+ var file = dir.get_next()
+ while file != "":
+ if file.ends_with(extension):
+ files.append(file)
+ file = dir.get_next()
+ return files