using System; using System.Diagnostics; using Babushka.scripts.CSharp.Common.Inventory; using Babushka.scripts.CSharp.Low_Code.Variables; using Godot; using Godot.Collections; namespace Babushka.scripts.CSharp.Common.Farming; /// /// Determines the behaviour of a plant in Babushka. /// public partial class PlantBehaviour2D : Node2D { [ExportGroup("Plant State")] [Export] private Sprite2D[] _seeds; [Export] private Sprite2D[] _smallPlants; [Export] private Sprite2D[] _bigPlants; [Export] private Sprite2D[] _readyPlants; [Export] private PlantState _state = PlantState.None; [Export] private FieldBehaviour2D _field; [Export] private ItemOnGround2D _harvestablePlant; [Export] private CpuParticles2D _magicEffect; [Export] private bool _magicWordNeeded = true; [ExportGroup("PlantConfig")] [Export] private string _prefabPath; [Export] private VariableNode _lifecycle; [Export] private int _daysWatered; private string _magicWordDialogicEventName = "MagicWord"; private Sprite2D? _currentPlantSprite = null; private bool _magicWordSaid = false; private bool _calledOnReady = false; private int _dayPlanted; private int _currentDay; public PlantState State { get => _state; set => _state = value; } /// /// The day count at the day this plant was planted. /// public int DayPlanted { get => _dayPlanted; set => _dayPlanted = value; } public int CurrentDayInCalendar { get => _currentDay; set { if (_currentDay == value) return; _currentDay = value; DaysGrowingChanged(); } } public string PrefabPath => _prefabPath; /// /// public accessor for the field reference /// public FieldBehaviour2D Field { get => _field; set => _field = value; } public int DaysWatered { get => _daysWatered; set { _daysWatered = value; } } public override void _Ready() { if (_state == PlantState.None) { _state = PlantState.Planted; _currentPlantSprite = GetRandomSprite(_seeds); _currentPlantSprite.Visible = true; } else { _calledOnReady = true; GrowPlant(); } } private void DaysGrowingChanged() { int lifecycle = _lifecycle.Payload.AsInt32(); Debug.Assert(lifecycle > 0); float growth = (float)_daysWatered / lifecycle; int growthFloor = Mathf.FloorToInt(growth); _state = growthFloor switch { 0 => PlantState.None, 1 => PlantState.Planted, 2 => PlantState.SmallPlant, _ => PlantState.BigPlant }; _calledOnReady = true; Grow(); } public void Grow() { GrowPlant(); } /// /// Transitions the plant to its next growth stage. /// public void GrowPlant() { if (!_calledOnReady) { if (_field.FieldState != FieldState.Watered || _magicWordSaid != _magicWordNeeded) return; } switch (_state) { case PlantState.None: _state = PlantState.Planted; _currentPlantSprite = GetRandomSprite(_seeds); _currentPlantSprite.Visible = true; break; case PlantState.Planted: _state = PlantState.SmallPlant; if(_currentPlantSprite != null) _currentPlantSprite.Visible = false; _currentPlantSprite = GetRandomSprite(_smallPlants); _currentPlantSprite.Visible = true; break; case PlantState.SmallPlant: _state = PlantState.BigPlant; if(_currentPlantSprite != null) _currentPlantSprite.Visible = false; _currentPlantSprite = GetRandomSprite(_bigPlants); _currentPlantSprite.Visible = true; break; case PlantState.BigPlant: _state = PlantState.Ready; if(_currentPlantSprite != null) _currentPlantSprite.Visible = false; _currentPlantSprite = GetRandomSprite(_readyPlants); _currentPlantSprite.Visible = true; //ActivatePickupAfterDelay(true); SetActiveHarvestablePlant(true); break; case PlantState.Ready: _state = PlantState.None; if(_currentPlantSprite != null) _currentPlantSprite.Visible = false; _currentPlantSprite = null; //ActivatePickupAfterDelay(false); SetActiveHarvestablePlant(false); break; default: break; } _field.UpdateFieldState(FieldState.Tilled); _magicWordSaid = false; _calledOnReady = false; } private Sprite2D GetRandomSprite(Sprite2D[] sprites) { Random rand = new Random(); return sprites[rand.Next(sprites.Length)]; } public async void ActivatePickupAfterDelay(bool activate) { await ToSignal(GetTree().CreateTimer(1.0f), "timeout"); SetActiveHarvestablePlant(activate); } private void SetActiveHarvestablePlant(bool active) { _harvestablePlant.IsActive = active; _harvestablePlant.UpdateVisuals(); } public void SayMagicWord(string wordEvent) { if (_magicWordDialogicEventName != wordEvent) return; _magicEffect.Emitting = true; _magicEffect.OneShot = true; _magicWordSaid = true; Grow(); } }