123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537 |
- using FL.Battle;
- using FL.Battle.Components;
- using FL.Battle.Skills;
- using FL.Data;
- using FL.Nodes.GameMain;
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using XGame;
- using XGame.Database;
- using XGame.Framework.Asyncs;
- using XGame.Framework.Components;
- using XGame.Framework.Map;
- using XGame.Framework.Time;
- namespace FL.Map.TestMainMap
- {
- public interface IEntitiesContext
- {
- IMapAssetModule Asset { get; }
- ITimeModule Time { get; }
- TestMainMapVM VM { get; }
- VfxComponent Vfx { get; }
- MapUIComponent MapUI { get; }
- }
- public partial class EntitiesComponent : Component<IEntitiesContext>
- {
- /// <summary>
- /// 怪物的位置相对于玩家战斗位置的偏移值
- /// </summary>
- private const float MONSTER_POSITION_OFFSET = 6;
- private PlayerEntityView _player;
- private Dictionary<long, PartnerEntityView> _partnerMap = new();
- private Dictionary<long, MonsterEntityView> _monsterMap = new();
- /// <summary>
- /// 地图实例对象,怪物、陷阱、召唤兽等
- /// key:UID
- /// </summary>
- private Dictionary<long, IEntityView> _entityViewsMap = new();
- private TargetSelector _selector;
- private ITimer _selectorTimer;
- protected override void OnEnable(object intent)
- {
- InitSelector();
- EventSingle.Instance.AddListener(EventDefine.GameMainMapLoadEntities, OnLoadEntities);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapRemoveSimpleEntity, OnRemoveSimpleEntity);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapStartMask, OnStartMask);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapGenBullet, OnGenBullet);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapGenCommons, OnGenCommons);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapAddBuff, OnAddBuff);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapRemoveBuff, OnRemoveBuff);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapReqPreviewBuffs, OnRequestBuffList);
- }
- protected override void OnDisable()
- {
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapLoadEntities, OnLoadEntities);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapRemoveSimpleEntity, OnRemoveSimpleEntity);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapStartMask, OnStartMask);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapGenBullet, OnGenBullet);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapGenCommons, OnGenCommons);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapAddBuff, OnAddBuff);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapRemoveBuff, OnRemoveBuff);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapReqPreviewBuffs, OnRequestBuffList);
- ClearSelector();
- Context.VM.Camera.Target = null;
- Context.Asset.Recycle(_player);
- foreach (var partner in _partnerMap.Values)
- {
- Context.Asset.Recycle(partner);
- }
- _partnerMap.Clear();
- foreach (var monster in _monsterMap.Values)
- {
- Context.Asset.Recycle(monster);
- }
- _monsterMap.Clear();
- foreach (var entity in _entityViewsMap.Values)
- {
- Context.Asset.Recycle(entity);
- }
- _entityViewsMap.Clear();
- ClearElementBuffs();
- }
- protected override void OnDispose()
- {
- }
- #region 事件监听
- private void OnLoadEntities(int eventId, object args)
- {
- var dto = (LoadEntitiesDto)args;
- if (dto.isPlayerMove)
- {
- ClearVfxs();
- }
- Context.MapUI.RefreshChapter(dto.chapterId);
- var asyncGroup = new AsyncGroup();
- if (dto.player != null)
- { // 第一波怪物,玩家不存在时
- var playerAsync = Context.Asset.LoadEntity<PlayerEntityView>(AddressableDefine.Player, Context.VM.PlayerRoot);
- playerAsync.On(_ =>
- {
- var entityView = playerAsync.Result;
- if (entityView == null)
- {
- return;
- }
- entityView.Entity = dto.player;
- Context.VM.Camera.Target = entityView.Move;// behaviour.transform;
- _player = entityView;
- _selector.Register(entityView);
- entityView.Selector = _selector;
- Context.MapUI.AddEntity(entityView);
- });
- playerAsync.Join(asyncGroup);
- }
- else if (dto.isChapterChanged)
- {
- Context.VM.Reset();
- _player.Reset();
- Context.MapUI.RefreshEntity(_player.Entity.EntityId);
- foreach (var item in _partnerMap)
- {
- item.Value.Reset();
- }
- }
- else if (dto.isBossPart)
- { // 重置玩家的血量
- _player.Reset(true);
- Context.MapUI.RefreshEntity(_player.Entity.EntityId);
- }
-
- var partnerCount = dto.partners?.Length ?? 0;
- if (partnerCount > 0)
- { // 创建伙伴实例
- for (var i = 0; i < partnerCount; i++)
- {
- var partner = dto.partners[i];
- var table = PartnerTableRepo.Get(partner.TableId);
- var loadAsync = Context.Asset.LoadEntity<PartnerEntityView>(table.Model, Context.VM.PlayerRoot);
- loadAsync.On(_ =>
- {
- var entityView = loadAsync.Result;
- if (entityView == null)
- {
- return;
- }
- entityView.Entity = partner;
- entityView.BodyMirror();
- _partnerMap.Add(partner.EntityId, entityView);
- _selector.Register(entityView);
- entityView.Selector = _selector;
- });
- loadAsync.Join(asyncGroup);
- }
- }
- var monsterCount = dto.monsters?.Length ?? 0;
- if (monsterCount > 0)
- { // 创建怪物实例
- for (var i = 0; i < monsterCount; i++)
- {
- var monster = dto.monsters[i];
- var table = MonsterTableRepo.Get(monster.TableId);
- var loadAsync = Context.Asset.LoadEntity<MonsterEntityView>(table.Model, Context.VM.EnemyRoot);
- loadAsync.On(_ =>
- {
- var entityView = loadAsync.Result;
- if (entityView == null)
- {
- return;
- }
- entityView.Entity = monster;
- entityView.Entity = monster;
- _monsterMap.Add(monster.EntityId, entityView);
- _selector.Register(entityView);
- entityView.Selector = _selector;
- if (table.Type == 1)
- { //boss的血条等boss移动到战斗位置再加载
- Context.MapUI.AddEntity(entityView);
- }
- });
- loadAsync.Join(asyncGroup);
- }
- }
- asyncGroup.On(_ =>
- {
- //Entities加载完成,开始移动
- if (dto.isPlayerMove)
- {
- _player.Reset(true);
- var moveArgs = new MoveArgs()
- {
- target = Context.VM.PlayerRoot.TransformPoint(dto.battlePosition)
- };
- _player.CommonAI.MoveToBattle(moveArgs, () =>
- {
- if (dto.isChapterChanged)
- {
- Context.VM.SetFocusPosition(_player.Position);
- }
- });
- foreach (var item in _partnerMap)
- {
- var entityView = item.Value;
- var entity = entityView.Entity;
- var tarPosition = dto.battlePosition;
- tarPosition += PartnersData.Instance.GetPartnerOffset(entity.Attr.UID);
- // 本地坐标转世界坐标
- tarPosition = Context.VM.PlayerRoot.TransformPoint(tarPosition);
- entityView.Reset(true);
- moveArgs = new MoveArgs()
- {
- target = tarPosition,
- };
- entityView.CommonAI.MoveToBattle(moveArgs);
- }
- }
- else if (partnerCount > 0)
- {
- for (var pIdx = 0; pIdx < partnerCount; pIdx++)
- {
- var entity = dto.partners[pIdx];
- var entityView = _partnerMap[entity.EntityId];
- entityView.CommonAI.PrepareBattle();
- }
- }
- //var monsterCount = dto.monsters?.Length ?? 0;
- for (var mIdx = 0; mIdx < monsterCount; mIdx++)
- {
- var entity = dto.monsters[mIdx];
- //var monsterTable = MonsterTableRepo.Get(entity.TableId);
- var tarPosition = entity.BirthPosition;
- tarPosition.y += (-dto.monsterMoveDistance + MONSTER_POSITION_OFFSET);
- tarPosition = Context.VM.EnemyRoot.TransformPoint(tarPosition);
- var entityView = _monsterMap[entity.EntityId];
- var moveArgs = new MoveArgs()
- {
- target = tarPosition,
- delay = entity.BirthDelay,
- };
- if (entity.BirthCurve > 0)
- {
- moveArgs.moveType = EMoveType.Curve;
- moveArgs.curve = Context.VM.MapPathCurve.GetCurve(entity.BirthCurve - 1);
- moveArgs.curveOffset = new Vector3(3, 0, 0);
- }
- entityView.CommonAI.MoveToBattle(moveArgs, () =>
- {
- if (entity.IsBoss)
- {
- Context.MapUI.AddBoss(entityView, dto.chapterId);
- }
- });
- }
- });
- asyncGroup.End();
- }
- private void OnRemoveEntity(int eventId, object args)
- {
- var entityId = (long)args;
- if (_monsterMap.TryGetValue(entityId, out var monster))
- {
- _monsterMap.Remove(entityId);
- _selector?.Unregister(monster);
- Context.Asset.Recycle(monster);
- RemoveElementBuff(entityId);
- return;
- }
- if (_partnerMap.TryGetValue(entityId, out var partner))
- {
- _partnerMap.Remove(entityId);
- _selector?.Unregister(partner);
- Context.Asset.Recycle(partner);
- return;
- }
- //if (entityId == _player?.Entity.EntityId)
- //{ // 玩家死亡只设置状态,不移除
- // _selector?.Unregister(_player);
- // Context.Asset.Recycle(_player);
- // _player = null;
- // Context.VM.Camera.Target = null;
- //}
- }
- private void OnRemoveSimpleEntity(int eventId, object args)
- {
- var entityId = (long)args;
- if (_entityViewsMap.TryGetValue(entityId, out var entityView))
- {
- _entityViewsMap.Remove(entityId);
- Context.Asset.Recycle(entityView);
- }
- }
- #endregion
- #region 目标选择
- private void InitSelector()
- {
- if (_selector == null)
- {
- _selector = new TargetSelector();
- }
- _selectorTimer = Context.Time.AddLooperTimer(100, _selector.OnUpdate);
- }
- private void ClearSelector()
- {
- _selector?.Clear();
- _selectorTimer?.Cancel();
- _selectorTimer = null;
- }
- #endregion
- #region 黑屏
- private void OnStartMask(int eventId, object args)
- {
- var sign = (EMapCombatSign)args;
- var duration = 2;
- ClearVfxs();
- if (sign is EMapCombatSign.Success)
- {
- PlayerMoveToCenter(duration);
- }
- else
- { // 玩家死亡,失败, 重置随从
- _player?.Reset();//
- foreach (var entity in _partnerMap.Values)
- {
- entity.Reset();
- }
- // 清空怪物
- foreach (var item in _monsterMap)
- {
- var entityId = item.Key;
- var monster = item.Value;
- //_monsterMap.Remove(entityId);
- _selector?.Unregister(monster);
- Context.Asset.Recycle(monster);
- RemoveElementBuff(entityId);
- }
- _monsterMap.Clear();
- }
- Context.VM.ShowBlackMask(duration, () =>
- {
- EventSingle.Instance.Notify(EventDefine.GameMainMapEndMask, sign);
- });
- }
- /// <summary>
- /// 没有怪物了,直接清空所有特效
- /// </summary>
- private void ClearVfxs()
- {
- foreach (var item in _entityViewsMap)
- {
- Context.Asset.Recycle(item.Value);
- }
- _entityViewsMap.Clear();
- Context.Vfx.Stop();
- }
- /// <summary>
- /// 玩家移动到屏幕中心
- /// </summary>
- /// <param name="duration">单位:秒</param>
- private void PlayerMoveToCenter(float duration)
- {
- var centerPosition = Context.VM.Camera.TopCenterToWorldPosition();
- var distance = centerPosition.y - _player.Position.y;
- var speed = distance / duration;
- // 使用玩家世界坐标的z值
- centerPosition.z = _player.Position.z;
- //var targetPosition = Context.VM.PlayerRoot.InverseTransformPoint(centerPosition);
- //Log.Debug($"PlayerMoveToCenter Player World:{_player.Position} Local:{_player.LocalPosition} Center World:{centerPosition}");
- _player.CommonAI.MoveTo(new MoveArgs
- {
- target = centerPosition,
- speed = speed,
- timeScale = 1,
- });
- foreach (var item in _partnerMap)
- {
- var entityView = item.Value;
- var entity = entityView.Entity;
- var tarPosition = centerPosition;
- tarPosition += PartnersData.Instance.GetPartnerOffset(entity.Attr.UID);
- entityView.CommonAI.MoveTo(new MoveArgs
- {
- target = tarPosition,
- speed = speed,
- timeScale = 1,
- });
- }
- }
- #endregion
- #region 子弹
- private void OnGenBullet(int eventId, object args)
- {
- var dto = (GenBulletDto)args;
- var targetType = dto.masterType == EEntityType.Monster ? EEntityType.Player : EEntityType.Monster;
- var skill = SkillTableRepo.Get(dto.tableId);
- var skillVfx = SkillVfxsTableRepo.Get(dto.tableId);
- var loadAsync = Context.Asset.LoadEntity<BulletEntityView>(skillVfx.SkillVfx, Context.VM.BulletRoot);
- var startTime = Context.Time.GetNowTime();
- loadAsync.On(_ =>
- {
- var delay = dto.delay > 0 ? Mathf.Max(dto.delay - (int)(Context.Time.GetNowTime() - startTime), 0) : 0;
- var view = loadAsync.Result;
- if (view == null)
- return;
- //var tarEntity = _selector.GetTarget((int)dto.targetId);
- //if (tarEntity == null || tarEntity.Entity.State == EEntityState.Dead)
- //{
- // Context.Asset.Recycle(view);
- // Log.Debug($"子弹加载成功,但是目标已死亡。Master:{dto.masterId} Target:{dto.targetId} Bullet:{dto.tableId}");
- // return;
- //}
- view.UID = UIDDefine.New();
- view.MasterId = dto.masterId;
- view.TableId = dto.tableId;
- view.Selector = _selector;
- view.Position = dto.from;
- _entityViewsMap.Add(view.UID, view);
- //var tarPosition = dto.to;
- //if (skill.SkillVfxType == (int)ESkillVfxType.BulletMortar)
- //{ // 目标位置随机,以本节战斗位置为中心偏移
- // tarPosition = _player.Position; //玩家的坐标和本节战斗的位置重叠
- // if (dto.masterType != EEntityType.Monster)
- // {// 施法者是玩家或者随从
- // tarPosition += skillVfx.SkillVfxPositions[1].ToVector3();
- // }
- // tarPosition.x += UnityEngine.Random.Range(-4, 5);
- // tarPosition.y += UnityEngine.Random.Range(-2, 2);
- //}
- view.AI.Start(dto.targetId, dto.to, targetType, delay);
- });
- }
- #endregion
- #region 召唤物
- private void OnGenCommons(int eventId, object args)
- {
- var dto = (GenSummonsDto)args;
- var skill = SkillTableRepo.Get(dto.tableId);
- var skillVfxs = SkillVfxsTableRepo.Get(dto.tableId);
- //var targetType = dto.masterType == EEntityType.Monster ? EEntityType.Player : EEntityType.Monster;
- var battlePosition = _player.Position;//玩家的坐标和本节战斗的位置重叠
- for (var i = 0; i < dto.count; i++)
- {
- switch ((ESkillVfxType)skill.SkillVfxType)
- {
- case ESkillVfxType.Trap:
- {
- var to = _selector.RandomPosition(dto.masterType == EEntityType.Monster ? EEntityType.Player : EEntityType.Monster, i == 0);
- //if (dto.masterType != EEntityType.Monster)
- //{ // 施法者是玩家或者随从
- // to += skillVfxs.SkillVfxPositions[1].ToVector3();
- //}
- //// 陷阱位置随机
- //to.x += UnityEngine.Random.Range(-4, 5);
- //to.y += UnityEngine.Random.Range(-2, 2);
- LoadTrap(dto, skillVfxs.SkillVfx, to);
- }
- break;
- case ESkillVfxType.AOE:
- {
- if (skillVfxs.VfxFollowType == (int)EVfxFollowType.World)
- { // 坐标修改为本次战斗的世界坐标
- dto.from = battlePosition;
- }
- var aoeFrom = skillVfxs.SkillVfxPositions[0].ToVector3();
- var aoeTo = skillVfxs.SkillVfxPositions[1].ToVector3();
- if (dto.masterType == EEntityType.Monster)
- { // 怪物在上,玩家在下
- aoeFrom.y *= -1;
- aoeTo.y *= -1;
- }
- aoeTo += dto.from;
- dto.from += aoeFrom;
- LoadAOEEntity(dto, skillVfxs.SkillVfx, aoeTo);
- }
- break;
- case ESkillVfxType.AOENoMove:
- {
- var to = battlePosition;
- to += skillVfxs.SkillVfxPositions[0].ToVector3();
- dto.from = to;
- LoadAOEEntity(dto, skillVfxs.SkillVfx, to);
- }
- break;
- case ESkillVfxType.AOETarget:
- {
- var to = dto.from;
- LoadAOEEntity(dto, skillVfxs.SkillVfx, to);
- }
- break;
- default:
- throw new NotImplementedException();
- }
- }
- }
- private void LoadTrap(GenSummonsDto dto, string vfxName, Vector3 tarPosition)
- {
- var loadAsync = Context.Asset.LoadEntity<TrapEntityView>(vfxName, Context.VM.BulletRoot);
- loadAsync.On(_ =>
- {
- var view = loadAsync.Result;
- if (view == null)
- return;
- view.UID = UIDDefine.New();
- view.MasterId = dto.masterId;
- view.TableId = dto.tableId;
- view.Selector = _selector;
- view.Position = dto.from;
- _entityViewsMap.Add(view.UID, view);
- view.AI.Start(tarPosition, dto.targetType);
- });
- }
- private void LoadAOEEntity(GenSummonsDto dto, string vfxName, Vector3 tarPosition)
- {
- var loadAsync = Context.Asset.LoadEntity<AOEEntityView>(vfxName, Context.VM.BulletRoot);
- loadAsync.On(_ =>
- {
- var view = loadAsync.Result;
- if (view == null)
- return;
- view.UID = UIDDefine.New();
- view.MasterId = dto.masterId;
- view.TableId = dto.tableId;
- view.Selector = _selector;
- view.Position = dto.from;
- _entityViewsMap.Add(view.UID, view);
- view.AI.Start(tarPosition, dto.targetType);
- });
- }
- #endregion
- }
- }
|