-- 生命移除伤害,只会计算少女之抵抗,参数:单位、目标、百分比值、是否按当前生命值 function UnitDamageHpRemove(caster, target, percent, isCurrentHp) if THTD_IsValid(caster) and THTD_IsValid(target) then local tower = nil if caster:THTD_IsTower() then tower = caster elseif THTD_IsValid(caster.thtd_spawn_unit_owner) and caster.thtd_spawn_unit_owner:THTD_IsTower() then tower = caster.thtd_spawn_unit_owner end local health = target:GetHealth() local damage = 0 if isCurrentHp == true then damage = health * percent / 100 else damage = target:GetMaxHealth() * percent / 100 end local factor = 1.0 if target.unlimited_resist ~= nil then factor = 1 - target.unlimited_resist/100 end if damage * factor >= health then if tower ~= nil then tower:THTD_AddTowerDamage(health) end target:SetHealth(1) local DamageTable = { ability = nil, victim = target, attacker = caster, damage = 10000, damage_type = DAMAGE_TYPE_PURE, damage_flags = DOTA_DAMAGE_FLAG_NONE } ApplyDamage(DamageTable) else target:SetHealth(health - damage * factor) if tower ~= nil then tower:THTD_AddTowerDamage(damage * factor) end end end end -- 强制击杀 function CDOTA_BaseNPC:NpcKill(target) if target == nil or target:IsNull() or target:IsAlive() == false then return end local health = target:GetHealth() target.diseble_buff = true target:ForceKill(false) self:THTD_AddTowerDamage(health) end -- 卡牌秒杀技能,具有统一的上限 function CDOTA_BaseNPC:AbilityKill(target, ability) local tower if self:THTD_IsTower() then tower = self elseif self.thtd_spawn_unit_owner ~= nil and self.thtd_spawn_unit_owner:THTD_IsTower() then tower = self.thtd_spawn_unit_owner else print("----- error : AbilityKill is not a tower cast") return end -- if GameRules.player_bb_buff[playerid]["item_3019"] > 0 and GameRules.player_bb_buff[playerid]["item_3019_enable"] then -- factor = 1 + GameRules.player_bb_buff[playerid]["item_3019"]/100 -- end local damage = tower:GetKillDamage() local damageType = DAMAGE_TYPE_PURE if ability ~= nil then damageType = ability:GetAbilityDamageType() end local DamageTable = { ability = ability, victim = target, attacker = tower, damage = damage, damage_type = damageType, damage_flags = DOTA_DAMAGE_FLAG_NONE } UnitDamageTarget(DamageTable) end -- 获取卡牌秒杀伤害 function CDOTA_BaseNPC:GetKillDamage() return self:THTD_GetStarDamage() * 100 end -- 造成溢出伤害 function THTD_OverDamage(caster, ability, damage, point, range) if not THTD_IsValid(caster) then return end if damage == nil or damage <= 0 then return end local targetRange = range or 400 local damageType = DAMAGE_TYPE_PURE if ability ~= nil then damageType = ability:GetAbilityDamageType() end caster:SetContextThink(DoUniqueString("thtd_over_damage"), function() if GameRules:IsGamePaused() then return 0.03 end local targets = THTD_FindUnitsInRadius(caster,point,range) for k,v in pairs(targets) do local DamageTable = { ability = ability, victim = v, attacker = caster, damage = damage, damage_type = damageType, damage_flags = DOTA_DAMAGE_FLAG_NONE } UnitDamageTarget(DamageTable) local effectIndex = ParticleManager:CreateParticle("particles/heroes/thtd_flandre/abiilty_flandre_02_explosion.vpcf", PATTACH_CUSTOMORIGIN, caster) ParticleManager:SetParticleControl(effectIndex , 0 , v:GetOrigin()) ParticleManager:DestroyParticleSystem(effectIndex,false) end return nil end, 0.1) end -- 汇总式伤害结算 function UnitDamageApply(unit) if unit == nil or unit:IsNull() or unit:IsAlive() == false then return end if unit.thtd_player_index == nil then return end if unit.incoming_damage == nil or unit.incoming_damage == 0 then return end local DamageTable = { ability = nil, victim = unit, attacker = GameRules.HeroList[unit.thtd_player_index], damage = unit.incoming_damage, damage_type = DAMAGE_TYPE_PURE, damage_flags = DOTA_DAMAGE_FLAG_NONE } unit.incoming_damage = 0 ApplyDamage(DamageTable) end -- 汇总式伤害计算,如果isTest为true则返回生命/伤害占比,即目标当前生命值/本次伤害量的值,isAttack为普通攻击 function UnitDamageTarget(DamageTable, isTest, isAttack) local caster = DamageTable.attacker local target = DamageTable.victim -- local ability = DamageTable.ability local damageType = DamageTable.damage_type local damage = DamageTable.damage or 0 local returnNull = 9999 if damage <= 0 then return returnNull end if target == nil or target:IsNull() or target:IsAlive() == false then return returnNull end if target.thtd_damage_lock == true then return returnNull end -- 召唤物继承主人的装备和buff效果 local tower if caster:THTD_IsTower() then tower = caster elseif caster.thtd_spawn_unit_owner ~= nil and caster.thtd_spawn_unit_owner:THTD_IsTower() then tower = caster.thtd_spawn_unit_owner else return returnNull end -- 伤害类型转换 if tower:HasModifier("modifier_junko_01") then damageType = DAMAGE_TYPE_PURE elseif tower:HasModifier("modifier_daiyousei_03") then damageType = DAMAGE_TYPE_MAGICAL elseif tower:HasModifier("modifier_momiji_02") then damageType = DAMAGE_TYPE_PHYSICAL elseif target:HasModifier("modifier_sunny_02_debuff") then damageType = DAMAGE_TYPE_PURE end -- 附加星能伤害(如相机、BOSS键山雏) local extra = tower:GetExtraStarDamagePercentage() if extra >= 1000000 then local down = math.floor(extra/10000) local up = extra - down * 10000 - 5000 if up ~= 0 then damage = damage + tower:THTD_GetStarDamage() * up/100 end if damage > tower:THTD_GetStarDamage() * math.floor(down/100) then damage = damage * (down - math.floor(down/100) * 100)/100 end elseif extra ~= 0 then damage = damage + tower:THTD_GetStarDamage() * extra/100 end -- 计算双抗伤害 if isAttack == true then --普通攻击已经是税后伤害 if damageType ~= DAMAGE_TYPE_PHYSICAL then damage = damage / target:GetPhysicalFactor() if damageType == DAMAGE_TYPE_MAGICAL then damage = damage * target:GetMagicalFactor() end end else if damageType == DAMAGE_TYPE_MAGICAL then damage = damage * target:GetMagicalFactor() elseif damageType == DAMAGE_TYPE_PHYSICAL then damage = damage * target:GetPhysicalFactor() end end -- 装备4件套 if target:GetHealthPercent() > 70 and tower:HasModifier("modifier_item_2009_damage") then damage = damage * 2 end if target:GetHealthPercent() < 30 and tower:HasModifier("modifier_item_2010_damage") then damage = damage * 2 end -- 爆击伤害 if RollPercentage(tower:THTD_GetCritChance()) then damage = damage * (1 + tower:THTD_GetCritDamage()/100) end -- 增伤效果 if damageType == DAMAGE_TYPE_PHYSICAL then -- 攻击者物理增伤 damage = damage * (1 + tower:GetDamageOutgoingPhysical()/100) -- 被攻击者物理伤害加深 damage = damage * (1 + target:GetDamageIncomingPhysical()/100) -- 被攻击者物理伤害抵挡或附加 -- print("---- damage : ", damage) damage = damage - target:GetDamageBlockPhysical() -- print("damage block: ", damage) elseif damageType == DAMAGE_TYPE_MAGICAL then -- 攻击者魔法增伤 damage = damage * (1 + tower:GetDamageOutgoingMagical()/100) -- 被攻击者魔法伤害加深 damage = damage * (1 + target:GetDamageIncomingMagical()/100) -- 被攻击者魔法伤害抵挡或附加 damage = damage - target:GetDamageBlockMagical() elseif damageType == DAMAGE_TYPE_PURE then -- 攻击者纯粹增伤 damage = damage * (1 + tower:GetDamageOutgoingPure()/100) -- 被攻击者纯粹伤害加深 damage = damage * (1 + target:GetDamageIncomingPure()/100) -- 被攻击者纯粹伤害抵挡或附加 damage = damage - target:GetDamageBlockPure() end if damage <= 0 then return returnNull end -- 少女之抵抗 if target.unlimited_resist ~= nil then damage = damage * (1 - target.unlimited_resist/100) end damage = math.floor(damage) -- 伤害统计 if target.incoming_damage == nil then target.incoming_damage = 0 end local health = math.max(0, target:GetHealth() - target.incoming_damage) if isTest ~= true then local towerName = tower:GetUnitName() tower:THTD_AddTowerDamage(math.min(damage, health)) -- 击杀则立即结算 if damage >= health then local isDamageLock = false if target.komachi_04_damage_lock == true then isDamageLock = true elseif target.flandre_damage_lock == true then isDamageLock = true if towerName == "flandre" then if target.flandre_04_lock == true then if DamageTable.ability ~= nil and DamageTable.ability:GetAbilityName() == "thtd_flandre_04" then isDamageLock = false end else isDamageLock = false end end end if isDamageLock == true then target.incoming_damage = target.incoming_damage + math.max(0, health - 100) UnitDamageApply(target) else target.incoming_damage = target.incoming_damage + damage UnitDamageOnKill(tower, target) UnitDamageApply(target) if towerName == "flandre" and damage - health > 100 then THTD_OverDamage(tower, tower:FindAbilityByName("thtd_flandre_02"), damage - health, target:GetOrigin(), 400) end end else target.incoming_damage = target.incoming_damage + damage end return returnNull else return health/damage end end -- 技能的OnKill事件 function UnitDamageOnKill(caster, target) local unitName = caster:GetUnitName() if unitName == "nue" then if caster:FindAbilityByName("thtd_nue_03"):GetLevel() >= 1 then caster:FindAbilityByName("thtd_nue_01"):EndCooldown() caster:FindAbilityByName("thtd_nue_02"):EndCooldown() end elseif unitName == "rumia" then if caster.rumia_01_bonus == nil then caster.rumia_01_bonus = 0 end local max_count = caster:GetAbilityValue("thtd_rumia_01", "max_bonus") if caster:IsPower999() then if caster.rumia_01_bonus < max_count * 10 then caster.rumia_01_bonus = caster.rumia_01_bonus + 1 caster:THTD_AddBasePower(1) end else if caster.rumia_01_bonus < max_count then caster.rumia_01_bonus = caster.rumia_01_bonus + 1 caster:THTD_AddBasePower(1) elseif caster.rumia_01_bonus > max_count then caster:THTD_AddBasePower(-(caster.rumia_01_bonus - max_count)) caster.rumia_01_bonus = max_count end end elseif unitName == "yuyuko" then if caster:HasModifier("modifier_yuyuko_03_think") then if caster.yuyuko_kill_bonus_count == nil then caster.yuyuko_kill_bonus_count = 0 end local max_count = caster:GetAbilityValue("thtd_yuyuko_03", "max_count") local power_bonus = caster:GetAbilityValue("thtd_yuyuko_03", "power_bonus") if caster:IsPower999() then if caster.yuyuko_kill_bonus_count < max_count * 3 then caster.yuyuko_kill_bonus_count = caster.yuyuko_kill_bonus_count + 1 caster:THTD_AddBasePower(power_bonus) end else if caster.yuyuko_kill_bonus_count < max_count then caster.yuyuko_kill_bonus_count = caster.yuyuko_kill_bonus_count + 1 caster:THTD_AddBasePower(power_bonus) elseif caster.yuyuko_kill_bonus_count > max_count then caster:THTD_AddBasePower(-(caster.yuyuko_kill_bonus_count - max_count) * power_bonus) caster.yuyuko_kill_bonus_count = max_count end end end elseif unitName == "koishi" then if caster:HasModifier("passive_koishi_04_attack") then local effectIndex = ParticleManager:CreateParticle("particles/heroes/moluo/ability_moluo03_explosion.vpcf", PATTACH_CUSTOMORIGIN, caster) ParticleManager:SetParticleControl(effectIndex , 0, target:GetOrigin()) ParticleManager:SetParticleControl(effectIndex , 3, target:GetOrigin()) ParticleManager:DestroyParticleSystem(effectIndex,false) end elseif unitName == "sanae" or unitName == "kanako" or unitName == "suwako" then caster:THTD_AddFaith() elseif unitName == "futo" then local modifier = caster:FindModifierByName("modifier_futo_02_buff") if modifier == nil then local ability = caster:FindAbilityByName("thtd_futo_02") if ability:IsActivated() then modifier = ability:ApplyDataDrivenModifier(caster, caster, "modifier_futo_02_buff", {Duration = caster:GetAbilityValue("thtd_futo_02", "duration_time")}) modifier:SetStackCount(1) end else if modifier:GetStackCount() < caster:GetAbilityValue("thtd_futo_02", "max_count") then modifier:IncrementStackCount() end modifier:SetDuration(caster:GetAbilityValue("thtd_futo_02", "duration_time"),false) end end if caster:HasModifier("modifier_shinki_01_buff_kill") and caster.thtd_shinki_01_kill_count < 100 then caster.thtd_shinki_01_kill_count = caster.thtd_shinki_01_kill_count + 1 caster:THTD_AddBasePower(1 * caster.thtd_shinki_01_kill_count, "thtd_shinki_01_kill") caster:FindModifierByName("modifier_shinki_01_buff_kill"):SetStackCount(caster.thtd_shinki_01_kill_count) end if target:HasModifier("modifier_thtd_yuuka_03_death") then local modifier = target:FindModifierByName("modifier_thtd_yuuka_03_death") local yuuka = modifier:GetCaster() local max_count = yuuka:GetAbilityValue("thtd_yuuka_03", "max_count") local damage_up = yuuka:GetAbilityValue("thtd_yuuka_03", "damage_up") if yuuka.thtd_yuuka_03_kill_count == nil then yuuka.thtd_yuuka_03_kill_count = 0 end if yuuka.thtd_yuuka_03_kill_count < max_count then yuuka.thtd_yuuka_03_kill_count = yuuka.thtd_yuuka_03_kill_count + 1 local bonus = yuuka.thtd_yuuka_03_kill_count * damage_up yuuka:AddDamageOutgoingAll(bonus, "thtd_yuuka_03_kill_bonus") yuuka:THTD_AddBaseAttack(bonus, "thtd_yuuka_03_kill_bonus") yuuka:THTD_AddBasePower(bonus, "thtd_yuuka_03_kill_bonus") elseif yuuka.thtd_yuuka_03_kill_count > max_count then yuuka.thtd_yuuka_03_kill_count = max_count yuuka:AddDamageOutgoingAll(max_count * damage_up, "thtd_yuuka_03_kill_bonus") yuuka:THTD_AddBaseAttack(max_count * damage_up, "thtd_yuuka_03_kill_bonus") yuuka:THTD_AddBasePower(max_count * damage_up, "thtd_yuuka_03_kill_bonus") end end end -- 魔法抗性百分比更新,正增负减,如果小于0则设置为0 function CDOTA_BaseNPC:AddMagicalResist(addCount) if addCount == nil or addCount == 0 then return end addCount = math.floor(addCount) if self.base_magical_resistance == nil then self.base_magical_resistance = self:GetBaseMagicalResistanceValue() end if self.magical_resistance_to_zero == true then self:SetBaseMagicalResistanceValue(0) else local magical_resistance = self.base_magical_resistance + addCount self.base_magical_resistance = magical_resistance if magical_resistance > 0 then self:SetBaseMagicalResistanceValue(magical_resistance) else self:SetBaseMagicalResistanceValue(0) end end end -- 移除魔法抗性,即一直设置为0 function CDOTA_BaseNPC:RemoveMagicalResist() self.magical_resistance_to_zero = true self:SetBaseMagicalResistanceValue(0) end -- 物理护甲更新,正增负减,如果小于0则设置为0,注意只用基础护甲,Dota2自带减甲类modifier不可使用 function CDOTA_BaseNPC:AddPhysicalArmor(addCount) if addCount == nil or addCount == 0 then return end addCount = math.floor(addCount*100)/100 if self.base_armor == nil then self.base_armor = self:GetPhysicalArmorBaseValue() end if self.physical_armor_to_zero == true then self:SetPhysicalArmorBaseValue(0) else local armor = self.base_armor + addCount self.base_armor = armor if armor > 0 then self:SetPhysicalArmorBaseValue(armor) else self:SetPhysicalArmorBaseValue(0) end end end -- 移除物理护甲,即强制一直设置为0 function CDOTA_BaseNPC:RemovePhysicalArmor() self.physical_armor_to_zero = true self:SetPhysicalArmorBaseValue(0) end -- 获取物理护甲后的伤害系数 function CDOTA_BaseNPC:GetPhysicalFactor() local armor = self:GetPhysicalArmorValue(false) if armor > 0 then return 1 - (0.06 * armor /(1 + 0.06 * armor)) -- 7.27版本护甲计算 else return 1 - (0.06 * armor /(1 - 0.06 * armor)) -- 7.27版本负护甲计算,负甲增伤 end end -- 获取魔法抗性后的伤害系数 function CDOTA_BaseNPC:GetMagicalFactor() return 1 - self:GetBaseMagicalResistanceValue()/100 end --增加毒的层数,创建或更新对应buff function CDOTA_BaseNPC:AddPoison(stackCount, caster) local modifierName = "modifier_touhoutd_poison" local modifier = self:FindModifierByName(modifierName) if stackCount == nil then stackCount = 1 end if modifier == nil then if stackCount > 0 then if caster == nil then caster = self end modifier = self:AddNewModifier(caster, nil, modifierName, nil) if modifier == nil then return end modifier:SetStackCount(stackCount) end else local count = modifier:GetStackCount() + stackCount if count > 0 then modifier:SetStackCount(count) else self:RemoveModifierByName(modifierName) end end end --获取毒的层数,没有则返回0 function CDOTA_BaseNPC:GetPoisonCount() local modifierName = "modifier_touhoutd_poison" local modifier = self:FindModifierByName(modifierName) if modifier == nil then return 0 else return modifier:GetStackCount() end end