Dota 2 Workshop Tools:ru/Scripting:ru/Listening to game events:ru

From Valve Developer Community
Jump to: navigation, search
English

Введение

Эта статья посвящена функции 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 выше).


Предупреждение:Так как Valve иногда изменяет события, список Built-In Engine Events может быть не актуальным. Можно использовать функцию lua 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 будет обновлена.