diff --git a/BoundingBoxes/InteractionRay.cs b/BoundingBoxes/InteractionRay.cs new file mode 100644 index 0000000..8ca963e --- /dev/null +++ b/BoundingBoxes/InteractionRay.cs @@ -0,0 +1,54 @@ +using Godot; + +namespace SupaLidlGame.BoundingBoxes; + +public partial class InteractionRay : RayCast2D +{ + private InteractionTrigger _trigger; + + public InteractionTrigger Trigger + { + get => _trigger; + protected set + { + if (_trigger != value) + { + EmitSignal(SignalName.TriggerHit, value); + } + + if (_trigger is not null) + { + LastValidTrigger = value; + } + + _trigger = value; + } + } + + public InteractionTrigger LastValidTrigger { get; set; } + + [Signal] + public delegate void TriggerHitEventHandler(InteractionTrigger trigger); + + public override void _Ready() + { + + } + + public override void _PhysicsProcess(double delta) + { + if (IsColliding()) + { + var obj = GetCollider(); + // if obj is an InteractionTrigger then we signal hit + if (obj is InteractionTrigger trigger) + { + Trigger = trigger; + } + } + else + { + Trigger = null; + } + } +} diff --git a/BoundingBoxes/InteractionReceiver.cs b/BoundingBoxes/InteractionReceiver.cs index c5aba49..a568339 100644 --- a/BoundingBoxes/InteractionReceiver.cs +++ b/BoundingBoxes/InteractionReceiver.cs @@ -5,66 +5,4 @@ namespace SupaLidlGame.BoundingBoxes; public partial class InteractionReceiver : Area2D { - [Signal] - public delegate void TriggerEventHandler( - InteractionTrigger trigger, - InteractionTrigger closestTrigger); - - [Signal] - public delegate void ClosestTriggerEventHandler(InteractionTrigger trigger); - - private InteractionTrigger _closestTrigger; - - private HashSet _triggers; - - public InteractionReceiver() - { - _triggers = new HashSet(); - } - - private void UpdateClosestTrigger() - { - float minDist = float.MaxValue; - InteractionTrigger best = null; - - foreach (var trigger in _triggers) - { - float dist = trigger.GlobalPosition - .DistanceSquaredTo(GlobalPosition); - - if (dist <= minDist) - { - best = trigger; - minDist = dist; - } - } - - if (_closestTrigger != best) - { - EmitSignal(SignalName.ClosestTrigger, best); - _closestTrigger = best; - } - } - - public void _on_area_entered(Area2D area) - { - if (area is InteractionTrigger trigger) - { - EmitSignal(SignalName.Trigger, _closestTrigger); - } - } - - public void _on_area_exited(Area2D area) - { - // update closest trigger - if (area is InteractionTrigger trigger) - { - if (_triggers.Contains(trigger)) - { - _triggers.Remove(trigger); - } - UpdateClosestTrigger(); - } - GD.PushWarning("Area entered is not an InteractionTrigger."); - } } diff --git a/BoundingBoxes/InteractionTrigger.cs b/BoundingBoxes/InteractionTrigger.cs index 9c45016..1e7b830 100644 --- a/BoundingBoxes/InteractionTrigger.cs +++ b/BoundingBoxes/InteractionTrigger.cs @@ -1,7 +1,24 @@ using Godot; +using SupaLidlGame.Characters; namespace SupaLidlGame.BoundingBoxes; public partial class InteractionTrigger : Area2D { + [Signal] + public delegate void InteractionEventHandler(); + + [Signal] + public delegate void TargetEventHandler(); + + [Signal] + public delegate void UntargetEventHandler(); + + /// + /// Invokes or triggers an interaction to occur. + /// + public void InvokeInteraction() + { + EmitSignal(SignalName.Interaction); + } } diff --git a/Characters/Character.cs b/Characters/Character.cs index da2d29d..9bb77e6 100644 --- a/Characters/Character.cs +++ b/Characters/Character.cs @@ -73,9 +73,17 @@ public partial class Character : CharacterBody2D, IFaction [Export] public CharacterStateMachine StateMachine { get; set; } + [Export] + public BoundingBoxes.Hurtbox Hurtbox { get; set; } + [Export] public ushort Faction { get; set; } + public override void _Ready() + { + Hurtbox.ReceivedDamage += OnReceivedDamage; + } + public override void _Process(double delta) { if (StateMachine != null) @@ -133,7 +141,7 @@ public partial class Character : CharacterBody2D, IFaction StunTime += time; } - protected void DrawTarget() + protected virtual void DrawTarget() { Vector2 target = Target; float angle = Mathf.Atan2(target.Y, Mathf.Abs(target.X)); @@ -173,13 +181,14 @@ public partial class Character : CharacterBody2D, IFaction } } - public virtual void _on_hurtbox_received_damage( + public virtual void OnReceivedDamage( float damage, Character inflictor, float knockback, Vector2 knockbackOrigin = default, Vector2 knockbackVector = default) { + float oldHealth = Health; Health -= damage; // create damage text @@ -225,5 +234,19 @@ public partial class Character : CharacterBody2D, IFaction // very small pitch deviation sound.At(GlobalPosition).WithPitchDeviation(0.125f).Play(); } + + Events.HealthChangedArgs args = new Events.HealthChangedArgs + { + Attacker = inflictor, + OldHealth = oldHealth, + NewHealth = Health, + Damage = damage, + }; + EmitSignal(SignalName.Hurt, args); + + if (Health <= 0) + { + EmitSignal(SignalName.Death, args); + } } } diff --git a/Characters/ExampleEnemy.tscn b/Characters/ExampleEnemy.tscn index cbf1c2e..88734cd 100644 --- a/Characters/ExampleEnemy.tscn +++ b/Characters/ExampleEnemy.tscn @@ -130,7 +130,7 @@ _data = { "RESET": SubResource("Animation_k6l16") } -[node name="ExampleEnemy" type="CharacterBody2D" node_paths=PackedStringArray("Sprite", "Inventory", "StateMachine")] +[node name="ExampleEnemy" type="CharacterBody2D" node_paths=PackedStringArray("Sprite", "Inventory", "StateMachine", "Hurtbox")] y_sort_enabled = true texture_filter = 3 material = SubResource("ShaderMaterial_ms3xg") @@ -141,6 +141,7 @@ Health = 50.0 Sprite = NodePath("Sprite") Inventory = NodePath("Inventory") StateMachine = NodePath("StateMachine") +Hurtbox = NodePath("Hurtbox") Faction = 2 [node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("InitialState", "Character")] @@ -191,6 +192,4 @@ libraries = { [node name="HurtSound" type="AudioStreamPlayer2D" parent="."] stream = ExtResource("10_n1e64") -[connection signal="ReceivedDamage" from="Hurtbox" to="." method="_on_hurtbox_received_damage"] - [editable path="Hurtbox"] diff --git a/Characters/Player.cs b/Characters/Player.cs index 755fbab..6ba86b5 100644 --- a/Characters/Player.cs +++ b/Characters/Player.cs @@ -1,9 +1,12 @@ using Godot; +using GodotUtilities; using SupaLidlGame.Utils; +using SupaLidlGame.BoundingBoxes; namespace SupaLidlGame.Characters; -public partial class Player : Character +[Scene] +public sealed partial class Player : Character { private AnimatedSprite2D _sprite; private string _spriteAnim; @@ -11,6 +14,11 @@ public partial class Player : Character [Export] public PlayerCamera Camera { get; set; } + [Export] + public Marker2D DirectionMarker { get; private set; } + + public InteractionRay InteractionRay { get; private set; } + public string Animation { get => _sprite.Animation; @@ -32,11 +40,13 @@ public partial class Player : Character public override void _Ready() { + InteractionRay = GetNode("Direction2D/InteractionRay"); _sprite = GetNode("Sprite"); if (_spriteAnim != default) { _sprite.Animation = _spriteAnim; } + base._Ready(); } public override void ModifyVelocity() @@ -61,4 +71,12 @@ public partial class Player : Character GD.Print("died"); //base.Die(); } + + protected override void DrawTarget() + { + base.DrawTarget(); + DirectionMarker.GlobalRotation = DirectionMarker.GlobalPosition + .DirectionTo(GetGlobalMousePosition()) + .Angle(); + } } diff --git a/Characters/Player.tscn b/Characters/Player.tscn index 59650ff..e4f67b6 100644 --- a/Characters/Player.tscn +++ b/Characters/Player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=29 format=3 uid="uid://b2254pup8k161"] +[gd_scene load_steps=30 format=3 uid="uid://b2254pup8k161"] [ext_resource type="Script" path="res://Characters/Player.cs" id="1_flygr"] [ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_ngsgt"] @@ -12,6 +12,7 @@ [ext_resource type="Script" path="res://State/Character/PlayerRollState.cs" id="8_fy0v5"] [ext_resource type="PackedScene" uid="uid://cjgxyhgcyvsv7" path="res://BoundingBoxes/Hurtbox.tscn" id="9_avyu4"] [ext_resource type="AudioStream" uid="uid://njun3e6v4854" path="res://Assets/Sounds/hurt.wav" id="12_h0x0g"] +[ext_resource type="Script" path="res://BoundingBoxes/InteractionRay.cs" id="13_hs3u1"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_h78y7"] shader = ExtResource("2_ngsgt") @@ -133,19 +134,21 @@ _data = { "RESET": SubResource("Animation_k6l16") } -[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("Camera", "Sprite", "Inventory", "StateMachine")] +[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("Camera", "DirectionMarker", "Sprite", "Inventory", "StateMachine", "Hurtbox")] y_sort_enabled = true texture_filter = 3 material = SubResource("ShaderMaterial_h78y7") -position = Vector2(0, -12) +position = Vector2(1, -12) collision_layer = 6 collision_mask = 17 script = ExtResource("1_flygr") Camera = NodePath("Camera2D") +DirectionMarker = NodePath("Direction2D") Speed = 64.0 Sprite = NodePath("Sprite") Inventory = NodePath("Inventory") StateMachine = NodePath("StateMachine") +Hurtbox = NodePath("Hurtbox") Faction = 1 [node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("InitialState", "Character")] @@ -231,6 +234,13 @@ max_distance = 64.0 [node name="AudioListener2D" type="AudioListener2D" parent="."] current = true -[connection signal="ReceivedDamage" from="Hurtbox" to="." method="_on_hurtbox_received_damage"] +[node name="Direction2D" type="Marker2D" parent="."] +position = Vector2(0, 6) + +[node name="InteractionRay" type="RayCast2D" parent="Direction2D"] +target_position = Vector2(16, 0) +collision_mask = 64 +collide_with_areas = true +script = ExtResource("13_hs3u1") [editable path="Hurtbox"] diff --git a/Entities/Campfire.cs b/Entities/Campfire.cs index 5572dbb..3e22de4 100644 --- a/Entities/Campfire.cs +++ b/Entities/Campfire.cs @@ -1,23 +1,35 @@ using Godot; -using System; +using GodotUtilities; +using SupaLidlGame.BoundingBoxes; namespace SupaLidlGame.Entities; -public partial class Campfire : StaticBody2D +[Scene] +public partial class Campfire : StaticBody2D, Utils.IInteractive { private PointLight2D _light; + public InteractionTrigger InteractionTrigger { get; set; } + [Signal] - public delegate void OnCampfireUseEventHandler(); + public delegate void UseEventHandler(); public override void _Ready() { + InteractionTrigger = GetNode("InteractionTrigger"); _light = GetNode("PointLight2D"); + InteractionTrigger.Interaction += () => + { + // save the player's spawn position to be their position on interaction + EmitSignal(SignalName.Use); + + this.GetAncestor().SetSpawn(GlobalPosition); + }; } public override void _Process(double delta) { _light.Energy += (GD.Randf() - 0.5f) * 8 * (float)delta; - _light.Energy = Math.Clamp(_light.Energy, 1.2f, 2.0f); + _light.Energy = Mathf.Clamp(_light.Energy, 1.8f, 2f); } } diff --git a/Entities/Campfire.tscn b/Entities/Campfire.tscn index d5c10ce..b42c4c8 100644 --- a/Entities/Campfire.tscn +++ b/Entities/Campfire.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=11 format=3 uid="uid://dhl071rj5wyvx"] +[gd_scene load_steps=13 format=3 uid="uid://dhl071rj5wyvx"] [ext_resource type="Texture2D" uid="uid://yqet0b22i70d" path="res://Assets/Sprites/campfire.png" id="1_7eor7"] [ext_resource type="Script" path="res://Entities/Campfire.cs" id="1_w4gfp"] [ext_resource type="Texture2D" uid="uid://coarr28adgo1u" path="res://Assets/Sprites/Particles/point-light.png" id="3_lm3vq"] +[ext_resource type="Script" path="res://BoundingBoxes/InteractionTrigger.cs" id="4_h1bqe"] [sub_resource type="AtlasTexture" id="AtlasTexture_68qj1"] atlas = ExtResource("1_7eor7") @@ -55,6 +56,9 @@ animations = [{ [sub_resource type="RectangleShape2D" id="RectangleShape2D_ubam4"] size = Vector2(16, 4) +[sub_resource type="RectangleShape2D" id="RectangleShape2D_dfj3a"] +size = Vector2(20, 10) + [node name="Campfire" type="StaticBody2D"] texture_filter = 3 position = Vector2(0, -8) @@ -74,3 +78,12 @@ texture_scale = 0.25 [node name="CollisionShape2D" type="CollisionShape2D" parent="."] position = Vector2(0, 6) shape = SubResource("RectangleShape2D_ubam4") + +[node name="InteractionTrigger" type="Area2D" parent="."] +collision_layer = 64 +collision_mask = 0 +script = ExtResource("4_h1bqe") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="InteractionTrigger"] +position = Vector2(0, 5) +shape = SubResource("RectangleShape2D_dfj3a") diff --git a/Scenes/Map.cs b/Scenes/Map.cs index a51bcdb..f64f2eb 100644 --- a/Scenes/Map.cs +++ b/Scenes/Map.cs @@ -1,5 +1,4 @@ using Godot; -using System; namespace SupaLidlGame.Scenes; diff --git a/Scenes/Maps/Hills.tscn b/Scenes/Maps/Hills.tscn index f1a84a6..0a34a83 100644 --- a/Scenes/Maps/Hills.tscn +++ b/Scenes/Maps/Hills.tscn @@ -1,10 +1,11 @@ -[gd_scene load_steps=14 format=3 uid="uid://bxtpv6jqodj4v"] +[gd_scene load_steps=15 format=3 uid="uid://bxtpv6jqodj4v"] [ext_resource type="PackedScene" uid="uid://clwv2owvk6abe" path="res://Scenes/BaseMap.tscn" id="1_vly6f"] [ext_resource type="Texture2D" uid="uid://dl2h266oa2x31" path="res://Assets/Sprites/night-grass.png" id="2_ote21"] [ext_resource type="PackedScene" uid="uid://bf55wbq7m1gpp" path="res://Characters/ExampleEnemy.tscn" id="3_hwof6"] [ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="4_mwgaq"] [ext_resource type="PackedScene" uid="uid://5nvn1tw56m8e" path="res://Utils/Spawner.tscn" id="4_pi4df"] +[ext_resource type="PackedScene" uid="uid://dhl071rj5wyvx" path="res://Entities/Campfire.tscn" id="6_r6kxn"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_dvbe3"] texture = ExtResource("2_ote21") @@ -211,31 +212,31 @@ physics_layer_0/collision_mask = 16 physics_layer_1/collision_layer = 1 sources/0 = SubResource("TileSetAtlasSource_dvbe3") -[sub_resource type="ShaderMaterial" id="ShaderMaterial_kq7i3"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_qliqj"] resource_local_to_scene = true shader = ExtResource("4_mwgaq") shader_parameter/color = Quaternion(1, 1, 1, 1) shader_parameter/intensity = 0.0 -[sub_resource type="ShaderMaterial" id="ShaderMaterial_ck37u"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_xpy5p"] resource_local_to_scene = true shader = ExtResource("4_mwgaq") shader_parameter/color = Quaternion(1, 1, 1, 1) shader_parameter/intensity = 0.0 -[sub_resource type="ShaderMaterial" id="ShaderMaterial_3i2mi"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_jlmdb"] resource_local_to_scene = true shader = ExtResource("4_mwgaq") shader_parameter/color = Quaternion(1, 1, 1, 1) shader_parameter/intensity = 0.0 -[sub_resource type="ShaderMaterial" id="ShaderMaterial_trolh"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_pd2a6"] resource_local_to_scene = true shader = ExtResource("4_mwgaq") shader_parameter/color = Quaternion(1, 1, 1, 1) shader_parameter/intensity = 0.0 -[sub_resource type="ShaderMaterial" id="ShaderMaterial_vuv4g"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_th2v6"] resource_local_to_scene = true shader = ExtResource("4_mwgaq") shader_parameter/color = Quaternion(1, 1, 1, 1) @@ -251,26 +252,32 @@ layer_4/tile_data = PackedInt32Array(1114105, 196608, 3, 1114106, 262144, 3, 111 layer_5/tile_data = PackedInt32Array(786438, 262144, 3, 720899, 262144, 3, 851971, 458752, 3, 196611, 458752, 3, 1835019, 262144, 3, 1835034, 458752, 3) [node name="ExampleEnemy" parent="Entities" index="0" instance=ExtResource("3_hwof6")] -material = SubResource("ShaderMaterial_kq7i3") +material = SubResource("ShaderMaterial_qliqj") position = Vector2(169, 115) [node name="ExampleEnemy2" parent="Entities" index="1" instance=ExtResource("3_hwof6")] -material = SubResource("ShaderMaterial_ck37u") +material = SubResource("ShaderMaterial_xpy5p") position = Vector2(75, 130) [node name="ExampleEnemy3" parent="Entities" index="2" instance=ExtResource("3_hwof6")] -material = SubResource("ShaderMaterial_3i2mi") +material = SubResource("ShaderMaterial_jlmdb") position = Vector2(140, 177) [node name="ExampleEnemy4" parent="Entities" index="3" instance=ExtResource("3_hwof6")] -material = SubResource("ShaderMaterial_trolh") +material = SubResource("ShaderMaterial_pd2a6") position = Vector2(14, 159) [node name="ExampleEnemy5" parent="Entities" index="4" instance=ExtResource("3_hwof6")] -material = SubResource("ShaderMaterial_vuv4g") +material = SubResource("ShaderMaterial_th2v6") position = Vector2(10, 22) Faction = 1 +[node name="Campfire" parent="Entities" index="5" instance=ExtResource("6_r6kxn")] +position = Vector2(155, -27) + +[node name="PointLight2D" parent="Entities/Campfire" index="1"] +color = Color(0.996078, 0.780392, 0.501961, 1) + [node name="Spawner" parent="Spawners" index="0" instance=ExtResource("4_pi4df")] position = Vector2(250, 512) Character = ExtResource("3_hwof6") @@ -279,4 +286,5 @@ SpawnTime = 5.0 [node name="CollisionShape2D" parent="Spawners/Spawner/Area2D" index="0"] shape = SubResource("RectangleShape2D_oods2") +[editable path="Entities/Campfire"] [editable path="Spawners/Spawner"] diff --git a/State/Character/PlayerState.cs b/State/Character/PlayerState.cs index 8476929..ed57644 100644 --- a/State/Character/PlayerState.cs +++ b/State/Character/PlayerState.cs @@ -13,9 +13,10 @@ public abstract partial class PlayerState : CharacterState public override CharacterState Input(InputEvent @event) { var inventory = Character.Inventory; + var player = _player; if (this is PlayerIdleState or PlayerMoveState && - !_player.Inventory.IsUsingItem) + !player.Inventory.IsUsingItem) { if (@event.IsActionPressed("equip_1")) { @@ -25,6 +26,13 @@ public abstract partial class PlayerState : CharacterState { inventory.SelectedItem = inventory.GetItemByMap("equip_2"); } + + if (@event.IsActionPressed("interact")) + { + // if looking at a trigger then interact with it + GD.Print("interacting"); + player.InteractionRay.Trigger?.InvokeInteraction(); + } } return base.Input(@event); diff --git a/SupaLidlGame.csproj b/SupaLidlGame.csproj index c9adce8..e7f1627 100644 --- a/SupaLidlGame.csproj +++ b/SupaLidlGame.csproj @@ -3,4 +3,7 @@ net6.0 true + + + \ No newline at end of file diff --git a/SupaLidlGame.sln b/SupaLidlGame.sln index d222077..f6135a2 100644 --- a/SupaLidlGame.sln +++ b/SupaLidlGame.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SupaLidlGame", "SupaLidlGame.csproj", "{AF3A4D72-D276-44C3-A64F-EAB32D2B9B97}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SupaLidlGame", "SupaLidlGame.csproj", "{BC071CA6-9462-4CEC-AA20-B0CA618321E5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -9,11 +9,11 @@ Global ExportRelease|Any CPU = ExportRelease|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {AF3A4D72-D276-44C3-A64F-EAB32D2B9B97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AF3A4D72-D276-44C3-A64F-EAB32D2B9B97}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AF3A4D72-D276-44C3-A64F-EAB32D2B9B97}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU - {AF3A4D72-D276-44C3-A64F-EAB32D2B9B97}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU - {AF3A4D72-D276-44C3-A64F-EAB32D2B9B97}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU - {AF3A4D72-D276-44C3-A64F-EAB32D2B9B97}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU + {BC071CA6-9462-4CEC-AA20-B0CA618321E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC071CA6-9462-4CEC-AA20-B0CA618321E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC071CA6-9462-4CEC-AA20-B0CA618321E5}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU + {BC071CA6-9462-4CEC-AA20-B0CA618321E5}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU + {BC071CA6-9462-4CEC-AA20-B0CA618321E5}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU + {BC071CA6-9462-4CEC-AA20-B0CA618321E5}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU EndGlobalSection EndGlobal diff --git a/Utils/IInteractive.cs b/Utils/IInteractive.cs new file mode 100644 index 0000000..d094081 --- /dev/null +++ b/Utils/IInteractive.cs @@ -0,0 +1,6 @@ +namespace SupaLidlGame.Utils; + +public interface IInteractive +{ + public BoundingBoxes.InteractionTrigger InteractionTrigger { get; set; } +} diff --git a/Utils/World.cs b/Utils/World.cs index aa7eb4d..68c61c0 100644 --- a/Utils/World.cs +++ b/Utils/World.cs @@ -23,7 +23,9 @@ public partial class World : Node2D private string _currentMapResourcePath; - private Entities.Campfire _lastCampfire = null; + //private Entities.Campfire _lastCampfire = null; + public Vector2 SaveLocation { get; set; } + public string SaveMapKey { get; set; } private const string PLAYER_PATH = "res://Characters/Player.tscn"; private PackedScene _playerScene; @@ -47,25 +49,15 @@ public partial class World : Node2D CurrentPlayer.Death += (Events.HealthChangedArgs args) => { // TODO: respawn the player at the last campfire. + SpawnPlayer(); }; base._Ready(); } - public void LoadScene(PackedScene scene) + private void LoadMap(Map map) { - GD.Print("Loading map " + scene.ResourcePath); - - Map map; - if (_maps.ContainsKey(scene.ResourcePath)) - { - map = _maps[scene.ResourcePath]; - } - else - { - map = scene.Instantiate(); - _maps.Add(scene.ResourcePath, map); - } + GD.Print("Loading map " + map.Name); if (CurrentMap is not null) { @@ -86,6 +78,39 @@ public partial class World : Node2D } } + public void LoadScene(PackedScene scene) + { + Map map; + if (_maps.ContainsKey(scene.ResourcePath)) + { + map = _maps[scene.ResourcePath]; + } + else + { + map = scene.Instantiate(); + _maps.Add(scene.ResourcePath, map); + } + + LoadMap(map); + } + + public void LoadScene(string path) + { + Map map; + if (_maps.ContainsKey(path)) + { + map = _maps[path]; + } + else + { + var scene = ResourceLoader.Load(path); + map = scene.Instantiate(); + _maps.Add(scene.ResourcePath, map); + } + + LoadMap(map); + } + public void CreatePlayer() { CurrentPlayer = _playerScene.Instantiate(); @@ -117,7 +142,7 @@ public partial class World : Node2D } return false; }) as BoundingBoxes.ConnectorBox; - + CurrentPlayer.GlobalPosition = connector.GlobalPosition; } @@ -152,4 +177,34 @@ public partial class World : Node2D { throw new System.NotImplementedException(); } + + /// + /// Sets the player's saved spawn position. + /// + /// The position to save and spawn the player in + /// + /// The map to spawn the player in. If , use the + /// World's CurrentMap + /// + public void SetSpawn(Vector2 position, string mapKey = null) + { + GD.Print("Set spawn"); + if (mapKey is null) + { + mapKey = CurrentMap.SceneFilePath; + SaveLocation = position; + SaveMapKey = mapKey; + } + } + + public void SpawnPlayer() + { + // TODO: add max health property + CurrentPlayer.Health = 100; + CurrentPlayer.GlobalPosition = SaveLocation; + if (CurrentMap.SceneFilePath != SaveMapKey) + { + LoadScene(SaveMapKey); + } + } }