From 2cbf7e15a413a268d4aa048217d7d39cbe931d8c Mon Sep 17 00:00:00 2001 From: jonathan Date: Wed, 4 Feb 2026 19:40:10 +0100 Subject: [PATCH 1/8] Changed camera no not need a direct reference to vesna --- .../CSharp/Common/Camera/CameraController.cs | 20 +------------ scripts/CSharp/Common/Camera/CameraTarget.cs | 29 +++++++++++++++++++ .../CSharp/Common/Camera/CameraTarget.cs.uid | 1 + 3 files changed, 31 insertions(+), 19 deletions(-) create mode 100644 scripts/CSharp/Common/Camera/CameraTarget.cs create mode 100644 scripts/CSharp/Common/Camera/CameraTarget.cs.uid diff --git a/scripts/CSharp/Common/Camera/CameraController.cs b/scripts/CSharp/Common/Camera/CameraController.cs index 661e65c..73c88e4 100644 --- a/scripts/CSharp/Common/Camera/CameraController.cs +++ b/scripts/CSharp/Common/Camera/CameraController.cs @@ -5,26 +5,8 @@ namespace Babushka.scripts.CSharp.Common.Camera; public partial class CameraController : Camera2D { - #region Singleton ( Contains _EnterTree() ) // TODO: use autoload or other solution - - public static CameraController Instance { get; private set; } = null!; - - public override void _EnterTree() - { - Instance = this; - } - - #endregion - - [Export] private Node2D _followNode; - - public FightHappening? fightToShow; - - public override void _Process(double delta) { - this.GlobalPosition = /*fightToShow?.camPositionNode.GlobalPosition ??*/ _followNode.GlobalPosition; - + GlobalPosition = CameraTarget.GetActiveTarget().GlobalPosition; } - } diff --git a/scripts/CSharp/Common/Camera/CameraTarget.cs b/scripts/CSharp/Common/Camera/CameraTarget.cs new file mode 100644 index 0000000..1eff8cc --- /dev/null +++ b/scripts/CSharp/Common/Camera/CameraTarget.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using System.Linq; +using Godot; + +namespace Babushka.scripts.CSharp.Common.Camera; + +public partial class CameraTarget : Node2D +{ + private static readonly List AllTargets = new(); + + public static CameraTarget GetActiveTarget() // Called every frame. Maybe needs performance optimization in the future + { + return AllTargets + .OrderByDescending(t => t.Priority) + .First(); + } + + [Export] public float Priority { get; set; } + + public override void _EnterTree() + { + AllTargets.Add(this); + } + + public override void _ExitTree() + { + AllTargets.Remove(this); + } +} \ No newline at end of file diff --git a/scripts/CSharp/Common/Camera/CameraTarget.cs.uid b/scripts/CSharp/Common/Camera/CameraTarget.cs.uid new file mode 100644 index 0000000..0f69658 --- /dev/null +++ b/scripts/CSharp/Common/Camera/CameraTarget.cs.uid @@ -0,0 +1 @@ +uid://ccdhx1lt4n271 -- 2.36.3 From 89321e917a3f20eb9b25be0cc60e9bec837d5565 Mon Sep 17 00:00:00 2001 From: jonathan Date: Wed, 4 Feb 2026 19:43:49 +0100 Subject: [PATCH 2/8] Removed all outside connection to and from the Vesna prefabs --- prefabs/characters/Vesna.tscn | 26 +++++++++++++-- project.godot | 2 +- scenes/entity_scenes/farm_outside.tscn | 32 ++----------------- .../Common/Farming/FarmingControls2D.cs | 7 ++-- .../CSharp/Common/Farming/VesnaBehaviour2D.cs | 12 +++---- 5 files changed, 37 insertions(+), 42 deletions(-) diff --git a/prefabs/characters/Vesna.tscn b/prefabs/characters/Vesna.tscn index 0c92a50..cc9009f 100644 --- a/prefabs/characters/Vesna.tscn +++ b/prefabs/characters/Vesna.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=489 format=3 uid="uid://c25udixd5m6l0"] +[gd_scene load_steps=495 format=3 uid="uid://c25udixd5m6l0"] [ext_resource type="Script" uid="uid://b05uyj001ehwi" path="res://scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs" id="1_yd5ep"] [ext_resource type="Script" uid="uid://cjbclkxesh3hc" path="res://scripts/CSharp/Common/CharacterControls/PlayerMovement.cs" id="2_1vqmv"] @@ -286,6 +286,7 @@ [ext_resource type="Script" uid="uid://dj1qjambsa4pg" path="res://scripts/CSharp/Common/Farming/WateringCanSaveHelper.cs" id="472_kduih"] [ext_resource type="Texture2D" uid="uid://blh0t2ofqj2uq" path="res://art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0016.png" id="472_wdxsr"] [ext_resource type="AudioStream" uid="uid://dymoalptxmge" path="res://audio/sfx/Footsteps/Single/Gravel/Reverb/SFX_Footstep_Gravel_04_R.wav" id="473_8hbu5"] +[ext_resource type="Script" uid="uid://ccdhx1lt4n271" path="res://scripts/CSharp/Common/Camera/CameraTarget.cs" id="473_fn3kd"] [ext_resource type="AudioStream" uid="uid://4555a4w30tda" path="res://audio/sfx/Footsteps/Single/Gravel/Reverb/SFX_Footstep_Gravel_05_R.wav" id="474_t1d6r"] [ext_resource type="Texture2D" uid="uid://3t1m2xi4ks75" path="res://art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0018.png" id="474_tu801"] [ext_resource type="AudioStream" uid="uid://dpqvnogggvgea" path="res://audio/sfx/Footsteps/Single/Gravel/Reverb/SFX_Footstep_Gravel_06_R.wav" id="475_83c4i"] @@ -299,8 +300,12 @@ [ext_resource type="Texture2D" uid="uid://bopxv06co1osl" path="res://art/animation/Vesna2D/Vesna Anims Sequences/F02-Walk/0006.png" id="482_wfdif"] [ext_resource type="Script" uid="uid://iquhbkr7pqeg" path="res://scripts/CSharp/Common/Savegame/SaveCheats.cs" id="483_kduih"] [ext_resource type="Texture2D" uid="uid://coyggdfwgkeru" path="res://art/animation/Vesna2D/Vesna Anims Sequences/F02-Walk/0008.png" id="484_32thn"] +[ext_resource type="AudioStream" uid="uid://fsiypqhql67w" path="res://audio/sfx/Farming/SFX_GettingWater_01.wav" id="484_jb7tm"] [ext_resource type="Script" uid="uid://ca4s0algeij1h" path="res://scripts/CSharp/Common/Savegame/SaveIDProviderTool.cs" id="484_upuan"] +[ext_resource type="AudioStream" uid="uid://foyw26hq1qp5" path="res://audio/sfx/Farming/SFX_GettingWater_02.wav" id="485_fn3kd"] [ext_resource type="Texture2D" uid="uid://du6x1h42smp6m" path="res://art/animation/Vesna2D/Vesna Anims Sequences/F02-Walk/0010.png" id="486_kobao"] +[ext_resource type="AudioStream" uid="uid://c43a6x43jkikl" path="res://audio/sfx/Farming/SFX_GettingWater_Well_01_Reverb.wav" id="486_ux0r8"] +[ext_resource type="Script" uid="uid://cfnrd5k1k0gxw" path="res://scripts/CSharp/Common/AudioPlayer2D.cs" id="487_7qtxa"] [ext_resource type="Texture2D" uid="uid://bras5gn8ov27l" path="res://art/animation/Vesna2D/Vesna Anims Sequences/F02-Walk/0012.png" id="488_ygjj5"] [ext_resource type="Texture2D" uid="uid://rjmsht4g8dvp" path="res://art/animation/Vesna2D/Vesna Anims Sequences/F02-Walk/0014.png" id="490_6603x"] [ext_resource type="Texture2D" uid="uid://diqnv8ut7lffx" path="res://art/animation/Vesna2D/Vesna Anims Sequences/F02-Walk/0016.png" id="492_0tmn6"] @@ -484,7 +489,7 @@ [ext_resource type="Texture2D" uid="uid://b0v61all3tsny" path="res://art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0018.png" id="812_sf8kv"] [ext_resource type="Texture2D" uid="uid://cao7vqax8cblo" path="res://art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0020.png" id="814_3uq4g"] [ext_resource type="Script" uid="uid://bcskt5ckh3rqa" path="res://scripts/CSharp/Common/Farming/FarmingControls2D.cs" id="817_6nrw3"] -[ext_resource type="Script" uid="uid://cvkw4qd2hxksi" path="res://scripts/GdScript/dialogic_toggle.gd" id="819_4na52"] +[ext_resource type="Script" path="res://scripts/GdScript/dialogic_toggle.gd" id="819_4na52"] [sub_resource type="CircleShape2D" id="CircleShape2D_ssqtd"] radius = 110.018 @@ -2087,6 +2092,12 @@ stream_4/stream = ExtResource("474_t1d6r") stream_5/stream = ExtResource("475_83c4i") stream_6/stream = ExtResource("476_deeju") +[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_4da77"] +streams_count = 3 +stream_0/stream = ExtResource("484_jb7tm") +stream_1/stream = ExtResource("485_fn3kd") +stream_2/stream = ExtResource("486_ux0r8") + [node name="Vesna" type="Node2D" node_paths=PackedStringArray("_farmingControls", "_player2d", "_vesnaAnimations")] y_sort_enabled = true script = ExtResource("1_yd5ep") @@ -2175,6 +2186,10 @@ _wateringCanFillStateNode = NodePath("../WateringCanFillState") [node name="DetectionCross" parent="CharacterBody2D" instance=ExtResource("466_e04c3")] position = Vector2(0, -260) +[node name="CameraTarget" type="Node2D" parent="CharacterBody2D"] +script = ExtResource("473_fn3kd") +Priority = 10.0 + [node name="FarmingControls" type="Node2D" parent="." node_paths=PackedStringArray("_movingPlayer")] script = ExtResource("817_6nrw3") _sceneKeyProvider = ExtResource("471_83c4i") @@ -2197,6 +2212,12 @@ script = ExtResource("471_2f15g") [node name="Timer" type="Timer" parent="SFX/FootstepsAudio"] wait_time = 0.5 +[node name="FillWater SFX2" type="AudioStreamPlayer2D" parent="SFX"] +stream = SubResource("AudioStreamRandomizer_4da77") +max_distance = 20000000.0 +playback_type = 2 +script = ExtResource("487_7qtxa") + [node name="SaveSystem" type="Node" parent="."] [node name="SaveGameCheat" type="Node" parent="SaveSystem"] @@ -2206,6 +2227,7 @@ script = ExtResource("483_kduih") script = ExtResource("484_upuan") [connection signal="FilledWateringCan" from="." to="CharacterBody2D/WateringCan/WateringCanUI" method="Refill"] +[connection signal="FilledWateringCan" from="." to="SFX/FillWater SFX2" method="PlayOneShot"] [connection signal="InventorySelectionChanged" from="." to="CharacterBody2D/WateringCan/WateringCanUI" method="IsWateringCanActive"] [connection signal="PickedUpTool" from="." to="CharacterBody2D/visuals" method="ActivateTool"] [connection signal="PickedUpTool" from="." to="CharacterBody2D/WateringCan/WateringCanUI" method="IsWateringCanActive"] diff --git a/project.godot b/project.godot index 33b6217..ef0cf21 100644 --- a/project.godot +++ b/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="Babushka" -run/main_scene="uid://bopv10dqm1knc" +run/main_scene="uid://66pmq4efjip8" config/features=PackedStringArray("4.5", "C#", "Forward Plus") run/max_fps=120 boot_splash/fullsize=false diff --git a/scenes/entity_scenes/farm_outside.tscn b/scenes/entity_scenes/farm_outside.tscn index 02bd765..6c92e2a 100644 --- a/scenes/entity_scenes/farm_outside.tscn +++ b/scenes/entity_scenes/farm_outside.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=122 format=3 uid="uid://66pmq4efjip8"] +[gd_scene load_steps=118 format=3 uid="uid://66pmq4efjip8"] [ext_resource type="Script" uid="uid://cssdu8viimwm6" path="res://scripts/CSharp/Common/SceneTransition.cs" id="1_o8nii"] [ext_resource type="Script" uid="uid://bqomwxclsbhd3" path="res://scripts/CSharp/Common/Camera/CameraController.cs" id="2_mnal7"] @@ -63,9 +63,6 @@ [ext_resource type="Script" uid="uid://cfnrd5k1k0gxw" path="res://scripts/CSharp/Common/AudioPlayer2D.cs" id="61_sfnme"] [ext_resource type="AudioStream" uid="uid://dapsknn486aee" path="res://audio/sfx/Farming/SFX_WateringPlants_01.wav" id="62_38bnv"] [ext_resource type="AudioStream" uid="uid://dnyne8wov50so" path="res://audio/sfx/Farming/SFX_WateringPlants_02.wav" id="63_cbwuo"] -[ext_resource type="AudioStream" uid="uid://fsiypqhql67w" path="res://audio/sfx/Farming/SFX_GettingWater_01.wav" id="64_netyg"] -[ext_resource type="AudioStream" uid="uid://foyw26hq1qp5" path="res://audio/sfx/Farming/SFX_GettingWater_02.wav" id="65_ujx1u"] -[ext_resource type="AudioStream" uid="uid://c43a6x43jkikl" path="res://audio/sfx/Farming/SFX_GettingWater_Well_01_Reverb.wav" id="66_hokxo"] [ext_resource type="Script" uid="uid://cldtt4atgymm5" path="res://scripts/CSharp/Common/Quest/QuestTrigger.cs" id="67_qfkw3"] [ext_resource type="Resource" uid="uid://cm8kftow8br00" path="res://resources/quests/demo/1_talk_yeli_1.tres" id="68_ukjtk"] [ext_resource type="Script" uid="uid://c741nyedy26mx" path="res://scripts/CSharp/Common/QuestBehaviour/DetectInventoryContains.cs" id="69_3q2kg"] @@ -264,12 +261,6 @@ streams_count = 2 stream_0/stream = ExtResource("62_38bnv") stream_1/stream = ExtResource("63_cbwuo") -[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_618my"] -streams_count = 3 -stream_0/stream = ExtResource("64_netyg") -stream_1/stream = ExtResource("65_ujx1u") -stream_2/stream = ExtResource("66_hokxo") - [sub_resource type="Resource" id="Resource_y820s"] script = ExtResource("70_i0rxh") blueprint = ExtResource("33_iuqnb") @@ -284,7 +275,7 @@ metadata/_custom_type_script = "uid://be54lnb6gg81f" script = ExtResource("1_o8nii") _sceneNamesToLoad = PackedStringArray("res://scenes/Babushka_scene_indoor_common_room.tscn", "res://scenes/entity_scenes/outside_beets.tscn") -[node name="Camera2D" type="Camera2D" parent="." node_paths=PackedStringArray("_followNode")] +[node name="Camera2D" type="Camera2D" parent="."] position = Vector2(3180, 1961) scale = Vector2(1, 0.993819) offset = Vector2(0, -500) @@ -295,7 +286,6 @@ limit_right = 16000 limit_bottom = 4700 editor_draw_limits = true script = ExtResource("2_mnal7") -_followNode = NodePath("../YSorted/Vesna/CharacterBody2D") [node name="ParallaxBackground" type="ParallaxBackground" parent="."] @@ -966,10 +956,6 @@ z_index = 1 position = Vector2(9322, 2018) _hoe = ExtResource("28_678ve") -[node name="FarmingControls" parent="YSorted/Vesna" index="1" node_paths=PackedStringArray("_camera", "_fieldParent")] -_camera = NodePath("../../../Camera2D") -_fieldParent = NodePath("../../FieldParent") - [node name="Well" type="Sprite2D" parent="YSorted" node_paths=PackedStringArray("_interactionArea")] z_index = 1 y_sort_enabled = true @@ -2480,12 +2466,6 @@ max_distance = 20000000.0 playback_type = 2 script = ExtResource("61_sfnme") -[node name="FillWater SFX2" type="AudioStreamPlayer2D" parent="Audio/SFX"] -stream = SubResource("AudioStreamRandomizer_618my") -max_distance = 20000000.0 -playback_type = 2 -script = ExtResource("61_sfnme") - [node name="SpecialQuestTrigger" type="Node" parent="."] [node name="QuestInstantStart" type="Node" parent="SpecialQuestTrigger"] @@ -2552,23 +2532,16 @@ script = ExtResource("82_ec5sc") visible = false texture = ExtResource("83_50rxh") -[connection signal="FilledWateringCan" from="YSorted/Vesna" to="Audio/SFX/FillWater SFX2" method="PlayOneShot"] -[connection signal="InteractedTool" from="YSorted/Well/InteractionArea" to="YSorted/Vesna" method="TryFillWateringCan"] [connection signal="area_entered" from="YSorted/Well/InteractionArea/Area2D" to="YSorted/Well/InteractionArea" method="OnPlayerEntered"] [connection signal="area_exited" from="YSorted/Well/InteractionArea/Area2D" to="YSorted/Well/InteractionArea" method="OnPlayerExited"] -[connection signal="SuccessfulPickUp" from="YSorted/CanGenericPickup" to="YSorted/Vesna" method="HandlePickUp"] [connection signal="area_entered" from="YSorted/CanGenericPickup/PickupInteractionArea/Area2D" to="YSorted/CanGenericPickup/PickupInteractionArea" method="OnPlayerEntered"] [connection signal="area_exited" from="YSorted/CanGenericPickup/PickupInteractionArea/Area2D" to="YSorted/CanGenericPickup/PickupInteractionArea" method="OnPlayerExited"] -[connection signal="SuccessfulPickUp" from="YSorted/RakeGenericPickup" to="YSorted/Vesna" method="HandlePickUp"] [connection signal="area_entered" from="YSorted/RakeGenericPickup/PickupInteractionArea/Area2D" to="YSorted/RakeGenericPickup/PickupInteractionArea" method="OnPlayerEntered"] [connection signal="area_exited" from="YSorted/RakeGenericPickup/PickupInteractionArea/Area2D" to="YSorted/RakeGenericPickup/PickupInteractionArea" method="OnPlayerExited"] -[connection signal="SuccessfulPickUp" from="YSorted/SeedPickup" to="YSorted/Vesna" method="HandlePickUp"] [connection signal="area_entered" from="YSorted/SeedPickup/PickupInteractionArea/Area2D" to="YSorted/SeedPickup/PickupInteractionArea" method="OnPlayerEntered"] [connection signal="area_exited" from="YSorted/SeedPickup/PickupInteractionArea/Area2D" to="YSorted/SeedPickup/PickupInteractionArea" method="OnPlayerExited"] -[connection signal="SuccessfulPickUp" from="YSorted/BeetPickup" to="YSorted/Vesna" method="HandlePickUp"] [connection signal="area_entered" from="YSorted/BeetPickup/PickupInteractionArea/Area2D" to="YSorted/BeetPickup/PickupInteractionArea" method="OnPlayerEntered"] [connection signal="area_exited" from="YSorted/BeetPickup/PickupInteractionArea/Area2D" to="YSorted/BeetPickup/PickupInteractionArea" method="OnPlayerExited"] -[connection signal="SuccessfulPickUp" from="YSorted/SeedPickup2" to="YSorted/Vesna" method="HandlePickUp"] [connection signal="area_entered" from="YSorted/SeedPickup2/PickupInteractionArea/Area2D" to="YSorted/SeedPickup2/PickupInteractionArea" method="OnPlayerEntered"] [connection signal="area_exited" from="YSorted/SeedPickup2/PickupInteractionArea/Area2D" to="YSorted/SeedPickup2/PickupInteractionArea" method="OnPlayerExited"] [connection signal="InteractedTool" from="YSorted/Farm visuals/Static/EnterHouseInteraction" to="." method="LoadSceneAtIndex"] @@ -2588,7 +2561,6 @@ texture = ExtResource("83_50rxh") [connection signal="OnFulfilled" from="SpecialQuestTrigger/FieldWorkTrigger" to="SpecialQuestTrigger/FieldWorkTrigger/StartDialog" method="open"] [connection signal="tree_entered" from="SceneNameSetter" to="SceneNameSetter" method="Set"] -[editable path="YSorted/Vesna"] [editable path="YSorted/Well/InteractionArea"] [editable path="YSorted/CanGenericPickup"] [editable path="YSorted/CanGenericPickup/PickupInteractionArea"] diff --git a/scripts/CSharp/Common/Farming/FarmingControls2D.cs b/scripts/CSharp/Common/Farming/FarmingControls2D.cs index 163f07e..76630ae 100644 --- a/scripts/CSharp/Common/Farming/FarmingControls2D.cs +++ b/scripts/CSharp/Common/Farming/FarmingControls2D.cs @@ -8,11 +8,11 @@ public partial class FarmingControls2D : Node2D { [Export] private VariableResource _sceneKeyProvider; [Export] private Node2D _movingPlayer; - [Export] private Camera2D _camera; + //[Export] private Camera2D _camera; // can be replaced with GetViewport().GetCamera2D() [Export] private float _wateringCanParticlesVerticalOffset = 50f; [Export] private Vector2I _fieldOffsetVector = new Vector2I(735, 651); - [Export] private Node2D _fieldParent; + //[Export] private Node2D _fieldParent; // never used private int _toolId = -1; private bool _wateringCanFilled = false; @@ -51,7 +51,8 @@ public partial class FarmingControls2D : Node2D private Vector2I GetAdjustedMousePosition() { - Vector2 mousePosition = _camera.GetGlobalMousePosition(); + var camera = GetViewport().GetCamera2D(); + Vector2 mousePosition = camera.GetGlobalMousePosition(); Vector2I mousePositionInteger = (Vector2I) mousePosition; Vector2I adjustedPosition = AdjustValue(mousePositionInteger, _fieldOffsetVector); return adjustedPosition; diff --git a/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs b/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs index 46c9c19..0fcf55c 100644 --- a/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs +++ b/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs @@ -6,7 +6,7 @@ using Godot; namespace Babushka.scripts.CSharp.Common.Farming; -public partial class VesnaBehaviour2D : Node +public partial class VesnaBehaviour2D : Node2D // EntityNode { [ExportGroup("Farming")] [Export] private FarmingControls2D _farmingControls; @@ -39,11 +39,11 @@ public partial class VesnaBehaviour2D : Node /// Called when picking up an item. /// Makes sure that item animations are also updated when they are occupying a currently empty spot. /// - public void HandlePickUp() - { - //Calls the same event handler as the inventory to ensure the currently selected item is updated in the animation. - HandleInventorySelectedSlotIndexChanged(0); - } + //public void HandlePickUp() + //{ + // //Calls the same event handler as the inventory to ensure the currently selected item is updated in the animation. + // HandleInventorySelectedSlotIndexChanged(0); + //} private void HandleInventorySelectedSlotIndexChanged(int newIndex = 0) { -- 2.36.3 From 0bf3cc19c7271f88fdfcdd311dd3b209b462dc62 Mon Sep 17 00:00:00 2001 From: jonathan Date: Wed, 4 Feb 2026 19:57:46 +0100 Subject: [PATCH 3/8] Changed naming stile for constants to CAPSLOCK --- Babushka.sln.DotSettings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Babushka.sln.DotSettings b/Babushka.sln.DotSettings index a4c6213..23d4754 100644 --- a/Babushka.sln.DotSettings +++ b/Babushka.sln.DotSettings @@ -1,5 +1,7 @@  + <Policy><Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /></Policy> <Policy><Descriptor Staticness="Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Instance fields (not private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"><ElementKinds><Kind Name="CONSTANT_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AA_BB" /></Policy> Godot Signal [Signal] public delegate void $SignalName$EventHandler($END$); -- 2.36.3 From 1b77718b9b297b4c96fb99fffcaecb3e4efc16a5 Mon Sep 17 00:00:00 2001 From: jonathan Date: Wed, 4 Feb 2026 20:25:54 +0100 Subject: [PATCH 4/8] Added basic vesna entity --- prefabs/characters/Vesna.tscn | 4 ++-- prefabs/entity_placer/VesnaPlacer.tscn | 17 ++++++++++++++ prefabs/entity_system/entity_manager.tscn | 6 +++-- scenes/entity_scenes/farm_outside.tscn | 8 +++---- .../CSharp/Common/Farming/VesnaBehaviour2D.cs | 2 +- .../CSharp/GameEntity/Entities/VesnaEntity.cs | 18 +++++++++++++++ .../GameEntity/Entities/VesnaEntity.cs.uid | 1 + .../EntityPlacer/VesnaEntityPlacer.cs | 23 +++++++++++++++++++ .../EntityPlacer/VesnaEntityPlacer.cs.uid | 1 + 9 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 prefabs/entity_placer/VesnaPlacer.tscn create mode 100644 scripts/CSharp/GameEntity/Entities/VesnaEntity.cs create mode 100644 scripts/CSharp/GameEntity/Entities/VesnaEntity.cs.uid create mode 100644 scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs create mode 100644 scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs.uid diff --git a/prefabs/characters/Vesna.tscn b/prefabs/characters/Vesna.tscn index cc9009f..71b5a9d 100644 --- a/prefabs/characters/Vesna.tscn +++ b/prefabs/characters/Vesna.tscn @@ -2098,11 +2098,11 @@ stream_0/stream = ExtResource("484_jb7tm") stream_1/stream = ExtResource("485_fn3kd") stream_2/stream = ExtResource("486_ux0r8") -[node name="Vesna" type="Node2D" node_paths=PackedStringArray("_farmingControls", "_player2d", "_vesnaAnimations")] +[node name="Vesna" type="Node2D" node_paths=PackedStringArray("_farmingControls", "player2d", "_vesnaAnimations")] y_sort_enabled = true script = ExtResource("1_yd5ep") _farmingControls = NodePath("FarmingControls") -_player2d = NodePath("CharacterBody2D") +player2d = NodePath("CharacterBody2D") _vesnaAnimations = NodePath("CharacterBody2D/visuals") _hoe = ExtResource("2_dnm27") _wateringCan = ExtResource("3_e04c3") diff --git a/prefabs/entity_placer/VesnaPlacer.tscn b/prefabs/entity_placer/VesnaPlacer.tscn new file mode 100644 index 0000000..3abd595 --- /dev/null +++ b/prefabs/entity_placer/VesnaPlacer.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=4 format=3 uid="uid://cv7trh2b3dyiv"] + +[ext_resource type="Script" uid="uid://dcn4giw1auva4" path="res://scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs" id="1_nq5fu"] +[ext_resource type="Script" uid="uid://n7oihifvqp23" path="res://scripts/CSharp/Common/Animation/VesnaAnimations.cs" id="2_cpdud"] +[ext_resource type="Texture2D" uid="uid://cloe0etis2lcu" path="res://art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0001.png" id="451_d8nvl"] + +[node name="VesnaPlacer" type="Node2D"] +script = ExtResource("1_nq5fu") + +[node name="visuals" type="Node2D" parent="." node_paths=PackedStringArray("_sprite")] +position = Vector2(0, -374) +script = ExtResource("2_cpdud") +_sprite = NodePath("") + +[node name="0001" type="Sprite2D" parent="visuals"] +position = Vector2(1, 0) +texture = ExtResource("451_d8nvl") diff --git a/prefabs/entity_system/entity_manager.tscn b/prefabs/entity_system/entity_manager.tscn index 92dd554..36226ce 100644 --- a/prefabs/entity_system/entity_manager.tscn +++ b/prefabs/entity_system/entity_manager.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=4 format=3 uid="uid://hdfejdnmp8sl"] +[gd_scene load_steps=5 format=3 uid="uid://hdfejdnmp8sl"] [ext_resource type="Script" uid="uid://umop2b1m1qm8" path="res://scripts/CSharp/GameEntity/Management/EntityManager.cs" id="1_2bwns"] [ext_resource type="Script" uid="uid://bogqp274y1pgr" path="res://scripts/CSharp/GameEntity/Management/EntityNodeCreator.cs" id="2_8m173"] [ext_resource type="PackedScene" uid="uid://sbf12hin4kes" path="res://prefabs/Interactables/trash_object.tscn" id="3_v3vdc"] +[ext_resource type="PackedScene" uid="uid://c25udixd5m6l0" path="res://prefabs/characters/Vesna.tscn" id="4_8m173"] [node name="EntityManager" type="Node" node_paths=PackedStringArray("_nodeCreator")] script = ExtResource("1_2bwns") @@ -11,5 +12,6 @@ _nodeCreator = NodePath("EntityCreator") [node name="EntityCreator" type="Node" parent="."] script = ExtResource("2_8m173") _entityPrefabs = Dictionary[String, PackedScene]({ -"TrashEntity": ExtResource("3_v3vdc") +"TrashEntity": ExtResource("3_v3vdc"), +"VesnaEntity": ExtResource("4_8m173") }) diff --git a/scenes/entity_scenes/farm_outside.tscn b/scenes/entity_scenes/farm_outside.tscn index 6c92e2a..fcc5cf2 100644 --- a/scenes/entity_scenes/farm_outside.tscn +++ b/scenes/entity_scenes/farm_outside.tscn @@ -26,7 +26,7 @@ [ext_resource type="Texture2D" uid="uid://btea6eyucsyxj" path="res://art/farm/farming/farmobjekte/zaun/tilable fence middle part.png" id="24_hr375"] [ext_resource type="Texture2D" uid="uid://3ed3dgq3irn2" path="res://art/farm/farming/farmobjekte/zaun/tilable fence end part2.png" id="25_e15ep"] [ext_resource type="PackedScene" uid="uid://dfvgp1my5rydh" path="res://prefabs/characters/Yeli.tscn" id="26_hp2qi"] -[ext_resource type="PackedScene" uid="uid://c25udixd5m6l0" path="res://prefabs/characters/Vesna.tscn" id="27_slkey"] +[ext_resource type="PackedScene" uid="uid://cv7trh2b3dyiv" path="res://prefabs/entity_placer/VesnaPlacer.tscn" id="27_nqcah"] [ext_resource type="Resource" uid="uid://dlcmqfjvgphqu" path="res://resources/items/rake.tres" id="28_678ve"] [ext_resource type="Texture2D" uid="uid://dg7rlugnq0t45" path="res://art/farm/farming/farmobjekte/brünnen.png" id="29_6crsp"] [ext_resource type="Script" uid="uid://boehox1ydbcnx" path="res://scripts/CSharp/Common/Farming/WellBehaviour.cs" id="30_1l41q"] @@ -951,10 +951,8 @@ y_sort_enabled = true position = Vector2(6403, 3362) _timelinesToPlay = PackedStringArray("yeli_quest_select") -[node name="Vesna" parent="YSorted" instance=ExtResource("27_slkey")] -z_index = 1 -position = Vector2(9322, 2018) -_hoe = ExtResource("28_678ve") +[node name="VesnaPlacer" parent="YSorted" instance=ExtResource("27_nqcah")] +position = Vector2(9178, 2365) [node name="Well" type="Sprite2D" parent="YSorted" node_paths=PackedStringArray("_interactionArea")] z_index = 1 diff --git a/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs b/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs index 0fcf55c..44e171c 100644 --- a/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs +++ b/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs @@ -10,7 +10,7 @@ public partial class VesnaBehaviour2D : Node2D // EntityNode { [ExportGroup("Farming")] [Export] private FarmingControls2D _farmingControls; - [Export] private PlayerMovement _player2d; + [Export] public PlayerMovement player2d; [Export] private VesnaAnimations _vesnaAnimations; [Export] private ItemResource _hoe; [Export] private ItemResource _wateringCan; diff --git a/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs b/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs new file mode 100644 index 0000000..31c9d55 --- /dev/null +++ b/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs @@ -0,0 +1,18 @@ +using Babushka.scripts.CSharp.Common.Farming; +using Babushka.scripts.CSharp.GameEntity.Management; +using Godot; + +namespace Babushka.scripts.CSharp.GameEntity.Entities; + +public class VesnaEntity : PositionalEntity +{ + public override string EntityType => OWN_TYPE_NAME; + public const string OWN_TYPE_NAME = "VesnaEntity"; + + public override void InstantiateEntityNode(Node2D parent) + { + var node = (VesnaBehaviour2D) EntityManager.Instance.NodeCreator.InstantiateNode(OWN_TYPE_NAME); + node.player2d.GlobalPosition = position; + parent.AddChild(node); + } +} \ No newline at end of file diff --git a/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs.uid b/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs.uid new file mode 100644 index 0000000..2db9706 --- /dev/null +++ b/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs.uid @@ -0,0 +1 @@ +uid://c7e45co1valv3 diff --git a/scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs b/scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs new file mode 100644 index 0000000..495e143 --- /dev/null +++ b/scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs @@ -0,0 +1,23 @@ +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; +using Godot; + +namespace Babushka.scripts.CSharp.GameEntity.EntityPlacer; + +public partial class VesnaEntityPlacer : Node2D +{ + public override void _Ready() + { + var sceneName = EntityManager.Instance.CurrentEntitySceneContainer!.sceneName; + var loadedScenesEntity = EntityManager.Instance.GetUniqueEntity(); + + if (!loadedScenesEntity.WasSceneLoaded(sceneName)) + { + var entity = EntityManager.Instance.GetUniqueEntity(); + entity.position = GlobalPosition; + entity.sceneName = sceneName; + } + + QueueFree(); + } +} \ No newline at end of file diff --git a/scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs.uid b/scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs.uid new file mode 100644 index 0000000..30e8440 --- /dev/null +++ b/scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs.uid @@ -0,0 +1 @@ +uid://dcn4giw1auva4 -- 2.36.3 From 78412528091b9bd182b34c907db77e7871327be3 Mon Sep 17 00:00:00 2001 From: jonathan Date: Wed, 4 Feb 2026 20:40:50 +0100 Subject: [PATCH 5/8] Make Vesna entity save current position --- .../CSharp/Common/CharacterControls/PlayerMovement.cs | 10 ++++++++++ scripts/CSharp/GameEntity/Entities/VesnaEntity.cs | 2 +- scripts/CSharp/GameEntity/Management/EntityManager.cs | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/scripts/CSharp/Common/CharacterControls/PlayerMovement.cs b/scripts/CSharp/Common/CharacterControls/PlayerMovement.cs index bb95566..d40da0a 100644 --- a/scripts/CSharp/Common/CharacterControls/PlayerMovement.cs +++ b/scripts/CSharp/Common/CharacterControls/PlayerMovement.cs @@ -1,4 +1,5 @@ using Babushka.scripts.CSharp.Common.Services; +using Babushka.scripts.CSharp.GameEntity.Entities; using Godot; namespace Babushka.scripts.CSharp.Common.CharacterControls; @@ -8,6 +9,14 @@ public partial class PlayerMovement : CharacterBody2D [Export] private float _speed = 1000f; [Export] private Timer _stepTimer; + private PositionalEntity _entity; + + public void Initialize(PositionalEntity entity) + { + _entity = entity; + GlobalPosition = entity.position; + } + public override void _Process(double delta) { bool anyActionPressed = false; @@ -76,6 +85,7 @@ public partial class PlayerMovement : CharacterBody2D Velocity = currentVelocity; MoveAndSlide(); + _entity.position = GlobalPosition; } else { diff --git a/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs b/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs index 31c9d55..9a5aa5a 100644 --- a/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs +++ b/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs @@ -12,7 +12,7 @@ public class VesnaEntity : PositionalEntity public override void InstantiateEntityNode(Node2D parent) { var node = (VesnaBehaviour2D) EntityManager.Instance.NodeCreator.InstantiateNode(OWN_TYPE_NAME); - node.player2d.GlobalPosition = position; + node.player2d.Initialize(this); parent.AddChild(node); } } \ No newline at end of file diff --git a/scripts/CSharp/GameEntity/Management/EntityManager.cs b/scripts/CSharp/GameEntity/Management/EntityManager.cs index 3e14b1a..ee54350 100644 --- a/scripts/CSharp/GameEntity/Management/EntityManager.cs +++ b/scripts/CSharp/GameEntity/Management/EntityManager.cs @@ -93,6 +93,7 @@ public partial class EntityManager : Node { TrashEntity.OWN_TYPE_NAME => new TrashEntity(), LoadedScenesEntity.OWN_TYPE_NAME => new LoadedScenesEntity(), + VesnaEntity.OWN_TYPE_NAME => new VesnaEntity(), _ => throw new Exception($"Trying to load unknown entity type: {type}") }; -- 2.36.3 From a6fa4315dc8138c63b33ab56a5d0838eab65e8d5 Mon Sep 17 00:00:00 2001 From: jonathan Date: Wed, 4 Feb 2026 21:32:24 +0100 Subject: [PATCH 6/8] Moved the player inventory and selected slot to VesnaEntity --- .../Common/Animation/VesnaAnimations.cs | 6 +- .../CSharp/Common/Farming/FieldBehaviour2D.cs | 8 +- .../CSharp/Common/Farming/VesnaBehaviour2D.cs | 34 +++---- .../Common/Fight/Actions/EatBeetrootAction.cs | 6 +- .../Common/Fight/UI/HealButtonVisual.cs | 4 +- .../Common/Inventory/InventoryInstance.cs | 98 +++---------------- .../Common/Inventory/InventoryListener.cs | 23 +++-- .../Common/Inventory/InventoryManager.cs | 35 ------- .../Common/Inventory/InventoryTestScript.cs | 6 +- .../CSharp/Common/Inventory/InventoryUi.cs | 24 +++-- .../CSharp/Common/Inventory/ItemOnGround2D.cs | 95 +++++++++--------- .../Items/InventoryDependentInteractable.cs | 18 ++-- .../QuestBehaviour/DetectInventoryContains.cs | 8 +- .../CSharp/GameEntity/Entities/VesnaEntity.cs | 20 +++- 14 files changed, 165 insertions(+), 220 deletions(-) diff --git a/scripts/CSharp/Common/Animation/VesnaAnimations.cs b/scripts/CSharp/Common/Animation/VesnaAnimations.cs index f883252..1156d09 100644 --- a/scripts/CSharp/Common/Animation/VesnaAnimations.cs +++ b/scripts/CSharp/Common/Animation/VesnaAnimations.cs @@ -1,6 +1,8 @@ using System.Threading.Tasks; using Babushka.scripts.CSharp.Common.Inventory; using Babushka.scripts.CSharp.Common.Services; +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; using Godot; namespace Babushka.scripts.CSharp.Common.Animation; @@ -27,12 +29,12 @@ public partial class VesnaAnimations : Node private void SetupSubscriptions() { - InventoryManager.Instance.playerInventory.InventoryContentsChanged += HandleNewItemInInventory; + EntityManager.Instance.GetUniqueEntity().inventory.InventoryContentsChanged += HandleNewItemInInventory; } public override void _ExitTree() { - InventoryManager.Instance.playerInventory.InventoryContentsChanged -= HandleNewItemInInventory; + EntityManager.Instance.GetUniqueEntity().inventory.InventoryContentsChanged -= HandleNewItemInInventory; } private void HandleNewItemInInventory() diff --git a/scripts/CSharp/Common/Farming/FieldBehaviour2D.cs b/scripts/CSharp/Common/Farming/FieldBehaviour2D.cs index f747986..0e4d0c1 100644 --- a/scripts/CSharp/Common/Farming/FieldBehaviour2D.cs +++ b/scripts/CSharp/Common/Farming/FieldBehaviour2D.cs @@ -3,6 +3,8 @@ using Babushka.scripts.CSharp.Common.CharacterControls; using Babushka.scripts.CSharp.Common.DayAndNight; using Babushka.scripts.CSharp.Common.Inventory; using Babushka.scripts.CSharp.Common.Savegame; +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; using Babushka.scripts.CSharp.Low_Code.Events; using Babushka.scripts.CSharp.Low_Code.Variables; using Godot; @@ -178,8 +180,8 @@ public partial class FieldBehaviour2D : Sprite2D, ISaveable private bool TryPlant() { bool success = false; - int currentSlotIndex = InventoryManager.Instance.CurrentSelectedSlotIndex; - ItemInstance? item = InventoryManager.Instance.playerInventory.Slots[currentSlotIndex].itemInstance; + int currentSlotIndex = EntityManager.Instance.GetUniqueEntity().CurrentSelectedSlotIndex; + ItemInstance? item = EntityManager.Instance.GetUniqueEntity().inventory.Slots[currentSlotIndex].itemInstance; if (item == null || PlantingPlaceholder.GetChildCount() > 0 || item.amount == 0) return success; @@ -189,7 +191,7 @@ public partial class FieldBehaviour2D : Sprite2D, ISaveable if (!string.IsNullOrEmpty(plantPrefabPath)) { PlantPrefab(plantPrefabPath); - InventoryManager.Instance.playerInventory.RemoveItem(currentSlotIndex); + EntityManager.Instance.GetUniqueEntity().inventory.RemoveItem(currentSlotIndex); success = true; } diff --git a/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs b/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs index 44e171c..d6e2824 100644 --- a/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs +++ b/scripts/CSharp/Common/Farming/VesnaBehaviour2D.cs @@ -2,6 +2,8 @@ using Babushka.scripts.CSharp.Common.Animation; using Babushka.scripts.CSharp.Common.CharacterControls; using Babushka.scripts.CSharp.Common.Inventory; using Babushka.scripts.CSharp.Common.Services; +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; using Godot; namespace Babushka.scripts.CSharp.Common.Farming; @@ -20,34 +22,32 @@ public partial class VesnaBehaviour2D : Node2D // EntityNode [Signal] public delegate void InventorySelectionChangedEventHandler(int toolId); - private InventoryManager _inventoryManager; - private InventoryInstance _inventoryInstance; + //private InventoryManager _inventoryManager; + private VesnaEntity _vesnaEntity; + private InventoryInstance _playerInventory; public override void _Ready() { - _inventoryManager = InventoryManager.Instance; - _inventoryInstance = _inventoryManager.playerInventory; - _inventoryManager.SlotIndexChanged += HandleInventorySelectedSlotIndexChanged; + _vesnaEntity = EntityManager.Instance.GetUniqueEntity(); + _playerInventory = _vesnaEntity.inventory; + _vesnaEntity.SlotIndexChanged += HandleInventorySelectedSlotIndexChanged; + _playerInventory.InventoryContentsChanged += UpdateToolInHand; } public override void _ExitTree() { - _inventoryManager.SlotIndexChanged -= HandleInventorySelectedSlotIndexChanged; + _vesnaEntity.SlotIndexChanged -= HandleInventorySelectedSlotIndexChanged; + _playerInventory.InventoryContentsChanged -= UpdateToolInHand; } - /// - /// Called when picking up an item. - /// Makes sure that item animations are also updated when they are occupying a currently empty spot. - /// - //public void HandlePickUp() - //{ - // //Calls the same event handler as the inventory to ensure the currently selected item is updated in the animation. - // HandleInventorySelectedSlotIndexChanged(0); - //} + private void HandleInventorySelectedSlotIndexChanged(int _ = 0) + { + UpdateToolInHand(); + } - private void HandleInventorySelectedSlotIndexChanged(int newIndex = 0) + private void UpdateToolInHand() { - InventorySlot currentSlot = InventoryManager.Instance.GetCurrentSelectedSlot(); + InventorySlot currentSlot = _playerInventory.Slots[_vesnaEntity.CurrentSelectedSlotIndex]; ItemInstance? currentItem = currentSlot.itemInstance; int toolId = -1; diff --git a/scripts/CSharp/Common/Fight/Actions/EatBeetrootAction.cs b/scripts/CSharp/Common/Fight/Actions/EatBeetrootAction.cs index 791488b..0671d64 100644 --- a/scripts/CSharp/Common/Fight/Actions/EatBeetrootAction.cs +++ b/scripts/CSharp/Common/Fight/Actions/EatBeetrootAction.cs @@ -3,6 +3,8 @@ using System.Diagnostics; using System.Threading.Tasks; using Babushka.scripts.CSharp.Common.Inventory; using Babushka.scripts.CSharp.Common.Util; +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; namespace Babushka.scripts.CSharp.Common.Fight.Actions; @@ -17,7 +19,7 @@ public class EatBeetrootAction : FighterAction { Debug.Assert(FightWorld.Instance.itemBeetrootToEatForHealth != null, "Item to eat for health has not been set in the FightWorld autoload"); - return !InventoryManager.Instance.playerInventory!.HasItems(new ItemInstance + return !EntityManager.Instance.GetUniqueEntity().inventory.HasItems(new ItemInstance { blueprint = FightWorld.Instance.itemBeetrootToEatForHealth }); } @@ -35,7 +37,7 @@ public class EatBeetrootAction : FighterAction { var fighter = HappeningData.fighterTurn.Current; - var result = InventoryManager.Instance.playerInventory!.TryRemoveAllItems( + var result = EntityManager.Instance.GetUniqueEntity().inventory.TryRemoveAllItems( new ItemInstance { blueprint = FightWorld.Instance.itemBeetrootToEatForHealth! }); if (result != InventoryActionResult.Success) diff --git a/scripts/CSharp/Common/Fight/UI/HealButtonVisual.cs b/scripts/CSharp/Common/Fight/UI/HealButtonVisual.cs index 7cc8a4a..1e01331 100644 --- a/scripts/CSharp/Common/Fight/UI/HealButtonVisual.cs +++ b/scripts/CSharp/Common/Fight/UI/HealButtonVisual.cs @@ -1,4 +1,6 @@ using Babushka.scripts.CSharp.Common.Inventory; +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; using Godot; namespace Babushka.scripts.CSharp.Common.Fight.UI; @@ -9,7 +11,7 @@ public partial class HealButtonVisual : Button public void UpdateText() { - var healItemsLeft = InventoryManager.Instance.playerInventory!.TotalItemsOfBlueprint(_healItemBlueprint); + var healItemsLeft = EntityManager.Instance.GetUniqueEntity().inventory.TotalItemsOfBlueprint(_healItemBlueprint); Text = $"x{healItemsLeft} - Heal"; } } \ No newline at end of file diff --git a/scripts/CSharp/Common/Inventory/InventoryInstance.cs b/scripts/CSharp/Common/Inventory/InventoryInstance.cs index 431ec45..a548af1 100644 --- a/scripts/CSharp/Common/Inventory/InventoryInstance.cs +++ b/scripts/CSharp/Common/Inventory/InventoryInstance.cs @@ -7,21 +7,16 @@ using Babushka.scripts.CSharp.Common.Savegame; namespace Babushka.scripts.CSharp.Common.Inventory; -public partial class InventoryInstance : Node, ISaveable +public partial class InventoryInstance { - private List _slots = new(); + private readonly List _slots; public IReadOnlyList Slots => _slots; - [Signal] - public delegate void SlotAmountChangedEventHandler(); - - [Signal] - public delegate void InventoryContentsChangedEventHandler(); - - public static string ID = "inventoryInstance"; + public event Action? SlotAmountChanged; + public event Action? InventoryContentsChanged; /// - /// The total amount of Inventoryslots in the inventory (empty and occupied). + /// The total amount of InventorySlots in the inventory (empty and occupied). /// [Export] public int SlotAmount @@ -41,29 +36,20 @@ public partial class InventoryInstance : Node, ISaveable } } - EmitSignal(SignalName.SlotAmountChanged); + SlotAmountChanged?.Invoke(); } } - public override void _EnterTree() - { - LoadFromSaveData(); - InventoryContentsChanged += UpdateSaveData; - SlotAmountChanged += UpdateSaveData; - SavegameService.OnSaveGameReset += SaveGameReset; - } - - public override void _ExitTree() + public InventoryInstance(int slotCount) { - InventoryContentsChanged -= UpdateSaveData; - SlotAmountChanged -= UpdateSaveData; - SavegameService.OnSaveGameReset -= SaveGameReset; + _slots = new(); + SlotAmount = slotCount; } public InventoryActionResult AddItem(ItemInstance newItem) { var result = AddItemAndStackRecursive(newItem, 0); - EmitSignal(SignalName.InventoryContentsChanged); + InventoryContentsChanged?.Invoke(); return result; } @@ -137,7 +123,7 @@ public partial class InventoryInstance : Node, ISaveable if (itemInstance.amount == 0) _slots[inventorySlot].itemInstance = null; - EmitSignal(SignalName.InventoryContentsChanged); + InventoryContentsChanged?.Invoke(); return InventoryActionResult.Success; } @@ -174,7 +160,7 @@ public partial class InventoryInstance : Node, ISaveable break; } - EmitSignal(SignalName.InventoryContentsChanged); + InventoryContentsChanged?.Invoke(); return InventoryActionResult.Success; } @@ -187,7 +173,7 @@ public partial class InventoryInstance : Node, ISaveable return InventoryActionResult.DestinationFull; _slots[destinationSlot].itemInstance = itemInstance; - EmitSignal(SignalName.InventoryContentsChanged); + InventoryContentsChanged?.Invoke(); return InventoryActionResult.Success; } @@ -207,62 +193,4 @@ public partial class InventoryInstance : Node, ISaveable { return items.All(HasItems); } - - #region SAVE AND LOAD - - public void UpdateSaveData() - { - var payloadData = new Godot.Collections.Dictionary(); - - for (int i = 0; i < _slots.Count; i++) - { - if (!_slots[i].IsEmpty()) - { - string key = i.ToString(); - string[] value = new string[2]; - value[0] = _slots[i].itemInstance.blueprint.ResourcePath; - value[1] = _slots[i].itemInstance.amount.ToString(); - payloadData.Add(key, value); - } - } - - SavegameService.AppendDataToSave(ID, payloadData); - } - - public void LoadFromSaveData() - { - var id = ID; - - Godot.Collections.Dictionary save = SavegameService.GetSaveData(id); - - if (save.Count > 0) - { - for (int i = 0; i < _slots.Count; i++) - { - if (save.TryGetValue(i.ToString(), out Variant inventoryItemData)) - { - string[] savePayload = inventoryItemData.AsStringArray(); - ItemResource resource = ResourceLoader.Load(savePayload[0]); - int _amount = int.Parse(savePayload[1]); - - ItemInstance instance = new ItemInstance { blueprint = resource, amount = _amount }; - AddItem(instance); - } - } - } - } - - /// - /// Called when a new save is created. - /// Needs to do a runtime check because the InventoryInstance is already in existence at the beginning of the first scene. - /// - private void SaveGameReset() - { - foreach (var slot in _slots) - { - slot.itemInstance = null; - } - } - - #endregion } \ No newline at end of file diff --git a/scripts/CSharp/Common/Inventory/InventoryListener.cs b/scripts/CSharp/Common/Inventory/InventoryListener.cs index 424ebb1..5841700 100644 --- a/scripts/CSharp/Common/Inventory/InventoryListener.cs +++ b/scripts/CSharp/Common/Inventory/InventoryListener.cs @@ -1,3 +1,5 @@ +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; using Godot; namespace Babushka.scripts.CSharp.Common.Inventory; @@ -8,16 +10,25 @@ public partial class InventoryListener : Node [Signal] public delegate void ItemInstanceActivatedEventHandler(bool activated); + private VesnaEntity _vesnaEntity; + private InventoryInstance _playerInventory; + + public override void _EnterTree() + { + _vesnaEntity = EntityManager.Instance.GetUniqueEntity(); + _playerInventory = _vesnaEntity.inventory; + } + public override void _Ready() { - InventoryManager.Instance.playerInventory.InventoryContentsChanged += HandleNewItemInInventory; - InventoryManager.Instance.SlotIndexChanged += HandleNewItemInInventory; + _playerInventory.InventoryContentsChanged += HandleNewItemInInventory; + _vesnaEntity.SlotIndexChanged += HandleNewItemInInventory; } public override void _ExitTree() { - InventoryManager.Instance.playerInventory.InventoryContentsChanged -= HandleNewItemInInventory; - InventoryManager.Instance.SlotIndexChanged -= HandleNewItemInInventory; + _playerInventory.InventoryContentsChanged -= HandleNewItemInInventory; + _vesnaEntity.SlotIndexChanged -= HandleNewItemInInventory; } private void HandleNewItemInInventory(int newIndex) @@ -27,8 +38,8 @@ public partial class InventoryListener : Node private void HandleNewItemInInventory() { - int currentSlotIndex = InventoryManager.Instance.CurrentSelectedSlotIndex; - ItemInstance? instance = InventoryManager.Instance.playerInventory.Slots[currentSlotIndex].itemInstance; + int currentSlotIndex = _vesnaEntity.CurrentSelectedSlotIndex; + ItemInstance? instance = _playerInventory.Slots[currentSlotIndex].itemInstance; if (instance != null) { ItemResource? item = instance.blueprint; diff --git a/scripts/CSharp/Common/Inventory/InventoryManager.cs b/scripts/CSharp/Common/Inventory/InventoryManager.cs index 36166b1..078aa66 100644 --- a/scripts/CSharp/Common/Inventory/InventoryManager.cs +++ b/scripts/CSharp/Common/Inventory/InventoryManager.cs @@ -5,25 +5,8 @@ namespace Babushka.scripts.CSharp.Common.Inventory; public partial class InventoryManager : Node { - [Signal] - public delegate void SlotIndexChangedEventHandler(int newIndex); - - public static InventoryManager Instance { get; private set; } = null!; - public int CurrentSelectedSlotIndex - { - get => _currentSelectedSlotIndex; - set - { - if (value >= 0 && value <= 8) - { - _currentSelectedSlotIndex = value; - EmitSignalSlotIndexChanged(_currentSelectedSlotIndex); - } - } - } - public InventoryInstance? playerInventory; private int _currentSelectedSlotIndex = 0; @@ -34,9 +17,6 @@ public partial class InventoryManager : Node public override void _Ready() { - playerInventory = new InventoryInstance(); - playerInventory.SlotAmount = 37; - AddChild(playerInventory); } public InventoryActionResult CreateItem( @@ -82,19 +62,4 @@ public partial class InventoryManager : Node { return inventory.RemoveItem(inventorySlot); } - - public InventoryActionResult CollectItem(ItemInstance itemInstance) - { - return playerInventory.AddItem(itemInstance); - } - - public InventorySlot GetCurrentSelectedSlot() - { - if (CurrentSelectedSlotIndex < 0 || CurrentSelectedSlotIndex > 8) - throw new ArgumentOutOfRangeException( - nameof(CurrentSelectedSlotIndex), - "currentInventoryBarIndex must be between 0 and 8 (inclusively)"); - - return playerInventory.Slots[CurrentSelectedSlotIndex]; - } } diff --git a/scripts/CSharp/Common/Inventory/InventoryTestScript.cs b/scripts/CSharp/Common/Inventory/InventoryTestScript.cs index b7a1cc4..f02945f 100644 --- a/scripts/CSharp/Common/Inventory/InventoryTestScript.cs +++ b/scripts/CSharp/Common/Inventory/InventoryTestScript.cs @@ -1,4 +1,6 @@ -using Godot; +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; +using Godot; namespace Babushka.scripts.CSharp.Common.Inventory; public partial class InventoryTestScript : Node @@ -10,7 +12,7 @@ public partial class InventoryTestScript : Node { foreach (var itemResource in _testItemsToCreate) { - InventoryManager.Instance.CreateItem(itemResource, InventoryManager.Instance.playerInventory); + InventoryManager.Instance.CreateItem(itemResource, EntityManager.Instance.GetUniqueEntity().inventory); } } } diff --git a/scripts/CSharp/Common/Inventory/InventoryUi.cs b/scripts/CSharp/Common/Inventory/InventoryUi.cs index 11d9cfd..b207880 100644 --- a/scripts/CSharp/Common/Inventory/InventoryUi.cs +++ b/scripts/CSharp/Common/Inventory/InventoryUi.cs @@ -1,3 +1,5 @@ +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; using Godot; namespace Babushka.scripts.CSharp.Common.Inventory; @@ -10,6 +12,7 @@ public partial class InventoryUi : Control [Export] private Control _slotSelect; private InventoryInstance _playerInventory; + private VesnaEntity _vesnaEntity; private int? _slotOnMouse; private bool _inventoryExtended = false; private Tween? _inventoryExtensionTween; @@ -18,17 +21,18 @@ public partial class InventoryUi : Control public override void _Ready() { - _playerInventory = InventoryManager.Instance.playerInventory; + _vesnaEntity = EntityManager.Instance.GetUniqueEntity(); + _playerInventory = _vesnaEntity.inventory; //PopulateSlots(); SubscribeSlots(); SetSlotContent(); SetSlotSelectPosition(); - InventoryManager.Instance.playerInventory.InventoryContentsChanged += SetSlotContent; + _playerInventory.InventoryContentsChanged += SetSlotContent; } public override void _ExitTree() { - InventoryManager.Instance.playerInventory.InventoryContentsChanged -= SetSlotContent; + _playerInventory.InventoryContentsChanged -= SetSlotContent; UnsubscribeSlots(); } @@ -75,7 +79,7 @@ public partial class InventoryUi : Control private void SetSlotSelectPosition() { - _slotSelect.GlobalPosition = _headerSlots[InventoryManager.Instance.CurrentSelectedSlotIndex].GlobalPosition; + _slotSelect.GlobalPosition = _headerSlots[_vesnaEntity.CurrentSelectedSlotIndex].GlobalPosition; } private void PopulateSlots() @@ -147,17 +151,17 @@ public partial class InventoryUi : Control if (Input.IsActionJustPressed("ui_inventory_disadvance")) { - InventoryManager.Instance.CurrentSelectedSlotIndex++; - if (InventoryManager.Instance.CurrentSelectedSlotIndex > 8) - InventoryManager.Instance.CurrentSelectedSlotIndex = 0; + _vesnaEntity.CurrentSelectedSlotIndex++; + if (_vesnaEntity.CurrentSelectedSlotIndex > 8) + _vesnaEntity.CurrentSelectedSlotIndex = 0; SetSlotSelectPosition(); } if (Input.IsActionJustPressed("ui_inventory_advance")) { - InventoryManager.Instance.CurrentSelectedSlotIndex--; - if (InventoryManager.Instance.CurrentSelectedSlotIndex < 0) - InventoryManager.Instance.CurrentSelectedSlotIndex = 8; + _vesnaEntity.CurrentSelectedSlotIndex--; + if (_vesnaEntity.CurrentSelectedSlotIndex < 0) + _vesnaEntity.CurrentSelectedSlotIndex = 8; SetSlotSelectPosition(); } } diff --git a/scripts/CSharp/Common/Inventory/ItemOnGround2D.cs b/scripts/CSharp/Common/Inventory/ItemOnGround2D.cs index c13f4e8..5cf0225 100644 --- a/scripts/CSharp/Common/Inventory/ItemOnGround2D.cs +++ b/scripts/CSharp/Common/Inventory/ItemOnGround2D.cs @@ -1,4 +1,6 @@ using Babushka.scripts.CSharp.Common.Savegame; +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; using Godot; using Godot.Collections; @@ -44,7 +46,7 @@ public partial class ItemOnGround2D : Node, ISaveable if (!IsActive) return; - var result = InventoryManager.Instance.CollectItem(itemInstance.Clone()); + var result = EntityManager.Instance.GetUniqueEntity().inventory.AddItem(itemInstance.Clone()); EmitSignal(SignalName.SuccessfulPickUp); if (result == InventoryActionResult.Success) { @@ -111,51 +113,54 @@ public partial class ItemOnGround2D : Node, ISaveable public void LoadFromSaveData() { - if (!_saveToDisk) - return; - - if (_infiniteSupply) - return; - - // standard check: how many times has this item been collected? - string id = GetMeta("SaveID").AsString(); - - Dictionary save = SavegameService.GetSaveData(id); - if (save.Count > 0) - { - if(save.TryGetValue("pickupCounter", out Variant countVar)) - { - int count = countVar.AsInt32(); - for (int i = 0; i < count; i++) - { - Pickup(); - } - } - } + // WON'T FIX - WILL BE REDONE ANYWAY + + //if (!_saveToDisk) + // return; + // + //if (_infiniteSupply) + // return; + // + //// standard check: how many times has this item been collected? + //string id = GetMeta("SaveID").AsString(); + // + //Dictionary save = SavegameService.GetSaveData(id); + //if (save.Count > 0) + //{ + // if(save.TryGetValue("pickupCounter", out Variant countVar)) + // { + // int count = countVar.AsInt32(); + // for (int i = 0; i < count; i++) + // { + // Pickup(); + // } + // } + //} + // //separate check for unique items: If already in inventory, delete this instance. - ItemResource itemResource = itemInstance.blueprint; - Dictionary savegameData = SavegameService.GetSaveData(InventoryInstance.ID); - if (savegameData.Count > 0) - { - foreach (var kvp in savegameData) - { - // if it's a unique item, then it can only exist once in the world (either as a pickup OR in the inventory) - if (itemInstance.blueprint.isUnique) - { - //comparing resource path to identify the item - string[] valuePair = kvp.Value.AsStringArray(); - if (valuePair[0] == itemResource.ResourcePath) - { - int amountInInventory = int.Parse(valuePair[1]); - // comparing amount to see if it's all in the inventory now. - if (amountInInventory > 0) - { - Pickup(); - } - } - } - } - } + //ItemResource itemResource = itemInstance.blueprint; + //Dictionary savegameData = SavegameService.GetSaveData(InventoryInstance.ID); + //if (savegameData.Count > 0) + //{ + // foreach (var kvp in savegameData) + // { + // // if it's a unique item, then it can only exist once in the world (either as a pickup OR in the inventory) + // if (itemInstance.blueprint.isUnique) + // { + // //comparing resource path to identify the item + // string[] valuePair = kvp.Value.AsStringArray(); + // if (valuePair[0] == itemResource.ResourcePath) + // { + // int amountInInventory = int.Parse(valuePair[1]); + // // comparing amount to see if it's all in the inventory now. + // if (amountInInventory > 0) + // { + // Pickup(); + // } + // } + // } + // } + //} } } diff --git a/scripts/CSharp/Common/Items/InventoryDependentInteractable.cs b/scripts/CSharp/Common/Items/InventoryDependentInteractable.cs index 84de2d5..d8247b3 100644 --- a/scripts/CSharp/Common/Items/InventoryDependentInteractable.cs +++ b/scripts/CSharp/Common/Items/InventoryDependentInteractable.cs @@ -1,5 +1,7 @@ using Babushka.scripts.CSharp.Common.CharacterControls; using Babushka.scripts.CSharp.Common.Inventory; +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; using Godot; using Godot.Collections; @@ -10,21 +12,21 @@ public partial class InventoryDependentInteractable : Node2D [Export] private InteractionArea2D _interactionArea; [Export] private Array _itemsToReactTo; [Export] private bool _activateOnItem = true; - - private InventoryManager _inventoryManager; - private InventoryInstance _inventoryInstance; + + private VesnaEntity _vesnaEntity; + private InventoryInstance _playerInventory; public override void _Ready() { - _inventoryManager = InventoryManager.Instance; - _inventoryInstance = _inventoryManager.playerInventory; - _inventoryManager.SlotIndexChanged += HandleInventorySelectedSlotIndexChanged; + _vesnaEntity = EntityManager.Instance.GetUniqueEntity(); + _playerInventory = _vesnaEntity.inventory; + _vesnaEntity.SlotIndexChanged += HandleInventorySelectedSlotIndexChanged; } private void HandleInventorySelectedSlotIndexChanged(int newIndex) { - int currentSlotIndex = InventoryManager.Instance.CurrentSelectedSlotIndex; - ItemInstance? item = InventoryManager.Instance.playerInventory.Slots[currentSlotIndex].itemInstance; + int currentSlotIndex = _vesnaEntity.CurrentSelectedSlotIndex; + ItemInstance? item = _playerInventory.Slots[currentSlotIndex].itemInstance; if (item != null) { diff --git a/scripts/CSharp/Common/QuestBehaviour/DetectInventoryContains.cs b/scripts/CSharp/Common/QuestBehaviour/DetectInventoryContains.cs index a5a5f8b..3c30628 100644 --- a/scripts/CSharp/Common/QuestBehaviour/DetectInventoryContains.cs +++ b/scripts/CSharp/Common/QuestBehaviour/DetectInventoryContains.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Linq; using Babushka.scripts.CSharp.Common.Inventory; using Babushka.scripts.CSharp.Common.Quest; +using Babushka.scripts.CSharp.GameEntity.Entities; +using Babushka.scripts.CSharp.GameEntity.Management; public partial class DetectInventoryContains : QuestFulfillmentBase { @@ -12,7 +14,7 @@ public partial class DetectInventoryContains : QuestFulfillmentBase public override void _Ready() { QuestManager.Instance!.QuestsChanged += CheckInventory; - InventoryManager.Instance.playerInventory.InventoryContentsChanged += CheckInventory; + EntityManager.Instance.GetUniqueEntity().inventory.InventoryContentsChanged += CheckInventory; CheckInventory(); } @@ -20,12 +22,12 @@ public partial class DetectInventoryContains : QuestFulfillmentBase public override void _ExitTree() { QuestManager.Instance!.QuestsChanged -= CheckInventory; - InventoryManager.Instance.playerInventory.InventoryContentsChanged -= CheckInventory; + EntityManager.Instance.GetUniqueEntity().inventory.InventoryContentsChanged -= CheckInventory; } private void CheckInventory() { - if (IsQuestActive() && InventoryManager.Instance.playerInventory.HasItems(_itemsToContain)) + if (IsQuestActive() && EntityManager.Instance.GetUniqueEntity().inventory.HasItems(_itemsToContain)) { Fulfill(); } diff --git a/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs b/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs index 9a5aa5a..0772287 100644 --- a/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs +++ b/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs @@ -1,4 +1,6 @@ -using Babushka.scripts.CSharp.Common.Farming; +using System; +using Babushka.scripts.CSharp.Common.Farming; +using Babushka.scripts.CSharp.Common.Inventory; using Babushka.scripts.CSharp.GameEntity.Management; using Godot; @@ -8,7 +10,23 @@ public class VesnaEntity : PositionalEntity { public override string EntityType => OWN_TYPE_NAME; public const string OWN_TYPE_NAME = "VesnaEntity"; + public readonly InventoryInstance inventory = new (37); + + public event Action? SlotIndexChanged; + private int _currentSelectedSlotIndex; + public int CurrentSelectedSlotIndex + { + get => _currentSelectedSlotIndex; + set + { + if (value >= 0 && value <= 8) + { + _currentSelectedSlotIndex = value; + SlotIndexChanged?.Invoke(_currentSelectedSlotIndex); + } + } + } public override void InstantiateEntityNode(Node2D parent) { var node = (VesnaBehaviour2D) EntityManager.Instance.NodeCreator.InstantiateNode(OWN_TYPE_NAME); -- 2.36.3 From c7142111ed36706b974cbb71e1197d8016d3af0e Mon Sep 17 00:00:00 2001 From: jonathan Date: Wed, 4 Feb 2026 22:01:26 +0100 Subject: [PATCH 7/8] Made Player inventory saveable --- .../Common/Inventory/InventoryInstance.cs | 31 +++++++++++++++++-- .../CSharp/Common/Inventory/InventorySlot.cs | 27 +++++++++++++++- .../CSharp/Common/Inventory/ItemInstance.cs | 2 +- .../CSharp/GameEntity/Entities/VesnaEntity.cs | 15 +++++++++ 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/scripts/CSharp/Common/Inventory/InventoryInstance.cs b/scripts/CSharp/Common/Inventory/InventoryInstance.cs index a548af1..b0014b8 100644 --- a/scripts/CSharp/Common/Inventory/InventoryInstance.cs +++ b/scripts/CSharp/Common/Inventory/InventoryInstance.cs @@ -4,10 +4,12 @@ using Godot; using System.Collections.Generic; using System.Linq; using Babushka.scripts.CSharp.Common.Savegame; +using Babushka.scripts.CSharp.GameEntity.LoadSave; +using Newtonsoft.Json.Linq; namespace Babushka.scripts.CSharp.Common.Inventory; -public partial class InventoryInstance +public partial class InventoryInstance : IJsonSerializable { private readonly List _slots; public IReadOnlyList Slots => _slots; @@ -138,7 +140,7 @@ public partial class InventoryInstance if (hasItemsCount < items.amount) return InventoryActionResult.SourceDoesNotExist; - var amountToRemove = items.amount; + var amountToRemove = items.amount; foreach (var s in _slots) { if (s.IsEmpty() || s.itemInstance!.blueprint != items.blueprint) @@ -159,7 +161,7 @@ public partial class InventoryInstance if (amountToRemove == 0) break; } - + InventoryContentsChanged?.Invoke(); return InventoryActionResult.Success; } @@ -193,4 +195,27 @@ public partial class InventoryInstance { return items.All(HasItems); } + + public void LoadFromJson(JObject json) + { + var itemsArray = (JArray?)json["items"]; + if (itemsArray == null) return; + + foreach (var (itemToken, slot) in itemsArray.Zip(_slots)) + { + var itemObj = (JObject?)itemToken; + if (itemObj == null) continue; + slot.LoadFromJson(itemObj); + } + + InventoryContentsChanged?.Invoke(); + } + + public JObject SaveToJson() + { + return new JObject + { + ["items"] = new JArray(_slots.Select(s => s.SaveToJson())) + }; + } } \ No newline at end of file diff --git a/scripts/CSharp/Common/Inventory/InventorySlot.cs b/scripts/CSharp/Common/Inventory/InventorySlot.cs index fec8f36..90e6537 100644 --- a/scripts/CSharp/Common/Inventory/InventorySlot.cs +++ b/scripts/CSharp/Common/Inventory/InventorySlot.cs @@ -1,11 +1,14 @@ #nullable enable +using Babushka.scripts.CSharp.GameEntity.LoadSave; +using Newtonsoft.Json.Linq; + namespace Babushka.scripts.CSharp.Common.Inventory; /// /// Represents a virtual object wrapper for an item instance. /// Can return the containing item or null. /// -public class InventorySlot +public class InventorySlot: IJsonSerializable { /// /// The inventory item instance that may or may not be bound to this slot. @@ -20,5 +23,27 @@ public class InventorySlot { return itemInstance == null; } + + public void LoadFromJson(JObject json) + { + var itemJson = json.Value("item"); + if (itemJson != null) + { + itemInstance = new ItemInstance(); + itemInstance.LoadFromJson(itemJson); + } + else + { + itemInstance = null; + } + } + + public JObject SaveToJson() + { + return new JObject() + { + ["item"] = itemInstance?.SaveToJson() + }; + } } diff --git a/scripts/CSharp/Common/Inventory/ItemInstance.cs b/scripts/CSharp/Common/Inventory/ItemInstance.cs index 6dd2ff7..b83d597 100644 --- a/scripts/CSharp/Common/Inventory/ItemInstance.cs +++ b/scripts/CSharp/Common/Inventory/ItemInstance.cs @@ -9,7 +9,7 @@ namespace Babushka.scripts.CSharp.Common.Inventory; [GlobalClass] public partial class ItemInstance : Resource, IJsonSerializable { - [Export] public required ItemResource blueprint; + [Export] public ItemResource blueprint; [Export] public int amount = 1; public ItemInstance Clone() diff --git a/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs b/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs index 0772287..1f219e5 100644 --- a/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs +++ b/scripts/CSharp/GameEntity/Entities/VesnaEntity.cs @@ -3,6 +3,7 @@ using Babushka.scripts.CSharp.Common.Farming; using Babushka.scripts.CSharp.Common.Inventory; using Babushka.scripts.CSharp.GameEntity.Management; using Godot; +using Newtonsoft.Json.Linq; namespace Babushka.scripts.CSharp.GameEntity.Entities; @@ -33,4 +34,18 @@ public class VesnaEntity : PositionalEntity node.player2d.Initialize(this); parent.AddChild(node); } + + public override void SaveEntity(JObject json) + { + base.SaveEntity(json); + json["slot"] = CurrentSelectedSlotIndex; + json["inventory"] = inventory.SaveToJson(); + } + + public override void LoadEntity(JObject json) + { + base.LoadEntity(json); + CurrentSelectedSlotIndex = json.Value("slot"); + inventory.LoadFromJson(json.Value("inventory")!); + } } \ No newline at end of file -- 2.36.3 From 7ab513f01ce1bdcc1612a5edec39aa7dad2cf813 Mon Sep 17 00:00:00 2001 From: jonathan Date: Wed, 4 Feb 2026 22:17:45 +0100 Subject: [PATCH 8/8] Made that vesna can move to the beets scene --- scenes/entity_scenes/outside_beets.tscn | 38 ++++++++++--------- .../EntityPlacer/VesnaEntityPlacer.cs | 5 +-- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/scenes/entity_scenes/outside_beets.tscn b/scenes/entity_scenes/outside_beets.tscn index 54d9534..9737842 100644 --- a/scenes/entity_scenes/outside_beets.tscn +++ b/scenes/entity_scenes/outside_beets.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=99 format=3 uid="uid://by0tsbnlflt32"] +[gd_scene load_steps=100 format=3 uid="uid://by0tsbnlflt32"] [ext_resource type="Script" uid="uid://cssdu8viimwm6" path="res://scripts/CSharp/Common/SceneTransition.cs" id="1_amrci"] [ext_resource type="Script" uid="uid://bqomwxclsbhd3" path="res://scripts/CSharp/Common/Camera/CameraController.cs" id="2_muqao"] @@ -26,7 +26,6 @@ [ext_resource type="Shader" uid="uid://xnky830dtfsn" path="res://shader/repeat_texture.gdshader" id="24_it0dm"] [ext_resource type="Texture2D" uid="uid://btea6eyucsyxj" path="res://art/farm/farming/farmobjekte/zaun/tilable fence middle part.png" id="25_o2tj7"] [ext_resource type="Texture2D" uid="uid://3ed3dgq3irn2" path="res://art/farm/farming/farmobjekte/zaun/tilable fence end part2.png" id="26_3huw1"] -[ext_resource type="PackedScene" uid="uid://c25udixd5m6l0" path="res://prefabs/characters/Vesna.tscn" id="27_prtwx"] [ext_resource type="Resource" uid="uid://dlcmqfjvgphqu" path="res://resources/items/rake.tres" id="28_ed312"] [ext_resource type="Texture2D" uid="uid://dg7rlugnq0t45" path="res://art/farm/farming/farmobjekte/brünnen.png" id="29_bsi8d"] [ext_resource type="PackedScene" uid="uid://cqc72e4hq6bcd" path="res://prefabs/interactions/interaction_area_2d.tscn" id="30_tdbxb"] @@ -43,8 +42,10 @@ [ext_resource type="Texture2D" uid="uid://blb3agipyxnal" path="res://art/farm/farming/farmobjekte/zaun/fence_door.png" id="41_6ulg3"] [ext_resource type="PackedScene" uid="uid://dpbbroif2tnil" path="res://prefabs/interactions/generic_item_on_ground_2d.tscn" id="42_yddng"] [ext_resource type="Texture2D" uid="uid://dmo21h14toxfu" path="res://art/indoor/indoor outdoor/domovoi.png" id="43_j7hi4"] +[ext_resource type="PackedScene" uid="uid://cv7trh2b3dyiv" path="res://prefabs/entity_placer/VesnaPlacer.tscn" id="44_sqbr3"] [ext_resource type="Resource" uid="uid://cndd64batns31" path="res://resources/items/wateringcan.tres" id="44_v53u5"] [ext_resource type="PackedScene" uid="uid://cgjc4wurbgimy" path="res://prefabs/UI/Inventory/Inventory.tscn" id="45_4k41w"] +[ext_resource type="Script" uid="uid://ca1pg6k3gn47y" path="res://scripts/CSharp/GameEntity/Management/EntitySceneContainer.cs" id="45_54vw7"] [ext_resource type="AudioStream" uid="uid://dku1rq5cocisg" path="res://audio/Music/Farming_90BPM_69Bars.wav" id="46_kqri4"] [ext_resource type="Script" uid="uid://clxb3n668oud3" path="res://scripts/CSharp/Common/Audio/AudioDebugger.cs" id="47_1nlk0"] [ext_resource type="AudioStream" uid="uid://cfqg50am0swb7" path="res://audio/Music/Farming_90BPM_69Bars_Loop.wav" id="48_uesai"] @@ -253,7 +254,7 @@ stream_2/stream = ExtResource("56_vedvh") script = ExtResource("1_amrci") _sceneNamesToLoad = PackedStringArray("res://scenes/entity_scenes/farm_outside.tscn") -[node name="Camera2D" type="Camera2D" parent="." node_paths=PackedStringArray("_followNode")] +[node name="Camera2D" type="Camera2D" parent="."] position = Vector2(3180, 1961) scale = Vector2(1, 0.993819) offset = Vector2(0, -500) @@ -264,7 +265,6 @@ limit_right = 11000 limit_bottom = 6000 editor_draw_limits = true script = ExtResource("2_muqao") -_followNode = NodePath("../YSorted/Vesna/CharacterBody2D") [node name="ParallaxBackground" type="ParallaxBackground" parent="."] @@ -964,17 +964,6 @@ shape = SubResource("RectangleShape2D_0qu0h") z_index = 1 y_sort_enabled = true -[node name="Vesna" parent="YSorted" instance=ExtResource("27_prtwx")] -z_index = 1 -position = Vector2(2693, 1876) -_hoe = ExtResource("28_ed312") - -[node name="Animated Sprites" parent="YSorted/Vesna/CharacterBody2D/visuals" index="0"] -position = Vector2(-33, 554) - -[node name="FarmingControls" parent="YSorted/Vesna" index="1" node_paths=PackedStringArray("_camera")] -_camera = NodePath("../../../Camera2D") - [node name="Brünnen" type="Sprite2D" parent="YSorted"] z_index = 1 y_sort_enabled = true @@ -2070,6 +2059,13 @@ _blueprint = ExtResource("44_v53u5") [node name="CollisionShape3D" parent="YSorted/WateringCan/PickupInteractionArea/Area2D" index="0"] shape = SubResource("CircleShape2D_34r5t") +[node name="VesnaPlacer" parent="YSorted" instance=ExtResource("44_sqbr3")] +position = Vector2(3708, 2279) + +[node name="EntitySceneContainer" type="Node2D" parent="YSorted"] +script = ExtResource("45_54vw7") +sceneName = "outside_beets" + [node name="CanvasLayer" parent="." instance=ExtResource("45_4k41w")] [node name="Inventory" parent="CanvasLayer" index="1"] @@ -2145,32 +2141,38 @@ script = ExtResource("59_d24ik") [node name="SaveIDProvider" type="Node" parent="SaveSystem"] script = ExtResource("60_yr8eo") -[connection signal="FilledWateringCan" from="YSorted/Vesna" to="Audio/SFX/FillWater SFX2" method="PlayOneShot"] -[connection signal="InteractedTool" from="YSorted/Brünnen/InteractionArea" to="YSorted/Vesna" method="TryFillWateringCan"] [connection signal="InteractedTool" from="YSorted/Blocker/BackToFarm" to="." method="LoadSceneAtIndex"] [connection signal="finished" from="Audio/Background Music Ramp up" to="Audio/Background Music loop" method="PlayFromOffset"] [connection signal="tree_entered" from="SceneNameSetter" to="SceneNameSetter" method="Set"] -[editable path="YSorted/Vesna"] [editable path="YSorted/Brünnen/InteractionArea"] [editable path="YSorted/Farm visuals/FieldParent/BaseField"] [editable path="YSorted/Farm visuals/FieldParent/BaseField/FieldActivator/InteractionArea"] +[editable path="YSorted/Farm visuals/FieldParent/BaseField/SaveSystem"] [editable path="YSorted/Farm visuals/FieldParent/BaseField2"] [editable path="YSorted/Farm visuals/FieldParent/BaseField2/FieldActivator/InteractionArea"] +[editable path="YSorted/Farm visuals/FieldParent/BaseField2/SaveSystem"] [editable path="YSorted/Farm visuals/FieldParent/BaseField3"] [editable path="YSorted/Farm visuals/FieldParent/BaseField3/FieldActivator/InteractionArea"] +[editable path="YSorted/Farm visuals/FieldParent/BaseField3/SaveSystem"] [editable path="YSorted/Farm visuals/FieldParent/BaseField4"] [editable path="YSorted/Farm visuals/FieldParent/BaseField4/FieldActivator/InteractionArea"] +[editable path="YSorted/Farm visuals/FieldParent/BaseField4/SaveSystem"] [editable path="YSorted/Farm visuals/FieldParent/BaseField5"] [editable path="YSorted/Farm visuals/FieldParent/BaseField5/FieldActivator/InteractionArea"] +[editable path="YSorted/Farm visuals/FieldParent/BaseField5/SaveSystem"] [editable path="YSorted/Farm visuals/FieldParent/BaseField6"] [editable path="YSorted/Farm visuals/FieldParent/BaseField6/FieldActivator/InteractionArea"] +[editable path="YSorted/Farm visuals/FieldParent/BaseField6/SaveSystem"] [editable path="YSorted/Farm visuals/FieldParent/BaseField7"] [editable path="YSorted/Farm visuals/FieldParent/BaseField7/FieldActivator/InteractionArea"] +[editable path="YSorted/Farm visuals/FieldParent/BaseField7/SaveSystem"] [editable path="YSorted/Farm visuals/FieldParent/BaseField8"] [editable path="YSorted/Farm visuals/FieldParent/BaseField8/FieldActivator/InteractionArea"] +[editable path="YSorted/Farm visuals/FieldParent/BaseField8/SaveSystem"] [editable path="YSorted/Farm visuals/FieldParent/BaseField9"] [editable path="YSorted/Farm visuals/FieldParent/BaseField9/FieldActivator/InteractionArea"] +[editable path="YSorted/Farm visuals/FieldParent/BaseField9/SaveSystem"] [editable path="YSorted/Blocker/BackToFarm"] [editable path="YSorted/RakeGenericPickup"] [editable path="YSorted/RakeGenericPickup/PickupInteractionArea"] diff --git a/scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs b/scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs index 495e143..5f3acdf 100644 --- a/scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs +++ b/scripts/CSharp/GameEntity/EntityPlacer/VesnaEntityPlacer.cs @@ -9,11 +9,10 @@ public partial class VesnaEntityPlacer : Node2D public override void _Ready() { var sceneName = EntityManager.Instance.CurrentEntitySceneContainer!.sceneName; - var loadedScenesEntity = EntityManager.Instance.GetUniqueEntity(); + var entity = EntityManager.Instance.GetUniqueEntity(); - if (!loadedScenesEntity.WasSceneLoaded(sceneName)) + if (entity.sceneName != sceneName) { - var entity = EntityManager.Instance.GetUniqueEntity(); entity.position = GlobalPosition; entity.sceneName = sceneName; } -- 2.36.3