separate spy disguise and infiltrate

- add thief to classic-ra & monster tank madness
- remove crude workarounds for allies04
This commit is contained in:
Matthias Mailänder
2013-03-09 13:13:21 +01:00
parent ca6cc3fbe1
commit 49cfa21ddb
15 changed files with 190 additions and 80 deletions

View File

@@ -66,7 +66,7 @@ namespace OpenRA.Traits
public interface INotifyOwnerChanged { void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner); } public interface INotifyOwnerChanged { void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner); }
public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); } public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); }
public interface INotifyOtherCaptured { void OnActorCaptured(Actor self, Actor captured, Actor captor, Player oldOwner, Player newOwner); } public interface INotifyOtherCaptured { void OnActorCaptured(Actor self, Actor captured, Actor captor, Player oldOwner, Player newOwner); }
public interface IAcceptSpy { void OnInfiltrate(Actor self, Actor spy); } public interface IAcceptInfiltrator { void OnInfiltrate(Actor self, Actor infiltrator); }
public interface IStoreOre { int Capacity { get; } } public interface IStoreOre { int Capacity { get; } }
public interface IToolTip public interface IToolTip
{ {

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA.Activities
if( !target.OccupiesSpace.OccupiedCells().Any( x => x.First == self.Location ) ) if( !target.OccupiesSpace.OccupiedCells().Any( x => x.First == self.Location ) )
return NextActivity; return NextActivity;
foreach (var t in target.TraitsImplementing<IAcceptSpy>()) foreach (var t in target.TraitsImplementing<IAcceptInfiltrator>())
t.OnInfiltrate(target, self); t.OnInfiltrate(target, self);
if (self.HasTrait<DontDestroyWhenInfiltrating>()) if (self.HasTrait<DontDestroyWhenInfiltrating>())

View File

@@ -25,16 +25,16 @@ namespace OpenRA.Mods.RA
public object Create(ActorInitializer init) { return new InfiltrateForCash(this); } public object Create(ActorInitializer init) { return new InfiltrateForCash(this); }
} }
class InfiltrateForCash : IAcceptSpy class InfiltrateForCash : IAcceptInfiltrator
{ {
InfiltrateForCashInfo info; InfiltrateForCashInfo info;
public InfiltrateForCash(InfiltrateForCashInfo info) { this.info = info; } public InfiltrateForCash(InfiltrateForCashInfo info) { this.info = info; }
public void OnInfiltrate(Actor self, Actor spy) public void OnInfiltrate(Actor self, Actor infiltrator)
{ {
var targetResources = self.Owner.PlayerActor.Trait<PlayerResources>(); var targetResources = self.Owner.PlayerActor.Trait<PlayerResources>();
var spyResources = spy.Owner.PlayerActor.Trait<PlayerResources>(); var spyResources = infiltrator.Owner.PlayerActor.Trait<PlayerResources>();
var toTake = (targetResources.Cash + targetResources.Ore) * info.Percentage / 100; var toTake = (targetResources.Cash + targetResources.Ore) * info.Percentage / 100;
var toGive = Math.Max(toTake, info.Minimum); var toGive = Math.Max(toTake, info.Minimum);
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA
Sound.PlayToPlayer(self.Owner, info.SoundToVictim); Sound.PlayToPlayer(self.Owner, info.SoundToVictim);
self.World.AddFrameEndTask(w => w.Add(new CashTick(toGive, 30, 2, self.CenterLocation, self.World.AddFrameEndTask(w => w.Add(new CashTick(toGive, 30, 2, self.CenterLocation,
spy.Owner.ColorRamp.GetColor(0)))); infiltrator.Owner.ColorRamp.GetColor(0))));
} }
} }
} }

View File

