Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ProximityExternalCondition ignoring the owner change event #20511

Merged
merged 1 commit into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion OpenRA.Mods.Common/Traits/Conditions/ExternalCondition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class ExternalConditionInfo : TraitInfo
public override object Create(ActorInitializer init) { return new ExternalCondition(this); }
}

public class ExternalCondition : ITick, INotifyCreated
public class ExternalCondition : ITick, INotifyCreated, INotifyOwnerChanged
{
readonly struct TimedToken
{
Expand Down Expand Up @@ -222,6 +222,12 @@ void ITick.Tick(Actor self)

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();
Expand Down
42 changes: 36 additions & 6 deletions OpenRA.Mods.Common/Traits/Conditions/ProximityExternalCondition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class ProximityExternalConditionInfo : ConditionalTraitInfo
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;

Expand Down Expand Up @@ -123,19 +123,18 @@ void ActorEntered(Actor a)

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>()
Expand All @@ -159,5 +158,36 @@ void ActorExited(Actor a)
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;
}
}
}
}
}
1 change: 1 addition & 0 deletions OpenRA.Mods.Common/TraitsInterfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ public interface INotifyParachute { void OnParachute(Actor self); void OnLanded(

[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(); }
Expand Down