Elin Decompiled Documentation EA 23.153 Nightly
Loading...
Searching...
No Matches
AttackProcess.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using UnityEngine;
5
6public class AttackProcess : EClass
7{
8 public static AttackProcess Current = new AttackProcess();
9
10 public int dNum;
11
12 public int dDim;
13
14 public int dBonus;
15
16 public int toHit;
17
18 public int toHitBase;
19
20 public int toHitFix;
21
22 public int evasion;
23
24 public int penetration;
25
26 public int distMod;
27
28 public int attackIndex;
29
30 public int dNumAmmo;
31
32 public int dDimAmmo;
33
34 public int dBonusAmmo;
35
36 public int numFire;
37
39
40 public float dMulti;
41
42 public bool crit;
43
44 public bool critFury;
45
46 public bool hit;
47
48 public bool evadePlus;
49
50 public bool isThrow;
51
52 public bool ignoreAnime;
53
54 public bool ignoreAttackSound;
55
56 public Chara CC;
57
58 public Card TC;
59
60 public Point TP;
61
63
65
66 public Thing weapon;
67
68 public Thing ammo;
69
71
73
75
76 public bool IsMartial => weapon == null;
77
78 public bool IsMartialWeapon
79 {
80 get
81 {
82 if (weapon != null)
83 {
84 return weapon.category.skill == 100;
85 }
86 return false;
87 }
88 }
89
90 public bool IsRanged
91 {
92 get
93 {
94 if (toolRange != null && !isThrow)
95 {
97 }
98 return false;
99 }
100 }
101
102 public bool IsCane
103 {
104 get
105 {
106 if (IsRanged)
107 {
109 }
110 return false;
111 }
112 }
113
114 public static int GetWeaponEnc(Chara CC, Thing w, int ele, bool addSelfEnc = false)
115 {
116 return (addSelfEnc ? CC.Evalue(ele) : 0) + (w?.Evalue(ele) ?? 0) + (CC.IsPCFactionOrMinion ? EClass.pc.faction.charaElements.Value(ele) : 0);
117 }
118
119 public string GetText()
120 {
121 string text = dNum + "d" + dDim;
122 text = text + ((dBonus >= 0) ? "+" : "") + dBonus;
123 string @ref = (IsMartial ? "evalHand".lang() : "evalWeapon".lang((attackIndex + 1).ToString() ?? ""));
124 return "attackEval".lang(@ref, text, dMulti.ToString("F2") ?? "", toHit.ToString() ?? "", penetration.ToString() ?? "");
125 }
126
127 public void Prepare(Chara _CC, Thing _weapon, Card _TC = null, Point _TP = null, int _attackIndex = 0, bool _isThrow = false)
128 {
129 CC = _CC;
130 TC = _TC;
131 TP = _TP;
132 isThrow = _isThrow;
133 weapon = _weapon;
134 ammo = _weapon?.ammoData;
135 hit = (crit = (critFury = (evadePlus = false)));
137 attackType = AttackType.Slash;
138 attackStyle = AttackStyle.Default;
139 evasion = 0;
140 penetration = 0;
141 distMod = 100;
142 attackIndex = _attackIndex;
144 ignoreAnime = (ignoreAttackSound = false);
145 if (!isThrow)
146 {
147 if (!IsRanged)
148 {
150 }
151 else if (TP != null)
152 {
153 int num = CC.pos.Distance(TP);
154 distMod = Mathf.Max(115 - 10 * Mathf.Abs(num - toolRange.BestDist) * 100 / (100 + weapon.Evalue(605) * 10), 80);
155 }
156 }
157 if (isThrow)
158 {
159 bool flag = weapon.HasTag(CTAG.throwWeapon) || weapon.HasTag(CTAG.throwWeaponEnemy);
160 int num2 = (int)Mathf.Clamp(Mathf.Sqrt(weapon.SelfWeight + weapon.ChildrenWeight) * 3f + 25f + (float)(flag ? 75 : 0), 10f, 400f + Mathf.Sqrt(CC.STR) * 50f);
161 int num3 = Mathf.Clamp(weapon.material.hardness, flag ? 40 : 20, 200);
163 attackType = AttackType.Blunt;
164 dBonus = CC.DMG + (CC.IsPCParty ? 3 : 7);
165 dNum = 2;
166 dDim = (((!CC.IsPCParty) ? CC.LV : 0) + CC.STR + CC.Evalue(108)) * num2 / 100 * num3 / 100 / 2;
167 dMulti = 1f;
168 toHitBase = EClass.curve(CC.DEX / 4 + CC.STR / 2 + weaponSkill.Value, 50, 25) + (CC.IsPCFaction ? 75 : 250);
169 toHitFix = CC.HIT + weapon.HIT;
170 penetration = 25;
171 }
172 else if (IsMartial || IsMartialWeapon)
173 {
175 bool flag2 = weapon != null && weapon.Evalue(482) > 0;
176 if (flag2)
177 {
179 }
180 attackType = ((!CC.race.meleeStyle.IsEmpty()) ? CC.race.meleeStyle.ToEnum<AttackType>() : ((EClass.rnd(2) == 0) ? AttackType.Kick : AttackType.Punch));
181 dBonus = CC.DMG + CC.encLV + (int)Mathf.Sqrt(Mathf.Max(0, weaponSkill.GetParent(CC).Value / 5 + weaponSkill.Value / 4));
182 dNum = 2 + Mathf.Min(weaponSkill.Value / 10, 4);
183 dDim = 5 + (int)Mathf.Sqrt(Mathf.Max(0, weaponSkill.Value / 3));
184 dMulti = 0.6f + (float)(weaponSkill.GetParent(CC).Value / 2 + weaponSkill.Value / 2 + CC.Evalue(flag2 ? 304 : 132) / 2) / 50f;
185 dMulti += 0.05f * (float)CC.Evalue(1400);
187 toHitFix = CC.HIT;
188 if (attackStyle == AttackStyle.Shield)
189 {
190 toHitBase = toHitBase * 75 / 100;
191 }
192 penetration = Mathf.Clamp(weaponSkill.Value / 10 + 5, 5, 20) + CC.Evalue(92);
193 if (IsMartialWeapon)
194 {
195 dBonus += weapon.DMG;
196 dNum += weapon.source.offense[0];
197 dDim = Mathf.Max(dDim / 2 + weapon.c_diceDim, 1);
200 if (!weapon.source.attackType.IsEmpty())
201 {
202 attackType = weapon.source.attackType.ToEnum<AttackType>();
203 }
204 }
205 }
206 else
207 {
208 if (IsRanged)
209 {
211 }
212 else
213 {
215 }
216 if (!weapon.source.attackType.IsEmpty())
217 {
218 attackType = weapon.source.attackType.ToEnum<AttackType>();
219 }
220 bool flag3 = IsCane || weapon.Evalue(482) > 0;
221 if (flag3)
222 {
224 }
225 dBonus = CC.DMG + CC.encLV + weapon.DMG;
226 dNum = weapon.source.offense[0];
228 dMulti = 0.6f + (float)(weaponSkill.GetParent(CC).Value + weaponSkill.Value / 2 + CC.Evalue(flag3 ? 304 : (IsRanged ? 133 : 132))) / 50f;
229 dMulti += 0.05f * (float)CC.Evalue(IsRanged ? 1404 : 1400);
230 toHitBase = EClass.curve((IsCane ? CC.WIL : CC.DEX) / 4 + weaponSkill.GetParent(CC).Value / 3 + weaponSkill.Value, 50, 25) + 50;
231 toHitFix = CC.HIT + weapon.HIT;
232 penetration = weapon.Penetration + CC.Evalue(92);
233 if (IsCane)
234 {
235 toHitBase += 50;
236 }
237 }
238 if (ammo != null && !(ammo.trait is TraitAmmoTalisman))
239 {
240 dNumAmmo = ((ammo.source.offense.Length != 0) ? ammo.source.offense[0] : 0);
242 dBonusAmmo = ammo.DMG + ammo.encLV;
243 if (dNumAmmo < 1)
244 {
245 dNumAmmo = 1;
246 }
247 if (dDimAmmo < 1)
248 {
249 dDimAmmo = 1;
250 }
251 toHitFix += ammo.HIT;
252 }
253 else
254 {
255 dNumAmmo = 0;
256 dDimAmmo = 0;
257 }
258 if (dNum < 1)
259 {
260 dNum = 1;
261 }
262 if (dDim < 1)
263 {
264 dDim = 1;
265 }
266 if (penetration > 100)
267 {
268 penetration = 100;
269 }
270 if (attackStyle == AttackStyle.TwoHand)
271 {
272 dMulti = dMulti * 1.5f + 0.1f * Mathf.Sqrt(Mathf.Max(0, CC.Evalue(130)));
273 }
274 dMulti = dMulti * (float)distMod / 100f;
275 toHit = (toHitBase + toHitFix) * (100 + CC.Evalue(414)) / 100;
276 toHit = toHit * distMod / 100;
277 if (CC.HasCondition<ConBane>())
278 {
279 toHit = toHit * 75 / 100;
280 }
281 if (TC != null && CC.HasHigherGround(TC))
282 {
283 toHit = toHit * 120 / 100;
284 }
285 if (CC.ride != null)
286 {
287 toHit = toHit * 100 / (100 + 500 / Mathf.Max(5, 10 + CC.EvalueRiding()));
288 }
289 if (CC.parasite != null)
290 {
291 toHit = toHit * 100 / (100 + 1000 / Mathf.Max(5, 10 + CC.Evalue(227)));
292 }
293 if (CC.host != null)
294 {
295 if (CC.host.ride == CC)
296 {
297 toHit = toHit * 100 / (100 + 1000 / Mathf.Max(5, 10 + CC.STR));
298 }
299 if (CC.host.parasite == CC)
300 {
301 toHit = toHit * 100 / (100 + 2000 / Mathf.Max(5, 10 + CC.DEX));
302 }
303 }
304 if (attackStyle == AttackStyle.TwoHand)
305 {
306 toHit += 25 + (int)Mathf.Sqrt(Mathf.Max(0, CC.Evalue(130)) * 2);
307 }
308 else if (attackStyle == AttackStyle.TwoWield && toHit > 0)
309 {
310 toHit = toHit * 100 / (115 + attackIndex * 15 + attackIndex * Mathf.Clamp(2000 / (20 + CC.EvalueMax(131, -10)), 0, 100));
311 }
312 if (CC.isBlind)
313 {
314 toHit /= ((IsRanged || isThrow) ? 10 : 3);
315 }
317 {
318 toHit /= 2;
319 }
320 if (TC != null)
321 {
322 evasion = EClass.curve(TC.PER / 3 + TC.Evalue(150), 50, 10) + TC.DV + 25;
323 if (TC.isChara && TC.Chara.isBlind)
324 {
325 evasion /= 2;
326 }
327 if (TC.HasCondition<ConDim>())
328 {
329 evasion /= 2;
330 }
331 if (TC.isChara && TC.Chara.HasHigherGround(CC))
332 {
333 evasion = evasion * 120 / 100;
334 }
335 }
336 }
337
338 public void PlayRangedAnime(int numFire)
339 {
340 if (weapon == null)
341 {
342 return;
343 }
344 bool isGun = toolRange is TraitToolRangeGun;
345 bool isCane = toolRange is TraitToolRangeCane;
346 GameSetting.EffectData data = EClass.setting.effect.guns.TryGetValue(weapon.id) ?? EClass.setting.effect.guns[isCane ? "cane" : (isGun ? "gun" : "bow")];
347 bool isPCC = CC.IsPCC && CC.renderer.hasActor;
348 Vector2 firePos = (isPCC ? new Vector2(data.firePos.x * (float)((CC.renderer.actor.currentDir != 0 && CC.renderer.actor.currentDir != 1) ? 1 : (-1)), data.firePos.y) : Vector2.zero);
349 Chara _CC = CC;
350 Point _TP = posRangedAnime.Copy();
351 Thing _weapon = weapon;
352 bool ignoreSound = ignoreAttackSound;
354 Color effColor = Color.white;
355 if (isCane)
356 {
357 IEnumerable<Element> enumerable = toolRange.owner.elements.dict.Values.Where((Element e) => e.source.categorySub == "eleAttack");
358 if (enumerable.Count() > 0)
359 {
360 Element element = enumerable.RandomItem();
361 effColor = EClass.Colors.elementColors[element.source.alias];
362 }
363 }
364 for (int i = 0; i < numFire; i++)
365 {
366 TweenUtil.Delay((float)i * data.delay, delegate
367 {
369 {
370 if (_weapon.id == "gun_rail")
371 {
372 _CC.PlayEffect("laser").GetComponent<SpriteBasedLaser>().Play(_TP.PositionCenter());
373 }
374 else
375 {
376 Effect effect = Effect.Get("ranged_arrow")._Play(_CC.pos, _CC.isSynced ? _CC.renderer.position : _CC.pos.Position(), 0f, _TP, data.sprite);
377 if (isCane)
378 {
379 effect.sr.color = effColor;
380 }
381 }
382 if (data.eject)
383 {
384 if (!ignoreSound)
385 {
386 _CC.PlaySound("bullet_drop");
387 }
388 _CC.PlayEffect("bullet").Emit(1);
389 }
390 if (isGun)
391 {
392 if (isPCC)
393 {
394 _weapon.PlayEffect(data.idEffect.IsEmpty("gunfire"), useRenderPos: true, 0f, firePos);
395 }
396 else
397 {
398 _CC.PlayEffect(data.idEffect.IsEmpty("gunfire"));
399 }
400 }
401 if (!ignoreSound)
402 {
403 _CC.PlaySound(data.idSound.IsEmpty("attack_gun"));
404 }
405 }
406 });
407 }
408 }
409
410 public int GetRawDamage(float dmgMulti, bool crit, bool maxRoll)
411 {
412 bool flag = CC.HasCondition<ConReload>();
413 int num = Dice.Roll(dNum, dDim, dBonus, CC);
414 if (ammo != null && !flag)
415 {
417 }
418 if (crit || maxRoll)
419 {
420 num = Dice.RollMax(dNum, dDim, dBonus);
421 if (ammo != null && !flag)
422 {
424 }
425 if (crit && (IsMartial || IsMartialWeapon))
426 {
427 dMulti *= 1.25f;
428 }
429 }
430 int num2 = CC.Evalue(1355);
431 ConStrife condition = CC.GetCondition<ConStrife>();
432 if (condition != null)
433 {
434 num += condition.GetDice().Roll();
435 }
436 else if (num2 > 0)
437 {
438 num++;
439 }
440 num = Mathf.Clamp(num, 0, 9999999);
441 num = (int)(dMulti * (float)num * dmgMulti);
442 return Mathf.Clamp(num, 0, 9999999);
443 }
444
445 public bool Perform(int count, bool hasHit, float dmgMulti = 1f, bool maxRoll = false, bool subAttack = false)
446 {
447 bool flag = CC.HasCondition<ConReload>();
448 bool flag2 = CC.HasElement(486) && CC.IsPCFactionOrMinion;
449 hit = CalcHit();
450 if (CC.id == "tsunami")
451 {
452 hit = true;
453 }
454 int num = GetRawDamage(dmgMulti, crit, maxRoll);
455 if (IsRanged && count >= numFireWithoutDamageLoss)
456 {
457 num = num * 100 / (100 + (count - numFireWithoutDamageLoss + 1) * 30);
458 }
459 if (CC.isRestrained)
460 {
461 num /= 2;
462 }
463 List<Element> list2 = new List<Element>();
464 int num2 = CC.Evalue(91);
465 int num3 = 0;
466 if (weapon != null)
467 {
468 list2 = weapon.elements.dict.Values.ToList();
469 if (ammo != null && !flag)
470 {
471 list2 = list2.Concat(ammo.elements.dict.Values).ToList();
472 }
473 num2 += weapon.Evalue(91, ignoreGlobalElement: true);
474 num3 += weapon.Evalue(603, ignoreGlobalElement: true);
475 }
476 else if (CC.id == "rabbit_vopal")
477 {
478 list2.Add(Element.Create(6650, 100));
479 }
480 int bane;
481 if (TC?.Chara != null)
482 {
483 SourceRace.Row race = TC.Chara.race;
484 bane = 0;
485 AddBane(valid: true, 468, 50);
486 AddBane(race.IsUndead, 461, 100);
487 AddBane(race.IsAnimal, 463, 100);
488 AddBane(race.IsHuman, 464, 100);
489 AddBane(race.IsDragon, 460, 100);
490 AddBane(race.IsGod, 466, 100);
491 AddBane(race.IsMachine, 465, 100);
492 AddBane(race.IsFish, 467, 100);
493 AddBane(race.IsFairy, 462, 100);
494 if (bane != 0)
495 {
496 num = num * (100 + bane * 3) / 100;
497 }
498 }
499 if (CC.IsPCFaction)
500 {
501 foreach (Element value in EClass.pc.faction.charaElements.dict.Values)
502 {
503 if (value.Value > 0)
504 {
505 list2.Add(value);
506 }
507 }
508 }
509 if (hit && num2 > EClass.rnd(100))
510 {
511 CC.Say("vopal");
512 penetration = 100;
513 }
514 if (crit)
515 {
516 CC.Say((critFury ? "fury_" : "") + (CC.IsHostile() ? "critical_enemy" : "critical"));
517 if (CC.IsPC)
518 {
519 CC.PlaySound("critical");
520 }
521 }
522 if (CC.isSynced || (TC != null && TC.isSynced))
523 {
524 if (toolRange != null && (!IsRanged || count == 0) && !flag && !ignoreAnime)
525 {
527 }
528 if (hit && TC != null && !hasHit)
529 {
530 PlayHitEffect();
531 }
532 }
533 if (TC == null)
534 {
535 CC.Say(IsRanged ? "attack_air_range" : "attack_air", CC);
536 return true;
537 }
538 if (!hit)
539 {
540 if (TC != null)
541 {
542 if (CC.IsPCParty)
543 {
544 CC.Say(evadePlus ? "evadePlus2" : "evade2", CC, TC);
545 }
546 else
547 {
548 TC.Say(evadePlus ? "evadePlus" : "evade", TC, CC);
549 }
550 ModExpDef(150, 90);
551 ModExpDef(151, 90);
552 }
553 Proc(list2);
554 return false;
555 }
556 if (TC.IsPC)
557 {
558 Msg.SetColor("attack_pc");
559 EClass.pc.Say("attackMeleeToPC", CC, TC, GetAttackText(attackType, 3));
560 }
561 else
562 {
563 CC.Say("attackMelee", CC, TC, GetAttackText(attackType, 0));
564 }
565 bool showEffect = true;
566 int num4 = 0;
567 int num5 = 0;
568 int num6 = 0;
569 ConWeapon conWeapon = null;
570 if (weapon != null)
571 {
572 foreach (Element value2 in weapon.elements.dict.Values)
573 {
574 if (value2.source.categorySub == "eleConvert")
575 {
576 num4 = EClass.sources.elements.alias[value2.source.aliasRef].id;
577 num5 = 50 + value2.Value * 2;
578 num6 = Mathf.Min(value2.Value, 100);
579 break;
580 }
581 }
582 }
583 if (num4 == 0)
584 {
586 {
587 conWeapon = CC.GetCondition<ConWeapon>();
588 num4 = conWeapon.sourceElement.id;
589 num5 = conWeapon.power / 2;
590 num6 = (int)Mathf.Min(40f + MathF.Sqrt(conWeapon.power), 80f);
591 }
592 if (conWeapon == null && weapon == null && (CC.MainElement != Element.Void || CC.HasElement(1565)))
593 {
594 num4 = (CC.HasElement(1565) ? 915 : CC.MainElement.id);
595 num5 = CC.Power / 3 + EClass.rnd(CC.Power / 2);
596 if (CC.MainElement != Element.Void)
597 {
598 num5 += CC.MainElement.Value;
599 }
600 showEffect = false;
601 num6 = 50;
602 }
603 if (conWeapon == null && weapon != null && weapon.trait is TraitToolRangeCane)
604 {
605 IEnumerable<Element> enumerable = weapon.elements.dict.Values.Where((Element e) => e.source.categorySub == "eleAttack");
606 if (enumerable.Count() > 0)
607 {
608 num4 = enumerable.RandomItem().id;
609 num5 = num4 switch
610 {
611 920 => 30,
612 914 => 50,
613 918 => 50,
614 _ => 100,
615 };
616 }
617 num6 = 50;
618 }
619 }
620 int num7 = num;
621 int num8 = num * num6 / 100;
622 num -= num8;
623 int num9 = num * penetration / 100;
624 num -= num9;
625 num = TC.ApplyProtection(num) + num9 + num8;
626 int weaponEnc = GetWeaponEnc(CC, weapon, 609, addSelfEnc: true);
627 TC.DamageHP(num, num4, num5, (!IsRanged && !isThrow) ? AttackSource.Melee : AttackSource.Range, CC, showEffect, weapon);
628 if (conWeapon != null && (weaponEnc <= 0 || !(Mathf.Min(10f + Mathf.Sqrt(weaponEnc) * 5f, 90f) > (float)EClass.rnd(100))))
629 {
630 conWeapon.Mod(-1);
631 }
632 bool flag3 = IsCane || (weapon != null && weapon.Evalue(482) > 0);
633 int attackStyleElement = CC.body.GetAttackStyleElement(attackStyle);
634 if (!subAttack)
635 {
636 int mod2 = 100 / (count + 1);
637 if (!IsRanged || count == 0)
638 {
639 ModExpAtk(weaponSkill.id, mod2);
640 ModExpAtk(flag3 ? 304 : (IsRanged ? 133 : 132), mod2);
641 }
642 if (crit)
643 {
644 ModExpAtk(134, 50);
645 }
646 if (count == 0 && attackStyleElement != 0)
647 {
648 ModExpAtk(attackStyleElement, 100);
649 }
650 }
651 if (!CC.IsAliveInCurrentZone || !TC.IsAliveInCurrentZone)
652 {
653 return true;
654 }
655 if (EClass.rnd(8) == 0 && TC.isChara && CC.HasElement(1219))
656 {
657 CC.Say("abCrab", CC, TC);
658 TC.Chara.AddCondition<ConParalyze>(30 + EClass.rnd(30));
659 TC.Chara.AddCondition<ConGravity>();
660 }
661 if (list2.Count > 0 && !flag2)
662 {
663 foreach (Element item in list2)
664 {
665 if (!TC.IsAliveInCurrentZone)
666 {
667 break;
668 }
669 if (item.IsActive(weapon) && item.source.categorySub == "eleAttack")
670 {
671 int num10 = 25;
672 int dmg = EClass.rnd(num * (100 + item.Value * 10) / 500 + 5);
673 if (conWeapon == null && weapon != null && weapon.trait is TraitToolRangeCane)
674 {
675 num10 = 0;
676 }
677 if (num10 > EClass.rnd(100))
678 {
679 TC.DamageHP(dmg, item.id, isThrow ? (100 + item.Value * 5) : (30 + item.Value), AttackSource.WeaponEnchant, CC);
680 }
681 }
682 }
683 Proc(list2);
684 }
685 if (!CC.IsAliveInCurrentZone || !TC.IsAliveInCurrentZone)
686 {
687 return true;
688 }
689 if (!IsRanged && !flag2 && attackStyle == AttackStyle.Shield)
690 {
691 int num11 = CC.Evalue(123);
692 if (CC.elements.ValueWithoutLink(123) >= 10 && Mathf.Clamp(Mathf.Sqrt(num11) - 2f, 8f, 12f) > (float)EClass.rnd(100))
693 {
694 num = num7 * Mathf.Min(50 + num11, 200) / 100;
695 num = TC.ApplyProtection(num);
696 Debug.Log("Bash:" + num + "/" + num7);
697 CC.PlaySound("shield_bash");
698 CC.Say("shield_bash", CC, TC);
699 TC.DamageHP(num, AttackSource.None, CC);
700 if (TC.IsAliveInCurrentZone && TC.isChara)
701 {
702 if (EClass.rnd(2) == 0)
703 {
704 TC.Chara.AddCondition<ConDim>(50 + (int)Mathf.Sqrt(num11) * 10);
705 }
706 TC.Chara.AddCondition<ConParalyze>(EClass.rnd(2), force: true);
707 }
708 }
709 }
710 if (!CC.IsAliveInCurrentZone || !TC.IsAliveInCurrentZone)
711 {
712 return true;
713 }
714 if (TC.isChara && !TC.HasCondition<ConGravity>() && num3 > 0 && num3 * 2 + 15 > EClass.rnd(100) && !TC.isRestrained && TC.Chara.TryMoveFrom(CC.pos) == Card.MoveResult.Success)
715 {
716 TC.pos.PlayEffect("vanish");
717 TC.PlaySound("push", 1.5f);
718 }
719 return true;
720 void AddBane(bool valid, int idEle, int mod)
721 {
722 if (valid)
723 {
724 bane += (CC.Evalue(idEle) + ((weapon != null) ? weapon.Evalue(idEle, ignoreGlobalElement: true) : 0)) * mod / 100;
725 }
726 }
727 bool IgnoreExp()
728 {
729 if (!CC.HasEditorTag(EditorTag.Invulnerable) && !CC.HasEditorTag(EditorTag.InvulnerableToMobs) && !TC.HasEditorTag(EditorTag.Invulnerable))
730 {
731 return TC.HasEditorTag(EditorTag.InvulnerableToMobs);
732 }
733 return true;
734 }
735 void ModExpAtk(int ele, int mod)
736 {
737 if (!IgnoreExp() && (!TC.isCopy || EClass.rnd(10) == 0))
738 {
739 int a = (Mathf.Clamp((TC.LV + 10 - CC.elements.ValueWithoutLink(ele)) / 2, 1, 10) + Mathf.Min(TC.LV / 10, 10)) * mod / 100;
740 a = Mathf.Min(a, 200);
741 if (TC == CC)
742 {
743 a /= 2;
744 }
745 if (a > 0)
746 {
747 CC.ModExp(ele, a + EClass.rnd(a / 2 + 1));
748 }
749 }
750 }
751 void ModExpDef(int ele, int mod)
752 {
753 if (!IgnoreExp() && (!CC.isCopy || EClass.rnd(10) == 0))
754 {
755 int a2 = (Mathf.Clamp((CC.LV + 10 - TC.elements.ValueWithoutLink(ele)) / 2, 1, 10) + Mathf.Min(CC.LV / 10, 10)) * mod / 100;
756 a2 = Mathf.Min(a2, TC.isRestrained ? 10 : 200);
757 if (TC == CC)
758 {
759 a2 /= 2;
760 }
761 if (!TC.IsPC && !TC.isRestrained && !TC.HasHost)
762 {
763 a2 *= 3;
764 }
765 if (a2 > 0)
766 {
767 TC.ModExp(ele, a2 + EClass.rnd(a2 / 2 + 1));
768 }
769 }
770 }
771 void PlayHitEffect()
772 {
773 string id = "hit_default";
774 string id2 = "hit_default";
775 switch (attackType)
776 {
777 case AttackType.Slash:
778 id2 = "hit_slash";
779 id = "hit_slash";
780 break;
781 case AttackType.Spore:
782 id2 = "hit_spore";
783 id = "hit_spore";
784 break;
785 case AttackType.Claw:
786 case AttackType.Bite:
787 id2 = "hit_claw";
788 id = "hit_claw";
789 break;
790 case AttackType.Blunt:
791 case AttackType.Punch:
792 case AttackType.Kick:
793 case AttackType.Bow:
794 case AttackType.Gun:
795 case AttackType.Cane:
796 id2 = "hit_blunt";
797 id = "hit_blunt";
798 break;
799 }
800 if (TC != null)
801 {
802 TC.PlayEffect(id2).SetScale(crit ? 1.25f : 0.75f);
803 }
804 CC.PlaySound(id);
805 }
806 void Proc(List<Element> list)
807 {
808 if (list == null)
809 {
810 return;
811 }
812 foreach (Element item2 in list)
813 {
814 if (item2 is Ability)
815 {
816 int num12 = 10 + item2.Value / 5;
817 int power = EClass.curve((100 + item2.Value * 10) * (100 + weaponSkill.Value) / 100, 400, 100);
818 if (num12 > EClass.rnd(100))
819 {
820 Act obj = item2 as Act;
821 Card card = (obj.TargetType.CanSelectSelf ? CC : TC);
822 string text = ((item2.source.proc.Length >= 2) ? item2.source.proc[1] : "");
823 string text2 = obj.source.abilityType.TryGet(0);
824 switch (text2)
825 {
826 case "buff":
827 if (CC.HasCondition(text))
828 {
829 continue;
830 }
831 card = CC;
832 break;
833 case "debuff":
834 case "attack":
835 case "dot":
836 card = TC;
837 break;
838 }
839 if (subAttack)
840 {
841 if (card == CC)
842 {
843 continue;
844 }
845 switch (text2)
846 {
847 case "attackArea":
848 case "summon":
849 case "teleport":
850 case "suicide":
851 continue;
852 }
853 }
854 if (card.IsAliveInCurrentZone)
855 {
856 Card tC = TC;
857 ActEffect.ProcAt(item2.source.proc[0].ToEnum<EffectId>(), power, BlessedState.Normal, CC, card, card.pos, isNeg: false, new ActRef
858 {
859 n1 = text,
860 aliasEle = item2.source.aliasRef,
861 noFriendlyFire = true
862 });
863 TC = tC;
864 }
865 }
866 }
867 }
868 }
869 }
870
871 private bool Crit()
872 {
873 crit = true;
874 return true;
875 }
876
877 private bool EvadePlus()
878 {
879 evadePlus = true;
880 return false;
881 }
882
883 public bool CalcHit()
884 {
885 if (critFury)
886 {
887 crit = true;
888 return true;
889 }
890 if (TC != null)
891 {
892 if (TC.HasCondition<ConDim>() && EClass.rnd(4) == 0)
893 {
894 return Crit();
895 }
896 if (TC.IsDeadOrSleeping)
897 {
898 return Crit();
899 }
900 int num = TC.Evalue(151);
901 if (num != 0 && toHit < num * 10)
902 {
903 int num2 = evasion * 100 / Mathf.Clamp(toHit, 1, toHit);
904 if (num2 > 300 && EClass.rnd(num + 250) > 100)
905 {
906 return EvadePlus();
907 }
908 if (num2 > 200 && EClass.rnd(num + 250) > 150)
909 {
910 return EvadePlus();
911 }
912 if (num2 > 150 && EClass.rnd(num + 250) > 200)
913 {
914 return EvadePlus();
915 }
916 }
917 if (TC.Evalue(57) > EClass.rnd(100))
918 {
919 return EvadePlus();
920 }
921 }
922 if (EClass.rnd(20) == 0)
923 {
924 return true;
925 }
926 if (EClass.rnd(20) == 0)
927 {
928 return false;
929 }
930 if (toHit < 1)
931 {
932 return false;
933 }
934 if (evasion < 1)
935 {
936 return true;
937 }
938 if (EClass.rnd(toHit) < EClass.rnd(evasion * (IsRanged ? 150 : 125) / 100))
939 {
940 return false;
941 }
942 if (EClass.rnd(5000) < CC.Evalue(73) + 50)
943 {
944 return Crit();
945 }
946 if ((float)(CC.Evalue(90) + ((weapon != null) ? weapon.Evalue(90, ignoreGlobalElement: true) : 0)) + Mathf.Sqrt(CC.Evalue(134)) > (float)EClass.rnd(200))
947 {
948 return Crit();
949 }
950 if (CC.Evalue(1420) > 0)
951 {
952 int num3 = Mathf.Min(100, 100 - CC.hp * 100 / CC.MaxHP) * (50 + CC.Evalue(1420) * 50) / 100;
953 if (num3 >= 50 && num3 * num3 * num3 * num3 / 3 > EClass.rnd(100000000))
954 {
955 return Crit();
956 }
957 }
958 return true;
959 }
960
961 public string GetAttackText(AttackType type, int id)
962 {
963 return Lang.GetList("attack" + type)[id];
964 }
965}
AttackSource
Definition: AttackSource.cs:2
AttackStyle
Definition: AttackStyle.cs:2
AttackType
Definition: AttackType.cs:2
BlessedState
Definition: BlessedState.cs:2
CTAG
Definition: CTAG.cs:2
EditorTag
Definition: EditorTag.cs:2
EffectId
Definition: EffectId.cs:2
if(item3.idFile==idFirstFile &&item3.id==idFirstTopic)
Definition: UIBook.cs:627
static void ProcAt(EffectId id, int power, BlessedState state, Card cc, Card tc, Point tp, bool isNeg, ActRef actRef=default(ActRef))
Definition: ActEffect.cs:407
Definition: ACT.cs:62
TraitToolRange toolRange
AttackType attackType
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)
string GetAttackText(AttackType type, int id)
static AttackProcess Current
Definition: AttackProcess.cs:8
int GetRawDamage(float dmgMulti, bool crit, bool maxRoll)
string GetText()
bool ignoreAttackSound
int numFireWithoutDamageLoss
bool IsMartialWeapon
Point posRangedAnime
Element weaponSkill
static int GetWeaponEnc(Chara CC, Thing w, int ele, bool addSelfEnc=false)
AttackStyle attackStyle
void PlayRangedAnime(int numFire)
void Mod(int a, bool force=false)
SourceElement.Row sourceElement
virtual int currentDir
Definition: CardActor.cs:41
Vector3 position
Definition: CardRenderer.cs:21
CardActor actor
Definition: CardRenderer.cs:11
Definition: Card.cs:11
int DMG
Definition: Card.cs:2267
bool IsPCFactionOrMinion
Definition: Card.cs:2208
int EvalueMax(int ele, int min=0)
Definition: Card.cs:2521
ElementContainerCard elements
Definition: Card.cs:37
string id
Definition: Card.cs:31
int ChildrenWeight
Definition: Card.cs:1949
bool HasElement(int ele, int req=1)
Definition: Card.cs:5566
bool isRestrained
Definition: Card.cs:550
virtual int Power
Definition: Card.cs:2231
SourceMaterial.Row material
Definition: Card.cs:1987
SoundSource PlaySound(string id, float v=1f, bool spatial=true)
Definition: Card.cs:5776
int HIT
Definition: Card.cs:2265
bool isCopy
Definition: Card.cs:862
Thing ammoData
Definition: Card.cs:1745
int hp
Definition: Card.cs:226
int WIL
Definition: Card.cs:2279
int STR
Definition: Card.cs:2269
bool HasTag(CTAG tag)
Definition: Card.cs:2531
Point pos
Definition: Card.cs:55
int DEX
Definition: Card.cs:2271
Effect PlayEffect(string id, bool useRenderPos=true, float range=0f, Vector3 fix=default(Vector3))
Definition: Card.cs:5810
Trait trait
Definition: Card.cs:49
int encLV
Definition: Card.cs:310
int c_diceDim
Definition: Card.cs:1349
MoveResult
Definition: Card.cs:13
bool HasEditorTag(EditorTag tag)
Definition: Card.cs:2536
virtual Thing Thing
Definition: Card.cs:1994
int Evalue(int ele)
Definition: Card.cs:2507
void ModExp(string alias, int a)
Definition: Card.cs:2584
SourceCategory.Row category
Definition: Card.cs:1985
CardRenderer renderer
Definition: Card.cs:57
int LV
Definition: Card.cs:370
void Say(string lang, string ref1=null, string ref2=null)
Definition: Card.cs:6423
AttackStyle GetAttackStyle()
Definition: CharaBody.cs:433
int GetAttackStyleElement(AttackStyle style)
Definition: CharaBody.cs:466
Definition: Chara.cs:10
override bool IsAliveInCurrentZone
Definition: Chara.cs:557
Element MainElement
Definition: Chara.cs:713
CharaBody body
Definition: Chara.cs:94
Faction faction
Definition: Chara.cs:423
override bool IsPC
Definition: Chara.cs:608
Chara host
Definition: Chara.cs:33
override bool IsPCParty
Definition: Chara.cs:611
int EvalueRiding()
Definition: Chara.cs:5668
bool HasCondition(string alias)
Definition: Chara.cs:8716
override bool isSynced
Definition: Chara.cs:687
override bool IsPCFaction
Definition: Chara.cs:667
override int MaxHP
Definition: Chara.cs:704
Zone currentZone
Definition: Chara.cs:251
bool HasHigherGround(Card c)
Definition: Chara.cs:1042
Chara parasite
Definition: Chara.cs:30
Chara ride
Definition: Chara.cs:27
bool isBlind
Definition: Chara.cs:130
bool IsHostile()
Definition: Chara.cs:6034
bool isConfused
Definition: Chara.cs:126
SourceRace.Row race
Definition: Chara.cs:460
UD_String_Color elementColors
Definition: ConDim.cs:2
Dice GetDice()
Definition: ConStrife.cs:52
bool IsGameStarted
Definition: Core.cs:84
Definition: Dice.cs:4
static int RollMax(int num, int sides, int bonus=0)
Definition: Dice.cs:46
static int Roll(int num, int sides, int bonus=0, Card card=null)
Definition: Dice.cs:15
Definition: EClass.cs:5
static ColorProfile Colors
Definition: EClass.cs:38
static int curve(int a, int start, int step, int rate=75)
Definition: EClass.cs:63
static int rnd(int a)
Definition: EClass.cs:58
static Core core
Definition: EClass.cs:6
static Zone _zone
Definition: EClass.cs:20
static SourceManager sources
Definition: EClass.cs:42
static Chara pc
Definition: EClass.cs:14
static GameSetting setting
Definition: EClass.cs:34
Definition: Effect.cs:7
Effect _Play(Point from, Vector3 fromV, float fixY=0f, Point to=null, Sprite sprite=null)
Definition: Effect.cs:115
Effect Emit(int num)
Definition: Effect.cs:279
static Effect Get(Effect original)
Definition: Effect.cs:85
Dictionary< int, Element > dict
int Value(int ele)
int ValueWithoutLink(int ele)
Element GetOrCreateElement(Element ele)
int id
Definition: ELEMENT.cs:248
SourceElement.Row source
Definition: ELEMENT.cs:271
int Value
Definition: ELEMENT.cs:290
static Element Create(int id, int v=0)
Definition: ELEMENT.cs:1097
static Element Void
Definition: ELEMENT.cs:236
Element GetParent(Card c)
Definition: ELEMENT.cs:520
ElementContainerFaction charaElements
Definition: FACTION.cs:146
UD_String_EffectData guns
Definition: GameSetting.cs:276
EffectSetting effect
Definition: GameSetting.cs:299
Definition: Lang.cs:6
static string[] GetList(string id)
Definition: Lang.cs:114
Definition: Msg.cs:5
static void SetColor()
Definition: Msg.cs:22
Definition: Point.cs:9
ref Vector3 Position(int height)
Definition: Point.cs:536
Point Copy()
Definition: Point.cs:479
ref Vector3 PositionCenter()
Definition: Point.cs:575
int Distance(Point p)
Definition: Point.cs:969
SourceElement elements
Definition: TC.cs:4
Definition: Thing.cs:8
SourceThing.Row source
Definition: Thing.cs:11
bool isEquipped
Definition: Thing.cs:17
override int SelfWeight
Definition: Thing.cs:62
int Penetration
Definition: Thing.cs:34
virtual Element WeaponSkill
Card owner
Definition: Trait.cs:26
bool TryGetValue(TKey key, out TValue value)
Definition: UDictionary.cs:178
Definition: Zone.cs:12
Definition: ActRef.cs:2