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