From 8d52b49e572b3a4d1d7dd187fba354e96d293387 Mon Sep 17 00:00:00 2001 From: MaddoScientisto Date: Sun, 1 Mar 2026 20:59:11 +0100 Subject: [PATCH] Autopickup for player --- 3D/Scenes/Props/Box_3D_Red.tscn | 12 +- Scenes/Actors/IsoPlayer_FSM.tscn | 19 ++- Scenes/HUD/HUD.tscn | 112 ++++++------- .../FSM/3DPlayer/AutoPickupModule3D.cs | 152 ++++++++++++++++++ .../FSM/3DPlayer/AutoPickupModule3D.cs.uid | 1 + Scripts/Interactables/ItemPickup3D.cs | 8 +- 6 files changed, 242 insertions(+), 62 deletions(-) create mode 100644 Scripts/Components/FSM/3DPlayer/AutoPickupModule3D.cs create mode 100644 Scripts/Components/FSM/3DPlayer/AutoPickupModule3D.cs.uid diff --git a/3D/Scenes/Props/Box_3D_Red.tscn b/3D/Scenes/Props/Box_3D_Red.tscn index dbfbedbe..bb64c042 100644 --- a/3D/Scenes/Props/Box_3D_Red.tscn +++ b/3D/Scenes/Props/Box_3D_Red.tscn @@ -17,8 +17,14 @@ metadata/_custom_type_script = "uid://ddsqqfx1usc3j" [sub_resource type="Resource" id="Resource_fkd2x"] script = ExtResource("4_hlryi") Item = ExtResource("5_r3p83") -Chance = 100.0 -Count = 4 +Chance = 70.0 +metadata/_custom_type_script = "uid://cq65aed620ijo" + +[sub_resource type="Resource" id="Resource_hlryi"] +script = ExtResource("4_hlryi") +Item = ExtResource("5_r3p83") +Chance = 40.0 +Count = 2 metadata/_custom_type_script = "uid://cq65aed620ijo" [sub_resource type="BoxShape3D" id="BoxShape3D_hsg1w"] @@ -34,7 +40,7 @@ script = ExtResource("1_kvqx7") Health = 8.0 ExplosionData = ExtResource("2_jolck") DamageResistances = Array[ExtResource("3_7px86")]([SubResource("Resource_7px86")]) -LootDrops = Array[ExtResource("4_hlryi")]([SubResource("Resource_fkd2x")]) +LootDrops = Array[ExtResource("4_hlryi")]([SubResource("Resource_fkd2x"), SubResource("Resource_hlryi")]) [node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=169677373] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00549316, 0.0253752, -0.000488281) diff --git a/Scenes/Actors/IsoPlayer_FSM.tscn b/Scenes/Actors/IsoPlayer_FSM.tscn index 48820909..4f81944b 100644 --- a/Scenes/Actors/IsoPlayer_FSM.tscn +++ b/Scenes/Actors/IsoPlayer_FSM.tscn @@ -28,6 +28,8 @@ [ext_resource type="PackedScene" uid="uid://cfgc6ik8vb08c" path="res://Scenes/Weapons/BaseWeapon_3D.tscn" id="17_olwak"] [ext_resource type="Script" uid="uid://cqyr8mko8oo5" path="res://Scripts/Components/FSM/3DPlayer/PlayerAcidDeathModule.cs" id="19_7selo"] [ext_resource type="PackedScene" uid="uid://cwnyegefc8o6q" path="res://Scenes/HUD/WorldSelector3D.tscn" id="24_j6bpw"] +[ext_resource type="Script" uid="uid://s4xt80pu6lgl" path="res://Scripts/Components/FSM/3DPlayer/AutoPickupModule3D.cs" id="25_j6bpw"] +[ext_resource type="AudioStream" uid="uid://b3rm0vj6x54k4" path="res://SFX/th_knockoff_sfx/click_collect.wav" id="26_10kkd"] [ext_resource type="Script" uid="uid://hdw15b6fi7de" path="res://Scripts/Components/Actors/3D/PlayerDamageReceiver3D.cs" id="26_ok6gd"] [ext_resource type="Script" uid="uid://ddsqqfx1usc3j" path="res://Scripts/Resources/DamageResistance.cs" id="27_5v3dv"] [ext_resource type="Script" uid="uid://cqwvssstkrdmw" path="res://Scripts/Components/Actors/ActorResourceProvider.cs" id="28_b3jpo"] @@ -51,6 +53,8 @@ height = 0.679688 height = 1.18042 radius = 1.20117 +[sub_resource type="SphereShape3D" id="SphereShape3D_10kkd"] + [sub_resource type="SphereShape3D" id="SphereShape3D_ok250"] [sub_resource type="Resource" id="Resource_c4ide"] @@ -224,7 +228,7 @@ script = ExtResource("3_cc7e7") _inputProvider = NodePath("../../InputProvider") AnimationProvider = NodePath("../../AnimationProvider") DamageReceiver = NodePath("../../DamageReceiver") -_moduleNodes = [NodePath("../../InputProvider"), NodePath("../../MovementModule"), null, NodePath("../../InteractionController"), NodePath("../../ActivationProvider"), NodePath("../../WeaponModule"), NodePath("../../CrosshairModule"), NodePath("../../GrazingModule")] +_moduleNodes = [NodePath("../../InputProvider"), NodePath("../../MovementModule"), null, NodePath("../../InteractionController"), NodePath("../../ActivationProvider"), NodePath("../../WeaponModule"), NodePath("../../CrosshairModule"), NodePath("../../GrazingModule"), NodePath("../../AutoPickupModule")] [node name="Dead" type="Node" parent="StateMachine" unique_id=316659315] script = ExtResource("5_ok250") @@ -253,7 +257,7 @@ material_override = ExtResource("7_yarib") pixel_size = 0.05 texture_filter = 0 sprite_frames = ExtResource("12_j6bpw") -animation = &"walk_up" +animation = &"Drowning" script = ExtResource("9_yarib") [node name="Legs" type="AnimatedSprite3D" parent="AnimationProvider" unique_id=995566769] @@ -329,6 +333,17 @@ script = ExtResource("11_4cdxq") stream = ExtResource("13_2ffwi") bus = &"Effects" +[node name="AutoPickupModule" type="Area3D" parent="." unique_id=1006870778] +collision_layer = 0 +collision_mask = 32 +script = ExtResource("25_j6bpw") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="AutoPickupModule" unique_id=543949155] +shape = SubResource("SphereShape3D_10kkd") + +[node name="PickupSound" type="AudioStreamPlayer3D" parent="AutoPickupModule" unique_id=1774707395] +stream = ExtResource("26_10kkd") + [node name="AudioListener3D" type="AudioListener3D" parent="." unique_id=1967851684] current = true diff --git a/Scenes/HUD/HUD.tscn b/Scenes/HUD/HUD.tscn index 5dd69e6e..5ea4e09b 100644 --- a/Scenes/HUD/HUD.tscn +++ b/Scenes/HUD/HUD.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=41 format=3 uid="uid://dkwi1hu1bixoe"] +[gd_scene format=3 uid="uid://dkwi1hu1bixoe"] [ext_resource type="Script" uid="uid://baf6pxbvhqmjk" path="res://Scripts/Hud.cs" id="1_m0hb0"] [ext_resource type="PackedScene" uid="uid://dsaj5dx82brsg" path="res://Scenes/HUD/UiSelector.tscn" id="2_jidad"] @@ -97,7 +97,7 @@ shader_parameter/x_curve = 10.0 shader_parameter/y_curve = 10.0 shader_parameter/aberration_strength = 0.6140002666650002 -[node name="HUD" type="CanvasLayer" node_paths=PackedStringArray("_healthLabel", "_healthBar", "_shieldLabel", "_shieldBar", "_motivationLabel", "_itemsContainer", "_gameOverPanel", "_fairyTerminatedPanel", "_hudInfoPanel", "NotificationsContainer", "WeaponContainer", "PauseMenuContainer", "DebugMenuHolder")] +[node name="HUD" type="CanvasLayer" unique_id=71145519 node_paths=PackedStringArray("_healthLabel", "_healthBar", "_shieldLabel", "_shieldBar", "_motivationLabel", "_itemsContainer", "_gameOverPanel", "_fairyTerminatedPanel", "_hudInfoPanel", "NotificationsContainer", "WeaponContainer", "PauseMenuContainer", "DebugMenuHolder")] process_mode = 3 script = ExtResource("1_m0hb0") SelectorScene = ExtResource("2_jidad") @@ -120,82 +120,82 @@ PauseMenuScene = ExtResource("3_hxmxt") DebugMenuTemplate = ExtResource("4_gd1k6") DebugMenuHolder = NodePath("DebugContainer") -[node name="FairyTerminated" type="PanelContainer" parent="."] +[node name="FairyTerminated" type="PanelContainer" parent="." unique_id=1026530899] visible = false offset_left = -3.0 offset_top = 34.0 -offset_right = 323.0 -offset_bottom = 88.0 +offset_right = 387.0 +offset_bottom = 106.0 -[node name="VBoxContainer2" type="VBoxContainer" parent="FairyTerminated"] +[node name="VBoxContainer2" type="VBoxContainer" parent="FairyTerminated" unique_id=1249429394] layout_mode = 2 size_flags_vertical = 4 theme_override_constants/separation = -4 -[node name="GameOver" type="Label" parent="FairyTerminated/VBoxContainer2"] +[node name="GameOver" type="Label" parent="FairyTerminated/VBoxContainer2" unique_id=547746558] visible = false layout_mode = 2 text = "FAIRY: TERMINATED" label_settings = SubResource("LabelSettings_a7f6n") horizontal_alignment = 1 -[node name="TextureRect" type="TextureRect" parent="FairyTerminated/VBoxContainer2"] +[node name="TextureRect" type="TextureRect" parent="FairyTerminated/VBoxContainer2" unique_id=989090588] layout_mode = 2 size_flags_horizontal = 4 texture = ExtResource("8_3523e") stretch_mode = 2 -[node name="Label" type="Label" parent="FairyTerminated/VBoxContainer2"] +[node name="Label" type="Label" parent="FairyTerminated/VBoxContainer2" unique_id=1144362125] visible = false layout_mode = 2 text = "Press Shoot button to reform" label_settings = SubResource("LabelSettings_5na8k") horizontal_alignment = 1 -[node name="GameOver" type="PanelContainer" parent="."] +[node name="GameOver" type="PanelContainer" parent="." unique_id=1424509047] visible = false offset_left = -3.0 offset_top = 34.0 offset_right = 323.0 offset_bottom = 88.0 -[node name="VBoxContainer2" type="VBoxContainer" parent="GameOver"] +[node name="VBoxContainer2" type="VBoxContainer" parent="GameOver" unique_id=1979473657] layout_mode = 2 size_flags_vertical = 4 theme_override_constants/separation = -4 -[node name="GameOver" type="Label" parent="GameOver/VBoxContainer2"] +[node name="GameOver" type="Label" parent="GameOver/VBoxContainer2" unique_id=1203229580] visible = false layout_mode = 2 text = "FAIRY: TERMINATED" label_settings = SubResource("LabelSettings_a7f6n") horizontal_alignment = 1 -[node name="TextureRect" type="TextureRect" parent="GameOver/VBoxContainer2"] +[node name="TextureRect" type="TextureRect" parent="GameOver/VBoxContainer2" unique_id=2045152992] layout_mode = 2 size_flags_horizontal = 4 texture = ExtResource("10_s015s") stretch_mode = 2 -[node name="Label" type="Label" parent="GameOver/VBoxContainer2"] +[node name="Label" type="Label" parent="GameOver/VBoxContainer2" unique_id=290816364] visible = false layout_mode = 2 text = "Press Shoot button to reform" label_settings = SubResource("LabelSettings_5na8k") horizontal_alignment = 1 -[node name="MessageTimer" type="Timer" parent="."] +[node name="MessageTimer" type="Timer" parent="." unique_id=308504005] wait_time = 2.0 one_shot = true -[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."] +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=465828645] visible = false position = Vector2(67, 47) sprite_frames = SubResource("SpriteFrames_78fwv") frame = 1 frame_progress = 0.8514 -[node name="HudInfo" type="VBoxContainer" parent="."] +[node name="HudInfo" type="VBoxContainer" parent="." unique_id=1663735786] anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 @@ -209,10 +209,10 @@ size_flags_horizontal = 3 size_flags_vertical = 3 theme_override_constants/separation = 0 -[node name="HealthBarContainer" type="HBoxContainer" parent="HudInfo"] +[node name="HealthBarContainer" type="HBoxContainer" parent="HudInfo" unique_id=1485920073] layout_mode = 2 -[node name="HealthBar" type="ProgressBar" parent="HudInfo/HealthBarContainer"] +[node name="HealthBar" type="ProgressBar" parent="HudInfo/HealthBarContainer" unique_id=937426877] custom_minimum_size = Vector2(34, 8) layout_mode = 2 size_flags_vertical = 4 @@ -222,16 +222,16 @@ value = 50.0 rounded = true show_percentage = false -[node name="HealthLabel" type="Label" parent="HudInfo/HealthBarContainer"] +[node name="HealthLabel" type="Label" parent="HudInfo/HealthBarContainer" unique_id=768460674] layout_mode = 2 text = "100/100" label_settings = ExtResource("2_x7kl7") vertical_alignment = 1 -[node name="ShieldBarContainer" type="HBoxContainer" parent="HudInfo"] +[node name="ShieldBarContainer" type="HBoxContainer" parent="HudInfo" unique_id=1668694771] layout_mode = 2 -[node name="ShieldBar" type="ProgressBar" parent="HudInfo/ShieldBarContainer"] +[node name="ShieldBar" type="ProgressBar" parent="HudInfo/ShieldBarContainer" unique_id=1137386812] custom_minimum_size = Vector2(34, 8) layout_mode = 2 size_flags_vertical = 4 @@ -240,38 +240,38 @@ theme_override_styles/fill = SubResource("StyleBoxTexture_5cvcb") value = 50.0 show_percentage = false -[node name="ShieldLabel" type="Label" parent="HudInfo/ShieldBarContainer"] +[node name="ShieldLabel" type="Label" parent="HudInfo/ShieldBarContainer" unique_id=1805514884] layout_mode = 2 text = "100/100" label_settings = ExtResource("2_x7kl7") vertical_alignment = 1 -[node name="MotivationContainer" type="HBoxContainer" parent="HudInfo"] +[node name="MotivationContainer" type="HBoxContainer" parent="HudInfo" unique_id=327806189] layout_mode = 2 -[node name="Label" type="Label" parent="HudInfo/MotivationContainer"] +[node name="Label" type="Label" parent="HudInfo/MotivationContainer" unique_id=1088378433] layout_mode = 2 text = "Motivation:" label_settings = ExtResource("2_x7kl7") -[node name="Motivationlabel" type="Label" parent="HudInfo/MotivationContainer"] +[node name="Motivationlabel" type="Label" parent="HudInfo/MotivationContainer" unique_id=617537863] layout_mode = 2 text = "100%" label_settings = ExtResource("2_x7kl7") vertical_alignment = 1 -[node name="ItemsContainer" type="VBoxContainer" parent="HudInfo"] +[node name="ItemsContainer" type="VBoxContainer" parent="HudInfo" unique_id=29990649] layout_mode = 2 size_flags_vertical = 3 theme_override_constants/separation = 0 -[node name="NotificationsContainer" type="VBoxContainer" parent="."] +[node name="NotificationsContainer" type="VBoxContainer" parent="." unique_id=1410590531] anchors_preset = 3 anchor_left = 1.0 anchor_top = 1.0 anchor_right = 1.0 anchor_bottom = 1.0 -offset_left = -156.0 +offset_left = -113.0 offset_top = -34.0 grow_horizontal = 0 grow_vertical = 0 @@ -279,7 +279,7 @@ size_flags_vertical = 3 theme_override_constants/separation = 0 alignment = 2 -[node name="WeaponContainer" type="VBoxContainer" parent="."] +[node name="WeaponContainer" type="VBoxContainer" parent="." unique_id=613768405] anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 @@ -291,21 +291,21 @@ grow_vertical = 0 theme_override_constants/separation = 0 metadata/_edit_group_ = true -[node name="Label" type="Label" parent="WeaponContainer"] +[node name="Label" type="Label" parent="WeaponContainer" unique_id=1544331200] layout_mode = 2 text = "Weapon" label_settings = ExtResource("2_x7kl7") -[node name="WeaponContainer" type="PanelContainer" parent="WeaponContainer"] +[node name="WeaponContainer" type="PanelContainer" parent="WeaponContainer" unique_id=1330746632] layout_mode = 2 size_flags_vertical = 3 theme = ExtResource("9_sx5r0") theme_override_styles/panel = ExtResource("17_bljno") -[node name="BossHud" parent="." instance=ExtResource("5_vmict")] +[node name="BossHud" parent="." unique_id=1635516703 instance=ExtResource("5_vmict")] visible = false -[node name="DebugContainer" type="PanelContainer" parent="."] +[node name="DebugContainer" type="PanelContainer" parent="." unique_id=2004128887] visible = false anchors_preset = 15 anchor_right = 1.0 @@ -313,21 +313,21 @@ anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -[node name="PauseMenuContainer" type="PanelContainer" parent="."] +[node name="PauseMenuContainer" type="PanelContainer" parent="." unique_id=2045387146] visible = false offset_left = 106.0 offset_top = 26.0 offset_right = 226.0 offset_bottom = 144.0 -[node name="Control" type="Panel" parent="."] +[node name="Control" type="Panel" parent="." unique_id=941994087] offset_left = 30.0 offset_top = 24.0 offset_right = 354.0 offset_bottom = 198.0 theme_override_styles/panel = ExtResource("20_0ncp3") -[node name="InventoryMenu" type="TabContainer" parent="Control" node_paths=PackedStringArray("ParentContainer")] +[node name="InventoryMenu" type="TabContainer" parent="Control" unique_id=1439629064 node_paths=PackedStringArray("ParentContainer")] layout_mode = 1 anchors_preset = 8 anchor_left = 0.5 @@ -348,7 +348,7 @@ script = ExtResource("11_7pulb") ParentContainer = NodePath("..") metadata/_edit_group_ = true -[node name="Weapons" type="ItemList" parent="Control/InventoryMenu"] +[node name="Weapons" type="ItemList" parent="Control/InventoryMenu" unique_id=932926637] visible = false layout_mode = 2 theme = ExtResource("9_sx5r0") @@ -360,7 +360,7 @@ script = ExtResource("10_oflr6") ItemsFilter = Array[int]([9]) metadata/_tab_index = 0 -[node name="Consumables" type="ItemList" parent="Control/InventoryMenu"] +[node name="Consumables" type="ItemList" parent="Control/InventoryMenu" unique_id=610897193] visible = false layout_mode = 2 theme = ExtResource("9_sx5r0") @@ -372,7 +372,7 @@ script = ExtResource("10_oflr6") ItemsFilter = Array[int]([4, 5, 8, 7, 6]) metadata/_tab_index = 1 -[node name="Ammo" type="ItemList" parent="Control/InventoryMenu"] +[node name="Ammo" type="ItemList" parent="Control/InventoryMenu" unique_id=1227461482] visible = false layout_mode = 2 theme = ExtResource("9_sx5r0") @@ -384,7 +384,7 @@ script = ExtResource("10_oflr6") ItemsFilter = Array[int]([3]) metadata/_tab_index = 2 -[node name="Key" type="ItemList" parent="Control/InventoryMenu"] +[node name="Key" type="ItemList" parent="Control/InventoryMenu" unique_id=1623766474] visible = false layout_mode = 2 theme = ExtResource("9_sx5r0") @@ -396,7 +396,7 @@ script = ExtResource("10_oflr6") ItemsFilter = Array[int]([0, 1, 2, 13, 10, 11, 12]) metadata/_tab_index = 3 -[node name="Status" type="PanelContainer" parent="Control/InventoryMenu" node_paths=PackedStringArray("HealthExpansionCounter", "ShieldExpansionCounter", "WeaponButton")] +[node name="Status" type="PanelContainer" parent="Control/InventoryMenu" unique_id=266629319 node_paths=PackedStringArray("HealthExpansionCounter", "ShieldExpansionCounter", "WeaponButton")] layout_mode = 2 theme = ExtResource("9_sx5r0") theme_override_styles/panel = ExtResource("13_sjdna") @@ -408,32 +408,32 @@ ShieldExpansionCounter = NodePath("MarginContainer/HBoxContainer/VBoxContainer3/ WeaponButton = NodePath("MarginContainer/HBoxContainer/VBoxContainer2/EquippedWeapon") metadata/_tab_index = 4 -[node name="MarginContainer" type="MarginContainer" parent="Control/InventoryMenu/Status"] +[node name="MarginContainer" type="MarginContainer" parent="Control/InventoryMenu/Status" unique_id=1419887516] layout_mode = 2 theme_override_constants/margin_left = 32 theme_override_constants/margin_right = 32 -[node name="HBoxContainer" type="HBoxContainer" parent="Control/InventoryMenu/Status/MarginContainer"] +[node name="HBoxContainer" type="HBoxContainer" parent="Control/InventoryMenu/Status/MarginContainer" unique_id=260671629] layout_mode = 2 alignment = 1 -[node name="VBoxContainer2" type="VBoxContainer" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer"] +[node name="VBoxContainer2" type="VBoxContainer" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer" unique_id=1376371555] layout_mode = 2 size_flags_horizontal = 2 alignment = 1 -[node name="EquippedWeapon" type="Button" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer/VBoxContainer2"] +[node name="EquippedWeapon" type="Button" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer/VBoxContainer2" unique_id=1982020961] layout_mode = 2 text = "IC-9 " icon = ExtResource("19_h6xwv") -[node name="VBoxContainer3" type="VBoxContainer" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer"] +[node name="VBoxContainer3" type="VBoxContainer" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer" unique_id=153340910] layout_mode = 2 size_flags_horizontal = 10 alignment = 1 -[node name="Shield" type="Button" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer/VBoxContainer3"] +[node name="Shield" type="Button" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer/VBoxContainer3" unique_id=28187213] layout_mode = 2 theme_override_constants/line_spacing = -4 text = "Ice @@ -441,42 +441,42 @@ Crystal" icon = ExtResource("22_jefn6") alignment = 0 -[node name="HBoxContainer" type="HBoxContainer" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer/VBoxContainer3"] +[node name="HBoxContainer" type="HBoxContainer" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer/VBoxContainer3" unique_id=805702230] layout_mode = 2 -[node name="HealthExtensions" type="Button" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer/VBoxContainer3/HBoxContainer"] +[node name="HealthExtensions" type="Button" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer/VBoxContainer3/HBoxContainer" unique_id=1491820858] layout_mode = 2 text = "x2" icon = ExtResource("19_j6myr") alignment = 0 -[node name="ShieldExtensions" type="Button" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer/VBoxContainer3/HBoxContainer"] +[node name="ShieldExtensions" type="Button" parent="Control/InventoryMenu/Status/MarginContainer/HBoxContainer/VBoxContainer3/HBoxContainer" unique_id=622876464] layout_mode = 2 text = "x1" icon = ExtResource("22_5cvcb") alignment = 0 -[node name="VBoxContainer" type="VBoxContainer" parent="Control/InventoryMenu/Status"] +[node name="VBoxContainer" type="VBoxContainer" parent="Control/InventoryMenu/Status" unique_id=936621407] custom_minimum_size = Vector2(96, 0) layout_mode = 2 size_flags_horizontal = 4 size_flags_vertical = 3 -[node name="Label" type="Label" parent="Control/InventoryMenu/Status/VBoxContainer"] +[node name="Label" type="Label" parent="Control/InventoryMenu/Status/VBoxContainer" unique_id=768148166] layout_mode = 2 size_flags_horizontal = 4 size_flags_vertical = 0 text = "CIRNO" label_settings = SubResource("LabelSettings_bkqle") -[node name="TextureRect" type="TextureRect" parent="Control/InventoryMenu/Status/VBoxContainer"] +[node name="TextureRect" type="TextureRect" parent="Control/InventoryMenu/Status/VBoxContainer" unique_id=307448839] layout_mode = 2 size_flags_vertical = 3 texture = ExtResource("19_n0pka") expand_mode = 1 stretch_mode = 3 -[node name="ColorRect" type="ColorRect" parent="Control"] +[node name="ColorRect" type="ColorRect" parent="Control" unique_id=1220058668] material = SubResource("ShaderMaterial_0ncp3") layout_mode = 1 anchors_preset = 15 @@ -490,7 +490,7 @@ grow_horizontal = 2 grow_vertical = 2 mouse_filter = 2 -[node name="FPS" type="Label" parent="."] +[node name="FPS" type="Label" parent="." unique_id=259143833] z_index = 20 z_as_relative = false anchors_preset = 1 diff --git a/Scripts/Components/FSM/3DPlayer/AutoPickupModule3D.cs b/Scripts/Components/FSM/3DPlayer/AutoPickupModule3D.cs new file mode 100644 index 00000000..d3c8854b --- /dev/null +++ b/Scripts/Components/FSM/3DPlayer/AutoPickupModule3D.cs @@ -0,0 +1,152 @@ +using System.Collections.Generic; +using System.Linq; +using Cirno.Scripts.Interactables; +using Godot; + +namespace Cirno.Scripts.Components.FSM._3DPlayer; + +/// +/// Detects nearby items whose loot table contains at least one +/// auto-pickup entry and magnets them toward the player. Items are only formally collected +/// (inventory added, node freed) once they physically reach the player's position. +/// +/// Radius can be increased at runtime via equipment or upgrade systems — just write to +/// and the underlying collision shape is updated automatically. +/// +public partial class AutoPickupModule3D : Area3D, IModule +{ + // Speed at which attracted items move toward the player (units/second). + private const float AttractionSpeed = 12f; + + // Squared distance threshold at which an item is considered "collected". + private const float CollectDistanceSq = 0.15f * 0.15f; + + [Export] + private float _radius = 3f; + + /// + /// The radius of the auto-pickup detection sphere. + /// Assigning a new value resizes the underlying collision shape immediately. + /// + public float Radius + { + get => _radius; + set + { + _radius = value; + UpdateCollisionRadius(); + } + } + + private bool _enabled; + private CollisionShape3D _collisionShape; + private AudioStreamPlayer3D _pickupSound; + + // Items currently being attracted toward the player. + private readonly HashSet _trackedItems = []; + + public IStateMachine StateMachine { get; private set; } + + public void Init(IStateMachine machine) + { + StateMachine = machine; + _collisionShape = GetNodeOrNull("CollisionShape3D") ?? CreateCollisionShape(); + _pickupSound = GetNodeOrNull("PickupSound"); + UpdateCollisionRadius(); + } + + private CollisionShape3D CreateCollisionShape() + { + var shape = new CollisionShape3D { Shape = new SphereShape3D { Radius = _radius } }; + AddChild(shape); + return shape; + } + + public void EnterState(PlayerState state) + { + _enabled = true; + AreaEntered += OnAreaEntered; + AreaExited += OnAreaExited; + } + + public void ExitState(PlayerState state) + { + _enabled = false; + AreaEntered -= OnAreaEntered; + AreaExited -= OnAreaExited; + _trackedItems.Clear(); + } + + public void Process(double delta) { } + + public void PhysicsProcess(double delta) + { + if (!_enabled || _trackedItems.Count == 0) return; + + var playerPos = StateMachine.MainObject.GlobalPosition; + var toRemove = new List(); + + foreach (var item in _trackedItems) + { + if (!IsInstanceValid(item)) + { + toRemove.Add(item); + continue; + } + + var direction = playerPos - item.GlobalPosition; + var distanceSq = direction.LengthSquared(); + + if (distanceSq <= CollectDistanceSq) + { + item.Collect(); + _pickupSound?.Play(); + toRemove.Add(item); + continue; + } + + // Move the item toward the player, scaling speed so it feels snappy at any distance. + item.GlobalPosition += direction.Normalized() * AttractionSpeed * (float)delta; + } + + foreach (var item in toRemove) + { + _trackedItems.Remove(item); + } + } + + private void OnAreaEntered(Area3D area) + { + if (!_enabled) return; + if (area is not ItemPickup3D pickup) return; + if (!pickup.AutoPickup) return; + + // Only attract items whose inventory can still accept them to avoid a + // looping autopickup situation when the inventory slot is full. + var canAdd = pickup.LootTable.Aggregate(false, + (current, item) => current || InventoryManager.Instance.CanAddItem(item.ItemKey)); + + if (canAdd) + { + _trackedItems.Add(pickup); + } + } + + private void OnAreaExited(Area3D area) + { + if (area is ItemPickup3D pickup) + { + _trackedItems.Remove(pickup); + } + } + + private void UpdateCollisionRadius() + { + if (_collisionShape?.Shape is SphereShape3D sphere) + { + sphere.Radius = _radius; + } + } +} + + diff --git a/Scripts/Components/FSM/3DPlayer/AutoPickupModule3D.cs.uid b/Scripts/Components/FSM/3DPlayer/AutoPickupModule3D.cs.uid new file mode 100644 index 00000000..f1cea49a --- /dev/null +++ b/Scripts/Components/FSM/3DPlayer/AutoPickupModule3D.cs.uid @@ -0,0 +1 @@ +uid://s4xt80pu6lgl diff --git a/Scripts/Interactables/ItemPickup3D.cs b/Scripts/Interactables/ItemPickup3D.cs index 227067c1..ed10941c 100644 --- a/Scripts/Interactables/ItemPickup3D.cs +++ b/Scripts/Interactables/ItemPickup3D.cs @@ -107,10 +107,16 @@ public partial class ItemPickup3D : Interactable3D QueueFree(); } + /// + /// Auto-pickup items are handled exclusively by AutoPickupModule3D. + /// Returning false here prevents them from entering the normal + /// interaction selector, so they cannot be manually activated by the player. + /// + public override bool CanActivate() => !_autoPickup; + public void Collect() { AddItemsToInventory(); - } public void SetSprite(Texture2D sprite)