diff options
Diffstat (limited to 'scripts/placer.gd')
-rw-r--r-- | scripts/placer.gd | 210 |
1 files changed, 210 insertions, 0 deletions
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() |