qvvxvvq 111 Опубликовано 30 Декабря 2014 Поделиться Опубликовано 30 Декабря 2014 Перенос оружия.Сложность. СредняяВот мой способ как перенести оружие с одного мода на другой. Это работает только (ТЧ на ТЧ), (ЗП НА ЗП), и (ЧН на ЧН).Опытные знают это, так что расскажу новичка, итак поехали. 1.И так для начала возьмем наш файл, к примеру w_ak74.ltx, копируем его из другого мода в наш с заменой, открываем его и ищем там snd_*****(это звуки оружия, и где они находятся), пример weapons\ak47\ak47_draw, и т.д. 2.Идем по этому тому адресу и копируем все файлы в нашу папку с игрой, именно по такому адресу.3. Далее идем в папку meshes\weapons\ak74\wpn_ak74_hud, открываем любым текстовым радактором (желательно Notepad ++), нажимаем Ctrl+F, и вводим "Wpn", там будет примерно такое "wpn\wpn_ak74", (по разному), значит идем по этому адресу textures\wpn\wpn_ak74, копируем этот файл в нашу папку по тому же адресу, (так же как и звуки), потом еще раз нажимаем "Wpn", и копируем, повторяем эту процедуру со всеми остальными файлами.Вроде Все, заходим в игру и радуемся. Удачи. 1 1 Ссылка на комментарий
NL-Vincenz 12 Опубликовано 22 Февраля 2015 Поделиться Опубликовано 22 Февраля 2015 (изменено) Решил создать гайд по спавну через программу ACDC ТЧ. Для тех, кто вообще не знает даже что такое ACDC и с чем его едят. Думаю кому-нибудь пригодиться. Несомненно спавнить лучше через SDK, но есть такие люди которые не умеют пользоваться сие инструментом. 1. Скачиваем программу Active Perl на сайте: www.activestate.com/activeperl (По непонятным мне причинам с AMK форума нельзя перейти на данный сайт, так-что копируйте и вставляйте в строку браузера.) Обращаем внимание на свою систему. Если у вас x64 качаем для x64, если x86 то x86. Думаю понятно. Устанавливаем. 2. Далее в корне игры создаем папку gamedata, в неё кидаем файл game.graph из распакованого сталкера. Ссылка на распаковщик для сталкера: http://yadi.sk/d/iMeW6v0reQPW4 Далее в папке gamedata создаем папку spawns в неё кидаем файл all.spawn из того-же распакованого сталкера. 3. Далее качаем программу ACDC по ссылке: http://yadi.sk/d/aEFtlI_veQE6m распаковываем архив видим папку acdc, эту папку кидаем в свою папку spawns. 4. Заходим в папку ACDC видим два батника: acdc_compile - Это компиляция. acdc_decompile - Это декомпиляция. Нажимаем декомпиляцию, пойдет процесс. Когда процесс будет окончен, нажимаем любую клавишу окно исчезнет. Делее мы видим папку unpack. 5. Давайте заспавним сталкера! Открываем alife_l01_escape. "escape" это название локации. Что мы видим? Всякие не понятные секции, символы.. Страшно? Все просто! Листаем в самый конец. Последняя секция под номером [869], после неё создаем свою секцию, так-же при помощи комментариев поясню что к чему: [870] ; 870 номер секции, после неё 871, 872 и так-далее. ; cse_abstract properties section_name = stalker name = esc_vagon ; это имя пишем свое. position = -199.870178222656,-19.8877372741699,-137.10905456543 ; Координаты. direction = 0,0.00316426996141672,0.062321275472641 version = 118 script_version = 6 ; cse_alife_trader_abstract properties money = 5000 character_profile = esc_vagon ; это ваше имя сталкера из characters_desc_***** ; cse_alife_object properties game_vertex_id = 57 ; гейм вертекс. distance = 9.80000019073486 level_vertex_id = 52330 ; левел вертекс. object_flags = 0xffffffbf custom_data = <<END [logic] ; ЛОГИКА!!! active = walker@stay_at_position, danger = danger_ignore [danger_ignore] ignore_distance = 5 [walker@stay_at_position] path_walk = esc_lager_petruha_walk ; точка где он будет стоять. ps. имя вводите свое но что бы вконце было walk. А в начале имя локации esc - esc_lager_petruha_walk. path_look = esc_lager_petruha_look ; точка куда он будет смотреть. ps. имя вводите свое но что бы вконце было look. А в начале имя локации esc - esc_lager_petruha_look. END story_id = 5481 ; ВАЖНО! SID. Прописываем его в файле [b]game_story_ids[/b] который лежит в папке [i]config[/i]. ; cse_visual properties visual_name = actors\novice\green_stalker_2 ; cse_alife_creature_abstract properties g_team = 0 g_squad = 1 g_group = 5 health = 1 dynamic_out_restrictions = dynamic_in_restrictions = upd:health = 1 upd:timestamp = 0x617a6b75 upd:creature_flags = 0x6b upd:position = -199.870178222656,-19.8877372741699,-137.10905456543 ; теже самые координаты что и вверху upd:o_model = 0 upd:o_torso = 0.00316426996141672,0.062321275472641,0 upd:g_team = 0 upd:g_squad = 1 upd:g_group = 5 ; cse_alife_monster_abstract properties upd:next_game_vertex_id = 65535 upd:prev_game_vertex_id = 65535 upd:distance_from_point = 0 upd:distance_to_point = 0 equipment_preferences = 2,2,0,1,1 main_weapon_preferences = 0,2,0,2 ; cse_ph_skeleton properties ; cse_alife_human_stalker properties upd:start_dialog = ; se_stalker properties ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6. Далее.. Идем в игру снимаем координаты, где он будет стоять и куда он будет смотреть. 7. Прописываем пути в файле way_l01_escape, что находиться в папке unpack. Идем в самый конец. И после: [escape_factory_look_common] points = p0 p0:name = wp00|n=1 p0:flags = 0x1 p0:position = 114.742797851563,-7.17558288574219,-33.0148315429688 p0:game_vertex_id = 125 p0:level_vertex_id = 417148 Ставим: [esc_lager_petruha_walk] ; точка где он стоит, имя из ЛОГИКИ! points = p0 p0:name = name00 p0:flags = 0x400 p0:position = -60.1297874450684,-5.67141437530518,6.7514533996582 ; координаты где он стоит p0:game_vertex_id = 113 ; гейм вертекс p0:level_vertex_id = 347680 ; левел вертекс [esc_lager_petruha_look] ; точка куда он смотрит, имя из ЛОГИКИ! points = p0 p0:name = name00 p0:flags = 0x400 p0:position = 106.122169494629,-3.09708905220032,-7.83051156997681 ; координаты куда он смотрит p0:game_vertex_id = 117 ; гейм вертекс p0:level_vertex_id = 407096 ; левер вертекс Сохраняем! 8. Далее в character_desc_escape или еще где-то у вас должен быть прописан НПС. Если не прописали, прописываем. <specific_character id="esc_vagon" team_default = "1"> ; имя в name = esc_vagon что вверху. <name>esc_vagon_name</name> <icon>ui_npc_u_stalker_bandit_master</icon> <bio>esc_vagon_bio</bio> <class>esc_petruha</class> <community>stalker</community> <terrain_sect>stalker_terrain</terrain_sect> <rank>534</rank> <reputation>234</reputation> <snd_config>characters_voice\human_03\stalker\</snd_config> <crouch_type>0</crouch_type> <visual>actors\bandit\stalker_bandit_master</visual> <supplies> [spawn] \n wpn_pm \n ammo_9x18_fmj = 1 \n #include "gameplay\character_items.xml" \n #include "gameplay\character_food.xml" </supplies> #include "gameplay\character_criticals_5.xml" #include "gameplay\character_dialogs.xml" <start_dialog>hello_dialog</start_dialog> </specific_character> 9. Идем в npc_profile, что в папке gameplay, прописываем в конце нашего НПС: <character id="esc_vagon"> <class>esc_vagon</class> <specific_character>esc_vagon</specific_character> </character> Надеюсь, вы справитесь. 10. Идем в папку acdc. Нажимаем acdc_compile, пойдет процесс компиляции. ВСЕ! Если вы меня правильно поняли и все сделали как надо, то по указанным координатам должен появиться НПС, который будет смотреть в вашу заданную точку. ВНИМАНИЕ!!! Все мои комментарии после знака ; и знак сам - удаляем! Изменено 22 Февраля 2015 пользователем NL-Vincenz 2 1 Ссылка на комментарий
Это популярное сообщение. Samber13 227 Опубликовано 1 Марта 2015 Это популярное сообщение. Поделиться Опубликовано 1 Марта 2015 (изменено) Продолжу тему о шрифтах http://www.amk-team.ru/forum/index.php?showtopic=6458&p=902166 @FantomICW рассказал о списке доступных шрифтов и их регистрации. И упомянул о fonts.ltx Рассмотрим его получше. В этом файле список шрифтов и их параметров. В качестве примера рассмотрим секцию: [ui_font_arial_14] shader = hud\font texture = ui\ui_font_arial_14_1024 texture800 = ui\ui_font_arial_14_800 texture1600 = ui\ui_font_arial_14_1600 Параметр "shader", как не сложно догадаться назначает шейдер на шрифт. Подробней чуть позже. Параметр "texture" указывает на текстуру с этим самым шрифтом. Цифры в параметрах вида "texture800" означают разрешение монитора, при котором будет использована та или иная текстура. Текстуры с префиксами "_west","_cent" означают кодировки.По умолчанию во всех шрифтах используется шейдер "hud\font". Если мы попробуем поменять его, скажем на "hud\default", то получится нечто подобное:Связано это с особенностью текстур. Немного отвлечёмся. Попробовав открыть такую текстуру плагином nvidia для фотошопа, я получил нечто абсолютно бесформенное. Кроме квадрата Малевича, был альфа-канал, на котором не отчётливо можно было разобрать контуры некоторых символов. Сторонние вьюверы и редакторы показывали подобный неоднозначный результат. Но затратив немного времени и сил я разобрался с этим и перевёл этот 8-битный одноканальный файл в привычный DXT5.И так возвращаемся к шейдерам. Если на DXT5 текстуру шрифта назначить шейдер "hud\default", то она будет отображаться правильно. Цвет шрифта будет взят напрямую из RGB каналов текстуры, а не из назначенных параметров. Минусы такого шейдера очевидны, но если скажем, вам нужны чёрные контуры на символах или по вашей задумке буквы должны быть радужными, то это может, пригодится. Если же на DXT5 текстуру шрифта назначить шейдер "hud\font", то символы считываются с альфа-канала без ошибок, так же как и с оригинальной текстуры. RGB-каналы при этом не используются. Именно по этой причине разработчики сжали текстуры шрифтов.У каждой текстуры шрифта есть свой ".ini" файл, в котором, одна постоянная секция "symbol_coords". Не сложно догадаться, что здесь вписаны координаты каждого символа. И так же встречается секция "width_correction" - поправка по ширине.Надеюсь, что статья будет полезной. Добра и удачи в разработке Изменено 1 Марта 2015 пользователем Samber13 2 6 Калькулятор номера билда. Ссылка на комментарий
Это популярное сообщение. Сталкер Лом 356 Опубликовано 9 Марта 2015 Это популярное сообщение. Поделиться Опубликовано 9 Марта 2015 Создание LOD статических объектов. Первый видеоурок. На днях решил сделать ЛОД этой самой цистерны, да не сразу вспомнил, что для него надо делать. Сравнил с оригинальными ЛОДами и решил и себе, и другим памятку сделать. Советы\пожелания лучше в личку, чтобы тут тему не засорять. 2 3 2 Работы на Artstation - https://www.artstation.com/artist/stalker_lom Ссылка на комментарий
Это популярное сообщение. Сталкер Лом 356 Опубликовано 8 Апреля 2015 Это популярное сообщение. Поделиться Опубликовано 8 Апреля 2015 (изменено) По просьбам трудящихся... Создание играющего магнитофона\радио для ЗП. 0. Первый пункт - если вы будете складывать секции звуков в отдельный файл. Если добавляете в уже имеющийся (например, script_sound_zaton) - переходите к пункту 2. 1. Сначала мы зарегистрируем наши звуки. Для этого пройдём в configs\misc\script_sound.ltx и сделаем регистрацию нашего нового файла с музыкой (можно сделать в уже существующем). Для этого после строки: #include "script_sound_underpass.ltx" Вставим нашу регистрацию нового файла: #include "script_sound_bar.ltx" ;Допустим, я работаю с локацией Бар - поэтому, _bar, но названия могут быть и произвольными А также добавим наш файл в лист: [list]: list_music_and_stories, list_script_sound_zaton, list_script_sound_jupiter, list_script_sound_pripyat, list_script_sound_underpass, list_script_sound_bar ;Вот он: последний в списке 2. Зарегистрировали, перейдём к файлу, для этого создадим его под именем list_script_sound_bar (новый текстовый документ -> сменить имя и расширение на .ltx). Наполняем: [list_script_sound_bar] ;Имя с секциями звуков в этом файле bar_music_main [bar_music_main] ;Конкретно секция нужного нам звука type = 3d npc_prefix = false path = music\radio\bar_main_ ;Путь до наших звуков shuffle = rnd idle = 2,4,100 Подробно о настройке можно (и нужно) почитать вот эту хорошую статейку: http://stalkerin.gameru.net/wiki/index.php?title=CoP._Разбор_звуковых_конфигов_в_script_sound_*** 3. Соответственно, в папку sounds\music\radio положим файлы в формате .ogg с именем bar_main_<Номер_звука>. Со звуками закончили, теперь надо создать логику для объекта, который будет проигрывать наши звуки. 4. Идём в папку configs\scripts\bar (как вы помните, имя папки bar у каждого будет своя) и создаём там файл bar_a1_radio.ltx. Наполним его: [logic] active = ph_sound@idle [ph_sound@idle] sound = bar_music_main Также подробнее про схему ph_sound можно почитать тут: http://stalkerin.gameru.net/wiki/index.php?title=Настройка_логики._Часть_4 Дело за малым, нужно создать само радио. 5. Тут уж, кто как: кто в all.spawn добавлять секцию будет, кто в СДК. 5.1. All.spawn [49] ; cse_abstract properties section_name = physic_destroyable_object name = bar_radio position = -141.697998046875,-22.3415851593018,-353.995544433594 :Позиция, вертексы, направление - это вы знаете direction = -1.70000002981396e-005,3.14159202575684,0 ; cse_alife_object properties game_vertex_id = 1407 distance = 0 level_vertex_id = 747615 object_flags = 0xffffff3a custom_data = <<END [logic] cfg = configs\scripts\bar\bar_a1_radio.ltx ;Путь до логики END ; cse_visual properties visual_name = dynamics\el_tehnika\radio ;Путь до визуала ; cse_ph_skeleton properties ; cse_alife_object_physic properties physic_type = 0x3 mass = 3 fixed_bones = link ;кость, которая будет зафиксирована, чтобы не утащили 5.2. СДК 6. Последний штрих - нужно вернуть в ЗП схему проигрывания звуков объектами - она в оригинале отключена за ненадобностью. Идём в scripts\modules.script и после строки №60 (ph_oscillate) пишем load_scheme("ph_sound", "ph_sound", stype_item) Скрипт схемы нужно создать и заполнить его таким содержимым: --[[ Сталкер Лом Чуть переделал схему: * Настроил на проигрывание звуков из ltx файла - так привычнее. * Соответственно, теперь не надо указывать в секции логики тип звука - берётся из ltx файла 19.02.14 ]] class "snd_source" function snd_source:__init (obj, storage) self.object = obj self.st = storage self.destructed = false end function snd_source:reset_scheme(loading) self.last_update = 0 self.st.signals = {} self.played_sound = nil self.first_sound = true self.st.pause_time = 0 self.st.sound_set = true if loading == false then self.destructed = false else self.destructed = xr_logic.pstor_retrieve (self.object, "destr") end end function snd_source:save () xr_logic.pstor_store (self.object, "destr", self.destructed) end function snd_source:hit_callback(obj, amount, local_direction, who, bone_index) if self.st.no_hit == true then return end printf ("SOUND SOURCE HAVE A HIT") local who_name if who then who_name = who:name() else who_name = "nil" end printf("_bp: snd_source:hit_callback obj='%s', amount=%d, who='%s'", obj:name(), amount, who_name) if self.played_sound ~= nil then self.played_sound:stop () self.played_sound = nil end self.destructed = true end function snd_source:update(delta) if self.destructed == true then return end if xr_logic.try_switch_to_another_section (self.object, self.st, db.actor) then return end if self.st.pause_time - device ():time_global () > 0 then return end self.st.pause_time = 0 if self.st.sound_set == true then self.st.sound_set = false --[[ if self.st.random then self.played_sound = xr_sound.get_sound_object(self.st.theme, "random") elseif self.st.looped then self.played_sound = xr_sound.get_sound_object(self.st.theme, "looped") else self.played_sound = xr_sound.get_sound_object(self.st.theme, "seq") end ]] self.played_sound = xr_sound.set_sound_play(self.object:id(), self.st.theme) if self.played_sound ~= nil then self.played_sound:play_at_pos (self.object, self.object:position ()) else self.st.signals["theme_end"] = true end self.first_sound = false end if self.last_update == 0 then self.last_update = device ():time_global () else if device ():time_global () - self.last_update > 50 then self.last_update = 0 else return end end if self.played_sound ~= nil then if self.played_sound:playing () == false then if self.first_sound == false then self.st.signals["sound_end"] = true end self.st.sound_set = true if self.st.pause_min ~= 0 or self.st.pause_max ~= 0 then local time = math.random (self.st.pause_min, self.st.pause_max) self.st.pause_time = device ():time_global () + time end self.first_sound = false else self.played_sound:set_position (self.object:position ()) end end end function snd_source:deactivate () if self.played_sound ~= nil then self.played_sound:stop () self.played_sound = nil end end function add_to_binder (npc, ini, scheme, section, storage) local new_action = snd_source (npc, storage) -- Зарегистрировать все actions, в которых должен быть вызван метод reset_scheme при изменении настроек схемы: xr_logic.subscribe_action_for_events(npc, storage, new_action) end function set_scheme(npc, ini, scheme, section, gulag_name) local st = xr_logic.assign_storage_and_bind(npc, ini, scheme, section) st.logic = xr_logic.cfg_get_switch_conditions(ini, section, npc) st.theme = utils.cfg_get_string(ini, section, "sound", npc, false, "") -- st.looped = utils.cfg_get_bool (ini, section, "looped", npc, false, false) -- st.random = utils.cfg_get_bool (ini, section, "random", npc, false, true) st.pause_min = utils.cfg_get_number (ini, section, "min_idle", npc, false, 0) st.pause_max = utils.cfg_get_number (ini, section, "max_idle", npc, false, 0) st.no_hit = utils.cfg_get_bool (ini, section, "no_hit", npc, false, true) if st.pause_max < st.pause_min then abort ("PH_SOUND - invalid time range !!!") end end Это чуть правленая мною схема, чтобы можно было использовать звуки из ltx файлов, как это принято в ЗП. Вот, собственно, и всё. Да, конечно, есть урок из поста 42, но каждый раз править скрипт, добавляя\убирая звуки - не гуд, а вот делать всё через ltx файлы гораздо удобнее. Стандартизация, так сказать. В общем, кому что, а мне так сподручнее, может быть и вам будет лучше. Изменено 8 Апреля 2015 пользователем Сталкер Лом 2 2 2 Работы на Artstation - https://www.artstation.com/artist/stalker_lom Ссылка на комментарий
sneik 341 Опубликовано 8 Апреля 2015 Поделиться Опубликовано 8 Апреля 2015 (изменено) А если в файле логики записать вот так. [logic] active = ph_idle@wait [ph_idle@wait] hit_on_bone = 0| nil on_info = {=actor_in_zone(название_рестрактора, покрывающего,зону_звучания_радио)} ph_idle@play %=play_sound(bar_music_main)% [ph_idle@play] hit_on_bone = 0| nil %=stop_sound% on_info = {!actor_in_zone(название_рестрактора, покрывающего,зону_звучания_радио)} ph_idle@wait %=stop_sound% on_info2 = {!is_playing_sound} ph_idle@wait То ни каких правок скрипта делать не надо. Радио звучит только тогда когда ГГ в зоне звучания, вышел - радио заглохло. Изменено 8 Апреля 2015 пользователем sneik 4 Ссылка на комментарий
Это популярное сообщение. Сталкер Лом 356 Опубликовано 29 Апреля 2015 Это популярное сообщение. Поделиться Опубликовано 29 Апреля 2015 Создание LOD динамических объектов. Пожелания, критика приветствуется 4 3 Работы на Artstation - https://www.artstation.com/artist/stalker_lom Ссылка на комментарий
Это популярное сообщение. Clayman 104 Опубликовано 18 Мая 2015 Это популярное сообщение. Поделиться Опубликовано 18 Мая 2015 (изменено) Создание модуля автоматического получения game_vertex и level_vertex любой локации мода, для спавна динамических аномалий. Категория: для новичков. Платформа: ЗП (не вижу причин, чтобы это не работало на ЧН и ТЧ). Для кого-то это будет "изобретать вилосипед", кому-то, надеюсь, пригодится. Прикручивая модуль динамических аномалий для своего пака локаций (ЗП) я пересмотрел несколько готовых решений (АМК ЗП в частности и другие). Практически во всех модах, где реализуется спавн аномалий по рандомным гейм-вертексам локации присутствуют подобные конструкции:local level_vertexes={escape = 597179,garbage = 1045075}local game_vertexes={escape = {0,240},garbage = {241,500}}Т.е таблицы с прописанными диапазонами гейм-вертексов и максимальными значениями левел-вертексов всех локаций. Где эти значения брать? Обычно запускают специальный скрипт в игре, с помощью которого получаем эти данные. Я в частности, использовал подобные скрипты, описанные на сталкервики (на их базе и создан этот модуль).Но, когда мы подключаем новую локацию или меняем количество граф-поинтов на локе, или корректируем АИ-сетку, эти значения будут постоянно меняться. И нам каждый раз придется запускать игру, запускать скрипт, снимать параметры и вбивать их в таблицы. При активной работе над локациями, это очень неудобно. Поэтому, в мою голову пришла мысль, поражающая своей новизной и гениальностью - если есть скрипт, который это делает, почему бы его не встроить в сам модуль динамических аномалий и автоматически получать нужные нам значения? Сказано - сделано. Подобный модуль можно использовать и для случайного спавна других предметов и возможно для других целей. Итак, в нужном вам модуле (динамические аномалии) пишем две функции: -- Функция получает таблицы левел-вертексов всех уровней и возвращает нужную (по уровню)function GetLevelsVertexes(level) local lvtab ={} local i = 0 while game_graph():valid_vertex_id(i) do local lv = game_graph():vertex(i):level_vertex_id() local ln = alife():level_name(game_graph():vertex(i):level_id()) if not lvtab[ln] then lvtab[ln] ={} end table.insert(lvtab[ln], lv) i = i+1 end return lvtab[level]end--------------Функция получает таблицы всех гейм-вертексов и возвращает нужную (по уровню)function GetGameVertexes(level) local gvtab ={} local i = 0 while game_graph():valid_vertex_id(i) do local ln = alife():level_name(game_graph():vertex(i):level_id()) if not gvtab[ln] then gvtab[ln] ={} end table.insert(gvtab[ln], i) i = i+1 end return gvtab[level]end Функции получают имя уровня как входной параметр, возвращают нужные таблицы левел и гейм вертексов для этого уровня. Далее используем эти данные в нужном вам месте. Например, получение рандомного левел вертекса для текущего уровня: local level_name = level.name() local lvtab = GetLevelsVertexes(level_name) local lvx = math.max(unpack(lvtab)) local lv = math_random(1,lvx) --//рандомный левел-вертекс Получение диапазона гейм-вертексов для текущего уровня: local lname = level.name() local gvtab = GetGameVertexes(lname)local gv_min = math.min(unpack(gvtab))local gv_max = math.max(unpack(gvtab)) Вот и все. Теперь при любых изменениях с гейм-графом и аи-сеткой вы будете автоматически вычислять нужные значения. Очевидные, но очень удобные вещи. Скрипт не претендует на шедевр программирования, улучшения от профессионалов приветствуются Изменено 18 Мая 2015 пользователем Clayman 3 2 Ссылка на комментарий
Nazgool 250 Опубликовано 18 Мая 2015 Поделиться Опубликовано 18 Мая 2015 (изменено) @Clayman, Функции я бы написал малость по другому. В таком плане : local lvtab = setmetatable({}, {__index = function (t,k) t[k] = {} return t[k] end})function GetLevelsVertexes(level) local i = 0 local graph = game_graph() local sim = alife() while graph:valid_vertex_id(i) do local v = graph:vertex(i) local data = lvtab[sim:level_name(v:level_id())] data[#data+1] = v:level_vertex_id() i = i+1 end return lvtab[level]end Это раза в 3 быстрее (простое кеширование глобальных функций и методов). Да и setmetatable позволяет, элегантнее что-ли, автоматизировать заполнение lvtab. @Clayman, сорри. Я не правильно понял задачу. Прочитал ещё раз внимательнее. Ведь нужно при каждом вызове функции обновлять данные для определенной локации? Тогда никаких внешних таблиц не нужно. Все проще, и ещё малость быстрее. function GetLevelsVertexes(level) local t = {} local i = 0 local graph = game_graph() local sim = alife() while graph:valid_vertex_id(i) do local v = graph:vertex(i) local ln = sim:level_name(v:level_id()) if ln == level then t[#t+1] = v:level_vertex_id() end i = i+1 end return tend Изменено 20 Мая 2015 пользователем BFG 2 2 Ссылка на комментарий
Это популярное сообщение. HellRatz 2 892 Опубликовано 25 Мая 2015 Это популярное сообщение. Поделиться Опубликовано 25 Мая 2015 (изменено) Последние оставшиеся уроки от Wo1fRam, которые он не удалил. Бэкап с закрытой ныне темы. Перенос моделей артефактов из ЧН/ЗП в ТЧ Перенос моделей артефактов из ЧН/ЗП в ТЧ и обратно. Автор: Wo1fRam. Вступление. Наверное, многие задавались вопросом «А как же перенести модель артефакта из ЧН/ЗП в ТЧ?». Или наоборот, может некоторым новые модели артефактов в ЧН/ЗП не нравятся, и они хотят их заменить на более привычные из ТЧ. Некоторые разобрались и сделали (и не рассказывают, жабы), некоторые пытаются что-то мудрить в 3d редакторах, а некоторые вообще не знают что делать и при этом говорят другим, что такое невозможно. Ещё как возможно! Сначала я тупо перетащил модель из ЗП в ТЧ, но получил вылет. Потом я, не на что особо не надеясь, попробовал перенести через СДК. И, к моему удивлению, всё заработало! Итак, нам понадобятся: 1. X-Ray SDK 0.4 (или 0.5/0.7, если переносите из ТЧ в ЧН/ЗП) 2. Настроенный конвертер Бардака. 3. Распакованные файлы ТЧ и ЧН/ЗП. Начнём, пожалуй. Давайте сперва определимся, модель какого артефакта мы хотим перенести. Я решил перенести «Каменный цветок» из ЗП в ТЧ. При небольшом знании английского языка, модель найти достаточно легко. Она находится в директорииgamedata\meshes\dynamics\artefacts и называется af_cristall_flower.ogf. Копируем её в папку с конвертером Бардака (у меня это папка level_editor). Нам нужно преобразовать модель в формат .object. Создаём батник с таким кодом: converter -ogf -object af_cristall_flower.ogf pause Запускаем батник, ждём долю секунды и видим в папке свежесозданный файл af_cristall_flower.object. Запускаем ActorEditor и подгружаем в него этот файл. Если ругается на недостающие текстуры – возьмите их из ЧН/ЗП и добавьте в свою геймдату. Теперь нажимаем File-->Export-->Export OGF... и сохраняем модель. Вообще, чтобы в дальнейшем не париться с переносом конфига, а, следовательно, чтобы было легче адаптировать модель артефакта для любого мода на ТЧ, надо задать модели то имя, которое имеет стандартная модель. Только в ТЧ модели артефактов как-то странно названы. Но можно поглядеть в файле gamedata\config\misc\artefacts.ltx. Там нас тоже спасёт небольшое знание «инглиша». В случае с «Каменным цветком», имя секции в конфиге будет, как ни странно, [af_cristall_flower], а путь к модели: visual = physics\anomaly\artefact_blackdrip_2.ogf Следовательно, сохраняем модель в директорию <gamedata вашего мода>\meshes\physics\anomaly\ под именемartefact_blackdrip_2.ogf. Если вы задали своё имя, то пропишите его в конфиге вместо оригинального. Естественно, тогда придётся копировать к себе ещё и конфиг. Вот и всё! Теперь дело за малым: протестировать. Примечание: Модели артефактов из ТЧ в ЧН/ЗП переносятся точно так же, только с использованием соответствующего СДК. © Wo1fRam При размещении на различных сайтах и форумах не забывайте указывать автора. Создание тайников в Зове Припяти КАК СОЗДАТЬ СВОЙ ТАЙНИК в Зове Припяти Автор: Wo1fRam От автора:Подобные уроки не раз встречались на различных форумах и на сталкерине. Но, они были какими-то сухими. Это вставить туда, это сюда... А зачем, почему, что это даст?.. Кто на эти вопросы ответит? В данном туторе я попытался объяснить всё как можно подробнее. Внимание!Данный тутор рассчитан на тех, кто имеет представление о работе в X-Ray SDK, а именно: работа со спавн-элементами, компиляция спавна. Инструменты и оборудование:1. Настроенный X-Ray SDK 0.7.2. Файлы: configs\misc\secret_zaton.ltx2. Прямые руки и голова (желательно с мозгами внутри ). Вступление:В ЗП система тайников была сильно переработана. Это не бездонный рюкзак, в который может поместиться сколько угодно вещей. Это просто лежащие в укромном местечке предметы, при поднятии которых появляется сообщение «Найден тайник».Такой тайник сделать очень просто при наличии вышеперечисленных инструментов. Ковыряние all.spawn мы разбирать не будем, поскольку это уже «прошлый век». Работа:Итак, открываем в СДК, к примеру, Затон. Ищем место, где хотим сделать тайник. Спавним предметы (например, калаш, 3 пачки патронов к нему, аптечку и бутылку водки). Затем выделяем их и в графе “Custom Data” пишем: [secret]name = zat_hiding_place_my Здесь [secret] – это секция, указывающая на то, что эти вещи являются тайником; zat_hiding_place_my – имя нашего тайника.И не забудьте в свойствах предметов снять галочки с параметров “Used AI locations”, “Useful for AI” и “Visible for AI”. Это нужно, чтобы предметы появились в нужном месте и чтобы их никто не спионерил. Также рядом с тайником нужно разместить спейс-рестриктор. Имя его должно быть zat_hiding_place_my, то есть которое мы указали в свойствах предметов. В “Custom Data” пишем следующее: [secret]cfg = misc\secret_zaton.ltx Здесь [secret] – секция, указывающая на то, что этот рестриктор контролирует тайник; cfg = misc\secret_zaton.ltx – ссылка на файл с описанием тайника.Также снимаем галочку с параметра “Used AI locations”, чтобы рестриктор мог находиться вне АИ-сетки, и ставим тип рестриктора “NOT A restrictor”. Всё, работа в СДК закончена. Сохраняем, компилируем спавн. Теперь перейдём к настройке конфигов. Помните, мы в свойствах рестриктора писали ссылку на файл? Так вот, открываем этот файл (configs\misc\secret_zaton.ltx) и в конце секции [list_zaton] пишем имя нашего тайника: zat_hiding_place_my. Это мы зарегистрировали наш тайник. Теперь создадим его описание. Для этого в самом конце файла создадим следующую секцию: [zat_hiding_place_my]wpn_ak74 = 1, 1ammo_5.45x39_fmj = 3, 1medkit = 1, 1vodka = 1, 1 Теперь разберёмся что к чему: в квадратных скобках написано название тайника; wpn_ak74 – это предмет (в данном случае калаш); первое число – количество предметов; второе – я так и не понял зачем оно нужно, поэтому лучше писать 1). Вот и всё. Сохраняем изменения и бежим тестировать! Изменено 25 Мая 2015 пользователем HellRatz 7 GTA 3 MAP X-Ray | NFS U:2 MAP X-Ray | RTCW MAP X-Ray | L2D | Раритетные моды на моем облаке — на память о былом. Ссылка на комментарий
Дормидонт 144 Опубликовано 12 Июля 2015 Поделиться Опубликовано 12 Июля 2015 второе – я так и не понял зачем оно нужно, поэтому лучше писать 1). ИМХО, это вероятность (в данном случае 100-процентная) выпадения этого предмета... Ссылка на комментарий
Atin 88 Опубликовано 19 Июля 2015 Поделиться Опубликовано 19 Июля 2015 (изменено) Создание LOD динамических объектов. От себя дополню, хоть и запоздало. Суть создания LOD (level of detail - уровень детализации) заключается в снижении триангуляжа/полигонажа модели. Движки считают именно треугольники, поэтому нужно ориентироваться исключительно на их число. Заранее модель триагнулировать смысла нет, экспортер это сам делает. Нюансы по созданию LOD`ов: 1. LOD должен быть минимум в два раза легче, чем оригинальная модель. Каждый последующий LOD так же должен быть легче предыдущего в два раза или больше. Пример: оригинал домика 6000 треугольников; LOD1 3000; LOD2 1500; LOD3 750; LOD4 100 (так как расстояние уже большое и можно хоть коробкой делать). 2. Основной задачей LOD`а является сохранение приемлемого внешнего вида на дистанции, но с хорошей оптимизацией. Важно осознавать на какой дистанции будет вестись переключение LOD`ов. При создании LOD`а крайне важно не искажать крупные формы объекта, чтобы не было видно тех самых переключений, которые будут бросаться в глаза, когда LOD сильно отличается по форме от оригинала. Лёгкие искажения допустимы. 3. Сокращение числа полигонов/трианглов нужно вести от мелких элементов к крупным. На дальних LOD`ах можно мелкие элементы удалять вовсе (дверные петли, ручки и прочее). Чтобы не рисковать запороть LOD удалением мелких элементов стоит делать дубликат и сначала не удалять элементы, а просто их скрыть и свериться, если нормально, то удалять совсем. 4. Хорошим приёмом будет прямо в 3D max выставлять LOD`ы по дистанции переключения и смотреть не сильно ли бросается в глаза их низкая детализация. Выравниваем оригинал по LOD`у (который, к примеру, на 15 метрах от нуля) и смотрим из камеры на нулевой точке; включаем/выключаем оригинал и определяем не сильно ли бросаются в глаза искажения основных форм объекта. 5. Самый дальний LOD с простейшей формой называется Impostor. Обычно это или скрещенные плейны или коробка. Пока такой список навскидку получился. Изменено 20 Июля 2015 пользователем HellRatz 2 2 Ссылка на комментарий
Serge! 127 Опубликовано 2 Октября 2015 Поделиться Опубликовано 2 Октября 2015 Учим ТЧ русскому языку. Сложность: Легко Файлы: ui_save_dialog.script и ui_mm_save_dlg.xml Сначала проделаем маленькую, но необходимую работу. Нам надо в окне диалога определить индикатор текущего языка ввода. Для этого открываем файл ui_mm_save_dlg.xml и в конец тега form добавим строчки, чтобы получилось так: <st_lang x="280" y="400" width="30" height="20"> <text font="graffiti22" align="c" /> <text_color> <e r="227" g="199" b="178"/> <h r="255" g="0" b="0"/> </text_color> </st_lang> </form> Закрываем файл. Он нам больше не понадобится.В отдельном файле (например, ui_save_dlg_rus.script) создаем таблицу перекодировки. Это массив ключами которого являются коды печатных символов английского алфавита, а значениями - соответствующие им коды криллицы. Выглятит она следующим образом: local tbl_lang = { [034] = 221, -- " --> Э [039] = 253, -- ' --> э [044] = 225, -- , --> б ... -- и т.д. } local tbl_ansii = { [ 039 ] = 253, -- ' --> э [ 044 ] = 225, -- , --> б [ 046 ] = 254, -- . --> ю [ 047 ] = 046, -- / --> . [ 058 ] = 198, -- : --> Ж [ 059 ] = 230, -- ; --> ж [ 060 ] = 193, -- < --> Б [ 062 ] = 222, -- > --> Ю [ 065 ] = 212, -- A --> Ф [ 066 ] = 200, -- B --> И [ 067 ] = 209, -- C --> С [ 068 ] = 194, -- D --> В [ 069 ] = 211, -- E --> У [ 070 ] = 192, -- F --> А [ 071 ] = 207, -- G --> П [ 072 ] = 208, -- H --> Р [ 073 ] = 216, -- I --> Ш [ 074 ] = 206, -- J --> О [ 075 ] = 203, -- K --> Л [ 076 ] = 196, -- L --> Д [ 077 ] = 220, -- M --> Ь [ 078 ] = 210, -- N --> Т [ 079 ] = 217, -- O --> Щ [ 080 ] = 199, -- P --> З [ 081 ] = 201, -- Q --> Й [ 082 ] = 202, -- R --> К [ 083 ] = 219, -- S --> Ы [ 084 ] = 197, -- T --> Е [ 085 ] = 195, -- U --> Г [ 086 ] = 204, -- V --> М [ 087 ] = 214, -- W --> Ц [ 088 ] = 215, -- X --> Ч [ 089 ] = 205, -- Y --> Н [ 090 ] = 223, -- Z --> Я [ 091 ] = 245, -- [ --> х [ 093 ] = 250, -- ] --> ъ [ 097 ] = 244, -- a --> ф [ 098 ] = 232, -- b --> и [ 099 ] = 241, -- c --> с [ 100 ] = 226, -- d --> в [ 101 ] = 243, -- e --> у [ 102 ] = 224, -- f --> а [ 103 ] = 239, -- g --> п [ 104 ] = 240, -- h --> р [ 105 ] = 248, -- i --> ш [ 106 ] = 238, -- j --> о [ 107 ] = 235, -- k --> л [ 108 ] = 228, -- l --> д [ 109 ] = 252, -- m --> ь [ 110 ] = 242, -- n --> т [ 111 ] = 249, -- o --> щ [ 112 ] = 231, -- p --> з [ 113 ] = 233, -- q --> й [ 114 ] = 234, -- r --> к [ 115 ] = 251, -- s --> ы [ 116 ] = 229, -- t --> е [ 117 ] = 227, -- u --> г [ 118 ] = 236, -- v --> м [ 119 ] = 246, -- w --> ц [ 120 ] = 247, -- x --> ч [ 121 ] = 237, -- y --> н [ 122 ] = 255, -- z --> я [ 123 ] = 213, -- { --> Х [ 125 ] = 218, -- } --> Ъ } Теперь основное. Возможны два варианта решения задачи руссификации. Мы рассмотрим их оба. Первый. Это упрощённый вариант, который тем не менее вполне устроит подавляющее число пользователей. Преимущества: очень простая реализация с минимальными правками дистрибутивных скриптов. Решается стандартными средствами Lua и не требуется никаких дополнительный функций и внешних скриптов (кроме таблицы перекодировки) Недостатки: Ввод смешанного текста хоть и допускается, но при этом полностью теряется возможность корректировки введённого текста. При вводе однородного текста - корректировка корректна. Открываем в редакторе файл ui_save_dialog.script. 1. Вверху, сразу под комментариями описания, определяем переменную подключающую таблицу перекодировки: local t_lang = ui_save_dlg_rus.tbl_ansii 2. Создадим индикатор текущего языка ввода текста.Договоримся, что переключать раскладку будем щелчком левой кнопки мыши по индикатору или клавишей левый-Ctrl (причем она бутет работать как тригер), а перевключать режим временного изменения языка ввода будем при нажатой и удерживаемой клавише левый-Alt. Для этого в методе save_dialog:InitControls() в самом конце вставим: self.ind_lan = xml:Init3tButton("form:st_lang", self.form) self:Register(self.ind_lan, "button_lang") self.ind_lan:SetText("Рус") self.mode_lang = true Где: self.mode_lang - флаг текущего языка ввода (true - русский, false - английский) Таким образом индикатор режима ввода мы создали, теперь надо обеспечить его функционирование. Для этого в функцию InitCallBacks() вставим строку self:AddCallback("button_lang", ui_events.BUTTON_CLICKED, self.OnChg_lan, self) а под блоком вставляем функцию: function save_dialog:OnChg_lan() self.mode_lang = not self.mode_lang if self.mode_lang then self.ind_lang:SetText("Рус") else self.ind_lang:SetText("Eng") end end Здесь всё янсно - сначала инвертируем флаг текущего языка ввода и потом меняем текст индикатора. Далее функцию function save_dialog:OnKeyboard(dik, keyboard_action), в конец условного блока (перед end), добавляем строки: elseif keyboard_action == ui_events.WINDOW_KEY_PRESSED then -- вызываются на нажатие клавиши if dik == DIK_keys.DIK_LCONTROL or dik == DIK_keys.DIK_LMENU then self:OnChg_lan() end elseif keyboard_action == ui_events.WINDOW_KEY_RELEASED then -- вызываются на отпускание клавиши if dik == DIK_keys.DIK_LMENU then self:OnChg_lan() end 3. Чтобы отслеживать изменения в поле редактирования и проводить перекодировку введенного теста, в функцию InitCallBacks() дабавим строку: self:AddCallback("edit_filename", ui_events.EDIT_TEXT_CHANGED, self.OnEdit_CHANGED, self) Теперь надо, чтобы это отработало. Для этого под функцией save_dialog:OnChg_lan() вставляем еще одну свою ффункцию: function save_dialog:OnEdit_CHANGED() if self.mode_lang then -- /1 local str_edit = self:GetEditBox("edit_filename") -- /2 local txt, copy_txt, cls = str_edit:GetText(), "" -- /3 for n = 1, txt:len() do cls = txt:byte(n) -- /4 if t_lang[cls] ~= nil then copy_txt = copy_txt..string.char(t_lang[cls]) -- /5 else copy_txt = copy_txt..string.char(cls) end -- /6 end str_edit:SetText(copy_txt) -- /7 end end Рассмотрим построчно, что эта функция делает:- проверяем установлен ли флаг ввода кириллицы (1) - если установлен, то подключаем окно поля редактирования (2) - получаем строку введенного текста и инициализируем переменную для её копии (3) - в цикле получаем код каждого символа строки ввода (4) - ищем в таблице перекодировки соответствующий русский символ (стандартный ввод всегда английский) и если находим, то заменяем английский символ на русский (5) - если же не находим, то оставляем исходный (6) - возвращаем строку в поле редактирования (7) На этом всё. Данный алгоритм, с учетом отмеченных выше ограничений, вполне стабильно работает на всех модах платформы ТЧ, в которые я играл. Все необходимые откорректированные файлы этого урока будут доступны через сутки от даты публикации в течении месяца здесь: https://yadi.sk/d/UAn5jdKRjUmrz Второй вариант реализации этой же задачи мы рассмотрим в следующем уроке. 3 Ссылка на комментарий
Это популярное сообщение. Serge! 127 Опубликовано 19 Октября 2015 Это популярное сообщение. Поделиться Опубликовано 19 Октября 2015 Учим ТЧ русскому языку (продолжение).Сначала вернёмся к первому уроку. Charsi предложил свой, более компактный, вариант функции обработки добавления символа в строку ввода, который обрабатывает не всю строку, а только последний символ.Привожу его полностью: function save_dialog:OnEdit_CHANGED() local str_edit = self:GetEditBox("edit_filename") local txt = str_edit:GetText() txt = txt:gsub(".$", function(ch) local _ch = t_lang[ch:byte()] return _ch and string.char(_ch) or ch end) str_edit:SetText(txt) end Какой из вариантов Вас больше устраивает, определитесь самостоятельно, ну а мы идём дальше. Всё, что в первом уроке было написано до подзаголовка «Первый» остаётся в силе с одним замечанием.В таблице перекодировки, ссылка на которую дана в первом уроке, отсутствует пара символов. Добавьте их самостоятельно в самое начало таблицы. [034] = 221, -- " --> Э [035] = 185, -- # --> № Второй.На первом уроке мы научились вводить символы кириллицы в поле EditBox. Однако наш вариант имел существенный недостаток – в нём отсутствовала возможность корректного исправления текста вводимой строки. Давайте попробуем это исправить.Рассмотрим все возможные операции при корректировке:1 - добавление символа в конец строки;2 - удаление последнего введенного символа;3 – перемещение по строке влево/вправо;4 – вставка символа в позиции курсора в середине строки;5 – удаление символа в позиции курсора в середине строки;6 - удаление символа перед позицией курсора в середине строки. Большую часть этих операций движок замечательно проделывает сам и нам остаётся только отслеживать результат его работы и учитывать его. А вот две операции требуют нашего активного вмешательства: это 2 и 4, которые связаны с вводом новых символов. 1. Добавим две новых переменных к той, что была определена в п. 1 первого урока: local edb_Pos, edb_Str = 1, {} Где: edb_Pos – позиция курсора в поле EditBox (инициируется 1) и edb_Str – массив, в котором мы будем сохранять символы вводимого текста.2. В пункте 2 (урока 1) менять ничего не требуется, поэтому берем его, целиком как есть, а вот пункт 3 подлежит коренной реконструкции.3. Так как мы решили, что все события производимые пользователем в поле EditBox будем контролировать сами, то первым делом отключаем прерывание генерируемое движком при изменении поля. Для этого в функции save_dialog:InitCallBacks() удаляем добавленную нами в первом уроке строку: self:AddCallback("edit_filename", ui_events.EDIT_TEXT_CHANGED, self.OnEdit_CHANGED, self) Саму нашу функцию save_dialog:OnEdit_CHANGED() пока не трогаем.Далее пойдём от простого к более сложному. Простое - это отследить те моменты, которые мы договорились отдать на откуп самому движку, т.е. перемещение по строке и удаление. Делать это будем в функции save_dialog:OnKeyboard(dik, keyboard_action). Для этого добавляем в неё, после уже вставленных нами ранее (в 1 уроке) несколько дополнительных строк, чтобы в итоге получилось так: if keyboard_action == ui_events.WINDOW_KEY_PRESSED then if dik == DIK_keys.DIK_LCONTROL or dik == DIK_keys.DIK_LMENU then self: OnChg_lan() elseif dik == DIK_keys.DIK_LEFT then if edb_Pos > 1 then edb_Pos = edb_Pos - 1 end elseif dik == DIK_keys.DIK_RIGHT then if edb_Pos <= #edb_Str then edb_Pos = edb_Pos + 1 end elseif dik == DIK_keys.DIK_DELETE then if edb_Pos <= #edb_Str then table.remove(edb_Str,edb_Pos) end elseif dik == DIK_keys.DIK_BACK then if edb_Pos > 1 then edb_Pos = edb_Pos-1 end table.remove(edb_Str,edb_Pos) elseif (dik > 1 and dik <= 13) or (dik >= 16 and dik <= 27) or (dik >= 30 and dik <= 40) or (dik >= 44 and dik <= 53) or dik == 57 or (dik >= 71 and dik <= 83) then self:OnEdit_CHANGED() end Здесь всё достаточно просто. При перемещении стрелками проверяем новое положение курсора и, если оно в пределах строки, то запоминаем его позицию. При удалении символа из строки удаляем соответствующий элемент из массива копии строки и опять же запоминаем текущую позицию ввода.Теперь осталось только разобрать со вставкой символа. Для этого отлавливаются прерывания от всех клавиш с печатными символами и, если такое обнаружено, то вызывается функция обработчик, т.е. наша OnEdit_CHANGED(). Обратите внимание, что мы даже не пытаемся отловить ввод буквы ‘ё’, т.к. на этой же клавише размещена тильда ‘~’, которую движок обрабатывает специальным образом для вывода окна консоли.И так, если мы зафиксировали факт нажатия клавиши с печатным символом, то вызываем OnEdit_CHANGED(), которая теперь не привязана к сообщениям от движка и находится под полным нашим контролем. Вот этим контролем и займёмся.Убираем в ней все содержимое и вставляем новое. Должно получиться следующее: function save_dialog:OnEdit_CHANGED() local str_edit = self:GetEditBox("edit_filename") -- /1 local sim = str_edit:GetText():match ('.', edb_Pos) -- /2 local cls = self.mode_lang and t_lang[sim:byte()] -- /3 sim = cls and string.char(cls) or sim -- /4 table.insert(edb_Str, edb_Pos, sim) -- /5 edb_Pos = #edb_Str + 1 -- /6 str_edit:SetText(table.concat(edb_Str)) -- /7 end Здесь тоже нет особых сложностей, но, тем не менее, прокомментируем наши действия.Подключаемся к контролу EditBox (1) и получаем символ, находящийся в текущей позиции ввода (2). Если включен режим кириллицы, то ищем код переданного движком символа (он всегда английский) в таблице перекодировки и при его наличии получаем соответствующий код русского символа (3). Если код найден, то подменяем английский символ русским, а если нет, то оставляем всё как есть (4). Заносим полученный символ в массив копии строки ввода в соответствии со значение текущей позиции курсора (5). Устанавливаем новую текущую позиции ввода (6), преобразуем массив символов в строку и возвращаем её в поле ввода (7).Если Вы всё проделами правильно, то теперь можете вводить имя сохраняемого файла в английской, русской или смешанной кодировке, а также корректировать вводимый текст без искажения его синтаксиса.Послесловие:Этот алгоритм имеет отличие от стандартной обработки строки редактирования, которое выражается в том, что при вставке символа в середину строки, позиции ввода следующего символа всегда устанавливается в её конец, тогда как в “штатной” – текущей становится следующая позиция. В этой ситуации есть свой плюс и свой минус, однако в любом случае, как побороть это, я просто не знаю. 1 4 Ссылка на комментарий
Это популярное сообщение. Моддер 7 Опубликовано 12 Ноября 2015 Это популярное сообщение. Поделиться Опубликовано 12 Ноября 2015 (изменено) Как лечить раненных НПС-враговСложность: оч. легкоСовместимость с модами: легко совместимоМногие люди в своих модификациях хотят добавить возможность лечить раненных врагов, как, например, в Солянке. Я тоже однажды заинтересовался этим вопросом и, не найдя на него ответа в интернете, занялся решением проблемы сам. В итоге мне это удалось и теперь выкладываю плоды своих стараний на просторы интернета . Запрет диалога с раненными противниками находится в файле xr_wounded.script, и выглядит так (я снабдил его комментариями, если вы не сильно шарите в скриптах): if self.object:relation(db.actor) == game_object.enemy then --если отношение НПС к ГГ = отношению к врагум self.object:disable_talk() --блокировать диалоги else --иначе self.object:enable_talk() --разрешить диалог end --конец условия (if) Дабы позволить ГГ говорить с врагами (только раненными) достаточно удалить лишнее и оставить всего одну строку: self.object:enable_talk() Но! Если ГГ попробует обратиться к раненным представителям бандитов, монолитовцев, наёмников, зомби (возможно), военных или противников на Арене - скорее всего произойдёт Фатал Еррор с логом на отсутствие подходящей фразы для диалога (в оригинальной игре с вероятностью 99%). Так вот, лично для себя я нашёл простое решение, которое подходило и по концепции моего мода - запретить диалог с данными группировками. Вот таким макаром: local comm = self.object:character_community() --переменной обозначил "понятие" группировки обьекта (НПС) if comm == "zombied" or --если НПС - зомби, или comm == "bandit" or --НПС - бандит, или comm == "monolith" or --НПС - монолитовец, или comm == "arena_enemy" or --НПС - боец арены, или comm == "killer" or --НПС - наёмник, или comm == "military" then --НПС - вояка, тогда self.object:disable_talk() --запретить диалог else -- иначе self.object:enable_talk() --разрешить диалог end -- The End! просто заменить изначальные строки этими и теперь ГГ сможет лечить врагов одиночек, долговцев, свободовцев и учёных.Но есть ещё один момент. При лечении врагов, если всё сделать как было написано будет ещё одна проблемка - они так и останутся врагами после лечения и будут дальше атаковать ГГ.Разумно было бы сделать НПС если не другом, то по крайней мере нейтралом. Для этого необходимо в файле dialogs.script кусок скрипта if second_speaker:relation(first_speaker) ~= game_object.enemy then second_speaker:set_relation(game_object.friend, first_speaker) end first_speaker:change_character_reputation(10); end заменить на if second_speaker:relation(first_speaker) == game_object.enemy then second_speaker:set_relation(game_object.friend, first_speaker) first_speaker:set_relation(game_object.friend, second_speaker) end first_speaker:change_character_reputation(10); end Всё! Да и уже готовый файл xr_wounded.script и dialogs.script со всеми описанными правками прилагается https://yadi.sk/d/-ZEwRBo7kPwCP.Как сделать костюм с системой автолечения (изначально для ТЧ)Сложность: легкоСовместимость с модами: придётся поработать Подобную схему делал для своего мода, теперь выкладываю здесь ее аналог, мало мальски продуманный для оригинального ТЧ:Принцип работыФункция (скрипт), указанная в бинд_сталкер.скрипт (кто не знает что это - загуглите ) выполняется движком несколько раз в секунду. Задача функции - проверять одет ли на ГГ нужный костюм, сколько у ГГ здоровья и если здоровья мало - использовать медикаменты (если у ГГ они есть, разумеется). Вот и всё!Порядок работы (для оригинального ТЧ)Создаём новый костюм. Можно конечно и для существующего прописать всё, но лучше потратить на минутку больше и сделать качественнее. В файл gamedata/config/misc/unique_items.ltx в конец добавляем новую секцию: [outfit_stalker_m3]:stalker_outfit ;Комбез с системой автоприёма медикаментов $spawn = "outfit\uniq\outfit_stalker_m3" inv_name = stalker_outfit_name_m3 inv_name_short = stalker_outfit_name_m3 description = stalker_outfit_description_m3 inv_grid_x = 16 inv_grid_y = 24 В файл gamedata/config/text/rus/string_table_outfit.xml в конец перед тэгом </string_table> дописываем: <string id="stalker_outfit_name_m3"> <text>Прототип мед. комбинезона</text> </string> <string id="stalker_outfit_description_m3"> <text>Данный образец является прототипом защитного комбинезона сталкера. От оригинала он отличается наличием уникальной системы приёма медикаментов. Если здоровье хозяина опуститься ниже 20% будет автоматически использован мед. препарат.</text> </string> Делаем схему рабочейВ файле bind_stalker.script под строкой function actor_binder:update(delta) пишем med_outfit.main() --лечащий костюм, примерно так (таким образом мы будем вызывать наш будущий скрипт несколько раз в секунду): function actor_binder:update(delta) med_outfit.main() --Лечащий костюм Создаём файл med_outfit.script в соответствующей папке и в сам файл пишем: function main() local medkit = db.actor:object("medkit") local medkit_army = db.actor:object("medkit_army") local medkit_scientic = db.actor:object("medkit_scientic") local outfit = db.actor:item_in_slot(6) --определяем предмет в слоте 6 (костюм) local snd = sound_object([[device/pda/pda_tip]]) --звук сообщения if outfit and outfit:section() == "outfit_stalker_m3" and db.actor.health < 0.20 and db.actor.health > 0.005 then if medkit then db.actor:eat(medkit) snd:play_no_feedback(db.actor,sound_object.s2d, 0, vector():set(0, 0, 0), 1) db.actor:give_game_news("\n%c[255,255,0,0]Была автоматически использована аптечка.", "ui\\ui_iconsTotal", Frect():set(0,0,83,47), 1, 2000) elseif medkit_army then db.actor:eat(medkit_army) snd:play_no_feedback(db.actor,sound_object.s2d, 0, vector():set(0, 0, 0), 1) db.actor:give_game_news("\n%c[255,255,0,0]Была автоматически использована армейская аптечка.", "ui\\ui_iconsTotal", Frect():set(0,0,83,47), 1, 2000) elseif medkit_scientic then db.actor:eat(medkit_scientic) snd:play_no_feedback(db.actor,sound_object.s2d, 0, vector():set(0, 0, 0), 1) db.actor:give_game_news("\n%c[255,255,0,0]Была автоматически использована научная аптечка.", "ui\\ui_iconsTotal", Frect():set(0,0,83,47), 1, 2000) end end end Теперь если ХП у актёра меньше 20%, одет нужный костюм и есть аптечка - она автоматически используется.Чтобы Волк выдал его в начале игры в файле escape_dialog.script в функции give_weapon_to_actor допишем: dialogs.relocate_item_section(trader, "outfit_stalker_m3", "in") Готово, можно тестировать! Изменено 30 Ноября 2015 пользователем HellRatz 2 4 Ссылка на комментарий
Forser 47 Опубликовано 8 Декабря 2015 Поделиться Опубликовано 8 Декабря 2015 (изменено) Реализация хита артефактов из инвентаря, слотов и пояса. Сложность: средняя Платформа: проверялось на SoC Требование: наличие исходников движка и базовые знания работы в MVS 2005 и выше. И так, открывает Actor.cpp из состава xrGame и ищем метод HitArtefactsOnBelt и UpdateArtefactsOnBelt, а в них строки: for(TIItemContainer::iterator it = inventory().m_belt.begin(); inventory().m_belt.end() != it; ++it)И меняем m_belt на m_all.P.S. Есть хотим, чтоб хит выдавался только из рюкзака, то в HitArtefactsOnBelt, в место m_belt, пишим m_ruck. (Не проверял, только догадка) Изменено 8 Декабря 2015 пользователем Forser 1 Ссылка на комментарий
НаноБот 742 Опубликовано 14 Января 2016 Поделиться Опубликовано 14 Января 2016 (изменено) Решил я как то заспавнить скриптом машинку в Зов Припяти, машинка за спавнилась, но физики нет у машинки. Начал ковырять, ковырял, ковырял, и понял что нет класса SCRPTCAR. Восстанавливаем класс SCRPTCAR. cs_register(object_factory, "CCar", "se_car.se_car", "SCRPTCAR", "car_s") Это добавляем после hanging_lamp Серверный объект. ---------------------------------------------------------------------class "se_car" (cse_alife_car)--------------------function se_car:__init (section) super (section)--log("_bp: set_car:__init")self.ini = nilself.spawner_present = falseend--------------------function se_car:can_switch_offline ()return cse_alife_car.can_switch_offline(self)end--------------------function se_car:can_switch_online ()if not self.ini thenself.ini = self:spawn_ini()self.spawner_present = self.ini:section_exist("spawner")endif self.ini == nil or self.spawner_present == false thenreturn cse_alife_car.can_switch_online(self)endreturn xr_spawner.check_spawn(self)end-------------------- Ещё желательно надо добавить файл ph_car.script из мода GLADIATORII Или ещё проще, задать класс C_NIVA. Нива если кто помнит первая машинка из древних билдов. В общем, как то так. Изменено 14 Января 2016 пользователем Kirgudu Добавлено Kirgudu, 14 Января 2016 Перенёс из «Ковырялки ТЧ» 1 1 1 ...в конце концов, важен лишь, машинный код. СТАЛКЕР только для ПК! Ссылка на комментарий
sneik 341 Опубликовано 24 Марта 2016 Поделиться Опубликовано 24 Марта 2016 Уроки по созданию сквадов и заселению локаций в ЗП. https://yadi.sk/d/mGM6354oqS3ef 1 3 Ссылка на комментарий
Это популярное сообщение. PTB 8 Опубликовано 18 Мая 2016 Это популярное сообщение. Поделиться Опубликовано 18 Мая 2016 (изменено) Скриптовые ролики Автора не помню.Внёс небольшие правки.В игре пишем в консоли demo_record название_вашего_роликаПробелом отмечаем точки через которые должна пролететь камера. Внимание! Если точки отделить слишком далеко, то они пролетят с сумашедшей скоростью! Сделав все точки куда пролетит камера, возвращаемся к месту где должен стоять ГГ(Если вы снимали например из бункера Сидора, то обратно камера политит прямо через terrein(землю)).Проиграть получившееся демо можно проиграть через консоль:demo_play название_вашего_роликаТеперь со скриптами делаем функцию function любое_название()local console = get_console()console: execute("demo_play название_ролика")end В идеале в функцию надо добавить отключение HUD’a, порытся в анимациях (не модельных) чтобы при начале скриптового ролика на несколько секунд не вылазил черный экран и сделать так чтобы в ролике бн сам Глав Герой. Все демо сохраняются в ХР примерно c:\documents and settings\all users\документы\stalker-shoc\savedgames.ыл виде Создание костюма с автоматическим применением препаратов.Решил побаловаться со скриптами, вот что получилось: Создаём скрипт ваше_название.scriptи пишем в него следующее: function kiber_outfit()local slot_outfit = db.actor:item_in_slot(6) -- переменная слотаlocal object_1 = db.actor:object("protection_outfit") -- переменная объекта (в данном случае укреплённый костюм учёного)if slot_outfit and slot_outfit:section() == "protection_outfit" and object_1 ~= nil then -- если в слоте бронька указаная в local object_1if db.actor.health <= 0.3 then -- если хп меньше 30%if db.actor:object("medkit") ~= nil ordb.actor:object("medkit_army") ~= nil ordb.actor:object("medkit_scientic") ~= nil thenlocal news_text = "%c[155,160,160,160]Автоматический приём медицинских препаратов\\n%c[default]Применение:%c[255,160,160,160] Принимаю медицинский препарат. %c[default]"db.actor:give_game_news(news_text, "ui\\ui_iconsTotal",Frect():set(0,188,83,47), 0, 5000)automat_medkits()endendendendfunction automat_medkits()if db.actor:eat(db.actor:object("medkit")) ~= nil ordb.actor:eat(db.actor:object("medkit_army")) ~= nil ordb.actor:eat(db.actor:object("medkit_scientic")) ~= nil thenendend После этого в файле bind_stalker.script после строки object_binder.update(self, delta) пишем ваше_название_скрипта.kiber_outfit() Всё. Платформа: ТЧРешил поковырять скрипт, который выше под спойлером, получилось чёт вроде смены группировки при смене костюма.(скрипт надо дорабатывать) function test() --название функцииlocal gg = db.actor -- переменная ГГlocal item = gg:item_in_slot(6) -- переменная слота под костюмыlocal object_1 = db.actor:object("novice_outfit") -- переменная костюма новичка(можно менять на свои)local object_2 = db.actor:object("bandit_outfit") -- переменная костюма бандитаlocal object_3 = db.actor:object("killer_outfit") -- переменная костюма наёмникаlocal object_4 = db.actor:object("specops_outfit")-- переменная костюма военныхif item and item:section() == "novice_outfit" and object_1 ~= nil then--Смена группировки ГГprintf("ACTOR NOW IN [sTALKER] COMMUNITY")if db.actor then db.actor:set_character_community("stalker", 0, 0)end -- -- -- --return true end-- Ну и дальше также, только с другими костюмами.if item and item:section() == "bandit_outfit" and object_2 ~= nil thenprintf("ACTOR NOW IN [bANDIT] COMMUNITY") if db.actor then db.actor:set_character_community("bandit", 0, 0) end return true endif item and item:section() == "killer_outfit" and object_3 ~= nil thenprintf("ACTOR NOW IN [KILLER] COMMUNITY") if db.actor then db.actor:set_character_community("killer", 0, 0) end return true endif item and item:section() == "specops_outfit" and object_4 ~= nil thenprintf("ACTOR NOW IN [MILITARY] COMMUNITY") if db.actor then db.actor:set_character_community("military", 0, 0) end return true endend Изменено 8 Декабря 2016 пользователем BFG 1 5 В жизни много плохих моментов. Пытайся избавляться от них ! Ссылка на комментарий
Это популярное сообщение. FantomICW 678 Опубликовано 16 Июня 2016 Это популярное сообщение. Поделиться Опубликовано 16 Июня 2016 (изменено) [CoP] Пресеты Custom Data для SDK Добрый день! Предлагаю небольшую шпаргалку для тех, кто работает с заселением в SDK LE и более-менее понимает, для чего, вообще, нужен данный код. Фактически создано для копипаста и экономии времени. Для новичков, может, тоже будет не лишним почитать. Что необходимо учесть: 1. Я привык разбивать логику различных групп объектов по подпапкам (smart, anomaly, npc_logic, monsters_logic и другие). Это не есть обязательным, но рекомендую действовать таким же образом. Практика показывает, что другим модмейкерам, в этом случае, будет легче ориентироваться в файлах логики Вашего мода. 2. Каждый пресет является среднестатистическим набором для логики. Вы, само собой, можете убирать/добавлять дополнительные секции в роде collide, story_object. 3. Вместо location, в пути прописываете название локации. Удачи! ;) Для Custom Data в SDK [smart_terrain] cfg = scripts\location\smart\smart_name.ltx [anomal_zone] cfg = scripts\location\anomaly\anomal_zone.ltx [camp] cfg = scripts\camp.ltx [story_object] story_id = restr_story_id [logic] cfg = scripts\location\restrictors_logic\restr.ltx [logic] cfg = scripts\sr_sleep.ltx [story_object] story_id = object_story_id [collide] ignore_static ignore_small_objects [logic] cfg = scripts\location\physic_objects\object.ltx [physics_common] ;Альтернатива параметру fixed_bones, используется для квестовых айтемов device_pda и т. д. fixed_bones = link [story_object] story_id = anim_object_story_id [collide] ignore_static ignore_small_objects [logic] cfg = scripts\location\physic_objects\anim_object.ltx [animated_object] [story_object] story_id = box_story_id [logic] cfg = scripts\location\inventory_box\box.ltx [story_object] story_id = actor_box_story_id [logic] cfg = scripts\actor_inventory_box.ltx [level_spot] actor_box [logic] cfg = scripts\door.ltx Другое [exclusive] monster = location\monsters_logic\monster_l.ltx npc = location\npc_logic\npc_l.ltx ;==============================For SDK and logic==============================; ;------------------------------------------- ;Smart Terrain ;------------------------------------------- [smart_terrain] cfg = scripts\location\smart\smart_name.ltx ;------------------------------------------- ;Anomal Zone ;------------------------------------------- [anomal_zone] cfg = scripts\location\anomaly\anomal_zone.ltx ;------------------------------------------- ;Camp ;------------------------------------------- [camp] cfg = scripts\camp.ltx ;------------------------------------------- ;Space Resctrictor ;------------------------------------------- [story_object] story_id = restr_story_id [logic] cfg = scripts\location\restrictors_logic\restr.ltx ;------------------------------------------- ;Sleep Zone ;------------------------------------------- [logic] cfg = scripts\sr_sleep.ltx ;------------------------------------------- ;Physic Objects and Quest Items ;------------------------------------------- [story_object] story_id = object_story_id [collide] ignore_static ignore_small_objects [logic] cfg = scripts\location\physic_objects\object.ltx [physics_common] fixed_bones = link ;------------------------------------------- ;Anim Object ;------------------------------------------- [story_object] story_id = anim_object_story_id [collide] ignore_static ignore_small_objects [logic] cfg = scripts\location\physic_objects\anim_object.ltx [animated_object] ;------------------------------------------- ;Inventory Box ;------------------------------------------- [story_object] story_id = box_story_id [logic] cfg = scripts\location\inventory_box\box.ltx ;------------------------------------------- ;Actor Inventory Box ;------------------------------------------- [story_object] story_id = actor_box_story_id [logic] cfg = scripts\sr_sleep.ltx [level_spot] actor_box ;------------------------------------------- ;Door ;------------------------------------------- [logic] cfg = scripts\door.ltx ;==============================For Smart Configs==============================; [exclusive] monster = location\monsters_logic\monster_l.ltx npc = location\npc_logic\npc_l.ltx Изменено 15 Декабря 2017 пользователем Murarius 2 6 Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти