using CommonAI.Zone;
using CommonAI.Zone.Helper;
using CommonAI.Zone.Instance;
using CommonAI.Zone.Formula;
using CommonLang;
using CommonLang.Log;
using System.Collections.Generic;
using XmdsCommon.Message;
using XmdsCommon.Plugin;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.Skills;
using CommonAI.Zone.ZoneEditor;
using System.Diagnostics;
using XmdsCommonServer.Plugin.Units;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.DamageCalculator;
using XmdsCommonServer.XLS.Data;
using System;
using XmdsCommonServer.Plugin.Scene;
using CommonLang.Vector;
using CommonLang.Concurrent;
using CommonAI.Data;
using static CommonAI.Zone.Instance.InstanceUnit;
using CommonAI.data;
using XmdsCommonServer.Plugin.Base;
using XmdsCommonSkill.Plugin.CardSkill;
using CommonAI.ZoneServer.JSGModule;
using XmdsCommonServer.Plugin.JSGXmdsModule;
namespace XmdsCommonServer.Plugin
{
///
/// FileName: XmdsVirtualUnit.cs
///
public partial class XmdsVirtual : XmdsCommon.Plugin.VirtualUnitBase
{
private static AtomicInteger s_alloc_object_count = new AtomicInteger(0);
///
/// 分配实例数量
///
public static int AllocCount { get { return s_alloc_object_count.Value; } }
#region Log.
public static Logger log = LoggerFactory.GetLogger("XVirtual");
public static void FormatLog(string txt, params object[] args)
{
//if (args != null) { log.Debug(string.Format(txt, args)); }
//else { log.Debug(txt); }
}
public static void FormatLog(uint level, string txt, params object[] args)
{
if (args != null)
{
switch (level)
{
case LoggerLevel.ERROR:
log.Error(string.Format(txt, args));
break;
case LoggerLevel.WARNNING:
log.Warn(string.Format(txt, args));
break;
case LoggerLevel.INFO:
log.Info(string.Format(txt, args));
break;
default:
//log.Debug(string.Format(txt, args));
break;
}
}
else
{
switch (level)
{
case LoggerLevel.ERROR:
log.Error(txt);
break;
case LoggerLevel.WARNNING:
log.Warn(txt);
break;
case LoggerLevel.INFO:
log.Info(txt);
break;
default:
//log.Debug(txt);
break;
}
}
}
#endregion
#region 战斗状态恢复配置.
//血量恢复时间和系数,目前战中和非战中恢复速度一致.
//HP回复频率.
public static readonly int Coefficient_HPRebornTime = 5000;
//战斗中HP回复系数.
public static readonly float Coefficient_CombatHPReborn = 1f;
#endregion
readonly public UnitInfo mInfo;
readonly public InstanceUnit mUnit;
readonly public XmdsUnitProperties mProp;
readonly public XmdsHateSystem mHateSystem;
//是否完成初始化技能.
protected bool mFinishSkillInit = false;
public XmdsUnitProp MirrorProp;
//脱战计时器.
private TimeExpire mOutOfCombatTime = null;
//血量回复计时器.
private TimeInterval mHPRebornTimer = null;
//定力值回复计时器.
private TimeInterval mMPRebornTimer = null;
//出生点坐标.
protected float mBirthPosX;
protected float mBirthPosY;
//坐骑状态.
private bool mIsMounted = false;
//是否在战斗状态.
private BattleStatus mInCombatState = BattleStatus.None;
//游戏服场景配置.
public XmdsServerSceneData ServerSceneData = null;
//隐身时队友是否可见.
protected bool mTeamMemberVisible = true;
public virtual bool TeamMemberVisible { get { return mTeamMemberVisible; } set { mTeamMemberVisible = value; } }
//是否无敌.
public bool IsInvincible { get; set; }
//虚无状态无视技能.
public bool NothingnessIgnoreSkill { get; set; }
//虚无状态无视Buff效果.
public bool NothingnessIgnoreBuff { get; set; }
//虚无状态无视所有效果.
public bool NothingnessIgnoreAll { get; set; }
//恢复MP状态,不可打断
public int mRecoverMPLeftTimes;
//PVP触发的玩家id
public string mPvpTriggerPlayerId;
//战斗状态变更通知.
public delegate void OnCombatChangeEvent(BattleStatus status);
public event OnCombatChangeEvent OnHandleCombatChangeEvent
{
add { event_OnHandleCombatChangeEvent += value; }
remove { event_OnHandleCombatChangeEvent -= value; }
}
protected event OnCombatChangeEvent event_OnHandleCombatChangeEvent;
#region 属性变更.
//操作指令申请计数.
private int mPropChangeOperationCount = 0;
//操作指令合集.
private HashMap mPropChangeMap = new HashMap();
protected PlayerBattlePropChangeEventB2C mBattlePropChangeEvt = null;
private int mVirtualInventorySize = 0;
#endregion
#region 战斗状态变更原因.
public const byte COMBATSTATE_CHANGE_REASON_DORESET = 1;
#endregion
public XmdsVirtual(InstanceUnit unit)
{
s_alloc_object_count++;
mUnit = unit;
mInfo = unit.Info;
mProp = unit.Info.Properties as XmdsUnitProperties;
mHateSystem = new XmdsHateSystem(this);
}
~XmdsVirtual() { s_alloc_object_count--; }
public void OnInit(InstanceUnit unit, bool pointLv)
{
UnitInfo info = unit.Info;
FormatLog("- 初始化单位 : {0} - {0} ", unit.ID, unit.Name);
Stopwatch sw = Stopwatch.StartNew();
try
{
//出生点坐标.
mBirthPosX = mUnit.X;
mBirthPosY = mUnit.Y;
//背包格子数.
mVirtualInventorySize = mProp.ServerData.Prop.CurInventorySize;
//非玩家,速度配置0
if (mInfo.UType != UnitInfo.UnitType.TYPE_PLAYER && mProp.ServerData.Prop.MoveSpeed == 0)
{
mProp.ServerData.Prop.MoveSpeed = mInfo.MoveSpeedSEC;
}
//当前场景类型.
InitSceneInfo();
//子类初始化.
Init(pointLv);
//基础信息初始化.
InitBaseData(mProp.ServerData.Prop);
//坐骑信息记录.
CheckMountStatus(mProp.ServerData.AvatarList);
if (this.mCardModule == null)
{
this.CreateCreateCardModule();
}
//初始化技能信息.
InitSkillInfo(mProp.ServerData);
//脱战计时器初始化.
InitOutOfCombatTime();
//初始化HP恢复计时器.
InitRebornTimer();
//(最后执行)同步给客户度信息.
SyncClientData();
//施放技能监听.
mUnit.OnLaunchSkill += OnLaunchSkillHandler;
//技能新增监听.
mUnit.OnSkillAdded += OnSkillAddHandler;
//技能移除监听.
mUnit.OnSkillRemoved += OnSkillRemoveHandler;
//技能变更监听.
mUnit.OnStateChanged += OnStateChangedHandler;
//物品时候时触发.
mUnit.OnUseItem += MUnit_OnUseItem;
mUnit.OnSkillHitTarget += OnSkillHitTargetHandler;
}
catch(Exception e)
{
log.Error("单位初始化异常:" + unit.Info.ID + ", " + e);
}
finally
{
sw.Stop();
if (sw.ElapsedMilliseconds > 10)
{
FormatLog("XmdsVirtual create overload , stopwatch time {0} > 10ms", sw.ElapsedMilliseconds);
}
}
}
private void MUnit_OnUseItem(InstanceUnit obj, ItemTemplate item, InstanceUnit item_creater)
{
BattleFunction battleFuntion = BattleFunction.GetInstance();
if (item != null && battleFuntion != null)
{
int id = (item.Properties as XmdsItemProperties).TriggerFunctionID;
if (id != 0)
{
battleFuntion.TriggrBattleFunction(id, this, this);
}
}
}
public void OnDispose(InstanceUnit owner)
{
if(this.mUnit != null)
{
//施放技能监听.
mUnit.OnLaunchSkill -= OnLaunchSkillHandler;
//技能新增监听.
mUnit.OnSkillAdded -= OnSkillAddHandler;
//技能移除监听.
mUnit.OnSkillRemoved -= OnSkillRemoveHandler;
//技能变更监听.
mUnit.OnStateChanged -= OnStateChangedHandler;
//物品时候时触发.
mUnit.OnUseItem -= MUnit_OnUseItem;
mUnit.OnSkillHitTarget -= OnSkillHitTargetHandler;
}
Dispose();
}
///
/// 供子类重铸.
///
protected virtual void Init(bool pointLv) { }
public bool IsFinishSkillInit()
{
return mFinishSkillInit;
}
#region 常用API.
protected virtual void SyncClientData()
{
//推属性变更计算.
UnitPropRefresh();
//第一次将全部属性推给客户端.
SyncBattlePropsFields(PlayerBattlePropChangeEventB2C.MASK_ALL);
}
public int GetUnitLv()
{
if (this.mProp.ServerData.BaseInfo.UnitLv == 0)
{
return 1;
}
return this.mProp.ServerData.BaseInfo.UnitLv;
}
public int GetStateLv()
{
return this.mProp.ServerData.BaseInfo.StateLv;
}
// 神器id
public int GetArtifactIndex()
{
return ((XmdsUnitProp)mProp.ServerData.Prop).ArtifactIndex;
}
//获得神器克制id
public bool IsArtifactRestrain(UnitFateType fateType)
{
return ((int)fateType-1) == (((XmdsUnitProp)mProp.ServerData.Prop).ArtifactIndex + 1) % 5;
}
//是否有神器
public bool IsHasArtifact()
{
return ((XmdsUnitProp)mProp.ServerData.Prop).ArtifactIndex != (int)ArtifactType.None;
}
//神器背饰id
public int GetArtifactDefenceIndex()
{
return ((XmdsUnitProp)mProp.ServerData.Prop).ArtifactDefenceIndex;
}
protected void InitBaseInfo(XmdsUnitBaseInfo baseInfo)
{
//同步等级信息.
mProp.ServerData.BaseInfo = baseInfo;
this.mUnit.Level = mProp.ServerData.BaseInfo.UnitLv;
}
public HateSystem GetHateSystem()
{
return mHateSystem;
}
///
/// 获得攻击目标.
///
///
public virtual InstanceUnit GetAtkTarget(InstanceUnit target)
{
var unit_prop = target.Virtual as XmdsVirtual;
return DispatchGetAtkUnitEvent(unit_prop).mUnit;
}
///
/// 物品触发单位加血效果.
///
///
public int AddHPByItem(int hp)
{
int v = hp;
this.mUnit.ReduceHP(-v, null, null, false, null);
return v;
}
///
/// 女武神能量变更.
///
///
public void AddEnergyByItem(int value)
{
}
///
/// 通知单位接收跳字事件.
///
///
///
public void SendHPChangeMessage(uint objID, int value)
{
BattleHintNumberB2C evt = new BattleHintNumberB2C();
evt.Value = -value;
evt.State = (byte)UnitHitEventState.Normal;
evt.TargetObjID = this.mUnit.ID;
this.mUnit.queueEvent(evt);
}
///
/// 通知单位接收能量变更跳字事件.
///
///
///
public void SendMPChangeMessage(uint objID, int value)
{
BattleHintNumberB2C evt = new BattleHintNumberB2C();
evt.Value = -value;
evt.State = (byte)UnitHitEventState.MP;
evt.TargetObjID = this.mUnit.ID;
this.mUnit.queueEvent(evt);
}
public void SendBattleHintNumberB2C(int Value, UnitHitEventState type, uint targetId = 0)
{
BattleHintNumberB2C evt = new BattleHintNumberB2C();
evt.Value = Value;
evt.State = (byte)type;
evt.TargetObjID = targetId == 0 ? this.mUnit.ID : targetId;
this.mUnit.queueEvent(evt);
}
///
/// 加血.
///
/// 血量
/// 加血者
/// 是否发送协议
public void AddHP(int hp, InstanceUnit sender = null, bool sendMsg = true, DamageSource dmgSrc = DamageSource.Def)
{
this.mUnit.ReduceHP(-hp, sender, null, sendMsg, null, false, dmgSrc);
}
public void AddHP(int hp, InstanceUnit sender, DamageSource dmgSrc)
{
this.mUnit.ReduceHP(-hp, sender, null, true, null, false, dmgSrc);
}
///
/// 加能量.
///
///
/// 是否发送协议
public void AddMP(int mp, InstanceUnit sender, bool sendMsg = true, bool force = false, AttackSource source = null)
{
this.mUnit.AddMP(mp, sender, force, false, source);
}
public void AddMP(int mp, InstanceUnit sender, AttackSource source)
{
this.mUnit.AddMP(mp, sender, true, false, source);
}
public bool IsCanReduceMP(bool force)
{
return force || mRecoverMPLeftTimes <= 0;
}
///
/// 获得角色原始属性.
///
///
public XmdsUnitProp GetOriginProp()
{
return mProp.ServerData.Prop;
}
///
/// 判断一定概率是否触发概率单位为万分比:填写1000表示百分之10.
///
///
///
public bool RandomPercent(int percent)
{
return XmdsDamageCalculator.IsInRandomRange(percent,
this.mUnit.RandomN, (int)XmdsDamageCalculator.PERER);
}
protected virtual void Dispose()
{
DestorySkill();
mOutOfCombatTime = null;
mHPRebornTimer = null;
mMPRebornTimer = null;
OnHealEventHandle = null;
event_OnCombatStateChangeHandle = null;
event_OnHandleCombatChangeEvent = null;
mBattlePropChangeEvt = null;
// if(this.mCardModule != null)
// {
// this.mCardModule.Dispose();
// }
ClearRegistEvent();
mHateSystem.Dispose();
}
///
/// 是否在异常状态内.
///
///
public bool IsInDebuffStatus()
{
bool ret = false;
if (this.mUnit.IsStun || this.mUnit.IsSilent)
{
ret = true;
}
//取当前所有BUFF,判断如果有隐身BUFF立即解除该BUFF.
using (var buffList = ListObjectPool.AllocAutoRelease())
{
this.mUnit.GetAllBuffStatus(buffList);
if (buffList != null && buffList.Count > 0)
{
for (int i = 0; i < buffList.Count; i++)
{
if (XmdsInstanceUtils.IsControlBuff(buffList[i].Data))
{
return true;
}
}
}
}
return ret;
}
//移除控制buff
public void RemoveControlBuff()
{
//取当前所有BUFF,判断如果有隐身BUFF立即解除该BUFF.
using (var buffList = ListObjectPool.AllocAutoRelease())
{
//InstanceUnit.BuffState bfs = null;
//XmdsBuffProperties prop = null;
//BuffTemplate bt = null;
this.mUnit.GetAllBuffStatus(buffList);
if (buffList == null || buffList.Count <= 0)
{
return;
}
for (int i = 0; i < buffList.Count; i++)
{
if (XmdsInstanceUtils.IsControlBuff(buffList[i].Data))
{
this.mUnit.removeBuff(buffList[i].Data.ID);
}
}
}
}
protected bool IsBusy()
{
bool ret = false;
if (this.mUnit.CurrentState != null &&
(this.mUnit.CurrentState is InstanceUnit.StateSkill))// ||
//(this.mUnit.CurrentState is InstanceUnit.StatePickObject))
{
ret = true;
}
return ret;
}
///
/// 向战斗服发送提示信息.
///
///
public void SendMsgToClient(string msg)
{
if (msg != null)
{
ShowTipsEventB2C evt = new ShowTipsEventB2C();
evt.Msg = msg;
this.mUnit.queueEvent(evt);
}
}
//单独给玩家发送消息,非广播
public void SendMsgToPlayer(ObjectEvent evt, bool force = false)
{
this.mUnit.queueEvent(evt, force);
}
///
/// 获取当前可用背包格子数量.
///
///
public int GetInventorySize()
{
if (mProp != null)
{
return mProp.ServerData.Prop.CurInventorySize;
}
return 0;
}
public void SetInventorySize(int size)
{
if (mProp != null)
{
mProp.ServerData.Prop.CurInventorySize = size;
VirtualInventorySize = size;
}
}
public int VirtualInventorySize
{
get { return mVirtualInventorySize; }
set { mVirtualInventorySize = value; }
}
///
/// 组队背包格子数.
///
///
public int GetTeamInventorySize()
{
if (mProp != null)
{
return mProp.ServerData.Prop.CurTeamInventorySize;
}
return 0;
}
public bool ContainBuff(bool isDebuff)
{
using (var buffList = ListObjectPool.AllocAutoRelease())
{
InstanceUnit.BuffState bfs = null;
XmdsBuffProperties prop = null;
BuffTemplate bt = null;
this.mUnit.GetAllBuffStatus(buffList);
if (buffList != null && buffList.Count > 0)
{
for (int i = 0; i < buffList.Count; i++)
{
bfs = buffList[i];
bt = bfs.Data;
prop = bt.Properties as XmdsBuffProperties;
if (prop.Dispelled == false) { continue; }
if (bt.IsHarmful == isDebuff)
{
return true;
}
}
}
}
return false;
}
///
/// 记录同步可视数据.
/// 战斗服数据大致分为两块,一部分用作战斗计算使用,另一部分用作同步客户端表现相关信息,
/// 当表现信息变更时,需要将数据同步给syncInfo,底层每次调用时时直接拿syncInfo来推送.
///
protected void SyncPlayerVisibleData()
{
if (this.mUnit.VisibleInfo is PlayerVisibleDataB2C)
{
PlayerVisibleDataB2C pvd = this.mUnit.VisibleInfo as PlayerVisibleDataB2C;
pvd.AvatarList = this.mProp.ServerData.AvatarList;
pvd.BaseInfo = this.mProp.ServerData.BaseInfo;
pvd.UnitPKInfo = this.mProp.ServerData.UnitPKInfo;
pvd.UnitSceneInfo = this.mProp.ServerData.UnitSceneInfo;
}
}
///
/// 当前场景信息初始化记录.
///
protected virtual void InitSceneInfo()
{
EditorScene es = mUnit.Parent as EditorScene;
XmdsSceneProperties zp = es.Data.Properties as XmdsSceneProperties;
ServerSceneData = zp.ServerSceneData;
}
protected bool CalPKValue(XmdsVirtual target)
{
//特殊规则,跨服场景,击杀非本服玩家.
if (this.mUnit.GetSceneType() >= CommonAI.Data.SceneType.CROSS_SERVER_NEW)
{
XmdsVirtual_Player r = target.GetPlayerUnit();
if (r != null && this.GetServerID() != r.GetServerID())
{
return false;
}
}
return ServerSceneData.CalPKValue;
}
public virtual PKMode GetCurPKMode()
{
if (mProp.ServerData.UnitPKInfo != null)
{
return mProp.ServerData.UnitPKInfo.CurPKMode;
}
return PKMode.Peace;
}
///
/// 获得当前PK等级(判断是否为红名).
///
///
public virtual PKLevel GetCurPKLevel()
{
PKLevel ret = PKLevel.White;
if (mProp != null && mProp.ServerData.UnitPKInfo != null)
{
ret = mProp.ServerData.UnitPKInfo.CurPKLevel;
}
return ret;
}
///
/// 服ID.
///
///
public virtual int GetServerID()
{
int ret = 0;
if (this.mProp.ServerData != null && this.mProp.ServerData.BaseInfo != null)
{
ret = this.mProp.ServerData.BaseInfo.ServerID;
}
return ret;
}
///
/// 获得公会ID.
///
///
public virtual string GetGuildID()
{
string ret = null;
if (this.mProp.ServerData != null && this.mProp.ServerData.BaseInfo != null)
{
ret = this.mProp.ServerData.BaseInfo.GuildID;
}
return ret;
}
///
/// 获得阵营ID
///
///
public virtual int GetForceID()
{
return this.mUnit.Force;
}
///
/// 获得单位ID(玩家返回UUID).
///
///
public virtual string GetPlayerUUID()
{
return mUnit.ID.ToString();
}
///
/// 重置功能,血量、buff、状态、技能全部变为初始状态.
///
public void Reset()
{
//脱战.
SetCombatState(BattleStatus.None, 1);
//BUFF.
this.mUnit.clearBuffs();
//技能CD.
this.mUnit.ClearAllSkillCD();
//坐骑状态.
this.TakeOffMount();
//回血重置.
if (mHPRebornTimer != null)
{
mHPRebornTimer.Reset();
}
if(mMPRebornTimer != null)
{
mMPRebornTimer.Reset();
}
this.mUnit.startRebirth();
this.mUnit.CurrentHP = this.mUnit.MaxHP;
this.mUnit.CurrentMP = this.mUnit.MaxMP;
}
///
/// 获取当前强度类型
///
///
public string GetCurSceneType()
{
return ServerSceneData.SceneHard;
}
///
/// 获取当前场景类型
///
///
public CommonAI.XmdsConstConfig.AreaType CurAreaType()
{
return ServerSceneData.CurAreaType;
}
protected virtual void OnHeal(XmdsVirtual attcker, int value, ref AtkResult result)
{
if (OnHealEventHandle != null)
{
OnHealEventHandle.Invoke(attcker, this, value, ref result);
}
}
public void SendBattleFloatTipsEventB2C(BattleFloatTipsEventB2C evt)
{
if (evt != null)
{
this.mUnit.queueEvent(evt);
}
}
public void SendBubbleTipsEventB2C(string msg)
{
if (!string.IsNullOrEmpty(msg))
{
var evt = new BubbleTipsEventB2C();
evt.Msg = msg;
this.mUnit.queueEvent(evt);
}
}
///
/// 能否使用物品.
///
///
public bool CanUseItem()
{
bool ret = true;
ret = (!this.mUnit.IsSilent);
return ret;
}
///
/// 同步归属权信息.
///
///
///
public virtual void SyncHeirsInfo(string name, int hpPercent, CommonAI.Data.XmdsUnitPro protype)
{
}
///
/// 是否可被攻击.
///
public virtual bool IsAttackable(XmdsVirtual attacker)
{
return true;
}
public virtual int GetVirtualTemplateID()
{
return mInfo.TemplateID;
}
///
/// 治愈效果,满血、满蓝.
///
public virtual void DoCure()
{
this.AddHP(this.mUnit.MaxHP, null, false);
this.AddMP(this.mUnit.MaxMP, null, false, true);
}
public bool SkillAutoLaunchTest(InstanceUnit.SkillState ss)
{
bool ret = false;
UnitSkill us = XmdsBattleSkill.GetUnitSkill(ss.Data.ID); ;
if (us != null)
{
ret = us.SkillAutoLaunchTest(ss, this);
}
return ret;
}
#endregion
#region 基础事件.
///
/// 角色本身的初始化.
///
///
private void Unit_OnActivated(InstanceUnit unit)
{
mUnit.OnActivated -= Unit_OnActivated;
}
//主动移除技能.
public GameSkill RemoveSkill(int skillID)
{
GameSkill skillData = this.SkillHelper.GetGameSkill(skillID);
if (skillData == null)
{
return null;
}
if (skillData.SkillType == XmdsSkillType.passive || skillData.SkillType == XmdsSkillType.petGivePassive)
{
this.SkillHelper.RemovePassiveSkill(skillID);
return null;
}
else
{
SkillState skillState = this.mUnit.getSkillState(skillID);
this.SkillHelper.RemoveActiveSkill(skillID);
return skillData;
}
}
#endregion
#region 安全区域
private bool mIsInSafeArea = false;
///
/// 是否在安全区域
///
public bool IsInSafeArea(){ return mIsInSafeArea; }
//跟新战斗区域状态
private void UpdateAreaState(int intervalMS)
{
//var sa = mUnit.Parent.GetArea(mUnit.X, mUnit.Y);
var sa = mUnit.CurrentArea;
if (sa != null && sa.CurrentMapNodeValue == XmdsMapBlock.BLOCK_VALUE_SAFE)
{
this.mIsInSafeArea = true;
}
else
{
this.mIsInSafeArea = false;
}
}
public void OnPlayerKillMonster(InstanceUnit monster)
{
try
{
XmdsInstancePlayer player = this.mUnit as XmdsInstancePlayer;
List members = player.TeamVirtual == null ? null : player.TeamVirtual.GetTeamMembers();
log.Info("--------OnPlayerKillMonster print start:" + mUnit.PlayerUUID + ", 场景ID" + mUnit.Parent.GetSceneID() + ", 怪ID:"
+ monster.Info.ID + ", 队伍人数:" + (members == null ? -1 : members.Count));
if(members == null)
{
JSGXmdsHackerModule.OnPlayerKillMonster(player, monster);
}
else
{
//foreach(XmdsInstancePlayer member in members)
{
JSGXmdsHackerModule.OnPlayerKillMonster(player, monster);
}
}
}
catch (Exception e)
{
log.Warn("XMDSS OnPlayerKillMonster catch:", e);
}
}
#endregion
#region 战斗状态.
///
/// 是否在战斗状态.
///
public BattleStatus CombatState
{
get { return mInCombatState; }
}
public virtual void SetCombatState(BattleStatus value, byte reason = 0, String pvpTriggerPlayerId = "")
{
// 只有在空闲状态才允许设置技能展示状态
if (value == BattleStatus.ReadyBattle && mInCombatState != BattleStatus.None)
{
return;
}
if (value != BattleStatus.None && mOutOfCombatTime != null)
{
mOutOfCombatTime.Reset();
}
if (mInCombatState != value)
{
if (value == BattleStatus.None)
{
if (JudgeChangeCombatStateChange(value, reason))
{
mInCombatState = value;
CombatStateConnect(value, reason);
OnCombatStateChange(mInCombatState);
//单位脱战了
this.mUnit.Parent.cb_unitOutBattleCallBack(this.mUnit);
}
}
else if (value > mInCombatState)//战斗状态等级不同.
{
if (JudgeChangeCombatStateChange(value, reason))
{
mInCombatState = value;
CombatStateConnect(value, reason);
OnCombatStateChange(mInCombatState);
}
}
}
if(mInCombatState == BattleStatus.PVP)
{
this.mPvpTriggerPlayerId = pvpTriggerPlayerId;
}
}
public bool IsInPVP()
{
return mInCombatState == BattleStatus.PVP ? true : false;
}
public bool IsInPVE()
{
return mInCombatState == BattleStatus.PVE ? true : false;
}
public BattleStatus GetBattleStatus()
{
return mInCombatState;
}
//坐骑状态变更.
public bool IsMounted
{
set { mIsMounted = value; }
get { return mIsMounted; }
}
private void CheckMountStatus(List list)
{
if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i].PartTag == XmdsAvatarInfo.XmdsAvatar.Ride_Equipment)
{
if (!string.IsNullOrEmpty(list[i].FileName))
{
//有坐骑信息.
IsMounted = true;
break;
}
}
}
}
}
//状态改变时候触发.
protected virtual void OnCombatStateChange(BattleStatus status)
{
//脱战时,清空仇恨列表.
if (status == BattleStatus.None && this.mUnit.IsDead() == false)
{
mHateSystem.Clear();
if (event_OnCombatStateChangeHandle != null)
{
event_OnCombatStateChangeHandle.Invoke(this, false);
}
FormatLog("{0}脱离战斗", mInfo.Name);
}
//状态变更时,需要同步告知客户端做响应表现.
if (status != BattleStatus.None)
{
FormatLog("{0}进入战斗", mInfo.Name);
}
SyncUnitCombatState(status);
if (event_OnHandleCombatChangeEvent != null)
{
event_OnHandleCombatChangeEvent.Invoke(status);
}
var scene = (mUnit.Parent as XmdsServerScene);
scene.callback_OnCombatStateChange(this.mUnit, status);
}
protected virtual bool JudgeChangeCombatStateChange(BattleStatus status, byte reason)
{
bool ret = true;
//默认为0,特殊情况不为0.
if (reason != 0)
{
ret = true;
}
else
{
if (status == BattleStatus.None)
{
//表示单位一旦开始追击不会退出战斗状态.
if (this.mUnit.Info.GuardRangeLimit == 0)
{
return false;
}
}
}
return ret;
}
protected virtual void ChangeCombatStateFromAtk(XmdsVirtual target)
{
var s = (this.IsPlayerUnit() && target.IsPlayerUnit()) ? BattleStatus.PVP : BattleStatus.PVE;
SetCombatState(s, 0, target.mUnit.PlayerUUID);
}
protected virtual void CombatStateConnect(BattleStatus status, byte reason)
{
}
public virtual void OnHitOthter(XmdsVirtual target)
{
}
private void SyncUnitCombatState(BattleStatus status)
{
//改走通用字段.
//mUnit.queueEvent(new CombatStateChangeEvent(mUnit.ID, status));
//Dummy_0用来同步战斗状态.
mUnit.Dummy_0 = (byte)status;
}
//脱战计时器.
private void InitOutOfCombatTime()
{
if (mProp.IsUseCombatTimeCount == true)
{
if (this.mUnit.IsMonster)
{
mOutOfCombatTime = new TimeExpire(XmdsConfig.Instance.OUTOF_BATTLE_MONSTER);
}
else
{
mOutOfCombatTime = new TimeExpire(XmdsConfig.Instance.OUTOF_BATTLE_PLAYER);
}
}
}
//更新脱战计时.
private void UpdateOutOfCombatTime(int time)
{
if (mInCombatState != BattleStatus.None && mOutOfCombatTime != null && mOutOfCombatTime.Update(time))
{
SetCombatState(BattleStatus.None);
}
}
#endregion
#region 基础信息.
protected void InitBaseData(XmdsUnitProp data)
{
//复制原始单位数据.
MirrorProp = (XmdsUnitProp)data.Clone();
this.mUnit.SetMaxHP(data.MaxHP, true);
if (data.HP >= 0)
{
this.mUnit.CurrentHP = data.HP;
}
this.mUnit.MaxMP = data.ShieldValue;
this.mUnit.CurrentMP = data.ShieldValue;
SycSkillCdReduce();
SycControledTimeReduce();
SycMoveSpeed();
SycAttackSpeed();
}
public void SycMoveSpeed()
{
this.mUnit.SetMoveSpeed(this.MirrorProp.MoveSpeed);
}
private void SycAttackSpeed()
{
this.mUnit.SetAttackSpeed(this.MirrorProp.AttackSpeed);
}
private void SycMaxHP()
{
mUnit.SetMaxHP(this.MirrorProp.MaxHP, true);
}
private void SycSkillCdReduce()
{
mUnit.SetSkillCdReduce(this.MirrorProp.SkillCD);
}
private void SycControledTimeReduce()
{
mUnit.SetControledTimeReduce(this.MirrorProp.CtrlTimeReduce);
}
#endregion
#region 血量回复.
private void InitRebornTimer()
{
if (mHPRebornTimer == null)
{
mHPRebornTimer = new TimeInterval(Coefficient_HPRebornTime);
mHPRebornTimer.FirstTimeEnable = false;
}
if(mMPRebornTimer == null)
{
mMPRebornTimer = new TimeInterval< int > (GlobalData.SHIELD_RECOVER_INTERVAL);
mMPRebornTimer.FirstTimeEnable = false;
}
}
private void UpdateHPReborn(int intervalMS)
{
try
{
if (MirrorProp.HPReborn > 0 && this.mUnit.CurrentHP < this.mUnit.MaxHP && mHPRebornTimer != null && !this.mUnit.IsDead())
{
if (mHPRebornTimer.Update(intervalMS))
{
if (mInCombatState != BattleStatus.None)
{
int v = CUtils.CastInt(MirrorProp.MaxHPReborn * Coefficient_CombatHPReborn);
this.mUnit.AddHP(v, null);
}
else
{
this.mUnit.AddHP(MirrorProp.MaxHPReborn, null);
}
}
}
}
catch(Exception e)
{
log.Error("UpdateHPReborn catch : " + this.mUnit.Info.ID + ", IsActive: " + this.mUnit.IsActive +
", " + (mMPRebornTimer == null ? "timer null" : "OK") + ", " + e);
}
}
private void UpdateMPReborn(int intervalMS)
{
try
{
if(this.mRecoverMPLeftTimes > 0 && mMPRebornTimer != null && mMPRebornTimer.Update(intervalMS))
{
int addMP = 0;
if(--this.mRecoverMPLeftTimes == 0)
{
addMP = this.mUnit.MaxMP - this.mUnit.CurrentMP;
}
else
{
addMP = this.mUnit.MaxMP / GlobalData.SHIELD_RECOVER_TIME;
}
this.AddMP(addMP, null);
}
}
catch (Exception e)
{
log.Error("UpdateMPReborn catch : " + this.mUnit.Info.ID + ", IsActive: " + this.mUnit.IsActive +
", " + (mMPRebornTimer == null ? "timer null" : "OK") + ", " + e);
}
}
public void StartRecoverMP(bool reset = false)
{
if (reset)
{
this.mRecoverMPLeftTimes = 0;
}
else
{
this.mRecoverMPLeftTimes = GlobalData.SHIELD_RECOVER_TIME;
}
}
#endregion
#region Formula调用.
public void OnUnitRemoved() { }
public virtual int OnHit(XmdsVirtual attacker, AttackSource source)
{
AtkResult result = new AtkResult();
//无敌直接免疫打击效果.
if ((this.IsInvincible == true) && source.FromExpectTarget == SkillTemplate.CastTarget.Enemy)
{
attacker.OnHitOthter(this);
//无敌时仇恨减为1.
attacker.mHateSystem.SetHateInfo(this.mUnit.ID, 1);
//攻击者进度战斗状态.
attacker.ChangeCombatStateFromAtk(this);
mHateSystem.OnHitted(attacker, this, 0, ref result);
source.OutIsDamage = false;
source.OutClientState = (int)UnitHitEventState.Immunity;
return 0;
}
#region 特殊状态判断.
if (this.NothingnessIgnoreBuff)
{
if (source.FromBuffState != null)
{
return 0;
}
}
if (this.NothingnessIgnoreSkill)
{
if (source.FromSkillState != null || source.FromSpellUnit != null)
{
return 0;
}
}
if (this.NothingnessIgnoreAll)
{
return 0;
}
#endregion
int damage = this.On_hit_unit_vs_unit(attacker, this, source, ref result);
if (damage < 0)
{
OnHeal(attacker, -damage, ref result);
//加血.
if (attacker.CombatState != BattleStatus.None) { SetCombatState(attacker.CombatState); }
}
else if(this.mUnit.ID != attacker.mUnit.ID)//自己对自己作用的不算
{
if (damage == 0 && source.OutClientState != (int)UnitHitEventState.Dodge)//增益、负面效果.
{
if (source.FromExpectTarget == SkillTemplate.CastTarget.Enemy)//负面效果.
{
attacker.OnHitOthter(this);
//攻击者进度战斗状态.
attacker.ChangeCombatStateFromAtk(this);
mHateSystem.OnHitted(attacker, this, damage, ref result);
var v = (this.IsPlayerUnit() && attacker.IsPlayerUnit()) ? BattleStatus.PVP : BattleStatus.PVE;
//单位被攻击,且从PVE状态转为PVP状态,
if (v == BattleStatus.PVP && CombatState != BattleStatus.PVP)
{
UnderAttackCheck(attacker);
}
SetCombatState(v, 0, attacker.mUnit.PlayerUUID);
//坐骑状态下检查受击影响.
MountOnHitCheck(attacker);
//判断异常状态(击倒击飞).
{
MountOnHit(source);
}
}
else //增益效果.
{
if (this != attacker)
{
//施术者或受攻击者双方互相影响.
if (this.CombatState != BattleStatus.None)
{
attacker.SetCombatState(this.CombatState);
}
if (attacker.CombatState != BattleStatus.None)
{
SetCombatState(attacker.CombatState);
}
}
}
}
else
{
attacker.OnHitOthter(this);
//致命一击时候死亡状态不设置.
// if (this.mUnit.CurrentHP - damage > 0)
{
var s = (this.IsPlayerUnit() && attacker.IsPlayerUnit()) ? BattleStatus.PVP : BattleStatus.PVE;
//单位被攻击,且从PVE状态转为PVP状态,
if (s == BattleStatus.PVP && CombatState != BattleStatus.PVP)
{
UnderAttackCheck(attacker);
}
SetCombatState(s, 0, attacker.mUnit.PlayerUUID);
}
//攻击者进度战斗状态.
attacker.ChangeCombatStateFromAtk(this);
//仇恨值计算.
attacker.DispatchCalThreatValueEvent(this, source, ref result);
mHateSystem.OnHitted(attacker, this, damage, ref result);
//坐骑状态下检查受击影响.
MountOnHitCheck(attacker);
//判断异常状态(击倒击飞).
{
MountOnHit(source);
}
//扣除定力
if (this.mUnit.MaxMP > 0 && result.breakShieldValue > 0)
{
this.AddMP(-result.breakShieldValue, attacker.mUnit, source);
}
}
}
//if (damage == 0)
//{
// source.OutIsDamage = false;
//}
return damage;
}
public virtual void OnUnitDead(XmdsVirtual killer)
{
//坐骑状态设置为false.
TakeOffMount();
//脱战.
SetCombatState(BattleStatus.None, 1);
if (mHateSystem != null)
{
mHateSystem.Clear();
}
}
public virtual void OnKillUnit(XmdsVirtual dead)
{
}
///
/// 是否属于玩家.
///
///
public virtual bool IsPlayerUnit()
{
return false;
}
///
/// 获取对应玩家单位.
///
///
public virtual XmdsVirtual_Player GetPlayerUnit()
{
return null;
}
public void OnHandleNetMessage(ObjectAction action)
{
}
public void OnTriggerStart(InstanceUnit.TriggerState trigger, XmdsVirtual target)
{
}
public virtual void OnUpdateTriggerSkill(int intervalMS, bool slowRefresh)
{
// 区域刷新 //
UpdateAreaState(intervalMS);
//同步战斗属性协议.
UpdateBattlePropsChangeEvt();
//慢刷新,不必要每一帧都刷新
if (slowRefresh)
{
int slowInterval = intervalMS * GlobalData.ZONE_UPDATE_SLOW;
//计算是否脱战.
UpdateOutOfCombatTime(slowInterval);
//HP回复.
UpdateHPReborn(slowInterval);
UpdateMPReborn(slowInterval);
//仇恨系统刷新.
UpdateHateSystem(slowInterval);
}
//技能刷新.
UpdateSkillHelper(intervalMS, slowRefresh);
// if (this.mCardModule != null)
// {
// this.mCardModule.Update(intervalMS, slowRefresh);
// }
}
public void OnBuffBegin(InstanceUnit.BuffState state, XmdsVirtual sender)
{
BuffTemplate template = state.Data;
XmdsBuffProperties prop = template.Properties as XmdsBuffProperties;
List list = null;
if (state.Tag != null)
{
list = state.Tag as List;
}
//异常BUFF对坐骑状态有影响.
MountOnBuffBegin(template);
if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
UnitBuff ub = list[i] as UnitBuff;
ub.BuffBegin(this, sender, state);
}
}
DispatchBuffEvent(state, BuffEventType.Begin, null);
}
public void OnBuffUpdate(InstanceUnit.BuffState state, int time)
{
BuffTemplate template = state.Data;
List list = null;
if (state.Tag != null)
{
list = state.Tag as List;
}
if (list != null && list.Count != 0)
{
int count = 0;
for (int i = 0; i < list.Count; i++)
{
UnitBuff ub = list[i] as UnitBuff;
ub.BuffUpdate(this, state);
if (ub.IsInvaild())
{
count++;
}
}
if (count == list.Count)//当前BUFF所有能力都已失效,主动移出该BUFF.
{
this.mUnit.removeBuff(template.ID);
}
}
}
public void OnBuffEnd(InstanceUnit.BuffState state, string result, bool replace)
{
BuffTemplate template = state.Data;
XmdsBuffProperties prop = template.Properties as XmdsBuffProperties;
List list = null;
if (state.Tag != null)
{
list = state.Tag as List;
}
if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
UnitBuff ub = list[i] as UnitBuff;
ub.BuffEnd(this, state, replace);
}
}
DispatchBuffEvent(state, BuffEventType.End, result);
}
#endregion
#region 属性能力重算.
///
/// 刷新属性.
///
protected void UnitPropRefresh(XmdsUnitProp prop = null)
{
if (prop == null)
{
XmdsUnitProp zup = GetOriginProp();
this.MirrorProp = zup.Clone() as XmdsUnitProp;
}
else
{
this.MirrorProp = prop;
}
foreach (KeyValuePair kvp in mPropChangeMap)
{
ChangeProp(kvp.Value);
}
int srcHP = this.MirrorProp.MaxHP;
// 更新虚拟属性,只影响数值,不计入显示和战力计算(也不在面板上显示)
if(this.mProp.ServerData.PropExt != null && this.mUnit.IsPlayer)
{
this.MirrorProp.AddTo(this.mProp.ServerData.PropExt);
}
SycMaxHP();
SycSkillCdReduce();
SycControledTimeReduce();
SycMoveSpeed();
SycAttackSpeed();
//隐藏属性导致玩家血量变了,同步最大血量ext
if(this.MirrorProp.MaxHP != srcHP)
{
SyncBattlePropsFields(UnitAttributeType.SetMaxHP);
}
}
private void ChangeProp(PropChangeOperation opt)
{
XmdsUnitProp zup = GetOriginProp();
switch (opt.Type)
{
case UnitAttributeType.Defence:
if (opt.OpType == PropChangeOperation.OperateType.Percent)
{
this.MirrorProp.DefencePer += opt.Value;
}
else
{
this.MirrorProp.BaseDefence += opt.Value;
}
//攻击异常日志
JSGXmdsHackerModule.PrintAttrErrorInfo(this, opt.Type, this.MirrorProp.Defence, this.GetOriginProp().Defence);
break;
case UnitAttributeType.CritRate:
this.MirrorProp.CritRate += opt.Value;
break;
case UnitAttributeType.MaxHP:
if (opt.OpType == PropChangeOperation.OperateType.Percent)
{
this.MirrorProp.HPPer += opt.Value;
}
else
{
this.MirrorProp.BaseMaxHP += opt.Value;
}
mUnit.SetMaxHP(this.MirrorProp.MaxHP, true);
//攻击异常日志
JSGXmdsHackerModule.PrintAttrErrorInfo(this, opt.Type, this.MirrorProp.MaxHP, this.GetOriginProp().MaxHP);
break;
case UnitAttributeType.Attack:
if (opt.OpType == PropChangeOperation.OperateType.Percent)
{
this.MirrorProp.AttackPer += opt.Value;
}
else
{
this.MirrorProp.BaseAttack += opt.Value;
}
//攻击异常日志
if (this.MirrorProp.MaxAttack > this.GetOriginProp().MaxAttack * 3)
{
JSGXmdsHackerModule.PrintAttrErrorInfo(this, opt.Type, this.MirrorProp.MaxAttack, this.GetOriginProp().MaxAttack);
}
break;
case UnitAttributeType.HealedEffect:
this.MirrorProp.HealedEffect += opt.Value;
break;
case UnitAttributeType.HealEffect:
this.MirrorProp.HealEffect += opt.Value;
break;
case UnitAttributeType.PlayerDamageReduce:
this.MirrorProp.PlayerDamageReduce += opt.Value;
// 免伤异常日志
JSGXmdsHackerModule.PrintAttrErrorInfo(this, opt.Type, this.MirrorProp.PlayerDamageReduce, opt.Value);
break;
case UnitAttributeType.MoveSpeed:
this.MirrorProp.MoveSpeed += GetOpValueFloat(zup.MoveSpeed, opt.Value, opt.OpType);
this.MirrorProp.VelocityAddition += opt.Value;
break;
case UnitAttributeType.PickupRange:
this.MirrorProp.pickupRange += GetOpValue(zup.pickupRange, opt.Value, opt.OpType);
break;
case UnitAttributeType.AttackSpeed:
this.MirrorProp.AttackSpeed += GetOpValue(zup.AttackSpeed, opt.Value, opt.OpType);
break;
case UnitAttributeType.SkillLanuchSpeed:
this.MirrorProp.SkillCD += GetOpValue(zup.SkillCD, opt.Value, opt.OpType);
break;
case UnitAttributeType.ControlTimeReduce:
this.MirrorProp.CtrlTimeReduce += opt.Value;
break;
case UnitAttributeType.SkillDamage:
this.MirrorProp.SkillDamageAdd += opt.Value;
break;
case UnitAttributeType.IngoreDefence:
if (opt.OpType == PropChangeOperation.OperateType.Percent)
{
this.MirrorProp.IgnoreDefensePer += opt.Value;
}
else
{
this.MirrorProp.BaseIgnoreDefense += opt.Value;
}
break;
case UnitAttributeType.SkillLeech:
this.MirrorProp.ActiveAtkLeech += opt.Value;
break;
case UnitAttributeType.CritDamage:
this.MirrorProp.CritDamage += opt.Value;
break;
case UnitAttributeType.PlayerDamageAdd:
this.MirrorProp.PlayerDamageAdd += opt.Value;
// 伤害增加异常日志
JSGXmdsHackerModule.PrintAttrErrorInfo(this, opt.Type, this.MirrorProp.PlayerDamageAdd, opt.Value);
break;
case UnitAttributeType.MonsterDamageAdd:
this.MirrorProp.monsterDamageAdd += opt.Value;
break;
case UnitAttributeType.MonsterDamageReduce:
this.MirrorProp.monsterDamageReduce += opt.Value;
break;
case UnitAttributeType.AllDmgAdd:
this.MirrorProp.AllDmgAdd += opt.Value;
// 伤害增加异常日志
JSGXmdsHackerModule.PrintAttrErrorInfo(this, opt.Type, this.MirrorProp.AllDmgAdd, opt.Value);
break;
case UnitAttributeType.AllDmgReduce:
this.MirrorProp.AllDmgReduce += opt.Value;
// 伤害增加异常日志
JSGXmdsHackerModule.PrintAttrErrorInfo(this, opt.Type, this.MirrorProp.AllDmgReduce, opt.Value);
break;
case UnitAttributeType.SetMaxHP:
this.MirrorProp.BaseMaxHP = opt.Value;
break;
case UnitAttributeType.CritRate_NormalAtk:
this.MirrorProp.NormalAtkCriteRate += opt.Value;
break;
case UnitAttributeType.HPRecover:
if (opt.OpType == PropChangeOperation.OperateType.Percent)
{
this.MirrorProp.HPRecoverPer += opt.Value;
}
else
{
this.MirrorProp.HPReborn += opt.Value;
}
break;
case UnitAttributeType.EAttack_Gold:
this.MirrorProp.ArtifactAttack[(int)ArtifactType.Gold] += opt.Value;
break;
case UnitAttributeType.EAttack_Wood:
this.MirrorProp.ArtifactAttack[(int)ArtifactType.Wood] += opt.Value;
break;
case UnitAttributeType.EAttack_Water:
this.MirrorProp.ArtifactAttack[(int)ArtifactType.Water] += opt.Value;
break;
case UnitAttributeType.EAttack_Fire:
this.MirrorProp.ArtifactAttack[(int)ArtifactType.Fire] += opt.Value;
break;
case UnitAttributeType.EAttack_Soil:
this.MirrorProp.ArtifactAttack[(int)ArtifactType.Soil] += opt.Value;
break;
case UnitAttributeType.EDefence_Gold:
this.MirrorProp.ArtifactDefense[(int)ArtifactType.Gold] += opt.Value;
break;
case UnitAttributeType.EDefence_Wood:
this.MirrorProp.ArtifactDefense[(int)ArtifactType.Wood] += opt.Value;
break;
case UnitAttributeType.EDefence_Water:
this.MirrorProp.ArtifactDefense[(int)ArtifactType.Water] += opt.Value;
break;
case UnitAttributeType.EDefence_Fire:
this.MirrorProp.ArtifactDefense[(int)ArtifactType.Fire] += opt.Value;
break;
case UnitAttributeType.EDefence_Soil:
this.MirrorProp.ArtifactDefense[(int)ArtifactType.Soil] += opt.Value;
break;
case UnitAttributeType.ToBoss_CriteRate:
this.MirrorProp.ToBossCritRate += opt.Value;
break;
case UnitAttributeType.ToBoss_CriteDamage:
this.MirrorProp.ToBossCritDamage += opt.Value;
break;
case UnitAttributeType.MonsterRestraint_1:
this.MirrorProp.MonsterRestraint[(int)UnitFateType.One - 1] += opt.Value;
break;
case UnitAttributeType.MonsterRestraint_2:
this.MirrorProp.MonsterRestraint[(int)UnitFateType.Two - 1] += opt.Value;
break;
case UnitAttributeType.MonsterRestraint_3:
this.MirrorProp.MonsterRestraint[(int)UnitFateType.Three - 1] += opt.Value;
break;
case UnitAttributeType.MonsterRestraint_4:
this.MirrorProp.MonsterRestraint[(int)UnitFateType.Four - 1] += opt.Value;
break;
case UnitAttributeType.MonsterRestraint_5:
this.MirrorProp.MonsterRestraint[(int)UnitFateType.Five - 1] += opt.Value;
break;
default:
break;
}
}
private int GetOpValue(float UnitProp, float changeValue, PropChangeOperation.OperateType type)
{
float ret = 0;
if (type == PropChangeOperation.OperateType.Percent)
{
ret = UnitProp * (changeValue / XmdsDamageCalculator.PERER);
}
else
{
ret = changeValue;
}
return CUtils.CastInt(ret);
}
private float GetOpValueFloat(float UnitProp, float changeValue, PropChangeOperation.OperateType type)
{
float ret = 0;
if (type == PropChangeOperation.OperateType.Percent)
{
ret = UnitProp * (changeValue / XmdsDamageCalculator.PERER);
}
else
{
ret = changeValue;
}
return ret;
}
public PropChangeOperation CreatePropChangeOpertation(UnitBuff buff)
{
return new PropChangeOperation(buff == null ? 0 : buff.GetBindBuffID());
}
/** 被动改变数值 */
public void ChangeMaxHP(int addValues)
{
mProp.ServerData.Prop.BaseMaxHP += addValues;
mUnit.SetMaxHP(this.MirrorProp.MaxHP, true);
}
/** 被动改变攻击,除非死亡,否则不清除属性 */
public void ChangeAttack(int addValues)
{
mProp.ServerData.Prop.BaseAttack += addValues;
UnitPropRefresh();
}
/** 被动改变防御,除非死亡,否则不清除属性 */
public void ChangeDefence(int addValues)
{
mProp.ServerData.Prop.BaseDefence += addValues;
UnitPropRefresh();
}
/** 被动改变攻速,除非死亡,否则不清除属性 */
public void ChangeAtkSpeed(int addValues)
{
mProp.ServerData.Prop.AttackSpeed += addValues;
UnitPropRefresh();
}
/** 被动改变暴击伤害,除非死亡,否则不清除属性 */
public void ChangeCriteDamage(int addValues)
{
mProp.ServerData.Prop.CritDamage += addValues;
UnitPropRefresh();
}
/** 被动改变暴击率,除非死亡,否则不清除属性 */
public void ChangeCriteRate(int addValues)
{
mProp.ServerData.Prop.CritRate += addValues;
UnitPropRefresh();
}
///
/// 插入一条属性变更操作指令,返回id用来删除.
///
///
public int AddPropChangeOperation(PropChangeOperation opt)
{
int ret = 0;
mPropChangeOperationCount++;
ret = mPropChangeOperationCount;
mPropChangeMap.Add(ret, opt);
//立刻生效计算.
UnitPropRefresh();
SyncBattlePropsFields(opt.Type);
return ret;
}
public bool UpdatePropChangeOperation(int OpID, PropChangeOperation opt)
{
if (mPropChangeMap.ContainsKey(OpID))
{
mPropChangeMap[OpID] = opt;
//立刻生效计算.
UnitPropRefresh();
SyncBattlePropsFields(opt.Type);
return true;
}
return false;
}
///
///删除属性变更操作指令.
///
public void RemovePropChangeOperation(int id)
{
PropChangeOperation opt;
if (mPropChangeMap != null && mPropChangeMap.TryGetValue(id, out opt))
{
mPropChangeMap.Remove(id);
SyncBattlePropsFields(opt.Type);
UnitPropRefresh();
}
else
{
FormatLog("RemovePropChangeOperation Error");
}
}
public HashMap GetChangePropMap()
{
return this.mPropChangeMap;
}
///
/// 操作指令.
///
public class PropChangeOperation
{
///
/// 操作属性.
///
public UnitAttributeType Type;
///
/// 操作值.
///
public int Value;
///
/// 操作类型.
///
public OperateType OpType;
//唯一标识key
private int mBindBuffID;
///
/// 操作类型:值加减,百分比,
///
public enum OperateType : byte
{
Value,
Percent,
}
public PropChangeOperation(int buffID)
{
this.mBindBuffID = buffID;
}
public int GetBindBuffID()
{
return this.mBindBuffID;
}
public override string ToString()
{
return "[" + this.mBindBuffID + ", " + this.Type + ", " + this.Value + ", " + this.OpType + "]";
}
}
///
/// 操作标识.
///
public enum UnitAttributeType : Byte
{
None, //无.
MoveSpeed, //速度.
Defence, //防御.
Attack, //最大攻击
/**attention, 这里存在坑,之前增伤,减伤被改成玩家后,后来有需要所有的增伤,减伤,有新加了一个奇怪的东西。 容易混淆*/
PlayerDamageAdd, // 伤害加成(玩家之间)
PlayerDamageReduce, // 伤害减免(被改成玩家之间)
MonsterDamageAdd, // 怪物(妖兽)伤害增加
MonsterDamageReduce, // 怪物(妖兽)免伤
AllDmgReduce, // 所有伤害减免
AllDmgAdd, // 单位增伤,IncAllDamage改成玩家之间导致新增一个奇怪所有增伤属性
HealEffect, //治疗效果.
HealedEffect, //受治疗效果.
MaxHP, //生命上限.
CritRate, //暴击率
PickupRange, //拾取距离
AttackSpeed, //攻速, 普攻冷却缩减
SkillLanuchSpeed, //技能冷却缩减
ControlTimeReduce, //控制时间改变,韧性
SkillDamage, //技能伤害
IngoreDefence, //无视防御
SkillLeech, //技能吸血
CritDamage, //暴击伤害
SetMaxHP, //设置最大血量
CritRate_NormalAtk, //普攻暴击率(为实现技能效果加的)
HPRecover, //生命恢复效果
EAttack_Gold,
EAttack_Wood,
EAttack_Water,
EAttack_Fire,
EAttack_Soil,
EDefence_Gold,
EDefence_Wood,
EDefence_Water,
EDefence_Fire,
EDefence_Soil,
ToBoss_CriteRate,
ToBoss_CriteDamage,
MonsterRestraint_1, // 命格克制
MonsterRestraint_2,
MonsterRestraint_3,
MonsterRestraint_4,
MonsterRestraint_5,
}
// 数值上限
public class GamePropLimit
{
public const int AttackSpeed_Down = -5000; // 攻速下限
public const int AttackSpeed_Up = 25000; // 攻速上限
public const int MoveSpeed = 4000; // 移速
public const int SkillLaunchSpeed = 5000; // 冷却缩减
public const int DamageRemit = 5000; // 伤害减免
public const int CtrlTimeReduce = 5000; // 韧性
public const int SkillDamageAdd = 5000; // 技能伤害增幅
public const int HealthAddition = 5000; // 治疗增幅
public const int CtrlAddition = 5000; // 控制增幅
}
///
/// 同步客户端.
///
private void UpdateBattlePropsChangeEvt()
{
if (mBattlePropChangeEvt != null)
{
GenBattlePropsFields(mBattlePropChangeEvt);
SendBattlePropsChangeEvt(mBattlePropChangeEvt);
mBattlePropChangeEvt = null;
}
}
private ulong GetBattlePropFieldsMask(UnitAttributeType type)
{
ulong mask = 0;
switch (type)
{
case UnitAttributeType.MaxHP:
mask = PlayerBattlePropChangeEventB2C.MASK_MAX_HP;
break;
case UnitAttributeType.MoveSpeed:
mask = PlayerBattlePropChangeEventB2C.MASK_MOVE_SPEED | PlayerBattlePropChangeEventB2C.MASK_MOVE_SPEED_ADDITION;
break;
case UnitAttributeType.Attack:
mask = PlayerBattlePropChangeEventB2C.MASK_ATTACK;
break;
case UnitAttributeType.IngoreDefence:
mask = PlayerBattlePropChangeEventB2C.MASK_IGNORE_DEFENSE_PER;
break;
case UnitAttributeType.Defence:
mask = PlayerBattlePropChangeEventB2C.MASK_DEF;
break;
case UnitAttributeType.CritRate:
mask = PlayerBattlePropChangeEventB2C.MASK_CRIT_RATE;
break;
case UnitAttributeType.CritDamage:
mask = PlayerBattlePropChangeEventB2C.MASK_CRIT_DAMAGE;
break;
case UnitAttributeType.PlayerDamageReduce:
mask = PlayerBattlePropChangeEventB2C.MASK_ALL_DAMAGE_REDUCE;
break;
case UnitAttributeType.HealEffect:
mask = PlayerBattlePropChangeEventB2C.MASK_HEALEFFECT;
break;
case UnitAttributeType.HealedEffect:
mask = PlayerBattlePropChangeEventB2C.MASK_HEALEDEFFECT;
break;
case UnitAttributeType.AttackSpeed:
mask = PlayerBattlePropChangeEventB2C.MASK_ATTACK_SPEED;
break;
case UnitAttributeType.SkillLanuchSpeed:
mask = PlayerBattlePropChangeEventB2C.MASK_SKILL_CD;
break;
case UnitAttributeType.ControlTimeReduce:
mask = PlayerBattlePropChangeEventB2C.MASK_CTRLTIME_REDUCE;
break;
case UnitAttributeType.SkillDamage:
mask = PlayerBattlePropChangeEventB2C.MASK_SKILLDAMAGE;
break;
case UnitAttributeType.PlayerDamageAdd:
mask = PlayerBattlePropChangeEventB2C.MASK_INCALLDAMAGE;
break;
case UnitAttributeType.SetMaxHP:
mask = PlayerBattlePropChangeEventB2C.MASK_MAX_HP_EXT;
break;
case UnitAttributeType.SkillLeech:
mask = PlayerBattlePropChangeEventB2C.MASK_ACTIVE_ATK_LEECH;
break;
case UnitAttributeType.HPRecover:
mask = PlayerBattlePropChangeEventB2C.MASK_HP_REBORN;
break;
case UnitAttributeType.EAttack_Gold:
mask = PlayerBattlePropChangeEventB2C.MASK_GOLD_ATTACK;
break;
case UnitAttributeType.EAttack_Wood:
mask = PlayerBattlePropChangeEventB2C.MASK_WOOD_ATTACK;
break;
case UnitAttributeType.EAttack_Water:
mask = PlayerBattlePropChangeEventB2C.MASK_WATER_ATTACK;
break;
case UnitAttributeType.EAttack_Fire:
mask = PlayerBattlePropChangeEventB2C.MASK_FIRE_ATTACK;
break;
case UnitAttributeType.EAttack_Soil:
mask = PlayerBattlePropChangeEventB2C.MASK_SOIL_ATTACK;
break;
case UnitAttributeType.EDefence_Gold:
mask = PlayerBattlePropChangeEventB2C.MASK_GOLD_DEFENSE;
break;
case UnitAttributeType.EDefence_Wood:
mask = PlayerBattlePropChangeEventB2C.MASK_WOOD_DEFENSE;
break;
case UnitAttributeType.EDefence_Water:
mask = PlayerBattlePropChangeEventB2C.MASK_WATER_DEFENSE;
break;
case UnitAttributeType.EDefence_Fire:
mask = PlayerBattlePropChangeEventB2C.MASK_FIRE_DEFENSE;
break;
case UnitAttributeType.EDefence_Soil:
mask = PlayerBattlePropChangeEventB2C.MASK_SOIL_DEFENSE;
break;
case UnitAttributeType.ToBoss_CriteRate:
mask = PlayerBattlePropChangeEventB2C.MASK_TOBOSS_CRIT_RATE;
break;
case UnitAttributeType.ToBoss_CriteDamage:
mask = PlayerBattlePropChangeEventB2C.MASK_TOBOSS_CRIT_DAMAGE;
break;
case UnitAttributeType.MonsterRestraint_1:
mask = PlayerBattlePropChangeEventB2C.MASK_MONSTER_RESTRAINT_1;
break;
case UnitAttributeType.MonsterRestraint_2:
mask = PlayerBattlePropChangeEventB2C.MASK_MONSTER_RESTRAINT_2;
break;
case UnitAttributeType.MonsterRestraint_3:
mask = PlayerBattlePropChangeEventB2C.MASK_MONSTER_RESTRAINT_3;
break;
case UnitAttributeType.MonsterRestraint_4:
mask = PlayerBattlePropChangeEventB2C.MASK_MONSTER_RESTRAINT_4;
break;
case UnitAttributeType.MonsterRestraint_5:
mask = PlayerBattlePropChangeEventB2C.MASK_MONSTER_RESTRAINT_5;
break;
//case UnitAttributeType.
//mask = PlayerBattlePropChangeEventB2C.MASK_BREAK_SHIELD;
//break;
default:
break;
}
return mask;
}
private void SyncBattlePropsFields(UnitAttributeType type)
{
ulong mask = GetBattlePropFieldsMask(type);
SyncBattlePropsFields(mask);
}
public virtual void SyncBattlePropsFields(ulong mask)
{
//该功能实现转移至player.
//donothing.
}
private void GenBattlePropsFields(PlayerBattlePropChangeEventB2C evt)
{
XmdsUnitProp UseProp = this.MirrorProp; //this.GetOriginProp();
evt.MaxHP = UseProp.MaxHP;
evt.MoveSpeed = UseProp.MoveSpeed;
evt.HPReborn = UseProp.HPReborn;
//同步Attribute
evt.HPPer = UseProp.HPPer;
evt.Attack = UseProp.MaxAttack;
evt.AttackPer = UseProp.AttackPer;
evt.Def = UseProp.Defence;
evt.DefPer = UseProp.DefencePer;
evt.IgnoreDefensePer = UseProp.IgnoreDefensePer;
evt.CritRate = UseProp.CritRate;
evt.ResCritRate = UseProp.ResCritRate;
evt.CritDamage = UseProp.CritDamage;
evt.IncAllDamage = UseProp.PlayerDamageAdd;
evt.AllDamageReduce = UseProp.PlayerDamageReduce;
evt.CtrlTimeReduce = UseProp.CtrlTimeReduce;
evt.SkillCD = UseProp.SkillCD;
evt.HealEffect = UseProp.HealEffect;
evt.HealedEffect = UseProp.HealedEffect;
evt.SkillDamage = UseProp.SkillDamageAdd;
evt.AttackSpeed = UseProp.AttackSpeed;
evt.ControlUp = UseProp.ControlUp;
evt.GoldAttack = UseProp.ArtifactAttack[(int)ArtifactType.Gold];
evt.WoodAttack = UseProp.ArtifactAttack[(int)ArtifactType.Wood];
evt.WaterAttack = UseProp.ArtifactAttack[(int)ArtifactType.Water];
evt.FireAttack = UseProp.ArtifactAttack[(int)ArtifactType.Fire];
evt.SoilAttack = UseProp.ArtifactAttack[(int)ArtifactType.Soil];
evt.GoldDefense = UseProp.ArtifactDefense[(int)ArtifactType.Gold];
evt.WoodDefense = UseProp.ArtifactDefense[(int)ArtifactType.Wood];
evt.WaterDefense = UseProp.ArtifactDefense[(int)ArtifactType.Water];
evt.FireDefense = UseProp.ArtifactDefense[(int)ArtifactType.Fire];
evt.SoilDefense = UseProp.ArtifactDefense[(int)ArtifactType.Soil];
evt.ToBossCritRate = UseProp.ToBossCritRate;
evt.ToBossCritDamage = UseProp.ToBossCritDamage;
evt.GoldRestraint = UseProp.ArtifactRestraint[(int)ArtifactType.Gold];
evt.WoodRestraint = UseProp.ArtifactRestraint[(int)ArtifactType.Wood];
evt.WaterRestraint = UseProp.ArtifactRestraint[(int)ArtifactType.Water];
evt.FireRestraint = UseProp.ArtifactRestraint[(int)ArtifactType.Fire];
evt.SoilRestraint = UseProp.ArtifactRestraint[(int)ArtifactType.Soil];
evt.GoldResist = UseProp.ArtifactResist[(int)ArtifactType.Gold];
evt.WoodResist = UseProp.ArtifactResist[(int)ArtifactType.Wood];
evt.WaterResist = UseProp.ArtifactResist[(int)ArtifactType.Water];
evt.FireResist = UseProp.ArtifactResist[(int)ArtifactType.Fire];
evt.SoilResist = UseProp.ArtifactResist[(int)ArtifactType.Soil];
evt.PvpKillValue = UseProp.KillValuePer;
evt.YaoQiLevel = UseProp.YaoQiLevel;
evt.NormalAtkLeech = UseProp.NormalAtkLeech;
evt.ActiveAtkLeech = UseProp.ActiveAtkLeech;
evt.ArtifactMainPer = UseProp.ArtifactMainPer;
evt.FieldBossDamageAdd = UseProp.monsterDamageAdd;
evt.MaxHPExt = this.MirrorProp.MaxHP;
evt.DungeonMonsterDamageAdd = UseProp.monsterDamageReduce;
evt.MoveSpeedAddition = UseProp.VelocityAddition;
for(int i = 0; i < (int)UnitFateType.Five; i++)
{
evt.MonsterRestraint[i] = UseProp.MonsterRestraint[i];
}
//// 猎妖属性
evt.monsterAtk = UseProp.monsterAtk;
evt.monsterDef = UseProp.monsterDef;
evt.monsterAtkPer = UseProp.monsterAtkPer;
evt.monsterDefPer = UseProp.monsterDefPer;
}
private void UpdateHateSystem(int intervalMS)
{
if (mHateSystem != null)
{
//定期去除仇恨对象.
mHateSystem.Update(intervalMS);
}
}
private void SendBattlePropsChangeEvt(PlayerBattlePropChangeEventB2C evt)
{
this.mUnit.queueEvent(evt);
}
private void UnderAttackCheck(XmdsVirtual attacker)
{
//单位被攻击,且从PVE状态转为PVP状态,
if (this is XmdsVirtual_Player)
{
var atk = attacker.GetPlayerUnit();
if (atk != null)
{
UnderAttackNotifyB2C evt = new UnderAttackNotifyB2C();
evt.AttackerID = atk.mUnit.ID;
evt.AttackerInfo = atk.mProp.ServerData.BaseInfo;
this.mUnit.queueEvent(evt);
}
}
}
public bool IsAllies(CommonAI.Zone.Formula.IVirtualUnit target, bool includeSelf = true, bool onlyForTeam = false)
{
XmdsVirtual unit = target as XmdsVirtual;
if (unit == null)
{
return false;
}
return IsMember(unit, this.GetCurPKMode(), includeSelf, onlyForTeam);
}
public virtual int GetMaType() { return -1; }
public virtual bool IsLvRepress() { return false; }
public virtual bool IsBoss() { return false; }
public virtual void doEvent(JSGCustomOpType value) {}
public virtual uint GetMasterID() { return 0; }
public virtual InstanceUnit GetMasterUnit() { return null; }
public virtual InstanceUnit GetPetUnit()
{
return null;
}
///
/// 下坐骑.
///
public virtual void TakeOffMount()
{
if (mIsMounted == true)
{
SyncMountStatus(false);
}
}
public int GetHealedEffect()
{
return this.MirrorProp.HealedEffect;
}
public int GetHealEffect()
{
return this.MirrorProp.HealEffect;
}
/** 获得单位职业 */
public XmdsUnitPro GetUnitPro()
{
return this.mProp.ServerData.BaseInfo.ProType;
}
//性别: 0-男,1-女
public int GetUnitSex()
{
return this.mProp.ServerData.BaseInfo.sex;
}
/** 获得宠物天赋加成 */
public virtual int GetPetTalentAddition(UnitFateType type)
{
return ((XmdsUnitProp)mProp.ServerData.Prop).fateValue;
}
public UnitFateType GetUnitFateType()
{
return ((XmdsUnitProp)mProp.ServerData.Prop).fateType;
}
#endregion
}
}