Elin Decompiled Documentation EA 23.343.5 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 long toHit;
11
12 public long toHitBase;
13
14 public long evasion;
15
16 public int dNum;
17
18 public int dDim;
19
20 public int dBonus;
21
22 public int toHitFix;
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 int num = w?.Evalue(ele) ?? 0;
118 {
119 num += EClass.pc.faction.charaElements.Value(ele);
120 }
121 num = num * (100 + GetTwoHandEncBonus(CC, w)) / 100;
122 if (addSelfEnc)
123 {
124 num += CC.Evalue(ele);
125 }
126 return num;
127 }
128
129 public static int GetTwoHandEncBonus(Chara CC, Thing w)
130 {
131 if (CC == null || CC.body.GetAttackStyle() != AttackStyle.TwoHand || w == null || !w.IsWeapon)
132 {
133 return 0;
134 }
135 return Mathf.Clamp(CC.Evalue(130) / 15, 0, 2) * 25;
136 }
137
138 public string GetText()
139 {
140 string text = dNum + "d" + dDim;
141 text = text + ((dBonus >= 0) ? "+" : "") + dBonus;
142 string @ref = (IsMartial ? "evalHand".lang() : "evalWeapon".lang((attackIndex + 1).ToString() ?? ""));
143 return "attackEval".lang(@ref, text, dMulti.ToString("F2") ?? "", toHit.ToString() ?? "", penetration.ToString() ?? "");
144 }
145
146 public void Prepare(Chara _CC, Thing _weapon, Card _TC = null, Point _TP = null, int _attackIndex = 0, bool _isThrow = false)
147 {
148 CC = _CC;
149 TC = _TC;
150 TP = _TP;
151 isThrow = _isThrow;
152 weapon = _weapon;
153 ammo = _weapon?.ammoData;
154 hit = (crit = (critFury = (evadePlus = false)));
156 attackType = AttackType.Slash;
157 attackStyle = AttackStyle.Default;
158 evasion = 0L;
159 penetration = 0;
160 distMod = 100;
161 attackIndex = _attackIndex;
163 ignoreAnime = (ignoreAttackSound = false);
164 if (!isThrow)
165 {
166 if (!IsRanged)
167 {
169 }
170 else if (TP != null)
171 {
172 int num = CC.pos.Distance(TP);
173 distMod = Mathf.Max(115 - 10 * Mathf.Abs(num - toolRange.BestDist) * 100 / (100 + weapon.Evalue(605) * 10), 80);
174 }
175 }
176 if (isThrow)
177 {
178 bool flag = weapon.HasTag(CTAG.throwWeapon) || weapon.HasTag(CTAG.throwWeaponEnemy);
179 int num2 = (int)Mathf.Clamp(Mathf.Sqrt(weapon.SelfWeight + weapon.ChildrenWeight) * 3f + 25f + (float)(flag ? 75 : 0), 10f, 400f + Mathf.Sqrt(CC.STR) * 50f);
180 int num3 = Mathf.Clamp(weapon.material.hardness, flag ? 40 : 20, 200);
182 attackType = AttackType.Blunt;
183 dBonus = CC.DMG + (CC.IsPCParty ? 3 : 7) + Math.Min(weapon.encLV, 99);
184 dNum = 2;
185 dDim = (((!CC.IsPCParty) ? CC.LV : 0) + CC.STR + CC.Evalue(108)) * num2 / 100 * num3 / 100 / 2;
186 dMulti = 1f + (float)CC.Evalue(132) / 500f;
187 toHitBase = EClass.curve(CC.DEX / 4 + CC.STR / 2 + weaponSkill.Value, 50, 25) + (CC.IsPCFaction ? 75 : 250);
188 toHitFix = CC.HIT + weapon.HIT;
189 penetration = 25;
190 }
191 else if (IsMartial || IsMartialWeapon)
192 {
194 bool flag2 = weapon != null && weapon.Evalue(482) > 0;
195 if (flag2)
196 {
198 }
199 attackType = ((!CC.race.meleeStyle.IsEmpty()) ? CC.race.meleeStyle.ToEnum<AttackType>() : ((EClass.rnd(2) == 0) ? AttackType.Kick : AttackType.Punch));
200 dBonus = CC.DMG + CC.encLV + (int)Mathf.Sqrt(Mathf.Max(0, weaponSkill.GetParent(CC).Value / 5 + weaponSkill.Value / 4));
201 dNum = 2 + Mathf.Min(weaponSkill.Value / 10, 4);
202 dDim = 5 + (int)Mathf.Sqrt(Mathf.Max(0, weaponSkill.Value / 3));
203 dMulti = 0.6f + (float)(weaponSkill.GetParent(CC).Value / 2 + weaponSkill.Value / 2 + CC.Evalue(flag2 ? 304 : 132) / 2) / 50f;
204 dMulti += 0.05f * (float)CC.Evalue(1400);
206 toHitFix = CC.HIT;
207 if (attackStyle == AttackStyle.Shield)
208 {
209 toHitBase = toHitBase * 75 / 100;
210 }
211 penetration = Mathf.Clamp(weaponSkill.Value / 10 + 5, 5, 20) + CC.Evalue(92);
212 if (CC.HasElement(1246))
213 {
214 penetration += 25;
215 }
216 if (IsMartialWeapon)
217 {
218 dBonus += weapon.DMG;
219 dNum += weapon.source.offense[0];
220 dDim = Mathf.Max(dDim / 2 + weapon.c_diceDim, 1);
223 if (!weapon.source.attackType.IsEmpty())
224 {
225 attackType = weapon.source.attackType.ToEnum<AttackType>();
226 }
227 }
228 }
229 else
230 {
231 if (IsRanged)
232 {
234 }
235 else
236 {
238 }
239 if (!weapon.source.attackType.IsEmpty())
240 {
241 attackType = weapon.source.attackType.ToEnum<AttackType>();
242 }
243 bool flag3 = IsCane || weapon.Evalue(482) > 0;
244 if (flag3)
245 {
247 }
248 dBonus = CC.DMG + CC.encLV + weapon.DMG;
249 dNum = weapon.source.offense[0];
251 dMulti = 0.6f + (float)(weaponSkill.GetParent(CC).Value + weaponSkill.Value / 2 + CC.Evalue(flag3 ? 304 : (IsRanged ? 133 : 132))) / 50f;
252 dMulti += 0.05f * (float)CC.Evalue(IsRanged ? 1404 : 1400);
253 toHitBase = EClass.curve((IsCane ? CC.WIL : CC.DEX) / 4 + weaponSkill.GetParent(CC).Value / 3 + weaponSkill.Value, 50, 25) + 50;
254 if (CC.HasElement(1208) && weaponSkill.id == 101)
255 {
256 toHitBase = toHitBase * 115 / 100;
257 }
258 toHitFix = CC.HIT + weapon.HIT;
259 penetration = weapon.Penetration + CC.Evalue(92);
260 if (IsRanged)
261 {
262 if (CC.HasElement(1244))
263 {
264 penetration += 25;
265 }
266 }
267 else if (CC.HasElement(1247))
268 {
269 penetration += 25;
270 }
271 if (IsCane)
272 {
273 toHitBase += 50L;
274 }
275 }
276 if (ammo != null && !(ammo.trait is TraitAmmoTalisman))
277 {
278 dNumAmmo = ((ammo.source.offense.Length != 0) ? ammo.source.offense[0] : 0);
280 dBonusAmmo = ammo.DMG + ammo.encLV;
281 if (dNumAmmo < 1)
282 {
283 dNumAmmo = 1;
284 }
285 if (dDimAmmo < 1)
286 {
287 dDimAmmo = 1;
288 }
289 toHitFix += ammo.HIT;
290 }
291 else
292 {
293 dNumAmmo = 0;
294 dDimAmmo = 0;
295 dBonusAmmo = 0;
296 }
297 if (dNum < 1)
298 {
299 dNum = 1;
300 }
301 if (dDim < 1)
302 {
303 dDim = 1;
304 }
305 if (penetration > 100)
306 {
307 penetration = 100;
308 }
309 if (attackStyle == AttackStyle.TwoHand)
310 {
311 dMulti = dMulti * 1.5f + 0.1f * Mathf.Sqrt(Mathf.Max(0, CC.Evalue(130)));
312 }
313 dMulti = dMulti * (float)distMod / 100f;
314 toHit = (toHitBase + toHitFix) * (100 + CC.Evalue(414)) / 100;
315 toHit = toHit * distMod / 100;
316 if (CC.HasCondition<ConBane>())
317 {
318 toHit = toHit * 75 / 100;
319 }
320 if (TC != null && CC.HasHigherGround(TC))
321 {
322 toHit = toHit * 120 / 100;
323 }
324 if (CC.ride != null)
325 {
326 toHit = toHit * 100 / (100 + 500 / Mathf.Max(5, 10 + CC.EvalueRiding()));
327 }
328 if (CC.parasite != null)
329 {
330 toHit = toHit * 100 / (100 + 1000 / Mathf.Max(5, 10 + CC.Evalue(227)));
331 }
332 if (CC.host != null)
333 {
334 if (CC.host.ride == CC)
335 {
336 toHit = toHit * 100 / (100 + 1000 / Mathf.Max(5, 10 + CC.STR));
337 }
338 if (CC.host.parasite == CC)
339 {
340 toHit = toHit * 100 / (100 + 2000 / Mathf.Max(5, 10 + CC.DEX));
341 }
342 }
343 if (attackStyle == AttackStyle.TwoHand)
344 {
345 toHit += 25 + (int)Mathf.Sqrt(Mathf.Max(0, CC.Evalue(130)) * 2);
346 }
347 else if (attackStyle == AttackStyle.TwoWield)
348 {
349 int num4 = CC.EvalueMax(131, -10);
350 int num5 = ((num4 >= 50) ? 10 : ((num4 >= 25) ? 12 : 15));
351 if (toHit > 0)
352 {
353 toHit = toHit * 100 / (100 + (attackIndex + 1) * num5 + attackIndex * Mathf.Clamp(2000 / (20 + num4), 0, 100));
354 }
355 }
356 if (CC.isBlind)
357 {
358 toHit /= ((IsRanged || isThrow) ? 10 : 3);
359 }
361 {
362 toHit /= 2L;
363 }
364 if (TC != null)
365 {
366 evasion = EClass.curve(TC.PER / 3 + TC.Evalue(150), 50, 10) + TC.DV + 25;
367 if (TC.isChara && TC.Chara.isBlind)
368 {
369 evasion /= 2L;
370 }
371 if (TC.HasCondition<ConDim>())
372 {
373 evasion /= 2L;
374 }
375 if (TC.isChara && TC.Chara.HasHigherGround(CC))
376 {
377 evasion = evasion * 120 / 100;
378 }
379 }
380 }
381
382 public void PlayRangedAnime(int numFire, float delay = 0f)
383 {
384 if (weapon == null)
385 {
386 return;
387 }
388 bool isGun = toolRange is TraitToolRangeGun;
389 bool isCane = toolRange is TraitToolRangeCane;
390 GameSetting.EffectData data = EClass.setting.effect.guns.TryGetValue(weapon.id) ?? EClass.setting.effect.guns[isCane ? "cane" : (isGun ? "gun" : "bow")];
391 bool isPCC = CC.IsPCC && CC.renderer.hasActor;
392 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);
393 Chara _CC = CC;
394 Point _TP = posRangedAnime.Copy();
395 Thing _weapon = weapon;
396 bool ignoreSound = ignoreAttackSound;
398 Color effColor = Color.white;
399 if (isCane)
400 {
401 Element element = toolRange.owner.elements.dict.Values.Where((Element e) => e.source.categorySub == "eleAttack").RandomItem();
402 if (element != null)
403 {
404 effColor = EClass.Colors.elementColors.TryGetValue(element.source.alias, "eleFire");
405 }
406 if (data.caneColor.a > 0f)
407 {
408 effColor = (data.caneColorBlend ? Color.Lerp(effColor, data.caneColor, 0.5f) : data.caneColor);
409 }
410 }
411 bool isLaser = toolRange is TraitToolRangeGunEnergy || data.forceLaser;
412 bool isRail = isLaser && (weapon.id == "gun_rail" || data.forceRail);
413 Vector3 muzzleFix = (data.fireFromMuzzle ? ((Vector3)firePos) : Vector3.zero);
414 for (int num = 0; num < numFire; num++)
415 {
416 TweenUtil.Delay((float)num * data.delay + delay, delegate
417 {
419 {
420 Vector3 fromV = (_CC.isSynced ? _CC.renderer.position : _CC.pos.Position()) + muzzleFix;
421 switch (_weapon.id)
422 {
423 case "gun_rail":
424 _CC.PlayEffect("laser_rail", useRenderPos: true, 0f, muzzleFix).GetComponent<SpriteBasedLaser>().Play(_TP.PositionCenter());
425 break;
426 case "gun_laser":
427 _CC.PlayEffect("laser", useRenderPos: true, 0f, muzzleFix).GetComponent<SpriteBasedLaser>().Play(_TP.PositionCenter());
428 break;
429 case "gun_laser_assault":
430 Effect.Get("ranged_laser")._Play(_CC.pos, fromV, 0f, _TP, data.sprite);
431 break;
432 default:
433 if (isLaser)
434 {
435 string id = (isRail ? "laser_rail" : "laser");
436 _CC.PlayEffect(id, useRenderPos: true, 0f, muzzleFix).GetComponent<SpriteBasedLaser>().Play(_TP.PositionCenter());
437 }
438 else
439 {
440 Effect effect = Effect.Get("ranged_arrow")._Play(_CC.pos, fromV, 0f, _TP, data.sprite);
441 if (isCane)
442 {
443 effect.sr.color = effColor;
444 }
445 }
446 break;
447 }
448 if (data.eject)
449 {
450 if (!ignoreSound)
451 {
452 _CC.PlaySound(data.idSoundEject.IsEmpty("bullet_drop"));
453 }
454 _CC.PlayEffect("bullet").Emit(1);
455 }
456 if (isGun)
457 {
458 if (isPCC)
459 {
460 _weapon.PlayEffect(data.idEffect.IsEmpty("gunfire"), useRenderPos: true, 0f, firePos);
461 }
462 else
463 {
464 _CC.PlayEffect(data.idEffect.IsEmpty("gunfire"));
465 }
466 }
467 if (!ignoreSound)
468 {
469 _CC.PlaySound(data.idSound.IsEmpty("attack_gun"));
470 }
471 }
472 });
473 }
474 }
475
476 public int GetRocketPower()
477 {
478 return (30 + (dNum * dDim + dBonus) + (dNumAmmo * dDimAmmo + dBonusAmmo)) * (100 + (int)Mathf.Sqrt(weaponSkill.Value) * 8) / 100;
479 }
480
481 public long GetRawDamage(float dmgMulti, bool crit, bool maxRoll)
482 {
483 bool flag = CC.HasCondition<ConReload>();
484 long num = Dice.Roll(dNum, dDim, dBonus, CC);
485 if (ammo != null && !flag)
486 {
488 }
489 if (crit || maxRoll)
490 {
491 num = Dice.RollMax(dNum, dDim, dBonus);
492 if (ammo != null && !flag)
493 {
495 }
496 if (crit && (IsMartial || IsMartialWeapon))
497 {
498 dMulti *= 1.25f;
499 }
500 }
501 if (CC.Evalue(1355) > 0)
502 {
503 num++;
504 }
505 num = (long)(dMulti * (float)num * dmgMulti);
506 long num2 = 99999999L;
507 ConStrife condition = CC.GetCondition<ConStrife>();
508 if (condition != null)
509 {
510 num = num * (100 + condition.lv * 10) / 100;
511 num2 = num2 * (100 + condition.lv * 5) / 100;
512 }
513 return (long)Mathf.Clamp(num, 0f, num2);
514 }
515
516 public static void ProcShieldEncs(Chara CC, Card TC, int mtpChance = 100)
517 {
518 foreach (BodySlot slot in CC.body.slots)
519 {
520 if (slot.elementId == 35 && slot.thing != null && (slot.thing.category.IsChildOf("shield") || slot.thing.category.IsChildOf("martial")))
521 {
522 ProcAbility(slot.thing.elements.dict.Values.ToList(), CC, TC, CC.Evalue((slot.thing.category.skill == 0) ? 123 : slot.thing.category.skill), subAttack: false, mtpChance);
523 }
524 }
525 }
526
527 public static void ProcAbility(List<Element> list, Chara CC, Card TC, int bonus, bool subAttack = false, int mtpChance = 100)
528 {
529 if (list == null)
530 {
531 return;
532 }
533 foreach (Element item in list)
534 {
535 ProcAbility(item, CC, TC, bonus, subAttack, mtpChance);
536 }
537 }
538
539 public static void ProcAbility(Element e, Chara CC, Card TC, int bonus, bool subAttack = false, int mtpChance = 100)
540 {
541 if (!(e is Ability))
542 {
543 return;
544 }
545 int num = (10 + e.Value / 5) * mtpChance / 100;
546 int power = EClass.curve((100 + e.Value * 10) * (100 + bonus) / 100, 400, 100);
547 if (e.id == 6602)
548 {
549 num = 100;
550 }
551 if (num <= EClass.rnd(100))
552 {
553 return;
554 }
555 Act obj = e as Act;
556 Card card = (obj.TargetType.CanSelectSelf ? CC : TC);
557 string text = ((e.source.proc.Length >= 2) ? e.source.proc[1] : "");
558 string text2 = obj.source.abilityType.TryGet(0);
559 switch (text2)
560 {
561 case "buff":
562 if (CC.HasCondition(text))
563 {
564 return;
565 }
566 card = CC;
567 break;
568 case "debuff":
569 case "attack":
570 case "dot":
571 card = TC;
572 break;
573 }
574 if (subAttack)
575 {
576 if (card == CC)
577 {
578 return;
579 }
580 switch (text2)
581 {
582 case "summon":
583 return;
584 case "teleport":
585 return;
586 case "suicide":
587 return;
588 }
589 }
590 if (card.IsAliveInCurrentZone)
591 {
592 Card tC = Act.TC;
593 ActEffect.ProcAt(e.source.proc[0].ToEnum<EffectId>(), power, BlessedState.Normal, CC, card, card.pos, isNeg: false, new ActRef
594 {
595 n1 = text,
596 aliasEle = e.source.aliasRef,
597 noFriendlyFire = true
598 });
599 Act.TC = tC;
600 }
601 }
602
603 public bool Perform(int count, bool hasHit, float dmgMulti = 1f, bool maxRoll = false, bool subAttack = false)
604 {
605 bool flag = CC.HasCondition<ConReload>();
606 bool flag2 = CC.HasElement(486) && CC.IsPCFactionOrMinion;
607 hit = CalcHit();
608 if (CC.id == "tsunami")
609 {
610 hit = true;
611 }
612 long num = GetRawDamage(dmgMulti, crit, maxRoll);
613 if (IsRanged && count >= numFireWithoutDamageLoss)
614 {
615 num = num * 100 / (100 + (count - numFireWithoutDamageLoss + 1) * 30);
616 }
617 if (CC.isRestrained)
618 {
619 num /= 2;
620 }
621 List<Element> list = new List<Element>();
622 int num2 = CC.Evalue(91);
623 string id = CC.id;
624 if ((id == "stalker" || id == "stalker_shadow") && TC.isChara && TC.Chara.CanSee(CC))
625 {
626 num2 = 0;
627 }
628 int num3 = 0;
629 if (weapon != null)
630 {
631 list = weapon.elements.dict.Values.ToList();
632 if (ammo != null && !flag)
633 {
634 list = list.Concat(ammo.elements.dict.Values).ToList();
635 }
636 num2 += weapon.Evalue(91, ignoreGlobalElement: true);
637 num3 += weapon.Evalue(603, ignoreGlobalElement: true);
638 }
639 foreach (Element value in CC.elements.dict.Values)
640 {
641 if (!value.IsGlobalElement && value.source.categorySub == "eleAttack")
642 {
643 list.Add(value);
644 }
645 }
646 if (!IsRanged && !isThrow && CC.HasElement(1426))
647 {
648 list.Add(Element.Create(6650, 100));
649 }
650 int bane;
651 if (TC?.Chara != null)
652 {
653 bane = 0;
654 AddBane(valid: true, 468, 50);
655 AddBane(TC.Chara.IsUndead, 461, 100);
656 AddBane(TC.Chara.IsAnimal, 463, 100);
657 AddBane(TC.Chara.IsHuman, 464, 100);
658 AddBane(TC.Chara.IsDragon, 460, 100);
659 AddBane(TC.Chara.IsGod, 466, 100);
660 AddBane(TC.Chara.IsMachine, 465, 100);
661 AddBane(TC.Chara.IsFish, 467, 100);
662 AddBane(TC.Chara.IsFairy, 462, 100);
663 if (bane != 0)
664 {
665 num = num * (100 + bane * 3) / 100;
666 }
667 }
668 if (CC.IsPCFaction)
669 {
670 foreach (Element value2 in EClass.pc.faction.charaElements.dict.Values)
671 {
672 if (value2.Value > 0)
673 {
674 list.Add(value2);
675 }
676 }
677 }
678 if (hit && num2 > EClass.rnd(100))
679 {
680 CC.Say("vopal");
681 penetration = 100;
682 }
683 if (crit)
684 {
685 CC.Say((critFury ? "fury_" : "") + (CC.IsHostile() ? "critical_enemy" : "critical"));
686 if (CC.IsPC)
687 {
688 CC.PlaySound("critical");
689 }
690 }
691 if (CC.isSynced || (TC != null && TC.isSynced))
692 {
693 if (toolRange != null && (!IsRanged || count == 0) && !flag && !ignoreAnime)
694 {
696 }
697 if (hit && TC != null && !hasHit)
698 {
699 PlayHitEffect();
700 }
701 }
702 if (TC == null)
703 {
704 if (weapon == null || !(weapon.trait is TraitToolRangeGunRocket))
705 {
706 CC.Say(IsRanged ? "attack_air_range" : "attack_air", CC);
707 }
708 return true;
709 }
710 if (!hit)
711 {
712 if (TC != null)
713 {
714 if (CC.IsPCParty)
715 {
716 CC.Say(evadePlus ? "evadePlus2" : "evade2", CC, TC);
717 }
718 else
719 {
720 TC.Say(evadePlus ? "evadePlus" : "evade", TC, CC);
721 }
722 ModExpDef(150, 90);
723 ModExpDef(151, 90);
724 }
725 ProcAbility(list, CC, TC, weaponSkill.Value * (100 + GetTwoHandEncBonus(CC, weapon)) / 100, subAttack);
726 return false;
727 }
728 if (TC.IsPC)
729 {
730 Msg.SetColor("attack_pc");
731 EClass.pc.Say("attackMeleeToPC", CC, TC, GetAttackText(attackType, 3));
732 }
733 else
734 {
735 CC.Say("attackMelee", CC, TC, GetAttackText(attackType, 0));
736 }
737 bool showEffect = true;
738 int num4 = 0;
739 int num5 = 0;
740 int num6 = 0;
741 ConWeapon conWeapon = null;
742 if (weapon != null)
743 {
744 foreach (Element value3 in weapon.elements.dict.Values)
745 {
746 if (value3.source.categorySub == "eleConvert")
747 {
748 num4 = EClass.sources.elements.alias[value3.source.aliasRef].id;
749 num5 = 50 + value3.Value * 2;
750 num6 = Mathf.Min(value3.Value, 100);
751 break;
752 }
753 }
754 }
755 if (num4 == 0)
756 {
758 {
759 conWeapon = CC.GetCondition<ConWeapon>();
760 num4 = conWeapon.sourceElement.id;
761 num5 = conWeapon.power / 2;
762 num6 = (int)Mathf.Min(40f + MathF.Sqrt(conWeapon.power), 80f);
763 }
764 if (conWeapon == null && (weapon == null || IsMartialWeapon) && (CC.MainElement != Element.Void || CC.HasElement(1565)))
765 {
766 num4 = (CC.HasElement(1565) ? 915 : CC.MainElement.id);
767 num5 = CC.Power / 3 + EClass.rnd(CC.Power / 2);
768 if (CC.MainElement != Element.Void)
769 {
770 num5 += CC.MainElement.Value;
771 }
772 showEffect = false;
773 num6 = 50;
774 }
775 if (conWeapon == null && weapon != null && weapon.trait is TraitToolRangeCane)
776 {
777 IEnumerable<Element> enumerable = weapon.elements.dict.Values.Where((Element e) => e.source.categorySub == "eleAttack");
778 if (enumerable.Count() > 0)
779 {
780 num4 = enumerable.RandomItem().id;
781 num5 = num4 switch
782 {
783 920 => 30,
784 914 => 50,
785 918 => 50,
786 _ => 100,
787 };
788 }
789 num6 = 50;
790 }
791 }
792 long num7 = num;
793 long num8 = num * num6 / 100;
794 num -= num8;
795 long num9 = num * penetration / 100;
796 num -= num9;
797 num = TC.ApplyProtection(num) + num9 + num8;
798 int weaponEnc = GetWeaponEnc(CC, weapon, 609, addSelfEnc: true);
799 TC.DamageHP(num, num4, num5, (!IsRanged && !isThrow) ? AttackSource.Melee : AttackSource.Range, CC, showEffect, weapon);
800 if (conWeapon != null && (weaponEnc <= 0 || !(Mathf.Min(10f + Mathf.Sqrt(weaponEnc) * 5f, 90f) > (float)EClass.rnd(100))))
801 {
802 conWeapon.Mod(-1);
803 }
804 bool flag3 = IsCane || (weapon != null && weapon.Evalue(482) > 0);
805 int attackStyleElement = CC.body.GetAttackStyleElement(attackStyle);
806 if (!subAttack)
807 {
808 int mod = 100 / (count + 1);
809 if (!IsRanged || count == 0)
810 {
811 ModExpAtk(weaponSkill.id, mod);
812 ModExpAtk(flag3 ? 304 : (IsRanged ? 133 : 132), mod);
813 }
814 if (crit)
815 {
816 ModExpAtk(134, 50);
817 }
818 if (count == 0 && attackStyleElement != 0)
819 {
820 ModExpAtk(attackStyleElement, 100);
821 }
822 }
823 if (!CC.IsAliveInCurrentZone || !TC.IsAliveInCurrentZone)
824 {
825 return true;
826 }
827 if (EClass.rnd(8) == 0 && TC.isChara && CC.HasElement(1219))
828 {
829 CC.Say("abCrab", CC, TC);
830 TC.Chara.AddCondition<ConParalyze>(30 + EClass.rnd(30));
831 TC.Chara.AddCondition<ConGravity>();
832 }
833 if (list.Count > 0 && !flag2)
834 {
835 foreach (Element item in list)
836 {
837 if (!TC.IsAliveInCurrentZone)
838 {
839 break;
840 }
841 if (!item.IsActive(weapon) || !(item.source.categorySub == "eleAttack"))
842 {
843 continue;
844 }
845 int num10 = 25;
846 long num11 = EClass.rnd(num * (100 + item.Value * 10) / 500 + 5);
847 num11 = num11 * (100 + GetTwoHandEncBonus(CC, weapon)) / 100;
848 if (num11 >= 0)
849 {
850 if (conWeapon == null && weapon != null && weapon.trait is TraitToolRangeCane)
851 {
852 num10 = 0;
853 }
854 if (num10 > EClass.rnd(100))
855 {
856 TC.DamageHP(num11, item.id, isThrow ? (100 + item.Value * 5) : (30 + item.Value), AttackSource.WeaponEnchant, CC);
857 }
858 }
859 }
860 ProcAbility(list, CC, TC, weaponSkill.Value * (100 + GetTwoHandEncBonus(CC, weapon)) / 100, subAttack);
861 }
862 if (!CC.IsAliveInCurrentZone || !TC.IsAliveInCurrentZone)
863 {
864 return true;
865 }
866 if (!IsRanged && !flag2 && attackStyle == AttackStyle.Shield)
867 {
868 int num12 = CC.Evalue(123);
869 int num13 = CC.Evalue(381);
870 if (CC.elements.ValueWithoutLink(123) >= 10 && Mathf.Clamp(Mathf.Sqrt(num12) - 2f, 8f, 15f) + Mathf.Min(Mathf.Sqrt(num13), 25f) > (float)EClass.rnd(100))
871 {
872 num = num7 * (Mathf.Min(50 + num12 + num13, 200) + (int)Mathf.Min(Mathf.Sqrt(num13), 100f)) / 100;
873 penetration = (int)Mathf.Sqrt(num13) + ((num13 != 0) ? 20 : 0);
874 if (penetration > 100)
875 {
876 penetration = 100;
877 }
878 num9 = num * penetration / 100;
879 num -= num9;
880 num = TC.ApplyProtection(num) + num9;
881 Debug.Log("Bash:" + num + "/" + num7);
882 CC.PlaySound("shield_bash");
883 CC.Say("shield_bash", CC, TC);
884 TC.DamageHP(num, AttackSource.None, CC);
885 if (TC.IsAliveInCurrentZone && TC.isChara)
886 {
887 if (EClass.rnd(2) == 0)
888 {
889 TC.Chara.AddCondition<ConDim>(50 + (int)Mathf.Sqrt(num12) * 10);
890 }
891 TC.Chara.AddCondition<ConParalyze>(EClass.rnd(2), force: true);
892 }
893 if (!TC.isRestrained)
894 {
895 ProcShieldEncs(CC, TC, 500 + num13);
896 }
898 {
899 CC.ModExp(123, 50);
900 }
901 }
902 }
903 if (!CC.IsAliveInCurrentZone || !TC.IsAliveInCurrentZone)
904 {
905 return true;
906 }
907 if (CC.HasElement(1253) && (!CC.HasElement(486) || !CC.IsPCFactionOrMinion))
908 {
909 TC.DamageHP(num7 / 10, 916, 100, AttackSource.None, CC);
910 }
911 if (!CC.IsAliveInCurrentZone || !TC.IsAliveInCurrentZone)
912 {
913 return true;
914 }
915 if (TC.isChara && !TC.HasCondition<ConGravity>() && num3 > 0 && num3 * 2 + 15 > EClass.rnd(100) && !TC.isRestrained && TC.Chara.TryMoveFrom(CC.pos) == Card.MoveResult.Success)
916 {
917 TC.pos.PlayEffect("vanish");
918 TC.PlaySound("push", 1.5f);
919 }
920 return true;
921 void AddBane(bool valid, int idEle, int num14)
922 {
923 if (valid)
924 {
925 bane += (CC.Evalue(idEle) + ((weapon != null) ? weapon.Evalue(idEle, ignoreGlobalElement: true) : 0) + ((ammo != null) ? ammo.Evalue(idEle, ignoreGlobalElement: true) : 0)) * num14 / 100;
926 }
927 }
928 bool IgnoreExp()
929 {
930 if (!CC.HasEditorTag(EditorTag.Invulnerable) && !CC.HasEditorTag(EditorTag.InvulnerableToMobs) && !TC.HasEditorTag(EditorTag.Invulnerable))
931 {
932 return TC.HasEditorTag(EditorTag.InvulnerableToMobs);
933 }
934 return true;
935 }
936 void ModExpAtk(int ele, int num14)
937 {
938 if (!IgnoreExp() && (!TC.isCopy || EClass.rnd(10) == 0))
939 {
940 int a = (Mathf.Clamp((TC.LV + 10 - CC.elements.ValueWithoutLink(ele)) / 2, 1, 10) + Mathf.Min(TC.LV / 10, 10)) * num14 / 100;
941 a = Mathf.Min(a, 200);
942 if (TC == CC)
943 {
944 a /= 2;
945 }
946 if (a > 0)
947 {
948 CC.ModExp(ele, a + EClass.rnd(a / 2 + 1));
949 }
950 }
951 }
952 void ModExpDef(int ele, int num14)
953 {
954 if (!IgnoreExp() && (!CC.isCopy || EClass.rnd(10) == 0))
955 {
956 int a = (Mathf.Clamp((CC.LV + 10 - TC.elements.ValueWithoutLink(ele)) / 2, 1, 10) + Mathf.Min(CC.LV / 10, 10)) * num14 / 100;
957 a = Mathf.Min(a, TC.isRestrained ? 10 : 200);
958 if (TC == CC)
959 {
960 a /= 2;
961 }
962 if (!TC.IsPC && !TC.isRestrained && !TC.HasHost)
963 {
964 a *= 3;
965 }
966 if (a > 0)
967 {
968 TC.ModExp(ele, a + EClass.rnd(a / 2 + 1));
969 }
970 }
971 }
972 void PlayHitEffect()
973 {
974 string id2 = "hit_default";
975 string id3 = "hit_default";
976 switch (attackType)
977 {
978 case AttackType.Slash:
979 id3 = "hit_slash";
980 id2 = "hit_slash";
981 break;
982 case AttackType.Spore:
983 id3 = "hit_spore";
984 id2 = "hit_spore";
985 break;
986 case AttackType.Claw:
987 case AttackType.Bite:
988 id3 = "hit_claw";
989 id2 = "hit_claw";
990 break;
991 case AttackType.Blunt:
992 case AttackType.Punch:
993 case AttackType.Kick:
994 case AttackType.Bow:
995 case AttackType.Gun:
996 case AttackType.Cane:
997 id3 = "hit_blunt";
998 id2 = "hit_blunt";
999 break;
1000 }
1001 if (TC != null)
1002 {
1003 TC.PlayEffect(id3).SetScale(crit ? 1.25f : 0.75f);
1004 }
1005 CC.PlaySound(id2);
1006 }
1007 }
1008
1009 private bool Crit()
1010 {
1011 crit = true;
1012 return true;
1013 }
1014
1015 private bool EvadePlus()
1016 {
1017 evadePlus = true;
1018 return false;
1019 }
1020
1021 public bool CalcHit()
1022 {
1023 if (CC.HasCondition<ConAmbush>())
1024 {
1025 return Crit();
1026 }
1027 if (critFury)
1028 {
1029 return Crit();
1030 }
1031 if (CC.HasCondition<ConSevenSense>() && (CC.HasElement(1244) || CC.HasElement(1246) || CC.HasElement(1247) || CC.HasElement(1253)))
1032 {
1033 return true;
1034 }
1035 if (TC != null)
1036 {
1037 if (TC.HasCondition<ConDim>() && EClass.rnd(4) == 0)
1038 {
1039 return Crit();
1040 }
1041 if (TC.IsDeadOrSleeping)
1042 {
1043 return Crit();
1044 }
1045 int num = TC.Evalue(151);
1046 if (num != 0 && toHit < num * 10)
1047 {
1048 float num2 = (float)(evasion * 100) / Mathf.Clamp(toHit, 1f, toHit);
1049 if (num2 > 300f && EClass.rnd(num + 250) > 100)
1050 {
1051 return EvadePlus();
1052 }
1053 if (num2 > 200f && EClass.rnd(num + 250) > 150)
1054 {
1055 return EvadePlus();
1056 }
1057 if (num2 > 150f && EClass.rnd(num + 250) > 200)
1058 {
1059 return EvadePlus();
1060 }
1061 }
1062 int num3 = TC.Evalue(57);
1063 if (num3 > 0)
1064 {
1065 if (num3 > EClass.rnd(100))
1066 {
1067 return EvadePlus();
1068 }
1069 }
1070 else if (num3 < 0 && num3 * -1 > EClass.rnd(100))
1071 {
1072 return true;
1073 }
1074 }
1075 if (EClass.rnd(20) == 0)
1076 {
1077 return true;
1078 }
1079 if (EClass.rnd(20) == 0)
1080 {
1081 return false;
1082 }
1083 if (toHit < 1)
1084 {
1085 return false;
1086 }
1087 if (evasion < 1)
1088 {
1089 return true;
1090 }
1091 if (EClass.rnd(toHit) < EClass.rnd(evasion * (IsRanged ? 150 : 125) / 100))
1092 {
1093 return false;
1094 }
1095 if (EClass.rnd(5000) < CC.Evalue(73) + 50)
1096 {
1097 return Crit();
1098 }
1099 if ((float)(CC.Evalue(90) + ((weapon != null) ? weapon.Evalue(90, ignoreGlobalElement: true) : 0)) + Mathf.Sqrt(CC.Evalue(134)) > (float)EClass.rnd(200))
1100 {
1101 return Crit();
1102 }
1103 if (CC.Evalue(1420) > 0)
1104 {
1105 int num4 = Mathf.Min(100, 100 - CC.hp * 100 / CC.MaxHP) * (50 + CC.Evalue(1420) * 50) / 100;
1106 if (num4 >= 50 && num4 * num4 * num4 * num4 / 3 > EClass.rnd(100000000))
1107 {
1108 return Crit();
1109 }
1110 }
1111 return true;
1112 }
1113
1114 public string GetAttackText(AttackType type, int id)
1115 {
1116 return Lang.GetList("attack" + type)[id];
1117 }
1118}
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
if(!match.Success)
EditorTag
Definition: EditorTag.cs:2
EffectId
Definition: EffectId.cs:2
static void ProcAt(EffectId id, int power, BlessedState state, Card cc, Card tc, Point tp, bool isNeg, ActRef actRef=default(ActRef))
Definition: ActEffect.cs:519
Definition: ACT.cs:62
static Card TC
Definition: ACT.cs:79
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 void ProcAbility(List< Element > list, Chara CC, Card TC, int bonus, bool subAttack=false, int mtpChance=100)
static AttackProcess Current
Definition: AttackProcess.cs:8
long GetRawDamage(float dmgMulti, bool crit, bool maxRoll)
int GetRocketPower()
static void ProcAbility(Element e, Chara CC, Card TC, int bonus, bool subAttack=false, int mtpChance=100)
static int GetTwoHandEncBonus(Chara CC, Thing w)
string GetText()
bool ignoreAttackSound
int numFireWithoutDamageLoss
bool IsMartialWeapon
Point posRangedAnime
Element weaponSkill
void PlayRangedAnime(int numFire, float delay=0f)
static int GetWeaponEnc(Chara CC, Thing w, int ele, bool addSelfEnc=false)
AttackStyle attackStyle
static void ProcShieldEncs(Chara CC, Card TC, int mtpChance=100)
void Mod(int a, bool force=false)
SourceElement.Row sourceElement
int elementId
Definition: BodySlot.cs:6
Thing thing
Definition: BodySlot.cs:8
virtual int currentDir
Definition: CardActor.cs:41
CardActor actor
Definition: CardRenderer.cs:11
Definition: Card.cs:11
int DMG
Definition: Card.cs:2401
bool IsPCFactionOrMinion
Definition: Card.cs:2342
int EvalueMax(int ele, int min=0)
Definition: Card.cs:2718
ElementContainerCard elements
Definition: Card.cs:42
string id
Definition: Card.cs:36
int ChildrenWeight
Definition: Card.cs:2065
bool isRestrained
Definition: Card.cs:569
virtual int Power
Definition: Card.cs:2365
SourceMaterial.Row material
Definition: Card.cs:2103
SoundSource PlaySound(string id, float v=1f, bool spatial=true)
Definition: Card.cs:6641
int HIT
Definition: Card.cs:2399
bool isCopy
Definition: Card.cs:881
Thing ammoData
Definition: Card.cs:1825
int hp
Definition: Card.cs:245
int WIL
Definition: Card.cs:2413
int STR
Definition: Card.cs:2403
bool HasTag(CTAG tag)
Definition: Card.cs:2728
Point pos
Definition: Card.cs:60
int DEX
Definition: Card.cs:2405
Effect PlayEffect(string id, bool useRenderPos=true, float range=0f, Vector3 fix=default(Vector3))
Definition: Card.cs:6675
Trait trait
Definition: Card.cs:54
int encLV
Definition: Card.cs:329
int c_diceDim
Definition: Card.cs:1429
MoveResult
Definition: Card.cs:13
bool HasEditorTag(EditorTag tag)
Definition: Card.cs:2733
virtual Thing Thing
Definition: Card.cs:2110
int Evalue(int ele)
Definition: Card.cs:2704
void ModExp(string alias, int a)
Definition: Card.cs:2781
SourceCategory.Row category
Definition: Card.cs:2101
bool IsWeapon
Definition: Card.cs:2260
CardRenderer renderer
Definition: Card.cs:64
bool HasElement(int ele, bool includeNagative=false)
Definition: Card.cs:6379
int LV
Definition: Card.cs:389
void Say(string lang, string ref1=null, string ref2=null)
Definition: Card.cs:7319
List< BodySlot > slots
Definition: CharaBody.cs:8
AttackStyle GetAttackStyle()
Definition: CharaBody.cs:508
int GetAttackStyleElement(AttackStyle style)
Definition: CharaBody.cs:541
Definition: Chara.cs:10
override bool IsAliveInCurrentZone
Definition: Chara.cs:567
BaseCondition GetCondition(string idCon)
Definition: Chara.cs:10066
Element MainElement
Definition: Chara.cs:735
CharaBody body
Definition: Chara.cs:94
Faction faction
Definition: Chara.cs:431
override bool IsPC
Definition: Chara.cs:630
Chara host
Definition: Chara.cs:33
override bool IsPCParty
Definition: Chara.cs:633
int EvalueRiding()
Definition: Chara.cs:6495
bool HasCondition(string alias)
Definition: Chara.cs:10010
override bool isSynced
Definition: Chara.cs:709
override bool IsPCFaction
Definition: Chara.cs:689
override int MaxHP
Definition: Chara.cs:726
Zone currentZone
Definition: Chara.cs:259
bool HasHigherGround(Card c)
Definition: Chara.cs:1249
Chara parasite
Definition: Chara.cs:30
Chara ride
Definition: Chara.cs:27
bool isBlind
Definition: Chara.cs:132
bool IsHostile()
Definition: Chara.cs:6909
bool isConfused
Definition: Chara.cs:128
SourceRace.Row race
Definition: Chara.cs:468
UD_String_Color elementColors
Definition: ConDim.cs:2
bool IsGameStarted
Definition: Core.cs:87
Definition: Dice.cs:5
static long RollMax(int num, int sides, int bonus=0)
Definition: Dice.cs:81
static long Roll(int num, int sides, int bonus=0, Card card=null)
Definition: Dice.cs:59
Definition: EClass.cs:6
static int curve(long _a, int start, int step, int rate=75)
Definition: EClass.cs:69
static ColorProfile Colors
Definition: EClass.cs:39
static Core core
Definition: EClass.cs:7
static Zone _zone
Definition: EClass.cs:21
static int rnd(long a)
Definition: EClass.cs:59
static SourceManager sources
Definition: EClass.cs:43
static Chara pc
Definition: EClass.cs:15
static GameSetting setting
Definition: EClass.cs:35
Definition: Effect.cs:7
Effect _Play(Point from, Vector3 fromV, float fixY=0f, Point to=null, Sprite sprite=null)
Definition: Effect.cs:117
Effect Emit(int num)
Definition: Effect.cs:283
static Effect Get(Effect original)
Definition: Effect.cs:80
Dictionary< int, Element > dict
int Value(int ele)
int ValueWithoutLink(int ele)
Element GetOrCreateElement(Element ele)
int id
Definition: ELEMENT.cs:259
SourceElement.Row source
Definition: ELEMENT.cs:282
int Value
Definition: ELEMENT.cs:301
static Element Create(int id, int v=0)
Definition: ELEMENT.cs:1163
static Element Void
Definition: ELEMENT.cs:247
bool IsGlobalElement
Definition: ELEMENT.cs:354
Element GetParent(Card c)
Definition: ELEMENT.cs:559
ElementContainerFaction charaElements
Definition: FACTION.cs:146
UD_String_EffectData guns
Definition: GameSetting.cs:279
EffectSetting effect
Definition: GameSetting.cs:344
Definition: Lang.cs:7
static string[] GetList(string id)
Definition: Lang.cs:113
Definition: Msg.cs:5
static void SetColor()
Definition: Msg.cs:22
Definition: Point.cs:9
ref Vector3 Position(int height)
Definition: Point.cs:553
Point Copy()
Definition: Point.cs:491
ref Vector3 PositionCenter()
Definition: Point.cs:592
int Distance(Point p)
Definition: Point.cs:995
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:64
int Penetration
Definition: Thing.cs:34
virtual Element WeaponSkill
Card owner
Definition: Trait.cs:28
bool TryGetValue(TKey key, out TValue value)
Definition: UDictionary.cs:178
Definition: Zone.cs:12
Definition: ActRef.cs:2