Files
OpenRA/OpenRA.Mods.RA/World/ResourceClaimLayer.cs
James Dunne 80123b6aa4 Many harvester behavior improvements; summary below.
Implemented Harvester territory marking with a simple resource claim system in ResourceClaimLayer trait added to World.
Added customCost for PathSearch to support new Harvester search preferences.
Explicit delivery order forces harvester to always deliver to that refinery.
Explicit harvest order frees harvester from forced delivery refinery and allows for auto-balancing.
Harvesters auto-balance refinery choice such that no more than 3 harvesters are linked to any one refinery at a time.
Harvesters try very hard to not block the refinery dock location.
Harvesters try to avoid enemy territory when searching for resources.
Group-select harvest order intelligently disperses harvesters around the order location.
Fixed PathFinder caching to not be a sliding window. This is a correctness issue. Sliding window causes no-route paths to be cached permanently in tight move loops and doesn't allow eventual progress to be made. This may have negative performance implications.
2012-06-24 20:26:00 -05:00

122 lines
3.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public sealed class ResourceClaimLayerInfo : TraitInfo<ResourceClaimLayer>
{
}
public sealed class ResourceClaimLayer : IWorldLoaded
{
Dictionary<CPos, ResourceClaim> claimByCell;
Dictionary<Actor, ResourceClaim> claimByActor;
private void MakeClaim(Actor claimer, CPos cell)
{
UnclaimByActor(claimer);
UnclaimByCell(cell, claimer);
claimByActor[claimer] = claimByCell[cell] = new ResourceClaim(claimer, cell);
}
private void Unclaim(ResourceClaim claim, Actor claimer)
{
if (claimByActor.Remove(claim.Claimer) & claimByCell.Remove(claim.Cell))
{
if (claim.Claimer.Destroyed) return;
if (!claim.Claimer.IsInWorld) return;
if (claim.Claimer.IsDead()) return;
claim.Claimer.Trait<INotifyResourceClaimLost>().OnNotifyResourceClaimLost(claim.Claimer, claim, claimer);
}
}
public void WorldLoaded(OpenRA.World w)
{
// NOTE(jsd): 32 seems a sane default initial capacity for the total # of harvesters in a game. Purely a guesstimate.
claimByCell = new Dictionary<CPos, ResourceClaim>(32);
claimByActor = new Dictionary<Actor, ResourceClaim>(32);
}
/// <summary>
/// Attempt to claim the resource at the cell for the given actor.
/// </summary>
/// <param name="claimer"></param>
/// <param name="cell"></param>
/// <returns></returns>
public bool ClaimResource(Actor claimer, CPos cell)
{
// Has anyone else claimed this point?
ResourceClaim claim;
if (claimByCell.TryGetValue(cell, out claim))
{
// Same claimer:
if (claim.Claimer == claimer) return true;
// This is to prevent in-fighting amongst friendly harvesters:
if (claimer.Owner == claim.Claimer.Owner) return false;
if (claimer.Owner.Stances[claim.Claimer.Owner] == Stance.Ally) return false;
// If an enemy/neutral claimed this, don't respect that claim:
}
// Either nobody else claims this point or an enemy/neutral claims it:
MakeClaim(claimer, cell);
return true;
}
/// <summary>
/// Release the last resource claim made on this cell.
/// </summary>
/// <param name="cell"></param>
public void UnclaimByCell(CPos cell, Actor claimer)
{
ResourceClaim claim;
if (claimByCell.TryGetValue(cell, out claim))
Unclaim(claim, claimer);
}
/// <summary>
/// Release the last resource claim made by this actor.
/// </summary>
/// <param name="claimer"></param>
public void UnclaimByActor(Actor claimer)
{
ResourceClaim claim;
if (claimByActor.TryGetValue(claimer, out claim))
Unclaim(claim, claimer);
}
/// <summary>
/// Is the cell location <paramref name="cell"/> claimed for harvesting by any other actor?
/// </summary>
/// <param name="self"></param>
/// <param name="cell"></param>
/// <returns>true if already claimed by an ally that isn't <paramref name="self"/>; false otherwise.</returns>
public bool IsClaimedByAnyoneElse(Actor self, CPos cell, out ResourceClaim claim)
{
if (claimByCell.TryGetValue(cell, out claim))
{
// Same claimer:
if (claim.Claimer == self) return false;
// This is to prevent in-fighting amongst friendly harvesters:
if (self.Owner == claim.Claimer.Owner) return true;
if (self.Owner.Stances[claim.Claimer.Owner] == Stance.Ally) return true;
// If an enemy/neutral claimed this, don't respect that claim and fall through:
}
else
{
// No claim.
claim = null;
}
return false;
}
}
}