Перейти к контенту

Рекомендуемые сообщения

Тема для обсуждения скриптов всего и всех в серии игр STALKER.


Задавая вопрос (!):
1. Внимательно изучите суть вопроса. Вопрос должен соответствовать выбранной Вами темы. Это поможет сохранить порядок и читабельность темы, а также облегчит поиск и понимание сего;
2. Изучите то, что уже есть в теме (пролистайте "руками", воспользуйтесь поиском на форуме);
3. Изучите информацию которая может вам помочь:

 
 

Stalkerin. Там есть много хороших статей касательно данной темы.
Уроки по модостроению. Есть рабочие примеры готовых скриптов различного назначения.

 

Справочное руководство по языку Lua 5.1
https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual/ru
Справочник по функциям и классам. Собрано много информации по функциям и классам, не всем, но по основные сведения предоставлены.

4. Дабы не превращать обсуждение в "кашу" разной информативной направленности, задавайте несколько вопросов по порядку (в разных постах) после того, как получите ответ на предыдущий вопрос;
5. "Спасибо" и тому подобное - будьте так любезны в ПМ. Если не любите писать в ПМ, в конце вопроса напишите фразу: "Заранее спасибо!" - или что-то в этом духе;
6. ПОЖАЛУЙСТА! Указывайте, для какой игры Вам необходима информация (ТЧ, ЧН, ЗП), если стоит мод - укажите название мода;
7. Если Вы что-то сделали и результат не такой, какой Вами задумывался, то, пожалуйста, приводите коды которые Вы изменяли/писали целиком! Это поможет другим правильно ответить на Ваш вопрос, а также оградит Вас от лишней писанины.
8. Оформляйте сообщение. Пользуйтесь тегами для того, чтобы отделить код от текста. Пишите грамотно - ПОЛЬЗУЙТЕСЬ ЗНАКАМИ ПРЕПИНАНИЯ.
9. И помните: «Правильно заданный вопрос – половина ответа».

 

Какие вопросы следует задавать, а какие нет...

 

Задавайте вопросы, которые касаются непосредственно скриптов и их работы, т.е. Вы что-то делаете, а у Вас что-то не получается, при этом у Вас на руках должен быть хотя бы какой-то код, свидетельствующий о Вашей причастности к вопросу.

 

Вопросы которые будут удалятся, следовательно их задавать не нужно:
-- Где находится та или иная функция?
Для ответа используем поиск по словам среди файлов оригинальной игры или мода, если объект поиска относится к нему, при помощью программы, которая Вам наиболее симпатизирует;
-- Как сделать что-то/то-то?
С подобными вопросами, либо в "ковырялки", где Вам вероятнее всего так же не ответят, либо выдвигаем мысли, подкреплённые теорией, практикой (идеальный вариант) и здравым рассудком;
-- Вопросы со смыслом: "сделайте", "совместите" и подобными глаголами повелительного наклонения.
-- К тому же удалению будут подвергаться вопросы, в которых масштабно не используются теги, для отделения кода и цитат от основного текста, а также не вписан в спойлер код размером превышающие семь строк.
Ответ на возможно возникший вопрос: В какую тему можно обратиться по поводу логики и спавна объектов?
В тему "ковырялок" соответствующей версии игры, для которой Вы задаёте вопрос.

И последнее: очень рекомендовано к прочтению Правила форума
 


  • Спасибо 1
  • Полезно 2
Ссылка на комментарий

Здравствуйте! Сегодня решил попробовать свои силы в создании модов для Сталкера, так как это моя любимая игра. Когда-то раньше пробовал, но почему-то забросил...

Я в основном занимаюсь Web-программированием, а сегодня попробовал скрипты, минут за 20 сделал  такую штуку, как механизм событий и их обработчиков, это что-то вроде биндинга, но по-другому работает.

Принцип сейчас покажу в коде:
 


function handler()
    -- Тут всякий код
end
function handler2()
    -- Тут всякий код
end

setHander("test_action", handler)
setHander("test_action", handler2)

setAction("test_acton")
-- Будет выполнен код из функций handler() и hander2()

Такая штука будет очень полезна, когда нужно обработать какое-то событие в моде и вся эта система должна содержаться в порядке.
Вызывать события можно вообще любые:
setAction("bla-bla-bla"). Если нет обработчиков, то ничего не произойдёт, но ошибок не будет

Регистрировать обработчики можно в любом месте любого скрипта, будет работать.

Например при заходе на локацию вызывать событие on_location_zaton, тогда можно будет событие обрабатывать.

В общем система очень простая и полезная, можно много применений найти. Её можно использовать в любой версии Сталкера, так как она использует только возможности языка Lua

Также в приведённом коде есть ещё некоторые функции, они может и не самые полезные, но их тоже можно использовать.

Я хочу заделать что-то вроде прослойки между теми скриптовыми функциями, что сейчас есть и модами, чтобы облегчить использование некоторых возможностей.

 

Мог объяснить не очень понятно, просто спать уже хочу... Критикуйте) буду только рад

Как вам моя идея? Есть ли у неё перспективы?
Если есть предложения, чего бы ещё сделать, предлагайте)
 

 

 

--[[
MOD TOOLS 0.0.1
Инструменты для облегчения модификаций

Разработчик: Николай1
]]

-- Массив с обработчиками
hooks = {}

--[[
Вызов события. Вызов происходит корректно и не вызывает ошибок, даже если не было зарегистрировано
обработчиков для этого события. В таком случае функция возвращает false

action_name [String] - название события

Пример:
setAction("test_action")
]]
function setAction(action_name)
    if hooks[action_name] == nil then
        return false
    end
    
    for action,hook in pairs(hooks[action_name]) do
        hook()
    end
end

--[[
Добавление обработчика к событию.
Можно добавлять много обработчиков для одного события

action_name [String] - название события
handler [Callback] - функция-обаботчик

Пример:
function handler()
    -- Тут всякий код
end
function handler2()
    -- Тут всякий код
end

setHander("test_action", handler)
setHander("test_action", handler2)
]]
function setHandler(action_name, handler)
    if hooks[action_name] == nil then
        hooks[action_name] = {}
    end
    
    table.insert(hooks[action_name], handler)
end

--[[
Эта функция лишняя, её использовал для теста механизма событий
]]
function route()
    setAction("test")
end

-- Создать предмет под ногами игрока
-- [String] item - код предмета, например medkit
-- [Int] count - количиство предметов
function spawnNearActor(item, count)
    if count == nil then
        alife():create(item, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id())
    else
        for i = 1, count do
            alife():create(item, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id())
        end
    end
end

-- Создать предмет в инвентаре игрока
-- [String] item - код предмета, например medkit
function addToActorInventory(item, count)
    addToInventory(item, db.actor:id(), db.actor:position(), db.actor:game_vertex_id(), count);
end

-- Создать предмет в инвентаре
-- [String] item - код предмета, например medkit
-- [Int] character_id - ID персонажа, которому нужно создать предмет
-- [Vector] position - координаты добавления объекта
-- [Int] game_vertex_id - game_vertex_id для создания предмета
-- [Int] count - количиство предметов
function addToInventory(item, character_id, position, game_vertex_id, count)
    if count == nil or count == 1 then
        alife():create(item, position, 1, game_vertex_id, character_id)
    else
        for i = 1, count do
            alife():create(item, position, 1, game_vertex_id, character_id)
        end
    end
end

-- Сохранить значение переменной
-- [String] variable_name - название переменной
-- [Mixed] value - значение переменной
function setVar(variable_name, value)
    xr_logic.pstor_store(db.actor, variable_name, value)
end

-- Получить значение переменной
-- [String] variable_name - название переменной
-- [Mixed] default_value - значение по-умолчанию, значение переменной, которое будет возвращено,
-- если переменной не существует
function getVar(variable_name, default_value)
    return xr_logic.pstor_retrieve(db.actor, variable_name, default_value)
end

--[[
Действия с переменной с помощью одной функции

variable_name [String] - название переменной
value [Mixed] - значение переменной (или значение по-умолчанию)
is_set [Bool] - флаг создания переменной. Если стоит 1 - будет использовано действие
"Сохранить значение переменной"

Примеры использования:

Получение значения переменной:
var("test_var", false) -- Второй аргумент - значение по-умолчанию
var("test_var", false, false) -- Третив аргумент - отключение флага установки переменной

Установка значения переменной
var("test_var", "test_value", true)
]]
function var(variable_name, value, is_set)
    -- Если is_set не задан, ставим false
    if (is_set == nil) then
        is_set = false
    end

    if (is_set == false) then
        -- Если is_set равен 0 или false, то получаем значение переменной
        return _getVar(variable_name, value)
    else
        -- Если стоит флаг создания, то устанавливаем значение переменной
        return _setVar(variable_name, value)
    end
