Svoboда 3 Опубликовано 23 Апреля 2009 Поделиться Опубликовано 23 Апреля 2009 Тема для обсуждения скриптов всего и всех в серии игр STALKER. Задавая вопрос (!): 1. Внимательно изучите суть вопроса. Вопрос должен соответствовать выбранной Вами темы. Это поможет сохранить порядок и читабельность темы, а также облегчит поиск и понимание сего; 2. Изучите то, что уже есть в теме (пролистайте "руками", воспользуйтесь поиском на форуме); 3. Изучите информацию которая может вам помочь: Stalkerin. Там есть много хороших статей касательно данной темы.Уроки по модостроению. Есть рабочие примеры готовых скриптов различного назначения. Справочное руководство по языку Lua 5.1https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual/ruСправочник по функциям и классам. Собрано много информации по функциям и классам, не всем, но по основные сведения предоставлены. Логика со вступлением и четырьмя частями: ВступлениеЧасть перваяЧасть втораяЧасть третьяЧасть четвертая. Smart_terrain (в простонароде - гулаг)Интересный способ настроики логики для гулаговСкриптовая часть игровой логики 4. Дабы не превращать обсуждение в "кашу" разной информативной направленности, задавайте несколько вопросов по порядку (в разных постах) после того, как получите ответ на предыдущий вопрос; 5. "Спасибо" и тому подобное - будьте так любезны в ПМ. Если не любите писать в ПМ, в конце вопроса напишите фразу: "Заранее спасибо!" - или что-то в этом духе; 6. ПОЖАЛУЙСТА! Указывайте, для какой игры Вам необходима информация (ТЧ, ЧН, ЗП), если стоит мод - укажите название мода; 7. Если Вы что-то сделали и результат не такой, какой Вами задумывался, то, пожалуйста, приводите коды которые Вы изменяли/писали целиком! Это поможет другим правильно ответить на Ваш вопрос, а также оградит Вас от лишней писанины. 8. Оформляйте сообщение. Пользуйтесь тегами для того, чтобы отделить код от текста. Пишите грамотно - ПОЛЬЗУЙТЕСЬ ЗНАКАМИ ПРЕПИНАНИЯ. 9. И помните: «Правильно заданный вопрос – половина ответа». Какие вопросы следует задавать, а какие нет... Задавайте вопросы, которые касаются непосредственно скриптов и их работы, т.е. Вы что-то делаете, а у Вас что-то не получается, при этом у Вас на руках должен быть хотя бы какой-то код, свидетельствующий о Вашей причастности к вопросу. Вопросы которые будут удалятся, следовательно их задавать не нужно:-- Где находится та или иная функция? Для ответа используем поиск по словам среди файлов оригинальной игры или мода, если объект поиска относится к нему, при помощью программы, которая Вам наиболее симпатизирует;-- Как сделать что-то/то-то? С подобными вопросами, либо в "ковырялки", где Вам вероятнее всего так же не ответят, либо выдвигаем мысли, подкреплённые теорией, практикой (идеальный вариант) и здравым рассудком;-- Вопросы со смыслом: "сделайте", "совместите" и подобными глаголами повелительного наклонения.-- К тому же удалению будут подвергаться вопросы, в которых масштабно не используются теги, для отделения кода и цитат от основного текста, а также не вписан в спойлер код размером превышающие семь строк.Ответ на возможно возникший вопрос: В какую тему можно обратиться по поводу логики и спавна объектов? В тему "ковырялок" соответствующей версии игры, для которой Вы задаёте вопрос. И последнее: очень рекомендовано к прочтению Правила форума 1 2 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/
Николай1 1 Опубликовано 11 Апреля 2015 Поделиться Опубликовано 11 Апреля 2015 Здравствуйте! Сегодня решил попробовать свои силы в создании модов для Сталкера, так как это моя любимая игра. Когда-то раньше пробовал, но почему-то забросил...Я в основном занимаюсь 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 ]] 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-930321
Desertir 202 Опубликовано 13 Апреля 2015 Поделиться Опубликовано 13 Апреля 2015 Как вам моя идея? Есть ли у неё перспективы?Такое уже есть, как минимум в двух экземплярах - это я еще не особо осведомлённый в делах скриптового моддинга. Но на еще один велосипед посмотреть можно, сарказма тут нет, ибо так оно и есть. 1. Убило название функции для срабатывания события - setAction. Установить действие? Иногда называют такие методы fire или fireEvent, но не setAction. 2. Нет передачи аргументов в хендлеры. 3. Нет прерывания срабатывания событий (в цикле). 4. Симпатичное комментирование кода, конкретно описание аргументов + тип. Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-930619
Kirgudu 1 328 Опубликовано 13 Апреля 2015 Поделиться Опубликовано 13 Апреля 2015 (изменено) @Николай1, начинание благое, жаль только припозднилось года этак на 2-3.Но если удастся предложить что-то действительно новое и полезное - всем будет только хорошо. Для начала рекомендую изучить аналогичные решения, уже предложенные другими авторами, коих даже больше, чем указал @Desertir. Можно сделать общий поиск по форуму слова «event». Или поискать отдельные варианты: "Песочница" от @xStream, слот-сигнальная система от @Malandrinus, были ещё частные реализации от @Artos и, кажется, @Monnoroch и @Viнt@rь. Изменено 13 Апреля 2015 пользователем Kirgudu Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-930627
AndrewMor 533 Опубликовано 15 Апреля 2015 Поделиться Опубликовано 15 Апреля 2015 Кто объяснит, как в цикле for отловить последнюю итерацию? function take_money(pid) local cond = 5000local col = 0local count = db.actor:object_count() - 1if has_alife_info("ui_car_body") thenfor i=0, count dolocal item = db.actor:object(i)if item:section() == "pack_money" thenlocal sobj = alife():object(item:id())if sobj thencol = col + 1db.actor:give_money(cond)alife():release(sobj,true)endendendendend Нужно вывести итоговое значение переменной col. Пробовал проверку сделать if i=count then . . . end так вылетает. Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931055
Kirgudu 1 328 Опубликовано 15 Апреля 2015 Поделиться Опубликовано 15 Апреля 2015 @AndrewMor, как минимум "if i==count then", чтобы не вылетало. А во-вторых, после окончания действия цикла (перед закрывающим функцию "end") в переменной col как раз и будет нужное значение, можно делать с ним что угодно. 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931057
AndrewMor 533 Опубликовано 15 Апреля 2015 Поделиться Опубликовано 15 Апреля 2015 как минимум "if i==count then", чтобы не вылетало. Блин, ну конечно. Привычка, что "=" - это сравнение. Спасибо. Kirgudu, переписал функцию так: function take_money(pid)local cond = 5000local col = 0local count = db.actor:object_count() - 1if has_alife_info("ui_car_body") thenfor i=0, count dolocal item = db.actor:object(i)if item:section() == "pack_money" thenlocal sobj = alife():object(item:id())if sobj thencol = col + 1alife():release(sobj,true)endendif i == count and col ~= 0 thencond = cond * coldb.actor:give_money(cond)local text = "Найдено денег - "..condnews_manager.send_tip(db.actor, cond, nil, nil, 30000)endendendend но сообщение выводится не один раз, как задумывал, а столько раз, сколько нужного предмета попало в рюкзак. А если перед закрывающим функцию end вывод вписать, то вообще ничего не выводится. Почему? Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931059
Kirgudu 1 328 Опубликовано 15 Апреля 2015 Поделиться Опубликовано 15 Апреля 2015 Потому что переменая i существует только внутри цикла, а вне его равна nil. Оставь только проверку на col ~= 0. Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931068
AndrewMor 533 Опубликовано 15 Апреля 2015 Поделиться Опубликовано 15 Апреля 2015 @Kirgudu, А всё равно выводится не одно сообщение, а несколько. Я так понимаю, что биндер отслеживает получение первого предмета и идет подсчет в цикле. Выводится сообщение. Далее отслеживается получение предмета номер 2, опять цикл и вывод сообщения. Ну и так далее. А как бы мне сделать, чтобы выводилось только одно, итоговое сообщение? Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931073
Kirgudu 1 328 Опубликовано 15 Апреля 2015 Поделиться Опубликовано 15 Апреля 2015 @AndrewMor, ты б объяснил толком, что хочешь сделать. Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931078
AndrewMor 533 Опубликовано 15 Апреля 2015 Поделиться Опубликовано 15 Апреля 2015 @Kirgudu, при взятии денег из схрона прибавлять их к общим деньгам ГГ, взятые деньги из рюкзака долой, а потом выводить сообщение о полученной сумме целиком. Эта моя функция вызывается из биндера on_take_item. Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931082
Карлан 1 050 Опубликовано 15 Апреля 2015 Поделиться Опубликовано 15 Апреля 2015 @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 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931101
Dennis_Chikin 3 665 Опубликовано 15 Апреля 2015 Поделиться Опубликовано 15 Апреля 2015 "при взятии денег из схрона прибавлять их к общим деньгам ГГ" Если деньги - это предмет, то вешаем вызов на on_take_item_from_box(). Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931135
Карлан 1 050 Опубликовано 15 Апреля 2015 Поделиться Опубликовано 15 Апреля 2015 @Dennis_Chikin, лучше на обретение. Какая разница откуда ты их получил если алгоритм для всего один и тот же? Будь-то труп, тайник или любой другой способ. 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931139
J.A.A. 2 Опубликовано 16 Апреля 2015 Поделиться Опубликовано 16 Апреля 2015 Ребята, помощь нужна. Мне нужно заспавнить physic_destroyable_object. Через all.spawn всё красиво, но есть одно "НО" - не работает функция [spawner]. Может быть через скрипт как-то можно его спавнить, а то я что-то не догоняю... PS Всем мир! Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931259
AndrewMor 533 Опубликовано 16 Апреля 2015 Поделиться Опубликовано 16 Апреля 2015 Мне нужно заспавнить physic_destroyable_object. Через all.spawn всё красиво, но есть одно "НО" - не работает функция [spawner]. Насколько я помню, секция spawner работает только для НПС и монстров. Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931277
AndrewMor 533 Опубликовано 18 Апреля 2015 Поделиться Опубликовано 18 Апреля 2015 Всем привет, опять я со своей проблемой по деньгам. В bind.stalker.script в биндере take_item_from_box пишу: money.take_money(item) Мой скрипт: function take_money(pid) db.actor:iterate_inventory(is_item, db.actor)endfunction is_item(npc, item)local cond = math.ceil(math.random(28,70)*100)local section = item:section()if item:section() == "pack_money" thenlocal sobj = alife():object(item:id())if sobj thenalife():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)endendend Или так: function take_money(pid)local cond = math.ceil(math.random(28,70)*100)local count = db.actor:object_count() - 1for i=0, count dolocal item = db.actor:object(i)if item:section() == "pack_money" thenlocal sobj = alife():object(item:id())if sobj thendb.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)endendendend Результат один и тот же: первый предмет, берущийся из ящика, не обрабатывается. Остается в рюкзаке. Соответственно, если в ящике 8 предметов, то обрабатываются только 7, один остается в инвентаре. Почему? Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931718
Карлан 1 050 Опубликовано 18 Апреля 2015 Поделиться Опубликовано 18 Апреля 2015 @AndrewMor, зачем ты спрашиваешь? Я тебе сказал как нужно сделать, но ты упорно продолжаешь делать по своему. Ты понимаешь как работает коллбек? В общем, как говорится, "если не можешь - значит не нужно"(с). 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931725
AndrewMor 533 Опубликовано 18 Апреля 2015 Поделиться Опубликовано 18 Апреля 2015 @Карлан, Я делал, как ты посоветовал, и все равно не работает. PS: ты бы лучше объяснил, что где не так. В общем, спасибо за "помощь". Карлан, по твоему совету при обыске трупа вылет: Expression : fatal errorFunction : CScriptEngine::lua_errorFile : E:\stalker\sources\trunk\xr_3da\xrGame\script_engine.cppLine : 73Description : Arguments : LUA error: ...blishing\s.t.a.l.k.e.r\gamedata\scripts\money.script:39: attempt to index global 'alife' (a function value) Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931727
Карлан 1 050 Опубликовано 18 Апреля 2015 Поделиться Опубликовано 18 Апреля 2015 @AndrewMor, скобки добавить не додумался? Я же не точный код дал, а набросок. 1 Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931731
Dennis_Chikin 3 665 Опубликовано 18 Апреля 2015 Поделиться Опубликовано 18 Апреля 2015 function take_money(pid) db.actor:iterate_inventory(is_item, db.actor) end Жуть какая... Собственно, то, что получаем - это и есть искомый предмет. Все. Получаем id, получаем объект, удаляем. Больше ничего не надо. Ни каких итераций. Единственный момент - после того, как удалили, ни каких действий в :on_что-попало() быть не должно. Собственно, я в статье про использование именно по-этому и сделал выбор нужной функции по таблице. Ну и продолжение трэда можно в курилке посмотреть. Ссылка на комментарий https://www.amk-team.ru/forum/topic/6185-skriptovanie/page/309/#findComment-931747
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти