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
}
}