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

[lua, cache] Особенности функции ReplaceHeroWith

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

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
Недавно я столкнулся с необходимостью использовать функцию ReplaceHeroWith, и при использовании возникла вполне очевидная ситуация, героя меняет, но вместо модели героя и его вещей появилась моделька, а точнее ее отсутствие, она же ERROR.
Познакомьтесь с виспом:

Заменял его с помощью:
Код
PlayerResource:ReplaceHeroWith(playerid, "npc_dota_hero_wisp", gold, 0)
*Далее я буду использовать свена, для удобства
Чутка поразмыслив, не сложно догадаться что модельки не прокешированы, и нужно их прокешировать, первое что придет на ум это использовать
Код
PrecacheUnitByNameSync("npc_dota_hero_sven", function() end)
или же
Код
PrecacheUnitByNameASync("npc_dota_hero_sven", function() end)
Но и тут постиг фейл, моделька героя и стандартные шмотки загрузятся, а другие косметические(например всеми любимый дк хук) не загрузятся. Через lua пока что нельзя посмотреть какие шмотки надеты на герое, так что идем глубже и быдлокодим.
Если нельзя загрузить конкретную шмотку на героя, загрузим же их все на текущего героя.
Не секрет что шмотки(косметические) прописаны в items_game.txt
Значит необходимо загрузить этот файл, найти в нем все предметы на нашего героя(виспа) и прокешировать их по одному. Загружать оптимально при загрузке игры, что бы не тратить слишком много времени во время игры и не вызывать подлагиваний, значит кешируем сразу в Precache( contex)
Я нашел этот код на просторах гугла от автора Warchasers, но увы он положил на него свой болт, и не описал нигде функцию проверки по герою, так что пришлось быдлокодить ее.

Весь код можно разделить на несколько условных блоков:
  • чтение всего файла items_game.txt
  • выборка из файла раннее считанного в переменную(а точнее в массив таблицу) только косметических предметов
  • выборка из таблицы косметических предметов тех вещей, которые надеваются на нужных нам героев(ну или можно все грузить, и потратить минуты 2 при каждом старте игры) и пересылаем их в другую таблицу, в таблицу шмоток на кеширование
  • собственно кеширование всех моделей из таблицы на кэширование
Сам код( или на скрине в конце файла, там красивее выглядит)
Код
function Precache( context )
print('[Precache] Start')
local wearables = LoadKeyValues("scripts/items/items_game.txt") -- загружаем весь файл

local wearablesList = {} --переменная для надеваемых шмоток(для всех героев)
local precacheWearables = {} --переменная только для шмоток нужного героя
local precacheParticle = {}
for k, v in pairs(wearables) do
if k == 'items' then
wearablesList = v
end
end
local counter = 0
local counter_particle = 0
local value
for k, v in pairs(wearablesList) do -- выбираем из списка предметов только предметы на нужных героев
if IsForHero("npc_dota_hero_sven", wearablesList[k]) then
if wearablesList[k]["model_player"] then
value = wearablesList[k]["model_player"]
precacheWearables[value] = true
end
if wearablesList[k]["particle_file"] then -- прекешируем еще и частицы, куда ж без них!
value = wearablesList[k]["particle_file"]
precacheParticle[value] = true
end
end
end

for wearable,_ in pairs( precacheWearables ) do --собственно само прекеширование всех занесенных в список шмоток
print("Precache model: " .. wearable)
PrecacheResource( "model", wearable, context )
counter = counter + 1
end

for wearable,_ in pairs( precacheParticle) do --и прекеширование частиц
print("Precache particle: " .. wearable)
PrecacheResource( "particle", wearable, context )
counter_particle = counter_particle + 1

end

PrecacheUnitByNameSync("npc_dota_hero_sven", context) -- прекешируем саму модель героя! иначе будут бегать шмотки без тела
wearables = nil -- ОБНУЛЯЙТЕ ДЕТИ ПЕРЕМЕННЫЕ
wearablesList = {0} -- ОБНУЛЯЙТЕ ДЕТИ ПЕРЕМЕННЫЕ И МАССИВЫ, НЕ КУШАЙТЕ ПАМЯТИ ЛИШНЕЙ
precacheWearables = {0} -- ОБНУЛЯЙТЕ ДЕТИ ПЕРЕМЕННЫЕ И МАССИВЫ, НЕ КУШАЙТЕ ПАМЯТИ ЛИШНЕЙ
precacheParticle = {0}

print('[Precache]' .. counter .. " models loaded and " .. counter_particle .." particles loaded")
print('[Precache] End')
end

function IsForHero(str, tbl)
if type(tbl["used_by_heroes"]) ~= type(1) and tbl["used_by_heroes"] then -- привет от вашего друга, индийского быдлокодера работающего за еду
if tbl["used_by_heroes"][str] then
return true
end
end
return false
end
Собственно, прокешировав все шмотки мы получим дофига потраченных ресурсов прокешированные косметические предметы на героя, для свена одного например вышло порядка 100 шмоток. Учитывая что всего в файле тысячи шмоток, то это довольно быстро делается(за доли секунды на самом деле).

Ну собственно вот и все, может быть кому то и пригодится этот быдлокод.
Спасибо автору Warchasers за реализацию большей части.
PS. Если вы создавали кастомного героя и прописывали ему шмотки, то вам не нужно это все, вам хватит простого PrecacheUnitByNameSync/PrecacheUnitByNameASync!
Скрин кода прикладываю.
Спойлер
[свернуть]
« Последнее редактирование: 19-07-2015, 20:15:29 от CryDeS »

Оффлайн doter.ua

  • Друзья CG
  • 272
  • Мощь: 1
Полезная инфа есть, но новичкам такое показывать нельзя.
З.Ы. Мне показалось, или у вас поиск по таблице "перебором", вместо  прямого обращения по ключу.
гайды
сурпрайз mthfckr :D

[свернуть]

Оффлайн Se7eN

  • Продвинутый
  • 298
  • Мощь: 11
  • King
А вообще всё доступно и понятно, +rep) :-[

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
Полезная инфа есть, но новичкам такое показывать нельзя.
З.Ы. Мне показалось, или у вас поиск по таблице "перебором", вместо  прямого обращения по ключу.
Да, поиск по таблице перебором, по этому и быдлокод. Когда писал забыл про обращение по ключу. Переделаю чуть позже.
И вся суть темы в том что бы прекешировать косметические предметы нужных героев, видел на зарубежных форумах что спрашивают как это сделать, решил почему бы и не написать.
Переделал(но блок с кодом начал выдавать чудеса, незнаю почему  :( ), теперь кушает меньше ресурсов.
« Последнее редактирование: 14-07-2015, 12:09:05 от CryDeS »

Оффлайн Escapists Harmony

  • 70
  • Мощь: 1
Скажите пожалуйста, а если нужно нескольких героев таким образом прекешнуть, нужно столько же раз скопировать код начиная от print('[Precache] Start') и заканчивая return false т.е. все внутрь одной функции или нужно отдельную функцию делать? Или можно как то проще?  :o

Оффлайн Escapists Harmony

  • 70
  • Мощь: 1
И у меня кастомные герои, я их прекешнул через PrecacheUnitByNameSync, но при использовании replaceherowith (смена виспёнка на нужного героя) герой, на которого у меня надеты шмотки появляется "голым". Использовал ваш/warchasers код, все естественно работает. Только нужно на всех используемых мною героях сделать

Оффлайн Escapists Harmony

  • 70
  • Мощь: 1
О, кажись разобрался. На скриншоте увидел комментарий. Спасибо за гайд!)

Оффлайн Escapists Harmony

  • 70
  • Мощь: 1
Скажите пожалуйста, а что делать с кастомными партиклами в шмотках?? Сеты грузятся, но без них :'(

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
Скажите пожалуйста, а что делать с кастомными партиклами в шмотках?? Сеты грузятся, но без них :'(
Прикрепить их руками я думаю. не знаю есть ли они в itemlist

Оффлайн Escapists Harmony

  • 70
  • Мощь: 1
Тут нужны ребята поопытнее) Это мой первый опыт... Хотелось бы скрипт, подобный вашему. Чтоб не грузил систему и сам отбирал нужные частицы в зависимости от героя.

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
Тут нужны ребята поопытнее) Это мой первый опыт... Хотелось бы скрипт, подобный вашему. Чтоб не грузил систему и сам отбирал нужные частицы в зависимости от героя.
Нужно знать все частицы которые нужно грузить => нужно иметь список всех частиц для данного героя => нужно искать!
У кого есть идеи где искать, поищите (мб даже в самом itemlist хранятся, что довольно логично было бы) :)
Кстати вспомнил, все частицы для данного героя хранятся в папке с ним. Возможно(?) и частицы для предметов тоже, как вариант прокешировать всю папку с героем на наличие частиц? :D

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
Порылся в itemlist, увидел вот что
Спойлер
Код
"140"
...
"model_player" "models/heroes/phantom_assassin/phantom_assassin_weapon.mdl"
"particle_file" "particles/econ/items/phantom_assassin/phantom_assassin_weapon_generic.pcf"
...
[свернуть]
Исходя из этого эффекты на оружие хранится в ключе "particle_file", а из этого следует что по аналогии с функцией в шапке можно грузить еще и частицу, добавив всего несколько строк.
Спойлер
Код
for k, v in pairs(wearablesList) do -- выбираем из списка предметов только предметы на нужных героев
if IsForHero(heroname, wearablesList[k]) then
if wearablesList[k]["model_player"] then
value = wearablesList[k]["model_player"]
precacheWearables[value] = true
end
if wearablesList[k]["particle_file"] then
value = wearablesList[k]["particle_file"]
precacheParticle[value] = true
end
end
end
[свернуть]
Собственно почти все. Сейчас добавлю в шапку
« Последнее редактирование: 19-07-2015, 20:16:39 от CryDeS »

Оффлайн Escapists Harmony

  • 70
  • Мощь: 1
хм пишет что 0 particles loaded... При выборе героя кастомных партиклов на сете не появляется.

Оффлайн CryDeS

  • Друзья CG
  • 1200
  • Мощь: 12
хм пишет что 0 particles loaded... При выборе героя кастомных партиклов на сете не появляется.
Можешь сказать поточнее что за сет? И что за конкретно частица должна быть?

Оффлайн Escapists Harmony

  • 70
  • Мощь: 1
Сет на рики от версуты. Monstrous Reprisal. Там глаза и хвост. Это как пример. Просто у из тех героев, которые у меня на карте доступны, только на него у меня есть сет с частицами. При реплейсе героя, частиц нет. При создании вручную -createhero они есть. Все находятся в particles/econ/items/riki/riki_haze_atrocity
« Последнее редактирование: 20-07-2015, 23:10:02 от Escapists Harmony »