Скрипты |
Здравствуйте, гость ( Авторизация | Регистрация )
Сайт S.T.A.L.K.E.R. Inside / [ЗП] Параметры командной строки / Распаковщик ресурсов
Скрипты |
13.07.2009, 11:34
Сообщение
#241
|
|
Навий черны у ношьти Репутация: 377 Группа: Забанен Сообщений: 2210 Регистрация: 11.03.2009 |
FAQ Lua в X-Ray Список всех функций, переменных, классов и т.п. что используются в Сталкере находится по адресу: Код gamedata/scripts/lua_help.script Для получения файла надо распаковать игру. Можно скачать, в принципе Тут =>> Уроки Сообщение отредактировал RayTwitty - 09.06.2018, 20:23 -------------------- нарушение правил п. 7.2
|
 
|
|
|
|
21.11.2019, 19:34
Сообщение
#242
|
|
Почти Мастер Репутация: 75 Группа: Участник Сообщений: 1168 Награды: 4 Регистрация: 10.11.2015 |
Кстати, функции типа object_binder.update(self, delta) можно спокойно исключить, это просто пустышки, которые ничего не делают, кроме времени(2-3 мксек). Исключения только для метода net_spawn, там это нужно.
-------------------- СТАЛКЕР только для ПК!
|
 
|
|
23.11.2019, 07:43
Сообщение
#243
|
|
Почти Игрок Репутация: 1 Группа: Участник Сообщений: 17 Награды: 1 Регистрация: 14.01.2013 |
Хотел добавить свою аи-схему, которая запускается во время боя. Все подключил, добавил эвалуатор, работает. А вот экшен не работает от слова совсем. В чем могла быть ошибка?
Код Код local base = xr_evaluators_id.combat_new_base local eval_on_combat = base + 0 base = xr_actions_id.combat_new_base local act_on_combat = base + 0 ---------------------------------------------------------------------------------------------------------------------- -- модификация xr_combat ---------------------------------------------------------------------------------------------------------------------- class "evaluator_mod_combat" (property_evaluator) function evaluator_mod_combat:__init(name,storage) super (nil, name) self.st = storage end function evaluator_mod_combat:evaluate() local cond = self.object:motivation_action_manager():current_action_id() == stalker_ids.action_combat_planner --news_manager.send_tip(db.actor, self.object:character_name()) return cond end ---------------------------------------------------------------------------------------------------------------------- class "action_mod_combat" (action_base) function action_mod_combat:__init(name,storage) super (nil, name) self.st = storage end function action_mod_combat:initialize() action_base.initialize(self) news_manager.send_tip(db.actor, 1) end function action_mod_combat:execute() action_base.execute(self) end function action_mod_combat:finalize() action_base.finalize(self) end ---------------------------------------------------------------------------------------------------------------------- -- binder ---------------------------------------------------------------------------------------------------------------------- function add_to_binder(npc, ini, scheme, section, storage) local manager = npc:motivation_action_manager() manager:add_evaluator( eval_on_combat, this.evaluator_mod_combat("eval_mod_combat",storage) ) local action = this.action_mod_combat("act_mod_combat",storage) --action:add_precondition(world_property(stalker_ids.property_alive, true)) manager:add_action(act_on_combat, action) end Сообщение отредактировал Gaz24 - 23.11.2019, 08:18 |
 
|
|
23.11.2019, 10:55
Сообщение
#244
|
|
Игровое Воплощение Репутация: 394 Группа: Участник Сообщений: 4791 Награды: 4 Регистрация: 27.04.2011 |
Хотел добавить свою аи-схему, которая запускается во время боя. Все подключил, добавил эвалуатор, работает. А вот экшен не работает от слова совсем. В чем могла быть ошибка? Он и не должен работать, ты же экшен никак в GOAP не встроил: 1. твоему экшену надо добавить прекондишен и эффект. Например, что он вызывается, когда world_property(eval_on_combat) = true и обещает перевести world_property(eval_on_combat) в false. 2. добавить существующему экшену прекондишен world_property(eval_on_combat) = false, например к stalker_ids.action_combat_planner Тогда НПЦ попытается в очередной раз попытается решить загадку зоны; увидит, что ему мешает world_property(eval_on_combat) = true(пункт 2); для устранения такой неприятности у него есть твой экшен(пункт 1) и НПЦ запустит твой экшен. Посмотри на аи-схемы из оригинала или из модов. Там есть оба пункта. |
 
