- 25 Сен 2015
- 2,348
- 41
Итак, в этой теме я задавал вопрос: "а как сделать так, чтобы при смерти героя, с него выпадали его вещи?"
Создал отдельную тему, ибо так код будет проще найти да и это же все же скрипт.
Почему не "можно ли", а сразу "как"? Ну, об этом не здесь.
Значит, на данный момент, более простого способа не нашел. На более красивый мне делает намеки CryDeS, за что ему спасибо, но мне тааак лень реализовывать это. Да и ресурсы, которые в итоге будут сэкономлены, не так важны в данной ситуации (мы же не шаттл строим).
Первым делом обращаем внимание на слушателя:
И, взятой отсюда, пример функции вроде:
Кто читал эту тему, да и просто, кто "почти в теме", зададуться сразу же вопросом: хммм, чувак, да по стуи, можно взять этот код, задать слушателю ловить не убийство юнитов, а убийство конкретно игрока, сменить в функции "OnEntityKilled":
на
Покопаться в этом источнике в поисках подходящих функция и готово, получится что-то вроде этого:
Однако, жмем мы такие, значит, кнопку build и, будучи Бэном Аффлеком, говорим: "Я бэтмен".
А нам в ответ: "нет".
Вы такие: "Что, вот мой костюм, я Бэтмен! "
А вам : "Вы не Кристиан Бэйл".
К чему я это... Да к тому, что код не заработает.
Однако, если мутить не через GetPlayer() при смерти героя, а через EntIndexToHScript() при смерти юнита, то все работает. В чем же косяк? Почему так? Да дело в том, что хоть обе функции
Дают нам handle`r,это еще не говорит о том, что это один и тот же handle`r (хотя в ООП, получая один и тот же класс, тип данных, вы точно уверены, что можете с ним творить то, что разрешено делать с этим классом в документации).
Нет, ребята, тут не ООП. И моя невнимательность привела меня к ошибке.
Так что же не так? А вот, что: если обратить внимание на шапки функций, то можно увидеть следующую картину:
Кто еще не понял, разъясню: дело в том, что handle`r из метода GetPlayer() относится к классу "CDOTA_PlayerResource", а мы пытаемся на нем развернуть метод, который относится к "CDOTA_BaseNPC_Hero". Обертка одинаковая, а начинка разная.
На "схеме 1" видно, что это методы двух разных дорог, полос развития. На handle`r из GetPlayer() можно воздействовать методами из CBaseEntity, но нельзя воздействовать методами CBazeAnimating и т.д. Однако, методы ветки CBazeAnimating работают для handle`r из Global (EntIndexToHScript()). Handle`r из GetPlayer() - он player-овский, а handle`r из EntIndexToHScript() - это handle`r entity-вский. Хоть player в теории изначально и был entity, но он уже не помидор, а кетчуп.
Но, копаясь дальше в "CDOTA_PlayerResource", находим интересную функцию:
Что это, спросите вы меня? А я вам скажу - это сокосжиматель, делающий из кетчупа помидор.
Конечный код:
Создал отдельную тему, ибо так код будет проще найти да и это же все же скрипт.
Почему не "можно ли", а сразу "как"? Ну, об этом не здесь.
Значит, на данный момент, более простого способа не нашел. На более красивый мне делает намеки CryDeS, за что ему спасибо, но мне тааак лень реализовывать это. Да и ресурсы, которые в итоге будут сэкономлены, не так важны в данной ситуации (мы же не шаттл строим).
Первым делом обращаем внимание на слушателя:
Код:
ListenToGameEvent("entity_killed", OnEntityKilled, nil)
И, взятой отсюда, пример функции вроде:
Код:
function OnEntityKilled (event)
local killedEntity = EntIndexToHScript(event.entindex_killed)
if killedEntity ~= nil then
CreateDrop("item_flask", killedEntity:GetAbsOrigin())
end
end
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
Кто читал эту тему, да и просто, кто "почти в теме", зададуться сразу же вопросом: хммм, чувак, да по стуи, можно взять этот код, задать слушателю ловить не убийство юнитов, а убийство конкретно игрока, сменить в функции "OnEntityKilled":
Код:
local killedEntity = EntIndexToHScript(event.entindex_killed)
на
Код:
local killedPlayer = PlayerResource:GetPlayer(data.PlayerID)
Покопаться в этом источнике в поисках подходящих функция и готово, получится что-то вроде этого:
Код:
function FT:InitGameMode()
ListenToGameEvent("dota_player_killed", Dynamic_Wrap(FT, "OnHeroKilled"), self) --ловим событие смерти игрока
end
function FT:OnHeroKilled(data)
local killedPlayer = PlayerResource:GetPlayer(data.PlayerID) --получаем игрока
if killedPlayer:GetNumItemsInInventory() ~=0 then --проверяем наличие вещей в инвентаре
for i=0,5 do --Дорогая, как же все шестеро детей на месте? смотри: 0, 1, 2...
local item = killedPlayer:GetItemInSlot(i); --получаем вещицу из слота инвентаря
--не знаю, как можно выяснить номера ячеек с вещью, поэтому мутим так
if item ~= nil then --проверяем на пустую ячейку
local position = killedPlayer:GetAbsOrigin() -- позиция игрока
local name = item:GetAbilityName() -- берем имя шмоточки, не знаю альтернативной функции
killedPlayer:RemoveItem(item) -- удаляем шмоточку из инвентаря
FT:CreateDrop(name, position) -- создаем шмоточку по имени
end
end
end
end
function FT: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
Однако, жмем мы такие, значит, кнопку build и, будучи Бэном Аффлеком, говорим: "Я бэтмен".
А нам в ответ: "нет".
Вы такие: "Что, вот мой костюм, я Бэтмен! "
А вам : "Вы не Кристиан Бэйл".
К чему я это... Да к тому, что код не заработает.
Однако, если мутить не через GetPlayer() при смерти героя, а через EntIndexToHScript() при смерти юнита, то все работает. В чем же косяк? Почему так? Да дело в том, что хоть обе функции
Дают нам handle`r,это еще не говорит о том, что это один и тот же handle`r (хотя в ООП, получая один и тот же класс, тип данных, вы точно уверены, что можете с ним творить то, что разрешено делать с этим классом в документации).
Нет, ребята, тут не ООП. И моя невнимательность привела меня к ошибке.
Так что же не так? А вот, что: если обратить внимание на шапки функций, то можно увидеть следующую картину:
(схема 1)
Кто еще не понял, разъясню: дело в том, что handle`r из метода GetPlayer() относится к классу "CDOTA_PlayerResource", а мы пытаемся на нем развернуть метод, который относится к "CDOTA_BaseNPC_Hero". Обертка одинаковая, а начинка разная.
На "схеме 1" видно, что это методы двух разных дорог, полос развития. На handle`r из GetPlayer() можно воздействовать методами из CBaseEntity, но нельзя воздействовать методами CBazeAnimating и т.д. Однако, методы ветки CBazeAnimating работают для handle`r из Global (EntIndexToHScript()). Handle`r из GetPlayer() - он player-овский, а handle`r из EntIndexToHScript() - это handle`r entity-вский. Хоть player в теории изначально и был entity, но он уже не помидор, а кетчуп.
Но, копаясь дальше в "CDOTA_PlayerResource", находим интересную функцию:
Что это, спросите вы меня? А я вам скажу - это сокосжиматель, делающий из кетчупа помидор.
Конечный код:
Код:
function FT:InitGameMode()
ListenToGameEvent("dota_player_killed", Dynamic_Wrap(FT, "OnHeroKilled"), self)
en
function FT:OnHeroKilled(data)
print("----------------------------------------Hero Killed----------------------------------------")
local killedEntity = PlayerResource:GetSelectedHeroEntity(data.PlayerID)
if killedEntity:GetNumItemsInInventory() ~=0 then
for i=0,5 do
local item = killedEntity:GetItemInSlot(i);
if item ~= nil then
local position = killedEntity:GetAbsOrigin()
local name = item:GetAbilityName()
killedEntity:RemoveItem(item)
FT:CreateDrop(name, position)
end
end
end
end
function FT: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
Последнее редактирование модератором: