Merge pull request #4858 from cjshmyr/spyfix

Spy class refactoring
This commit is contained in:
Matthias Mailänder
2014-03-16 09:04:16 +01:00
12 changed files with 132 additions and 110 deletions

View File

@@ -115,6 +115,8 @@ NEW:
Updated shroud-based traits to use world units.
Renamed AttackTesla into AttackCharge and un-hardcoded initial charge delay and delay for additional charges.
Updated RenderBuildingCharge so you can set a custom charge sequence name (default is active).
Added IEffectiveOwner interface for traits/logic that temporarily alter an actor's apparent owner.
Renamed Spy trait to Disguise, SpyToolTip trait to DisguiseToolTip, and RenderSpy trait to RenderDisguise.
Server:
Message of the day is now shared between all mods and a default motd.txt gets created in the user directory.
Asset Browser:

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -29,8 +29,10 @@ namespace OpenRA
Lazy<IOccupySpace> occupySpace;
Lazy<IFacing> facing;
Lazy<Health> health;
Lazy<IEffectiveOwner> effectiveOwner;
public IOccupySpace OccupiesSpace { get { return occupySpace.Value; } }
public IEffectiveOwner EffectiveOwner { get { return effectiveOwner.Value; } }
public CPos Location { get { return occupySpace.Value.TopLeft; } }
public WPos CenterPosition { get { return occupySpace.Value.CenterPosition; } }
@@ -74,6 +76,7 @@ namespace OpenRA
facing = Lazy.New(() => TraitOrDefault<IFacing>());
health = Lazy.New(() => TraitOrDefault<Health>());
effectiveOwner = Lazy.New(() => TraitOrDefault<IEffectiveOwner>());
applyIRender = (x, wr) => x.Render(this, wr);
applyRenderModifier = (m, p, wr) => p.ModifyRender(this, wr, m);

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -84,6 +84,11 @@ namespace OpenRA.Traits
bool IsValidTarget(Actor self, Actor saboteur);
}
public interface IStoreOre { int Capacity { get; } }
public interface IEffectiveOwner
{
bool Disguised { get; }
Player Owner { get; }
}
public interface IToolTip
{
string Name();

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -15,20 +15,14 @@ namespace OpenRA.Mods.RA
{
public static class ActorExts
{
static bool IsDisguisedSpy(this Actor a)
{
var spy = a.TraitOrDefault<Spy>();
return spy != null && spy.Disguised;
}
public static bool AppearsFriendlyTo(this Actor self, Actor toActor)
{
var stance = toActor.Owner.Stances[self.Owner];
if (stance == Stance.Ally)
return true;
if (self.IsDisguisedSpy() && !toActor.HasTrait<IgnoresDisguise>())
return toActor.Owner.Stances[self.Trait<Spy>().disguisedAsPlayer] == Stance.Ally;
if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised && !toActor.HasTrait<IgnoresDisguise>())
return toActor.Owner.Stances[self.EffectiveOwner.Owner] == Stance.Ally;
return stance == Stance.Ally;
}
@@ -39,8 +33,8 @@ namespace OpenRA.Mods.RA
if (stance == Stance.Ally)
return false; /* otherwise, we'll hate friendly disguised spies */
if (self.IsDisguisedSpy() && !toActor.HasTrait<IgnoresDisguise>())
return toActor.Owner.Stances[self.Trait<Spy>().disguisedAsPlayer] == Stance.Enemy;
if (self.EffectiveOwner != null && self.EffectiveOwner.Disguised && !toActor.HasTrait<IgnoresDisguise>())
return toActor.Owner.Stances[self.EffectiveOwner.Owner] == Stance.Enemy;
return stance == Stance.Enemy;
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -16,56 +16,59 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
class SpyToolTipInfo : TooltipInfo, Requires<SpyInfo>
class DisguiseToolTipInfo : TooltipInfo, Requires<DisguiseInfo>
{
public override object Create (ActorInitializer init) { return new SpyToolTip(init.self, this); }
public override object Create (ActorInitializer init) { return new DisguiseToolTip(init.self, this); }
}
class SpyToolTip : IToolTip
class DisguiseToolTip : IToolTip
{
Actor self;
TooltipInfo Info;
Spy spy;
TooltipInfo info;
Disguise disguise;
public DisguiseToolTip(Actor self, TooltipInfo info)
{
this.self = self;
this.info = info;
disguise = self.Trait<Disguise>();
}
public string Name()
{
if (spy.Disguised)
if (disguise.Disguised)
{
if (self.Owner == self.World.LocalPlayer)
return "{0} ({1})".F(Info.Name, spy.disguisedAsName);
return spy.disguisedAsName;
return "{0} ({1})".F(info.Name, disguise.AsName);
return disguise.AsName;
}
return Info.Name;
return info.Name;
}
public Player Owner()
{
if (spy.Disguised)
if (disguise.Disguised)
{
if (self.Owner == self.World.LocalPlayer)
return self.Owner;
return spy.disguisedAsPlayer;
return disguise.AsPlayer;
}
return self.Owner;
}
public SpyToolTip( Actor self, TooltipInfo info )
{
this.self = self;
Info = info;
spy = self.Trait<Spy>();
}
}
class DisguiseInfo : TraitInfo<Disguise> { }
class SpyInfo : TraitInfo<Spy> { }
class Spy : IIssueOrder, IResolveOrder, IOrderVoice, IRadarColorModifier, INotifyAttack
class Disguise : IEffectiveOwner, IIssueOrder, IResolveOrder, IOrderVoice, IRadarColorModifier, INotifyAttack
{
public Player disguisedAsPlayer;
public string disguisedAsSprite, disguisedAsName;
public Player AsPlayer;
public string AsSprite;
public string AsName;
public bool Disguised { get { return disguisedAsPlayer != null; } }
public bool Disguised { get { return AsPlayer != null; } }
public Player Owner { get { return AsPlayer; } }
public IEnumerable<IOrderTargeter> Orders
{
@@ -79,6 +82,7 @@ namespace OpenRA.Mods.RA
{
if (order.OrderID == "Disguise")
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
return null;
}
@@ -97,7 +101,7 @@ namespace OpenRA.Mods.RA
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "Disguise") ? "Attack" : null;
return order.OrderString == "Disguise" ? "Attack" : null;
}
public Color RadarColorOverride(Actor self)
@@ -105,25 +109,24 @@ namespace OpenRA.Mods.RA
if (!Disguised || self.Owner.IsAlliedWith(self.World.RenderPlayer))
return self.Owner.Color.RGB;
return disguisedAsPlayer.Color.RGB;
return AsPlayer.Color.RGB;
}
void DisguiseAs(Actor target)
{
var tooltip = target.TraitsImplementing<IToolTip>().FirstOrDefault();
disguisedAsName = tooltip.Name();
disguisedAsPlayer = tooltip.Owner();
disguisedAsSprite = target.Trait<RenderSprites>().GetImage(target);
AsName = tooltip.Name();
AsPlayer = tooltip.Owner();
AsSprite = target.Trait<RenderSprites>().GetImage(target);
}
void DropDisguise()
{
disguisedAsName = null;
disguisedAsPlayer = null;
disguisedAsSprite = null;
AsName = null;
AsPlayer = null;
AsSprite = null;
}
/* lose our disguise if we attack anything */
public void Attacking(Actor self, Target target, Armament a, Barrel barrel) { DropDisguise(); }
}

View File

@@ -1,6 +1,6 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.RA.Effects
Lazy<HiddenUnderFog> huf;
Lazy<FrozenUnderFog> fuf;
Lazy<Spy> spy;
Lazy<Disguise> disguise;
Lazy<Cloak> cloak;
Cache<Player, GpsWatcher> watcher;
Cache<Player, FrozenActorLayer> frozen;
@@ -53,7 +53,7 @@ namespace OpenRA.Mods.RA.Effects
huf = Lazy.New(() => self.TraitOrDefault<HiddenUnderFog>());
fuf = Lazy.New(() => self.TraitOrDefault<FrozenUnderFog>());
spy = Lazy.New(() => self.TraitOrDefault<Spy>());
disguise = Lazy.New(() => self.TraitOrDefault<Disguise>());
cloak = Lazy.New(() => self.TraitOrDefault<Cloak>());
watcher = new Cache<Player, GpsWatcher>(p => p.PlayerActor.Trait<GpsWatcher>());
@@ -65,7 +65,7 @@ namespace OpenRA.Mods.RA.Effects
if (cloak.Value != null && cloak.Value.Cloaked)
return false;
if (spy.Value != null && spy.Value.Disguised)
if (disguise.Value != null && disguise.Value.Disguised)
return false;
if (huf.Value != null && !huf.Value.IsVisible(self, self.World.RenderPlayer))

View File

@@ -320,7 +320,7 @@
<Compile Include="Render\RenderHarvester.cs" />
<Compile Include="Render\RenderInfantry.cs" />
<Compile Include="Render\RenderInfantryPanic.cs" />
<Compile Include="Render\RenderSpy.cs" />
<Compile Include="Render\RenderDisguise.cs" />
<Compile Include="Render\RenderLandingCraft.cs" />
<Compile Include="Render\RenderUnit.cs" />
<Compile Include="Render\RenderUnitReload.cs" />
@@ -348,7 +348,7 @@
<Compile Include="SmokeTrailWhenDamaged.cs" />
<Compile Include="SpawnMPUnits.cs" />
<Compile Include="SpawnMapActors.cs" />
<Compile Include="Spy.cs" />
<Compile Include="Disguise.cs" />
<Compile Include="StoresOre.cs" />
<Compile Include="StrategicVictoryConditions.cs" />
<Compile Include="SupplyTruck.cs" />

