----------------------------------
-- 战斗计算
-- calcHurt 		计算伤害
----------------------------------

local CombatDefine = require("combat.CombatDefine")
local CombatObj = require("combat.CombatObj")
local RoleDefine = require("role.RoleDefine")
local Util = require("common.Util")
local CombatBuff = require("combat.CombatBuff")
local CombatImpl = require("combat.CombatImpl")
-- local SkillExcel = require("excel.skill").skill
local Gm = require("chat.Gm")
-- local BufferExcel = require("excel.buffer").buffer
local BeSkill = require("combat.BeSkill")
local CombatPosLogic = require("combat.CombatPosLogic")
local CmdTypeExcel = require("excel.buffer").cmdType
local WinnerRelicLogic = require("winnerRelic.WinnerRelicLogic")

-- 基础攻击
local function getBaseAtk(attacker)
    local baseAtk = attacker.attr[RoleDefine.ATK]
    return baseAtk
end
-- 攻击加成
local function getAtkRate(attacker)
    local atkRate = attacker.attr[RoleDefine.ATK_RATE] or 0
    return atkRate / 10000
end

function getOutAtk(attacker)
    --local baseAtk = getBaseAtk(attacker)
    --local atkRate = getAtkRate(attacker)
    --local outAtk = baseAtk *(1 + atkRate)
    local outAtk = getBaseAtk(attacker)
    outAtk = outAtk + attacker.attr[RoleDefine.STEAL_ATK]

    local extraAtkVal = BeSkill.GetExtraAttrByShaQi(attacker, RoleDefine.ATK)
    outAtk = outAtk + extraAtkVal

    outAtk = outAtk > 0 and outAtk or 0
    return outAtk
end

-- 护甲
function getDef(defender, skillConfig)
    local def = defender.attr[RoleDefine.DEF]
    local rate = defender.attr[RoleDefine.DEF_RATE]
    def = def *(10000 + rate) / 10000
    def = def + defender.attr[RoleDefine.STEAL_DEF]
    def = def > 0 and def or 0
    return def
end

-- 破甲率
local function getPojia(attacker, defender, skillConfig)
    local hushiHujia = skillConfig and skillConfig.otherArgs.hushiHujia or 0
    -- 职业忽视护甲
    local jobhushiHujia = skillConfig.otherArgs.jobhushiHujia
    if jobhushiHujia then
        for k, v in ipairs(jobhushiHujia[1]) do
            if defender.job == v then
                hushiHujia = hushiHujia + jobhushiHujia[2]
                break
            end
        end
    end

    -- 本阵容职业数破甲率提升
    local jobCamphushiHujia = skillConfig.otherArgs.jobCamphushiHujia 
    if jobCamphushiHujia then
       for _,pos in ipairs(CombatDefine.SIDE2POS[attacker.side]) do
	      local obj = CombatImpl.objList[pos]
          if obj and obj.job == jobCamphushiHujia[1] then
              hushiHujia = hushiHujia + jobCamphushiHujia[2]
          end
       end
    end

    local statusPoJia = BeSkill.getStatusPojia(attacker, defender)

    local pojia = attacker.attr[RoleDefine.POJIA] or 0
    local extraPoJiaVal = BeSkill.GetExtraAttrByShaQi(attacker, RoleDefine.POJIA)
    pojia = pojia + extraPoJiaVal

    local pojia_dk = defender.attr[RoleDefine.POJIA_DK] or 0

    local total = hushiHujia + pojia + statusPoJia - pojia_dk
    total = total < 0 and 0 or total
    return total/10000
end

-- 神圣伤害
local function getShenshengHurtRate(attacker)
    local shenshengHurtRate = attacker.attr[RoleDefine.SHENSHENG_HURT_RATE] or 0
    return shenshengHurtRate / 10000
end


-- 是否格挡
local function isGedang(defender)
    -- return false
    local geDangRate = CombatObj.getValue(defender, RoleDefine.GEDANG)
    if geDangRate <= 0 then
        return false
    end

    local randValue = math.random(0, 10000)
    if geDangRate > randValue then
        return true
    end

    return false
end

-- 减伤率proel
local function getJianshangRate(attacker, defender)
    local jianshangRate = defender.attr[RoleDefine.JIANSHANG_RATE] or 0
    jianshangRate = jianshangRate + attacker.attr[RoleDefine.ATK_JIANSHANG_RATE] or 0
    if attacker.hurtType == CombatDefine.PHY_HURT_TYPE then
        jianshangRate = jianshangRate +(defender.attr[RoleDefine.JIANSHANG_PHY_RATE] or 0)
    elseif attacker.hurtType == CombatDefine.MAGIC_HURT_TYPE then
        jianshangRate = jianshangRate +(defender.attr[RoleDefine.JIANSHANG_MAGIC_RATE] or 0)
    end
    jianshangRate = jianshangRate + CombatObj.getJobJianshangRate(attacker, defender)
    jianshangRate = jianshangRate + CombatObj.getCampJianshangRate(attacker,defender)

    return jianshangRate/10000
end

-- 是否暴击
local function isBaoji(attacker, defender, skillConfig)
    --if CombatImpl.isFanji or CombatImpl.comboType > 0 then
    --    return false
    --end

    if skillConfig.otherArgs and skillConfig.otherArgs.noBaoji == 1 then
        return false
    end

    if CombatBuff.isStatus(attacker, { "feng" }) then
        return false
    end

    local baoji = attacker.attr[RoleDefine.BAOJI] or 0
    baoji = baoji + CombatObj.getStatusBaoji(attacker, defender)
    -- 被动技能暴击加成
    baoji = baoji + BeSkill.getStatusBaoji(attacker, defender, skillConfig)

    local antiBaoji = defender.attr[RoleDefine.ANTI_BAOJI] or 0
    baoji = baoji - antiBaoji
    if skillConfig.otherArgs.addBaoji then
        baoji = baoji + skillConfig.otherArgs.addBaoji
    end

    if skillConfig.otherArgs.selfHpBaoJi then
        local cmpValue =(attacker.hp * 10000) / CombatObj.getHpMax(attacker) - skillConfig.otherArgs.selfHpBaoJi[2]
        if skillConfig.otherArgs.selfHpBaoJi[1] == 1 then
            if cmpValue >= 0 then
                baoji = baoji + skillConfig.otherArgs.selfHpBaoJi[3]
            end
        else
            if cmpValue <= 0 then
                baoji = baoji + skillConfig.otherArgs.selfHpBaoJi[3]
            end
        end
    end

    if skillConfig.otherArgs.addStatusBaoji then
        local status = CombatBuff.getStatus(defender)
        local isStatus = false
        for k, v in ipairs(skillConfig.otherArgs.addStatusBaoji[1]) do
            if status[v] then
                isStatus = true
                break
            end
        end
        if isStatus then
            baoji = baoji + skillConfig.otherArgs.addStatusBaoji[2]
        end
    end

    if skillConfig.otherArgs.addNotBaoji then
        if attacker.notSkillBaoJi and attacker.notSkillBaoJi[skillConfig.id] then
           baoji = baoji + skillConfig.otherArgs.addNotBaoji
        end
    end

    local r = math.random(0, 10000)
    if r <= baoji then
        attacker.notBaoJi = nil
        if attacker.notSkillBaoJi and attacker.notSkillBaoJi[skillConfig.id] then
           attacker.notSkillBaoJi[skillConfig.id] = nil
        end
        return true
    end
    attacker.notBaoJi = true

    if skillConfig.otherArgs.addNotBaoji then
       attacker.notSkillBaoJi = attacker.notSkillBaoJi or {}
       attacker.notSkillBaoJi[skillConfig.id] = true
    end
end

local function getBaojiHurtRate(attacker, defender, skillConfig)
    local baojiRate = 10000
    local isBaoji = isBaoji(attacker, defender, skillConfig)
    if isBaoji then
        baojiRate = attacker.attr[RoleDefine.BAOJI_HURT_RATE]
        if skillConfig.otherArgs and skillConfig.otherArgs.baojiHurtRate then
            baojiRate = baojiRate + skillConfig.otherArgs.baojiHurtRate
        end
        -- 对指定控制状态暴击加成 走的角色属性
        baojiRate = baojiRate + CombatObj.getStatusBaojiHurtRate(attacker, defender)
        -- 对指定状态暴击加成  走的技能状态属性
        if skillConfig.otherArgs.addStatusBaoji and skillConfig.otherArgs.addStatusBaoji[3] then
            local status = CombatBuff.getStatus(defender)
            local isStatus = false
            for k, v in ipairs(skillConfig.otherArgs.addStatusBaoji[1]) do
                if status[v] then
                    isStatus = true
                    break
                end
            end
            if isStatus then
                baojiRate = baojiRate + skillConfig.otherArgs.addStatusBaoji[3]
            end
        end
        baojiRate = baojiRate - defender.attr[RoleDefine.ANTI_BAOJI_HURT_RATE]
        baojiRate = baojiRate < 0 and 10000 or baojiRate
    end
    return isBaoji, baojiRate / 10000
end

-- 分摊比率
FENTAN_TYPE1 = 1 -- 对所有攻击对象进行平摊
local function getFentanRate(skillConfig, targets)
    local fentanParam = skillConfig.otherArgs and skillConfig.otherArgs.fentan
    if fentanParam then
        if fentanParam.type == 1 then
            return 1 / #targets
        end
    end
    return 1
end

--计算怒火层数
local function getnuohuorate(attacker)
    local relicid = attacker.relic.relicID or 0
    local star = attacker.relic.star or 0
    local cengshu = 0
    if attacker.buffcmd["winner_nuhuo"] then
        local nIndex = attacker.buffcmd["winner_nuhuo"][1]
        local tBuffData = attacker.buffer[nIndex]
        if tBuffData.cnt < 10 then
            cengshu = tBuffData.cnt
        end
    end
    local addrate = 1
    if cengshu >= 0 then
         addrate = WinnerRelicLogic.WinnerRelic_GetRateLife(relicid,star)
         addrate = addrate * cengshu
    end
    -- print("getnuohuorate addrate = "..addrate.." cengshu = "..cengshu)
    return addrate
end
-- 被动技能影响的输出率
local function getBeSkillOutRate(attacker, defender, skillConfig, index, targets)
    -- 被动技能影响的输出率
    local outBeSkillRate = BeSkill.getOutAtkRate(attacker, defender)
    outBeSkillRate = 10000 - outBeSkillRate
    outBeSkillRate = outBeSkillRate < 0 and 0 or outBeSkillRate

    return outBeSkillRate / 10000
end

