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)