using CommonLang.Log; using CommonAI.Zone; using CommonAI.Zone.Instance; using System; using System.Collections.Generic; using System.Web.Helpers; using XmdsServerNode.Node; using XmdsCommon.Message; using XmdsCommon.Plugin; using XmdsCommonServer.Plugin; using XmdsCommonServer.Plugin.Units; using CommonAI.Zone.ZoneEditor; using XmdsCommon.EditorData; using CommonLang.Vector; using CommonLang; using static CommonAI.XmdsConstConfig; using CommonAI.Data; namespace XmdsServerEdgeJS.Zone { public class XmdsZoneNode { private readonly Logger log; private readonly ZoneService service; private readonly string instanceID; private readonly ServerZoneNode node; //连斩生效时间 private long continueKillsValidTime = 0; public string InstanceID { get { return instanceID; } } public ServerZoneNode Node { get { return node; } } public void SendToGameServer(string name, Object param) { node.SendToGameServer(name, param); } public string GetBindGameSrvId() { return node.GetBindGameSrvId(); } internal XmdsZoneNode(ZoneService svc, string instanceId, string gameServerId) { this.log = LoggerFactory.GetLogger(string.Format("XmdsZoneNode-{0}", instanceId)); this.service = svc; this.instanceID = instanceId; this.node = new ServerZoneNode(gameServerId); } internal void Start(int mapTemplateId, string data, Action started) { dynamic config = Json.Decode(data); this.node.OnZoneStart += (z) => { started(this); }; string monsterHard = (string)config.monsterHard; byte sceneType = (byte)config.sceneType; byte areaType = (byte)config.areaType; int averageLevel = Convert.ToInt32(config.averageLevel); double propRatio = 0; double floorRatio = 0; if (averageLevel > 0) { propRatio = Convert.ToDouble(config.propRatio); floorRatio = Convert.ToDouble(config.floorRatio); } bool canRiding = true; bool isteam = config.isTeam == null ? false : (bool)config.isTeam; if (config.canRiding != null) { canRiding = config.canRiding; } int killInterval = (config.killInterval != null) ? (int)(config.killInterval) : 0; int killFullNum = (config.killFullNum != null) ? (int)(config.killFullNum) : 0; int killFullCollSec = (config.killFullCollSec != null) ? (int)(config.killFullCollSec) : 0; GSCreateAreaData gsData = new GSCreateAreaData(); gsData.value1 = (config.value1 != null) ? ((int)(config.value1)) : 0; gsData.value2 = (config.value2 != null) ? ((int)(config.value2)) : 0; this.node.Start(instanceID, mapTemplateId, config.monsterHard, (byte)config.allowAutoGuard, config.calPKValue, averageLevel, floorRatio, propRatio, killInterval, killFullNum, killFullNum, config.usespaceDiv, (CommonAI.Data.SceneType)sceneType, gsData, (AreaType)areaType, isteam, canRiding); //this.node.Zone.OnUnitDead += zone_onUnitDead; //this.node.Zone.OnGameOver += zone_onGameOver; this.node.Zone.OnUnitGotInstanceItem += zone_onUnitGotInstanceItem; this.node.Zone.OnUnitPickUnit += zone_onUnitPickUnit; this.node.Zone.OnSendMessageToGS += zone_onSendMessageToGS; this.node.Zone.OnTryPickItem += zone_onTryPickItem; } internal void Stop(Action stopped) { if (node.IsDisposed) { stopped(this); } else { node.OnZoneStop += (z) => { stopped(this); }; node.Stop(); } if(this.node != null && this.node.Zone != null) { //this.node.Zone.OnUnitDead -= zone_onUnitDead; //this.node.Zone.OnGameOver -= zone_onGameOver; this.node.Zone.OnUnitGotInstanceItem -= zone_onUnitGotInstanceItem; this.node.Zone.OnUnitPickUnit -= zone_onUnitPickUnit; this.node.Zone.OnSendMessageToGS -= zone_onSendMessageToGS; this.node.Zone.OnTryPickItem -= zone_onTryPickItem; } } //------------------------------------------------------------------------------------------------------ private HashMap _BornPlace = null; private HashMap _BornPlaceExt = null; public TVector2 r2b_get_getBornPlace(int areaId, string pointId) { lock (this) { if (_BornPlace == null) { _BornPlace = new HashMap(); _BornPlaceExt = new HashMap(); List Decorations = this.Node.SceneData.Decorations; foreach (DecorationData decoration in Decorations) { foreach (AbilityData ability in decoration.Abilities) { XmdsSceneTransportAbilityData sceneAbility = ability as XmdsSceneTransportAbilityData; if (sceneAbility != null) { if (!string.IsNullOrEmpty(sceneAbility.NextScenePosition)) { string[] pos = sceneAbility.NextScenePosition.Split(new Char[] { ',' }); TVector2 posInfo = new TVector2((float)Convert.ToSingle(pos[0]), (float)Convert.ToSingle(pos[1])); _BornPlace.Put(sceneAbility.NextSceneID, posInfo); _BornPlaceExt.Put(decoration.Name, posInfo); } } } } } TVector2 ret; if (pointId != null && _BornPlaceExt.TryGetValue(pointId, out ret)) { return ret; } else if (_BornPlace.TryGetValue(areaId, out ret)) { return ret; } return new TVector2(0, 0); } } //------------------------------------------------------------------------------------------------------ #region _场景内事件_ private bool zone_onTryPickItem(InstanceZone zone, InstanceUnit unit, InstanceItem item) { XmdsInstancePlayer player = unit as XmdsInstancePlayer; XmdsItemProperties prop = item.Info.Properties as XmdsItemProperties; if (player != null && prop != null && prop.IsTaskItem) { List quests = player.GetQuests(); for (int i = 0; i < quests.Count; i++) { var q = quests[i]; var t = XmdsQuestData.GetTaskType(q); var targetId = XmdsQuestData.GetTargetID(q); var is_complete = XmdsQuestData.IsTargetComplete(q); if (!is_complete && t == (int)XmdsQuestData.TaskType.InterActiveItem && targetId == item.Info.TemplateID) { return true; } } return false; } else { return true; } } private void zone_onSendMessageToGS(InstanceZone zone, CommonAI.ZoneServer.SendMessageB2R e) { var eventParam = new { instanceId = zone.UUID, eventName = "message", msg = e.Message }; node.SendToGameServer(EventType.areaEvent.ToString(), eventParam); } private void zone_onUnitPickUnit(InstanceZone zone, InstanceUnit obj, InstanceUnit pickable) { if (obj is InstancePlayer) { string uuid = (obj as InstancePlayer).PlayerUUID; var eventParam = new { eventName = "interActiveItem", playerId = uuid, itemId = pickable.Info.TemplateID, x = obj.X, y = obj.Y }; node.SendToGameServer(EventType.playerEvent.ToString(), eventParam); } } private void zone_onUnitGotInstanceItem(InstanceZone zone, InstanceUnit unit, InstanceItem item) { InstancePlayer player = (unit as InstancePlayer); string uuid = player.PlayerUUID; XmdsDropableInstanceItem it = item as XmdsDropableInstanceItem; XmdsItemProperties prop = it.Info.Properties as XmdsItemProperties; XmdsCommon.Message.DropItem dropitem = it.GenSyncInfo(false).ExtData as XmdsCommon.Message.DropItem; if (dropitem != null) { var eventParam = new { eventName = "pickItem", instanceId = zone.UUID, playerId = uuid, itemId = dropitem.ObjID, isGuard = player.IsGuard, objectId = item.Info.ID, //type = prop.ItemType, //templateID = it.Info.TemplateID }; node.SendToGameServer(EventType.areaEvent.ToString(), eventParam); //u.queueEvent(new UnitGotInstanceItemEvent(u.ID, this.ID)); } else { dynamic eventParam = new { eventName = "interActiveItem", playerId = uuid, itemId = item.Info.TemplateID, objId = item.ID, type = prop.ItemType, isRemove = item.IsPickAll(), x = item.X, y = item.Y }; node.SendToGameServer(EventType.playerEvent.ToString(), eventParam); } } /// /// 单位死亡事件 /// /// /// /// private void zone_onUnitDead(InstanceZone zone, InstanceUnit obj, InstanceUnit attacker) { //玩家死亡为1,怪物死亡为0 int type = 0; //玩家id string playerId = null; long pkTime = 0; int pkValue = 0; if (obj is XmdsInstancePlayer) { type = 1;//玩家. playerId = (obj as InstancePlayer).PlayerUUID; XmdsVirtual_Player virPlayer = obj.Virtual as XmdsVirtual_Player; pkTime = virPlayer.getPkTime(); pkValue = virPlayer.getPkValue(); } else if (obj is XmdsInstancePet && !(obj is XmdsInstanceSummonUnit)) { type = 2;//宠物. var pet = obj as XmdsInstancePet; if (pet.Master != null && pet.Master is InstancePlayer) { playerId = (pet.Master as InstancePlayer).PlayerUUID; } } int attackType = 0; //如果最后一击是宠物,则找主人 if (attacker is InstancePet) { attacker = (attacker as InstancePet).Master; attackType = 1; } else if (attacker is InstanceSummon) { attacker = (attacker as InstanceSummon).SummonerUnit; } else if (attacker is XmdsInstanceSummonUnit) { attacker = (attacker as XmdsInstanceSummonUnit).SummonerUnit; } InstancePlayer hitFinal = attacker as InstancePlayer; //击中列表 List playerIds = new List(2); //玩家被杀,改玩家添加到列表 if (type == 1) { playerIds.Add(playerId); } if (hitFinal != null) { playerIds.Add(hitFinal.PlayerUUID); } #region 怪物ID特殊逻辑. //怪物生成时会随机出更高级的怪物,能力ID都会变更,但模板ID却一样。游戏服取MonsterID查找掉落和经验.Edit by Alex.Yu. int tpID = obj.Info.TemplateID; //击杀助攻列表. List atkAssistantList = null; if (type == 0 && obj is XmdsInstanceMonster) { tpID = (obj as XmdsInstanceMonster).MonsterID; if (tpID <= 0) { tpID = obj.Info.TemplateID; log.Info("zone_onUnitDead单位id异常:" + obj.Info.TemplateID + ", " + obj.Info.Name + ", obj: " + obj + ", " + zone.GetSceneID()); } atkAssistantList = (obj.Virtual as XmdsVirtual).mHateSystem.GetAtkAssistantList(); } else if (type == 1) { atkAssistantList = (obj.Virtual as XmdsVirtual).mHateSystem.GetAtkAssistantList(); } // log.Warn("单位死亡事件====unitTemplateId=" + tpID + ", type=" + type + ", 死亡了..."); // if (type != 2 && playerIds.Count == 0 && (atkAssistantList == null || atkAssistantList.Count == 0)) // { // return; // } #endregion //log.Info("monster dead objId:" + obj.ID + " templateId:" + tpID + " type " + type); int aID = 0; int aQColor = 0; int aLevel = 0; string aName = ""; string sceneType = ""; if (attacker != null) { if (attacker is XmdsInstanceMonster) { MonsterVisibleDataB2C mvd = attacker.GenSyncUnitInfo().VisibleInfo as MonsterVisibleDataB2C; sceneType = (attacker.Virtual as XmdsVirtual).GetCurSceneType(); aID = attacker.Info.TemplateID; aQColor = (int)mvd.Qcolor; aName = mvd.DisplayName; aLevel = attacker.GenSyncUnitInfo().Level; } else if (attacker.IsPlayerUnit && obj.IsMonster) { InstanceUnit attackerUnit = attacker.IsPet ? attacker.Virtual.GetMasterUnit() : attacker; if (attackerUnit != null) { attackerUnit.Virtual.DispatchKillOtherEvent(attackerUnit.Virtual, obj.Virtual); } else { log.Warn("zone_onUnitDead: 找不到人形攻击者:" + attacker.Info.ID + ", " + zone.GetSceneID()); } } } //连斩数计算 if (zone is EditorScene) { EditorScene scene = zone as EditorScene; if (scene != null && scene.Data.killInterval > 0 && attacker != null) { long curTime = CommonLang.CUtils.localTimeMS; if (continueKillsValidTime < curTime && attacker.Statistic != null && curTime - attacker.Statistic.preKillTime < scene.Data.killInterval) { attacker.updateContinueKills(); //如果连斩有上限,并且达到上限后有一定冷却时间 if (scene.Data.killMax > 0 && scene.Data.killMaxCoolTime > 0 && attacker.Statistic.continueKills >= scene.Data.killMax) { attacker.Statistic.continueKills = 0; this.continueKillsValidTime = curTime + scene.Data.killMaxCoolTime * 1000; } } else { attacker.resetContinueKills(); } attacker.Statistic.preKillTime = curTime; } } XmdsVirtual vir = (obj.Virtual as XmdsVirtual); XmdsHateSystem zhs = vir.GetHateSystem() as XmdsHateSystem; InstancePlayer belongPlayer = zhs.GetHeirs() as InstancePlayer; //Console.Write("attacker objId:" + aID + " aQColor:" + aQColor + " aName " + aName + " aLevel " + aLevel); var eventParam = new { eventName = "unitDead", playerIds = playerIds, areaId = zone.TerrainSrc.TemplateID, instanceId = zone.UUID, hitFinal = (hitFinal == null) ? null : hitFinal.PlayerUUID, belongPlayerId = (belongPlayer == null) ? null : belongPlayer.PlayerUUID, unitType = type, unitPlayerId = playerId, unitTemplateId = tpID, unitLevel = obj.Level, objId = obj.ID, posX = obj.get_x(), posY = obj.get_y(), attackerTemplateId = aID, attackerQColor = aQColor, attackerName = aName, attackerLevel = aLevel, attackerSceneType = sceneType, attackType = attackType, atkAssistantList = atkAssistantList, awardPlayer = zhs.GetSharedList(), refreshPoint = obj.GetAttribute("RefreshMonsterTag"), pkTime = pkTime, pkValue = pkValue, continuekills = attacker == null ? 0 : attacker.Statistic.continueKills, gsFlag = obj.gameServerFlag }; if (obj.IsPlayer) { log.Info("玩家死亡:" + (obj == null ? "null" : obj.PlayerUUID) + ", 攻击者:" + (attacker == null ? "null" : (attacker.PlayerUUID + ", " + attacker.Info.ID)) + ", Scene:" + zone.GetSceneID()); } node.SendToGameServer(EventType.areaEvent.ToString(), eventParam); } #endregion } }