Elin Decompiled Documentation EA 23.231 Nightly
Loading...
Searching...
No Matches
ActRanged.cs
Go to the documentation of this file.
1using System.Collections.Generic;
2using System.Linq;
3using UnityEngine;
4
5public class ActRanged : ActThrow
6{
7 public bool IsReload
8 {
9 get
10 {
12 {
13 return !(EClass.player.currentHotItem.Thing.trait is TraitToolRangeCane);
14 }
15 return false;
16 }
17 }
18
20
21 public override int PerformDistance => 99;
22
23 public override string Name
24 {
25 get
26 {
27 if (!IsReload)
28 {
29 return base.Name;
30 }
31 return "ActReload".lang();
32 }
33 }
34
35 public override string GetText(string str = "")
36 {
37 if (!IsReload)
38 {
39 return base.GetText(str);
40 }
41 return Name;
42 }
43
44 public override bool CanPerform()
45 {
47 {
48 return false;
49 }
51 {
52 return false;
53 }
54 if (Act.TC == null)
55 {
56 return Act.CC.CanSeeLos(Act.TP);
57 }
59 {
60 return false;
61 }
62 return Act.CC.CanSeeLos(Act.TC.pos);
63 }
64
65 public override bool Perform()
66 {
67 if (Act.TC == null)
68 {
69 Act.TC = Act.TP.FindAttackTarget();
70 }
71 if (Act.TC != null)
72 {
73 Act.TP.Set(Act.TC.pos);
74 }
76 {
78 {
79 target = Act.TC,
80 range = true
81 });
82 return true;
83 }
85 if (!Act.CC.IsPC)
86 {
88 }
90 if (weapon != null && Act.CC.IsPC && Act.CC.body.IsTooHeavyToEquip(weapon))
91 {
92 Msg.Say("tooHeavyToEquip", weapon);
93 return false;
94 }
95 if (weapon == null || !weapon.CanAutoFire(Act.CC, Act.TC))
96 {
97 return false;
98 }
99 TraitToolRange traitRange = weapon.trait as TraitToolRange;
100 bool flag = weapon.trait is TraitToolRangeCane;
101 GameSetting.EffectData effectData = EClass.setting.effect.guns.TryGetValue(weapon.id) ?? EClass.setting.effect.guns[flag ? "cane" : ((weapon.trait is TraitToolRangeGun) ? "gun" : "bow")];
102 bool hasHit = false;
103 int numFire = effectData.num;
104 int numFireWithoutDamageLoss = numFire;
105 int num = GetWeaponEnc(602);
106 int drill = GetWeaponEnc(606);
107 int scatter = GetWeaponEnc(607);
108 int chaser = GetWeaponEnc(620);
109 if (num > 0)
110 {
111 numFire += Mathf.Min(num / 10 + ((num % 10 > EClass.rnd(10)) ? 1 : 0), 10);
112 numFireWithoutDamageLoss += num / 100 + ((num % 100 > EClass.rnd(100)) ? 1 : 0);
113 }
114 numFire += Act.CC.Evalue(1652);
115 int num2 = numFire;
116 int num3 = 1 + weapon.material.hardness / 30 + EClass.rnd(3);
117 int num4 = weapon.Evalue(604);
118 if (num4 > 0)
119 {
120 for (int i = 0; i < numFire; i++)
121 {
122 if (Mathf.Sqrt(num4) * 5f + 10f > (float)EClass.rnd(100))
123 {
124 num2--;
125 }
126 }
127 num3 = Mathf.Max(1, num3 * 100 / (100 + num4 * 5));
128 }
129 string missSound = ((weapon.trait is TraitToolRangeGun) ? "miss_bullet" : "miss_arrow");
130 if (flag)
131 {
132 foreach (Element item in weapon.elements.dict.Values.Where((Element e) => e.source.categorySub == "eleAttack"))
133 {
134 num3 += item.source.LV / 15;
135 }
136 if (Act.CC.IsPC)
137 {
138 if (Act.CC.mana.value < num3)
139 {
140 if (!Act.CC.ai.IsNoGoal)
141 {
142 return false;
143 }
145 {
146 ActPlan.warning = true;
147 Dialog.TryWarnMana(delegate
148 {
149 if (Perform())
150 {
152 }
153 });
154 return false;
155 }
156 }
157 EClass.ui.CloseLayers();
158 }
159 }
160 else
161 {
162 if (IsReload)
163 {
164 return TryReload(weapon);
165 }
166 if (weapon.c_ammo <= 0)
167 {
168 if (!TryReload(weapon))
169 {
170 if (Act.CC.IsPC)
171 {
172 EInput.Consume();
173 }
174 return false;
175 }
177 {
178 return true;
179 }
180 }
181 if (Act.CC.HasCondition<ConFear>())
182 {
183 Act.CC.Say("fear", Act.CC, Act.TC);
184 if (Act.CC.IsPC)
185 {
186 EInput.Consume(consumeAxis: true);
187 }
188 return true;
189 }
190 }
191 Act.TC?.Chara?.RequestProtection(Act.CC, delegate(Chara c)
192 {
193 Act.TC = c;
194 });
195 Act.CC.LookAt(Act.TP);
196 int index = 0;
197 Point orgTP = Act.TP.Copy();
198 List<Point> points = new List<Point>();
199 if (drill > 0)
200 {
201 points = EClass._map.ListPointsInLine(Act.CC.pos, Act.TP, drill / 10 + ((drill % 10 > EClass.rnd(10)) ? 1 : 0) + 1);
202 }
203 else if (scatter > 0)
204 {
205 Act.TP.ForeachNeighbor(delegate(Point _p)
206 {
207 points.Add(_p.Copy());
208 });
209 }
211 {
212 EClass.Wait(0.25f, Act.CC);
213 }
214 Shoot(Act.TC, Act.TP, subAttack: false);
215 if (points.Count > 0)
216 {
217 Point obj = Act.TP.Copy();
218 foreach (Point item2 in points)
219 {
220 if (item2.Equals(obj))
221 {
222 continue;
223 }
224 Chara firstChara = item2.FirstChara;
225 if (firstChara != null && !firstChara.IsHostile(Act.CC))
226 {
227 continue;
228 }
229 if (scatter > 0)
230 {
231 if (EClass.rnd(EClass.rnd(100) + 1) > scatter)
232 {
233 continue;
234 }
235 }
236 else if (firstChara == null)
237 {
238 continue;
239 }
240 Shoot(item2.FirstChara ?? item2.FindThing<TraitTrainingDummy>()?.owner, item2, subAttack: true);
241 }
242 }
243 if (!(weapon.trait is TraitToolRangeCane))
244 {
245 weapon.c_ammo -= num2;
246 if (weapon.ammoData != null)
247 {
248 weapon.ammoData.Num = weapon.c_ammo;
249 }
250 if (weapon.c_ammo <= 0)
251 {
252 weapon.c_ammo = 0;
253 weapon.ammoData = null;
254 }
255 }
256 if (Act.CC.IsPC)
257 {
259 }
260 if (Act.TC != null && !hasHit)
261 {
262 Act.CC.PlaySound(missSound);
263 }
264 if (!Act.CC.isDead)
265 {
266 if (EClass.rnd(2) == 0)
267 {
268 Act.CC.RemoveCondition<ConInvisibility>();
269 }
270 if (weapon.trait is TraitToolRangeCane)
271 {
272 Act.CC.mana.Mod(-num3 * numFire);
273 }
274 }
275 return true;
276 int GetWeaponEnc(int ele)
277 {
278 return weapon.Evalue(ele) + (Act.CC.IsPCFactionOrMinion ? EClass.pc.faction.charaElements.Value(ele) : 0);
279 }
280 void Prepare()
281 {
283 AttackProcess.Current.numFire = numFire;
284 AttackProcess.Current.numFireWithoutDamageLoss = numFireWithoutDamageLoss;
285 AttackProcess.Current.posRangedAnime = Act.TP.Copy();
286 AttackProcess.Current.ignoreAnime = index > 1;
287 AttackProcess.Current.ignoreAttackSound = false;
288 if (drill > 0 && points.Count > 0)
289 {
290 AttackProcess.Current.posRangedAnime = points.LastItem();
291 }
292 else if (scatter > 0)
293 {
294 AttackProcess.Current.ignoreAnime = false;
295 AttackProcess.Current.ignoreAttackSound = index > 1;
296 }
297 }
298 void Shoot(Card _tc, Point _tp, bool subAttack)
299 {
300 float dmgMulti = 1f;
301 index++;
302 Act.TC = _tc;
303 Act.TP = _tp;
304 CellEffect effect = Act.TP.cell.effect;
305 if (effect != null && effect.id == 6 && EClass.rnd(2) == 0)
306 {
307 Prepare();
309 Act.CC.PlaySound(missSound);
310 Act.CC.Say("abMistOfDarkness_miss", Act.CC);
311 }
312 else
313 {
314 if (scatter > 0)
315 {
316 dmgMulti = Mathf.Clamp(1.2f - 0.2f * (float)Act.CC.Dist(Act.TP) - (Act.TP.Equals(orgTP) ? 0f : 0.4f), 0.2f, 1f);
317 }
318 for (int j = 0; j < numFire; j++)
319 {
320 Act.TC = _tc;
321 Card tC = Act.TC;
322 Chara cC = Act.CC;
323 Point point = Act.TP.Copy();
324 if (traitRange.ChanceMissAim > 0 && EClass.rnd(traitRange.ChanceMissAim) == 0)
325 {
327 }
328 Prepare();
329 int num5 = 0;
330 if (weapon.trait is TraitToolRangeGunEnergy && Act.TC != null && Act.TC.isChara && Act.TC.HasElement(383))
331 {
332 if (weapon.id == "gun_laser")
333 {
334 num5 = 50;
335 }
336 num5 += Mathf.Max(25 * Act.TC.PER / Mathf.Max(1, Act.CC.PER), 50);
337 if (Act.CC.IsPowerful)
338 {
339 num5 /= 2;
340 }
341 }
342 if (num5 > EClass.rnd(100))
343 {
344 List<Chara> list = Act.TC.pos.ListCharasInRadius(Act.TC.Chara, Act.TC.GetSightRadius(), (Chara c) => c.IsHostile(Act.TC.Chara));
345 Chara chara = ((list.Count > 0) ? list.RandomItem() : Act.CC?.Chara);
346 Act.TC.Say((Act.TC.isChara && Act.TC.Chara.IsHostile()) ? "attack_reflect_enemy" : "attack_reflect");
347 Act.TC.PlaySound("attack_gun_laser_parry");
349 AttackProcess.Current.CC = Act.TC?.Chara;
350 AttackProcess.Current.TC = chara;
352 AttackProcess.Current.posRangedAnime = chara.pos;
353 AttackProcess.Current.Perform(j, hasHit, chara.IsPCFactionOrMinion ? 0.1f : 2.5f, maxRoll: true, subAttack: true);
354 }
355 else if (AttackProcess.Current.Perform(j, hasHit, dmgMulti, maxRoll: false, subAttack))
356 {
357 hasHit = true;
358 }
359 else if (chaser > 0)
360 {
361 for (int k = 0; k < 10; k++)
362 {
363 if (chaser > EClass.rnd(4 + (int)Mathf.Pow(4f, k + 2 + j)))
364 {
365 Act.CC.Say(Act.CC.IsHostile() ? "attack_chaser_enemy" : "attack_chaser");
366 if (AttackProcess.Current.Perform(j, hasHit, dmgMulti, maxRoll: false, subAttack))
367 {
368 hasHit = true;
369 break;
370 }
371 }
372 }
373 }
374 switch (traitRange.GroundHitEffect)
375 {
376 case TraitToolRange.HitEffect.Rocket:
377 ActEffect.ProcAt(EffectId.Rocket, AttackProcess.Current.GetRocketPower(), BlessedState.Normal, Act.CC, null, Act.TP, isNeg: true, new ActRef
378 {
379 origin = Act.CC.Chara,
380 refThing = weapon,
381 aliasEle = "eleImpact"
382 });
383 break;
384 case TraitToolRange.HitEffect.Gravity:
385 ActEffect.ProcAt(EffectId.GravityGun, AttackProcess.Current.GetRocketPower() / 2, BlessedState.Normal, Act.CC, null, Act.TP, isNeg: true, new ActRef
386 {
387 origin = Act.CC.Chara,
388 refThing = weapon,
389 aliasEle = "eleImpact"
390 });
391 break;
392 }
393 Act.TC = tC;
394 Act.CC = cC;
395 Act.TP.Set(point);
396 if (traitRange.GroundHitEffect == TraitToolRange.HitEffect.None && (Act.TC == null || !Act.TC.IsAliveInCurrentZone))
397 {
398 break;
399 }
400 }
401 if (Act.TC != null)
402 {
404 }
405 }
406 }
407 }
408
409 public static bool TryReload(Thing weapon, Thing ammo = null)
410 {
411 TraitToolRange traitToolRange = weapon.trait as TraitToolRange;
412 if (Act.CC.IsPC)
413 {
415 }
416 if (weapon.ammoData != null)
417 {
418 if (weapon.ammoData.Num > 0)
419 {
420 Act.CC.Pick(weapon.ammoData);
421 }
422 weapon.ammoData = null;
423 }
424 int num = 0;
425 if (ammo == null)
426 {
428 }
429 if (ammo == null)
430 {
431 if (Act.CC.IsPC && !traitToolRange.AutoRefillAmmo)
432 {
433 if (!weapon.IsMeleeWithAmmo)
434 {
435 Msg.Say("noAmmo", weapon);
436 }
437 return false;
438 }
439 num = traitToolRange.MaxAmmo;
440 }
441 else
442 {
443 num = Mathf.Min(ammo.Num, traitToolRange.MaxAmmo);
444 Thing thing = ammo.Split(num);
445 Act.CC.Say("takeAmmo", thing);
446 if (thing.GetRootCard() == Act.CC)
447 {
448 thing.parent.RemoveCard(thing);
449 }
450 weapon.ammoData = thing;
451 }
452 weapon.c_ammo = num;
453 int reloadTurn = traitToolRange.ReloadTurn;
454 reloadTurn = reloadTurn * 100 / (100 + Act.CC.Evalue(1652) * 100);
455 if (traitToolRange.NeedReload && reloadTurn > 0)
456 {
457 Act.CC.AddCondition<ConReload>(reloadTurn * 10);
458 }
459 return true;
460 }
461}
BlessedState
Definition: BlessedState.cs:2
EffectId
Definition: EffectId.cs:2
virtual bool IsNoGoal
Definition: AIAct.cs:74
static void ProcAt(EffectId id, int power, BlessedState state, Card cc, Card tc, Point tp, bool isNeg, ActRef actRef=default(ActRef))
Definition: ActEffect.cs:500
override bool Perform()
Definition: ActRanged.cs:65
override string Name
Definition: ActRanged.cs:24
override CursorInfo CursorIcon
Definition: ActRanged.cs:19
override int PerformDistance
Definition: ActRanged.cs:21
static bool TryReload(Thing weapon, Thing ammo=null)
Definition: ActRanged.cs:409
bool IsReload
Definition: ActRanged.cs:8
override string GetText(string str="")
Definition: ActRanged.cs:35
override bool CanPerform()
Definition: ActRanged.cs:44
Thing target
Definition: ActThrow.cs:5
Definition: ACT.cs:62
static Card TC
Definition: ACT.cs:79
static Point TP
Definition: ACT.cs:81
static Chara CC
Definition: ACT.cs:77
void Prepare(Chara _CC, Thing _weapon, Card _TC=null, Point _TP=null, int _attackIndex=0, bool _isThrow=false)
bool Perform(int count, bool hasHit, float dmgMulti=1f, bool maxRoll=false, bool subAttack=false)
static AttackProcess Current
Definition: AttackProcess.cs:8
int GetRocketPower()
void PlayRangedAnime(int numFire, float delay=0f)
virtual void NextFrame()
Definition: Card.cs:11
bool IsPCFactionOrMinion
Definition: Card.cs:2260
virtual Chara Chara
Definition: Card.cs:2058
int GetSightRadius()
Definition: Card.cs:6308
bool IsRestrainedResident
Definition: Card.cs:2246
bool HasElement(int ele, int req=1)
Definition: Card.cs:5826
bool isRestrained
Definition: Card.cs:566
int PER
Definition: Card.cs:2327
SoundSource PlaySound(string id, float v=1f, bool spatial=true)
Definition: Card.cs:6058
ICardParent parent
Definition: Card.cs:55
Point pos
Definition: Card.cs:59
Trait trait
Definition: Card.cs:53
bool IsPowerful
Definition: Card.cs:2082
virtual bool IsAliveInCurrentZone
Definition: Card.cs:2115
virtual bool isChara
Definition: Card.cs:2071
Card GetRootCard()
Definition: Card.cs:3356
int Evalue(int ele)
Definition: Card.cs:2559
int Dist(Card c)
Definition: Card.cs:7559
CardRenderer renderer
Definition: Card.cs:61
void Say(string lang, string ref1=null, string ref2=null)
Definition: Card.cs:6710
CellEffect effect
Definition: Cell.cs:94
bool IsTooHeavyToEquip(Thing thing)
Definition: CharaBody.cs:156
Definition: Chara.cs:10
CharaBody body
Definition: Chara.cs:94
AIAct ai
Definition: Chara.cs:200
Condition AddCondition(string id, int p=100, bool force=false)
Definition: Chara.cs:9063
Thing FindAmmo(Thing weapon)
Definition: Chara.cs:7680
Faction faction
Definition: Chara.cs:425
override bool IsPC
Definition: Chara.cs:610
bool CanSeeLos(Card c, int dist=-1)
Definition: Chara.cs:1248
bool RequestProtection(Chara attacker, Action< Chara > action)
Definition: Chara.cs:8243
bool HasCondition(string alias)
Definition: Chara.cs:9220
AIAct SetAI(AIAct g)
Definition: Chara.cs:8693
Thing ranged
Definition: Chara.cs:98
Stats mana
Definition: Chara.cs:1152
void DoHostileAction(Card _tg, bool immediate=false)
Definition: Chara.cs:6247
bool IsHostile()
Definition: Chara.cs:6424
bool isDead
Definition: Chara.cs:387
override void LookAt(Card c)
Definition: Chara.cs:3504
bool TryEquipRanged()
Definition: Chara.cs:7710
Thing Pick(Thing t, bool msg=true, bool tryStack=true)
Definition: Chara.cs:4234
new GameConfig game
Definition: CoreConfig.cs:605
bool godMode
Definition: CoreDebug.cs:173
CoreConfig config
Definition: Core.cs:70
static CursorInfo IconRange
Definition: Dialog.cs:7
static bool warned
Definition: Dialog.cs:49
static void TryWarnMana(Action action)
Definition: Dialog.cs:391
Definition: EClass.cs:5
static Core core
Definition: EClass.cs:6
static void Wait(float a, Card c)
Definition: EClass.cs:102
static Map _map
Definition: EClass.cs:18
static int rnd(long a)
Definition: EClass.cs:58
static Player player
Definition: EClass.cs:12
static Chara pc
Definition: EClass.cs:14
static CoreDebug debug
Definition: EClass.cs:48
static UI ui
Definition: EClass.cs:16
static GameSetting setting
Definition: EClass.cs:34
Definition: EInput.cs:8
static void Consume(int _skipFrame)
Definition: EInput.cs:656
int Value(int ele)
ElementContainerFaction charaElements
Definition: FACTION.cs:146
UD_String_EffectData guns
Definition: GameSetting.cs:276
EffectSetting effect
Definition: GameSetting.cs:299
virtual Thing Thing
Definition: HotItem.cs:38
static void SetDirty(Thing t)
List< Point > ListPointsInLine(Point center, Point to, int radius)
Definition: Map.cs:2326
Definition: Msg.cs:5
static string Say(string idLang, string ref1, string ref2=null, string ref3=null, string ref4=null)
Definition: Msg.cs:58
void EndTurn(bool consume=true)
Definition: Player.cs:2061
HotItem currentHotItem
Definition: Player.cs:1097
Definition: Point.cs:9
Point Copy()
Definition: Point.cs:479
Point Set(int _x, int _z)
Definition: Point.cs:491
void ForeachNeighbor(Action< Point > action, bool diagonal=true)
Definition: Point.cs:1385
List< Chara > ListCharasInRadius(Chara cc, int dist, Func< Chara, bool > func, bool onlyVisible=true)
Definition: Point.cs:1208
bool Equals(int _x, int _z)
Definition: Point.cs:948
Card FindAttackTarget()
Definition: Point.cs:1086
Chara FirstChara
Definition: Point.cs:276
Cell cell
Definition: Point.cs:51
Thing FindThing(Func< Thing, bool > func)
Definition: Point.cs:1128
Point GetRandomNeighbor()
Definition: Point.cs:747
virtual void Mod(int a)
Definition: Stats.cs:135
virtual int value
Definition: Stats.cs:56
Definition: Thing.cs:8
virtual HitEffect GroundHitEffect
virtual bool AutoRefillAmmo
virtual bool NeedReload
virtual int ChanceMissAim
Card owner
Definition: Trait.cs:27
bool TryGetValue(TKey key, out TValue value)
Definition: UDictionary.cs:178
void RemoveCard(Card c)
Definition: ActRef.cs:2