Renamed a bunch of player stuff to pawn stuff and implemented extensive work on getting single-address 'netplay' code working. Not sure if I've created issues with single player but in theory it should all transfer across as if the player is simply always the host.

This commit is contained in:
2026-01-08 07:15:20 -05:00
parent 9fe376e27e
commit ec02685065
69 changed files with 1525 additions and 708 deletions

View File

@@ -1,4 +1,4 @@
class_name PawnData extends Resource
class_name PawnBaseData extends Resource
@export var name : String
@@ -17,7 +17,7 @@ class_name PawnData extends Resource
@export var reload_time : float = 1.25
var model
var portrait
@export var portrait : Texture2D
@export var nameplate : Texture2D
@export var starting_traps : Array[TrapSet] = [null, null, null]

View File

@@ -1,7 +1,8 @@
[gd_resource type="Resource" script_class="PawnData" load_steps=6 format=3 uid="uid://yosnkcj4ci4v"]
[gd_resource type="Resource" script_class="PawnBaseData" load_steps=7 format=3 uid="uid://yosnkcj4ci4v"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn.gd" id="1_qrt0o"]
[ext_resource type="Texture2D" uid="uid://3dj2p3xerc45" path="res://visuals/images/temp_portraits/tg-abdoll-relin.jpg" id="1_4g7al"]
[ext_resource type="Script" uid="uid://b0b1107c0d807" path="res://data/trapset.gd" id="2_4g7al"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn_base_data.gd" id="2_8dqhi"]
[sub_resource type="Resource" id="Resource_qrt0o"]
script = ExtResource("2_4g7al")
@@ -22,7 +23,7 @@ qty = 2
metadata/_custom_type_script = "uid://b0b1107c0d807"
[resource]
script = ExtResource("1_qrt0o")
script = ExtResource("2_8dqhi")
name = "Abdoll Relin"
move_speed = 3.0
life = 75
@@ -34,5 +35,6 @@ range_damage = 12
range_time = 1.0
melee_time = 1.25
reload_time = 1.75
portrait = ExtResource("1_4g7al")
starting_traps = Array[ExtResource("2_4g7al")]([SubResource("Resource_qrt0o"), SubResource("Resource_4g7al"), SubResource("Resource_8dqhi")])
metadata/_custom_type_script = "uid://c53ohdio1ksp1"

View File

@@ -1,7 +1,8 @@
[gd_resource type="Resource" script_class="PawnData" load_steps=6 format=3 uid="uid://df4gqi1us2dwu"]
[gd_resource type="Resource" script_class="PawnBaseData" load_steps=7 format=3 uid="uid://df4gqi1us2dwu"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn.gd" id="1_ocmvf"]
[ext_resource type="Texture2D" uid="uid://2qoouiv1cf0i" path="res://visuals/images/temp_portraits/tg-john-bishous.jpg" id="1_sb8f5"]
[ext_resource type="Script" uid="uid://b0b1107c0d807" path="res://data/trapset.gd" id="2_sb8f5"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn_base_data.gd" id="2_tu5w7"]
[sub_resource type="Resource" id="Resource_ocmvf"]
script = ExtResource("2_sb8f5")
@@ -21,7 +22,7 @@ qty = 2
metadata/_custom_type_script = "uid://b0b1107c0d807"
[resource]
script = ExtResource("1_ocmvf")
script = ExtResource("2_tu5w7")
name = "John Bishous"
move_speed = 2.5
life = 125
@@ -33,5 +34,6 @@ range_damage = 20
range_time = 0.75
melee_time = 1.0
reload_time = 1.75
portrait = ExtResource("1_sb8f5")
starting_traps = Array[ExtResource("2_sb8f5")]([SubResource("Resource_ocmvf"), SubResource("Resource_sb8f5"), SubResource("Resource_tu5w7")])
metadata/_custom_type_script = "uid://c53ohdio1ksp1"

View File

@@ -1,6 +1,7 @@
[gd_resource type="Resource" script_class="PawnData" load_steps=6 format=3 uid="uid://dnty6gi4s2vdl"]
[gd_resource type="Resource" script_class="PawnBaseData" load_steps=7 format=3 uid="uid://dnty6gi4s2vdl"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn.gd" id="1_h6eg2"]
[ext_resource type="Texture2D" uid="uid://db0n6kjwucthf" path="res://visuals/images/temp_portraits/tg-lou-riche.jpg" id="1_onotk"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn_base_data.gd" id="2_7kyxn"]
[ext_resource type="Script" uid="uid://b0b1107c0d807" path="res://data/trapset.gd" id="2_onotk"]
[sub_resource type="Resource" id="Resource_h6eg2"]
@@ -22,7 +23,7 @@ qty = 3
metadata/_custom_type_script = "uid://b0b1107c0d807"
[resource]
script = ExtResource("1_h6eg2")
script = ExtResource("2_7kyxn")
name = "Lou Riche"
move_speed = 3.0
life = 100
@@ -32,5 +33,6 @@ melee_damage = 12
range_damage = 4
range_time = 0.4
melee_time = 1.25
portrait = ExtResource("1_onotk")
starting_traps = Array[ExtResource("2_onotk")]([SubResource("Resource_h6eg2"), SubResource("Resource_onotk"), SubResource("Resource_7kyxn")])
metadata/_custom_type_script = "uid://c53ohdio1ksp1"

View File

@@ -1,6 +1,7 @@
[gd_resource type="Resource" script_class="PawnData" load_steps=6 format=3 uid="uid://bpb2nok3rqm1g"]
[gd_resource type="Resource" script_class="PawnBaseData" load_steps=7 format=3 uid="uid://bpb2nok3rqm1g"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn.gd" id="1_g4lbt"]
[ext_resource type="Texture2D" uid="uid://ci86bksme5114" path="res://visuals/images/temp_portraits/tg-tenrou-ugetsu.jpg" id="1_fm4bf"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn_base_data.gd" id="2_0fl5x"]
[ext_resource type="Script" uid="uid://b0b1107c0d807" path="res://data/trapset.gd" id="2_fm4bf"]
[sub_resource type="Resource" id="Resource_g4lbt"]
@@ -22,7 +23,7 @@ qty = 2
metadata/_custom_type_script = "uid://b0b1107c0d807"
[resource]
script = ExtResource("1_g4lbt")
script = ExtResource("2_0fl5x")
name = "Tenrou Ugetsu"
move_speed = 3.5
life = 100
@@ -33,5 +34,6 @@ range_damage = 3
range_time = 0.3
melee_time = 1.25
reload_time = 0.6
portrait = ExtResource("1_fm4bf")
starting_traps = Array[ExtResource("2_fm4bf")]([SubResource("Resource_g4lbt"), SubResource("Resource_fm4bf"), SubResource("Resource_0fl5x")])
metadata/_custom_type_script = "uid://c53ohdio1ksp1"

View File

@@ -1,6 +1,7 @@
[gd_resource type="Resource" script_class="PawnData" load_steps=6 format=3 uid="uid://casciqabe0wgo"]
[gd_resource type="Resource" script_class="PawnBaseData" load_steps=7 format=3 uid="uid://casciqabe0wgo"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn.gd" id="1_y3bgy"]
[ext_resource type="Texture2D" uid="uid://bsug1ur2gifkh" path="res://visuals/images/temp_portraits/tg-tico.jpg" id="1_o3qj5"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn_base_data.gd" id="2_cxp03"]
[ext_resource type="Script" uid="uid://b0b1107c0d807" path="res://data/trapset.gd" id="2_o3qj5"]
[sub_resource type="Resource" id="Resource_y3bgy"]
@@ -22,7 +23,7 @@ qty = 4
metadata/_custom_type_script = "uid://b0b1107c0d807"
[resource]
script = ExtResource("1_y3bgy")
script = ExtResource("2_cxp03")
name = "Tico"
move_speed = 3.0
life = 75
@@ -34,5 +35,6 @@ range_damage = 10
range_time = 1.0
melee_time = 1.25
reload_time = 2.0
portrait = ExtResource("1_o3qj5")
starting_traps = Array[ExtResource("2_o3qj5")]([SubResource("Resource_y3bgy"), SubResource("Resource_o3qj5"), SubResource("Resource_cxp03")])
metadata/_custom_type_script = "uid://c53ohdio1ksp1"

View File

@@ -1,7 +1,8 @@
[gd_resource type="Resource" script_class="PawnData" load_steps=6 format=3 uid="uid://6s8tqfssrt5i"]
[gd_resource type="Resource" script_class="PawnBaseData" load_steps=7 format=3 uid="uid://6s8tqfssrt5i"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn.gd" id="1_ydc1g"]
[ext_resource type="Texture2D" uid="uid://bp6wc55s2t4si" path="res://visuals/images/temp_portraits/tg-van-raily.jpg" id="1_crpmc"]
[ext_resource type="Script" uid="uid://b0b1107c0d807" path="res://data/trapset.gd" id="2_crpmc"]
[ext_resource type="Script" uid="uid://c53ohdio1ksp1" path="res://data/pawn_base_data.gd" id="2_nf0ju"]
[sub_resource type="Resource" id="Resource_nf0ju"]
script = ExtResource("2_crpmc")
@@ -21,7 +22,7 @@ qty = 4
metadata/_custom_type_script = "uid://b0b1107c0d807"
[resource]
script = ExtResource("1_ydc1g")
script = ExtResource("2_nf0ju")
name = "Van Raily"
move_speed = 3.0
life = 100
@@ -30,5 +31,6 @@ melee_damage = 10
range_damage = 5
range_time = 0.5
melee_time = 1.0
portrait = ExtResource("1_crpmc")
starting_traps = Array[ExtResource("2_crpmc")]([SubResource("Resource_nf0ju"), SubResource("Resource_2pr8m"), SubResource("Resource_1yw33")])
metadata/_custom_type_script = "uid://c53ohdio1ksp1"

BIN
external/concepts.clip vendored Normal file

Binary file not shown.

BIN
external/tingles.clip vendored Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -11,6 +11,7 @@ config_version=5
[application]
config/name="Net Gunner"
run/main_scene="uid://dd40q2mv84pmc"
config/features=PackedStringArray("4.5", "Forward Plus")
config/icon="res://visuals/images/icon.svg"

View File

@@ -1,12 +1,9 @@
[gd_scene load_steps=21 format=3 uid="uid://ck4x56txf676a"]
[gd_scene load_steps=13 format=3 uid="uid://ck4x56txf676a"]
[ext_resource type="Script" uid="uid://grs3nyom325o" path="res://scripts/character_select.gd" id="1_bow2h"]
[ext_resource type="Script" uid="uid://blljmwvft1g8m" path="res://scripts/pawn_display.gd" id="2_5wdeo"]
[ext_resource type="PackedScene" uid="uid://46rpw0rrd51m" path="res://templates/pawn_display.tscn" id="2_5wdeo"]
[ext_resource type="Texture2D" uid="uid://dri0a20l6kpbj" path="res://visuals/images/icon.svg" id="2_uxcyu"]
[ext_resource type="AudioStream" uid="uid://vcatohtmt8bk" path="res://audio/music/16 - Character Select.mp3" id="3_bow2h"]
[ext_resource type="Texture2D" uid="uid://lttjm6mhx2nx" path="res://visuals/images/chselector.png" id="3_uxcyu"]
[ext_resource type="Script" uid="uid://qwyhu0gexeah" path="res://scripts/cs_trap_display.gd" id="3_w1hxv"]
[ext_resource type="Script" uid="uid://cu7ho7656m6hp" path="res://scripts/pawn_selector.gd" id="6_5cdo8"]
[ext_resource type="AudioStream" uid="uid://cwmfd8ov3lj1h" path="res://audio/sounds/menu select.wav" id="7_bqp8h"]
[ext_resource type="AudioStream" uid="uid://doelc8yt5snc2" path="res://audio/sounds/Keypad A.wav" id="8_5cdo8"]
@@ -50,10 +47,10 @@ void fragment() {
//}
"
[sub_resource type="ShaderMaterial" id="ShaderMaterial_uxcyu"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_5wdeo"]
shader = SubResource("Shader_fa52j")
shader_parameter/granularity = 20.0000007125
shader_parameter/opacity_limit = 0.0
shader_parameter/granularity = 10.0000002375
shader_parameter/opacity_limit = 0.86
[sub_resource type="Gradient" id="Gradient_ak2if"]
offsets = PackedFloat32Array(0)
@@ -63,11 +60,6 @@ colors = PackedColorArray(0, 0, 0, 1)
gradient = SubResource("Gradient_ak2if")
width = 1
[sub_resource type="ShaderMaterial" id="ShaderMaterial_5wdeo"]
shader = SubResource("Shader_fa52j")
shader_parameter/granularity = 10.0000002375
shader_parameter/opacity_limit = 0.86
[sub_resource type="Gradient" id="Gradient_w1hxv"]
offsets = PackedFloat32Array(1)
colors = PackedColorArray(1, 1, 1, 1)
@@ -76,62 +68,6 @@ colors = PackedColorArray(1, 1, 1, 1)
gradient = SubResource("Gradient_w1hxv")
width = 1
[sub_resource type="Animation" id="Animation_fa52j"]
resource_name = "selecting"
length = 0.2667
loop_mode = 1
step = 0.0168
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:visible")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.0001, 0.13333334, 0.26666668),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [true, true, false, true]
}
[sub_resource type="Animation" id="Animation_5wdeo"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:visible")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="Animation" id="Animation_w1hxv"]
resource_name = "selected"
step = 0.0168
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:visible")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_bqp8h"]
_data = {
&"RESET": SubResource("Animation_5wdeo"),
&"selected": SubResource("Animation_w1hxv"),
&"selecting": SubResource("Animation_fa52j")
}
[node name="Control" type="Control"]
layout_mode = 3
anchors_preset = 15
@@ -141,6 +77,11 @@ grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_bow2h")
[node name="SelectorSpawner" type="MultiplayerSpawner" parent="."]
unique_name_in_owner = true
_spawnable_scenes = PackedStringArray("uid://bvypswoe6diaq")
spawn_path = NodePath("../Panel2/SelectorStart")
[node name="Panel" type="Panel" parent="."]
layout_mode = 1
anchors_preset = 15
@@ -149,253 +90,31 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="P1PawnDisplay" type="Panel" parent="Panel"]
unique_name_in_owner = true
layout_mode = 1
[node name="Control" type="Control" parent="Panel"]
anchors_preset = 0
offset_left = 94.0
offset_top = 96.0
offset_right = 794.0
offset_bottom = 796.0
script = ExtResource("2_5wdeo")
[node name="TextureRect" type="TextureRect" parent="Panel/P1PawnDisplay"]
material = SubResource("ShaderMaterial_uxcyu")
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = SubResource("GradientTexture1D_fa52j")
expand_mode = 1
[node name="Control" type="Control" parent="Panel/P1PawnDisplay"]
anchors_preset = 0
offset_left = 108.0
offset_top = 286.0
offset_right = 392.0
offset_bottom = 350.0
[node name="PawnName" type="Label" parent="Panel/P1PawnDisplay/Control"]
unique_name_in_owner = true
modulate = Color(0, 0.3254902, 1, 1)
layout_mode = 0
offset_left = 37.0
offset_top = 288.0
offset_right = 448.0
offset_bottom = 355.0
theme_override_font_sizes/font_size = 48
text = "NAME GOES HERE"
horizontal_alignment = 1
[node name="VBoxContainer" type="VBoxContainer" parent="Panel/P1PawnDisplay/Control"]
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -39.0
offset_top = 281.0
offset_right = 245.0
offset_bottom = 394.0
grow_horizontal = 2
grow_vertical = 0
[node name="Panel" type="PanelContainer" parent="Panel/P1PawnDisplay/Control/VBoxContainer"]
layout_mode = 2
[node name="TrapContainer" type="HBoxContainer" parent="Panel/P1PawnDisplay/Control/VBoxContainer/Panel"]
unique_name_in_owner = true
layout_mode = 2
[node name="TextureRect" type="TextureRect" parent="Panel/P1PawnDisplay/Control/VBoxContainer/Panel/TrapContainer"]
custom_minimum_size = Vector2(92, 64)
layout_mode = 2
expand_mode = 1
script = ExtResource("3_w1hxv")
[node name="Label" type="Label" parent="Panel/P1PawnDisplay/Control/VBoxContainer/Panel/TrapContainer/TextureRect"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -40.0
offset_top = -23.0
grow_horizontal = 0
grow_vertical = 0
text = "##"
horizontal_alignment = 2
[node name="TextureRect2" type="TextureRect" parent="Panel/P1PawnDisplay/Control/VBoxContainer/Panel/TrapContainer"]
custom_minimum_size = Vector2(92, 64)
layout_mode = 2
expand_mode = 1
script = ExtResource("3_w1hxv")
[node name="Label" type="Label" parent="Panel/P1PawnDisplay/Control/VBoxContainer/Panel/TrapContainer/TextureRect2"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -40.0
offset_top = -23.0
grow_horizontal = 0
grow_vertical = 0
text = "##"
horizontal_alignment = 2
[node name="TextureRect3" type="TextureRect" parent="Panel/P1PawnDisplay/Control/VBoxContainer/Panel/TrapContainer"]
custom_minimum_size = Vector2(92, 64)
layout_mode = 2
expand_mode = 1
script = ExtResource("3_w1hxv")
[node name="Label" type="Label" parent="Panel/P1PawnDisplay/Control/VBoxContainer/Panel/TrapContainer/TextureRect3"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -40.0
offset_top = -23.0
grow_horizontal = 0
grow_vertical = 0
text = "##"
horizontal_alignment = 2
[node name="Panel2" type="Panel" parent="Panel"]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -794.0
offset_top = 98.0
offset_right = -94.0
offset_bottom = 798.0
grow_horizontal = 0
offset_right = 134.0
offset_bottom = 138.0
[node name="TextureRect" type="TextureRect" parent="Panel/Panel2"]
material = SubResource("ShaderMaterial_uxcyu")
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = SubResource("GradientTexture1D_fa52j")
expand_mode = 1
[node name="Label" type="Label" parent="Panel/Panel2"]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -40.0
offset_bottom = 23.0
grow_horizontal = 0
theme_override_font_sizes/font_size = 24
text = "EASY"
[node name="Control" type="Control" parent="Panel/Panel2"]
anchors_preset = 0
offset_left = 108.0
offset_top = 286.0
offset_right = 392.0
offset_bottom = 350.0
[node name="Label" type="Label" parent="Panel/Panel2/Control"]
[node name="P1PawnDisplay" parent="Panel/Control" instance=ExtResource("2_5wdeo")]
unique_name_in_owner = true
layout_mode = 0
offset_left = 33.0
offset_top = 286.0
offset_right = 444.0
offset_bottom = 353.0
theme_override_colors/font_color = Color(1, 0, 0, 1)
theme_override_font_sizes/font_size = 48
text = "NAME GOES HERE"
horizontal_alignment = 1
offset_left = 0.0
offset_top = 0.0
offset_right = 700.0
offset_bottom = 700.0
[node name="VBoxContainer" type="VBoxContainer" parent="Panel/Panel2/Control"]
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -42.0
offset_top = 280.0
offset_right = 242.0
offset_bottom = 393.0
grow_horizontal = 2
grow_vertical = 0
[node name="P2PawnDisplay" parent="Panel/Control" instance=ExtResource("2_5wdeo")]
unique_name_in_owner = true
layout_mode = 0
offset_left = 1032.0
offset_top = 0.0
offset_right = 1732.0
offset_bottom = 700.0
[node name="Panel" type="PanelContainer" parent="Panel/Panel2/Control/VBoxContainer"]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="Panel/Panel2/Control/VBoxContainer/Panel"]
layout_mode = 2
[node name="TextureRect" type="TextureRect" parent="Panel/Panel2/Control/VBoxContainer/Panel/HBoxContainer"]
custom_minimum_size = Vector2(92, 64)
layout_mode = 2
expand_mode = 1
[node name="Label" type="Label" parent="Panel/Panel2/Control/VBoxContainer/Panel/HBoxContainer/TextureRect"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -40.0
offset_top = -23.0
grow_horizontal = 0
grow_vertical = 0
text = "##"
horizontal_alignment = 2
[node name="TextureRect2" type="TextureRect" parent="Panel/Panel2/Control/VBoxContainer/Panel/HBoxContainer"]
custom_minimum_size = Vector2(92, 64)
layout_mode = 2
expand_mode = 1
[node name="Label" type="Label" parent="Panel/Panel2/Control/VBoxContainer/Panel/HBoxContainer/TextureRect2"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -40.0
offset_top = -23.0
grow_horizontal = 0
grow_vertical = 0
text = "##"
horizontal_alignment = 2
[node name="TextureRect3" type="TextureRect" parent="Panel/Panel2/Control/VBoxContainer/Panel/HBoxContainer"]
custom_minimum_size = Vector2(92, 64)
layout_mode = 2
expand_mode = 1
[node name="Label" type="Label" parent="Panel/Panel2/Control/VBoxContainer/Panel/HBoxContainer/TextureRect3"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -40.0
offset_top = -23.0
grow_horizontal = 0
grow_vertical = 0
text = "##"
horizontal_alignment = 2
[node name="PawnName" parent="Panel/Control/P2PawnDisplay/Control" index="0"]
modulate = Color(0.78848296, 0, 0.22455063, 1)
[node name="Panel2" type="Panel" parent="."]
custom_minimum_size = Vector2(0, 250)
@@ -743,23 +462,6 @@ offset_top = 40.0
offset_right = 478.0
offset_bottom = 80.0
[node name="Selector" type="TextureRect" parent="Panel2"]
unique_name_in_owner = true
texture_filter = 1
layout_mode = 0
offset_left = 438.0
offset_top = 40.0
offset_right = 608.0
offset_bottom = 210.0
texture = ExtResource("3_uxcyu")
script = ExtResource("6_5cdo8")
[node name="AnimationPlayer" type="AnimationPlayer" parent="Panel2/Selector"]
libraries = {
&"": SubResource("AnimationLibrary_bqp8h")
}
autoplay = "selecting"
[node name="Panel3" type="Panel" parent="."]
layout_mode = 1
anchors_preset = 10
@@ -795,3 +497,9 @@ stream = ExtResource("7_bqp8h")
[node name="SwitchSound" type="AudioStreamPlayer" parent="."]
unique_name_in_owner = true
stream = ExtResource("8_5cdo8")
[connection signal="spawned" from="SelectorSpawner" to="." method="_on_selector_spawner_spawned"]
[connection signal="child_entered_tree" from="Panel2/SelectorStart" to="." method="_on_selector_start_child_entered_tree"]
[editable path="Panel/Control/P1PawnDisplay"]
[editable path="Panel/Control/P2PawnDisplay"]

View File

@@ -3,7 +3,7 @@
[ext_resource type="Script" uid="uid://dep7nr2nkdmga" path="res://scripts/multiplayer_setup.gd" id="1_lckj3"]
[node name="MultiplayerSetup" type="MultiplayerSpawner" groups=["level_spawner"]]
_spawnable_scenes = PackedStringArray("uid://ti65jukt8gvs")
_spawnable_scenes = PackedStringArray("uid://ti65jukt8gvs", "uid://ck4x56txf676a")
spawn_path = NodePath(".")
script = ExtResource("1_lckj3")

File diff suppressed because one or more lines are too long

10
scenes/net_test.tscn Normal file
View File

@@ -0,0 +1,10 @@
[gd_scene load_steps=2 format=3 uid="uid://biha5f6hrjils"]
[ext_resource type="Script" uid="uid://dk2gtt380ld51" path="res://scripts/net_test.gd" id="1_x15u5"]
[node name="NetTest" type="MultiplayerSpawner" groups=["level_spawner"]]
_spawnable_scenes = PackedStringArray("uid://ti65jukt8gvs", "uid://ck4x56txf676a", "uid://by6suwmds7xq2")
spawn_path = NodePath(".")
script = ExtResource("1_x15u5")
[connection signal="spawned" from="." to="." method="_on_level_spawned"]

View File

@@ -1,18 +1,14 @@
[gd_scene load_steps=9 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="Script" uid="uid://d3t381vws7vns" path="res://scripts/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="Script" uid="uid://clqnjqolkujea" path="res://scripts/combat_target.gd" id="6_qcd3b"]
[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="FastNoiseLite" id="FastNoiseLite_qcd3b"]
frequency = 0.02
fractal_octaves = 6
[sub_resource type="BoxShape3D" id="BoxShape3D_tmr53"]
size = Vector3(1, 2, 1)
[sub_resource type="Environment" id="Environment_x4b8f"]
ambient_light_color = Color(1, 1, 1, 1)
ambient_light_energy = 2.18
glow_enabled = true
[node name="Node3D" type="Node3D"]
script = ExtResource("1_qcd3b")
@@ -23,18 +19,6 @@ layer = 1000
[node name="HUD" parent="CanvasLayer" instance=ExtResource("1_x4b8f")]
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 0.49999997, 0.86602545, 0, -0.86602545, 0.49999997, 0, 18.855, 10.107289)
projection = 1
size = 5.0
script = ExtResource("3_qcd3b")
noise = SubResource("FastNoiseLite_qcd3b")
[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
omni_attenuation = -0.165
[node name="Floor" type="GridMap" parent="."]
unique_name_in_owner = true
mesh_library = ExtResource("7_88ety")
@@ -67,14 +51,26 @@ collision_layer = 0
collision_mask = 0
metadata/_editor_floor_ = Vector3(0, -1, 0)
[node name="Combat Target" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.926114, 0, -4.1967854)
script = ExtResource("6_qcd3b")
[node name="PawnSpawner" type="MultiplayerSpawner" parent="."]
_spawnable_scenes = PackedStringArray("uid://c8xf3qawk5c6u")
spawn_path = NodePath("../Pawns")
[node name="CSGBox3D" type="CSGBox3D" parent="Combat Target"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
size = Vector3(1, 2, 1)
[node name="TrapSpawner" type="MultiplayerSpawner" parent="."]
_spawnable_scenes = PackedStringArray("uid://bk3yqawritfnj")
spawn_path = NodePath("../Traps")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Combat Target" groups=["combat"]]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("BoxShape3D_tmr53")
[node name="CameraSpawner" type="MultiplayerSpawner" parent="."]
_spawnable_scenes = PackedStringArray("uid://cqa0p34mbk6so")
spawn_path = NodePath("../Cameras")
[node name="Pawns" type="Node3D" parent="."]
unique_name_in_owner = true
[node name="Cameras" type="Node3D" parent="."]
unique_name_in_owner = true
[node name="Traps" type="Node3D" parent="."]
unique_name_in_owner = true
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_x4b8f")

View File

@@ -279,7 +279,7 @@ layout_mode = 0
offset_right = 1152.0
offset_bottom = 648.0
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
[node name="Music" type="AudioStreamPlayer" parent="."]
stream = ExtResource("4_mykxm")
autoplay = true
@@ -316,6 +316,7 @@ clip_text = true
text_overrun_behavior = 1
[node name="TextureRect4" type="TextureRect" parent="."]
visible = false
material = SubResource("ShaderMaterial_lrxh4")
layout_mode = 0
offset_right = 1920.0

View File

@@ -4,16 +4,50 @@ extends Node
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")
const vs_man_level = preload("res://scenes/test_level.tscn")
const pawn_select_scene = preload("res://scenes/character_select.tscn")
var player : Player
var player : PawnController
var hud : HUD
var level : Level
var multiplayer_game : bool = false
var num_players : int = 1
var pawns_selected : Dictionary[int, PawnBaseData] = {}
var level_synced : Dictionary[int, bool] = {}
var net_test : bool #TODO: Remove later
func setup_player(player : Player) -> void:
self.player = player
func _ready() -> void:
var args : Dictionary = {}
for arg in OS.get_cmdline_args():
if arg.begins_with("--"):
var flag = arg.lstrip("--")
args[flag]=true
if args.has("net_test"):
net_test = true
func setup_player(pc : PawnController) -> void:
var is_local = false
Game.level.pawns[pc.id] = pc
if pc.id == Multiplayer.id:
is_local = true
if is_local:
player = pc
if hud:
hud.register_player(player)
hud.register_pawn(pc,is_local)
func is_multiplayer() -> bool:
return multiplayer_game
func start_level(pawns : Dictionary[int, PawnBaseData]) -> void:
if !Multiplayer.is_host():
return
pawns_selected = pawns
for i in Multiplayer.players.values():
level_synced[i] = false
level_synced[1] = true
switch_scene(vs_man_level)
func switch_scene(packed_scene : PackedScene) -> void:
var blinder = blinder_template.instantiate() as TextureRect
@@ -21,21 +55,55 @@ func switch_scene(packed_scene : PackedScene) -> void:
blinder.self_modulate.a = 0
add_child(blinder)
tween.tween_property(blinder, "self_modulate:a", 1, .15)
tween.tween_callback(Callable(get_tree().change_scene_to_packed).bind(packed_scene))
var spawner = get_tree().get_first_node_in_group("level_spawner") as MultiplayerSpawner
tween.tween_callback(spawner.add_child.bind(packed_scene.instantiate(),true))
tween.tween_property(blinder, "self_modulate:a", 0, .15)
tween.tween_callback(blinder.queue_free)
pass
@rpc("call_local", "any_peer", "reliable")
func start_pawn_select(mplayer : bool) -> void:
var setup = get_tree().get_first_node_in_group("scenes")
multiplayer_game = mplayer
setup.queue_free()
num_players = Multiplayer.players.size()
var blinder = blinder_template.instantiate() as TextureRect
var tween = create_tween()
blinder.self_modulate.a = 0
add_child(blinder)
tween.tween_property(blinder, "self_modulate:a", 1, .15)
if Multiplayer.is_server():
var pawn_select = pawn_select_scene.instantiate()
var spawner = get_tree().get_first_node_in_group("level_spawner") as MultiplayerSpawner
tween.tween_callback(spawner.add_child.bind(pawn_select))
tween.tween_property(blinder, "self_modulate:a", 0, .15)
tween.tween_callback(blinder.queue_free)
@rpc("call_local", "any_peer", "reliable")
func start_vs_man() -> void:
var setup = get_tree().get_first_node_in_group("scenes")
setup.queue_free()
if Multiplayer.is_server():
var level = vs_man_level.instantiate()
var level_scene = vs_man_level.instantiate()
var spawner = get_tree().get_first_node_in_group("level_spawner") as MultiplayerSpawner
spawner.add_child(level)
spawner.add_child(level_scene)
@rpc("call_remote", "any_peer", "reliable")
func level_spawned(peer_id : int) -> void:
if !Multiplayer.is_host():
return
level_synced[peer_id] = true
check_level_ready()
func check_level_ready() -> void:
var ready : bool = true
for id in level_synced:
if level_synced[id] == false:
ready = false
if ready:
level.setup()
func oneshot(stream : AudioStream) -> void:
var shot = one_shot_template.instantiate()
shot.stream = stream

View File

@@ -7,6 +7,9 @@ var handle : String
var id : int = 1
var players : Dictionary = {}
signal client_added(handle : String, id : int)
signal all_ready()
var player_readiness : Dictionary[int, bool] = {}
var waiting : bool = false
func become_host() -> void:
print("Starting host!")
@@ -14,6 +17,7 @@ func become_host() -> void:
var server_peer = ENetMultiplayerPeer.new()
server_peer.create_server(SERVER_PORT)
players[handle] = 1
player_readiness[1] = false
multiplayer.multiplayer_peer = server_peer
id = multiplayer.get_unique_id()
print("%s %d t" % [handle, multiplayer.get_unique_id()])
@@ -29,13 +33,33 @@ func join_game(new_handle : String) -> Error:
multiplayer.multiplayer_peer = client_peer
handle = new_handle
id = multiplayer.get_unique_id()
players[handle] = id
player_readiness[id] = false
if !error:
print("%s %d" % [handle, multiplayer.get_unique_id()])
await get_tree().create_timer(0.5).timeout
get_handle_from_peer(1)
return !error
func is_server() -> bool:
return multiplayer && multiplayer.is_server()
func is_host() -> bool:
return id == 1
func _process(delta: float) -> void:
if waiting:
var ready : bool = true
for pr in player_readiness.values():
if !pr:
ready = false
break
if ready:
all_ready.emit()
waiting = false
for pr in player_readiness.keys():
player_readiness[pr] = false
func _add_player_to_game(id : int) -> void:
print("Player %s joined the game!" % id)
await get_tree().create_timer(0.5).timeout
@@ -47,10 +71,15 @@ func _remove_player_from_game(id : int) -> void:
func get_handle_from_peer(peer_id) -> void:
rpc_id(peer_id, "report_handle_to_peer", id)
@rpc("call_local", "any_peer", "reliable")
func set_player_ready(peer_id : int) -> void:
player_readiness[peer_id] = true
@rpc("any_peer", "call_remote")
func receive_peer_handle(peer_id, peer_handle) -> void:
print("Player %s identified as %s!" % [peer_id, peer_handle])
players[peer_handle] = peer_id
player_readiness[peer_id] = false
client_added.emit(peer_handle, peer_id)
@rpc("any_peer", "call_remote")

View File

@@ -1,6 +1,6 @@
extends Control
var pawns : Array[PawnData] = [
const pawns : Array[PawnBaseData] = [
preload("res://data/pawns/van_reily.tres"),
preload("res://data/pawns/lou_riche.tres"),
preload("res://data/pawns/tico.tres"),
@@ -9,35 +9,83 @@ var pawns : Array[PawnData] = [
preload("res://data/pawns/tenrou_ugetsu.tres")
]
const p_colors : Array[Color] = [
Color.ROYAL_BLUE,
Color.RED
]
const selector_template = preload("res://templates/pawn_selector.tscn")
@onready var pawn_displays : Array[PawnDisplay] = [
%P1PawnDisplay,
%P2PawnDisplay
]
var selector_wait : float = 0
var selection : int = 0
var selected : int = -1
@onready var selector = %Selector
var selectors : Dictionary[int,PawnSelector] = {}
var displays : Dictionary[int, PawnDisplay] = {}
@onready var selector_start : Control = %SelectorStart
@onready var p1_pawn_display : PawnDisplay = %P1PawnDisplay
@onready var switch_sound : AudioStreamPlayer = %SwitchSound
@onready var select_sound : AudioStreamPlayer = %SelectSound
func _ready() -> void:
Multiplayer.waiting = true
var plist
if Game.is_multiplayer():
plist = Multiplayer.players.values()
for i in range(Game.num_players):
displays[plist[i]] = pawn_displays[i]
change_display(plist[i], 0)
else:
displays[1] = pawn_displays[0]
change_display(1, 0)
Multiplayer.all_ready.connect(add_selector, CONNECT_ONE_SHOT)
Multiplayer.set_player_ready.rpc(Multiplayer.id)
#Set up each pawn on bottom
#Highlight P1 pawn as 0
change_display(1, 0)
pass
func _process(delta : float) -> void:
if selected != -1:
return
func add_selector() -> void:
spawn_selector.rpc_id(1, Multiplayer.id)
@rpc("call_local","any_peer","reliable")
func spawn_selector(peer_id) -> void:
var selector = selector_template.instantiate()
selector.setup(peer_id, p_colors[0] if Multiplayer.is_host() else p_colors[1])
selector.name = selector.name + str(peer_id)
selector_start.add_child(selector)
selector.set_multiplayer_authority(peer_id)
#print("Character select spawned selector %s for player %d" % [selector.name, Multiplayer.id])
func _process(delta : float) -> void:
if !selectors.has(Multiplayer.id):
return
var locked = true
var pawns_selected : Dictionary[int, PawnBaseData] = {}
for selector : PawnSelector in selectors.values():
if !selector.selected:
locked = false
else:
pawns_selected[selector.player_id] = pawns[selector.selection]
if locked:
Game.start_level(pawns_selected)
if selectors[Multiplayer.id].selected != false:
return
var selector = selectors[Multiplayer.id]
if Input.is_action_just_pressed("ui_accept"):
selected = selection
selector.play_animation("selected")
select_sound.play()
lock_selector.rpc(selector.player_id)
if selector_wait > 0:
selector_wait -= delta
return
var input_vector = Input.get_vector("west","east","north","south")
var input_vector : Vector2
if Multiplayer.is_host():
input_vector = Input.get_vector("west","east","north","south")
else:
input_vector = Input.get_vector("ui_focus_prev","ui_focus_next","north","south")
var move_dir : Vector2 = Vector2.ZERO
if input_vector.x < 0:
@@ -47,15 +95,35 @@ func _process(delta : float) -> void:
move_dir.x += 1
if move_dir.x != 0:
selection = wrapi(selection + sign(move_dir.x),0, len(pawns))
change_display(1, selection)
selector.position = selector_start.position + Vector2(175 * selection, 0)
switch_sound.play()
move_selector.rpc(selector.player_id, wrapi(selector.selection + sign(move_dir.x),0, len(pawns)))
selector_wait = 0.25
@rpc("any_peer","call_local","reliable")
func move_selector(peer_id : int, selection : int) -> void:
var selector : PawnSelector = selectors[peer_id]
selector.selection = selection
change_display(peer_id, selector.selection)
var v = Vector2(175 * selector.selection, 0)
selector.position = Vector2(175 * selector.selection, 0)
switch_sound.play()
@rpc("any_peer","call_local","reliable")
func lock_selector(peer_id : int) -> void:
var selector : PawnSelector = selectors[peer_id]
selector.selected = true
selector.play_animation("selected")
select_sound.play()
func change_display(player : int, selection: int) -> void:
var pd : PawnDisplay
if player == 1:
pd = p1_pawn_display
var pd : PawnDisplay = displays[player]
pd.set_pawn_name(pawns[selection].name)
pd.set_portrait(pawns[selection].portrait)
pd.set_traps(pawns[selection].starting_traps)
func _on_selector_start_child_entered_tree(node: Node) -> void:
selectors[node.player_id] = node
func _on_selector_spawner_spawned(node: Node) -> void:
selectors[node.player_id] = node

View File

@@ -44,7 +44,7 @@ var disarm_icons : Array[TextureButton]
var disarm_buttons : Array[int]
var progress : int
var disarming : bool
var failed : bool
var difficulty : int = 1
func _process(delta: float) -> void:
@@ -73,15 +73,11 @@ func try_advance(btn : int) -> void:
disarm_icons[progress].button_pressed = true
progress += 1
if progress >= len(disarm_buttons):
Game.player.close_modal()
Game.oneshot(success_sound)
Game.level.disarm_trap(square)
succeed()
else:
Game.oneshot(progress_sound)
else:
Game.player.close_modal()
Game.oneshot(fail_sound)
Game.level.activate_trap(square)
fail()
func button_pressed(event : InputEventAction) -> void:
@@ -97,8 +93,21 @@ func button_pressed(event : InputEventAction) -> void:
Game.player.close_modal()
_: return
func _on_timer_timeout() -> void:
func fail() -> void:
if failed:
return
failed = true
Game.player.close_modal()
Game.oneshot(fail_sound)
Game.level.activate_trap(square)
func succeed() -> void:
Game.player.close_modal()
Game.oneshot(success_sound)
Game.level.disarm_trap(square)
func _on_trap_failed() -> void:
fail()
func _on_trap_removed(type : Trap.Type) -> void:
Game.player.close_modal()

View File

@@ -2,21 +2,24 @@ class_name HUD extends Control
@onready var trap_display : TrapDisplay = %TrapDisplay
@onready var p1_healthbar : HealthBar = %P1HealthBar
@onready var p2_healthbar : HealthBar = %P2HealthBar
@onready var control_display : ControlDisplay = %ControlDisplay
@onready var ammo_label : Label = %AmmoLabel
func _ready() -> void:
Game.hud = self
func register_player(player : Player) -> void:
player.health_changed.connect(p1_healthbar._on_health_changed)
player.poison_status_changed.connect(p1_healthbar._on_poison_status_changed)
trap_display._on_trap_list_changed(player.data.traps, player.data.active_trap)
player.trap_cycled.connect(trap_display._on_trap_cycled)
player.trap_quantity_changed.connect(trap_display._on_trap_quantity_changed)
player.trap_list_changed.connect(trap_display._on_trap_list_changed)
player.combat_target_changed.connect(control_display._on_melee_range_changed)
player.ammo_changed.connect(_on_ammo_changed)
set_ammo(player.ammo)
func register_pawn(player : PawnController, is_local : bool) -> void:
player.health_changed.connect(p1_healthbar._on_health_changed if is_local else p2_healthbar._on_health_changed)
player.poison_status_changed.connect(p1_healthbar._on_poison_status_changed if is_local else p2_healthbar._on_poison_status_changed)
if is_local:
trap_display._on_trap_list_changed(player.data.traps, player.data.active_trap)
player.trap_cycled.connect(trap_display._on_trap_cycled)
player.trap_quantity_changed.connect(trap_display._on_trap_quantity_changed)
player.trap_list_changed.connect(trap_display._on_trap_list_changed)
player.combat_target_changed.connect(control_display._on_melee_range_changed)
player.ammo_changed.connect(_on_ammo_changed)
set_ammo(player.ammo)
func set_ammo(ammo : int) -> void:
ammo_label.text = str(ammo)

View File

@@ -1,33 +1,52 @@
class_name Level extends Node3D
const player_controller = preload("res://templates/singleplayer_pc.tscn")
const pawn_controller = preload("res://templates/pawn_controller.tscn")
const trap_template = preload("res://templates/trap.tscn")
const camera_template = preload("res://templates/camera.tscn")
const camera_offset = Vector3(0, 10, 5.25)
@onready var floor_layer : GridMap = %Floor
@onready var ramp_layer : GridMap = %Ramps
@onready var marker_layer : GridMap = %Markers
@onready var pawns_node : Node3D = %Pawns
@onready var traps_node : Node3D = %Traps
@onready var cameras_node : Node3D = %Cameras
@export var difficulty : int = 1
var traps : Dictionary[Vector3i, Trap] = {}
var pawns : Dictionary[int, PawnController] = {}
var cameras : Dictionary[int, PawnCamera] = {}
func _ready() -> void:
Game.level = self
var player = player_controller.instantiate()
var traps : Array[PlayerData.TrapData] = [
PlayerData.TrapData.new(Trap.Type.FORCE_PANEL, 3, 3),
PlayerData.TrapData.new(Trap.Type.BOMB, 3, 3),
PlayerData.TrapData.new(Trap.Type.SWITCH, 3, 3),
PlayerData.TrapData.new(Trap.Type.MINE, 3, 3),
PlayerData.TrapData.new(Trap.Type.GAS, 3, 3)
]
add_child(player)
generate_trap(Trap.Type.FORCE_PANEL, Vector3(-1, 0, 0), Vector3i(5,0,2))
generate_trap(Trap.Type.FORCE_PANEL, Vector3(0, 0, -1), Vector3i(-3,0,2))
generate_trap(Trap.Type.MINE, Vector3(0, 0, 0), Vector3i(-3,0,-4))
generate_trap(Trap.Type.BOMB, Vector3(0, 0, 0), Vector3i(-2,0,-4))
generate_trap(Trap.Type.BOMB, Vector3(0, 0, 0), Vector3i(-4,0,-4))
player.setup(traps)
func setup() -> void:
if Multiplayer.is_host():
spawn_players()
func spawn_players() -> void:
for key in Game.pawns_selected:
var pc : PawnController = pawn_controller.instantiate()
var pd = Game.pawns_selected[key]
pawns_node.add_child(pc,true)
var traps : Array = []
for trap : TrapSet in pd.starting_traps:
var dict = {
"type":trap.type,
"qty":trap.qty
}
traps.append(dict)
var position : Vector3
if key == Multiplayer.id:
position = Vector3(0,0,0)
else:
position = Vector3(3,0,0)
pc.setup.rpc(key,traps,position)
add_pawn_camera(pc)
func is_square_detected(crd) -> bool:
return marker_layer.get_cell_item(crd + Vector3i(0,-1,0)) != GridMap.INVALID_CELL_ITEM
@@ -46,10 +65,20 @@ func detect_square(crd : Vector3i, mark : bool) -> bool:
trap.reveal()
return true
@rpc("any_peer", "call_local", "reliable")
func add_pawn_camera(pawn : PawnController) -> void:
if Multiplayer.is_host():
var camera : PawnCamera = camera_template.instantiate()
camera.position = pawn.global_position + camera_offset
cameras_node.add_child(camera,true)
camera.register_pawn.rpc(pawn.id)
func add_trap(trap : Trap, crd : Vector3i) -> void:
trap.square = crd
traps[crd] = trap
trap.global_position = Vector3(crd) + Vector3(.5, 0, .5)
trap.position = Vector3(crd) + Vector3(.5, 0, .5)
add_child(trap)
func add_projectile(shot : Projectile) -> void:
@@ -74,12 +103,12 @@ func is_valid_trap_square(crd : Vector3i) -> bool:
return true
func add_vfx(vfx, crd : Vector3i) -> void:
vfx.global_position = Vector3(crd) #+ Vector3(0.5, 0, 0.5)
vfx.position = Vector3(crd) #+ Vector3(0.5, 0, 0.5)
add_child(vfx)
func activate_trap(crd : Vector3i) -> void:
var trap = traps[crd]
#if trap:
if traps.has(crd):
traps[crd].activate()
func generate_trap(type : Trap.Type, dir : Vector3, square : Vector3i):

View File

@@ -1,4 +1,4 @@
class_name MultiplayerPC extends Player
class_name MultiplayerPC extends PawnController
@export var player_id := 1 :
set(id):
@@ -12,7 +12,7 @@ func _enter_tree() -> void:
func setup(id) -> void:
name = "Player " + str(id)
player_id = id
if Multiplayer.is_server() == (id == 1):
if Multiplayer.id == id:
Game.player = self
func _physics_process(delta: float) -> void:

View File

@@ -1,14 +1,19 @@
extends Node3D
extends Level
const pawn_controller_template = preload("res://templates/pawn_controller.tscn")
const multiplayer_pc_template = preload("res://templates/multiplayer_pc.tscn")
const camera_template = preload("res://templates/camera.tscn")
@onready var player_spawner = %Spawner
func _ready() -> void:
print("LEVEL LOADING, ID: " + str(Multiplayer.id) + " with " + str(Multiplayer.players.size()) + " keys recognized")
if Multiplayer.is_server():
for key in Multiplayer.players.values():
var pc = multiplayer_pc_template.instantiate()
player_spawner.add_player(pc, key)
pc.setup(key)
var camera = camera_template.instantiate()
add_child(camera)
Game.level = self
func setup() -> void:
if Multiplayer.is_host():
spawn_players()
func spawn_players() -> void:
for key in Game.pawns_selected:
var pc : PawnController = pawn_controller_template.instantiate()
var pd = Game.pawns_selected[key]
player_spawner.add_pawn(pc, key)
pc.setup(key,pd.starting_traps)

View File

@@ -42,7 +42,7 @@ func _on_hosting_back_button_pressed() -> void:
func _on_start_game_button_pressed() -> void:
Game.start_vs_man.rpc()
Game.start_pawn_select.rpc(true)
func _on_waiting_back_button_pressed() -> void:
@@ -61,7 +61,7 @@ func _on_join_button_pressed() -> void:
#Check for valid game
#If found
%Joining.visible = false
if Multiplayer.join_game(handle):
if await Multiplayer.join_game(handle):
%"Host Waiting".visible = true
%StartButton.visible = false

View File

@@ -6,9 +6,9 @@ var spawn_points : Array = []
func _enter_tree() -> void:
spawn_points = $SpawnPoints.get_children()
func add_player(player : MultiplayerPC, key) -> void:
func add_pawn(player : PawnController, key) -> void:
spawn_node.add_child(player)
if key == 1: #Server
if player.id == 1: #Host
player.global_position = spawn_points[0].global_position
else:
player.global_position = spawn_points[1].global_position

22
scripts/net_test.gd Normal file
View File

@@ -0,0 +1,22 @@
extends MultiplayerSpawner
func _ready() -> void:
if Game.net_test:
await get_tree().create_timer(0.25).timeout
Multiplayer.join_game("123")
else:
Multiplayer.handle = "456"
Multiplayer.become_host()
await get_tree().create_timer(2).timeout
var pids = Multiplayer.players.values()
if Multiplayer.is_host():
var ps : Dictionary[int, PawnBaseData] = {
pids[0] : load("res://data/pawns/van_reily.tres"),
pids[1] : load("res://data/pawns/lou_riche.tres")
}
Game.start_level(ps)
func _on_level_spawned(_node: Node) -> void:
Game.level_spawned.rpc_id(1, Multiplayer.id)

1
scripts/net_test.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://dk2gtt380ld51

View File

@@ -5,6 +5,17 @@ class_name PawnBody extends Node3D
@onready var anim_player : AnimationPlayer = %AnimationPlayer
@onready var ranged_point : Node3D = %RangedPoint
@onready var material : StandardMaterial3D = $Mesh.material
@onready var struggle_ui : Sprite3D = %StruggleUI
@onready var struggle_bar : ProgressBar = %StruggleBar
func play_animation(anim_name : String) -> void:
anim_player.play(anim_name)
func show_struggle() -> void:
struggle_ui.visible = true
func _on_struggle_changed(value : float) -> void:
if value <= 0:
struggle_ui.visible = false
else:
struggle_bar.value = value

View File

@@ -1,4 +1,5 @@
class_name PlayerCamera extends Camera3D
class_name PawnCamera extends Camera3D
var target
var player_offset : Vector3
@@ -11,20 +12,21 @@ var noise_y = 0
var trauma = 0.0 # Current shake strength.
var trauma_power = 2 # Trauma exponent. Use [2, 3].
func _enter_tree() -> void:
call_deferred("register_player")
func _ready() -> void:
randomize()
noise = FastNoiseLite.new()
noise.seed = randi()
func register_player() -> void:
target = Game.player
@rpc("any_peer", "call_local", "reliable")
func register_pawn(id : int) -> void:
set_multiplayer_authority(id)
if id == Multiplayer.id:
make_current()
target = Game.level.pawns[id]
target.camera = self
if target:
player_offset = global_position - target.global_position
player_offset = position - target.global_position
func add_trauma(amount):
trauma = min(trauma + amount, 1.0)

View File

@@ -1,4 +1,4 @@
class_name Player extends CharacterBody3D
class_name PawnController extends CharacterBody3D
enum State {
NORMAL,
@@ -9,13 +9,14 @@ enum State {
DEAD
}
const camera_template = preload("res://templates/camera.tscn")
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 : PawnBody = $PawnBody
@onready var data : PlayerData = $Data
@onready var data : PawnLevelData = $Data
@onready var trap_sound : AudioStreamPlayer3D = $TrapSound
@onready var detonate_sound : AudioStreamPlayer3D = $DetonateSound
@onready var detect_sound : AudioStreamPlayer3D = $DetectSound
@@ -35,6 +36,8 @@ var detect_squares : Dictionary[Vector3i, bool] = {}
var detect_tween : Tween = null
var fling_direction : Vector3
var fling_speed : float
var struggle_timer : float
var struggle_angle : float
var poison_strength : int = 0
var poison_time_remaining : float = 0
@@ -57,7 +60,7 @@ var input_locked : bool = false
var action_tween : Tween = null
var camera : PlayerCamera = null
var camera : PawnCamera = null
var modal = null
@@ -65,9 +68,11 @@ signal trap_cycled(trap_index : int)
signal trap_quantity_changed(trap_index : int, quantity : int)
signal trap_list_changed(traps)
signal health_changed(current : int, max : int)
signal harmed()
signal poison_status_changed(poisoned : bool)
signal combat_target_changed(melee : bool)
signal ammo_changed(current : int, max : int)
signal struggling(value : float)
func _physics_process(delta: float) -> void:
if attack_timer > 0:
@@ -86,53 +91,82 @@ func _physics_process(delta: float) -> void:
var dir = Input.get_vector("west", "east", "north", "south")
dir = Vector3(dir.x, 0, dir.y)
if struggle_timer > 0:
struggle_timer -= delta
var snapped_angle = round(dir.angle_to(Vector3(1,0,0)) * 4 / PI) * PI * .25
if abs(snapped_angle - struggle_angle) >= PI * .25:
struggle_angle = snapped_angle
struggle_timer -= 2 * delta
struggling.emit(struggle_timer)
if struggle_timer <= 0:
hurt(1)
knockdown(facing)
else:
return
if input_locked or modal != null:
dir = Vector3.ZERO
if state == State.FLUNG:
dir = fling_direction
body.look_at(body.global_position - dir)
var down = 0
if !is_on_floor():
down = velocity.y + get_gravity().y * delta
velocity = fling_speed * dir
#Raycast for a wall
var space_state = get_world_3d().direct_space_state
# use global coordinates, not local to node
var start = global_position + Vector3(0,0.25,0)
var end = start + velocity.normalized() * 0.25 + velocity * 2 * delta
var query = PhysicsRayQueryParameters3D.create(start, end, 1|2, [self])
var result = space_state.intersect_ray(query)
if result:
var opp : Player = result.collider as Player
if opp:
opp.knockdown(fling_direction)
opp.hurt(10)
knockdown(-fling_direction)
hurt(10)
else:
velocity += Vector3(0, down, 0)
move_and_slide()
elif dir.length_squared() > 0:
facing = dir.normalized()
var down = 0
if !is_on_floor():
down = velocity.y + get_gravity().y * delta
body.look_at(body.global_position - dir)
velocity = speed * dir
if is_poisoned():
velocity *= 0.5
if detecting:
velocity *= .33
velocity += Vector3(0, down, 0)
move_and_slide()
elif !is_on_floor():
velocity += get_gravity() * delta
move_and_slide()
var can_fall : bool = false
var moving : bool = false
match(state):
State.FLUNG:
can_fall = true
moving = true
dir = fling_direction
body.look_at(body.global_position - dir)
can_fall = true
velocity = fling_speed * dir
#Raycast for a wall
var space_state = get_world_3d().direct_space_state
# use global coordinates, not local to node
var start = global_position + Vector3(0,0.25,0)
var end = start + velocity.normalized() * 0.25 + velocity * 2 * delta
var query = PhysicsRayQueryParameters3D.create(start, end, 1|2, [self])
var result = space_state.intersect_ray(query)
if result:
var opp : PawnController = result.collider as PawnController
if opp:
opp.knockdown(fling_direction)
opp.hurt(10)
knockdown(-fling_direction)
hurt(10)
moving = false
State.NORMAL:
can_fall = true
if dir.length_squared() > 0:
moving = true
facing = dir.normalized()
body.look_at(body.global_position - dir)
velocity = speed * dir
if is_poisoned():
velocity *= 0.5
if detecting:
velocity *= .33
State.KNOCKUP:
if is_on_floor():
knockdown(facing)
else:
moving = true
can_fall = true
State.KNOCKDOWN,State.BOUND,State.DEAD:
return
if can_fall:
var down = 0
if !is_on_floor():
velocity.y = velocity.y + get_gravity().y * delta
moving = true
if moving:
move_and_slide()
if detecting:
update_detecting()
#Deal with the rest of the buttons
if !input_locked:
if modal:
var evt = InputEventAction.new()
@@ -224,7 +258,7 @@ func check_attack_target() -> void:
var end = target.global_position + Vector3(0,1,0)
var query = PhysicsRayQueryParameters3D.create(start, end, 1|2, [self])
var result = space_state.intersect_ray(query)
if !result or (result.collider is not Player and result.collider is not CombatTarget):
if !result or (result.collider is not PawnController and result.collider is not CombatTarget):
return
if d_sq < melee_sq:
@@ -330,11 +364,12 @@ func detect_alert() -> void:
detect_tween = create_tween()
detect_tween.tween_interval(.75)
detect_tween.tween_property(detect_icon, "visible", false, 0)
detect_tween.tween_property(self, "detect_tween", null, 0)
detect_tween.tween_callback(func(): detect_tween = null)
func close_modal() -> void:
modal.queue_free()
modal = null
if modal != null:
modal.queue_free()
modal = null
func show_remove_trap_modal() -> void:
stop_detecting()
@@ -347,9 +382,13 @@ func show_disarm_trap_modal() -> void:
modal = disarm_trap_modal.instantiate()
modal.difficulty = Game.level.difficulty
modal.square = current_square
var trap = Game.level.traps[current_square]
trap.disarming = true
trap.disarm_id = Multiplayer.id
trap.removed.connect(modal._on_trap_removed)
trap.activated.connect(modal._on_trap_failed)
harmed.connect(modal._on_trap_failed)
Game.level.add_child(modal)
func start_detecting() -> void:
@@ -388,8 +427,16 @@ func stop_detecting() -> void:
Game.level.detect_square(sq, false)
detect_squares = {}
func setup(traps) -> void:
$Data.traps = traps
@rpc("authority", "call_local", "reliable")
func setup(id : int, traps : Array, pos : Vector3) -> void:
self.id = id
self.global_position = pos
var traplist : Array[PawnLevelData.TrapData] = []
for trap in traps:
traplist.append(PawnLevelData.TrapData.new(trap.type, trap.qty, trap.qty))
$Data.traps = traplist
set_multiplayer_authority(id)
struggling.connect(body._on_struggle_changed)
Game.setup_player(self)
func remove_trap_at(square) -> void:
@@ -400,7 +447,7 @@ func remove_trap_at(square) -> void:
d.quantity += 1
trap_quantity_changed.emit(i, d.quantity)
break
trap.queue_free()
trap.remove()
Game.level.traps.erase(square)
func cycle_active_trap(dir) -> void:
@@ -420,6 +467,12 @@ func can_hurt() -> bool:
func hurt(damage : int) -> void:
data.life = max(0, data.life - damage)
if damage > 0:
harmed.emit()
if struggle_timer > 0:
struggle_timer = 0
struggling.emit(struggle_timer)
knockdown(Vector3(0,0,-1))
health_changed.emit(data.life, data.max_life)
func _on_trap_disarmed(type : Trap.Type) -> void:
@@ -429,7 +482,13 @@ func _on_trap_disarmed(type : Trap.Type) -> void:
d.max -= 1
trap_quantity_changed.emit(i, d.quantity)
break
#hurt
#blast
#blast_players
#activate
#activate_trap
#fail
#on_trap_failed
func _on_trap_activated(type : Trap.Type) -> void:
for i in range(len(data.traps)):
var d = data.traps[i]
@@ -484,6 +543,26 @@ func knockdown(direction : Vector3) -> void:
knockdown_tween.tween_callback(Callable(body.look_at).bind(facing, Vector3(0,1,0)))
func knockup(velocity : Vector3) -> void:
state = State.KNOCKUP
input_locked = true
if state != State.KNOCKUP:
state = State.KNOCKUP
input_locked = true
if is_on_floor():
self.velocity = Vector3.UP * .1
move_and_slide()
self.velocity = velocity
func pitfall(duration : float) -> void:
struggle_timer = duration
body.struggle_bar.max_value = struggle_timer
body.struggle_bar.value = struggle_timer
body.show_struggle()
func start_pitfall(square : Vector3, duration : float) -> void:
input_locked = true
velocity = Vector3.ZERO
var tween = create_tween()
tween.tween_property(self, "position", square + Vector3(.5,0,.5), 0.25)
tween.tween_property(self, "input_locked", false, 0)
tween.tween_callback(pitfall.bind(duration))

View File

@@ -2,7 +2,10 @@ class_name PawnDisplay extends Panel
@onready var pawn_name : Label = %PawnName
@onready var trap_container : HBoxContainer = %TrapContainer
@onready var portrait : TextureRect = $Portrait
@onready var portrait_blinder : TextureRect = $PortraitBlinder
var traps : Array = []
var swap_portrait_tween : Tween = null
func _ready() -> void:
for child in trap_container.get_children():
@@ -16,5 +19,21 @@ func set_traps(trap_list : Array[TrapSet]) -> void:
trap.setup(trap_list[tcount].type, trap_list[tcount].qty)
tcount+=1
func set_portrait(picture : Texture2D) -> void:
if swap_portrait_tween != null and swap_portrait_tween.is_running():
swap_portrait_tween.stop()
swap_portrait_tween = create_tween()
swap_portrait_tween.tween_property(portrait_blinder, "visible", true, 0)
swap_portrait_tween.tween_method(tv_blur, 1.0, 0.0, .1)
swap_portrait_tween.tween_property(portrait, "texture", picture, 0)
swap_portrait_tween.tween_method(tv_blur, 0.0, 1.0, .1)
swap_portrait_tween.tween_property(portrait_blinder, "visible", false, 0)
portrait.texture = picture
func tv_blur(amount : float) -> void:
var blinder_mat : ShaderMaterial = portrait_blinder.material
blinder_mat.set_shader_parameter("opacity_limit", amount)
func set_pawn_name(name : String) -> void:
pawn_name.text = name

View File

@@ -1,4 +1,4 @@
class_name PlayerData extends Node
class_name PawnLevelData extends Node
class TrapData:
var type : Trap.Type

View File

@@ -1,6 +1,13 @@
extends TextureRect
class_name PawnSelector extends TextureRect
@onready var anim_player : AnimationPlayer = $AnimationPlayer
@export var player_id : int
@export var selection : int = 0
@export var selected : bool
func setup(id : int, color : Color) -> void:
player_id = id
modulate = color
func play_animation(anim : String) -> void:
anim_player.play(anim)

10
scripts/pitfall.gd Normal file
View File

@@ -0,0 +1,10 @@
extends Node3D
@onready var timer : Timer = $Timer
var duration : float
func _ready() -> void:
timer.start(duration)
func _on_timer_timeout() -> void:
queue_free()

1
scripts/pitfall.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://c14c3ogbf7i33

View File

@@ -19,5 +19,5 @@ func _on_body_entered(body: Node) -> void:
func _on_hit_area_entered(body: Node3D) -> void:
if body is Player:
if body is PawnController:
body.hurt(damage)

View File

@@ -1,60 +1,77 @@
extends Control
@onready var menu_list : Array = [
{
"option": %STORY,
"scene" : preload("res://scenes/character_select.tscn")
},
{
"option": %"VS-COM",
"scene" : preload("res://scenes/character_select.tscn")
},
{
"option": %"VS-MAN",
"scene" : preload("res://scenes/multiplayer_setup.tscn")
},
{
"option": %STORY,
"scene" : preload("res://scenes/character_select.tscn")
},
{
"option": %RECORD,
"scene" : preload("res://scenes/character_select.tscn")
},
{
"option": %OPTION,
"scene" : preload("res://scenes/character_select.tscn")
}
]
@onready var switch_sound : AudioStreamPlayer = %SwitchSound
@onready var select_sound : AudioStreamPlayer = %SelectSound
@onready var menu : Control = %Menu
@onready var start : Label = %START
@onready var target : TextureRect = %Target
var opened : bool = false
var menu_choice : int = 0
var shot_tween : Tween
var glow_tween : Tween
@onready var menu_list : Array = [
%STORY,
%"VS-COM",
%"VS-MAN",
%RECORD,
%OPTION
]
var vs_com_scene = preload("res://scenes/character_select.tscn")
func _ready() -> void:
shot_tween = create_tween()
%Target.scale = Vector2(2,2)
%Target.modulate.a = 0
target.scale = Vector2(2,2)
target.modulate.a = 0
shot_tween.set_parallel(true)
shot_tween.tween_property(%Target, "modulate:a", 1, 1)
shot_tween.tween_property(%Target, "scale", Vector2(1,1), 1)
shot_tween.tween_property(%Target, "rotation", PI / 4, 1)
shot_tween.tween_property(target, "modulate:a", 1, 1)
shot_tween.tween_property(target, "scale", Vector2(1,1), 1)
shot_tween.tween_property(target, "rotation", PI / 4, 1)
glow_tween = create_tween()
glow_tween.set_loops(-1)
glow_tween.tween_property(%Target, "modulate:a", .8, .5)
glow_tween.tween_property(%Target, "modulate:a", 1, .5)
glow_tween.tween_property(target, "modulate:a", .8, .5)
glow_tween.tween_property(target, "modulate:a", 1, .5)
func _process(delta: float) -> void:
if Input.is_action_just_pressed("ui_menu"):
opened = !opened
%START.visible = !opened
%Menu.visible = opened
%SelectSound.play()
start.visible = !opened
menu.visible = opened
select_sound.play()
if opened:
menu_choice = 0
switch_menu()
switch_menu(0)
if opened:
if Input.is_action_just_pressed("ui_up"):
menu_choice -= 1
if menu_choice < 0:
menu_choice = len(menu_list) - 1
%SwitchSound.play()
switch_menu()
elif Input.is_action_just_pressed("ui_down"):
menu_choice += 1
if menu_choice >= len(menu_list):
menu_choice = 0
%SwitchSound.play()
switch_menu()
elif Input.is_action_just_pressed("ui_accept"):
Game.switch_scene(vs_com_scene)
var menu_dir = 0
menu_dir += 1 if Input.is_action_just_pressed("ui_down") else 0
menu_dir -= 1 if Input.is_action_just_pressed("ui_up") else 0
if menu_dir != 0:
switch_sound.play()
switch_menu(wrapi(menu_choice + menu_dir, 0, len(menu_list)))
if Input.is_action_just_pressed("ui_accept"):
Game.switch_scene(menu_list[menu_choice].scene)
func switch_menu() -> void:
for child in %Menu.get_children():
child.visible = false
menu_list[menu_choice].visible = true
func switch_menu(new_choice : int) -> void:
menu_list[menu_choice].option.visible = false
menu_choice = new_choice
menu_list[menu_choice].option.visible = true

View File

@@ -28,6 +28,7 @@ const trap_icons : Dictionary = {
const bomb_explosion_template = preload("res://templates/explosion.tscn")
const mine_explosion_template = preload("res://templates/explosion.tscn")
const pitfall_template = preload("res://templates/pitfall.tscn")
const switch_explosion_template = preload("res://templates/explosion.tscn")
const gas_emitter_template = preload("res://templates/gas_emitter.tscn")
const force_activate_sound = preload("res://audio/sounds/TomWinandySFX_UI_ScifiTech_Start_06.wav")
@@ -46,6 +47,7 @@ var square : Vector3i
var trap_owner : int
var direction : Vector3
var expended : bool = false
var disarming : bool
var disarm_id : int
@@ -55,6 +57,8 @@ var damage : int = 10
var just_revealed : bool = false
signal removed(type : Trap.Type)
signal disarmed(type : Trap.Type)
signal activated(type : Trap.Type)
@@ -66,6 +70,10 @@ func setup(type : Type, direction : Vector3, trap_owner : int) -> void:
var cardinal : float = roundi(r * 2 / PI) * PI / 2
self.direction = Vector3(cos(cardinal), 0, sin(cardinal))
func remove() -> void:
removed.emit(type)
queue_free()
func disarm() -> void:
disarmed.emit(type)
queue_free()
@@ -113,12 +121,20 @@ func _ready() -> void:
func _process(delta: float) -> void:
just_revealed = false
func blast(body : Player) -> void:
func blast(body : PawnController) -> void:
body.hurt(damage)
body.knockup((global_position.direction_to(body.global_position) + Vector3(0,2,0)) * 3)
func activate() -> void:
if expended:
return
var explode : bool = false
match(type):
Type.PITFALL:
generate_pitfall(square)
for body in get_overlapping_bodies():
body.start_pitfall(square, 6.0)
#Generate the circle here
Type.FORCE_PANEL:
Game.oneshot(force_activate_sound)
for body in get_overlapping_bodies():
@@ -146,15 +162,21 @@ func activate() -> void:
trigger_adjacent_bombs()
blast_players()
expended = true
Game.level.remove_trap_square(square)
activated.emit(type)
queue_free()
func trigger_adjacent_bombs() -> void:
for trap : Trap in range_area.get_overlapping_areas():
if trap.type == Type.BOMB:
if trap.type == Type.BOMB and trap != self:
trap.delay_trigger()
func generate_pitfall(suqare : Vector3i) -> void:
var pitfall = pitfall_template.instantiate()
pitfall.duration = 6.0
Game.level.add_vfx(pitfall, square)
func blast_players() -> void:
for body in range_area.get_overlapping_bodies():
blast(body)
@@ -168,7 +190,7 @@ func delay_trigger() -> void:
func _on_body_entered(body: Node3D) -> void:
if type == Type.GAS:
if type == Type.GAS or type == Type.BOMB:
return
if body.id == trap_owner:

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=36 format=3 uid="uid://bgocskbofewsr"]
[gd_scene load_steps=35 format=3 uid="uid://bgocskbofewsr"]
[ext_resource type="Script" uid="uid://bm50jiya4s3ei" path="res://scripts/hud.gd" id="1_jiiqi"]
[ext_resource type="Texture2D" uid="uid://dri0a20l6kpbj" path="res://visuals/images/icon.svg" id="1_k5de2"]
@@ -14,6 +14,7 @@
[ext_resource type="Script" uid="uid://bolw6n14ocxt3" path="res://scripts/healthbar.gd" id="4_iv5le"]
[ext_resource type="Texture2D" uid="uid://bcv3f38cib5xk" path="res://visuals/images/icons/mine.png" id="4_l86lr"]
[ext_resource type="Texture2D" uid="uid://cyuylbs0o72xk" path="res://visuals/images/icons/pitfall.png" id="5_aopqe"]
[ext_resource type="Texture2D" uid="uid://cge3xladgqjp6" path="res://visuals/materials/poison gradient.tres" id="5_jf5vi"]
[ext_resource type="Texture2D" uid="uid://hiwrcar5fnyk" path="res://visuals/images/icons/switch.png" id="6_e7ody"]
[ext_resource type="Texture2D" uid="uid://cccpeolat5pk5" path="res://visuals/images/icons/selector.png" id="7_bftxg"]
[ext_resource type="Texture2D" uid="uid://divrb0alxk567" path="res://visuals/images/icons/trap arrow.png" id="12_bftxg"]
@@ -32,13 +33,6 @@
[ext_resource type="Texture2D" uid="uid://bg0h4l3162pn5" path="res://visuals/images/icons/melee attack button.png" id="28_jf5vi"]
[ext_resource type="Texture2D" uid="uid://c64lykkbavdmi" path="res://visuals/images/icons/lit melee attack button.png" id="29_deun7"]
[sub_resource type="Gradient" id="Gradient_iv5le"]
offsets = PackedFloat32Array(0, 0.59079283, 1)
colors = PackedColorArray(0.33862844, 7.9006626e-05, 0.33938414, 1, 0, 0.36556464, 0, 1, 0.6879359, 1, 0, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_1ghxf"]
gradient = SubResource("Gradient_iv5le")
[sub_resource type="Gradient" id="Gradient_1ghxf"]
[sub_resource type="GradientTexture1D" id="GradientTexture1D_gomyg"]
@@ -99,7 +93,7 @@ nine_patch_stretch = true
texture_progress = ExtResource("3_vhta5")
script = ExtResource("4_iv5le")
healthy_gradient = ExtResource("3_vhta5")
poisoned_gradient = SubResource("GradientTexture1D_1ghxf")
poisoned_gradient = ExtResource("5_jf5vi")
[node name="PanelContainer2" type="PanelContainer" parent="Control/PanelContainer/HBoxContainer/VBoxContainer2"]
custom_minimum_size = Vector2(250, 100)
@@ -114,11 +108,15 @@ layout_mode = 2
texture = ExtResource("3_k0acs")
[node name="P2HealthBar" type="TextureProgressBar" parent="Control/PanelContainer/HBoxContainer/VBoxContainer2/PanelContainer2/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 50)
layout_mode = 2
value = 100.0
nine_patch_stretch = true
texture_progress = ExtResource("3_vhta5")
script = ExtResource("4_iv5le")
healthy_gradient = ExtResource("3_vhta5")
poisoned_gradient = ExtResource("5_jf5vi")
[node name="VBoxContainer" type="VBoxContainer" parent="Control/PanelContainer/HBoxContainer"]
custom_minimum_size = Vector2(150, 0)

View File

@@ -1,9 +1,17 @@
[gd_scene load_steps=2 format=3 uid="uid://cqa0p34mbk6so"]
[gd_scene load_steps=3 format=3 uid="uid://cqa0p34mbk6so"]
[ext_resource type="Script" uid="uid://cymi1n4gavixy" path="res://scripts/level_camera.gd" id="1_ysaec"]
[ext_resource type="Script" uid="uid://cymi1n4gavixy" path="res://scripts/pawn_camera.gd" id="1_ysaec"]
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_ysaec"]
properties/0/path = NodePath(".:position")
properties/0/spawn = true
properties/0/replication_mode = 1
[node name="Camera" type="Camera3D"]
transform = Transform3D(1, 0, 0, 0, 0.49999997, 0.86602545, 0, -0.86602545, 0.49999997, 0, 0, 0)
projection = 1
size = 5.0
script = ExtResource("1_ysaec")
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_ysaec")

View File

@@ -107,4 +107,4 @@ layout_mode = 2
text = "00.000"
horizontal_alignment = 1
[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"]
[connection signal="timeout" from="Timer" to="." method="_on_trap_failed"]

View File

@@ -1,32 +1,32 @@
[gd_scene load_steps=32 format=3 uid="uid://c8xf3qawk5c6u"]
[gd_scene load_steps=34 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://wye3mat5y5yg" path="res://scripts/pawn_body.gd" id="2_ac3v1"]
[ext_resource type="Material" uid="uid://b8e84edfrnn1a" path="res://visuals/materials/pawn.tres" id="2_j3lta"]
[ext_resource type="Script" uid="uid://6w608y2grdqb" path="res://scripts/player_data.gd" id="2_sfa2f"]
[ext_resource type="AudioStream" uid="uid://b8ko5lwikj8ts" path="res://audio/sounds/Whoosh Blade 001.wav" id="3_6r6k1"]
[ext_resource type="PackedScene" uid="uid://cfunlbp8arnlh" path="res://templates/bullet.tscn" id="3_ghbft"]
[ext_resource type="AudioStream" uid="uid://cjrlb4qiy23sj" path="res://audio/sounds/impact_deep_thud_bounce_09.wav" id="3_sfa2f"]
[ext_resource type="AudioStream" uid="uid://dufoyvysi4pa1" path="res://audio/sounds/Whoosh Blade 002.wav" id="4_ac3v1"]
[ext_resource type="AudioStream" uid="uid://cfq0pu0qxgb6u" path="res://audio/sounds/134688__otbtechno__bike-bell.wav" id="4_xb5g3"]
[ext_resource type="Texture2D" uid="uid://dmnwtwu5v4voh" path="res://visuals/images/icons/detect mark.png" id="5_fwehh"]
[ext_resource type="AudioStream" uid="uid://boe6fidhl6ut5" path="res://audio/sounds/Whoosh Blade 003.wav" id="5_rclin"]
[ext_resource type="AudioStream" uid="uid://b3x0xqu8yrib4" path="res://audio/sounds/Whoosh Blade 004.wav" id="6_0pfk2"]
[ext_resource type="AudioStream" uid="uid://cmnibhyxpag0a" path="res://audio/sounds/BeepBeep_high.wav" id="6_wva0c"]
[ext_resource type="AudioStream" uid="uid://1m2yfje18spo" path="res://audio/sounds/Whoosh Blade 005.wav" id="7_fifli"]
[ext_resource type="AudioStream" uid="uid://c1j8hjmw45x86" path="res://audio/sounds/Hitech Shot A.wav" id="9_fifli"]
[ext_resource type="AudioStream" uid="uid://dgftxjb34d2ph" path="res://audio/sounds/Hitech Shot B.wav" id="10_ghbft"]
[ext_resource type="AudioStream" uid="uid://bguwdvatsf87l" path="res://audio/sounds/Hitech Shot C.wav" id="11_fuq8x"]
[ext_resource type="AudioStream" uid="uid://cw31ymbqgqcq2" path="res://audio/sounds/sci-fi_weapon_reload_03.wav" id="13_fuq8x"]
[ext_resource type="AudioStream" uid="uid://blbk74d50ldut" path="res://audio/sounds/sci-fi_forcefield_hum_loop_02.wav" id="16_yixtd"]
[ext_resource type="AudioStream" uid="uid://fqnkbcrbpi0s" path="res://audio/sounds/2 BROKEN - CK - BEAM Wood Ceiling Drop On Concrete.wav" id="17_vmejf"]
[ext_resource type="Script" uid="uid://bcs7ygh6s3l35" path="res://scripts/pawn_controller.gd" id="1_h27ep"]
[ext_resource type="Script" uid="uid://wye3mat5y5yg" path="res://scripts/pawn_body.gd" id="2_dn5ph"]
[ext_resource type="PackedScene" uid="uid://cfunlbp8arnlh" path="res://templates/bullet.tscn" id="3_pnc3q"]
[ext_resource type="Material" uid="uid://b8e84edfrnn1a" path="res://visuals/materials/pawn.tres" id="4_8twd3"]
[ext_resource type="AudioStream" uid="uid://b8ko5lwikj8ts" path="res://audio/sounds/Whoosh Blade 001.wav" id="5_77xwu"]
[ext_resource type="AudioStream" uid="uid://dufoyvysi4pa1" path="res://audio/sounds/Whoosh Blade 002.wav" id="6_fjlhr"]
[ext_resource type="AudioStream" uid="uid://boe6fidhl6ut5" path="res://audio/sounds/Whoosh Blade 003.wav" id="7_3ldvn"]
[ext_resource type="AudioStream" uid="uid://b3x0xqu8yrib4" path="res://audio/sounds/Whoosh Blade 004.wav" id="8_5bpar"]
[ext_resource type="AudioStream" uid="uid://1m2yfje18spo" path="res://audio/sounds/Whoosh Blade 005.wav" id="9_a4li3"]
[ext_resource type="AudioStream" uid="uid://c1j8hjmw45x86" path="res://audio/sounds/Hitech Shot A.wav" id="10_80lp4"]
[ext_resource type="AudioStream" uid="uid://dgftxjb34d2ph" path="res://audio/sounds/Hitech Shot B.wav" id="11_n15br"]
[ext_resource type="AudioStream" uid="uid://bguwdvatsf87l" path="res://audio/sounds/Hitech Shot C.wav" id="12_rtmky"]
[ext_resource type="AudioStream" uid="uid://cw31ymbqgqcq2" path="res://audio/sounds/sci-fi_weapon_reload_03.wav" id="13_bdfr7"]
[ext_resource type="Script" uid="uid://6w608y2grdqb" path="res://scripts/pawn_level_data.gd" id="14_ncd3b"]
[ext_resource type="AudioStream" uid="uid://cjrlb4qiy23sj" path="res://audio/sounds/impact_deep_thud_bounce_09.wav" id="15_rsl1q"]
[ext_resource type="AudioStream" uid="uid://blbk74d50ldut" path="res://audio/sounds/sci-fi_forcefield_hum_loop_02.wav" id="16_t8028"]
[ext_resource type="AudioStream" uid="uid://fqnkbcrbpi0s" path="res://audio/sounds/2 BROKEN - CK - BEAM Wood Ceiling Drop On Concrete.wav" id="17_o127k"]
[ext_resource type="AudioStream" uid="uid://cfq0pu0qxgb6u" path="res://audio/sounds/134688__otbtechno__bike-bell.wav" id="18_1x3g1"]
[ext_resource type="Texture2D" uid="uid://dmnwtwu5v4voh" path="res://visuals/images/icons/detect mark.png" id="19_5822g"]
[ext_resource type="AudioStream" uid="uid://cmnibhyxpag0a" path="res://audio/sounds/BeepBeep_high.wav" id="20_v7o58"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_y646j"]
next_pass = ExtResource("2_j3lta")
next_pass = ExtResource("4_8twd3")
albedo_color = Color(0.08468992, 0.08468992, 0.08468992, 1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_lnbra"]
next_pass = ExtResource("2_j3lta")
next_pass = ExtResource("4_8twd3")
albedo_color = Color(0, 1, 1, 1)
[sub_resource type="BoxShape3D" id="BoxShape3D_j3lta"]
@@ -38,6 +38,57 @@ emission_enabled = true
emission = Color(1, 0, 0, 1)
emission_energy_multiplier = 16.0
[sub_resource type="Animation" id="Animation_56qyi"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("MeleeArea/HitShape:disabled")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("MeleeArea/HitShape:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector3(0.6446533, 0.4691162, 0.6541977)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("MeleeArea/HitShape:rotation")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector3(0, 0.76134753, 0)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("MeleeArea/HitShape:visible")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_ofpku"]
resource_name = "melee"
length = 0.25
@@ -104,57 +155,6 @@ tracks/4/keys = {
}]
}
[sub_resource type="Animation" id="Animation_56qyi"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("MeleeArea/HitShape:disabled")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("MeleeArea/HitShape:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector3(0.6446533, 0.4691162, 0.6541977)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("MeleeArea/HitShape:rotation")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector3(0, 0.76134753, 0)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("MeleeArea/HitShape:visible")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_ac3v1"]
resource_name = "shoot"
length = 0.2
@@ -196,22 +196,30 @@ _data = {
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_ghbft"]
streams_count = 5
stream_0/stream = ExtResource("3_6r6k1")
stream_1/stream = ExtResource("4_ac3v1")
stream_2/stream = ExtResource("5_rclin")
stream_3/stream = ExtResource("6_0pfk2")
stream_4/stream = ExtResource("7_fifli")
stream_0/stream = ExtResource("5_77xwu")
stream_1/stream = ExtResource("6_fjlhr")
stream_2/stream = ExtResource("7_3ldvn")
stream_3/stream = ExtResource("8_5bpar")
stream_4/stream = ExtResource("9_a4li3")
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_rclin"]
streams_count = 3
stream_0/stream = ExtResource("9_fifli")
stream_1/stream = ExtResource("10_ghbft")
stream_2/stream = ExtResource("11_fuq8x")
stream_0/stream = ExtResource("10_80lp4")
stream_1/stream = ExtResource("11_n15br")
stream_2/stream = ExtResource("12_rtmky")
[sub_resource type="ViewportTexture" id="ViewportTexture_yixtd"]
viewport_path = NodePath("PawnBody/Subviewport")
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_a5wj7"]
radius = 0.3
height = 1.0
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_h27ep"]
properties/0/path = NodePath(".:position")
properties/0/spawn = true
properties/0/replication_mode = 1
[node name="Player" type="CharacterBody3D" groups=["combat"]]
physics_interpolation_mode = 1
collision_layer = 2
@@ -219,13 +227,13 @@ collision_mask = 5
floor_constant_speed = true
floor_max_angle = 0.93549645
floor_snap_length = 1.0
script = ExtResource("1_a5wj7")
script = ExtResource("1_h27ep")
speed = 3.0
[node name="PawnBody" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.425, 0)
script = ExtResource("2_ac3v1")
projectile_template = ExtResource("3_ghbft")
script = ExtResource("2_dn5ph")
projectile_template = ExtResource("3_pnc3q")
[node name="Mesh" type="CSGBox3D" parent="PawnBody"]
size = Vector3(0.5, 0.85, 0.5)
@@ -276,29 +284,59 @@ stream = SubResource("AudioStreamRandomizer_rclin")
[node name="ReloadSound" type="AudioStreamPlayer3D" parent="PawnBody"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.425, 0)
stream = ExtResource("13_fuq8x")
stream = ExtResource("13_bdfr7")
[node name="Subviewport" type="SubViewport" parent="PawnBody"]
disable_3d = true
transparent_bg = true
handle_input_locally = false
gui_disable_input = true
size = Vector2i(150, 60)
[node name="VBoxContainer" type="VBoxContainer" parent="PawnBody/Subviewport"]
offset_right = 40.0
offset_bottom = 40.0
[node name="Label" type="Label" parent="PawnBody/Subviewport/VBoxContainer"]
layout_mode = 2
text = "Struggle to Escape!"
[node name="StruggleBar" type="ProgressBar" parent="PawnBody/Subviewport/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 20)
layout_mode = 2
max_value = 5.0
value = 5.0
show_percentage = false
[node name="StruggleUI" type="Sprite3D" parent="PawnBody"]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.75085443, 0)
visible = false
billboard = 1
texture = SubResource("ViewportTexture_yixtd")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4665325, 0)
shape = SubResource("CapsuleShape3D_a5wj7")
[node name="Data" type="Node" parent="."]
script = ExtResource("2_sfa2f")
script = ExtResource("14_ncd3b")
[node name="TrapSound" type="AudioStreamPlayer3D" parent="."]
stream = ExtResource("3_sfa2f")
stream = ExtResource("15_rsl1q")
[node name="FlingSound" type="AudioStreamPlayer3D" parent="."]
stream = ExtResource("16_yixtd")
stream = ExtResource("16_t8028")
[node name="CrashSound" type="AudioStreamPlayer3D" parent="."]
stream = ExtResource("17_vmejf")
stream = ExtResource("17_o127k")
[node name="AudioListener3D" type="AudioListener3D" parent="."]
current = true
[node name="DetectSound" type="AudioStreamPlayer3D" parent="."]
stream = ExtResource("4_xb5g3")
stream = ExtResource("18_1x3g1")
volume_db = -80.0
max_db = -11.464
@@ -307,8 +345,11 @@ transform = Transform3D(0.75, 0, 0, 0, 0.75, 0, 0, 0, 0.75, 0, 1.2337646, 0)
visible = false
billboard = 1
no_depth_test = true
texture = ExtResource("5_fwehh")
texture = ExtResource("19_5822g")
[node name="DetonateSound" type="AudioStreamPlayer3D" parent="."]
stream = ExtResource("6_wva0c")
stream = ExtResource("20_v7o58")
max_db = -7.0
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_h27ep")

186
templates/pawn_display.tscn Normal file
View File

@@ -0,0 +1,186 @@
[gd_scene load_steps=8 format=3 uid="uid://46rpw0rrd51m"]
[ext_resource type="Script" uid="uid://blljmwvft1g8m" path="res://scripts/pawn_display.gd" id="1_c4qnx"]
[ext_resource type="Texture2D" uid="uid://dri0a20l6kpbj" path="res://visuals/images/icon.svg" id="2_dvd7o"]
[ext_resource type="Script" uid="uid://qwyhu0gexeah" path="res://scripts/cs_trap_display.gd" id="3_ph4cm"]
[sub_resource type="Shader" id="Shader_fa52j"]
code = "shader_type canvas_item;
uniform sampler2D main_texture;
uniform float granularity : hint_range(5, 30) = 15.0;
uniform float opacity_limit;
float random (vec2 uv) {
return fract(sin(dot(uv.xy,
vec2(12.9898,78.233))) * 43758.5453123);
}
void vertex() {
// Called for every vertex the material is visible on.
}
void fragment() {
// Called for every pixel the material is visible on.
vec2 uv = UV;
float g = ( pow(granularity, 2));
uv = round((uv * g)) / g;
uv.y = TIME * uv.y + TIME * .05;
uv.x = 10.0 * TIME * uv.x + TIME * 1.0;
float val = random(uv);
float op = random(-uv) / val;
float alpha = 1.0;
if(op < opacity_limit){
alpha = 0.0;
}
vec4 color = vec4(val, val, val, alpha * COLOR.a);
COLOR = color;
}
//void light() {
// // Called for every pixel for every light affecting the CanvasItem.
// // Uncomment to replace the default light processing function with this one.
//}
"
[sub_resource type="ShaderMaterial" id="ShaderMaterial_w1hxv"]
shader = SubResource("Shader_fa52j")
shader_parameter/granularity = 20.0000007125
shader_parameter/opacity_limit = 0.0
[sub_resource type="Gradient" id="Gradient_ak2if"]
offsets = PackedFloat32Array(0)
colors = PackedColorArray(0, 0, 0, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_fa52j"]
gradient = SubResource("Gradient_ak2if")
width = 1
[node name="PawnDisplay" type="Panel"]
offset_left = 94.0
offset_top = 96.0
offset_right = 794.0
offset_bottom = 796.0
script = ExtResource("1_c4qnx")
[node name="Portrait" type="TextureRect" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = ExtResource("2_dvd7o")
expand_mode = 1
[node name="PortraitBlinder" type="TextureRect" parent="."]
material = SubResource("ShaderMaterial_w1hxv")
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = SubResource("GradientTexture1D_fa52j")
expand_mode = 1
[node name="Control" type="Control" parent="."]
anchors_preset = 0
offset_left = 108.0
offset_top = 286.0
offset_right = 392.0
offset_bottom = 350.0
[node name="PawnName" type="Label" parent="Control"]
unique_name_in_owner = true
modulate = Color(0, 0.3254902, 1, 1)
layout_mode = 0
offset_left = 37.0
offset_top = 288.0
offset_right = 448.0
offset_bottom = 355.0
theme_override_font_sizes/font_size = 48
text = "NAME GOES HERE"
horizontal_alignment = 1
[node name="VBoxContainer" type="VBoxContainer" parent="Control"]
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -39.0
offset_top = 281.0
offset_right = 245.0
offset_bottom = 394.0
grow_horizontal = 2
grow_vertical = 0
[node name="Panel" type="PanelContainer" parent="Control/VBoxContainer"]
layout_mode = 2
[node name="TrapContainer" type="HBoxContainer" parent="Control/VBoxContainer/Panel"]
unique_name_in_owner = true
layout_mode = 2
[node name="TextureRect" type="TextureRect" parent="Control/VBoxContainer/Panel/TrapContainer"]
custom_minimum_size = Vector2(92, 64)
layout_mode = 2
expand_mode = 1
script = ExtResource("3_ph4cm")
[node name="Label" type="Label" parent="Control/VBoxContainer/Panel/TrapContainer/TextureRect"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -40.0
offset_top = -23.0
grow_horizontal = 0
grow_vertical = 0
text = "##"
horizontal_alignment = 2
[node name="TextureRect2" type="TextureRect" parent="Control/VBoxContainer/Panel/TrapContainer"]
custom_minimum_size = Vector2(92, 64)
layout_mode = 2
expand_mode = 1
script = ExtResource("3_ph4cm")
[node name="Label" type="Label" parent="Control/VBoxContainer/Panel/TrapContainer/TextureRect2"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -40.0
offset_top = -23.0
grow_horizontal = 0
grow_vertical = 0
text = "##"
horizontal_alignment = 2
[node name="TextureRect3" type="TextureRect" parent="Control/VBoxContainer/Panel/TrapContainer"]
custom_minimum_size = Vector2(92, 64)
layout_mode = 2
expand_mode = 1
script = ExtResource("3_ph4cm")
[node name="Label" type="Label" parent="Control/VBoxContainer/Panel/TrapContainer/TextureRect3"]
layout_mode = 1
anchors_preset = 3
anchor_left = 1.0
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -40.0
offset_top = -23.0
grow_horizontal = 0
grow_vertical = 0
text = "##"
horizontal_alignment = 2

View File

@@ -0,0 +1,84 @@
[gd_scene load_steps=8 format=3 uid="uid://bvypswoe6diaq"]
[ext_resource type="Texture2D" uid="uid://lttjm6mhx2nx" path="res://visuals/images/chselector.png" id="1_0mfxo"]
[ext_resource type="Script" uid="uid://cu7ho7656m6hp" path="res://scripts/pawn_selector.gd" id="2_xjj1m"]
[sub_resource type="Animation" id="Animation_5wdeo"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:visible")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="Animation" id="Animation_w1hxv"]
resource_name = "selected"
step = 0.0168
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:visible")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="Animation" id="Animation_fa52j"]
resource_name = "selecting"
length = 0.2667
loop_mode = 1
step = 0.0168
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:visible")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.0001, 0.13333334, 0.26666668),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [true, true, false, true]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_bqp8h"]
_data = {
&"RESET": SubResource("Animation_5wdeo"),
&"selected": SubResource("Animation_w1hxv"),
&"selecting": SubResource("Animation_fa52j")
}
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_0mfxo"]
properties/0/path = NodePath(".:player_id")
properties/0/spawn = true
properties/0/replication_mode = 1
properties/1/path = NodePath(".:modulate")
properties/1/spawn = true
properties/1/replication_mode = 1
[node name="Selector" type="TextureRect"]
texture_filter = 1
offset_right = 170.0
offset_bottom = 170.0
texture = ExtResource("1_0mfxo")
script = ExtResource("2_xjj1m")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_bqp8h")
}
autoplay = "selecting"
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_0mfxo")

50
templates/pitfall.tscn Normal file
View File

@@ -0,0 +1,50 @@
[gd_scene load_steps=6 format=3 uid="uid://pxr0irlqarst"]
[ext_resource type="Script" uid="uid://c14c3ogbf7i33" path="res://scripts/pitfall.gd" id="1_pl1py"]
[ext_resource type="Texture2D" uid="uid://dvxj8a5dj535k" path="res://visuals/images/pitfall.png" id="2_4wfyu"]
[sub_resource type="Animation" id="Animation_eaqbt"]
resource_name = "expand"
length = 0.2
tracks/0/type = "scale_3d"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite3D")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = PackedFloat32Array(0, 1, 0.1, 0.1, 0.1, 0.1, 1, 1.3, 1.3, 1.3, 0.16666667, 1, 1, 1, 1)
[sub_resource type="Animation" id="Animation_r4vne"]
length = 0.001
tracks/0/type = "scale_3d"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite3D")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = PackedFloat32Array(0, 1, 1, 1, 1)
[sub_resource type="AnimationLibrary" id="AnimationLibrary_ywdt3"]
_data = {
&"RESET": SubResource("Animation_r4vne"),
&"expand": SubResource("Animation_eaqbt")
}
[node name="Pitfall" type="Node3D"]
script = ExtResource("1_pl1py")
[node name="Sprite3D" type="Sprite3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 0.5, 0.2, 0.5)
cast_shadow = 0
pixel_size = 0.0156
texture = ExtResource("2_4wfyu")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_ywdt3")
}
autoplay = "expand"
[node name="Timer" type="Timer" parent="."]
[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 B

After

Width:  |  Height:  |  Size: 561 B

BIN
visuals/images/pitfall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

View File

@@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dvxj8a5dj535k"
path.s3tc="res://.godot/imported/pitfall.png-7673e18ab20390801e280f7c682caf5c.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://visuals/images/pitfall.png"
dest_files=["res://.godot/imported/pitfall.png-7673e18ab20390801e280f7c682caf5c.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://3dj2p3xerc45"
path="res://.godot/imported/tg-abdoll-relin.jpg-65cf431718591156b10842d38472cb8d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://visuals/images/temp_portraits/tg-abdoll-relin.jpg"
dest_files=["res://.godot/imported/tg-abdoll-relin.jpg-65cf431718591156b10842d38472cb8d.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://2qoouiv1cf0i"
path="res://.godot/imported/tg-john-bishous.jpg-c29528d028526c2676d1cd0f5fa58757.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://visuals/images/temp_portraits/tg-john-bishous.jpg"
dest_files=["res://.godot/imported/tg-john-bishous.jpg-c29528d028526c2676d1cd0f5fa58757.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://db0n6kjwucthf"
path="res://.godot/imported/tg-lou-riche.jpg-de2121514503ad46934f2b490f749d22.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://visuals/images/temp_portraits/tg-lou-riche.jpg"
dest_files=["res://.godot/imported/tg-lou-riche.jpg-de2121514503ad46934f2b490f749d22.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ci86bksme5114"
path="res://.godot/imported/tg-tenrou-ugetsu.jpg-be7357ef2a05f32703f92b59bba15865.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://visuals/images/temp_portraits/tg-tenrou-ugetsu.jpg"
dest_files=["res://.godot/imported/tg-tenrou-ugetsu.jpg-be7357ef2a05f32703f92b59bba15865.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bsug1ur2gifkh"
path="res://.godot/imported/tg-tico.jpg-2583811c1d5e9514a31e06ef7c6a60d6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://visuals/images/temp_portraits/tg-tico.jpg"
dest_files=["res://.godot/imported/tg-tico.jpg-2583811c1d5e9514a31e06ef7c6a60d6.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bp6wc55s2t4si"
path="res://.godot/imported/tg-van-raily.jpg-f26f9106f8cfa2ef65265596304a91d6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://visuals/images/temp_portraits/tg-van-raily.jpg"
dest_files=["res://.godot/imported/tg-van-raily.jpg-f26f9106f8cfa2ef65265596304a91d6.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

View File

@@ -0,0 +1,8 @@
[gd_resource type="GradientTexture1D" load_steps=2 format=3 uid="uid://cge3xladgqjp6"]
[sub_resource type="Gradient" id="Gradient_iv5le"]
offsets = PackedFloat32Array(0, 0.59079283, 1)
colors = PackedColorArray(0.33862844, 7.9006626e-05, 0.33938414, 1, 0, 0.36556464, 0, 1, 0.6879359, 1, 0, 1)
[resource]
gradient = SubResource("Gradient_iv5le")

View File

@@ -0,0 +1,3 @@
[gd_resource type="ViewportTexture" format=3 uid="uid://csc28ut68d6af"]
[resource]