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

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

@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

 

Или я не правильно вопрос понял?

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

Я не понял, куда делась ведущая вертикальная черта во второй подстроке. С которой позиция будет не 3, а 1.

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

Вертикальная черта относится к классу %p. Она учитывается на предыдущей итерации, но не попадает в захват. 

 

Можно же всё сразу захватить. Вроде побыстрее работает.

for dist,state,sound in string.gfind( s, "%|*(%d+)%|([^%|%@]+)%@?([^%|]+)" ) do
Изменено пользователем Charsi
Ссылка на комментарий

"Вертикальная черта относится к классу %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(), разумеется.

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

Может что-то типа :

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.

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

Ну а теперь profile_timer() в руки, и мерить варианты. ;)

И кстати, проверить случай с 50|{=best_pistol}psy_armed,psy_pain|20|=best_pistol}psy_shoot,psy_pain

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

А в чём проблема с этим случаем? Так же как и с другими. Всё парсится.

Посмотри на паттерн - str:gmatch('([^'..sep..']+)'..sep..'?([^'..sep..'?]*)'). Знаки вопроса замечаешь? Поэтому если нет саунда, то и ... Бог с ним.

Строки с "trim" вхождений ('^%s*(.-)%s*) можно убрать. В parse_condlist они всё равно убираются.

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

Здравствуйте.

Сделал функцию, которая выдаёт ГГ инфопоршень при переходе на локацию (ну, тут видно):





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_"?

Изменено пользователем Сталкер Лом

Работы на Artstationhttps://www.artstation.com/artist/stalker_lom

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

@Сталкер Лом, можно удалять их через цикл. Например, пронумеровать все локации и 

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

yl59NI59OeI.jpg

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

Снова помощи просим.

Вопрос возник, касательно таблиц: как их пополнять? Я сделал так:

создал пустую таблицу вне функции



local tbl_locs = {}

и после посещения локации пополняю таблицу вот так



local level = level.name()

tbl_locs["level"] = true

Но после посещения Затона и Янова, при вызове функции по удалению инфопоршней игра вылетает, жалуясь на то, что таблица пустая ( attempt to concatenate field '?' (a nil value) ). Не подскажете, как правильно пополнять таблицы и, на будущее, удалять данные из них?

P.S. Чую, я и не таблицу вовсе пополнял, а что-то другое творил, но в скриптах искал примеры и наткнулся на нечто вышеописанное, подумал, что это и есть пополнение таблицы...

Изменено пользователем Сталкер Лом

Работы на Artstationhttps://www.artstation.com/artist/stalker_lom

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

Сталкер Лом,

после посещения Затона и Янова, при вызове функции по удалению инфопоршней игра вылетает, жалуясь на то, что таблица пустая

Переход на другой уровень = загрузка сейва = перезапуск скриптовой машины = обнуление всех глобальных переменных

  • Нравится 1
 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

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

@Сталкер Лом, тебе это нужно, я так понял, для того, чтобы при следующем заходе на локацию спавнились новые аномалии? Тогда можно сохранить имя текущего уровня в пстор и на 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 не помню, так что проверь (= ) Изменено пользователем ColR_iT

Аддон для ОП-2.09.2: Яндекс/Google/GitHub

naxac.gif

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

Сталкер Лом,

сначала тебе нужно разобраться с индексированием таблиц.

Вот три сосны, в которых ты запутался :

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 - база знаний - Незаконченные статьи -  Таблицы...

Изменено пользователем Gun12
  • Нравится 2
Ссылка на комментарий

@Сталкер Лом, к выше сказанному добавлю что называть свою переменную level вообще не очень хорошо, т.к сделав такое:

local level = level.name()

 

Ты в рамках твоей функции ниже уже лишаешься доступа к функциям из namespace level, т.к при попытке допустим такого:

 

local level = level.name()

if level.rain_factor() > 0 then

...

 

У тебя будет вылет, ибо в level у тебя теперь строка хранится.

Изменено пользователем ColR_iT

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

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

А вот я тут опять не понимаю, и опять с регэкспами.
На этот раз соседний с parse_data xr_meet.parse_syn_data. Ну, то есть, st1@snd1|st2@snd2 он, положим, разгребет. Но там в поиске шаблон какой-вообще чудовищный, и мне интересно, что будет, если он по ошибке таки получит что-нибудь, реально начинающееся на | ?

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

Господа! Скачал мо (фриплэй старт), при переходе на другую лакацию или загрузке сохранения выдает: 

"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].pstor
if not pstor then
pstor = {}
db.storage[npc_id].pstor = pstor
end
local 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 = 30
end
for i = 1, ctr do
local varname = reader:r_stringZ()
local tn = reader:r_u8()
if tn == pstor_number then
pstor[varname] = reader:r_float()
elseif tn == pstor_string then
pstor[varname] = reader:r_stringZ()
elseif tn == pstor_boolean then
pstor[varname] = reader:r_bool()
elseif tn == pstor_custom then
local classname = reader:r_stringZ()
if classname == "" then
classname = varname
end
pstor[varname] = pstor_custom_impl[classname]()
pstor[varname]:load(reader)
else
-- не надо пытаться вылетать - просто не пишем поврежденные данные
-- при этом обязательно удалять саму переменную - в результате записи
-- мусора в пстор одно только ее название может повесить загрузку
pstor[varname] = nil
end
end
end

 

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

Dennis_Chikin

Да, шаблон не очень понятен. В формате записи syndata и близко нет символа |. Или могут быть варианты через | ? (запамятовал)

Не совсем ясно, тебя интересует шаблон, защищаюший от разных строк 's' ?

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

"Или могут быть варианты через | ? (запамятовал)"

Разделитель. Там в итоге получается тоже таблица, как и в parse_data(). Вот что и где с ней дальше делают - не смотрел еще.

 

Но шаблон все равно странен.

И, естественно, сразу возникает мысль: либо такое действительно зачем-то нужно, либо это запчасть от чего-то еще, но недоделанное/обрезанное. И тогда если переписывать - нельзя ли упростить, либо чревато ахтунгом, если ЭТО в исходном виде переваривает нечто, что я еще не нашел, но где-то есть, а новый вариант на такое рассчитан не будет.

То есть, если трогать, то надо разбираться, как же оно все-таки работает, и зачем ?

Ссылка на комментарий
То есть, если трогать, то надо разбираться, как же оно все-таки работает, и зачем ?

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

Функция '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
 

 

 

Изменено пользователем Artos
  • Нравится 1

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

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

Artos, по вариантам:

 

state == {} - это нормально ?

Захват первого | в подстроку - он зачем оставлен ?

 

P.S. В абсолютном большинстве случаев abort из xr_logic.script не срабатывает. Так что передавать что-то неотловленное раньше, и непися/секцию/имя строки в parse_condlist и иже с ним - малополезно.

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

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

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

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

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

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

Войти

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

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

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...