end

--[[
Выполнить какую-либо функцию заданное число раз
]]
--[[
function runFunction(func, count, ...)
    if count == nil or count = 1 then
        func(arg)
    else
        for i = 1, count do
            func(arg)
        end
    end
end
]]

 

 

Добавлено Dennis_Chikin,

Пока будет здесь,ибо не очень понятны перспективы отдельной темы.

  • Нравится 1
Ссылка на комментарий

Как вам моя идея? Есть ли у неё перспективы?

Такое уже есть, как минимум в двух экземплярах - это я еще не особо осведомлённый в делах скриптового моддинга.

Но на еще один велосипед посмотреть можно, сарказма тут нет, ибо так оно и есть.

 

1. Убило название функции для срабатывания события - setAction. Установить действие? Иногда называют такие методы fire или fireEvent, но не setAction.

2. Нет передачи аргументов в хендлеры.

3. Нет прерывания срабатывания событий (в цикле).

4. Симпатичное комментирование кода, конкретно описание аргументов + тип.

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий

@Николай1, начинание благое, жаль только припозднилось года этак на 2-3.
Но если удастся предложить что-то действительно новое и полезное - всем будет только хорошо.

Для начала рекомендую изучить аналогичные решения, уже предложенные другими авторами, коих даже больше, чем указал @Desertir.

Можно сделать общий поиск по форуму слова «event». Или поискать отдельные варианты: "Песочница" от @xStream, слот-сигнальная система от @Malandrinus, были ещё частные реализации от @Artos и, кажется, @Monnoroch и @Viнt@rь.

Изменено пользователем Kirgudu
Ссылка на комментарий

Кто объяснит, как в цикле for отловить последнюю итерацию?

 

function take_money(pid)


local cond = 5000
local col = 0
local count = db.actor:object_count() - 1
if has_alife_info("ui_car_body") then
for i=0, count do
local item = db.actor:object(i)
if item:section() == "pack_money" then
local sobj = alife():object(item:id())
if sobj then
col = col + 1
db.actor:give_money(cond)
alife():release(sobj,true)
end
end
end
end
end

 

 

Нужно вывести итоговое значение переменной col. Пробовал проверку сделать

 

if i=count then

.

.

.

end

 

так вылетает.

Сталкер - наше всё!

Ссылка на комментарий

@AndrewMor, как минимум "if i==count then", чтобы не вылетало.

А во-вторых, после окончания действия цикла (перед закрывающим функцию "end") в переменной col как раз и будет нужное значение, можно делать с ним что угодно.

  • Спасибо 1
Ссылка на комментарий

 

 

как минимум "if i==count then", чтобы не вылетало.

Блин, ну конечно. Привычка, что "=" - это сравнение. Спасибо.


Kirgudu, переписал функцию так:

function take_money(pid)
local cond = 5000
local col = 0
local count = db.actor:object_count() - 1
if has_alife_info("ui_car_body") then
for i=0, count do
local item = db.actor:object(i)
if item:section() == "pack_money" then
local sobj = alife():object(item:id())
if sobj then
col = col + 1
alife():release(sobj,true)
end
end
if i == count and col ~= 0 then
cond = cond * col
db.actor:give_money(cond)
local text = "Найдено денег - "..cond
news_manager.send_tip(db.actor, cond, nil, nil, 30000)
end
end
end
end

 

но сообщение выводится не один раз, как задумывал, а столько раз, сколько нужного предмета попало в рюкзак. А если перед закрывающим функцию end вывод вписать, то вообще ничего не выводится. Почему?

Сталкер - наше всё!

Ссылка на комментарий

@Kirgudu, А всё равно выводится не одно сообщение, а несколько. Я так понимаю, что биндер отслеживает получение первого предмета и идет подсчет в цикле. Выводится сообщение. Далее отслеживается получение предмета номер 2, опять цикл и вывод сообщения. Ну и так далее. А как бы мне сделать, чтобы выводилось только одно, итоговое сообщение?

Сталкер - наше всё!

Ссылка на комментарий

@Kirgudu, при взятии денег из схрона прибавлять их к общим деньгам ГГ, взятые деньги из рюкзака долой, а потом выводить сообщение о полученной сумме целиком. Эта моя функция вызывается из биндера on_take_item.

Сталкер - наше всё!

Ссылка на комментарий

@AndrewMor, как-то так лучше сделать:

