diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/bullet.gd | 6 | ||||
-rw-r--r-- | scripts/debug.gd | 7 | ||||
-rw-r--r-- | scripts/enemies.gd | 41 | ||||
-rw-r--r-- | scripts/fx/fx_enemy_damage.gd | 5 | ||||
-rw-r--r-- | scripts/gui.gd | 27 | ||||
-rw-r--r-- | scripts/movement.gd | 398 | ||||
-rw-r--r-- | scripts/path.gd | 9 | ||||
-rw-r--r-- | scripts/turret.gd | 109 |
8 files changed, 229 insertions, 373 deletions
diff --git a/scripts/bullet.gd b/scripts/bullet.gd index 9b4434d..994d3d1 100644 --- a/scripts/bullet.gd +++ b/scripts/bullet.gd @@ -3,6 +3,8 @@ extends Spatial var _enemies_holder var shooter +var damage = 1 + var timer = 0 var time_life = 3 var speed = 7 @@ -10,7 +12,7 @@ var hit_something = false func _ready(): _enemies_holder = get_tree().root.get_child(0).find_node("enemies") - $Area.connect("body_entered", self, "collided") + var _err = $Area.connect("body_entered", self, "collided") func _physics_process(delta): var forward_dir = -global_transform.basis.z.normalized() @@ -27,7 +29,7 @@ func collided(body): if hit_something == false: var groups = parent.get_groups() if "enemies" in groups: - _enemies_holder.damage(parent.name) + _enemies_holder.damage(parent.name, damage) hit_something = true queue_free() diff --git a/scripts/debug.gd b/scripts/debug.gd index 339eec7..b65bd79 100644 --- a/scripts/debug.gd +++ b/scripts/debug.gd @@ -5,9 +5,9 @@ var _path var _enemies func _ready(): - _path = get_tree().root.get_child(0).find_node("path") - _player = get_tree().root.get_child(0).find_node("player") - _enemies = get_tree().root.get_child(0).find_node("enemies") + _path = get_tree().root.get_child(0).get_node("path") + _player = get_tree().root.get_child(0).get_node("player") + _enemies = get_tree().root.get_child(0).get_node("enemies") func _process(delta): pass @@ -16,7 +16,6 @@ func _process(delta): func _on_Button_button_down(): _enemies.spawn() - func _on_Button2_button_down(): var res = _path.load_nodes() _path.hide() diff --git a/scripts/enemies.gd b/scripts/enemies.gd index 08cc389..2144bdf 100644 --- a/scripts/enemies.gd +++ b/scripts/enemies.gd @@ -1,8 +1,11 @@ extends Node +var _resources : Node + var _path var _enemy_blue var _dissolve_mat : ShaderMaterial +var _enemy_mat : Material var _fx_holder var _fx_enemy_damage @@ -12,11 +15,27 @@ var _shapes = {} var serial_enemy = 0 var enemies = {} +var colors = [ + Color.red, + Color.purple, + Color.blue, + Color.mediumseagreen, + Color.green, + Color.greenyellow, + Color.yellow, + Color.orange, + Color.violet, + Color.indigo, +] + func _ready(): - _fx_holder = get_tree().root.get_child(0).find_node("fx") - _path = get_tree().root.get_child(0).find_node("path") + var root = get_tree().root.get_child(0) + _fx_holder = root.get_node("fx") + _path = root.get_node("path") + _resources = root.get_node("player").get_node("resources") _dissolve_mat = load("res://shaders/dissolve_mat.tres") + _enemy_mat = load("res://models/shapes/Enemy.material") _enemy_blue = load("res://scenes/enemy.tscn") _fx_enemy_damage = load("res://scenes/fx/enemy_damage.tscn") @@ -42,10 +61,13 @@ func spawn(): instance.name = str(serial_enemy) var instance_model = _shapes[_shapes.keys()[randi() % _shapes.size()]].instance() instance.add_child(instance_model) + instance_model.get_child(0).set_surface_material(0, _enemy_mat.duplicate()) + var axis : Vector3 = Quat(Vector3(0, randf()*TAU, 0)) * Vector3.RIGHT enemies[serial_enemy] = { "cur": 0, "hp": 10, "rel": 0, "ops": instance_model.name, - "axis": [axis.x, axis.y, axis.z] } + "axis": [axis.x, axis.y, axis.z] + } serial_enemy += 1 func node_from_id (id): @@ -87,18 +109,23 @@ func _physics_process(delta): var axis = Vector3(enemy.axis[0], enemy.axis[1], enemy.axis[2]) child.transform.basis = child.transform.basis.rotated(axis, delta) + + var mesh : MeshInstance = child.get_node(enemy.ops).get_child(0) + mesh.get_active_material(0).albedo_color = colors[enemy.hp-1] for id in delist: get_node(str(id)).queue_free() enemies.erase(id) -func damage(name): +func damage(name, amt): var id = int(name) var enemy = enemies[id] - enemies[id].hp -= 1 - fx_damage(name) + if enemy.hp > 0: + enemy.hp -= amt + _resources.add({ enemy.ops[0]: amt }) + fx_damage(name) func fx_damage(name): var id = int(name) @@ -114,4 +141,4 @@ func fx_damage(name): var instance_model = _shapes[enemy["ops"]].instance() instance.add_child(instance_model) - instance.refresh_shader(_dissolve_mat.duplicate()) + instance.refresh_shader(_dissolve_mat.duplicate(), colors[enemy.hp-1]) diff --git a/scripts/fx/fx_enemy_damage.gd b/scripts/fx/fx_enemy_damage.gd index 48f4629..2ec1d96 100644 --- a/scripts/fx/fx_enemy_damage.gd +++ b/scripts/fx/fx_enemy_damage.gd @@ -1,7 +1,7 @@ extends Spatial var timer = 0 -var timer_life = 0.5 +var timer_life = 1 var anim_size = 1 @@ -9,9 +9,10 @@ var _mesh : MeshInstance var base -func refresh_shader(mat): +func refresh_shader(mat, color : Color): _mesh = get_child(0).get_child(0) _mesh.set_surface_material(0, mat) + _mesh.get_active_material(0).set_shader_param("albedo", color) func refresh_basis(): base = transform.basis diff --git a/scripts/gui.gd b/scripts/gui.gd index bae4ffc..03a2e04 100644 --- a/scripts/gui.gd +++ b/scripts/gui.gd @@ -1,12 +1,23 @@ -extends Panel +extends Control -var _player -var _label +var player : Node +var _in_editor : bool -func _ready(): - _player = self.get_parent().get_parent().find_node("player") - _label = self.find_node("Label") +var bottom_bar : Control +var top_bar : Control + +func _fetch (): + var root = get_tree().root.get_child(0) + player = root.get_node("player") + + if bottom_bar == null: bottom_bar = get_node("bottom_bar") + if top_bar == null: top_bar = get_node("top_bar") -func _process(delta): - _label.text = str(_player.sel_map[_player.sel]) +func _ready(): + _fetch() + bottom_bar.build() +func refresh (in_editor : bool): + _fetch() + bottom_bar.refresh(in_editor) + top_bar.refresh(in_editor) diff --git a/scripts/movement.gd b/scripts/movement.gd index 0b7726d..587b338 100644 --- a/scripts/movement.gd +++ b/scripts/movement.gd @@ -1,209 +1,132 @@ extends KinematicBody +var in_editor : bool = false + var vel = Vector3() -var _mouse = Vector2() -var sensitivity_mouse = 0.1 +var camera = Camera -var _camera : Camera +var _mouse = Vector2() +var sensitivity_mouse = 10 -var _normal = Vector3.ZERO -var _colliding = false -var _colliding_group = [] -var _colliding_node -var _collision_point +var placer : Spatial var _pivot var _pivot_dist -var _pivot_rot -var _pivot_look +var _orbit_timer -var _world +var _world : VoxelMesh -var _turret : PackedScene -var _turret_holder -var _turret_blues = [] +var _gui : Control -var _attach_point -var _attach_point_holder +var _turret_holder : Node +var _attach_point_holder : Node +var path_holder : Node +var load_turrets : Node +var ptr : Node -var _path_start -var _path -var _path_end -var _path_holder +var _enemies : Node -var sel = 0; -var sel_map = [ - "turrets", "path start", "path", "path end", "attach point" -] +var sel = { + "type": "", + "name": "" +} func _ready(): - _camera = $Camera + camera = $camera + placer = $placer - _world = self.get_parent().find_node("world") - _turret_holder = self.get_parent().find_node("turrets") - _path_holder = self.get_parent().find_node("path") - _attach_point_holder = self.get_parent().find_node("attach") + var root = get_tree().root.get_child(0) - _turret = load("res://scenes/turret.tscn") - _path_start = load("res://scenes/path_start.tscn") - _path = load("res://scenes/path.tscn") - _path_end = load("res://scenes/path_end.tscn") - _attach_point = load("res://scenes/attach_point.tscn") + path_holder = root.get_node("path") + _gui = root.get_node("gui") + _enemies = root.get_node("enemies") + ptr = root.find_node("pointer"); - load_turrets() + var saveload = root.get_node("saveload") + load_turrets = saveload.get_node("load_turrets") - #_save() - _load() - -func load_turrets(): - _turret_blues = [] - var dir = Directory.new() - dir.open("res://models/turrets") - dir.list_dir_begin(true) - var turr = dir.get_next() - while turr != "": - if (turr.ends_with(".glb")): - _turret_blues.append(load("res://models/turrets/" + turr)) - turr = dir.get_next() - -func get_map_state (): - var state = {} + _gui.refresh(in_editor) - 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] + refresh_path() - 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] +func refresh_gui(): + _gui.refresh(in_editor) - 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): - _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() +func gui_editor_toggle_event (): + in_editor = !in_editor + _gui.refresh(in_editor) + refresh_path() - clear_children(_path_holder) - for pobj in state["path"]: - var blue = _path - if "start" in pobj.id: - blue = _path_start - if "end" in pobj.id: - blue = _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); +func gui_start_wave_event (): + refresh_path() + _enemies.spawn() + _gui.refresh(in_editor) - clear_children(_attach_point_holder) - for pobj in state["attach"]: - var blue = _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 _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 _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"): - _save() - if Input.is_action_just_released("load"): - _load() - -func clear_children (node): - for n in node.get_children(): - node.remove_child(n) - n.queue_free() - -func look_free (delta, m): +func refresh_path(): + if in_editor: + path_holder.show() + else: + var _res = path_holder.load_nodes() + path_holder.hide() + +func selected_event (sel_name, sel_type): + sel.name = sel_name + sel.type = sel_type + _gui.refresh(in_editor) + + if sel_type == "turrets": + var info = load_turrets.info[sel.name] + var model = load_turrets.models[info.model_name] + var instance_model = model.instance() + instance_model.name = "preview" + ptr.add_child(instance_model) + elif sel_type != "": + ptr.get_node("base").visible = true + +func look_free (m): self.transform.basis = self.transform.basis.rotated(Vector3.UP, m.x) var rrrot = self.transform.basis.get_rotation_quat() self.transform.basis = self.transform.basis.rotated(rrrot*Vector3.RIGHT, m.y) -func look_orbit(delta, m): +func look_orbit(m): var diff : Vector3 = self.transform.origin - _pivot + _pivot_dist = diff.length() var orbit : Basis = Transform.looking_at(diff, Vector3.UP).basis orbit = orbit.rotated(Vector3.UP, m.x) orbit = orbit.rotated(orbit.get_rotation_quat()*Vector3.RIGHT, -m.y) - self.transform.basis = self.transform.basis.rotated(Vector3.UP, m.x) - var rrrot = self.transform.basis.get_rotation_quat() - self.transform.basis = self.transform.basis.rotated(rrrot*Vector3.RIGHT, m.y) - var normdiff = diff.normalized() self.transform.origin = _pivot - orbit.z * _pivot_dist + + diff = self.transform.origin - _pivot + self.transform.basis = self.transform.basis.slerp( \ + Transform.looking_at(-diff, Vector3.UP).basis, _orbit_timer) + func _move_input(delta): - var dir = Vector3() - var m = _mouse + m *= delta _mouse = Vector2() - - var orbiting = false if Input.is_action_just_pressed("orbit"): - if _colliding: - _pivot = _collision_point + if placer.colliding: + _pivot = placer.collision_point var diff : Vector3 = self.transform.origin - _pivot - _pivot_rot = Transform.looking_at(diff, Vector3.UP).basis.get_rotation_quat() _pivot_dist = diff.length() - _pivot_look = Transform(Basis(), _collision_point) + _orbit_timer = 0 else: _pivot = null + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + if Input.is_action_pressed("orbit"): + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) if _pivot != null: - orbiting = true - look_orbit(delta, m) + _orbit_timer = min(1, _orbit_timer+delta * 2) + look_orbit(m) else: - look_free(delta, m) - - Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) - - if Input.is_action_pressed("look"): - look_free(delta, m) + look_free(m) + elif Input.is_action_pressed("look"): + look_free(m) Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) var input_movement_vector = Vector3() @@ -221,7 +144,7 @@ func _move_input(delta): input_movement_vector.y -= 1 input_movement_vector = input_movement_vector.normalized() - dir = self.transform.basis.get_rotation_quat() * input_movement_vector + var dir : Vector3 = self.transform.basis.get_rotation_quat() * input_movement_vector vel += dir * delta; vel *= 0.8 @@ -230,164 +153,7 @@ func _move_input(delta): if collision: vel = Vector3(0, 0, 0) func _physics_process(delta): - if Input.is_action_just_released("cycle_forward"): - sel += 1 - if sel >= len(sel_map): - sel = len(sel_map)-1 - if Input.is_action_just_released("cycle_backward"): - sel -= 1 - if sel < 0: - sel = 0 - _move_input(delta) - _pointer() - -func check_overlap_pointer(): - var ptr = self.get_parent().find_node("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 = _turret.instance() - _turret_holder.add_child(instance) - instance.transform.origin = pos; - instance.transform.basis = Basis(rot); - instance.refresh_normal() - var instance_model = _turret_blues[0].instance() - instance_model.name = "model" - instance.add_child(instance_model) - instance.refresh_model() - -func _inst_path_start (pos, rot): - var instance = _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 = _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 = _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 = _attach_point.instance() - _attach_point_holder.add_child(instance) - instance.transform.origin = pos; - instance.transform.basis = Basis(rot); - -func place (group, inst : FuncRef): - var ptr = self.get_parent().find_node("pointer"); - 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()) - -func delete (group): - if Input.is_action_just_pressed("cancel"): - if _colliding && group in _colliding_group: - _colliding_node.queue_free() - -func _pointer (): - var ptr = self.get_parent().find_node("pointer"); - - var space: PhysicsDirectSpaceState = get_world().direct_space_state as PhysicsDirectSpaceState - var mouse2d = get_viewport().get_mouse_position() - var from = _camera.project_ray_origin(mouse2d) - var to = (from + _camera.project_ray_normal(mouse2d) * 5) - - ptr.transform.origin = to - - var mask = 1 - if sel in [1, 2, 3]: mask = 3 - var result = space.intersect_ray(from, to, [], mask) - if result.size() > 0: - ptr.get_child(0).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.get_child(0).visible = false - - match sel: - 0: - place("attach", funcref(self, "_inst_turret")) - delete("turret") - 1: - place("voxels", funcref(self, "_inst_path_start")) - delete("path") - 2: - place("path", funcref(self, "_inst_path")) - delete("path") - 3: - place("path", funcref(self, "_inst_path_end")) - delete("path") - 4: - place("voxels", funcref(self, "_inst_attach")) - delete("attach") func _input(event): if event is InputEventMouseMotion: diff --git a/scripts/path.gd b/scripts/path.gd index bd3b40f..f8c0fb7 100644 --- a/scripts/path.gd +++ b/scripts/path.gd @@ -8,9 +8,6 @@ const dirs = [ var nodes = [] - -func _ready(): - pass # Replace with function body. func next_node (node, dir): var pos : Vector3 = node.transform.origin @@ -59,13 +56,13 @@ func load_nodes (): func hide (): for child in get_children(): - var mesh = child.find_node("MeshInstance") + var mesh = child.get_node("MeshInstance") mesh.visible = false func show (): for child in get_children(): - var mesh = child.find_node("MeshInstance") - mesh.visible = false + var mesh = child.get_node("MeshInstance") + mesh.visible = true # Called every frame. 'delta' is the elapsed time since the previous frame. #func _process(delta): diff --git a/scripts/turret.gd b/scripts/turret.gd index cc90dd4..9dce497 100644 --- a/scripts/turret.gd +++ b/scripts/turret.gd @@ -1,28 +1,30 @@ extends Spatial -var _path -var _enemies -var _projectiles_holder +var _path : Node +var _enemies : Node +var _projectiles_holder : Node +var _enemies_holder : Node -var _base -var _gun -var _shooting_point -var _normal +var _base : Spatial +var _gun : Spatial +var _shooting_point : Vector3 +var _normal : Vector3 var aim_mode = "first" var _target = null -var _range = 10 +var projectile : PackedScene -var projectile +var info : Dictionary -var cooldown = 0.1 var cooldown_timer = 0 func _ready(): - _path = get_tree().root.get_child(0).find_node("path") - _enemies = get_tree().root.get_child(0).find_node("enemies") - _projectiles_holder = get_tree().root.get_child(0).find_node("projectiles") + var root = get_tree().root.get_child(0) + _path = root.get_node("path") + _enemies = root.get_node("enemies") + _projectiles_holder = root.get_node("projectiles") + _enemies_holder = root.find_node("enemies") projectile = load("res://scenes/projectiles/bullet.tscn") @@ -34,17 +36,20 @@ func refresh_model(): _base = get_node("model").find_node("pivot*").find_node("base*") _gun = _base.find_node("gun*") +func refresh_info(tinfo): + self.info = tinfo + func filter_in_range(set): var filtered = [] for target in set: var node = _enemies.node_from_id(target) var dist = (node.transform.origin - _shooting_point).length_squared() - if dist < _range*_range: + if dist < info.range*info.range: filtered += [target] return filtered func filter_visible(set): - var space: PhysicsDirectSpaceState = get_world().direct_space_state as PhysicsDirectSpaceState + var space: PhysicsDirectSpaceState = get_world().direct_space_state var from = _shooting_point var filtered = [] @@ -86,28 +91,76 @@ func _physics_process(delta): var direction = (enemy.transform.origin - _shooting_point).normalized() var proj_normal = direction - _normal.dot(direction) * _normal - var base_rot = Transform().looking_at(proj_normal, _normal).basis.get_rotation_quat() + var base_rot : Quat = Transform().looking_at(proj_normal, _normal).basis.get_rotation_quat() - var perp = proj_normal.cross(_normal).normalized() + var perp = -proj_normal.cross(_normal).normalized() var proj_forward = direction - perp.dot(direction) * perp - var gun_rot = Transform().looking_at(proj_forward, perp).basis.get_rotation_quat() + var gun_rot : Quat = Transform().looking_at(proj_forward, perp).basis.get_rotation_quat() gun_rot = Quat(direction, PI/2) * gun_rot + gun_rot = gun_rot.normalized() + gun_rot = base_rot.inverse() * gun_rot - _base.global_transform.basis = Basis(base_rot) - _gun.global_transform.basis = Basis(gun_rot) + var base_basis = _base.global_transform.basis.get_rotation_quat() + var base_angle = base_basis.angle_to(base_rot) + if base_angle > 0.01: + var base_amt = (info.turn_speed * delta) / base_angle + base_amt = min(1, base_amt) + _base.global_transform.basis = Basis(base_basis.slerp(Basis(base_rot), base_amt)) + + var gun_basis = _gun.transform.basis.get_rotation_quat() + var gun_angle = gun_basis.angle_to(gun_rot) + if gun_angle > 0.01: + var gun_amt = (info.turn_speed * delta) / gun_angle + gun_amt = min(1, gun_amt) + _gun.transform.basis = Basis(gun_basis.slerp(Basis(gun_rot), gun_amt)) cooldown_timer += delta - if cooldown_timer > cooldown: - cooldown_timer -= cooldown - shoot(direction) + if cooldown_timer > info.cooldown: + cooldown_timer -= info.cooldown + shoot() + +func spread (amt : int) -> Array: + var dirs = [] + var width : int = ceil(sqrt(amt)) + for i in amt: + var dir = _gun.global_transform.basis + var x = floor(i%width)-width/2+(width+1)%2*0.5 + var y = floor(i/width)-floor(sqrt(amt)-1)/2 + var spread = info.projectile.spread + dir = dir.rotated(_normal, deg2rad(x*spread)) + dir = dir.rotated(_normal.cross(dir.z).normalized(), deg2rad(y*spread)) + dirs.append(dir) + return dirs -func shoot (dir): - shoot_projectile(dir) +func shoot (): + if info.projectile.amount > 1: + for dir in spread(info.projectile.amount): + match info.projectile.type: + "bullet": shoot_bullet(dir) + "ray": shoot_ray(dir) + else: + match info.projectile.type: + "bullet": shoot_bullet(_gun.global_transform.basis) + "ray": shoot_ray(_gun.global_transform.basis) -func shoot_projectile (dir): +func shoot_bullet (dir : Basis): var instance = projectile.instance() _projectiles_holder.add_child(instance) - instance.transform = Transform().looking_at(dir, _normal) - instance.transform.origin = _shooting_point + dir*0.3; + instance.transform.basis = dir + instance.transform.origin = _shooting_point - dir.z*0.3; instance.shooter = self + instance.damage = info.damage + instance.speed = info.projectile.speed + +func shoot_ray (dir : Basis): + var space: PhysicsDirectSpaceState = get_world().direct_space_state + var from = _shooting_point + var to = _shooting_point - dir.z*info.range; + + var result = space.intersect_ray(from, to, _path.nodes, 1) + if result.size() > 0: + var parent = result.collider.get_parent() + var groups = parent.get_groups() + if "enemies" in groups: + _enemies_holder.damage(parent.name, info.damage) |