using System; using CoreGame; using CoreGame.Render; using GAS.Runtime; using Sog; using UnityEngine; using xFrame; namespace CoreGame.Render { public static class ZoneSrv { public static void CreateZoneEntityByAbility(GameAbilityContext ctx, int zoneId) { if (ctx.castPos.Count == 0) { return; } var casterEid = ctx.ownerEnt.creationIndex; if (ctx.ownerEnt.hasBullet) { casterEid = ctx.ownerEnt.bullet.casterEid; } else if (ctx.ownerEnt.hasZone) { casterEid = ctx.ownerEnt.zone.casterEid; } var caster = Contexts.Combat.GetEntity(casterEid); if (caster == null) return; var zoneData = ZoneDescMgr.Instance.GetConfig(zoneId); // 需要拿发射者的属性 var zoneAmount = (int)ExpressionEvaluator.CalcVal_WithCtx(zoneData.zoneAmount, ctx, 1); // var ret = new CombatEntity[zoneAmount]; for (int i = 0; i < zoneAmount; i++) { var ce = Contexts.Combat.CreateEntity("Zone" + zoneId); ce.AddFaction(caster.faction.faction, SelectUseType.Zone); var isFollow = zoneData.isFollow != 0; var loopType = zoneData.zoneLoopType; var offsetPos = RandomSrv.insideUnitCircle * (zoneData.offset * BattleConst.TenThousandReverse); var duration = (float)ExpressionEvaluator.CalcVal_WithCtx(zoneData.duration, ctx, 7); var interval = (float)ExpressionEvaluator.CalcVal_WithCtx(zoneData.interval, ctx, 2); var loopCnt = (int)ExpressionEvaluator.CalcVal_WithCtx(zoneData.times, ctx, 3); var castEid = ctx.castTarget.Count > i ? ctx.castTarget[i] : -1; var castPos = ctx.castPos.Count > i ? ctx.castPos[i] : ctx.castPos[0]; var castTarget = Contexts.Combat.GetEntity(castEid); ce.AddProperty(); caster.property.TaskSnapShot(ce.property.container); ce.AddZone(caster.creationIndex, castEid, zoneId, isFollow, offsetPos, loopType, duration, loopCnt, interval, zoneData.skill1, zoneData.EndSkill, interval, zoneData.destroyOnTargetMiss == Bool.TRUE); ce.AddLogicTransform(Fixed64Vector2.zero, Fixed64Vector2.one, Fixed64Vector2.right); ce.AddTransformProxy(Vector2.zero, Vector2.right, ce); ce.AddGaCtxTransfer(ctx.abilitySpec.gaParams, ctx.abilitySpec.gaInitCfg, ctx.level); ce.AddAudio(ce.creationIndex); var ignore = ListPool.Pop(); ignore.Add(typeof(Animator)); ce.AddAsset( new MainAssetParam() { path = zoneData.Prefab, parentNodeName = "RenderWorld", } , ignore); if (isFollow && castTarget != null) { ce.logicTransform.SetPosition(castTarget.logicTransform.position + offsetPos); ce.logicTransform.SetDirection(castTarget.logicTransform.forward); } else { ce.logicTransform.SetPosition(castPos + offsetPos); ce.logicTransform.SetDirection(Fixed64Vector2.right); } if (zoneData.skill1 != 0) { ce.zone.attachAbilityCtxSeq = ZoneAttachAbility(ce, zoneData.skill1); } if (zoneData.EndSkill != 0) { ce.zone.endAbilityCtxSeq = ZoneAttachAbility(ce, zoneData.EndSkill); } // ce.LoadAsset(); // ret[i] = ce; } // return ret; } public static void DestroyZone(CombatEntity zoneEnt) { zoneEnt.isDestroyEnt = true; } public static void InvalidateZone(CombatEntity zoneEnt) { if (zoneEnt.hasZone == false) { XLog.LogDebug("InvalidateZone zoneEnt.hasZone == false"); return; } zoneEnt.asset?.HideMainAsset(); // 隐藏模型, 但不销毁 zoneEnt.zone.hasInvalidated = true; } public static void DestroyInvalidZoneFromSpec(AbilitySpec abilitySpec) { var ctxOwnerEnt = abilitySpec.ctx.ownerEnt; var zone = ctxOwnerEnt.zone; if (zone == null) { XLog.LogDebug("DestroyInvalidZoneFromSpec zone == null"); return; } if (zone.hasInvalidated == false) { XLog.LogDebug("DestroyInvalidZoneFromSpec zone not invalidated"); return; } zone.invalidatedCount--; if (zone.invalidatedCount <= 0) { DestroyZone(ctxOwnerEnt); } } public static bool ZoneActiveAbility(CombatEntity entity, int seq, bool dropAbilityWhenEnd) { if (entity.hasAbilitySystem == false) return false; var res = false; var ctx = entity.abilitySystem.AbilityContainer.HasAbility(seq) ? entity.abilitySystem.GetAbilitySpecs(seq).ctx : null; if (ctx != null) { var zone = entity.zone; var gaCtxTransfer = entity.gaCtxTransfer; ctx.castPos.Add(entity.logicTransform.position); ctx.castTarget.Add(zone.targetEid); // 有可能追着目标 ZoneTryRegisterEndAbility(zone, ctx); ctx.dropAbilityWhenEnd = dropAbilityWhenEnd; res = ctx.asc.TryActivateAbility_WithSeqAndParam(ctx.gaSeq, gaCtxTransfer.gaParams); } return res; } private static int ZoneAttachAbility(CombatEntity entity, int abilityId) { var gaCtxTransfer = entity.gaCtxTransfer; var ctx = AbilitySrv.GrantTransferAbility(entity, abilityId, gaCtxTransfer.gaInitCfg, null, gaCtxTransfer.level); return ctx.gaSeq; } private static void ZoneTryRegisterEndAbility(ZoneComponent zone, GameAbilityContext context) { if (zone.hasInvalidated) { zone.invalidatedCount++; context.abilitySpec.RegisterEndAbility(DestroyInvalidZoneFromSpec); } } } }