Skip to content

Commit db4698e

Browse files
committed
- Fixed discount on subsequent Upgrade Center plugs.
- Fixed Voidspike not despawning on player losing. - Fixed powers not starting fully charged when the actor with the support power existed before the power became enabled. - Covenant powers initially have 1 minute charge.
1 parent 0098c5b commit db4698e

16 files changed

Lines changed: 372 additions & 30 deletions
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#region Copyright & License Information
2+
/*
3+
* Copyright (c) The OpenRA Developers and Contributors
4+
* This file is part of OpenRA, which is free software. It is made
5+
* available to you under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation, either version 3 of
7+
* the License, or (at your option) any later version. For more
8+
* information, see COPYING.
9+
*/
10+
#endregion
11+
12+
using System.Collections.Generic;
13+
using OpenRA.Mods.Common;
14+
using OpenRA.Mods.Common.Traits;
15+
using OpenRA.Primitives;
16+
using OpenRA.Traits;
17+
18+
namespace OpenRA.Mods.CA.Traits
19+
{
20+
[Desc("Player receives a unit for free once the building is placed. This also works for structures.",
21+
"If you want more than one unit to appear copy this section and assign IDs like FreeActor@2, ...")]
22+
public class FreeActorCAInfo : ConditionalTraitInfo, IEditorActorOptions
23+
{
24+
[ActorReference]
25+
[FieldLoader.Require]
26+
[Desc("Name of the actor.")]
27+
public readonly string Actor = null;
28+
29+
[Desc("Offset relative to the top-left cell of the building.")]
30+
public readonly CVec SpawnOffset = CVec.Zero;
31+
32+
[Desc("Which direction the unit should face.")]
33+
public readonly WAngle Facing = WAngle.Zero;
34+
35+
[Desc("Whether another actor should spawn upon re-enabling the trait.")]
36+
public readonly bool AllowRespawn = false;
37+
38+
[Desc("Display order for the free actor checkbox in the map editor")]
39+
public readonly int EditorFreeActorDisplayOrder = 4;
40+
41+
IEnumerable<EditorActorOption> IEditorActorOptions.ActorOptions(ActorInfo ai, World world)
42+
{
43+
yield return new EditorActorCheckbox("Spawn Child Actor", EditorFreeActorDisplayOrder,
44+
actor =>
45+
{
46+
var init = actor.GetInitOrDefault<FreeActorInit>(this);
47+
if (init != null)
48+
return init.Value;
49+
50+
return true;
51+
},
52+
(actor, value) => actor.ReplaceInit(new FreeActorInit(this, value), this));
53+
}
54+
55+
public override object Create(ActorInitializer init) { return new FreeActorCA(init, this); }
56+
}
57+
58+
public class FreeActorCA : ConditionalTrait<FreeActorCAInfo>
59+
{
60+
protected bool allowSpawn;
61+
62+
public FreeActorCA(ActorInitializer init, FreeActorCAInfo info)
63+
: base(info)
64+
{
65+
allowSpawn = init.GetValue<FreeActorInit, bool>(info, true);
66+
}
67+
68+
protected override void TraitEnabled(Actor self)
69+
{
70+
if (!allowSpawn)
71+
return;
72+
73+
allowSpawn = Info.AllowRespawn;
74+
75+
self.World.AddFrameEndTask(w =>
76+
{
77+
var td = new TypeDictionary
78+
{
79+
new ParentActorInit(self),
80+
new OwnerInit(self.Owner),
81+
};
82+
83+
var ai = w.Map.Rules.Actors[Info.Actor];
84+
85+
if (self.Info.HasTraitInfo<IOccupySpaceInfo>() && ai.HasTraitInfo<IOccupySpaceInfo>())
86+
td.Add(new LocationInit(self.Location + Info.SpawnOffset));
87+
88+
if (self.Info.HasTraitInfo<IFacingInfo>() && ai.HasTraitInfo<IFacingInfo>())
89+
td.Add(new FacingInit(Info.Facing));
90+
91+
w.CreateActor(Info.Actor, td);
92+
});
93+
}
94+
}
95+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#region Copyright & License Information
2+
/**
3+
* Copyright (c) The OpenRA Combined Arms Developers (see CREDITS).
4+
* This file is part of OpenRA Combined Arms, which is free software.
5+
* It is made available to you under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation, either version 3 of the License,
7+
* or (at your option) any later version. For more information, see COPYING.
8+
*/
9+
#endregion
10+
11+
using System;
12+
using System.Collections.Generic;
13+
using OpenRA.Traits;
14+
15+
namespace OpenRA.Mods.CA.Traits
16+
{
17+
[Desc("For storing global support power properties e.g. to limit the number of times timers are modified.")]
18+
public class SupportPowerInstanceManagerInfo : TraitInfo
19+
{
20+
public override object Create(ActorInitializer init) { return new SupportPowerInstanceManager(); }
21+
}
22+
23+
public class SupportPowerInstanceManager
24+
{
25+
public readonly HashSet<string> InitiallyFullyChargedPowers = new HashSet<string>();
26+
27+
public SupportPowerInstanceManager()
28+
{
29+
30+
}
31+
}
32+
}

OpenRA.Mods.CA/Traits/SupportPowers/RangedGpsRadarProvider.cs renamed to OpenRA.Mods.CA/Traits/RangedGpsRadarProvider.cs

File renamed without changes.

OpenRA.Mods.CA/Traits/SupportPowers/AttackOrderPowerCA.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Collections.Generic;
1212
using System.Linq;
1313
using OpenRA.Graphics;
14+
using OpenRA.Mods.CA.Traits;
1415
using OpenRA.Mods.Common.Graphics;
1516
using OpenRA.Mods.Common.Orders;
1617
using OpenRA.Mods.Common.Traits;
@@ -57,6 +58,11 @@ public override void SelectTarget(Actor self, string order, SupportPowerManager
5758
self.World.OrderGenerator = new SelectAttackOrderPowerCATarget(self, order, manager, info.Cursor, MouseButton.Left, attack, this);
5859
}
5960

61+
public override SupportPowerInstance CreateInstance(string key, SupportPowerManager manager)
62+
{
63+
return new SupportPowerInstanceCA(key, Info, manager);
64+
}
65+
6066
public override void Activate(Actor self, Order order, SupportPowerManager manager)
6167
{
6268
base.Activate(self, order, manager);
@@ -109,8 +115,11 @@ bool IsValidTarget(World world, CPos cell)
109115
{
110116
var pos = world.Map.CenterOfCell(cell);
111117
var range = attack.GetMaximumRange().LengthSquared;
118+
var minRange = attack.GetMinimumRange().LengthSquared;
112119

113-
return world.Map.Contains(cell) && instance.Instances.Any(a => !a.IsTraitPaused && (a.Self.CenterPosition - pos).HorizontalLengthSquared < range);
120+
return world.Map.Contains(cell) && instance.Instances.Any(a => !a.IsTraitPaused
121+
&& (a.Self.CenterPosition - pos).HorizontalLengthSquared < range
122+
&& (a.Self.CenterPosition - pos).HorizontalLengthSquared >= minRange);
114123
}
115124

116125
protected override IEnumerable<Order> OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi)
@@ -135,7 +144,6 @@ protected override void Tick(World world)
135144

136145
protected override IEnumerable<IRenderable> RenderAnnotations(WorldRenderer wr, World world)
137146
{
138-
var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
139147
var info = instance.Info as AttackOrderPowerCAInfo;
140148

141149
foreach (var a in instance.Instances.Where(i => !i.IsTraitPaused))
@@ -161,6 +169,8 @@ protected override IEnumerable<IRenderable> RenderAnnotations(WorldRenderer wr,
161169

162170
if (info.TargetCircleRadius > WDist.Zero)
163171
{
172+
var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos);
173+
164174
yield return new RangeCircleAnnotationRenderable(
165175
world.Map.CenterOfCell(xy),
166176
info.TargetCircleRadius,

OpenRA.Mods.CA/Traits/SupportPowers/DetonateWeaponPower.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ public DetonateWeaponPower(Actor self, DetonateWeaponPowerInfo info)
9595
Info = info;
9696
}
9797

98+
public override SupportPowerInstance CreateInstance(string key, SupportPowerManager manager)
99+
{
100+
return new SupportPowerInstanceCA(key, Info, manager);
101+
}
102+
98103
public override void Activate(Actor self, Order order, SupportPowerManager manager)
99104
{
100105
base.Activate(self, order, manager);

OpenRA.Mods.CA/Traits/SupportPowers/GrantPrerequisiteChargeDrainPowerCA.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public void Deactivate(Actor self, SupportPowerInstance instance)
8989

9090
IEnumerable<string> ITechTreePrerequisite.ProvidesPrerequisites => active ? prerequisites : Enumerable.Empty<string>();
9191

92-
public class DischargeableSupportPowerInstance : SupportPowerInstance
92+
public class DischargeableSupportPowerInstance : SupportPowerInstanceCA
9393
{
9494
// Whether the power is available to activate (even if not fully charged)
9595
bool available;

OpenRA.Mods.CA/Traits/SupportPowers/ProduceActorPowerCA.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ public ProduceActorPowerCA(ActorInitializer init, ProduceActorPowerCAInfo info)
7676
faction = init.GetValue<FactionInit, string>(init.Self.Owner.Faction.InternalName);
7777
}
7878

79+
public override SupportPowerInstance CreateInstance(string key, SupportPowerManager manager)
80+
{
81+
return new SupportPowerInstanceCA(key, Info, manager);
82+
}
83+
7984
public override void SelectTarget(Actor self, string order, SupportPowerManager manager)
8085
{
8186
if (info.AutoFire || !info.SelectProducer)

OpenRA.Mods.CA/Traits/SupportPowers/SpawnActorPowerCA.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,15 @@ public SpawnActorPowerCA(Actor self, SpawnActorPowerCAInfo info)
4242
Info = info;
4343
}
4444

45+
public override SupportPowerInstance CreateInstance(string key, SupportPowerManager manager)
46+
{
47+
return new SupportPowerInstanceCA(key, Info, manager);
48+
}
49+
4550
public override void Activate(Actor self, Order order, SupportPowerManager manager)
4651
{
4752
base.Activate(self, order, manager);
4853

49-
5054
if (Info.DisplayBeacon)
5155
{
5256
var timer = new Countdown(Info.BeaconDuration);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#region Copyright & License Information
2+
/**
3+
* Copyright (c) The OpenRA Combined Arms Developers (see CREDITS).
4+
* This file is part of OpenRA Combined Arms, which is free software.
5+
* It is made available to you under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation, either version 3 of the License,
7+
* or (at your option) any later version. For more information, see COPYING.
8+
*/
9+
#endregion
10+
11+
12+
using OpenRA.Mods.Common.Traits;
13+
14+
namespace OpenRA.Mods.CA.Traits
15+
{
16+
// Extends the base SupportPowerInstance to allow modifying the remaining ticks.
17+
public class SupportPowerInstanceCA : SupportPowerInstance
18+
{
19+
public SupportPowerInstanceCA(string key, SupportPowerInfo info, SupportPowerManager manager)
20+
: base(key, info, manager)
21+
{
22+
23+
}
24+
25+
public void SetRemainingTicks(int ticks)
26+
{
27+
remainingSubTicks = (ticks * 100).Clamp(0, TotalTicks * 100);
28+
}
29+
30+
public void AddToRemainingTicks(int ticks)
31+
{
32+
remainingSubTicks = (remainingSubTicks + ticks * 100).Clamp(0, TotalTicks * 100);
33+
}
34+
35+
public void SubtractFromRemainingTicks(int ticks)
36+
{
37+
remainingSubTicks = (remainingSubTicks - ticks * 100).Clamp(0, TotalTicks * 100);
38+
}
39+
}
40+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#region Copyright & License Information
2+
/**
3+
* Copyright (c) The OpenRA Combined Arms Developers (see CREDITS).
4+
* This file is part of OpenRA Combined Arms, which is free software.
5+
* It is made available to you under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation, either version 3 of the License,
7+
* or (at your option) any later version. For more information, see COPYING.
8+
*/
9+
#endregion
10+
11+
using OpenRA.Mods.Common.Traits;
12+
using System;
13+
14+
namespace OpenRA.Mods.CA.Traits
15+
{
16+
public enum SupportPowerTimerUpdateType
17+
{
18+
Add,
19+
Subtract,
20+
Set
21+
}
22+
23+
[Desc("When trait is enabled the named support power will have its timer updated.")]
24+
class UpdatesSupportPowerTimerInfo : ConditionalTraitInfo
25+
{
26+
[FieldLoader.Require]
27+
[Desc("The support power to charge.")]
28+
public readonly string OrderName = null;
29+
30+
[Desc("If set to true, the support power will be fully charged the first time it becomes available. " +
31+
"Otherwise it will be fully charged every time the trait is enabled.")]
32+
public readonly bool InitialOnly = false;
33+
34+
public readonly int Ticks = 0;
35+
36+
public readonly SupportPowerTimerUpdateType Type = SupportPowerTimerUpdateType.Set;
37+
38+
public override object Create(ActorInitializer init) { return new UpdatesSupportPowerTimer(init, this); }
39+
}
40+
41+
class UpdatesSupportPowerTimer : ConditionalTrait<UpdatesSupportPowerTimerInfo>
42+
{
43+
readonly SupportPowerManager supportPowerManager = null;
44+
readonly SupportPowerInstanceManager supportPowerInstanceManager;
45+
46+
public UpdatesSupportPowerTimer(ActorInitializer init, UpdatesSupportPowerTimerInfo info)
47+
: base(info)
48+
{
49+
supportPowerManager = init.Self.Owner.PlayerActor.TraitOrDefault<SupportPowerManager>();
50+
supportPowerInstanceManager = init.Self.Owner.PlayerActor.TraitOrDefault<SupportPowerInstanceManager>();
51+
}
52+
53+
protected override void TraitEnabled(Actor self)
54+
{
55+
self.World.AddFrameEndTask(w => {
56+
if (supportPowerManager.Powers.ContainsKey(Info.OrderName))
57+
{
58+
if (supportPowerManager.Powers[Info.OrderName] is SupportPowerInstanceCA instance)
59+
{
60+
if (Info.InitialOnly && supportPowerInstanceManager.InitiallyFullyChargedPowers.Contains(Info.OrderName))
61+
return;
62+
63+
switch (Info.Type)
64+
{
65+
case SupportPowerTimerUpdateType.Add:
66+
instance.AddToRemainingTicks(Info.Ticks);
67+
break;
68+
case SupportPowerTimerUpdateType.Subtract:
69+
instance.SubtractFromRemainingTicks(Info.Ticks);
70+
break;
71+
case SupportPowerTimerUpdateType.Set:
72+
instance.SetRemainingTicks(Info.Ticks);
73+
break;
74+
}
75+
76+
if (Info.InitialOnly)
77+
supportPowerInstanceManager.InitiallyFullyChargedPowers.Add(Info.OrderName);
78+
79+
} else {
80+
throw new InvalidOperationException(
81+
$"UpdatesSupportPowerTimer trait requires SupportPowerInstanceCA for {Info.OrderName}, " +
82+
$"but found {supportPowerManager.Powers[Info.OrderName].GetType().Name}.");
83+
}
84+
}
85+
});
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)