IPB

Помощь по разделу

Сайт S.T.A.L.K.E.R. Inside / [ЗП] Параметры командной строки / Распаковщик ресурсов

>

Скрипты

 
 Орион
сообщение 13.07.2009, 11:34
Сообщение #241


Навий черны у ношьти
***************

Группа: Забанен
Сообщений: 2210
Регистрация: 11.03.2009
Из: Лиманск
Пользователь №: 10251




FAQ

Lua в X-Ray

Список всех функций, переменных, классов и т.п. что используются в Сталкере находится по адресу:
Код
gamedata/scripts/lua_help.script

Для получения файла надо распаковать игру. Можно скачать, в принципе (IMG:style_emoticons/default/smile.gif) Тут =>>Ссылко<<=
Уроки

Пример создания непися скриптами ЛУА. Автор: меченый(стрелок)
Скриптинг на инсайде



Сообщение отредактировал RayTwitty - 09.06.2018, 20:23
Перейти в начало страницы
 
 
 
Ответов
 NanoBot-AMK
сообщение 21.11.2019, 19:34
Сообщение #242


Почти Игроман
*********

Группа: Участник
Сообщений: 683
Регистрация: 10.11.2015
Пользователь №: 22739



Кстати, функции типа object_binder.update(self, delta) можно спокойно исключить, это просто пустышки, которые ничего не делают, кроме времени(2-3 мксек). Исключения только для метода net_spawn, там это нужно.
Перейти в начало страницы
 
 
 Gaz24
сообщение 23.11.2019, 07:43
Сообщение #243


Почти Игрок
**

Группа: Участник
Сообщений: 17
Регистрация: 14.01.2013
Пользователь №: 15612



Хотел добавить свою аи-схему, которая запускается во время боя. Все подключил, добавил эвалуатор, работает. А вот экшен не работает от слова совсем. В чем могла быть ошибка?

Код
Код
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
Перейти в начало страницы
 
 
 abramcumner
сообщение 23.11.2019, 10:55
Сообщение #244


Босс
********************

Группа: Участник
Сообщений: 4327
Регистрация: 27.04.2011
Из: Россия
Пользователь №: 14366



Цитата(Gaz24 @ 23.11.2019, 07:39) *
Хотел добавить свою аи-схему, которая запускается во время боя. Все подключил, добавил эвалуатор, работает. А вот экшен не работает от слова совсем. В чем могла быть ошибка?

Он и не должен работать, ты же экшен никак в 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) и НПЦ запустит твой экшен.

Посмотри на аи-схемы из оригинала или из модов. Там есть оба пункта.
Перейти в начало страницы
 
 
 Gaz24
сообщение 23.11.2019, 11:54
Сообщение #245


Почти Игрок
**

Группа: Участник
Сообщений: 17
Регистрация: 14.01.2013
Пользователь №: 15612



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)
Перейти в начало страницы
 
 
 abramcumner
сообщение 23.11.2019, 13:16
Сообщение #246


Босс
********************

Группа: Участник
Сообщений: 4327
Регистрация: 27.04.2011
Из: Россия
Пользователь №: 14366



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
Перейти в начало страницы
 
 
 Gaz24
сообщение 23.11.2019, 14:04
Сообщение #247


Почти Игрок
**

Группа: Участник
Сообщений: 17
Регистрация: 14.01.2013
Пользователь №: 15612



abramcumner, заработало, спасибо. Правда с прекондишенами надо поиграться. А так, осознал.

Если ты говорил про эту статью, то я на нее очень сильно опирался, но из-за своего косяка вообще не понимал.

Сообщение отредактировал Gaz24 - 23.11.2019, 14:14
Перейти в начало страницы
 
 
 RayTwitty
сообщение 08.01.2020, 22:34
Сообщение #248


Босс
********************

Группа: Участник
Сообщений: 4202
Регистрация: 24.09.2010
Пользователь №: 14086



В дополнение к посту про class ini_file

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
vector<result> r_vector(string<section>, string<line>) - разбивает строку вида "param = number,number,number" и возвращает сформированный из этих компонентов вектор.
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")


З.Ы. Это перенос моего старого поста с другого форума. Пусть будет и здесь.
Перейти в начало страницы
 
 
 Diesel
сообщение 02.07.2020, 20:22
Сообщение #249


Почти Игроман
*********

Группа: Участник
Сообщений: 589
Регистрация: 07.08.2015
Пользователь №: 22230



Вопрос по скрипту ОГСМ 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
Перейти в начало страницы
 
 
 Diesel
сообщение 09.08.2020, 02:18
Сообщение #250


Почти Игроман
*********

Группа: Участник
Сообщений: 589
Регистрация: 07.08.2015
Пользователь №: 22230



Кто желает разобраться в хитросплетениях диалога. Вылет идёт когда раненому даю аптечку в ЧН (мод 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
Перейти в начало страницы
 
 
 
 

 
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 

Текстовая версия Сейчас: 14.08.2020, 14:47