diff --git a/project.godot b/project.godot index bc3a5ad..ae0e618 100644 --- a/project.godot +++ b/project.godot @@ -86,3 +86,18 @@ detect={ "events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":3,"pressure":0.0,"pressed":true,"script":null) ] } +"lay trap"={ +"deadzone": 0.2, +"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":2,"pressure":0.0,"pressed":true,"script":null) +] +} +attack={ +"deadzone": 0.2, +"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":true,"script":null) +] +} +detonate={ +"deadzone": 0.2, +"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null) +] +} diff --git a/scenes/test_level.tscn b/scenes/test_level.tscn index c8d1622..68cbf7f 100644 --- a/scenes/test_level.tscn +++ b/scenes/test_level.tscn @@ -1,22 +1,11 @@ -[gd_scene load_steps=11 format=3 uid="uid://by6suwmds7xq2"] +[gd_scene load_steps=6 format=3 uid="uid://by6suwmds7xq2"] [ext_resource type="Script" uid="uid://d3t381vws7vns" path="res://scripts/test_level.gd" id="1_qcd3b"] [ext_resource type="PackedScene" uid="uid://bgocskbofewsr" path="res://templates/HUD.tscn" id="1_x4b8f"] [ext_resource type="Script" uid="uid://cymi1n4gavixy" path="res://scripts/level_camera.gd" id="3_qcd3b"] -[ext_resource type="ArrayMesh" uid="uid://bih57xe642hrc" path="res://models/trap.obj" id="4_tmr53"] -[ext_resource type="Texture2D" uid="uid://dri0a20l6kpbj" path="res://visuals/images/icon.svg" id="6_ahbqi"] [ext_resource type="MeshLibrary" uid="uid://bhpyvhf36jl0f" path="res://testing.tres" id="7_88ety"] [ext_resource type="MeshLibrary" uid="uid://cvhm40o2uw5mr" path="res://testing markers.tres" id="7_ahbqi"] -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_qcd3b"] -albedo_color = Color(0, 0, 1, 1) - -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_88ety"] -albedo_color = Color(1, 0, 0, 1) - -[sub_resource type="BoxShape3D" id="BoxShape3D_dw7u0"] -size = Vector3(0.8, 1, 0.8) - [node name="Node3D" type="Node3D"] script = ExtResource("1_qcd3b") @@ -31,25 +20,6 @@ projection = 1 size = 5.0 script = ExtResource("3_qcd3b") -[node name="Area3D" type="Area3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.496, 0, 0.479267) - -[node name="Trap" type="MeshInstance3D" parent="Area3D"] -transform = Transform3D(0.25, 0, 0, 0, 0.25, 0, 0, 0, 0.25, 0, 0, 0) -material_overlay = SubResource("StandardMaterial3D_qcd3b") -mesh = ExtResource("4_tmr53") -skeleton = NodePath("") -surface_material_override/0 = SubResource("StandardMaterial3D_88ety") - -[node name="CollisionShape3D" type="CollisionShape3D" parent="Area3D"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) -shape = SubResource("BoxShape3D_dw7u0") - -[node name="Sprite3D" type="Sprite3D" parent="Area3D"] -transform = Transform3D(1, 0, 0, 0, -4.371139e-08, -1, 0, 1, -4.371139e-08, 0, 0.05, 0) -visible = false -texture = ExtResource("6_ahbqi") - [node name="OmniLight3D" type="OmniLight3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 18.508709, 0) omni_range = 25.142 diff --git a/scripts/autos/game.gd b/scripts/autos/game.gd index 46da4e7..10f133d 100644 --- a/scripts/autos/game.gd +++ b/scripts/autos/game.gd @@ -1,14 +1,8 @@ extends Node -enum TrapType{ - BOMB, - MINE, - GAS, - FORCE_PANEL, - SWITCH, - PITFALL -} + const blinder_template = preload("res://templates/blinder.tscn") +const one_shot_template = preload("res://templates/one_shot.tscn") const vs_man_level = preload("res://scenes/multiplayer_test.tscn") @@ -41,3 +35,11 @@ func start_vs_man() -> void: var spawner = get_tree().get_first_node_in_group("level_spawner") as MultiplayerSpawner spawner.add_child(level) + +func oneshot(stream : AudioStream) -> void: + var shot = one_shot_template.instantiate() + shot.stream = stream + if level: + level.add_child(shot) + else: + add_child(shot) diff --git a/scripts/autos/multiplayer.gd b/scripts/autos/multiplayer.gd index 117533d..760d476 100644 --- a/scripts/autos/multiplayer.gd +++ b/scripts/autos/multiplayer.gd @@ -4,7 +4,7 @@ extends Node const SERVER_PORT = 8080 const SERVER_IP = "127.0.0.1" var handle : String -var id : int +var id : int = 1 var players : Dictionary = {} signal client_added(handle : String, id : int) diff --git a/scripts/disarm_trap_modal.gd b/scripts/disarm_trap_modal.gd new file mode 100644 index 0000000..3ecebb0 --- /dev/null +++ b/scripts/disarm_trap_modal.gd @@ -0,0 +1,103 @@ +class_name DisarmTrapModal extends Control + + +const action_value : Dictionary[String, int] = { + "detonate" : 0, + "lay trap" : 1, + "detect" : 2, + "attack" : 3 +} + +const icon_textures : Array = [ + { + "normal" : preload("res://visuals/images/icons/switch button.png"), + "pressed" : preload("res://visuals/images/icons/lit switch button.png") + }, + { + "normal" : preload("res://visuals/images/icons/trap button.png"), + "pressed" : preload("res://visuals/images/icons/lit trap button.png") + }, + { + "normal" : preload("res://visuals/images/icons/detect button.png"), + "pressed" : preload("res://visuals/images/icons/lit detect button.png") + }, + { + "normal" : preload("res://visuals/images/icons/ranged attack button.png"), + "pressed" : preload("res://visuals/images/icons/lit ranged attack button.png") + }, +] + +const disarm_icon_template = preload("res://templates/disarm_icon.tscn") +const success_sound = preload("res://audio/sounds/menu select.wav") +const fail_sound = preload("res://audio/sounds/134688__otbtechno__bike-bell.wav") +const progress_sound = preload("res://audio/sounds/BUTTON Generic Metal Medium High Mechanics 02.wav") + +@onready var confirmation_dialog : ConfirmationDialog = %ConfirmationDialog +@onready var disarm_window : PanelContainer = %DisarmWindow +@onready var disarm_button_container : HBoxContainer = %DisarmContainer +@onready var timer : Timer = %Timer +@onready var timer_label : Label = %TimerLabel + + +var square : Vector3i +var disarm_icons : Array[TextureButton] +var disarm_buttons : Array[int] +var progress : int +var disarming : bool + +var difficulty : int = 1 + + +func _process(delta: float) -> void: + timer_label.text = "%02d.3" % timer.time_left + +func start_disarming() -> void: + disarming = true + progress = 0 + disarm_icons = [] + disarm_buttons = [] + for i in range(difficulty): + var btn = randi_range(0,3) + var icon : TextureButton = disarm_icon_template.instantiate() + icon.texture_normal = icon_textures[btn].normal + icon.texture_pressed = icon_textures[btn].pressed + disarm_buttons.append(btn) + disarm_icons.append(icon) + disarm_button_container.add_child(icon) + confirmation_dialog.visible = false + disarm_window.visible = true + timer.start(3 + (2 * len(disarm_buttons) * randf_range(.75, 1.25) )) + +func try_advance(btn : int) -> void: + + if btn == disarm_buttons[progress]: + disarm_icons[progress].set_pressed_no_signal(true) + progress += 1 + if progress >= len(disarm_buttons): + Game.player.close_modal() + Game.oneshot(success_sound) + Game.level.disarm_trap(square) + else: + Game.oneshot(progress_sound) + else: + Game.player.close_modal() + Game.oneshot(fail_sound) + Game.level.activate_trap(square) + + +func button_pressed(event : InputEventAction) -> void: + if disarming: + try_advance(action_value[event.action]) + else: + match(event.action): + "detonate": + start_disarming() + "attack": + Game.player.close_modal() + _: return + + +func _on_timer_timeout() -> void: + Game.player.close_modal() + Game.oneshot(fail_sound) + Game.level.activate_trap(square) diff --git a/scripts/disarm_trap_modal.gd.uid b/scripts/disarm_trap_modal.gd.uid new file mode 100644 index 0000000..bca239d --- /dev/null +++ b/scripts/disarm_trap_modal.gd.uid @@ -0,0 +1 @@ +uid://5nrsscwod1xg diff --git a/scripts/one_shot.gd b/scripts/one_shot.gd new file mode 100644 index 0000000..fa0ffa0 --- /dev/null +++ b/scripts/one_shot.gd @@ -0,0 +1,8 @@ +extends AudioStreamPlayer + +func _ready() -> void: + $Timer.start(stream.get_length()) + + +func _on_timeout() -> void: + queue_free() diff --git a/scripts/one_shot.gd.uid b/scripts/one_shot.gd.uid new file mode 100644 index 0000000..279b35b --- /dev/null +++ b/scripts/one_shot.gd.uid @@ -0,0 +1 @@ +uid://cb72nk0ddi3c diff --git a/scripts/player.gd b/scripts/player.gd index 2c03eef..a76aa56 100644 --- a/scripts/player.gd +++ b/scripts/player.gd @@ -1,21 +1,34 @@ class_name Player extends CharacterBody3D +const trap_template = preload("res://templates/trap.tscn") +const remove_trap_modal = preload("res://templates/remove_trap_modal.tscn") +const disarm_trap_modal = preload("res://templates/disarm_trap_modal.tscn") + @export var speed : float = 10 @onready var body = $Body -@onready var data : PlayerData = $Data +@onready var data : PlayerData = $Data +@onready var trap_sound : AudioStreamPlayer3D = $TrapSound +var button_actions : Dictionary[int, String] var current_square : Vector3i -var detecting : bool +var detecting : bool = false var detect_squares : Dictionary[Vector3i, bool] = {} +var input_locked : bool = false +var action_tween : Tween = null + +var modal = null + signal trap_cycled(trap_index) signal trap_quantity_changed(trap_index, quantity) signal trap_list_changed(traps) - + func _physics_process(delta: float) -> void: var dir = Input.get_vector("west", "east", "north", "south") dir = Vector3(dir.x, 0, dir.y) + if input_locked or modal != null: + dir = Vector3.ZERO if dir.length_squared() > 0: body.look_at(body.global_position - dir) velocity = speed * dir @@ -24,18 +37,70 @@ func _physics_process(delta: float) -> void: if !is_on_floor(): velocity += get_gravity() move_and_slide() + elif !is_on_floor(): + velocity = get_gravity() + move_and_slide() + if detecting: update_detecting() - - if Input.is_action_just_pressed("left cycle trap"): - cycle_active_trap(-1) - if Input.is_action_just_pressed("right cycle trap"): - cycle_active_trap(1) - if Input.is_action_just_pressed("detect"): - start_detecting() - elif Input.is_action_just_released("detect"): - stop_detecting() + + if !input_locked: + if modal: + var evt = InputEventAction.new() + var buttons = [ + "lay trap", + "detect", + "attack", + "detonate" + ] + for button in buttons: + if Input.is_action_just_pressed(button): + evt.action = button + evt.pressed = true + modal.button_pressed(evt) + else: + if Input.is_action_just_pressed("left cycle trap"): + cycle_active_trap(-1) + if Input.is_action_just_pressed("right cycle trap"): + cycle_active_trap(1) + if Input.is_action_just_pressed("detect"): + start_detecting() + elif Input.is_action_just_released("detect"): + stop_detecting() + if !detecting and Input.is_action_just_pressed("lay trap"): + try_lay_trap() +func try_lay_trap() -> void: + if !is_on_floor(): + return + + if data.traps[data.active_trap].quantity < 1: + return + + var square : Vector3i = (global_position - Vector3.ONE * .5).round() + if !Game.level.is_valid_trap_square(square): + return + + action_tween = create_tween() + input_locked = true + action_tween.tween_interval(.2) + action_tween.tween_callback(Callable(lay_trap).bind(square, data.active_trap)) + action_tween.tween_interval(.25) + action_tween.tween_callback(clear_action) + +func lay_trap(square : Vector3i, idx : int) -> void: + var type : Trap.Type = data.traps[idx].type + var trap = trap_template.instantiate() + trap.setup(type, Multiplayer.id) + trap.disarmed.connect(_on_trap_disarmed) + data.traps[idx].quantity -= 1 + trap_quantity_changed.emit(idx, data.traps[idx].quantity) + Game.level.add_trap(trap, square) + trap_sound.play() + +func clear_action() -> void: + input_locked = false + action_tween = null func update_detecting() -> void: var new_square : Vector3i = (global_position - Vector3.ONE * .5).round() @@ -68,9 +133,30 @@ func update_detecting() -> void: for key in remove_list: detect_squares.erase(key) + var trap : Trap = Game.level.get_square_trap(current_square) + if trap != null: + if trap.trap_owner == Multiplayer.id: + show_remove_trap_modal() + else: + show_disarm_trap_modal() + +func close_modal() -> void: + modal.queue_free() + modal = null +func show_remove_trap_modal() -> void: + stop_detecting() + modal = remove_trap_modal.instantiate() + modal.square = current_square + Game.level.add_child(modal) +func show_disarm_trap_modal() -> void: + stop_detecting() + modal = disarm_trap_modal.instantiate() + modal.difficulty = Game.level.difficulty + modal.square = current_square + Game.level.add_child(modal) func start_detecting() -> void: detecting = true @@ -92,6 +178,10 @@ func start_detecting() -> void: for key in remove_list: detect_squares.erase(key) + var trap : Trap = Game.level.get_square_trap(current_square) + if trap != null: + if trap.trap_owner == Multiplayer.id: + show_remove_trap_modal() func stop_detecting() -> void: detecting = false @@ -103,6 +193,17 @@ func setup(traps) -> void: $Data.traps = traps Game.setup_player(self) +func remove_trap_at(square) -> void: + var trap : Trap = Game.level.traps[square] + for i in range(len(data.traps)): + var d = data.traps[i] + if d.type == trap.type: + d.quantity += 1 + trap_quantity_changed.emit(i, d.quantity) + break + trap.queue_free() + Game.level.traps.erase(square) + func cycle_active_trap(dir) -> void: var prev = data.active_trap data.active_trap += dir @@ -114,3 +215,11 @@ func cycle_active_trap(dir) -> void: if prev != data.active_trap: trap_cycled.emit(data.active_trap) + +func _on_trap_disarmed(type : Trap.Type) -> void: + for i in range(len(data.traps)): + var d = data.traps[i] + if d.type == type: + d.max -= 1 + trap_quantity_changed.emit(i, d.quantity) + break diff --git a/scripts/player_data.gd b/scripts/player_data.gd index d21d59e..6c3caa6 100644 --- a/scripts/player_data.gd +++ b/scripts/player_data.gd @@ -1,11 +1,11 @@ class_name PlayerData extends Node class TrapData: - var type : Game.TrapType + var type : Trap.Type var quantity : int var max : int - func _init(type : Game.TrapType, quantity : int, max : int) -> void: + func _init(type : Trap.Type, quantity : int, max : int) -> void: self.type = type self.quantity = quantity self.max = max diff --git a/scripts/remove_trap_modal.gd b/scripts/remove_trap_modal.gd new file mode 100644 index 0000000..aa53c4d --- /dev/null +++ b/scripts/remove_trap_modal.gd @@ -0,0 +1,12 @@ +class_name RemoveTrapModal extends ConfirmationDialog + +var square : Vector3i + +func button_pressed(event : InputEventAction) -> void: + match(event.action): + "detonate": + Game.player.remove_trap_at(square) + Game.player.close_modal() + "attack": + Game.player.close_modal() + _: return diff --git a/scripts/remove_trap_modal.gd.uid b/scripts/remove_trap_modal.gd.uid new file mode 100644 index 0000000..8f8d730 --- /dev/null +++ b/scripts/remove_trap_modal.gd.uid @@ -0,0 +1 @@ +uid://bj1udbw3sm73f diff --git a/scripts/test_level.gd b/scripts/test_level.gd index 794feac..dbca205 100644 --- a/scripts/test_level.gd +++ b/scripts/test_level.gd @@ -1,26 +1,71 @@ class_name Level extends Node3D const player_controller = preload("res://templates/singleplayer_pc.tscn") +const trap_template = preload("res://templates/trap.tscn") @onready var floor_layer : GridMap = %Floor @onready var marker_layer : GridMap = %Markers +@export var difficulty : int = 1 + +var traps : Dictionary[Vector3i, Trap] = {} + +func _ready() -> void: + Game.level = self + var player = player_controller.instantiate() + var traps : Array[PlayerData.TrapData] = [ + PlayerData.TrapData.new(Trap.Type.BOMB, 3, 3), + PlayerData.TrapData.new(Trap.Type.SWITCH, 3, 3), + PlayerData.TrapData.new(Trap.Type.MINE, 3, 3) + ] + add_child(player) + generate_trap(Trap.Type.MINE, Vector3i(5,0,2)) + player.setup(traps) + +func is_square_detected(crd) -> bool: + return marker_layer.get_cell_item(crd + Vector3i(0,-1,0)) != GridMap.INVALID_CELL_ITEM + func detect_square(crd : Vector3i, mark : bool) -> bool: var cell = floor_layer.get_cell_item(crd) if cell == GridMap.INVALID_CELL_ITEM: return false marker_layer.set_cell_item(crd, 0 if mark else GridMap.INVALID_CELL_ITEM) + if mark: + var trap_crd = crd + Vector3i(0,1,0) + if traps.has(trap_crd): + var trap : Trap = traps[trap_crd] + if trap.trap_owner != Multiplayer.id: + trap.reveal() + return true + +func add_trap(trap : Trap, crd : Vector3i) -> void: + trap.square = crd + traps[crd] = trap + trap.global_position = Vector3(crd) + Vector3(.5, 0, .5) + add_child(trap) + pass + +func get_square_trap(crd : Vector3i) -> Trap: + if traps.has(crd): + return traps[crd] + else: + return null + +func is_valid_trap_square(crd : Vector3i) -> bool: + if floor_layer.get_cell_item(crd + Vector3i(0,-1,0)) == GridMap.INVALID_CELL_ITEM: + return false + if traps.has(crd): + return false return true -func _ready() -> void: - Game.level = self - var player = player_controller.instantiate() - var traps : Array[PlayerData.TrapData] = [ - PlayerData.TrapData.new(Game.TrapType.BOMB, 3, 3), - PlayerData.TrapData.new(Game.TrapType.SWITCH, 3, 3), - PlayerData.TrapData.new(Game.TrapType.MINE, 3, 3) - ] - add_child(player) - player.setup(traps) +func generate_trap(type : Trap.Type, square : Vector3i): + var trap = trap_template.instantiate() + trap.setup(type, -1) + add_trap(trap, square) + +func disarm_trap(crd : Vector3i) -> void: + var trap = traps[crd] + trap.disarm() + traps.erase(crd) diff --git a/scripts/trap.gd b/scripts/trap.gd new file mode 100644 index 0000000..0c85bde --- /dev/null +++ b/scripts/trap.gd @@ -0,0 +1,54 @@ +class_name Trap extends Area3D + +enum Type{ + BOMB, + MINE, + GAS, + FORCE_PANEL, + SWITCH, + PITFALL +} + +const trap_icons : Dictionary = { + Trap.Type.BOMB : preload("res://visuals/images/icons/t-bomb.png"), + Trap.Type.GAS : preload("res://visuals/images/icons/t-gas.png"), + Trap.Type.PITFALL : preload("res://visuals/images/icons/t-pitfall.png"), + Trap.Type.FORCE_PANEL : preload("res://visuals/images/icons/t-force_panel.png"), + Trap.Type.SWITCH : preload("res://visuals/images/icons/t-switch.png"), + Trap.Type.MINE : preload("res://visuals/images/icons/t-mine.png"), +} + +@onready var model : MeshInstance3D = %Model +@onready var icon : Sprite3D = %Icon +@onready var material : StandardMaterial3D = model.get_surface_override_material(0) +@onready var reveal_timer : Timer = %RevealTimer +var type : Type +var square : Vector3i +var trap_owner : int +signal disarmed(type : Trap.Type) + + +func setup(type : Type, trap_owner : int) -> void: + self.type = type + self.trap_owner = trap_owner + +func disarm() -> void: + disarmed.emit(type) + queue_free() + +func reveal() -> void: + model.visible = true + reveal_timer.start(5) + +func _on_reveal_timeout() -> void: + if Game.level.is_square_detected(square): + reveal_timer.start(5) + else: + model.visible = false + +func _ready() -> void: + var owns_trap = trap_owner == Multiplayer.id + icon.texture = trap_icons[type] + model.visible = owns_trap + icon.visible = owns_trap + material.albedo_color = Color.YELLOW if owns_trap else Color.RED diff --git a/scripts/trap.gd.uid b/scripts/trap.gd.uid new file mode 100644 index 0000000..98c217b --- /dev/null +++ b/scripts/trap.gd.uid @@ -0,0 +1 @@ +uid://yjsgte3x7jjw diff --git a/scripts/trap_icon.gd b/scripts/trap_icon.gd index 96bb7f9..5f4f68f 100644 --- a/scripts/trap_icon.gd +++ b/scripts/trap_icon.gd @@ -1,18 +1,18 @@ class_name TrapIcon extends Control const trap_icons : Dictionary = { - Game.TrapType.BOMB : preload("res://visuals/images/icons/bomb.png"), - Game.TrapType.GAS : preload("res://visuals/images/icons/gas.png"), - Game.TrapType.PITFALL : preload("res://visuals/images/icons/pitfall.png"), - Game.TrapType.FORCE_PANEL : preload("res://visuals/images/icons/force_panel.png"), - Game.TrapType.SWITCH : preload("res://visuals/images/icons/switch.png"), - Game.TrapType.MINE : preload("res://visuals/images/icons/mine.png"), + Trap.Type.BOMB : preload("res://visuals/images/icons/bomb.png"), + Trap.Type.GAS : preload("res://visuals/images/icons/gas.png"), + Trap.Type.PITFALL : preload("res://visuals/images/icons/pitfall.png"), + Trap.Type.FORCE_PANEL : preload("res://visuals/images/icons/force_panel.png"), + Trap.Type.SWITCH : preload("res://visuals/images/icons/switch.png"), + Trap.Type.MINE : preload("res://visuals/images/icons/mine.png"), } @onready var icon_image : TextureRect = %Icon @onready var qty_label : Label = %Label -func setup(type : Game.TrapType, qty : int) -> void: +func setup(type : Trap.Type, qty : int) -> void: icon_image.texture = trap_icons[type] set_quantity(qty) diff --git a/templates/disarm_icon.tscn b/templates/disarm_icon.tscn new file mode 100644 index 0000000..953db07 --- /dev/null +++ b/templates/disarm_icon.tscn @@ -0,0 +1,11 @@ +[gd_scene load_steps=3 format=3 uid="uid://c5ienwpgidanx"] + +[ext_resource type="Texture2D" uid="uid://bxs0jj4y4clvv" path="res://visuals/images/icons/detect button.png" id="1_tmc0a"] +[ext_resource type="Texture2D" uid="uid://bxxm3c2lpmr4f" path="res://visuals/images/icons/lit detect button.png" id="2_75gk1"] + +[node name="DisarmIcon" type="TextureButton"] +custom_minimum_size = Vector2(32, 32) +texture_normal = ExtResource("1_tmc0a") +texture_pressed = ExtResource("2_75gk1") +ignore_texture_size = true +stretch_mode = 0 diff --git a/templates/disarm_trap_modal.tscn b/templates/disarm_trap_modal.tscn new file mode 100644 index 0000000..603e769 --- /dev/null +++ b/templates/disarm_trap_modal.tscn @@ -0,0 +1,110 @@ +[gd_scene load_steps=4 format=3 uid="uid://v12wymuy2xk6"] + +[ext_resource type="Script" uid="uid://5nrsscwod1xg" path="res://scripts/disarm_trap_modal.gd" id="1_eo0gq"] +[ext_resource type="Texture2D" uid="uid://barbcaa2xvgkk" path="res://visuals/images/icons/switch button.png" id="2_cgabh"] +[ext_resource type="Texture2D" uid="uid://diyks5oxgidoo" path="res://visuals/images/icons/ranged attack button.png" id="3_06srb"] + +[node name="DisarmTrapModal" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_eo0gq") + +[node name="ConfirmationDialog" type="ConfirmationDialog" parent="."] +unique_name_in_owner = true +oversampling_override = 1.0 +initial_position = 1 +visible = true +transient = false +borderless = true +always_on_top = true +unfocusable = true +ok_button_text = "Disarm" +dialog_text = "Disarm Trap?" + +[node name="Control" type="Control" parent="ConfirmationDialog"] +layout_mode = 3 +anchors_preset = 0 +offset_left = 8.0 +offset_top = 8.0 +offset_right = 192.0 +offset_bottom = 51.0 + +[node name="TextureRect" type="TextureRect" parent="ConfirmationDialog/Control"] +z_index = 10 +layout_mode = 0 +offset_left = 36.0 +offset_top = 29.0 +offset_right = 68.0 +offset_bottom = 61.0 +texture = ExtResource("2_cgabh") +expand_mode = 1 + +[node name="TextureRect2" type="TextureRect" parent="ConfirmationDialog/Control"] +z_index = 10 +layout_mode = 0 +offset_left = 120.0 +offset_top = 29.0 +offset_right = 152.0 +offset_bottom = 61.0 +texture = ExtResource("3_06srb") +expand_mode = 1 + +[node name="Timer" type="Timer" parent="."] +unique_name_in_owner = true + +[node name="DisarmSound" type="AudioStreamPlayer" parent="."] + +[node name="SuccessSound" type="AudioStreamPlayer" parent="."] + +[node name="AudioStreamPlayer3" type="AudioStreamPlayer" parent="."] + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="DisarmWindow" type="PanelContainer" parent="CanvasLayer"] +unique_name_in_owner = true +visible = false +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -96.0 +offset_top = -56.0 +offset_right = 96.0 +offset_bottom = 56.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/DisarmWindow"] +layout_mode = 2 +alignment = 1 + +[node name="PressToDisarmHeader" type="Label" parent="CanvasLayer/DisarmWindow/VBoxContainer"] +layout_mode = 2 +text = "PRESS TO DISARM" +horizontal_alignment = 1 + +[node name="Panel" type="PanelContainer" parent="CanvasLayer/DisarmWindow/VBoxContainer"] +layout_mode = 2 + +[node name="DisarmContainer" type="HBoxContainer" parent="CanvasLayer/DisarmWindow/VBoxContainer/Panel"] +unique_name_in_owner = true +layout_mode = 2 +alignment = 1 + +[node name="TimeRemainingLabel" type="Label" parent="CanvasLayer/DisarmWindow/VBoxContainer"] +layout_mode = 2 +text = "TIME REMAINING: " +horizontal_alignment = 1 + +[node name="TimerLabel" type="Label" parent="CanvasLayer/DisarmWindow/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "00.000" +horizontal_alignment = 1 + +[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"] diff --git a/templates/one_shot.tscn b/templates/one_shot.tscn new file mode 100644 index 0000000..505aadd --- /dev/null +++ b/templates/one_shot.tscn @@ -0,0 +1,10 @@ +[gd_scene load_steps=2 format=3 uid="uid://cmw77i7e7jxkn"] + +[ext_resource type="Script" uid="uid://cb72nk0ddi3c" path="res://scripts/one_shot.gd" id="1_k1ss2"] + +[node name="OneShot" type="AudioStreamPlayer"] +script = ExtResource("1_k1ss2") + +[node name="Timer" type="Timer" parent="."] + +[connection signal="timeout" from="Timer" to="." method="_on_timeout"] diff --git a/templates/remove_trap_modal.tscn b/templates/remove_trap_modal.tscn new file mode 100644 index 0000000..2717404 --- /dev/null +++ b/templates/remove_trap_modal.tscn @@ -0,0 +1,51 @@ +[gd_scene load_steps=4 format=3 uid="uid://bwj76wt4pab4t"] + +[ext_resource type="Script" uid="uid://bj1udbw3sm73f" path="res://scripts/remove_trap_modal.gd" id="1_27jge"] +[ext_resource type="Texture2D" uid="uid://barbcaa2xvgkk" path="res://visuals/images/icons/switch button.png" id="2_dmpk7"] +[ext_resource type="Texture2D" uid="uid://diyks5oxgidoo" path="res://visuals/images/icons/ranged attack button.png" id="3_42gya"] + +[node name="RemoveTrapModal" type="ConfirmationDialog"] +handle_input_locally = false +canvas_item_default_texture_filter = 2 +gui_disable_input = true +oversampling_override = 1.0 +title = "Remove Trap?" +initial_position = 1 +visible = true +transient = false +borderless = true +always_on_top = true +unfocusable = true +content_scale_mode = 1 +content_scale_aspect = 2 +ok_button_text = "Remove" +dialog_text = "Remove Trap?" +script = ExtResource("1_27jge") + +[node name="Control" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_left = 8.0 +offset_top = 8.0 +offset_right = 192.0 +offset_bottom = 51.0 + +[node name="TextureRect" type="TextureRect" parent="Control"] +z_index = 10 +layout_mode = 0 +offset_left = 36.0 +offset_top = 29.0 +offset_right = 68.0 +offset_bottom = 61.0 +texture = ExtResource("2_dmpk7") +expand_mode = 1 + +[node name="TextureRect2" type="TextureRect" parent="Control"] +z_index = 10 +layout_mode = 0 +offset_left = 120.0 +offset_top = 29.0 +offset_right = 152.0 +offset_bottom = 61.0 +texture = ExtResource("3_42gya") +expand_mode = 1 diff --git a/templates/singleplayer_pc.tscn b/templates/singleplayer_pc.tscn index 3abd200..d5a0a02 100644 --- a/templates/singleplayer_pc.tscn +++ b/templates/singleplayer_pc.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=6 format=3 uid="uid://c8xf3qawk5c6u"] +[gd_scene load_steps=7 format=3 uid="uid://c8xf3qawk5c6u"] [ext_resource type="Script" uid="uid://bcs7ygh6s3l35" path="res://scripts/player.gd" id="1_a5wj7"] [ext_resource type="Script" uid="uid://6w608y2grdqb" path="res://scripts/player_data.gd" id="2_sfa2f"] +[ext_resource type="AudioStream" uid="uid://cjrlb4qiy23sj" path="res://audio/sounds/impact_deep_thud_bounce_09.wav" id="3_sfa2f"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_y646j"] albedo_color = Color(0.08468992, 0.08468992, 0.08468992, 1) @@ -38,3 +39,9 @@ shape = SubResource("CapsuleShape3D_a5wj7") [node name="Data" type="Node" parent="."] script = ExtResource("2_sfa2f") + +[node name="TrapSound" type="AudioStreamPlayer3D" parent="."] +stream = ExtResource("3_sfa2f") + +[node name="AudioListener3D" type="AudioListener3D" parent="."] +current = true diff --git a/templates/trap.tscn b/templates/trap.tscn new file mode 100644 index 0000000..3fba576 --- /dev/null +++ b/templates/trap.tscn @@ -0,0 +1,43 @@ +[gd_scene load_steps=7 format=3 uid="uid://bk3yqawritfnj"] + +[ext_resource type="Script" uid="uid://yjsgte3x7jjw" path="res://scripts/trap.gd" id="1_6h4aj"] +[ext_resource type="ArrayMesh" uid="uid://bih57xe642hrc" path="res://models/trap.obj" id="2_oj6ox"] +[ext_resource type="Texture2D" uid="uid://cmlp8tn6mnbd" path="res://visuals/images/icons/t-bomb.png" id="3_mxvh5"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_qcd3b"] +albedo_color = Color(0, 0, 1, 1) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_88ety"] +resource_local_to_scene = true +albedo_color = Color(1, 1, 0, 1) + +[sub_resource type="BoxShape3D" id="BoxShape3D_dw7u0"] +size = Vector3(0.8, 1, 0.8) + +[node name="Trap" type="Area3D"] +script = ExtResource("1_6h4aj") + +[node name="Model" type="MeshInstance3D" parent="."] +unique_name_in_owner = true +transform = Transform3D(0.25, 0, 0, 0, 0.25, 0, 0, 0, 0.25, 0, 0, 0) +material_overlay = SubResource("StandardMaterial3D_qcd3b") +mesh = ExtResource("2_oj6ox") +skeleton = NodePath("") +surface_material_override/0 = SubResource("StandardMaterial3D_88ety") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +shape = SubResource("BoxShape3D_dw7u0") + +[node name="Icon" type="Sprite3D" parent="."] +unique_name_in_owner = true +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0) +pixel_size = 0.0075 +axis = 1 +double_sided = false +texture = ExtResource("3_mxvh5") + +[node name="RevealTimer" type="Timer" parent="."] +unique_name_in_owner = true + +[connection signal="timeout" from="RevealTimer" to="." method="_on_reveal_timeout"] diff --git a/visuals/images/icons/t-bomb.png b/visuals/images/icons/t-bomb.png new file mode 100644 index 0000000..fe28874 Binary files /dev/null and b/visuals/images/icons/t-bomb.png differ diff --git a/visuals/images/icons/t-bomb.png.import b/visuals/images/icons/t-bomb.png.import new file mode 100644 index 0000000..a02987f --- /dev/null +++ b/visuals/images/icons/t-bomb.png.import @@ -0,0 +1,41 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cmlp8tn6mnbd" +path.s3tc="res://.godot/imported/t-bomb.png-b0fba279e3e15cee1114dff95868ac2c.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://visuals/images/icons/t-bomb.png" +dest_files=["res://.godot/imported/t-bomb.png-b0fba279e3e15cee1114dff95868ac2c.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 diff --git a/visuals/images/icons/t-force_panel.png b/visuals/images/icons/t-force_panel.png new file mode 100644 index 0000000..fb7685c Binary files /dev/null and b/visuals/images/icons/t-force_panel.png differ diff --git a/visuals/images/icons/t-force_panel.png.import b/visuals/images/icons/t-force_panel.png.import new file mode 100644 index 0000000..fa20c80 --- /dev/null +++ b/visuals/images/icons/t-force_panel.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dxbdj3448tcse" +path="res://.godot/imported/t-force_panel.png-8187f2672c6b23f490483f18d6c18d70.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://visuals/images/icons/t-force_panel.png" +dest_files=["res://.godot/imported/t-force_panel.png-8187f2672c6b23f490483f18d6c18d70.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/visuals/images/icons/t-gas.png b/visuals/images/icons/t-gas.png new file mode 100644 index 0000000..ea6a42a Binary files /dev/null and b/visuals/images/icons/t-gas.png differ diff --git a/visuals/images/icons/t-gas.png.import b/visuals/images/icons/t-gas.png.import new file mode 100644 index 0000000..2594220 --- /dev/null +++ b/visuals/images/icons/t-gas.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://r7grey8tumrp" +path="res://.godot/imported/t-gas.png-110c34a22ea1a82475e91c8498c0628f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://visuals/images/icons/t-gas.png" +dest_files=["res://.godot/imported/t-gas.png-110c34a22ea1a82475e91c8498c0628f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/visuals/images/icons/t-mine.png b/visuals/images/icons/t-mine.png new file mode 100644 index 0000000..3c7e92e Binary files /dev/null and b/visuals/images/icons/t-mine.png differ diff --git a/visuals/images/icons/t-mine.png.import b/visuals/images/icons/t-mine.png.import new file mode 100644 index 0000000..b584a03 --- /dev/null +++ b/visuals/images/icons/t-mine.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://r1c5q74q4n12" +path="res://.godot/imported/t-mine.png-93926d001ee567f1ac6b631b1f6bea15.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://visuals/images/icons/t-mine.png" +dest_files=["res://.godot/imported/t-mine.png-93926d001ee567f1ac6b631b1f6bea15.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/visuals/images/icons/t-pitfall.png b/visuals/images/icons/t-pitfall.png new file mode 100644 index 0000000..b111034 Binary files /dev/null and b/visuals/images/icons/t-pitfall.png differ diff --git a/visuals/images/icons/t-pitfall.png.import b/visuals/images/icons/t-pitfall.png.import new file mode 100644 index 0000000..0990850 --- /dev/null +++ b/visuals/images/icons/t-pitfall.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d3rydevalb47q" +path="res://.godot/imported/t-pitfall.png-b517735d43c995be7bbcb62b2f335337.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://visuals/images/icons/t-pitfall.png" +dest_files=["res://.godot/imported/t-pitfall.png-b517735d43c995be7bbcb62b2f335337.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/visuals/images/icons/t-switch.png b/visuals/images/icons/t-switch.png new file mode 100644 index 0000000..1fc4b37 Binary files /dev/null and b/visuals/images/icons/t-switch.png differ diff --git a/visuals/images/icons/t-switch.png.import b/visuals/images/icons/t-switch.png.import new file mode 100644 index 0000000..ac36a72 --- /dev/null +++ b/visuals/images/icons/t-switch.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bvfb6ntwfwopc" +path="res://.godot/imported/t-switch.png-e4dbb8ba88d48cbefbc08280c0c6cbe2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://visuals/images/icons/t-switch.png" +dest_files=["res://.godot/imported/t-switch.png-e4dbb8ba88d48cbefbc08280c0c6cbe2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1