Implement Fort Fight minigame (#75)
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Reviewed-on: #75
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Minigames.FortFight.Projectiles
|
||||
{
|
||||
/// <summary>
|
||||
/// Trash Bag projectile - splits into multiple smaller pieces on impact.
|
||||
/// Deals AOE damage in a forward cone.
|
||||
/// </summary>
|
||||
public class TrashBagProjectile : ProjectileBase
|
||||
{
|
||||
[Header("Trash Bag Specific")]
|
||||
[Tooltip("Prefab for individual trash pieces (small debris)")]
|
||||
[SerializeField] private GameObject trashPiecePrefab;
|
||||
|
||||
protected override void OnHit(Collision2D collision)
|
||||
{
|
||||
// Deal initial damage from trash bag itself
|
||||
var block = collision.gameObject.GetComponent<Fort.FortBlock>();
|
||||
if (block != null)
|
||||
{
|
||||
block.TakeDamage(Damage);
|
||||
Logging.Debug($"[TrashBagProjectile] Dealt {Damage} damage to {block.gameObject.name}");
|
||||
}
|
||||
|
||||
// Get settings for trash pieces
|
||||
var settings = GameManager.GetSettingsObject<AppleHills.Core.Settings.IFortFightSettings>();
|
||||
int pieceCount = settings?.TrashBagPieceCount ?? 8;
|
||||
|
||||
Logging.Debug($"[TrashBagProjectile] Splitting into {pieceCount} pieces");
|
||||
|
||||
// Get contact normal and impact point
|
||||
Vector2 hitNormal = collision.contacts[0].normal;
|
||||
Vector2 impactPoint = collision.contacts[0].point;
|
||||
|
||||
// Spawn trash pieces (NOT parented, so they persist as debris)
|
||||
SpawnTrashPieces(impactPoint, hitNormal);
|
||||
|
||||
// Destroy trash bag after spawning pieces
|
||||
DestroyProjectile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawn multiple trash pieces in a cone away from the hit surface.
|
||||
/// Uses hit normal + projectile momentum for realistic splash effect.
|
||||
/// </summary>
|
||||
private void SpawnTrashPieces(Vector2 impactPoint, Vector2 hitNormal)
|
||||
{
|
||||
if (trashPiecePrefab == null)
|
||||
{
|
||||
Logging.Warning("[TrashBagProjectile] No trash piece prefab assigned!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get settings
|
||||
var settings = GameManager.GetSettingsObject<AppleHills.Core.Settings.IFortFightSettings>();
|
||||
int pieceCount = settings?.TrashBagPieceCount ?? 8;
|
||||
float pieceForce = settings?.TrashBagPieceForce ?? 10f;
|
||||
float spreadAngle = settings?.TrashBagSpreadAngle ?? 60f;
|
||||
|
||||
// Calculate projectile's incoming direction (momentum)
|
||||
Vector2 incomingDirection = rb2D.linearVelocity.normalized;
|
||||
if (incomingDirection == Vector2.zero)
|
||||
{
|
||||
incomingDirection = LaunchDirection;
|
||||
}
|
||||
|
||||
// Calculate reflection direction from hit normal
|
||||
// This creates a bounce-like effect
|
||||
Vector2 reflectDirection = Vector2.Reflect(incomingDirection, hitNormal);
|
||||
|
||||
// Blend between reflection and pure normal for more variety
|
||||
// 70% normal (splash away from surface) + 30% reflection (maintain some momentum direction)
|
||||
Vector2 baseDirection = (hitNormal * 0.7f + reflectDirection * 0.3f).normalized;
|
||||
|
||||
// Spawn pieces in a cone around the base direction
|
||||
for (int i = 0; i < pieceCount; i++)
|
||||
{
|
||||
// Calculate angle offset for this piece within the spread cone
|
||||
float t = pieceCount > 1 ? i / (float)(pieceCount - 1) : 0.5f;
|
||||
float angleOffset = Mathf.Lerp(-spreadAngle / 2f, spreadAngle / 2f, t);
|
||||
float angleRadians = Mathf.Atan2(baseDirection.y, baseDirection.x) + angleOffset * Mathf.Deg2Rad;
|
||||
|
||||
Vector2 pieceDirection = new Vector2(Mathf.Cos(angleRadians), Mathf.Sin(angleRadians));
|
||||
|
||||
// Spawn trash piece slightly offset from impact point
|
||||
Vector2 spawnOffset = pieceDirection * 0.2f; // Small offset to prevent clipping
|
||||
GameObject piece = Instantiate(trashPiecePrefab, (Vector2)impactPoint + spawnOffset, Quaternion.identity);
|
||||
|
||||
// Setup trash piece physics
|
||||
Rigidbody2D pieceRb = piece.GetComponent<Rigidbody2D>();
|
||||
if (pieceRb != null)
|
||||
{
|
||||
// Apply force with some randomness for more natural spread
|
||||
float randomForce = pieceForce * Random.Range(0.8f, 1.2f);
|
||||
pieceRb.AddForce(pieceDirection * randomForce, ForceMode2D.Impulse);
|
||||
|
||||
// Add some random spin
|
||||
pieceRb.AddTorque(Random.Range(-100f, 100f));
|
||||
}
|
||||
|
||||
Logging.Debug($"[TrashBagProjectile] Spawned trash piece {i} in direction {pieceDirection}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user