using System; using System.Collections.Generic; using AOT; using GAS.Runtime; using NavMeshPlus.Components; using Sog; using UnityEngine; namespace CoreGame.Render { /// /// 创建实体的服务,虽然没有英雄,怪物等概念,但实际是需要有, /// TODO: 逻辑表现的实体ID要一直 /// public static class EntityCreateSrv { public static void CreateBattleTeam() { // 创建英雄 var heroEntity = CreateHeroEntity(Contexts.Combat, CoreUIBridge.BattleInfoParams.heroSkinId); heroEntity.transformProxy.SetPosition(CoreUIBridge.BattleInfoParams.playerBronPosition); heroEntity.transformProxy.SetDirection(Vector3.right); // heroEntity.TagAggregator.AddFixedTag(GTagLib.State_CannotBeOppoCatch); BattleModule.s_LocalPlayerEid = heroEntity.creationIndex; #if UNITY_EDITOR BattleSimulateData.AttachTest(heroEntity); #endif } public static CombatEntity CreateHeroEntity(CombatContext context, int heroSkinId) { var showCfg = RoleModelDescMgr.Instance.GetConfig(heroSkinId); var ce = context.CreateEntity("Hero" + heroSkinId); PropertySrv.GetHeroBasePropValue(ce); ce.AddCommandReceiver(ce); ce.isHero = true; ce.AddBlackboard(CfgType.HeroCfg, heroSkinId, new[] { heroSkinId }, Array.Empty(), ce.creationIndex, false); ce.AddFaction(Faction.Player, SelectUseType.Actor); ce.AddTransformProxy(Vector2.zero, Vector2.right, ce); ce.AddAudio(ce.creationIndex); AbilitySrv.AttachActiveAbilityGroup(CommParamDescMgr.Instance.RoleDefaultSki.int_val, ce); ce.AddAsset(new MainAssetParam() { path = $"{showCfg.folderPath}/{showCfg.prefabAnim}.prefab", parentNodeName = "RenderWorld", scaleParam = 1, }, null); var subAssetData = SptPool.Malloc(); subAssetData.Awake(ce.creationIndex, CoreUIBridge.BattleInfoParams.wingPath, BindPointType.Wing, null); ce.asset.PushMainPartAsset(ref subAssetData); // ce.blackboard.SetBornPos(ce.logicTransform.position); Contexts.Combat.localPlayerEid = ce.creationIndex; ce.isLocalPlayer = true; ce.isAttractor = true; ce.AddEquips(ce); ce.equips.SwitchSlotNoCheck(CoreUIBridge.BattleInfoParams.equipInfo.currentGunSlot); GunSrv.DynamicEquipGun(ce, CoreUIBridge.BattleInfoParams.equipInfo); return ce; } public static CombatEntity CreateCameraEntity(CombatContext context, string prefabPath) { var combatEntity = context.CreateEntity("VirtualCamera"); combatEntity.AddAsset( new MainAssetParam() { path = prefabPath, parentNodeName = "RenderWorld", scaleParam = 1, }, null); // combatEntity.LoadAsset(); return combatEntity; } public static CombatEntity CreateJumpTextEntity(CombatContext context, object initData = null) { var combatEntity = context.SetJumpText(new Queue()); combatEntity.Name = "JumpText"; return combatEntity; } public static CombatEntity CreateJoystickEntity(CombatContext context, object initData = null) { var combatEntity = context.CreateEntity("JoystickEntity"); combatEntity.AddAsset( new MainAssetParam() { path = "Model/Joystick", parentNodeName = "UICanvas/GlobalWindowManager/JoyStick", scaleParam = 1, }, null); // combatEntity.LoadAsset(); return combatEntity; } public static CombatEntity[] CreateObstacleEntities(CombatContext context, object initData = null) { const int componentIndex = CombatComponentsLookup.Collider2DProxy; var modifiers = NavMeshModifier.activeModifiers; var gameObject = new GameObject("ObstacleEntities_Logic"); var allObstacle = context.CreateEntity("ObstacleEntities_Logic"); allObstacle.isObstacle = true; allObstacle.AddFaction(Faction.None, SelectUseType.Obstacle, Faction.None); var proxy = (Collider2DProxy)allObstacle.CreateComponent(componentIndex, CombatComponentsLookup.componentTypes[componentIndex]); allObstacle.AddComponent(componentIndex, proxy); allObstacle.AddTransformProxy(Vector2.zero, Vector2.right, allObstacle); (proxy).Init(gameObject, allObstacle); AbilitySrv.GrantBaseAbility(allObstacle); allObstacle.TagCountContainer.UpdateTagCount(GTagLib.Entity_Obstacle, 1); var fac = allObstacle.faction; for (var i = 0; i < modifiers.Count; i++) { var modifier = modifiers[i]; if (modifier.TryGetComponent(out var collider2D)) { proxy.FillColliderByInit(collider2D, fac, true); } } return null; } public static void CreateSummonEntities(GameAbilityContext ctx, int summonId) { var tbSummon = SummonDescMgr.Instance.GetConfig(summonId); var summoner = ctx.ownerEnt; var summonerFaction = summoner.faction; var queryParam = new QueryParam { faction = summonerFaction.faction, selectUseType = SelectUseType.Summon }; var friendSummon = Contexts.Combat.GetEntitiesWithFactionCommonBeQueryParam(queryParam); int existAmount = 0; foreach (var ent in friendSummon) { if (ent.summon.summonId == summonId) existAmount++; } var summonAmount = (float)ExpressionEvaluator.CalcVal_WithCtx(tbSummon.summonAmount, ctx, 2f); var summonAmountMax = (float)ExpressionEvaluator.CalcVal_WithCtx(tbSummon.maxAmount, ctx, 3f); var summonCount = summonAmount + existAmount < summonAmountMax ? (int)summonAmount : (int)summonAmountMax - existAmount; if (summonCount == 0) { return; } var summonerPos = Vector2.zero ;//summoner.logicTransform.position; var summonDistance = (float)ExpressionEvaluator.CalcVal_WithCtx(tbSummon.summonDistance, ctx, 5f); var maxSurvivalTime = (float)ExpressionEvaluator.CalcVal_WithCtx(tbSummon.maxTime, ctx, 5f); var survivalParam1 = (float)ExpressionEvaluator.CalcVal_WithCtx(tbSummon.survivalParam1, ctx, 10f); var survivalType = tbSummon.survivalType; var tbMonster = MonsterPropDescMgr.Instance.GetConfig(tbSummon.monsterID); // var res = new CombatEntity[summonCount]; for (var i = 0; i < summonCount; i++) { var ce = Contexts.Combat.CreateEntity("Summon" + tbMonster.name); ce.AddFaction(summonerFaction.faction, SelectUseType.Summon); PropertySrv.GetMonsterPropValue(ce, tbMonster.id); var propertyComponent = ce.property; propertyComponent.SetLinkEid(summoner.creationIndex); propertyComponent.SetLinkProperty(PropertyDef.Level); if (string.IsNullOrEmpty(tbSummon.hpFixedInc) == false) { var totalHp = ExpressionEvaluator.CalcVal_WithCtx(tbSummon.hpFixedInc, ctx, 0); propertyComponent.SetProperty(PropertyDef.HpFixedIncrease, totalHp, true); propertyComponent.SetProperty(PropertyDef.CurHp, totalHp, true); } if (string.IsNullOrEmpty(tbSummon.atkFixedInc) == false) { var atk = ExpressionEvaluator.CalcVal_WithCtx(tbSummon.atkFixedInc, ctx, 0); propertyComponent.SetProperty(PropertyDef.AtkFixedIncrease, atk, true); } if (string.IsNullOrEmpty(tbSummon.defFixedInc) == false) { var def = ExpressionEvaluator.CalcVal_WithCtx(tbSummon.defFixedInc, ctx, 0); propertyComponent.SetProperty(PropertyDef.DefFixedIncrease, def, true); } var affixIds = GetMonsterRandomAffixIds(tbMonster); ce.AddBlackboard(CfgType.MonsterCfg, tbMonster.id, Array.Empty(), affixIds, ce.creationIndex, tbMonster.NoChangeDir == 0); ce.AddSummon(summonId, maxSurvivalTime, survivalType, survivalParam1); if (tbSummon.dieWithSummoner != 0) { var lifeBindMeComponent = summoner.lifeBindMe; if (lifeBindMeComponent == null) { summoner.AddLifeBindMe(summoner); lifeBindMeComponent = summoner.lifeBindMe; } lifeBindMeComponent.AddChild(ce.creationIndex, i == 0); } ce.AddParentRecorder(CompLinkerType.Summon2C, summoner.creationIndex); if (summonerFaction.faction == Faction.Player) ce.isPartner = true; else ce.AddMonster(tbMonster.type); AbilitySrv.AttachActiveAbilityGroup(tbMonster.skillGroup, ce); AttachAffixTalentToEntity(ce); for (int j = 0; j < tbMonster.AssetTags.Length; j++) { var gameplayTag = AbilitySrv.GetGameplayTag(tbMonster.AssetTags[j]); ce.TagCountContainer.AddFixedTag(gameplayTag); } ce.AddAsset( new MainAssetParam { path = tbMonster.prefab, parentNodeName = "RenderWorld", scaleParam = 1, }, null); // ce.LoadAsset(); var randomPos2D = MathHelper.OnsideUnitCircleRandom(summonDistance); // summonerPos = summonerPos + randomPos2D; // var vector2 = MathViewUtils.ToVector2(summonerPos); // NavMesh.SamplePosition(fixed64Vector2, out var closestHit, 10f, NavMesh.AllAreas); // var pos = new Vector2(closestHit.position.x, closestHit.position.y); // ce.AddLogicTransform(summonerPos, Fixed64Vector2.one, Fixed64Vector2.right); // ce.AddTransformProxy(summonerPos.ToVector2(), Vector2.right, ce); ce.AddAudio(ce.creationIndex); ce.blackboard.SetBornPos(ce.logicTransform.position, randomPos2D); } } public static CombatEntity BronMonsterEntity(CombatContext context, CombatEntity parentEnt, ref MonsterData monsterData) { var tbMonster = MonsterPropDescMgr.Instance.GetConfig(monsterData.unitId); if (tbMonster == null) return null; var ce = context.CreateEntity("Monster" + tbMonster.name); var affixIds = GetMonsterRandomAffixIds(tbMonster); ce.AddBlackboard(CfgType.MonsterCfg, monsterData.unitId, Array.Empty(), affixIds, ce.creationIndex, tbMonster.NoChangeDir == 0); // var hasHit = NavMesh.Raycast(monsterData.srcPos, monsterData.position, out var closestHit, NavMesh.AllAreas); // // var isSucc = NavMesh.SamplePosition(monsterData.position, out var closestHit, 10f, NavMesh.AllAreas); // if (hasHit) // { // var normalDir = new Vector2(closestHit.normal.x, closestHit.normal.y); // Vector2 newPos = closestHit.position; // monsterData.position = newPos + normalDir * monsterData.pushRadius; // NavMesh.SamplePosition(monsterData.position, out var closestHit2, 10f, NavMesh.AllAreas); // monsterData.position = new Vector2(closestHit2.position.x, closestHit2.position.y); // } ce.AddLogicTransform(monsterData.position, Fixed64Vector2.one, Fixed64Vector2.right); ce.blackboard.SetBornPos(ce.logicTransform.position); // if (parentEnt != null) // ce.AddParentRecorder(CompLinkerType.Summon2C, parentEnt.creationIndex); ce.AddEffectShowProxy(tbMonster.VFXsize * BattleConst.TenThousandReverse.AsFloat, ce); ce.AddBorn(tbMonster.bornTime * BattleConst.TenThousandReverse.AsFloat, tbMonster.bornVFX); return ce; } public static CombatEntity CreateMonsterByBorn(CombatEntity ce) { var blackboard = ce.blackboard; var tbMonster = MonsterPropDescMgr.Instance.GetConfig(blackboard.unitCfgId); ce.AddMonster(tbMonster.type); PropertySrv.GetMonsterPropValue(ce, tbMonster.id); // 阵营要先设置,碰撞有依赖 ce.AddFaction(Faction.Enemy, SelectUseType.Actor); ce.AddAudio(ce.creationIndex); AbilitySrv.AttachActiveAbilityGroup(tbMonster.skillGroup, ce); AttachAffixTalentToEntity(ce); if (tbMonster.type == MonsterType.Boss) { ce.TagCountContainer.AddFixedTag("Entity.Monster.Boss"); // 添加可再生护盾 if (tbMonster.ShieldValue > 0) { ce.AddRefreshableHpShield(tbMonster.ShieldType, tbMonster.ShieldValue, tbMonster.ShieldRestore * 0.001f); ce.AddReload(0); } } ce.AddAsset( new MainAssetParam() { path = tbMonster.prefab, parentNodeName = "RenderWorld", scaleParam = 1, }, null); // ce.LoadAsset(); var levelWaveEntity = Contexts.Combat.LevelWave; levelWaveEntity.DispatchEvent(ClientEvent.LevelMonsterRage, null); return ce; } public static int[] GetMonsterRandomAffixIds(MonsterPropDesc tbMonster) { var randomAffixes = tbMonster.randomAffixes; if (randomAffixes == 0) { return Array.Empty(); } var affixesRandomGroupDesc = AffixesRandomGroupDescMgr.Instance.GetConfig(randomAffixes); if (affixesRandomGroupDesc == null || affixesRandomGroupDesc.affixesGroup.Length == 0) { return Array.Empty(); } var affixesRandomGroup = affixesRandomGroupDesc.affixesGroup; var randomIndex = RandomSrv.Range(0, affixesRandomGroup.Length); var affixesId = affixesRandomGroup[randomIndex]; var affixes = AffixesDescMgr.Instance.GetConfig(affixesId); var affixIds = new int[affixes.affixes.Length]; for (var i = 0; i < affixes.affixes.Length; i++) { var affixId = affixes.affixes[i]; affixIds[i] = affixId; } return affixIds; } public static void AttachAffixTalentToEntity(CombatEntity ce) { var blackboard = ce.blackboard; if (ce.blackboard == null) return; for (int i = 0; i < blackboard.affixIds.Length; i++) { var affixId = blackboard.affixIds[i]; var affix = AffixDescMgr.Instance.GetConfig(affixId); AbilitySrv.AttachTalent_WithGaParam(ce, affix.talentID, null, 1); } } } }