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

CryDeS

Друзья CG
14 Июл 2015
1,210
11
Недавно я столкнулся с необходимостью использовать функцию ReplaceHeroWith, и при использовании возникла вполне очевидная ситуация, героя меняет, но вместо модели героя и его вещей появилась моделька, а точнее ее отсутствие, она же ERROR.
Познакомьтесь с виспом:
image.png

Заменял его с помощью:
Код:
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, но увы он положил на него свой болт, и не описал нигде функцию проверки по герою, так что пришлось быдлокодить ее.

Весь код можно разделить на несколько условных блоков:

  • [li]чтение всего файла items_game.txt[/li]
    [li]выборка из файла раннее считанного в переменную(а точнее в массив таблицу) только косметических предметов[/li]
    [li]выборка из таблицы косметических предметов тех вещей, которые надеваются на нужных нам героев(ну или можно все грузить, и потратить минуты 2 при каждом старте игры) и пересылаем их в другую таблицу, в таблицу шмоток на кеширование[/li]
    [li]собственно кеширование всех моделей из таблицы на кэширование[/li]
Сам код( или на скрине в конце файла, там красивее выглядит)
Код:
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!
Скрин кода прикладываю.
image.png
 
Последнее редактирование модератором:

doter.ua

Продвинутый
17 Авг 2014
280
5
Полезная инфа есть, но новичкам такое показывать нельзя.
З.Ы. Мне показалось, или у вас поиск по таблице "перебором", вместо прямого обращения по ключу.
 
Последнее редактирование модератором:

CryDeS

Друзья CG
14 Июл 2015
1,210
11
Полезная инфа есть, но новичкам такое показывать нельзя.
З.Ы. Мне показалось, или у вас поиск по таблице "перебором", вместо прямого обращения по ключу.
Да, поиск по таблице перебором, по этому и быдлокод. Когда писал забыл про обращение по ключу. Переделаю чуть позже.
И вся суть темы в том что бы прекешировать косметические предметы нужных героев, видел на зарубежных форумах что спрашивают как это сделать, решил почему бы и не написать.
Переделал(но блок с кодом начал выдавать чудеса, незнаю почему :( ), теперь кушает меньше ресурсов.
 
Последнее редактирование модератором:

Escapists Harmony

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

Escapists Harmony

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

Escapists Harmony

Активный
4 Июл 2015
70
0
О, кажись разобрался. На скриншоте увидел комментарий. Спасибо за гайд!)
 

Escapists Harmony

Активный
4 Июл 2015
70
0
Скажите пожалуйста, а что делать с кастомными партиклами в шмотках?? Сеты грузятся, но без них :'(
 

CryDeS

Друзья CG
14 Июл 2015
1,210
11
Последнее редактирование модератором:

Escapists Harmony

Активный
4 Июл 2015
70
0
Тут нужны ребята поопытнее) Это мой первый опыт... Хотелось бы скрипт, подобный вашему. Чтоб не грузил систему и сам отбирал нужные частицы в зависимости от героя.
 

CryDeS

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

CryDeS

Друзья CG
14 Июл 2015
1,210
11
Порылся в 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
Собственно почти все. Сейчас добавлю в шапку
 
Последнее редактирование модератором:

Escapists Harmony

Активный
4 Июл 2015
70
0
хм пишет что 0 particles loaded... При выборе героя кастомных партиклов на сете не появляется.
 

CryDeS

Друзья CG
14 Июл 2015
1,210
11
хм пишет что 0 particles loaded... При выборе героя кастомных партиклов на сете не появляется.
Можешь сказать поточнее что за сет? И что за конкретно частица должна быть?
 
Последнее редактирование модератором:

Escapists Harmony

Активный
4 Июл 2015
70
0
Сет на рики от версуты. Monstrous Reprisal. Там глаза и хвост. Это как пример. Просто у из тех героев, которые у меня на карте доступны, только на него у меня есть сет с частицами. При реплейсе героя, частиц нет. При создании вручную -createhero они есть. Все находятся в particles/econ/items/riki/riki_haze_atrocity
 

CryDeS

Друзья CG
14 Июл 2015
1,210
11
Сет на рики от версуты. Monstrous Reprisal. Там глаза и хвост. Это как пример. Просто у из тех героев, которые у меня на карте доступны, только на него у меня есть сет с частицами. При реплейсе героя, частиц нет. При создании вручную -createhero они есть. Все находятся в particles/econ/items/riki/riki_haze_atrocity
Попробуй вручную прекешировать при старте игры чисто эти частицы, и скажи получилось или нет.
Код:
 PrecacheResource("particle_folder", "particles/econ/items/riki", context)
А порывшись в itemlist я наткнулся на такую строку, которую вроде скрипт сверху должен обрабатывать.
Код:
"particle_file"		"particles/econ/items/riki/riki_haze_atrocity.pcf"
PS. Если при ручно прекеширование папки с частичками все равно не будет частиц, значит проблема в том что ReplaceHeroWith не создает сами частички.
 
Последнее редактирование модератором:

Escapists Harmony

Активный
4 Июл 2015
70
0
Есть ли вариант как не используя этот код, давать игрокам героя с дефолтным сетом? Т.е. сбрасывать надетые ими шмотки.
 

CryDeS

Друзья CG
14 Июл 2015
1,210
11
Есть ли вариант как не используя этот код, давать игрокам героя с дефолтным сетом? Т.е. сбрасывать надетые ими шмотки.
По идее можно прикрепить любые шмотки(в том числе и стандартные), одно но, как это сделать нормально пока загадка. Для каждого героя на каждую шмотку есть свое название слота, которое нигде не прописано(или я не нашел). Так что надо разобраться в названиях слотов на каждого героя, и сделать отдельную функцию для переодевания. Готовой пока нет нигде.
 
Последнее редактирование модератором:

Escapists Harmony

Активный
4 Июл 2015
70
0
То есть функция ReplaceHeroWith на данный момент полноценно меняет героя (хотя бы с дефолтными шмотками) только с танцами? Я почему спрашиваю, у меня две проблемы:

1) Кто бы ни был лидером лобби, хостом автоматически становлюсь я. Все игроки не загружаются, пытаются переподключаться, но в конечном итоге имеют статус failed.
2) Даже если игроки загружаются (что происходит крайне редко), при замене виспа ( который выдается всем форсировано и у которого они видят модель) они видят Error вместо героев. Вообще нет никакой модели. В то время как я вижу их всех правильно.

У меня есть подозрение что это связано с этим кодом. Хотя на самом деле, я в растерянности.
 

CryDeS

Друзья CG
14 Июл 2015
1,210
11
То есть функция ReplaceHeroWith на данный момент полноценно меняет героя (хотя бы с дефолтными шмотками) только с танцами? Я почему спрашиваю, у меня две проблемы:

1) Кто бы ни был лидером лобби, хостом автоматически становлюсь я. Все игроки не загружаются, пытаются переподключаться, но в конечном итоге имеют статус failed.
2) Даже если игроки загружаются (что происходит крайне редко), при замене виспа ( который выдается всем форсировано и у которого они видят модель) они видят Error вместо героев. Вообще нет никакой модели. В то время как я вижу их всех правильно.

У меня есть подозрение что это связано с этим кодом. Хотя на самом деле, я в растерянности.
Функция полноценно меняет героя на другого, но без прекеширования шмоток. А то что хостом становишься ты, это я не знаю, где то очень серьезные ошибки видимо по ходу кода( у меня все работает нормально, и прокешировав героя в precache все игроки видят модели после замены без всяких ошибок, проверяй свои костыли, где то есть серьезный)
 
Последнее редактирование модератором:
Реклама: