- Какие Lua-скрипты вообще существуют в Dota 2
- Папки и файлы: где хранить Lua
- Как Dota “понимает”, что надо выполнить ваш Lua (RunScript)
- Где писать код: какие функции ожидает Dota
- Как правильно вызывать модификаторы из Lua
- Клиент/сервер: почему “оно не работает” у многих
- Частые ошибки новичков и как их избежать
- Откуда брать основу: обучение через рабочие примеры
- Небольшая “карта” процесса: что сделать, чтобы Lua реально заработал
- Источники (официальные и максимально релевантные)
- Итог
Lua-скрипты в Dota 2 запускаются не “просто потому что вы их написали”, а только когда Dota сама загружает Lua в нужном месте: через Lua-скрипты abilities/modifiers или через datadriven (когда в файлах конфигурации прописан RunScript на конкретную функцию в Lua). Поэтому ответ на вопрос “как использовать Lua скрипты в доте” сводится к тому, чтобы правильно подключить скрипт к игровым сущностям (модификаторам, способностям, item-ам) и убедиться, что код исполняется в клиенте/сервере там, где это предусмотрено.
Какие Lua-скрипты вообще существуют в Dota 2
В реальности в Dota 2 вы работаете с Lua как с прикладным слоем, который вызывает игровое окружение Dota. Почти всегда речь про один из вариантов:
| Вариант | Где подключается | Что реально запускает Dota | Для чего обычно |
|---|---|---|---|
| Ability / Modifier Script | В описании способности/модификатора (внутри datadriven или KV) | Dota грузит Lua, когда создаётся способность/модификатор | Логика скиллов, пассивки, поведение модификаторов |
Datadriven RunScript |
В .txt конфигурации datadriven (item/ability) |
Dota вызывает указанную Lua-функцию при событии | Сценарии предметов, кастомных реакций на события |
| Отладка Lua в инструментах | Через встроенные инструменты/консольные команды разработчика | Инструменты загружают/выполняют скрипты | Проверка Lua-кода, диагностика |
Главный принцип: Dota должна “узнать” ваш Lua-файл и вашу функцию из KV/datadriven. Самостоятельно “инжектить Lua VM” или подменять окружение — это другая история (и в игре обычно не даст результата, если вы не повторяете именно то API и именно тот рантайм Dota).
Папки и файлы: где хранить Lua
Самый частый путь для логики предметов/модификаторов в кастомной datadriven-части:
| Назначение | Типичный путь |
|---|---|
| Lua предметов/модификаторов в datadriven | scripts/vscripts/items/ (или другая подпапка внутри vscripts) |
| KV/Datadriven описания | файлы в структуре npc_*.txt, где Dota читает datadriven-описания |
В примере battle fury (datadriven) Lua лежит как:
scripts/vscripts/items/item_bfury.lua
А в datadriven указывается путь:
"ScriptFile" "items/item_bfury.lua"
Обратите внимание: в ScriptFile путь задаётся относительно vscripts (то есть без scripts/vscripts/ в начале).
Как Dota “понимает”, что надо выполнить ваш Lua (RunScript)
События в datadriven подключают Lua через блок RunScript. Примерная схема выглядит так:
- В
.txtdatadriven вы объявляете модификатор. - Для нужного события (например,
OnCreated,OnDestroy,OnIntervalThink) добавляетеRunScript. - Внутри
RunScriptуказываете: ScriptFile(Lua-файл)Function(имя функции в Lua)
В battle fury это сделано так:
"OnCreated"
{
"RunScript"
{
"ScriptFile" "items/item_bfury.lua"
"Function" "modifier_item_bfury_datadriven_on_created"
}
}
А для таймера:
"OnIntervalThink"
{
"RunScript"
{
"ScriptFile" "items/item_bfury.lua"
"Function" "modifier_item_bfury_datadriven_on_interval_think"
}
}
То есть Dota сама вызывает Lua, когда:
1) модификатор создан/удалён/получил tick,
2) срабатывает событие,
3) выполнено условие RunScript.
Где писать код: какие функции ожидает Dota
В Lua вы пишете именно те функции, которые прописаны в Function в RunScript.
Для модификатора предмета в примере battle fury используются:
modifier_item_bfury_datadriven_on_created(keys)modifier_item_bfury_datadriven_on_destroy(keys)modifier_item_bfury_datadriven_on_interval_think(keys)modifier_item_bfury_datadriven_cleave_on_interval_think(keys)
Обычно Dota передаёт в аргумент keys контекст (кастер, способность, параметры события и т.д.). В вашем Lua доступно то, что Dota кладёт в keys.
Пример логики (смысл тот же, что в исходном материале):
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
Ключевой момент: если вы назвали функцию иначе, чем в Function — Dota её не найдёт. Если вы ожидаете поля в keys, которых там нет — логика сломается.
Как правильно вызывать модификаторы из Lua
В datadriven логике обычно используется:
| Что нужно | Как делают |
|---|---|
| Присвоить модификатор юниту | keys.ability:ApplyDataDrivenModifier(caster, target, "modifier_name", {duration = ...}) |
| Снять модификатор | caster:RemoveModifierByName("modifier_name") |
| Проверять состояние | caster:IsRangedAttacker(), caster:HasModifier("modifier_name") |
В battle fury модификатор клива выдаётся только если герой ближнего боя, и снимается при смене формы (у юнитов типа Troll Warlord это критично).
Клиент/сервер: почему “оно не работает” у многих
Самая частая причина, когда люди пытаются “использовать Lua скрипты в доте” не через правильные точки входа: они ожидают, что Lua вызовется и в том месте, где Dota этого не делает.
Практические правила:
- Ваш Lua код для способностей/модификаторов должен быть подключён через datadriven/KV так, чтобы Dota сама его грузила и вызывала.
- Если вы запускаете Lua вне этого механизма (например, через внешний injector/DLL), то вы не получаете нужное игровое API и нужный контекст исполнения Dota. Тогда
Entities,GetLocalPlayerи подобные вещи просто не существуют в том окружении, которое вы создали. Даже если Lua “запускается”, игровые сущности и методы не появятся сами.
Именно поэтому правильный путь для “обычного использования Lua в Dota” — это datadriven + RunScript или скрипты abilities/modifiers, а не самостоятельная VM со своим окружением.
Частые ошибки новичков и как их избежать
| Ошибка | Почему так | Как исправить |
|---|---|---|
| “Скрипт есть, но в игре ничего не происходит” | Dota не знает, что грузить, или событие не наступило, или путь/имя функции не совпало | Проверьте ScriptFile, Function, имя модификатора и что модификатор реально создаётся |
| “Функции вызываются, но логика не выполняется” | Условия проверяются не так (например, вы перепутали IsRangedAttacker() и инверсию) |
Сверьте условия типов атаки/формы юнита |
| “Код ломается на попытке использовать Entities/GetLocalPlayer” | Это не тот API и не тот рантайм Dota, который доступен в встроенных Lua-скриптах | Используйте функции Dota через keys/контекст abilities/modifiers |
“Пишу OnIntervalThink, но всё не тикет” |
Не задан ThinkInterval или модификатор не активен/не создан |
Убедитесь, что в datadriven есть ThinkInterval и что модификатор действительно существует |
Откуда брать основу: обучение через рабочие примеры
Самый надёжный способ научиться — брать пример datadriven предмета, где:
- есть секция модификатора,
- есть RunScript на события,
- есть ApplyDataDrivenModifier и RemoveModifierByName.
Battle fury из примера как раз такой: там через OnCreated выдаётся модификатор клива, через OnDestroy он убирается, а через ThinkInterval происходит контроль смены ближний/дальний.
Небольшая “карта” процесса: что сделать, чтобы Lua реально заработал
| Шаг | Что сделать | Результат |
|---|---|---|
| Подготовить datadriven/KV | Создать/объявить модификатор или способность и привязать к ней события | Dota начинает вызывать ваши обработчики |
| Создать Lua-файл в нужной папке | Например scripts/vscripts/items/item_bfury.lua |
Код доступен по пути ScriptFile |
Добавить RunScript в события |
ScriptFile + Function |
Dota вызывает вашу Lua-функцию в нужный момент |
В Lua использовать контекст keys |
keys.caster, keys.ability, ApplyDataDrivenModifier |
Модификаторы и логика начинают работать как задумано |
Источники (официальные и максимально релевантные)
- Valve Developer Community: Lua Abilities and Modifiers (как устроены abilities/modifiers Lua)
https://developer.valvesoftware.com/wiki/Ru/Dota_2_Workshop_Tools/Lua_Abilities_and_Modifiers - Valve Developer Community: Debugging Lua scripts (как отлаживать Lua в контексте Dota)
https://developer.valvesoftware.com/wiki/Ru/Dota_2_Workshop_Tools/Scripting/Debugging_Lua_scripts
Итог
Чтобы использовать Lua-скрипты в Dota 2, нужно не “выполнить Lua где-то”, а подключить его к игровому механизму, чтобы Dota сама загрузила ваш файл и вызвала ваши функции. Самый понятный рабочий паттерн — datadriven + RunScript, как в примере battle fury: OnCreated/OnDestroy/OnIntervalThink в .txt вызывают нужные функции в вашем Lua-файле, а дальше вы управляете модификаторами через ApplyDataDrivenModifier и RemoveModifierByName.