BattleUtil = {} --local BattleUtil = BattleUtil local floor = math.floor local max = math.max local min = math.min --local Random = Random --local RoleDataName = RoleDataName --local BattleEventName = BattleEventName local function clamp(v, minValue, maxValue) if v < minValue then return minValue end if v > maxValue then return maxValue end return v end function BattleUtil.CreateBuffId(skill, index) local id = 0 if skill.preAI then --主动技能生成buff id = skill.owner.uid * 10000 + index else --被动技能生成buff id = skill.owner.uid * 1000 + index end return id end function BattleUtil.CalBaseDamage(atkRole, defRole, baseDamage, baseFactor) local atkData, defData = atkRole.data, defRole.data if not baseFactor then baseFactor = 1 end --伤害 =(基础伤害*(1+己伤害加成-目标伤害减免)*(1+己方属性伤害加成-目标属性伤害减免),10%*己攻) local damage = baseDamage * baseFactor * (1 + atkData:GetData(RoleDataName.DamageBocusFactor)) * (1 - defData:GetData(RoleDataName.DamageReduceFactor)) * (1 + atkData:GetData(RoleDataName.FireDamageBocusFactor)) * (1 - defData:GetData(RoleDataName.FireDamageReduceFactor)) * --火系 (1 + atkData:GetData(RoleDataName.WindDamageBocusFactor)) * (1 - defData:GetData(RoleDataName.WindDamageReduceFactor)) * --风系 (1 + atkData:GetData(RoleDataName.IceDamageBocusFactor)) * (1 - defData:GetData(RoleDataName.IceDamageReduceFactor)) * --冰系 (1 + atkData:GetData(RoleDataName.LandDamageBocusFactor)) * (1 - defData:GetData(RoleDataName.LandDamageReduceFactor)) * --地系 (1 + atkData:GetData(RoleDataName.LightDamageBocusFactor)) * (1 - defData:GetData(RoleDataName.LightDamageReduceFactor)) * --光系 (1 + atkData:GetData(RoleDataName.DarkDamageBocusFactor)) * (1 - defData:GetData(RoleDataName.DarkDamageReduceFactor)) --暗系 return damage end function BattleUtil.CalHit(atkRole, defRole) --命中率 = clamp(自身命中率-敌方闪避率,0,1) local hit = atkRole:GetRoleData(RoleDataName.Hit) local dodge = defRole:GetRoleData(RoleDataName.Dodge) local bHit = Random.Range01() <= clamp(hit - dodge, 0, 1) if bHit then else atkRole.Event:DispatchEvent(BattleEventName.RoleDodge) defRole.Event:DispatchEvent(BattleEventName.RoleBeDodge) end return bHit end function BattleUtil.CalCrit(atkRole, defRole) local bCrit = Random.Range01() <= clamp(atkRole:GetRoleData(RoleDataName.Crit), 0, 1) if bCrit then atkRole.Event:DispatchEvent(BattleEventName.RoleCrit, defRole) defRole.Event:DispatchEvent(BattleEventName.RoleBeCrit, atkRole) end return bCrit end function BattleUtil.CalShield(atkRole, defRole, damage) local buff for i=1, defRole.shield.size do buff = defRole.shield.buffer[i] if damage < buff.shieldValue then buff.shieldValue = buff.shieldValue - damage buff.damageSum = buff.damageSum + damage return 0 else buff.damageSum = buff.damageSum + buff.shieldValue damage = damage - buff.shieldValue buff.shieldValue = 0 buff.disperse = true end end return damage end function BattleUtil.ApplyDamage(atkRole, defRole, damage, bCrit) if not bCrit then bCrit = false end damage = floor(damage + 0.5) local finalDmg = defRole.data:SubValue(RoleDataName.Hp, damage) if finalDmg > 0 then if atkRole then atkRole.Event:DispatchEvent(BattleEventName.RoleDamage, defRole, damage, bCrit) end defRole.Event:DispatchEvent(BattleEventName.RoleBeDamaged, atkRole, damage, bCrit) if defRole:GetRoleData(RoleDataName.Hp) <= 0 then defRole.isDead = true defRole.Event:DispatchEvent(BattleEventName.RoleDead) BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoleDead, defRole) end end return finalDmg end --执行完整的命中,伤害,暴击计算,返回命中,暴击 function BattleUtil.CalDamage(atkRole, defRole, damageType, baseFactor) if atkRole.isTeam and not defRole.isDead then return BattleUtil.ApplyDamage(atkRole, defRole, damageType), false end local bCrit = false local baseDamage bCrit = BattleUtil.CalCrit(atkRole, defRole) local defence = 0 if damageType == 1 then --1 物理 2 魔法 defence = defRole:GetRoleData(RoleDataName.PhysicalDefence) else defence = defRole:GetRoleData(RoleDataName.MagicDefence) end local attack = 0 if atkRole.GetAttackFunc then attack = atkRole.GetAttackFunc(bCrit) else attack = atkRole:GetRoleData(RoleDataName.Attack) end --计算暴击 if bCrit or defRole.isFlagCrit then local critDamageFactor = atkRole:GetRoleData(RoleDataName.CritDamageFactor) baseDamage = attack * critDamageFactor - 0.5 * defence else baseDamage = attack - 0.5 * defence end baseDamage = BattleUtil.CalBaseDamage(atkRole, defRole, baseDamage, baseFactor) baseDamage = max(baseDamage, 0.1 * attack) local func for i=1, atkRole.exCalDmgList.size do func = atkRole.exCalDmgList.buffer[i] baseDamage = func(baseDamage) end baseDamage = BattleUtil.CalShield(atkRole, defRole, baseDamage) local finalDmg = 0 --计算实际造成的扣血 if not defRole.isDead then finalDmg = BattleUtil.ApplyDamage(atkRole, defRole, baseDamage, bCrit) end return finalDmg, bCrit end function BattleUtil.ApplyTreat(castRole, targetRole, value, baseFactor) if not baseFactor then baseFactor = 1 end local maxHp = targetRole:GetRoleData(RoleDataName.MaxHp) local hp = targetRole:GetRoleData(RoleDataName.Hp) local factor = castRole:GetRoleData(RoleDataName.TreatFacter) local treat = min(floor(value * baseFactor * factor + 0.5), maxHp - hp) targetRole.data:AddValue(RoleDataName.Hp, treat) castRole.Event:DispatchEvent(BattleEventName.RoleTreat, targetRole, treat) targetRole.Event:DispatchEvent(BattleEventName.RoleBeTreated, castRole, treat) end function BattleUtil.RandomAction(rand, action) if Random.Range01() <= rand and action then action() end end function BattleUtil.RandomList(arr) if #arr <= 1 then return end local index for i=#arr, 1, -1 do index = Random.RangeInt(1, i) arr[i], arr[index] = arr[index], arr[i] end end function BattleUtil.GetPropertyName(type) if type == 1 then return RoleDataName.Strength elseif type == 2 then return RoleDataName.Energy elseif type == 3 then return RoleDataName.Vitality elseif type == 4 then return RoleDataName.Dexterity elseif type == 5 then return RoleDataName.Speed elseif type == 6 then return RoleDataName.PhysicalAttack elseif type == 7 then return RoleDataName.MagicAttack elseif type == 8 then return RoleDataName.PhysicalDefence elseif type == 9 then return RoleDataName.MagicDefence end end function BattleUtil.GetHPPencent(role) return role:GetRoleData(RoleDataName.Hp) / role:GetRoleData(RoleDataName.MaxHp) * 100 end