CustomGames.ru - Dota 2 пользовательские игры

Кодим функции: "дроп с игрока" или "будьте внимательнее"

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Илья

  • Супермодератор
  • 1904
  • Мощь: 16
Итак, в этой теме  я задавал вопрос: "а как сделать так, чтобы при смерти героя, с него выпадали его вещи?"
Создал отдельную тему, ибо так код будет проще найти да и это же все же скрипт.
Почему не "можно ли", а сразу "как"? Ну, об этом не здесь.

Значит, на данный момент, более простого способа не нашел. На более красивый мне делает намеки 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 
[свернуть]
« Последнее редактирование: 12-10-2015, 22:38:16 от Илья »

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
Шикарное разбирательство. Плюсанул бы, да сайт уже запрещает тебя плюсить -.-

Оффлайн Илья

  • Супермодератор
  • 1904
  • Мощь: 16
Шикарное разбирательство. Плюсанул бы, да сайт уже запрещает тебя плюсить -.-

Спасибо, мне тебя уже тоже плюсовать нельзя)

Оффлайн Илья

  • Супермодератор
  • 1904
  • Мощь: 16
Решая некоторые новые вопросы на GitHab`e, наткнулся на один интересный источник.

Таким образом можно задавать конкретной вещи "пассивку" , которая будет ее дропать из инвентаря игрока.
А раз мой код похож на этот, то я не могу не радоваться, ибо выходит, что я более менее правильно реализовал идею.

Может, кому пригодиться на будущее: кто любит прилагать больше усилий, но при этом делать основной код легче.
« Последнее редактирование: 16-10-2015, 12:45:37 от Илья »

Оффлайн xxNpCxx

  • 85
  • Мощь: 0
  • Do it simple bitch
Итак, в этой теме  я задавал вопрос: "а как сделать так, чтобы при смерти героя, с него выпадали его вещи?"
Создал отдельную тему, ибо так код будет проще найти да и это же все же скрипт.
Почему не "можно ли", а сразу "как"? Ну, об этом не здесь.

Значит, на данный момент, более простого способа не нашел. На более красивый мне делает намеки 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 
[свернуть]
Молодец!