-- 输出率（英雄技能伤害率＋所有技能伤害率）
local function getOutRate(attacker, defender, skillConfig, index, targets)
    -- 普攻技能伤害率
    -- if skillConfig.type == CombatDefine.SKILL_TYPE1 then
    -- return 10000
    -- en

    local hurtRate = index and skillConfig.hurtRate[index] or skillConfig.hurtRate[1]
    if not hurtRate or hurtRate == 0 then
        if CombatImpl.fightMode[1] == CombatDefine.FIGHT_MODE1 then
           return 10000 + CombatImpl.fightMode[4]
        end
        return 10000
    end

    if CombatImpl.fightMode[1] == CombatDefine.FIGHT_MODE1 then
       hurtRate = hurtRate + CombatImpl.fightMode[4]
    end

    local outBeSkillRate = BeSkill.getOutAtkRate2(attacker, skillConfig)
    hurtRate = hurtRate + outBeSkillRate


    -- 战斗模式的伤害加成（死战）
    
    local fentanRate = getFentanRate(skillConfig, targets)
    
    --怒火对伤害的加成
    -- local nuhuo = getnuohuorate(attacker)

    hurtRate = hurtRate * fentanRate

    local confHurtRate = skillConfig.otherArgs.extraHurtRate
    if confHurtRate then
        local r = math.random(0, 10000)
        for k, v in ipairs(confHurtRate) do
            if r <= v[1] then
                hurtRate = hurtRate *(1 + v[2] / 10000)
                break
            else
                r = r - v[1]
            end
        end
    end

    confHurtRate = skillConfig.otherArgs.extraSpeedHurt
    if confHurtRate then
        local atkSpeed = CombatObj.getValue(attacker, RoleDefine.SPEED)
        local defSpeed = CombatObj.getValue(defender, RoleDefine.SPEED)
        if atkSpeed > defSpeed then
            hurtRate = hurtRate + confHurtRate
        end
    end

    if skillConfig.otherArgs.targetHp then
        local cmpValue =(defender.hp * 10000) / CombatObj.getHpMax(defender) - skillConfig.otherArgs.targetHp[2]
        if skillConfig.otherArgs.targetHp[1] == 1 then
            if cmpValue >= 0 then
                hurtRate = hurtRate + skillConfig.otherArgs.targetHp[3]
            end
        else
            if cmpValue <= 0 then
                hurtRate = hurtRate + skillConfig.otherArgs.targetHp[3]
            end
        end
    end

    if skillConfig.otherArgs.selfHpHurt then
        local cmpValue =(attacker.hp * 10000) / CombatObj.getHpMax(attacker) - skillConfig.otherArgs.selfHpHurt[2]
        if skillConfig.otherArgs.selfHpHurt[1] == 1 then
            if cmpValue >= 0 then
                hurtRate = hurtRate + skillConfig.otherArgs.selfHpHurt[3]
            end
        else
            if cmpValue <= 0 then
                hurtRate = hurtRate + skillConfig.otherArgs.selfHpHurt[3]
            end
        end
    end

    if skillConfig.otherArgs.buffHurt then
        local condData = skillConfig.otherArgs.buffHurt
        local targetObj = condData[1] == CombatDefine.ATTACK_SIDE and attacker or defender
        local condCmd = condData[2]
        local buffNum = CombatBuff.getBuffCnt(targetObj, condCmd)
        if buffNum > 0 then
            local baseVal = condData[3]
            local calcMode = condData[4]
            if calcMode == 1 then
                baseVal = baseVal + buffNum
            elseif calcMode == 2 then
                baseVal = baseVal - buffNum
            elseif calcMode == 3 then
                baseVal = baseVal * buffNum
            elseif calcMode == 4 then
                baseVal = baseVal / buffNum
            end

            hurtRate = hurtRate + baseVal
        end
    end


    if skillConfig.type == CombatDefine.SKILL_TYPE1 then
        return hurtRate
    end

    return hurtRate + attacker.attr[RoleDefine.SKILL_HURT_RATE]
end

-- 额外伤害加成百分比
local function getExtraHurtRate(attacker, defender, skillConfig)
    
    local extraHurtRate = 0
    -- 虚弱
    extraHurtRate = extraHurtRate + defender.attr[RoleDefine.XURUO] 
    -- 伤害加成
    extraHurtRate = extraHurtRate + attacker.attr[RoleDefine.HURT_RATE] + CombatPosLogic.getRestrict(attacker,defender,RoleDefine.HURT_RATE)
    -- buffer相关额外伤害加成
    extraHurtRate = extraHurtRate + CombatBuff.getExtraHurtRate(attacker, defender, skillConfig)
    -- 职业相关额外伤害加成
    extraHurtRate = extraHurtRate + CombatObj.getJobHurtRate(attacker, defender)
    -- 状态相关额外伤害加成
    extraHurtRate = extraHurtRate + CombatObj.getStatusHurtRate(attacker, defender)
    -- 被动技能伤害加成
    extraHurtRate = extraHurtRate + BeSkill.getExtraHurtRate(attacker, defender, skillConfig)
    -- 被动技能48伤害加成
    extraHurtRate = extraHurtRate + BeSkill.getExtraHurtRateEx(attacker, defender)
    -- 阵营相关额外伤害加成
    extraHurtRate = extraHurtRate + CombatObj.getCampHurtRate(attacker, defender)

    local jobHurt = skillConfig.otherArgs.jobHurt
    if jobHurt then
        for k, v in ipairs(jobHurt[1]) do
            if defender.job == v then
                extraHurtRate = extraHurtRate + jobHurt[2]
                break
            end
        end
    end

    if skillConfig.otherArgs.statusHurt then
        local status = CombatBuff.getStatus(defender)
        local isStatus = false
        for k, v in ipairs(skillConfig.otherArgs.statusHurt[1]) do
            if status[v] then
                isStatus = true
                break
            end
        end
        if isStatus then
            extraHurtRate = extraHurtRate + skillConfig.otherArgs.statusHurt[2]
        end
    end
    
    if skillConfig.otherArgs.statusHurt2 then
        local status = CombatBuff.getStatus(defender)
        local cmdList = CmdTypeExcel[skillConfig.otherArgs.statusHurt2[1]].cmd
        for k, v in ipairs(cmdList) do
            if status[v] then
                extraHurtRate = extraHurtRate + skillConfig.otherArgs.statusHurt2[2] * #status[v] 
            end
        end
    end

    -- 负面状态 计算伤害率
    if skillConfig.otherArgs.statusHurt3 then
       local bufferCnt = CombatBuff.getCombatBufferCnt(defender, skillConfig.otherArgs.statusHurt3[1])
       if bufferCnt > 0 then
          extraHurtRate = extraHurtRate + skillConfig.otherArgs.statusHurt3[2] * bufferCnt
       end
    end

    return extraHurtRate / 10000
end

-- 额外伤害加成
local function getExtraHurt(attacker, defender, skillConfig)
    local extraHurt = 0
    -- buffer相关额外伤害
    extraHurt = extraHurt + CombatBuff.getExtraHurt(attacker, defender, skillConfig)
    -- 被动技能额外伤害
    extraHurt = extraHurt + BeSkill.getExtraHurt(attacker, defender, skillConfig)


    return extraHurt
