Compare commits
5 Commits
e64bcc0427
...
def6539bbc
| Author | SHA1 | Date | |
|---|---|---|---|
| def6539bbc | |||
| c38526bc48 | |||
| e6793fde61 | |||
| f92ddf567d | |||
| 9187e6abff |
BIN
godot/assets/HealthPickup.fbx
Normal file
BIN
godot/assets/HealthPickup.fbx
Normal file
Binary file not shown.
46
godot/assets/HealthPickup.fbx.import
Normal file
46
godot/assets/HealthPickup.fbx.import
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="scene"
|
||||||
|
importer_version=1
|
||||||
|
type="PackedScene"
|
||||||
|
uid="uid://dgav57iyh6nxg"
|
||||||
|
path="res://.godot/imported/HealthPickup.fbx-608a017b8743e952888462d93dec636c.scn"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/HealthPickup.fbx"
|
||||||
|
dest_files=["res://.godot/imported/HealthPickup.fbx-608a017b8743e952888462d93dec636c.scn"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
nodes/root_type=""
|
||||||
|
nodes/root_name=""
|
||||||
|
nodes/root_script=null
|
||||||
|
mesh_library/use_node_names_as_mesh_names=false
|
||||||
|
array_mesh/deduplicate_surfaces=true
|
||||||
|
nodes/apply_root_scale=true
|
||||||
|
nodes/root_scale=1.0
|
||||||
|
nodes/import_as_skeleton_bones=false
|
||||||
|
nodes/use_name_suffixes=true
|
||||||
|
nodes/use_node_type_suffixes=true
|
||||||
|
meshes/ensure_tangents=true
|
||||||
|
meshes/generate_lods=true
|
||||||
|
meshes/create_shadow_meshes=true
|
||||||
|
meshes/light_baking=1
|
||||||
|
meshes/lightmap_texel_size=0.2
|
||||||
|
meshes/force_disable_compression=false
|
||||||
|
skins/use_named_skins=true
|
||||||
|
animation/import=true
|
||||||
|
animation/fps=30
|
||||||
|
animation/trimming=true
|
||||||
|
animation/remove_immutable_tracks=true
|
||||||
|
animation/import_rest_as_RESET=false
|
||||||
|
import_script/path=""
|
||||||
|
materials/extract=0
|
||||||
|
materials/extract_format=0
|
||||||
|
materials/extract_path=""
|
||||||
|
_subresources={}
|
||||||
|
fbx/importer=0
|
||||||
|
fbx/allow_geometry_helper_nodes=false
|
||||||
|
fbx/embedded_image_handling=1
|
||||||
|
fbx/naming_version=2
|
||||||
@ -1,11 +1,7 @@
|
|||||||
[gd_scene format=3 uid="uid://7iooamjot1tg"]
|
[gd_scene format=3 uid="uid://7iooamjot1tg"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://ct70bpbca8one" path="res://scenes/player/local_player.tscn" id="1_yjvui"]
|
[ext_resource type="PackedScene" uid="uid://dov2eh5u4ypnx" path="res://scenes/misc/health_pickup.tscn" id="2_yffox"]
|
||||||
[ext_resource type="PackedScene" uid="uid://kfxc0migw80o" path="res://scenes/player/remote_player.tscn" id="2_kcncr"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://hmh2lrrlo2wy" path="res://scenes/player/replay_player.tscn" id="3_8af6u"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://dfnbc8sbufa4j" path="res://scenes/misc/ball.tscn" id="3_e0nj3"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://c1r8nk58cci3a" path="res://scenes/misc/goal.tscn" id="4_w7til"]
|
[ext_resource type="PackedScene" uid="uid://c1r8nk58cci3a" path="res://scenes/misc/goal.tscn" id="4_w7til"]
|
||||||
[ext_resource type="PackedScene" uid="uid://dc17w5n6y1an" path="res://scenes/misc/replay_ball.tscn" id="5_oqkce"]
|
|
||||||
|
|
||||||
[sub_resource type="ImageTexture" id="ImageTexture_3vyb7"]
|
[sub_resource type="ImageTexture" id="ImageTexture_3vyb7"]
|
||||||
|
|
||||||
@ -15,32 +11,20 @@ albedo_texture = SubResource("ImageTexture_3vyb7")
|
|||||||
[sub_resource type="PlaneMesh" id="PlaneMesh_1cgct"]
|
[sub_resource type="PlaneMesh" id="PlaneMesh_1cgct"]
|
||||||
size = Vector2(100, 100)
|
size = Vector2(100, 100)
|
||||||
|
|
||||||
[sub_resource type="BoxShape3D" id="BoxShape3D_1cgct"]
|
|
||||||
size = Vector3(100, 0.01, 100)
|
|
||||||
|
|
||||||
[sub_resource type="BoxShape3D" id="BoxShape3D_3g557"]
|
[sub_resource type="BoxShape3D" id="BoxShape3D_3g557"]
|
||||||
size = Vector3(1000, 1, 1000)
|
size = Vector3(1000, 1, 1000)
|
||||||
|
|
||||||
|
[sub_resource type="BoxShape3D" id="BoxShape3D_1cgct"]
|
||||||
|
size = Vector3(100, 0.01, 100)
|
||||||
|
|
||||||
[node name="map" type="Map" unique_id=914577955 node_paths=PackedStringArray("spawners", "ball_spawner")]
|
[node name="map" type="Map" unique_id=914577955 node_paths=PackedStringArray("spawners", "ball_spawner")]
|
||||||
spawners = [NodePath("team1_spawner"), NodePath("team2_spawner")]
|
spawners = [NodePath("team1_spawner"), NodePath("team2_spawner")]
|
||||||
ball_spawner = NodePath("ball_spawner")
|
ball_spawner = NodePath("ball_spawner")
|
||||||
local_player = ExtResource("1_yjvui")
|
|
||||||
remote_player = ExtResource("2_kcncr")
|
|
||||||
replay_player = ExtResource("3_8af6u")
|
|
||||||
ball = ExtResource("3_e0nj3")
|
|
||||||
replay_ball = ExtResource("5_oqkce")
|
|
||||||
|
|
||||||
[node name="terrain" type="MeshInstance3D" parent="." unique_id=1474127252]
|
[node name="terrain" type="MeshInstance3D" parent="." unique_id=1474127252]
|
||||||
material_override = SubResource("StandardMaterial3D_u8vuu")
|
material_override = SubResource("StandardMaterial3D_u8vuu")
|
||||||
mesh = SubResource("PlaneMesh_1cgct")
|
mesh = SubResource("PlaneMesh_1cgct")
|
||||||
|
|
||||||
[node name="static_body_3d" type="StaticBody3D" parent="terrain" unique_id=203785193]
|
|
||||||
collision_layer = 7
|
|
||||||
collision_mask = 7
|
|
||||||
|
|
||||||
[node name="collision_shape_3d" type="CollisionShape3D" parent="terrain/static_body_3d" unique_id=1466526153]
|
|
||||||
shape = SubResource("BoxShape3D_1cgct")
|
|
||||||
|
|
||||||
[node name="directional_light_3d" type="DirectionalLight3D" parent="." unique_id=793524416]
|
[node name="directional_light_3d" type="DirectionalLight3D" parent="." unique_id=793524416]
|
||||||
transform = Transform3D(1, 0, 0, 0, 0.7274598, 0.6861503, 0, -0.6861503, 0.7274598, -5.1267624, 3.3997262, 3.715582)
|
transform = Transform3D(1, 0, 0, 0, 0.7274598, 0.6861503, 0, -0.6861503, 0.7274598, -5.1267624, 3.3997262, 3.715582)
|
||||||
|
|
||||||
@ -67,3 +51,13 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -12.468555, 0.0050001144, 4.4
|
|||||||
[node name="goal2" parent="." unique_id=1997661586 instance=ExtResource("4_w7til")]
|
[node name="goal2" parent="." unique_id=1997661586 instance=ExtResource("4_w7til")]
|
||||||
team = 1
|
team = 1
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.417626, 0.0050001144, -3.8839006)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.417626, 0.0050001144, -3.8839006)
|
||||||
|
|
||||||
|
[node name="static_body_3d" type="StaticBody3D" parent="." unique_id=203785193]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.526536, 0, 10.695821)
|
||||||
|
collision_layer = 7
|
||||||
|
collision_mask = 7
|
||||||
|
|
||||||
|
[node name="collision_shape_3d" type="CollisionShape3D" parent="static_body_3d" unique_id=1466526153]
|
||||||
|
shape = SubResource("BoxShape3D_1cgct")
|
||||||
|
|
||||||
|
[node name="health_pickup" parent="static_body_3d/collision_shape_3d" unique_id=1860192333 instance=ExtResource("2_yffox")]
|
||||||
|
|||||||
14
godot/mesh/health_pickup.tscn
Normal file
14
godot/mesh/health_pickup.tscn
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[gd_scene format=3 uid="uid://d0hq2ctndreej"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dgav57iyh6nxg" path="res://assets/HealthPickup.fbx" id="1_r21p4"]
|
||||||
|
|
||||||
|
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_tue51"]
|
||||||
|
albedo_color = Color(0, 1, 0, 1)
|
||||||
|
emission_enabled = true
|
||||||
|
emission = Color(0, 1, 0, 1)
|
||||||
|
emission_energy_multiplier = 5.0
|
||||||
|
|
||||||
|
[node name="HealthPickup" unique_id=663926357 instance=ExtResource("1_r21p4")]
|
||||||
|
|
||||||
|
[node name="Cube" parent="." index="0" unique_id=659090742]
|
||||||
|
surface_material_override/0 = SubResource("StandardMaterial3D_tue51")
|
||||||
BIN
godot/raw_assets/Soldier/HealthPickup.blend
Normal file
BIN
godot/raw_assets/Soldier/HealthPickup.blend
Normal file
Binary file not shown.
BIN
godot/raw_assets/Soldier/HealthPickup.blend1
Normal file
BIN
godot/raw_assets/Soldier/HealthPickup.blend1
Normal file
Binary file not shown.
19
godot/scenes/misc/health_pickup.tscn
Normal file
19
godot/scenes/misc/health_pickup.tscn
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[gd_scene format=3 uid="uid://dov2eh5u4ypnx"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://d0hq2ctndreej" path="res://mesh/health_pickup.tscn" id="1_1mios"]
|
||||||
|
|
||||||
|
[sub_resource type="SphereShape3D" id="SphereShape3D_1cgct"]
|
||||||
|
radius = 0.8577998
|
||||||
|
|
||||||
|
[node name="health_pickup" type="HealthPickup" unique_id=1860192333 node_paths=PackedStringArray("pickup_area")]
|
||||||
|
pickup_area = NodePath("area_3d")
|
||||||
|
|
||||||
|
[node name="area_3d" type="Area3D" parent="." unique_id=168425054]
|
||||||
|
transform = Transform3D(0.5306476, 0, -0.8475926, 0, 1, 0, 0.8475926, 0, 0.5306476, 0, 1.2881019, 0)
|
||||||
|
collision_layer = 0
|
||||||
|
collision_mask = 3
|
||||||
|
|
||||||
|
[node name="HealthPickup" parent="area_3d" unique_id=663926357 instance=ExtResource("1_1mios")]
|
||||||
|
|
||||||
|
[node name="collision_shape_3d" type="CollisionShape3D" parent="area_3d" unique_id=1572818215]
|
||||||
|
shape = SubResource("SphereShape3D_1cgct")
|
||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1cgct"]
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1cgct"]
|
||||||
|
|
||||||
[sub_resource type="ViewportTexture" id="ViewportTexture_1cgct"]
|
[sub_resource type="ViewportTexture" id="ViewportTexture_orxjf"]
|
||||||
viewport_path = NodePath("health_bar_sprite/health_bar_viewport")
|
viewport_path = NodePath("health_bar_sprite/health_bar_viewport")
|
||||||
|
|
||||||
[sub_resource type="Curve" id="Curve_yli5f"]
|
[sub_resource type="Curve" id="Curve_yli5f"]
|
||||||
@ -32,7 +32,10 @@ point_count = 2
|
|||||||
width = 70
|
width = 70
|
||||||
curve = SubResource("Curve_qn18y")
|
curve = SubResource("Curve_qn18y")
|
||||||
|
|
||||||
[node name="player" type="RemotePlayer" unique_id=845968872 node_paths=PackedStringArray("soldier_mesh", "collider", "effects", "spectator_camera", "camera_origin", "name_label", "health_bar", "health_bar_sprite")]
|
[sub_resource type="ViewportTexture" id="ViewportTexture_rmxnb"]
|
||||||
|
viewport_path = NodePath("double_health_bar_sprite/health_bar_viewport")
|
||||||
|
|
||||||
|
[node name="player" type="RemotePlayer" unique_id=845968872 node_paths=PackedStringArray("soldier_mesh", "collider", "effects", "spectator_camera", "camera_origin", "name_label", "health_bar", "double_health_bar", "health_bar_sprite", "double_health_bar_sprite")]
|
||||||
move_speed = 7.0
|
move_speed = 7.0
|
||||||
soldier_mesh = NodePath("soldier_m")
|
soldier_mesh = NodePath("soldier_m")
|
||||||
collider = NodePath("collision_shape_3d")
|
collider = NodePath("collision_shape_3d")
|
||||||
@ -43,7 +46,9 @@ spectator_camera = NodePath("spectate_root/spectate_camera")
|
|||||||
camera_origin = NodePath("camera_origin")
|
camera_origin = NodePath("camera_origin")
|
||||||
name_label = NodePath("name_label")
|
name_label = NodePath("name_label")
|
||||||
health_bar = NodePath("health_bar_sprite/health_bar_viewport/health_bar")
|
health_bar = NodePath("health_bar_sprite/health_bar_viewport/health_bar")
|
||||||
|
double_health_bar = NodePath("double_health_bar_sprite/health_bar_viewport/double_health_bar")
|
||||||
health_bar_sprite = NodePath("health_bar_sprite")
|
health_bar_sprite = NodePath("health_bar_sprite")
|
||||||
|
double_health_bar_sprite = NodePath("double_health_bar_sprite")
|
||||||
collision_layer = 2
|
collision_layer = 2
|
||||||
collision_mask = 4
|
collision_mask = 4
|
||||||
slide_on_ceiling = false
|
slide_on_ceiling = false
|
||||||
@ -78,7 +83,7 @@ font_size = 64
|
|||||||
[node name="health_bar_sprite" type="Sprite3D" parent="." unique_id=1478315510]
|
[node name="health_bar_sprite" type="Sprite3D" parent="." unique_id=1478315510]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.1606798, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.1606798, 0)
|
||||||
billboard = 1
|
billboard = 1
|
||||||
texture = SubResource("ViewportTexture_1cgct")
|
texture = SubResource("ViewportTexture_orxjf")
|
||||||
|
|
||||||
[node name="health_bar_viewport" type="SubViewport" parent="health_bar_sprite" unique_id=1819065918]
|
[node name="health_bar_viewport" type="SubViewport" parent="health_bar_sprite" unique_id=1819065918]
|
||||||
disable_3d = true
|
disable_3d = true
|
||||||
@ -98,3 +103,27 @@ texture_progress = SubResource("CurveTexture_840kl")
|
|||||||
tint_under = Color(0, 0, 0, 0.3647059)
|
tint_under = Color(0, 0, 0, 0.3647059)
|
||||||
tint_over = Color(1, 1, 1, 0)
|
tint_over = Color(1, 1, 1, 0)
|
||||||
tint_progress = Color(0.5660922, 1.7688051e-06, 3.3691526e-07, 1)
|
tint_progress = Color(0.5660922, 1.7688051e-06, 3.3691526e-07, 1)
|
||||||
|
|
||||||
|
[node name="double_health_bar_sprite" type="Sprite3D" parent="." unique_id=1003826376]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.075818, 0)
|
||||||
|
billboard = 1
|
||||||
|
texture = SubResource("ViewportTexture_rmxnb")
|
||||||
|
|
||||||
|
[node name="health_bar_viewport" type="SubViewport" parent="double_health_bar_sprite" unique_id=1279264647]
|
||||||
|
disable_3d = true
|
||||||
|
transparent_bg = true
|
||||||
|
size = Vector2i(70, 10)
|
||||||
|
size_2d_override = Vector2i(70, 10)
|
||||||
|
size_2d_override_stretch = true
|
||||||
|
|
||||||
|
[node name="double_health_bar" type="TextureProgressBar" parent="double_health_bar_sprite/health_bar_viewport" unique_id=62083710]
|
||||||
|
offset_right = 70.0
|
||||||
|
offset_bottom = 1.0
|
||||||
|
scale = Vector2(1, 5)
|
||||||
|
value = 50.0
|
||||||
|
texture_under = SubResource("CurveTexture_3g557")
|
||||||
|
texture_over = SubResource("CurveTexture_1cgct")
|
||||||
|
texture_progress = SubResource("CurveTexture_840kl")
|
||||||
|
tint_under = Color(0, 0, 0, 0)
|
||||||
|
tint_over = Color(1, 1, 1, 0)
|
||||||
|
tint_progress = Color(0.5660922, 1.7688051e-06, 3.3691526e-07, 1)
|
||||||
|
|||||||
@ -32,7 +32,10 @@ point_count = 2
|
|||||||
width = 70
|
width = 70
|
||||||
curve = SubResource("Curve_qn18y")
|
curve = SubResource("Curve_qn18y")
|
||||||
|
|
||||||
[node name="player" type="RemotePlayer" unique_id=845968872 node_paths=PackedStringArray("soldier_mesh", "collider", "effects", "spectator_camera", "camera_origin", "name_label", "health_bar", "health_bar_sprite")]
|
[sub_resource type="ViewportTexture" id="ViewportTexture_bfcd3"]
|
||||||
|
viewport_path = NodePath("double_health_bar_sprite/double_health_bar_viewport")
|
||||||
|
|
||||||
|
[node name="player" type="RemotePlayer" unique_id=845968872 node_paths=PackedStringArray("soldier_mesh", "collider", "effects", "spectator_camera", "camera_origin", "name_label", "health_bar", "double_health_bar", "health_bar_sprite", "double_health_bar_sprite")]
|
||||||
move_speed = 5.0
|
move_speed = 5.0
|
||||||
soldier_mesh = NodePath("soldier_m")
|
soldier_mesh = NodePath("soldier_m")
|
||||||
collider = NodePath("collision_shape_3d")
|
collider = NodePath("collision_shape_3d")
|
||||||
@ -43,7 +46,9 @@ spectator_camera = NodePath("spectate_root/spectate_camera")
|
|||||||
camera_origin = NodePath("camera_origin")
|
camera_origin = NodePath("camera_origin")
|
||||||
name_label = NodePath("name_label")
|
name_label = NodePath("name_label")
|
||||||
health_bar = NodePath("health_bar_sprite/health_bar_viewport/health_bar")
|
health_bar = NodePath("health_bar_sprite/health_bar_viewport/health_bar")
|
||||||
|
double_health_bar = NodePath("double_health_bar_sprite/double_health_bar_viewport/double_health_bar")
|
||||||
health_bar_sprite = NodePath("health_bar_sprite")
|
health_bar_sprite = NodePath("health_bar_sprite")
|
||||||
|
double_health_bar_sprite = NodePath("double_health_bar_sprite")
|
||||||
collision_layer = 16
|
collision_layer = 16
|
||||||
collision_mask = 4
|
collision_mask = 4
|
||||||
|
|
||||||
@ -96,3 +101,27 @@ texture_progress = SubResource("CurveTexture_840kl")
|
|||||||
tint_under = Color(0, 0, 0, 0.3647059)
|
tint_under = Color(0, 0, 0, 0.3647059)
|
||||||
tint_over = Color(1, 1, 1, 0)
|
tint_over = Color(1, 1, 1, 0)
|
||||||
tint_progress = Color(0.5660922, 1.7688051e-06, 3.3691526e-07, 1)
|
tint_progress = Color(0.5660922, 1.7688051e-06, 3.3691526e-07, 1)
|
||||||
|
|
||||||
|
[node name="double_health_bar_sprite" type="Sprite3D" parent="." unique_id=1841216543]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.0923502, 0)
|
||||||
|
billboard = 1
|
||||||
|
texture = SubResource("ViewportTexture_bfcd3")
|
||||||
|
|
||||||
|
[node name="double_health_bar_viewport" type="SubViewport" parent="double_health_bar_sprite" unique_id=1749355472]
|
||||||
|
disable_3d = true
|
||||||
|
transparent_bg = true
|
||||||
|
size = Vector2i(70, 10)
|
||||||
|
size_2d_override = Vector2i(70, 10)
|
||||||
|
size_2d_override_stretch = true
|
||||||
|
|
||||||
|
[node name="double_health_bar" type="TextureProgressBar" parent="double_health_bar_sprite/double_health_bar_viewport" unique_id=220343908]
|
||||||
|
offset_right = 70.0
|
||||||
|
offset_bottom = 1.0
|
||||||
|
scale = Vector2(1, 5)
|
||||||
|
value = 50.0
|
||||||
|
texture_under = SubResource("CurveTexture_3g557")
|
||||||
|
texture_over = SubResource("CurveTexture_1cgct")
|
||||||
|
texture_progress = SubResource("CurveTexture_840kl")
|
||||||
|
tint_under = Color(0, 0, 0, 0)
|
||||||
|
tint_over = Color(1, 1, 1, 0)
|
||||||
|
tint_progress = Color(0.5660922, 1.7688051e-06, 3.3691526e-07, 1)
|
||||||
|
|||||||
@ -19,6 +19,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
util::NetVector3,
|
util::NetVector3,
|
||||||
},
|
},
|
||||||
|
pickup::{Pickup, PickupCommon, PickupKind},
|
||||||
player::{
|
player::{
|
||||||
DamageSource, IPlayer, NetTransform, ball::Ball, local_player::LocalPlayer,
|
DamageSource, IPlayer, NetTransform, ball::Ball, local_player::LocalPlayer,
|
||||||
remote_player::RemotePlayer, weapon::WeaponType,
|
remote_player::RemotePlayer, weapon::WeaponType,
|
||||||
@ -366,6 +367,8 @@ impl Game {
|
|||||||
pub fn on_game_finished();
|
pub fn on_game_finished();
|
||||||
#[signal]
|
#[signal]
|
||||||
pub fn on_player_killed(player: u16);
|
pub fn on_player_killed(player: u16);
|
||||||
|
#[signal]
|
||||||
|
pub fn on_map_loaded(map: Gd<Map>);
|
||||||
|
|
||||||
pub fn singleton() -> Option<Gd<Game>> {
|
pub fn singleton() -> Option<Gd<Game>> {
|
||||||
if GameManager::singleton().get_children().len() > 0 {
|
if GameManager::singleton().get_children().len() > 0 {
|
||||||
@ -693,7 +696,7 @@ impl Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_map_loaded(&mut self, map: Gd<Map>) {
|
pub fn on_map_loaded(&mut self, map: Gd<Map>) {
|
||||||
self.current_map = Some(map);
|
self.current_map = Some(map.clone());
|
||||||
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer {
|
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer {
|
||||||
if let PeerKind::Client(peer, to) = peer {
|
if let PeerKind::Client(peer, to) = peer {
|
||||||
peer.send_reliable(to, Package::MapLoaded);
|
peer.send_reliable(to, Package::MapLoaded);
|
||||||
@ -706,6 +709,7 @@ impl Game {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.signals().on_map_loaded().emit(&map);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn_ball(
|
pub fn spawn_ball(
|
||||||
@ -1207,6 +1211,37 @@ impl Game {
|
|||||||
pub fn recorder(&mut self) -> &mut Option<Gd<ReplayRecorder>> {
|
pub fn recorder(&mut self) -> &mut Option<Gd<ReplayRecorder>> {
|
||||||
&mut self.replay_recorder
|
&mut self.replay_recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_pickup(&mut self, id: u8, player_id: u16) {
|
||||||
|
self.run_deferred(move |s| {
|
||||||
|
let kind = if let Some(map) = &mut s.current_map
|
||||||
|
&& let Some(pickup) = map.bind_mut().pickups.get_mut(&id)
|
||||||
|
{
|
||||||
|
pickup.dyn_bind_mut().on_pickup();
|
||||||
|
pickup.dyn_bind().kind()
|
||||||
|
} else {
|
||||||
|
PickupKind::Health
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(player) = s.find_player_mut(player_id)
|
||||||
|
&& let Some(character) = &mut player.character
|
||||||
|
{
|
||||||
|
character.dyn_bind_mut().on_pickup(kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(recorder) = &mut s.replay_recorder {
|
||||||
|
recorder
|
||||||
|
.bind_mut()
|
||||||
|
.record_event(ReplayEvent::Pickup(kind, player_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer
|
||||||
|
&& let PeerKind::Server(peer, _) = peer
|
||||||
|
{
|
||||||
|
peer.broadcast_reliable(Package::Pickup(id, player_id));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|||||||
@ -11,6 +11,7 @@ pub mod killbox;
|
|||||||
pub mod map;
|
pub mod map;
|
||||||
pub mod map_resource;
|
pub mod map_resource;
|
||||||
pub mod net;
|
pub mod net;
|
||||||
|
pub mod pickup;
|
||||||
pub mod player;
|
pub mod player;
|
||||||
pub mod popup_queue;
|
pub mod popup_queue;
|
||||||
pub mod replay;
|
pub mod replay;
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use godot::{classes::CharacterBody3D, prelude::*};
|
use godot::{classes::CharacterBody3D, prelude::*};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
game_manager::{Game, GameManager},
|
game_manager::{Game, GameManager},
|
||||||
net::util::NetVector3,
|
net::util::NetVector3,
|
||||||
|
pickup::Pickup,
|
||||||
player::{
|
player::{
|
||||||
IPlayer, NetTransform, ball::Ball, local_player::LocalPlayer, remote_player::RemotePlayer,
|
IPlayer, NetTransform, ball::Ball, local_player::LocalPlayer, remote_player::RemotePlayer,
|
||||||
},
|
},
|
||||||
@ -17,6 +20,9 @@ pub struct Map {
|
|||||||
#[export]
|
#[export]
|
||||||
pub ball_spawner: Option<Gd<Node3D>>,
|
pub ball_spawner: Option<Gd<Node3D>>,
|
||||||
|
|
||||||
|
pickup_counter: u8,
|
||||||
|
pub pickups: HashMap<u8, DynGd<Node3D, dyn Pickup>>,
|
||||||
|
|
||||||
base: Base<Node3D>,
|
base: Base<Node3D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,4 +194,11 @@ impl Map {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn register_pickup(&mut self, pickup: DynGd<Node3D, dyn Pickup>) -> u8 {
|
||||||
|
let id = self.pickup_counter;
|
||||||
|
self.pickup_counter += 1;
|
||||||
|
self.pickups.insert(id, pickup);
|
||||||
|
id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ use crate::{
|
|||||||
game_manager::{Game, GameManager, GameOption, GameOptionValue, NetPlayer},
|
game_manager::{Game, GameManager, GameOption, GameOptionValue, NetPlayer},
|
||||||
game_settings::GameSettingsManager,
|
game_settings::GameSettingsManager,
|
||||||
net::{net_stats::Stats, util::NetVector3},
|
net::{net_stats::Stats, util::NetVector3},
|
||||||
|
pickup::PickupKind,
|
||||||
player::{DamageSource, NetTransform, weapon::WeaponType},
|
player::{DamageSource, NetTransform, weapon::WeaponType},
|
||||||
popup_queue::{Popup, PopupQueue},
|
popup_queue::{Popup, PopupQueue},
|
||||||
ui::cli::{CliColor, CommandLinePanel},
|
ui::cli::{CliColor, CommandLinePanel},
|
||||||
@ -314,6 +315,7 @@ pub enum Package {
|
|||||||
SwapWeapon(u16, WeaponType),
|
SwapWeapon(u16, WeaponType),
|
||||||
Goal(Vec<u8>),
|
Goal(Vec<u8>),
|
||||||
Announcement(u16, Announcement),
|
Announcement(u16, Announcement),
|
||||||
|
Pickup(u8, u16),
|
||||||
|
|
||||||
// End-of-Game packages
|
// End-of-Game packages
|
||||||
FinishGame,
|
FinishGame,
|
||||||
|
|||||||
@ -226,6 +226,11 @@ impl NetworkManager {
|
|||||||
game.bind_mut().on_chat_message(source_id, message);
|
game.bind_mut().on_chat_message(source_id, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Package::Pickup(pickup_id, player_id) => {
|
||||||
|
if let Some(game) = &mut Game::singleton() {
|
||||||
|
game.bind_mut().on_pickup(pickup_id, player_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
149
rust/src/pickup.rs
Normal file
149
rust/src/pickup.rs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
use godot::{classes::Area3D, prelude::*};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
game_manager::Game,
|
||||||
|
map::Map,
|
||||||
|
net::network_manager::NetworkManager,
|
||||||
|
player::{IPlayer, local_player::LocalPlayer},
|
||||||
|
replay::StandaloneReplayManager,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
pub enum PickupKind {
|
||||||
|
Health,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub enum ReplayVisibility {
|
||||||
|
#[default]
|
||||||
|
NoReplay,
|
||||||
|
Hidden,
|
||||||
|
Visible,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node3D, init, tool)]
|
||||||
|
pub struct HealthPickup {
|
||||||
|
#[export]
|
||||||
|
pub pickup_area: Option<Gd<Area3D>>,
|
||||||
|
|
||||||
|
time_elapsed: f64,
|
||||||
|
pickup_id: Option<u8>,
|
||||||
|
respawn: f64,
|
||||||
|
replay_visibility: ReplayVisibility,
|
||||||
|
|
||||||
|
base: Base<Node3D>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode3D for HealthPickup {
|
||||||
|
fn ready(&mut self) {
|
||||||
|
if let Some(area) = self.pickup_area.clone() {
|
||||||
|
area.signals()
|
||||||
|
.body_entered()
|
||||||
|
.connect_other(self, Self::on_collision);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(game) = &Game::singleton() {
|
||||||
|
game.signals()
|
||||||
|
.on_map_loaded()
|
||||||
|
.connect_other(self, Self::register_pickup);
|
||||||
|
} else {
|
||||||
|
StandaloneReplayManager::singleton()
|
||||||
|
.signals()
|
||||||
|
.on_map_loaded()
|
||||||
|
.connect_other(self, Self::register_pickup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, delta: f64) {
|
||||||
|
self.time_elapsed += delta;
|
||||||
|
self.respawn -= delta;
|
||||||
|
self.update_common(self.time_elapsed);
|
||||||
|
if let Some(mut area) = self.pickup_area.clone() {
|
||||||
|
match self.replay_visibility {
|
||||||
|
ReplayVisibility::NoReplay => {
|
||||||
|
area.set_visible(self.is_active());
|
||||||
|
}
|
||||||
|
ReplayVisibility::Hidden => area.set_visible(false),
|
||||||
|
ReplayVisibility::Visible => area.set_visible(true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HealthPickup {
|
||||||
|
pub fn register_pickup(&mut self, mut map: Gd<Map>) {
|
||||||
|
self.run_deferred(move |s| {
|
||||||
|
let id = map
|
||||||
|
.bind_mut()
|
||||||
|
.register_pickup(s.to_gd().into_dyn().upcast());
|
||||||
|
s.pickup_id = Some(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_dyn]
|
||||||
|
impl Pickup for HealthPickup {
|
||||||
|
fn area(&mut self) -> &mut Option<Gd<Area3D>> {
|
||||||
|
&mut self.pickup_area
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kind(&self) -> PickupKind {
|
||||||
|
PickupKind::Health
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<u8> {
|
||||||
|
self.pickup_id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_pickup(&mut self) {
|
||||||
|
self.respawn = 30.;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_active(&self) -> bool {
|
||||||
|
self.respawn <= 0.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_replay(&mut self, visible: ReplayVisibility) {
|
||||||
|
self.replay_visibility = visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Pickup {
|
||||||
|
fn area(&mut self) -> &mut Option<Gd<Area3D>>;
|
||||||
|
fn kind(&self) -> PickupKind;
|
||||||
|
fn id(&self) -> Option<u8>;
|
||||||
|
fn on_pickup(&mut self);
|
||||||
|
fn is_active(&self) -> bool;
|
||||||
|
fn set_replay(&mut self, visibility: ReplayVisibility);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait PickupCommon {
|
||||||
|
fn update_common(&mut self, time_elapsed: f64);
|
||||||
|
fn on_collision(&mut self, collider: Gd<Node3D>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pickup> PickupCommon for T {
|
||||||
|
fn update_common(&mut self, time_elapsed: f64) {
|
||||||
|
if let Some(area) = self.area() {
|
||||||
|
area.set_position(Vector3::UP * 1.5 + Vector3::UP * (time_elapsed.sin() / 4.) as f32);
|
||||||
|
area.set_rotation(Vector3::UP * time_elapsed as f32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_collision(&mut self, collider: Gd<Node3D>) {
|
||||||
|
if !NetworkManager::singleton().bind().is_host() || !self.is_active() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Some(game) = &mut Game::singleton()
|
||||||
|
&& let Ok(player) = collider.try_dynify::<dyn IPlayer>()
|
||||||
|
{
|
||||||
|
game.bind_mut().on_pickup(
|
||||||
|
self.id().unwrap_or(0),
|
||||||
|
player.dyn_bind().get_player_id().unwrap_or(0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,6 +21,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
util::cast_ray,
|
util::cast_ray,
|
||||||
},
|
},
|
||||||
|
pickup::PickupKind,
|
||||||
player::{
|
player::{
|
||||||
DamageSource, DamageSourceSignal, IPlayer, NetTransform, PlayerCommon,
|
DamageSource, DamageSourceSignal, IPlayer, NetTransform, PlayerCommon,
|
||||||
effects::PlayerEffects,
|
effects::PlayerEffects,
|
||||||
@ -298,6 +299,20 @@ impl IPlayer for LocalPlayer {
|
|||||||
fn get_health(&self) -> i32 {
|
fn get_health(&self) -> i32 {
|
||||||
self.health
|
self.health
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn heal(&mut self, amount: i32) {
|
||||||
|
self.run_deferred(move |s| {
|
||||||
|
let delta = (s.health + amount).min(200) - s.health;
|
||||||
|
s.run_deferred(move |s| s.signals().on_heal().emit(delta));
|
||||||
|
s.health += delta;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_pickup(&mut self, kind: PickupKind) {
|
||||||
|
match kind {
|
||||||
|
PickupKind::Health => self.heal(100),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[godot_api]
|
#[godot_api]
|
||||||
@ -592,6 +607,8 @@ impl LocalPlayer {
|
|||||||
killbox_kind: KillboxKind,
|
killbox_kind: KillboxKind,
|
||||||
damage: i32,
|
damage: i32,
|
||||||
);
|
);
|
||||||
|
#[signal]
|
||||||
|
pub fn on_heal(amount: i32);
|
||||||
|
|
||||||
fn set_lock(&mut self, locked: bool) {
|
fn set_lock(&mut self, locked: bool) {
|
||||||
self.locked = locked;
|
self.locked = locked;
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use crate::{
|
|||||||
network_manager::NetworkManager,
|
network_manager::NetworkManager,
|
||||||
util::{NetVector3, shotgun_ray},
|
util::{NetVector3, shotgun_ray},
|
||||||
},
|
},
|
||||||
|
pickup::PickupKind,
|
||||||
player::{
|
player::{
|
||||||
shootable::Shootable,
|
shootable::Shootable,
|
||||||
weapon::{BallWeapon, Weapon, WeaponType},
|
weapon::{BallWeapon, Weapon, WeaponType},
|
||||||
@ -58,6 +59,8 @@ pub trait IPlayer {
|
|||||||
fn get_camera_origin(&self) -> Option<Gd<Node3D>>;
|
fn get_camera_origin(&self) -> Option<Gd<Node3D>>;
|
||||||
fn is_replay_mode(&self) -> bool;
|
fn is_replay_mode(&self) -> bool;
|
||||||
fn get_health(&self) -> i32;
|
fn get_health(&self) -> i32;
|
||||||
|
fn heal(&mut self, amount: i32);
|
||||||
|
fn on_pickup(&mut self, kind: PickupKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PlayerCommon {
|
pub trait PlayerCommon {
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use godot::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
game_manager::Game,
|
game_manager::Game,
|
||||||
killbox::KillboxKind,
|
killbox::KillboxKind,
|
||||||
|
pickup::PickupKind,
|
||||||
player::{
|
player::{
|
||||||
DamageSource, DamageSourceSignal, IPlayer, NetTransform, PlayerCommon,
|
DamageSource, DamageSourceSignal, IPlayer, NetTransform, PlayerCommon,
|
||||||
effects::PlayerEffects,
|
effects::PlayerEffects,
|
||||||
@ -43,7 +44,11 @@ pub struct RemotePlayer {
|
|||||||
#[export]
|
#[export]
|
||||||
health_bar: Option<Gd<TextureProgressBar>>,
|
health_bar: Option<Gd<TextureProgressBar>>,
|
||||||
#[export]
|
#[export]
|
||||||
|
double_health_bar: Option<Gd<TextureProgressBar>>,
|
||||||
|
#[export]
|
||||||
health_bar_sprite: Option<Gd<Sprite3D>>,
|
health_bar_sprite: Option<Gd<Sprite3D>>,
|
||||||
|
#[export]
|
||||||
|
double_health_bar_sprite: Option<Gd<Sprite3D>>,
|
||||||
|
|
||||||
pub player_id: Option<u16>,
|
pub player_id: Option<u16>,
|
||||||
pub player_name: String,
|
pub player_name: String,
|
||||||
@ -153,10 +158,7 @@ impl IPlayer for RemotePlayer {
|
|||||||
s.kill(source);
|
s.kill(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(health_bar) = &mut s.health_bar {
|
s.update_health_bar();
|
||||||
let value = (s.health as f64 / 100.).clamp(0., 1.) * 100.;
|
|
||||||
health_bar.set_value(value);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,8 +189,11 @@ impl IPlayer for RemotePlayer {
|
|||||||
if let Some(mut name) = self.name_label.take() {
|
if let Some(mut name) = self.name_label.take() {
|
||||||
name.queue_free();
|
name.queue_free();
|
||||||
}
|
}
|
||||||
if let Some(healthbar_sprit) = &mut self.health_bar_sprite {
|
if let Some(healthbar_sprite) = &mut self.health_bar_sprite {
|
||||||
healthbar_sprit.set_visible(false);
|
healthbar_sprite.set_visible(false);
|
||||||
|
}
|
||||||
|
if let Some(double_health_bar_sprite) = &mut self.double_health_bar_sprite {
|
||||||
|
double_health_bar_sprite.set_visible(false);
|
||||||
}
|
}
|
||||||
self.is_dead = true;
|
self.is_dead = true;
|
||||||
}
|
}
|
||||||
@ -234,6 +239,21 @@ impl IPlayer for RemotePlayer {
|
|||||||
fn get_health(&self) -> i32 {
|
fn get_health(&self) -> i32 {
|
||||||
self.health
|
self.health
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn heal(&mut self, amount: i32) {
|
||||||
|
self.run_deferred(move |s| {
|
||||||
|
let delta = (s.health + amount).min(200) - s.health;
|
||||||
|
s.run_deferred(move |s| s.signals().on_heal().emit(delta));
|
||||||
|
s.health += delta;
|
||||||
|
s.update_health_bar();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_pickup(&mut self, kind: PickupKind) {
|
||||||
|
match kind {
|
||||||
|
PickupKind::Health => self.heal(100),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[godot_api]
|
#[godot_api]
|
||||||
@ -247,6 +267,7 @@ impl ICharacterBody3D for RemotePlayer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.swap_weapon(WeaponType::Raygun, false);
|
self.swap_weapon(WeaponType::Raygun, false);
|
||||||
|
self.update_health_bar();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process(&mut self, delta: f64) {
|
fn process(&mut self, delta: f64) {
|
||||||
@ -292,6 +313,19 @@ impl RemotePlayer {
|
|||||||
killbox_kind: KillboxKind,
|
killbox_kind: KillboxKind,
|
||||||
damage: i32,
|
damage: i32,
|
||||||
);
|
);
|
||||||
|
#[signal]
|
||||||
|
pub fn on_heal(amount: i32);
|
||||||
|
|
||||||
|
pub fn update_health_bar(&mut self) {
|
||||||
|
if let Some(health_bar) = &mut self.health_bar {
|
||||||
|
let value = (self.health as f64 / 100.).clamp(0., 1.) * 100.;
|
||||||
|
health_bar.set_value(value);
|
||||||
|
}
|
||||||
|
if let Some(double_health_bar) = &mut self.double_health_bar {
|
||||||
|
let double_value = ((self.health as f64 - 100.) / 100.).clamp(0., 1.) * 100.;
|
||||||
|
double_health_bar.set_value(double_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[godot_dyn]
|
#[godot_dyn]
|
||||||
|
|||||||
@ -15,6 +15,7 @@ use crate::{
|
|||||||
game_manager::{Game, GameManager, Player},
|
game_manager::{Game, GameManager, Player},
|
||||||
map::Map,
|
map::Map,
|
||||||
net::{network_manager::BallSync, util::NetVector3},
|
net::{network_manager::BallSync, util::NetVector3},
|
||||||
|
pickup::{PickupKind, ReplayVisibility},
|
||||||
player::{
|
player::{
|
||||||
DamageSource, IPlayer, NetTransform, ball::Ball, remote_player::RemotePlayer,
|
DamageSource, IPlayer, NetTransform, ball::Ball, remote_player::RemotePlayer,
|
||||||
weapon::WeaponType,
|
weapon::WeaponType,
|
||||||
@ -43,7 +44,11 @@ pub struct StandaloneReplayManager {
|
|||||||
base: Base<Node>,
|
base: Base<Node>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
impl StandaloneReplayManager {
|
impl StandaloneReplayManager {
|
||||||
|
#[signal]
|
||||||
|
pub fn on_map_loaded(map: Gd<Map>);
|
||||||
|
|
||||||
pub fn singleton() -> Gd<StandaloneReplayManager> {
|
pub fn singleton() -> Gd<StandaloneReplayManager> {
|
||||||
get_autoload_by_name::<StandaloneReplayManager>(STANDALONE_REPLAY_GLOBAL)
|
get_autoload_by_name::<StandaloneReplayManager>(STANDALONE_REPLAY_GLOBAL)
|
||||||
}
|
}
|
||||||
@ -85,7 +90,7 @@ impl StandaloneReplayManager {
|
|||||||
.connect_other(self, Self::on_done);
|
.connect_other(self, Self::on_done);
|
||||||
|
|
||||||
playback.bind_mut().replay = replay;
|
playback.bind_mut().replay = replay;
|
||||||
playback.bind_mut().current_map = Some(map);
|
playback.bind_mut().current_map = Some(map.clone());
|
||||||
playback.bind_mut().current_time = 0.;
|
playback.bind_mut().current_time = 0.;
|
||||||
playback.bind_mut().fast_forwarding = false;
|
playback.bind_mut().fast_forwarding = false;
|
||||||
playback.bind_mut().spectated_player_id = 0;
|
playback.bind_mut().spectated_player_id = 0;
|
||||||
@ -109,6 +114,7 @@ impl StandaloneReplayManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.signals().on_map_loaded().emit(&map);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_done(&mut self) {
|
pub fn on_done(&mut self) {
|
||||||
@ -191,6 +197,17 @@ impl INode for ReplayPlayback {
|
|||||||
self.player_data = frame.player_data.clone();
|
self.player_data = frame.player_data.clone();
|
||||||
self.running_goals = frame.goals.clone();
|
self.running_goals = frame.goals.clone();
|
||||||
|
|
||||||
|
if let Some(map) = &mut self.current_map {
|
||||||
|
for (id, visible) in frame.pickups_visible {
|
||||||
|
if let Some(pickup) = map.bind_mut().pickups.get_mut(&id) {
|
||||||
|
pickup.dyn_bind_mut().set_replay(match visible {
|
||||||
|
true => ReplayVisibility::Visible,
|
||||||
|
false => ReplayVisibility::Hidden,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let ReplayBall::World(ball_state) = &frame.ball_data {
|
if let ReplayBall::World(ball_state) = &frame.ball_data {
|
||||||
if let Some(ball) = &mut self.ball {
|
if let Some(ball) = &mut self.ball {
|
||||||
ball.bind_mut().apply_sync(BallSync {
|
ball.bind_mut().apply_sync(BallSync {
|
||||||
@ -275,6 +292,11 @@ impl INode for ReplayPlayback {
|
|||||||
.take_damage(*damage_source, *damage, false);
|
.take_damage(*damage_source, *damage, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ReplayEvent::Pickup(kind, player_id) => {
|
||||||
|
if let Some(character) = self.player_characters.get_mut(player_id) {
|
||||||
|
character.bind_mut().on_pickup(*kind);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,6 +342,11 @@ impl INode for ReplayPlayback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exit_tree(&mut self) {
|
fn exit_tree(&mut self) {
|
||||||
|
if let Some(map) = &mut self.current_map {
|
||||||
|
for (_, pickup) in &mut map.bind_mut().pickups {
|
||||||
|
pickup.dyn_bind_mut().set_replay(ReplayVisibility::NoReplay);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (_, character) in &mut self.player_characters {
|
for (_, character) in &mut self.player_characters {
|
||||||
character.queue_free();
|
character.queue_free();
|
||||||
}
|
}
|
||||||
@ -419,6 +446,8 @@ impl ReplayRecorder {
|
|||||||
|
|
||||||
let mut goals = HashMap::new();
|
let mut goals = HashMap::new();
|
||||||
|
|
||||||
|
let mut pickups_visible = HashMap::new();
|
||||||
|
|
||||||
if let Some(game) = Game::singleton() {
|
if let Some(game) = Game::singleton() {
|
||||||
for player in &game.bind().players {
|
for player in &game.bind().players {
|
||||||
if let Some(state) = player.get_state(player.clone()) {
|
if let Some(state) = player.get_state(player.clone()) {
|
||||||
@ -438,6 +467,12 @@ impl ReplayRecorder {
|
|||||||
ReplayBall::Held
|
ReplayBall::Held
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(map) = &game.bind().current_map {
|
||||||
|
for (id, pickup) in &map.bind().pickups {
|
||||||
|
pickups_visible.insert(*id, pickup.dyn_bind().is_active());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
goals = game.bind().goals.clone();
|
goals = game.bind().goals.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,6 +481,7 @@ impl ReplayRecorder {
|
|||||||
ReplayFrame {
|
ReplayFrame {
|
||||||
time: self.time_elapsed,
|
time: self.time_elapsed,
|
||||||
goals,
|
goals,
|
||||||
|
pickups_visible,
|
||||||
player_data,
|
player_data,
|
||||||
ball_data,
|
ball_data,
|
||||||
events: Vec::new(),
|
events: Vec::new(),
|
||||||
@ -525,6 +561,7 @@ pub struct ReplayFrame {
|
|||||||
time: f64,
|
time: f64,
|
||||||
player_data: HashMap<u16, ReplayPlayerState>,
|
player_data: HashMap<u16, ReplayPlayerState>,
|
||||||
ball_data: ReplayBall,
|
ball_data: ReplayBall,
|
||||||
|
pickups_visible: HashMap<u8, bool>,
|
||||||
events: Vec<ReplayEvent>,
|
events: Vec<ReplayEvent>,
|
||||||
goals: HashMap<u8, u16>,
|
goals: HashMap<u8, u16>,
|
||||||
}
|
}
|
||||||
@ -537,6 +574,7 @@ pub enum ReplayEvent {
|
|||||||
Jump(u16),
|
Jump(u16),
|
||||||
Punch(u16, NetVector3),
|
Punch(u16, NetVector3),
|
||||||
TakeDamage(u16, DamageSource, i32),
|
TakeDamage(u16, DamageSource, i32),
|
||||||
|
Pickup(PickupKind, u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
|
|||||||
@ -63,7 +63,6 @@ impl IHBoxContainer for PlayerListing {
|
|||||||
|
|
||||||
impl PlayerListing {
|
impl PlayerListing {
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
godot_print!("update");
|
|
||||||
if let Some(player_id) = self.player_id {
|
if let Some(player_id) = self.player_id {
|
||||||
if let Some(game) = Game::singleton() {
|
if let Some(game) = Game::singleton() {
|
||||||
if let Some(player) = game.bind().find_player(player_id) {
|
if let Some(player) = game.bind().find_player(player_id) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user