Files
2HUCardTDGame/game/scripts/vscripts/system/damage.lua
2021-11-10 08:48:00 -05:00

518 lines
20 KiB
Lua
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 生命移除伤害,只会计算少女之抵抗,参数:单位、目标、百分比值、是否按当前生命值
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