Listening to game events
Contents
Введение
Эта статья посвящена функции ListenToGameEvent(string eventName, handle functionToCall, handle context)
.
Пример 1
Каждый раз когда уровень героя повышается, сообщение показывается всем игрокам:
-- scripts/vscripts/addon_game_mode.lua
function LevelUpMessage (eventInfo)
Say(nil, "Один из героев повысил свой уровень!", false)
end
function Activate ()
ListenToGameEvent("dota_player_gained_level", LevelUpMessage, nil)
end
В данном скрипте используется две функции:
LevelUpMessage
: Здесь используется функцияSay
чтобы показать сообщение всем игрокам.Activate
: Игра вызывает эту функцию один раз при загрузке карты. При запуске этой функции вызывается функцияListenToGameEvent(string eventName, handle functionToCall, handle context)
с соответствующими параметрами.
Пример 2
Когда уровень героя достигает 6 показываем сообщение всем игрокам:
-- scripts/vscripts/addon_game_mode.lua
function Level6Message (eventInfo)
if eventInfo.level == 6 then
Say(nil, "Один из героев достиг 6-го уровня", false)
end
end
function Activate ()
ListenToGameEvent("dota_player_gained_level", Level6Message, nil)
end
В функции Level6Message
используется параметр eventInfo
для получения уровня героя.
Функция ListenToGameEvent
Здесь есть описание функции ListenToGameEvent
:
int ListenToGameEvent(string eventName, handle functionToCall, handle context)
Параметры
- eventName
- Имя события, которое будет прослушиваться(привязываться) к данной функции. Полный список событий можно посмотреть в этом списке Built-In Engine Events .
- functionToCall
- Функия, которая будет вызываться, когда событие будет срабатывать в игре.
- context
- Здесь можно использовать пустое значение
nil
или объект (например таблицу или функцию). Если вы используете объект в качестве параметра, то он будет передан функции functionToCall в качестве первого параметра, когда событие произойдет.
Детали события
При вызове функции ListenToGameEvent
с параметрами, происходит вызов функции, привязанной к событию каждый раз когда происходит это событие. Когда игра вызывает эту функцию, она передает таблицу с параметрами события. Эти параметры содержат информацию о событии. На странице Built-In Engine Events можно найти, какие параметры содержит то или иное событие. Например событие "dota_player_gained_level"
имеет параметр level
(смотри Пример 2 выше).
pairs
чтобы посмотреть какие параметры имеет та или иная таблица:
for key,val in pairs(tbl) do
print(key, val)
end
tbl
на имя таблицы, которую хотите проверить.)Функция вызываемая при возникновении события
Если ваша функция определена как:
function MyFunction (arg)
-- здесь ваш код
end
то вызов ListenToGameEvent
будет выглядеть так:
ListenToGameEvent("some_event_name", MyFunction, nil)
Но что если ваша функция определена так?
function MyClass:MyFunction (arg)
-- здесь мой код
end
Помни: Это короткий стиль
function MyClass.MyFunction (self, arg)
-- здесь мой код
end
Ваша функция принимает два параметра. В данной ситуации вызов ListenToGameEvent
будет выглядеть так:
ListenToGameEvent("some_event_name", MyClass.MyFunction, ?)
или так (смотри ЧАВО ниже):
ListenToGameEvent("some_event_name", Dynamic_Wrap(MyClass, "MyFunction"), ?)
Замените ?
на объект, который будет использоваться в качестве self
в функции. Далее идут примеры:
Пример 3
Кога NPC создается, выводим на экран сколько раз это произошло:
-- scripts/vscripts/addon_game_mode.lua
if MyClass == nil then
MyClass = class({})
end
function MyClass:InitGameMode ()
self.numSpawned = 0
ListenToGameEvent("npc_spawned", MyClass.MyFunction, self)
end
function MyClass:MyFunction ()
self.numSpawned = self.numSpawned + 1
print("NPC создался: " .. self.numSpawned .. " раз")
end
function Activate ()
GameRules.MyAddon = MyClass()
GameRules.MyAddon:InitGameMode()
end
Больше примеров
Пример 4
Когда игрок выбирает героя, мы даем ему артефакт BlinkDagger:
-- scripts/vscripts/addon_game_mode.lua
function GiveBlinkDagger (hero)
if hero:HasRoomForItem("item_blink", true, true) then
local dagger = CreateItem("item_blink", hero, hero)
dagger:SetPurchaseTime(0)
hero:AddItem(dagger)
end
end
function OnHeroPicked (event)
local hero = EntIndexToHScript(event.heroindex)
GiveBlinkDagger(hero)
end
function Activate ()
ListenToGameEvent("dota_player_pick_hero", OnHeroPicked, nil)
end
Пример 5
Команда, которая первая совершила 5 убийств побеждает:
-- scripts/vscripts/addon_game_mode.lua
if CustomGameMode == nil then
CustomGameMode = class({})
end
function Activate ()
GameRules.CustomAddon = CustomGameMode()
GameRules.CustomAddon:InitGameMode(5)
end
function CustomGameMode:InitGameMode (killLimit)
self.killLimit = killLimit
ListenToGameEvent("entity_killed", Dynamic_Wrap(CustomGameMode, "OnEntityKilled"), self)
end
function CustomGameMode:OnEntityKilled ()
if PlayerResource:GetTeamKills(DOTA_TEAM_GOODGUYS) == self.killLimit then
GameRules:SetGameWinner(DOTA_TEAM_GOODGUYS)
elseif PlayerResource:GetTeamKills(DOTA_TEAM_BADGUYS) == self.killLimit then
GameRules:SetGameWinner(DOTA_TEAM_BADGUYS)
end
end
Пример 6
Когда юнит умирает, он оставляет после себя артефакт healing salve (item_flask
):
-- scripts/vscripts/addon_game_mode.lua
function CreateDrop (itemName, pos)
local newItem = CreateItem(itemName, nil, nil)
newItem:SetPurchaseTime(0)
CreateItemOnPositionSync(pos, newItem)
newItem:LaunchLoot(false, 300, 0.75, pos + RandomVector(RandomFloat(50, 350)))
end
function OnEntityKilled (event)
local killedEntity = EntIndexToHScript(event.entindex_killed)
if killedEntity ~= nil then
CreateDrop("item_flask", killedEntity:GetAbsOrigin())
end
end
function Activate ()
ListenToGameEvent("entity_killed", OnEntityKilled, nil)
end
RollPercentage
для задания шанса дропа артефакта.ЧАВО
Вопрос: Что означает Dynamic_Wrap
?
Ответ: Используйте Dynamic_Wrap
если вы хотите, чтобы консольная команда "script_reload"
также перезагружала прослушивание событий.
Dynamic_Wrap
можно посмотреть здесь: /path/to/Steam/SteamApps/common/dota 2 beta/dota/scripts/vscripts/utils/vscriptinit.lua
.Больше деталей: предположим вы зарегистрировали прослушку события:
ListenToGameEvent("some_event_name", MyClass.MyFunction, someObj)
Если вы изменили исходный код функции MyClass.MyFunction
и затем вызвали команду "script_reload"
в консоли, ваши изменения не будут видны. Это будет до сих пор старая версия функции MyClass.MyFunction
. Чтобы это исправить используйте Dynamic_Wrap
:
ListenToGameEvent("some_event_name", Dynamic_Wrap(MyClass, "MyFunction"), someObj)
Теперь, каждый раз при возникновении события, игра проверяет функцию MyFunction
вместе с MyClass
и запускает его с новой функцией. Когда вы измените исходный код MyClass.MyFunction
и вызовете команду "script_reload"
в консоли, функция MyFunction
будет обновлена.