Платформа: Сталкер Зов Припяти 1.6.02 Автор: FantomICW Введение Доброго времени суток и с Новым годом, друзья! Мне бы очень хотелось преподнести вам, дорогие коллеги, небольшой презент под новогоднюю елку. Итак, новый тутор по Gui. На самом деле, здесь не будет тех Gui-элементов, о которых вы могли читать в туторах Хована, strelok200 или мом прошлом. Сегодня тема посвящена интерактивному элементу карты - отметке квестового НПС. В логики НПС есть известный оверрайд (параметр) level_spot. Им можно задавать НПС свою отметку (элемент Gui):
Код
level_spot = название_метки
Такие отметки можно видеть у техников, медиков, торговцев и т. д. Например, у Сыча в логике стоит вот такая штука:
Код
level_spot = trader
Метка торговца. А мы сегодня сделаем, пожалуй, метку для лидеров группировок (ну, или отрядов). Поехали. Подготовка к действу
- Paint Net (редактируем тестуры) - Notepad++ (рекомендую для редактирования текстовых файлов игры)
Практика
Для начала сделаем саму иконку. Все подобные иконки хранятся в текстуре textures/ui/ui_actor_hint_wnd.dds. Давайте и мы в этот раз не отойдем от шаблона. Запускаем Paint Net, который идеально подходит для и открываем данную текстуру. Теперь правее найдем всю эту текстурную группу иконок и выделим любую из "большой подгруппы". Поясню: существует две подгруппы. Это "большая" (для карты) и "маленькая" (для мини-карты на HUD). Лучше начать с большой. Вообщем, выделяем любую "большую" иконку. Копируем ее, вставляем на новый слой и перемещаем на свободное место: Теперь, не снимая выделения, запускаем Коррекция-->Оттенок и насыщенность, и перекрасим иконку в красные тона для разнообразия: Конечно же нам нужно заменить центральную часть иконки на другое изображение, поэтому берем ластик и аккуратно стираем крест по центру: Следующий шаг - берем инструмент "Текст". Им мы поставим по центру кружочка букву "L". Почему именно ее? Потому что лидер = leader Шрифт, цвет и размер по усмотрению. Я взял "Arial" с размером 8 и цветом, приближенном к цвету кружка: Хорошо. Дальше нам нужно сделать уменьшенную копию для нашей иконки, чтоб было что поставить на мини-карту. Для этого копируем иконку и вставляем ее в документ с пустым фоном и размером 19x19 px. Просто размер всех "больших" иконок квестовых НПС именно 19x19. Если появится сообщение в роде "Не хватает места для вставленного изображения", игнорируйте, оставляйте как есть, полотно увеличивать не надо. Просто разместите иконку по центру полотна. Дальше выбираем Изображение-->Изменить размер, и заменяем ширину на 15, а высоту на 14. Копируем уменьшенное изображение, вставляем обратно в текстуру, располагаем где-то рядом с "большой" иконкой. "Маленькая" немного утратила насыщенность. По желанию это можно подправить все тем же инструментом Коррекция-->Оттенок и насыщенность. С самой текстурой все. Но Paint Net не закрываем. Сохраняем текстуру.
Ок, мы прошли творческий этап. Прежде всего берем инструмент "Выделение" (белая стрелочка). Выделяем условный квадратик 19х19 (смотрим размер внизу левее) и перемещаем его к "большой" иконке Внизу слева появятся координаты x и y. Открываем сразу файл configs/ui/texrures_desc/ui_actor_pda_icons.xml. Там зарегистрированы оригинальные иконки (там указываются координаты по текстуре, где они находятся + им задается уникальный ID; как и во всех файлах texrures_desc). Видим там такое:
Вот так регистрирутся иконки. Разберем элементы регистра. Файл, в котором находятся иконки. В данном случае - ui\ui_actor_hint_wnd.dds. Нам подходит! texture id="ID_иконки" - задается уникальный ID x="6" y="543" width="19" height="19" - координаты, ширина, высота...смотрите детальней в прошлом туторе Итак, у нас есть уже координаты для "большой". Запишем куда-то. Создаем выделением условный квадратик (технически - прямоугольник) 15х14 для "маленькой", снимаем координаты, записываем. Теперь создадим для них секции где-то среди регистра файла:
ui_inGame2_PDA_icon_Stalker_Leader - "большая" ui_inGame2_PDA_icon_Stalker_Leader_small- "маленькая" С регистром визуала метки закончили. Далее нужно регистрировать ее как Gui-элемент. Откроем configs/ui/map_spots.xml. Найдем там вот такое:
На самом деле, эта байда состоит из трех секций. Первая - ui_pda2_leader_location. В ней есть установка:
Код
hint="st_ui_pda_legend_leader"
Это означает, что при наведении на метки, которые указаны в этой секции, будет всплывать текст st_ui_pda_legend_leader. level_map spot указывается секция "большой" метка, которую мы видим далее. Соответственно, в mini_map_spot - секция "маленькой". Вот и сами эти секции:
Тут задается ширина и высота иконок-текстур, пара дополнительных параметров в роде растяжения, выравнивания и прочего. Не вижу смысла здесь долго мусолить Не забудьте - нужно скопировать новые секции и поместить их также в файл map_spots_16.xml. Осталось добавить в configs/text/rus/любой_файл.xml текстовую секцию:
Предпоследняя часть. Нужно добавить секцию ui_pda2_leader_location в scripts/stalker_generic.script. В нескольких местах. В функциях reset_show_spot и remove_level_spot, которые обрабатывают метки. Под этим:
Код
elseif map_spot == "medic" then map_location = "ui_pda2_medic_location" hint = "st_ui_pda_legend_medic"
Этим:
Код
elseif level.map_has_object_spot(npc_id, "ui_pda2_medic_location") ~= 0 then level.map_remove_object_spot(npc_id, "ui_pda2_medic_location")
И этим:
Код
elseif map_spot == "medic" then map_location = "ui_pda2_medic_location"
На самом деле, тут не нужно много думать, если нету на то желания. Шаблон есть? Творческая работа уже была? Вперед, можно и немного "потупить", копипастя секции из скриптов Правда. Говорю как модмейкер с определенным опытом, иногда нужно покайфовать во время работы, не напрягаясь о значении каждой долбанной коммент-черточки в lua-скрипте Но поскольку у меня есть определенные традиции передачи знаний, я сделаю пометки в коде. Замечу, что в каждом случае будем использовать выражение elseif ("если не так, а так..."). Вообщем, вот так выглядят функции:
Код
function reset_show_spot(npc, scheme, st, section) local spot_section if scheme == nil or scheme == "nil" then --Проверка на работоспособность схемы spot_section = utils.cfg_get_string(st.ini, st.section_logic, "show_spot", npc, false, "") else spot_section = utils.cfg_get_string(st.ini, section, "show_spot", npc, false, "") end local map_spot = utils.cfg_get_string(st.ini, st.section_logic, "level_spot", npc, false, "") --Проверка наличия оверрайда в логике if map_spot == nil then --Если нету, то map_spot = utils.cfg_get_string(st.ini, section, "level_spot", npc, false, "") --то оставляем как есть end if map_spot ~= nil then --Если есть, то map_spot = xr_logic.parse_condlist(npc, section, "level_spot", map_spot) --Берем значение из логики НПС map_spot = xr_logic.pick_section_from_condlist(db.actor, npc, map_spot) --Или определяем, что это ГГ (выставляем метку ГГ) end --' printf("STALKER SPOT SECTION [%s]", utils.to_str(spot_section))
if spot_section == nil then --Если наличие метки стоит на "false", то spot_section = "true" --возвращаем наличие метки на "true" end
local spot = "false" -- if character_community(npc) ~= "zombied" then local spot_condlist = xr_logic.parse_condlist(npc, section, "show_spot", spot_section) spot = xr_logic.pick_section_from_condlist(db.actor, npc, spot_condlist) -- end
local sim = alife() if not sim then return end
local obj = sim:object(npc:id()) if obj and obj.online then local npc_id = npc:id() if spot == "false" then -- прячем obj:visible_for_map(false) else -- ставим obj:visible_for_map(true) end if map_spot ~= nil then --Если есть значение, то local map_location = "" local hint = "" if map_spot == "trader" then --Если значение "trader", то map_location = "ui_pda2_trader_location" --Работает секция "ui_pda2_trader_location" hint = "st_ui_pda_legend_trader" --И всплывает при наведении курсора текст "st_ui_pda_legend_trader" elseif map_spot == "mechanic" then --Дальше тому подобное map_location = "ui_pda2_mechanic_location" hint = "st_ui_pda_legend_mechanic" elseif map_spot == "guider" then map_location = "ui_pda2_scout_location" hint = "st_ui_pda_legend_scout" --[[ local smarts_tbl = sim_board.get_sim_board().smarts local npc_smrt_id = obj.m_smart_terrain_id if npc_smrt_id ~= 65535 and npc_smrt_id ~= nil then local npc_smart = smarts_tbl[npc_smrt_id].smrt if npc_smart then local smart_name = smart_names.get_smart_terrain_name(npc_smart) hint = game.translate_string(hint).."\\n"..game.translate_string("st_location").." "..smart_name end end ]] elseif map_spot == "quest_npc" then map_location = "ui_pda2_quest_npc_location" hint = "st_ui_pda_legend_vip" elseif map_spot == "medic" then map_location = "ui_pda2_medic_location" hint = "st_ui_pda_legend_medic" elseif map_spot == "leader" then map_location = "ui_pda2_leader_location" hint = "st_ui_pda_legend_leader" end if level.map_has_object_spot(npc_id, map_location) ~= 0 then level.map_remove_object_spot(npc_id, map_location) end if db.actor and npc and npc:general_goodwill(db.actor) > -1000 then level.map_add_object_spot(npc_id, map_location, hint) end else if level.map_has_object_spot(npc_id, "ui_pda2_trader_location") ~= 0 then --Похожая система, только для убора метки level.map_remove_object_spot(npc_id, "ui_pda2_trader_location") elseif level.map_has_object_spot(npc_id, "ui_pda2_mechanic_location") ~= 0 then level.map_remove_object_spot(npc_id, "ui_pda2_mechanic_location") elseif level.map_has_object_spot(npc_id, "ui_pda2_scout_location") ~= 0 then level.map_remove_object_spot(npc_id, "ui_pda2_scout_location") elseif level.map_has_object_spot(npc_id, "ui_pda2_quest_npc_location") ~= 0 then level.map_remove_object_spot(npc_id, "ui_pda2_quest_npc_location") elseif level.map_has_object_spot(npc_id, "ui_pda2_medic_location") ~= 0 then level.map_remove_object_spot(npc_id, "ui_pda2_medic_location") elseif level.map_has_object_spot(npc_id, "ui_pda2_leader_location") ~= 0 then level.map_remove_object_spot(npc_id, "ui_pda2_leader_location") end end end end
function remove_level_spot(npc, st) local map_spot = utils.cfg_get_string(st.ini, st.section_logic, "level_spot", npc, false, "") --Проверка наличия оверрайда в логике if map_spot == nil then --Если нету, то map_spot = utils.cfg_get_string(st.ini, st.active_section, "level_spot", npc, false, "") --то оставляем как есть end if map_spot ~= nil then --Если есть, то map_spot = xr_logic.parse_condlist(npc, st.active_section, "level_spot", map_spot) --Берем значение из логики НПС map_spot = xr_logic.pick_section_from_condlist(db.actor, npc, map_spot) --Или определяем, что это ГГ (выставляем метку ГГ) end local sim = alife() if not sim then return end
local obj = sim:object(npc:id()) if obj then --Если объект существует local npc_id = npc:id() --Локальная переменная "obj" if map_spot ~= "" and map_spot ~= nil then --Начинаем перечислять "Если значение...", если в значении вообще что-то есть local map_location = "" --Локальная переменная "map_location" = "выставляемое значение" if map_spot == "trader" then --Если значение оверрайда - "trader", то map_location = "ui_pda2_trader_location" --то убирается секция "ui_pda2_trader_location" elseif map_spot == "mechanic" then --Если "mechanik", то map_location = "ui_pda2_mechanic_location" --то секция "ui_pda2_mechanic_location" elseif map_spot == "guider" then --И так далее... map_location = "ui_pda2_scout_location" elseif map_spot == "quest_npc" then map_location = "ui_pda2_quest_npc_location" elseif map_spot == "medic" then map_location = "ui_pda2_medic_location" elseif map_spot == "leader" then map_location = "ui_pda2_leader_location" end if level.map_has_object_spot(npc_id, map_location) ~= 0 then level.map_remove_object_spot(npc_id, map_location) --Убираем метку end end end end
Вот и все. Последний шаг. Откроем логику любого нужного НПС, и пропишем в секции [logic] такое:
Код
show_spot = leader ;Значение "leader" мы зарегистрировали в скрипте
Вот и все! Спасибо за внимание!
Сообщение отредактировал FantomICW - Среда, 01.01.2014, 19:04
Фрейшиц, на ТЧ другая схема. Во-первых, я не встречал там оверрайда level_spot. И в скрипте stalker_generic.script ничего про него нету. Можно конечно попробовать адаптировать часть скрипта от ЗП. Однако можно попробовать поставить метку через движковую функцию set_map_location(string). Ее мужно увидеть в расстановке меток на целевой объект в task_manager.script. Там оно выглядит как:
FantomICW, хех, я делал так же, все получилось. Но вот беда: на миникарте сквозь новую отметку пробивается значок командира (звезда) НПС. А ведь если брать метки от разработчиков - у них ничего не просвечивает. Как это исправить?
FantomICW, то есть? Все измерено точно и координаты записаны по аналогии от разрабов. Метка на глобалке стоит идеально, и на мини карте тож, но звезда просвечивает. Думал понизить прозрачность метки - но как-то не вышло.
новую метку для НПС создал, всё прекрасно на глобальной и мини-карте отображается, только на мини-карте сквозь эту новую метку звёздочка лидера сквада прорисовывается, хотя в stalker_generic.script секции, отвечающие за удаление старой метки, вроде нормально прописаны:
Код
elseif level.map_has_object_spot(npc_id, "ui_pda2_barmen_location") ~= 0 then level.map_remove_object_spot(npc_id, "ui_pda2_barmen_location") end elseif map_spot == "barmen" then map_location = "ui_pda2_barmen_location"
Код
elseif map_spot == "barmen" then map_location = "ui_pda2_barmen_location"
end if level.map_has_object_spot(npc_id, map_location) ~= 0 then level.map_remove_object_spot(npc_id, map_location) end
mmihaill, akmc47u, есть два варианта: либо спавнить нпс через алл спавн, либо добавлять в сквад к нужному нпс еще одного непися и делать его лидером, тогда у нужного нпс будет метка.