chunk 1: core gameplay scripts scenes runtime assets
This commit is contained in:
107
Assets/Scripts/AI/Actions/CollectBagAction.cs
Normal file
107
Assets/Scripts/AI/Actions/CollectBagAction.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// CollectBagAction — Navigate to nearest unclaimed available/dropped cash box.
|
||||
/// Prioritizes hot-drop boxes (bonus value) and closer boxes.
|
||||
/// Respects TeamBlackboard claims to prevent clustering.
|
||||
/// </summary>
|
||||
public class CollectBagAction : AIAction
|
||||
{
|
||||
public override string Name => "CollectBag";
|
||||
|
||||
public override float Score(AIBlackboard bb, TeamBlackboard tb)
|
||||
{
|
||||
// Can't collect if dead or already full
|
||||
if (bb.isDead) return 0f;
|
||||
if (bb.carriedBagCount >= 3) return 0f;
|
||||
|
||||
// No bags nearby
|
||||
int totalNearby = bb.nearbyAvailableBags.Count + bb.nearbyDroppedBags.Count;
|
||||
if (totalNearby == 0) return 0f;
|
||||
|
||||
float score = 0.5f; // Base desire to collect
|
||||
|
||||
// Bonus for hot-drop bags (time-sensitive)
|
||||
for (int i = 0; i < bb.nearbyDroppedBags.Count; i++)
|
||||
{
|
||||
if (bb.nearbyDroppedBags[i].IsHotDrop)
|
||||
{
|
||||
score += 0.2f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Distance factor — closer bags = higher score
|
||||
float distanceFactor = InverseCurve(bb.nearestBagDistance, 25f);
|
||||
score *= (0.5f + distanceFactor * 0.5f);
|
||||
|
||||
// Less desire to collect when already carrying (deposit instead)
|
||||
if (bb.carriedBagCount >= 2)
|
||||
score *= 0.3f;
|
||||
else if (bb.carriedBagCount >= 1)
|
||||
score *= 0.6f;
|
||||
|
||||
// Reduce if nearby enemies (risky to collect)
|
||||
if (bb.nearbyEnemyCount > 0 && bb.nearestEnemyDistance < 8f)
|
||||
score *= 0.6f;
|
||||
|
||||
// Low health = less collecting
|
||||
score *= (0.3f + bb.healthPercent * 0.7f);
|
||||
|
||||
return Mathf.Clamp01(score);
|
||||
}
|
||||
|
||||
public override void Execute(AIBrain brain, AIBlackboard bb, TeamBlackboard tb)
|
||||
{
|
||||
// Find best bag (prefer dropped hot-drops, then closest available)
|
||||
CashBag bestBag = null;
|
||||
float bestScore = float.MinValue;
|
||||
|
||||
// Check dropped bags first (higher priority)
|
||||
for (int i = 0; i < bb.nearbyDroppedBags.Count; i++)
|
||||
{
|
||||
CashBag bag = bb.nearbyDroppedBags[i];
|
||||
if (bag == null || bag.IsCarried) continue;
|
||||
if (tb.IsBagClaimed(bag, brain)) continue;
|
||||
|
||||
float dist = Vector3.Distance(brain.transform.position, bag.transform.position);
|
||||
float bagScore = bag.GetEffectiveValue() / Mathf.Max(dist, 1f);
|
||||
if (bag.IsHotDrop) bagScore *= 2f; // Big bonus for hot drops
|
||||
|
||||
if (bagScore > bestScore) { bestScore = bagScore; bestBag = bag; }
|
||||
}
|
||||
|
||||
// Then available bags
|
||||
if (bestBag == null)
|
||||
{
|
||||
for (int i = 0; i < bb.nearbyAvailableBags.Count; i++)
|
||||
{
|
||||
CashBag bag = bb.nearbyAvailableBags[i];
|
||||
if (bag == null || bag.IsCarried) continue;
|
||||
if (tb.IsBagClaimed(bag, brain)) continue;
|
||||
|
||||
float dist = Vector3.Distance(brain.transform.position, bag.transform.position);
|
||||
float bagScore = bag.Value / Mathf.Max(dist, 1f);
|
||||
|
||||
if (bagScore > bestScore) { bestScore = bagScore; bestBag = bag; }
|
||||
}
|
||||
}
|
||||
|
||||
if (bestBag == null)
|
||||
{
|
||||
// No unclaimed bags, go idle
|
||||
return;
|
||||
}
|
||||
|
||||
// Claim and navigate
|
||||
tb.TryClaimBag(bestBag, brain);
|
||||
bb.targetBag = bestBag;
|
||||
brain.NavigateTo(bestBag.transform.position);
|
||||
}
|
||||
|
||||
public override void OnExit(AIBrain brain, AIBlackboard bb, TeamBlackboard tb)
|
||||
{
|
||||
tb.ReleaseBagClaim(brain);
|
||||
bb.targetBag = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user