Fix ProximityExternalCondition ignoring the owner change event

This commit is contained in:
Gustas
2022-12-05 17:08:14 +02:00
committed by Matthias Mailänder
parent e22d7b31f9
commit ae45707c84
3 changed files with 44 additions and 7 deletions

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits
public override object Create(ActorInitializer init) { return new ExternalCondition(this); }
}
public class ExternalCondition : ITick, INotifyCreated
public class ExternalCondition : ITick, INotifyCreated, INotifyOwnerChanged
{
readonly struct TimedToken
{
@@ -222,6 +222,12 @@ namespace OpenRA.Mods.Common.Traits
bool Notifies(IConditionTimerWatcher watcher) { return watcher.Condition == Info.Condition; }
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
{
foreach (var pair in self.World.ActorsWithTrait<INotifyProximityOwnerChanged>())
pair.Trait.OnProximityOwnerChanged(self, oldOwner, newOwner);
}
void INotifyCreated.Created(Actor self)
{
watchers = self.TraitsImplementing<IConditionTimerWatcher>().Where(Notifies).ToArray();

View File

@@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits
public override object Create(ActorInitializer init) { return new ProximityExternalCondition(init.Self, this); }
}
public class ProximityExternalCondition : ConditionalTrait<ProximityExternalConditionInfo>, ITick, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyOtherProduction
public class ProximityExternalCondition : ConditionalTrait<ProximityExternalConditionInfo>, ITick, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyOtherProduction, INotifyProximityOwnerChanged
{
readonly Actor self;
@@ -123,19 +123,18 @@ namespace OpenRA.Mods.Common.Traits
public void UnitProducedByOther(Actor self, Actor producer, Actor produced, string productionType, TypeDictionary init)
{
// If the produced Actor doesn't occupy space, it can't be in range
// If the produced Actor doesn't occupy space, it can't be in range.
if (produced.OccupiesSpace == null)
return;
// We don't grant conditions when disabled
// We don't grant conditions when disabled.
if (IsTraitDisabled)
return;
// Work around for actors produced within the region not triggering until the second tick
// Work around for actors produced within the region not triggering until the second tick.
if ((produced.CenterPosition - self.CenterPosition).HorizontalLengthSquared <= Info.Range.LengthSquared)
{
var stance = self.Owner.RelationshipWith(produced.Owner);
if (!Info.ValidRelationships.HasRelationship(stance))
if (!Info.ValidRelationships.HasRelationship(self.Owner.RelationshipWith(produced.Owner)))
return;
var external = produced.TraitsImplementing<ExternalCondition>()
@@ -159,5 +158,36 @@ namespace OpenRA.Mods.Common.Traits
if (external.TryRevokeCondition(a, self, token))
break;
}
void INotifyProximityOwnerChanged.OnProximityOwnerChanged(Actor actor, Player oldOwner, Player newOwner)
{
// If the Actor doesn't occupy space, it can't be in range.
if (actor.OccupiesSpace == null)
return;
// We don't grant conditions when disabled.
if (IsTraitDisabled)
return;
// Work around for actors changin owner within the region.
if ((actor.CenterPosition - self.CenterPosition).HorizontalLengthSquared <= Info.Range.LengthSquared)
{
var hasRelationship = Info.ValidRelationships.HasRelationship(self.Owner.RelationshipWith(actor.Owner));
var contains = tokens.TryGetValue(actor, out var token);
if (hasRelationship && !contains)
{
var external = actor.TraitsImplementing<ExternalCondition>().FirstOrDefault(t => t.Info.Condition == Info.Condition && t.CanGrantCondition(self));
if (external != null)
tokens[actor] = external.GrantCondition(actor, self);
}
else if (!hasRelationship && contains)
{
tokens.Remove(actor);
foreach (var external in actor.TraitsImplementing<ExternalCondition>())
if (external.TryRevokeCondition(actor, self, token))
break;
}
}
}
}
}

View File

@@ -183,6 +183,7 @@ namespace OpenRA.Mods.Common.Traits
[RequireExplicitImplementation]
public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner, BitSet<CaptureType> captureTypes); }
public interface INotifyProximityOwnerChanged { void OnProximityOwnerChanged(Actor actor, Player oldOwner, Player newOwner); }
public interface INotifyDiscovered { void OnDiscovered(Actor self, Player discoverer, bool playNotification); }
public interface IRenderActorPreviewInfo : ITraitInfoInterface { IEnumerable<IActorPreview> RenderPreview(ActorPreviewInitializer init); }
public interface ICruiseAltitudeInfo : ITraitInfoInterface { WDist GetCruiseAltitude(); }