View File

@@ -0,0 +1,50 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
namespace OpenRA.Mods.RA.Render
{
class RenderDisguiseInfo : RenderInfantryProneInfo
{
public override object Create(ActorInitializer init) { return new RenderDisguise(init.self, this); }
}
class RenderDisguise : RenderInfantryProne
{
RenderDisguiseInfo info;
string intendedSprite;
Disguise disguise;
public RenderDisguise(Actor self, RenderDisguiseInfo info)
: base(self, info)
{
this.info = info;
disguise = self.Trait<Disguise>();
intendedSprite = disguise.AsSprite;
}
protected override string PaletteName(Actor self)
{
var player = disguise.AsPlayer ?? self.Owner;
return info.Palette ?? info.PlayerPalette + player.InternalName;
}
public override void Tick(Actor self)
{
if (disguise.AsSprite != intendedSprite)
{
intendedSprite = disguise.AsSprite;
anim.ChangeImage(intendedSprite ?? GetImage(self), info.StandAnimations.Random(Game.CosmeticRandom));
UpdatePalette();
}
base.Tick(self);
}
}
}

View File

@@ -1,48 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
namespace OpenRA.Mods.RA.Render
{
class RenderSpyInfo : RenderInfantryProneInfo
{
public override object Create(ActorInitializer init) { return new RenderSpy(init.self, this); }
}
class RenderSpy : RenderInfantryProne
{
RenderSpyInfo info;
string disguisedAsSprite;
Spy spy;
public RenderSpy(Actor self, RenderSpyInfo info) : base(self, info)
{
this.info = info;
spy = self.Trait<Spy>();
disguisedAsSprite = spy.disguisedAsSprite;
}
protected override string PaletteName(Actor self)
{
var player = spy.disguisedAsPlayer ?? self.Owner;
return info.Palette ?? info.PlayerPalette + player.InternalName;
}
public override void Tick(Actor self)
{
if (spy.disguisedAsSprite != disguisedAsSprite)
{
disguisedAsSprite = spy.disguisedAsSprite;
anim.ChangeImage(disguisedAsSprite ?? GetImage(self), info.StandAnimations.Random(Game.CosmeticRandom));
UpdatePalette();
}
base.Tick(self);
}
}
}

View File

@@ -150,6 +150,19 @@ namespace OpenRA.Utility
node.Key = "Immobile";
}
// Spy was renamed to Disguise
if (engineVersion < 20140314)
{
if (depth == 1 && node.Key == "Spy")
node.Key = "Disguise";
if (depth == 1 && node.Key == "SpyToolTip")
node.Key = "DisguiseToolTip";
if (depth == 1 && node.Key == "RenderSpy")
node.Key = "RenderDisguise";
}
UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1);
}
}

View File

@@ -194,7 +194,7 @@ SPY:
Hotkey: p
Valued:
Cost: 500
SpyToolTip:
DisguiseToolTip:
Name: Spy
Description: Infiltrates enemy structures to gather \nintelligence. Exact effect depends on the \nbuilding infiltrated.\n Strong vs Nothing\n Weak vs Everything\n Special Ability: Disguised
Selectable:
@@ -209,12 +209,12 @@ SPY:
Passenger:
PipType: Yellow
TakeCover:
Spy:
Disguise:
Infiltrates:
Types: Cash, SupportPower, Exploration
-AutoTarget:
-RenderInfantry:
RenderSpy:
RenderDisguise:
IdleAnimations: idle1,idle2
StandAnimations: stand,stand2
Armament:

View File

@@ -273,7 +273,7 @@ CHAMSPY:
Hotkey: p
Valued:
Cost: 700
SpyToolTip:
DisguiseToolTip:
Name: Chameleon Spy
Description: Infiltrates enemy structures to gather \nintelligence. Exact effect depends on the \nbuilding infiltrated.\n Strong vs Nothing\n Weak vs Everything\n Special Ability: Disguised
Selectable:
@@ -287,12 +287,12 @@ CHAMSPY:
Range: 9c0
Passenger:
TakeCover:
Spy:
Disguise:
Infiltrates:
Types: Cash, SupportPower, Exploration
-AutoTarget:
-RenderInfantry:
RenderSpy:
RenderDisguise:
IdleAnimations: idle1,idle2
CYBORG: