Skip to content

Commit c9c2479

Browse files
Zimmermann GyulaMailaender
Zimmermann Gyula
authored andcommitted
Add Infector logic.
1 parent 43f28ea commit c9c2479

File tree

4 files changed

+492
-0
lines changed

4 files changed

+492
-0
lines changed

OpenRA.Mods.RA2/Activities/Infect.cs

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#region Copyright & License Information
2+
/*
3+
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
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.Linq;
13+
using OpenRA.Mods.Common.Activities;
14+
using OpenRA.Mods.Common.Traits;
15+
using OpenRA.Mods.RA2.Traits;
16+
using OpenRA.Primitives;
17+
using OpenRA.Traits;
18+
19+
namespace OpenRA.Mods.RA2.Activities
20+
{
21+
class Infect : Enter
22+
{
23+
readonly AttackInfect attackInfect;
24+
readonly Target target;
25+
26+
bool jousting;
27+
28+
public Infect(Actor self, Target target, AttackInfect attackInfect, Color? targetLineColor)
29+
: base(self, target, targetLineColor)
30+
{
31+
this.target = target;
32+
this.attackInfect = attackInfect;
33+
}
34+
35+
protected override void OnFirstRun(Actor self)
36+
{
37+
attackInfect.IsAiming = true;
38+
}
39+
40+
protected override void OnLastRun(Actor self)
41+
{
42+
attackInfect.IsAiming = false;
43+
}
44+
45+
protected override void OnEnterComplete(Actor self, Actor targetActor)
46+
{
47+
self.World.AddFrameEndTask(w =>
48+
{
49+
if (self.IsDead || attackInfect.IsTraitDisabled)
50+
return;
51+
52+
if (jousting)
53+
{
54+
attackInfect.RevokeJoustCondition(self);
55+
jousting = false;
56+
}
57+
58+
attackInfect.DoAttack(self, target);
59+
60+
var infectable = targetActor.TraitOrDefault<Infectable>();
61+
if (infectable == null || infectable.IsTraitDisabled || infectable.Infector != null)
62+
return;
63+
64+
w.Remove(self);
65+
66+
infectable.Infector = self;
67+
infectable.AttackInfect = attackInfect;
68+
69+
infectable.FirepowerMultipliers = self.TraitsImplementing<IFirepowerModifier>()
70+
.Select(a => a.GetFirepowerModifier()).ToArray();
71+
72+
var info = attackInfect.InfectInfo;
73+
infectable.Ticks = info.DamageInterval;
74+
infectable.GrantCondition(targetActor);
75+
infectable.RevokeCondition(targetActor, self);
76+
});
77+
}
78+
79+
void CancelInfection(Actor self)
80+
{
81+
if (jousting)
82+
{
83+
attackInfect.RevokeJoustCondition(self);
84+
jousting = false;
85+
}
86+
87+
if (target.Type != TargetType.Actor)
88+
return;
89+
90+
if (target.Actor.IsDead)
91+
return;
92+
93+
var infectable = target.Actor.TraitOrDefault<Infectable>();
94+
if (infectable == null || infectable.IsTraitDisabled || infectable.Infector != null)
95+
return;
96+
97+
infectable.RevokeCondition(target.Actor, self);
98+
}
99+
100+
bool IsValidInfection(Actor self, Actor targetActor)
101+
{
102+
if (attackInfect.IsTraitDisabled)
103+
return false;
104+
105+
if (targetActor.IsDead)
106+
return false;
107+
108+
if (!target.IsValidFor(self) || !attackInfect.HasAnyValidWeapons(target))
109+
return false;
110+
111+
var infectable = targetActor.TraitOrDefault<Infectable>();
112+
if (infectable == null || infectable.IsTraitDisabled || infectable.Infector != null)
113+
return false;
114+
115+
return true;
116+
}
117+
118+
bool CanStartInfect(Actor self, Actor targetActor)
119+
{
120+
if (!IsValidInfection(self, targetActor))
121+
return false;
122+
123+
// IsValidInfection validated the lookup, no need to check here.
124+
var infectable = targetActor.Trait<Infectable>();
125+
return infectable.TryStartInfecting(targetActor, self);
126+
}
127+
128+
protected override bool TryStartEnter(Actor self, Actor targetActor)
129+
{
130+
var canStartInfect = CanStartInfect(self, targetActor);
131+
if (canStartInfect == false)
132+
{
133+
CancelInfection(self);
134+
Cancel(self, true);
135+
}
136+
137+
// Can't leap yet
138+
if (attackInfect.Armaments.All(a => a.IsReloading))
139+
return false;
140+
141+
return true;
142+
}
143+
144+
protected override void TickInner(Actor self, Target target, bool targetIsDeadOrHiddenActor)
145+
{
146+
if (target.Type != TargetType.Actor || !IsValidInfection(self, target.Actor))
147+
{
148+
CancelInfection(self);
149+
Cancel(self, true);
150+
return;
151+
}
152+
153+
var info = attackInfect.InfectInfo;
154+
if (!jousting && !IsCanceling && (self.CenterPosition - target.CenterPosition).Length < info.JumpRange.Length)
155+
{
156+
jousting = true;
157+
attackInfect.GrantJoustCondition(self);
158+
IsInterruptible = false;
159+
}
160+
}
161+
}
162+
}
+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#region Copyright & License Information
2+
/*
3+
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
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 OpenRA.Activities;
13+
using OpenRA.Mods.Common.Traits;
14+
using OpenRA.Mods.RA2.Activities;
15+
using OpenRA.Primitives;
16+
using OpenRA.Traits;
17+
18+
namespace OpenRA.Mods.RA2.Traits
19+
{
20+
[Desc("Move onto the target then execute the attack.")]
21+
public class AttackInfectInfo : AttackFrontalInfo, Requires<MobileInfo>
22+
{
23+
[Desc("Range of the final jump of the infector.")]
24+
public readonly WDist JumpRange = WDist.Zero;
25+
26+
[Desc("Conditions that last from start of the joust until the attack.")]
27+
[GrantedConditionReference]
28+
public readonly string JumpCondition = "jumping";
29+
30+
[FieldLoader.Require]
31+
[Desc("How much damage to deal.")]
32+
public readonly int Damage = 0;
33+
34+
[FieldLoader.Require]
35+
[Desc("How often to deal the damage.")]
36+
public readonly int DamageInterval = 0;
37+
38+
[Desc("Damage types for the infection damage.")]
39+
public readonly BitSet<DamageType> DamageTypes = default(BitSet<DamageType>);
40+
41+
[Desc("Damage types which allows the infector survive when it's host dies.")]
42+
public readonly BitSet<DamageType> SurviveHostDamageTypes = default(BitSet<DamageType>);
43+
44+
public override object Create(ActorInitializer init) { return new AttackInfect(init.Self, this); }
45+
}
46+
47+
public class AttackInfect : AttackFrontal
48+
{
49+
public readonly AttackInfectInfo InfectInfo;
50+
51+
ConditionManager conditionManager;
52+
int joustToken = ConditionManager.InvalidConditionToken;
53+
54+
public AttackInfect(Actor self, AttackInfectInfo info)
55+
: base(self, info)
56+
{
57+
InfectInfo = info;
58+
}
59+
60+
protected override void Created(Actor self)
61+
{
62+
conditionManager = self.TraitOrDefault<ConditionManager>();
63+
base.Created(self);
64+
}
65+
66+
protected override bool CanAttack(Actor self, Target target)
67+
{
68+
if (target.Type != TargetType.Actor)
69+
return false;
70+
71+
if (self.Location == target.Actor.Location && HasAnyValidWeapons(target))
72+
return true;
73+
74+
return base.CanAttack(self, target);
75+
}
76+
77+
public void GrantJoustCondition(Actor self)
78+
{
79+
if (conditionManager != null && !string.IsNullOrEmpty(InfectInfo.JumpCondition))
80+
joustToken = conditionManager.GrantCondition(self, InfectInfo.JumpCondition);
81+
}
82+
83+
public void RevokeJoustCondition(Actor self)
84+
{
85+
if (joustToken != ConditionManager.InvalidConditionToken)
86+
joustToken = conditionManager.RevokeCondition(self, joustToken);
87+
}
88+
89+
public override Activity GetAttackActivity(Actor self, AttackSource source, Target newTarget, bool allowMove, bool forceAttack, Color? targetLineColor)
90+
{
91+
return new Infect(self, newTarget, this, targetLineColor);
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)