Здесь я попытаюсь показать процесс создания пика и рассказать что-нибудь по теме. Пишу это сразу как только проснулся, так что могу где-то затупить, пишите в комментах, исправлю.
Итак, свой пик героев нужен скорее всего для того, чтобы разделить героев света и тьмы. Если же вам просто нужно выдавать разного героя для каждой команды, то панорама для этого не нужна.
Начнём наверное с неё, ибо это самое простенькое для меня:
PANORAMA
Вроде с панорамой всё, теперь луа:
LUA
Вроде всё, как вы поняли я не писал это специально для гайда, я делаю кастомку и взял код, что написал оттуда, и сделал гайд из этого, немного поменяв код под это.
Так как я делаю кастомки в доте и играю в пупк у меня нет друзей и эту штуку и проверял только в соло, а кастомка моя ещё не готова, я был бы благодарен если бы вы проверили это с друзьями или ещё с кем-то и отписались, что работает или не работает.
Я всё ещё не очень проснулся и мог реально где-то ошибица поэтому пишите в комментах я исправлю всё.
уф, больше часа потратил на этот гайд, и это не считая сколько я этот код писал, хотя выглядит он не таким сложным(и гайд и код), если вам понравилось поставьте люкантропа пожалуйста
UPD1: Добавил пример
UPD2: исправил ошибку, которую ниже описали, спасибо кста
этот гайд очень устарел лично для меня, всё можно гораздо лучше сделать, но мне лень
Итак, свой пик героев нужен скорее всего для того, чтобы разделить героев света и тьмы. Если же вам просто нужно выдавать разного героя для каждой команды, то панорама для этого не нужна.
Начнём наверное с неё, ибо это самое простенькое для меня:
PANORAMA
Создаём нужные файлы, а именно:
В "content/dota_addons/addon_name/panorama/layout/custom_game" надо создать "pick.xml",
в "content/dota_addons/addon_name/panorama/styles" надо создать "pick.css"
и в "content/dota_addons/addon_name/panorama/scripts" надо создать "pick.js"
Подключаем нужные файлы:
В "content/dota_addons/addon_name/panorama/layout/custom_game/custom_ui_manifest.xml" надо подключить новый элемент худа.
(Да, делать пик мы будем уже после спавна героев, по другому никак(наверное), поэтому это элемент именно худа игры, а не выбора или загрузочного экрана).
В созданном нами "pick.xml" надо подключить файлы стилей и скриптов:
А теперь, когда всё подключено, можно начинать писать штуки.
(Я надеюсь, что с css вы сами разберётесь и поставите что надо, куда надо. Если, что чекайте мой старый(относительно) Гайд по загрузочному экрану.)
Начнём с "pick.xml":
Вроде всё просто, да? теперь переходим к "pick.js", js для меня это что-то дико непонятное я вообще иногда в шоке как что-то, что я пишу на js работает(впрочем не только на js).
Надо всё же упомянуть кое-что про css, в моём примере используется стиль, который я ещё пару лет назад взял из петров и использую до сих пор:
В "content/dota_addons/addon_name/panorama/layout/custom_game" надо создать "pick.xml",
в "content/dota_addons/addon_name/panorama/styles" надо создать "pick.css"
и в "content/dota_addons/addon_name/panorama/scripts" надо создать "pick.js"
Подключаем нужные файлы:
В "content/dota_addons/addon_name/panorama/layout/custom_game/custom_ui_manifest.xml" надо подключить новый элемент худа.
(Да, делать пик мы будем уже после спавна героев, по другому никак(наверное), поэтому это элемент именно худа игры, а не выбора или загрузочного экрана).
XML:
<CustomUIElement type="Hud" layoutfile="file://{resources}/layout/custom_game/pick.xml" />
XML:
<scripts>
<include src="file://{resources}/scripts/pick.js" />
</scripts>
<styles>
<include src="file://{resources}/styles/pick.css" />
</styles>
А теперь, когда всё подключено, можно начинать писать штуки.
(Я надеюсь, что с css вы сами разберётесь и поставите что надо, куда надо. Если, что чекайте мой старый(относительно) Гайд по загрузочному экрану.)
Начнём с "pick.xml":
XML:
<root>
//-это у вас уже должно быть
<scripts>
<include src="file://{resources}/scripts/pick.js" />
</scripts>
<styles>
<include src="file://{resources}/styles/pick.css" />
</styles>
//-
<Panel> //первая панель всегда без id, ибо дота ругается по какой-то причине.
<Panel id="bg"> // это панель заднего фона, в css ставим 1920x1080 и чёрный фон, можно картинку по желанию
<Panel id="radiant"> // герои света
<Button id="dragon_knight" onactivate="PickHero('dragon_knight');"> // кнопка выбора героя, которая вызывает функцию js и отправляет имя героя. У вас таких будет несколько, под каждого героя, у меня одня, для примера
<Image class="icon" src="file://{images}/pick/dragon_knight.png"/> //картинка на кнопке
</Button>
</Panel>
<Panel id="dire"> // герои тьмы
<Button id="pudge" onactivate="PickHero('pudge');">
<Image class="icon" src="file://{images}/pick/pudge.png"/>
</Button>
</Panel>
</Panel>
<Panel id="timer"> // таймер, если у вас ограниченное время на выбор героев
<Label id="timerlabel" text="60"/>
</Panel>
</Panel>
</root>
Вроде всё просто, да? теперь переходим к "pick.js", js для меня это что-то дико непонятное я вообще иногда в шоке как что-то, что я пишу на js работает(впрочем не только на js).
Надо всё же упомянуть кое-что про css, в моём примере используется стиль, который я ещё пару лет назад взял из петров и использую до сих пор:
CSS:
.Hide
{
transform: translate3d( 75px, 0px, 0px );
blur: gaussian( 15.0 );
opacity: 0.0;
}
JavaScript:
//-здесь ставим слушатели на кастомные ивенты из луа
GameEvents.Subscribe( "ban_hero", OnBanHero);
GameEvents.Subscribe( "send_time", OnTime);
GameEvents.Subscribe( "time_over", OnTimeOver);
GameEvents.Subscribe( "prepare", OnPrepare);
//-
function OnPrepare(arg){ // функция в которой мы будем прятать героев противопложной команды для игрока
$.Msg("#" + arg.key1)
$("#" + arg.key1).ToggleClass("Hide");
}
function PickHero(hero) { // функция, которую запускает наша кнопка в "pick.xml", отправляет имя выборанного героя в луа
var data = {
pick: hero,
}
GameEvents.SendCustomGameEventToServer( "pick_hero_event", data );
$("#bg").DeleteAsync(0.0);
}
function OnBanHero(arg){ //функция, которая прячет героя для всех игроков после выбора, если у вас одного героя могут выбрать несколько раз, то она вам не нужна
$("#" + arg.key1).ToggleClass("Hide");
}
function OnTime(arg){ //функция отсчёта времени, ненужна если у вас неогранниченное время на выбор героя
$("#timerlabel").text = arg.key1;
}
function OnTimeOver(){ // функция, которая удаляет пик с экрана
$("#bg").DeleteAsync(0.0);
}
Вроде с панорамой всё, теперь луа:
LUA
Lua для меня не так сложен, как js, но код выглядит так, будто я хотел построить дом из дерева и пошёл в шахту.
У меня есть свой отдельный файл для некоторых функций, но вы можете и в одном файле всё написать.
Я использую barebones и файл events.lua соответственно.
Начнём с него
events.lua:
теперь gamemode.lua:
В фукции GameMode:InitGameMode() регаем слушателя:
и пишем в этой функции:
далее у меня свой файл, но вы можете писать в одном из предыдущих:
У меня есть свой отдельный файл для некоторых функций, но вы можете и в одном файле всё написать.
Я использую barebones и файл events.lua соответственно.
Начнём с него
events.lua:
Lua:
function GameMode:OnNPCSpawned(keys)
DebugPrint("[BAREBONES] NPC Spawned")
DebugPrintTable(keys)
local npc = EntIndexToHScript(keys.entindex)
if npc:IsRealHero() then
local teamn = GetTeamName(npc:GetTeamNumber())
local playerID = npc:GetPlayerOwner():GetPlayerID()
if teamn == '#DOTA_GoodGuys' then --проверка на команду, отправляем команду, которую прячем, можно несклько, для этого надо больше проверок на команды
-- если что, в js это функция "OnPrepare"
local event_data = { key1 = "dire" }
CustomGameEventManager:Send_ServerToPlayer(PlayerResource:GetPlayer(playerID), "prepare", event_data )
else
local event_data = { key1 = "radiant" }
CustomGameEventManager:Send_ServerToPlayer(PlayerResource:GetPlayer(playerID), "prepare", event_data )
end
end
end
end
теперь gamemode.lua:
В фукции GameMode:InitGameMode() регаем слушателя:
Lua:
CustomGameEventManager:RegisterListener( "pick_hero_event", OnPickHero )
Lua:
function OnPickHero( eventSourceIndex, keys ) -- эту функцию запускает кнока выбора героя, в js функция PickHero(hero)
local pid = nil -- id игрока
for k,v in pairs(keys) do -- отправляется две строчки, одна с id игрока, другая уже кастомная с выбранным героем
if k == "pick" then -- если вторая строчка, то...
print(pid) -- принты для проверки, можно убрать
print("npc_dota_hero_"..v) -- принты для проверки, можно убрать
PlayerResource:ReplaceHeroWith(pid, "npc_dota_hero_"..v, 0, 0) -- выдаём героя
local event_data = { key1 = v }
CustomGameEventManager:Send_ServerToAllClients( "ban_hero", event_data ) -- отправляем ивент и прячем героя в js функции OnBanHero
else
pid = v -- если первая строчка то сохраняем id игрока
end
end
end
далее у меня свой файл, но вы можете писать в одном из предыдущих:
Lua:
timetopickleft = 60 -- время на выбор героев
function timetopick() -- функция отсчёта времени, ненужна вам если у вас неогранниченное... ну вы поняли, запустите где-нибудь в InitGameMode(), например
Timers:CreateTimer(function() -- создаём таймер, но извращённый
timetopickleft = timetopickleft - 1; -- считаем секундочки
print(timetopickleft) -- спамим в консоль
local event_data = { key1 = timetopickleft }
CustomGameEventManager:Send_ServerToAllClients( "send_time", event_data ) -- отправляем ивент в js, что время менялось на экране, функция OnTime
if timetopickleft == 0 then -- если время вышло, то
CustomGameEventManager:Send_ServerToAllClients( "time_over", nil ) -- отправляем ивент, чтобы спрятать пик для всех игроков, функция js OnTimeOver
return nil -- останавливаем таймер
else -- если время ещё есть, то
return 1.0 -- возвращаем секунду для таймера
end
end)
end
Вроде всё, как вы поняли я не писал это специально для гайда, я делаю кастомку и взял код, что написал оттуда, и сделал гайд из этого, немного поменяв код под это.
Так как я делаю кастомки в доте и играю в пупк у меня нет друзей и эту штуку и проверял только в соло, а кастомка моя ещё не готова, я был бы благодарен если бы вы проверили это с друзьями или ещё с кем-то и отписались, что работает или не работает.
Я всё ещё не очень проснулся и мог реально где-то ошибица поэтому пишите в комментах я исправлю всё.
уф, больше часа потратил на этот гайд, и это не считая сколько я этот код писал, хотя выглядит он не таким сложным(и гайд и код), если вам понравилось поставьте люкантропа пожалуйста
UPD1: Добавил пример
UPD2: исправил ошибку, которую ниже описали, спасибо кста
этот гайд очень устарел лично для меня, всё можно гораздо лучше сделать, но мне лень
Последнее редактирование: