ColR_iT 171 Опубликовано 27 Января 2014 Поделиться Опубликовано 27 Января 2014 (изменено) @Dennis_Chikin, gfind находит два вхождения: Первое: 50|{=best_pistol}psy_armed,psy_pain@wounded_psyгде: t_pos = 3 s_pos = 36 dist = 50 state = {=best_pistol}psy_armed,psy_pain sound = wounded_psy И второе: 20|=best_pistol}psy_shoot,psy_pain@{=best_pistol}wounded_psy_shoot,wounded_psyгде: t_pos = 3 s_pos = 35 dist = 20 state = {=best_pistol}psy_shoot,psy_pain sound = {=best_pistol}wounded_psy_shoot,wounded_psy Или я не правильно вопрос понял? Изменено 27 Января 2014 пользователем ColR_iT Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 27 Января 2014 Поделиться Опубликовано 27 Января 2014 Я не понял, куда делась ведущая вертикальная черта во второй подстроке. С которой позиция будет не 3, а 1. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Charsi 440 Опубликовано 27 Января 2014 Поделиться Опубликовано 27 Января 2014 (изменено) Вертикальная черта относится к классу %p. Она учитывается на предыдущей итерации, но не попадает в захват. Можно же всё сразу захватить. Вроде побыстрее работает. for dist,state,sound in string.gfind( s, "%|*(%d+)%|([^%|%@]+)%@?([^%|]+)" ) do Изменено 27 Января 2014 пользователем Charsi Lua и LuaJIT плагины для Notepad++ SciTE-RU 3.5.5 плагины для MilkShape3D Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 27 Января 2014 Поделиться Опубликовано 27 Января 2014 (изменено) "Вертикальная черта относится к классу %p" О, спасибо. Нет, оптимизировать так, по-моему, нельзя. Звук может быть не прописан. Как минимум, %@?([^%|]*), и проверка на ~= "". А с оптимизацией надо смотреть, и во многих случаях строки на разбор вообще не отдавать, сразу подставляя готовые таблицы. upd: И, кстати, сначала выделять только значение и строку, а строку потом уже еще раз разбирать. С учетом последующего (xr_meet.script) - что-то типа вот такого: local t, n = {}, 0 local pos, state, snd for d, v in string.gfind( s, "[%|%s]*(%d+)[%|%s]*([^%|]+)" ) do n = n + 1 pos = string.find( v, "%@" ) if pos then state, snd = string.sub( v, 1, pos - 1 ), string.sub( v, pos + 1 ) t[n] = { ["dist"] = tonumber( dist ), ["state"] = xr_logic.parse_condlist( npc, dist, state, state ), ["sound"] = xr_logic.parse_condlist( npc, dist, snd, snd ) } else t[n] = { ["dist"] = tonumber( dist ), ["state"] = xr_logic.parse_condlist( npc, dist, v, v ) } end end ...мда, и моя любимая привычка с копипастом строк, не проверив имена переменных... Либо dist в цикле, либо d в tonumber(), разумеется. Изменено 27 Января 2014 пользователем Dennis_Chikin Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Nazgool 250 Опубликовано 28 Января 2014 Поделиться Опубликовано 28 Января 2014 (изменено) Может что-то типа : local dist_action_sep = '|' local state_sound_sep = '@' local t = {} function parse_my_condlist(str, sep) for one, two in str:gmatch('([^'..sep..']+)'..sep..'?([^'..sep..'?]*)') do one = one:match('^%s*(.-)%s*$') two = two:match('^%s*(.-)%s*$') if sep == dist_action_sep then t[#t+1] = {dist = tonumber(one)} parse_my_condlist(two, state_sound_sep) elseif sep == state_sound_sep then t[#t].state = one t[#t].sound = #two>0 and two or nil end end end parse_my_condlist(s, dist_action_sep) Получается таблица вида : { [1] = { ["state"] = "{=best_pistol}psy_armed,psy_pain", ["sound"] = "wounded_psy", ["dist"] = 50, }, [2] = { ["state"] = "{=best_pistol}psy_shoot,psy_pain", ["sound"] = "{=best_pistol}wounded_psy_shoot,wounded_psy", ["dist"] = 20, }, } В принципе можно парсить и дальше. Получится что-то вроде стандартной функции parse_condlist. Изменено 28 Января 2014 пользователем Gun12 Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 28 Января 2014 Поделиться Опубликовано 28 Января 2014 Ну а теперь profile_timer() в руки, и мерить варианты. И кстати, проверить случай с 50|{=best_pistol}psy_armed,psy_pain|20|=best_pistol}psy_shoot,psy_pain Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Nazgool 250 Опубликовано 28 Января 2014 Поделиться Опубликовано 28 Января 2014 (изменено) А в чём проблема с этим случаем? Так же как и с другими. Всё парсится. Посмотри на паттерн - str:gmatch('([^'..sep..']+)'..sep..'?([^'..sep..'?]*)'). Знаки вопроса замечаешь? Поэтому если нет саунда, то и ... Бог с ним. Строки с "trim" вхождений ('^%s*(.-)%s*) можно убрать. В parse_condlist они всё равно убираются. Изменено 28 Января 2014 пользователем Gun12 Ссылка на комментарий
Сталкер Лом 356 Опубликовано 29 Января 2014 Поделиться Опубликовано 29 Января 2014 (изменено) Здравствуйте. Сделал функцию, которая выдаёт ГГ инфопоршень при переходе на локацию (ну, тут видно): function create() local level = level.name() if not db.actor:has_info("dynamic_anoms_to_"..level) then db.actor:give_info_portion("dynamic_anoms_to_"..level) end end Всё нормально: посетили Затон, получили поршень dynamic_anoms_to_zaton - как и надо. Но в какой-то момент нужно эти поршни удалить... Если у меня было бы 3-4 локации, то можно было бы прописать проверку, подобие "если ГГ имеет поршень посещения Затона, Янова и Припяти, то удалить их", но у меня лок уже с десяток и, надеюсь, будет больше. Перечислять все можно, но вдруг есть ещё какой-то способ? Допустим, можно ли удалить поршни, если в их названии есть какая-то буквенная часть, допустим, "dynamic_anoms_to_"? Изменено 29 Января 2014 пользователем Сталкер Лом Работы на Artstation - https://www.artstation.com/artist/stalker_lom Ссылка на комментарий
azrael1325 28 Опубликовано 29 Января 2014 Поделиться Опубликовано 29 Января 2014 @Сталкер Лом, можно удалять их через цикл. Например, пронумеровать все локации и for i = 1, 10 do disable_info("dynamic_anoms_to_"..i) end Или сделать таблицу с именами локаций: local tbl_locs = { "zaton", "jupiter", ... } Тогда цикл: for i = 0, #tbl_locs do disable_info("dynamic_anoms_to_"..tbl_locs[i]) end Возможно, есть способ вместо таблицы получить скриптами названия всех локаций, но я его, к сожалению, не знаю. 1 Ссылка на комментарий
Сталкер Лом 356 Опубликовано 30 Января 2014 Поделиться Опубликовано 30 Января 2014 (изменено) Снова помощи просим. Вопрос возник, касательно таблиц: как их пополнять? Я сделал так: создал пустую таблицу вне функции local tbl_locs = {} и после посещения локации пополняю таблицу вот так local level = level.name() tbl_locs["level"] = true Но после посещения Затона и Янова, при вызове функции по удалению инфопоршней игра вылетает, жалуясь на то, что таблица пустая ( attempt to concatenate field '?' (a nil value) ). Не подскажете, как правильно пополнять таблицы и, на будущее, удалять данные из них? P.S. Чую, я и не таблицу вовсе пополнял, а что-то другое творил, но в скриптах искал примеры и наткнулся на нечто вышеописанное, подумал, что это и есть пополнение таблицы... Изменено 30 Января 2014 пользователем Сталкер Лом Работы на Artstation - https://www.artstation.com/artist/stalker_lom Ссылка на комментарий
Malandrinus 615 Опубликовано 30 Января 2014 Поделиться Опубликовано 30 Января 2014 Сталкер Лом, после посещения Затона и Янова, при вызове функции по удалению инфопоршней игра вылетает, жалуясь на то, что таблица пустая Переход на другой уровень = загрузка сейва = перезапуск скриптовой машины = обнуление всех глобальных переменных 1 Плагины Total Commander для работы с игровыми архивами: Архиваторный плагин (для работы с одиночным архивом): link1 link2 Системный плагин (для распаковки установленной игры): link1 link2 Ссылка на комментарий
naxac 2 445 Опубликовано 30 Января 2014 Поделиться Опубликовано 30 Января 2014 (изменено) @Сталкер Лом, тебе это нужно, я так понял, для того, чтобы при следующем заходе на локацию спавнились новые аномалии? Тогда можно сохранить имя текущего уровня в пстор и на net_spawn актора повесить проверку: function create() local level = level.name() if not has_alife_info("dynamic_anoms_to_"..level) then db.actor:give_info_portion("dynamic_anoms_to_"..level) end local sl = xr_logic.pstor_retrieve(db.actor,"dla","") if sl~="" and level~=sl then db.actor:disable_info_portion("dynamic_anoms_to_"..sl) xr_logic.pstor_store(db.actor,"dla",level) end endТ.о. при переходе на другую локацию новый поршен будед выдаваться, а старый удаляться. (точно названия ф-ций из xr_logic не помню, так что проверь (= ) Изменено 30 Января 2014 пользователем ColR_iT Аддон для ОП-2.09.2: Яндекс/Google/GitHub Ссылка на комментарий
Nazgool 250 Опубликовано 30 Января 2014 Поделиться Опубликовано 30 Января 2014 (изменено) Сталкер Лом, сначала тебе нужно разобраться с индексированием таблиц. Вот три сосны, в которых ты запутался : 1. tbl_locs["level"] = true 2. tbl_locs.level = true 3. tbl_locs[level] = true Первый и второй варианты полностью эквивалентны. Они определяют, что в таблицу tbl_locs добавляется поле, в котором ключем(индексом) является строка!!! "level". В третьем случае индексом поля будет значение, которое храниться в переменной с именем level. По правилам индексирования таблиц это может быть любой тип данных lua кроме nil. У тебя как раз должен быть этот случай, т.к. в переменной level ты сохраняешь результат работы функции level.name(). Почитай : PiL rus(только начало) - http://aap13.narod.ru/PiL/2.5.html и http://aap13.narod.ru/PiL/3.6.html PiL eng(полностью) - http://www.lua.org/pil/contents.html тут я когда-то начинал писать - http://stalkerin.gameru.net - база знаний - Незаконченные статьи - Таблицы... Изменено 30 Января 2014 пользователем Gun12 2 Ссылка на комментарий
*Shoker* 322 Опубликовано 1 Февраля 2014 Поделиться Опубликовано 1 Февраля 2014 (изменено) @Сталкер Лом, к выше сказанному добавлю что называть свою переменную level вообще не очень хорошо, т.к сделав такое: local level = level.name() Ты в рамках твоей функции ниже уже лишаешься доступа к функциям из namespace level, т.к при попытке допустим такого: local level = level.name() if level.rain_factor() > 0 then ... У тебя будет вылет, ибо в level у тебя теперь строка хранится. Изменено 1 Февраля 2014 пользователем ColR_iT Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 1 Февраля 2014 Поделиться Опубликовано 1 Февраля 2014 (изменено) А вот я тут опять не понимаю, и опять с регэкспами.На этот раз соседний с parse_data xr_meet.parse_syn_data. Ну, то есть, st1@snd1|st2@snd2 он, положим, разгребет. Но там в поиске шаблон какой-вообще чудовищный, и мне интересно, что будет, если он по ошибке таки получит что-нибудь, реально начинающееся на | ? Изменено 1 Февраля 2014 пользователем ColR_iT Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
BrokenEarth 0 Опубликовано 1 Февраля 2014 Поделиться Опубликовано 1 Февраля 2014 Господа! Скачал мо (фриплэй старт), при переходе на другую лакацию или загрузке сохранения выдает: "gamedata\scripts\xr_logic.script:1303: attempt to call field '?' (a nil value)" нашёл я в блакноте строку под номером 1303 (если конечно я правильно понял). Там такая функция: (помогите разобраться, сам в скриптовании тю-тю). function pstor_load_all(obj, reader) local npc_id = obj:id()local pstor = db.storage[npc_id].pstorif not pstor thenpstor = {}db.storage[npc_id].pstor = pstorendlocal ctr = reader:r_u32()if tonumber(ctr) > 30 and tostring(obj:name()) ~= "single_player" and npc_id ~= db.actor:id() then-- максимум 30 итераций - это число ещё уточняется, возможно понадобится больше-- если у вас в пстор что-то свое пишется, ориентируйтесь на свои значения-- и обязательно убираем из проверки актора - у него очень толстый пстор, и к тому же-- если уж поврежденным будет его пстор, то тут точно уже ничего не поможетdgblog("ОБНАРУЖЕН ОБЪЕКТ С ПОВРЕЖДЕННЫМ PSTOR: "..tostring(obj:name()).." БУДЕТ ПРОИЗВЕДЕНА ПОПЫТКА ВОССТАНОВЛЕНИЯ")ctr = 30endfor i = 1, ctr dolocal varname = reader:r_stringZ()local tn = reader:r_u8()if tn == pstor_number thenpstor[varname] = reader:r_float()elseif tn == pstor_string thenpstor[varname] = reader:r_stringZ()elseif tn == pstor_boolean thenpstor[varname] = reader:r_bool()elseif tn == pstor_custom thenlocal classname = reader:r_stringZ()if classname == "" thenclassname = varnameendpstor[varname] = pstor_custom_impl[classname]()pstor[varname]:load(reader)else-- не надо пытаться вылетать - просто не пишем поврежденные данные-- при этом обязательно удалять саму переменную - в результате записи-- мусора в пстор одно только ее название может повесить загрузкуpstor[varname] = nilendendend Ссылка на комментарий
Nazgool 250 Опубликовано 1 Февраля 2014 Поделиться Опубликовано 1 Февраля 2014 (изменено) Dennis_Chikin Да, шаблон не очень понятен. В формате записи syndata и близко нет символа |. Или могут быть варианты через | ? (запамятовал) Не совсем ясно, тебя интересует шаблон, защищаюший от разных строк 's' ? Изменено 1 Февраля 2014 пользователем Gun12 Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 2 Февраля 2014 Поделиться Опубликовано 2 Февраля 2014 "Или могут быть варианты через | ? (запамятовал)" Разделитель. Там в итоге получается тоже таблица, как и в parse_data(). Вот что и где с ней дальше делают - не смотрел еще. Но шаблон все равно странен. И, естественно, сразу возникает мысль: либо такое действительно зачем-то нужно, либо это запчасть от чего-то еще, но недоделанное/обрезанное. И тогда если переписывать - нельзя ли упростить, либо чревато ахтунгом, если ЭТО в исходном виде переваривает нечто, что я еще не нашел, но где-то есть, а новый вариант на такое рассчитан не будет. То есть, если трогать, то надо разбираться, как же оно все-таки работает, и зачем ? Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Artos 99 Опубликовано 2 Февраля 2014 Поделиться Опубликовано 2 Февраля 2014 (изменено) То есть, если трогать, то надо разбираться, как же оно все-таки работает, и зачем ? Если захотелось трогать, то нужно разбираться не столь с "как работает", а "как должно работать", т.е. что же скрипт (заложенный в него алгоритм) должен выполнять с заданной ему строкою в конфиге... Функция 'parse_syn_data' в цикле должна разбивать строку по маске-символу '|' и из первой ее части (подстроки) брать данные о звуке для статуса, разбивая подстроку по маске-символу '@'. И т.о. все что после '|?' (если имеется) - откладывается для разбора в следующем подцикле итерации по строке... если он по ошибке таки получит что-нибудь, реально начинающееся на | ? Вот и должен конфигер писать в конфиге для логики не абы-что, а то, что требуется и должно быть прочитано и "понято" скриптом! Т.е. чтобы начиналось не просто с "реального", а с реально значимого. function parse_data(oNPC,sStr) local tRet = {} if sStr and sStr ~= '' then local sField,sDist,sState,sSound,tDat for sField in sStr:gmatch("(%|*%d+%|[^%|]+)%p*") do sDist,sState,sSound = sField:match('^%s*([^| ]+)%|*([^|@ ]*)@*(%S*)') if not (tonumber(sDist) and sState) or sState == '' then log("parse_data:NPC=[%s],dist=[%s]=[%s][%s]:f[%s]:<%s>", oNPC and oNPC:name(), sDist, sState, sSound, sField, "Info") --/#~# end tDat = {dist = tonumber(sDist)} if sState then if sState ~= '' then tDat.state = xr_logic.parse_condlist(oNPC, sDist, sState, sState) else tDat.state = {} end end if sSound and sSound ~= '' then tDat.sound = xr_logic.parse_condlist(oNPC, sDist, sSound, sSound) end table.insert(tRet, tDat) end end -- log("parse_data:NPC=[%s],Str=[%s]%s", oNPC and oNPC:name(), sStr, '') --/#~# --table.print(tRet,"parse_data|"..(oNPC and oNPC:name()) or '') --/#~# return tRet --/> end function parse_zone_data(oNPC,sStr) local tRet = {} if sStr and sStr ~= '' then local sField,sZone,sState,sSound,tDat for sField in sStr:gmatch("(%|*[^%|]+%|[^%|]+)%p*") do sZone,sState,sSound = sField:match('^%s*([^| ]+)%|*([^|@ ]*)@*(%S*)') if not (sZone and sState) or sState == '' then log("parse_zone_data:NPC=[%s]<~zone=[%s]=[%s][%s]:f[%s]:<%s>", oNPC and oNPC:name(), sZone, sState, sSound, sField, "Info") --/#~# end tDat = {zone = sZone} if sState then if sState ~= '' then tDat.state = xr_logic.parse_condlist(oNPC, sDist, sState, sState) else tDat.state = {} end end if sSound and sSound ~= '' then tDat.sound = xr_logic.parse_condlist(oNPC, sZone, sSound, sSound) end table.insert(tRet, tDat) end end -- log("parse_zone_data:NPC=[%s],Str=[%s]%s", oNPC and oNPC:name(), sStr, '') --/#~# --table.print(tRet,"parse_zone_data|"..(oNPC and oNPC:name()) or '') --/#~# return tRet --/> end function parse_syn_data(oNPC,sStr) local tRet = {} if sStr and sStr ~= '' then local sField,sState,sSound for sField in sStr:gmatch("(%|*[^%|]+%|*)%p*") do sState,sSound = sField:match('^%s*([^@| ]+)@*([^@| ]*).*') if not sState or sState == '' then log("parse_data:NPC=[%s],st[%s],snd[%s]:f[%s]:<%s>", oNPC and oNPC:name(), sState, sSound, sField, "Info") --/#~# end if sState and sState == '' then sState = nil end if sSound and sSound == '' then sSound = nil end table.insert( tRet, {state = sState, sound = sSound} ) end end -- log("parse_syn_data:NPC=[%s],Str=[%s]%s", oNPC and oNPC:name(), sStr, '') --/#~# --table.print(tRet,"parse_syn_data|"..(oNPC and oNPC:name()) or '') --/#~# return tRet --/> end function parse_data(oNPC,sStr) local tRet = {} if sStr and sStr ~= '' then local sField,sDist,sState,sSound,tDat for sField in sStr:gmatch("(%|*%d+%|[^%|]+)%p*") do sDist,sState,sSound = sField:match('^%s*([^| ]+)%|*([^|@ ]*)@*(%S*)') if not (tonumber(sDist) and sState) or sState == '' then log("parse_data:NPC=[%s],dist=[%s]=[%s][%s]:f[%s]:<%s>", oNPC and oNPC:name(), sDist, sState, sSound, sField, "Info") --/#~# end tDat = {dist = tonumber(sDist)} if sState then if sState ~= '' then tDat.state = xr_logic.parse_condlist(oNPC, sDist, sState, sState) else tDat.state = {} end end if sSound and sSound ~= '' then tDat.sound = xr_logic.parse_condlist(oNPC, sDist, sSound, sSound) end table.insert(tRet, tDat) end end -- log("parse_data:NPC=[%s],Str=[%s]%s", oNPC and oNPC:name(), sStr, '') --/#~# --table.print(tRet,"parse_data|"..(oNPC and oNPC:name()) or '') --/#~# return tRet --/> end function parse_zone_data(oNPC,sStr) local tRet = {} if sStr and sStr ~= '' then local sField,sZone,sState,sSound,tDat for sField in sStr:gmatch("(%|*[^%|]+%|[^%|]+)%p*") do sZone,sState,sSound = sField:match('^%s*([^| ]+)%|*([^|@ ]*)@*(%S*)') if not (sZone and sState) or sState == '' then log("parse_zone_data:NPC=[%s]<~zone=[%s]=[%s][%s]:f[%s]:<%s>", oNPC and oNPC:name(), sZone, sState, sSound, sField, "Info") --/#~# end tDat = {zone = sZone} if sState then if sState ~= '' then tDat.state = xr_logic.parse_condlist(oNPC, sDist, sState, sState) else tDat.state = {} end end if sSound and sSound ~= '' then tDat.sound = xr_logic.parse_condlist(oNPC, sZone, sSound, sSound) end table.insert(tRet, tDat) end end -- log("parse_zone_data:NPC=[%s],Str=[%s]%s", oNPC and oNPC:name(), sStr, '') --/#~# --table.print(tRet,"parse_zone_data|"..(oNPC and oNPC:name()) or '') --/#~# return tRet --/> end function parse_syn_data(oNPC,sStr) local tRet = {} if sStr and sStr ~= '' then local sField,sState,sSound for sField in sStr:gmatch("(%|*[^%|]+%|*)%p*") do sState,sSound = sField:match('^%s*([^@| ]+)@*([^@| ]*).*') if not sState or sState == '' then log("parse_data:NPC=[%s],st[%s],snd[%s]:f[%s]:<%s>", oNPC and oNPC:name(), sState, sSound, sField, "Info") --/#~# end if sState and sState == '' then sState = nil end if sSound and sSound == '' then sSound = nil end table.insert( tRet, {state = sState, sound = sSound} ) end end -- log("parse_syn_data:NPC=[%s],Str=[%s]%s", oNPC and oNPC:name(), sStr, '') --/#~# --table.print(tRet,"parse_syn_data|"..(oNPC and oNPC:name()) or '') --/#~# return tRet --/> end Изменено 2 Февраля 2014 пользователем Artos 1 "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Dennis_Chikin 3 658 Опубликовано 2 Февраля 2014 Поделиться Опубликовано 2 Февраля 2014 Artos, по вариантам: state == {} - это нормально ? Захват первого | в подстроку - он зачем оставлен ? P.S. В абсолютном большинстве случаев abort из xr_logic.script не срабатывает. Так что передавать что-то неотловленное раньше, и непися/секцию/имя строки в parse_condlist и иже с ним - малополезно. Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти