-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStatusEffect.cs
More file actions
185 lines (161 loc) · 5.38 KB
/
StatusEffect.cs
File metadata and controls
185 lines (161 loc) · 5.38 KB
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
using System;
using System.Linq;
using FunkEngine;
using Godot;
/// <summary>
/// Status Effect class.
/// Preferably set up as a static default status, then apply status using GetInstance, but custom statuses can be defined elsewhere.
/// Invoke StatusEnd to remove status.
/// </summary>
public partial class StatusEffect : TextureRect, IBattleEvent
{ //TODO: Status effects that are permanent, and status effects that don't take up a slot/are invisible
public static readonly string LoadPath = "res://Classes/StatusEffects/StatusIcon.tscn";
public PuppetTemplate Sufferer { get; private set; }
public int Count { get; private set; }
public string StatusName { get; private set; }
[Export]
private Label CountLabel { get; set; }
internal delegate void StatusEndHandler(StatusEffect status);
internal event StatusEndHandler StatusEnd;
#region DefaultStatuses
private static readonly Action<BattleEventArgs, StatusEffect> BlockEffect = (e, self) =>
{
if (e is BattleDirector.Harbinger.OnDamageInstanceArgs dmgArgs)
{
if (dmgArgs.Dmg.Target != self.Sufferer || dmgArgs.Dmg.Damage <= 0)
return;
dmgArgs.Dmg.ModifyDamage(0, 0);
self.DecCount();
}
};
/// <summary>
/// On the owner receiving a damage instance, if valid (correct target and dmg > 0) sets damage to 0 and reduces count.
/// </summary>
public static readonly StatusEffect Block = new StatusEffect()
.InitStatus(
"Block",
BlockEffect,
BattleEffectTrigger.OnDamageInstance,
GD.Load<Texture2D>("res://Classes/StatusEffects/Assets/Status_Block.png")
)
.SetTags(true);
private static readonly Action<BattleEventArgs, StatusEffect> MulliganEffect = (e, self) =>
{
if (e is not BattleDirector.Harbinger.NoteHitArgs { Timing: Timing.Miss })
return;
e.BD.NPB.SetIgnoreMiss(true); //Intercept the miss
self.DecCount();
};
/// <summary>
/// If the player missed, take damage, but don't receive combo penalty.
/// </summary>
public static readonly StatusEffect Mulligan = new StatusEffect()
.InitStatus(
"Mulligan",
MulliganEffect,
BattleEffectTrigger.NoteHit,
GD.Load<Texture2D>("res://Classes/StatusEffects/Assets/Status_Mulligan.png")
)
.SetTags(true);
private static readonly Action<BattleEventArgs, StatusEffect> PoisonEffect = (e, self) =>
{
if (e is not BattleDirector.Harbinger.LoopEventArgs)
return;
if (self.Sufferer == null)
return;
self.Sufferer.TakeDamage(new DamageInstance(self.Count, null, null)); //TODO: More robust damage types
self.DecCount();
};
/// <summary>
/// On loop, the owner takes damage equal to number of stacks, then the count gets decremented.
/// </summary>
public static readonly StatusEffect Poison = new StatusEffect()
.InitStatus(
"Poison",
PoisonEffect,
BattleEffectTrigger.OnLoop,
GD.Load<Texture2D>("res://Classes/StatusEffects/Assets/Status_Poison.png")
)
.SetTags(true);
#endregion
private BattleEffectTrigger _trigger;
private Action<BattleEventArgs, StatusEffect> _effect;
public BattleEffectTrigger GetTrigger()
{
return _trigger;
}
public void OnTrigger(BattleEventArgs e)
{
_effect(e, this);
}
public StatusEffect InitStatus(
string name,
Action<BattleEventArgs, StatusEffect> effect,
BattleEffectTrigger trigger,
Texture2D texture = null
)
{
_effect = effect;
_trigger = trigger;
StatusName = name;
Texture = texture;
return this;
}
public StatusEffect CreateInstance(int count = 1)
{
StatusEffect result = GD.Load<PackedScene>(LoadPath).Instantiate<StatusEffect>();
result.SetCount(count);
result.InitStatus(Name, _effect, _trigger, Texture);
result.SetTags(_stackable, _refreshes);
return result;
}
public void SetOwner(PuppetTemplate owner)
{
Sufferer = owner;
}
public void IncCount(int count = 1)
{
SetCount(Count + count);
}
public void DecCount(int count = 1)
{
SetCount(Count - count);
}
public void SetCount(int count)
{
Count = count;
CountLabel.Text = Count.ToString();
if (Count <= 0)
{
StatusEnd?.Invoke(this);
}
}
/// <summary>
/// Re-applying a status increases the count.
/// </summary>
private bool _stackable;
/// <summary>
/// Re-applying a status sets the count to the higher counte
/// </summary>
private bool _refreshes;
public StatusEffect SetTags(bool stackable = false, bool refreshes = false)
{
_stackable = stackable;
_refreshes = refreshes;
return this;
}
//Called if a puppet is receiving a duplicate effect.
public void StackEffect(StatusEffect incomingEffect)
{
if (incomingEffect.StatusName != StatusName)
return;
if (_stackable)
{
IncCount(incomingEffect.Count);
}
if (_refreshes && incomingEffect.Count >= Count)
{
SetCount(incomingEffect.Count);
}
}
}