Добрый день всем читателям!
Сегодня мы создадим предмет из доты2, который называется battle fury. Этот топор распространяет урон по всем юнитам в небольшом радиусе. Начнём!
Note: На днях выпущу общий гайд по datadriven способностям, а этот урок должен был идти как дополнение к нему.
Note: Обязательно прочитайте и вникните в код.
Итак. Battle fury как предмет.
План урока:
1. Рассмотреть datadriven-составляющую предмета. Посмотреть как устроены события, как устроены действия.
2. Рассмотреть lua-скрипт с комментариями, чтобы вам было понятно ЧТО и ЗАЧЕМ делается.
Код:
"item_bfury_datadriven"
{
"BaseClass" "item_datadriven" //указываем класс предмета
"ID" "1145" //У вольво предмет 145 ID, мы ставим 1145, для себя
"AbilityBehavior" "DOTA_ABILITY_BEHAVIOR_PASSIVE" //пассивка (сплэш)
"Model" "models/props_gameplay/red_box.vmdl" //красный ящик, модель
"Effect" "particles/generic_gameplay/dropped_item.vpcf"
"AbilityTextureName" "item_bfury" //иконка предмета
// Item Info
//-------------------------------------------------------------------------------------------------------------
"ItemCost" "4350" //сколько стоит предмет
"ItemShopTags" "damage;health_regen;mana_regen;hard_to_tag" //тэги для
"ItemQuality" "epic" //качество предмета стоит epic, значит предмет редкий
"ItemAliases" "bf;battle fury" //алиасы для предмета, позже скажу для чего
"ItemDeclarations" "DECLARE_PURCHASES_TO_TEAMMATES | DECLARE_PURCHASES_IN_SPEECH | DECLARE_PURCHASES_TO_SPECTATORS" //показывать союзникам что вы его купили, озвучивать героем предмет, показывать броадкастерам что он был куплен
//С подготовкой закончено, теперь сам datadriven-код.
// Special
//-------------------------------------------------------------------------------------------------------------
"AbilitySpecial" //Специальные значения предмета, чтобы мы могли их брать отсюда
{
"01"
{
"var_type" "FIELD_INTEGER"
"bonus_damage" "65" //[b]Бонусный урон, пока что просто задается как параметр, если оставите его так, то он не будет давать урона[/b]
}
"02"
{
"var_type" "FIELD_INTEGER"
"bonus_health_regen" "6" //бонусная регенерация хп
}
"03"
{
"var_type" "FIELD_INTEGER"
"bonus_mana_regen_percentage" "150" //бонусная регенерация маны в процентах
}
"04"
{
"var_type" "FIELD_INTEGER"
"cleave_damage_percent" "35" //процент сплэша
}
"05"
{
"var_type" "FIELD_INTEGER"
"cleave_radius" "250" //радиус сплэша
}
}
"Modifiers" //Секция модифиеры
{
"modifier_item_bfury_datadriven" //Модификатор баттлы
{
"Passive" "1" //пассивный
"IsHidden" "1" //скрытый, не виден на панели статусов
"Attributes" "MODIFIER_ATTRIBUTE_MULTIPLE" //Мультипл тут означает что предмет усиливает сразу несколько параметров
"Properties"
{
"MODIFIER_PROPERTY_BASEATTACK_BONUSDAMAGE" "%bonus_damage" // Как вы видите, мы берем это значение из переменной которой мы указывали выше, в AbilitySpecial, там мы указали 65 урона, значит даваться будет 65). Но это всего лишь модификатор! Урон всё ещё не дается при поднятии предмета, мы обязательно должны "Дать" этот модификатор какому-либо юниту, в данном случае тому, кто поднимет предмет
"MODIFIER_PROPERTY_HEALTH_REGEN_CONSTANT" "%bonus_health_regen"
"MODIFIER_PROPERTY_MANA_REGEN_PERCENTAGE" "%bonus_mana_regen_percentage" //То же самое с регеном маны и хп.
}
"OnCreated" //СОБЫТИЕ: когда юнит поднимает предмет, мы запускаем скрипт
{
"RunScript" //вот тут секция запуска скрипта
{
"ScriptFile" "items/item_bfury.lua" //название скрипта
"Function" "modifier_item_bfury_datadriven_on_created" //функция внутри скрипта
}
}
"OnDestroy" //СОБЫТИЕ: когда предмет выкидывается
{
"RunScript" //запускаем скрипт)
{
"ScriptFile" "items/item_bfury.lua" //путь к скрипту)
"Function" "modifier_item_bfury_datadriven_on_destroy" //функция
}
}
//Итак теперь мы каждые .03 секунды будем проверять
//вдруг герой ближнего боя поменял свой тип атаки на дальний бой, тогда мы заберем сплэш
"ThinkInterval" ".03" //таймер, который будет выполняться каждые 0.03 сек.
"OnIntervalThink" //СОБЫТИЕ: на каждое срабатывание таймера
{
"RunScript" //запустить скрипт
{
"ScriptFile" "items/item_bfury.lua"
"Function" "modifier_item_bfury_datadriven_on_interval_think" //функция проверки
}
}
}
"modifier_item_bfury_datadriven_cleave" //Вот теперь тот самый сплэш.
{
"Passive" "0" //активная
"IsHidden" "1" //скрытый модификатор
"Attributes" "MODIFIER_ATTRIBUTE_MULTIPLE" //даёт аттрибуты
"OnAttackLanded" //СОБЫТИЕ: когда юнит обладающий предметом атаковал
{
"CleaveAttack" //сделать сплэш атаку.
{
"CleavePercent" "%cleave_damage_percent" //процент сплэша, указан выше
"CleaveRadius" "%cleave_radius" //радиус
"CleaveEffect" "particles/items_fx/battlefury_cleave.vpcf" //эффект
}
"FireSound" //Так же воспроизвести звук
{
"EffectName" "DOTA_Item.BattleFury" //путь к звуку
"Target" "TARGET" //на цель, обладателя предмета
}
}
//Continually check to see if the hero this modifier is on is still melee
//(since some units, like Troll Warlord, can switch between ranged/melee forms).
"ThinkInterval" ".03" //ещё одна доп. проверка на ближника/дальника
"OnIntervalThink"
{
"RunScript"
{
"ScriptFile" "items/item_bfury.lua"
"Function" "modifier_item_bfury_datadriven_cleave_on_interval_think"
}
}
}
}
}
Так, в datadriven разобрались. Как вы знаете, вся datadriven-инфа по предметам находится в npc_items_custom.txt
Теперь скрипт.
Код:
--[[ ============================================================================================================
Author: Rook
Date: February 2, 2015
Called when a Battle Fury is acquired. Grants the cleave modifier if the caster is a melee hero.
================================================================================================================= ]]
function modifier_item_bfury_datadriven_on_created(keys)
if not keys.caster:IsRangedAttacker() then
keys.ability:ApplyDataDrivenModifier(keys.caster, keys.caster, "modifier_item_bfury_datadriven_cleave", {duration = -1})
end
end
--[[ ============================================================================================================
Author: Rook
Date: February 2, 2015
Called when a Battle Fury is removed from the caster's inventory. Removes a cleave modifier if they are a melee hero.
================================================================================================================= ]]
function modifier_item_bfury_datadriven_on_destroy(keys)
if not keys.caster:IsRangedAttacker() then
keys.caster:RemoveModifierByName("modifier_item_bfury_datadriven_cleave")
end
end
--[[ ============================================================================================================
Author: Rook
Date: February 2, 2015
Called regularly while the caster has a Battle Fury in their inventory. If the caster has switched from ranged
to melee, give them cleave modifier(s).
================================================================================================================= ]]
function modifier_item_bfury_datadriven_on_interval_think(keys)
if not keys.caster:IsRangedAttacker() and not keys.caster:HasModifier("modifier_item_bfury_datadriven_cleave") then
for i=0, 5, 1 do
local current_item = keys.caster:GetItemInSlot(i)
if current_item ~= nil then
if current_item:GetName() == "item_bfury_datadriven" then
keys.ability:ApplyDataDrivenModifier(keys.caster, keys.caster, "modifier_item_bfury_datadriven_cleave", {duration = -1})
end
end
end
end
end
--[[ ============================================================================================================
Author: Rook
Date: February 2, 2015
Called regularly while the caster has at least one cleave modifier from Battle Fury. If the caster is no longer
melee (which would be the case on, for example, Troll Warlord), remove the cleave modifiers from the caster.
================================================================================================================= ]]
function modifier_item_bfury_datadriven_cleave_on_interval_think(keys)
if keys.caster:IsRangedAttacker() then
while keys.caster:HasModifier("modifier_item_bfury_datadriven_cleave") do
keys.caster:RemoveModifierByName("modifier_item_bfury_datadriven_cleave")
end
end
end
Когда предмет был подобран, вызывается эта функция. Если герой БЛИЖНЕГО БОЯ, то даёт ему модификатор сплэша. Как вы поняли, если нет модификатора - нет сплэша.
IsRangedAttacker() - проверка на дальний бой. Однако если взять обратное значение типа:
If not IsRangedAttacker(), то всё работает на ура!)
Когда предмет был выброшен или продан, то удаляет модификатор, если герой БЛИЖНЕГО БОЯ.
Функция вызывается каждые 0.03 секунды и проверяет не переключился ли герой с ближнего на дальний бой.
Если да, то забирает модификатор.
Вызывается, если у героя есть хоть один модификатор сплэша, и затем проверяется не поменял ли герой свой тип атаки с ближнего на дальний. Если поменял - модификатор удаляется.
Путь: scripts/vscripts/items/item_bfury.lua
Название скрипта: item_bfury.lua
Поздравляем, теперь вы создали свой первый предмет!
Пока, что достаточно было просто скопировать код, но это уже много!
Старайтесь и у вас всегда будет получаться лучше и лучше!
Последнее редактирование модератором: