GAMEINATOR forums _ Мастерская: создание модов для S.T.A.L.K.E.R. _ Скрипты
Автор: vintprog 05.07.2009, 16:03
Какие возможности у скрипта LUA?
Можно например реализовать: Гравитационое оружия, Литания на самолетах, Огнемет, прикрепление приклада и.т.д?
Автор: Shadow. 05.07.2009, 16:10
Хотелось бы научиться данному языку хоть немного.Подскажите кто-нибудь нормальный учебник по этому делу.
Автор: Stalbar 05.07.2009, 16:13
Цитата(vintprog @ 05.07.2009, 20:03)
Какие возможности у скрипта LUA?
Можно например реализовать: Гравитационое оружия, Литания на самолетах, Огнемет, прикрепление приклада и.т.д?
Вы это хотите "чисто на скриптах" изобразить??
Цитата(Shadow. @ 05.07.2009, 20:10)
Хотелось бы научиться данному языку хоть немного.Подскажите кто-нибудь нормальный учебник по этому делу.
учебник там --> http://www.lua.ru/doc/
Автор: vintprog 05.07.2009, 16:20
Нет я просто интересуюся можно ли создать такое.
Скриптингом только недавно начал заниматса в STALKER,а так я программирую на Delphi немного знаю C++, еще хачю найти учебники по модингу, и по создания нового HUD -оружия
Автор: Neo][ 05.07.2009, 17:00
Цитата(vintprog @ 05.07.2009, 19:20)
еще хачю найти учебники по модингу, и по создания нового HUD -оружия
vintprog, в помощь http://stalkerin.gameru.net/wiki
Автор: vintprog 05.07.2009, 17:10
Neo][ Спасибо больщое, а что правдо выйдет SDK для одиночной игры?
Автор: Lance 05.07.2009, 17:19
Цитата(vintprog @ 05.07.2009, 21:10)
Neo][ Спасибо больщое, а что правдо выйдет SDK для одиночной игры?
хочется ответить словами из песни: "... наверно, в следующей жизни, когда я стану кошкой..."
Автор: vintprog 05.07.2009, 17:23
Ну что можно реализовать те возможности, что я описал выше в скрипти Stalker?
Автор: Unstoppoble 05.07.2009, 17:42
Цитата(vintprog @ 05.07.2009, 18:23)
Ну что можно реализовать те возможности, что я описал выше в скрипти Stalker?
Цитата
Гравитационое оружия, Литания на самолетах,
Речь об этом ? Если да, то ответ - нет.
Автор: Merc Shram 05.07.2009, 17:47
http://www.lua.ru/doc/
Научись сначала писать правильно
Можно например реализовать: Гравитационое оружия, -> Гравитационное оружие Литания на самолетах, -> Летание на самолетах
Автор: vintprog 05.07.2009, 18:00
А вобще можно?
Автор: Орион 05.07.2009, 18:01
Цитата(Unstoppoble @ 05.07.2009, 17:42)
ответ - нет.
Автор: vintprog 05.07.2009, 18:14
А перемещать npc на координаты, и ставить партиклы на координаты это хоть можно в скриптенги?
Автор: Stalbar 05.07.2009, 18:28
Цитата(vintprog @ 05.07.2009, 22:14)
А перемещать npc на координаты, и ставить партиклы на координаты это хоть можно в скриптенги?
В "скриптенги" точно нельзя. Ибо нет такого, не то что понятия, - слова такого нет. Тебе дали кучу ссылок на информацию - читай, изучай, пробуй. Будут адекватные вопросы - будут адекватные ответы.
Автор: CHOPK 05.07.2009, 18:29
Цитата(vintprog @ 05.07.2009, 16:03)
Огнемет,
АМК уже давно сделали огнёмёт
Цитата(Stalbar @ 05.07.2009, 16:13)
учебник там --> http://www.lua.ru/doc/
о,спс,давно искал)
Автор: UX.Loki 05.07.2009, 19:08
vintprog, поставь мозилу файрфокс , он умеет подчеркивать не правильные грамматически слова и выдавать верные решения .
Автор: BAC9-FLCL 05.07.2009, 19:41
Видимо, заметить тему было сложно. http://www.gameru.net/forum/index.php?showtopic=14792
Автор: vintprog 12.07.2009, 11:37
Все облазел не могу найти учебники по скриптпингу s.t.a.l.k.e.r, будь он не ладный этот LUA пока внем разберещся борода вырастет,лутчи был бы Pascal или c++, срочно нужно сделать моды новых миссий новых возможностей, пожалуйста помогите мне найти учебники или статьи по скриптпингу.
Автор: Shadow. 12.07.2009, 11:53
Как-бы с такой грамматикой ты далеко не пойдёшь... А лучше скажу - выкинь эту мысль из головы,с нуля вот так,взять и начать писать скрипты тебе будет сложно.Хотя почему....даже невозможно www.lua.ru
Автор: DmitrjT 12.07.2009, 11:58
http://wiki.masu-inform.ru:8888/index.php/Lua http://club.shelek.ru/viewart.php?id=77 Если применительно к Сталкеру то примеры есть в билде 1935 и на АМК и OGSE форумах.
Автор: vintprog 12.07.2009, 12:05
В сталкере невидел var, мне нужно знать функцыии для создания NPC, как заставить их ийти на заданые координаты, как выдать им пушки, как заставить их стрелять в кого либо... ***** в Delphi и C++ программить и то лутче.
кто знает эти функцыии?
1. маты запрещены правилами форума 2. безграмотные сообщения тоже
Автор: DmitrjT 12.07.2009, 12:12
Вот тебе простой пример Создание NPC "привязанного к точке" автор Меченый(Стрелок) (amk-team)
Снайпер
*1 Для начала создадим профиль! Откроем фаил character_****.xml и создаем там новый профиль Пример: <specific_character id="название_секции" team_default = "1"> <name>GENERATE_NAME_stalker</name> <icon>иконка</icon> <map_icon x="1" y="0"></map_icon> <bio>Опытный сталкер. Детальная информация отсутствует.</bio>
<class>класс</class> <community>группировка</community> <terrain_sect>stalker_terrain</terrain_sect> <snd_config>characters_voice\human_01\папка с названием группировки\</snd_config>
<rank>цифры от 0 до 900</rank> <reputation>цифры от 0 до 1000</reputation>
<visual>путь до модели"визуала"</visual> <supplies> [spawn] \n оружие \n патроны к этому оружию = 5 \n </supplies> #include "gameplay\character_criticals_4.xml" #include "gameplay\character_dialogs.xml" </specific_character>
*2 Теперь нужно прописать класс нашего НПС в npc_profile.xml Пример: <character id="название_секции из character_****.xml"> <class>класс прописанный вами ранее</class> <specific_character>название_секции из character_****.xml</specific_character> </character>
*3 Теперь зарегистрируем Нашего НПС в spawn_section.ltx Пример: [секция спавна(название пишите сами)]:stalker $spawn = "respawn\секция спавна" character_profile = название_секции из character_****.xml spec_rank = regular ;это ранг непеся оставляйте как есть ,особой роли не играет community = группировка которую вы приписали этому (название_секции из character_****.xml) custom_data = scripts\sniper_addon\sniper_addon_***_logic.ltx;*** - если группировка НПС нейтральна к вам или дружелюбна ,то friend , в противном случае enemy
*4 Потом открываем xr_conditions.script и добавляем вот такую функцию function is_sniper_enemy(enemy, object) return enemy:id() ~= db.actor:id() end PS:Если нет такого фаила ,то возьмите из оригинальной Игры!
*5 Теперь осталось Заспавнить Нашего НПСа PS:Тем кто делает это впервые ,прочитайте дальше ,а если сталкивались ,всё равно читайте
*5.1 Для Начала нам нужно снять координаты того места Где появится наш Снайпер. Для этого открываем ui_main_menu.script находим вот примерно такое if dik == DIK_keys.DIK_Q then self:OnMessageQuitWin() end и делаем так : if dik == DIK_keys.DIK_Q then self:OnMessageQuitWin() elseif dik==DIK_keys.DIK_W then self:position_info() end И в конец фаила.В Самый Конец!!! function main_menu:position_info() local a = db.actor:position() local vid = db.actor:level_vertex_id() local gvid = db.actor:game_vertex_id() local text = "GPS:\\nX= "..a.x.."\\nY= "..a.y.."\\nZ= "..a.z.."\\nlevel_vertex= "..vid.."\\ngame_vertex_id= "..gvid news_manager.send_tip(db.actor, text, nil, nil, 30000) end Сохраняем!!! *5.2 Заходим в игру ,добегаем до места где бы хотели чтобы сидел снайпер,выходим в Меню и в меню жмём на W , потом возвращаемся в игру И Делаем скриншот (F12) *5.3 Далее создаём скрипт спавна (создаётся с помощью блокнота или Notepad++) Например sniper_add.script В нём будем писать функции! function start_add_spawn()--\\*Это "список".Сюда будем вписывать вызов всех функции спавна --\\*Сюда вписываем название ваших функций --пример: spawn_sniper_one() end
function название_латиницей()--\\spawn_sniper_one() local x= смотрим скриншот и переписываем сюда x local y= смотрим скриншот и переписываем сюда y local z= смотрим скриншот и переписываем сюда z local level_vertex= смотрим скриншот и переписываем сюда level_vertex local game_vertex_id= смотрим скриншот и переписываем сюда game_vertex_id alife():create("тут название вашей из spawn_section.ltx",vector():set(x,y,z),level_vertex,game_vertex_id) end
function save_variable(variable_name, value) xr_logic.pstor_store(db.actor, variable_name, value) end function load_variable(variable_name, value_if_not_found) return xr_logic.pstor_retrieve(db.actor, variable_name, value_if_not_found) end
*5.4 Когда вписали всех наших Снайперов и все функции спавна и внесли их в "список",то добавляем вызов нашей функции в bind_stalker.script
в функцию actor_binder:update(delta) перед последнем end'ом этой функции добавляем if sniper_add.load_variable("spawn_sniper",false)==false then sniper_add.start_add_spawn() sniper_add.save_variable("spawn_sniper",true) end
Сохраняем!
*6 Теперь работаем с логикой. в папке configs/scripts создаём папку с sniper_addon , открываем её *6.1 Создаём два фаила sniper_addon_friend_logic.ltx и sniper_addon_enemy_logic.ltx *6.2 открываем sniper_addon_friend_logic.ltx и вписываем туда: ;SNIPER ADDON ;Меченый(Стрелок) [logic] active = remark@search
DmitrjT Не плохо,интересно есть справочник всех функцый в сталкере, есл есть тогда можно садитса делать моды на сталкер.
Автор: DmitrjT 12.07.2009, 12:21
Всех я не встречал, но если надо могу выложить туторы что были в билде 1935. посмотри на АМК там в школе модинга более менее подробно эти вопросы рассмотрены.
Автор: vintprog 12.07.2009, 12:24
DmitrjT Будь добр выложи пожалйста, просто по сриптить охота классные моды, если че потом сделаю мод выложу тоже, или я че найду тоже выложу полезное.
Для тех кого интересует скриптинг в Сталкере выкладываю статью тов. KamikaZze (ogse team) к сожалению полностью доделать ее нет времени полный текст материалов можно найти http://forum.ogse.ru/viewtopic.php?f=6&t=476&start=15 http://stalker-mod.ucoz.ru/_ld/0/20_2r6.rtf
Автор: jboo7 18.07.2009, 20:19
Можно ли как-то взорвать бочку не причиняя ей вред?) То есть не стрелять, не взрывать её, вообще с ней ничего не делать. Просто заспавнить через скрипт и потом так же через скрипт взорвать. Типа дистанционная бомба
Автор: Орион 18.07.2009, 20:34
Это как? О_о
Автор: jboo7 18.07.2009, 20:53
Что "как?"? Заспавнил бочку где-то рядом с собой, и нажал на заветную кнопку в главном меню, возвратился в игру и ты уже труп, потому что бочка взорвалась от нажатия на ту заветную кнопку. Как это можно было бы реализовать?
Автор: Орион 18.07.2009, 21:04
Кнопкой не знаю, если честно.. спейс рестриктором можно. Все помним сцены с туннелями в Рыжем Лесу, куда убегал Стрелок?) Можно по аналогии попробовать.
Автор: jboo7 18.07.2009, 21:26
Можно немного поподробнее?)
Автор: PATRON 18.07.2009, 23:43
Может попробовать нанести обьекту hit при помощи скрипта? Отследить его id, и дать хитом?
Автор: jboo7 18.07.2009, 23:51
А как тогда отследить его id после создания через alife():create?
Автор: Stalbar 19.07.2009, 08:53
Цитата(jboo7 @ 19.07.2009, 03:51)
А как тогда отследить его id после создания через alife():create?
Ну етить... Вот ведь вопросы В мануалах всё расписано как, и не только это, кстати... Читайте мануалы, и будет вам счастье.
Код
-- Создаём объект local obj_name -- имя объекта local pos, lvid, gvid -- позиция, левел-вертекс, гейм-вертекс spawn_obj = alife():create(obj_name, pos, lvid, gvid) -- спавним объект local obj_id = spawn_obj.id -- комментарии нужны? Если да, то это и есть "его id после создания"
Потом, когда нужно, наносим объекту хит, в данном случае взрывом
Код
-- получаем игровой объект по его номеру и взрываем local boom_obj = level.object_by_id(obj_id) local boom = hit() boom.direction = vector():set(0,0,0) -- направление хита boom.impulse = 10 -- импульс boom.draftsman = boom_obj boom.power = 10 -- сила хита boom.type = hit.explosion -- тип хита, в данном случае, взрыв if boom_obj then -- проверка, а собственно есть то, что нужно взорвать? boom_obj:hit(boom) -- большой бада-бум end
Не сложно ведь?
Автор: PATRON 19.07.2009, 11:40
Stalbar, ну спасибо, давно искал это!
Автор: jboo7 19.07.2009, 13:50
Спасибо, Stalbar, проверю счас
Автор: jboo7 19.07.2009, 16:57
Попробовал то, что посоветовал Stalbar с канистрой из АМК. Ничего с канистрой не произошло, проверил вот эту строчку local boom_obj = level.object_by_id(obj_id) просто обратившись к объекту boom_obj:name(). Выкинуло, подозреваю, что level.object_by_id попросту ничего не вернуло и в boom_obj ничего нет.
Автор: Stalbar 19.07.2009, 23:34
Цитата(jboo7 @ 19.07.2009, 20:57)
Попробовал то, что посоветовал Stalbar с канистрой из АМК. Ничего с канистрой не произошло, проверил вот эту строчку local boom_obj = level.object_by_id(obj_id) просто обратившись к объекту boom_obj:name(). Выкинуло, подозреваю, что level.object_by_id попросту ничего не вернуло и в boom_obj ничего нет.
Распиши подробно, что делаешь, как обращаешься, откуда и т.п. Пишешь, что выкинуло - лог имеется? Попробуй получить имя, как boom_obj:section_name()
Автор: jboo7 20.07.2009, 01:53
Код у меня такой:
local object_s = alife():create("amk_kanistra",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id()) local object_id = object_s.id local object_n = level.object_by_id(object_id)
--local st = object_n:name() --узнаем имя, для проверки) --get_console():execute("object_n..name>>"..st)
if object_n then object_n:hit(boom) else --чтобы не было вылетов, выведем просто в консоль, что объекта нет get_console():execute("object_n..is..nill>>") end
Если убрать там комменты, игра вылетит с таким логом:
Expression : fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description : <no expression> Arguments : LUA error: ...s\s.t.a.l.k.e.r\gamedata\scripts\ui_main_menu.script:452: attempt to index local 'object_n' (a nil value)
Отсюда следует, что object_n = nil ...
Вместо вылетов поставил условие, чтобы не надоедало)
то есть канистру в инвентарь спавните. а разве level.object_by_id() что-нибудь возвращает для объектов в инвентаре, и присутсвует ли вообще эта канистра в игре как объект, который можно взорвать? попробуйте просто перед собой заспавнить в паре метров.
Код
local pos = db.actor:position() local dir = db.actor:direction() pos = pos:add(dir:mul(5)) -- создаем предмет в 5 метрах прямо перед нами alife():create(чего_надо, pos, 1, db.actor:game_vertex_id())
Автор: jboo7 20.07.2009, 02:46
По сути у тебя тоже самое, что и у меня. Чтобы заспавнить в инвентарь нужно писать так
--local st = object_n:name() --узнаем имя, для проверки) --get_console():execute("object_n..name>>"..st)
Измени и дополни вывод инфы
local st = object_n:section_name() --узнаем имя, для проверки) get_console():execute("object_n..name>>"..tostring(st)) get_console():execute("object_id>>"..tostring(object_id))
и посмотри, что выдаст
Цитата(jboo7 @ 20.07.2009, 05:53)
else --чтобы не было вылетов, выведем просто в консоль, что объекта нет get_console():execute("object_n..is..nill>>")
А вот это отрабатывает в консоль? Если object_n nil то в логе будет такая запись..
--local st = object_n:name() --узнаем имя, для проверки) --get_console():execute("object_n..name>>"..st)
Измени и дополни вывод инфы
local st = object_n:section_name() --узнаем имя, для проверки) get_console():execute("object_n..name>>"..tostring(st)) get_console():execute("object_id>>"..tostring(object_id))
и посмотри, что выдаст
Я попробую, но в принципе в этом нет смысла, потому что в логе написано, что object_n == nil. Для этого я и добавил там в условие else, чтобы узнать есть ли этот объект вообще.
В общем оставил только незакомментеной строчку get_console():execute("object_id>>"..tostring(object_id)). id у неё есть какое-то...
Цитата(Stalbar @ 20.07.2009, 08:28)
Цитата(jboo7 @ 20.07.2009, 05:53)
else --чтобы не было вылетов, выведем просто в консоль, что объекта нет get_console():execute("object_n..is..nill>>")
А вот это отрабатывает в консоль? Если object_n nil то в логе будет такая запись..
Просто консоль попытается это воспринять как команда, но такой команды нет, поэтому, если зайти в консоль и если object_n == nil, то в консол красным будет выведена надпись "object_n..is..nill>>"
При запуске того кода в консол выводится "object_n..is..nill>>".
Автор: Stalbar 20.07.2009, 12:56
Цитата(jboo7 @ 20.07.2009, 05:53)
if object_n then object_n:hit(boom) else --чтобы не было вылетов, выведем просто в консоль, что объекта нет get_console():execute("object_n..is..nill>>") end
Тогда не парься и давай хит прямо по object_s
if object_s then object_s:hit(boom) else --чтобы не было вылетов, выведем просто в консоль, что объекта нет get_console():execute("object_s..is..nill>>") end
Автор: jboo7 20.07.2009, 13:21
Цитата(Stalbar @ 20.07.2009, 12:56)
Цитата(jboo7 @ 20.07.2009, 05:53)
if object_n then object_n:hit(boom) else --чтобы не было вылетов, выведем просто в консоль, что объекта нет get_console():execute("object_n..is..nill>>") end
Тогда не парься и давай хит прямо по object_s
if object_s then object_s:hit(boom) else --чтобы не было вылетов, выведем просто в консоль, что объекта нет get_console():execute("object_s..is..nill>>") end
После этого игра вылетает с таким логом
Expression : fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description : <no expression> Arguments : LUA error: ...s\s.t.a.l.k.e.r\gamedata\scripts\ui_main_menu.script:464: attempt to call method 'hit' (a nil value)
То есть у object_s нема метода hit(). И че делать?)
Автор: jboo7 21.07.2009, 18:24
Кто-то знает какого класса объект, возвращаемый alife():create()?
Автор: HikeR 21.07.2009, 18:34
ссылку на game_object, надо полагать.
Автор: jboo7 21.07.2009, 18:44
Тогда у него был метод hit(), но его у него нет. Еще варианты
Автор: Stalbar 21.07.2009, 20:38
jboo7, самому докопаться до истины - "не наш метод"?? Ну ок, сделаю тебе полный "тутор по взрыву канистры". В картинках. С кодом.
Так как амк_канистры не нашёл, сделал пример на "Ниве", надеюсь, это-то сможешь поменять?? В файле ui_main_menu.script объявляем переменную в самом начале:
local niva_id = 0
далее добавляем свои вызовы в function main_menu:OnKeyboard(dik, keyboard_action) - вешаем на F1 и F2
Код
if dik == DIK_keys.DIK_F1 then if level.present() and (db.actor ~= nil) and db.actor:alive() then local console = get_console() console:execute("main_menu off") spawn_niva() end end if dik == DIK_keys.DIK_F2 then if level.present() and (db.actor ~= nil) and db.actor:alive() then local console = get_console() console:execute("main_menu off") boom_niva() end end
в конце скрипта, собственно, "наше всё"
Код
function spawn_niva() local lvid, gvid = db.actor:level_vertex_id(),db.actor:game_vertex_id() local pos = db.actor:position() local dir = db.actor:direction() pos = pos:add(dir:mul(5)) local spawn_item = alife():create("vehicle_niva",pos,lvid, gvid) local niva_name = spawn_item:section_name() niva_id = spawn_item.id amk.logf("Марка и номер двигателя: "..tostring(niva_name).." "..tostring(spawn_item.id)) end
function boom_niva() local obj_niva = level.object_by_id(niva_id) if obj_niva then local niva_pos = obj_niva:position() local niva_dist = niva_pos:distance_to(db.actor:position()) amk.logf("Номер авто в ГАИ: "..tostring(niva_id)) amk.logf("Позиция авто: "..tostring(niva_pos.x).." "..tostring(niva_pos.y).." "..tostring(niva_pos.z)) amk.logf("Расстояние до актора: "..tostring(niva_dist)) local boom = hit() boom.direction = vector():set(0,1,0) boom.impulse = 1 boom.draftsman = obj_niva boom.power = 10 boom.type = hit.explosion obj_niva:hit(boom) else amk.logf("Авто в ГАИ не зарегестировано!! Угнали??") end end
Запускаем, проверяем, скриним
http://img.gameru.net/?v=05729.jpg
Тыц на Esc и F1, опа, сработало!
http://img.gameru.net/?v=a2a89.jpg
И в логе появилось ! Unknown command: :Марка и номер двигателя: vehicle_niva 41217
Вывод в лог используется амк-шный, ибо удобен... если у тебя нет файла amk.script ( в чём я сомневаюсь), то вот используемые функции
Код
function logf( fmt, ... ) logf_console = get_console() logf = logf_main logf_main( fmt, ... ) end
function logf_main( fmt, ... ) local c = select( "#", ... ) if c <= 0 then -- nothing to format logf_console:execute( ":" .. string.gsub( fmt, " ", "\160" ) ) else logf_console:execute( ":" .. string.gsub( string.format( fmt, ... ), " ", "\160" ) ) end end
Вопросы??
Автор: jboo7 21.07.2009, 21:33
Без сомнений всё подробно описал, респект) Но вопрос только один: почему level.object_by_id амк_канистру не находит?..
Автор: Stalbar 21.07.2009, 21:56
Цитата(jboo7 @ 22.07.2009, 01:33)
Без сомнений всё подробно описал, респект) Но вопрос только один: почему level.object_by_id амк_канистру не находит?..
А откуда уверенность, что не находит? Судя по вашему коду, там проверки на это нет... Я видел только попытки получить name неверным методом (--local st = object_n:name() --узнаем имя, для проверки)), а проверку того, что же всё-таки содержится в object_n я не видел. Собственно, весь пример выше и нужен был только для "показа" переменных.
Автор: jboo7 21.07.2009, 22:03
CODE
if object_n then object_n:hit(boom) else get_console():execute("object_n..is..nill>>") end
А это разве не проверка в моем коде на существование объекта?
Автор: Stalbar 21.07.2009, 22:26
jboo7, тогда пожалуйста, по порядку Весь код, что приведён в первом сообщении на этой странице - он откуда? Как вызывается? Этот код из одной функции, или из нескольких?
Автор: jboo7 21.07.2009, 22:38
Две функции, думаю не стоит рассказывать как я их вызываю)
CODE
function main_menu:spawn(n) local object_s = alife():create("amk_kanistra",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id()) local object_id = object_s.id object_n = level.object_by_id(object_id) end
if object_n then object_n:hit(boom) else get_console():execute("object_n..is..nil>") end end
Тут все понятно, но в object_n пусто...
Автор: Kolmogor 21.07.2009, 22:48
Цитата(jboo7 @ 21.07.2009, 23:38)
Две функции, думаю не стоит рассказывать как я их вызываю)
function main_menu:spawn(n) local object_s = alife():create("amk_kanistra", ...) local object_id = object_s.id object_n = level.object_by_id(object_id) end
Тут все понятно, но в object_n пусто...
В этой функции вы пытаетесь получить клиентский объект сразу после создания. Его еще нет в игре, так как в онлайн он еще не перешел. Поэтому там и пусто. Лучше запомнить object_id и по нему получить клиентский объект в explode()
То есть как-то так
CODE
local object_id
function main_menu:spawn(n) local object_s = alife():create("amk_kanistra",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id()) object_id = object_s.id end
local object_n = level.object_by_id(object_id) if object_n then object_n:hit(boom) else get_console():execute("object_n..is..nil>") end end
Автор: jboo7 21.07.2009, 23:10
Kolmogor, спасибо большое) Это действительно помогло) Не думал, что все так просто, одну строку перенести в другое место
Автор: HikeR 21.07.2009, 23:33
Цитата(Kolmogor @ 21.07.2009, 23:48)
Вэтой функции вы пытаетесь получить клиентский объект сразу после создания. Его еще нет в игре, так как в онлайн он еще не перешел.
кстати, может кто скажет, почему цикл while с ожиданием наступления момента появления объекта в онлайне сразу после создания обычно вызывает краш? и есть ли какой-то аналог ф-ии wait(столько-то-секунд), которую можно использовать?
просто была такая же заморочка. iterate_inventory(... -- перебираю инвентарь alife():release(... -- убираю некоторый объект iterate_inventory(... -- опять перебираю, а объект все еще есть.
если добавить проверку вида while true do if not is_object_online(obj_id) then break end end
то вываливаюсь, а по идее цикл должен был крутится пока этот obj_id не перестанет отзываться.
Автор: Stalbar 22.07.2009, 09:09
HikeR, насчёт аналога - не подскажу, но может попробовать такую конструкцию? В начале скрипта поставить что-то типа
local flag = true
Затем, после того как "alife():release(... -- убираю некоторый объект", в цикле ставить проверку, наподобие
while flag == true do if "убитый_объект" ~= nil then flag = true else flag = false end end
Автор: Kolmogor 22.07.2009, 09:26
Цитата(HikeR @ 22.07.2009, 00:33)
просто была такая же заморочка. iterate_inventory(... -- перебираю инвентарь alife():release(... -- убираю некоторый объект iterate_inventory(... -- опять перебираю, а объект все еще есть.
Думаю дело в этом: alife():release(...) убивает серверный объект iterate_inventory(...) итерирует по клиентским А синхронизация серверных и клиентских произойдет не раньше следующего actor_binder:update.
Автор: PATRON 22.07.2009, 10:43
А можно как-то, зная название обьекта, и не спавня его(так как он в игре уже есть как онлайн), ударить по нему хитом? Вот например удаление долговца:
Код
function udar_nishtak() for a=10,65635,1 do local obj=alife():object(a) if obj and string.find(obj:name(),"dolg_regular") then alife():release(obj,true) end end end
А вот кто-нибудь может переделать этот код, чтобы получилось что-то вроде:
Код
function udar_nishtak() for a=10,65635,1 do local obj=alife():object(a) if obj and string.find(obj:name(),"dolg_regular") then Какой код нужно поставить сюда, для хита? end end end
Автор: vintprog 22.07.2009, 11:22
А кто знает как удалить все миссии действия в скриптах. И начать делать миссии и всякое с нуля?
Автор: Kolmogor 22.07.2009, 12:00
Цитата(PATRON @ 22.07.2009, 11:43)
А можно как-то, зная название обьекта, и не спавня его(так как он в игре уже есть как онлайн), ударить по нему хитом?
выше был пример взрыва бочки. Её взрывали нанося хит. Разницы между бочкой и долговцем в этом случае никакой
Автор: Stalbar 22.07.2009, 14:32
Цитата(Kolmogor @ 22.07.2009, 16:00)
Цитата(PATRON @ 22.07.2009, 11:43)
А можно как-то, зная название обьекта, и не спавня его(так как он в игре уже есть как онлайн), ударить по нему хитом?
выше был пример взрыва бочки. Её взрывали нанося хит. Разницы между бочкой и долговцем в этом случае никакой
Можно дополнить? В примере выше использовался тип повреждения hit.explosion... Надо-ли говорить, что тип не один? Есть несколько типов - можете найти примеры использования в оригинальных скриптах и наносить объекту хит, наиболее подходящий для ситуации.
Автор: HikeR 22.07.2009, 15:02
Цитата(Stalbar @ 22.07.2009, 10:09)
но может попробовать такую конструкцию?
она по сути повторяет тот же while true...
Цитата(Kolmogor @ 22.07.2009, 10:26)
А синхронизация серверных и клиентских произойдет не раньше следующего actor_binder:update.
ахха, то есть минимальный момент времени, который нужно подождать - 1FPS. вопрос в том, как именно нужно ждать ;) просто есть подозрение, что любой цикл приостанавливает выполнение скрипта, и при определенной задержке, то есть при отсутсвии возврата, игра крешится, специально либо из-за рассинхронизации. а вешать на апдейт разовую ф-ию как-то не хочется.
Автор: Kolmogor 22.07.2009, 21:31
Цитата(Stalbar @ 22.07.2009, 15:32)
Можно дополнить? В примере выше использовался тип повреждения hit.explosion... Надо-ли говорить, что тип не один? Есть несколько типов - можете найти примеры использования в оригинальных скриптах и наносить объекту хит, наиболее подходящий для ситуации.
есть еще hit.burn hit.chemical_burn hit.fire_wound hit.radiation hit.shock hit.strike hit.telepatic hit.wound Использовать так же как и hit.explosion. Эти значения взял из файла lua_help.script. Там же можно найти и много другой полезной информации. Ну а какой наиболее подходящий Вам виднее
Цитата(HikeR @ 22.07.2009, 16:02)
ахха, то есть минимальный момент времени, который нужно подождать - 1FPS. вопрос в том, как именно нужно ждать просто есть подозрение, что любой цикл приостанавливает выполнение скрипта, и при определенной задержке, то есть при отсутсвии возврата, игра крешится, специально либо из-за рассинхронизации. а вешать на апдейт разовую ф-ию как-то не хочется.
Как обойтись без влезания в апдейт я не знаю. Можно еще правда set_fastcall попытаться приспособить(по использованию в скриптах чем-то напоминает апдейт ). Когда нужно - установить, а после срабатывания сбросить.
Ну и кстати с циклом по идее вылета не должно быть. просто по идее биндер должен зависнуть и все (то есть перестать срабатывать функции биндера). В АМК например, это зависание отлавливается и игра специально крешится. А можно лог вылета, если сохранился
смотрел на это дело, но издалека, надо попробовать.
Цитата(Kolmogor @ 22.07.2009, 22:31)
А можно лог вылета, если сохранился
у меня имеется некоторая трабла в виде установленной семерки, которая падает в синий экран при краше сталкера, а ребутить машину ночью никак нельзя. как-нить на днях выложу, если еще интересно будет.
Автор: Stalbar 23.07.2009, 10:10
Вопрос - кто-нибудь знает, как прочитать последнюю строку консоли в запущенной игре?
Автор: jboo7 23.07.2009, 11:46
В lua_help.script есть класс CConsole.
CODE
C++ class CConsole { function execute_script(string); function get_string(string); function execute(string); function get_bool(CConsole*, string); function get_float(CConsole*, string); function get_integer(CConsole*, string); function get_token(string); function show(); function hide(); };
Может get_string() что-то даст, по названию как ни как
Автор: Stalbar 23.07.2009, 11:51
Да, это я видел, даже пробовал вытащить именно через get_console:get_string(), что-то пока не получается. Поэтому и спросил, может кто подтолкнёт..
Автор: jboo7 23.07.2009, 12:49
get_string определенно не то, что нужно, потому что она возвращает значение в строке любой консольной команды, переданой в качестве параметра...
local str = get_console():get_string("rs_stats")
в итоге в str будет "on" или "off"
и разницы между get_string и get_token не нашел...
Автор: kutuzvden 23.07.2009, 13:02
Здрасте. Мб не совсем в тему, но все таки. Подскажите плиз, где находится в сталкере скрипт, отвечающий за голод, а то я в скриптах не бум бум-хочу сделать аналогичный скрипт по примеру голода. И еще: где и что нужно написать, чтоб игра обращалась к этому скрипту?
Автор: jboo7 23.07.2009, 13:40
Stalbar, может попробуешь сохранять лог-игры, когда нужно во время её работы, и просто читать от туда последнюю строку?
Автор: Stalbar 23.07.2009, 13:54
jboo7, флушить лог можно, но как добиться, чтобы это происходило именно в момент появления там нужной мне строки???? Хотя, если по этому условию можно флушить лог, то тогда мне и лог совсем не нужен Мне нужно отловить именно появление определённой строки в логе, вернее в консоли.
Автор: Kolmogor 23.07.2009, 17:18
Цитата(Stalbar @ 23.07.2009, 14:54)
Мне нужно отловить именно появление определённой строки в логе, вернее в консоли.
А какая задача вообще стоит? Зачем пытаешься строку в консоли отловить? Может необязательно строку в консоли отлавливать, может по-другому можно?
Автор: Stalbar 23.07.2009, 17:47
Цитата(Kolmogor @ 23.07.2009, 21:18)
А какая задача вообще стоит? Зачем пытаешься строку в консоли отловить? Может необязательно строку в консоли отлавливать, может по-другому можно?
При активации артефакта под названием "мина" рождается аномалия "минное поле" Движок на это непотребство реагирует выдачей в консоль 2 строк такого вида: artefact [af_mine31076] spawned a zone [zone_mine_field] at [92.799683] - !!!processing_enabled ->destroy_queue.push_back af_mine31076[31076] frame [18310] Вот хочу попытаться отловить не факт перемещения игроком в активный слот айтема (он его может покрутить в руках и назад в рюкзак сунуть), а именно момент активации мины, после которого движок выдаёт в консоль вышеприведённые строки. Также очень хочется отловить момент "сработки" минного поля, как вот это реализовать - я пока в глубоких раздумьях... Если по варианту активации мины есть решение, но очень "некрасивое", я бы сказал, хотелось бы более элегантного, то по вопросу срабатывания минного поля мыслей пока никаких нет. Совсем.
Автор: Kolmogor 23.07.2009, 23:24
Цитата(Stalbar @ 23.07.2009, 18:47)
Вот хочу попытаться отловить не факт перемещения игроком в активный слот айтема (он его может покрутить в руках и назад в рюкзак сунуть), а именно момент активации мины, после которого движок выдаёт в консоль вышеприведённые строки.
При активации мины артефакт пропадает? Тогда это отлавливается как и использование предмета: в on_item_drop запоминаем ид, и в апдейт проверяем наличие объекта с таким ид - если объекта нет - значит заюзали
Автор: Stalbar 23.07.2009, 23:46
Цитата(Kolmogor @ 24.07.2009, 03:24)
При активации мины артефакт пропадает? Тогда это отлавливается как и использование предмета: в on_item_drop запоминаем ид, и в апдейт проверяем наличие объекта с таким ид - если объекта нет - значит заюзали
Ну вот что-то наподобие сейчас и используется, только отслеживается появление аномалии, а не использование артефакта, потому как аномалии всё равно все "на учёте" и появление новой нужно фиксировать. А вот момент срабатывания уже самой аномалии на сегодняшний момент вижу только как проверку по нанесению хита какому-либо объекту в известной позиции (радиус аномалии). Пока больше никаких вариантов по этой проблеме у меня нет.
Автор: kutuzvden 24.07.2009, 00:07
Ау... Ответьте.
Автор: DmitrjT 24.07.2009, 00:53
Цитата(kutuzvden @ 24.07.2009, 01:07)
Ау... Ответьте.
В ЛС
Автор: IG-2007 24.07.2009, 09:36
Цитата(Stalbar @ 24.07.2009, 00:46)
А вот момент срабатывания уже самой аномалии на сегодняшний момент вижу только как проверку по нанесению хита какому-либо объекту в известной позиции (радиус аномалии). Пока больше никаких вариантов по этой проблеме у меня нет.
Можно определять не срабатывание аномалии, а вхождение в область её действия. В ЧН так отслеживалось наступание ГГ на мины.
Автор: Stalbar 24.07.2009, 10:13
Цитата(IG-2007 @ 24.07.2009, 13:36)
Можно определять не срабатывание аномалии, а вхождение в область её действия. В ЧН так отслеживалось наступание ГГ на мины.
Ну да, значит "рою" в правильном направлении Спасибо!
Автор: IG-2007 24.07.2009, 11:55
Цитата(Stalbar @ 24.07.2009, 11:13)
Ну да, значит "рою" в правильном направлении Спасибо!
Да, не за что Можно ещё в моде ZEN-а посмотреть, там было минирование. Он долго мучался с повторным срабатыванием мин, но потом, вроде бы, победил. Так что, там должно быть реализовано отслеживание срабатывания и не только для ГГ.
Автор: Stalbar 24.07.2009, 14:56
Цитата(IG-2007 @ 24.07.2009, 15:55)
Можно ещё в моде ZEN-а посмотреть, там было минирование. Он долго мучался с повторным срабатыванием мин, но потом, вроде бы, победил. Так что, там должно быть реализовано отслеживание срабатывания и не только для ГГ.
Там просто заносились все новые минные поля в табличку и спустя энное кол-во часов убирались. Все. И сработавшие и не сработавшие.
Автор: vintprog 31.07.2009, 07:10
Ребята может кто подсказать несколько функцый: 1) как спавнить npc с хендлом и по этому хендлу менять его пармметры? 2) как дать npc-у оружие и.т.д. 3) как заставить npc стрелять без перерывов например с ak 4) как заставить npc идти на опредиленые координаты 5) как уничтожить npc
Автор: HikeR 31.07.2009, 11:36
vintprog, начните с вики для начала.
Автор: bill_gates 10.08.2009, 13:52
Люди, помогите! Как можно реализовать таймер через скрипт? Чтобы таймер запускался в игровом времени через функцию (например, вызываемую диалогом) и по истечении времени, на которое он был поставлен он должен выполнять определенную функцию. Например, чтобы после диалога с npc через 10 минут игрового времени актору выдавался инфопоршень. Как запускать функции из диалога и т.д. я знаю, но вот как сделать таймер не пойму. В amk и ogsm модах есть функция g_start_timer. Пробовал через нее - ничего не выходит(((
Автор: Stalbar 10.08.2009, 19:30
Цитата(bill_gates @ 10.08.2009, 17:52)
В amk и ogsm модах есть функция g_start_timer. Пробовал через нее - ничего не выходит(((
Т.е. пробовал "выдёргивать" только эту функцию, или в самих модах пробовал запускать свой таймер? Не получается - игра крэшится с ошибкой, или просто ничего не происходит? Конкретизируй проблему
Автор: bill_gates 10.08.2009, 20:59
Все! Я разобрался наконец. Просто я забывал добавить имя таймера в функцию __do_timer_action. Теперь все работает.
Автор: Nekt 10.08.2009, 21:42
kutuzvden на сколько помнится даже опроса на сколько голоден нету, как у здоровья. Так-что ... Хотя если кто знает, функцию опроса можете просветить человека.
Автор: Lance 20.08.2009, 09:49
На днях тут пришла идея с ЛЦУ для оружия. И вот что заинтересовало: Чисто теоретически, можно ли написать такой скрипт, чтобы при переключении на оружие с ЛЦУ, прицел менялся на динамический прицел-точку как в режиме без оружия?
Автор: Орион 20.08.2009, 11:49
Lance, Можно, но очень много мороки с проверками фова, враг/невраг и состояние оружия)Скрипт будет очень громоздким и мб просадку фпс даст хорошую. Но в теории - реально
Автор: Lance 20.08.2009, 21:15
да враг/невраг ненадо совсем, т.к. тупо красная точка, цвет не меняет... Хм. ну если идея кому понравилась, я моделькой лцу снабжу за написаный скрипт) т.к. пока самому луа учить времени нет.
Автор: jboo7 09.09.2009, 23:46
Можно как-то организовать респаун долговцев на кордоне?
Автор: jocker_27 06.10.2009, 13:56
Комрады, а можно (чисто теоретически) привязать alife к мультиплееру?
Автор: Орион 06.10.2009, 14:23
jocker_27, Нет, невозможно.
Автор: 123456 30.11.2009, 22:48
Люди, нужна помощь! Как в ТЧ в ДМ называются и вызываются функции fraglist и playerlist ??
Автор: 123456 02.12.2009, 00:08
Никто незнает
Автор: Shadow. 02.12.2009, 00:14
Цитата(jocker_27 @ 06.10.2009, 13:56)
Комрады, а можно (чисто теоретически) привязать alife к мультиплееру?
Цитата
jocker_27, Нет, невозможно.
Орион,соответственно,сделать в мультиплеере спавн предметов в инвентарь по нажатию кнопки в меню тоже никак?
Автор: Орион 02.12.2009, 00:35
Shadow., Даже не пробовал... попробуй) Проблема в том, что не все далеко переменные глобальные инициализируются в мп-режиме. Следовательно, не все методы будут работать. Спавн через alife():create() вряд ли будет работать по понятным причинам
Автор: 123456 02.12.2009, 01:17
Автор: Shadow. 02.12.2009, 15:03
Цитата(Орион @ 02.12.2009, 00:35)
Shadow., Даже не пробовал... попробуй) Проблема в том, что не все далеко переменные глобальные инициализируются в мп-режиме. Следовательно, не все методы будут работать. Спавн через alife():create() вряд ли будет работать по понятным причинам
Верно,не работает. Скрипт спавна в принципе делал давно,как раз через alife():create(), в сингле работает исправно,а вот в мультиплеере вылет с уж не помню каким логом. А сделать как-то иначе возможно?
Автор: Орион 02.12.2009, 15:14
Shadow., Угу. Дизассемблер и учебник по языку асмы в руки. Поделишься результатами
Автор: Scarabay 05.12.2009, 17:14
Всем привет. Подскажите пожалуйста, как создать спейс рестриктор через скрипт, и чтобы он использовал логику из .лтх файла. Заранее спасибо
Автор: =SaleR= 05.12.2009, 18:06
Scarabay, вот статья со сталкер-портала:
Тыц
Первое обновление. Теперь можно выбирать, какой формы будет рестриктор, Шар или Куб. Для Куба устанавливаются размеры по x,y,z.
Второе обновление. Теперь, в качестве кастом даты, можно указывать ltx файлы, из папки config. Путь указывается таким образом:
local ltx = "scripts\имя_файла.ltx"
Итак. Создаём файл _new_create.script, если такового ещё нет, и добавляем в него нашу функцию:
function create_restr(storid, pos_restr, lvid_restr, gvid_restr, custom_restr, radius_restr, ax_x, ax_y, ax_z) local obj = alife():create("space_restrictor", pos_restr, lvid_restr, gvid_restr)
local packet = net_packet() obj:STATE_Write(packet) ----------------------- load ------------------------------ local game_vertex_id = packet:r_u16() local cse_alife_object__unk1_f32 = packet:r_float() local cse_alife_object__unk2_u32 = packet:r_u32() local level_vertex_id = packet:r_u32() local object_flags = packet:r_u32() local custom_data = packet:r_stringZ() local story_id = packet:r_u32() local spawn_story_id = packet:r_u32() local shape_count = packet:r_u8() for i=1,shape_count do local shape_type = packet:r_u8() if shape_type == 0 then local center = packet:r_vec3() local radius = packet:r_float() else local axis_x = packet:r_vec3() local axis_y = packet:r_vec3() local axis_z = packet:r_vec3() local offset = packet:r_vec3() end end
local restrictor_type = packet:r_u8() -------------------------- save ----------------------------- packet:w_begin(game_vertex_id) packet:w_float(cse_alife_object__unk1_f32) packet:w_u32(cse_alife_object__unk2_u32) packet:w_u32(level_vertex_id) packet:w_u32( bit_not(193) )
if custom_restr ~= nil then if string.find (custom_restr, '.ltx') ~= nil then custom_restr = '[logic]\n cfg = '..custom_restr..'\n' end packet:w_stringZ(custom_restr) else packet:w_stringZ(custom_data) end
if storid ~= nil then packet:w_u32(storid) else packet:w_u32(story_id) end
packet:w_u32(spawn_story_id)
packet:w_u8(1) if radius_restr ~= nil then packet:w_u8(0) packet:w_vec3(vector():set(0, 0, 0)) packet:w_float(radius_restr) elseif radius_restr == nil and ax_x == nil then packet:w_u8(0) packet:w_vec3(vector():set(0, 0, 0)) packet:w_float(2.5) else packet:w_u8(1) packet:w_vec3(vector():set(ax_x, 0, 0)) packet:w_vec3(vector():set(0, ax_y, 0)) packet:w_vec3(vector():set(0, 0, ax_z)) packet:w_vec3(vector():set(0, 0, 0)) end
packet:w_u8(restrictor_type) ----------------------------------------------------- packet:r_seek(0) obj:STATE_Read(packet, packet:w_tell()) end
Вызов спавна будет производиться из других функций, других файлов, таким образом:
для формы Шар: _new_create.create_restr(sid, pos, lv, gv, ltx, radius)
для Формы Куб: _new_create.create_restr(sid, pos, lv, gv, ltx, nil, x, y, z)
Где: sid --стори айди рестриктора (или nil, если не используется) pos --позиция спавна рестриктора vector():set(x,y,z) lv --левел вертекс позиции спавна gv --гейм вертекс позиции спавна ltx --кастом дата рестриктора radius --радиус зоны рестриктора (в метрах) (или nil, если используется форма куба) x,y,z --размеры куба, по x,y,z соответственно.
Теперь разберём такие настройки как, ltx и sid.
--------------------------------- ltx
Кастом дата рестриктора. Тобишь, логика по которой будет работать данный рестриктор. Чтобы указать логику из статитеского файла ltx, находящегося в папке config, нужно прописать так:
local ltx = "scripts\\имя_файла.ltx"
или
local ltx = "misc\\имя_файла.ltx"
или
local ltx = "имя_файла.ltx"
В зависимости от того, где лежит требуемый файл, относительно папки config.
Если нас статический ltx не устраивает. То можно прописать логику динамически. Тобишь, в той же функции, от куда и будет вызываться спавн рестриктора. Итак, пред вызовом спавна создаём локальную переменную ltx, и в значении данной переменной прописываем всю логику нашего рестриктора. Например, установим эффект активации слота "ножь", при входе ГГ в рестриктор:
local ltx = "[logic]\n".. "active = sr_idle@in\n"..
\n -прописать в новой строке, динамического файла ltx. .. -привязать следующую строку к общей схеме динамического ltx. Каждая строка, обязательно заключается в кавычки, кроме двоеточия. В последней строке, двоеточие запрещается ставить категорически.
Если логика рестриктора, не предусмотрена, то вместо неё ставить nil.
Есть возможность использовать значения по умолчанию:
_new_create.create_restr(sid, pos, lv, gv, ltx)
или
_new_create.create_restr(sid, pos, lv, gv) если custom_data не предусматривается.
По умолчанию рестриктор имеет форму Шара, с радиусом 2.5 метра.
Всё. Пробуйте. У меня работает отлично.
Автор: macron 16.12.2009, 20:36
Цитата(Shadow. @ 02.12.2009, 15:03)
Скрипт спавна в принципе делал давно,как раз через alife():create(), в сингле работает исправно,а вот в мультиплеере вылет с уж не помню каким логом. А сделать как-то иначе возможно?
Shadow., скрипты в мультиплеере - штука не простая. Вещи типа "alife():create()" там не должны работать в принципе. У меня точно срабатывали совсем примитивные скрипты на выполнение консольной команды (причем только на невыделенном сервере). Сам скрипт запускался через level.ltx конкретного уровня, туда добавлял:
[level_scripts] script=ыыыы
где ыыыы - этоо файл gamedata\scripts\ыыыы.script. Вроде еще можно грузить через gamedata\config\script.ltx - там есть отдельные секции для каждого mp-режима.
ЗЫ: возник ряд вопросов по скриптам: 1. Можно ли скриптом разрешить трупу/с трупа жрать аптечку или еду? Чтобы на 6 патче не вылетало.
2. В 7 mp-патче значительно ускорен курсор в менюшках - очень резво реагирует на движение мышки, удобней вобщем. В его xrgame.dll добавлена такая фишка: CUICursor::UpdateCursorPosition. В 4 и 6 патче такого нет. Можно ли скриптом добавить "акселерацию" мышки в менюшках?
3. Нужен скрипт для переключения оружия из одного слота без захода в инвентарь: то есть, допустим, у нас в руках автомат и в рюкзаке автомат. Нажимаем на 3, и оружие меняется.
Автор: Shadow. 16.12.2009, 21:01
Цитата
Сам скрипт запускался через level.ltx конкретного уровня, туда добавлял:
[level_scripts] script=ыыыы
Я всё делал через скрипт главного меню,мне так проще,на основе вызова Spawnmenu,что по кнопке S(закомменчено в финалке).Фактически,только добавить нужные функции и всё,ну на крайняк тупо вызов функции из другого скрипта,чтобы поопрятнее выглядело.
Автор: whoami 20.12.2009, 12:14
...продолжаю работу одного человека по воссоздания крысы, как полноценно играбельного монстра, с модельками и анимацией всё в порядке, но:
вылеты
expression : fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description : <no expression> Arguments : LUA error: ...lker_soc\datas\gamedata\scripts\smart_terrain.script:1137: attempt to call method 'smart_terrain_id' (a nil value)
if нпс залезет в аномалию\его прибъёт другой монстр
expression : fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description : <no expression> Arguments : LUA error: ...alker_soc\datas\gamedata\scripts\xr_statistic.script:105: attempt to concatenate local 'community' (a nil value)
if гг убъёт нпс
Автор: Darien 25.12.2009, 19:08
Цитата(whoami @ 20.12.2009, 12:14)
...продолжаю работу одного человека по воссоздания крысы, как полноценно играбельного монстра, с модельками и анимацией всё в порядке, но:
вылеты
expression : fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description : <no expression> Arguments : LUA error: ...lker_soc\datas\gamedata\scripts\smart_terrain.script:1137: attempt to call method 'smart_terrain_id' (a nil value)
if нпс залезет в аномалию\его прибъёт другой монстр
expression : fatal error Function : CScriptEngine::lua_error File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp Line : 73 Description : <no expression> Arguments : LUA error: ...alker_soc\datas\gamedata\scripts\xr_statistic.script:105: attempt to concatenate local 'community' (a nil value)
if гг убъёт нпс
Я в этом не очень разбрираюсь, но ответить попробую: 1)Либо ты используешь метод класса, который не поддерживает этот метод, либо сам метод не существует. 2)Возможно, ты не правильно используешь concat. Помимо чисел и строк что-нибудь пытаешься соединить? Сейчас буду проверять из-за чего выскакивает.
Кидай сюда обе ф-ии, разберёмся.
Автор: whoami 03.01.2010, 11:53
спасибо за ответ...
Цитата
1)Либо ты используешь метод класса, который не поддерживает этот метод, либо сам метод не существует.
вообщето да, секция конфига крысы базирована на конфиге тушкана ([m_rat_e]:m_tushkano_e), но класс крысячий
Цитата
2)Возможно, ты не правильно используешь concat.
эээм... скрипты вообщето я не трогал
Автор: dnepar 03.01.2010, 11:55
люди тут вопрос у меня возник
Автор: eNdimion 14.01.2010, 21:58
Код
[i]У объекта сталкера можно вызвать скриптовые функции flags32 get_actor_relation_flags() set_actor_relation_flags(flags32)
Т.е. предполагается работь следующим образом: Смотрим, когда есть такая возможность и актер рядом, что флажки не пустые. В соответствии с поднятым флагом выполняем какое-то действие (устанавливаем диалог, играем звук/анимацию), а потом сбрасываем флаг.[/i]
честно сказать не очень шарю в скриптинге... это работает?
Автор: -=Kurt=- 10.02.2010, 23:27
Цитата(macron @ 16.12.2009, 21:36)
ЗЫ: возник ряд вопросов по скриптам: 1. Можно ли скриптом разрешить трупу/с трупа жрать аптечку или еду? Чтобы на 6 патче не вылетало.
Я в любом случае не отвечу, н омне просто интересно, что значит эта фраза .
Цитата
3. Нужен скрипт для переключения оружия из одного слота без захода в инвентарь: то есть, допустим, у нас в руках автомат и в рюкзаке автомат. Нажимаем на 3, и оружие меняется.
+1 - тоже интересует этот вопрос. Макрон, ты случаем не над мп-модом трудишься? Напоследок, вопрос ко всем: можноли в мп скриптом лечить актора при наличии у него в инвентаре аптечки? Я давным-давно пробовал переделать сингловый скрипт, но ничего не вышло....
Автор: bill_gates 10.04.2010, 21:23
Люди, а что такое нетпакет? И зачем он нужен?
Автор: rekongstor 16.04.2010, 14:59
Как спавнить через Net Packet?
Автор: Scarabay 24.07.2010, 22:19
Всем привет. Может кто поделится функцией определения визуала нпс? Или хотя бы расскажите как считать необходимые данные из нет-пакета? Заранее спасибо.
Автор: djslavikoz 29.09.2010, 07:25
Подскажите пожалуста функцию спавна вертольота через скрипт. Желательно подробно что и куда нада писать
Автор: сталкероид 29.09.2010, 23:07
Цитата(bill_gates @ 10.04.2010, 21:23)
Люди, а что такое нетпакет? И зачем он нужен?
Буквально "сетевой пакет". Небольшая область памяти (8 кбайт), в которую записывается текущее состояние какого-либо объекта (актора, непися и т.д.), т.е. количество лута в инвентаре, список хабара в нычках, выполненные квесты, статистика и пр. Работать с ним можно, только когда объект находится в оффлайне. Подробнее от нет_пакете и не только http://www.amk-team.ru/forum/index.php?showtopic=7450&view=findpost&p=258470 djslavikoz, какой именно вертолет? Если просто валяющийся на земле, то прописать его в алспавне по аналогии с другими трупиками вертолетов, а если прилетающий по какому-то событию, то тогда все гораздо сложнее - надо прописать рестриктор и написать вертолету логику (можно глянуть например http://stalkerin.gameru.net/wiki/index.php/%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0_%D0%BB%D0%BE%D0%B3%D0%B8%D0%BA%D0%B8._%D0%A7%D0%B0%D1%81%D1%82%D1%8C_4#3.12._.D0.9B.D0.BE.D0.B3.D0.B8.D0.BA.D0.B0_.D0.B2.D0.B5.D1.80.D1.82.D0.BE.D0.BB.D1.91.D1.82.D0.B0).
Автор: djslavikoz 30.09.2010, 07:23
Сталкероид В основном я научился спавнить через all.spawn . Ну примерно вот так.
[10001] ; cse_abstract properties section_name = helicopter name = esc_heli_55555 position = 57.8794326782227,-0.705963671207428,114.27214050293 direction = 0,-1.47526597976685,0
; cse_alife_helicopter properties cse_alife_helicopter__unk1_sz = idle engine_sound = alexmx\helicopter Вопрос так в чём моя проблема????? Проблема в том что я создал новую локацию(военную базу) и когда делаю таким способом как на ескейпе то получаю лог вот такого плана. FATAL ERROR
Вообще, ругается на то, что не может найти цикл анимации (есть такой файлик .skl). Попробуй вообще убрать эту строку в алспавне motion_name = helicopter\aaa.anm . К чему это относится: cse_alife_helicopter__unk1_sz = idle?
Автор: djslavikoz 05.10.2010, 10:19
Господа скриптологи помогите пожалоста. Лог по вашей теме. Ето спавн вертольота. Как написал мне на амк форуме один товарищ.... Цытирую
Надо дописать функцию в xr_effects.script, какую я не знаю, сам не делал.
! Unknown command: ERROR:object * Log file has been saved successfully!
FATAL ERROR
[error]Expression : fatal error [error]Function : CScriptEngine::lua_error [error]File : E:\stalker\patch_1_0004\xr_3da\xrGame\script_engine.cpp [error]Line : 73 [error]Description : <no expression> [error]Arguments : LUA error: ....r. - shadow of chernobyl\gamedata\scripts\_g.script:20: bad argument #2 to 'format' (string expected, got no value)
Автор: Lekzd 05.10.2010, 10:46
djslavikoz, вот нет, чтобы сравнить файлы без изменений и с изменениями (программа для этого специальная есть) не уповай на экстрасенсов - их тут нет
Автор: nike88 05.10.2010, 12:13
djslavikoz допиши что-то типа
Код
function уровень_heli_mapspot(actor, npc, p) if p[1] and not level_tasks.is_map_spot_present( p[1], "anomaly_zone_location" ) then level_tasks.add_location( p[1], "anomaly_zone_location", "vertolyot!" ) end end
Автор: RedPython 24.10.2010, 17:34
Как можно получить имя текущей погодной секции? Нужно что-то типа level.get_weather_name()
Автор: Erwin Rommel 25.10.2010, 08:53
Поставь ватчдог от АМК и смотри в консоли погодные секции. Проследи работу игры
Автор: Kolmogor 25.10.2010, 10:56
Цитата(RedPython @ 24.10.2010, 18:34)
Как можно получить имя текущей погодной секции? Нужно что-то типа level.get_weather_name()
level.get_weather()
Автор: djslavikoz 27.02.2011, 10:58
Ребята вот пример спавна через скрипт:
local zombie_types = {"zombie_weak", "zombie_normal", "zombie_strong", "zombie_immortal", "zombie_ghost"} function spawn_zombies( position, total ) local zombie_index local new_pos, x_offset, z_offset for zombie_index=1, total do x_offset = math.random(5) z_offset = math.random(5) new_pos = position new_pos.x = new_pos.x + x_offset new_pos.z = new_pos.z + z_offset alife():create(zombie_types[math.random(5)],new_pos,326087,91) end end function zombie_story_1(actor, npc) local spawn_point = vector():set(43.21, 2.14, 47.16) spawn_zombies(spawn_point, 10) end
Скажите пожалуйста ,а можно в этом скрипте прописать логику ?????
Автор: BelKa Production 21.07.2011, 16:46
djslavikoz, У меня вместо слов - черные линии. Я не большой спец. по скриптам. Может я и ошибаюсь, но в скрипте логику приписать нельзя
Автор: Modera 21.07.2011, 16:49
угу её надо писать в конфе т.е. надо создать новый тип зомбей с костюм датой
Автор: K.D. 21.07.2011, 19:55
логику вписать можно. Но надо перезаписывать нет-пакет. Скрипт по объему вырастет сурово)
Автор: alg0r1tm 11.10.2011, 14:32
Помогите плиз разобратся в сне от АМК Цель такова: нужно сделать сон как в билдах через инвентарь Простите за банальность
Зы, не пинайте только) я в скриптах null
Автор: Policai 23.02.2012, 07:34
Народ!!!! Нужна помощь гуру!
Анимация - дверь сдвигающаяся всторону, 1 кость, сдвиг вправо на 1.5 метра, 3 секунды пауза и сдвиг обратно на место.(Самодельный обьект, ставлю через спавн, в сдк анимация работает) Попытался запустить анимацию по анологии лабы х-8 из припяти. В кустом дата прописана ссылка на логику, с текстом:
Дверь [collide] ignore_static
[animated_object]
Пульт взят оттуда же , с родной логикой, я просто изменил на своё название анимации, спейса и смарта:
Всё проходит до запуска анимации, то есть без карты требует карту доступа, с картой появляется сообщение доступ разрешён, потом завис на 3-4 секунды, (в этот момент должна отработать анимация), и вылет с жалобой:
Лог FATAL ERROR [error]Expression : !m_error_code [error]Function : raii_guard::~raii_guard [error]File : D:\prog_repository\sources\trunk\xrServerEntities\script_storage.cpp [error]Line : 748 [error]Description : ....r. - Зов Припяти\gamedata\scripts\xr_effects.script:1317: attempt to index field '?' (a nil value) stack trace:
Понимаю что это всё туфта, просто я в скриптах ноль, и пытаюсь разобраться методом тыка.
xr_effects родной нетронутый. Подскажите куда ткнуться.
Автор: Ким 23.02.2012, 08:40
Policai, xr_effects, строчки с 1314 по 1320: function anim_obj_forward(actor, npc, p) for k,v in pairs(p) do if v ~= nil then db.anim_obj_by_name[v]:anim_forward() - 1317 строка end end end твоя логика [ph_button@unlocked] anim = idle tooltip = st_lx8_button_press_true on_game_timer = 20 | {-lx8_door_open} %+lx8_door_open =anim_obj_forward(lim_door_laba_hide)% - ссылается на 1317 строку on_game_timer2 = 10 | {-lx8_green_on} %+lx8_green_on =turn_off(lx8_light_switch_1_red_id) =turn_on(lx8_light_switch_1_green_id)% on_info = {=actor_in_zone(lim_sr_actor_in_lab) -lim_actor_in_lab} %+lim_actor_in_lab =create_squad(lx8_polter_squad:lim_smart_terrain)%
Что-то не так с названием анимки, либо она не подходит.
Кстати, ты на ТЧ это делаешь?) Если на ТЧ, то надо допилить этот самый эффектс, три функции, как минимум, добавить.
Автор: Policai 23.02.2012, 09:07
Цитата
Что-то не так с названием анимки, либо она не подходит.
Кстати, ты на ТЧ это делаешь?) Если на ТЧ, то надо допилить этот самый эффектс, три функции, как минимум, добавить.
Ким В этом то и проблема, анимка другая, на родной двери от этого скрипта 9 костей и работает на поворот, но она работает анимацией, и прописана анимацией, моя анимация - одна кость и работает на сдвиг, я просто не знаком со скриптами и попытался методом тыка подсунуть. Платформа ЗП. Гугл не помогает, а я не знаю как это делается. Мне нужно просто запустить выбранную анимацию по команде. Такая же проблема у меня и с мостом в рыжем лесу, не хочет он опускаться когда мне надо, попытался проследить скрипты с которыми он работает в оригинале ЧН, заблудился, там их штук 20 задействовано. Вопрос такой: Как простейшим методом запустить выбранную анимацию по некой команде.
Автор: Ким 23.02.2012, 10:47
Policai, вот так и вызывается. Пример простой логики для теста: [logic] active = ph_button@test
Насчёт двери не знаю как привязать анимку, вечером ещё гляну
По идее к двери не привязана анимка, она просто переходит в состояние "открыто" (во всяком случае анимка не указывается в логике, где-то в скриптах может быть) там просто переход к другой логике, где дверь: "locked = false"
Чисто теоритечески логика для двери: [logic] active = ph_door@test
[ph_door@test] anim = idle on_info = {+door_open} %=anim_obj_forward(анимация_открытия)% должна работать, по идее функция указана в xr_effects, а значит должна вызываться для любых объектов (такого типа). Попробуй привзять стандартную анимаку через эту логику, если заработает, значит и твоя анимка будет работать
Автор: Policai 23.02.2012, 10:49
Тут вроде понял, возник сразу вопрос, логика двери??? У меня простая анимация, вернее в максе вшил 3 одна просто открытие open, вторая закрытие close, и третья полный цикл: открытие, задержка в открытом состоянии 3 секунды и закрытие idle. Вшил также две контрольные точки, закрытая дверь и открытая дверь. Теперь можно по подробнее по логике двери? что это? анимация вшитая или писать логику для неё надо?
Цитата
просто я в скриптах ноль, и пытаюсь разобраться методом тыка
Автор: Ким 23.02.2012, 10:55
Вообще в xr_effects указано три типа функций - anim_obj_forward, anim_obj_backforward и anim_obj_forward (reset, точного названия не помню). Соотвественно все три можно вызывать из логики.
"Тут вроде понял, возник сразу вопрос, логика двери??? У меня простая анимация, вернее в максе вшил 3 одна просто открытие open, вторая закрытие close, и третья полный цикл: открытие, задержка в открытом состоянии 3 секунды и закрытие idle. Вшил также две контрольные точки, закрытая дверь и открытая дверь. Теперь можно по подробнее по логике двери? что это? анимация вшитая или писать логику для неё надо?" я них.. ничего не понял Да, в спавне укажу путь к кастомдате двери, по этому пути создай лтх файл логики (с соответствующим названием), туда напиши логику, что я тебе написал) Ну, знаешь ли, без логики анимация как бы не работает А вот то, что ты написал в первом посте - это привязка к кнопке, естественно кнопка не может открыться, это же кнопка, а не дверь)
Policai, там ничего сложного, поверь) Просто большинство скриптов написано.. эм.. как бы сказать.. некомпетентными людьми)
Вот смотри, логика для двери, используется у нас в "Обливион Лосте" (в бета тесте отсутствует): [logic] active = ph_door@locked
[ph_door@locked] locked = true on_info = {+quest_gr_art_1_start} ph_door@close - игрок получает первое задание и дверь открывается, ну прям как в ТЧ tip_open = tip_door_locked snd_open_start = trader_door_locked not_for_npc = true
первом посте - это привязка к кнопке, естественно кнопка не может открыться, это же кнопка, а не дверь)
Я сделал по анологии, именно так сделан вход в лабу х-8. на двери прописано что это анимация а на пульте то что у меня в посте, я и сделал также....
наверно по разному общаемся... да и трудно обьяснить тупому мне.... я работаю не с аллспавном а в сдк.
Я сделал так: ставлю физик\ доор, присваиваю визуал моей двери, прописываю там анимацию полную idle, (Мне надо чтоб дверь открылась и закрылась сама )в кустом дате указываю путь к файлу лтх с названием как у этой двери. В этом лтх прописываю:
[collide] ignore_static
[animated_object]
ставлю пульт сбоку и прописываю в кустом дата путь к лтх с названием как и у пульта, в лтх прописываю:
Именно так сделано в ЗП вход в лабу х-8. Жирным выделено то что я поменял на своё, всё остальное так как было в оригинале. Карточку заспавнил рядышком и проверяю в игре. Подхожу к пульту, появляется надпись нужна карта доступа, отхожу , беру карту, подхожу с картой, появляется надпись Открыть, нажимаю ввод появляется надпись Доступ разрешён потом 3-4 секунды и вылет с жалобой на строку 1317. Я понимаю что эта анимация просто не прописана поэтому вылет. Я также понимаю что скорее всего логика на ту родную анимацию уже есть в файлах игры где то, вопрос где?
Извини пожалуста Ким что я такой навязчивый, просто у меня очень много анимаций по всем локам, и мне хотелось бы понять что то общее, чтоб не искать ответы на вопросы по каждой анимации. Скорее всего я не прав, но мне кажется почему то, что будет проще работать если у меня будет какой то основной общий скрипт, прописанный с небольшими изменениями или на пульте с картой или на пульт с кнопками, или просто в спейс рестрикторе, скрипт который просто даёт команду на запуск выбранной анимации.
Автор: Ким 23.02.2012, 12:51
Policai, погоди, но зачем создавать анимку, если такая уже есть? Возьми аналог (те же двери лифта) и установи их на дверь (в тч - это проход со свалки к бару).
Автор: Policai 23.02.2012, 13:08
Тут ситуация такая что таких анимок нету..... Моя дверь это стена отьезжающая вбок.... или круглая бункерная дверь, плюс сама анимация с другими костями и цикличная. Те анимации которые уже есть подходящие для меня, я использую, с ними нет проблем, проблемы только с новыми анимациями.
Автор: Ким 23.02.2012, 13:12
Policai, тогда их надо прописывать в скриптах, но там будет куча возни. Вообще анимка отъезжающей двери быть таки должна)
Автор: Policai 23.02.2012, 13:27
В ЗП нету отьезжающих дверей...... повырезали всё, есть лифтовые двери но там нет анимации как таковой, там 2 положения, открытые и закрытые, типо актор не видит сам процесс открывания, думаю это сделать проще.... а мне надо именно чтоб был этот сам процесс открытия двери... в этом весь смак... с ТЧ и ЧН в ЗП не работают скрипты, с мостом в рыжем лесу такая же проблема....
Автор: Dart_Sergius 23.02.2012, 21:22
Цитата(Ким @ 23.02.2012, 13:12)
Policai, тогда их надо прописывать в скриптах, но там будет куча возни.
Кстати интересный вопрос где их прописывать. Тоже интересовала эта проблема, решения пока не нашёл.
Автор: Ким 24.02.2012, 08:08
Dart_Sergius, скорее всего в ph_door, там смещение каждого объекта надо будет указать и т.д. Либо с нуля написать скрипт логики.
Автор: Policai 26.02.2012, 17:08
Ким Всё разобрался..... сделал, всё гораздо проще чем кажется..... Единственный минус что на любую анимацию я использую логику двери...... какие могут быть последствия? А так работает всё как надо, и не нужно писать скрипт логики с нуля.
Сейчас у меня практически на одинаковой логике работает анимация стены сдвигающейся в сторону, управление с пульта, и подьёмный мост с рыжего леса, управление с рубильника, и самодельная дверь, тоже с пульта...
Автор: Ким 26.02.2012, 17:29
Policai, ну ка напиши в чем проблема была, а то кому-нибудь понадобится) Последствия? Да вроде не должны быть, единственное в игре не красиво будет.
Автор: Tron 28.02.2012, 16:12
скажу сразу,что в lua,я почти профан(синтаксиса не знаю) и сейчас его прикручиваю к движку Возможен ли precache?-т.е инклуд скрипта,но его выполнение будет происходить только после вызова именно этого скрипта.. Читал про "http://www.gamedev.ru/code/forum/?id=119712",но у автора почти такая же байда как и у меня
Вводить собственный precache всех ресурсов не хотелось бы-нужны именно скрипты
Автор: [=sinedsc=] 09.05.2012, 10:18
Параметр в кастом дате смарт террейна
Код
stay = min[, max] ;время, на которое сталкер останется, умолчание=навсегда
как задаются параметры min и мах? пытался задавать так
Код
stay = 9, 11
пишет что инвалидный параметр. Подскажите как задать этот параметр
Автор: Tron 02.06.2014, 02:12
Забыл отписать-разобрался в своей проблеме. Линковал статически луабинд,ко многим длл.кам из проекта,и передавал туда lua_state. Вообще странно было,что статические функции работали
Автор: Alwen 11.06.2014, 17:41
Вопрос по работе диалогов. В чем может быть ошибка?
dialogs_escape.script
function money_check_1() return db.actor:money() >= 10 end
function fuel_to_actor_1(oSpeaker1, oSpeaker2) dialogs.give_items("explosive_mobiltank", 1) dialogs.relocate_money(oNPC, 10, "out") end
function money_check_2() return db.actor:money() >= 20 end
function fuel_to_actor_2(oSpeaker1, oSpeaker2) dialogs.give_items("explosive_mobiltank", 2) dialogs.relocate_money(oNPC, 20, "out") end
function money_check_4() return db.actor:money() >= 40 end
function fuel_to_actor_4(oSpeaker1, oSpeaker2) dialogs.give_items("explosive_mobiltank", 4) dialogs.relocate_money(oNPC, 40, "out") end
function no_money_for_fuel() return db.actor:money() >= 0 end
<phrase id="7"> <precondition>dialog_escape.no_money_for_fuel</precondition> <text>Походу, пока тебе с твоими деньгами только пешеходом быть.</text> </phrase>
</phrase_list>
</dialog>
При кликах на пункты с выбором(3, 4, 5) иногда выкидывает фразу из диалога "не хватает денег", как будто врет функция money_check_X. При повторном клике все идет как надо и это сообщение выскакивает когда положено.
За основу взял диалог с покупкой авто у Бармена из LA, и там не понятно назначение функции в конце:
Цитата
function not_has_car_money() return not has_car_money() end -- has_car_money - денег >= цене самого дешевого автомобиля
, которая является предусловием для пункта диалога "у тебя нет денег" в dialogs.xml
Что эта функция выполняет, если и так по умолчанию при недостатке денег диалог на "нет денег" и ссылается?
Автор: K.D. 11.06.2014, 18:11
Цитата(Alwen @ 11.06.2014, 18:41)
function no_money_for_fuel() return db.actor:money() >= 0 end
Уверен?
Автор: Alwen 11.06.2014, 18:46
Цитата(K.D. @ 11.06.2014, 19:11)
Цитата(Alwen @ 11.06.2014, 18:41)
function no_money_for_fuel() return db.actor:money() >= 0 end
Уверен?
Нет. Но если делать как у торговли авто ЛА, с предусловием актор_мани() <= мин_цена_айтема, то при выборе самого дорого товара и недостатке денег на него стабильно получаю вылет No available phrase to say, dialog[esc_need_fuel]
Автор: K.D. 11.06.2014, 19:09
Цитата(Alwen @ 11.06.2014, 19:46)
Нет. Но если делать как у торговли авто ЛА
Причем тут ЛА? Очевидно же, что функция возвращает true всегда, когда у актора есть деньги. Т.о. прекондишн твоей фразы про нехватку денег всегда пропускает эту фразу. Делай конкретно в этом месте < 10. Upd: лучше сделать так, наверное. Сделай для каждой фразы свою фразу отказа и там отдельную функцию no_money с разными количествами проверямых денег.
Автор: Alwen 11.06.2014, 20:01
Второй вариант сделал, но мучает этот вылет "No available phrase to say, dialog[esc_need_fuel]", если нажимать вариант на 40 при 30 денег в инентаре.
dialog_escape.script
function money_check_1() return db.actor:money() >= 10 end
function fuel_to_actor_1(oSpeaker1, oSpeaker2) dialogs.give_items("explosive_mobiltank", 1) dialogs.relocate_money(oNPC, 10, "out") end
function money_check_2() return db.actor:money() >= 20 end
function fuel_to_actor_2(oSpeaker1, oSpeaker2) dialogs.give_items("explosive_mobiltank", 2) dialogs.relocate_money(oNPC, 20, "out") end
function money_check_4() return db.actor:money() >= 40 end
function fuel_to_actor_4(oSpeaker1, oSpeaker2) dialogs.give_items("explosive_mobiltank", 4) dialogs.relocate_money(oNPC, 40, "out") end
Перенеси весь текст (<text></text>) в любой файл из config\text\rus.
Автор: abramcumner 11.06.2014, 20:52
Цитата(Alwen @ 11.06.2014, 21:01)
Код
function no_money_for_fuel() return not money_check_1 end
А в ЛА-то скобочки были:
Код
function not_has_car_money() return not has_car_money() end
Может проще добавить эти канистры в продажу по десяточке?
Автор: Alwen 11.06.2014, 21:50
Про скобочки забыл Теперь все заработало. Спасибо всем отписавшимся.
Автор: hi_flyer 07.07.2014, 19:36
Ни у кого случайно не остался xs_sandbox от xStream ? Скиньте у кого есть плиз.
Автор: Pavel_Blend 16.12.2014, 19:46
Хочу изучить луа. Скачал интерпретатор, пишу код. Но когда запускаю скрипт двойным щелчком мыши, он выполняется и окно сразу закрывается. Как заставить консольное окно не закрываться? Чтобы можно было посмотреть на результат работы.
Автор: Modera 16.12.2014, 19:58
Pavel_Blend, pause
Автор: Pavel_Blend 16.12.2014, 22:06
Modera, это в батнике писать ведь? А стандартными средствами луа это никак не сделать? Чтобы в самом коде это было прописано. Я ведь скрипты не через батники хотел запускать, а двойным щелчком.
Автор: HikeR 16.12.2014, 22:47
выкиньте мышь и осваивайте консоль. cmd -> lua.exe script.lua -> результат работы.
Автор: Forser 11.09.2015, 19:49
Цитата(hi_flyer @ 07.07.2014, 19:31)
Ни у кого случайно не остался xs_sandbox от xStream ? Скиньте у кого есть плиз.
https://yadi.sk/d/GV1pRum8ibXrK
Автор: evg 30.11.2016, 03:39
как создать новый ammo_class для оружия
Автор: aka_sektor 26.04.2017, 13:58
А вот такой вопрос: возможно ли вынести текст о версии мода из скрипта ui_main_menu.script, в какой-нибудь конфиг? в скрипте он прописан как:
Просто в чем суть, при обновлении мода, нужно менять скрипт, а если этот мод ещё куда-то адаптирован, то нужно будет повторно скрипт менять. Не проще ли в одном конфиг файле версию менять и все?
Автор: RayTwitty 26.04.2017, 20:28
Цитата(aka_sektor @ 26.04.2017, 14:01)
Не проще ли в одном конфиг файле версию менять и все?
АМК в 2008 году это сделали.
Автор: Forser 26.04.2017, 23:14
Цитата(RayTwitty @ 26.04.2017, 20:31)
Цитата(aka_sektor @ 26.04.2017, 14:01)
Не проще ли в одном конфиг файле версию менять и все?
АМК в 2008 году это сделали.
Ты сейчас про xml?
Автор: aka_sektor 27.04.2017, 00:14
Цитата(RayTwitty @ 26.04.2017, 20:31)
АМК в 2008 году это сделали.
Угу, похоже на то:
ТЧ финалка
Код
function main_menu:InitControls() self:Init(0,0,1024,768) local xml = CScriptXmlInit() xml:ParseFile("ui_mm_main.xml")
news_id - это текст сообщения, т.е. string id. В моей логике имя sad_artefact_upgr_ready sender - это иконка в секции tips_icons news_manager.script. В моей логике имя sad_atr_trader sender_id - а это заголовок сообщения, story_id NPC.
story_id моего персонажа прописан в файле по пути: gamedata\configs\creatures\spawn_sections_sad.ltx
Дело в том, что хоть story_id и указан, заголовок все также остается как "Сообщение".
Автор: aka_sektor 11.06.2017, 23:02
UPD: Я все-таки думаю, что story_id читается, но не отображается. Потому что, если указать другое имя, не являющееся story_id - игра вылетит. Думаю, дело в функции send_tip в news_manager.script. Там не прописано отображение имени. Возможно, что-то со времен прошлых игр удалили из скриптов, т.к. я действительно не помню чтобы в ЗП игрок получал сообщения с подписанным именем NPC.
Автор: AndreySol 24.06.2017, 09:03
Цитата(aka_sektor @ 11.06.2017, 22:45)
...чтобы в сообщении указывалось имя NPC, а не писалось "Сообщение".
Цитата
Думаю, дело в функции send_tip в news_manager.script. Там не прописано отображение имени.
Зачем гадать ? Открыть скрипт и посмотреть код !
Код
local news_text = "%c[255,160,160,160[b]]"..game.translate_string("st_tip").."[/b]\\n".."%c[default]"..game.translate_string(news_id) actor:give_game_news(news_text, "ui\\ui_iconsTotal", Frect():set(x,y,83,47), timeout*1000, showtime)
st_tip(в gamedata\config\text\rus\ui_st_pda.xml): <string id="st_tip"> <text>Сообщение</text> </string> Если очень хочется - доработать ф-цию, в ее начале по StoryID получаем объект, соответственно получить от объекта его игровое имя и подставить вместо game.translate_string("st_tip").
Автор: aka_sektor 24.06.2017, 10:55
AndreySol, сорян, тут не отписался, уже давно разобрался. Подсказали правильную функцию: http://ap-pro.ru/forum/114-90122-1046243-16-1497252988
Логику закрывающих ключевых слов проверьте. Выход из выражения не в том месте.
Автор: Anarchy 12.07.2017, 17:19
Подскажите. Всеми известный скрипт xrs_armor.script будет работать на платформе зп, если заменить все переменные, или всё же требуется изменение скрипта?
Автор: NanoBot-AMK 21.07.2017, 20:06
Сейчас работаю над новым гравиприводом, обнаружил такой баг, когда НПС выхватывает оружия у врага, и притягивает его с себе, то срабатывает команда self.target:transfer_item(self.target, self.parent), и захваченное оружие отправляется к НПС в инвентарь, в логе выскакивает: ~ ERROR: can't detach independant object. entity[wpn_bm160159:159], parent[wpn_bm160159:159], section[wpn_bm16] И меняется у НПС clsid с script_stalker=33 на 83. Мод AI additions версия 2.0 fix3 Может именно в нём дело. Кстати, да, у меня НПС могут использовать гравипривод, выхватывая оружие у врагов, и ещё в планах научить доставать разные вещи из аномалий.
Автор: NanoBot-AMK 08.08.2017, 23:44
У кого есть дока по методам для управления сталкеров типа set_item и другим методам? Что у меня плохо получается непысей программировать.
Автор: Gaz24 21.09.2017, 23:24
Всем привет. Мне нужно удалить вещи из инвентаря НПС при старте игры (например удалить ПДА), причем отдельным скриптом. Проблема заключается в подключении. Пробовал через bind_stalker и xr_motivator подключать, не получается. Хотя в Ai Addtitions спавн вещей через скрипт работает (в сехеме rx_knife функция spawn_knife(npc)).
Автор: aka_sektor 21.09.2017, 23:37
Цитата(Gaz24 @ 21.09.2017, 23:24)
удалить вещи из инвентаря НПС при старте игры
А изначально его инвентарь отредактировать что мешает?
Автор: Gaz24 22.09.2017, 06:29
Цитата(aka_sektor @ 22.09.2017, 00:37)
Цитата(Gaz24 @ 21.09.2017, 23:24)
удалить вещи из инвентаря НПС при старте игры
А изначально его инвентарь отредактировать что мешает?
Проблема в том, что ПДА для сталкеров не прописывается ни в конфигах, ни в скриптах. Так что мне надо его удалить через скрипт.
Автор: aka_sektor 22.09.2017, 11:24
Цитата(Gaz24 @ 22.09.2017, 06:29)
ПДА для сталкеров
А каким образом он вообще попадает NPC в инвентарь? Какой-то мод? В оригинале не выпадали им КПК. Глянул бы как там устроено в моде то, может банальный death_manager.
Автор: RayTwitty 22.09.2017, 13:42
Цитата(Gaz24 @ 22.09.2017, 06:29)
что ПДА для сталкеров не прописывается ни в конфигах, ни в скриптах
config\gameplay\character_*.xml файлы персонажей смотрел? ПДА там должен прописываться.
device_pda, вроде так называется.
Автор: Gaz24 22.09.2017, 17:40
Цитата(RayTwitty @ 22.09.2017, 14:42)
config\gameplay\character_*.xml файлы персонажей смотрел? ПДА там должен прописываться.
device_pda, вроде так называется.
Искал Notepad'ом++. Выдало только 1 результат, да и то в энциклопедии. Я уверен что спавн ПДА очень хитро завязан профили персонажей.
Это просто статья в "энциклопедии". В оригинале, описание предметов выпилили из КПК в ТЧ. Восстановлено в "Истории Прибоя".
Ты хоть заскринь, что имеешь ввиду. Ты так и не ответил, что там у тебя? Мод или что?
В ТЧ есть секция device_pda в gamedata\config\misc\items.ltx
Автор: Gaz24 22.09.2017, 18:10
Цитата(aka_sektor @ 22.09.2017, 18:45)
Ты хоть заскринь, что имеешь ввиду. Ты так и не ответил, что там у тебя? Мод или что?
Прошу прощения. Я пока в чистом ТЧ делаю эту фичу, но потом добавлю ее свой мод. Хочу удалить из инвентаря неписей пда. Я заметил, что если удалить пда у живых неписей, то в контактах они не будут отображаться. Причем сделать так, что у них в место пда был предмет "выключенный пда или т.п." на классе антирадина или гитары. И хотел бы сделать в отдельном скрипте через подключение в bind_stalker и xr_motivator.
Такая идея у меня появилась после Lost Alpha, где враги в контактах не отображались.
Секцию пда в items.ltx смотрел. Ничего интересного в ней не нашел. Разве что проверить класс в ресурсах или исходниках.
Автор: aka_sektor 22.09.2017, 18:12
Цитата(Gaz24 @ 22.09.2017, 18:10)
Я пока в чистом ТЧ делаю эту фичу
Прикалываешься? Сам добавил, а потом спрашиваешь как удалить. Все я сваливаю...
Автор: Gaz24 22.09.2017, 18:15
Цитата(aka_sektor @ 22.09.2017, 19:12)
Сам добавил, а потом спрашиваешь как удалить.
В том то и дело, что я ничего не добавлял. Потому и спрашиваю где у сталкеров пда спавнится, если нет никаких секций спавна ни в конфигах, ни в скриптах.
Автор: RedPython 22.09.2017, 19:03
Боюсь, что пда — это часть сущности сталкиров в системе алайф нехай программисты скажут точно
Автор: hi_flyer 22.09.2017, 19:21
Если не ошибаюсь, ПДА ровно как и болт спавнит движок в НПС. Без сторонних .ltx или .xml
Автор: RayTwitty 22.09.2017, 19:26
Цитата(Gaz24 @ 22.09.2017, 18:10)
Я заметил, что если удалить пда у живых неписей, то в контактах они не будут отображаться
Ясен пень, ПЫС на этапе тру разработки сделало все по уму - отображаются не НПС на карте, а именно ПДА)
Кстати, а ведь в оригинале ПДА скрыты при обыске, ибо находятся в слоте. Так зачем удалять их?
Автор: SkyLoader 22.09.2017, 19:32
Если в игре ломаются скрипты(биндеры), то после смерти неписей можно увидеть у них в инвентаре пда, гармошки, гитары, которые из за поломки скриптов не удаляются. Причем пда имеет название, завязанное на имени непися, например, "Пда Васян Маслинный". Очевидно предположить, что это делается в движке, так как пда и непись связываются. Удалить пда у живого непися скорее всего можно, но это может повлечь за собой последствия. Лучше не стоит этого делать.
Автор: Gaz24 22.09.2017, 19:38
Цитата(RayTwitty @ 22.09.2017, 20:26)
Кстати, а ведь в оригинале ПДА скрыты при обыске, ибо находятся в слоте. Так зачем удалять их?
Они не скрыты. После смерти удаляются detath_manager'ом. А удалить ПДА я хочу чтобы вместо него добавить в инвнтарь неписю предмет "выключенный пда" или вообще не ничего не добавлять, чтобы придать некого реализма.
Автор: AndreySol 23.09.2017, 08:01
Цитата(Gaz24 @ 22.09.2017, 20:38)
... чтобы вместо него добавить в инвнтарь неписю предмет "выключенный пда" или вообще не ничего не добавлять, чтобы придать некого реализма.
В чем реализм - сталкер, которому прилетело насмерть в голову, все-же успел выключить ПДА... "из последних сил"?
Автор: Gaz24 23.09.2017, 12:33
Цитата(AndreySol @ 23.09.2017, 09:01)
В чем реализм - сталкер, которому прилетело насмерть в голову, все-же успел выключить ПДА... "из последних сил"?
Реализм заключается в том, что ПДА удаляется и спавнится вместо него "выключенный" еще у живых нпс . Например чтобы не палится в контактах других у сталкеров, или вообще ПДА сломан у него, ну и т.д.
Автор: aka_sektor 05.12.2017, 20:04
Словил тут вылет, когда помер в ЗП:
Код
xr_conditions.script:2196: attempt to index field 'actor' (a nil value)
Точнее при загрузке последнего сохранения.
В кондишнс у меня добавлен код:
Код
function sad_predateli_pda() if (db.actor:object("sad_mudak_pda") ~= nil) and not (db.actor:has_info("sad_predateli_info")) then db.actor:give_info_portion("sad_predateli_info") end end
2196 это вторая строка, которая if В чем тут дело?
Изначальная функция взята отсюда: http://www.amk-team.ru/forum/topic/8806-cop-kvesty/?page=2&tab=comments#comment-349951
Автор: RayTwitty 05.12.2017, 20:15
Цитата(aka_sektor @ 05.12.2017, 20:04)
при загрузке
Ты хочешь получить клиентский объект актора до того как он появился. Это надо делать на net_spawn или ставить колбек на выход в онлайн (тема избитая).
Автор: aka_sektor 05.12.2017, 20:48
Цитата(RayTwitty @ 05.12.2017, 20:15)
ставить колбек
Да, там ниже это и предложили: http://www.amk-team.ru/forum/topic/8806-cop-kvesty/?do=findComment&comment=350365
Вот только с колбеком on_item_take есть косяк, описанный в этом посте: http://www.amk-team.ru/forum/topic/6185-skriptovanie/?do=findComment&comment=1122162
Цитата(RayTwitty @ 05.12.2017, 20:15)
надо делать на net_spawn
Можешь показать?
Вообще, предложили дописать проверку актера на nil, вот так:
Код
function sad_predateli_pda() if db.actor ~= nil and db.actor:object("sad_mudak_pda") ~= nil and not db.actor:has_info("sad_predateli_info") then db.actor:give_info_portion("sad_predateli_info") end end
UPD: Проверил - больше не вылетает.
Автор: RayTwitty 27.05.2018, 17:00
Запамятовал, ключом таблицы в Lua может быть только строка или целое число?))
upd:
Цитата
Тип table (таблица) реализует ассоциативные массивы, это значит, что массив может быть проиндексирован не только числами, но и любым Lua значением, кроме nil и NaN. (Not a Number специальное значение для представления неопределенных и непредставимых числовых результатов, таких как 0/0.) Таблицы могут быть гетерогенными (разнородными); т.е. могут содержать значения всех типов (кроме nil). Любой ключ со значением nil не считается частью таблицы. И наоборот, любой ключ, не являющийся частью таблицы, имеет ассоциированное значение nil.
Действительно работает))
Код
local t1 = { [1] = "one" }
local t2 = { [t1] = "two" }
print(t2[t1]) --> "two"
Хотя на практике я не встречал, чтобы в качестве ключей использовалось что-то отличное от числа или строки.
Автор: TIGER_VLAD 27.05.2018, 17:59
Цитата(RayTwitty @ 27.05.2018, 17:00)
Запамятовал, ключом таблицы в Lua может быть только строка или целое число?))
upd:
Цитата
Тип table (таблица) реализует ассоциативные массивы, это значит, что массив может быть проиндексирован не только числами, но и любым Lua значением, кроме nil и NaN. (Not a Number специальное значение для представления неопределенных и непредставимых числовых результатов, таких как 0/0.) Таблицы могут быть гетерогенными (разнородными); т.е. могут содержать значения всех типов (кроме nil). Любой ключ со значением nil не считается частью таблицы. И наоборот, любой ключ, не являющийся частью таблицы, имеет ассоциированное значение nil.
Действительно работает))
Код
local t1 = { [1] = "one" }
local t2 = { [t1] = "two" }
print(t2[t1]) --> "two"
Хотя на практике я не встречал, чтобы в качестве ключей использовалось что-то отличное от числа или строки.
А еще для строковых ключей квадратные скобки можно не указывать: local my_t = {green="зеленый", yellow="желтый", red="красный"}
Автор: kiperenok 09.06.2018, 19:56
Объясните пожалуйста синтаксис второй строчки кода, что делает двоеточие ? Вообще интересует синтаксис двоеточия в Lua.
local visualMonitor = require( "com.ponywolf.visualMonitor" ) -- к локальной переменной visualMonitor подключить файл visualMonitor local visMon = visualMonitor:new()
Автор: RayTwitty 09.06.2018, 20:14
Цитата(kiperenok @ 09.06.2018, 19:56)
Объясните пожалуйста синтаксис второй строчки кода, что делает двоеточие ?
Обращение к полю. Погугли операторы и метатаблицы Lua.
Вот неплохое руководство по Lua: https://yadi.sk/d/4EUvTWhzdnAve
Автор: kiperenok 09.06.2018, 20:22
Цитата(RayTwitty @ 09.06.2018, 20:14)
Цитата(kiperenok @ 09.06.2018, 19:56)
Объясните пожалуйста синтаксис второй строчки кода, что делает двоеточие ?
Обращение к полю. Погугли операторы и метатаблицы Lua.
Вот неплохое руководство по Lua: https://yadi.sk/d/4EUvTWhzdnAve
А так это просто книга Роберта Иерусалимски - просто интерактиваная. Спасибо что скинул ссылку. Че то бегло пробежался по метатаблицам и такого не увидел
Автор: abramcumner 09.06.2018, 20:27
Цитата(kiperenok @ 09.06.2018, 20:22)
Че то бегло пробежался по метатаблицам и такого не увидел
А в операторах нет оператора двоеточие и в метатаблицах нет Двоеточие это синтаксический сахар для сокращения записи. Запись local visMon = visualMonitor:new() эквивалентна local visMon = visualMonitor.new(visualMonitor)
То есть объект перед двоеточием передается первым параметром в функцию. А при объявлении функции через двоеточие в функцию добавляется первый аргумент self.
https://www.lua.org/manual/5.3/manual.html#3.4.11
Цитата
The colon syntax is used for defining methods, that is, functions that have an implicit extra parameter self. Thus, the statement function t.a.b.c:f (params) body end is syntactic sugar for t.a.b.c.f = function (self, params) body end
Автор: kiperenok 19.06.2018, 14:07
abramcumner помоги со следующим:
function instance:touch(event) self.xScale, self.yScale = 0.95, 0.95 end
Как я это понял - self это первый скрытый параметр у функции, тогда получается у функции touch первым аргументом идет instance, а вторым event. Тогда self.xScale равносильно instance.xScale ?
Автор: Neo][ 19.06.2018, 14:33
kiperenok, по вопросу - в зависимости от того, как вызываешь touch и да, и нет Если вызываешь, как instance:touch(ev) или instance.touch(instance, ev) то да, если же как instance.touch(other_table, ev) то нет.
Я думаю эта https://www.lua.org/pil/16.html отвечает на все вопросы )
Автор: kiperenok 19.06.2018, 15:36
Цитата(Neo][ @ 19.06.2018, 14:33)
Я думаю эта https://www.lua.org/pil/16.html отвечает на все вопросы )
Не в моем случае Там все на английском.
Автор: abramcumner 19.06.2018, 16:12
Цитата(kiperenok @ 19.06.2018, 14:07)
Как я это понял - self это первый скрытый параметр у функции, тогда получается у функции touch первым аргументом идет instance, а вторым event. Тогда self.xScale равносильно instance.xScale ?
Да, все правильно. Но это странный подход - разбирать код таким образом Тебе абревиатура ООП о чем-нибудь говорит? Объекты там, классы.
Цитата
Не в моем случае laugh.gif Там все на английском.
RayTwitty давал ссылку на эту же книгу на русском
Автор: kiperenok 19.06.2018, 19:23
Цитата(abramcumner @ 19.06.2018, 16:12)
RayTwitty давал ссылку на эту же книгу на русском
Нашел в книге на русском эту главу, прочитал - вот теперь все понятно. Всем кто помог БОЛЬШОЕ спасибо !
Автор: buffy 12.12.2018, 16:19
Последняя luabind на текущий момент 0.7.1(2014 год) судя соурсфоржу и гиту. Проект в каком либо виде поддерживается на данный момент?
Автор: Marafonec 27.09.2019, 18:39
Парни, может кто подсказать в чем кроется проблема? Вот такой код
Код
for cf, sec in string.gmatch(str, "%s*([%\%.-_%w]+)%s*%|%s*([-_%w]+)%s*") do
валит игру с логом:
Код
SCRIPT SYNTAX ERROR: c:\ogsr\gamedata\scripts\_utils.script:225: invalid escape sequence near '"%s*([%'
Использую недавно вышедший движок OGSR x64. На оригинальном движке ТЧ этот код работает безо вских проблем.
Автор: Люпус Эст 28.09.2019, 01:37
Небось старый луа просто тихо удалял бекслеш, а новый уже не переваривает кривые ескейп-последовательности и хочет, чтобы ты экранировал \. Попробуй добавить ещё один бекслеш перед существующим. Хз как в огср, но в обычном луа5.3 оно вывелось без ошибок: https://rextester.com/live/XSSP38105
А что вообще должна делать эта регулярка?
Автор: abramcumner 28.09.2019, 11:06
Цитата(Люпус Эст @ 28.09.2019, 01:37)
А что вообще должна делать эта регулярка?
Ищет пары слов, разделенные вертикальной чертой.
Автор: Marafonec 28.09.2019, 13:07
Цитата(Люпус Эст @ 28.09.2019, 01:37)
Попробуй добавить ещё один бекслеш перед существующим.
Спасибо, помогло.
Цитата(Люпус Эст @ 28.09.2019, 01:37)
Хз как в огср, но в обычном луа5.3 оно вывелось без ошибок
Судя по логу: "--LUA version: [LuaJIT 2.1.0-beta3]"
Цитата(Люпус Эст @ 28.09.2019, 01:37)
А что вообще должна делать эта регулярка?
+++
--/summary/>> функция парсинга параметров файла "overrides_by_schemes.ltx" function getTableValuesParam(str) local all_els = {} --'парсим скриптовые таблицы for ft in string.gmatch(str, '%"%s*([-_%.%w]+)%s*%"') do local base_tbl, file_name local tbl_name = ft for f, t in string.gmatch(ft, "([-_%w]+)%.([-_%w]+)") do file_name = f tbl_name = t end if file_name and tbl_name then base_tbl = _G[file_name] and _G[file_name][tbl_name] else base_tbl = _G[ft] end if type(base_tbl) == "table" then for k in pairs(base_tbl) do table.insert(all_els, k) end end end --'парсим конфиговые списки параметров for cf, sec in string.gmatch(str, "%s*([%\\%.-_%w]+)%s*%|%s*([-_%w]+)%s*") do --'"%s*([%' local ini = ini_file(cf) if ini and ini:section_exist(sec) then do local ind = 0 repeat local valid, id, value = ini:r_line(sec, ind, "", "") if valid then table.insert(all_els, id.." >> "..value) end ind = ind + 1 until (not valid) end end end --'парсим дополнительные параметры for pm, list in string.gmatch(str, "%s*([%+%-])%s*%{%s*([-_%s%,%w]+)%s*%}") do for el in string.gmatch(list, "%s*([^%,%s][-_%w]+)%s*") do if pm == "+" then table.insert(all_els, el) end if pm == "-" then local ind = 0 for i, v in ipairs(all_els) do if v == el then ind = i break end end if ind > 0 and all_els[ind] then table.remove(all_els, ind) end end end end return all_els end
Автор: Pavel_Blend 14.11.2019, 17:11
Я сегодня ещё раз начал вникать в луа. Частично прочитал несколько небольших учебников. Появились вопросы:
1) что это за слово class? Понятно, что создаёт класс, но в Notepad++ это ключевое слово даже не подсвечивается цветом. Такое ощущение, что эта вещь есть только в сталкеровских скриптах. Это слово class ведь не стандартная для языка часть?
2) как в луа работает система модулей и пакетов? В книжках пишут, что нужно использовать require. Но в сталкерских скриптах нету ни одного require. Я заметил, что модули используются без импорта. Например, если в папке gamedata\scripts есть файл my_module.script, то чтобы использовать функции из этого модуля, нужно сразу (без импорта) к ним обращаться: my_module.my_funct() В питоне с модулями всё по-другому. Их всегда нужно импортировать так: import my_module, а потом использовать так: my_module.my_funct(). Но в луа я не совсем понимаю, как обращаться к коду из вне. Всё как волшебство какое-то. Пишем my_module.my_funct() и он сам импортируется что ли?
3) откуда растут ноги у скриптов сталкера? Какой скрипт вызывается самым первым? Что является началом работы скриптов?
4) как скриптом вывести в игровую консоль сообщение? printf вроде не работает.
Автор: abramcumner 14.11.2019, 17:33
Цитата(Pavel_Blend @ 14.11.2019, 17:07)
1) что это за слово class? Понятно, что создаёт класс, но в Notepad++ это ключевое слово даже не подсвечивается цветом. Такое ощущение, что эта вещь есть только в сталкеровских скриптах. Это слово class ведь не стандартная для языка часть?
Это магия луа+луабинд. Луа: при вызове функции с одним строковым(таблицей) параметром можно опускать скобки. Записи class("se_stalker") и class "se_stalker" эквивалентны. Луабинд: добавляет функцию class и прочую обвязку. См. luabind open.cpp
Цитата
2) как в луа работает система модулей и пакетов? В книжках пишут, что нужно использовать require. Но в сталкерских скриптах нету ни одного require. Я заметил, что модули используются без импорта. Например, если в папке gamedata\scripts есть файл my_module.script, то чтобы использовать функции из этого модуля, нужно сразу (без импорта) к ним обращаться: my_module.my_funct() В питоне с модулями всё по-другому. Их всегда нужно импортировать так: import my_module, а потом использовать так: my_module.my_funct(). Но в луа я не совсем понимаю, как обращаться к коду из вне. Всё как волшебство какое-то. Пишем my_module.my_funct() и он сам импортируется что ли?
Это магия движка. Если не находится таблица my_module, пытается подгрузить из одноименного файла .script.
Цитата
3) откуда растут ноги у скриптов сталкера? Какой скрипт вызывается самым первым? Что является началом работы скриптов?
Формально наверное _G.script. Но скрипты, привязанные к серверным и клиентским объектам, диалогам и прочему, вызываются "сами по себе".
Цитата
4) как скриптом вывести в игровую консоль сообщение? printf вроде не работает.
Если собрать движок без дефайна MASTER_GOLD работает и printf и log. Если на оригинальном движке, то только через console():execute("load ~~~"..escape(msg)). Типа загружаешь несуществующий сейв, движок ругается на его отсутствие и выводит твою строку В принципе во всех модах есть уже готовая функция log/dbglog.
Автор: Modera 14.11.2019, 17:40
Цитата(abramcumner @ 14.11.2019, 17:29)
Это магия луа+луабинд. Луа: при вызове функции с одним строковым(таблицей) параметром можно опускать скобки. Записи class("se_stalker") и class "se_stalker" эквивалентны. Луабинд: добавляет функцию class и прочую обвязку. См. luabind open.cpp
Ещё стоит упомянуть что это функция возвращает функцию в которую передаётся базовый класс в скобках. Это уже граничит с чёрной магией, но луабинд целиком на ней построен, так что не страшно.
Автор: atanda 14.11.2019, 18:09
Цитата(Pavel_Blend @ 14.11.2019, 17:07)
3) откуда растут ноги у скриптов сталкера? Какой скрипт вызывается самым первым? Что является началом работы скриптов?
Я тоже задавался этим вопросом, но после анализа(возможно, плохого) исходников пришёл к выводу, что фактически ничего не является началом работы. Каждый скрипт уникален и не предполагает наличие соседей. При загрузки скрипта, чтобы не конфликтовали глобальные переменные, для содержимого(функций, глоб. переменных) создаётся отдельное пространство имён. Далее скрипт исполняется, при обращении к несуществующей на момент исполнения таблице, например, my_script, действия продолжаются рекурсивно.
Автор: RayTwitty 14.11.2019, 20:09
Цитата(Pavel_Blend @ 14.11.2019, 17:07)
2) как в луа работает система модулей и пакетов?
В сталкерском луа вообще нет как таковых модулей и пакетов. Обращаемся сразу, никаких импортов, инклудов, запросов и т.д. С этим намного проще, чем в чистых языках.
Автор: Pavel_Blend 14.11.2019, 20:41
Меня ещё удивил то факт, что можно обращаться к некоторым функциям, не указывая модуля, в котором они хранятся. Например, функция printf хранится в файле _g.script, а вызывать из других скриптов её можно так: printf(), а не так _g.printf(). Ещё видел другую функцию (не printf), которая так же использовалась.
Автор: RayTwitty 14.11.2019, 21:54
Цитата(Pavel_Blend @ 14.11.2019, 20:37)
Меня ещё удивил то факт, что можно обращаться к некоторым функциям, не указывая модуля, в котором они хранятся.
Это касается содержимого только _g скрипта. g - global
Автор: Pavel_Blend 16.11.2019, 21:58
Продолжаю изучать луа. Кое что изучил, но всё равно не могу писать скрипты для сталкера. Какой способ изучения лучше всего выбрать, чтобы начать программировать для сталкера? Я пока думаю так:
1) читаю учебник "Программирование на языке Lua. Третье издание. (рус)" (ссылка в шапке данной темы), чтобы изучить чистый луа (без сталкеровских классов/функций) (или есть более полная/лучшая книга на русском?)
2) изучить стандартную библиотеку луа (на удивление она оказалась крошечной, по сравнению со стандартной библиотекой python)
3) как-то изучить сталкеровские функции/классы по lua_help.script
Наверное, самое трудное - это 3 пункт. Так как информация в lua_help.script не многословная и в сети нету полной документации.
Пока я остановился на первом пункте. И получилось сделать свой первый скрипт: https://github.com/PavelBlend/stalker-lua-scripts/blob/master/dm_reader.lua
Он считывает бинарные данные из dm файлов, помещает их в таблицу и печатает в консоль.
Ещё пытался изучать скрипты от модов, но ничего не понял. Изучал nlc7 и удивился скриптам, а именно sak_dialog.script и sak.script. Эти скрипты имеют несколько тысяч строк кода. Один в 9 тысяч, другой в 11 тысяч. Как разработчики умудряются с такими скриптами работать? Я бы разделил бы их на куски по 100-500 строк. Наверняка диалоги можно было бы разбить по локациям.
Автор: abramcumner 17.11.2019, 11:47
Цитата(Pavel_Blend @ 16.11.2019, 21:54)
Ещё пытался изучать скрипты от модов, но ничего не понял.
А зачем моды, лучше с оригинала начать тогда. На АМК есть тема с разбором lua_help: https://www.amk-team.ru/forum/topic/7450-spravochnik-po-funkciyam-i-klassam/ В ней если не все описано, то очень многое.
Цитата
Изучал nlc7 и удивился скриптам, а именно sak_dialog.script и sak.script. Эти скрипты имеют несколько тысяч строк кода. Один в 9 тысяч, другой в 11 тысяч. Как разработчики умудряются с такими скриптами работать? Я бы разделил бы их на куски по 100-500 строк. Наверняка диалоги можно было бы разбить по локациям.
Диалоги и так разбиты по локациям(config/gameplay/dialogs_*.xml), в скриптах вспомогательная обвязка. Из-за того, что в оригинале из диалога в скриптовую функцию нельзя передать аргументы, приходится плодить кучу функций, которые вызывают одну и ту же функцию, но с разными аргументами. А если делать какой-нибудь бартер/выбор награды/починку на диалогах, то количество скриптовых функций разрастается в геометрической прогрессии. Смысла разбивать диалоговые функции по разным файлам нет, и пишутся и читаются они наоборот: сначала диалог, потом функция. Точно также и функции для логики.
Автор: atanda 17.11.2019, 14:10
Цитата(Pavel_Blend @ 16.11.2019, 21:54)
Изучал nlc7 и удивился скриптам, а именно sak_dialog.script и sak.script
Вполне возможно, что alpet'ом была написана на дельфях утилита для создания диалогов и в ней можно было бы писать экшены, а потом утилита сама записывала функции в файлик.
Автор: RayTwitty 17.11.2019, 15:26
Pavel_Blend, может стоит сначала изучить файловую структуру игры? Не просто где конфиги и где скрипты, а более детально - диалоги, предметы, существа, UI, тексты и т.д. А по модам изучать смысла мало - как правило там лютый ахтунг, который только добавит вопросов.
Автор: Gaz24 18.11.2019, 14:49
Добрый день. Вопрос по поводу скриптов и аи-схем. Как определить, что НПС в определенный момент времени ведет огонь через менеджер состояний или другой метод?
Автор: Pavel_Blend 18.11.2019, 23:50
Такой вопрос возник:
движок сталкера добавляет функции в луа, которые равноправны функциям из базовой библиотеки? То есть например, есть функции pairs, getmetatable, next, которые находятся в базовой библиотеке. И чтобы их вызвать, достаточно написать getmetatable(). Но есть функции, которые предоставляются другими библиотеками, доступ к которым осуществляется не просто find, а string.find или math.abs. То есть нужно писать имя библиотеки и ставить точку, после которой идёт имя функции. Так вот, движок сталкера добавляет функции в базовую библиотеку, и чтобы использовать эти функции, не нужно писать имя библиотеки и точку. Например, есть такие функции, как vector(). Я ведь всё правильно понял? Ну, что движок xray добавляет новые функции именно в базовую библиотеку.
И ещё вопрос: есть ли у кого xml файл для Notepad++, который добавляет подсветку синтаксиса lua вместе со всеми сталкеровскими функциями? И чтобы сталкеровские функции были отличны по цвету от стандартных. Просто у меня не получается добавить новые ключевые слова в файл langs.xml. Notepad их просто игнорирует. Поэтому мне нужен отдельный xml файл с User Defined Language с описанием всего синтаксиса луа + сталкеровские функции.
Автор: atanda 18.11.2019, 23:58
Цитата(Pavel_Blend @ 18.11.2019, 23:46)
Ну, что движок xray добавляет новые функции именно в базовую библиотеку.
Смысл верен, только всё немного не так: "регистрация" происходит не в "базовой библиотеке", а в глобальном пространстве имён "_G", т.е. вызывая string.find, ты фактически делаешь _G["string"].find. Луа проходится по таблице и ищет соответствующее пространство имён, в данном случае "string".
Автор: Pavel_Blend 19.11.2019, 00:02
atanda, понятно. А для notepad++ ни кто не добавлял сталкеровские функции? Для новичков было бы удобнее. Так как большая часть кода в сталкере - это вызов функций, добавленных из движка.
Автор: atanda 19.11.2019, 00:16
Примерно так: https://images.gameru.net/image/e5d347bf789ede3.png.html или создавать свои файлы синтаксиса.
Автор: abramcumner 19.11.2019, 00:16
Pavel_Blend, https://ap-pro.ru/forum/105-10388-1
Автор: Pavel_Blend 19.11.2019, 00:25
abramcumner, по твоей ссылке есть только автозавершение и проверка синтаксиса. Мне нужна подсветка синтаксиса сталкеровских функций. Только нужно, чтобы цвет отличался от стандартных функций.
Автор: RayTwitty 19.11.2019, 00:55
Цитата(Pavel_Blend @ 19.11.2019, 00:21)
Мне нужна подсветка синтаксиса сталкеровских функций. Только нужно, чтобы цвет отличался от стандартных функций.
Такого вроде не существует. Единственное что я например делал, так это ассоциацию файлов .script с lua-синтаксисом (в оригинальном луа расширение .lua).
Цитата(Pavel_Blend @ 18.11.2019, 23:46)
Так вот, движок сталкера добавляет функции в базовую библиотеку, и чтобы использовать эти функции, не нужно писать имя библиотеки и точку. Например, есть такие функции, как vector().
Ну так самописный вектор они в глобальную загнали, поэтому нет никаких "библиотек". В луа/сталке тут более уместно пространства имен.
Цитата(atanda @ 18.11.2019, 23:54)
Луа проходится по таблице и ищет соответствующее пространство имён, в данном случае "string".
А еще, при однозначном определении типа, можно прям как в питоне вызывать напрямую))
Код
local t = "lol" t:find("kek")
Автор: atanda 19.11.2019, 08:28
Цитата(RayTwitty @ 19.11.2019, 00:51)
можно прям как в питоне вызывать напрямую
Это больше похоже на синтаксический сахар.
Автор: Pavel_Blend 19.11.2019, 14:01
Цитата(RayTwitty @ 19.11.2019, 00:51)
Цитата(Pavel_Blend @ 19.11.2019, 00:21)
Мне нужна подсветка синтаксиса сталкеровских функций. Только нужно, чтобы цвет отличался от стандартных функций.
Такого вроде не существует. Единственное что я например делал, так это ассоциацию файлов .script с lua-синтаксисом (в оригинальном луа расширение .lua).
а в каком текстовом редакторе есть возможность добавить новые ключевые слова в lua, чтобы они были произвольного цвета, отличного от цвета стандартных функций? И как получить список всех функций, которые добавил движок в луа сталкера? Я пробовал пройтись по значениям из _G таблицы, но в ней, помимо си++ функций есть обычные скрипты, стандартные луа функции и прочее. Единственный способ - это извлекать имена из lua_help.script?
Автор: Pavel_Blend 19.11.2019, 21:29
Получилось заставить Notepad++ читать более 4 наборов ключевых слов. Добавил ключевые слова из сталкеровского движка. Теперь они подсвечиваются розовым цветом. Но я не всё добавил. И так же добавилось кое-что лишнее. Например, функция printf. Она определена в файле _G.script и по идее не должна подсвечиваться розовым цветом. Как я узнал список ключевых слов: запустил игру и вызвал скрипт, который выводил в файл все ключи таблицы _G. Там много чего лишнего. А не добавились методы классов. На скриншоте видно, что слово object_binder подсвечено цветом, а net_spawn - нет. Нужно сделать подсветку метода net_spawn и всех других методов сталкеровских классов. Но вот как узнать список всех классов методов? https://images.gameru.net/image/b270d4aa76fd1ca.jpg.html
Автор: Shoкer 19.11.2019, 23:06
Pavel_Blend, открой скрипт lua_help.script из оригинальной игры. Там будет всё то, что экспортируется из движка. Всё остальное создаётся напрямую в скриптах. Ещё много полезного есть здесь - https://www.amk-team.ru/forum/topic/7450-spravochnik-po-funkciyam-i-klassam/ , хотя писалось достаточно давно, ещё до исходников движка.
Автор: NanoBot-AMK 21.11.2019, 19:34
Кстати, функции типа object_binder.update(self, delta) можно спокойно исключить, это просто пустышки, которые ничего не делают, кроме времени(2-3 мксек). Исключения только для метода net_spawn, там это нужно.
Автор: Gaz24 23.11.2019, 07:43
Хотел добавить свою аи-схему, которая запускается во время боя. Все подключил, добавил эвалуатор, работает. А вот экшен не работает от слова совсем. В чем могла быть ошибка?
Код
Код
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()
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
Автор: abramcumner 23.11.2019, 10:55
Цитата(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
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
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)".
Сейчас по идее аи-схема должна зависать. Если запустить такой скрипт на отладочном движке, то в лог будет выведен дамп с указанием, что пошло не так.
Автор: Gaz24 23.11.2019, 14:04
abramcumner, заработало, спасибо. Правда с прекондишенами надо поиграться. А так, осознал.
Если ты говорил про эту http://stalkerin.gameru.net/wiki/index.php?title=SoC._Логика_NPC, то я на нее очень сильно опирался, но из-за своего косяка вообще не понимал.
Автор: RayTwitty 08.01.2020, 22:34
В дополнение к https://www.amk-team.ru/forum/topic/7450-spravochnik-po-funkciyam-i-klassam/?do=findComment&comment=302379
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, только этот метод убирает ещё и кавычки.
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
Вопрос по скрипту ОГСМ 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 09.08.2020, 02:18
Кто желает разобраться в хитросплетениях диалога. Вылет идёт когда раненому даю аптечку в ЧН (мод 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]
//вызвать скриптовую присоединенную функцию //активируется после сказанной фразы //первый параметр - тот кто говорит фразу, второй - тот кто слушает 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);
Ну, и дебильный вопрос: нафига здесь в движке ассерт? У меня за 10 лет, только на аптечках и вылетало.
Автор: Pavel_Blend 07.09.2020, 16:02
Недавно возобновил изучение луа. Вот вроде бы проще питона, но как-то труднее его изучить. Может из-за того, что желание изучать меньше. В общем пытаюсь хоть что-то сделать в скриптах. Максимум удалось вывести сообщение в консоль. При изучении нужно знать две вещи: сам луа и собственно функции движка (в блендере это называется API, наверное в X-Ray это тоже API в виде lua функций). С первым вроде бы понятно, информацию найти можно, а вот со вторым труднее. Читал на АМК посты по функциям и ничего не понятно.
В общем вопросы (эти вопросы по ТЧ скриптам):
как вообще можно встроить свои собственные скрипты в сталкер? Я пока знаю, что можно в диалогах прописать вызов скрипта и функции. А какие ещё способы есть?
И как сделать редактор погоды в игре? Чтобы нажать клавишу, после чего появятся интерфейс с крутилками (которые управляются клавиатурой), который будет в углу и не будет загораживать обзор и при появлении этих крутилок можно спокойно перемещаться по локации (то есть движение мыши не блокируется, как это происходит при открытии инвентаря). И как сделать печать изменённых параметров погоды на экран (чтобы можно было сделать скрин параметров, а потом переписать их в конфиг)?
Автор: RayTwitty 07.09.2020, 21:20
Цитата(Pavel_Blend @ 07.09.2020, 16:02)
При изучении нужно знать две вещи: сам луа и собственно функции движка (в блендере это называется API, наверное в X-Ray это тоже API в виде lua функций).
Луа в сталкере это по сути интерфейс, осуществляющий доступ к внутридвижковым объектам. Этакая надстройка на логикой внутри движка.
Цитата(Pavel_Blend @ 07.09.2020, 16:02)
как вообще можно встроить свои собственные скрипты в сталкер? Я пока знаю, что можно в диалогах прописать вызов скрипта и функции. А какие ещё способы есть?
Можно просто вызвать любую функцию в скрипте, тогда он инициализируется. Поскольку, почти все начинают работать с конкретными объектами и чаще всего с актором, свои скрипты инициализируют из bind_stalker.script.
Цитата(Pavel_Blend @ 07.09.2020, 16:02)
И как сделать редактор погоды в игре?
В ТЧ без правок движка никак. Исходя из первой моей цитаты, тебе потребуется написать экспорт движковых функций в Lua, после чего написать на основе оконной системы сталкера весь интерфейс. Задача весьма нетривиальная и не на пару часов.
Автор: Pavel_Blend 08.09.2020, 17:44
Цитата(RayTwitty @ 07.09.2020, 21:20)
Можно просто вызвать любую функцию в скрипте, тогда он инициализируется. Поскольку, почти все начинают работать с конкретными объектами и чаще всего с актором, свои скрипты инициализируют из bind_stalker.script.
а вообще, какой принцип работы скриптов в сталкере? Вот в blender game engine есть такое понятие, как такт, который длится 1/60 секунд. Во время этого такта выполняются действия. А в сталкере как всё работает? Например, как работает bind_stalker? В этом скрипте каждый кадр выполняется определённая функция? Или данный скрипт выполняется один раз за весь сеанс игры? И вообще где выполняется основная работа скриптовой системы? Вот к примеру скрипт из диалога выполнится только один раз. А какие скрипты непрерывно работают в игре и обрабатывают события?
Автор: Diesel 08.09.2020, 21:35
Pavel_Blend, движок заранее заготовленные внедряет свои щупальца в скрипты. И ждёт их изменений, согласно обновлений в движке. В движке создаются скрипты, как основа, для луа. Каждая функция луа, заранее прописана в движок. Если и не прописана, то предок этой функции всё равно в движке есть.
В поиск визуалки забей .def и увидишь сколько их там.
Автор: RayTwitty 08.09.2020, 23:06
Цитата(Pavel_Blend @ 08.09.2020, 17:44)
В этом скрипте каждый кадр выполняется определённая функция?
Нет, в движке есть глобальный шедулер (апдейтер), из которого уже апдейтятся все онлайновые объекты (он в свою очередь вроде бы как раз из рендера должен вызываться, но я уже не помню). Покадрового апдейта в скриптах нет, у актора вроде бы интервал каждые 20-40 мс, он динамичен, для этого есть переменная delta в аргументе. У других объектов интервал в целях оптимизации может быть больше.
Цитата(Pavel_Blend @ 08.09.2020, 17:44)
Или данный скрипт выполняется один раз за весь сеанс игры?
Код который ничем не обернут (не в функции, не в таблице и т.д.), вызывается при инициализации скрипта. Сам скрипт может инициализироваться только при его вызове, и это не гарантированно при старте игры. бинд_сталкер например инитится при появлении онлайнового актора, если конечно до этого момента еще кто-нибудь в этот скрипт не полезет за чем нибудь. Проще говоря, скрипты инициализируются по мере надобности.
Плюс те же функции в биндерах, вызываются при определенных события. Например net_spawn при появлении актора на уровне, update - периодический апдейт (см. выше) и т.д.
Цитата(Pavel_Blend @ 08.09.2020, 17:44)
А какие скрипты непрерывно работают в игре и обрабатывают события?
Ну кроме апдейта объектов и некоторых апдейтов в UI-интерфейсах таких нет.
Автор: Pavel_Blend 10.09.2020, 12:23
А с помощью скриптов возможно сделать такую вещь:
добавить отметки в пда на все динамические объекты. На сталкеров, на мутантов, тайники, физические объекты, лампочки, бочки, аномалии, еду, патроны, оружие. В общем на всё. И сделать так, чтобы при убийстве сталкера, в пда была метка его трупа. Только метка меняла цвет на серый. Была метка бандита, к примеру, красной, а при убийстве стала серой. И чтобы можно было скрывать метки по типу: аномалии, тайники, трупы, физ. объекты и т. д.
И как можно полностью отключить респавн? Чтобы новые мутанты и сталкеры не появлялись?
Автор: Yara 10.09.2020, 21:31
Цитата(Pavel_Blend @ 10.09.2020, 15:23)
И как можно полностью отключить респавн? Чтобы новые мутанты и сталкеры не появлялись?
Попробуй в se_respawn.script заремить строку self:spawn(), а для отметок всего использую такое:
...
CODE
По клавише в главном меню: ui_main_menu.script, ----------------------------- function main_menu:OnKeyboard(dik, keyboard_action) --virtual function ... if keyboard_action == ui_events.WINDOW_KEY_PRESSED then ... if dik == DIK_keys.DIK_NUMPAD0 then if (level.present() and db.actor ~= nil and db.actor:alive()) then this.mark_all_objects() end end
В самый конец файла добавить:
function mark_all_objects() for i=1,65535,1 do local obj = alife():object(i) if (obj and obj.parent_id and obj.parent_id == 65535) then local obj_name = obj:name()
-- from _g.script
if (IsStalker(obj)) then level.map_add_object_spot(obj.id, "obj_location", tostring(obj_name)) end if (IsMonster(obj)) then --if (IsMonster(obj) and obj:alive()) then -- только живых level.map_add_object_spot(obj.id, "obj_location", tostring(obj_name)) end
if ( isWeapon(obj) or -- оружие
-- from lua_help.script
get_clsid(obj)==clsid.wpn_ammo or -- патроны get_clsid(obj)==clsid.wpn_ammo_og7b or -- выстрелы рг/пг get_clsid(obj)==clsid.wpn_ammo_vog25 or get_clsid(obj)==clsid.wpn_ammo_m209 or
get_clsid(obj)==clsid.obj_explosive or -- взрывные бочки и прочее
get_clsid(obj)==clsid.obj_food or -- еда и медицина get_clsid(obj)==clsid.obj_antirad or get_clsid(obj)==clsid.obj_bandage or get_clsid(obj)==clsid.obj_bottle or get_clsid(obj)==clsid.obj_medkit or
get_clsid(obj)==clsid.equ_stalker_s or -- костюмы
get_clsid(obj)==clsid.artefact_s or -- арты get_clsid(obj)==clsid.artefact or
get_clsid(obj)==clsid.inventory_box or -- тайники get_clsid(obj)==clsid.obj_phskeleton or -- физ.объекты get_clsid(obj)==clsid.obj_phys_destroyable or get_clsid(obj)==clsid.obj_physic or get_clsid(obj)==clsid.obj_breakable or get_clsid(obj)==clsid.script_phys or get_clsid(obj)==clsid.obj_climable or -- лестницы get_clsid(obj)==clsid.projector or -- прожектор get_clsid(obj)==clsid.hanging_lamp or -- лампочки
get_clsid(obj)==clsid.ameba_zone or -- аномалии get_clsid(obj)==clsid.torrid_zone or get_clsid(obj)==clsid.zone or get_clsid(obj)==clsid.zone_acid_fog or get_clsid(obj)==clsid.zone_bfuzz_s or get_clsid(obj)==clsid.zone_dead or get_clsid(obj)==clsid.zone_galant_s or get_clsid(obj)==clsid.zone_galantine or get_clsid(obj)==clsid.zone_mbald_s or get_clsid(obj)==clsid.zone_mincer_s or get_clsid(obj)==clsid.zone_mosquito_bald or get_clsid(obj)==clsid.zone_radioactive or get_clsid(obj)==clsid.zone_rusty_hair or get_clsid(obj)==clsid.nogravity_zone or
get_clsid(obj)==clsid.level_changer or -- переходы get_clsid(obj)==clsid.respawn or -- респавнеры get_clsid(obj)==clsid.smart_terrain or -- смарты get_clsid(obj)==clsid.script_restr or -- рестрикторы get_clsid(obj)==clsid.script_zone or get_clsid(obj)==clsid.car_s or -- машины get_clsid(obj)==clsid.script_heli or -- вертолёты get_clsid(obj)==clsid.helicopter ) then level.map_add_object_spot(obj.id, "obj_location", tostring(obj_name)) end
добавить отметки в пда на все динамические объекты. На сталкеров, на мутантов, тайники, физические объекты, лампочки, бочки, аномалии, еду, патроны, оружие. В общем на всё.
Можно. Перебираешь все айдишники (1..65536, 0 - актор, его пропускаем) объектов в игре через alife():object(id), или если нужно только онлайновых то level.object_by_id(id). Добавляем метку через level.map_add_object_spot.
Цитата(Pavel_Blend @ 10.09.2020, 12:23)
И сделать так, чтобы при убийстве сталкера, в пда была метка его трупа. Только метка меняла цвет на серый. Была метка бандита, к примеру, красной, а при убийстве стала серой.
Так это штатный механизм ПДА. Надо только тег level_spot/mini_spot в xml конфиге проверить/сделать.
Цитата(Pavel_Blend @ 10.09.2020, 12:23)
И чтобы можно было скрывать метки по типу: аномалии, тайники, трупы, физ. объекты и т. д.
Для этого нужно написать UI, в котором добавлять/удалять метки по типу объекта. Скрывать нельзя, только если экспортировать из движка получение CUIStatic метки.
Цитата(RayTwitty @ 07.09.2020, 21:20)
В ТЧ без правок движка никак. Исходя из первой моей цитаты, тебе потребуется написать экспорт движковых функций в Lua, после чего написать на основе оконной системы сталкера весь интерфейс. Задача весьма нетривиальная и не на пару часов.
Вот кстати чувак сделал консольные команды, к которым можно привязаться в интерфейсе https://www.gameru.net/forum/index.php?s=&showtopic=23443&view=findpost&p=1680713 Правда команд мало, и вообще это нужно было бы сделать через экспорт методов, но уж как есть.
Автор: Pavel_Blend 13.09.2020, 13:01
RayTwitty, попробовал редактор погоды. Трудновато редактировать. Хотелось бы иметь ползунки, чтобы плавно менять цвета. Ну или чтобы были горячие клавиши. Например, стрелки (вниз-вверх - листать параметры, влево-вправо - менять значения параметров). И ещё трудно угадать цвет солнца. Всё таки без игрового редактора удобнее тем, что можно загрузить в фотошоп текстуру неба и пипеткой скопировать цвет солнца. А потом пропорционально его увеличить или уменьшить.
А что ещё интересного можно сделать с помощью скриптов, кроме проставления меток?
И вопрос: я проставил метки на всех сталкеров и удалил респавн. Зачистил локации от врагов, но не от всех. Остались монолитовцы, к примеру. Они видны на карте, но их там нет. И монстры. Монолитовцы в припяти возле гаражей у костра. Они не спавнятся. Не выполнено определённое условие для их спавна. В userdata у них прописано это:
CODE
[smart_terrains] none = true
[logic] active = kamp1 combat_ignore = combat_ignore
А что ещё интересного можно сделать с помощью скриптов, кроме проставления меток?
Ну так весь сюжет в общем-то скриптами строится. Вся логика объектов в конечном счете разворачивается в скрипты(xr_logic.script и все схемы поведения), все гулаги и их работы(xr_gulag.script). Спавн объектов, всякие UI-окна с различным функционалом.
Автор: RayTwitty 11.12.2020, 02:18
Наткнулся на интересный прикол с вещественным типом в 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. оказывается в Питоне есть целый класс для таких нужд: https://www.bestprog.net/ru/2019/10/18/python-numbers-with-fixed-precision-class-decimal-ru/#q03 поэтому функция
Код
function normalize_decimal(n) return tonumber(tostring(n)) end
уже не так сильно похожа на дичь... Возможно в питонском классе внутри происходит тоже самое.
Автор: 1001v 11.12.2020, 03:02
RayTwitty, https://0.30000000000000004.com/
Автор: RayTwitty 11.12.2020, 05:33
Цитата(RayTwitty @ 11.12.2020, 02:18)
работает отлично в обоих случаях.
А вот в стулкере в отличии от консольной Луа почему-то не сработало.
Поэтому пришлось расчехлить функцию округления с заданной точностью и вручную указывать количество знаков:
Код
function math.round(n, exactness) return tonumber(string.format("%."..(exactness or 0).."f", n)) end
local value = 0.65 value = value + 0.05 value = value + 0.05 print(value) --> 0.75 if math.round(value, 2) <= 0.75 then print("YES") else print("NO") end --> YES
Автор: abramcumner 11.12.2020, 13:14
Цитата(RayTwitty @ 11.12.2020, 05:33)
А вот в стулкере в отличии от консольной Луа почему-то не сработало.
Потому что это дичь и не должно работать. Попробуй свою функцию не на 0.75, а 0.8, например. Почитай ссылку, которую дали.
Цитата
math.round(value, 2) <= 0.75
Можно нормально же записать в виде value < 0.75 + eps, где eps ты выбрал 0.01.
Зачем тебе вообще проверять на равенство?
Цитата
Возможно в питонском классе внутри происходит тоже самое.
Питоновский класс реализует арифметику на числах с фиксированной точкой. Основан на https://github.com/python/cpython/tree/e42b705188271da108de42b55d9344642170aa2b/Modules/_decimal. Можно затащить в луа и будет, как в питоне
Автор: RayTwitty 11.12.2020, 23:18
Цитата(abramcumner @ 11.12.2020, 13:14)
Можно нормально же записать в виде value < 0.75 + eps, где eps ты выбрал 0.01.
В реальном коде условие сложнее, есть еще нижняя граница, где нужно уже отнимать eps. В целом, fsimilar из движка ровно это и делает, только нужно изменить функцию на предмет сравнения <= или >=.
Цитата
value < 0.75
У меня шаг 0.05, с таким условием застопорится на 0.7. Можно в константе указать заранее больше, но эта константа может меняться в дальнейшем и не хотелось бы подразумевать в ней некоторые условия и подводные камни.
Цитата(abramcumner @ 11.12.2020, 13:14)
Потому что это дичь и не должно работать.
Да, я об этом сразу и написал) Просто меня навело на мысль, что стандартный print выводит число с правильной точностью и возможно дело в банальном переводе в строку. Исходники не смотрел, быстрее было в консоли проверить на практике. Выходит, что нет и там скорее всего какой-нибудь format как у меня в round-функции.
Цитата(abramcumner @ 11.12.2020, 13:14)
Почитай ссылку, которую дали.
Я на основе этой ссылки и других, которые сам нашел, последний пост и написал. Ранее я уже писал про eps, это первое что я и сделал - прибавил и отнял 0.00001. Вопрос был даже не в этом скорее, а почему в Луа только со второй операции начинает портиться точность.
Автор: abramcumner 12.12.2020, 02:12
Цитата(RayTwitty @ 11.12.2020, 23:18)
Ранее я уже писал про eps, это первое что я и сделал - прибавил и отнял 0.00001. Вопрос был даже не в этом скорее, а почему в Луа только со второй операции начинает портиться точность.
Ни число 0.7, ни число 0.05 не могут быть представлены в формате ieee754. Вместо них берутся ближайшие значения. Условно 0.70000000001 и 0.04999999999. Так получается, что в сумме они дают 0.75. А если к 0.650000000001 прибавить два раза по 0.04999999999, то 0.75 не получится. Точность вычислений никуда не девается, она ровно такая же точная
Цитата
У меня шаг 0.05, с таким условием застопорится на 0.7.
Если работает через преобразование в строку, то и с эпсилоном в условиях должен работать.
Автор: RayTwitty 12.12.2020, 03:42
Цитата(abramcumner @ 12.12.2020, 02:12)
Если работает через преобразование в строку, то и с эпсилоном в условиях должен работать.
А не прокатит с эпсилоном в моем случае. Но по другой причине: при изменении прозрачности, у меня вот эта погрешность с каждым шагом увеличивается и если погонять туда-сюда получается лютое смещение - не тысячные, а уже десятые. Я правда не совсем уверен, что это вина чисто Луа, возможно арифметика в сталкерском методе. У меня новый метод для оконных классов, который меняет прозрачность - по сути тот же стандартный SetColor, только устанавливает альфу 0..1 (умножается на 255). При получении соответственно делится. Сама прозрачность устанавливается v:SetOpacity(v:GetOpacity() + step), видимо здесь накапливается погрешность. Всё это удалось решить с помощью math.round на каждом шаге (заодно, оно же решило вопрос при сравнении с границами).
Если делать совсем по красоте, то надо тащить питоновский класс))
Автор: abramcumner 12.12.2020, 15:27
Цитата(RayTwitty @ 12.12.2020, 03:42)
Сама прозрачность устанавливается v:SetOpacity(v:GetOpacity() + step), видимо здесь накапливается погрешность.
Ну пусть здесь "копится погрешность", но по-прежнему непонятно в чем проблема. Похоже ты делаешь какое-то анимирование(типа проявляешь окно). Пусть у тебя на каком-то шаге(хотя по расчетам должно было сработать) не сработало условие value >= 0.75, потому что value = 0.7499999, ну так сработает на следующем. Будет 0.799999999. Это так принципиально?
Или можно делать по шагам. Посчитал, что прозрачность нужно изменить за 5 итераций, ну и сделал 5 итераций. В конце можно установить прозрачность на то значение, которое требуется.
Автор: RayTwitty 12.12.2020, 16:41
Цитата(abramcumner @ 12.12.2020, 15:27)
Ну пусть здесь "копится погрешность", но по-прежнему непонятно в чем проблема.
Было две разных проблемы: 1) Сравнение с пределом (константой 0.75). Лечится эпсилоном к константе или math.round к value. 2) Проблема с прозрачностью, выше пост. Скорее всего внутридвижковая проблема сталкера, лечится math.round на каждом шаге.
Цитата(abramcumner @ 12.12.2020, 15:27)
Или можно делать по шагам.
По шагам, по сути, я тоже делал но там именно накапливается погрешность. К примеру первые 10 раз получается от 0.25 до 0.74, потом вернулись на 10 назад, получили не 0.25, а уже 0.24 и т.д. Так нижний предел я легко сместил до 0.1 вообще Видимо где-то, что-то округляется, в Луа или в движке при делении/умножении хз. math.round корректировка на каждом шаге помогла.
А могут быть потери при переводе float -> u32? У меня прозрачность float от 0 до 1, а альфа текстуры задается целым числом от 0 до 255: alpha = u32(opacity*255.f) соответственно геттер обратно преобразует u32 -> float. opacity = float(alpha)/255.f
Автор: abramcumner 14.12.2020, 22:58
Цитата(RayTwitty @ 12.12.2020, 16:41)
А могут быть потери при переводе float -> u32? У меня прозрачность float от 0 до 1, а альфа текстуры задается целым числом от 0 до 255: alpha = u32(opacity*255.f) соответственно геттер обратно преобразует u32 -> float. opacity = float(alpha)/255.f
Да, конечно. К тому же здесь ты переводишь не в u32, а в u8 по сути.
Автор: RayTwitty 14.12.2020, 23:29
abramcumner, исправить никак нельзя? Или только переписывать весь код цвета на один формат?
Автор: abramcumner 14.12.2020, 23:33
Вот так в цикле не писать "v:SetOpacity(v:GetOpacity() + step)" и все. В начале сделать local opacity = v:GetOpacity() и работать уже с переменной opacity.
Автор: RayTwitty 14.12.2020, 23:55
abramcumner, идею понял, только в моем случае все несколько сложнее - окон (статиков) куда больше чем один, у базового окна куча дочерних, для которых я пропорционально тоже меняю прозрачность. В этом случае, придется в таблице хранить текущую прозрачность для каждого из них. В целом, пока выглядит более хлопотнее чем:
Код
local normalize_opacity = function(opacity) return math.round(opacity, 2) end
for k, v in pairs(windows_collection) do v:SetOpacity(normalize_opacity(v:GetOpacity() + step)) end
Но если с типами в движке ничего замутить нельзя (и без переписывания целиком управления цветом), тогда ладно.
Автор: abramcumner 15.12.2020, 12:23
Цитата(RayTwitty @ 14.12.2020, 23:55)
Но если с типами в движке ничего замутить нельзя (и без переписывания целиком управления цветом), тогда ладно.
Можно перевести SetOpacity/GetOpacity на работу с диапазоном 0-255, а не 0..1. Тогда вообще все должно круто работать.
Автор: RayTwitty 10.01.2021, 02:00
Есть функция clamp, которая держит число в рамках диапазона. Стандартная функция и много где используется, в движке сталкера, в вебе (особенно в css) и т.д.
Код
function clamp(n, min, max) return n < min and min or n > max and max or n end
Есть еще такая функция - по сути тоже самое, что и предыдущее, только если n больше максимального, то возвращается минимальное и наоборот. Для простоты обозвал ее iclamp (inverted clamp). У меня часто используется в разных списках, прокрутках значений, переключении полей TABом и т.д.
Код
function iclamp(n, min, max) return min + (n - min) % (max - min + 1) end
Вопрос - может быть у последней функции есть какое-то общепринятое название? Не сильно важно конечно, но мб кто-то в курсе. Пока оставлю как есть.
The modulo with offset a modd n is implemented in Mathematica as[16] Mod[a, n, d].
Думаю и для луа сойдет math.fmod с тремя аргументами.
Автор: RayTwitty 11.01.2021, 01:15
abramcumner, а там разве не со смещением? https://en.wikipedia.org/wiki/Wrapping_(graphics)? В моем случае, при превышении max всегда будет на выходе min, то есть по смыслу (применения) функция как раз ближе к clamp-у.
Вот кстати wrap, переписанный с википедии под луа, с включением мин/макса:
Код
function wrap(x, min, max) x = x - math.floor((x - min) / (max - min + 1)) * (max - min + 1) --[[if x < 0 then x = x + max - min end]] return x end
PS условие с проверкой на ноль можно выпилить по идее.
Автор: abramcumner 11.01.2021, 02:14
RayTwitty, со смещением. В твоем iclamp по идее тоже превышение прибавляется к min. На мой взгляд все три функции делают одно и то же. Название wrap лучше и привычнее.
Автор: RayTwitty 11.01.2021, 02:42
Цитата(abramcumner @ 11.01.2021, 02:14)
В твоем iclamp по идее тоже превышение прибавляется к min.
Нет, при превышении max результат будет равен min, при принижении(? ) min результат будет равен max. wrap тоже самое, только учитывает смещение.
В общем я понял, что в принципе, можно называть как угодно Видимо мой случай часто делают просто условиями по месту и не парятся с отдельными функциями.
Ну, на сколько я знаю луа использует не регекспы, а паттерны, которые выглядят похожими, но соответствуют различным входным данным. http://lua-users.org/wiki/PatternsTutorial
Цитата(RayTwitty @ 14.01.2021, 00:54)
Но ведь %w как раз должен соответствовать классу [A-Za-z0-9_] ?
нет. https://www.lua.org/manual/5.3/manual.html#6.4.1
Твой код следует написать так
Код
string.match("hud_fov 0.55", "^([%w_]+)")
Может быть можно сделать проще - не знаю, я не силён в паттернах, да и на луа давно не кодил.
Автор: RayTwitty 15.01.2021, 01:27
Цитата(atanda @ 14.01.2021, 10:45)
Ну, на сколько я знаю луа использует не регекспы, а паттерны, которые выглядят похожими, но соответствуют различным входным данным
Да, в луа %w не содержит нижнее подчеркивание.
Цитата
For example, [%w_] (or [_%w]) represents all alphanumeric characters plus the underscore.
Подразумевается, мы сами как бы группу(класс) расширяем. По работе в основном сталкиваюсь с js и питоном, там по стандарту андескор в \w есть. Спасибо за наводку.
Автор: Пчел 3д 24.01.2021, 14:01
Добрый день, подскажите пожалуйста, как прописать скрипт на дверь в сталкер зов припяти, чтоб дверь открывалась нажатием клавиши "F" (использовать). Скрипт двери я прописал, но дверь открывается только в одну сторону и только тогда, когда актер в нее упирается. А хотелось бы как в игре, чтоб выскочило сообщение (открыть дверь - нажмите F)
Автор: Билдомассон 24.01.2021, 15:29
Цитата(Пчел 3д @ 24.01.2021, 14:01)
Добрый день, подскажите пожалуйста, как прописать скрипт на дверь в сталкер зов припяти, чтоб дверь открывалась нажатием клавиши "F" (использовать). Скрипт двери я прописал, но дверь открывается только в одну сторону и только тогда, когда актер в нее упирается. А хотелось бы как в игре, чтоб выскочило сообщение (открыть дверь - нажмите F)
скопируй логику какой-нибудь из labx8.level, он по-моему идет вместе с сдк 0.7. ну или вот взял логику от рандомной двери:
Добрый день, подскажите пожалуйста, как прописать скрипт на дверь в сталкер зов припяти, чтоб дверь открывалась нажатием клавиши "F" (использовать). Скрипт двери я прописал, но дверь открывается только в одну сторону и только тогда, когда актер в нее упирается. А хотелось бы как в игре, чтоб выскочило сообщение (открыть дверь - нажмите F)
скопируй логику какой-нибудь из labx8.level, он по-моему идет вместе с сдк 0.7. ну или вот взял логику от рандомной двери: