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

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

Спасибо за советы.Будем иметь в виду.Но я полагаю, что проще данную функцию спавна вынести в логику самого рестриктора и добавить функции в xr_effects.Примерно так:

on_actor_inside = nil %=spawn_dolg_bandit_scene%

--Сцена долг против бандитов на Затоне
function spawn_dolg_bandit_scene(actor, npc)
alife():create("dolg_resp",vector():set(429.889343261719,36.2633438110352,-23.8600177764893),1670996,3693)
alife():create("dolg_resp",vector():set(429.889343261719,36.2633438110352,-23.8600177764893),1670996,3693)
alife():create("bar_dolg_respawn_2",vector():set(429.889343261719,36.2633438110352,-23.8600177764893),1670996,3693)
alife():create("bar_dolg_respawn_3",vector():set(421.454193115234,36.2633438110352,-6.27680397033691),1670996,3693)
alife():create("bar_dolg_respawn_3",vector():set(421.454193115234,36.2633438110352,-6.27680397033691),1670996,3693)
alife():create("bandit_resp_regular",vector():set(424.308135986328,36.263313293457,-0.790691018104553),1660741,3691)
alife():create("bandit_resp_regular",vector():set(424.308135986328,36.263313293457,-0.790691018104553),1660741,3691)
alife():create("bandit_resp_veteran",vector():set(424.308135986328,36.263313293457,-0.790691018104553),1660741,3691)
alife():create("bandit_resp_master",vector():set(452.111480712891,36.7123184204102,-5.0364670753479),1706851,3691)
alife():create("bandit_resp_master",vector():set(452.111480712891,36.7123184204102,-5.0364670753479),1706851,3691)
end

 

Та-а-ак, понеслось ... Начали с локации - всплывает некий рестриктор. Что дальше всплывет?

Должно быть понятно, что на вопросы "а будет ли загружать что-то? и как лучше?" и подобные - каждая мелочь важна!

И что ты ждешь в ответ на это пост, даже не задав вопроса? Критику и очередные готовые коды?

--/ Artos

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

Artos, насчёт модератора - это ты прав, пускай он даст оценку действиям - и моим, и твоим, в том числе.

А раз ты куратор темы, то ответь мне на вопрос (то есть, помоги разобраться).

Цитирую:

Слова о связи этого конкретного респавнера 'esc2_respawn_bandits_fabrika' упомянута именно из-за его закомментированной логики связанной с конкретным гулагом. И его близким расположением - ведь работа выбирается от ближайшей

...Прекрасно понятно (другим, а не тебе) что разработчиками этот респавнер предназначался именно для этого гулага. Хотя по сути, он также может служить и для других гулагов.

Говоря о том, что "разработчиками этот респавнер предназначался именно для этого гулага", ты связывался с разработчиками по этому вопросу, или это твои домыслы?

Поясняю: это критически важно для моей модификации игры, серьёзно. Не спрашивай "зачем" - просто ответь.

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

Окончательный (надеюсь) вариант "Экономичная упаковка таблиц в строку и обратно".

1. При упаковке таблиц типа 'список': {v1,v2,v3,v4} в пак-строку для каждого элемента записывается только однобайтный признак, и опускаются сами индексы.

Экономия: Общее кол-во байт всех индексов таблицы, каждый разряд которых 1 байт.

Т.е. для списка в 100 элементов экономия: 1х9 + 2х90 + 3х1 - 1 = 191 байт.

2. При упаковке целочисленных чисел > 9, число упаковывается не как десятичная строка, а как хекс-строка.

Пример: 12345 == 0х3039 => "12345" ~= "3039" и экономится как минимум 1 байт на каждом числе.

При сохранении чисел большой разрадности (до 14) - экономия может составлять 3 байта на каждое число.

3. Таблицы должны содержать только элементы типов: строка, число, булево значение, субтаблицы и nil.

Элементы типов: юзердата, функция, поток - запрещены для упаковки.

4. Исправлена ошибка AMK-варианта при упаковке таблиц с булевыми значениями в полях.

5. Совместимость со скриптами и сэйвами, использовавшими упаковку/распаковку из amk.script.

Обратная совместимость отсутствует.

 

Пример практичеккого применения:

В игре в таблицу запоминаются игровые идентификаторы (ID) объектов.

Для 198 объектов:

Паковка таблицы амк-вариантом: 1925 байт

Паковка таблицы 'экономным': 1065 байт

--/------------------------------------------------------------------
--/ Упаковка таблицы в строку (стринг) и обратная распаковка
--/------------------------------------------------------------------
--/ Внимание! Строки в структуре таблицы не должны содержать символов с кодами 0-31.
--[[--------------------------------------------------------
  Формат упаковки:
    table     ::= ( listtable | hashtable )
    subtable  ::= ( listtable | hashtable )
    listtable ::= 0x6 valuetype ( value | subtable 0x5 )
    hashtable ::= keytype key valuetype ( value | subtable 0x5 )
    keytype   ::= ( 0x1 | 0x2 | 0x7 )
    valuetype ::= ( 0x1 | 0x2 | 0x3 | 0x4 | 0x7 )
--]]--------------------------------------------------------
local tPackChar = { --/ служебная таблица маркеров упаковки
  d = {1, string.char(1)}, --/(SOH) - 'number' (dec)
  s = {2, string.char(2)}, --/(STX) - 'string'
  b = {3, string.char(3)}, --/(ETX) - 'boolean'
  t = {4, string.char(4)}, --/(EOT) - 'table'
  e = {5, string.char(5)}, --/(ENQ) - table-end
  l = {6, string.char(6)}, --/(ACK) - table-list
  h = {7, string.char(7)}  --/(BEL) - number-hex
}
--/--------------------------------------------------------
--/ функции для совместимости с сэйвами на базе amk.script
--/--------------------------------------------------------
--/ упаковка таблицы в строку (стринг)
function pack_array_to_string(tTbl,bList)
  return this.Pack_Tbl(tTbl,bList) --/> String
end
--/ распаковка 'упакованной' строки (стринга) в таблицу
function unpack_array_from_string(sStr)
  if sStr and sStr ~= '' then
    --/ amk-format упаковки был тэгирован символом c кодом 1 (0x1) --
    if sStr:sub(1,1) == string.char(1) then --/ amk-format?
      if (sStr:sub(2,2) == tPackChar.d[2] or sStr:sub(2,2) == tPackChar.s[2]) then
        --/ далее (со 2-го символа) начинается упакованная строка таблицы
        sStr = sStr:sub(2,-1) --/ отрезаем 1-й символ
      end
    end
    --/< ------------------------------------------------------------
    return this.Parse_Str(sStr) or {} --/> Table
  end
  return {} --/> Zero-Table
end
--/--------------------------------------------------------
--/ упаковка таблицы (списка) 'tTbl' в строку 'sStr'
--/--------------------------------------------------------
function Pack_Tbl(tTbl,bList) --/< table [,(nil|true|false)]
  if type(tTbl) ~= 'table' then
    printf("Pack_Tbl:Not_Table=["..type(tTbl).."]:<Warning!>")
    return "" --/> zero-string (не таблица!)
  elseif not next(tTbl) then --/ отсутствует 1-й элемента таблицы?
    return "" --/> zero-string (таблица пуста)
  end
  --/ упаковка ключа (индекса) элемента таблицы
  local function Pack_Key(key,sType)
    if sType == 'number' then
      if key > 9 and key == math.floor(key) then --/ 2-х байтовое или более и целочисленное?
        return tPackChar.h[2] .. string.format('%X', key) --/> 'hex'-строка
      else
        return tPackChar.d[2] .. key --/> 'dec'-строка
      end
    elseif sType == 'string' then
      return tPackChar.s[2] .. key --/> строка
    end
    abort("Pack_Tbl:UnSupported_KeyType=" .. tostring(sType)
  end
  --/ упаковка значения элемента таблицы
  local function Pack_Value(value,sType)
    if sType == 'number' then
      if value > 9 and value == math.floor(value) then --/ 2-х байтовое или более и целочисленное?
        return tPackChar.h[2] .. string.format('%X', value) --/> 'hex'-строка
      else
        return tPackChar.d[2] .. value --/> 'dec'-строка
      end
    elseif sType == 'string' then
      return tPackChar.s[2] .. value --/> строка
    elseif sType == 'boolean' then
      return tPackChar.b[2] .. ((value and "1") or "0") --/> 'bool'-строка ('0'|'1')
    elseif sType == 'table' then
      return tPackChar.t[2] .. this.Pack_Tbl(value) .. tPackChar.e[2] --/> рекурсивный вызов
    end
    abort("Pack_Tbl:UnSupported_ValueType=" .. tostring(sType)
  end
  --/ all pack
  local tStr,iCntIdx = {},0
  --/ проверка: таблица типа 'список'?
  --/ TODO: проконтролировать на корректность работы с различными типами таблиц
  if bList == nil then --/ если не задан тип таблицы - определяем 'список' или нет
    --/ элементов 'списка' > 0|9, 1-й индекс начинается с 1 и за 'списком' отсутствует хеш-элемент
    iCntIdx = #tTbl --/ длина индексированной части таблицы
    bList = iCntIdx > 0 and not next(tTbl,iCntIdx) --/ (by Gun12) флаг списка (true|false)
  end
  --/< ----------------------------------------
  if bList then --/ упаковывается список?
    table.insert( tStr, tPackChar.l[2] ) --/< маркер 'list' (список)
    for i=1,iCntIdx do
      local v = tTbl[i]
      table.insert( tStr, Pack_Value(v,type(v)) )
    end
  else --/ полная упаковка (ключ и значение)
    for k,v in pairs(tTbl) do
      table.insert( tStr, Pack_Key(k,type(k)) )
      table.insert( tStr, Pack_Value(v,type(v)) )
    end
  end
  return table.concat(tStr),bList --/> строка [и флаг 'список']
end
--/--------------------------------------------------------
--/ распаковка строки 'sStr' (или части строки от 'at') в таблицу 'tTbl'
--/--------------------------------------------------------
function Parse_Str(sStr,at)
  local tTbl,iLen = {},sStr:len() --/ заготовка таблицы и длина строки
  if not at then at = 1 end --/ по умолчанию: парсинг с начала строки
  local key,value,iByte = nil,nil,nil
  --/ -------------------------------------------
  iByte,at = Get_Byte(sStr,at) --/ код at-го символа в строке
  --/ проверка: упакована таблица типа 'список' (table-list)?
  local bList = iByte == tPackChar.l[1] --/ флаг: 'начало списка' (table-list)
  if bList then --/ 'список'?
    iByte,at = this.Get_Byte(sStr,at)--/ пропускаем маркер списка и переходим к следующему символу
  end
  --/ цикл парсинга строки с at-го символа
  while at < iLen do --/ (суб)строка не закончилась?
    if iByte == tPackChar.e[1] then --/ проверка: маркер конца субтаблицы?
      return tTbl,at --/> субстрока субтаблицы закончилась - выход из функции
    end
    if not bList then --/ режим 'общей' таблицы (не 'список')?
      --/ парсинг 'key'
      if     iByte == tPackChar.s[1] then --/ 'string'?
        key,at = this.Get_Str(sStr,at)
      elseif iByte == tPackChar.d[1] then --/ 'number' (dec)?
        key,at = this.Get_Num(sStr,at)
      elseif iByte == tPackChar.h[1] then --/ 'number-hex'?
        key,at = this.Get_Num(sStr,at,true) --/< 'true' - флаг распаковка 'hex'-строки
      else --/ ошибка формата упаковки
        abort("Parse_Str:(%s):UnSupported_TypeKey=" .. tostring(iByte)
      end
      iByte,at = this.Get_Byte(sStr,at) --/ код следующего символа строки
    end
    --/ парсинг 'value'
    if     iByte == tPackChar.d[1] then --/ 'number' (dec)?
      value,at = this.Get_Num(sStr,at)
    elseif iByte == tPackChar.h[1] then --/ 'number-hex'?
      value,at = this.Get_Num(sStr,at,true) --/< 'true' - флаг распаковка 'hex'-строки
    elseif iByte == tPackChar.s[1] then --/ 'string'?
      value,at = this.Get_Str(sStr,at)
    elseif iByte == tPackChar.b[1] then --/ 'boolean'?
      value,at = this.Get_Bool(sStr,at)
    elseif iByte == tPackChar.t[1] then --/ 'table'?
      value,at = this.Parse_Str(sStr,at) --/> рекурсивный вызов для 'табличных субстрок'
    else --/ ошибка формата упаковки
      abort("Parse_Str:(%s):UnSupported_TypeValue=" .. tostring(iByte)
    end
    --/ запоминаем элемент в таблицу
    if bList then --/ элемент списка?
      table.insert(tTbl, value) --/ добавляем в таблицу типа 'список' (table-list)
    else --/ элемент 'общей' таблицы
      tTbl[key] = value
    end
    iByte,at = this.Get_Byte(sStr,at) --/ код следующего символа строки
  end
  return tTbl,at --/>
end

--/ получение кода at-го символа строки и индекса следующего за ним символа
function Get_Byte(sStr,at)
  return string.byte(sStr:sub(at,at)), at+1 --/>
end
--/ по-символьный парсер строки 'sStr' от at до 1-го 'управляющего' символа
function Get_Str(sStr,at) --/< стринг(строка) и начальный индекс в нем
  local iLen = sStr:len() --/ индекс конца стринга(строки)
  for i=at,iLen do
    if string.byte(sStr:sub(i,i)) < 32 then --/ 'управляющий' символ?
      if i == at then --/ 1-м символом идет управляющий? (пустая строка)
        return "", i --/> zero-string,iNext
      end
      --/ начальная часть (суб)строки и индекс 1-го упр.символа
      return sStr:sub(at,i-1), i --/> sSubStr,iNext
    end
  end
  --/ вся (суб)строка до конца и индекс 'после конца'
  return sStr:sub(at,iLen), iLen+1 --/> sSubStr,iNext
end
--/ перевод части (от 'at') строки 'sStr' в число (десятичное)
function Get_Num(sStr,at,bHex)
  local sSubStr,iNext = this.Get_Str(sStr,at)
  local iNum = nil
  if bHex then --/ распаковка хекс-строки?
    iNum = tonumber(sSubStr,16) --/ перевод 'hex'-строки в десятичное число
  else
    iNum = tonumber(sSubStr) --/ перевод 'dec'-строки в десятичное число
  end
  if iNum then --/ есть число?
    return iNum, iNext --/>
  elseif sSubStr == "" then --/ пустая субстрока?
    printf("Get_Num:SubStr=" .. tostring(sSubStr)
    return 0, iNext --/> #?# пока не будем прерывать
  else --/ ошибка формата упаковки
    abort("Get_Num:SubStr=" .. tostring(sSubStr)
  end
end
--/ перевод части (от 'at') строки 'sStr' в булево значение (true|false)
function Get_Bool(sStr,at)
  local sSubStr,iNext = this.Get_Str(sStr,at)
  return (sSubStr == "1" or string.lower(sSubStr:match('^%s*(%S*)') or '') == 'true'), iNext --/>
end
--/------------------------------------------------------------------

Критика, вопросы и пожелания приветствуются.

P.S. Внес неск. косметических правок.

P.P.S. Правка: Убрана излишняя проверка на 1-й индекс списков. 15.09.2011 10:30 МСК

============================================================

=VENOM=

Кура́тор (от лат. curator) — тот, кто наблюдает за ходом определённой работы или иным процессом.
Исходя из этого общего определения, куратор не обязан по своей должности отвечать или обучать.

Отвечать или нет - это его личное право, как одного из форумчан.

Отвечая не на твой вопрос, но связанный по теме и уже задававшийся в ЛС:

То, что раздел имеет названием "Школа модинга" (ИМХО не очень удачное), не означает что тут как в общеобразовательной школе имеются штатные учителя. Эта школа САМОобразовательная! Сами форумчане создали ее, сами же обучают друг другу, делясь знаниями. Никто тут ничем не обязан ни кому, кроме соблюдения правил портала и общепринятых.

 

По существу вопроса:

Нет смысла мусорить словами о связях с разработчиками ... Ответ каждому ясен - нет, конечно. Можено назвать домыслами, можно и логическим выводом.

1. Само название, данное разработчиками респавнеру 'esc2_respawn_bandits_fabrika' - говорит о прямой связи с АТП-шным гулагом 'esc_fabrika_bandit'. Иных ассоциаций врядли можно придумать. Или у тебя и тут есть возражения?

2. В all.spawn'е имеется закомментированная строка в секции [respawn] этого респавнера:

';conditions = {+esc_kill_bandits_quest_kill} 80, 0'

- которая также (будучи активной), связывала бы разрешение события спавна этим респавнером (отключала бы запрет) с выдачей инфопоршня рестриктором 'esc_fabrika_bandit_space_restrictor', который также имеет и соответствующее название и расположен по коорданатам АТП-шного гулага esc_fabrika_bandit'.

3. По координатам респавнера, по которым разработчики его прописали, можно видеть, что место спавна бандитов - довольно закрытый уголок Кордона у заваленного прохода на ТД, т.е. возле АТП. Учитывая, что при выборе работы в гулагах учитывается и расстояние (выбирается работа ближайшего гулага), ясно, что разработчиками задумано, что бандиты заспавненые этим рестриктором должны в первую очередь попадать в АТП-шный гулаг 'esc_fabrika_bandit' (если там конечно были бы свободные работы).

 

Если эти доводы не являются достаточно логичными и очевидными для слов о 'связи респавнера и гулага' - то ... справку от разработчиков я конечно не предоставлю, а дальше убеждать/доказывать - не намерен.

Сама игра это доказывает: После выноса бандитов с АТП и пробежки за квестовой курткой для Шустрого, порой можно встретить в том районе заспавнившуюся именно этим респавнером. кучку бандитов, бредущих на АТП. Если их не трогать - они и оседают на АТП, зачистив его от разведчиков Толика (если те еще живы).

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

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

Ссылка на комментарий
3. По координатам респавнера, по которым разработчики его прописали, можно видеть, что место спавна бандитов - довольно закрытый уголок Кордона у заваленного прохода на ТД, т.е. возле АТП. Учитывая, что при выборе работы в гулагах учитывается и расстояние (выбирается работа ближайшего гулага), ясно, что разработчиками задумано, что бандиты заспавненые этим рестриктором должны в первую очередь попадать в АТП-шный гулаг 'esc_fabrika_bandit' (если там конечно были бы свободные работы).

Неверно. В теории может и должны, но на практике такого никогда не будет.

Не забывай, что мы не в топике по оригинальной игре и то, что давным давно уже сделано и работает в некоторых модах твое категоричное "неверно" и "никогда" опроверкает именно практикой! Не глаголь "истины" и не окажешся неправым. --/ Artos

Когда этот респавнер заработает, гулаг с бандитами уже будет заполнен из других респавнеров. На практике бандиты из респавнера esc2_respawn_bandits_fabrika идут куда угодно, но не на esc_fabrika_bandit. Почему - смотри ниже.

 

Если эти доводы не являются достаточно логичными и очевидными для слов о 'связи респавнера и гулага' - то ... справку от разработчиков я конечно не предоставлю, а дальше убеждать/доказывать - не намерен.

Сама игра это доказывает: После выноса бандитов с АТП и пробежки за квестовой курткой для Шустрого, порой можно встретить в том районе заспавнившуюся именно этим респавнером. кучку бандитов, бредущих на АТП. Если их не трогать - они и оседают на АТП, зачистив его от разведчиков Толика (если те еще живы).

Игра доказывает обратное - просто посмотри то, о чем говорил =VENOM= и все поймешь.

В онлайне респавнеры не работают из-за неуказанного respawn_radius. Поэтому гулаги заполняются респавнерами, находящимися на другой локации. А бандиты идут вовсе и не на АТП - просто гейм-граф такой.

 

Меньше пустопорожних измышлений, больше практики :)

Поаккуратнее в выражениях, даже улыбаясь следует выбирать слова. А попрактиковаться тебе бы не помешало, а не зашориваться только на кодах оригинала. --/ Artos

 

Добавлено через 19 мин.:

=VENOM=,

если хочешь, чтобы респавнеры работали в соответствии со своими названиями, то прописывай им respawn_radius. Но не уверен что это хорошая идея - может получаться как на свалке у ангара - непрерывный поток НПЦ. Сейчас от момента спавна до прибытия на точку проходит достаточно много времени именно из-за того, что НПЦ далеко идти от респавнера. А если бы все было как говорит Artos, то не успел бы обшмонать бандитов на АТП, как туда уже новые входят :)

 

Оффтоп.

Вообще надо сделать один респавнер на всех на Кордоне - типа в зону приходят. Он штампует сталкеров новичков. На кордоне посадить вербовщиков в долг/свободу/бандиты. Сталкеры подходят к ним, болтают и решают куда вступать. Собираются группами и дуют на базы группировок. А уже оттуда пусть расползаются по всей зоне :) В зомби пусть попадают зомбированные сталкеры, в монолит полу зомбированные.

Типа симуляция.

Ну или выставить им по одному респавнеру на базах.

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

Artos

Вот тут у тебя лишняя проверка and iFirstIdx == 1 :

 local iCnt = #tTbl --/ длина индексированной части таблицы
local bList = iCnt > 0 and iFirstIdx == 1 and not next(tTbl,iCnt)

Почему?

Про вычислении длины таблицы local iCnt = #tTbl на самом деле мы прицеливается сразу в 2-х зайцев.

Переменная iCnt может иметь (как бы логически) два значения (первый заяц) :

0 - в таблице не найдены поля списка.

не 0 - в таблице найдено поле (последовательность полей) списка.

Второй заяц :

Если 0, то в таблице нет поля с индексом 1

Если не 0, то поле (поля) найдены, значит в этих полях не может не быть поля с индексом 1.

 

В выражении bList = iCnt > 0 производим выстрел по этим зайцам.

 

Спасибо! Ты прав. Просто вначале подстраховался, а потом пересмотрев кучу вариаций с различными структурами таблиц и, удостоверивщись в обязательном наличии 1-го индекса для 'списков', забыл убрать подстраховку. Подправил. Хотя ... в таких функциях, которые дают данные для сэйвов - необременительные перестраховки порой не помешали бы.

--/ Artos

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

abramcumner

От имени координатора темы делаю замечание за неадекватные и по сути грубые высказывания.

Называть 'пустопорожними измышлениями' без вестких на то оснований и доказательств - это уже переход грани культурного обсуждения/спора, переход на базарную ругань и попытка оскорбить/унизить оппонента. Причем уже не первый раз ...

Думаю модератор вечером выскажет свое мнение и примет соответствующее решение.

 

И давайте придерживаться рамок нормальных дискуссий и споров, указывая и на ошибки другого и признавая свои ...

 

По сути поста:

Вынужден признать свою оплошность/ошибку, т.к. уже несколько лет прошло как поправив коды оригинальной игры, не знаю забот с респавнерами. Виноват, сам свои же шоры не заметил. Но это не делает слова 'пустопорожними измышлениями', а с большой вероятностью и являются вариантом решения так и не заданного '=VENOM=''ом прямого вопроса.

 

Итак, что имеем в 'se_respawn.script'? Условие, по которому в 'se_respawn:update_online()' отключается респавнер, если ему не задан параметр 'respawn_radius'. Причем этот параметр довольно редко задан и как правило 200-300 метров.

Действительно, если не обращать внимания на отсутствие этого параметра - респавн происходил бы в самое неподходяшее время (не успел АТП зачистить - туда уже идут новые) и еще хуже - порой бы НПС спавнились бы из воздуха на глазах у игрока.

Начинаем вносить правки, дабы не зависить от причуд респавнеров с других локаций и ждать когда кто-то когда-то дойдет до нужного гулага. Можно конечно в сами секции каждого нужного респавнера занести параметр 'respawn_radius', но ... это довольно много правок в all.spawn'е и при разработке мода довольно не гибкое решение, требующее каждый раз начинать НИ.

Правим 'se_respawn.script'.

1. В корне скрипта создает константу, которая не даст спавниться объектам перед глазами игрока:

local RESPAWN_RADIUS = utils.cfg_get_number(system_ini(), "alife", "switch_distance", nil, false, 150) --/ радиус респауна

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

2. Вносим правки в онлайн-апдейт:

-- Обновление в онлайне
function se_respawn:update_online()
  --'cse_alife_smart_zone.update( self )
  --'printf("RESPAWN: [%s] se_respawn update_online", tostring(self:name()))
  --[[ --/ закомментировали запрет спавна для респавнеров без параметра "respawn_radius"
  if self.respawn_radius == -1 then
    sim_statistic.respawn_enabled(self, false)
    return
  end
  --]]
  local iDist = (db.actor and  db.actor:position():distance_to(self.position)) or 0 --/ дистанция до респавнера
  if (self.respawn_radius or -1) ~= -1 then --/ еcли задан радиус спавна
    if iDist >= self.respawn_radius then
      --/ еали задан радиус и актор далеко -  разрещаем спавн
      self:execute()
     end
  elseif iDist >= RESPAWN_RADIUS then
    --/ еали НЕ задан радиус и актор далеко -  разрещаем спавн
    self:execute()
  else
    sim_statistic.respawn_enabled(self, false)
  end
end

- т.е. отключив запрет для незаданного радиуса спавна мы и обрабатываем рестрикторы с заданным параметром и с незаданным. Для рестрикторов с незаданным радиусом критерием является радиус алайфа.

Т.о. у нас заработали все респавнеры на текущей локации и перед носом спавниться НПС не будут.

Применительно к гулагу АТП - пока игрок не отойдет после зачистки на достаточную дистанцию - ближайший респавнер не активен.

Используя остальные параметры нужных респавнеров - можно при желании регулировать и периоды респавна и пр ...

 

Для принимающих все это за 'пустопорожние измышления' - можно все это наблюдать уже не один год в игре с модом "SIMBION".

Так что ... от теории до практики не так уж и далеко и она (практика) зависит от желания и дел, а не от слов, правильных или ошибочных.

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

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

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

Artos

Разве в рестрикторах нет логики, которая обрабатывается не зависимо от того, находится ли в нём ГГ или нет? Кажется sr_idle или как то так называлась.

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

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

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

*Shoker*

И к чему твой вопрос-возражение? Если задаешь вопрос, то потрудись чтобы была понятно его связь с чем-либо конкретно.

Раз начали в тонкости и конкретику впадать, то следует конкретизировать слова, дабы не возникло недопониманий и не провоцировать как с респавнерами флуд '

прав-не прав'.

Под рестриктором, как правило, подразумевают объект класса 'SPC_RS_S' (cекцией 'space_restrictor'). Именно про них ведем речь. Если иначе - уточняй. А то и костер (clsid.script_restr) кто-то сейчас к спейс-рестрктору приравняет ...

Изначально спейс-рестриктор не имеет своей прописанной логики и требуется в его кастомдату прописать то, что потребно разработчику/модмейкеру.

Общие схемы, которые могут быть использованы для рестрикторов прописаны в 'modules.script'. Внесещь в конфиг рестриктора нужные секции и впишешь в активную логику - будет и требуемая логика.

 

Ну а по последнему твоему вопросу - и что же будет обрабатывать некоей своей 'встроенной логикой' рестриктор? Если ты о вопросе 'antreg'-а, то ... какой вообще смысл от дефолтного рестриктора? Ему требовалось по событию 'актор на Кордоне и есть инфопоршень' - произвести было спавн. В этом контексте твой вопрос-возражение не могу понять.

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

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

> http://www.amk-team.ru/forum/index.php?s=&...st&p=627193 <

Такой спейс-рестриктор должен тогда быть размером со всю локацию (весь затон в его радиусе), ...

Ну и ...? Можно конечно и правой пяткой почесать правое ухо, но зачем? ;-)

В третий раз повторю: В условии вопроса говорилось, что "если актор на Кордоне" ... Ты предложил проверку "текущая локация Кордон?" заменить на некий рестриктор, который по некоей дефолтной логике что-то должен сделать? В теории конечно можно, (пятка дотянется до уха). Ты считаешь что работа любой основной схемы логики, которая выполняед достаточно большое кол-во перекрестных перепроверок и пр. будет эквивалентной заменой паре простейших проверок (см. код е #2761)?

Мне непонятно дальнейшее выяснение темы рестриктора в контексте заданного вопроса, т.к. очевидно, что это проигрышный вариант.

--/ Artos

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

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

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

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

А зачем размером со всю локацию? У меня инфопоршни выдавались по on_info даже когда спейс_рестриктор был за пределами а-лайфа

Freedom

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

Нет, я предлагал как вариант ковыряние в пысовских скриптах заменить на тот способ, которым пользовались сами GSC. Тем паче что там гораздо проще сделать сложные проверки за счёт готовых функций из xr_conditions\effects

 

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

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

 

***

http://www.amk-team.ru/forum/index.php?s=&...st&p=627335

 

И заметь, я в своём посте указал на твою ошибку (?), что "спейс-рестриктор должен тогда быть размером со всю локацию" притом что по моим знаниям - это утверждение не верно, т.к у рестрикторов есть логика вида sr_idle.

 

[logic]

active = sr_idle

 

[sr_idle]

on_info = {+esc_habar_tonnel_spawn} sr_idle@1 %=spawn_object(esc_trader_habar:esc_trader_habar_2_spawn:0)%

 

[sr_idle@1]

on_info = {=actor_has_item(esc_trader_habar)} sr_idle@wait %+esc_actor_inside_habar%

 

[sr_idle@wait]

]

 

 

Вот я и уточняю - здесь моя ли ошибка, что я считаю что таже логика sr_idle у рестриктора работает не зависимо от нахождения ГГ в зоне онного (что позволяет реализовать идею panzyuza), или же твоя, утверждающая что если ГГ не в зоне действия рестриктора, то никакая логика у него выполнятся не будет.

 

А ты мне опять рассказываешь условие вопроса panzyuza, которое к моему вопросу (именно вопросу-уточнению) вообще ни какого отношения не имеет.

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

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

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

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

Действительно, гораздо проще реализовать через рестрикторы(что я и сделал).И схема sr_idle действительно многофункциональна и для данных условий просто необходима.Даже часть скриптовых функций на квесты можно реализовать через рестрикторы.Не такая уж у них и сложная логика.Главное не ошибиться в передаче параметров и логических цепочках.Поизучав все возможные виды логики у рестрикторов и функции скриптов xr_conditions и xr_effects, выяснил, что в данной связке есть огромные возможности.И гораздо проще в обращении, если правильно понять.

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

*Shoker*

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

я предлагал как вариант ковыряние в пысовских скриптах заменить на тот способ, которым пользовались сами GSC. Тем паче что там гораздо проще сделать сложные проверки за счёт готовых функций из xr_conditions\effects
Кому что проще - это зависит тоько от познаний и навыков. Да и иные аспекты нередко имеют влиятие на проще или нет.

а) Если я разрабатываю один свой мод - мне не обязательно ориентироваться на кого-то, кто паралельно правит один и тот же общий скрипт. Выгода использования общей логики и стандартных схем - в том, что ее использование позволяет распаралелить процесс разработки.

б) Если делается патч к уже имеющейся игре/моду, то внесениеизменение логики объектам (если они не вынесены в конфиг-файл) - требует игру начинать заново или же еще более сложными скриптовыми методами замещать/изменять логику из all.spawn'а.

в) Мне иль любому скриптеру гораздо проще добавить пару требуемых строк в скрипты, чем тратить гораздо больше времени на распаковку-правку-запаковку алл.спавна. Параллельно (см.предложенный вариант кодов) можно улучшать и оптимизировать и имеющиеся коды, ведь вносимые переменные могут использованы и в других местах.

г) Уже вроде как пояснил, что даже если и проще что-то сделать, то лучше ли это для игры - далеко не факт. Повторяю, замена пары простых проверок добавленных в скрипты на порядок менее ресурсоемко, чем простенькое использование аналогичного из общей логики (схем).

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

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

Если таких правок накапливатся побольше - кто-то начинает уже задумываться о будущем ...

Если кол-во заплаток переходит критическую черту - начинаются лаги и пр. проблемы. Уже требуется что-то менять/переделывать. И тот, кто лепил заплатки абы как "лишь бв работало" сталкивается с горой кодов, которые требуется переделать ... и плюет нередко на все это хозяйство.

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

а) Использовать штатные коды и стандартную логику? Можно конечно ... Но далеко ли уедешь. Возможности штатной логики достаточно широки, но и довольно ограничены. Использование в простых случаях (как с упомянутымм вопросом) - приводит к растранжириванию ресурсов игры и "микросекунды" начинают складываться порой и в секунды.

Ну а про посложнее, когда невозможно обойтись штатной логикой - все одно придется делать скриптовые правки.

б) Уже упоминал о коллбэках и 'лаунчерах'. Первоначально для написания гибкой и достаточно универсальной системы потребуется и время и знания и навыки. Но(!), взляни на уже упомянутый мод Симбиона или лайнчер из АМК 0.4. Они позволяют решать экономии ресурсов гораздо более гибко и эффективно, чем стандартные метооды.

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

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

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

В итоге никаких постоянных проверок в апдейте актора с переборами таблиц, никаких постоянных проверок какими-либо рестрикторами и их схемами, никаких лишних объектов и пр. И никакого даже копеешного пожирания ресурсов на других локациях.

 

Так что лучше? Тяп-ляп заплатки? Метод разработчиков? Написание своей системы базовых скриптов?

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

 

Ну и на твой вопрос о 'sr_idle:

Разве в рестрикторах нет логики, которая обрабатывается не зависимо от того, находится ли в нём ГГ или нет?
Странно заданый вопрос ... вырванный из некоего контекста.

Ответ: Нет, логики в 'голом' рестрикторе никакой. Заспавни и сам посмотри. 'Голым' рестриктором (его типом) если только что-то разрешать/запрещить для вхождения в него.

Если пропишешь логику типа 'sr_idle' - эта логика будет работать на зависимо от нахождения ГГ в его зоне. И даже более - сама способна проверять этот факт (on_actor_inside).

 

Добавлено через 9 мин.:

panzyuza: Действительно, гораздо проще реализовать через рестрикторы

Не стану переубеждать, но укажу минусы.

- кол-во объектов в игре ограничено числом 65535. Каждый рестриктор - это объект с его ID.

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

Несложно прикинуть, во что обойдется "простота", если каждое подходящее событие реализовывать на рестрикторах ...

 

Простота и оптимальность - не синонимы!

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

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

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

*Shoker*, panzyuza

То, что вы спорите и "бьетесь", отстаивая своё мнение хорошо конечно. Сам любитель "подраться".

Но в этом бою вы находитесь заведомо в проигрышной ситуации.

Ваш оппонент обладает багажом разнообразных приемов и опытом их применения.

Вам есть чем ответить? Может какой-нибудь туз в рукаве завалялся?

Неизвестный приём?

Не думаю.

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

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

Gun12

Тут не о 'драке' иль споре пока говорить стОит.

И они и ты и я, ИМХО, из одной 'породы' - упертые искатели-познаватели. Готовы сами искать и ковырять, порой что-то находим, как нам кажется стОящее, и не готовы сразу отбросить и довериться сторонним словам и идти иным путем.

Тут можно провести аналогию как в школе:

Вначале познается арифметика.

Слагать/вычитать научились и применяем 1+1 = 2 и т.п. Но когда уже хочется 2+2+2+2+2 - то ...

