using CommonAI.Zone; using CommonAI.ZoneClient; using CommonLang.Geometry; using ET.Client; using ET.EventType; using Sirenix.Utilities; using System; using System.IO; using XmdsCommon.Message; namespace ET { [FriendOf(typeof(UnitMgr))] public partial class BattleMgr : Singleton, ISingletonAwake, ISingletonUpdate, ILayerClient { public ZoneLayer Layer; private readonly MemoryStream writeBuffer = new MemoryStream(2048); private EventDispatcher zoneEventHandler; private EventDispatcher objectEventHandler; private static CommonLang.Geometry.Vector3 vecTemp = new(); public void Awake() { zoneEventHandler = new(); objectEventHandler = new(); registerEventHandler(); Layer = TemplateManager.Factory.CreateClientZoneLayer(BattleResourceMgr.Instance.GameEditorTemplates, this); Layer.ActorSyncMode = SyncMode.ForceByServer; Layer.LayerInit += LayerEvent_Init; Layer.ObjectEnter += LayerEvent_ObjectEnter; Layer.ObjectLeave += LayerEvent_ObjectLeave; Layer.MessageReceived += LayerEvent_MessageReceived; Layer.DecorationChanged += LayerEvent_DecorationChanged; } public void Update(int timeMS) { //TODO: Send ping Layer.BeginUpdate(timeMS); Layer.Update(); this.doUpdate(); } //ILayerClient接口实现,供layer层调用 //layer层在收到LockActorEvent消息后调用 void ILayerClient.BattleReady(bool bok) { Log.Debug($"battle ready......{bok}"); //TODO: 等GameObjectPool.cache完场景资源后,再play bgm var scnData = Layer.Data; if(!scnData.BGM.IsNullOrWhitespace() ) { EventSystem.Instance.Publish(PlayBgm.Static.Clone(true, scnData.BGM)); } } //ILayerClient接口实现,供layer层调用 //layer层中需要发送消息到战斗服 public void SendAction(CommonAI.Zone.Action action) { if(PlayerComponent.Instance == null) { Log.Error("playerComponent is null"); return; } Log.Debug($">>>Send BattleMsg: {action.GetType()}"); writeBuffer.Position = 0; if (BattleResourceMgr.Instance.BattleMsgDecoder.doEncode(writeBuffer, action)) { PlayerComponent.Instance.ClientScene().GetComponent().Session.Send(new BattleEventPushToServer() { data = writeBuffer.ToArray() }); } } //客户端自己模拟创建消息,发送到zonelayer层处理 public void PostMsg2Layer(CommonLang.Protocol.IMessage msg) { Layer.ProcessMessage(msg); } //layer层在处理好战斗服推送的ClientEnterScene消息后回调 protected void LayerEvent_Init(CommonAI.ZoneClient.ZoneLayer layer) { Log.Debug($"OnLayerInit- scene template ID:{layer.Data.ID}"); } //单位进入战斗 protected void LayerEvent_ObjectEnter(ZoneLayer layer, ZoneObject obj) { //Log.Debug($"OnObjectEnter: {obj}@{obj.ObjectID}"); var unit = BattleUnitFactory.Instance.Create(obj); if(unit != null ) { UnitMgr.Instance.PutUnit(obj.ObjectID, unit); if (unit is BattleActor) { UnitMgr.Instance.Actor = unit as BattleActor; } unit.OnAwake(obj); } else { Log.Error($"unknow object enter:{obj.Name} ID:{obj.ObjectID}"); } } //单位离开战斗 protected void LayerEvent_ObjectLeave(ZoneLayer layer, ZoneObject obj) { //Log.Debug($"OnObjectLeave: {obj.ObjectID}"); var unit = UnitMgr.Instance.GetUnit(obj.ObjectID); if(unit == null) { Log.Error($"LayerEvent_ObjectLeave not exist:{obj.Name}:{obj.ObjectID}"); return; } unit.OnSleep(); UnitMgr.Instance.RemoveUnit(obj.ObjectID); } protected void LayerEvent_DecorationChanged(CommonAI.ZoneClient.ZoneLayer layer, CommonAI.ZoneClient.ZoneEditorDecoration ed) { Log.Error("Layer_DecorationChanged"); /*DataMgr.Instance.RegionManager.OnDecorationChanged(ed); if (mDecoMgr != null) { mDecoMgr.OnStateChange(ed); }*/ } protected void LayerEvent_MessageReceived(CommonAI.ZoneClient.ZoneLayer layer, CommonLang.Protocol.IMessage msg) { if (msg is ZoneEvent) { zoneEventHandler.Notify(msg as ZoneEvent); } else if(msg is ObjectEvent) { objectEventHandler.Notify(msg as ObjectEvent); } } private void registerEventHandler() { //actor=================== objectEventHandler.AddListener((ev) => { var isAutoFight = (ev as SetAutoBattleB2C).isAutoBattle != 0; Log.Debug($"AutoFight: {isAutoFight}"); (UnitMgr.Instance.Actor.ZUnit as ZoneActor).IsGuard = isAutoFight; }); objectEventHandler.AddListener((ev) => { var e = ev as PlayerFocuseTargetEvent; if(e.ObjectID == UnitMgr.Instance.ActorId) { var target = UnitMgr.Instance.GetUnit(e.targetUnitID); if (target != null) { Log.Debug($"we have target: {target.Id}"); } } }); objectEventHandler.AddListener((ev) => { }); objectEventHandler.AddListener((ev) => { }); objectEventHandler.AddListener((ev) => { }); objectEventHandler.AddListener((ev) => { var e = ev as UnitHitEvent; var unit = UnitMgr.Instance.GetUnit(e.ObjectID); if(unit == null) { Log.Warning($"Ignore unit({e.ObjectID}) on hit, not exist?"); return; } if (e.dmgSrc == CommonAI.Data.DamageSource.RemedyPoison) { //伤害来源于叠毒BUFF e.client_state = (byte)UnitHitEventState.PoisonBuff; } //TODO: 显示伤害飘字 LaunchEffect hitEffect = e.effect; if (hitEffect != null) { float roation = 0f; if (hitEffect.IsSyncSenderRotation) { //设置特效的rotation为施法者与受击连线方向的rotation var sender = UnitMgr.Instance.GetUnit(e.senderId); if (sender != null) { Vector3 difpos = new Vector3(unit.ZoneObject.X, unit.ZoneObject.Y, 0) - new Vector3(sender.ZoneObject.X, sender.ZoneObject.Y, 0); roation = (float)-Math.Atan2(-difpos.Y, difpos.X); } } if (hitEffect.BindBody) { vecTemp.Set(0, 0, 0); } else { vecTemp.Set(unit.ZoneObject.X, unit.ZoneObject.Y, unit.ZoneObject.Z); } EventSystem.Instance.Publish(PlayEffectEvent.Static.Clone(hitEffect, e.ObjectID, vecTemp, 0, roation)); } }); objectEventHandler.AddListener((ev) => { //TODO:替代virtual层 var e = ev as PlayerPKModeChangeEventB2C; Log.Debug($"PKMode: {e.CurMode}"); }); objectEventHandler.AddListener((ev) => { }); objectEventHandler.AddListener((ev) => { }); objectEventHandler.AddListener((ev) => { }); objectEventHandler.AddListener((ev) => { var e = ev as UnitEffectEvent; vecTemp.Set(0,0,0); var unit = UnitMgr.Instance.GetUnit(e.object_id); if (unit != null && !e.effect.BindBody) { vecTemp.Set(unit.ZoneObject.X, unit.ZoneObject.Y, unit.ZoneObject.Z); } EventSystem.Instance.Publish(PlayEffectEvent.Static.Clone(e.effect, e.ObjectID, vecTemp)); }); objectEventHandler.AddListener((ev) => { var prop = (ev as XmdsUnitPropEventB2C).Props; Log.Debug($"UnitPropChange: {ev.ObjectID}"); }); //NPCCureEventB2C //MonsterSufferDamageInfoB2C //BattleHintNumberB2C //BattleFloatTipsEventB2C //BubbleTipsEventB2C //怪物归属权 //MonsterHeirInfoChangeEventB2C zoneEventHandler.AddListener((ev) => { var e = ev as AddEffectEvent; if(e.hostId == 0 || UnitMgr.Instance.HasUnit(e.hostId)) { vecTemp.Set(e.x, e.y, 0); EventSystem.Instance.Publish(PlayEffectEvent.Static.Clone(e.effect, e.hostId, vecTemp)); } }); /*BubbleTalkEvent AddEffectEvent SyncEnvironmentVarEvent ScriptCommandEvent ScriptAddUnitEventsB2C ScriptRemoveUnitEventsB2C PlaySoundEventB2CForAll SyncFlagsEvent ChangeBGMEvent PlayDestoryEffect*/ /*var e = msg as CommonAI.Zone.Event; if (e is ChatEvent) { var evt = (e as ChatEvent); var message = evt.Message; var evt_param = message.Split('|'); if (evt_param.Length >= 2 && evt_param[0] == "Notice.Msg") { var dic = GameUtil.GetDBData("NoticeMsg", int.Parse(evt_param[1])); if (dic != null) { string result = ""; if (evt_param.Length >= 3 && evt_param[2] != null) { //根据参数个数 依次填值 string[] par = evt_param[2].Split('.'); if (par != null && par.Length > 0) { switch (par.Length) { case 1: { result = Average(dic["MsgContent"] as string, par[0]); break; } case 2: { result = Average(dic["MsgContent"] as string, par[0], par[1]); break; } case 3: { result = Average(dic["MsgContent"] as string, par[0], par[1], par[2]); break; } case 4: { result = Average(dic["MsgContent"] as string, par[0], par[1], par[2], par[3]); break; } case 5: { result = Average(dic["MsgContent"] as string, par[0], par[1], par[2], par[3], par[4]); break; } } } } else { //没有参数 result = (dic["MsgContent"] as string); } // EventManager.Fire("Event.OnEventHandler.star", new Dictionary() { {"content", result}, {"keepTime", "" + (evt.KeepTimeMS/1000)}, {"content_is_text", "true"} }); } else { YXJDebug.logError("config not exist >" + msg); } } else if (evt_param.Length == 2) { string funcName = "GlobalHooks." + evt_param[0]; object[] param = evt_param[1].Split(','); //Client.GetMainState().GetFunction(funcName).LazyCall(param); if (param.Length == 0) Client.GetMainState().Call(funcName, Client.LogMiss); else if (param.Length == 1) Client.GetMainState().Call(funcName, param[0], Client.LogMiss); else if (param.Length == 2) Client.GetMainState().Call(funcName, param[0], param[1], Client.LogMiss); else if (param.Length == 3) Client.GetMainState().Call(funcName, param[0], param[1], param[2], Client.LogMiss); else if (param.Length == 4) Client.GetMainState().Call(funcName, param[0], param[1], param[2], param[3], Client.LogMiss); else if (param.Length == 5) Client.GetMainState().Call(funcName, param[0], param[1], param[2], param[3], param[4], Client.LogMiss); else { YXJDebug.logError("BattleClientBase.OnEventHandler Error!funcName is {0}", funcName); } } else { //位面进入退出效果 if (msg == "EnterAOI") { var wwe = Camera.main.GetComponent(); if (wwe != null) { wwe.SetParam(40, -30, 3, 2); wwe.play(); } //GameAlertManager.Instance.setAutoAnimiVisible(false); InAOI = true; } else if (msg == "LeaveAOI") { var wwe = Camera.main.GetComponent(); if (wwe != null) { wwe.SetParam(40, -30, 3, 2); wwe.play(); } InAOI = false; } else { //普通chatevent EventManager.Fire("Event.OnEventHandler.star", new Dictionary() { {"content", msg}, {"isImportant", "1"}, {"keepTime", "" + (evt.KeepTimeMS/1000)} }); } } } else if (e is CommonAI.Zone.ZoneEvent) { if (e is BubbleTalkEvent) { BubbleTalkEvent evt = e as BubbleTalkEvent; if (evt.TalkInfos != null) { foreach (var info in evt.TalkInfos) { System.Action callback = delegate () { if (info.TalkUnit == 0) { YXJDebug.logError("旁白气泡还没有实现>{0}", info.TalkContent); return; } ComAIUnit unit = GetUnitById(info.TalkUnit) as ComAIUnit; if (unit == null) { if (info.TalkContent != "bubblechat") { YXJDebug.logDebug(">BubbleTalkEvent unit not exist: {0}>>{1}", info.TalkUnit, info.TalkContent); } return; } if (info.TalkContent == "bubblechat") { UIBridgeManager.Instance.QuestUIBridge.BubbleTalkEventSend(unit); } else { var txt = ConfigMgr.Instance.TxtCfg.GetTextByKey("GameEditor_" + info.TalkContent); unit.AddBubbleChat(txt, info.TalkKeepTimeMS / 1000); } if (!string.IsNullOrEmpty(info.TalkActionType)) { unit.PlayAnimationWhileIdle(info.TalkActionType); } }; if (info.TalkDelayTimeMS > 0) { GameGlobal.Instance.StartCoroutine(WaitForSeconds(info.TalkDelayTimeMS / 1000, callback)); } else { callback.Invoke(); } } } } else if (e is AddEffectEvent && battleManager != null) { AddEffectEvent evt = e as AddEffectEvent; if (evt.hostId == 0 || GetUnitById(evt.hostId) != null) { Vector3 pos = battleManager.GetU3DPosByUnitCell(evt.x, evt.y); pos = ComAICell.AdjustHeight(pos); Quaternion rotation = Quaternion.Euler(0, evt.direction * Mathf.Rad2Deg + 90, 0); EffectPlayer.SetRotationOnetime(rotation); //--->这个功能加个参数不就好了 →_→ EffectPlayer.Play(evt.effect, pos, false); } } else if (e is AddEffectEvent2 && battleManager != null) { AddEffectEvent2 evt = e as AddEffectEvent2; if (evt.hostId == 0 || GetUnitById(evt.hostId) != null) { Vector3 pos = battleManager.GetU3DPosByUnitCell(evt.x, evt.y); pos = ComAICell.AdjustHeight(pos); Vector3 targetPos = battleManager.GetU3DPosByUnitCell(evt.TargetX, evt.TargetY); EffectPlayer.PlayLocal(evt.effect, pos, false, 0, 0, 0, 0, evt.ET, targetPos, evt.FollowActor); } } else if (e is SyncEnvironmentVarEvent) { SyncEnvironmentVarEvent evt = e as SyncEnvironmentVarEvent; UIBridgeManager.Instance.BattleUIBridge.EnvironmentVarChange(evt.Key, evt.Value); } else if (e is ScriptCommandEvent) { ScriptCommandEvent evt = e as ScriptCommandEvent; string[] evt_param = evt.message.Split('|'); if (evt_param.Length == 2) { object[] param = evt_param[1].Split(','); string funcName = "GlobalHooks." + evt_param[0]; if (param.Length == 0) Client.GetMainState().Call(funcName, Client.LogMiss); else if (param.Length == 1) Client.GetMainState().Call(funcName, param[0], Client.LogMiss); else if (param.Length == 2) Client.GetMainState().Call(funcName, param[0], param[1], Client.LogMiss); else if (param.Length == 3) Client.GetMainState().Call(funcName, param[0], param[1], param[2], Client.LogMiss); else if (param.Length == 4) Client.GetMainState().Call(funcName, param[0], param[1], param[2], param[3], Client.LogMiss); else if (param.Length == 5) Client.GetMainState().Call(funcName, param[0], param[1], param[2], param[3], param[4], Client.LogMiss); else { YXJDebug.logError("BattleClientBase.OnEventHandler Error!funcName is {0}", funcName); } } } else if (e is LockActorEvent) { LockActorEvent evt = e as LockActorEvent; OnLockActorEvent(evt); } else if (e is ScriptAddUnitEventsB2C) { ScriptAddUnitEventsB2C evt = e as ScriptAddUnitEventsB2C; OnScriptAddUnitEvent(evt); } else if (e is ScriptRemoveUnitEventsB2C) { ScriptRemoveUnitEventsB2C evt = e as ScriptRemoveUnitEventsB2C; OnScriptRemoveUnitEvents(evt); } else if (e is PlaySoundEventB2CForAll) { PlaySoundEventB2CForAll evt = e as PlaySoundEventB2CForAll; XmdsSoundManager.GetXmdsInstance().PlaySound(evt.SoundName); } else if (e is SyncFlagsEvent && mDecoMgr != null) { mDecoMgr.LoadDecos(); } else if (e is ChangeBGMEvent) { XmdsSoundManager.GetXmdsInstance().ChangeBGM((e as ChangeBGMEvent).FileName); } else if (e is PlayDestoryEffect) { if (EffectPlayer == null) return; PlayDestoryEffect destoryEffect = e as PlayDestoryEffect; Vector3 vec = new Vector3(destoryEffect.X, destoryEffect.Y, destoryEffect.Z); Quaternion rotation = Quaternion.Euler(0, destoryEffect.Direction * Mathf.Rad2Deg + 90, 0); LaunchEffect effect = new LaunchEffect(); effect.Name = destoryEffect.EffectName; EffectPlayer.SetRotationOnetime(rotation); EffectPlayer.Play(effect, vec, true); } else { //YXJDebug.logInfo("OnEventHandler not implemented! {0}", e.ToString()); } }*/ } } }