MapComponent.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. using FL.Battle;
  2. using FL.Data;
  3. using FL.FGUI;
  4. using FL.Map;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using UnityEngine;
  8. using XGame;
  9. using XGame.Database;
  10. using XGame.Framework.Interfaces;
  11. using XGame.Framework.Map;
  12. using XGame.Framework.Nodes;
  13. using XGame.Framework.Time;
  14. namespace FL.Nodes.GameMain
  15. {
  16. public class MapComponent : NodeComponent, IUpdate
  17. {
  18. private int _chapterId;
  19. private EMapSchedule _schedule;
  20. private ITimer _monsterTimer;
  21. private PlayerEntity _player;
  22. /// <summary>
  23. /// 怪物坐标相对出生点的偏移值
  24. /// 怪物最多13个,分两排排列,索引如下
  25. /// 二排 9 5 1 2 6 10
  26. /// 一排 11 7 3 0 4 8 12
  27. /// 0的左边偏移值为负数
  28. /// </summary>
  29. private Vector3 _monsterOffset = new Vector3(0.8f, 1.5f, 0);
  30. /// <summary>
  31. /// 空闲的怪物位置索引
  32. /// </summary>
  33. private List<int> _unusedIndexs;
  34. /// <summary>
  35. /// 怪物的实例对象
  36. /// </summary>
  37. private Dictionary<long, MonsterEntity> _monsterMap;
  38. /// <summary>
  39. /// 伙伴的实例对象
  40. /// </summary>
  41. private Dictionary<long, PartnerEntity> _partnerMap;
  42. private MapKey _currentMap;
  43. public override void OnEnable(object intent)
  44. {
  45. EventSingle.Instance.AddListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity);
  46. EventSingle.Instance.AddListener(EventDefine.GameMainMapEndMask, OnMapEndMask);
  47. EventSingle.Instance.AddListener(EventDefine.PartnerDown, OnPartnerDown);
  48. EventSingle.Instance.AddListener(EventDefine.PartnerUp, OnPartnerUp);
  49. InitMonsters();
  50. StartMap(PlayerData.Instance.chapterId);
  51. }
  52. public override void OnDisable()
  53. {
  54. EventSingle.Instance.RemoveListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity);
  55. EventSingle.Instance.RemoveListener(EventDefine.GameMainMapEndMask, OnMapEndMask);
  56. EventSingle.Instance.RemoveListener(EventDefine.PartnerDown, OnPartnerDown);
  57. EventSingle.Instance.RemoveListener(EventDefine.PartnerUp, OnPartnerUp);
  58. _player = null;
  59. _partnerMap?.Clear();
  60. _monsterTimer?.Cancel();
  61. _monsterTimer = null;
  62. _monsterMap?.Clear();
  63. _unusedIndexs?.Clear();
  64. Context.Map.Close(_currentMap);
  65. _currentMap = null;
  66. }
  67. void IUpdate.Update(int millisecond)
  68. {
  69. if (_player == null)
  70. return;
  71. }
  72. private void InitMonsters()
  73. {
  74. if (_unusedIndexs == null)
  75. _unusedIndexs = new List<int>();
  76. else
  77. _unusedIndexs.Clear();
  78. for (var i = 0; i < 13; i++)
  79. {
  80. _unusedIndexs.Add(i);
  81. }
  82. }
  83. private void StartMap(int chapterId)
  84. {
  85. _chapterId = chapterId;
  86. _schedule = EMapSchedule.LoadingMap;
  87. var chapter = ChapterTableRepo.Get(_chapterId);
  88. var map = MapTableRepo.Get(chapter.Map);
  89. var mapKey = MapKeys.NameToKey(map.AssetName);
  90. if (mapKey == _currentMap)
  91. { // 是同一个地图
  92. StartChapter(true, false);
  93. }
  94. else
  95. {
  96. // 关闭当前地图
  97. Context.Map.Close(_currentMap);
  98. _currentMap = mapKey;
  99. // 加载新地图
  100. var mapAsync = Context.Map.RunAsync(mapKey);
  101. mapAsync.On(_ =>
  102. {
  103. StartChapter(true, true);
  104. });
  105. }
  106. }
  107. private void StartChapter(bool isChapterChanged, bool isMapChanged)
  108. {
  109. _schedule = EMapSchedule.Monster1;
  110. var chapter = ChapterTableRepo.Get(_chapterId);
  111. var map = MapTableRepo.Get(chapter.Map);
  112. var dto = new LoadEntitiesDto();
  113. dto.chapterId = _chapterId;
  114. dto.isChapterChanged = isChapterChanged;
  115. dto.isPlayerMove = true;
  116. //战斗位置
  117. dto.battlePosition = map.BattlePositions[chapter.Part - 1].ToVector3();
  118. var isGenPlayer = _player == null;
  119. if (isGenPlayer)
  120. {
  121. _player = GenPlayer(map.PlayerBirth.ToVector3());
  122. //玩家
  123. dto.player = _player;
  124. //伙伴
  125. var partners = GenPartners(_player.BirthPosition);
  126. AddPartners(partners);
  127. dto.partners = partners;
  128. }
  129. else if (isMapChanged)
  130. {
  131. //玩家
  132. dto.player = _player;
  133. //伙伴
  134. dto.partners = _partnerMap.Values.ToArray();
  135. }
  136. if (isChapterChanged)
  137. {
  138. // 重置玩家血量
  139. _player.Attr.Dynamic.Clear();
  140. _player.Attr.ResetHp();
  141. // 随从可能有替换过,重置随从的出生点
  142. var birthPosition = _player.BirthPosition;
  143. foreach (var partner in _partnerMap.Values)
  144. {
  145. partner.BirthPosition = birthPosition + PartnersData.Instance.GetPartnerOffset(partner.Attr.UID);
  146. }
  147. }
  148. //怪物数据
  149. var monsters = GenMonsters();
  150. AddMonsters(monsters);
  151. dto.monsters = monsters;
  152. dto.monsterMoveDistance = map.MonsterPositions[chapter.Part - 1].ToVector3().y - dto.battlePosition.y;
  153. //定时器
  154. if (chapter.Part_type == 0)
  155. { // 普通节点,增加定时器
  156. dto.monsterMoveDelay = 0;
  157. _monsterTimer = Context.Time.AddDelayLooperTimer(chapter.Interval * 6, chapter.Interval * 6, OnLoopGenMonsters);
  158. }
  159. else
  160. { // boss关卡,直接到最后
  161. dto.monsterMoveDelay = 1000;
  162. _schedule = EMapSchedule.Monster5;
  163. Context.UI.OpenAsync(UIKeys.MainBossLaiXi);
  164. Context.Time.AddDelayTimer(1000, () =>
  165. { //1秒后自动关闭
  166. Context.UI.Close(UIKeys.MainBossLaiXi);
  167. });
  168. }
  169. EventSingle.Instance.Notify(EventDefine.GameMainMapLoadEntities, dto);
  170. }
  171. private void OnLoopGenMonsters(int times)
  172. {
  173. _schedule += 1;
  174. if (_schedule == EMapSchedule.Monster5)
  175. {
  176. _monsterTimer.Cancel();
  177. _monsterTimer = null;
  178. }
  179. var chapter = ChapterTableRepo.Get(_chapterId);
  180. var map = MapTableRepo.Get(chapter.Map);
  181. var dto = new LoadEntitiesDto();
  182. dto.chapterId = _chapterId;
  183. //战斗位置
  184. dto.battlePosition = map.BattlePositions[chapter.Part - 1].ToVector3();
  185. //怪物数据
  186. var monsters = GenMonsters();
  187. AddMonsters(monsters);
  188. dto.monsters = monsters;
  189. dto.monsterMoveDistance = map.MonsterPositions[chapter.Part - 1].ToVector3().y - dto.battlePosition.y;
  190. EventSingle.Instance.Notify(EventDefine.GameMainMapLoadEntities, dto);
  191. }
  192. private PlayerEntity GenPlayer(Vector3 birth)
  193. {
  194. var playerData = PlayerData.Instance;
  195. var player = new PlayerEntity()
  196. {
  197. BirthPosition = birth//玩家出生点
  198. };
  199. var entityAttr = new EntityAttributes(0, playerData.UID)
  200. {
  201. Name = playerData.Name,
  202. Radius = 1,
  203. AttackCD = 2000,
  204. };
  205. entityAttr.CopyFrom(playerData.Attr);
  206. player.Init(UIDDefine.New(), entityAttr, playerData.skillIds);
  207. return player;
  208. }
  209. private PartnerEntity[] GenPartners(Vector3 targetPosition)
  210. {
  211. var goneUpMap = PartnersData.Instance.GoneUpMap;
  212. var count = goneUpMap.Count;
  213. var partners = new PartnerEntity[count];
  214. var index = 0;
  215. foreach (var partnerUID in goneUpMap.Keys)
  216. {
  217. partners[index++] = GenPartner(targetPosition, partnerUID);
  218. }
  219. return partners;
  220. }
  221. private PartnerEntity GenPartner(Vector3 targetPosition, long partnerId)
  222. {
  223. var partner = PartnersData.Instance.PartnersMap[partnerId];
  224. var entity = new PartnerEntity()
  225. {
  226. BirthPosition = targetPosition + PartnersData.Instance.GetPartnerOffset(partner.UID),
  227. EpigraphId = 20300,
  228. };
  229. var entityAttr = new EntityAttributes(partner.TableId, partner.UID)
  230. {
  231. Name = partner.Name,
  232. Radius = partner.Radius,
  233. AttackCD = 6000,
  234. };
  235. entityAttr.CopyFrom(partner.Attr);
  236. var table = PartnerTableRepo.Get(partner.TableId);
  237. entity.Init(UIDDefine.New(), entityAttr, new int[] { table.Skill });
  238. return entity;
  239. }
  240. private void AddPartners(PartnerEntity[] partners)
  241. {
  242. if (partners == null || partners.Length == 0) return;
  243. if (_partnerMap == null)
  244. {
  245. _partnerMap = new Dictionary<long, PartnerEntity>();
  246. }
  247. foreach (var partner in partners)
  248. {
  249. _partnerMap.Add(partner.EntityId, partner);
  250. }
  251. }
  252. /// <summary>
  253. /// 获取怪物的出生坐标和索引
  254. /// </summary>
  255. /// <param name="position"></param>
  256. /// <param name="positionIdx"></param>
  257. /// <returns></returns>
  258. private Vector3 GetMonsterBirth(Vector3 position, out int positionIdx)
  259. {
  260. if (_unusedIndexs.Count > 0)
  261. {
  262. positionIdx = _unusedIndexs[0];
  263. _unusedIndexs.RemoveAt(0);
  264. }
  265. else
  266. {
  267. positionIdx = 0;
  268. }
  269. if (positionIdx == 0)
  270. {
  271. return position;
  272. }
  273. var offset = Vector3.zero;
  274. var xMultiple = (positionIdx + 1) / 2;
  275. offset.x = _monsterOffset.x * xMultiple;
  276. if (positionIdx % 2 != 0)
  277. { // 索引为奇数的在左边
  278. offset.x = -offset.x;
  279. }
  280. if (xMultiple % 2 != 0)
  281. { // 倍数为奇数的在上面
  282. offset.y = _monsterOffset.y;
  283. }
  284. var target = position + offset;
  285. // 随机偏移xy(-0.2, 0.2)
  286. target.x += Random.Range(-0.25f, 0.25f);
  287. target.y += Random.Range(-0.25f, 0.25f);
  288. return target;
  289. }
  290. private void PushMonstPositionIdx(int positionIdx)
  291. {
  292. if (_unusedIndexs.Contains(positionIdx))
  293. return; // 避免重复记录
  294. for (var i = 0; i < _unusedIndexs.Count; i++)
  295. {
  296. if (positionIdx < _unusedIndexs[i] && (i == 0 || positionIdx > _unusedIndexs[i - 1]))
  297. { // 小于当前索引的值 且 大于(i - 1 )的值
  298. _unusedIndexs.Insert(i, positionIdx);
  299. return;
  300. }
  301. }
  302. _unusedIndexs.Add(positionIdx);
  303. }
  304. private MonsterEntity[] GenMonsters()
  305. {
  306. var chapter = ChapterTableRepo.Get(_chapterId);
  307. var map = MapTableRepo.Get(chapter.Map);
  308. Vector3 birthPosition = map.MonsterPositions[chapter.Part - 1].ToVector3();
  309. int[] monsterRefresh = null;
  310. switch (_schedule)
  311. {
  312. case EMapSchedule.Monster1:
  313. monsterRefresh = chapter.Monster_refresh1;
  314. break;
  315. case EMapSchedule.Monster2:
  316. monsterRefresh = chapter.Monster_refresh2;
  317. break;
  318. case EMapSchedule.Monster3:
  319. monsterRefresh = chapter.Monster_refresh3;
  320. break;
  321. case EMapSchedule.Monster4:
  322. monsterRefresh = chapter.Monster_refresh4;
  323. break;
  324. case EMapSchedule.Monster5:
  325. monsterRefresh = chapter.Monster_refresh5;
  326. break;
  327. default:
  328. break;
  329. }
  330. var monsterCount = (monsterRefresh != null && monsterRefresh.Length > 0) ? monsterRefresh[1] : 0;
  331. if (monsterCount > 0)
  332. { // 数量0-3
  333. var monsters = new MonsterEntity[monsterCount];
  334. for (var i = 0; i < monsterCount; i++)
  335. {
  336. var position = GetMonsterBirth(birthPosition, out var positionIdx);
  337. var monsterTab = MonsterTableRepo.Get(monsterRefresh[0]);
  338. var entityAttr = new EntityAttributes(monsterTab.Id, UIDDefine.New())
  339. {
  340. Name = monsterTab.Name,
  341. Radius = monsterTab.ModelSize * 0.5f,
  342. AttackCD = 3000,
  343. };
  344. entityAttr.Static.Hp = monsterTab.Hp;
  345. entityAttr.Static.HpLimit = monsterTab.Hp;
  346. entityAttr.Static.MoveSpeed = Mathf.RoundToInt(monsterTab.Speed);
  347. entityAttr.Static.Attack = monsterTab.Atk;
  348. entityAttr.CurrentHp = monsterTab.Hp;
  349. var entity = new MonsterEntity();
  350. entity.Init(UIDDefine.New(), entityAttr, monsterTab.Skills);
  351. entity.BirthPosition = position;
  352. entity.PositionIdx = positionIdx;
  353. monsters[i] = entity;
  354. }
  355. return monsters;
  356. }
  357. return null;
  358. }
  359. private void AddMonsters(MonsterEntity[] monsters)
  360. {
  361. if (monsters == null || monsters.Length == 0) return;
  362. if (_monsterMap == null)
  363. {
  364. _monsterMap = new Dictionary<long, MonsterEntity>();
  365. }
  366. foreach (var monsterInfo in monsters)
  367. {
  368. _monsterMap.Add(monsterInfo.EntityId, monsterInfo);
  369. }
  370. }
  371. #region 事件监听
  372. private void OnRemoveEntity(int eventId, object args)
  373. {
  374. var entityId = (long)args;
  375. if (_monsterMap.TryGetValue(entityId, out var entity))
  376. {
  377. _monsterMap.Remove(entityId);
  378. PushMonstPositionIdx(entity.PositionIdx);
  379. CheckMonsterAllDead();
  380. return;
  381. }
  382. if (_partnerMap.TryGetValue(entityId, out var partner))
  383. {
  384. _partnerMap.Remove(entityId);
  385. return;
  386. }
  387. if (entityId == _player.EntityId)
  388. {
  389. _player = null;
  390. //TODO 失败结算
  391. }
  392. }
  393. private void OnPartnerDown(int eventId, object args)
  394. {
  395. var partnerUID = (long)args;
  396. var entityId = GetPartnerEntityIdByUID(partnerUID);
  397. if (entityId == 0)
  398. return;
  399. EventSingle.Instance.Notify(EventDefine.GameMainMapRemoveEntity, entityId);
  400. }
  401. private void OnPartnerUp(int eventId, object args)
  402. {
  403. var partnerUID = (long)args;
  404. var entityId = GetPartnerEntityIdByUID(partnerUID);
  405. if (entityId != 0)
  406. return; // 已经有实例对象了
  407. var chapter = ChapterTableRepo.Get(_chapterId);
  408. var map = MapTableRepo.Get(chapter.Map);
  409. var dto = new LoadEntitiesDto();
  410. dto.chapterId = _chapterId;
  411. //战斗位置
  412. dto.battlePosition = map.BattlePositions[chapter.Part - 1].ToVector3();
  413. var partner = GenPartner(dto.battlePosition, partnerUID);
  414. var partners = new PartnerEntity[] { partner };
  415. AddPartners(partners);
  416. dto.partners = partners;
  417. EventSingle.Instance.Notify(EventDefine.GameMainMapLoadEntities, dto);
  418. }
  419. //private void OnExchangePartner(int eventId, object args)
  420. //{
  421. // var addPartners = (List<int>)args;
  422. // var activePartnerIds = PartnersData.Instance.ActiveUIDs;
  423. // var count = addPartners.Count;
  424. // // 从后往前移除
  425. // for (var i = 0; i < count; i++)
  426. // {
  427. // var partnerId = activePartnerIds[activePartnerIds.Count - 1];
  428. // activePartnerIds.RemoveAt(activePartnerIds.Count - 1);
  429. // var EntityId = GetPartnerUIDByTableId(partnerId);
  430. // if (EntityId == 0)
  431. // continue;
  432. // EventSingle.Instance.Notify(EventDefine.GameMainMapRemoveEntity, EntityId);
  433. // }
  434. // activePartnerIds.AddRange(addPartners);
  435. // var chapter = ChapterTableRepo.Get(_chapterId);
  436. // var map = MapTableRepo.Get(chapter.Map);
  437. // var dto = new LoadEntitiesDto();
  438. // dto.chapterId = _chapterId;
  439. // //战斗位置
  440. // dto.battlePosition = map.BattlePositions[chapter.Part - 1].ToVector3();
  441. // var partners = GenPartners(dto.battlePosition, addPartners);
  442. // AddPartners(partners);
  443. // dto.partners = partners;
  444. // EventSingle.Instance.Notify(EventDefine.GameMainMapLoadEntities, dto);
  445. //}
  446. private void OnMapEndMask(int eventId, object args)
  447. {
  448. var chapter = ChapterTableRepo.Get(_chapterId);
  449. var nextChapter = ChapterTableRepo.Next(_chapterId);
  450. //没找到新关卡,重新开始
  451. if (nextChapter == null || nextChapter.Chapter != chapter.Chapter)
  452. { // 没有新关卡 || 章节id变化
  453. //TODO 章节切换
  454. }
  455. var chapterId = nextChapter?.Id ?? PlayerData.Instance.chapterId;
  456. StartMap(chapterId);
  457. }
  458. #endregion
  459. private void CheckMonsterAllDead()
  460. {
  461. if (_monsterMap.Count > 0) return;
  462. // 怪物全部死亡
  463. var chapter = ChapterTableRepo.Get(_chapterId);
  464. if (chapter.Part_type == 1)
  465. { //boss关卡
  466. //TODO 结算
  467. Context.UI.OpenAsync(UIKeys.MainBattleOverVictory);
  468. Context.Time.AddDelayTimer(2000, () =>
  469. { //2秒后自动关闭
  470. Context.UI.Close(UIKeys.MainBattleOverVictory);
  471. EventSingle.Instance.Notify(EventDefine.GameMainMapStartMask);
  472. });
  473. }
  474. else if (_schedule == EMapSchedule.Monster5)
  475. {
  476. _chapterId++;
  477. StartChapter(false, false);
  478. }
  479. }
  480. private long GetPartnerEntityIdByUID(long uid)
  481. {
  482. foreach (var item in _partnerMap)
  483. {
  484. if (item.Value.Attr.UID == uid)
  485. return item.Key;
  486. }
  487. return 0;
  488. }
  489. }
  490. }