123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- using FL.Battle;
- using FL.Data;
- using FL.FGUI;
- using FL.Map;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- using XGame;
- using XGame.Database;
- using XGame.Framework.Interfaces;
- using XGame.Framework.Map;
- using XGame.Framework.Nodes;
- using XGame.Framework.Time;
- namespace FL.Nodes.GameMain
- {
- public class MapComponent : NodeComponent, IUpdate
- {
- private int _chapterId;
- private EMapSchedule _schedule;
- private ITimer _monsterTimer;
- /// <summary>
- /// boss战斗倒计时
- /// </summary>
- private ITimer _bossTimer;
- private PlayerEntity _player;
- /// <summary>
- /// 怪物坐标相对出生点的偏移值
- /// 怪物最多13个,分两排排列,索引如下
- /// 二排 9 5 1 2 6 10
- /// 一排 11 7 3 0 4 8 12
- /// 0的左边偏移值为负数
- /// </summary>
- private Vector3 _monsterOffset = new Vector3(0.8f, 1.5f, 0);
- /// <summary>
- /// 空闲的怪物位置索引
- /// </summary>
- private List<int> _unusedIndexs;
- /// <summary>
- /// 怪物的实例对象
- /// </summary>
- private Dictionary<long, MonsterEntity> _monsterMap;
- /// <summary>
- /// 伙伴的实例对象
- /// </summary>
- private Dictionary<long, PartnerEntity> _partnerMap;
- private MapKey _currentMap;
- public override void OnEnable(object intent)
- {
- EventSingle.Instance.AddListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapEndMask, OnMapEndMask);
- EventSingle.Instance.AddListener(EventDefine.PartnerDown, OnPartnerDown);
- EventSingle.Instance.AddListener(EventDefine.PartnerUp, OnPartnerUp);
- InitMonsters();
- StartMap(PlayerData.Instance.chapterId);
- }
- public override void OnDisable()
- {
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapEndMask, OnMapEndMask);
- EventSingle.Instance.RemoveListener(EventDefine.PartnerDown, OnPartnerDown);
- EventSingle.Instance.RemoveListener(EventDefine.PartnerUp, OnPartnerUp);
- _player = null;
- _partnerMap?.Clear();
- _monsterTimer?.Cancel();
- _monsterTimer = null;
- _bossTimer?.Cancel();
- _bossTimer = null;
- _monsterMap?.Clear();
- _unusedIndexs?.Clear();
- Context.Map.Close(_currentMap);
- _currentMap = null;
- }
- void IUpdate.Update(int millisecond)
- {
- if (_player == null)
- return;
- }
- private void InitMonsters()
- {
- if (_unusedIndexs == null)
- _unusedIndexs = new List<int>();
- else
- _unusedIndexs.Clear();
- for (var i = 0; i < 13; i++)
- {
- _unusedIndexs.Add(i);
- }
- }
- private void StartMap(int chapterId)
- {
- _chapterId = chapterId;
- _schedule = EMapSchedule.LoadingMap;
- var chapter = ChapterTableRepo.Get(_chapterId);
- var map = MapTableRepo.Get(chapter.Map);
- var mapKey = MapKeys.NameToKey(map.AssetName);
- if (mapKey == _currentMap)
- { // 是同一个地图
- StartChapter(true, false);
- }
- else
- {
- // 关闭当前地图
- Context.Map.Close(_currentMap);
- _currentMap = mapKey;
- // 加载新地图
- var mapAsync = Context.Map.RunAsync(mapKey);
- mapAsync.On(_ =>
- {
- StartChapter(true, true);
- });
- }
- }
- private void StartChapter(bool isChapterChanged, bool isMapChanged)
- {
- _schedule = EMapSchedule.Monster1;
- var chapter = ChapterTableRepo.Get(_chapterId);
- var map = MapTableRepo.Get(chapter.Map);
- var dto = new LoadEntitiesDto();
- dto.chapterId = _chapterId;
- dto.isChapterChanged = isChapterChanged;
- dto.isBossPart = chapter.Part_type == 1;
- dto.isPlayerMove = true;
- //战斗位置
- dto.battlePosition = GetBattlePosition(map, chapter.Part);// map.BattlePositions[chapter.Part - 1].ToVector3();
- var isGenPlayer = _player == null;
- if (isGenPlayer)
- {
- _player = GenPlayer(map.PlayerBirth.ToVector3());
- //玩家
- dto.player = _player;
- //伙伴
- var partners = GenPartners(_player.BirthPosition);
- AddPartners(partners);
- dto.partners = partners;
- }
- else if (isMapChanged)
- {
- //玩家
- dto.player = _player;
- //伙伴
- dto.partners = _partnerMap.Values.ToArray();
- }
- if (isChapterChanged || dto.isBossPart)
- {
- // 重置玩家血量
- _player.Attr.Dynamic.Clear();
- _player.Attr.ResetHp();
- }
- if (isChapterChanged)
- {
- // 随从可能有替换过,重置随从的出生点
- var birthPosition = _player.BirthPosition;
- foreach (var partner in _partnerMap.Values)
- {
- partner.BirthPosition = birthPosition + PartnersData.Instance.GetPartnerOffset(partner.Attr.UID);
- }
- }
- //怪物数据
- var monsters = GenMonsters();
- AddMonsters(monsters);
- dto.monsters = monsters;
- dto.monsterMoveDistance = map.MonsterBirth.Y - map.BattleFirst.Y;// map.MonsterPositions[chapter.Part - 1].ToVector3().y - dto.battlePosition.y;
- //定时器
- if (!dto.isBossPart)
- { // 普通节点,增加定时器
- dto.monsterMoveDelay = 0;
- _monsterTimer = Context.Time.AddDelayLooperTimer(chapter.Interval * 6, chapter.Interval * 6, OnLoopGenMonsters);
- }
- else
- { // boss关卡,直接到最后
- dto.monsterMoveDelay = 1000;
- _schedule = EMapSchedule.Monster5;
- Context.UI.OpenAsync(UIKeys.MainBossLaiXi);
- Context.Time.AddDelayTimer(1000, () =>
- { //1秒后自动关闭
- Context.UI.Close(UIKeys.MainBossLaiXi);
- if (chapter.Time > 0)
- {// boss战斗倒计时
- _bossTimer = Context.Time.AddDelayTimer(chapter.Time, CombatFailed);
- EventSingle.Instance.Notify(EventDefine.GameMainMapBossStart, chapter.Id);
- }
- });
- }
- EventSingle.Instance.Notify(EventDefine.GameMainMapLoadEntities, dto);
- }
- private void OnLoopGenMonsters(int times)
- {
- _schedule += 1;
- if (_schedule == EMapSchedule.Monster5)
- {
- _monsterTimer.Cancel();
- _monsterTimer = null;
- }
- var chapter = ChapterTableRepo.Get(_chapterId);
- var map = MapTableRepo.Get(chapter.Map);
- var dto = new LoadEntitiesDto();
- dto.chapterId = _chapterId;
- //战斗位置
- dto.battlePosition = GetBattlePosition(map, chapter.Part);// map.BattlePositions[chapter.Part - 1].ToVector3();
- //怪物数据
- var monsters = GenMonsters();
- AddMonsters(monsters);
- dto.monsters = monsters;
- dto.monsterMoveDistance = map.MonsterBirth.Y - map.BattleFirst.Y;// map.MonsterPositions[chapter.Part - 1].ToVector3().y - dto.battlePosition.y;
- EventSingle.Instance.Notify(EventDefine.GameMainMapLoadEntities, dto);
- }
- private PlayerEntity GenPlayer(Vector3 birth)
- {
- var playerData = PlayerData.Instance;
- var player = new PlayerEntity()
- {
- BirthPosition = birth//玩家出生点
- };
- var entityAttr = new EntityAttributes(0, playerData.UID)
- {
- Name = playerData.Name,
- Radius = 1,
- AttackCD = 2000,
- };
- entityAttr.CopyFrom(playerData.Attr);
- player.Init(UIDDefine.New(), entityAttr, playerData.skillIds);
- return player;
- }
- private PartnerEntity[] GenPartners(Vector3 targetPosition)
- {
- var goneUpMap = PartnersData.Instance.GoneUpMap;
- var count = goneUpMap.Count;
- var partners = new PartnerEntity[count];
- var index = 0;
- foreach (var partnerUID in goneUpMap.Keys)
- {
- partners[index++] = GenPartner(targetPosition, partnerUID);
- }
- return partners;
- }
- private PartnerEntity GenPartner(Vector3 targetPosition, long partnerId)
- {
- var partner = PartnersData.Instance.PartnersMap[partnerId];
- var entity = new PartnerEntity()
- {
- BirthPosition = targetPosition + PartnersData.Instance.GetPartnerOffset(partner.UID),
- EpigraphId = 20300,
- };
- var entityAttr = new EntityAttributes(partner.TableId, partner.UID)
- {
- Name = partner.Name,
- Radius = partner.Radius,
- AttackCD = 6000,
- };
- entityAttr.CopyFrom(partner.Attr);
- var table = PartnerTableRepo.Get(partner.TableId);
- entity.Init(UIDDefine.New(), entityAttr, new int[] { partner.SkillId });
- return entity;
- }
- private void AddPartners(PartnerEntity[] partners)
- {
- if (partners == null || partners.Length == 0) return;
- if (_partnerMap == null)
- {
- _partnerMap = new Dictionary<long, PartnerEntity>();
- }
- foreach (var partner in partners)
- {
- _partnerMap.Add(partner.EntityId, partner);
- }
- }
- /// <summary>
- /// 获取怪物的出生坐标和索引
- /// </summary>
- /// <param name="position"></param>
- /// <param name="positionIdx"></param>
- /// <returns></returns>
- private Vector3 GetMonsterBirth(Vector3 position, out int positionIdx)
- {
- if (_unusedIndexs.Count > 0)
- {
- positionIdx = _unusedIndexs[0];
- _unusedIndexs.RemoveAt(0);
- }
- else
- {
- positionIdx = 0;
- }
- if (positionIdx == 0)
- {
- return position;
- }
- var offset = Vector3.zero;
- var xMultiple = (positionIdx + 1) / 2;
- offset.x = _monsterOffset.x * xMultiple;
- if (positionIdx % 2 != 0)
- { // 索引为奇数的在左边
- offset.x = -offset.x;
- }
- if (xMultiple % 2 != 0)
- { // 倍数为奇数的在上面
- offset.y = _monsterOffset.y;
- }
- var target = position + offset;
- // 随机偏移xy(-0.2, 0.2)
- target.x += Random.Range(-0.25f, 0.25f);
- target.y += Random.Range(-0.25f, 0.25f);
- return target;
- }
- private void PushMonstPositionIdx(int positionIdx)
- {
- if (_unusedIndexs.Contains(positionIdx))
- return; // 避免重复记录
- for (var i = 0; i < _unusedIndexs.Count; i++)
- {
- if (positionIdx < _unusedIndexs[i] && (i == 0 || positionIdx > _unusedIndexs[i - 1]))
- { // 小于当前索引的值 且 大于(i - 1 )的值
- _unusedIndexs.Insert(i, positionIdx);
- return;
- }
- }
- _unusedIndexs.Add(positionIdx);
- }
- private MonsterEntity[] GenMonsters()
- {
- var chapter = ChapterTableRepo.Get(_chapterId);
- var map = MapTableRepo.Get(chapter.Map);
- Vector3 birthPosition = GetMonsterBirth(map, chapter.Part);// map.MonsterPositions[chapter.Part - 1].ToVector3();
- int[] monsterRefresh = null;
- switch (_schedule)
- {
- case EMapSchedule.Monster1:
- monsterRefresh = chapter.Monster_refresh1;
- break;
- case EMapSchedule.Monster2:
- monsterRefresh = chapter.Monster_refresh2;
- break;
- case EMapSchedule.Monster3:
- monsterRefresh = chapter.Monster_refresh3;
- break;
- case EMapSchedule.Monster4:
- monsterRefresh = chapter.Monster_refresh4;
- break;
- case EMapSchedule.Monster5:
- monsterRefresh = chapter.Monster_refresh5;
- break;
- default:
- break;
- }
- var monsterCount = (monsterRefresh != null && monsterRefresh.Length > 0) ? monsterRefresh[1] : 0;
- if (monsterCount > 0)
- { // 数量0-3
- var monsters = new MonsterEntity[monsterCount];
- for (var i = 0; i < monsterCount; i++)
- {
- var position = GetMonsterBirth(birthPosition, out var positionIdx);
- var monsterTab = MonsterTableRepo.Get(monsterRefresh[0]);
- var entityAttr = new EntityAttributes(monsterTab.Id, UIDDefine.New())
- {
- Name = monsterTab.Name,
- Radius = monsterTab.ModelSize * 0.5f,
- AttackCD = 3000,
- };
- entityAttr.Static.Hp = monsterTab.Hp;
- entityAttr.Static.HpLimit = monsterTab.Hp;
- entityAttr.Static.MoveSpeed = Mathf.RoundToInt(monsterTab.Speed);
- entityAttr.Static.Attack = monsterTab.Atk;
- entityAttr.CurrentHp = monsterTab.Hp;
- var entity = new MonsterEntity();
- entity.Init(UIDDefine.New(), entityAttr, monsterTab.Skills);
- entity.BirthPosition = position;
- entity.PositionIdx = positionIdx;
- monsters[i] = entity;
- }
- return monsters;
- }
- return null;
- }
- private void AddMonsters(MonsterEntity[] monsters)
- {
- if (monsters == null || monsters.Length == 0) return;
- if (_monsterMap == null)
- {
- _monsterMap = new Dictionary<long, MonsterEntity>();
- }
- foreach (var monsterInfo in monsters)
- {
- _monsterMap.Add(monsterInfo.EntityId, monsterInfo);
- }
- }
- #region 事件监听
- private void OnRemoveEntity(int eventId, object args)
- {
- var entityId = (long)args;
- if (_monsterMap.TryGetValue(entityId, out var entity))
- {
- _monsterMap.Remove(entityId);
- PushMonstPositionIdx(entity.PositionIdx);
- CheckMonsterAllDead();
- return;
- }
- if (_partnerMap.TryGetValue(entityId, out var partner))
- {
- _partnerMap.Remove(entityId);
- return;
- }
- if (entityId == _player.EntityId)
- {
- //TODO 失败结算
- CombatFailed();
- }
- }
- private void OnPartnerDown(int eventId, object args)
- {
- var partnerUID = (long)args;
- var entityId = GetPartnerEntityIdByUID(partnerUID);
- if (entityId == 0)
- return;
- EventSingle.Instance.Notify(EventDefine.GameMainMapRemoveEntity, entityId);
- }
- private void OnPartnerUp(int eventId, object args)
- {
- var partnerUID = (long)args;
- var entityId = GetPartnerEntityIdByUID(partnerUID);
- if (entityId != 0)
- return; // 已经有实例对象了
- var chapter = ChapterTableRepo.Get(_chapterId);
- var map = MapTableRepo.Get(chapter.Map);
- var dto = new LoadEntitiesDto();
- dto.chapterId = _chapterId;
- //战斗位置
- dto.battlePosition = GetBattlePosition(map, chapter.Part);// map.BattlePositions[chapter.Part - 1].ToVector3();
- var partner = GenPartner(dto.battlePosition, partnerUID);
- var partners = new PartnerEntity[] { partner };
- AddPartners(partners);
- dto.partners = partners;
- EventSingle.Instance.Notify(EventDefine.GameMainMapLoadEntities, dto);
- }
- //private void OnExchangePartner(int eventId, object args)
- //{
- // var addPartners = (List<int>)args;
- // var activePartnerIds = PartnersData.Instance.ActiveUIDs;
- // var count = addPartners.Count;
- // // 从后往前移除
- // for (var i = 0; i < count; i++)
- // {
- // var partnerId = activePartnerIds[activePartnerIds.Count - 1];
- // activePartnerIds.RemoveAt(activePartnerIds.Count - 1);
- // var EntityId = GetPartnerUIDByTableId(partnerId);
- // if (EntityId == 0)
- // continue;
- // EventSingle.Instance.Notify(EventDefine.GameMainMapRemoveEntity, EntityId);
- // }
- // activePartnerIds.AddRange(addPartners);
- // var chapter = ChapterTableRepo.Get(_chapterId);
- // var map = MapTableRepo.Get(chapter.Map);
- // var dto = new LoadEntitiesDto();
- // dto.chapterId = _chapterId;
- // //战斗位置
- // dto.battlePosition = map.BattlePositions[chapter.Part - 1].ToVector3();
- // var partners = GenPartners(dto.battlePosition, addPartners);
- // AddPartners(partners);
- // dto.partners = partners;
- // EventSingle.Instance.Notify(EventDefine.GameMainMapLoadEntities, dto);
- //}
- private void OnMapEndMask(int eventId, object args)
- {
- var isSuccess = (bool)args;
- var chapter = ChapterTableRepo.Get(_chapterId);
- int chapterId;
- if (isSuccess)
- {
- var nextChapter = ChapterTableRepo.Next(_chapterId);
- //没找到新关卡,重新开始
- if (nextChapter == null || nextChapter.Chapter != chapter.Chapter)
- { // 没有新关卡 || 章节id变化
- //TODO 章节切换
- }
- chapterId = nextChapter?.Id ?? PlayerData.Instance.chapterId;
- }
- //else if (chapter.Part_type == 1)
- //{ // boss节点失败,进入本关卡小怪节点循环
- // TODO
- //}
- else
- { // 普通节点失败,重置到本关卡第一个节点
- chapterId = _chapterId / 10 * 10 + 1;
- }
- StartMap(chapterId);
- }
- #endregion
- private void CheckMonsterAllDead()
- {
- if (_monsterMap.Count > 0) return;
- // 怪物全部死亡
- var chapter = ChapterTableRepo.Get(_chapterId);
- if (chapter.Part_type == 1)
- { //boss关卡
- //TODO 结算
- _bossTimer?.Cancel();
- _bossTimer = null;
- Context.UI.OpenAsync(UIKeys.MainBattleOverVictory);
- Context.Time.AddDelayTimer(2000, () =>
- { //2秒后自动关闭
- Context.UI.Close(UIKeys.MainBattleOverVictory);
- EventSingle.Instance.Notify(EventDefine.GameMainMapStartMask, true);
- });
- }
- else if (_schedule == EMapSchedule.Monster5)
- {
- _chapterId++;
- StartChapter(false, false);
- }
- }
- /// <summary>
- /// 战斗失败
- /// </summary>
- private void CombatFailed()
- {
- // 清空怪物数据
- foreach(var item in _monsterMap)
- {
- PushMonstPositionIdx(item.Value.PositionIdx);
- }
- _monsterMap.Clear();
- Context.UI.OpenAsync(UIKeys.MainBattleOverFail);
- EventSingle.Instance.Notify(EventDefine.GameMainMapStartMask, false);
- }
- private long GetPartnerEntityIdByUID(long uid)
- {
- foreach (var item in _partnerMap)
- {
- if (item.Value.Attr.UID == uid)
- return item.Key;
- }
- return 0;
- }
- private Vector3 GetBattlePosition(MapTable map, int mapPart)
- {
- return map.BattleFirst.ToVector3() + map.PartMove.ToVector3() * (mapPart - 1);
- }
- private Vector3 GetMonsterBirth(MapTable map, int mapPart)
- {
- return map.MonsterBirth.ToVector3() + map.PartMove.ToVector3() * (mapPart - 1);
- }
- }
- }
|