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

Скриптование


Svoboда

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

Подготавливаю русский мануал.

Заодно и правленый LuaXml.lua подкину. Там функция find не очень.

Да и добавил несколько новых.

 

 

http://rghost.ru/53555112

Остальные ответы по ходу дела.

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

Поделиться этим сообщением


Ссылка на сообщение

Shadows

Каждый преследует свои цели. Предлагая идею динамического файла, я не не ставлю цели читать оригинальные в принципе.

Потому что мне это не нужно.

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

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

Практически это всегда простая таблица, изредка со вложенной таблицей.

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

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

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

Поэтому и работа функции (той же find) предполагает работу с классическим XML.

 

А для Сталкера идея и исполнение Charsi отличное.

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

Поделиться этим сообщением


Ссылка на сообщение

@Akella-96 aka SvD, 

При такой неопределённой ситуации нужно начинать с all.spawn-а

Логика рестриктора сна (напр. Затона) name = zat_a2_sr_sleep находиться в файле cfg = scripts\sr_sleep.ltx.

Нужно проверить, срабатывает ли рестриктор при заходе в него ГГ :

on_actor_inside = sr_idle@run %=run_tutorial(tutorial_sleep)%

Должна вызываться функция xr_effects.run_tutorial

Проставь выводы в лог и посмотри что работает а что нет.

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

Изменено пользователем Dennis_Chikin
тому, кому отвечали - явно не интересно. Остальным - тем более.

Поделиться этим сообщением


Ссылка на сообщение

@Старлей,

Сейчас существует не один вариант автоматизированной работы с нетпакетом .

Но поскольку хочешь увидеть структуру, то нужно смотреть в ACDC.

Там отслеживать последовательности... В общем вспомнил, что несколько лет назад делал себе утилиту для создания пакета.

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

http://rghost.ru/54850426

А я её удалю наконец, раз на глаза попалась :)

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

Поделиться этим сообщением


Ссылка на сообщение
использование object_count на мой взгляд не оправдано

Совершенно верно.

Конечно перебор массива for start,limit,step do работет гораздо быстрее. Но всё зависит от конкретной ситуации.

 

В общем случае вызов функции - операция более дорогая, чем любые другие

Объявление функции может быть. Но потом она находиться на стеке достаточно близко

Если нужно что-то использовать многократно, то лучше объявить функцию и затем обращаться к ней

 

Насколько быстрее я уже не помню, но, что быстрее, - так точно

Это верно. iterate_inventory раза в два быстрее. Почему? Выше писал и...

 

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

...из уже заранее объявленной функции внутри db.actor:iterate_inventory(function (dummy,item) 

 

abramcumner

Дружище, вижу что тут. Ответь мне сам знаешь где :)

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

Поделиться этим сообщением


Ссылка на сообщение

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

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

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

 

Вампир35

Используй такую конструкцию :

function твой_класс:Update()
    CUIScriptWnd.Update(self) -- обязательно!
    -- твои действия
end

А занимался ли кто оптимизацией массового входа неписей в онлайн?

Подобной оптимизацией уже занимались.

 

Когда-то давно я написал подробный тутор по работе с coroutine.

На его основе Artos уже сделал рабочий код перебора 65535 объектов с "растяжкой" во времени.

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

В общем нужно поискать. Или, при возможности (памяти) , я восстановлю этот код

Вот. Нашел :)

Как пример.

 

 

 

Вот это на апдейте у актора:

на апдейте 
local iPrкомпания-разработчик (признана нежелательной)an =  25  --/ периодичность сканирования Зоны (25ms => ~15 минут)

 

function OnUpdate(uo,delta)

  --/ непрерывное циклическое сканирование локаций по всему диапазону ID объектов (1...65534)

  if coroutine.status(CoScan) == 'suspended' then --/ статус сопрограммы: приостановлена?

    local bFlg,Result = coroutine.resume(CoScan, iPrкомпания-разработчик (признана нежелательной)an) --/ (пере)запуск сопрограммы

    if not bFlg then --/ ошибка при выполнении сопрограммы

      printf("OnUpdate:Error_CoScan=[%s]:<%s>", Result, "Error!")

    end

  end

end

А это основа сопрограммы:

цикл coroutine 
local tOAMain,tTmpMain = {},{} --/ дин.массив основных объектов (используется в m_news.script)

local tOwners,tTmpOwn  = {},{} --/ дин.массив владельцев предметов

 

local CoScan = coroutine.create( --/ сопрограмма сканирования объектов игры

  function(iTimeLimit) --/ функция сканирования объектов игры с ограничением времени работы

--    log("%s:CoScan:TimeLimit=[%s]:[%s]", sModule, iTimeLimit, ">") --/#~#

    local oPTimer,iTimeStop,soObj = nil,nil,nil

    local iCurID = 65535 --/ начальный ID

    while true do

      if iCurID >= 65534 then --/ проверка: цикл закончен (или предустановка)?

        --coroutine.yield(iCurID) --/ приостановка (опционально)

        if iCurID == 65534 then

          tOAMain,tOwners = tTmpMain,tTmpOwn --/ обновляем основные массивы

          log("%s:CoScan:Owners=[%s]:Time=[%s]%s", sModule, GetSizeTable(tOwners), Get_StrTime(), "") --/#~#

          --Print_Tables_OffLineAlife() --/#~# for Debug

        end

        --/ предустановки для нового цикла:

        tTmpMain,tTmpOwn = {},{} --/ временные массивы

        iCurID = 0 --/ начальный ID (опускаем 0-actor)

        iTimeStop = iTimeLimit --/ начальная установка для таймера

        oPTimer = profile_timer() --/ (пере)создаем объект таймера

      end

      iCurID = iCurID +1 --/ переход к следующему ID

      soObj = sim:object(iCurID) --/ очередной серверный объект игры

      if soObj then --/ объект в игре? ('пустышки' пропускаются и таймером)

        oPTimer:start() --/ старт таймера (на продолжение)

        --/ -- обработка объекта ----------------

        this.Build_TableObj(soObj,iCurID)

        --/ -------------------------------------

        oPTimer:stop() --/ (при)остановка таймера

        if oPTimer:time() > iTimeStop then --/ проверка: не закончен ли лимит времени?

          coroutine.yield(iCurID) --/ приостановка цикла

          iTimeStop = oPTimer:time() + iTimeLimit --/ обновляем для текущего подцикла сканирования

        end

      end

    end

    printf("%s:DoScan:<Error!>")

    return 65535 --/>

  end

)

Т.о. и эксклюзивные таблицы доступны и коллбэки их актуализируют и ... периодически каждые 10...15 минут эти таблицы освежаются просканнированным глобальным диапазоном по всем объектам, котрый не единовременно выполняется (давая лаги в игре), а размазанно по всему временному интервалу. Т.е. вариант включает в себя все достоинства известных вариантов, исключает лаги и почти исключает зависимость от 'пропущенных' недоработок коллбэков.

Будучи запущенным один раз - на протяжении всей игры периодически сканирует всю Зону по всем объектам создавая соответствующие 'тематические' таблицы. И все это практически в фоновом режиме. 

 

 

Вот инфа по coroutine :

http://www.amk-team.ru/forum/index.php?showtopic=7450&page=16#entry622983

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

Поделиться этим сообщением


Ссылка на сообщение

Стандартных способов не знаю, а альтернативный придумал: )

Нужно пространство имён IO, посредством которого читать xrGame.dll. Если подойдёт, то часика через полтора покажу. Сейчас нет возможности.

Поделиться этим сообщением


Ссылка на сообщение

Не думаю что у тебя получиться читать байт код

IO для того и создана, чтобы читать файлы. Особенно если разрабы предусмотрели модификатор 'b' для функции io.open.

Собственно свой предыдущий пост я и писал, потому что уже получилось. Иначе сидел бы молча.

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

Поделиться этим сообщением


Ссылка на сообщение

Desertir

Смещение отличается в разных версиях xrGame.

 

Zander_driver

Не знаю что дальше хочешь делать, но вот тебе массив t с ключами из clsid, а дальше уже просто. (сделано топором, зато быстро и главное работает. оптимизируешь сам)

local xrgame_path = getFS():update_path("$fs_root$", "bin\\xrGame.dll")
local f = io.open(xrgame_path, 'rb')
local s = f:read('*a')

local _,start = s:find('CCharacterInfo>::InitInternal')
local limit = s:find('CObjectItemClientServerSingleMp')
start = start + 10

local p = f:seek("set", start)
local t = {}
local key = ''

while p < limit do
    local w = f:read(1)
	if w:byte()~=0 then
	    key = key..w
	elseif #key>0 then
	    if clsid[key] then
	        t[#t+1] = key
		end
	    key = ''
	end
	p = p+1
end
Изменено пользователем Nazgool
  • Спасибо 1

Поделиться этим сообщением


Ссылка на сообщение

Desertir

Наверное существует и x-ray extensions, в котором время от времени что-то меняется?

Или нет?

 

Речь шла о способе "вытаскивания" ключей clsid из userdata!

Свои, добавленные, можно "запомнить" и стандартными средствами lua.

А "на кой ..." меня не интересует. Надо человеку, значит надо. Более интересно само решение поставленной задачи. Просто академический интерес.

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

Поделиться этим сообщением


Ссылка на сообщение

Andrey07071977

 

 

Не знаю что дальше хочешь делать,

А почему я это написал?

 

 

а дальше уже просто

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

Если я ещё и это сделаю, то что останется вопрошающему?

 

И ещё. Я никого не заставляю пользоваться этим. Одному это жесть, другому извращения.

Это одна из техник!

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

Поделиться этим сообщением


Ссылка на сообщение
составь табличку соответствий ключей к числовым констатам

А чего там составлять? Заменить в коде

elseif #key>0 then
   if clsid[key] then
       t[#t+1] = key
   end

на

elseif #key>0 then
        local k = clsid[key]
        if k then
             t[key] = k
             t[k] = key
        end

и получиться таблица вида :

{ строка = число,
  число = строка,
  ...
}

и так будет для каждого поля из clsid. Т.е. обращаться к ней можно будет и по строке и по номеру.

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

Насколько я понял по условию, никакой динамики и не нужно. Просто необходим список и всё. Читать его один раз при загрузке - много времени не займёт. Вроде так?

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

Поделиться этим сообщением


Ссылка на сообщение

ПЫСовское описание параметров team, squad и group :

1. Команда (team).

Описывает принадлежность персонажа в определенному типу сталкеров. Таким образом все военные сталкеры имеют одинаковую команду, все сталкеры, находящиеся в одной группировке имеют одинаковую команду.
- 0: к этой команде принадлежат: Актер, Торговец, Бармен, Представитель ученных, другие сюжетные миролюбивые персонажи. К этой команде также относятся все сталкеры-одиночки, которые по умолчанию должны быть нейтральными к актеру.
- 1: к этой команде относятся все сталкеры-одиночки, которые по умолчанию должны быть врагами по отношению к актеру.
- 2: Военные сталкеры, армия.
- 3: Параноики, зомбированные и сумасшедшие сталкеры, которые уже с трудом могут принадлежать к какой то категории. Они сами по себе.
- 4: Reserved
- 5: Группировка «Долг»
- 6: Группировка «Грех»
- 7: Группировка «Монолит»
- 8: Сталкеры анархисты из группировки «Свобода»
- 9..31: Reserved

2. Отряд (squad)
Описывает принадлежность сталкеров из одной команды к разным группам внутри одного уровня. Это разделение существует внутри каждого уровня. Для каждой команды это разделение тоже особое. Значение отряда должно находится в пределах от 0 до 31.

3. Группа (group)
Описывает разбиение больших отрядов на более мелкие структурные единицы. Если такое разделение не нужно – дублирует отряд. Сталкерам одиночкам лучше давать уникальные группы. Значение группы должно находится в пределах от 0 до 31.


Распределение по сквадам и группам.
Сквад сталкера ставится в зависимости от уровня, на котором он спавнится.
Группа ставится каждому человеку своя отдельная. Получается что на одном уровне не может быть больше чем 32 сталкеров одиночек в каждой команде. Итого 32 нейтральных, 32 злых. Если, скажем, необходимо поставить группу из трех бандитов – то всем им нужно ставить одинаковую группу. Тогда общее число сталкеров увеличится. Вообщем думаю что хватит с головой 
0: Escape
1: Garbage
2: Agroprom
3: DarkDolina
4: RostokBar
5:
6:
7:
8:
9:
10:

11-31: Reserved

изначально group использовалась для синхронизации передвижения НПС по путям, синхронизация производилась при помощи флага n в точках движения walk, а так же при условии нахождения НПС в одной группе.

 

Ещё описание :

squad. Что именно определяет этот параметр. Понятно, что если не задан, то будет значение из профиля НПС, но в целом, для чего нужен squad?Для ТЧ это скорее рудимент, оставшийся от попыток организовать отряды/группы из НПС, но так и не реализованные в игре.

 

group. Также не ясно. Каким образом данный параметр влияет на поведение НПС?Аналогично squad - рудимент. В гулагах эти параметры практически не задействованы.

Так что делай выводы.

Изменено пользователем Nazgool
  • Полезно 2

Поделиться этим сообщением


Ссылка на сообщение

@Barmolini, 

weathers[level.get_weather()], судя по твоей таблице, может возвратить только два типа значения. Либо 'nil', либо 'number'

Возвратит 'number' - замечательно. Возвратит 'nil' - не беда. На этот случай и сработает or и get_float.

...and weathers[level.get_weather()... совсем лишнее.

  • Спасибо 1
  • Согласен 1

Поделиться этим сообщением


Ссылка на сообщение

dc

Наверняка человек мало что понял.

Меня самого выражение ( ( ( n1:id() ~= 0 ) and n1 ) or n2 ) несколько смутило. В том смысле, что необходимо некоторое время, чтобы сопоставить - кто такой n1 и n2 по отношению к first и second speaker-ам.  Да и столько скобок, что ... ну на любителя конечно.

Наверное просто стоило сказать что speaker-ы поменялись местами, и чтобы далее не заморачиваться на эту тему, нужно написать дополнительную функцию, которая сама будет ставить first_speaker-ом actor-а. Типа :

function normalize_speakers(first_speaker, second_speaker)
    local is_actor  = first_speaker:id() == 0
    return is_actor and first_speaker or second_speaker, is_actor and second_speaker or first_speaker
end


function give_kolbasa(first_speaker, second_speaker)
    first_speaker, second_speaker = normalize_speakers(first_speaker, second_speaker)
    -- ну и далее по тексту
end

........

dc

10000. Ну а как по-другому контролировать speaker-ов?

Вызовы из логики ещё можно поправить в xr_logic. А из xml и скриптов как?

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

Поделиться этим сообщением


Ссылка на сообщение

@mumie,

https://yadi.sk/d/4EUvTWhzdnAve

Глава 21.3 "Шаблоны".

Я зря что-ли столько времени убил на это руководство?

 

 

Если ты делишь строку на слова, разделенные пробелом ... тебе нужен паттерн %w+

На любителя. Я, например, использую %S+.

Но в данном случае не до жиру )

Изменено пользователем Nazgool
  • Полезно 2

Поделиться этим сообщением


Ссылка на сообщение
дружище, я не случайно привел цитату

 

...Если ты делишь строку на слова, разделенные пробелом...тебе нужен паттерн %w+
Являясь как бы скриптером, я не могу себе позволить упускать даже мелких деталей, поскольку, сам понимаешь, такие мелочи могут кардинально изменять код.
Поэтому вышеприведённую цитату я воспринимаю буквально (как задачу).
А она звучит как разделение по пробелам (вернее пробельным символам).
Поэтому, в данном контексте, разделение %S+ точнее подходит под определение задачи.
Под другую цитату решение может быть совершенно другим.
 

 

Блин, чувак, ну а как ты это руководство выложил? Неизвестно где, неизвестно когда.
Чувак, кто ищет - тот всегда найдет.
Как еще можно назвать тему "Язык Lua. Общие вопросы программирования.", чтобы было понятнее о чем там идет речь.
Если почитать хотя бы последнюю страницу, то 3-й пост с краю будет то, что нужно.
И в подпись добавлять бесполезно. Я не часто отмечаюсь постами. Так что быстрее всё-таки найти в теме. Да и в шапку забивать подобные вещи должен кто-то из руководства, который посчитает информацию достойной этого.
 
З.Ы. пожалуйста.
Изменено пользователем Nazgool

Поделиться этим сообщением


Ссылка на сообщение

@Kirgudu,

"А ларчик просто открывался" :). Спасибо.
Можно ещё запилить "Справочное руководство" по функциям.
У меня процентов на 60 оно уже сделано. Материала полезного куча.
Но это может быть достаточно долго.
Можно было бы постепенно добавлять информацию, но она раствориться по страницам.
Не создавать же отдельную тему? Да и редактировать, если что, у меня нет возможности.
Подумаю.
 
В зависимости от того, как организовано - можно и создать. Есть же "справочник по функциям и классам" по движку. А можно  - и в имеющуюся - не так уж часто туда что-то постится, чтобы потерялось. dc
Изменено пользователем Dennis_Chikin
  • Нравится 1

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

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