diff --git a/Assets/Scripts/Minigames/FortFight/Core/AmmunitionManager.cs b/Assets/Scripts/Minigames/FortFight/Core/AmmunitionManager.cs
index 4b5df415..cdbc11fb 100644
--- a/Assets/Scripts/Minigames/FortFight/Core/AmmunitionManager.cs
+++ b/Assets/Scripts/Minigames/FortFight/Core/AmmunitionManager.cs
@@ -220,6 +220,34 @@ namespace Minigames.FortFight.Core
return true;
}
+ ///
+ /// Select the first available (non-cooldown) ammo for a player.
+ /// Called at the start of each turn to reset selection.
+ ///
+ public bool SelectFirstAvailableAmmo(int playerIndex)
+ {
+ if (!_playerStates.ContainsKey(playerIndex))
+ {
+ Logging.Warning($"[AmmunitionManager] Player {playerIndex} state not found!");
+ return false;
+ }
+
+ var configs = AvailableConfigs;
+ foreach (var config in configs)
+ {
+ if (IsAmmoAvailable(config.projectileType, playerIndex))
+ {
+ return SelectAmmo(config.projectileType, playerIndex);
+ }
+ }
+
+ // Fallback: select default even if on cooldown (shouldn't happen in normal gameplay)
+ Logging.Warning($"[AmmunitionManager] Player {playerIndex}: No ammo available! Falling back to default.");
+ _playerStates[playerIndex].SelectedAmmo = defaultProjectileType;
+ OnAmmoSelected?.Invoke(defaultProjectileType, playerIndex);
+ return false;
+ }
+
///
/// Get currently selected projectile type for a specific player
///
diff --git a/Assets/Scripts/Minigames/FortFight/Core/ProjectileTurnAction.cs b/Assets/Scripts/Minigames/FortFight/Core/ProjectileTurnAction.cs
index 87973780..413e66a0 100644
--- a/Assets/Scripts/Minigames/FortFight/Core/ProjectileTurnAction.cs
+++ b/Assets/Scripts/Minigames/FortFight/Core/ProjectileTurnAction.cs
@@ -1,5 +1,4 @@
-using AppleHills.Core.Settings;
-using Core;
+using Core;
using Core.Settings;
using Minigames.FortFight.Data;
using Minigames.FortFight.Projectiles;
@@ -13,14 +12,14 @@ namespace Minigames.FortFight.Core
///
public class ProjectileTurnAction
{
- private SlingshotController slingshot;
- private AmmunitionManager ammoManager;
- private CameraController cameraController;
- private int playerIndex;
- private ProjectileBase activeProjectile;
- private bool launchComplete = false;
- private bool projectileSettled = false;
- private float settleTimer = 0f;
+ private SlingshotController _slingshot;
+ private AmmunitionManager _ammoManager;
+ private CameraController _cameraController;
+ private int _playerIndex;
+ private ProjectileBase _activeProjectile;
+ private bool _launchComplete = false;
+ private bool _projectileSettled = false;
+ private float _settleTimer = 0f;
private IFortFightSettings _cachedSettings;
private IFortFightSettings CachedSettings
@@ -35,14 +34,14 @@ namespace Minigames.FortFight.Core
}
}
- public bool IsComplete => projectileSettled;
+ public bool IsComplete => _projectileSettled;
public ProjectileTurnAction(SlingshotController slingshot, AmmunitionManager ammoManager, CameraController cameraController, int playerIndex)
{
- this.slingshot = slingshot;
- this.ammoManager = ammoManager;
- this.cameraController = cameraController;
- this.playerIndex = playerIndex;
+ this._slingshot = slingshot;
+ this._ammoManager = ammoManager;
+ this._cameraController = cameraController;
+ this._playerIndex = playerIndex;
}
///
@@ -53,12 +52,12 @@ namespace Minigames.FortFight.Core
Logging.Debug("[ProjectileTurnAction] Executing - enabling slingshot");
// Enable slingshot
- if (slingshot != null)
+ if (_slingshot != null)
{
- slingshot.Enable();
+ _slingshot.Enable();
// Subscribe to launch event
- slingshot.OnProjectileLaunched += HandleProjectileLaunched;
+ _slingshot.OnProjectileLaunched += HandleProjectileLaunched;
}
}
@@ -67,28 +66,28 @@ namespace Minigames.FortFight.Core
///
public void Update()
{
- if (!launchComplete) return;
+ if (!_launchComplete) return;
// Check if projectile is destroyed or stopped
- if (activeProjectile == null)
+ if (_activeProjectile == null)
{
// Projectile destroyed - start settle timer
- if (settleTimer == 0f)
+ if (_settleTimer == 0f)
{
Logging.Debug("[ProjectileTurnAction] Projectile destroyed - starting settle timer");
}
- settleTimer += Time.deltaTime;
+ _settleTimer += Time.deltaTime;
float settleDelay = CachedSettings?.ProjectileSettleDelay ?? 2.5f;
- if (settleTimer >= settleDelay)
+ if (_settleTimer >= settleDelay)
{
- projectileSettled = true;
+ _projectileSettled = true;
// Stop camera tracking when projectile settles
- if (cameraController != null)
+ if (_cameraController != null)
{
- cameraController.StopFollowingProjectile();
+ _cameraController.StopFollowingProjectile();
}
Logging.Debug("[ProjectileTurnAction] Turn action complete");
@@ -97,20 +96,20 @@ namespace Minigames.FortFight.Core
else
{
// Check if projectile has stopped moving
- Rigidbody2D rb = activeProjectile.GetComponent();
+ Rigidbody2D rb = _activeProjectile.GetComponent();
if (rb != null && rb.linearVelocity.magnitude < 0.5f)
{
- settleTimer += Time.deltaTime;
+ _settleTimer += Time.deltaTime;
float settleDelay = CachedSettings?.ProjectileSettleDelay ?? 2.5f;
- if (settleTimer >= settleDelay)
+ if (_settleTimer >= settleDelay)
{
- projectileSettled = true;
+ _projectileSettled = true;
// Stop camera tracking when projectile settles
- if (cameraController != null)
+ if (_cameraController != null)
{
- cameraController.StopFollowingProjectile();
+ _cameraController.StopFollowingProjectile();
}
Logging.Debug("[ProjectileTurnAction] Projectile settled - turn action complete");
@@ -119,7 +118,7 @@ namespace Minigames.FortFight.Core
else
{
// Reset settle timer if still moving
- settleTimer = 0f;
+ _settleTimer = 0f;
}
}
}
@@ -129,10 +128,10 @@ namespace Minigames.FortFight.Core
///
public void Cancel()
{
- if (slingshot != null)
+ if (_slingshot != null)
{
- slingshot.Disable();
- slingshot.OnProjectileLaunched -= HandleProjectileLaunched;
+ _slingshot.Disable();
+ _slingshot.OnProjectileLaunched -= HandleProjectileLaunched;
}
}
@@ -140,26 +139,47 @@ namespace Minigames.FortFight.Core
{
Logging.Debug($"[ProjectileTurnAction] Projectile launched: {projectile.gameObject.name}");
- launchComplete = true;
- activeProjectile = projectile;
+ _launchComplete = true;
+ _activeProjectile = projectile;
// Disable slingshot after launch
- if (slingshot != null)
+ if (_slingshot != null)
{
- slingshot.Disable();
+ _slingshot.Disable();
}
// Trigger cooldown for used ammo for this player
- if (ammoManager != null)
+ if (_ammoManager != null)
{
- ProjectileType usedAmmoType = ammoManager.GetSelectedAmmoType(playerIndex);
- ammoManager.UseAmmo(usedAmmoType, playerIndex);
+ ProjectileType usedAmmoType = _ammoManager.GetSelectedAmmoType(_playerIndex);
+ _ammoManager.UseAmmo(usedAmmoType, _playerIndex);
+ }
+
+ // Check if this is a TrashBag projectile to handle explosion tracking
+ var trashBag = projectile as TrashBagProjectile;
+ if (trashBag != null)
+ {
+ trashBag.OnTrashPiecesSpawned += HandleTrashPiecesSpawned;
}
// Start camera tracking the projectile
- if (cameraController != null && projectile != null)
+ if (_cameraController != null && projectile != null)
{
- cameraController.StartFollowingProjectile(projectile.transform);
+ _cameraController.StartFollowingProjectile(projectile.transform);
+ }
+ }
+
+ ///
+ /// Handle trash bag explosion - switch camera to follow a trash piece
+ ///
+ private void HandleTrashPiecesSpawned(Transform trashPiece)
+ {
+ if (trashPiece != null && _cameraController != null)
+ {
+ Logging.Debug($"[ProjectileTurnAction] TrashBag exploded - switching camera to trash piece");
+ _cameraController.StartFollowingProjectile(trashPiece);
+
+ // The turn will complete when the trash piece settles (using existing settle logic)
}
}
}
diff --git a/Assets/Scripts/Minigames/FortFight/Core/TurnManager.cs b/Assets/Scripts/Minigames/FortFight/Core/TurnManager.cs
index c8322f90..e2f6c3a5 100644
--- a/Assets/Scripts/Minigames/FortFight/Core/TurnManager.cs
+++ b/Assets/Scripts/Minigames/FortFight/Core/TurnManager.cs
@@ -210,9 +210,12 @@ namespace Minigames.FortFight.Core
// Set slingshot owner (used for projectile ownership tracking)
activeSlingshot.SetOwner(_currentPlayer.PlayerIndex, _currentPlayer.IsAI);
- // Set current ammo on slingshot for this player
+ // Reset ammo selection to first available weapon at start of turn
if (AmmunitionManager.Instance != null)
{
+ AmmunitionManager.Instance.SelectFirstAvailableAmmo(_currentPlayer.PlayerIndex);
+
+ // Set the selected ammo on slingshot
ProjectileConfig currentAmmo = AmmunitionManager.Instance.GetSelectedAmmoConfig(_currentPlayer.PlayerIndex);
if (currentAmmo != null)
{
diff --git a/Assets/Scripts/Minigames/FortFight/Projectiles/TrashBagProjectile.cs b/Assets/Scripts/Minigames/FortFight/Projectiles/TrashBagProjectile.cs
index 904d3d58..384685d0 100644
--- a/Assets/Scripts/Minigames/FortFight/Projectiles/TrashBagProjectile.cs
+++ b/Assets/Scripts/Minigames/FortFight/Projectiles/TrashBagProjectile.cs
@@ -1,8 +1,10 @@
-using System.Collections;
+using System;
+using System.Collections;
using Core;
using Core.Settings;
using Input;
using UnityEngine;
+using Random = UnityEngine.Random;
namespace Minigames.FortFight.Projectiles
{
@@ -23,6 +25,12 @@ namespace Minigames.FortFight.Projectiles
private bool inputEnabled = false;
private bool hasExploded = false;
+ ///
+ /// Fired when trash bag explodes and spawns pieces.
+ /// Parameters: (Transform trashPieceToFollow) - a piece for camera to follow
+ ///
+ public event Action OnTrashPiecesSpawned;
+
public override void Launch(Vector2 direction, float force)
{
base.Launch(direction, force);
@@ -145,13 +153,14 @@ namespace Minigames.FortFight.Projectiles
///
/// Spawn multiple trash pieces in a cone away from the hit surface.
/// Uses hit normal + projectile momentum for realistic splash effect.
+ /// Returns the first spawned trash piece for camera tracking.
///
- private void SpawnTrashPieces(Vector2 impactPoint, Vector2 hitNormal)
+ private Transform SpawnTrashPieces(Vector2 impactPoint, Vector2 hitNormal)
{
if (trashPiecePrefab == null)
{
Logging.Warning("[TrashBagProjectile] No trash piece prefab assigned!");
- return;
+ return null;
}
// Get settings
@@ -175,6 +184,8 @@ namespace Minigames.FortFight.Projectiles
// 70% normal (splash away from surface) + 30% reflection (maintain some momentum direction)
Vector2 baseDirection = (hitNormal * 0.7f + reflectDirection * 0.3f).normalized;
+ Transform firstPiece = null;
+
// Spawn pieces in a cone around the base direction
for (int i = 0; i < pieceCount; i++)
{
@@ -189,6 +200,12 @@ namespace Minigames.FortFight.Projectiles
Vector2 spawnOffset = pieceDirection * 0.2f; // Small offset to prevent clipping
GameObject piece = Instantiate(trashPiecePrefab, (Vector2)impactPoint + spawnOffset, Quaternion.identity);
+ // Store first piece for camera tracking
+ if (i == 0 && piece != null)
+ {
+ firstPiece = piece.transform;
+ }
+
// Setup trash piece physics
Rigidbody2D pieceRb = piece.GetComponent();
if (pieceRb != null)
@@ -203,6 +220,14 @@ namespace Minigames.FortFight.Projectiles
Logging.Debug($"[TrashBagProjectile] Spawned trash piece {i} in direction {pieceDirection}");
}
+
+ // Fire event with first piece for camera tracking
+ if (firstPiece != null)
+ {
+ OnTrashPiecesSpawned?.Invoke(firstPiece);
+ }
+
+ return firstPiece;
}
#region ITouchInputConsumer Implementation