using CommonAI.Zone.Instance; using CommonAI.Zone.ZoneEditor; using System; using System.Collections.Generic; using System.Linq; using System.Text; using XmdsCommon.Plugin; using CommonAI.Zone; using CommonAI.Zone.Attributes; using CommonAI.Zone.Helper; using XmdsCommonServer.Plugin.Units; using XmdsCommonServer.Plugin.Quest; using XmdsCommon.EditorData; using CommonLang; using CommonLang.Vector; using CommonAI.RTS.Manhattan; using XmdsCommon.Message; using CommonAI.Data; using CommonAI.ZoneServer.JSGModule; namespace XmdsCommonServer.Plugin.Scene { /// /// Xmds场景 /// public class XmdsServerScene : EditorScene { /// /// 遍历单位 /// /// /// 设置为True,立即停止遍历 public delegate void ObjectForEachAction(T obj, ref bool cancel) where T : class; private HashMap> mRebirthRegionMap = new HashMap>(); public XmdsServerScene(TemplateManager templates, InstanceZoneListener listener, SceneData data, GSCreateAreaData gsData, string bindGameSrvId, int spaceDiv = 11) : this(templates, listener, data, gsData, spaceDiv, DateTime.Now.Millisecond, bindGameSrvId) { } protected XmdsServerScene(TemplateManager templates, InstanceZoneListener listener, SceneData data, GSCreateAreaData gsData, int spaceDiv, int rarndomSeed, string bindGameSrvId) : base(templates, listener, data, gsData, spaceDiv, rarndomSeed) { this.OnQuestAccepted += XmdsServerScene_OnQuestAccepted; this.OnQuestDropped += XmdsServerScene_OnQuestDropped; this.OnQuestCommitted += XmdsServerScene_OnQuestCommitted; this.OnQuestStatusChanged += XmdsServerScene_OnQuestStatusChanged; this.OnPlayerReady += XmdsServerScene_OnPlayerReady; //设置山大王信息 this.mKingID = XmdsDataMgr.GetInstance().GetMapKingID(this.GetSceneID()); this.mBindGameSrvId = bindGameSrvId; } protected override void InitTerrain(SceneData data, int spaceDiv, out ZoneManhattanMap terrain_data, out AstarManhattan path_finder, out ManhattanMapAreaGenerator area_gen) { //if ((data.Properties as XmdsSceneProperties).ServerSceneData.UsespaceDiv) { spaceDiv = 11; } //else { spaceDiv = 0; } base.InitTerrain(data, spaceDiv, out terrain_data, out path_finder, out area_gen); } // private static int GetSpaceDiv(SceneData data) // { // if ((data.Properties as XmdsSceneProperties).ServerSceneData.UsespaceDiv) { return 11; } // else { return 0; } // } //--------------------------------------------------------------------------------------------------------------------- #region _任务相关_ private void XmdsServerScene_OnPlayerReady(InstancePlayer player) { XmdsInstancePlayer p = player as XmdsInstancePlayer; var list = p.GetQuests(); foreach (var q in list) { QuestScriptManager.CreateQuestScript(q.QuestID, p); } } private void XmdsServerScene_OnQuestStatusChanged(InstancePlayer player, string quest, string key, string value) { if (key == XmdsQuestData.Attribute_InitOK) { QuestScriptManager.CreateQuestScript(quest, player as XmdsInstancePlayer); } else { QuestScriptManager.QuestStatusChanged(quest, player as XmdsInstancePlayer, key, value); } } private void XmdsServerScene_OnQuestAccepted(InstancePlayer player, string quest) { //此时没有属性,CreateQuestScript放在INIT_OK //QuestScriptManager.CreateQuestScript(quest, player as XmdsInstancePlayer); } private void XmdsServerScene_OnQuestCommitted(InstancePlayer player, string quest) { QuestScriptManager.ClearQuestScript(quest, player as XmdsInstancePlayer); } private void XmdsServerScene_OnQuestDropped(InstancePlayer player, string quest) { QuestScriptManager.ClearQuestScript(quest, player as XmdsInstancePlayer); } #endregion //--------------------------------------------------------------------------------------------------------------------- #region _AOI_相关_ public override bool IsTeammates(InstanceUnit src, InstanceUnit dst) { if (src != null && dst != null) { var s_v = src.Virtual as XmdsVirtual; var d_v = dst.Virtual as XmdsVirtual; return d_v.IsTeamMember(s_v.GetPlayerUUID()); } return false; } public override bool IsVisibleAOI(InstanceZoneObject src, InstanceZoneObject dst) { if (src is XmdsInstancePlayer) { XmdsInstancePlayer player = src as XmdsInstancePlayer; if (!player.IsPlayerReady()) { return false; } String bindPlayerId = dst.GetBindPlayerId(); if(bindPlayerId != null && bindPlayerId != player.PlayerUUID) { return false; } } if (src.AoiStatus == dst.AoiStatus) { var dstUnit = dst as InstanceUnit; if (dstUnit == null) { return true; } //if(dstUnit.IsPet) //{ // InstancePet dstPet = dst as InstancePet; // if(dstPet != null && dstPet.Master != null && dstPet.Master.AoiStatus != src.AoiStatus) // { // return false; // } //} if (dstUnit.IsVisible) { return true; } if (IsTeammates(src as InstanceUnit, dstUnit)) { return (dstUnit.Virtual as XmdsVirtual).TeamMemberVisible; } return false; } //else //{ // InstancePet dstPet = dst as InstancePet; // if (dstPet != null && dstPet.Master != null && dstPet.Master == src) // { // return true; // } //} return base.IsVisibleAOI(src, dst); } #endregion #region Attack. public override bool IsAttackable(InstanceUnit src, InstanceUnit target, SkillTemplate.CastTarget expectTarget, AttackReason reason, ITemplateData weapon) { // 宠物也能被攻击 //if (target is InstancePet) //{ // return false; //} var sp = (src.Virtual as XmdsVirtual); if (sp == null) { Log.Error("IsAttackable src or src.Virtual is null"); return false; } var dp = (target.Virtual as XmdsVirtual); if (dp == null) { Log.Error("IsAttackable target or target.Virtual is null"); return false; } #region 安全区域检测. 宠物不会是目标 if (expectTarget == SkillTemplate.CastTarget.Enemy && target.IsPlayerUnit && src.IsPlayerUnit) { if (target.Virtual.IsInSafeArea() || src.Virtual.IsInSafeArea()) { return false; } } #endregion #region 中立单位检测. if (target.Force == 0) //0代表绝对中立.不能被攻击. { return false; } #endregion #region 无敌单位. if (target.IsInvincible && expectTarget == SkillTemplate.CastTarget.Enemy) { return false; } //追杀怪只能追杀目标 if (!String.IsNullOrEmpty(src.GetAttackPlayer())) { if(target.PlayerUUID == null || target.PlayerUUID != src.GetAttackPlayer()) { return false; } } if (src != target && (!src.IsPlayerUnit || !JSGModule.IsExpectValidForPet(expectTarget))) { // 宠物攻击的时候 if (src.IsPet) { // 目标是宠物或者非主人 if (target.IsPet || (target.IsPlayer && src.Virtual.GetMasterID() != target.ID)) { return false; } } // 宠物被攻击的时候 else if (target.IsPet) { // 攻击者是宠物或者非主人 //if (src.IsPet || (src.IsPlayer && target.Virtual.GetMasterID() != src.ID)) { return false; } } } //被追杀人和怪 可攻击追杀怪 if(!String.IsNullOrEmpty(target.GetAttackPlayer()) && src.PlayerUUID != target.GetAttackPlayer()) { if (src.IsPet && src.Virtual.GetMasterUnit() != null) { if (src.Virtual.GetMasterUnit().PlayerUUID != target.GetAttackPlayer()) { return false; } } else { return false; } } #endregion #region 隐形对攻击的影响. //单位隐形时,需要判断搜索方是否为其队友,如果是则无视隐形,否按照攻击逻辑判断. //if(target.IsDead) //if (target.IsVisible == false) // { // if ((reason == AttackReason.Tracing || reason == AttackReason.Look) && // expectTarget == SkillTemplate.CastTarget.Enemy) // { // bool attackAble = false; // var zv = ((target as InstanceUnit).Virtual as XmdsVirtual); // if (zv.TeamMemberVisible) // { // //不是队友看不到单位,搜索时不可见. // var uuid = ((target as InstanceUnit).Virtual as XmdsVirtual).GetPlayerUUID(); // attackAble = !((src as InstanceUnit).Virtual as XmdsVirtual).IsTeamMember(uuid); // } // return attackAble; // } // } #endregion #region 位面检测. //隐身状态下,同位面,不可见,但可以被攻击. if (reason != AttackReason.Attack && !IsVisibleAOI(src, target))//AOI相关.不在同位面. { //非攻击性质才算AOI. return false; } #endregion #region PK等级保护. if (((target.Virtual) as XmdsVirtual).IsAttackable(src.Virtual as XmdsVirtual) == false) { return false; } #endregion #region 技能目标单位类型状态检测. //攻击作用单位类型. var unit_type = XmdsSkillProperties.TargetUnitType.ALL; if (weapon is SkillTemplate && reason == AttackReason.Attack) { unit_type = ((weapon as SkillTemplate).Properties as XmdsSkillProperties).NeedTargetType; } else if (weapon is SpellTemplate && reason == AttackReason.Attack) { unit_type = ((weapon as SpellTemplate).Properties as XmdsSpellProperties).NeedTargetType; } switch (unit_type) { case XmdsSkillProperties.TargetUnitType.Monster: if (!(dp is XmdsVirtual_Monster)) { return false; } break; case XmdsSkillProperties.TargetUnitType.Player: if (!(dp is XmdsVirtual_Player)) { return false; } break; case XmdsSkillProperties.TargetUnitType.ExcpetPlayer: if ((dp is XmdsVirtual_Player)) { return false; } break; } bool onlyForDead = false; //对死人. if (src.CurrentState != null) { InstanceUnit.State s = src.CurrentState; InstanceUnit.StateSkill ss = s as InstanceUnit.StateSkill; if (ss != null) { if ((ss.SkillData.Properties as XmdsSkillProperties).TargetType == XmdsSkillProperties.XmdsSkillTargetType.AllianceDead) { //只对死亡单位有效. onlyForDead = true; } } } if (!target.IsActive) { if (onlyForDead) { /* switch(expectTarget) { case SkillTemplate.CastTarget.Alias: case SkillTemplate.CastTarget.AlliesExcludeSelf: return (src.Virtual as XmdsVirtual).IsTeamMember((target.Virtual as XmdsVirtual).GetPlayerUUID()); } */ //只要是玩家,不管敌友,都可以复活. return (target is XmdsInstancePlayer); } return false; } else { //对活人. if (onlyForDead == false) { switch (expectTarget) { case SkillTemplate.CastTarget.Enemy: //不是自己人. return !(src.Virtual as XmdsVirtual).IsAllies((target.Virtual as XmdsVirtual), expectTarget, reason); case SkillTemplate.CastTarget.PetForMaster: //if (src.Virtual is XmdsVirtual_Pet) //{ // if ((src.Virtual as XmdsVirtual_Pet).IsMaster((target.Virtual as XmdsVirtual))) // return true; //} if(src is InstancePet) { InstancePet pet = src as InstancePet; if(pet != null && pet.Master == target) { return true; } } return false; case SkillTemplate.CastTarget.EveryOne: return JudgeEveryOneAttackable(src, target, expectTarget); case SkillTemplate.CastTarget.Alias: case SkillTemplate.CastTarget.AlliesExcludeSelf: // 可能存在即使队友,又是敌人的,所以如果是敌人就不认队友了,你tmd和我为敌,我就不给你加血 if (!(src.Virtual as XmdsVirtual).IsAllies((target.Virtual as XmdsVirtual), expectTarget, reason)) return false; if (src == target) { return false; } return (src.Virtual as XmdsVirtual).IsTeamMember(target); case SkillTemplate.CastTarget.AlliesIncludeSelf: // 可能存在即使队友,又是敌人的,所以如果是敌人就不认队友了,你tmd和我为敌,我就不给你加血 if (!(src.Virtual as XmdsVirtual).IsAllies((target.Virtual as XmdsVirtual), expectTarget, reason)) return false; return (src.Virtual as XmdsVirtual).IsTeamMember(target); //return (src.Virtual as XmdsVirtual).IsTeamMember((target.Virtual as XmdsVirtual).GetPlayerUUID()); case SkillTemplate.CastTarget.EveryOneExcludeSelf: return JudgeEveryOneAttackable(src, target, expectTarget); case SkillTemplate.CastTarget.Self: return src == target; case SkillTemplate.CastTarget.EnemyAndSelf: return src == target || !(src.Virtual as XmdsVirtual).IsAllies((target.Virtual as XmdsVirtual), expectTarget, reason); case SkillTemplate.CastTarget.NA: default: return false; } } return false; } #endregion } /** 判断所有人类型可攻击模式 */ private bool JudgeEveryOneAttackable(InstanceUnit src, InstanceUnit target, SkillTemplate.CastTarget expectTarget) { //if (SkillTemplate.CastTarget.EveryOne == expectTarget) //{ // return (!target.IsInvincible); //} //else if (SkillTemplate.CastTarget.EveryOneExcludeSelf == expectTarget) //{ // return (src != target) && (!target.IsInvincible); //} if (SkillTemplate.CastTarget.EveryOneExcludeSelf == expectTarget && src == target) { return false; } switch (src.Virtual.GetCurPKMode()) { case PKMode.Peace://和平模式使用默认出生的force. if (src.Virtual.GetForceID() == target.Virtual.GetForceID()) { return src.Virtual.IsAllies(target.Virtual, true, true); } return true; case PKMode.force://阵营模式使用Camp. if (src.Virtual.GetForceID() == target.Virtual.GetForceID()) { return false; } return !src.Virtual.IsAllies(target.Virtual, true, true); case PKMode.Guild: if (src.Virtual.IsGuildMember(target.Virtual.GetGuildID())) { return false; } return !src.Virtual.IsAllies(target.Virtual, true, true); case PKMode.Team: return !src.Virtual.IsAllies(target.Virtual, true, true); case PKMode.All: return !(src == target); case PKMode.Justice: if (target.Virtual.GetCurPKLevel() == PKLevel.White) { return false; } return !src.Virtual.IsAllies(target.Virtual, true, true); ; case PKMode.Server: if (src.Virtual.IsServerMember(target.Virtual.GetServerID())) { return false; } return !src.Virtual.IsAllies(target.Virtual, true, true); ; } return false; } #endregion #region Region相关. protected override void InitEditRegion(RegionData rdata) { base.InitEditRegion(rdata); //单位复活点. ZoneRegion flag = getFlag(rdata.Name) as ZoneRegion; if (flag != null && rdata.Abilities != null) { List temp = null; foreach (AbilityData td in rdata.Abilities) { if (td is XmdsRebirthAbility) { XmdsRebirthAbility zra = td as XmdsRebirthAbility; if (mRebirthRegionMap.TryGetValue(zra.START_Force, out temp)) { temp.Add(flag); } else { temp = new List(); temp.Add(flag); mRebirthRegionMap.Add(zra.START_Force, temp); } } } } } /// /// 遍历所有复活点 /// /// /// public void ForEachRebirthRegion(int force, Action action) { List temp = null; if (mRebirthRegionMap.TryGetValue(force, out temp)) { for (int i = temp.Count - 1; i >= 0; --i) { var rg = temp[i]; action(rg); } } } /// /// 获得最近的复活点 /// /// /// /// /// public ZoneRegion GetNearestRebirthRegion(float x, float y, int regionForce) { using (var list = ListObjectPool.AllocAutoRelease()) { ZoneRegion ret = null; float min_value = float.MaxValue; float len; this.ForEachRebirthRegion(regionForce, (rg) => { if (rg.Enable) { len = MathVector.getDistanceSquare(x, y, rg.X, rg.Y); if (len < min_value) { min_value = len; ret = rg; } } }); return ret; } } /// /// 获得该地图随机的复活点 /// /// /// public ZoneRegion GetRandomRebirthRegion(int regionForce) { using (var list = ListObjectPool.AllocAutoRelease()) { ZoneRegion ret = null; List temp = null; mRebirthRegionMap.TryGetValue(regionForce, out temp); //不知道阵营的情况下,用这个逻辑 if(temp == null) { mRebirthRegionMap.TryGetValue(-1, out temp); } if (temp != null) { int num = RandomN.Next(0, temp.Count); if (num > temp.Count) { num = temp.Count - 1; } return temp[num]; } return ret; } } /// /// 获得场景下对应阵营的出生点. /// /// /// public List GetRebirthRegions(byte startForce) { List ret = null; if (mRebirthRegionMap != null) { mRebirthRegionMap.TryGetValue(startForce, out ret); } return ret; } #endregion #region Events internal void callback_OnCombatStateChange(InstanceUnit unit, BattleStatus status) { if (mOnCombatStateChange != null) { mOnCombatStateChange.Invoke(unit, status); } } public delegate void CombatStateChangeHandler(InstanceUnit unit, BattleStatus status); [EventTriggerDescAttribute("单位战斗状态改变")] public event CombatStateChangeHandler OnCombatStateChange { add { mOnCombatStateChange += value; } remove { mOnCombatStateChange -= value; } } private CombatStateChangeHandler mOnCombatStateChange; protected override void ClearEvents() { mOnCombatStateChange = null; base.ClearEvents(); } #endregion } }