function take_money(obj)
if obj:section() == 'money_500' then
alife():release(alife:object(obj.fov and obj:id() or obj.id))
db.actor:give_money(500)
news_manager.send_tip(db.actor, "Получено 500 рублей.", nil, nil, 10000)
end
end

При желании рандомизировать, циклы тут точно не нужны, лишняя нагрузка.

  • Спасибо 1
  • Согласен 1
Ссылка на комментарий

"при взятии денег из схрона прибавлять их к общим деньгам ГГ"

 

Если деньги - это предмет, то вешаем вызов на on_take_item_from_box().

Ссылка на комментарий

@Dennis_Chikin, лучше на обретение. Какая разница откуда ты их получил если алгоритм для всего один и тот же? Будь-то труп, тайник или любой другой способ.

  • Согласен 1
Ссылка на комментарий

Ребята, помощь нужна.

Мне нужно заспавнить physic_destroyable_object. Через all.spawn всё красиво, но есть одно "НО" - не работает функция [spawner]. Может быть через скрипт как-то можно его спавнить, а то я что-то не догоняю... 

PS Всем мир!

Пишу мод с неповторимым сюжетом.

Нужны "модельеры"

Заинтересованным писать в ЛС

J.A.A..gif

Ссылка на комментарий

 

 

Мне нужно заспавнить physic_destroyable_object. Через all.spawn всё красиво, но есть одно "НО" - не работает функция [spawner].

Насколько я помню, секция spawner работает только для НПС и монстров.

Сталкер - наше всё!

Ссылка на комментарий

Всем привет, опять я со своей проблемой по деньгам.

В bind.stalker.script в биндере take_item_from_box пишу: money.take_money(item)

 

Мой скрипт:

function take_money(pid)


db.actor:iterate_inventory(is_item, db.actor)
end

function is_item(npc, item)
local cond = math.ceil(math.random(28,70)*100)
local section = item:section()
if item:section() == "pack_money" then
local sobj = alife():object(item:id())
if sobj then
alife():release(sobj,true)
db.actor:give_money(cond)
local text = "Найдено денег - "..cond.."\\nВсего денег - "..db.actor:money()
news_manager.send_tip(db.actor, text, nil, nil, 30000)
end
end
end

 

 

Или так:

function take_money(pid)
local cond = math.ceil(math.random(28,70)*100)
local count = db.actor:object_count() - 1
for i=0, count do
local item = db.actor:object(i)
if item:section() == "pack_money" then
local sobj = alife():object(item:id())
if sobj then
db.actor:give_money(cond)
local text = "Найдено денег - "..cond.."\\nВсего денег - "..db.actor:money()
news_manager.send_tip(db.actor, text, nil, nil, 30000)
alife():release(sobj,true)
end
end
end
end

 

 

Результат один и тот же: первый предмет, берущийся из ящика, не обрабатывается. Остается в рюкзаке. Соответственно, если в ящике 8 предметов, то обрабатываются только 7, один остается в инвентаре. Почему?

Сталкер - наше всё!

Ссылка на комментарий

@AndrewMor, зачем ты спрашиваешь? Я тебе сказал как нужно сделать, но ты упорно продолжаешь делать по своему. Ты понимаешь как работает коллбек? В общем, как говорится, "если не можешь - значит не нужно"(с).

  • Согласен 1
Ссылка на комментарий

@Карлан, Я делал, как ты посоветовал, и все равно не работает.

 

PS: ты бы лучше объяснил, что где не так. В общем, спасибо за "помощь".


Карлан, по твоему совету при обыске трупа вылет:

Expression : fatal error
Function : CScriptEngine::lua_error
File : E:\stalker\sources\trunk\xr_3da\xrGame\script_engine.cpp
Line : 73
Description :
Arguments : LUA error: ...blishing\s.t.a.l.k.e.r\gamedata\scripts\money.script:39: attempt to index global 'alife' (a function value)

Сталкер - наше всё!

Ссылка на комментарий

function take_money(pid)

db.actor:iterate_inventory(is_item, db.actor)

end

 

Жуть какая...

Собственно, то, что получаем - это и есть искомый предмет. Все. Получаем id, получаем объект, удаляем.

Больше ничего не надо. Ни каких итераций.

 

Единственный момент - после того, как удалили, ни каких действий в :on_что-попало() быть не должно. Собственно, я в статье про использование именно по-этому и сделал выбор нужной функции по таблице. Ну и продолжение трэда можно в курилке посмотреть.

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   1 пользователь

×
×
  • Создать...