|
|
23.11.2019, 11:54
Сообщение
#245
|
|
Почти Игрок Репутация: 1 Группа: Участник Сообщений: 17 Награды: 1 Регистрация: 14.01.2013 |
abramcumner, я со своим эвалуатором использовал изначально, поэтому другой запустил. Сделал так, как ты посоветовал. Все равно экшен не срабатывает. Я может плохо написал из-за своего непонимания.
Код Код local action = manager:action(stalker_ids.action_combat_planner) action:add_precondition(world_property(world_property(eval_on_combat), true)) local action = this.action_mod_combat("act_mod_combat",storage) action:add_effect(world_property(world_property(eval_on_combat), false)) manager:add_action(act_on_combat, action) |
 
|
|
23.11.2019, 13:16
Сообщение
#246
|
|
Игровое Воплощение Репутация: 394 Группа: Участник Сообщений: 4791 Награды: 4 Регистрация: 27.04.2011 |
Gaz24, не так. К сожалению не могу найти статью по аи-схемам в сталкере.
Смотри цель любого сталкера - решить загадку зоны, это world_property(puzzleSolved)=true, такой эффект есть у экшена xr_actions_id.alife. Но у него есть прекондишены: жив, нет врагов и тд. Планировщик НПЦ смотрит, как решить загадку зоны, она решается экшеном stalker_ids.action_alife. У него есть прекондишены, планировщик их проверяет. Если все выполнены, то нпц решает загадку зоны, игра заканчивается(в том самом билде). Если не выполнены, то планировщик ищет экшен, который выполнит прекондишен. У него опять проверяет прекондишены, ищет новый экшен,... В итоге доходит до экшена, который может сейчас выполнить и который ведет к решению загадки зоны. Например логика и гулаги подрубаются так: к экшену xr_actions_id.alife добавляется прекондишен типа "need_remark"=false, а action_remark умеет переводить need_remark в false. Сначала отыграй анимку, а потом можешь решать загадку зоны. Теперь по-твоему коду. Ты combat_planner`у добавил прекондишен eval_on_combat=true. Планировщик будет искать экшен, который переводит eval_on_combat в true. Но такого нет - act_mod_combat переводит eval_on_combat в false. Надо в эффекте поменять false на true. После этого твой экшен должен начать бесконечно вызываться. Ну и для срабатывания твоего экшена нужен враг, без него боевка и не будет запускаться. И так не надо писать "world_property(world_property(eval_on_combat), true)", просто "world_property(eval_on_combat, true)". Сейчас по идее аи-схема должна зависать. Если запустить такой скрипт на отладочном движке, то в лог будет выведен дамп с указанием, что пошло не так. Сообщение отредактировал abramcumner - 23.11.2019, 13:16 |
 
|
|
23.11.2019, 14:04
Сообщение
#247
|
|
Почти Игрок Репутация: 1 Группа: Участник Сообщений: 17 Награды: 1 Регистрация: 14.01.2013 |
abramcumner, заработало, спасибо. Правда с прекондишенами надо поиграться. А так, осознал.
Если ты говорил про эту статью, то я на нее очень сильно опирался, но из-за своего косяка вообще не понимал. Сообщение отредактировал Gaz24 - 23.11.2019, 14:14 |
 
|
|
08.01.2020, 22:34
Сообщение
#248
|
|
Игровой Бог Репутация: 648 Группа: Участник Сообщений: 5354 Награды: 9 Регистрация: 24.09.2010 |
В дополнение к
uint64<class_id> r_clsid(string<section>, string<line>) - возвращает id класса по имени класса (т.е. вызов ini:r_clsid(obj:section(), "class") полностью эквивалентен вызову obj:clsid()). string<result> r_string_wq(string<section>, string<line>) - тоже самое что и стандартный r_string, только этот метод убирает ещё и кавычки. Пример Код [mysection] param = "myvalue" ------------------ print(ini:r_string("mysection", "param")) print(ini:r_string_wq("mysection", "param")) Результаты Код "myvalue" myvalue int32<result> r_s32(string<section>, string<line>) - возвращает 4-байтовое целое число в диапазоне [-2.147.483.648, 2.147.483.647]. uint32<result> r_u32(string<section>, string<line>) - возвращает 4-байтовое беззнаковое целое число в диапазоне [0, 4.294.967.295]. int<item_id> r_token(string<section>, string<line>, token_list*) - довольно интересный метод, который работает следующим образом: Открыть Допустим, у нас имеется токен (лист с именами и их идентификаторами): Код local my_token = token_list() my_token:add("value1", 0) my_token:add("value2", 1) my_token:add("value3", 2) И имеется конфиг со строкой: Код [mysection] param = value2 Нам нужно выяснить, какому идентификатору соответствует это значение (и соответствует ли вообще). Читаем: Код local item_id = ini:r_token("mysection", "param", my_token) log(item_id) Результат Код 1 (что соответствует value2 = 1). Если значение в конфиге не соответствует никакому значению из токена, то вернет ноль. И ещё, сразу сюда же - метод ini_file* create_ini_file(string<file_text>) Собственно создает конфиг-файл. После чего, с ним можно работать как и с обычным конфигом: Код local ini = create_ini_file("[mysection]\nmyparam = value") З.Ы. Это перенос моего старого поста с другого форума. Пусть будет и здесь. -------------------- |
 
|
|
02.07.2020, 20:22
Сообщение
#249
|
|
Почти Мастер Репутация: 111 Группа: Участник Сообщений: 1158 Награды: 3 Регистрация: 07.08.2015 |
Вопрос по скрипту ОГСМ ogsm_rt_manager.script. В игре, с локациями ЧН, вылета не было. Вылет идёт по спавну в алспавн мертвого сталкера на новой локации.
--Регистрация целей для тасков типа kill_stalker function CRandomTask:register_target(obj) if IsStalker(obj) then for k,v in pairs(self.task_id_by_type["kill_stalker"]) do -- !!! ТУТ ВЫЛЕТ !!! if obj.alive ~= nil and obj:alive() == true and obj:profile_name() == self.task_info[v].target then if self.task_info[v].target_objects == nil then self.task_info[v].target_objects = {} end table.insert(self.task_info[v].target_objects, obj.id) end end end end Если выпиливаю полностью тело функции, то срабатывает нормально. А вообще это что за тема задумана такая? Может перечисление локаций ЧН сделать, типа такого? if level.name() == "agroprom_underground" then Или куда то надо новую локацию прописать или трупы? Тупизна меня обуяла. А там еще ака Bak намутил rx_wmgr.script - что на сивой кобыле не проехать. Короче, для нового уровня - ОГСМ - это Ж... Сообщение отредактировал Diesel - 02.07.2020, 21:15 |
 
|
|
09.08.2020, 02:18
Сообщение
#250
|
|
Почти Мастер Репутация: 111 Группа: Участник Сообщений: 1158 Награды: 3 Регистрация: 07.08.2015 |
Кто желает разобраться в хитросплетениях диалога. Вылет идёт когда раненому даю аптечку в ЧН (мод SGM).
Вылетает рандомно. В интернетах разумного ответа нет. FATAL ERROR [error]Expression : !phrase_dialog->m_PhraseVector.empty() [error]Function : CPhraseDialog::SayPhrase [error]File : .\PhraseDialog.cpp [error]Line : 146 [error]Description : No available phrase to say, dialog[dm_hello_dialog] stack trace: 0023:0077B1D3 xrCore.dll, xrDebug::backend(), x:\source_scs602\components\engine\xrcore\xrdebugnew.cpp, 278 0023:0077B381 xrCore.dll, xrDebug::fail(), x:\source_scs602\components\engine\xrcore\xrdebugnew.cpp, 366 0023:046E1113 xrGame.dll, CPhraseDialog::SayPhrase(), x:\source_scs602\components\engine\xrgame\phrasedialog.cpp, 146 0023:046E432A xrGame.dll, CPhraseDialogManager::SayPhrase(), x:\source_scs602\components\engine\xrgame\phrasedialogmanager.cpp, 77 0023:0490187A xrGame.dll, CUITalkWnd::SayPhrase(), x:\source_scs602\components\engine\xrgame\ui\uitalkwnd.cpp, 304 0023:04901D3F xrGame.dll, CUITalkWnd::UpdateQuestions(), x:\source_scs602\components\engine\xrgame\ui\uitalkwnd.cpp, 139 0023:04901EDA xrGame.dll, CUITalkWnd::Update(), x:\source_scs602\components\engine\xrgame\ui\uitalkwnd.cpp, 218 0023:04902317 xrGame.dll, CUITalkWnd::InitTalkDialog(), x:\source_scs602\components\engine\xrgame\ui\uitalkwnd.cpp, 83 0023:04902408 xrGame.dll, CUITalkWnd::Show(), x:\source_scs602\components\engine\xrgame\ui\uitalkwnd.cpp, 240 0023:048E81ED xrGame.dll, CDialogHolder::StartMenu(), x:\source_scs602\components\engine\xrgame\uidialogholder.cpp, 77 0023:048E82E8 xrGame.dll, CDialogHolder::StartStopMenu(), x:\source_scs602\components\engine\xrgame\uidialogholder.cpp, 224 0023:04960A28 xrGame.dll, CUIGameSP::StartTalk(), x:\source_scs602\components\engine\xrgame\uigamesp.cpp, 157 0023:046A956F xrGame.dll, CActor::RunTalkDialog(), x:\source_scs602\components\engine\xrgame\actor_communication.cpp, 210 0023:046A97B8 xrGame.dll, CActor::TryToTalk(), x:\source_scs602\components\engine\xrgame\actor_communication.cpp, 194 0023:046BCFA3 xrGame.dll, CActor::ActorUse(), x:\source_scs602\components\engine\xrgame\actorinput.cpp, 402 0023:046BD47C xrGame.dll, CActor::IR_OnKeyboardPress(), x:\source_scs602\components\engine\xrgame\actorinput.cpp, 144 0023:0468189B xrGame.dll, CLevel::IR_OnKeyboardPress(), x:\source_scs602\components\engine\xrgame\level_input.cpp, 416 0023:00411A02 xrEngine.exe, CInput::KeyUpdate(), x:\source_scs602\components\engine\xrengine\xr_input.cpp, 201 Движковый вылет bool CPhraseDialog::SayPhrase (DIALOG_SHARED_PTR& phrase_dialog, const shared_str& phrase_id) { THROW(phrase_dialog->IsInited()); phrase_dialog->m_SaidPhraseID = phrase_id; bool first_is_speaking = phrase_dialog->FirstIsSpeaking(); phrase_dialog->m_bFirstIsSpeaking = !phrase_dialog->m_bFirstIsSpeaking; const CGameObject* pSpeakerGO1 = smart_cast<const CGameObject*>(phrase_dialog->FirstSpeaker()); VERIFY(pSpeakerGO1); const CGameObject* pSpeakerGO2 = smart_cast<const CGameObject*>(phrase_dialog->SecondSpeaker()); VERIFY(pSpeakerGO2); if(!first_is_speaking) std::swap(pSpeakerGO1, pSpeakerGO2); CPhraseGraph::CVertex* phrase_vertex = phrase_dialog->data()->m_PhraseGraph.vertex(phrase_dialog->m_SaidPhraseID); THROW(phrase_vertex); CPhrase* last_phrase = phrase_vertex->data(); //вызвать скриптовую присоединенную функцию //активируется после сказанной фразы //первый параметр - тот кто говорит фразу, второй - тот кто слушает last_phrase->GetScriptHelper()->Action(pSpeakerGO1, pSpeakerGO2, *phrase_dialog->m_DialogId, phrase_id.c_str()); //больше нет фраз, чтоб говорить phrase_dialog->m_PhraseVector.clear(); if(phrase_vertex->edges().empty()) { phrase_dialog->m_bFinished = true; } else { //обновить список фраз, которые сейчас сможет говорить собеседник for(xr_vector<CPhraseGraph::CEdge>::const_iterator it = phrase_vertex->edges().begin(); it != phrase_vertex->edges().end(); it++) { const CPhraseGraph::CEdge& edge = *it; CPhraseGraph::CVertex* next_phrase_vertex = phrase_dialog->data()->m_PhraseGraph.vertex(edge.vertex_id()); THROW (next_phrase_vertex); shared_str next_phrase_id = next_phrase_vertex->vertex_id(); if(next_phrase_vertex->data()->GetScriptHelper()->Precondition(pSpeakerGO2, pSpeakerGO1, *phrase_dialog->m_DialogId, phrase_id.c_str(), next_phrase_id.c_str())) { phrase_dialog->m_PhraseVector.push_back(next_phrase_vertex->data()); #ifdef DEBUG if(psAI_Flags.test(aiDialogs)) { LPCSTR phrase_text = next_phrase_vertex->data()->GetText(); shared_str id = next_phrase_vertex->data()->GetID(); Msg("----added phrase text [%s] phrase_id=[%s] id=[%s] to dialog [%s]", phrase_text, phrase_id, id, phrase_dialog->m_DialogId.c_str()); } #endif } } R_ASSERT2 ( !phrase_dialog->m_PhraseVector.empty(), make_string( "No available phrase to say, dialog[%s]", *phrase_dialog->m_DialogId ) ); //упорядочить списко по убыванию благосклонности std::sort(phrase_dialog->m_PhraseVector.begin(), phrase_dialog->m_PhraseVector.end(), PhraseGoodwillPred); } //сообщить CDialogManager, что сказана фраза //и ожидается ответ if(first_is_speaking) phrase_dialog->SecondSpeaker()->ReceivePhrase(phrase_dialog); else phrase_dialog->FirstSpeaker()->ReceivePhrase(phrase_dialog); return phrase_dialog?!phrase_dialog->m_bFinished:true; } Ну, и дебильный вопрос: нафига здесь в движке ассерт? У меня за 10 лет, только на аптечках и вылетало. Сообщение отредактировал Diesel - 09.08.2020, 02:49 |
 
|
|
07.09.2020, 16:02
Сообщение
#251
|
|
Продвинутый геймер Репутация: 51 Группа: Участник Сообщений: 489 Награды: 3 Регистрация: 12.11.2012 |
Недавно возобновил изучение луа. Вот вроде бы проще питона, но как-то труднее его изучить. Может из-за того, что желание изучать меньше. В общем пытаюсь хоть что-то сделать в скриптах. Максимум удалось вывести сообщение в консоль. При изучении нужно знать две вещи: сам луа и собственно функции движка (в блендере это называется API, наверное в X-Ray это тоже API в виде lua функций).
С первым вроде бы понятно, информацию найти можно, а вот со вторым труднее. Читал на АМК посты по функциям и ничего не понятно. В общем вопросы (эти вопросы по ТЧ скриптам): как вообще можно встроить свои собственные скрипты в сталкер? Я пока знаю, что можно в диалогах прописать вызов скрипта и функции. А какие ещё способы есть? И как сделать редактор погоды в игре? Чтобы нажать клавишу, после чего появятся интерфейс с крутилками (которые управляются клавиатурой), который будет в углу и не будет загораживать обзор и при появлении этих крутилок можно спокойно перемещаться по локации (то есть движение мыши не блокируется, как это происходит при открытии инвентаря). И как сделать печать изменённых параметров погоды на экран (чтобы можно было сделать скрин параметров, а потом переписать их в конфиг)? -------------------- |
 
|
|
07.09.2020, 21:20
Сообщение
#252
|
|
Игровой Бог Репутация: 648 Группа: Участник Сообщений: 5354 Награды: 9 Регистрация: 24.09.2010 |
При изучении нужно знать две вещи: сам луа и собственно функции движка (в блендере это называется API, наверное в X-Ray это тоже API в виде lua функций). Луа в сталкере это по сути интерфейс, осуществляющий доступ к внутридвижковым объектам. Этакая надстройка на логикой внутри движка. как вообще можно встроить свои собственные скрипты в сталкер? Я пока знаю, что можно в диалогах прописать вызов скрипта и функции. А какие ещё способы есть? Можно просто вызвать любую функцию в скрипте, тогда он инициализируется. Поскольку, почти все начинают работать с конкретными объектами и чаще всего с актором, свои скрипты инициализируют из bind_stalker.script. И как сделать редактор погоды в игре? В ТЧ без правок движка никак. Исходя из первой моей цитаты, тебе потребуется написать экспорт движковых функций в Lua, после чего написать на основе оконной системы сталкера весь интерфейс. Задача весьма нетривиальная и не на пару часов. Сообщение отредактировал RayTwitty - 07.09.2020, 21:22 -------------------- |
 
|
|
08.09.2020, 17:44
Сообщение
#253
|
|
Продвинутый геймер Репутация: 51 Группа: Участник Сообщений: 489 Награды: 3 Регистрация: 12.11.2012 |
Можно просто вызвать любую функцию в скрипте, тогда он инициализируется. Поскольку, почти все начинают работать с конкретными объектами и чаще всего с актором, свои скрипты инициализируют из bind_stalker.script. а вообще, какой принцип работы скриптов в сталкере? Вот в blender game engine есть такое понятие, как такт, который длится 1/60 секунд. Во время этого такта выполняются действия. А в сталкере как всё работает? Например, как работает bind_stalker? В этом скрипте каждый кадр выполняется определённая функция? Или данный скрипт выполняется один раз за весь сеанс игры? И вообще где выполняется основная работа скриптовой системы? Вот к примеру скрипт из диалога выполнится только один раз. А какие скрипты непрерывно работают в игре и обрабатывают события? -------------------- |
 
|
|
08.09.2020, 21:35
Сообщение
#254
|
|
Почти Мастер Репутация: 111 Группа: Участник Сообщений: 1158 Награды: 3 Регистрация: 07.08.2015 |
Pavel_Blend, движок заранее заготовленные внедряет свои щупальца в скрипты. И ждёт их изменений, согласно обновлений в движке.
В движке создаются скрипты, как основа, для луа. Каждая функция луа, заранее прописана в движок. Если и не прописана, то предок этой функции всё равно в движке есть. В поиск визуалки забей .def и увидишь сколько их там. Сообщение отредактировал Diesel - 08.09.2020, 21:56 |
 
|
|
08.09.2020, 23:06
Сообщение
#255
|
|
Игровой Бог Репутация: 648 Группа: Участник Сообщений: 5354 Награды: 9 Регистрация: 24.09.2010 |
В этом скрипте каждый кадр выполняется определённая функция? Нет, в движке есть глобальный шедулер (апдейтер), из которого уже апдейтятся все онлайновые объекты (он в свою очередь вроде бы как раз из рендера должен вызываться, но я уже не помню). Покадрового апдейта в скриптах нет, у актора вроде бы интервал каждые 20-40 мс, он динамичен, для этого есть переменная delta в аргументе. У других объектов интервал в целях оптимизации может быть больше. Или данный скрипт выполняется один раз за весь сеанс игры? Код который ничем не обернут (не в функции, не в таблице и т.д.), вызывается при инициализации скрипта. Сам скрипт может инициализироваться только при его вызове, и это не гарантированно при старте игры. бинд_сталкер например инитится при появлении онлайнового актора, если конечно до этого момента еще кто-нибудь в этот скрипт не полезет за чем нибудь. Проще говоря, скрипты инициализируются по мере надобности. Плюс те же функции в биндерах, вызываются при определенных события. Например net_spawn при появлении актора на уровне, update - периодический апдейт (см. выше) и т.д. А какие скрипты непрерывно работают в игре и обрабатывают события? Ну кроме апдейта объектов и некоторых апдейтов в UI-интерфейсах таких нет. -------------------- |
 
|
|
10.09.2020, 12:23
Сообщение
#256
|
|
Продвинутый геймер Репутация: 51 Группа: Участник Сообщений: 489 Награды: 3 Регистрация: 12.11.2012 |
А с помощью скриптов возможно сделать такую вещь:
добавить отметки в пда на все динамические объекты. На сталкеров, на мутантов, тайники, физические объекты, лампочки, бочки, аномалии, еду, патроны, оружие. В общем на всё. И сделать так, чтобы при убийстве сталкера, в пда была метка его трупа. Только метка меняла цвет на серый. Была метка бандита, к примеру, красной, а при убийстве стала серой. И чтобы можно было скрывать метки по типу: аномалии, тайники, трупы, физ. объекты и т. д. И как можно полностью отключить респавн? Чтобы новые мутанты и сталкеры не появлялись? -------------------- |
 
|
|
10.09.2020, 21:31
Сообщение
#257
|
|
Опытный Геймер Репутация: 50 Группа: Участник Сообщений: 157 Награды: 2 Регистрация: 20.03.2014 |
И как можно полностью отключить респавн? Чтобы новые мутанты и сталкеры не появлялись? Попробуй в se_respawn.script заремить строку self:spawn(), а для отметок всего использую такое: ... CODE
|
 
|
|
12.09.2020, 23:30
Сообщение
#258
|
|
Игровой Бог Репутация: 648 Группа: Участник Сообщений: 5354 Награды: 9 Регистрация: 24.09.2010 |
А с помощью скриптов возможно сделать такую вещь: добавить отметки в пда на все динамические объекты. На сталкеров, на мутантов, тайники, физические объекты, лампочки, бочки, аномалии, еду, патроны, оружие. В общем на всё. Можно. Перебираешь все айдишники (1..65536, 0 - актор, его пропускаем) объектов в игре через alife():object(id), или если нужно только онлайновых то level.object_by_id(id). Добавляем метку через level.map_add_object_spot. И сделать так, чтобы при убийстве сталкера, в пда была метка его трупа. Только метка меняла цвет на серый. Была метка бандита, к примеру, красной, а при убийстве стала серой. Так это штатный механизм ПДА. Надо только тег level_spot/mini_spot в xml конфиге проверить/сделать. И чтобы можно было скрывать метки по типу: аномалии, тайники, трупы, физ. объекты и т. д. Для этого нужно написать UI, в котором добавлять/удалять метки по типу объекта. Скрывать нельзя, только если экспортировать из движка получение CUIStatic метки. В ТЧ без правок движка никак. Исходя из первой моей цитаты, тебе потребуется написать экспорт движковых функций в Lua, после чего написать на основе оконной системы сталкера весь интерфейс. Задача весьма нетривиальная и не на пару часов. Вот кстати чувак сделал консольные команды, к которым можно привязаться в интерфейсе https://www.gameru.net/forum/index.php?s=&a...t&p=1680713 Правда команд мало, и вообще это нужно было бы сделать через экспорт методов, но уж как есть. -------------------- |
 
|
|
13.09.2020, 13:01
Сообщение
#259
|
|
Продвинутый геймер Репутация: 51 Группа: Участник Сообщений: 489 Награды: 3 Регистрация: 12.11.2012 |
RayTwitty, попробовал редактор погоды. Трудновато редактировать. Хотелось бы иметь ползунки, чтобы плавно менять цвета. Ну или чтобы были горячие клавиши. Например, стрелки (вниз-вверх - листать параметры, влево-вправо - менять значения параметров). И ещё трудно угадать цвет солнца. Всё таки без игрового редактора удобнее тем, что можно загрузить в фотошоп текстуру неба и пипеткой скопировать цвет солнца. А потом пропорционально его увеличить или уменьшить.
А что ещё интересного можно сделать с помощью скриптов, кроме проставления меток? И вопрос: я проставил метки на всех сталкеров и удалил респавн. Зачистил локации от врагов, но не от всех. Остались монолитовцы, к примеру. Они видны на карте, но их там нет. И монстры. Монолитовцы в припяти возле гаражей у костра. Они не спавнятся. Не выполнено определённое условие для их спавна. В userdata у них прописано это: CODE
Как заспавнить с помощью скриптов объекты, которые уже есть, но не заспавнены (как монолитовцы). -------------------- |
 
|
|
30.09.2020, 17:06
Сообщение
#260
|
|
Опытный Геймер Репутация: 3 Группа: Участник Сообщений: 150 Награды: 3 Регистрация: 16.02.2014 |
Цитата А что ещё интересного можно сделать с помощью скриптов, кроме проставления меток? Ну так весь сюжет в общем-то скриптами строится. Вся логика объектов в конечном счете разворачивается в скрипты(xr_logic.script и все схемы поведения), все гулаги и их работы(xr_gulag.script). Спавн объектов, всякие UI-окна с различным функционалом. |
 
|
|
11.12.2020, 02:18
Сообщение
#261
|
|
Игровой Бог Репутация: 648 Группа: Участник Сообщений: 5354 Награды: 9 Регистрация: 24.09.2010 |
Наткнулся на интересный прикол с вещественным типом в Lua. Есть два листинга:
1) Здесь к одному числу прибавляется другое и в результате получается 0.75. После чего я выполняю сравнение с константой 0.75, которое разумеется проходит (YES). Код local value = 0.25 value = value + 0.5 print(value) --> 0.75 if value <= 0.75 then print("YES") else print("NO") end 2) По сути тоже самое, только довожу число до 0.75 за несколько шагов. Весь цимес заключается в том, что сравнение с константой 0.75 не проходит (NO)! Код local value = 0.25 for i = 1, 10 do value = value + 0.05 end print(value) --> 0.75 if value <= 0.75 then print("YES") else print("NO") end Если в Си у меня бы вопросов не возникло, то тут получается довольно неожиданно (всегда думал, что Lua пытается автоматом привести точность, что видно в первом листинге). В игре из-за этого не проходит сравнение по достижению числа верхней границы (меняю прозрачность и она не может дойти до 100%). Я так понимаю, это особенности внутренних расчетов Lua и на каком-то этапе там все-таки записывается в конец числа некий мусор? Получается, сравнивать надо с эпсилоном (+0.001 например) или вручную обрезать число до сотых? P.S. опытным путем выяснил, что сравнение перестает работать уже на втором шаге: Код local value = 0.7 value = value + 0.05 print(value) --> 0.75 if value <= 0.75 then print("YES") else print("NO") end --> YES Код local value = 0.65 value = value + 0.05 value = value + 0.05 print(value) --> 0.75 if value <= 0.75 then print("YES") else print("NO") end --> NO P.S2. соорудил такую дичь Код tonumber(tostring(value)) <= 0.75 работает отлично в обоих случаях. P.S3. оказывается в Питоне есть целый класс для таких нужд: поэтому функция Код function normalize_decimal(n) return tonumber(tostring(n)) end уже не так сильно похожа на дичь... Возможно в питонском классе внутри происходит тоже самое. Сообщение отредактировал RayTwitty - 11.12.2020, 03:14 -------------------- |
 
|
|
Текстовая версия | Сейчас: 26.04.2024, 17:14 |