initial commit
This commit is contained in:
2687
scripts/vscripts/system/ai.lua
Executable file
2687
scripts/vscripts/system/ai.lua
Executable file
File diff suppressed because it is too large
Load Diff
634
scripts/vscripts/system/combo.lua
Executable file
634
scripts/vscripts/system/combo.lua
Executable file
@@ -0,0 +1,634 @@
|
||||
local thtd_combo_table =
|
||||
{
|
||||
["cirno"] =
|
||||
{
|
||||
["letty_cirno"] =
|
||||
{
|
||||
["abilityName"] = "thtd_cirno_01",
|
||||
}
|
||||
},
|
||||
["letty"] =
|
||||
{
|
||||
["letty_cirno"] =
|
||||
{
|
||||
["abilityName"] = "thtd_letty_01",
|
||||
}
|
||||
},
|
||||
["lyrica"] =
|
||||
{
|
||||
["lyrica_lunasa_merlin"] =
|
||||
{
|
||||
["delay"] = 3,
|
||||
["duration"] = 3,
|
||||
["abilityName"] = "thtd_lyrica_01",
|
||||
}
|
||||
},
|
||||
["lunasa"] =
|
||||
{
|
||||
["lyrica_lunasa_merlin"] =
|
||||
{
|
||||
["delay"] = 3,
|
||||
["duration"] = 3,
|
||||
}
|
||||
},
|
||||
["merlin"] =
|
||||
{
|
||||
["lyrica_lunasa_merlin"] =
|
||||
{
|
||||
["delay"] = 3,
|
||||
["duration"] = 3,
|
||||
}
|
||||
},
|
||||
["youmu"] =
|
||||
{
|
||||
["yuyuko_youmu"] =
|
||||
{
|
||||
["delay"] = 9,
|
||||
["duration"] = 5,
|
||||
["abilityName"] = "thtd_youmu_01",
|
||||
},
|
||||
["youmu_reisen"] =
|
||||
{
|
||||
["abilityName"] = "thtd_youmu_02",
|
||||
}
|
||||
},
|
||||
["yuyuko"] =
|
||||
{
|
||||
["yuyuko_youmu"] =
|
||||
{
|
||||
["delay"] = 13,
|
||||
["duration"] = 5,
|
||||
["abilityName"] = "thtd_yuyuko_02",
|
||||
},
|
||||
["yuyuko_yukari"] =
|
||||
{
|
||||
["abilityName"] = "thtd_yuyuko_01",
|
||||
}
|
||||
},
|
||||
["marisa"] =
|
||||
{
|
||||
["reimu_marisa"] =
|
||||
{
|
||||
["delay"] = 3,
|
||||
["duration"] = 2,
|
||||
["abilityName"] = "thtd_marisa_01",
|
||||
["abilityName2"] = "thtd_marisa_03",
|
||||
},
|
||||
["marisa_alice"] =
|
||||
{
|
||||
["delay"] = 2,
|
||||
["duration"] = 3,
|
||||
["abilityName"] = "thtd_marisa_02",
|
||||
}
|
||||
},
|
||||
["alice"] =
|
||||
{
|
||||
["marisa_alice"] =
|
||||
{
|
||||
["delay"] = 3,
|
||||
["duration"] = 3,
|
||||
["abilityName"] = "thtd_alice_03",
|
||||
},
|
||||
["reimu_alice"] =
|
||||
{
|
||||
["delay"] = 3,
|
||||
["duration"] = 3,
|
||||
["abilityName"] = "thtd_alice_02",
|
||||
}
|
||||
},
|
||||
["koishi"] =
|
||||
{
|
||||
["koishi_satori"] =
|
||||
{
|
||||
["delay"] = 5,
|
||||
["duration"] = 2,
|
||||
["abilityName"] = "thtd_koishi_01",
|
||||
}
|
||||
},
|
||||
["satori"] =
|
||||
{
|
||||
["koishi_satori"] =
|
||||
{
|
||||
["abilityName"] = "thtd_satori_02",
|
||||
}
|
||||
},
|
||||
["sakuya"] =
|
||||
{
|
||||
["remilia_sakuya"] =
|
||||
{
|
||||
["delay"] = 3,
|
||||
["duration"] = 3,
|
||||
["abilityName"] = "thtd_sakuya_02",
|
||||
},
|
||||
["meirin_sakuya"] =
|
||||
{
|
||||
["abilityName"] = "thtd_sakuya_03",
|
||||
}
|
||||
},
|
||||
["koakuma"] =
|
||||
{
|
||||
["koakuma_patchouli"] =
|
||||
{
|
||||
["delay"] = 7,
|
||||
["duration"] = 3,
|
||||
["abilityName"] = "thtd_koakuma_01",
|
||||
}
|
||||
},
|
||||
["patchouli"] =
|
||||
{
|
||||
["koakuma_patchouli"] =
|
||||
{
|
||||
["delay"] = 5,
|
||||
["duration"] = 2,
|
||||
["abilityName"] = "thtd_patchouli_04",
|
||||
}
|
||||
},
|
||||
["eirin"] =
|
||||
{
|
||||
["eirin_kaguya"] =
|
||||
{
|
||||
["delay"] = 2,
|
||||
["duration"] = 2,
|
||||
["abilityName"] = "thtd_eirin_01",
|
||||
}
|
||||
},
|
||||
["kaguya"] =
|
||||
{
|
||||
["eirin_kaguya"] =
|
||||
{
|
||||
["delay"] = 2,
|
||||
["duration"] = 3,
|
||||
["abilityName"] = "thtd_kaguya_01",
|
||||
}
|
||||
},
|
||||
["yukari"] =
|
||||
{
|
||||
["reimu_yukari"] =
|
||||
{
|
||||
["abilityName"] = "thtd_yukari_01",
|
||||
},
|
||||
["chen_yukari_ran"] =
|
||||
{
|
||||
["abilityName"] = "thtd_yukari_04",
|
||||
}
|
||||
},
|
||||
["remilia"] =
|
||||
{
|
||||
["remilia_sakuya"] =
|
||||
{
|
||||
["abilityName"] = "thtd_remilia_04",
|
||||
},
|
||||
["remilia_flandre"] =
|
||||
{
|
||||
["abilityName"] = "thtd_remilia_02",
|
||||
}
|
||||
},
|
||||
["reimu"] =
|
||||
{
|
||||
["rumia_reimu"] =
|
||||
{
|
||||
["abilityName"] = "thtd_reimu_01",
|
||||
},
|
||||
["reimu_marisa"] =
|
||||
{
|
||||
["abilityName"] = "thtd_reimu_02",
|
||||
},
|
||||
["reimu_yukari"] =
|
||||
{
|
||||
["abilityName"] = "thtd_reimu_04",
|
||||
},
|
||||
},
|
||||
["flandre"] =
|
||||
{
|
||||
["remilia_flandre"] =
|
||||
{
|
||||
["abilityName"] = "thtd_flandre_02",
|
||||
}
|
||||
},
|
||||
["soga"] =
|
||||
{
|
||||
["futo_soga"] =
|
||||
{
|
||||
["abilityName"] = "thtd_soga_03",
|
||||
}
|
||||
},
|
||||
["minamitsu"] =
|
||||
{
|
||||
["nue_minamitsu"] =
|
||||
{
|
||||
["abilityName"] = "thtd_minamitsu_02",
|
||||
}
|
||||
},
|
||||
["futo"] =
|
||||
{
|
||||
["futo_soga"] =
|
||||
{
|
||||
["abilityName"] = "thtd_futo_02",
|
||||
}
|
||||
},
|
||||
["sanae"] =
|
||||
{
|
||||
["suwako_kanako_sanae"] =
|
||||
{
|
||||
["abilityName"] = "thtd_sanae_04",
|
||||
}
|
||||
},
|
||||
["tenshi"] =
|
||||
{
|
||||
["tenshi_iku"] =
|
||||
{
|
||||
["abilityName"] = "thtd_tenshi_03",
|
||||
}
|
||||
},
|
||||
["mokou"] =
|
||||
{
|
||||
["mokou_keine"] =
|
||||
{
|
||||
["abilityName"] = "thtd_mokou_01",
|
||||
}
|
||||
},
|
||||
["reisen"] =
|
||||
{
|
||||
["youmu_reisen"] =
|
||||
{
|
||||
["abilityName"] = "thtd_reisen_02",
|
||||
}
|
||||
},
|
||||
["utsuho"] =
|
||||
{
|
||||
["utsuho_rin"] =
|
||||
{
|
||||
["abilityName"] = "thtd_utsuho_01",
|
||||
}
|
||||
},
|
||||
["keine"] =
|
||||
{
|
||||
["mokou_keine"] =
|
||||
{
|
||||
["abilityName"] = "thtd_keine_03",
|
||||
}
|
||||
},
|
||||
["ran"] =
|
||||
{
|
||||
["chen_yukari_ran"] =
|
||||
{
|
||||
["abilityName"] = "thtd_ran_03",
|
||||
}
|
||||
},
|
||||
["yoshika"] =
|
||||
{
|
||||
["yoshika_seiga"] =
|
||||
{
|
||||
["abilityName"] = "thtd_yoshika_01",
|
||||
}
|
||||
},
|
||||
["rumia"] =
|
||||
{
|
||||
["rumia_reimu"] =
|
||||
{
|
||||
["abilityName"] = "thtd_rumia_04",
|
||||
}
|
||||
},
|
||||
["meirin"] =
|
||||
{
|
||||
["meirin_sakuya"] =
|
||||
{
|
||||
["abilityName"] = "thtd_meirin_02",
|
||||
}
|
||||
},
|
||||
["iku"] =
|
||||
{
|
||||
["tenshi_iku"] =
|
||||
{
|
||||
["abilityName"] = "thtd_iku_01",
|
||||
}
|
||||
},
|
||||
["junko"] =
|
||||
{
|
||||
["junko_hecatia"] =
|
||||
{
|
||||
["abilityName"] = "thtd_junko_01",
|
||||
}
|
||||
},
|
||||
["hecatia"] =
|
||||
{
|
||||
["junko_hecatia"] =
|
||||
{
|
||||
["abilityName"] = "thtd_hecatia_03",
|
||||
}
|
||||
},
|
||||
["daiyousei"] =
|
||||
{
|
||||
["daiyousei_cirno"] =
|
||||
{
|
||||
["abilityName"] = "thtd_daiyousei_03",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
function HasCombo(combo,name)
|
||||
for k,v in pairs(combo) do
|
||||
if k == name then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function CDOTA_BaseNPC:THTD_GetComboVoice(comboName)
|
||||
local data = thtd_combo_table[self:GetUnitName()][comboName]
|
||||
if data ~= nil and data["delay"] ~= nil then
|
||||
data["comboName"] = comboName
|
||||
else
|
||||
data = nil
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
-- 设置组合技能的生效或关闭,返回组合语音数据组,组合影响:升级技能为2级(可设置此等级下光环开启)、增加buff、返回语音。(和或)
|
||||
function CDOTA_BaseNPC:THTD_Set_Combo(combo)
|
||||
local comboVoiceTable = {}
|
||||
|
||||
local unitName = self:GetUnitName()
|
||||
local comboList = thtd_combo_table[unitName]
|
||||
if comboList == nil then
|
||||
combo = {}
|
||||
return comboVoiceTable
|
||||
end
|
||||
|
||||
for k,v in pairs(comboList) do
|
||||
local isChange = false
|
||||
|
||||
if v["abilityName"] ~= nil then
|
||||
local ability = self:FindAbilityByName(v["abilityName"])
|
||||
if ability == nil then
|
||||
print("----------- "..unitName..": combo error, combo: "..k..", ability: "..v["abilityName"]..", ability is nil")
|
||||
combo = {}
|
||||
return comboVoiceTable
|
||||
end
|
||||
|
||||
if ability:IsActivated() then
|
||||
if HasCombo(combo, k) then
|
||||
-- buff等级,如果为1,则仅开启buff不升级,否则升级,名称格式固定
|
||||
local buffOrLevel = ability:GetSpecialValueFor("has_combo_buff")
|
||||
if buffOrLevel > 0 and self:HasModifier("modifier_"..v["abilityName"].."_combo_buff") == false then
|
||||
isChange = true
|
||||
ability:ApplyDataDrivenModifier(self, self, "modifier_"..v["abilityName"].."_combo_buff", nil)
|
||||
end
|
||||
|
||||
if ability:GetLevel() ~= 2 and buffOrLevel ~= 1 then
|
||||
isChange = true
|
||||
ability:SetLevel(2)
|
||||
self[v["abilityName"].."bonus_level"] = nil
|
||||
|
||||
-- 升级后是否存在光环技能,名称格式固定
|
||||
local auraName = "modifier_"..v["abilityName"].."_aura"
|
||||
local auraLevel = ability:GetSpecialValueFor("open_aura_level") --开启等级要求
|
||||
if auraLevel == 2 and self:HasModifier(auraName) == false then
|
||||
ability:ApplyDataDrivenModifier(self, self, auraName, nil)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- buff等级,如果为1,则仅开启buff不升级,否则升级
|
||||
local buffOrLevel = ability:GetSpecialValueFor("has_combo_buff")
|
||||
if buffOrLevel > 0 and self:HasModifier("modifier_"..v["abilityName"].."_combo_buff") then
|
||||
isChange = true
|
||||
self:RemoveModifierByName("modifier_"..v["abilityName"].."_combo_buff")
|
||||
end
|
||||
|
||||
if ability:GetLevel() > 1 and buffOrLevel ~= 1 then
|
||||
isChange = true
|
||||
ability:SetLevel(1)
|
||||
self[v["abilityName"].."bonus_level"] = nil
|
||||
local auraName = "modifier_"..v["abilityName"].."_aura"
|
||||
local auraLevel = ability:GetSpecialValueFor("open_aura_level")
|
||||
if auraLevel > 1 and self:HasModifier(auraName) then
|
||||
self:RemoveModifierByName(auraName)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if v["abilityName2"] ~= nil then
|
||||
local ability = self:FindAbilityByName(v["abilityName2"])
|
||||
if ability == nil then
|
||||
print("----------- "..unitName..": combo error, combo: "..k..", ability: "..v["abilityName2"]..", ability is nil")
|
||||
combo = {}
|
||||
return comboVoiceTable
|
||||
end
|
||||
|
||||
if ability:IsActivated() then
|
||||
if HasCombo(combo, k) then
|
||||
-- buff等级,如果为1,则仅开启buff不升级,否则升级,名称格式固定
|
||||
local buffOrLevel = ability:GetSpecialValueFor("has_combo_buff")
|
||||
if buffOrLevel > 0 and self:HasModifier("modifier_"..v["abilityName2"].."_combo_buff") == false then
|
||||
isChange = true
|
||||
ability:ApplyDataDrivenModifier(self, self, "modifier_"..v["abilityName2"].."_combo_buff", nil)
|
||||
end
|
||||
|
||||
if ability:GetLevel() ~= 2 and buffOrLevel ~= 1 then
|
||||
isChange = true
|
||||
ability:SetLevel(2)
|
||||
self[v["abilityName2"].."bonus_level"] = nil
|
||||
|
||||
-- 升级后是否存在光环技能,名称格式固定
|
||||
local auraName = "modifier_"..v["abilityName2"].."_aura"
|
||||
local auraLevel = ability:GetSpecialValueFor("open_aura_level")
|
||||
if auraLevel == 2 and self:HasModifier(auraName) == false then
|
||||
ability:ApplyDataDrivenModifier(self, self, auraName, nil)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- buff等级,如果为1,则仅开启buff不升级,否则升级
|
||||
local buffOrLevel = ability:GetSpecialValueFor("has_combo_buff")
|
||||
if buffOrLevel > 0 and self:HasModifier("modifier_"..v["abilityName2"].."_combo_buff") then
|
||||
isChange = true
|
||||
self:RemoveModifierByName("modifier_"..v["abilityName2"].."_combo_buff")
|
||||
end
|
||||
|
||||
if ability:GetLevel() > 1 and buffOrLevel ~= 1 then
|
||||
isChange = true
|
||||
ability:SetLevel(1)
|
||||
self[v["abilityName2"].."bonus_level"] = nil
|
||||
local auraName = "modifier_"..v["abilityName2"].."_aura"
|
||||
local auraLevel = ability:GetSpecialValueFor("open_aura_level")
|
||||
if auraLevel > 1 and self:HasModifier(auraName) then
|
||||
self:RemoveModifierByName(auraName)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if isChange then
|
||||
local voiceData = self:THTD_GetComboVoice(k)
|
||||
if voiceData ~= nil then
|
||||
table.insert(comboVoiceTable, voiceData)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
combo = {}
|
||||
return comboVoiceTable
|
||||
end
|
||||
|
||||
|
||||
function CDOTA_BaseNPC:THTD_chen_thtd_combo(combo)
|
||||
local comboVoiceTable = {}
|
||||
if HasCombo(combo,"chen_yukari_ran") then
|
||||
if self.thtd_chen_01_distance_increase ~= 75 then
|
||||
self.thtd_chen_01_distance_increase = 75
|
||||
end
|
||||
else
|
||||
if self.thtd_chen_01_distance_increase ~= 100 then
|
||||
self.thtd_chen_01_distance_increase = 100
|
||||
end
|
||||
end
|
||||
combo = {}
|
||||
return comboVoiceTable
|
||||
end
|
||||
|
||||
function CDOTA_BaseNPC:THTD_sunny_thtd_combo(combo)
|
||||
local comboVoiceTable = {}
|
||||
|
||||
if HasCombo(combo,"luna_star_sunny") and self.thtd_combo_fairyList == nil then
|
||||
local hero = self:GetOwner()
|
||||
local sunny = nil
|
||||
local luna = nil
|
||||
local star = nil
|
||||
local sunnyList = {}
|
||||
local lunaList = {}
|
||||
local starList = {}
|
||||
for k,v in pairs(hero.thtd_hero_tower_list) do
|
||||
if v:GetUnitName() == "sunny" and v.thtd_is_in_fairy_combo~=true then
|
||||
table.insert(sunnyList,v)
|
||||
elseif v:GetUnitName() == "luna" and v.thtd_is_in_fairy_combo~=true then
|
||||
table.insert(lunaList,v)
|
||||
elseif v:GetUnitName() == "star" and v.thtd_is_in_fairy_combo~=true then
|
||||
table.insert(starList,v)
|
||||
end
|
||||
end
|
||||
if #sunnyList > 0 and #lunaList > 0 and #starList > 0 then
|
||||
--最大连线距离
|
||||
local maxDistance = 2000
|
||||
for sunnyK,sunnyV in pairs(sunnyList) do
|
||||
for lunaK,lunaV in pairs(lunaList) do
|
||||
--计算连线距离,如果小于
|
||||
if math.floor(GetDistanceBetweenTwoVec2D(sunnyV:GetAbsOrigin(), lunaV:GetAbsOrigin()) + 0.5) <= maxDistance then
|
||||
for starK,starV in pairs(starList) do
|
||||
--计算连线距离,如果小于
|
||||
if math.floor(GetDistanceBetweenTwoVec2D(starV:GetAbsOrigin(), lunaV:GetAbsOrigin()) + 0.5) <= maxDistance and math.floor(GetDistanceBetweenTwoVec2D(starV:GetAbsOrigin(), sunnyV:GetAbsOrigin()) + 0.5) <= maxDistance then
|
||||
sunny = sunnyV
|
||||
luna = lunaV
|
||||
star = starV
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if sunny ~= nil then break end
|
||||
end
|
||||
if sunny ~= nil then break end
|
||||
end
|
||||
end
|
||||
|
||||
if sunny~=nil and luna~=nil and star~=nil then
|
||||
local sunny_effectIndex = ParticleManager:CreateParticle("particles/heroes/daiyousei/ability_daiyousei_03.vpcf", PATTACH_CUSTOMORIGIN, sunny)
|
||||
ParticleManager:SetParticleControlEnt(sunny_effectIndex , 0, sunny, 5, "attach_hitloc", Vector(0,0,0), true)
|
||||
ParticleManager:SetParticleControlEnt(sunny_effectIndex , 1, luna, 5, "attach_hitloc", Vector(0,0,0), true)
|
||||
|
||||
local luna_effectIndex = ParticleManager:CreateParticle("particles/heroes/daiyousei/ability_daiyousei_03.vpcf", PATTACH_CUSTOMORIGIN, luna)
|
||||
ParticleManager:SetParticleControlEnt(luna_effectIndex , 0, luna, 5, "attach_hitloc", Vector(0,0,0), true)
|
||||
ParticleManager:SetParticleControlEnt(luna_effectIndex , 1, star, 5, "attach_hitloc", Vector(0,0,0), true)
|
||||
|
||||
local star_effectIndex = ParticleManager:CreateParticle("particles/heroes/daiyousei/ability_daiyousei_03.vpcf", PATTACH_CUSTOMORIGIN, star)
|
||||
ParticleManager:SetParticleControlEnt(star_effectIndex , 0, star, 5, "attach_hitloc", Vector(0,0,0), true)
|
||||
ParticleManager:SetParticleControlEnt(star_effectIndex , 1, sunny, 5, "attach_hitloc", Vector(0,0,0), true)
|
||||
|
||||
sunny.thtd_is_in_fairy_combo = true
|
||||
star.thtd_is_in_fairy_combo = true
|
||||
luna.thtd_is_in_fairy_combo = true
|
||||
|
||||
self.thtd_combo_fairyList =
|
||||
{
|
||||
sunny = sunny,
|
||||
star = star,
|
||||
luna = luna,
|
||||
}
|
||||
self:SetContextThink(DoUniqueString("thtd_fairy_combo"),
|
||||
function()
|
||||
if GameRules:IsGamePaused() then return 0.03 end
|
||||
if THTD_IsValid(self) == false or THTD_IsValid(star) == false or THTD_IsValid(luna) == false then
|
||||
ParticleManager:DestroyParticleSystem(luna_effectIndex,true)
|
||||
luna.thtd_is_in_fairy_combo = nil
|
||||
|
||||
ParticleManager:DestroyParticleSystem(star_effectIndex,true)
|
||||
star.thtd_is_in_fairy_combo = nil
|
||||
|
||||
ParticleManager:DestroyParticleSystem(sunny_effectIndex,true)
|
||||
sunny.thtd_is_in_fairy_combo = nil
|
||||
|
||||
sunny.thtd_combo_fairyList = nil
|
||||
|
||||
self:GetOwner():THTD_HeroComboRefresh()
|
||||
return nil
|
||||
end
|
||||
return 0.03
|
||||
end,
|
||||
0)
|
||||
end
|
||||
end
|
||||
combo = {}
|
||||
return comboVoiceTable
|
||||
end
|
||||
|
||||
function CDOTA_BaseNPC:THTD_wriggle_thtd_combo(combo)
|
||||
local comboVoiceTable = {}
|
||||
if HasCombo(combo,"wriggle_rumia") then
|
||||
if self.thtd_wriggle_rumia_combo ~= true then
|
||||
self.thtd_wriggle_rumia_combo = true
|
||||
end
|
||||
else
|
||||
if self.thtd_wriggle_rumia_combo ~= false then
|
||||
self.thtd_wriggle_rumia_combo = false
|
||||
end
|
||||
end
|
||||
combo = {}
|
||||
return comboVoiceTable
|
||||
end
|
||||
|
||||
|
||||
function UpdatePrismriverComboName(caster,target)
|
||||
if target.thtd_prismriver_comboName == nil then
|
||||
target.thtd_prismriver_comboName = {[1]="",[2]="",[3]=""}
|
||||
end
|
||||
target.thtd_prismriver_comboName[1] = target.thtd_prismriver_comboName[2]
|
||||
target.thtd_prismriver_comboName[2] = target.thtd_prismriver_comboName[3]
|
||||
target.thtd_prismriver_comboName[3] = caster:GetUnitName()
|
||||
end
|
||||
|
||||
function GetPrismriverComboName(target)
|
||||
if target.thtd_prismriver_comboName == nil then
|
||||
target.thtd_prismriver_comboName = {[1]="",[2]="",[3]=""}
|
||||
end
|
||||
return target.thtd_prismriver_comboName[1]..target.thtd_prismriver_comboName[2]..target.thtd_prismriver_comboName[3]
|
||||
end
|
||||
|
||||
function ResetPrismriverComboName(target)
|
||||
target.thtd_prismriver_comboName = {[1]="",[2]="",[3]=""}
|
||||
end
|
||||
|
||||
function GetCountPrismriver(target)
|
||||
if target.thtd_prismriver_comboName == nil then return 0 end
|
||||
local count = 0
|
||||
if target.thtd_prismriver_comboName[1] ~= "" then
|
||||
count = count + 1
|
||||
end
|
||||
if target.thtd_prismriver_comboName[2] ~= "" then
|
||||
count = count + 1
|
||||
end
|
||||
if target.thtd_prismriver_comboName[3] ~= "" then
|
||||
count = count + 1
|
||||
end
|
||||
return count
|
||||
end
|
||||
626
scripts/vscripts/system/custom_event.lua
Executable file
626
scripts/vscripts/system/custom_event.lua
Executable file
@@ -0,0 +1,626 @@
|
||||
-- 发送消息(左侧),例如 SendMsg(0, "test_tip", "总输出",90) "test_tip" "{s:player_name}<font color='red'>上一波最终阵容{s:locstring_value}低于{d:int_value}%总血量,不计入有效波数</font>"
|
||||
-- 可用固有系统变量名称:{s:player_name} 玩家姓名(会显示玩家头像)
|
||||
-- 可用变量(名称不可变):{s:locstring_value} 文本,可以是本地化字符如"#DOTA_Tooltip_Ability_item_life_rune",{d:int_value}数字,{s:ability_name}技能名称,%s1替代文本(用string_replace_token取代)
|
||||
-- 可以直接发送非本地化的文字,使用上述变量
|
||||
function SendMsg(playerID, message_text, locstring_value, int_value, ability_name, string_replace)
|
||||
local gameEvent = {}
|
||||
gameEvent["player_id"] = playerID
|
||||
gameEvent["locstring_value"] = locstring_value
|
||||
gameEvent["teamnumber"] = -1 --DOTA_TEAM_GOODGUYS
|
||||
gameEvent["int_value"] = int_value
|
||||
gameEvent["message"] = message_text
|
||||
gameEvent["string_replace_token"] = string_replace
|
||||
gameEvent["ability_name"] = ability_name
|
||||
FireGameEvent( "dota_combat_event_message", gameEvent )
|
||||
end
|
||||
|
||||
if CustomEvent == nil then
|
||||
CustomEvent = {}
|
||||
end
|
||||
|
||||
function CustomEvent:GetHero(data)
|
||||
local player = PlayerResource:GetPlayer(data.PlayerID)
|
||||
if player then
|
||||
local hero = player:GetAssignedHero()
|
||||
if hero then
|
||||
return hero
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
CustomEvent.on = function( event, func )
|
||||
CustomGameEventManager:RegisterListener(event, function(unused, data) func(data) end)
|
||||
end
|
||||
|
||||
-- 聊天栏显示消息,配合js实现变量化
|
||||
CustomEvent.on('custom_game_chat_msg', function(data)
|
||||
GameRules:SendCustomMessage(data.msg, PlayerResource:GetTeam(data.PlayerID), 0)
|
||||
end)
|
||||
|
||||
-- 选择难度
|
||||
PlayersSelectedDifficulty = {}
|
||||
CustomEvent.on('custom_game_select_difficulty', function(data)
|
||||
if #PlayersSelectedDifficulty == 0 then
|
||||
for i=0,PlayerResource:GetPlayerCount()-1 do
|
||||
if PlayerResource:IsValidPlayer(i) then
|
||||
PlayersSelectedDifficulty[i] = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local player = PlayerResource:GetPlayer(data.PlayerID)
|
||||
if player ==nil then return end
|
||||
|
||||
PlayersSelectedDifficulty[data.PlayerID] = data.level or 0
|
||||
CustomNetTables:SetTableValue("CustomGameInfo", "PlayersSelectedDifficulty", PlayersSelectedDifficulty )
|
||||
end)
|
||||
|
||||
-- 完成状态
|
||||
local PlayersCompleteStatus = {}
|
||||
CustomEvent.on('custom_game_complete_select_cards', function(data)
|
||||
if PlayersCompleteStatus[data.PlayerID] == 1 then return end
|
||||
|
||||
for k,v in pairs(data["cards"]) do
|
||||
local itemTable =
|
||||
{
|
||||
["itemName"] = k,
|
||||
["quality"]= towerNameList[k]["quality"],
|
||||
["count"]= v,
|
||||
}
|
||||
table.insert(towerPlayerList[data.PlayerID+1],itemTable)
|
||||
end
|
||||
|
||||
PlayersCompleteStatus[data.PlayerID] = 1
|
||||
CustomNetTables:SetTableValue("CustomGameInfo", "PlayersCompleteStatus", PlayersCompleteStatus )
|
||||
SetNetTableTowerPlayerList(data.PlayerID)
|
||||
end)
|
||||
|
||||
-- 投票踢人
|
||||
local playerVote =
|
||||
{
|
||||
vote_time = 0,
|
||||
vote_player = -1,
|
||||
kicked_player = -1,
|
||||
kicked_line = -1,
|
||||
agree_players = {}
|
||||
}
|
||||
|
||||
CustomEvent.on('custom_game_kick_vote', function(data)
|
||||
if SpawnSystem.CurWave > 50 + 20 then
|
||||
CustomGameEventManager:Send_ServerToPlayer(PlayerResource:GetPlayer(data.PlayerID), "display_custom_error", {msg="cannot_vote_when_over_some_waves"})
|
||||
return
|
||||
end
|
||||
local player = PlayerResource:GetPlayer(data.PlayerID)
|
||||
if player ==nil then return end
|
||||
local hero = player:GetAssignedHero()
|
||||
if hero.is_game_over == true then return end
|
||||
|
||||
if playerVote.kicked_player ~= - 1 and (math.floor(GameRules:GetGameTime()) - playerVote.vote_time) < 60 then
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "show_message", {msg="player_in_vote", duration=10, params={count=playerVote.kicked_player+1}, color="#ff0"})
|
||||
return
|
||||
end
|
||||
|
||||
local kicked_player = -1
|
||||
local spawner = SpawnSystem.AttackingSpawner
|
||||
if spawner == nil or #spawner == 0 then return end
|
||||
for _, spawnerLine in pairs(spawner) do
|
||||
if spawnerLine.index == data.line_index then
|
||||
kicked_player = spawnerLine.hero.thtd_player_id
|
||||
break
|
||||
end
|
||||
end
|
||||
if kicked_player == -1 then return end
|
||||
|
||||
playerVote.vote_time = math.floor(GameRules:GetGameTime())
|
||||
playerVote.vote_player = data.PlayerID
|
||||
playerVote.kicked_player = kicked_player
|
||||
playerVote.kicked_line = data.line_index
|
||||
playerVote.agree_players = {}
|
||||
CustomGameEventManager:Send_ServerToAllClients("kick_player", {vote_player=playerVote.vote_player, kicked_player=playerVote.kicked_player, kicked_line = playerVote.kicked_line})
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_kick_accept', function(data)
|
||||
local player = PlayerResource:GetPlayer(data.PlayerID)
|
||||
if player ==nil then return end
|
||||
local hero = player:GetAssignedHero()
|
||||
if hero.is_game_over == true then return end
|
||||
if playerVote.kicked_player == -1 then return end
|
||||
|
||||
if data.accept == 1 then
|
||||
table.insert(playerVote.agree_players, data.PlayerID)
|
||||
local agrees = playerVote.agree_players
|
||||
if #agrees >= (GetValidVotePlayerCount() - 1) then
|
||||
KickPlayer()
|
||||
end
|
||||
else
|
||||
playerVote.vote_time = 0
|
||||
playerVote.vote_player = -1
|
||||
playerVote.kicked_player = -1
|
||||
playerVote.kicked_line = - 1
|
||||
playerVote.agree_players = {}
|
||||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="player_vote_no_pass", duration=10, params={count=data.PlayerID+1}, color="#ff0"})
|
||||
end
|
||||
end)
|
||||
|
||||
function KickPlayer()
|
||||
for index,hero in pairs(GameRules.HeroList) do
|
||||
if hero ~= nil and hero.is_game_over ~= true and hero.thtd_player_id == playerVote.kicked_player then
|
||||
SpawnSystem:GameOver(hero)
|
||||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="player_vote_pass", duration=10, params={count=playerVote.kicked_player+1}, color="#ff0"})
|
||||
break
|
||||
end
|
||||
end
|
||||
playerVote.vote_time = 0
|
||||
playerVote.vote_player = -1
|
||||
playerVote.kicked_player = -1
|
||||
playerVote.kicked_line = - 1
|
||||
playerVote.agree_players = {}
|
||||
end
|
||||
|
||||
function GetValidVotePlayerCount()
|
||||
local count = 0
|
||||
for index,hero in pairs(GameRules.HeroList) do
|
||||
if hero~=nil and hero:IsNull()==false and hero:IsAlive() and hero.is_game_over~=true and hero.thtd_game_info["is_player_connected"] then
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- 选择初始卡
|
||||
CustomEvent.on('custom_game_select_start_card', function(data)
|
||||
local player = PlayerResource:GetPlayer(data.PlayerID)
|
||||
if player ==nil then return end
|
||||
local hero = player:GetAssignedHero()
|
||||
if hero:GetLevel() >= 6 then
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "select_start_card_finish", {})
|
||||
return
|
||||
end
|
||||
if hero:GetNumItemsInInventory() >= THTD_MAX_ITEM_SLOT then
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "display_custom_error", {msg="not_enough_item_slot"})
|
||||
return
|
||||
end
|
||||
local item = CreateItem(data.ItemName, nil, nil)
|
||||
if item ~= nil then
|
||||
item.owner_player_id = hero.thtd_player_id
|
||||
item.is_bonus_item = true
|
||||
hero:AddItem(item)
|
||||
-- if data.ItemName == "item_0003" then
|
||||
-- item = CreateItem("item_0088", nil, nil)
|
||||
-- item.owner_player_id = hero.thtd_player_id
|
||||
-- item.is_bonus_item = true
|
||||
-- hero:AddItem(item)
|
||||
-- end
|
||||
for i=1,5 do
|
||||
hero:HeroLevelUp(false)
|
||||
end
|
||||
-- hero:SetAbilityPoints(0)
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "select_start_card_finish", {})
|
||||
end
|
||||
end)
|
||||
|
||||
-- 选择初始奖励卡
|
||||
CustomEvent.on('custom_game_select_bonus_card', function(data)
|
||||
local player = PlayerResource:GetPlayer(data.PlayerID)
|
||||
if player ==nil then return end
|
||||
local hero = player:GetAssignedHero()
|
||||
if hero:GetLevel() >= 9 then return end
|
||||
if hero:GetNumItemsInInventory() >= THTD_MAX_ITEM_SLOT then
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "select_bonus_card_no_finish", {})
|
||||
CustomGameEventManager:Send_ServerToPlayer(player, "display_custom_error", {msg="not_enough_item_slot"})
|
||||
return
|
||||
end
|
||||
local item = CreateItem(data.ItemName, nil, nil)
|
||||
if item ~= nil then
|
||||
item.owner_player_id = hero.thtd_player_id
|
||||
item.is_bonus_item = true
|
||||
hero:AddItem(item)
|
||||
if data.ItemName == "item_3149" then
|
||||
for i=1,3 do
|
||||
local itemNew = CreateItem("item_3149", nil, nil)
|
||||
if itemNew ~= nil then
|
||||
itemNew.owner_player_id = playerId
|
||||
itemNew:SetPurchaser(hero)
|
||||
hero:AddItem(itemNew)
|
||||
end
|
||||
end
|
||||
end
|
||||
local cardName = item:THTD_GetCardName()
|
||||
if item:THTD_IsCardHasVoice() == true then EmitSoundOn(THTD_GetVoiceEvent(cardName,"spawn"),hero) end
|
||||
if item:THTD_IsCardHasPortrait() == true then
|
||||
local portraits= item:THTD_GetPortraitPath(cardName)
|
||||
local effectIndex = ParticleManager:CreateParticle(portraits, PATTACH_WORLDORIGIN, nil)
|
||||
ParticleManager:SetParticleControl(effectIndex, 0, Vector(-58,-80,0))
|
||||
ParticleManager:SetParticleControl(effectIndex, 1, Vector(80,0,0))
|
||||
ParticleManager:DestroyParticleSystemTime(effectIndex,6.0)
|
||||
effectIndex = ParticleManager:CreateParticle("particles/portraits/portraits_ssr_get_screen_effect.vpcf", PATTACH_WORLDORIGIN, nil)
|
||||
ParticleManager:DestroyParticleSystemTime(effectIndex,4.0)
|
||||
hero:EmitSound("Sound_THTD.thtd_draw_ssr")
|
||||
end
|
||||
for i=1,3 do
|
||||
hero:HeroLevelUp(false)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- 御币选择卡片
|
||||
CustomEvent.on('select_card', function(data)
|
||||
local player = PlayerResource:GetPlayer(data.PlayerID)
|
||||
if player==nil then return end
|
||||
local caster = player:GetAssignedHero()
|
||||
if caster == nil then return end
|
||||
local itemName = data.itemname
|
||||
if itemName ~= nil and THTD_GetItemCountByName(data.PlayerID,itemName) > 0 then
|
||||
if caster.thtd_last_select_item~=nil and caster.thtd_last_select_item:IsNull()==false then
|
||||
OnItemDestroyed(caster, caster.thtd_last_select_item, false)
|
||||
caster:THTD_AddCardPoolItem(itemName)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- 战利品奖励选择
|
||||
CustomEvent.on('select_battle_bonus_card', function(data)
|
||||
local itemName = data.itemname
|
||||
local hero = GameRules.HeroList[data.PlayerID]
|
||||
|
||||
if hero.bb_buff == nil then hero.bb_buff = {} end
|
||||
if #hero.bb_buff > 5 then return end
|
||||
|
||||
if string.sub(itemName,1,6) == "item_3" then
|
||||
if itemName == "item_3011" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3011"] = GameRules.player_bb_buff[data.PlayerID]["item_3011"] + 30
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3011", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3012" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3012"] = GameRules.player_bb_buff[data.PlayerID]["item_3012"] + 15
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3012", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3013" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3013"] = GameRules.player_bb_buff[data.PlayerID]["item_3013"] * (1 - 0.5)
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3013", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3014" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3014"] = GameRules.player_bb_buff[data.PlayerID]["item_3014"] + 1
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3014", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3015" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3015"] = GameRules.player_bb_buff[data.PlayerID]["item_3015"] + 15
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3015", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3016" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3016"] = GameRules.player_bb_buff[data.PlayerID]["item_3016"] + 1
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3016", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3017" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3017"] = GameRules.player_bb_buff[data.PlayerID]["item_3017"] + 5
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3017", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3018" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3018"] = GameRules.player_bb_buff[data.PlayerID]["item_3018"] * (1 - 0.2)
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3018", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3019" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3019"] = GameRules.player_bb_buff[data.PlayerID]["item_3019"] + 50
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3019", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3020" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3020"] = GameRules.player_bb_buff[data.PlayerID]["item_3020"] + 50
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3020", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3021" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3021"] = GameRules.player_bb_buff[data.PlayerID]["item_3021"] + 75
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3021", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3022" then
|
||||
local gold = 10000
|
||||
THTD_ModifyGoldEx(data.PlayerID, gold , true, DOTA_ModifyGold_Unspecified)
|
||||
SendOverheadEventMessage(hero:GetPlayerOwner(), OVERHEAD_ALERT_GOLD, hero, gold, hero:GetPlayerOwner())
|
||||
hero:EmitSound("Sound_THTD.thtd_nazrin_01")
|
||||
elseif itemName == "item_3023" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3023"] = GameRules.player_bb_buff[data.PlayerID]["item_3023"] + 50
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3023", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3024" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3024"] = GameRules.player_bb_buff[data.PlayerID]["item_3024"] + 50
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3024", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3025" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3025"] = GameRules.player_bb_buff[data.PlayerID]["item_3025"] + 5
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3025", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3026" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3026"] = GameRules.player_bb_buff[data.PlayerID]["item_3026"] + 30
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3026", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3027" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3027"] = GameRules.player_bb_buff[data.PlayerID]["item_3027"] + 1
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3027", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3028" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3028"] = GameRules.player_bb_buff[data.PlayerID]["item_3028"] + 1
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3028", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3029" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3029"] = GameRules.player_bb_buff[data.PlayerID]["item_3029"] + 20
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3029", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
elseif itemName == "item_3030" then
|
||||
GameRules.player_bb_buff[data.PlayerID]["item_3030"] = GameRules.player_bb_buff[data.PlayerID]["item_3030"] + 50
|
||||
hero:AddNewModifier(hero, nil, "modifier_bb_buff_3030", nil)
|
||||
table.insert(hero.bb_buff, itemName)
|
||||
else
|
||||
|
||||
end
|
||||
else
|
||||
local item = CreateItem(itemName, nil, nil)
|
||||
if item ~= nil then
|
||||
item.owner_player_id = hero.thtd_player_id
|
||||
item:SetPurchaser(hero)
|
||||
item:SetPurchaseTime(1.0)
|
||||
|
||||
if hero:GetNumItemsInInventory() >= THTD_MAX_ITEM_SLOT then
|
||||
CreateItemOnPositionSync(hero:GetAbsOrigin(), item)
|
||||
else
|
||||
hero:AddItem(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- AI选择
|
||||
CustomEvent.on('custom_game_choose_ai', function(data)
|
||||
local caster = EntIndexToHScript(data.entity)
|
||||
if caster == nil then return end
|
||||
if data.result == 1 or data.result == true then
|
||||
caster["thtd_"..data.name.."_0"..tostring(data.skill).."_cast"] = true
|
||||
else
|
||||
caster["thtd_"..data.name.."_0"..tostring(data.skill).."_cast"] = false
|
||||
end
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_command', function(data)
|
||||
if data["cmd"] == "wave" then
|
||||
SpawnSystem.ReachToWave = data["param"]
|
||||
CustomGameEventManager:Send_ServerToAllClients("show_message", {msg="reach_to_wave", duration=20, params={count=data["param"]}, color="#ff0"})
|
||||
return
|
||||
end
|
||||
|
||||
if data["cmd"] == "add" then
|
||||
PlayerResource:ModifyGold(data["PlayerID"], 95000 , true, DOTA_ModifyGold_Unspecified)
|
||||
local player = PlayerResource:GetPlayer(data["PlayerID"])
|
||||
local itemName = "item_"..data["param"]
|
||||
if string.len(itemName) ~= 9 then return end
|
||||
local item = CreateItem(itemName, nil, nil)
|
||||
if player ~= nil and item ~= nil then
|
||||
local hero = player:GetAssignedHero()
|
||||
if hero:GetNumItemsInInventory() < THTD_MAX_ITEM_SLOT then
|
||||
item.owner_player_id = hero.thtd_player_id
|
||||
hero:AddItem(item)
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if data["cmd"] == "tp" then
|
||||
local pos = string.split(data["param"], ",")
|
||||
if pos == nil or #pos < 2 then
|
||||
local player = PlayerResource:GetPlayer(data["PlayerID"])
|
||||
local hero = player:GetAssignedHero()
|
||||
local targets = THTD_FindUnitsInRadius(hero, hero:GetAbsOrigin(), 1000)
|
||||
for k,v in pairs(targets) do
|
||||
print("----------")
|
||||
print(v.thtd_next_corner)
|
||||
print(v.next_move_forward)
|
||||
print(v.next_move_point)
|
||||
hero:SetAbsOrigin(v.next_move_point)
|
||||
break
|
||||
end
|
||||
return
|
||||
end
|
||||
local vec = Vector(tonumber(pos[1]), tonumber(pos[2]), 144)
|
||||
if vec ~= nil then
|
||||
local player = PlayerResource:GetPlayer(data["PlayerID"])
|
||||
local hero = player:GetAssignedHero()
|
||||
hero:SetAbsOrigin(vec)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if data["cmd"] == "clearrank" then
|
||||
Service:ClearSameRank()
|
||||
return
|
||||
end
|
||||
|
||||
if data["cmd"] == "lv" then
|
||||
local player = PlayerResource:GetPlayer(data["PlayerID"])
|
||||
if player then
|
||||
local hero = player:GetAssignedHero()
|
||||
for k,v in pairs(hero.thtd_hero_tower_list) do
|
||||
if v~=nil and v:IsNull()==false and v:IsAlive() and v:THTD_IsTower() then
|
||||
v:THTD_SetAbilityLevelUp()
|
||||
v:THTD_SetAbilityLevelUp()
|
||||
v:THTD_SetAbilityLevelUp()
|
||||
v:THTD_SetAbilityLevelUp()
|
||||
if v:THTD_GetStar() < 5 then
|
||||
v:THTD_SetStar(5)
|
||||
end
|
||||
if v:THTD_GetLevel() < THTD_MAX_LEVEL then
|
||||
v:THTD_SetLevel(THTD_MAX_LEVEL)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if data["cmd"] == "boss" then
|
||||
SpawnSystem.AttackingSpawner[data["PlayerID"]+1].nextBossName = data["param"]
|
||||
return
|
||||
end
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_save_cardgroup', function(data)
|
||||
Service:SaveCardGroup(data.PlayerID, data.groupkey, data.groupdata)
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_rank_detail', function(data)
|
||||
local playerid = data.PlayerID
|
||||
local rankdata = {}
|
||||
rankdata['index'] = data.index
|
||||
|
||||
local playerRankData
|
||||
if data.type == 1 then
|
||||
playerRankData = GameRules.players_rank_data[data.index]
|
||||
else
|
||||
playerRankData = GameRules.players_team_rank_data[data.index]
|
||||
end
|
||||
if tostring(PlayerResource:GetSteamID(playerid)) == tostring(playerRankData.steamid) then
|
||||
rankdata['is_local_player'] = 1
|
||||
else
|
||||
rankdata['is_local_player'] = 0
|
||||
end
|
||||
rankdata['wave'] = playerRankData['wave']
|
||||
|
||||
for k,v in pairs(playerRankData) do
|
||||
if string.sub(k,1,4) == "card" then
|
||||
rankdata[k] = v
|
||||
end
|
||||
end
|
||||
if data.type == 1 then
|
||||
CustomGameEventManager:Send_ServerToPlayer(PlayerResource:GetPlayer(playerid), "thtd_rank_detail", rankdata)
|
||||
else
|
||||
CustomGameEventManager:Send_ServerToPlayer(PlayerResource:GetPlayer(playerid), "thtd_team_rank_detail", rankdata)
|
||||
end
|
||||
rankdata = {}
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_rank_reset', function(data)
|
||||
if tostring(PlayerResource:GetSteamID(data.PlayerID)) ~= GameRules.GameData.admin then return end
|
||||
|
||||
if data.index > 0 then
|
||||
if data.type == 1 then
|
||||
Service:ResetRank(data.index,"S")
|
||||
else
|
||||
Service:ResetRank(data.index,"D")
|
||||
end
|
||||
else
|
||||
if data.type == 1 then
|
||||
local total = #GameRules.players_rank
|
||||
local count = 1
|
||||
GameRules:GetGameModeEntity():SetContextThink(DoUniqueString("ResetRankAll"),
|
||||
function()
|
||||
Service:ResetRank(count,"S")
|
||||
count = count + 1
|
||||
if count > total then
|
||||
return nil
|
||||
else
|
||||
return 1.0
|
||||
end
|
||||
end,
|
||||
0)
|
||||
else
|
||||
local total = #GameRules.players_team_rank
|
||||
local count = 1
|
||||
GameRules:GetGameModeEntity():SetContextThink(DoUniqueString("ResetRankAll"),
|
||||
function()
|
||||
Service:ResetRank(count,"D")
|
||||
count = count + 1
|
||||
if count > total then
|
||||
return nil
|
||||
else
|
||||
return 1.0
|
||||
end
|
||||
end,
|
||||
0)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_train_card', function(data)
|
||||
local playerid = data.PlayerID
|
||||
local itemName = data.item_name
|
||||
local levelUp = data.level_up
|
||||
|
||||
if towerNameList[itemName] == nil then
|
||||
CustomGameEventManager:Send_ServerToPlayer(PlayerResource:GetPlayer(playerid), "thtd_train_card_complete", {code = 0, msg = "该卡牌还在制作中,请关注后续更新"})
|
||||
return
|
||||
end
|
||||
|
||||
local maxLevel = THTD_GetMaxPowerLevel(towerNameList[itemName]["cardname"])
|
||||
|
||||
if GameRules.PlayerData[playerid] == nil then
|
||||
CustomGameEventManager:Send_ServerToPlayer(PlayerResource:GetPlayer(playerid), "thtd_train_card_complete", {code = 0, msg = "没有用户数据"})
|
||||
elseif GameRules.PlayerData[playerid]["level_list"] == nil then
|
||||
CustomGameEventManager:Send_ServerToPlayer(PlayerResource:GetPlayer(playerid), "thtd_train_card_complete", {code = 0, msg = "获取已培养清单出错"})
|
||||
elseif GameRules.PlayerData[playerid]["level_list"][itemName] ~= nil and GameRules.PlayerData[playerid]["level_list"][itemName] >= maxLevel then
|
||||
CustomGameEventManager:Send_ServerToPlayer(PlayerResource:GetPlayer(playerid), "thtd_train_card_complete", {code = 0, msg = "已达到最大潜能"})
|
||||
else
|
||||
local point = 10
|
||||
if towerNameList[itemName]["quality"] == 1 then
|
||||
point = 5
|
||||
end
|
||||
local addLevel = math.min(levelUp, maxLevel - (GameRules.PlayerData[playerid]["level_list"][itemName] or 0))
|
||||
point = point * addLevel
|
||||
if GameRules.PlayerData[playerid]["point"] >= point then
|
||||
Service:SaveCardLevel(playerid, itemName, addLevel)
|
||||
else
|
||||
CustomGameEventManager:Send_ServerToPlayer(PlayerResource:GetPlayer(playerid), "thtd_train_card_complete", {code = 0, msg = "符卡精华数量不足"})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_pay_select', function(data)
|
||||
Service:CreateShopOrder(data.PlayerID, data.method, data.amount, data.price, data.type)
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_pay_query', function(data)
|
||||
Service:PayCheck(data.PlayerID)
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_pay_auto_query', function(data)
|
||||
Service:PayAutoCheck(data.PlayerID)
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_show_dps_card', function(data)
|
||||
local ent = data.ent
|
||||
if ent == 0 then return end
|
||||
local unit = EntIndexToHScript(ent)
|
||||
if not THTD_IsValid(unit) then return end
|
||||
|
||||
if unit.show_pds_card ~= true then
|
||||
unit.show_pds_card = true
|
||||
local count = 5
|
||||
unit:SetContextThink(DoUniqueString("custom_game_show_dps_card"),
|
||||
function()
|
||||
count = count - 1
|
||||
if count < 0 then
|
||||
unit:THTD_CreateLevelEffect()
|
||||
unit.show_pds_card = nil
|
||||
return nil
|
||||
end
|
||||
if count%2 == 0 then
|
||||
unit:THTD_DestroyLevelEffect()
|
||||
else
|
||||
unit:THTD_CreateLevelEffect()
|
||||
end
|
||||
return 0.3
|
||||
end,
|
||||
0.3)
|
||||
end
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_pause_game', function(data)
|
||||
if GameRules:IsGamePaused() then
|
||||
PauseGame(false)
|
||||
else
|
||||
PauseGame(true)
|
||||
GameRules:SendCustomMessage("#pause_game_forever", DOTA_TEAM_GOODGUYS, 0)
|
||||
end
|
||||
end)
|
||||
|
||||
CustomEvent.on('custom_game_update_data', function(data)
|
||||
Service:GetPlayerBaseData(data.PlayerID)
|
||||
end)
|
||||
518
scripts/vscripts/system/damage.lua
Executable file
518
scripts/vscripts/system/damage.lua
Executable file
@@ -0,0 +1,518 @@
|
||||
-- 生命移除伤害,只会计算少女之抵抗,参数:单位、目标、百分比值、是否按当前生命值
|
||||
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
|
||||
164
scripts/vscripts/system/items.lua
Executable file
164
scripts/vscripts/system/items.lua
Executable file
@@ -0,0 +1,164 @@
|
||||
function CDOTABaseAbility:THTD_UpdateItemStarLevel()
|
||||
local tower = self:THTD_GetTower()
|
||||
if tower == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local star = tower:THTD_GetStar()
|
||||
local level = tower:THTD_GetLevel()
|
||||
local item_level = (star-1) * 10 + level
|
||||
self:SetLevel(item_level) -- 也可以用 self:GetSecondaryCharges()
|
||||
-- star = math.floor((item_level-1)/10) + 1
|
||||
-- level = item_level - (star-1) * 10
|
||||
end
|
||||
|
||||
function CDOTABaseAbility:THTD_GetTower()
|
||||
return self.tower or nil
|
||||
end
|
||||
|
||||
function CDOTABaseAbility:THTD_RemoveItemInList(PlayerID)
|
||||
local list_num = PlayerID+1
|
||||
local itemName = self:GetAbilityName()
|
||||
|
||||
if itemName~=nil then
|
||||
for k,v in pairs(towerPlayerList[list_num]) do
|
||||
if v["itemName"] == itemName then
|
||||
v["count"] = v["count"] - 1
|
||||
if v["count"] <= 0 then
|
||||
table.remove(towerPlayerList[list_num],k)
|
||||
end
|
||||
SetNetTableTowerPlayerList(PlayerID)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function THTD_AddItemToListByName(PlayerID,itemNameRelease)
|
||||
local list_num = PlayerID+1
|
||||
local itemName = itemNameRelease
|
||||
|
||||
if itemName~=nil then
|
||||
for k,v in pairs(towerPlayerList[list_num]) do
|
||||
if v["itemName"] == itemName then
|
||||
v["count"] = v["count"] + 1
|
||||
SetNetTableTowerPlayerList(PlayerID)
|
||||
return
|
||||
end
|
||||
end
|
||||
local itemTable =
|
||||
{
|
||||
["itemName"] = itemName,
|
||||
["quality"]= towerNameList[itemName]["quality"],
|
||||
["count"]= 1,
|
||||
}
|
||||
table.insert(towerPlayerList[PlayerID+1],itemTable)
|
||||
SetNetTableTowerPlayerList(PlayerID)
|
||||
end
|
||||
end
|
||||
|
||||
function CDOTABaseAbility:THTD_GetCardName()
|
||||
if towerNameList[self:GetAbilityName()] ~= nil then
|
||||
return towerNameList[self:GetAbilityName()]["cardname"]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function CDOTABaseAbility:THTD_GetCardQuality()
|
||||
local unitName = self:GetAbilityName()
|
||||
if towerNameList[unitName] ~= nil then
|
||||
return towerNameList[unitName]["quality"]
|
||||
elseif unitName == "item_3150" or unitName == "item_3151" or unitName == "item_3152" then
|
||||
return 5
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function CDOTABaseAbility:THTD_IsCardHasPortrait()
|
||||
if towerNameList[self:GetAbilityName()] ~= nil then
|
||||
return towerNameList[self:GetAbilityName()]["hasPortrait"]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function CDOTABaseAbility:THTD_GetPortraitPath(unitName)
|
||||
return "particles/portraits/"..unitName.."/thtd_"..unitName.."_portraits.vpcf"
|
||||
end
|
||||
|
||||
function CDOTABaseAbility:THTD_IsCardHasVoice()
|
||||
if towerNameList[self:GetAbilityName()] ~= nil then
|
||||
return towerNameList[self:GetAbilityName()]["hasVoice"]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function THTD_GetVoiceEvent(cardName,key)
|
||||
return "Voice_THTD."..cardName.."."..key
|
||||
end
|
||||
|
||||
function THTD_GetItemCountByName(playerid,itemName)
|
||||
for k,v in pairs(towerPlayerList[playerid+1]) do
|
||||
if v["itemName"] == itemName then
|
||||
return v["count"]
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function ItemSetScale(item, scale)
|
||||
if item == nil then return end
|
||||
local box = item:GetContainer()
|
||||
if box == nil then return end
|
||||
box:SetModelScale(scale)
|
||||
end
|
||||
|
||||
local thtd_item_scale =
|
||||
{
|
||||
["kokoro"] = 0.55,
|
||||
["yoshika"] = 0.55,
|
||||
["aya"] = 0.55,
|
||||
["cirno"] = 0.55,
|
||||
["marisa"] = 0.55,
|
||||
["reimu"] = 0.55,
|
||||
["remilia"] = 0.65,
|
||||
["flandre"] = 0.65,
|
||||
["yukari"] = 0.45,
|
||||
["satori"] = 0.55,
|
||||
["patchouli"] = 0.55,
|
||||
["sakuya"] = 0.55,
|
||||
["youmu"] = 0.55,
|
||||
["tenshi"] = 0.55,
|
||||
["yuuka"] = 0.55,
|
||||
["clownpiece"] = 0.6,
|
||||
["wriggle"] = 1.3,
|
||||
["komachi"] = 0.55,
|
||||
["shikieiki"] = 0.65,
|
||||
["inaba"] = 0.65,
|
||||
["shinki"] = 0.50,
|
||||
["koishi"] = 0.55,
|
||||
}
|
||||
|
||||
function THTD_ItemSetScale(item)
|
||||
if item == nil then return end
|
||||
local cardName = item:THTD_GetCardName()
|
||||
if cardName ~= nil then
|
||||
if thtd_item_scale[cardName] == nil then
|
||||
-- ItemSetScale(item, 1.0)
|
||||
else
|
||||
ItemSetScale(item, thtd_item_scale[cardName])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function THTD_HasItemScale(item)
|
||||
if item == nil then return false end
|
||||
local cardName = item:THTD_GetCardName()
|
||||
if cardName ~= nil and thtd_item_scale[cardName] ~= nil then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
1065
scripts/vscripts/system/service.lua
Executable file
1065
scripts/vscripts/system/service.lua
Executable file
File diff suppressed because it is too large
Load Diff
1955
scripts/vscripts/system/spawner.lua
Executable file
1955
scripts/vscripts/system/spawner.lua
Executable file
File diff suppressed because it is too large
Load Diff
2643
scripts/vscripts/system/tower.lua
Executable file
2643
scripts/vscripts/system/tower.lua
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user