using CommonAI.Zone.Formula; using CommonLang; using System; using XmdsCommon.Plugin; using XmdsCommonServer.Plugin; using XmdsCommonServer.Plugin.XmdsSkillTemplate.DamageCalculator; using XmdsCommonServer.Plugin.XmdsSkillTemplate.Skills; using CommonAI.Zone; using CommonAI.Zone.Helper; using XmdsCommonServer.XLS.Data; using CommonAI.Zone.Instance; using XmdsCommon.EditorData; using XmdsCommonServer.Plugin.Units; using static XmdsCommonSkill.Plugin.Skills.BattleParams; using CommonAI.Data; using static CommonAI.Zone.UnitInfo; using XmdsCommon.Message; using CommonLang.Log; using System.Diagnostics; using System.Collections.Generic; using XmdsCommonServer.Plugin.Base; namespace XmdsCommonSkill.Plugin.Skills { /// /// FileName: XmdsSkillBase.cs /// Author: Alex.Yu /// Corporation:... /// Description: /// DateTime: 2015/6/25 9:32:33 /// #region 战斗数据. public class BattleParams { private static readonly ObjectPool s_ListPool = new ObjectPool(s_ListPool_OnCreate); private XmdsVirtual mAttacker; private XmdsVirtual mHitter; private AttackSource mSource; private GameSkill mGameSkill; private XmdsAttackProperties mProp; private XmdsVirtual.AtkResult mAtkResult; #region 计算结果. private int mThreatValue; //仇恨值 private int mSkillDamagePer; //技能伤害百分百 private int mSkillDamageModify; //技能伤害修改 private int mFinalCritRate; //最终暴击率 private int mFinalDamage; //最终伤害 private int mHitAdd; //命中增加 private int mCritAdd; //暴击增加 private int mDamageModifyAdd; //伤害绝对值增加 private int mSkillDamageAdd; //技能伤害增加 private int mHitResult; //打击结果 private int mHitDamge; //打击伤害 private DamageType mDamageType = DamageType.Damage; #endregion private BattleParams() { } public static BattleParams AllocAutoRelease() { BattleParams ret = s_ListPool.Get(); ret.ReSet(); return ret; } private static BattleParams s_ListPool_OnCreate() { return new BattleParams(); } public void ReSet() { // this.mHitUnits.Clear(); } public void Dispose() { OnDispose(); s_ListPool.Release(this); } private void OnDispose() { mAttacker = null; mHitter = null; mSource = null; mGameSkill = null; mProp = null; mThreatValue = 0; mSkillDamagePer = 0; mSkillDamageModify = 0; mFinalCritRate = 0; mFinalDamage = 0; mHitAdd = 0; mCritAdd = 0; mDamageModifyAdd = 0; mSkillDamageAdd = 0; mHitDamge = 0; mHitResult = 0; mDamageType = DamageType.Damage; } /// /// 攻击者. /// public XmdsVirtual Attacker { set { mAttacker = value; } get { return mAttacker; } } /// /// 被攻击者. /// public XmdsVirtual Hitter { get { return mHitter;} set { mHitter = value;} } /// /// 攻击源信息. /// public AttackSource Source { get {return mSource;} set { mSource = value; mProp = (mSource.Attack.Properties as XmdsAttackProperties); } } /// /// 攻击信息. /// public XmdsAttackProperties AtkProp { get { return mProp; }} public XmdsVirtual.AtkResult AtkResult { get { return mAtkResult; } set { mAtkResult = value; } } /// /// 技能信息. /// public GameSkill GameSkill { get{return mGameSkill;} set { mGameSkill = value; } } /// /// 技能伤害百分比. /// public int SkillDamagePer { get { return mSkillDamagePer; } set{ mSkillDamagePer = value;} } /// /// 技能伤害绝对值. /// public int SkillDamageModify { get { return mSkillDamageModify; } set { mSkillDamageModify = value; } } /// /// 最终技能伤害. /// public int FinalSkillDamage { get { return mFinalDamage; } set { mFinalDamage = value; } } /// /// 最终暴击. /// public int FinalCritRate { get { return mFinalCritRate; } set { mFinalCritRate = value; } } /// /// 威胁值. /// public int ThreatValue { get { return mThreatValue; } set { mThreatValue = value; } } /// /// 暴击增加. /// public int CritAdd { get { return mCritAdd; } set { mCritAdd = value; } } /// /// 命中增加. /// public int HitAdd { get { return mHitAdd; } set { mHitAdd = value; } } /// /// 伤害绝对值增加. /// public int DamageModifyAdd { get { return mDamageModifyAdd; } set { mDamageModifyAdd = value; } } /// /// 使用计算公式类型. /// public DamageType UseDamageType { get { return mDamageType; } set { mDamageType = value; } } /// /// 技能伤害增加. 技能伤害固定值 /// public int SkillDamageAdd { get { return mSkillDamageAdd; } set { mSkillDamageAdd = value; } } /// /// Hit结果,(伤害计算计算BUFF或其他异常状态作用最终效果.) /// public int HitResult { get { return mHitResult; } set { mHitResult = value; } } /// /// 打击伤害(FinalDamage经过暴击计算的值.) /// public int HitDamge { get { return mHitDamge; } set { mHitDamge = value; } } } #endregion public abstract class XmdsSkillBase : UnitSkill { /// /// 技能CD. /// protected static HashMap mSkillCD = new HashMap(); /// /// 技能是否能自动释放. /// protected static HashMap mSkillCanAuto = new HashMap(); #region 回调事件. public delegate void ScriptHandler(BattleParams param); public delegate bool ScriptHandler_Bool(BattleParams param); /// /// 计算闪避回调. /// protected ScriptHandler event_CalHitRateAdd; /// /// 计算暴击回调. /// protected ScriptHandler event_CalCritRateAdd; /// /// 计算技能伤害. /// protected ScriptHandler event_SkillDamagePer; /// /// 计算技能绝对值. /// protected ScriptHandler event_SkillDamageModify; /// /// 获取技能攻击类型(物理、魔法) /// protected ScriptHandler event_GetAttackType; /// /// 计算技能仇恨. /// protected ScriptHandler event_SkillThreatValue; /// /// 计算技能逻辑. /// protected ScriptHandler event_SkillLogic; /// /// 技能附加伤害加成. /// protected ScriptHandler event_DamageModifyAdd; /// /// 是否走伤害流程. /// protected ScriptHandler event_UseDamageType; /// /// 总技能伤害加成. /// protected ScriptHandler event_SkillDamageAdd; /// /// 计算伤害之后的技能逻辑回调. /// protected ScriptHandler event_SkillLogicAfterCalDamage; /// /// 计算最终伤害修改 /// protected ScriptHandler_Bool event_SkillFinalDamageModify; /// /// 计算招架结果类型 /// protected ScriptHandler event_SkillAtkRtl; //技能破定值 protected int mSkillBreakShieldValue; #endregion protected enum EventType : int { HitRateAdd = 1, //命中增加 CritRateAdd = 2, //暴击几率增加 DamagePer = 3, //--技能伤害 DamageModify = 4, //--伤害修改 AttackType = 5, //--攻击类型 ThreadValue = 6, //--仇恨值 SkillLogic = 7, //--技能逻辑 DamageModifyAdd = 8, //附加伤害 UseFormluaType = 9, //走伤害流程 SkillDamageAdd = 10, //技能伤害加成 SkillLogicAftercalDamage = 11, //伤害计算之后逻辑回调 SkillFinalDamageModify = 12, //技能最终伤害修改 GetCalAtkRlt = 13, //获得招架结果 } protected void RegistEvent(EventType type, ScriptHandler callBack) { switch (type) { case EventType.AttackType: event_GetAttackType = callBack; break; case EventType.CritRateAdd: event_CalCritRateAdd = callBack; break; case EventType.HitRateAdd: event_CalHitRateAdd = callBack; break; case EventType.DamagePer: event_SkillDamagePer = callBack; break; case EventType.DamageModify: event_SkillDamageModify = callBack; break; case EventType.ThreadValue: event_SkillThreatValue = callBack; break; case EventType.SkillLogic: event_SkillLogic = callBack; break; case EventType.DamageModifyAdd: event_DamageModifyAdd = callBack; break; case EventType.UseFormluaType: event_UseDamageType = callBack; break; case EventType.SkillDamageAdd: event_SkillDamageAdd = callBack; break; case EventType.SkillLogicAftercalDamage: event_SkillLogicAfterCalDamage = callBack; break; case EventType.GetCalAtkRlt: event_SkillAtkRtl = callBack; break; default: break; } } protected void RegistEvent_Bool(EventType type, ScriptHandler_Bool callBack) { switch (type) { case EventType.SkillFinalDamageModify: event_SkillFinalDamageModify = callBack; break; default: break; } } public override int SkillID { get { return -1; } } protected override void OnBaseInit(GameSkill info, XmdsVirtual unit, ref SkillTemplate template) { //技能CD由配置表控制. template.CoolDownMS = this.GetTargetFormulaValue(info.SkillLevel, this.GetSkillCD(info.SkillID)); //控制是否能自动施放. if (unit != null && unit.mUnit.IsPlayer && this.GetTargetFormulaValue(0, this.GetCanAuto(info.SkillID)) == 0) { info.AutoLaunch = false; } else { info.AutoLaunch = true; } OnInitConfig(); OnInit(info, unit, ref template); this.mSkillBreakShieldValue = XmdsGlobalData.GetSkillBreakShieldValue(info.SkillID); } /// /// 初始化回调,用于子类重铸. /// /// /// /// protected virtual void OnInit(GameSkill info, XmdsVirtual unit, ref SkillTemplate template) { } /** 敌伤害,友治疗,自动获取伤害类型 */ protected CommonAI.Data.DamageType AutoGetDamageType(BattleParams param, CommonAI.Data.DamageType alliesDamageType = CommonAI.Data.DamageType.Heal) { if(param.Attacker.GetCurPKMode() == PKMode.All) { return (param.Attacker == param.Hitter) ? alliesDamageType : CommonAI.Data.DamageType.Damage; } else if (param.Attacker.IsAllies(param.Hitter, true, true)) { //和平模式下,只有队友才有加血 return alliesDamageType; } else if (param.Attacker.GetCurPKMode() == PKMode.Peace && param.Hitter.IsPlayerUnit()) { //和平模式下,非队友,无伤害 return CommonAI.Data.DamageType.None; } return (param.Attacker == param.Hitter) ? alliesDamageType : CommonAI.Data.DamageType.Damage; } public override bool OnCallDamageProcess(XmdsVirtual attacker, XmdsVirtual hitter, AttackSource source, GameSkill gs, ref XmdsVirtual.AtkResult result, ref int damage) { BattleParams param = BattleParams.AllocAutoRelease(); try { //param.AttackRlt = result.rlt; param.Attacker = attacker; param.Hitter = hitter; param.Source = source; param.GameSkill = gs; param.AtkResult = result; try { param = OnDoSkillHitProcess(ref param); } catch (Exception error) { LogError(string.Format("skill {0} attackUID:{1}, HitterUID: {2}, SceneID:{3} SceneUID:{4} OnCallDamageProcess error:{5} - {6}", gs.SkillID, (attacker == null ? "anull" : attacker.mUnit.PlayerUUID), (hitter == null ? "hnull" : hitter.mUnit.PlayerUUID), (attacker == null ? -1 : attacker.mUnit.Parent.GetSceneID()), (attacker == null ? "snull" : attacker.mUnit.Parent.UUID), error.ToString(), error.StackTrace)); } damage = param.HitResult; //System.Console.WriteLine("伤害:" + attacker.mUnit.ID + ", 伤害:" + damage); //仇恨系数. //result.ThreatValue = param.ThreatValue; } finally { param.Dispose(); } result.breakShieldValue = CUtils.CastInt(this.mSkillBreakShieldValue * (1.0f + XmdsUnitProp.PER * attacker.MirrorProp.BreakShieldValue)); return true; } #region 工具API. public virtual int GetTargetFormulaValue(int lv, int[] formula) { return XmdsBattleHelper.GetTargetFormulaValue(lv, formula, SkillID); } public virtual int GetTargetFormulaValue(int lv, XmdsSkillValue formula) { return formula.GetValue(lv); } public override int GetSkillValue(AbstractSkillType type) { return 0; } //public virtual int GetTargetValue(int lv, XmdsSkillValue value) //{ // bool invaild = false; // int ret = value.GetValue(lv, out invaild); // if (invaild) // { // LogError(SkillID, lv); // } // return ret; //} private void LogError(int skill, int lv) { XmdsBattleHelper.LogError(string.Format("XmdsSkillBase get Value Error:skill id = {0} lv = {1}", skill, lv)); } /// /// 算基础伤害. /// /// /// /// /// public virtual int CalDamagePer(int baseValue, int lv) { //return (lv - 1) + baseValue; return baseValue; } public virtual int CalDamagePer(XmdsSkillValue baseValue, int lv) { //return (lv - 1) + baseValue.GetValue(lv); ; return baseValue.GetValue(lv); ; } public virtual int GetThreatValue(int formulaID1, int formulaID2) { return 0; } #endregion #region 常态注册. protected override void OnRegistEvent() { RegistEvents(); } private void RegistEvents() { this.RegistEvent(EventType.DamagePer, OnSkillDamagePerEvent); this.RegistEvent(EventType.DamageModify, OnskillDamageModifyEvent); this.RegistEvent(EventType.AttackType, OnAttackTypeEvent); this.RegistEvent(EventType.ThreadValue, OnThreatValueEvent); this.RegistEvent(EventType.SkillLogic, OnSkillLogicEvent); this.RegistEvent_Bool(EventType.SkillFinalDamageModify, OnSkillFinalDamageModifyEvent); this.RegistEvent(EventType.GetCalAtkRlt, OnGetCalAtkRlt); this.RegistEvent(EventType.SkillLogicAftercalDamage, OnSkillLogicAftercalDamage); } /// /// 得到仇恨. /// /// protected virtual void OnThreatValueEvent(BattleParams param) { param.ThreatValue = 0; } /// /// 得到技能百分比. /// /// protected virtual void OnSkillDamagePerEvent(BattleParams param) { } /// /// 得到技能伤害绝对值. /// /// protected virtual void OnskillDamageModifyEvent(BattleParams param) { } /// /// 得到技能伤害类型. /// /// protected virtual void OnAttackTypeEvent(BattleParams param) { } /// /// 技能特殊逻辑. /// /// protected virtual void OnSkillLogicEvent(BattleParams param) { } protected virtual void OnSkillLogicAftercalDamage(BattleParams param) { } /// /// 技能固定伤害.(最终值) /// reture不执行具体伤害逻辑计算,直接使用给定的伤害值 /// protected virtual bool OnSkillFinalDamageModifyEvent(BattleParams param) { return false; } /// /// 获得招架结果类型 /// /// protected virtual void OnGetCalAtkRlt(BattleParams param) { } #endregion private void OnDispose() { event_CalHitRateAdd = null; event_CalCritRateAdd = null; event_SkillDamagePer = null; event_SkillDamageModify = null; event_GetAttackType = null; event_SkillThreatValue = null; event_SkillLogic = null; event_SkillDamageAdd = null; event_SkillLogicAfterCalDamage = null; event_SkillFinalDamageModify = null; event_UseDamageType = null; event_DamageModifyAdd = null; } #region 新计算流程. protected BattleParams OnDoSkillHitProcess(ref BattleParams param) { OnCalAtkRlt(param); //获得伤害类型. OnAttackType(param); //是否使用伤害公式. OnUseDamageFormula(param); //获得技能伤害百分比. OnGetSkillDamagePer(param); //获得技能固定伤害. OnGetSkillDamageModify(param); //获得技能仇恨系数. OnGetSkillThreatValue(param); //技能逻辑调用. OnGetSkillLogic(param); //绝对伤害和计算伤害,只走一个 if (!OnSkillFinalDamageModify(param)) { switch (param.UseDamageType) { case CommonAI.Data.DamageType.Damage: OnGetDamage(param); break; case CommonAI.Data.DamageType.Heal: OnGetHeal(param); break; case CommonAI.Data.DamageType.None: param.FinalSkillDamage = 0; break; default: break; } //计算暴击效果. OnGetHitDamage(param); } OnDispatchEvent(param); //计算伤害之后的回调. OnGetSkillLogicAfterCalDamage(param); //处理吸血效果 if (param.UseDamageType == CommonAI.Data.DamageType.Damage && param.HitResult > 0) { ProcessAtkLeech(param); } return param; } #region 攻击逻辑结果计算. /// /// 计算攻击结果,闪避,暴击,命中. /// /// private void OnCalAtkRlt(BattleParams param) { //外部已经赋值了, 就不需要再计算了 if (param.Source.OutClientState != (byte)XmdsVirtual.UnitHitEventState.Normal) { return; } XmdsVirtual attacker = param.Attacker; XmdsVirtual hitter = param.Hitter; AttackSource atksource = param.Source; if (atksource.FromExpectTarget == SkillTemplate.CastTarget.Alias || atksource.FromExpectTarget == SkillTemplate.CastTarget.AlliesExcludeSelf || atksource.FromExpectTarget == SkillTemplate.CastTarget.AlliesIncludeSelf || atksource.FromExpectTarget == SkillTemplate.CastTarget.PetForMaster || attacker.GetPlayerUUID() == hitter.GetPlayerUUID()) { //param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.Normal; if (this.IsHealCritAttack(param)) { param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.Crit; } else { param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.Normal; } } else { if (hitter.GetMaType() >= (byte)MonsterVisibleDataB2C.MonsterType.MType4 && IsKillMonsterCrit(param)) { param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.KillMonsterCrit; //log.Info("斩妖暴击:" + attacker.mInfo.Name + ", " + hitter.mInfo.Name); } else { if (this.IsCritAttack(param)) { param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.Crit; } else { param.Source.OutClientState = (byte)XmdsVirtual.UnitHitEventState.Normal; } } } //二次计算一下招架结果 if (event_SkillAtkRtl != null) { event_SkillAtkRtl.Invoke(param); } } #region 是否斩妖的特殊暴击 private bool IsKillMonsterCrit(BattleParams param) { XmdsInstancePlayer attacker = param.Attacker.mUnit as XmdsInstancePlayer; XmdsInstanceMonster hitter = param.Hitter.mUnit as XmdsInstanceMonster; int yaoQiLevel = param.Attacker.MirrorProp.YaoQiLevel; if (attacker != null && hitter != null && yaoQiLevel > 0) { HateSystem.HateInfo hateInfo = param.Hitter.mHateSystem.getHateInfo(param.Attacker.mUnit.ID); if (hateInfo != null && XmdsDataMgr.GetInstance().IsZhanYaoCrit(attacker, param.Hitter.mUnit.Level, yaoQiLevel, ++hateInfo.hitNums, ref param.Source.OutClientStateExt)) { hateInfo.hitNums = 0; return true; } } return false; } #endregion #region 是否暴击. private bool IsCritAttack(BattleParams param) { XmdsVirtual attacker = param.Attacker; XmdsVirtual hitter = param.Hitter; OnFinalCritHandler(param); //如果为普攻,并且下次普攻概率不为0,走这个概率 if(param.GameSkill.SkillType == XmdsSkillType.normalAtk && param.Attacker.MirrorProp.NormalAtkCriteRate > 0) { return XmdsDamageCalculator.IsInRandomRange(param.Attacker.MirrorProp.NormalAtkCriteRate, attacker.mUnit.RandomN, (int)XmdsDamageCalculator.PERER); } else { int critRate = attacker.MirrorProp.CritRate; if (attacker.IsPlayerUnit() && hitter.IsBoss()) { critRate += attacker.MirrorProp.ToBossCritRate; } int finalCriteRate = critRate + param.CritAdd - hitter.MirrorProp.ResCritRate; param.FinalCritRate = finalCriteRate; return XmdsDamageCalculator.IsInRandomRange(finalCriteRate, attacker.mUnit.RandomN, (int)XmdsDamageCalculator.PERER); } } private bool IsHealCritAttack(BattleParams param) { /* 施法者的治疗暴击率 = 治疗暴击系数 * 施法者暴击 /(施法者暴击 + 施法者等级 * 100) +施法者.暴击率 + 被治疗者.受到治疗暴击率 wuyonghui(吴永辉) 07-25 14:56:26 最后个属性目前还没有,以后会有 (指的是“被治疗者.受到治疗暴击率”) */ XmdsVirtual attacker = param.Attacker; float critRate = attacker.MirrorProp.CritRate * XmdsUnitProp.PER; OnFinalCritHandler(param); var finalCriteRate = (int)critRate + param.CritAdd; param.FinalCritRate = finalCriteRate; return XmdsDamageCalculator.IsInRandomRange(finalCriteRate, attacker.mUnit.RandomN, (int)XmdsDamageCalculator.PERER); } private void OnFinalCritHandler(BattleParams param) { if (event_CalCritRateAdd != null) { event_CalCritRateAdd.Invoke(param); } } #endregion #endregion #region 技能攻击效果(逻辑、伤害). private void OnGetSkillDamagePer(BattleParams param) { if (event_SkillDamagePer != null) { event_SkillDamagePer.Invoke(param); } } private void OnGetSkillDamageModify(BattleParams param) { if (event_SkillDamageModify != null) { event_SkillDamageModify.Invoke(param); } } private void OnGetSkillThreatValue(BattleParams param) { if (event_SkillThreatValue != null) { event_SkillThreatValue.Invoke(param); } } private void OnAttackType(BattleParams param) { if (event_GetAttackType != null) { event_GetAttackType.Invoke(param); } } private void OnGetSkillLogic(BattleParams param) { if (event_SkillLogic != null) { event_SkillLogic.Invoke(param); } } protected virtual void OnGetSkillLogicAfterCalDamage(BattleParams param) { if (event_SkillLogicAfterCalDamage != null) { event_SkillLogicAfterCalDamage.Invoke(param); } } //技能最终伤害调整 private bool OnSkillFinalDamageModify(BattleParams param) { if (event_SkillFinalDamageModify != null) { return event_SkillFinalDamageModify.Invoke(param); } return false; } private void OnGetSkillDamageAdd(BattleParams param) { if (event_SkillDamageAdd != null) { event_SkillDamageAdd.Invoke(param); } } protected void OnGetDamage(BattleParams param) { XmdsVirtual attacker = param.Attacker; XmdsVirtual hitter = param.Hitter; OnGetDamageModifyAdd(param); int attackTemp = attacker.MirrorProp.GetFinalAttack(param.Hitter.mUnit.IsMonster); //计算面板物攻和技能加成效果. int attack = XmdsDamageCalculator.GetSkillDamage(attackTemp, param.SkillDamagePer, param.SkillDamageModify + param.DamageModifyAdd); if(attack <= 1 && attackTemp > 10) { string stackInfo = new StackTrace().ToString(); int spellID = (param.Source != null && param.Source.FromSpell != null) ? param.Source.FromSpell.ID : 0; XmdsVirtual.FormatLog(LoggerLevel.ERROR, "攻击异常 : {0}, {1}, {2}, {3}, {4}, {5}, {6}", attackTemp, attack, param.SkillDamagePer, param.SkillDamageModify, param.DamageModifyAdd, spellID, stackInfo); } OnGetSkillDamageAdd(param); param.FinalSkillDamage = XmdsDamageCalculator.GetDamage(attack, attacker, hitter, param.Source) + param.SkillDamageAdd; } //治疗量计算. private void OnGetHeal(BattleParams param) { XmdsVirtual attacker = param.Attacker; XmdsVirtual hitter = param.Hitter; int attack = attacker.MirrorProp.MaxAttack; //计算面板魔攻和技能加成效果. attack = XmdsDamageCalculator.GetSkillDamage(attack, param.SkillDamagePer, param.SkillDamageModify + param.DamageModifyAdd); int v = attack; //治疗量. //v = CUtils.CastInt(attack * (param.Attacker.MirrorProp.HealEffect / XmdsDamageCalculator.PERER + 1)); //受治疗量. //v = CUtils.CastInt(v * (hitter.MirrorProp.HealedEffect / XmdsDamageCalculator.PERER + 1)); param.FinalSkillDamage = -v - param.SkillDamageAdd; //如果治疗效果计算等0,强制转为-1. if (param.FinalSkillDamage == 0) { param.FinalSkillDamage = -1; } else if (param.FinalSkillDamage > 0) { XmdsVirtual.FormatLog("治疗量计算异常值 = {0}", param.FinalSkillDamage); } } /** 处理技能,普攻吸血效果 */ private void ProcessAtkLeech(BattleParams param) { //计算技能吸血和普攻吸血 int damage = param.HitResult; if(damage <= 0) { return; } if (param.Attacker.mUnit.CurrentHP < param.Attacker.mUnit.MaxHP) { if (param.GameSkill.SkillType == XmdsSkillType.normalAtk) { if (param.Attacker.MirrorProp.NormalAtkLeech > 0) { int addHP = CUtils.CastInt(damage * XmdsUnitProp.PER * param.Attacker.MirrorProp.NormalAtkLeech); if (addHP > 0) param.Attacker.mUnit.AddHP(addHP, param.Attacker.mUnit); } } else if (param.GameSkill.SkillType == XmdsSkillType.active) { if (param.Attacker.MirrorProp.ActiveAtkLeech > 0) { int addHP = CUtils.CastInt(damage * XmdsUnitProp.PER * param.Attacker.MirrorProp.ActiveAtkLeech); if (addHP > 0) param.Attacker.mUnit.AddHP(addHP, param.Attacker.mUnit); } } } } private void OnGetHitDamage(BattleParams param) { if (param.Source.OutClientState == (int)XmdsVirtual.UnitHitEventState.KillMonsterCrit) { param.HitDamge = CUtils.CastInt(param.FinalSkillDamage * (param.Source.OutClientStateExt * XmdsUnitProp.PER)); } else if (param.Source.OutClientState == (int)XmdsVirtual.UnitHitEventState.Crit) { int criteDmgRate; if (param.UseDamageType == CommonAI.Data.DamageType.Heal) criteDmgRate = XmdsDamageCalculator.GetCritHealDamage(param.FinalSkillDamage, param.Attacker, param.Hitter); else criteDmgRate = XmdsDamageCalculator.GetCritDamage(param.FinalSkillDamage, param.Attacker, param.Hitter); //MMO-14871: 2021.3.30调整算法 //2021.3.31暂时还原修改 //criteDmgRate = criteDmgRate / 2 + 5000; if (criteDmgRate > XmdsDamageCalculator.PERER) { param.HitDamge = CUtils.CastInt(param.FinalSkillDamage / XmdsDamageCalculator.PERER * criteDmgRate); } } else { param.HitDamge = param.FinalSkillDamage; } } private void OnGetDamageModifyAdd(BattleParams param) { if (event_DamageModifyAdd != null) { event_DamageModifyAdd.Invoke(param); } } private void OnUseDamageFormula(BattleParams param) { if (event_UseDamageType != null) { event_UseDamageType.Invoke(param); } } private void OnDispatchEvent(BattleParams param) { int result = param.HitDamge; XmdsVirtual.AtkResult r = param.AtkResult; param.Attacker.DispatchHitEvents(ref result, param.Attacker, param.Hitter, param.Source, ref r, param.UseDamageType); param.HitResult = result; } #endregion #endregion #region 基础事件监听. protected override void OnBaseDataInit() { base.OnBaseDataInit(); if (SkillID != -1) { XmdsSkillData data = XmdsDataMgr.GetInstance().GetXmdsSkillData(SkillID); if (data != null) { if(data.CDTime != null) { XmdsSkillValue skillCD; InitData(data, out skillCD, XmdsSkillData.XmdsSkillDataKey.CDTime); mSkillCD.Put(SkillID, skillCD); } if (data.canAuto != null) { XmdsSkillValue skillCanAuto; InitData(data, out skillCanAuto, XmdsSkillData.XmdsSkillDataKey.canAuto); mSkillCanAuto.Put(SkillID, skillCanAuto); } if(data.TalentData != null && data.TalentData.Length > 0) { XmdsSkillValue talentInfo; InitData(data, out talentInfo, XmdsSkillData.XmdsSkillDataKey.TalentData); XmdsGlobalData.PutTalentData(SkillID, talentInfo); } if(data.BreakShieldValue > 0) { XmdsGlobalData.PutSkillBreakShieldValue(SkillID, data.BreakShieldValue); } } else { XmdsVirtual.FormatLog(string.Format("XmdsSkillBase get Value Error:skill id = {0}", SkillID)); } } } private XmdsSkillValue GetSkillCD(int skillID) { XmdsSkillValue outSkillCD; mSkillCD.TryGetValue(skillID, out outSkillCD); return (outSkillCD == null) ? XmdsGlobalData.DefaultValue : outSkillCD; } private XmdsSkillValue GetCanAuto(int skillID) { XmdsSkillValue outData; mSkillCanAuto.TryGetValue(skillID, out outData); return (outData == null) ? XmdsGlobalData.DefaultValue : outData; } /// /// MP预判断. /// /// /// /// protected override bool OnUnitLaunchSkillEvent(GameSkill skillInfo, ref InstanceUnit.SkillState skill, XmdsVirtual launcher, ref InstanceUnit.LaunchSkillParam param) { bool ret = true; //if (skill.ID == SkillID) //{ // if (ret == false) // { // //发送提示. // launcher.SendMsgToClient(XmdsConstConfig.TIPS_MP_NOT_ENOUGH); // } //} return ret; } #region 技能自动战斗检测. public override bool SkillAutoLaunchTest(InstanceUnit.SkillState ss, XmdsVirtual launcher) { if (OnSkillAutoLaunchTest(ss, launcher)) { return true; } return false; } /// /// 技能自动战斗自定义检测. /// /// /// /// protected virtual bool OnSkillAutoLaunchTest(InstanceUnit.SkillState ss, XmdsVirtual launcher) { return true; } #endregion /// /// 技能施放完毕执行MP扣除. /// /// /// /// /// protected override int OnUnitLaunchSkillOver(GameSkill info, XmdsVirtual attacker, InstanceUnit.SkillState state) { return 0; } #endregion } public abstract class XmdsPassiveSkillBase : UnitPassiveSkill { /// ///计时器. /// private TimeExpire mTimer = null; private bool mIsCD = false; /// /// CD减少时间. /// private int mDecreaseTotalTimeMS = 0; public override int SkillID { get { return -1; } } protected bool IsCD { set { mIsCD = true; } get { return mIsCD; } } /// /// 获得主技能ID. /// /// public virtual int GetMainSkillID() { return -1; } protected override void OnUpdate(int intervalMS, bool slowRefresh) { //计时器刷新. TimerUpdate(intervalMS); base.OnUpdate(intervalMS, slowRefresh); } protected void GetNearUnitInfo(XmdsVirtual virInfo, float range, ref int alliesCount, ref int enemyCount) { int alliesCountTemp = 0; int enemyCountTemp = 0; using (var list = ListObjectPool.AllocAutoRelease()) { virInfo.mUnit.Parent.getObjectsRoundRange( (obj, dx, dy, dr) => { var u = obj as InstanceUnit; if (u.Virtual is XmdsVirtual_Player && CMath.includeRoundPoint(dx, dy, dr, u.X, u.Y)) { //己方单位. if (virInfo.mUnit.Force == u.Force) { alliesCountTemp++; } else { enemyCountTemp++; } } return true; }, virInfo.mUnit.X, virInfo.mUnit.Y, range, list, virInfo.mUnit.AoiStatus); } alliesCount = alliesCountTemp; enemyCount = enemyCountTemp; } protected List GetNearUnitList(XmdsVirtual virInfo, float range, bool includeSelf = false, int pointForce = 0) { List list = new List(); virInfo.mUnit.Parent.getObjectsRoundRange( (obj, dx, dy, dr) => { if(!includeSelf && obj == virInfo.mUnit) { return false; } var u = obj as InstanceUnit; if (pointForce > 0 && u.Force != pointForce) { return false; } return CMath.includeRoundPoint(dx, dy, dr, u.X, u.Y); }, virInfo.mUnit.X, virInfo.mUnit.Y, range, list, virInfo.mUnit.AoiStatus); return list; } public override int GetCDPassTime() { if (mTimer != null) { return mTimer.PassTimeMS; } return 0; } public override int GetCDTotalTime() { if (mTimer != null) { return mTimer.TotalTimeMS; } return 0; } public override void SetCDPassTime(int timeMS) { if (mTimer != null) { mTimer.Update(timeMS); } } public override int GetSkillValue(AbstractSkillType type) { return 0; } #region Timer相关. protected void SetTimer(int timeMS) { int t = timeMS - GetDecreaseTotalTimeMS(); t = Math.Max(1000, t); if (mTimer == null) { mTimer = new TimeExpire(t); } else { mTimer.Reset(t); } } /// /// 设置CD为true,重算CD. /// protected void RestartTimer() { mIsCD = true; if (mTimer != null) { mTimer.Reset(); } } protected void TimerUpdate(int intervalMS) { if (mTimer != null) { if (mIsCD == true && mTimer.Update(intervalMS)) { mIsCD = false; } } } public virtual int GetTargetFormulaValue(int lv, int[] formula) { return XmdsBattleHelper.GetTargetFormulaValue(lv, formula, SkillID); } public virtual int GetTargetFormulaValue(int lv, XmdsSkillValue formula) { return formula.GetValue(lv); } public override void SetDecreaseTotalTimeMS(int timeMS) { mDecreaseTotalTimeMS = timeMS; } public override int GetDecreaseTotalTimeMS() { return mDecreaseTotalTimeMS; } private void LogError(int skill, int lv) { XmdsBattleHelper.LogError(string.Format("XmdsPassiveSkillBase get Value Error:skill id = {0} lv = {1}", skill, lv)); } #endregion } }