end

-- 伤害倍数
local function getHurtMul(skillConfig)
    local mul = 1
    local hurtMul = skillConfig.otherArgs.hurtMul
    if hurtMul then
        local triggerRandVal = hurtMul[1] or 0
        local randVal = math.random(0,10000)
        if triggerRandVal >= randVal then
            mul = hurtMul[2] or 1
        end
    end

    return mul
end

-- 触发格挡后额外减伤
local function triggerGeDangExtraDef(defender)
    local extraDefVal = BeSkill.GetGeDangExtraDef(defender) or 0
    extraDefVal = extraDefVal / 10000
    return extraDefVal
end

-- 被动技能的伤害倍数
local function getBeSkillHurtMul(attacker)
    local hurtMul = BeSkill.GetBeSkillHurtMul(attacker) or 10000
    hurtMul = hurtMul / 10000
    return hurtMul
end

function initAttacker(attacker)
    if attacker.isPet or attacker.isElf then
        return
    end
    attacker.isBaoji = nil
    attacker.baojiHurtRate = nil
    attacker.handleAttr = nil
    CombatObj.setValue(attacker, RoleDefine.ATK_COMBAT_NOW, nil)
    CombatObj.setValue(attacker, RoleDefine.RATE_COMBAT_NOW, nil)
    CombatObj.setValue(attacker, RoleDefine.HURT_COMBAT_NOW, nil)
    attacker.beskill40 = nil
end

function calcPhyHurt(attacker, index, targets, skillConfig)
    local hurt = 0
    local flag = 0
    -- 技能是否无视护甲
    local noHuJia = false
    if skillConfig.otherArgs and skillConfig.otherArgs.noHuJia == 1 then
        noHuJia = true
    end

    local targetCnt = 1
    if skillConfig.otherArgs and skillConfig.otherArgs.hurtFenTan and skillConfig.otherArgs.hurtFenTan[1] == 1 then
        targetCnt = #targets
    end

    local defender = targets[index]
    local outRate = getOutRate(attacker, defender, skillConfig, index, targets)
    outRate = outRate / 10000
    local beSkillHurtRate = getBeSkillOutRate(attacker, defender, skillConfig)

    local pojia = getPojia(attacker, defender, skillConfig)
    local outAtk = attacker.attr[RoleDefine.ATK_COMBAT_NOW] or getOutAtk(attacker, skillConfig)

   
    local def = noHuJia == true and 0 or getDef(defender, skillConfig)

    local jianshangRate = getJianshangRate(attacker, defender)
    local extraHurtRate = getExtraHurtRate(attacker, defender, skillConfig)
    local extraHurt = getExtraHurt(attacker, defender, skillConfig)
    local isBaoji, baojiHurtRate = getBaojiHurtRate(attacker, defender, skillConfig)
    defender.isBaoji = isBaoji
    attacker.isBaoji = attacker.isBaoji or isBaoji
    if isBaoji then
        flag = Util.setBit(flag, CombatDefine.FLAG_BAOJI)
    end

    local shanghaiRate = 1 + extraHurtRate - jianshangRate
    shanghaiRate = shanghaiRate < 0 and 0 or shanghaiRate

    local coefDef = def * (1 - pojia)
    coefDef = coefDef < 0 and 0 or coefDef

    local rateCombatNow = (1 -  coefDef / (coefDef + 600)  ) * shanghaiRate
    hurt = outAtk * outRate * rateCombatNow * baojiHurtRate * beSkillHurtRate / targetCnt
    hurt = hurt + extraHurt
    CombatObj.setValue(attacker, RoleDefine.ATK_COMBAT_NOW, outAtk)
    
    -- 当伤害超过百分比 的 伤害 加深或者减免
    local parcentRate = BeSkill.getHurtPercentRate(attacker, defender, hurt, skillConfig)
    hurt = hurt *(1 + parcentRate / 10000)
    -- 测试用
    if Gm.wudi and attacker.pos <= 10 then
        hurt = 1000000000
    end

    -- 连击模式
    if CombatImpl.comboType > 0 then
       hurt = hurt * CombatImpl.comboHurtRate / 10000
    end

    if defender.fentq then
        hurt = math.ceil(hurt / defender.fentq)
    else
       --修正
	   if hurt <= 10000 then
	   	  hurt = hurt * math.random(100,500)/10000 + hurt
	   else
	   	  hurt = hurt * math.random(100,300)/10000 + hurt
	   end
    end

    hurt = math.ceil(hurt)
    if defender.attr[RoleDefine.HURT_RATE_MAX] > 0 then
        local hurtMax = CombatObj.getHpMax(defender) * defender.attr[RoleDefine.HURT_RATE_MAX] / 10000
        if hurt > hurtMax then
            hurt = hurtMax
        end
    end

    -- 剧情模式
    if CombatImpl.fightMode[1] == CombatDefine.FIGHT_MODE2 then
       local skillList = CombatImpl.fightMode[2]
       for k, v in pairs(skillList) do
          if skillConfig.id == v then
             hurt = defender.hp * 0.9
             break
          end
       end
    end

    --是否触发格挡
    if isGedang(defender) then
        -- hurt = hurt * 0.5
        local extraDefVal = triggerGeDangExtraDef(defender)
        hurt = hurt * (1- (0.5 + extraDefVal))
    end

    local hurtMul = getHurtMul(skillConfig)
    hurt = hurt * hurtMul

    hurtMul = getBeSkillHurtMul(attacker)
    hurt = hurt * hurtMul
    hurt = math.ceil(hurt)

    hurt = math.max(hurt, 1)
    CombatObj.updateValue(attacker, RoleDefine.HURT_COMBAT_NOW, hurt)
    return hurt, flag
end