Познаем умножение и рады, что нашелся более 'простой' способ работы с бОльшим числом чисел.

Но время идет и уже маловато арифметики - начинаем познавать алгебру и рады, что уравнениями можно еще более просто и быстро решать задачки.

Идет время ... и порой уже более серьезные задачки возникают - начинаем познавать и тригонометрия и интегралы и пр ...

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

Все приходит со временем, и необходимость изучать еще неведомое и пересматривать свои взгляды 'что такое хорошо и что такое плохо'. ;-) Пока своих шишек не набьют - врядли готовы верить на слово иль брать готовое но неведомое, требующее новых знаний.

 

Есть еще один момент.

*Shoker* поопытнее чем panzyuza в скриптах, конфигах, логике и второму проще узнать, понять и принять его относительно простые приемы и методы, но(!) ... Первый в основном занимается мелкими модификациями (откуда и пренебрежение ресурсами и оптимизациями), а вот второй (как понимаю), замахнулся на мод с немалым кол-вом локаций и, врядли пока представляет, что тут иной подход нужен. Совочком удобно копать в песочнице, а для рыться траншеи и лопаты маловато, неплох бы экскаватор. Но ... пока и лопата великовата и до руля экскаватора не достать. Вот и применяют уже знакомый и удобный совочек, благо не руками ... Подрастут ...;-)

 

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

 

[x]

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

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

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

Подскажите, какие скрипты работают при образовании лога в случае вылета? Просто где-то чего-то напорол, теперь если что-то вылетает, то лога просто нет!

 

Огорчу. При своих правках ты допустил где-то ошибку, которая приводит к т.н. безлоговым вылетам (пустой лог-файл).

За вывод лог-файла (запись в него) отвечает движек, а не скрипты. Причин возникновения ошибок, приводящих к подобным 'безлоговым' вылетам достаточно много и самых разных. Определить причину можно только анализом кодов и исправлением ошибки.

Откатись назад в своих правках.

--/ Artos

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

Ребят,подскажите,как можно в случае получения квеста получать инфу на экран,на манер Фоллаута 3?

Желательно пример скрипта

 

Давай начнем с того, что этот вопрос немножко не в тему...

Теперь по существу:

Выдать на экран сообщение о получении/завершении квеста можно воспользовавшись методами, которыми пользовались сами ПЫС, а именно:

При создании квеста (game_task) нужно не забыть про тег <text></text>. Подробнее об этом ты можешь прочитать здесь: Создание квестов (базовый уровень) ColT_iT

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

Всем привет, есть пару вопросов.

1) Имеется ли способ отлова открытой вкладке в ПДА? Если нет, то какими-нибудь обходными путями это можно выяснить?

2) Имеется скриптовое окно-меню. В нем есть статик, допустим 200х200. В этом статике есть текст, довольно большой. Есть ли возможность сделать, чтобы если текст не влазил в окно статика, появлялся скролл и можно было прокручивать текст? В конфигах есть параметр complex_mode, но он отвечает только за перенос текста на новые строчки, если строка не влазит в размеры статика...

 

Заранее спасибо.

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

Shadows,

1) Имеется ли способ отлова открытой вкладке в ПДА? Если нет, то какими-нибудь обходными путями это можно выяснить?

через модификации движка. Колмогор ещё делал выдачу инфопорции по переходу на конкретную закладку.

 

2) Имеется скриптовое окно-меню. В нем есть статик, допустим 200х200. В этом статике есть текст, довольно большой. Есть ли возможность сделать, чтобы если текст не влазил в окно статика, появлялся скролл и можно было прокручивать текст? В конфигах есть параметр complex_mode, но он отвечает только за перенос текста на новые строчки, если строка не влазит в размеры статика...

У статика прокрутки нет, на то он и статик. complex_mode кстати не отвечает за перенос, а только за то, чтобы работали вручную расставленные переносы.

 

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

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

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

 

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

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

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

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

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

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

Войти

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

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

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