forked from OpenRA/OpenRA
/
GrantPrerequisiteChargeDrainPower.cs
211 lines (169 loc) · 5.77 KB
/
GrantPrerequisiteChargeDrainPower.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#region Copyright & License Information
/*
* Copyright 2007-2019 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, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits
{
[Desc("Grants a prerequisite while discharging at a configurable rate.")]
public class GrantPrerequisiteChargeDrainPowerInfo : SupportPowerInfo, ITechTreePrerequisiteInfo
{
[Desc("Rate at which the power discharges compared to charging")]
public readonly int DischargeModifier = 300;
[FieldLoader.Require]
[Desc("The prerequisite type that this provides.")]
public readonly string Prerequisite = null;
[Translate]
[Desc("Label to display over the support power icon and in its tooltip while the power is active.")]
public readonly string ActiveText = "ACTIVE";
[Translate]
[Desc("Label to display over the support power icon and in its tooltip while the power is available but not active.")]
public readonly string AvailableText = "READY";
IEnumerable<string> ITechTreePrerequisiteInfo.Prerequisites(ActorInfo info)
{
yield return Prerequisite;
}
public override object Create(ActorInitializer init) { return new GrantPrerequisiteChargeDrainPower(init.Self, this); }
}
public class GrantPrerequisiteChargeDrainPower : SupportPower, ITechTreePrerequisite, INotifyOwnerChanged
{
readonly GrantPrerequisiteChargeDrainPowerInfo info;
TechTree techTree;
bool active;
public GrantPrerequisiteChargeDrainPower(Actor self, GrantPrerequisiteChargeDrainPowerInfo info)
: base(self, info)
{
this.info = info;
}
protected override void Created(Actor self)
{
// Special case handling is required for the Player actor.
// Created is called before Player.PlayerActor is assigned,
// so we must query other player traits from self, knowing that
// it refers to the same actor as self.Owner.PlayerActor
var playerActor = self.Info.Name == "player" ? self : self.Owner.PlayerActor;
techTree = playerActor.Trait<TechTree>();
base.Created(self);
}
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
{
techTree = newOwner.PlayerActor.Trait<TechTree>();
active = false;
}
public override SupportPowerInstance CreateInstance(string key, SupportPowerManager manager)
{
return new DischargeableSupportPowerInstance(key, info, manager);
}
public void Activate(Actor self, SupportPowerInstance instance)
{
active = true;
techTree.ActorChanged(self);
}
public void Deactivate(Actor self, SupportPowerInstance instance)
{
active = false;
techTree.ActorChanged(self);
}
IEnumerable<string> ITechTreePrerequisite.ProvidesPrerequisites
{
get
{
if (!active)
yield break;
yield return info.Prerequisite;
}
}
public class DischargeableSupportPowerInstance : SupportPowerInstance
{
// Whether the power is available to activate (even if not fully charged)
bool available;
// Whether the power is active right now
// Note that this is fundamentally different to SupportPowerInstance.Active
// which has a much closer meaning to available above.
bool active;
// Additional discharge rate accrued from damage
int additionalDischargeSubTicks = 0;
public DischargeableSupportPowerInstance(string key, GrantPrerequisiteChargeDrainPowerInfo info, SupportPowerManager manager)
: base(key, info, manager) { }
void Deactivate()
{
active = false;
notifiedCharging = false;
// Fully depleting the charge disables the power until it is again fully charged
if (!Active || remainingSubTicks >= TotalTicks * 100)
available = false;
foreach (var p in Instances)
((GrantPrerequisiteChargeDrainPower)p).Deactivate(p.Self, this);
}
public override void Tick()
{
var orig = remainingSubTicks;
base.Tick();
if (Ready)
available = true;
if (active && !Active)
Deactivate();
if (active)
{
remainingSubTicks = orig + ((GrantPrerequisiteChargeDrainPowerInfo)Info).DischargeModifier + additionalDischargeSubTicks;
additionalDischargeSubTicks = 0;
if (remainingSubTicks > TotalTicks * 100)
{
remainingSubTicks = TotalTicks * 100;
Deactivate();
}
}
}
public void Discharge(int subTicks)
{
additionalDischargeSubTicks += subTicks;
}
public override void Target()
{
if (available && Active)
Manager.Self.World.IssueOrder(new Order(Key, Manager.Self, false) { ExtraData = active ? 0U : 1U });
}
public override void Activate(Order order)
{
if (active && order.ExtraData == 0)
{
Deactivate();
return;
}
if (!available || order.ExtraData != 1)
return;
var power = Instances.FirstOrDefault(i => !i.IsTraitPaused);
if (power == null)
return;
active = true;
// Only play the activation sound once!
power.PlayLaunchSounds();
foreach (var p in Instances)
((GrantPrerequisiteChargeDrainPower)p).Activate(p.Self, this);
}
public override string IconOverlayTextOverride()
{
var info = Info as GrantPrerequisiteChargeDrainPowerInfo;
if (info == null || !Active)
return null;
return active ? info.ActiveText : available ? info.AvailableText : null;
}
public override string TooltipTimeTextOverride()
{
var info = Info as GrantPrerequisiteChargeDrainPowerInfo;
if (info == null || !Active)
return null;
return active ? info.ActiveText : available ? info.AvailableText : null;
}
}
}
}