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
Rewrite and simplify GPS dots #14117
Conversation
7c52238
to
93ed24b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good in testing. Works just as I imagined it.
I do wonder about making spies the color of their disguise. If you see a dot that's your color, there is only one thing in the game that can be. It'll tell you exactly what's going on instead of, 'He has a guy there'.
Needs rebase. |
93ed24b
to
b778e55
Compare
Rebased. |
b778e55
to
9ca225b
Compare
The motivation here is mainly technical. Having special case code in the GPS to check for “is this a disguised spy? Then remove the dot” is horrible for code generality. It is much nicer to have a blanket rule for “show dot for any hidden unit in the colour that the unit appears to the viewer”. I figured that this also matches the way that the satellite logically works: looking at the battlefield and reporting the location and owner of everything it sees. If you think that change will unduely hurt gameplay then I don’t have a strong objection against adding it back, but it would be a bit of a shame. |
@pchote I understand that as "dots for spies will be shown in the color of the player who controls them, regardless of their current disguise (or lack of)". Is that correct?
And @Smittytron is worried that the spy dot will show up as the color of their disguise. Is there a misunderstanding here? |
The spy dot will show up as the color of the disguise. |
Then I also wonder if that is a good idea. As Smitty put it "there is only one thing in the game that can be" On second thought that would make GPS a great counter to spies so maybe not such a bad idea. And yeah - that's how a satellite logically works. |
What about leaving spy dots as the color of their owner? The player with GPS will know something is there, they just won't know it's a spy until they see it. If this is also technically unfeasible, I have no objections to shipping this PR as is. Fixing GPS is much more important to gameplay. |
9ca225b
to
a622b48
Compare
Updated. I kept my first approach, but added a check to hide the indicator if it would otherwise be drawn in the color of the viewer or one of their allies. This is an improvement over the original (release/playtest) behavior, which would hide the indicator for all disguised spies, even if they were disguised as an enemy player. Now, in a FFA game with two enemies then enemy A's spy disguised as you will be hidden, and enemy A's spy disguised as enemy B will show as enemy B's. |
436b742
to
709a270
Compare
toPlayer.IsAlliedWith(actor.EffectiveOwner.Owner)) | ||
return false; | ||
|
||
return !visibility.IsVisible(actor, toPlayer) && toPlayer.Shroud.IsExplored(actor.CenterPosition); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You specify visibility = actor.TraitOrDefault<IDefaultVisibility>();
but don't appear to have handling for when it's null.
visibilityModifiers = actor.TraitsImplementing<IVisibilityModifier>().ToArray(); | ||
|
||
dotStates = new PlayerDictionary<DotState>(actor.World, | ||
player => new DotState(actor, player.PlayerActor.Trait<GpsWatcher>(), player.PlayerActor.TraitOrDefault<FrozenActorLayer>())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Should be indented.
@@ -90,7 +90,8 @@ protected virtual Activity InnerTick(Actor self, AttackBase attack) | |||
// HACK: This would otherwise break targeting frozen actors | |||
// The problem is that Shroud.IsTargetable returns false (as it should) for | |||
// frozen actors, but we do want to explicitly target the underlying actor here. | |||
if (!attack.Info.IgnoresVisibility && type == TargetType.Actor && !Target.Actor.Info.HasTraitInfo<FrozenUnderFogInfo>() && !self.Owner.CanTargetActor(Target.Actor)) | |||
if (!attack.Info.IgnoresVisibility && type == TargetType.Actor && !Target.Actor.Info.HasTraitInfo<FrozenUnderFogInfo>() | |||
&& !Target.Actor.CanBeViewedByPlayer(self.Owner)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to throw some more newlines in to aid readability since you're here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some small things to clean up, otherwise works as advertised.
Also needs a rebase.
OpenRA.Mods.Cnc/Traits/GpsWatcher.cs
Outdated
@@ -92,20 +90,11 @@ void RefreshGranted() | |||
tp.Trait.OnGpsRefresh(tp.Actor, owner); | |||
} | |||
|
|||
public bool HasFogVisibility() | |||
bool IPreventsShroudReset.PreventShroudReset(Actor self, Player byPlayer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a point to having these arguments if the only implementation of the interface is not going to be using them?
Flag was raised when I noticed the only two calls to this method passed logically different things as arguments, so something was bogus...
@@ -85,7 +85,7 @@ public override Activity Tick(Actor self) | |||
|
|||
// Target moved under the fog. Move to its last known position. | |||
if (Target.Type == TargetType.Actor && canHideUnderFog | |||
&& !self.Owner.CanTargetActor(Target.Actor)) | |||
&& !target.Actor.CanBeViewedByPlayer(self.Owner)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small style thing, but the Target
property wrapping the target
variable and then we using both throughout the class is messy, and you switched one of the usages from one to the other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Player.CanTargetActor(Actor)
has been removed. This is just switching it for the otherwise equivalent Actor.CanBeViewedByPlayer(Player)
, with no other changes to this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean Target.Actor
vs target.Actor
. That's the "change" here.
player => new DotState(actor, player.PlayerActor.Trait<GpsWatcher>(), player.PlayerActor.TraitOrDefault<FrozenActorLayer>())); | ||
} | ||
|
||
bool ShouldRender(DotState state, Player toPlayer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may be wrong here after all this time, but I have a nagging feeling the checks in this method aren't exactly ordered by how expensive they are to make.
On the offchance that I'm right, it's something small but worth the hassle.
// Hide the indicator if the unit appears to be owned by an allied player | ||
if (actor.EffectiveOwner != null && actor.EffectiveOwner.Owner != null && | ||
toPlayer.IsAlliedWith(actor.EffectiveOwner.Owner)) | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check means that you woudn't see dots for spies that are disguised as your/allied soldiers.
Simply removing it should be more than fine, as if it really was an allied unit it wouldn't be under fog (barring some really sick edge case in scripted missions?!?), so you wouldn't be seeing a dot anyway, and without it you see a dot in the proper color.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment about this in the original PR description and the discussion that followed. This was an intentional change in response to that PR feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[13:45] <+penev> fine, I guess it's too obvious if you see a dot in your color...
[13:45] <+penev> damn gameplay implications...
[13:45] <+penev> always messing with good code
[13:45] <+penev> :D
TODO: include a fix for #14229. |
709a270
to
2722ea5
Compare
Updated. #14229 requires cleaning up a different set of ugly GPS code than what is here, so i'm going to leave that for a later PR. |
2722ea5
to
afacac5
Compare
👍 |
Closes #14115.
The GPS code is a giant hack that doesn't fit with the current engine design, and can't reasonably be changed without changing its behaviour. #14115 shows that the legacy behaviour is controversial, and provides good motivation to rip out the problematic code.
The GPS dots are now purely visual, rendering for enemy actors who are (a) under fog (not shroud), (b) otherwise visible if the fog wasn't there (i.e. not cloaked), and (c) not already showing a visible frozen actor. Disguised actors (i.e. spies) now show indicators in their effective owner color instead of being hidden.