function calcMagicHurt(attacker, index, targets, skillConfig)
     local hurt = 0
    local flag = 0
    -- 技能是否无视护甲
    local noHuJia = false
    if skillConfig.otherArgs and skillConfig.otherArgs.noHuJia == 1 then
        noHuJia = true
    end

    local targetCnt = 1
    if skillConfig.otherArgs and skillConfig.otherArgs.hurtFenTan and skillConfig.otherArgs.hurtFenTan[1] == 1  then
        targetCnt = #targets
    end

    local defender = targets[index]
    local outRate = getOutRate(attacker, defender, skillConfig, index, targets)
    outRate = outRate / 10000
    local beSkillHurtRate = getBeSkillOutRate(attacker, defender, skillConfig)

    local pojia = getPojia(attacker, defender, skillConfig)
    local outAtk = attacker.attr[RoleDefine.ATK_COMBAT_NOW] or getOutAtk(attacker, skillConfig)

   
    local def = noHuJia == true and 0 or getDef(defender, skillConfig)

    local jianshangRate = getJianshangRate(attacker, defender)
    local extraHurtRate = getExtraHurtRate(attacker, defender, skillConfig)
    local extraHurt = getExtraHurt(attacker, defender, skillConfig)
    local isBaoji, baojiHurtRate = getBaojiHurtRate(attacker, defender, skillConfig)
    defender.isBaoji = isBaoji
    attacker.isBaoji = attacker.isBaoji or isBaoji
    if isBaoji then
        flag = Util.setBit(flag, CombatDefine.FLAG_BAOJI)
    end

    local shanghaiRate = 1 + extraHurtRate - jianshangRate
    shanghaiRate = shanghaiRate < 0 and 0 or shanghaiRate

    local coefDef = def * (1 - pojia)
    coefDef = coefDef < 0 and 0 or coefDef

    local rateCombatNow = (1 -  coefDef / (coefDef + 600)  ) * shanghaiRate
    hurt = outAtk * outRate * rateCombatNow * baojiHurtRate * beSkillHurtRate / targetCnt
    hurt = hurt + extraHurt
    CombatObj.setValue(attacker, RoleDefine.ATK_COMBAT_NOW, outAtk)
    

    -- 当伤害超过百分比 的 伤害 加深或者减免
    local parcentRate = BeSkill.getHurtPercentRate(attacker, defender, hurt, skillConfig)
    hurt = hurt *(1 + parcentRate / 10000)
    -- 测试用
    if Gm.wudi and attacker.pos <= 10 then
        hurt = 1000000000
    end

    -- 连击模式
    if CombatImpl.comboType > 0 then
       hurt = hurt * CombatImpl.comboHurtRate / 10000
    end


    if defender.fentq then
        hurt = math.ceil(hurt / defender.fentq)
    else
       --修正
	   if hurt <= 10000 then
	   	  hurt = hurt * math.random(100,500)/10000 + hurt
	   else
	   	  hurt = hurt * math.random(100,300)/10000 + hurt
	   end
    end

    hurt = math.ceil(hurt)
    if defender.attr[RoleDefine.HURT_RATE_MAX] > 0 then
        local hurtMax = CombatObj.getHpMax(defender) * defender.attr[RoleDefine.HURT_RATE_MAX] / 10000
        if hurt > hurtMax then
            hurt = hurtMax
        end
    end

    -- 剧情模式
    if CombatImpl.fightMode[1] == CombatDefine.FIGHT_MODE2 then
       local skillList = CombatImpl.fightMode[2]
       for k, v in pairs(skillList) do
          if skillConfig.id == v then
             hurt = defender.hp * 0.9
             break
          end
       end
    end

    --是否触发格挡
    if isGedang(defender) then
        -- hurt = hurt * 0.5
        local extraDefVal = triggerGeDangExtraDef(defender)
        hurt = hurt * (1- (0.5 + extraDefVal))
    end

    local hurtMul = getHurtMul(skillConfig)
    hurt = hurt * hurtMul

    hurtMul = getBeSkillHurtMul(attacker)
    hurt = hurt * hurtMul
    hurt = math.ceil(hurt)

    hurt = math.max(hurt, 1)

    CombatObj.updateValue(attacker, RoleDefine.HURT_COMBAT_NOW, hurt)
    return hurt, flag
end

--[[
   防守方最终闪避 =防守方闪避 * (1 - 攻击方额外命中)
]]
local function isShanbi(attacker, index, targets)
    local defender = targets[index]
    local jingzhun = CombatObj.getValue(attacker, RoleDefine.JINGZHUN) + CombatPosLogic.getRestrict(attacker,defender,RoleDefine.JINGZHUN)
    local shanbi = CombatObj.getValue(defender, RoleDefine.SHANBI)

    -- if jingzhun >= 10000 then
    --     local mingZhong = jingzhun - 10000
    --     mingZhong = mingZhong < 0 and 0 or mingZhong
    --     -- 强制设定额外命中不超过 99%
    --     if mingZhong >= 9900 then
    --        mingZhong = 9900
    --     end

    --     local shanbiRatio = 10000 - mingZhong
    --     shanbiRatio = shanbiRatio < 0 and 0 or shanbiRatio

        
    --     shanbi = math.floor(shanbi *(shanbiRatio / 10000))
    -- else
    --     shanbi = 10000 - jingzhun + shanbi
    -- end

    -- local r = math.random(1, 10000)
    -- if r < shanbi then
    --     return true
    -- end
    -- return false

    -- 修改
    local hitVal = math.max(jingzhun - shanbi, 0)
    local r = math.random(1, 10000)
    if r <= hitVal then
        return false
    end

    return true
end