@@ -16,11 +16,11 @@ namespace OpenRA.Mods.RA
{ {
class InfiltrateForExplorationInfo : TraitInfo<InfiltrateForExploration> {} class InfiltrateForExplorationInfo : TraitInfo<InfiltrateForExploration> {}
class InfiltrateForExploration : IAcceptSpy class InfiltrateForExploration : IAcceptInfiltrator
{ {
public void OnInfiltrate(Actor self, Actor spy) public void OnInfiltrate(Actor self, Actor infiltrator)
{ {
spy.Owner.Shroud.MergeShroud(self.Owner.Shroud); infiltrator.Owner.Shroud.MergeShroud(self.Owner.Shroud);
if (!self.Owner.HasFogVisibility()) if (!self.Owner.HasFogVisibility())
self.Owner.Shroud.ResetExploration(); self.Owner.Shroud.ResetExploration();
} }

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA
public object Create(ActorInitializer init) { return new InfiltrateForSupportPower(this); } public object Create(ActorInitializer init) { return new InfiltrateForSupportPower(this); }
} }
class InfiltrateForSupportPower : IAcceptSpy class InfiltrateForSupportPower : IAcceptInfiltrator
{ {
InfiltrateForSupportPowerInfo Info; InfiltrateForSupportPowerInfo Info;
@@ -29,11 +29,11 @@ namespace OpenRA.Mods.RA
Info = info; Info = info;
} }
public void OnInfiltrate(Actor self, Actor spy) public void OnInfiltrate(Actor self, Actor infiltrator)
{ {
spy.World.AddFrameEndTask(w => w.CreateActor(Info.Proxy, new TypeDictionary infiltrator.World.AddFrameEndTask(w => w.CreateActor(Info.Proxy, new TypeDictionary
{ {
new OwnerInit( spy.Owner ) new OwnerInit(infiltrator.Owner)
})); }));
} }
} }

View File

