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