function calcHurt(attacker, index, targets, skillConfig)
    -- 魔兽主动攻击伤害值为战前算出来的固定值
    if skillConfig.type == CombatDefine.SKILL_TYPE4 then
        return attacker.hurt or skillConfig.hurtRate[1], 0
    end

    -- 精灵技能
    if skillConfig.type == CombatDefine.SKILL_TYPE77 then
        local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
        return atk * (skillConfig.hurtRate[1] / 10000), 0
    end


    if not skillConfig.otherArgs.absoluteHit and isShanbi(attacker, index, targets) then
        local flag = 0
        flag = Util.setBit(flag, CombatDefine.FLAG_SHANBI)
        return 0, flag
    end

    if attacker.hurtType == CombatDefine.MAGIC_HURT_TYPE then
        return calcMagicHurt(attacker, index, targets, skillConfig)
    elseif attacker.hurtType == CombatDefine.PHY_HURT_TYPE then
        return calcPhyHurt(attacker, index, targets, skillConfig)
    else
        return calcPhyHurt(attacker, index, targets, skillConfig)
    end
end

-- 额外作用，buff的伤害加成
local function getCmdBuffHurtRate(attacker, defender)
    local extraHurtRate = 0
    if attacker and defender.pos and attacker.pos ~= defender.pos then
        extraHurtRate = extraHurtRate + CombatObj.getJobHurtRate(attacker, defender)
        -- 职业相关额外伤害加成
        extraHurtRate = extraHurtRate + CombatObj.getStatusHurtRate(attacker, defender)
        -- 状态相关额外伤害加成
        extraHurtRate = extraHurtRate + BeSkill.getExtraHurtRateEx(attacker, defender)
        --
    end
    return extraHurtRate / 10000
end



NO_EXCALC_LIST = {
    [7] = 1,
    [8] = 1,
    [11] = 1,
    [13] = 1,
    [14] = 1,
    [15] = 1,
    [16] = 1,
    [17] = 1,
    [18] = 1,
    [19] = 1,
}

function calcHp(attacker, defender, calcType, rate, isAddHp, flag)
    local hp
    -- 魔兽技能是 具体值 不需要 除以一万
    if calcType ~= 8 then
        rate = rate / 10000
    end

    local isCmdBuffHurtRate = nil
    local baoJi = 1
    if calcType == 1 then
        -- 攻击百分比(技能释放者)
        -- local atk = CombatObj.getValue(attacker,RoleDefine.ATK_COMBAT_NOW)
        -- hp = atk * rate
        local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
        local atkRate = CombatObj.getValue(attacker, RoleDefine.ATK_RATE) / 10000
        local extraHurtRate = 0
        if not isAddHp then
            extraHurtRate = defender.attr[RoleDefine.XURUO] / 10000
        end
        hp = atk *(1 + extraHurtRate) * rate
    elseif calcType == 2 then
        -- 生命上限百分比(技能释放者)
        hp = CombatObj.getHpMax(attacker) * rate
    elseif calcType == 3 then
        -- 当前生命百分比(技能释放者)
        hp = attacker.hp * rate
    elseif calcType == 4 then
        -- 损失生命百分比(技能释放者)
        hp =(CombatObj.getHpMax(attacker) - attacker.hp) * rate
    elseif calcType == 5 then
        -- 目标生命百分比(技能目标)
        hp = defender.hp * rate
    elseif calcType == 6 then
        -- 目标生命上限百分比(技能目标)
        hp = CombatObj.getHpMax(defender) * rate
        if flag ~= nil and flag > 0 then
            local atk = CombatObj.getValue(defender, RoleDefine.ATK)
            local atkMax = flag * atk / 10000
            if hp > atkMax then
                hp = atkMax
            end
        end
    elseif calcType == 7 then
        -- 伤害百分比
        local realAttacker = CombatImpl.nowAttacker or attacker
        hp = CombatObj.getValue(realAttacker, RoleDefine.HURT_COMBAT_NOW) * rate
        isCmdBuffHurtRate = true

    elseif calcType == 8 then
        -- 具体值（魔兽用）
        hp = rate
    elseif calcType == 9 then
        -- 当前攻击力百分比
        local atk = CombatObj.getValue(defender, RoleDefine.ATK)
        hp = atk * rate
    elseif calcType == 10 then
        -- 技能暴击时伤害的百分比
        hp = getOutAtk(attacker)
        local baojiRate = 10000
        baojiRate = attacker.attr[RoleDefine.BAOJI_HURT_RATE]
        baojiRate = baojiRate / 10000
        baoJi = baojiRate * rate
    elseif calcType == 11 then
        -- 生命上限百分比不走公式(技能释放者)
        hp = CombatObj.getHpMax(attacker) * rate
    elseif calcType == 12 then
        -- 当前战斗回合造成的总伤害
        if attacker.combatResult[4] then
            hp = - attacker.combatResult[4] * rate
        else
            hp = 1
        end
    elseif calcType == 13 then
        -- 当前生命百分比(技能释放者,不算减伤)
        hp = attacker.hp * rate
    elseif calcType == 14 then
        -- 损失生命百分比(技能释放者,不算减伤)
        hp =(CombatObj.getHpMax(attacker) - attacker.hp) * rate
    elseif calcType == 15 then
        -- 目标生命百分比(技能目标,不算减伤)
        hp = defender.hp * rate
    elseif calcType == 16 then
        -- 目标生命上限百分比(技能目标,不算减伤)
        hp = CombatObj.getHpMax(defender) * rate
        if flag ~= nil and flag > 0 then
            local atk = CombatObj.getValue(defender, RoleDefine.ATK)
            local atkMax = flag * atk / 10000
            if hp > atkMax then
                hp = atkMax
            end
        end
    elseif calcType == 17 then
        -- 回合内 目标上一次对我造成的伤害
        if defender.combatResult[5] and defender.combatResult[5][attacker.pos] then
            hp = - defender.combatResult[5][attacker.pos] * rate
        else
            hp = 1
        end
    elseif calcType == 18 then
        -- 当前攻击力百分比(不算减伤)
        local atk = CombatObj.getValue(defender, RoleDefine.ATK)
        hp = atk * rate
    elseif calcType == 19 then
        -- 攻击百分比(技能释放者,不算减伤)
        local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
        local atkRate = CombatObj.getValue(attacker, RoleDefine.ATK_RATE) / 10000
        local extraHurtRate = 0
        if not isAddHp then
            extraHurtRate = defender.attr[RoleDefine.XURUO] / 10000
        end
        hp = atk *(1 + atkRate) *(1 + extraHurtRate) * rate

    elseif calcType == 20 then
        -- 触发了被动技能类型40的攻击对象的伤害加成
        hp = 0
        if attacker.beskill40 then
            for pos in pairs(attacker.beskill40) do
                local hpAdd = attacker.combatResult[5][pos] or 0
                hp = hp + hpAdd
            end
        end
        hp = - hp * rate
    elseif calcType == 21 then
        -- 回合内 我对目标造成造成的伤害
        if attacker.combatResult[5] and attacker.combatResult[5][defender.pos] then
            hp = - attacker.combatResult[5][defender.pos] * rate
        else
            hp = 1
        end
    elseif calcType == 22 then
        -- 目标生命上限百分比(上限是自己的攻击)
        hp = CombatObj.getHpMax(defender) * rate
        if flag ~= nil and flag > 0 then
            local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
            local atkMax = flag * atk / 10000
            if hp > atkMax then
                hp = atkMax
            end
        end
    elseif calcType == 23 then
        -- 目标损失生命上限百分比  上限时攻击的4倍
        hp = (CombatObj.getHpMax(defender) - defender.hp) * rate
    elseif calcType == 24 then
        -- 目标损失生命上限百分比  上限时攻击的4倍
        hp = CombatObj.getValue(defender, RoleDefine.RATE_COMBAT_NOW) * rate
    elseif calcType == 25 then
        -- 目标当前生命百分比，不超过攻击者攻击力的10倍
        local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
        local nMaxHp = atk * 10
        hp = defender.hp * rate
        if hp > nMaxHp then
            hp = nMaxHp
        end
    elseif calcType == 26 then
        -- 当前攻击者攻击力百分比
        local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
        hp = atk * rate

    elseif calcType == 27 then
        -- 目标当前生命百分比，不超过攻击者攻击力的5倍
        local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
        local nMaxHp = atk * 5
        hp = defender.hp * rate
        if hp > nMaxHp then
            hp = nMaxHp
        end
    end

    if not NO_EXCALC_LIST[calcType] then
        if isAddHp then
            if defender.type == CombatDefine.COMBAT_OBJ_TYPE3 then
                hp = 0
            else
                local hpAddRate = CombatObj.getValue(defender, RoleDefine.HP_ADD_RATE) / 10000
                hp = hp *(1 + hpAddRate)
                hp = hp < 0 and 1 or hp
            end
        --[[
        else
            local defRate = getDef(defender)
            local jianshangRate = getJianshangRate(attacker, defender)
            local rateCombatNow =(1 -(defRate /(defRate + 600))) *(1 - jianshangRate)
            hp = hp * rateCombatNow * baoJi
        ]]--
        end
    end

    if not isAddHp and not isCmdBuffHurtRate then
        -- hp = hp * (1 + getCmdBuffHurtRate(attacker, defender))
    end

    if isAddHp and CombatImpl.comboType > 0  then
        hp = math.ceil(hp * 0.5)
    end
    hp = hp > 0 and hp or 0
    return hp
end

-- 复制原 calcHp(), 用于兼容 combatBuff.lua 之前的逻辑, combatBuff.lua 中使用该函数
function calcHpBuff(attacker, defender, calcType, rate, isAddHp, flag)
    local hp
    -- 魔兽技能是 具体值 不需要 除以一万
    if calcType ~= 8 then
        rate = rate / 10000
    end

    local isCmdBuffHurtRate = nil
    local baoJi = 1
    if calcType == 1 then
        -- 攻击百分比(技能释放者)
        -- local atk = CombatObj.getValue(attacker,RoleDefine.ATK_COMBAT_NOW)
        -- hp = atk * rate
        local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
        local atkRate = CombatObj.getValue(attacker, RoleDefine.ATK_RATE) / 10000
        local extraHurtRate = 0
        if not isAddHp then
            extraHurtRate = defender.attr[RoleDefine.XURUO] / 10000
        end
        hp = atk *(1 + extraHurtRate) * rate
    elseif calcType == 2 then
        -- 生命上限百分比(技能释放者)
        hp = CombatObj.getHpMax(attacker) * rate
    elseif calcType == 3 then
        -- 当前生命百分比(技能释放者)
        hp = attacker.hp * rate
    elseif calcType == 4 then
        -- 损失生命百分比(技能释放者)
        hp =(CombatObj.getHpMax(attacker) - attacker.hp) * rate
    elseif calcType == 5 then
        -- 目标生命百分比(技能目标)
        hp = defender.hp * rate
    elseif calcType == 6 then
        -- 目标生命上限百分比(技能目标)
        hp = CombatObj.getHpMax(defender) * rate
        if flag ~= nil and flag > 0 then
            local atk = CombatObj.getValue(defender, RoleDefine.ATK)
            local atkMax = flag * atk / 10000
            if hp > atkMax then
                hp = atkMax
            end
        end
    elseif calcType == 7 then
        -- 伤害百分比
        local realAttacker = CombatImpl.nowAttacker or attacker
        hp = CombatObj.getValue(realAttacker, RoleDefine.HURT_COMBAT_NOW) * rate
        isCmdBuffHurtRate = true

    elseif calcType == 8 then
        -- 具体值（魔兽用）
        hp = rate
    elseif calcType == 9 then
        -- 当前攻击力百分比
        local atk = CombatObj.getValue(defender, RoleDefine.ATK)
        hp = atk * rate
    elseif calcType == 10 then
        -- 技能暴击时伤害的百分比
        hp = getOutAtk(attacker)
        local baojiRate = 10000
        baojiRate = attacker.attr[RoleDefine.BAOJI_HURT_RATE]
        baojiRate = baojiRate / 10000
        baoJi = baojiRate * rate
    elseif calcType == 11 then
        -- 生命上限百分比不走公式(技能释放者)
        hp = CombatObj.getHpMax(attacker) * rate
    elseif calcType == 12 then
        -- 当前战斗回合造成的总伤害
        if attacker.combatResult[4] then
            hp = - attacker.combatResult[4] * rate
        else
            hp = 1
        end
    elseif calcType == 13 then
        -- 当前生命百分比(技能释放者,不算减伤)
        hp = attacker.hp * rate
    elseif calcType == 14 then
        -- 损失生命百分比(技能释放者,不算减伤)
        hp =(CombatObj.getHpMax(attacker) - attacker.hp) * rate
    elseif calcType == 15 then
        -- 目标生命百分比(技能目标,不算减伤)
        hp = defender.hp * rate
    elseif calcType == 16 then
        -- 目标生命上限百分比(技能目标,不算减伤)
        hp = CombatObj.getHpMax(defender) * rate
        if flag ~= nil and flag > 0 then
            local atk = CombatObj.getValue(defender, RoleDefine.ATK)
            local atkMax = flag * atk / 10000
            if hp > atkMax then
                hp = atkMax
            end
        end
    elseif calcType == 17 then
        -- 回合内 目标上一次对我造成的伤害
        if defender.combatResult[5] and defender.combatResult[5][attacker.pos] then
            hp = - defender.combatResult[5][attacker.pos] * rate
        else
            hp = 1
        end
    elseif calcType == 18 then
        -- 当前攻击力百分比(不算减伤)
        local atk = CombatObj.getValue(defender, RoleDefine.ATK)
        hp = atk * rate
    elseif calcType == 19 then
        -- 攻击百分比(技能释放者,不算减伤)
        local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
        local atkRate = CombatObj.getValue(attacker, RoleDefine.ATK_RATE) / 10000
        local extraHurtRate = 0
        if not isAddHp then
            extraHurtRate = defender.attr[RoleDefine.XURUO] / 10000
        end
        hp = atk *(1 + atkRate) *(1 + extraHurtRate) * rate

    elseif calcType == 20 then
        -- 触发了被动技能类型40的攻击对象的伤害加成
        hp = 0
        if attacker.beskill40 then
            for pos in pairs(attacker.beskill40) do
                local hpAdd = attacker.combatResult[5][pos] or 0
                hp = hp + hpAdd
            end
        end
        hp = - hp * rate
    elseif calcType == 21 then
        -- 回合内 我对目标造成造成的伤害
        if attacker.combatResult[5] and attacker.combatResult[5][defender.pos] then
            hp = - attacker.combatResult[5][defender.pos] * rate
        else
            hp = 1
        end
    elseif calcType == 22 then
        -- 目标生命上限百分比(上限是自己的攻击)
        hp = CombatObj.getHpMax(defender) * rate
        if flag ~= nil and flag > 0 then
            local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
            local atkMax = flag * atk / 10000
            if hp > atkMax then
                hp = atkMax
            end
        end
    elseif calcType == 23 then
        -- 目标损失生命上限百分比  上限时攻击的4倍
        hp = (CombatObj.getHpMax(defender) - defender.hp) * rate
    elseif calcType == 24 then
        -- 目标损失生命上限百分比  上限时攻击的4倍
        hp = CombatObj.getValue(defender, RoleDefine.RATE_COMBAT_NOW) * rate
    elseif calcType == 25 then
        -- 目标当前生命百分比，不超过攻击者攻击力的10倍
        local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
        local nMaxHp = atk * 10
        hp = defender.hp * rate
        if hp > nMaxHp then
            hp = nMaxHp
        end
    elseif calcType == 26 then
        -- 当前攻击者攻击力百分比
        local atk = CombatObj.getValue(attacker, RoleDefine.ATK)
        hp = atk * rate
    end

    if not NO_EXCALC_LIST[calcType] then
        if isAddHp then
            if defender.type == CombatDefine.COMBAT_OBJ_TYPE3 then
                hp = 0
            else
                local hpAddRate = CombatObj.getValue(defender, RoleDefine.HP_ADD_RATE) / 10000
                hp = hp *(1 + hpAddRate)
                hp = hp < 0 and 1 or hp
            end
        --[[
        else
            local defRate = getDef(defender)
            local jianshangRate = getJianshangRate(attacker, defender)
            local rateCombatNow =(1 -(defRate /(defRate + 600))) *(1 - jianshangRate)
            hp = hp * rateCombatNow * baoJi
        ]]--
        end
    end

    if not isAddHp and not isCmdBuffHurtRate then
        hp = hp * (1 + getCmdBuffHurtRate(attacker, defender))
    end

    if isAddHp and CombatImpl.comboType > 0  then
        hp = math.ceil(hp * 0.5)
    end
    hp = hp > 0 and hp or 0
    return hp
end




function calcBufferHp(attacker, defender, bufferID, isAddHp)
    --local conf = BufferExcel[bufferID]
    local conf = CombatBuff.GetBuffConfig(bufferID)
    local args
    if attacker.isPet then
        args = attacker.buffers[bufferID].args
    else
        args = conf.args
    end
    local hp = calcHp(attacker, defender, args[1], args[2], isAddHp)
    if args[5] then
        local limit = args[5] * CombatObj.getValue(attacker, RoleDefine.ATK_COMBAT_NOW) / 10000
        if hp > limit then
            hp = limit
        end
    end
    return hp
end


function calcValue(attacker, defender, calcType, rate)
    local value = 0
    rate = rate / 10000
    if calcType == 1 then
        -- 攻击百分比(技能防守)
        local atk = CombatObj.getValue(defender, RoleDefine.ATK)
        local atkValue = atk * rate
        if attacker.pos == defender.pos then
           value = value + atkValue
        else
           value = value - atkValue
        end
    end
    return value
end