@@ -0,0 +1,114 @@
#region Copyright & License Information
/*
* Copyright 2007-2012 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
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Buildings;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits;
using OpenRA.Mods.RA.Missions;
namespace OpenRA.Mods.RA
{
class InfiltratesInfo : ITraitInfo
{
public string[] InfiltrateTypes = {"Cash", "SupportPower", "Exploration"};
public object Create(ActorInitializer init) { return new Infiltrates(this); }
}
class Infiltrates : IIssueOrder, IResolveOrder, IOrderVoice
{
public readonly InfiltratesInfo Info;
public Infiltrates(InfiltratesInfo info)
{
Info = info;
}
public IEnumerable<IOrderTargeter> Orders
{
get
{
yield return new InfiltratorOrderTargeter(target => CanInfiltrate(target));
}
}
public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)
{
if (order.OrderID == "Infiltrate")
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
return null;
}
public string VoicePhraseForOrder(Actor self, Order order)
{
return (order.OrderString == "Infiltrate" && CanInfiltrate(order.TargetActor)) ? "Attack" : null;
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Infiltrate")
{
if (!CanInfiltrate(order.TargetActor))
return;
self.SetTargetLine(Target.FromOrder(order), Color.Red);
self.CancelActivity();
self.QueueActivity(new Enter(order.TargetActor));
self.QueueActivity(new Infiltrate(order.TargetActor));
}
}
bool CanInfiltrate(Actor target)
{
if (Info.InfiltrateTypes.Contains("Cash") && target.HasTrait<InfiltrateForCash>())
return true;
if (Info.InfiltrateTypes.Contains("SupportPower") && target.HasTrait<InfiltrateForSupportPower>())
return true;
if (Info.InfiltrateTypes.Contains("Exploration") && target.HasTrait<InfiltrateForExploration>())
return true;
if (Info.InfiltrateTypes.Contains("MissionObjective") && target.HasTrait<InfiltrateForMissionObjective>())
return true;
return false;
}
class InfiltratorOrderTargeter : UnitTraitOrderTargeter<IAcceptInfiltrator>
{
readonly Func<Actor, bool> useEnterCursor;
public InfiltratorOrderTargeter(Func<Actor, bool> useEnterCursor) : base("Infiltrate", 7, "enter", true, false)
{
ForceAttack=false;
this.useEnterCursor = useEnterCursor;
}
public override bool CanTargetActor(Actor self, Actor target, bool forceAttack, bool forceQueued, ref string cursor)
{
if (!base.CanTargetActor(self, target, forceAttack, forceQueued, ref cursor))
return false;
if (!useEnterCursor(target))
cursor = "enter-blocked";
return true;
}
}
}
}

View File

@@ -410,7 +410,7 @@ namespace OpenRA.Mods.RA.Missions
}; };
lab = actors["Lab"]; lab = actors["Lab"];
lab.AddTrait(new InfiltrateAction(OnLabInfiltrated)); lab.AddTrait(new InfiltrateForMissionObjective(OnLabInfiltrated));
lab.AddTrait(new TransformedAction(self => lab = self)); lab.AddTrait(new TransformedAction(self => lab = self));
reinforcementsEntryPoint = actors["ReinforcementsEntryPoint"]; reinforcementsEntryPoint = actors["ReinforcementsEntryPoint"];
@@ -456,13 +456,17 @@ namespace OpenRA.Mods.RA.Missions
public object Create(ActorInitializer init) { return new Allies04Hijackable(init.self); } public object Create(ActorInitializer init) { return new Allies04Hijackable(init.self); }
} }
class Allies04Hijackable : IAcceptSpy, INotifyPassengerExited class Allies04Hijackable : IAcceptInfiltrator, INotifyPassengerExited
{ {
public Player OldOwner; public Player OldOwner;
void OnTruckHijacked(Actor spy) { }
public Allies04Hijackable(Actor self) public Allies04Hijackable(Actor self)
{ {
OldOwner = self.Owner; OldOwner = self.Owner;
self.AddTrait(new InfiltrateForMissionObjective(OnTruckHijacked));
} }
public void OnInfiltrate(Actor self, Actor spy) public void OnInfiltrate(Actor self, Actor spy)

View File

@@ -230,11 +230,11 @@ namespace OpenRA.Mods.RA.Missions
} }
} }
class InfiltrateAction : IAcceptSpy class InfiltrateForMissionObjective : IAcceptInfiltrator
{ {
Action<Actor> a; Action<Actor> a;
public InfiltrateAction(Action<Actor> a) public InfiltrateForMissionObjective(Action<Actor> a)
{ {
this.a = a; this.a = a;
} }

View File

@@ -329,7 +329,7 @@ namespace OpenRA.Mods.RA.Missions
world.CreateActor("camera", greece, provingGroundsCameraPoint.Location, null); world.CreateActor("camera", greece, provingGroundsCameraPoint.Location, null);
superTankDome = actors["SuperTankDome"]; superTankDome = actors["SuperTankDome"];
superTankDome.AddTrait(new InfiltrateAction(OnSuperTankDomeInfiltrated)); superTankDome.AddTrait(new InfiltrateForMissionObjective(OnSuperTankDomeInfiltrated));
superTankDome.AddTrait(new TransformedAction(self => superTankDome = self)); superTankDome.AddTrait(new TransformedAction(self => superTankDome = self));
Game.MoveViewport(startEntryPoint.Location.ToFloat2()); Game.MoveViewport(startEntryPoint.Location.ToFloat2());

View File

@@ -409,6 +409,7 @@
<Compile Include="CloakPaletteEffect.cs" /> <Compile Include="CloakPaletteEffect.cs" />
<Compile Include="Widgets\ColorPreviewManagerWidget.cs" /> <Compile Include="Widgets\ColorPreviewManagerWidget.cs" />
<Compile Include="FogPalette.cs" /> <Compile Include="FogPalette.cs" />
<Compile Include="Infiltrates.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj"> <ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">

View File

@@ -84,15 +84,12 @@ namespace OpenRA.Mods.RA
{ {
get get
{ {
yield return new UnitTraitOrderTargeter<IAcceptSpy>( "SpyInfiltrate", 7, "enter", true, false ) { ForceAttack=false }; yield return new UnitTraitOrderTargeter<RenderInfantry>("Disguise", 7, "ability", true, true) { ForceAttack=false };
yield return new UnitTraitOrderTargeter<RenderInfantry>( "Disguise", 7, "ability", true, true ) { ForceAttack=false };
} }
} }
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued ) public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
{ {
if( order.OrderID == "SpyInfiltrate" )
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
if( order.OrderID == "Disguise" ) if( order.OrderID == "Disguise" )
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor }; return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
return null; return null;
@@ -100,14 +97,6 @@ namespace OpenRA.Mods.RA
public void ResolveOrder(Actor self, Order order) public void ResolveOrder(Actor self, Order order)
{ {
if (order.OrderString == "SpyInfiltrate")
{
self.SetTargetLine(Target.FromOrder(order), Color.Red);
self.CancelActivity();
self.QueueActivity(new Enter(order.TargetActor));
self.QueueActivity(new Infiltrate(order.TargetActor));
}
if (order.OrderString == "Disguise") if (order.OrderString == "Disguise")
{ {
var target = order.TargetActor == self ? null : order.TargetActor; var target = order.TargetActor == self ? null : order.TargetActor;
@@ -121,8 +110,7 @@ namespace OpenRA.Mods.RA
public string VoicePhraseForOrder(Actor self, Order order) public string VoicePhraseForOrder(Actor self, Order order)
{ {
return (order.OrderString == "Disguise" return (order.OrderString == "Disguise") ? "Attack" : null;
|| order.OrderString == "SpyInfiltrate") ? "Attack" : null;
} }
public Color RadarColorOverride(Actor self) public Color RadarColorOverride(Actor self)

View File

@@ -190,6 +190,8 @@ SPY:
PipType: Yellow PipType: Yellow
TakeCover: TakeCover:
Spy: Spy:
Infiltrates:
InfiltrateTypes: SupportPower, Exploration
-AutoTarget: -AutoTarget:
AttackMove: AttackMove:
JustMove: true JustMove: true
@@ -197,6 +199,36 @@ SPY:
RenderSpy: RenderSpy:
IdleAnimations: idle1,idle2 IdleAnimations: idle1,idle2
THF:
Inherits: ^Infantry
Buildable:
Queue: Infantry
BuildPaletteOrder: 60
Prerequisites: techcenter, tent
Owner: allies
Valued:
Cost: 400
Tooltip:
Name: Thief
Description: Steals enemy credits.\n Strong vs Nothing\n Weak vs Everything\n
Selectable:
Voice: ThiefVoice
Bounds: 12,17,0,-9
Health:
HP: 25
Mobile:
Speed: 4
RevealsShroud:
Range: 5
Passenger:
PipType: Yellow
Infiltrates:
InfiltrateTypes: Cash
TakeCover:
-AutoTarget:
AttackMove:
JustMove: true
E7: E7:
Inherits: ^Infantry Inherits: ^Infantry
Buildable: Buildable:

View File

@@ -301,27 +301,27 @@ Actors:
Actor83: ftur Actor83: ftur
Location: 67,34 Location: 67,34
Owner: Soviets Owner: Soviets
Actor73: spen.noinfiltrate Actor73: spen
Location: 31,82 Location: 31,82
Owner: Soviets Owner: Soviets
Actor37: dome.noinfiltrate Actor37: dome
Location: 44,57 Location: 44,57
Owner: Soviets Owner: Soviets
Actor65: sam Actor65: sam
Location: 50,37 Location: 50,37
Owner: Soviets Owner: Soviets
TurretFacing: 192 TurretFacing: 192
Actor70: spen.noinfiltrate Actor70: spen
Location: 39,71 Location: 39,71
Owner: Soviets Owner: Soviets
Actor71: spen.noinfiltrate Actor71: spen
Location: 25,68 Location: 25,68
Owner: Soviets Owner: Soviets
Actor64: sam Actor64: sam
Location: 28,43 Location: 28,43
Owner: Soviets Owner: Soviets
TurretFacing: 48 TurretFacing: 48
Actor72: spen.noinfiltrate Actor72: spen
Location: 23,76 Location: 23,76
Owner: Soviets Owner: Soviets
Actor88: tsla Actor88: tsla
@@ -465,13 +465,13 @@ Actors:
Actor130: apwr Actor130: apwr
Location: 101,16 Location: 101,16
Owner: Soviets Owner: Soviets
Actor134: proc.noinfiltrate Actor134: proc
Location: 106,30 Location: 106,30
Owner: Soviets Owner: Soviets
Actor135: fix Actor135: fix
Location: 102,25 Location: 102,25
Owner: Soviets Owner: Soviets
Actor136: dome.noinfiltrate Actor136: dome
Location: 107,25 Location: 107,25
Owner: Soviets Owner: Soviets
HijackFactory: weap HijackFactory: weap
@@ -1312,7 +1312,7 @@ Actors:
Actor414: sbag Actor414: sbag
Location: 74,60 Location: 74,60
Owner: Soviets Owner: Soviets
Actor412: proc.noinfiltrate Actor412: proc
Location: 84,68 Location: 84,68
Owner: Soviets Owner: Soviets
Actor472: brl3 Actor472: brl3
@@ -1809,44 +1809,6 @@ Rules:
AutoTargetIgnore: AutoTargetIgnore:
Allies04TransformOnLabInfiltrate: Allies04TransformOnLabInfiltrate:
ToActor: MISS ToActor: MISS
PROC.NoInfiltrate:
Inherits: PROC
-Buildable:
RenderBuilding:
Image: PROC
Tooltip:
Icon: procicon
-InfiltrateForCash:
Allies04TransformOnLabInfiltrate:
ToActor: PROC.NoFreeActor
PROC.NoFreeActor:
Inherits: PROC
-Buildable:
RenderBuilding:
Image: PROC
Tooltip:
Icon: procicon
-FreeActor:
DOME.NoInfiltrate:
Inherits: DOME
-Buildable:
RenderBuilding:
Image: DOME
Tooltip:
Icon: domeicon
-InfiltrateForExploration:
Allies04TransformOnLabInfiltrate:
ToActor: DOME
SPEN.NoInfiltrate:
Inherits: SPEN
-Buildable:
RenderBuilding:
Image: SPEN
Tooltip:
Icon: spenicon
-InfiltrateForSupportPower:
Allies04TransformOnLabInfiltrate:
ToActor: SPEN
LST.Unselectable: LST.Unselectable:
Inherits: LST Inherits: LST
Buildable: Buildable:
@@ -1875,6 +1837,8 @@ Rules:
RevealsShroud: RevealsShroud:
Range: 6 Range: 6
Spy: Spy:
Infiltrates:
InfiltrateTypes: MissionObjective
DOG.Patrol: DOG.Patrol:
Inherits: DOG Inherits: DOG
Buildable: Buildable:

View File

@@ -2535,11 +2535,14 @@ Rules:
MonsterTankMadnessScript: MonsterTankMadnessScript:
FirstStartUnits: 1tnk, 1tnk, 2tnk, 2tnk FirstStartUnits: 1tnk, 1tnk, 2tnk, 2tnk
SecondStartUnits: e1, e1, e1, e3, e3 SecondStartUnits: e1, e1, e1, e3, e3
ThirdStartUnits: spy, e6, e6 ThirdStartUnits: thf, e6, e6
FirstBaseUnits: 1tnk, 1tnk, 2tnk, arty, arty FirstBaseUnits: 1tnk, 1tnk, 2tnk, arty, arty
CivilianEvacuees: c1, c2, c5, c7, c8 CivilianEvacuees: c1, c2, c5, c7, c8
MissionObjectivesPanel: MissionObjectivesPanel:
ObjectivesPanel: MISSION_OBJECTIVES ObjectivesPanel: MISSION_OBJECTIVES
SPY:
Infiltrates:
InfiltrateTypes: MissionObjective
DEMITRI: DEMITRI:
Inherits: DELPHI Inherits: DELPHI
Tooltip: Tooltip:

View File

@@ -196,6 +196,8 @@ SPY:
PipType: Yellow PipType: Yellow
TakeCover: TakeCover:
Spy: Spy:
Infiltrates:
InfiltrateTypes: Cash, SupportPower, Exploration
-AutoTarget: -AutoTarget:
AttackMove: AttackMove:
JustMove: true JustMove: true
@@ -427,6 +429,8 @@ THF:
Range: 5 Range: 5
Passenger: Passenger:
PipType: Yellow PipType: Yellow
Infiltrates:
InfiltrateTypes: Cash
TakeCover: TakeCover:
-AutoTarget: -AutoTarget:
AttackMove: AttackMove: