/// <summary> /// Suffer the specified caster, target and damage. /// 收到伤害的时候,没有返回值. /// </summary> /// <param name="caster">释放者</param> /// <param name="target">目标者</param> /// <param name="damage">伤害值</param> public void Suffer(ServerNPC caster, ServerNPC sufferer, SelfDescribed des, WarServerNpcMgr npcMgr) { //拿到算子 InjuryOp sufOp = OperatorMgr.instance.getImplement <InjuryOp>(EffectOp.Injury); handled = new Dmg { dmgValue = des.targetEnd.param1, dmgType = (SkillTypeClass)des.targetEnd.param3, isCritical = des.targetEnd.param2 == 1, hitCls = (HurtHitClass)Enum.ToObject(typeof(HurtHitClass), des.targetEnd.param4), }; //TODO: find buff EffectConfigData[] help = null; suf = sufOp.toSuffer(ref handled, sufferer.data, caster.data, help); /// ///更多的事情发生了,比如护盾,吸血,反弹 /// report(caster.UniqueID, sufferer.UniqueID, suf, npcMgr); /// /// --------- 最终结算 -------- /// sufferer.data.rtData.curHp -= (int)handled.dmgValue; /// /// --------- 通知Trigger,OnKilled ---------- /// toTriggerMsg(caster, sufferer, npcMgr); }
public Dmg toTargetDmg(NPCData self, NPCData target, EffectConfigData cfg) { ///-------- 物理伤害强度------ ///先计算自己的物理伤害, float bphyselfhit = Physical_Hit(self, cfg); ///-------- 魔法伤害强度 ------- /// 先计算自己的魔法伤害, float bMagselfhit = Magical_Hit(self, cfg); ///-------- NPC的总攻击强度,是cfg.EffectClass 类型------- float hit = bphyselfhit + bMagselfhit; //---------- 开始计算伤害 --------- float dmg = 0f; switch (cfg.EffectClass) { case SkillTypeClass.Holly: //神圣伤害不减少伤害 dmg = hit; break; case SkillTypeClass.Magical: float magenemyavoid = Magical_Avoid(target, self); dmg = hit * (1.0f - magenemyavoid); break; case SkillTypeClass.Physical: float avdenemyratio = Physical_Avoid(target, self); dmg = hit * (1.0f - avdenemyratio); break; } /// --------- 暴击伤害 ---------- /// float critialRatio = CriticalRatio(self, target, cfg); bool isCri = PseudoRandom.getInstance().happen(critialRatio); if (isCri) { float addtion = AdditionRatio(self, cfg); dmg = dmg * addtion; } Dmg final = new Dmg() { dmgValue = dmg, dmgType = cfg.EffectClass, isCritical = isCri, hitCls = HurtHitClass.None, }; return(final); }
//收到伤害 protected void BeInjured(WarTarAnimParam param) { if (param == null) { ConsoleEx.DebugWarning("BeInjured :: BeInjured :: param is null"); return; } if (param.described != null) { SufferInjureEffect sufInjury = warServerMgr.sufMgr.getImplement <SufferInjureEffect>(EffectOp.Injury); SelfDescribed des = param.described; //记录攻击自己的人的ID data.btData.atkerID = des.src; if (des.target == UniqueId && IsAlive) { ServerNPC caster = npcMgr.GetNPCByUniqueID(des.src); sufInjury.Suffer(caster, this, des, npcMgr); Dmg oneDmg = sufInjury.getHandled; hpMsg.uniqueId = UniqueID; hpMsg.deltaHp = (int)oneDmg.dmgValue; hpMsg.curHp = data.rtData.curHp; hpMsg.totalHp = data.rtData.totalHp; hpMsg.isDamage = true; hpMsg.srcID = des.src; warServerMgr.realServer.proxyCli.NPChp(hpMsg); // if (caster.UniqueID == npcMgr.ActiveHero.UniqueId) // { // if (OnHitByActiveHero != null) // { // Vector3 posIn2D = Vector3.zero; // Vector3 posIn3D = transform.position; // posIn3D.y += 3.5f; // wmMgr.GetUIPos_Ref3DPos (posIn3D, ref posIn2D); // OnHitByActiveHero ((int)oneDmg.dmgValue, true, oneDmg.isCritical, posIn2D); // } // } //检查自己是否被杀 if (data.rtData.curHp <= 0) { BeKillded(); } } } }
SelfDescribed record(int CasterId, int SufferId, Dmg damage, int i) { //统计数据 SelfDescribed des = new SelfDescribed() { src = CasterId, target = SufferId, act = Verb.Strike, srcEnd = null, targetEnd = new EndResult() { param1 = (int)damage.dmgValue, param2 = damage.isCritical ? 1 : 0, param3 = (int)damage.dmgType, param4 = (int)damage.hitCls, } }; return(des); }
public Suf toSuffer(ref Dmg damage, NPCData suffer, NPCData from, EffectConfigData[] resis) { #if DEBUG Utils.Assert(suffer == null, "NPCData suffer can't be null."); Utils.Assert(suffer == null, "NPCData attacker can't be null."); #endif /// /// --------------- Suffer 获取Dot/Hot ------------- /// bool forbid_die = damage.hitCls.check(HurtHitClass.Forbid_Die); if (forbid_die) { if (damage.dmgValue >= suffer.rtData.curHp) { damage.dmgValue = suffer.rtData.curHp - 1; } } //TODO : 错误逻辑,仅仅是测试使用 bool forbid_shield = damage.hitCls.check(HurtHitClass.Forbid_ProtectionShield); if (!forbid_shield) //不无视护盾 { } //要计算反弹吗? bool rebound = false; switch (damage.dmgType) { case SkillTypeClass.Rebound_Hol: case SkillTypeClass.Rebound_Mag: case SkillTypeClass.Rebound_Phy: rebound = false; break; case SkillTypeClass.Holly: case SkillTypeClass.Magical: case SkillTypeClass.Physical: rebound = true; break; } if (rebound) //计算反弹 { } /// /// ---- 计算吸血 ------ /// Suf suf = new Suf() { sufValue = damage, rebValue = null, bdyValue = null, protectVal = null, resDmgType = ResistanteClass.None, }; return(suf); }
/// /// 带AI的伤害技能的实现 /// 但是要不要减伤 /// /// 〖物理伤害〗_敌=〖物理攻击力〗_敌×(1-〖物理免伤〗_自 ) /// 〖法术伤害〗_敌=〖法术攻击力〗_敌×(1-〖法术免伤〗_自 ) /// 〖伤害〗_敌=〖物理伤害〗_敌+〖法术伤害〗_敌 /// /// Self 对 target的技能伤害 /// 只考虑了输出值,并不考虑后续的反弹,护盾等情况 /// public Dmg toTargetDmg(NPCData self, NPCData target, EffectConfigData cfg) { ///-------- 物理伤害强度------ ///先计算自己的物理伤害, float bphyselfhit = Physical_Hit(self, cfg); ///-------- 魔法伤害强度 ------- /// 先计算自己的魔法伤害, float bMagselfhit = Magical_Hit(self, cfg); ///-------- NPC的总攻击强度,是cfg.EffectClass 类型------- float hit = bphyselfhit + bMagselfhit + cfg.Param3; HurtHitClass hitType = (HurtHitClass)Enum.ToObject(typeof(HurtHitClass), cfg.Param7); /// /// --------- 检测 不计算减伤 ----------- /// bool forbidArmer = hitType.check(HurtHitClass.Forbid_Armer); float dmg = 0f; if (forbidArmer) { dmg = hit; } else { switch (cfg.EffectClass) { case SkillTypeClass.Holly: //神圣伤害不减少伤害 dmg = hit; break; case SkillTypeClass.Magical: float magenemyavoid = Magical_Avoid(target, self); dmg = hit * (1.0f - magenemyavoid); break; case SkillTypeClass.Physical: float avdenemyratio = Physical_Avoid(target, self); dmg = hit * (1.0f - avdenemyratio); break; } } dmg = dmg * (1 + cfg.Param4 * Consts.OneThousand); /// --------- 暴击伤害 ---------- /// float critialRatio = CriticalRatio(self, target, cfg); bool isCri = PseudoRandom.getInstance().happen(critialRatio); if (isCri) { float addtion = AdditionRatio(self, cfg); dmg = dmg * addtion; } Dmg final = new Dmg() { dmgValue = dmg, dmgType = cfg.EffectClass, isCritical = isCri, hitCls = hitType, }; return(final); }
/// <summary> /// 处理主动打击其他NPC的时候,触发的事情 /// </summary> /// <param name="CasterId">施法者ID</param> /// <param name="SufferId">撞击者ID</param> /// <param name="idx">几个被撞击者</param> /// <param name="finalTar">是否最终目标</param> /// <param name="maxDis">是否最大距离</param> /// <param name="returnback">返回原处</param> /// <param name="EffectId">效果ID</param> /// <param name="npcMgr">Npc mgr.</param> void HandleOnAttack(int CasterId, int SufferId, int idx, bool finalTar, bool maxDis, bool returnback, int EffectId, WarServerNpcMgr npcMgr) { ServerNPC caster = npcMgr.GetNPCByUniqueID(CasterId); ServerNPC suffer = npcMgr.GetNPCByUniqueID(SufferId); /// /// -------- 获取Effect的配置 ------- /// EffectModel efModel = Core.Data.getIModelConfig <EffectModel>(); EffectConfigData efCfg = efModel.get(EffectId); Utils.Assert(efCfg == null, "Can't find Effect Configure. effect ID = " + EffectId); if (efSelector == null) { efSelector = EffectSufferShared.get(npcMgr); } /// /// 先做技能 /// IEnumerable <ServerNPC> filter = efSelector.Select(caster, new List <ServerNPC> { suffer }, efCfg); if (filter.Any()) { //消失的时候,触发可能的位移 HookNpcDisappearType disappearType = (HookNpcDisappearType)Enum.ToObject(typeof(HookNpcDisappearType), efCfg.Param2); //HookNpcDmgType hookDmgType = (HookNpcDmgType) Enum.ToObject(typeof(HookNpcDmgType), efCfg.Param8); HookNpcMoveType moveType = (HookNpcMoveType)Enum.ToObject(typeof(HookNpcMoveType), efCfg.Param5); /// /// 一定会有伤害,之后,先判定是否消失,如果消失,则再次判定是否移动 /// /// /// ------- 开始运算BulletOp -------- /// OperatorMgr OpMgr = OperatorMgr.instance; BulletNpcOp op = OpMgr.getImplement <BulletNpcOp>(EffectOp.Bullet_NPC); Dmg dmg = op.toTargetDmg(caster.data, suffer.data, efCfg); int moveDirection = 0; bool dis = Disappear(disappearType, idx, finalTar, maxDis, returnback); if (dis) { moveDirection = (int)moveType; } SelfDescribed des = record(CasterId, SufferId, dmg, dis, moveDirection); WarTarAnimParam param = new WarTarAnimParam() { OP = EffectOp.Injury, OringinOP = EffectOp.HookNpc, described = des, }; ///发送消息 npcMgr.SendMessageAsync(CasterId, SufferId, param); } }
/// <summary> /// 处理主动打击其他NPC的时候,触发的事情 /// </summary> void HandleOnAttack(MsgParam msg, WarServerNpcMgr npcMgr) { WarMsgParam warMsg = msg as WarMsgParam; if (warMsg != null) { if (efSelector == null) { efSelector = EffectSufferShared.get(npcMgr); } int CasterId = warMsg.Sender; int SufferId = warMsg.Receiver; int EffectId = warMsg.arg1; int FinalId = warMsg.arg2; //是否是最终目标 bool IsfinalTarget = SufferId == FinalId; /// /// -------- 获取Effect的配置 ------- /// EffectModel efModel = Core.Data.getIModelConfig <EffectModel>(); EffectConfigData efCfg = efModel.get(EffectId); Utils.Assert(efCfg == null, "Can't find Effect Configure. effect ID = " + EffectId); //半径 float radius = efCfg.Param9 * Consts.oneHundred; ServerNPC caster = npcMgr.GetNPCByUniqueID(CasterId); ServerNPC suffer = npcMgr.GetNPCByUniqueID(SufferId); /// /// ----------- 先坐第一步的选择和解析 ------------ /// IEnumerable <ServerNPC> filter = efSelector.Select(caster, new List <ServerNPC> { suffer }, efCfg); if (filter.Count() > 0) { BulletHurtType HurtType = (BulletHurtType)Enum.ToObject(typeof(BulletHurtType), efCfg.Param8); List <ServerNPC> targets = selectTarget(HurtType, suffer, IsfinalTarget, npcMgr, radius); int tarCnt = targets.Count; if (tarCnt > 0) { /// /// ------- 开始运算BulletOp -------- /// OperatorMgr OpMgr = OperatorMgr.instance; BulletNpcOp op = OpMgr.getImplement <BulletNpcOp>(EffectOp.Bullet_NPC); for (int i = 0; i < tarCnt; ++i) { ServerNPC target = targets[i]; //alive ? if (target.data.rtData.curHp > 0) { Dmg damage = op.toTargetDmg(caster.data, target.data, efCfg); SelfDescribed des = record(CasterId, SufferId, damage, i); WarTarAnimParam param = new WarTarAnimParam() { OP = EffectOp.Injury, OringinOP = EffectOp.Bullet_NPC, described = des, }; ///发送消息 npcMgr.SendMessageAsync(CasterId, SufferId, param); } } } } } }
public void Cast(ServerNPC src, IEnumerable <ServerNPC> skTarget, IEnumerable <ServerNPC> target, bool skDirectHurt, List <MsgParam> container) { #if DEBUG Utils.Assert(src == null, "Injury Effect can't find attacker."); Utils.Assert(skCfg == null, "Skill Configure is null in Injury Effect ."); #endif //发起者的信息 WarSrcAnimParam SrcParam = new WarSrcAnimParam() { OP = EffectOp.Injury, ShootAction = skCfg.ShootAction, ShootTime = skCfg.ShootTime, ShootEventTime = skCfg.ShootEventTime, //Debug信息 SkillId = skCfg == null ? -1 : skCfg.ID, }; SelfDescribed SrcDes = new SelfDescribed() { src = src.UniqueID, target = src.UniqueID, act = Verb.Punch, srcEnd = null, targetEnd = new EndResult() { param1 = 0, param2 = 0, param3 = 0, param4 = 0, param8 = skCfg.MissileSpeed, param9 = skCfg.Distance, }, }; SrcParam.described = SrcDes; List <ServerNPC> effTarget = target.ToList(); int count = effTarget.Count; //如果没有目标的时候 if (count == 0) { SrcParam.InjureTar = null; //新建一个目标为空的序列,主要告知skCfg.MissileSpeed 和 skCfg.Distance //该技能没有目标去命中 container.Add(SrcParam); return; } //如果存在目标的时候 InjuryOp cal = OpMgr.getImplement <InjuryOp>(EffectOp.Injury); List <ServerNPC> skillTarget = skTarget.ToList(); /// /// ---- 获取主目标 /// int MainTargetID = 0; int skcount = skillTarget.Count; if (skcount > 0) { ServerNPC npc = skillTarget[0]; MainTargetID = npc.UniqueID; } //count 必定 > 0 //如果是技能直接的伤害 if (skDirectHurt) { WarTarAnimParam[] TarList = new WarTarAnimParam[count]; for (int i = 0; i < count; ++i) { WarTarAnimParam TarParam = new WarTarAnimParam() { OP = EffectOp.Injury, HitAction = cfg.HitAction, SkillId = skCfg.ID, }; ServerNPC tar = effTarget[i]; Dmg dmg = cal.toTargetDmg(src.data, tar.data, cfg); SelfDescribed des = new SelfDescribed() { src = src.UniqueID, target = tar.UniqueID, act = Verb.Punch, srcEnd = null, targetEnd = new EndResult() { param1 = (int)dmg.dmgValue, param2 = dmg.isCritical ? 1 : 0, param3 = (int)dmg.dmgType, param4 = (int)dmg.hitCls, param5 = MainTargetID, param8 = skCfg.MissileSpeed, param9 = skCfg.Distance, }, }; TarParam.described = des; TarList[i] = TarParam; } SrcParam.InjureTar = TarList; container.Add(SrcParam); } else { container.Add(SrcParam); //如果不是技能的伤害,而是buff或者Trigger的伤害 for (int i = 0; i < count; ++i) { WarTarAnimParam TarParam = new WarTarAnimParam() { OP = EffectOp.Injury, HitAction = cfg.HitAction, SkillId = skCfg.ID, }; ServerNPC tar = effTarget[i]; Dmg dmg = cal.toTargetDmg(src.data, tar.data, cfg); SelfDescribed des = new SelfDescribed() { src = src.UniqueID, target = tar.UniqueID, act = Verb.Punch, srcEnd = null, targetEnd = new EndResult() { param1 = (int)dmg.dmgValue, param2 = dmg.isCritical ? 1 : 0, param3 = (int)dmg.dmgType, param4 = (int)dmg.hitCls, param5 = MainTargetID, param8 = skCfg.MissileSpeed, param9 = skCfg.Distance, }, }; TarParam.described = des; container.Add(TarParam); } } }
void report(int CasterId, int SufferId, Suf suf, WarServerNpcMgr npcMgr) { //检测护盾 if (suf.resDmgType.check(ResistanteClass.Protection)) { if (suf.protectVal != null) { //统计数据 SelfDescribed des = new SelfDescribed() { src = CasterId, target = SufferId, //SufferId 应该变为真实的护盾的NPC act = Verb.Punch, srcEnd = null, }; EndResult tarEnd = new EndResult(); Dmg protectDmg = suf.protectVal.Value; tarEnd.param1 = (int)protectDmg.dmgValue; tarEnd.param2 = protectDmg.isCritical ? 1 : 0; tarEnd.param3 = (int)protectDmg.dmgType; tarEnd.param4 = (int)HurtHitClass.None; des.targetEnd = tarEnd; WarTarAnimParam param = new WarTarAnimParam() { OP = EffectOp.Injury, OringinOP = EffectOp.Injury, described = des, }; npcMgr.SendMessageAsync(des.src, des.target, param); } } if (suf.resDmgType.check(ResistanteClass.Bloody) || suf.resDmgType.check(ResistanteClass.Rebound)) { //反弹不为空 if (suf.rebValue != null) { //统计数据 SelfDescribed des = new SelfDescribed() { src = SufferId, target = CasterId, act = Verb.Punch, srcEnd = null, }; EndResult tarEnd = new EndResult(); Dmg rebDmg = suf.rebValue.Value; tarEnd.param1 = (int)rebDmg.dmgValue; tarEnd.param2 = rebDmg.isCritical ? 1 : 0; tarEnd.param3 = (int)rebDmg.dmgType; tarEnd.param4 = (int)HurtHitClass.None; des.targetEnd = tarEnd; WarTarAnimParam param = new WarTarAnimParam() { OP = EffectOp.Injury, OringinOP = EffectOp.Injury, described = des, }; npcMgr.SendMessageAsync(des.src, des.target, param); } //吸血不为空 if (suf.bdyValue != null) { //统计数据 SelfDescribed des = new SelfDescribed() { src = SufferId, target = CasterId, act = Verb.Recover, srcEnd = null, }; EndResult tarEnd = new EndResult(); Dmg bdyDmg = suf.bdyValue.Value; tarEnd.param1 = (int)bdyDmg.dmgValue; tarEnd.param2 = bdyDmg.isCritical ? 1 : 0; tarEnd.param3 = (int)bdyDmg.dmgType; tarEnd.param4 = (int)HurtHitClass.None; des.targetEnd = tarEnd; WarTarAnimParam param = new WarTarAnimParam() { OP = EffectOp.Treat, OringinOP = EffectOp.Treat, described = des, }; npcMgr.SendMessageAsync(des.src, des.target, param); } } }