Elin Decompiled Documentation EA 23.252 Stable Patch 2
Loading...
Searching...
No Matches
GoalCombat.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using UnityEngine;
4
5public class GoalCombat : Goal
6{
7 public class ItemAbility
8 {
9 public Act act;
10
11 public int priority;
12
13 public int priorityMod;
14
15 public int chance;
16
17 public Chara tg;
18
19 public bool pt;
20
21 public bool aiPt;
22 }
23
25
26 public Chara tc;
27
28 public int idleCount;
29
30 public int moveFail;
31
32 public List<ItemAbility> abilities;
33
34 public List<Chara> charas = new List<Chara>();
35
37
38 public override bool CancelWhenDamaged => false;
39
40 public override bool CancelOnAggro => false;
41
43
44 public override bool CanManualCancel()
45 {
46 if (owner != null)
47 {
48 return !owner.isBerserk;
49 }
50 return false;
51 }
52
53 public override IEnumerable<Status> Run()
54 {
55 if (destEnemy != null)
56 {
57 owner.enemy = destEnemy;
58 destEnemy = null;
59 }
60 int count = 0;
61 int lostCount = 0;
62 bool dontWander = owner.IsPCParty && !owner.IsPC && EClass.game.config.tactics.dontWander;
63 while (true)
64 {
66 {
67 EClass._zone.SetAlarm(enable: true);
68 }
69 bool canSeeLos = false;
71 {
72 Debug.Log("■" + owner.Name + "/" + count + "/" + lostCount);
73 }
75 {
76 owner.enemy = null;
77 owner.ShowEmo(Emo.happy);
78 yield return Success();
79 }
80 count++;
81 if (dontWander && owner.enemy != null && !EClass.pc.isBlind && !EClass.pc.CanSeeLos(owner.enemy) && (owner.Dist(EClass.pc) > 4 || owner.Dist(owner.enemy) > 1))
82 {
84 if (firstStep.IsValid && !firstStep.HasChara)
85 {
86 owner.enemy = null;
87 }
88 }
89 tc = owner.enemy;
90 if (tc != null && owner.IsPCFaction)
91 {
93 {
94 owner.enemy = null;
95 yield return Success();
96 }
98 {
99 tc = (owner.enemy = null);
100 }
101 }
102 if (tc == null || tc.isDead || !tc.ExistsOnMap || !tc.pos.IsInBounds || lostCount >= (owner.IsPowerful ? 50 : 5) || !owner.CanSee(tc))
103 {
104 tc = (owner.enemy = null);
106 {
107 yield return Success();
108 }
110 lostCount = 0;
111 if (owner.enemy == null)
112 {
113 yield return Success();
114 }
115 tc = owner.enemy;
116 }
117 else
118 {
119 canSeeLos = owner.CanSeeLos(tc);
120 lostCount = ((!canSeeLos) ? (lostCount + 1) : 0);
121 }
122 if (owner.IsPC && tc.HasEditorTag(EditorTag.Invulnerable))
123 {
124 Msg.Say("abort_idle");
125 yield return Success();
126 }
127 if (tc.IsPCFaction && owner.id == "melilith_boss" && EClass._map.plDay.list.Count > 1 && EClass._map.plDay.list[0].data.id != 107)
128 {
129 EClass._zone.SetBGM(107);
130 }
131 if (abilities == null)
132 {
133 abilities = new List<ItemAbility>();
135 }
136 if (owner.IsPCFaction && tc.IsPCFaction && EClass.rnd(5) == 0 && count > 2)
137 {
138 CalmDown();
139 yield return Success();
140 }
142 {
143 if (owner.calmCheckTurn < 0 || (!owner.enemy.IsPCParty && EClass.rnd(10) == 0))
144 {
145 CalmDown();
146 yield return Success();
147 }
149 }
150 if (owner.IsPC)
151 {
152 CursorSystem.ignoreCount = 1;
153 }
154 if (tc.host != null && (tc.hp == 0 || EClass.rnd(5) == 0))
155 {
157 }
158 if (tc.parasite != null && !tc.isRestrained && tc.parasite.hp > 0 && EClass.rnd(5) == 0)
159 {
161 }
162 if (tc.ride != null && !tc.isRestrained && tc.ride.hp > 0 && EClass.rnd(5) == 0)
163 {
165 }
166 if (tc.enemy != null)
167 {
169 }
170 if (!tc.IsMinion && EClass.rnd(10) == 0 && EClass.rnd(tc.DEX + 10) > owner.LV && tc.HasElement(1315) && !owner.HasElement(1315) && owner.IsMachine && owner.CanBeTempAlly(tc) && owner.id != "mech_scarab")
171 {
172 owner.Say("dominate_machine", tc, owner);
173 owner.PlayEffect("boost");
174 owner.PlaySound("boost");
175 owner.ShowEmo(Emo.love);
176 owner.lastEmo = Emo.angry;
178 yield return Success();
179 }
180 if (EClass.rnd(5) == 0 && tc.HasElement(1325) && owner.IsPlant && owner.CanBeTempAlly(tc))
181 {
182 owner.Say("dominate_plant", tc, owner);
183 owner.ShowEmo(Emo.love);
184 owner.lastEmo = Emo.angry;
186 yield return Success();
187 }
188 if (EClass.rnd(20) == 0 && owner.isRestrained)
189 {
190 owner.Talk("restrained");
191 }
192 if (this is GoalAutoCombat)
193 {
195 EClass.pc.ModExp(135, 20);
196 }
197 int dist = owner.Dist(tc);
198 bool move = owner.host == null && (tactics.ChanceMove > EClass.rnd(100) || (owner.IsPC && tc.HasCondition<ConFear>() && dist >= EClass.pc.GetSightRadius() - 1));
199 bool haltSecondMove = false;
200 if (!owner.IsPC && owner.IsNeutralOrAbove() && !owner.isBlind && !owner.isSummon && !owner.IsMinion)
201 {
202 int num = -1;
203 if (tc.HasElement(1221))
204 {
205 num = 1;
206 }
207 if (tc.source.HasTag(CTAG.suicide) && !tc.HasCondition<ConWet>())
208 {
209 num = 3;
210 }
211 if (num > 0)
212 {
213 if (dist <= num)
214 {
215 if (EClass.rnd(15) == 0)
216 {
217 owner.Talk("run_suicide");
218 }
219 if (owner.host == null && owner.TryMoveFrom(tc.pos) != 0)
220 {
221 yield return Status.Running;
222 idleCount = 0;
223 continue;
224 }
226 {
227 Debug.Log("Failed to Run: " + owner.Name);
228 }
229 }
230 if (dist == num + 1)
231 {
232 haltSecondMove = true;
233 move = false;
234 idleCount = 0;
235 }
236 }
237 }
238 if (dontWander)
239 {
240 int num2 = owner.Dist(EClass.pc);
241 if (num2 > 3)
242 {
243 int x = tc.pos.x;
244 int z = tc.pos.z;
245 if (EClass.pc.pos.Distance(owner.pos.x + ((x > owner.pos.x) ? 1 : ((x < owner.pos.x) ? (-1) : 0)), owner.pos.z + ((z > owner.pos.z) ? 1 : ((z < owner.pos.z) ? (-1) : 0))) >= num2)
246 {
247 move = false;
248 haltSecondMove = true;
249 }
250 }
251 }
252 if ((owner.IsPC && EClass.game.config.autoCombat.bDontChase) || (!canSeeLos && tc.isHidden))
253 {
254 move = false;
255 haltSecondMove = true;
256 }
258 {
259 Debug.Log(owner.Name + "/" + move + "/" + haltSecondMove + "/" + dist);
260 }
261 if (move)
262 {
263 if (owner.IsPC && dist <= owner.GetSightRadius() && TryUseAbility(dist, beforeMove: true))
264 {
265 yield return Status.Running;
266 idleCount = 0;
267 continue;
268 }
269 if (TryMove(dist))
270 {
272 {
273 Debug.Log("moved:" + owner.Name);
274 }
275 yield return Status.Running;
276 idleCount = 0;
277 continue;
278 }
279 }
280 if (owner == null)
281 {
282 yield return Cancel();
283 }
284 if (dist <= owner.GetSightRadius() && TryUseAbility(dist))
285 {
286 yield return Status.Running;
287 idleCount = 0;
288 continue;
289 }
291 {
292 Debug.Log(owner.Name + "/" + move + "/" + haltSecondMove + "/" + tactics.ChanceSecondMove);
293 }
294 if (!move && !haltSecondMove && tactics.ChanceSecondMove > EClass.rnd(100) && TryMove(dist))
295 {
296 yield return Status.Running;
297 idleCount = 0;
298 continue;
299 }
300 if (owner == null)
301 {
302 yield return Cancel();
303 }
304 idleCount++;
305 if (TryAbortCombat())
306 {
307 yield return Success();
308 }
309 if (idleCount > 1 && owner.id == "keeper_garden" && owner.enemy != null)
310 {
311 owner.Teleport(owner.enemy.pos.GetNearestPoint(allowBlock: false, allowChara: false, allowInstalled: true, ignoreCenter: true, 3) ?? EClass._map.GetRandomSurface(), silent: false, force: true);
312 yield return Success();
313 }
314 if (idleCount > 2)
315 {
316 if (dontWander)
317 {
318 yield return Success();
319 }
320 idleCount = 0;
321 string aiIdle = owner.source.aiIdle;
322 if (aiIdle == "stand" || aiIdle == "root")
323 {
324 yield return Success();
325 }
326 yield return DoGoto(tc.pos);
327 }
328 else if (owner.FindNearestNewEnemy())
329 {
330 yield return Status.Running;
331 continue;
332 }
333 yield return Status.Running;
334 }
335 void CalmDown()
336 {
337 owner.enemy = null;
338 if (owner.ride != null)
339 {
340 owner.ride.enemy = null;
341 }
342 if (owner.parasite != null)
343 {
344 owner.parasite.enemy = null;
345 }
346 owner.hostility = owner.OriginalHostility;
347 if (tc.enemy == owner)
348 {
349 tc.enemy = null;
350 if (tc.ride != null)
351 {
352 tc.ride.enemy = null;
353 }
354 if (tc.parasite != null)
355 {
356 tc.parasite.enemy = null;
357 }
358 tc.hostility = tc.OriginalHostility;
359 }
360 owner.Say("calmDown", owner);
361 }
362 }
363
364 public bool TryMove(int dist)
365 {
367 {
368 Debug.Log("TryMove: " + owner.Name + "/" + dist);
369 }
370 if (owner.host != null)
371 {
372 return false;
373 }
374 if (owner.isBlind)
375 {
376 return owner.MoveRandom();
377 }
378 int num = (tc.HasCondition<ConFear>() ? 1 : tactics.DestDist);
379 if (!owner.IsPC && (tactics.source.id == "archer" || tactics.source.id == "gunner") && !owner.TryEquipRanged())
380 {
381 num = 1;
382 }
383 if (!owner.IsPC && num > 1)
384 {
385 if (tactics.DestDist == 2)
386 {
387 if (EClass.rnd(5) == 0)
388 {
389 num = 1;
390 }
391 }
392 else if (owner.turn / 3 % 5 > 2)
393 {
394 num--;
395 }
396 }
397 bool flag = false;
398 if (dist > num)
399 {
400 flag = owner.TryMoveTowards(tc.pos) != Card.MoveResult.Fail;
401 if (!flag)
402 {
403 moveFail++;
404 }
405 }
406 else if (dist < num)
407 {
408 flag = owner.TryMoveFrom(tc.pos) != Card.MoveResult.Fail;
409 }
410 if (flag)
411 {
412 moveFail = 0;
413 }
415 {
416 Debug.Log("TryMove:" + owner.Name + "/" + flag + "/" + dist + "/" + num);
417 }
418 return flag;
419 }
420
421 public void AddAbility(Act a, int mod = 0, int chance = 100, bool aiPt = false)
422 {
423 abilities.Add(new ItemAbility
424 {
425 act = a,
426 priorityMod = mod,
427 chance = chance,
428 aiPt = aiPt
429 });
430 }
431
432 public void TryAddAbility(int ele)
433 {
434 if (abilities == null)
435 {
437 }
438 foreach (ItemAbility ability in abilities)
439 {
440 Act obj = ability.act;
441 if (obj != null && obj.id == ele)
442 {
443 return;
444 }
445 }
446 AddAbility(Element.Create(ele) as Act);
447 }
448
449 public void TryRemoveAbility(int ele)
450 {
451 if (abilities == null)
452 {
453 return;
454 }
455 foreach (ItemAbility ability in abilities)
456 {
457 Act obj = ability.act;
458 if (obj != null && obj.id == ele)
459 {
460 abilities.Remove(ability);
461 break;
462 }
463 }
464 }
465
466 public virtual bool TryUseRanged(int dist)
467 {
468 if (owner.TryEquipRanged())
469 {
470 return ACT.Ranged.Perform(owner, tc);
471 }
472 return false;
473 }
474
475 public virtual bool TryThrow(int dist)
476 {
477 if (dist > owner.GetSightRadius())
478 {
479 return false;
480 }
481 Thing thing = owner.TryGetThrowable();
482 if (thing == null)
483 {
484 return false;
485 }
486 if (!ACT.Throw.CanPerform(owner, tc, tc.pos))
487 {
488 return false;
489 }
490 ActThrow.Throw(owner, tc.pos, tc, thing.HasElement(410) ? thing : thing.Split(1));
491 return true;
492 }
493
494 public virtual bool TryUseAbility(int dist, bool beforeMove = false)
495 {
496 if (abilities.Count == 0)
497 {
498 Debug.Log("no ability:" + owner);
499 return false;
500 }
501 int numEnemy = -1;
502 int numFriend = -1;
503 int numNeutral = -1;
504 bool charaBuilt = false;
505 bool flag = owner.CanSeeLos(tc, dist);
506 bool isPCFaction = owner.IsPCFaction;
507 bool flag2 = owner.HasCondition<ConSilence>();
508 bool isBlind = owner.isBlind;
509 bool flag3 = owner.HasCondition<ConFear>();
510 bool isConfused = owner.isConfused;
511 bool flag4 = owner.HasCondition<ConDim>();
512 bool flag5 = owner.HasCondition<ConSupress>();
513 foreach (ItemAbility ability in abilities)
514 {
515 Act act = ability.act;
516 if (act.id == 8801 && owner.race.id == "spider" && EClass._zone.HasField(10000) && !owner.IsPCFactionOrMinion)
517 {
518 ability.act = ACT.Create(50413);
519 }
520 ability.priority = 0;
521 ability.tg = null;
522 ability.pt = false;
523 if (EClass.rnd(100) >= ability.chance || (isBlind && act.HasTag("reqSight")) || (owner.isBerserk && !(act is ActMelee) && !(act is ActRanged) && !(act is ActBreathe) && !(act is ActThrow)))
524 {
525 continue;
526 }
527 int num = 0;
529 if (s.abilityType.Length == 0 || (owner.IsPC && flag2 && act is Spell) || (beforeMove && !act.HasTag("before_move")))
530 {
531 continue;
532 }
533 string text = s.abilityType[0];
534 if (flag5 && !(text == "melee") && !(text == "range") && EClass.rnd(2) == 0)
535 {
536 continue;
537 }
538 bool isHOT;
539 switch (text)
540 {
541 case "any":
542 num = 50;
543 break;
544 case "item":
545 num = (act as ActItem).BuildAct(owner);
546 break;
547 case "wait":
548 if (owner.IsPCParty)
549 {
550 continue;
551 }
552 num = 50;
553 break;
554 case "taunt":
555 {
556 bool flag10 = owner.HasCondition<StanceTaunt>();
557 bool flag11 = tactics.source.taunt != -1 && 100 * owner.hp / owner.MaxHP >= tactics.source.taunt;
558 num = ((flag10 && !flag11) ? 100 : ((!flag10 && flag11) ? 100 : 0));
559 break;
560 }
561 case "song":
562 {
563 bool flag7 = owner.HasCondition<BaseSong>();
564 bool flag8 = owner.mana.value > owner.mana.max / 3;
565 num = ((flag7 && !flag8) ? 100 : ((!flag7 && flag8) ? 100 : 0));
566 break;
567 }
568 case "melee":
569 if (tactics.source.melee == 0 || dist > owner.body.GetMeleeDistance())
570 {
571 continue;
572 }
573 num = ((!flag3) ? tactics.P_Melee : ((!owner.IsPC) ? (tactics.P_Melee / 2) : 0));
574 if (isConfused)
575 {
576 num -= (owner.IsPC ? 30 : 10);
577 }
578 if (isBlind)
579 {
580 num -= (owner.IsPC ? 50 : 10);
581 }
582 if (dist <= 1)
583 {
584 if (tc.HasElement(1221))
585 {
586 num -= 40;
587 }
588 if (tc.HasElement(1223))
589 {
590 num -= 40;
591 }
592 if (!owner.IsPC && owner.IsPCFaction && tc.id == "hedgehog_ether")
593 {
594 continue;
595 }
596 if (!owner.IsPCFaction && num < 10)
597 {
598 num = 10;
599 }
600 }
601 break;
602 case "range":
603 if (!flag || EClass.rnd(100) > tactics.RangedChance)
604 {
605 continue;
606 }
607 num = ((!flag3) ? tactics.P_Range : ((!owner.IsPC) ? (tactics.P_Range / 2) : 0));
608 if (isConfused)
609 {
610 num -= (owner.IsPC ? 30 : 10);
611 }
612 if (isBlind)
613 {
614 num -= (owner.IsPC ? 50 : 10);
615 }
616 if (owner.ranged != null && owner.ranged.trait is TraitToolRangeCane && owner.mana.value <= 0)
617 {
618 continue;
619 }
620 break;
621 case "teleport":
622 num = 40;
623 break;
624 case "hot":
625 case "heal":
626 isHOT = text == "hot";
627 num = ForeachChara(ability, (Chara c) => HealFactor(c), isFriendlyAbility: true);
628 if (ability.aiPt || (owner.IsPC && tactics.CastPartyBuff))
629 {
630 ability.pt = true;
631 }
632 break;
633 case "dot":
634 case "attack":
635 case "attackMelee":
636 {
637 if (!flag)
638 {
639 continue;
640 }
641 bool flag9 = text == "dot";
642 if (flag9 && (owner.isRestrained || (tc != null && tc.IsRestrainedResident)))
643 {
644 continue;
645 }
646 num = ((text == "attackMelee") ? tactics.P_Melee : tactics.P_Spell) + GetAttackMod(act);
647 if (num > 0 && flag9)
648 {
649 num += 10;
650 }
651 if (ability.aiPt)
652 {
653 ability.pt = true;
654 }
655 break;
656 }
657 case "attackArea":
658 {
659 if (owner.isRestrained || (tc != null && tc.IsRestrainedResident))
660 {
661 continue;
662 }
663 bool flag6 = act is ActBolt;
665 {
666 continue;
667 }
668 GetNumEnemy(flag6 ? 6 : 5);
669 if (numEnemy == 0 || (owner.IsPCFactionOrMinion && GetNumNeutral(flag6 ? 6 : 5) > 0))
670 {
671 continue;
672 }
673 num = tactics.P_Spell - 20 + numEnemy * 10 + GetAttackMod(act);
674 break;
675 }
676 case "buff":
677 num = ForeachChara(ability, (Chara c) => (!c.HasCondition(s.proc[1])) ? tactics.P_Buff : 0, isFriendlyAbility: true);
678 if (ability.aiPt || (owner.IsPC && tactics.CastPartyBuff))
679 {
680 ability.pt = true;
681 }
682 break;
683 case "buffStats":
684 num = ForeachChara(ability, delegate(Chara c)
685 {
686 Element buffStats2 = c.GetBuffStats(s.proc[1]);
687 return (buffStats2 == null || buffStats2.Value < 0) ? tactics.P_Buff : 0;
688 }, isFriendlyAbility: true);
689 if (ability.aiPt || (owner.IsPC && tactics.CastPartyBuff))
690 {
691 ability.pt = true;
692 }
693 break;
694 case "cure":
695 num = ForeachChara(ability, (Chara c) => c.CountDebuff() * 30, isFriendlyAbility: true);
696 if (ability.aiPt || (owner.IsPC && tactics.CastPartyBuff))
697 {
698 ability.pt = true;
699 }
700 break;
701 case "debuff":
702 if (!flag)
703 {
704 continue;
705 }
706 num = tactics.P_Debuff;
707 if (ability.aiPt)
708 {
709 ability.pt = true;
710 }
711 break;
712 case "debuffStats":
713 if (!flag)
714 {
715 continue;
716 }
717 num = ForeachChara(ability, delegate(Chara c)
718 {
719 Element buffStats = c.GetBuffStats(s.proc[1]);
720 return (buffStats == null || buffStats.Value > 0) ? tactics.P_Debuff : 0;
721 }, isFriendlyAbility: false);
722 if (ability.aiPt)
723 {
724 ability.pt = true;
725 }
726 break;
727 case "ground":
728 if (!flag || owner.isRestrained || (tc != null && tc.IsRestrainedResident))
729 {
730 continue;
731 }
732 num = 50;
733 if (isPCFaction)
734 {
735 num -= 10;
736 }
737 break;
738 case "summon":
739 {
740 if (owner.isRestrained || (tc != null && tc.IsRestrainedResident))
741 {
742 continue;
743 }
744 int num2 = EClass._zone.CountMinions(owner);
745 if (num2 >= owner.MaxSummon)
746 {
747 continue;
748 }
749 num = tactics.P_Summon - 20 * num2 / owner.MaxSummon;
750 break;
751 }
752 case "summonAlly":
753 if (owner.isRestrained || (tc != null && tc.IsRestrainedResident))
754 {
755 continue;
756 }
757 if (owner.IsPC)
758 {
759 if (EClass.player.lastEmptyAlly <= 0)
760 {
761 continue;
762 }
763 }
764 else if (EClass._zone.CountMinions(owner) > 0)
765 {
766 continue;
767 }
768 num = tactics.P_Summon;
769 break;
770 case "summonSpecial":
771 if (owner.GetInt(70) > EClass.world.date.GetRaw())
772 {
773 continue;
774 }
775 num = 1000;
776 break;
777 case "summonSpecial2":
778 num = 1000;
779 break;
780 case "suicide":
782 {
783 continue;
784 }
785 if (owner.HasTag(CTAG.kamikaze))
786 {
787 num = ((dist <= 1) ? 1000 : 0);
788 break;
789 }
790 num = 100 - 125 * owner.hp / owner.MaxHP;
791 if (EClass.rnd(200) <= num && (!owner.IsPowerful || owner.hp < owner.MaxHP / 2))
792 {
793 break;
794 }
795 continue;
796 default:
797 num = 0;
798 break;
799 }
800 switch (act.id)
801 {
802 case 6606:
803 if (owner.mana.value <= 0)
804 {
805 continue;
806 }
807 break;
808 case 6603:
809 if (!tc.IsPCParty || tc.Evalue(418) < 0)
810 {
811 break;
812 }
813 foreach (Chara member in EClass.pc.party.members)
814 {
815 if (member.Evalue(418) < 0)
816 {
817 owner.enemy = (tc = member);
818 return false;
819 }
820 }
821 break;
822 case 6602:
823 if (dist <= 1 || tc.HasCondition<ConEntangle>())
824 {
825 continue;
826 }
827 break;
828 case 6450:
829 if (isPCFaction && (tc.HasElement(1221) || tc.HasElement(1223) || tc.id == "hedgehog_ether"))
830 {
831 continue;
832 }
833 break;
834 case 8200:
835 case 8201:
836 if (owner.HasElement(400))
837 {
838 continue;
839 }
840 break;
841 case 6400:
842 if (isPCFaction)
843 {
844 continue;
845 }
846 break;
847 case 8790:
848 case 8791:
849 if (tc.host != null)
850 {
851 continue;
852 }
853 break;
854 case 6900:
855 if (owner.IsPC)
856 {
857 continue;
858 }
859 if (owner.IsPCParty)
860 {
861 foreach (Chara member2 in EClass.pc.party.members)
862 {
863 float num4 = 100f - (float)(member2.mana.value * 100) / MathF.Max(1f, member2.mana.max);
864 if (num4 > (float)num)
865 {
866 num = (int)num4;
867 }
868 }
869 }
870 else
871 {
872 num = 100 - owner.mana.value * 100 / Mathf.Max(1, owner.mana.max);
873 }
874 break;
875 case 6627:
877 {
878 continue;
879 }
880 num = 100 - owner.hp * 100 / Mathf.Max(1, owner.MaxHP);
881 break;
882 case 9200:
883 {
884 int num3 = 0;
885 foreach (Condition condition in tc.conditions)
886 {
887 if (condition.Type == ConditionType.Debuff)
888 {
889 num3++;
890 }
891 }
892 num = num3 * 15;
893 break;
894 }
895 }
896 if (s.target == "Neighbor")
897 {
898 if (dist > 1)
899 {
900 continue;
901 }
902 num += 10;
903 }
904 if (s.proc.Length != 0 && s.proc[0] == "Debuff" && tc.HasCondition(s.proc[1]))
905 {
906 continue;
907 }
908 if (s.abilityType.Length > 1)
909 {
910 num += (owner.IsPC ? s.abilityType[2] : s.abilityType[1]).ToInt();
911 }
912 if (act is Spell)
913 {
914 if (owner.IsPC)
915 {
916 if (act.vPotential <= 0)
917 {
918 continue;
919 }
920 if (flag2 || isConfused || flag4)
921 {
922 num -= 50;
923 }
924 }
925 else
926 {
927 if (flag2)
928 {
929 num -= 30;
930 }
931 if (isConfused || flag4)
932 {
933 num -= 10;
934 }
935 }
936 }
937 if (num > 0)
938 {
939 num += ability.priorityMod + EClass.rnd(tactics.RandomFacotr + ability.priorityMod);
940 }
941 ability.priority = num;
942 int HealFactor(Chara c)
943 {
944 if (isHOT && c.HasCondition(s.proc[1]))
945 {
946 return 0;
947 }
948 float num5 = (float)c.hp / (float)c.MaxHP;
949 if (num5 > (isHOT ? 0.85f : 0.75f))
950 {
951 return 0;
952 }
953 int num6 = tactics.P_Heal - (int)((float)tactics.P_Heal * num5) + (isHOT ? 50 : 25);
954 foreach (Condition condition2 in c.conditions)
955 {
956 if (condition2 is ConFear)
957 {
958 num6 += 10;
959 }
960 else if (condition2 is ConPoison)
961 {
962 num6 += 2;
963 }
964 else if (condition2 is ConConfuse)
965 {
966 num6 += 4;
967 }
968 else if (condition2 is ConDim)
969 {
970 num6 += 6;
971 }
972 else if (condition2 is ConBleed)
973 {
974 num6 += 8;
975 }
976 }
977 return num6;
978 }
979 }
980 abilities.Sort((ItemAbility a, ItemAbility b) => b.priority - a.priority);
981 foreach (ItemAbility ability2 in abilities)
982 {
983 if (ability2.priority <= 0)
984 {
985 continue;
986 }
988 {
989 Debug.Log(ability2.act.Name + "/" + ability2.priority);
990 }
991 if (ability2.act.source.alias == "ActRanged")
992 {
993 if (TryThrow(dist))
994 {
995 return true;
996 }
997 if (TryUseRanged(dist))
998 {
999 return true;
1000 }
1001 continue;
1002 }
1003 Cost cost = ability2.act.GetCost(owner);
1004 if (owner.IsPCParty && ability2.pt && !ability2.act.IsTargetHostileParty() && !ability2.act.TargetType.ForceParty && cost.cost * EClass.pc.party.members.Count > owner.mana.value)
1005 {
1006 continue;
1007 }
1008 if (isPCFaction && cost.cost > 0)
1009 {
1010 switch (cost.type)
1011 {
1012 case CostType.MP:
1013 if (cost.cost > owner.mana.value)
1014 {
1015 continue;
1016 }
1017 break;
1018 case CostType.SP:
1019 if (cost.cost > owner.stamina.value)
1020 {
1021 continue;
1022 }
1023 break;
1024 }
1025 }
1026 if (cost.cost > 0 && EClass.rnd(100) > tactics.AbilityChance)
1027 {
1028 continue;
1029 }
1030 Chara chara = owner;
1031 if (ability2.act.CanPerform(owner, ability2.tg ?? tc) && owner.UseAbility(ability2.act, ability2.tg ?? tc, null, (ability2.act.HaveLongPressAction && ability2.pt) || ability2.aiPt))
1032 {
1034 {
1035 Debug.Log("Used Ability: " + chara?.ToString() + "/" + ability2.act?.ToString() + "/" + ability2.tg?.ToString() + "/" + tc);
1036 Debug.Log(ability2.act.CanPerform(chara, ability2.tg ?? tc));
1037 }
1038 return true;
1039 }
1040 }
1042 {
1043 Debug.Log(owner.Name + "/" + abilities.Count);
1044 foreach (ItemAbility ability3 in abilities)
1045 {
1046 Debug.Log(ability3.act.Name + "/" + ability3.priority);
1047 }
1048 }
1049 return false;
1050 void BuildCharaList()
1051 {
1052 if (charaBuilt)
1053 {
1054 return;
1055 }
1056 charas.Clear();
1057 charaBuilt = true;
1058 int sightRadius = owner.GetSightRadius();
1059 foreach (Chara chara2 in EClass._map.charas)
1060 {
1061 if (chara2 != owner)
1062 {
1063 int num11 = owner.Dist(chara2);
1064 if (num11 > sightRadius || !owner.CanSeeLos(chara2, num11))
1065 {
1066 continue;
1067 }
1068 }
1069 charas.Add(chara2);
1070 }
1071 }
1072 int ForeachChara(ItemAbility a, Func<Chara, int> func, bool isFriendlyAbility)
1073 {
1074 if (a.act.TargetType.Range == TargetRange.Self)
1075 {
1076 a.tg = owner;
1077 return func(owner);
1078 }
1079 BuildCharaList();
1080 int num7 = 0;
1081 foreach (Chara chara3 in charas)
1082 {
1083 int num8 = func(chara3);
1084 if (num8 > 0)
1085 {
1086 if (isFriendlyAbility)
1087 {
1088 if (owner.IsPCParty)
1089 {
1090 if (!chara3.IsPCParty)
1091 {
1092 continue;
1093 }
1094 }
1095 else if (!owner.IsFriendOrAbove(chara3))
1096 {
1097 continue;
1098 }
1099 if (chara3 != owner)
1100 {
1101 num8 += tactics.P_Party;
1102 }
1103 }
1104 else if (!owner.IsHostile(chara3))
1105 {
1106 continue;
1107 }
1108 if (num8 >= num7)
1109 {
1110 a.tg = chara3;
1111 num7 = num8;
1112 }
1113 }
1114 }
1115 return num7;
1116 }
1117 int GetAttackMod(Act a)
1118 {
1119 if (!owner.IsPCParty || a.source.aliasRef.IsEmpty())
1120 {
1121 return 0;
1122 }
1123 int num9 = ((a.source.aliasRef == "mold") ? owner.MainElement.id : EClass.sources.elements.alias[a.source.aliasRef].id);
1124 int num10 = -15 * tc.ResistLvFrom(num9);
1125 if (a is ActSword)
1126 {
1127 num10 = 0;
1128 }
1129 if (owner.HasElement(1238) && num10 < -15)
1130 {
1131 num10 = -15;
1132 }
1133 switch (num9)
1134 {
1135 case 910:
1136 if (tc.isWet)
1137 {
1138 num10 -= 30;
1139 }
1140 break;
1141 case 911:
1142 if (tc.HasCondition<ConBurning>())
1143 {
1144 num10 -= 30;
1145 }
1146 break;
1147 case 912:
1148 if (tc.isWet)
1149 {
1150 num10 += 30;
1151 }
1152 break;
1153 }
1154 return num10;
1155 }
1156 void GetNumEnemy(int radius)
1157 {
1158 if (numEnemy != -1)
1159 {
1160 return;
1161 }
1162 BuildCharaList();
1163 numEnemy = 0;
1164 foreach (Chara chara4 in charas)
1165 {
1166 if (chara4.host == null && owner.IsHostile(chara4) && owner.Dist(chara4) < radius && owner.CanSeeLos(chara4))
1167 {
1168 numEnemy++;
1169 }
1170 }
1171 }
1172 int GetNumNeutral(int radius)
1173 {
1174 if (numNeutral != -1)
1175 {
1176 return numNeutral;
1177 }
1178 BuildCharaList();
1179 numNeutral = 0;
1180 foreach (Chara chara5 in charas)
1181 {
1182 if (!chara5.IsPCFactionOrMinion && chara5.IsNeutralOrAbove() && owner.Dist(chara5) <= radius && owner.CanSeeLos(chara5))
1183 {
1184 numNeutral++;
1185 }
1186 }
1187 return numNeutral;
1188 }
1189 }
1190
1191 public virtual void BuildAbilityList()
1192 {
1193 foreach (ActList.Item item in owner.ability.list.items)
1194 {
1195 AddAbility(item.act, 0, item.chance, item.pt);
1196 }
1201 {
1202 TryAddAbility(6410);
1203 }
1204 }
1205
1206 public virtual bool TryAbortCombat()
1207 {
1208 return false;
1209 }
1210}
BossType
Definition: BossType.cs:2
CTAG
Definition: CTAG.cs:2
ConditionType
Definition: ConditionType.cs:2
EditorTag
Definition: EditorTag.cs:2
Emo
Definition: Emo.cs:2
Hostility
Definition: Hostility.cs:2
MinionType
Definition: MinionType.cs:2
TargetRange
Definition: TargetRange.cs:2
Definition: ACT.cs:6
static ActRanged Ranged
Definition: ACT.cs:17
static ActThrow Throw
Definition: ACT.cs:19
static Act Create(int id)
Definition: ACT.cs:36
static ActMelee Melee
Definition: ACT.cs:15
static ActItem Item
Definition: ACT.cs:21
virtual Status Cancel()
Definition: AIAct.cs:291
virtual bool ShouldAllyAttack(Chara tg)
Definition: AIAct.cs:134
new Chara owner
Definition: AIAct.cs:14
Status
Definition: AIAct.cs:8
override string ToString()
Definition: AIAct.cs:124
Status DoGoto(Point pos, int dist=0, bool ignoreConnection=false, Func< Status > _onChildFail=null)
Definition: AIAct.cs:432
void SetTurbo(int mtp=-1)
Definition: AM_Adv.cs:1040
List< Item > items
Definition: ActList.cs:14
override bool Perform()
Definition: ActRanged.cs:65
static EffectIRenderer Throw(Card c, Point p, Thing t, ThrowMethod method=ThrowMethod.Default, float failChance=0f)
Definition: ActThrow.cs:97
override bool CanPerform()
Definition: ActThrow.cs:29
Definition: ACT.cs:62
CostType
Definition: ACT.cs:64
virtual TargetType TargetType
Definition: ACT.cs:142
virtual bool HaveLongPressAction
Definition: ACT.cs:133
virtual bool CanPerform()
Definition: ACT.cs:303
bool IsTargetHostileParty()
Definition: ACT.cs:241
static AM_Adv Adv
Definition: ActionMode.cs:15
int GetInt(int id, int? defaultInt=null)
Definition: BaseCard.cs:25
virtual ConditionType Type
Definition: BaseStats.cs:19
Definition: Card.cs:11
bool IsPCFactionOrMinion
Definition: Card.cs:2272
void Teleport(Point point, bool silent=false, bool force=false)
Definition: Card.cs:5871
Thing Split(int a)
Definition: Card.cs:3484
string id
Definition: Card.cs:35
int GetSightRadius()
Definition: Card.cs:6427
bool IsRestrainedResident
Definition: Card.cs:2258
bool isRestrained
Definition: Card.cs:566
SoundSource PlaySound(string id, float v=1f, bool spatial=true)
Definition: Card.cs:6177
void Talk(string idTopic, string ref1=null, string ref2=null, bool forceSync=false)
Definition: Card.cs:6733
int hp
Definition: Card.cs:242
string Name
Definition: Card.cs:2137
bool ExistsOnMap
Definition: Card.cs:2085
bool HasTag(CTAG tag)
Definition: Card.cs:2595
Point pos
Definition: Card.cs:59
int DEX
Definition: Card.cs:2335
Effect PlayEffect(string id, bool useRenderPos=true, float range=0f, Vector3 fix=default(Vector3))
Definition: Card.cs:6211
void ShowEmo(Emo _emo=Emo.none, float duration=0f, bool skipSame=true)
Definition: Card.cs:6145
Trait trait
Definition: Card.cs:53
bool IsPowerful
Definition: Card.cs:2094
MoveResult
Definition: Card.cs:13
bool HasEditorTag(EditorTag tag)
Definition: Card.cs:2600
BossType c_bossType
Definition: Card.cs:1221
int turn
Definition: Card.cs:65
int Evalue(int ele)
Definition: Card.cs:2571
int Dist(Card c)
Definition: Card.cs:7697
bool isHidden
Definition: Card.cs:530
void ModExp(string alias, int a)
Definition: Card.cs:2648
bool HasElement(int ele, bool includeNagative=false)
Definition: Card.cs:5932
int LV
Definition: Card.cs:386
int ResistLvFrom(int ele)
Definition: Card.cs:5922
void Say(string lang, string ref1=null, string ref2=null)
Definition: Card.cs:6850
ActList list
Definition: CharaAbility.cs:12
int GetMeleeDistance()
Definition: CharaBody.cs:451
Definition: Chara.cs:10
Element MainElement
Definition: Chara.cs:717
new TraitChara trait
Definition: Chara.cs:503
Hostility OriginalHostility
Definition: Chara.cs:471
CharaBody body
Definition: Chara.cs:94
AIAct ai
Definition: Chara.cs:202
MoveResult TryMoveFrom(Point p)
Definition: Chara.cs:2678
Element GetBuffStats(string alias)
Definition: Chara.cs:9423
bool isWet
Definition: Chara.cs:142
override bool IsPC
Definition: Chara.cs:612
Chara host
Definition: Chara.cs:33
bool IsPlant
Definition: Chara.cs:975
Point GetFirstStep(Point newPoint, PathManager.MoveType moveType=PathManager.MoveType.Default)
Definition: Chara.cs:2571
Chara GetNearbyCatToSniff()
Definition: Chara.cs:8076
bool CanSeeLos(Card c, int dist=-1)
Definition: Chara.cs:1250
override bool IsPCParty
Definition: Chara.cs:615
override string ToString()
Definition: Chara.cs:1172
Party party
Definition: Chara.cs:43
List< Condition > conditions
Definition: Chara.cs:211
bool HasCondition(string alias)
Definition: Chara.cs:9411
bool IsNeutralOrAbove()
Definition: Chara.cs:6580
override bool IsMinion
Definition: Chara.cs:627
bool MoveRandom()
Definition: Chara.cs:2576
int CountDebuff()
Definition: Chara.cs:9440
override bool IsPCFaction
Definition: Chara.cs:671
int MaxSummon
Definition: Chara.cs:714
Thing TryGetThrowable()
Definition: Chara.cs:7771
int calmCheckTurn
Definition: Chara.cs:116
void MakeMinion(Chara _master, MinionType type=MinionType.Default)
Definition: Chara.cs:2339
bool CanSee(Card c)
Definition: Chara.cs:1218
override bool IsPCFactionMinion
Definition: Chara.cs:655
bool IsFriendOrAbove()
Definition: Chara.cs:6624
override int MaxHP
Definition: Chara.cs:708
Thing ranged
Definition: Chara.cs:98
SourceChara.Row source
Definition: Chara.cs:158
Stats mana
Definition: Chara.cs:1154
bool FindNewEnemy()
Definition: Chara.cs:6448
Stats stamina
Definition: Chara.cs:1146
bool UseAbility(int idAct, Card tc=null, Point pos=null, bool pt=false)
Definition: Chara.cs:5834
Chara parasite
Definition: Chara.cs:30
Chara ride
Definition: Chara.cs:27
bool CanBeTempAlly(Chara c)
Definition: Chara.cs:2317
MoveResult TryMoveTowards(Point p)
Definition: Chara.cs:2616
bool isBerserk
Definition: Chara.cs:122
bool FindNearestNewEnemy()
Definition: Chara.cs:6517
Chara enemy
Definition: Chara.cs:86
CharaAbility ability
Definition: Chara.cs:424
Chara SetEnemy(Chara c=null)
Definition: Chara.cs:6306
bool isBlind
Definition: Chara.cs:130
bool IsMachine
Definition: Chara.cs:903
Tactics tactics
Definition: Chara.cs:834
bool IsHostile()
Definition: Chara.cs:6532
bool isDead
Definition: Chara.cs:389
bool isConfused
Definition: Chara.cs:126
bool TryEquipRanged()
Definition: Chara.cs:7847
void TrySetEnemy(Chara c)
Definition: Chara.cs:6323
SourceRace.Row race
Definition: Chara.cs:464
Definition: ConDim.cs:2
Definition: ConHOT.cs:4
Definition: ConWet.cs:2
bool logCombat
Definition: CoreDebug.cs:245
static CursorInfo IconMelee
int GetRaw(int offsetHours=0)
Definition: Date.cs:326
Definition: EClass.cs:6
static Game game
Definition: EClass.cs:9
static Zone _zone
Definition: EClass.cs:21
static World world
Definition: EClass.cs:41
static Map _map
Definition: EClass.cs:19
static int rnd(long a)
Definition: EClass.cs:59
static SourceManager sources
Definition: EClass.cs:43
static Player player
Definition: EClass.cs:13
static Chara pc
Definition: EClass.cs:15
static CoreDebug debug
Definition: EClass.cs:49
int id
Definition: ELEMENT.cs:250
SourceElement.Row source
Definition: ELEMENT.cs:273
int vPotential
Definition: ELEMENT.cs:256
bool HasTag(string tag)
Definition: ELEMENT.cs:473
int Value
Definition: ELEMENT.cs:292
virtual string Name
Definition: ELEMENT.cs:304
static Element Create(int id, int v=0)
Definition: ELEMENT.cs:1102
virtual Act.Cost GetCost(Chara c)
Definition: ELEMENT.cs:1032
Act act
Definition: ELEMENT.cs:394
ConfigTactics tactics
Definition: Game.cs:90
ConfigAutoCombat autoCombat
Definition: Game.cs:93
Config config
Definition: Game.cs:218
virtual bool TryUseRanged(int dist)
Definition: GoalCombat.cs:466
override IEnumerable< Status > Run()
Definition: GoalCombat.cs:53
virtual bool TryThrow(int dist)
Definition: GoalCombat.cs:475
virtual void BuildAbilityList()
Definition: GoalCombat.cs:1191
Chara tc
Definition: GoalCombat.cs:26
void TryRemoveAbility(int ele)
Definition: GoalCombat.cs:449
Tactics tactics
Definition: GoalCombat.cs:42
int idleCount
Definition: GoalCombat.cs:28
virtual bool TryAbortCombat()
Definition: GoalCombat.cs:1206
override bool CancelOnAggro
Definition: GoalCombat.cs:40
bool TryMove(int dist)
Definition: GoalCombat.cs:364
Chara destEnemy
Definition: GoalCombat.cs:24
List< ItemAbility > abilities
Definition: GoalCombat.cs:32
List< Chara > charas
Definition: GoalCombat.cs:34
virtual bool TryUseAbility(int dist, bool beforeMove=false)
Definition: GoalCombat.cs:494
override CursorInfo CursorIcon
Definition: GoalCombat.cs:36
override bool CancelWhenDamaged
Definition: GoalCombat.cs:38
int moveFail
Definition: GoalCombat.cs:30
void TryAddAbility(int ele)
Definition: GoalCombat.cs:432
override bool CanManualCancel()
Definition: GoalCombat.cs:44
void AddAbility(Act a, int mod=0, int chance=100, bool aiPt=false)
Definition: GoalCombat.cs:421
Definition: Goal.cs:4
Point GetRandomSurface(int x, int z, int radius, bool walkable=true, bool allowWater=false)
Definition: MapBounds.cs:182
Playlist plDay
Definition: Map.cs:77
List< Chara > charas
Definition: Map.cs:81
Definition: Msg.cs:5
static string Say(string idLang, string ref1, string ref2=null, string ref3=null, string ref4=null)
Definition: Msg.cs:58
List< Chara > members
Definition: Party.cs:19
bool IsCriminal
Definition: Player.cs:1337
int lastEmptyAlly
Definition: Player.cs:1193
Definition: Point.cs:9
int x
Definition: Point.cs:36
Point GetNearestPoint(bool allowBlock=false, bool allowChara=true, bool allowInstalled=true, bool ignoreCenter=false, int minRadius=0)
Definition: Point.cs:619
int z
Definition: Point.cs:39
bool IsValid
Definition: Point.cs:88
int Distance(Point p)
Definition: Point.cs:989
bool IsInBounds
Definition: Point.cs:104
bool HasChara
Definition: Point.cs:238
string[] abilityType
SourceElement elements
bool isAlarmSet
Definition: Spatial.cs:430
bool isPeace
Definition: Spatial.cs:406
Definition: SPELL.cs:620
virtual int value
Definition: Stats.cs:56
virtual int max
Definition: Stats.cs:68
int ChanceSecondMove
Definition: Tactics.cs:56
int RandomFacotr
Definition: Tactics.cs:12
int P_Party
Definition: Tactics.cs:71
int P_Spell
Definition: Tactics.cs:79
bool CastPartyBuff
Definition: Tactics.cs:88
int P_Debuff
Definition: Tactics.cs:83
int P_Buff
Definition: Tactics.cs:81
int P_Melee
Definition: Tactics.cs:73
int DestDist
Definition: Tactics.cs:24
int RangedChance
Definition: Tactics.cs:116
SourceTactics.Row source
Definition: Tactics.cs:3
int AbilityChance
Definition: Tactics.cs:100
int P_Range
Definition: Tactics.cs:75
int P_Summon
Definition: Tactics.cs:85
virtual TargetRange Range
Definition: TargetType.cs:25
virtual bool ForceParty
Definition: TargetType.cs:41
Definition: Thing.cs:8
GameDate date
Definition: World.cs:6
int CountMinions(Chara c)
Definition: Zone.cs:3733
virtual bool SetAlarmOnBreakLaw
Definition: Zone.cs:231
bool HasField(int idEle)
Definition: Zone.cs:2879
void SetBGM(List< int > ids, bool refresh=true, float fadeDuration=0f)
Definition: Zone.cs:2959
virtual bool IsTown
Definition: Zone.cs:223
bool IsPCFaction
Definition: Zone.cs:473
virtual void SetAlarm(bool enable)
Definition: Zone.cs:3588
Definition: ACT.cs:71
CostType type
Definition: ACT.cs:74
int cost
Definition: ACT.cs:72