Merge branch 'develop' into feature/quest_system

This commit is contained in:
cblech
2025-06-16 21:13:33 +02:00
439 changed files with 15734 additions and 7288 deletions
@@ -1,45 +0,0 @@
using Godot;
namespace Babushka.scripts.CSharp.Common.Camera;
public partial class CameraPivot : Node3D
{
[Export] private bool _canPitch;
[Export] private bool _canYaw;
[Export] private float _rotateSpeed = 0.003f;
[Export] private Node3D _subPivot;
public override void _Ready()
{
Input.MouseMode = Input.MouseModeEnum.Captured;
}
public override void _Input(InputEvent @event)
{
if(@event.IsActionPressed("click"))
{
if (Input.MouseMode == Input.MouseModeEnum.Visible)
{
Input.MouseMode = Input.MouseModeEnum.Captured;
}
}
if (@event.IsActionPressed("ui_cancel"))
{
Input.MouseMode = Input.MouseModeEnum.Visible;
}
if (@event is InputEventMouseMotion test)
{
if (Input.MouseMode != Input.MouseModeEnum.Captured)
return;
if (_canYaw)
_subPivot.RotateX(test.Relative.Y * -_rotateSpeed);
if(_canPitch)
this.RotateY(test.Relative.X * -_rotateSpeed);
}
}
}
@@ -1 +0,0 @@
uid://r5tahuqvbucy
@@ -1,34 +0,0 @@
using Godot;
namespace Babushka.scripts.CSharp.Common.CharacterControls;
public partial class InteractionArea : Node3D
{
[Export] private Area3D _area;
[Export] private Label3D _label;
[Export] private bool _showLabel = true;
[Signal]
public delegate void InteractedEventHandler();
public void OnPlayerEntered(Node3D player)
{
if(_showLabel)
_label.Show();
}
public void OnPlayerExited(Node3D player)
{
_label.Hide();
}
public override void _Input(InputEvent @event)
{
if (@event.IsAction("interact") && @event.IsPressed() && _area.HasOverlappingBodies())
{
_label.Hide();
EmitSignal(SignalName.Interacted);
}
}
}
@@ -1 +0,0 @@
uid://dumwt7lledufm
@@ -6,11 +6,11 @@ public partial class InteractionArea2D : Node2D
{
[Export] private Area2D _area;
[Export] private Label _label;
[Export] private SpriteSwitcher2D _sprites;
[Export] private SpriteSwitcher2D _sprites; // TODO: remove
[Export] private bool _showLabel = true;
[Export] private int _id;
[Export] private int _id = -1; // TODO: remove
[Signal] public delegate void InteractedToolEventHandler(int id);
[Signal] public delegate void InteractedToolEventHandler(int id); // TODO: remove
[Signal] public delegate void InteractedEventHandler();
public void OnPlayerEntered(Node2D player)
@@ -34,7 +34,7 @@ public partial class InteractionArea2D : Node2D
}
}
public void SetSpriteActiveState(bool success, int id)
public void SetSpriteActiveState(bool success, int id) // TODO: remove
{
if (_id == id)
{
@@ -1,3 +1,6 @@
using System.Threading.Tasks;
using Babushka.scripts.CSharp.Common.Inventory;
using Godot;
namespace Babushka.scripts.CSharp.Common.CharacterControls;
@@ -6,20 +9,43 @@ public partial class Player2D : CharacterBody2D
{
[Export] private float _speed = 100f;
[Export] private AnimatedSprite2D _sprite;
[Export] private SceneTree.GroupCallFlags _fieldFlags;
// -1 means no tool.
private int _toolID = -1;
private string _toolString;
private bool anyActionPressed;
private bool _canHandleInput = true;
private Vector2 _lastDirection = Vector2.Zero;
private InventoryManager _inventoryManager;
public override void _Ready()
{
InventoryManager.Instance.playerInventory.InventoryContentsChanged += HandleNewItemInInventory;
}
private void HandleNewItemInInventory()
{
// for future Kathi: this does not, in fact, check if an item has been added only, but triggers on every content change!
PlayPickUpAnimation();
}
public override void _Process(double delta)
{
anyActionPressed = false;
if (!_canHandleInput)
return;
if (Input.IsActionPressed("move_right"))
{
Velocity = new Vector2(_speed, 0);
MoveAndSlide();
_sprite.FlipH = false;
_sprite.Animation = "side_walking";
_sprite.Animation = "side walking" + _toolString;
anyActionPressed = true;
_lastDirection = Vector2.Right;
}
if (Input.IsActionPressed("move_left"))
@@ -27,24 +53,41 @@ public partial class Player2D : CharacterBody2D
Velocity = new Vector2(-_speed, 0);
MoveAndSlide();
_sprite.FlipH = true;
_sprite.Animation = "side_walking";
_sprite.Animation = "side walking" + _toolString;
anyActionPressed = true;
_lastDirection = Vector2.Left;
}
if (Input.IsActionPressed("move_up"))
{
Velocity = new Vector2(0, -_speed);
MoveAndSlide();
_sprite.Animation = "back walking";
_sprite.Animation = "back walking" + _toolString;
anyActionPressed = true;
_lastDirection = Vector2.Up;
}
if (Input.IsActionPressed("move_down"))
{
Velocity = new Vector2(0, _speed);
MoveAndSlide();
_sprite.Animation = "front walking";
_sprite.Animation = "front walking" + _toolString;
anyActionPressed = true;
_lastDirection = Vector2.Down;
}
if (Input.IsActionPressed("interact2"))
{
_sprite.Animation = "back interact";
anyActionPressed = true;
_lastDirection = Vector2.Up;
}
if (Input.IsActionPressed("item"))
{
_sprite.Animation = "diagonal item";
anyActionPressed = true;
_lastDirection = Vector2.Right;
}
if (anyActionPressed)
@@ -53,8 +96,83 @@ public partial class Player2D : CharacterBody2D
}
else
{
_sprite.Animation = "front idle";
//idle
if(_lastDirection == Vector2.Zero || _lastDirection == Vector2.Down)
_sprite.Animation = "front idle" + _toolString;
else if(_lastDirection == Vector2.Left || _lastDirection == Vector2.Right)
_sprite.Animation = "side idle" + _toolString;
else if(_lastDirection == Vector2.Up)
_sprite.Animation = "back idle" + _toolString;
}
}
public void ActivateTool(bool success, int id)
{
if (success)
{
_toolID = id;
}
else _toolID = -1;
switch (_toolID)
{
case 0:
_toolString = " rake";
break;
case 1:
_toolString = " wateringcan";
break;
default:
_toolString = "";
break;
}
}
/// <summary>
/// Called by FarmingControls Signal.
/// </summary>
public void PlayWateringAnimation()
{
if (_toolID == 1 && _canHandleInput)
{
_sprite.Animation = "diagonal wateringcan";
_sprite.Play();
_canHandleInput = false;
Task.Run(DelayedInputHandlerReset);
}
}
private async Task DelayedInputHandlerReset()
{
await Task.Delay(1000);
_canHandleInput = true;
}
public void PlayPickUpAnimation()
{
_sprite.Animation = "side pickup";
_sprite.Play();
_canHandleInput = false;
Task.Run(DelayedInputHandlerReset);
}
public void PlayFarmingAnimation()
{
_sprite.Animation = "diagonal farming";
_sprite.Play();
_canHandleInput = false;
Task.Run(DelayedInputHandlerReset);
}
public void PlayWateringCanFillupAnimation()
{
_sprite.Animation = "back interact";
_sprite.Play();
_canHandleInput = false;
_lastDirection = Vector2.Up;
Task.Run(DelayedInputHandlerReset);
}
}
@@ -1,133 +0,0 @@
using System.Diagnostics;
using Godot;
namespace Babushka.scripts.CSharp.Common.CharacterControls;
public partial class Player3D : CharacterBody3D
{
[Export] private float _speed = 1.0f;
[Export] private Camera3D _camera;
/// <summary>
/// The sprite arrays are all setup like this:
/// 0 - idle
/// 1 - walking
/// </summary>
[Export] private AnimatedSprite3D[] _frontSpritesAnimated;
[Export] private AnimatedSprite3D[] _sideSpritesAnimated;
[Export] private AnimatedSprite3D[] _backSpritesAnimated;
private bool _sideFlipped;
private Vector2 _lastDirection;
public override void _PhysicsProcess(double delta)
{
var inputDir = Input.GetVector("move_left", "move_right", "move_down", "move_up");
if (inputDir == Vector2.Zero)
{
if(_lastDirection != Vector2.Zero)
SwitchIdleSprites();
return;
}
MoveOnInput(inputDir, delta);
SwitchMovementSprites(inputDir);
}
private void MoveOnInput(Vector2 inputDir, double delta)
{
var direction = (Transform.Basis * new Vector3(inputDir.X, 0, inputDir.Y * (-1))).Normalized();
if (direction != Vector3.Zero)
Velocity = new Vector3(direction.X * _speed * (float) delta * Scale.X, Velocity.Y, direction.Z * _speed * (float) delta * Scale.Z);
else
Velocity = Velocity.MoveToward(new Vector3(0, 0, 0), _speed);
MoveAndSlide();
}
private void SwitchIdleSprites()
{
if (_lastDirection.X != 0)
{
ActivateSprite(0, false, true, false);
return;
}
if(_lastDirection.Y <= 0.0f)
ActivateSprite(0, true, false, false);
if(_lastDirection.Y > 0.0f)
ActivateSprite(0, false, false, true);
_lastDirection = Vector2.Zero;
}
private void SwitchMovementSprites(Vector2 inputDir)
{
float X = inputDir.X;
float Y = inputDir.Y;
_lastDirection = new Vector2(X, Y);
if (X != 0)
{
ActivateSprite(1, false, true, false);
if (X > 0.0f)
{
_sideFlipped = false;
}
if (X < 0.0f)
{
_sideFlipped = true;
}
foreach (var animatedSprite in _sideSpritesAnimated)
{
animatedSprite.FlipH = _sideFlipped;
}
return;
}
if (Y != 0)
{
if (Y > 0.0f)
{
ActivateSprite(1, false, false, true);
}
if (Y < 0.0f)
{
ActivateSprite(1, true, false, false);
}
}
}
private void ActivateSprite(int index, bool frontActive, bool sideActive, bool backActive)
{
DeactivateAll();
_frontSpritesAnimated[index].Visible = frontActive;
_sideSpritesAnimated[index].Visible = sideActive;
_backSpritesAnimated[index].Visible = backActive;
}
private void DeactivateAll()
{
foreach (var animatedSprite in _frontSpritesAnimated)
{
animatedSprite.Visible = false;
}
foreach (var animatedSprite in _sideSpritesAnimated)
{
animatedSprite.Visible = false;
}
foreach (var animatedSprite in _backSpritesAnimated)
{
animatedSprite.Visible = false;
}
}
}
@@ -1 +0,0 @@
uid://b4ugrget2x6lb
@@ -1,107 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Godot;
using Godot.Collections;
namespace Babushka.scripts.CSharp.Common.Farming;
[GlobalClass]
public partial class FarmingControls : Node3D
{
[Export] private Sprite3D _hoeSprite;
[Export] private Sprite3D _wateringCanSprite;
[Export] private PackedScene _fieldPrefab;
[Export] private Node3D _movingPlayer;
[Export] private Camera3D _camera;
public FieldService FieldParent;
private bool _hoeInHand = false;
private bool _waterCanInHand = false;
#region Tools
public bool ActivateHoe(bool activate)
{
bool success = ActivateTool(activate, _hoeSprite);
_hoeInHand = success;
return success;
}
public bool ActivateWateringCan(bool activate)
{
bool success = ActivateTool(activate, _wateringCanSprite);
_waterCanInHand = success;
return success;
}
private bool ActivateTool(bool activate, Sprite3D tool)
{
tool.Visible = !activate;
return !activate;
}
#endregion
public override void _Input(InputEvent @event)
{
Vector2 mousePosition = GetViewport().GetMousePosition();
var dropPlane = new Plane(new Vector3(0, 0, 10), 10);
Vector3? position3D = dropPlane.IntersectsRay(_camera.ProjectRayOrigin(mousePosition),
_camera.ProjectRayNormal(mousePosition));
if (position3D.HasValue)
{
Vector2I adjustedPosition = new Vector2I(AdjustValue(position3D.Value.X), AdjustValue(position3D.Value.Y));
if (@event.IsActionPressed("click") && _hoeInHand)
{
MakeField(adjustedPosition);
}
if (@event.IsActionPressed("click") && _waterCanInHand)
{
WaterTheField(adjustedPosition);
}
}
}
private void WaterTheField(Vector2I fieldPosition)
{
FieldBehaviour field = FieldParent.Get(fieldPosition);
if (field == null)
return;
field.Water();
}
private void MakeField(Vector2I fieldPosition)
{
if(FieldParent == null || _fieldPrefab == null)
return;
// only instantiate a field if there isn't one already.
if(FieldParent.Get(fieldPosition) == null)
{
Node fieldInstance = _fieldPrefab.Instantiate();
if (fieldInstance is Node3D field3d)
{
// add dictionary entry for the field
Array<Node> fields = field3d.FindChildren("*", nameof(FieldBehaviour));
if (fields.Count > 0)
FieldParent.TryAddEntry(fieldPosition, fields[0] as FieldBehaviour);
// reposition and reparent the instance
field3d.Position = new Vector3(fieldPosition.X, 0.1f, fieldPosition.Y * -1);;
FieldParent.AddChild(fieldInstance);
}
}
}
private int AdjustValue(float value)
{
return (int) Mathf.Floor(value);
}
}
@@ -1 +0,0 @@
uid://b1sscdr4ptec8
@@ -6,9 +6,6 @@ namespace Babushka.scripts.CSharp.Common.Farming;
[GlobalClass]
public partial class FarmingControls2D : Node2D
{
[Export] private Sprite2D _hoeSprite;
[Export] private Sprite2D _wateringCanEmptySprite;
[Export] private Sprite2D _wateringCanFilledSprite;
[Export] private PackedScene _fieldPrefab;
[Export] private Node2D _movingPlayer;
[Export] private Camera2D _camera;
@@ -20,6 +17,8 @@ public partial class FarmingControls2D : Node2D
private int _currentWateringCanStep = 0;
private int _wateringCanCapacity = 3;
[Signal] public delegate void WateringFieldEventHandler();
#region Tools
/// <summary>
@@ -32,43 +31,13 @@ public partial class FarmingControls2D : Node2D
bool activate;
//if our hands are empty, activate
if (_toolId == -1)
if (toolId == -1)
{
activate = true;
activate = false;
}
else
{
//if we're already carrying a tool, deactivate or fail return
if (_toolId == toolId)
{
activate = false;
}
else
{
return false;
}
}
switch (toolId)
{
case 0:
_hoeSprite.Visible = activate;
break;
case 1:
if (activate)
{
_wateringCanEmptySprite.Visible = true;
GD.Print("Activating empty Watering can sprite.");
}
else
{
_wateringCanEmptySprite.Visible = false;
_wateringCanFilledSprite.Visible = false;
}
break;
default:
_toolId = -1;
break;
activate = true;
}
_toolId = activate ? toolId : -1;
@@ -98,9 +67,6 @@ public partial class FarmingControls2D : Node2D
{
if (_toolId == 1 )
{
GD.Print("Watering can in hand, filling.");
_wateringCanEmptySprite.Visible = !fillUp;
_wateringCanFilledSprite.Visible = fillUp;
_wateringCanFilled = fillUp;
}
}
@@ -112,6 +78,7 @@ public partial class FarmingControls2D : Node2D
return;
field.Water();
EmitSignal(SignalName.WateringField);
if (_currentWateringCanStep < _wateringCanCapacity)
{
@@ -1,59 +0,0 @@
using System.Diagnostics;
using Godot;
namespace Babushka.scripts.CSharp.Common.Farming
{
public enum FieldState
{
Empty = 0,
Tilled = 1,
Planted = 2,
Watered = 3,
NotFound = 99
}
[GlobalClass]
public partial class FieldBehaviour : Sprite3D
{
[Export] private Texture2D Tilled;
[Export] private Texture2D Watered;
[Export] public FieldState FieldState = FieldState.Empty;
public Vector2 FieldPosition;
public override void _Ready()
{
Texture = Tilled;
base._Ready();
}
public void Water()
{
FieldState = FieldState.Watered;
Texture = Watered;
}
/// <summary>
/// Called when the player enters the field'S interaction area and presses <E>.
/// </summary>
public void Farm()
{
switch (FieldState)
{
case FieldState.Empty:
Texture = Tilled;
FieldState = FieldState.Tilled;
break;
case FieldState.Tilled:
FieldState = FieldState.Planted;
break;
case FieldState.Planted:
break;
default:
break;
}
}
}
}
@@ -1 +0,0 @@
uid://histmmyi1wr
@@ -2,6 +2,15 @@ using Godot;
namespace Babushka.scripts.CSharp.Common.Farming;
public enum FieldState
{
Empty = 0,
Tilled = 1,
Planted = 2,
Watered = 3,
NotFound = 99
}
[GlobalClass]
public partial class FieldBehaviour2D : Sprite2D
{
@@ -1,56 +0,0 @@
using System.Diagnostics;
using Godot;
using Godot.Collections;
namespace Babushka.scripts.CSharp.Common.Farming;
[GlobalClass]
public partial class FieldService : Node3D
{
[Export] private Dictionary<Vector2I, FieldBehaviour> fields = new Dictionary<Vector2I, FieldBehaviour>();
//Create
public bool TryAddEntry(Vector2I key, FieldBehaviour field)
{
if (!fields.ContainsKey(key))
{
fields.Add(key, field);
return true;
}
return false;
}
// Read
public FieldBehaviour Get(Vector2I key)
{
if (fields.TryGetValue(key, out FieldBehaviour field))
return field;
return field;
return null;
}
//Update
public void UpdateEntry(Vector2I fieldPosition, FieldBehaviour state)
{
if (fields.ContainsKey(fieldPosition))
{
fields[fieldPosition] = state;
}
else
{
TryAddEntry(fieldPosition, state);
}
}
//Delete
public void RemoveEntry(Vector2I fieldPosition)
{
if (fields.ContainsKey(fieldPosition))
{
fields.Remove(fieldPosition);
}
}
}
@@ -1 +0,0 @@
uid://c6hh7m8wikv04
@@ -1,68 +0,0 @@
using System;
using Godot;
namespace Babushka.scripts.CSharp.Common.Farming;
public enum PlantState
{
None = 0,
Planted = 1,
SmallPlant = 2,
BigPlant = 3,
Ready = 4
}
public partial class PlantBehaviour : Node3D
{
[Export] private Sprite3D[] _seeds;
[Export] private Sprite3D[] _smallPlants;
[Export] private Sprite3D[] _bigPlants;
[Export] private Sprite3D[] _readyPlants;
[Export] private PlantState _state = PlantState.None;
private Sprite3D _currentPlantSprite = null;
public void Grow()
{
switch (_state)
{
case PlantState.None:
_state = PlantState.Planted;
_currentPlantSprite = GetRandomSprite(_seeds);
_currentPlantSprite.Visible = true;
break;
case PlantState.Planted:
_state = PlantState.SmallPlant;
_currentPlantSprite.Visible = false;
_currentPlantSprite = GetRandomSprite(_smallPlants);
_currentPlantSprite.Visible = true;
break;
case PlantState.SmallPlant:
_state = PlantState.BigPlant;
_currentPlantSprite.Visible = false;
_currentPlantSprite = GetRandomSprite(_bigPlants);
_currentPlantSprite.Visible = true;
break;
case PlantState.BigPlant:
_state = PlantState.Ready;
_currentPlantSprite.Visible = false;
_currentPlantSprite = GetRandomSprite(_readyPlants);
_currentPlantSprite.Visible = true;
break;
case PlantState.Ready:
_state = PlantState.None;
_currentPlantSprite.Visible = false;
_currentPlantSprite = null;
break;
default:
break;
}
}
private Sprite3D GetRandomSprite(Sprite3D[] sprites)
{
Random rand = new Random();
return sprites[rand.Next(sprites.Length)];
}
}
@@ -1 +0,0 @@
uid://yfnjmuuxs3oq
@@ -1,8 +1,19 @@
using System;
using Babushka.scripts.CSharp.Common.CharacterControls;
using Babushka.scripts.CSharp.Common.Inventory;
using Godot;
namespace Babushka.scripts.CSharp.Common.Farming;
public enum PlantState
{
None = 0,
Planted = 1,
SmallPlant = 2,
BigPlant = 3,
Ready = 4
}
/// <summary>
/// Determines the behaviour of a plant in Babushka.
/// </summary>
@@ -14,9 +25,11 @@ public partial class PlantBehaviour2D : Node2D
[Export] private Sprite2D[] _readyPlants;
[Export] private PlantState _state = PlantState.None;
[Export] private FieldBehaviour2D _field;
[Export] private ItemOnGround2D _harvestablePlant;
private Sprite2D _currentPlantSprite = null;
/// <summary>
/// Transitions the plant to its next growth stage.
/// </summary>
@@ -25,6 +38,8 @@ public partial class PlantBehaviour2D : Node2D
if (_field.FieldState != FieldState.Watered)
return;
GetTree().CallGroup("PlantGrowing", Player2D.MethodName.PlayFarmingAnimation);
switch (_state)
{
case PlantState.None:
@@ -48,6 +63,7 @@ public partial class PlantBehaviour2D : Node2D
_state = PlantState.Ready;
_currentPlantSprite.Visible = false;
_currentPlantSprite = GetRandomSprite(_readyPlants);
_harvestablePlant.IsActive = true;
_currentPlantSprite.Visible = true;
break;
case PlantState.Ready:
@@ -58,7 +74,7 @@ public partial class PlantBehaviour2D : Node2D
default:
break;
}
_field.UpdateFieldState(FieldState.Tilled);
}
@@ -1,3 +1,5 @@
using Babushka.scripts.CSharp.Common.CharacterControls;
using Babushka.scripts.CSharp.Common.Inventory;
using Godot;
namespace Babushka.scripts.CSharp.Common.Farming;
@@ -7,12 +9,45 @@ public partial class VesnaBehaviour2D : Node
[ExportGroup("Farming")]
[Export] private FieldService2D _fieldParent;
[Export] private FarmingControls2D _farmingControls;
[Export] private Player2D _player2d;
[Export] private ItemResource _hoe;
[Export] private ItemResource _wateringCan;
[Signal] public delegate void PickedUpToolEventHandler(bool success, int toolId);
private InventoryManager _inventoryManager;
private InventoryInstance _inventoryInstance;
public override void _Ready()
{
_farmingControls.FieldService = _fieldParent;
_inventoryManager = InventoryManager.Instance;
_inventoryInstance = _inventoryManager.playerInventory;
_inventoryManager.SlotIndexChanged += HandleInventorySelectedSlotIndexChanged;
}
private void HandleInventorySelectedSlotIndexChanged(int newIndex)
{
InventorySlot currentSlot = InventoryManager.Instance.GetCurrentSelectedSlot();
ItemInstance? currentItem = currentSlot.itemInstance;
if (currentItem == null)
return;
if (currentItem.blueprint == _hoe)
{
ActivateTool(0);
return;
}
if (currentItem.blueprint == _wateringCan)
{
ActivateTool(1);
return;
}
ActivateTool(-1);
}
#region Farming
@@ -28,6 +63,7 @@ public partial class VesnaBehaviour2D : Node
if (toolId == 1)
{
_farmingControls.FillWateringCan(true);
_player2d.PlayWateringCanFillupAnimation();
}
}
@@ -1,13 +1,31 @@
#nullable enable
using System;
using Godot;
namespace Babushka.scripts.CSharp.Common.Inventory;
public partial class InventoryManager : Node
{
public static InventoryManager Instance { get; private set; }
[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;
public InventoryInstance playerInventory = new InventoryInstance();
private int _currentSelectedSlotIndex = 0;
public override void _EnterTree()
{
@@ -16,8 +34,7 @@ public partial class InventoryManager : Node
public override void _Ready()
{
playerInventory = new InventoryInstance();
playerInventory.SlotAmount = 30;
playerInventory.SlotAmount = 37;
}
public InventoryActionResult CreateItem(
@@ -68,4 +85,14 @@ public partial class InventoryManager : Node
{
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];
}
}
@@ -3,15 +3,14 @@ namespace Babushka.scripts.CSharp.Common.Inventory;
public partial class InventoryTestScript : Node
{
[Export]
private ItemResource _testItemToCreate;
[Export(PropertyHint.ArrayType)]
private ItemResource[] _testItemsToCreate;
public override void _Ready()
{
InventoryManager.Instance.CreateItem(_testItemToCreate, InventoryManager.Instance.playerInventory);
InventoryManager.Instance.CreateItem(_testItemToCreate, InventoryManager.Instance.playerInventory);
InventoryManager.Instance.CreateItem(_testItemToCreate, InventoryManager.Instance.playerInventory);
InventoryManager.Instance.CreateItem(_testItemToCreate, InventoryManager.Instance.playerInventory);
GD.Print("Added items");
foreach (var itemResource in _testItemsToCreate)
{
InventoryManager.Instance.CreateItem(itemResource, InventoryManager.Instance.playerInventory);
}
}
}
+64 -26
View File
@@ -1,28 +1,34 @@
#nullable enable
using Godot;
namespace Babushka.scripts.CSharp.Common.Inventory;
public partial class InventoryUi : Control
{
private GridContainer _slots;
private Control _slots;
private Control _slotsMover;
private InventoryInstance _playerInventory;
private Control _slotSelect;
private int? _slotOnMouse;
private int _selectedSlot = 0;
private bool _inventoryExtended = false;
private Tween? _inventoryExtensionTween;
[Export]
private float _inventoryClosedOffset = 0f;
[Export]
private float _inventoryOpenedOffset = 200f;
public override void _Ready()
{
GD.Print("Ready inventory ui");
_slots = GetNode<GridContainer>("SlotsContainer/Slots");
_slots = GetNode<Control>("SlotsContainer/SlotsMover/Slots");
_slotsMover = GetNode<Control>("SlotsContainer/SlotsMover");
_playerInventory = InventoryManager.Instance.playerInventory;
_slotSelect = GetNode<Control>("SlotsContainer/SlotSelectContainer/Selector");
PopulateSlots();
//PopulateSlots();
SubscribeSlots();
SetSlotContent();
SetSlotSelectPosition();
InventoryManager.Instance.playerInventory.InventoryContentsChanged += SetSlotContent;
@@ -40,21 +46,43 @@ public partial class InventoryUi : Control
var inventorySlot = _playerInventory.Slots[i];
var uiSlot = _slots.GetChild(i) as SlotUi;
uiSlot!.nameLabel.Text = inventorySlot.itemInstance?.blueprint.name ?? "";
uiSlot!.nameLabel.LabelSettings = uiSlot!.nameLabel.LabelSettings.Duplicate() as LabelSettings;
uiSlot!.nameLabel.LabelSettings!.FontColor = inventorySlot.itemInstance?.blueprint.color ?? Colors.White;
if (inventorySlot.itemInstance != null)
{
var blueprint = inventorySlot.itemInstance.blueprint;
var amount = inventorySlot.itemInstance.amount;
var amountText = inventorySlot.itemInstance != null &&
inventorySlot.itemInstance.amount != 1
? inventorySlot.itemInstance.amount.ToString()
: "";
uiSlot!.amountLabel.Text = amountText;
if (blueprint.icon != null)
{
// show icon
uiSlot!.nameLabel.Text = "";
uiSlot.icon.Texture = blueprint.icon;
}
else
{
// show name label
uiSlot!.nameLabel.Text = inventorySlot.itemInstance.blueprint.name;
uiSlot!.nameLabel.LabelSettings = uiSlot!.nameLabel.LabelSettings.Duplicate() as LabelSettings;
uiSlot!.nameLabel.LabelSettings!.FontColor = inventorySlot.itemInstance?.blueprint.color ?? Colors.White;
uiSlot.icon.Texture = null;
}
// amount
uiSlot!.amountLabel.Text = amount != 1 ? amount.ToString() : "";
}
else
{
uiSlot!.nameLabel.Text = "";
uiSlot!.icon.Texture = null;
uiSlot!.amountLabel.Text = "";
}
}
}
private void SetSlotSelectPosition()
{
_slotSelect.Position = new Vector2(_selectedSlot * 100, 0);
_slotSelect.Position = new Vector2(InventoryManager.Instance.CurrentSelectedSlotIndex * 100, 0);
}
private void PopulateSlots()
@@ -69,6 +97,16 @@ public partial class InventoryUi : Control
}
}
private void SubscribeSlots()
{
for (var index = 0; index < _playerInventory.Slots.Count; index++)
{
var slotInstance = _slots.GetChild<SlotUi>(index);
slotInstance.index = index;
slotInstance.Clicked += SlotClicked;
}
}
private void UnsubscribeSlots()
{
for (var index = 0; index < _playerInventory.Slots.Count; index++)
@@ -108,17 +146,17 @@ public partial class InventoryUi : Control
if (Input.IsActionJustPressed("ui_inventory_disadvance"))
{
_selectedSlot++;
if (_selectedSlot > 9)
_selectedSlot = 0;
InventoryManager.Instance.CurrentSelectedSlotIndex++;
if (InventoryManager.Instance.CurrentSelectedSlotIndex > 8)
InventoryManager.Instance.CurrentSelectedSlotIndex = 0;
SetSlotSelectPosition();
}
if (Input.IsActionJustPressed("ui_inventory_advance"))
{
_selectedSlot--;
if (_selectedSlot < 0)
_selectedSlot = 9;
InventoryManager.Instance.CurrentSelectedSlotIndex--;
if (InventoryManager.Instance.CurrentSelectedSlotIndex < 0)
InventoryManager.Instance.CurrentSelectedSlotIndex = 8;
SetSlotSelectPosition();
}
}
@@ -130,25 +168,25 @@ public partial class InventoryUi : Control
_inventoryExtended = !_inventoryExtended;
if (_inventoryExtended)
{
//GD.Print("Open inventory");
GD.Print("Open inventory");
_inventoryExtensionTween = GetTree().CreateTween();
_slotSelect.Hide();
_inventoryExtensionTween
.TweenProperty(_slots, "offset_bottom", -100, 0.4)
.TweenProperty(_slotsMover, "offset_bottom", _inventoryOpenedOffset, 0.4)
.SetTrans(Tween.TransitionType.Quad)
.SetEase(Tween.EaseType.Out);
}
else
{
//GD.Print("Close inventory");
GD.Print("Close inventory");
_inventoryExtensionTween = GetTree().CreateTween();
_slotSelect.Show();
_inventoryExtensionTween
.TweenProperty(_slots, "offset_bottom", 200, 0.4)
.TweenProperty(_slotsMover, "offset_bottom", _inventoryClosedOffset, 0.4)
.SetTrans(Tween.TransitionType.Quad)
.SetEase(Tween.EaseType.Out);
_slotOnMouse = null;
}
}
}
}
@@ -1,49 +0,0 @@
using Godot;
namespace Babushka.scripts.CSharp.Common.Inventory;
public partial class ItemOnGround : Node3D
{
private ItemInstance _itemInstance;
[Export]
private bool _infiniteSupply = false;
private Label3D _itemLabel => GetNode<Label3D>("ItemLabel");
private Label3D _pickupErrorLabel => GetNode<Label3D>("PickupErrorLabel");
public ItemInstance itemInstance
{
get => _itemInstance;
set
{
_itemInstance = value;
UpdateVisuals();
}
}
public void TryPickUp()
{
GD.Print("Trying to pick up item");
var result = InventoryManager.Instance.CollectItem(itemInstance.Clone());
if (result == InventoryActionResult.Success)
{
if (!_infiniteSupply)
{
QueueFree();
}
}
else
{
_pickupErrorLabel.Text = "Inventory Full";
var tween = GetTree().CreateTween();
tween.TweenInterval(2);
tween.TweenCallback(Callable.From(() => _pickupErrorLabel.Text = ""));
}
}
public void UpdateVisuals()
{
_itemLabel.Text = itemInstance.blueprint?.name ?? "Error Item";
}
}
@@ -1 +0,0 @@
uid://udhigottc8rg
@@ -0,0 +1,76 @@
using Godot;
namespace Babushka.scripts.CSharp.Common.Inventory;
public partial class ItemOnGround2D : Node
{
private ItemInstance _itemInstance;
[Export] private bool _infiniteSupply = false;
[Export] private int _finiteSupply = 1;
[Export] public bool IsActive = true;
private int pickUpCounter = 0;
private Label _itemLabel => GetNode<Label>("ItemLabel");
private Label _pickupErrorLabel => GetNode<Label>("PickupErrorLabel");
private Sprite2D _iconSprite => GetNode<Sprite2D>("Icon");
public ItemInstance itemInstance
{
get => _itemInstance;
set
{
_itemInstance = value;
UpdateVisuals();
}
}
public override void _Ready()
{
UpdateVisuals();
_pickupErrorLabel.Text = "";
}
public void TryPickUp()
{
if (!IsActive)
return;
var result = InventoryManager.Instance.CollectItem(itemInstance.Clone());
if (result == InventoryActionResult.Success)
{
if (!_infiniteSupply)
{
pickUpCounter++;
if (pickUpCounter >= _finiteSupply)
{
QueueFree();
}
}
}
else
{
_pickupErrorLabel.Text = "Inventory Full";
var tween = GetTree().CreateTween();
tween.TweenInterval(2);
tween.TweenCallback(Callable.From(() => _pickupErrorLabel.Text = ""));
}
}
public void UpdateVisuals()
{
if (!IsActive)
return;
_iconSprite.Texture = itemInstance?.blueprint?.icon;
if (_iconSprite.Texture == null)
{
_itemLabel.Text = itemInstance?.blueprint?.name ?? "Error Item";
}
else
{
_itemLabel.Text = "";
}
}
}
@@ -0,0 +1 @@
uid://btusf04xnywhm
@@ -10,7 +10,7 @@ public partial class ItemOnGroundSpawnWith : Node
{
if(_blueprint == null) return;
var parent = GetParent<ItemOnGround>();
var parent = GetParent<ItemOnGround2D>();
parent.itemInstance = new ItemInstance { blueprint = _blueprint };
}
}
@@ -10,6 +10,9 @@ public partial class ItemResource : Resource
[Export]
public Color color;
[Export]
public Texture2D? icon;
[Export]
public int maxStack;
@@ -8,6 +8,7 @@ public partial class SlotUi : Control
public Label nameLabel;
public int index;
public Label amountLabel;
public TextureRect icon;
[Signal] public delegate void ClickedEventHandler(int index);
@@ -15,6 +16,7 @@ public partial class SlotUi : Control
{
nameLabel = GetNode<Label>("NameLabel");
amountLabel = GetNode<Label>("AmountLabel");
icon = GetNode<TextureRect>("Icon");
}
public void _on_gui_input(InputEvent ev)
+22
View File
@@ -0,0 +1,22 @@
using Godot;
namespace Babushka.scripts.CSharp.Common;
public partial class SceneTransition : Node
{
[Export] private PackedScene _sceneToLoad;
[Export] private Node _sceneInstanceParent;
[Export] private bool _unloadSelf = true;
public void LoadScene()
{
Node sceneInstance = _sceneToLoad.Instantiate();
_sceneInstanceParent.AddChild(sceneInstance);
if (_unloadSelf)
{
QueueFree();
}
}
}
@@ -0,0 +1 @@
uid://cssdu8viimwm6
-36
View File
@@ -1,36 +0,0 @@
using Godot;
namespace Babushka.scripts.CSharp.Common;
/// <summary>
/// Switches between two Sprite Options.
/// </summary>
public partial class SpriteSwitcher : Node3D
{
[Export] private Sprite3D _trueSprite;
[Export] private Sprite3D _falseSprite;
[Export] private bool _state = true;
[Signal]
public delegate void SwitchEventHandler(bool state);
public override void _Ready()
{
SetState();
}
public void SwitchState()
{
_state = !_state;
EmitSignal(SignalName.Switch, _state);
SetState();
}
private void SetState()
{
if(_trueSprite != null)
_trueSprite.Visible = _state;
if(_falseSprite != null)
_falseSprite.Visible = !_state;
}
}
@@ -1 +0,0 @@
uid://v34pl0nlp4x