GlobalTrigger.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Security;
  6. public interface ITrigger
  7. {
  8. GameObject GetTriggerObj();
  9. };
  10. /// <summary>
  11. /// 新增枚举只能从后面加,因为已有配置被序列化到文件
  12. /// </summary>
  13. public enum EGlobalTriggerAct
  14. {
  15. TriggerDialogue,
  16. TriggerSpawn,
  17. TriggerPauseGame,
  18. TriggerSetGlobalVariable,
  19. TriggerMove,
  20. TriggerComingAnim,
  21. TriggerPlayEffect,
  22. TriggerExitBattle,
  23. TriggerCalcNextPoint,
  24. TriggerDisactive,
  25. TriggerCameraMove,
  26. TriggerRunGame,
  27. TriggerShowSkip,
  28. TriggerEnableSkill,
  29. TriggerDisableSkill,
  30. TriggerSetUINodeVis,
  31. TriggerPlayBGM,
  32. }
  33. /// <summary>
  34. /// 新增枚举只能从后面加,因为已有配置被序列化到文件
  35. /// </summary>
  36. public enum EGlobalGameEvent
  37. {
  38. SpawnGroupDead,
  39. ActorDead,
  40. FightPrepare,
  41. ActorDamage,
  42. FightStart,
  43. UseSkill,
  44. ActorInit,
  45. EnterCombat,
  46. DialogueFinished,
  47. MoveEnd,
  48. }
  49. public enum ECondtionType
  50. {
  51. None = 0,
  52. HP = 1,
  53. SP = 2,
  54. SkillId = 3,
  55. DialogueId = 4,
  56. FighterId = 5,
  57. }
  58. [Serializable]
  59. public struct STriggerCondition
  60. {
  61. public Int32 ActorId;
  62. public ECondtionType ConType;
  63. [FriendlyName("百分比数")]
  64. public int Percent;
  65. public bool FilterMatch(EGlobalGameEvent inEventType
  66. , int baseId
  67. , eTeamType teamId
  68. , int param)
  69. {
  70. if (ActorId != baseId)
  71. {
  72. return false;
  73. }
  74. switch (inEventType)
  75. {
  76. case EGlobalGameEvent.ActorDamage:
  77. Fighter fighter = BattleMgr.Instance.Battle.FighterMgr.GetFighterByBaseId(baseId, teamId);
  78. if (fighter == null)
  79. {
  80. return false;
  81. }
  82. if (!FilterMatchDamage(fighter.Life,fighter.MaxLife))
  83. {
  84. return false;
  85. }
  86. break;
  87. case EGlobalGameEvent.UseSkill:
  88. if (!FilterMatchSkill(param))
  89. {
  90. return false;
  91. }
  92. break;
  93. case EGlobalGameEvent.DialogueFinished:
  94. return Percent == param;
  95. case EGlobalGameEvent.MoveEnd:
  96. return Percent == param;
  97. default:
  98. break;
  99. }
  100. return true;
  101. }
  102. private bool FilterMatchDamage(int curHp,int maxLife)
  103. {
  104. int percentRevised = Percent;
  105. if (percentRevised < 0)
  106. {
  107. percentRevised = 0;
  108. }
  109. else if (percentRevised > 100)
  110. {
  111. percentRevised = 100;
  112. }
  113. int hpThreshold = maxLife * percentRevised / 100;
  114. if (curHp <= hpThreshold)
  115. {
  116. return true;
  117. }
  118. return false;
  119. }
  120. private bool FilterMatchSkill(int skillId)
  121. {
  122. return Percent == skillId;
  123. }
  124. }
  125. [Serializable]
  126. public class CTriggerMatch
  127. {
  128. public const int TriggerCountMax = 1;
  129. [FriendlyName("角色ID")]
  130. public int ActorId = 0;
  131. public eTeamType TeamType = eTeamType.Friend;
  132. public EGlobalGameEvent EventType = EGlobalGameEvent.SpawnGroupDead;
  133. public STriggerCondition[] Conditions = new STriggerCondition[0];
  134. [SerializeField]
  135. public TriggerActionWrapper[] ActionList = new TriggerActionWrapper[0];
  136. [FriendlyName("延迟触发时间(0表示无延迟,单位ms)")]
  137. public int DelayTime = 0;
  138. [HideInInspector, NonSerialized]
  139. public int m_triggeredCounter;
  140. }
  141. [AddComponentMenu("Trigger/Global Trigger")]
  142. public class GlobalTrigger : MonoBehaviour, ITrigger{
  143. public CTriggerMatch[] TriggerMatches = new CTriggerMatch[0];
  144. private class CDelayMatch
  145. {
  146. public CTriggerMatch TriggerMatch;
  147. }
  148. private Dictionary<int, CDelayMatch> DelayTimeSeqMap = new Dictionary<int, CDelayMatch>();
  149. public GameObject GetTriggerObj()
  150. {
  151. return gameObject;
  152. }
  153. private void Awake()
  154. {
  155. RegisterEvents();
  156. }
  157. private void OnDestroy()
  158. {
  159. UnregisterEvents();
  160. ClearDelayTimers();
  161. foreach (CTriggerMatch match in TriggerMatches)
  162. {
  163. if (match == null)
  164. {
  165. continue;
  166. }
  167. foreach (TriggerActionWrapper taw in match.ActionList)
  168. {
  169. if (taw != null)
  170. {
  171. taw.Destroy();
  172. }
  173. }
  174. }
  175. }
  176. private void RegisterEvents()
  177. {
  178. EventMgr.AddEventListener<Fighter>(ECoreEventType.EID_FIGHTER_DIE, onActorDead);
  179. EventMgr.AddEventListener<UIEventParamFighterHurt>(ECoreEventType.EID_FIGHTER_HURT, onActorDamage);
  180. EventMgr.AddEventListener<bool>(ECoreEventType.EID_BATTLE_NEW_FIGHTING_START, onFightStart);
  181. EventMgr.AddEventListener<Fighter>(ECoreEventType.EID_FIGHTER_SPAWN, onActorInit);
  182. EventMgr.AddEventListener<Fighter>(ECoreEventType.EID_FIGHTER_ENTERCOMBAT, onEnterCombat);
  183. EventMgr.AddEventListener<CastSkillData>(ECoreEventType.EID_Refresh_Skill, onFighterCastSkill);
  184. EventMgr.AddEventListener<int>(ECoreEventType.EID_Dialogue_Finished,onDialogueFinished);
  185. EventMgr.AddEventListener<int>(ECoreEventType.EID_Fighter_Move_End, onFighterMoveEnd);
  186. }
  187. private void UnregisterEvents()
  188. {
  189. EventMgr.RemoveEventListener<Fighter>(ECoreEventType.EID_FIGHTER_DIE, onActorDead);
  190. EventMgr.RemoveEventListener<UIEventParamFighterHurt>(ECoreEventType.EID_FIGHTER_HURT, onActorDamage);
  191. EventMgr.RemoveEventListener<bool>(ECoreEventType.EID_BATTLE_NEW_FIGHTING_START, onFightStart);
  192. EventMgr.RemoveEventListener<Fighter>(ECoreEventType.EID_FIGHTER_SPAWN, onActorInit);
  193. EventMgr.RemoveEventListener<Fighter>(ECoreEventType.EID_FIGHTER_ENTERCOMBAT, onEnterCombat);
  194. EventMgr.RemoveEventListener<CastSkillData>(ECoreEventType.EID_Refresh_Skill, onFighterCastSkill);
  195. EventMgr.RemoveEventListener<int>(ECoreEventType.EID_Dialogue_Finished, onDialogueFinished);
  196. EventMgr.RemoveEventListener<int>(ECoreEventType.EID_Fighter_Move_End, onFighterMoveEnd);
  197. }
  198. public void UpdateLogic(float delta)
  199. {
  200. }
  201. /// <summary>
  202. /// 全局Trigger在备战阶段即生效
  203. /// </summary>
  204. public void PrepareFight()
  205. {
  206. int count = TriggerMatches.Length;
  207. for (int i = 0; i < count; ++i)
  208. {
  209. CTriggerMatch match = TriggerMatches[i];
  210. if (match == null)
  211. {
  212. continue;
  213. }
  214. if (FilterMatch(EGlobalGameEvent.FightPrepare, match, 0, 0,i))
  215. {
  216. DoTriggering(match);
  217. }
  218. }
  219. }
  220. public void Dispose()
  221. {
  222. ClearDelayTimers();
  223. foreach (CTriggerMatch match in TriggerMatches)
  224. {
  225. if (match == null)
  226. {
  227. continue;
  228. }
  229. foreach (TriggerActionWrapper taw in match.ActionList)
  230. {
  231. if (taw != null)
  232. {
  233. taw.Destroy();
  234. }
  235. }
  236. }
  237. }
  238. private void DoTriggeringImpl(CTriggerMatch match, int baseId,eTeamType teamSide)
  239. {
  240. if (match.ActionList != null && match.ActionList.Length > 0)
  241. {
  242. int count = match.ActionList.Length;
  243. for (int i = 0; i < count; ++i)
  244. {
  245. TriggerActionWrapper taw = match.ActionList[i];
  246. if (taw == null)
  247. {
  248. continue;
  249. }
  250. TriggerActionBase tab = taw.GetActionInternal();
  251. if (tab == null)
  252. {
  253. taw.Init(0);
  254. tab = taw.GetActionInternal();
  255. DebugHelper.Assert(tab != null);
  256. }
  257. Fighter src = BattleMgr.Instance.Battle.FighterMgr.GetFighterByBaseId(baseId, teamSide);
  258. tab.TriggerEnter(src, this);
  259. }
  260. }
  261. }
  262. public void ClearDelayTimers()
  263. {
  264. var iter = DelayTimeSeqMap.GetEnumerator();
  265. while (iter.MoveNext())
  266. {
  267. int timeSeq = iter.Current.Key;
  268. TimerManager.Instance.RemoveTimer(timeSeq);
  269. }
  270. DelayTimeSeqMap.Clear();
  271. }
  272. private void OnDelayTriggerTimer(int inTimeSeq)
  273. {
  274. if (DelayTimeSeqMap.ContainsKey(inTimeSeq))
  275. {
  276. CDelayMatch delay = DelayTimeSeqMap[inTimeSeq];
  277. if (delay != null)
  278. {
  279. DoTriggeringImpl(delay.TriggerMatch, delay.TriggerMatch.ActorId,delay.TriggerMatch.TeamType);
  280. }
  281. DelayTimeSeqMap.Remove(inTimeSeq);
  282. }
  283. TimerManager.Instance.RemoveTimer(inTimeSeq);
  284. }
  285. private void DoTriggering(CTriggerMatch match)
  286. {
  287. if (CTriggerMatch.TriggerCountMax > 0)
  288. {
  289. if (++match.m_triggeredCounter > CTriggerMatch.TriggerCountMax)
  290. {
  291. return;
  292. }
  293. }
  294. Fighter src = BattleMgr.Instance.Battle.FighterMgr.GetFighterByBaseId(match.ActorId, match.TeamType);
  295. if (match.DelayTime > 0)
  296. {
  297. int timeSeq = TimerManager.Instance.AddTimer(match.DelayTime, 1, OnDelayTriggerTimer);
  298. if (timeSeq >= 0)
  299. {
  300. DebugHelper.Assert(!DelayTimeSeqMap.ContainsKey(timeSeq));
  301. CDelayMatch delay = new CDelayMatch();
  302. delay.TriggerMatch = match;
  303. DelayTimeSeqMap.Add(timeSeq, delay);
  304. }
  305. }
  306. else
  307. {
  308. DoTriggeringImpl(match, match.ActorId,match.TeamType);
  309. }
  310. }
  311. private bool FilterMatch(EGlobalGameEvent inEventType, CTriggerMatch match,int baseId,eTeamType teamId,int param)
  312. {
  313. if (match.EventType != inEventType)
  314. {
  315. return false;
  316. }
  317. if(match.Conditions == null || match.Conditions.Length == 0)
  318. {
  319. return true;
  320. }
  321. for(int idx =0; idx < match.Conditions.Length;idx++)
  322. {
  323. if (!match.Conditions[idx].FilterMatch(inEventType, baseId, teamId, param))
  324. {
  325. return false;
  326. }
  327. }
  328. return true;
  329. }
  330. private void onActorDead(CoreEvent<Fighter> ce)
  331. {
  332. Fighter src = ce.Data;
  333. int count = TriggerMatches.Length;
  334. for (int i = 0; i < count; ++i)
  335. {
  336. CTriggerMatch match = TriggerMatches[i];
  337. if (match == null)
  338. {
  339. continue;
  340. }
  341. if (FilterMatch(EGlobalGameEvent.ActorDead, match, src.Actor.BaseId, src.TeamSide, i))
  342. {
  343. DoTriggering(match);
  344. }
  345. }
  346. }
  347. private void onActorDamage(CoreEvent<UIEventParamFighterHurt> ce)
  348. {
  349. UIEventParamFighterHurt hurtParam = ce.Data;
  350. int count = TriggerMatches.Length;
  351. for (int i = 0; i < count; ++i)
  352. {
  353. CTriggerMatch match = TriggerMatches[i];
  354. if (match == null)
  355. {
  356. continue;
  357. }
  358. if (FilterMatch(EGlobalGameEvent.ActorDamage, match, hurtParam.mTarget.Actor.BaseId,hurtParam.mTarget.TeamSide,i))
  359. {
  360. DoTriggering(match);
  361. }
  362. }
  363. }
  364. private void onFighterCastSkill(CoreEvent<CastSkillData> ce)
  365. {
  366. CastSkillData skillData = ce.Data;
  367. if(skillData.IsCasting)
  368. {
  369. int count = TriggerMatches.Length;
  370. for (int i = 0; i < count; ++i)
  371. {
  372. CTriggerMatch match = TriggerMatches[i];
  373. if (match == null)
  374. {
  375. continue;
  376. }
  377. Fighter f = BattleMgr.Instance.Battle.FighterMgr.GetFighterByID(skillData.actorId,(eTeamType)skillData.teamSide);
  378. if (f!=null && FilterMatch(EGlobalGameEvent.UseSkill, match, f.Actor.BaseId, f.TeamSide, skillData.skillId))
  379. {
  380. DoTriggering(match);
  381. }
  382. }
  383. }
  384. }
  385. private void onFightStart(CoreEvent<bool> ce)
  386. {
  387. bool f = ce.Data;
  388. int count = TriggerMatches.Length;
  389. for (int i = 0; i < count; ++i)
  390. {
  391. CTriggerMatch match = TriggerMatches[i];
  392. if (match == null)
  393. {
  394. continue;
  395. }
  396. if (FilterMatch(EGlobalGameEvent.FightStart, match, 0, 0,i))
  397. {
  398. DoTriggering(match);
  399. }
  400. }
  401. }
  402. private void onDialogueFinished(CoreEvent<int> ce)
  403. {
  404. int dialogueId = ce.Data;
  405. //DebugHelper.LogError("onDialogueFinished:" + dialogueId);
  406. int count = TriggerMatches.Length;
  407. for (int i = 0; i < count; ++i)
  408. {
  409. CTriggerMatch match = TriggerMatches[i];
  410. if (match == null)
  411. {
  412. continue;
  413. }
  414. if (FilterMatch(EGlobalGameEvent.DialogueFinished, match,0,0, dialogueId))
  415. {
  416. DoTriggering(match);
  417. }
  418. }
  419. }
  420. private void onFighterMoveEnd(CoreEvent<int> ce)
  421. {
  422. int fighterCfgId = ce.Data;
  423. int count = TriggerMatches.Length;
  424. for (int i = 0; i < count; ++i)
  425. {
  426. CTriggerMatch match = TriggerMatches[i];
  427. if (match == null)
  428. {
  429. continue;
  430. }
  431. if (FilterMatch(EGlobalGameEvent.MoveEnd, match, 0, 0, fighterCfgId))
  432. {
  433. DoTriggering(match);
  434. }
  435. }
  436. }
  437. private void onActorInit(CoreEvent<Fighter> ce)
  438. {
  439. Fighter f = ce.Data;
  440. int count = TriggerMatches.Length;
  441. for (int i = 0; i < count; ++i)
  442. {
  443. CTriggerMatch match = TriggerMatches[i];
  444. if (match == null)
  445. {
  446. continue;
  447. }
  448. if (FilterMatch(EGlobalGameEvent.ActorInit, match, f.Actor.BaseId, f.TeamSide, i))
  449. {
  450. DoTriggering(match);
  451. }
  452. }
  453. }
  454. private void onEnterCombat(CoreEvent<Fighter> ce)
  455. {
  456. Fighter f = ce.Data;
  457. int count = TriggerMatches.Length;
  458. for (int i = 0; i < count; ++i)
  459. {
  460. CTriggerMatch match = TriggerMatches[i];
  461. if (match == null)
  462. {
  463. continue;
  464. }
  465. if (FilterMatch(EGlobalGameEvent.EnterCombat, match, f.Actor.BaseId, f.TeamSide, i))
  466. {
  467. DoTriggering(match);
  468. }
  469. }
  470. }
  471. public void SaveCfgToXml(SecurityElement parent)
  472. {
  473. AreaEventTriggerSpawn[] spawnTriggers = GetComponentsInChildren<AreaEventTriggerSpawn>(true);
  474. for(int idx =0; idx < spawnTriggers.Length;idx++)
  475. {
  476. AreaEventTriggerSpawn triggerSpawn = spawnTriggers[idx];
  477. SecurityElement childNode = triggerSpawn.SaveToXml();
  478. parent.AddChild(childNode);
  479. }
  480. if(TriggerMatches != null)
  481. {
  482. List<int> effectIds = new List<int>();
  483. SecurityElement effectGroupNode = new SecurityElement("EffectGroup");
  484. for (int idx =0; idx < TriggerMatches.Length;idx++)
  485. {
  486. CTriggerMatch tm = TriggerMatches[idx];
  487. if(tm!=null && tm.ActionList.Length > 0)
  488. {
  489. for(int jdx =0; jdx < tm.ActionList.Length;jdx++)
  490. {
  491. TriggerActionWrapper act = tm.ActionList[jdx];
  492. if(act!=null && act.TriggerType == EGlobalTriggerAct.TriggerPlayEffect && act.EnterUniqueId > 0)
  493. {
  494. if (effectIds.Contains(act.EnterUniqueId)) continue;
  495. SecurityElement effectNode = new SecurityElement("Effect");
  496. effectNode.AddAttribute("id", act.EnterUniqueId.ToString());
  497. effectGroupNode.AddChild(effectNode);
  498. effectIds.Add(act.EnterUniqueId);
  499. }
  500. }
  501. }
  502. }
  503. parent.AddChild(effectGroupNode);
  504. }
  505. }
  506. }