using CommonAI.Zone; using CommonAI.Zone.Helper; using CommonAI.ZoneClient; using ET; using ET.EventType; using Sirenix.Utilities; using System; using System.Collections.Generic; using XmdsCommon.Plugin; public class BattleUnit : BattleObject { public BattleUnit() { } public ZoneUnit ZUnit { get { return ZoneObject as ZoneUnit; } } public bool IsDead { get { return ZUnit.CurrentState == UnitActionStatus.Dead; } } private EventDispatcher<UnitActionStatus, object> actionChangeHandler; public int Vip = 0; public override void OnAwake(ZoneObject zo) { base.OnAwake(zo); actionChangeHandler = new(); registerActionHandler(); var zu = zo as ZoneUnit; zu.OnActionChanged += OnActionChanged; zu.OnSkillActionChanged += (ZoneUnit unit, ZoneUnit.SkillState skill, byte index) => { }; zu.OnHPChanged += (ZoneUnit unit, int oldHP, int newHP)=> { OnHPChanged(); }; zu.OnMPChanged += (ZoneUnit unit, int oldMaxMP, int newMaxMP) => { }; zu.OnMaxHPChanged += (ZoneUnit unit, int oldHP, int newHP) => { OnHPChanged(); }; zu.OnMaxMPChanged += (ZoneUnit unit, int oldMaxMP, int newMaxMP)=> { }; zu.OnLaunchSkill += OnLaunchSkill; zu.OnBuffAdded += (ZoneUnit unit, ZoneUnit.BuffState buff) => { EventSystem.Instance.Publish(BuffChangeEvent.Static.Clone(Id, buff, BuffChangeEvent.BuffOP.Add)); }; zu.OnBuffRemoved += (ZoneUnit unit, ZoneUnit.BuffState buff) => { EventSystem.Instance.Publish(BuffChangeEvent.Static.Clone(Id, buff, BuffChangeEvent.BuffOP.Remove)); }; zu.OnBuffChanged += (ZoneUnit unit, ZoneUnit.BuffState buff) => { EventSystem.Instance.Publish(BuffChangeEvent.Static.Clone(Id, buff, BuffChangeEvent.BuffOP.Change)); }; zu.OnRemoveBuffByOverlayLevel += (ZoneUnit unit, ZoneUnit.BuffState buff) => { }; zu.OnActionSubStatusChanged += OnActionSubStatusChanged; } public override void OnSleep() { base.OnSleep(); Vip = 0; } private static uint groupId = 1; protected static uint GroupId() { return ++ groupId; } protected virtual void OnLaunchSkill(ZoneUnit _, ZoneUnit.SkillState __, UnitLaunchSkillEvent ___) { CommonAI.ZoneClient.ZoneUnit.ISkillAction action = ZUnit.CurrentSkillAction; if(action == null) { Log.Warning("object's currentSkillAction = null, cannot launch skill"); return; } SkillTemplate skillTemplate = action.SkillData; var curActionIndex = action.CurrentActionIndex; if (skillTemplate.ActionQueue.Count <= curActionIndex) { Log.Error("Enter Skill state error> ({0})>CurrentActionIndex>{1}", skillTemplate.TemplateID, curActionIndex); return; } //Log.Debug($"OnLaunchSkill({Id}), skill({skillTemplate.TemplateID}), actionIndex:{curActionIndex}"); if (skillTemplate.IsSingleAction) { UnitActionData actdata = skillTemplate.ActionQueue[curActionIndex]; if (actdata.ActionName.IsNullOrWhitespace()) { Log.Debug($"ActionName is null @skill({skillTemplate.TemplateID}), actionIndex:{curActionIndex}"); return; } var duration = action.ActionTimeArray != null ? action.ActionTimeArray[0] : actdata.TotalTimeMS; EventSystem.Instance.Publish(PlayAnimatorEvent.Clone( Id, PlayAnimatorEvent.AniType.Skill, actdata.ActionName, duration, action.ActionSpeed, 0, actdata.IsCycAction, actdata.ActionAudioName) ); } else { float speed = 1.0f; bool isFrist = true; for (int i = curActionIndex; i < skillTemplate.ActionQueue.Count; i++) { UnitActionData item = skillTemplate.ActionQueue[i]; if (item.ActionName.IsNullOrWhitespace()) { Log.Debug($"ActionName is null @skill({skillTemplate.TemplateID}), actionIndex:{curActionIndex}"); return; } if (action.LaunchEvent != null) { speed = action.LaunchEvent.action_speed; if (action.LaunchEvent.action_speed_add != null && i < action.LaunchEvent.action_speed_add.Length) { speed += action.LaunchEvent.action_speed_add[i]; } } EventSystem.Instance.Publish(PlayAnimatorEvent.Clone( Id, PlayAnimatorEvent.AniType.Skill, item.ActionName, action.ActionTimeArray[i], speed, GroupId(), item.IsCycAction, isFrist ? item.ActionAudioName : "")); if(!item.ActionAudioName.IsNullOrWhitespace()) { if (isFrist) { isFrist = false; } else { Log.Error("not implements multiAction audio"); } } } } } private void OnHPChanged() { if (ZUnit.Info.Properties is XmdsUnitProperties prop) { //Log.Debug($"hp({ZUnit.TemplateID}) change: {ZUnit.HP}"); if (prop.GameStatusType == XmdsUnitProperties.StatusType.SpecialElite) { var hp = ZUnit.HP; var pg = hp * 100f / ZUnit.MaxHP; EventSystem.Instance.Publish(HPRefresh.Clone(HPRefresh.Index.Tower, pg, prop.ServerData.BaseInfo.name, hp.ToString())); return; } else if (prop.GameStatusType == XmdsUnitProperties.StatusType.SpecialBoss) { RefreshBossHPBar(prop); return; } if (prop.ShowHPBanner) { EventSystem.Instance.Publish(SyncUnitHpEvent.Clone(Id, ZUnit.HP * 100f / ZUnit.MaxHP)); } } } //有3个HP血条,找合适的条条显示 private static List<ZoneUnit> pgList = new(); public static void Reset() { pgList.Clear(); } private void RefreshBossHPBar(XmdsUnitProperties prop) { var hp = ZUnit.HP; int hide = -1; for(var i = 0; i < pgList.Count; i++) { var unit = pgList[i]; if(hide >= 0) { hp = unit.HP; prop = unit.Info.Properties as XmdsUnitProperties; EventSystem.Instance.Publish(HPRefresh.Clone(HPRefresh.Index.Boss1 + i - 1, hp * 100f / unit.MaxHP, prop.ServerData.BaseInfo.name, hp.ToString())); } else if(unit.TemplateID == ZUnit.TemplateID) { /*if(hp <= 0) { hide = i; EventSystem.Instance.Publish(HPRefresh.Clone(HPRefresh.Index.Boss1 + pgList.Count - 1, 0, "", "", false)); } else*/ { EventSystem.Instance.Publish(HPRefresh.Clone(HPRefresh.Index.Boss1 + i, hp * 100f / ZUnit.MaxHP, prop.ServerData.BaseInfo.name, hp.ToString())); return; } } } if(hide >= 0) { pgList.RemoveAt(hide); return; } if (pgList.Count >= 4) { Log.Error("wtf, more than 4 boss."); return; } if(hp <= 0) { return; } pgList.Add(ZUnit); EventSystem.Instance.Publish(HPRefresh.Clone(HPRefresh.Index.Boss1 + pgList.Count-1, hp * 100f / ZUnit.MaxHP, prop.ServerData.BaseInfo.name, hp.ToString())); } protected virtual void OnActionChanged(ZoneUnit unit, UnitActionStatus status, object evt) { //Log.Debug($"ActionChange({unit.Info.TemplateID}): {status}<= zobject status:{ZUnit.CurrentState}"); if(!actionChangeHandler.Notify(status, evt)) { Log.Error($"unhandle action changed: {status}"); } } protected virtual void OnActionSubStatusChanged(ZoneUnit unit, byte status, object evt) { //Log.Debug($"OnActionSubStatusChanged({unit.Info.TemplateID}): {status}<= zobject status:{ZUnit.CurrentSubState}"); } private void registerActionHandler() { actionChangeHandler.AddListener(UnitActionStatus.Idle, (_) => { EventSystem.Instance.Publish(PlayAnimatorEvent.Clone(Id, PlayAnimatorEvent.AniType.Idle)); }); var move = actionChangeHandler.AddListener(UnitActionStatus.Move, (o) => { EventSystem.Instance.Publish(PlayAnimatorEvent.Clone(Id, PlayAnimatorEvent.AniType.Run)); }); actionChangeHandler.AddListener(UnitActionStatus.Chaos, move); actionChangeHandler.AddListener(UnitActionStatus.ServerSyncMove, move); actionChangeHandler.AddListener(UnitActionStatus.Escape, move); var stun = actionChangeHandler.AddListener(UnitActionStatus.Stun, (o) => { //TODO: 判断没有FROZEN的BUFF状态,才进行stun的动作 }); actionChangeHandler.AddListener(UnitActionStatus.HitMove, stun); actionChangeHandler.AddListener(UnitActionStatus.Dead, (o) => { EventSystem.Instance.Publish(UnitDead.Clone(Id)); }); actionChangeHandler.AddListener(UnitActionStatus.Damage, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.Pick, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.Spawn, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.ChargeAtkMove, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.ChargeAtkIdle, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.DaZuo, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.DaZuoRecoveryAttr, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.ChuanGongA, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.ChuanGongB, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.BuffLockStateAction, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.HomeBack, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.ClearYaoQi, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.PetLock, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.BreakShield, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.Transport, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.Skill, (o) => { }); actionChangeHandler.AddListener(UnitActionStatus.Rebirth, (o) => { EventSystem.Instance.Publish(UnitRebirth.Clone(Id)); }); } }