Garry_Galler 7 Опубликовано 29 Января 2010 (изменено) Внесу небольшую лепту для желающих получить список вертексов - гейм и левел. Скрытый текст Написал пару функций которые при активации формируют таблицу со списком - как вы ее потом будете использовать - это уже ваша проблема. Получаем набор вертексов для каждого уровня. (набор разумеется не весь - а только тех левел вертексов, которые ассоциированы c гейм вертексами в файле game_graph ) Скрытый текст local lvtab ={} function LevelVertexId() --for i =0, 3511 do --можно и так делать. Номера гейм вертексов можно узнать из файла game_graph который конвертируется в txt прогой ggtool и тотал коммандером. --метод game_graph():valid_vertex_id(i) в данном случае делает тоже самое - подтверждает что гейм вертекс с таким то номером существует. local i = 0 while game_graph():valid_vertex_id(i) do local lv = game_graph():vertex(i):level_vertex_id() --получаем левел вертекс по гейм вертексу --получаем имя уровня по его номеру из секции в game_graph local ln = alife():level_name(game_graph():vertex(i):level_id()) if not lvtab[ln] then lvtab[ln] ={} end table.insert(lvtab[ln], lv) --заполняем таблицу i = i+1 end end таблица заполняется в таком виде: ключ- имя уровня, значение - таблица с данными для этого уровня. [имя_уровня] ={номер, номер, номер и т.д} так как выводить всю таблицу скажем на экран возможным не представляется, я выводил только минимальные и максимальные значения вертексов для каждого уровня. Вот такой функцией, для которой нужно в файле ui_custom_msgs.xml создать блок с координатами вывода текста. типа такого <cs_debug x="200" y="180" width="600" height="100" complex_mode="1"> <text font="letterica16" r="240" g="217" b="182" a="255" align="l"/> </cs_debug> (функцию вывода данных я активировал через первую функцию) function diapason() local text ="" for k, v in pairs(lvtab) do local n = table_maxn(v) local min_v = math.min(unpack(v)) local max_v= math.max(unpack(v)) local str = "Уровень ["..k.."]" local num = "число индексов ["..n.."]" local str = string.format("%s %s %s %s", str, min_v, max_v, num) text= text..str.."\\n" end local hud = get_hud() hud:AddCustomStatic("cs_debug", true) hud:GetCustomStatic("cs_debug"):wnd():SetTextST(text) hud:GetCustomStatic("cs_debug").m_endTime = time_global()/1000 + 180 end По аналогии с функцией получения левел вертексов можно сделать и функцию получения гейм вертексов и так же заполнить таблицу. Скрытый текст local gvtab ={} function GameVertexId() local i = 0 while game_graph():valid_vertex_id(i) do local ln = alife():level_name(game_graph():vertex(i):level_id()) if not gvtab[ln] then gvtab[ln] ={} end table.insert(gvtab[ln], i) i = i+1 end this.diapason_gv() --вызываем функцию для вывода данных на экран end и точно такую же функцию для вывода минимального и максимального значения гейм вертексов для каждого уровня. Так как геймвертексы идут неразрывно - то мы имея этот диапазон получаем точный список гейм вертеков для каждого уровня - от первого значения до последнего. Всего в игре как вы поняли 3512 гейм вертексов - от нулевого до 3511-го. function diapason_gv() local text ="" for k, v in pairs(gvtab) do local n = table_maxn(v) local min_v = math.min(unpack(v)) local max_v= math.max(unpack(v)) local str = "Уровень ["..k.."]" local num = "число индексов ["..n.."]" local str = string.format("%s %s %s %s", str, min_v, max_v, num) text= text..str.."\\n" end local hud = get_hud() hud:AddCustomStatic("cs_debug", true) hud:GetCustomStatic("cs_debug"):wnd():SetTextST(text) hud:GetCustomStatic("cs_debug").m_endTime = time_global()/1000 + 180 end Выводится также мин. и макс. значения - чего в данном случае вполне достаточно. чуть не забыл - так как в сталкере не работает функция table.maxn() - которая возвращает кол-во целочисленных индексов в таблице, то я пользуюсь ее самопальным аналогом, (который считает индексы всех типов - хоть числовые, хоть строковые - причем для числовых не важно идут ли они в математическом порядке или вразнобой) вызывая там где надо table_maxn(имя таблицы) function table_maxn(tbl) local k = 0 for _, v in pairs(tbl) do k = k + 1 end return k end Полученные таким образом таблицы можно динамически использовать прямо в игре для соответствующих целей. Небольшое дополнение по методам: Скрытый текст game_graph() --метод определения файла game.graph vertex(*gvid*) --метод определения секции в данном файле (гейм_вертекс) level.vertex_position(*lvid*) возвращает векторную позицию по левел вертексу. Применим только к активной локации. game_graph():vertex(*gvid*):level_point() возвращает позицию по гейм вертексу - локальную. (точнее говоря возвращается позиция самого гейм вертекса из соответствующей ему секции в файле game.graph) Можно определять на любых локациях (активных/не активных). game_graph():vertex(*gvid*):game_point() также возвращает позицию по гейм вертексу - только мировую(относительно всей карты игры). game_graph():vertex(*gvid*):level_vertex_id() возвращает левел-вертекс по гейм-вертексу. alife():level_name(*level_id*) возвращает имя уровня по его числовому идентификатору. Аргументом может служить метод приведенный ниже. game_graph():vertex(*gvid*):level_id() возвращает числовой идентификатор уровня по гейм вертексу game_graph():valid_vertex_id(*gvid*) возвращает boolean - true\false -существует или нет геймвертекс Изменено 29 Июля 2024 пользователем Kirgudu Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 3 Августа 2010 (изменено) По классу CTime: Универсалка для получения текущих игровых даты\времени (для вывода например на худ) от Artosa (ну и меня тоже - вместе как то на форуме СП забавлялись вышеприведенными методами и в итоге пришли к почти идентичным кодам ) --/ передаем аргументы из числа "Y", "M", "D", h"", "m", "s", "ms" - по одной штуке, смотря какое значение текущего игрового времени или даты хотим получить; по умолчанию функция возвращает секунды. function Get_StringOnTimeOrDate(sType) if sType then local tTime = { ["Y"] = game.CTime.DateToYear, --/ 2012 ["M"] = game.CTime.DateToToMonth, --/ 01/2012 ["D"] = game.CTime.DateToDay, --/ 01/01/2012 ["h"] = game.CTime.TimeToHours, --/ 23 ["m"] = game.CTime.TimeToMinutes, --/ 23:59 ["s"] = game.CTime.TimeToSeconds, --/ 23:59:59 ["ms"] = game.CTime.TimeToMilisecs --/ 23:59:59:999 } if sType == string.lower(sType) then --/ аргумент в нижнем регистре return game.get_game_time():timeToString(tTime[sType] or 0) --/> время end return game.get_game_time():dateToString(tTime[sType] or 0) --/> дата end return game.get_game_time():timeToString(game.CTime.TimeToSeconds) --/> по дефолту 23:59:59 end Изменено 29 Июля 2024 пользователем Kirgudu Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 30 Августа 2010 (изменено) Содержание: а) имена файлов\модулей игры - идут как строковые ключи в нижнем регистре(правило соблюдается для всех ключей вообще). Значением ключа в данном случае является таблица содержащая(опять же как строковые ключи) все имена функций, скриптовых классов, констант и глобальных(локальные сюда не попадают) переменных модуля. Значения ключей - соответственно function, userdata, table, значение инициированных переменных - смотря что содержит файл. б) имена движковых классов - тип значения =userdata (из lua недоступен для чтения - так что узнать список методов не получится). в) имена Lua функций экспортированных в библиотеки игры(наконец то я узнал их точный список ) - идут либо как название функции, либо как название пространства имен Lua - table, math, string - соответственно тип значения либо function, либо (во втором случае) таблица, в которой перечисляются уже сами функции экспортированные из данного пространства имен (это уже второй уровень итерации). г) имена пространств имен игры и глобальных функций - типа device(), get_hud(), get_console(), time_global() и т.д. д) имена глобальных скриптовых функций из файла _g.script. Вроде все (хотя может чего и упустил - табличка все таки большая). Заметил что в таблице присутствуют метод\ы (из экспортированных namespace - например из actor_stats), которые в lua_help не указаны. Кстати: метатаблица _G содержит субтаблицу _g в которой практически(точно не сверял) все тоже самое, что и в таблице первого уровня, и при этом субтаблица _g содержит еще и саму себя. На втором уровне итерации - (когда тип значения table) если пройтись по модулям, то получаем список имен функций и переменных модуля - как я уже выше указывал. Собственно можно зайти дальше - в таблицы третьего и четвертого(если есть) уровня - но это не имеет смысла, так как получим содержание таблиц из скриптов игры, которые и так можно либо посмотреть наглядно(если они заполнены), либо проитерировать в игре. Код для получения распечатки _G (итерация двухуровневая): pcall встроен для того, чтобы не вылетать на рабочий стол при итерации этой метатаблицы, так как в некоторых местах tostring'u попадаются неприемлемые для конвертации значения - nil или вызов функции. В этом случае в распечатке будет указано место ошибки и вместо значения строка "error_value". function PrintG() local res, value for k, v in pairs(_G) do Console(tostring(k).." = "..tostring(v)) --Console() это моя "обертка" get_console() - забыл ее заменить здесь if type(v)== "table" then get_console():execute("load ~ "..string.format("РАСПЕЧАТЫВАЕМ СУБТАБЛИЦУ: %s ", k)) for key, val in pairs(_G[k]) do res, value = pcall(tostring, val) if not res then get_console():execute("load ~ ".."Ошибка преобразования значения: "..value) value="error_value" end get_console():execute("load ~ "..string.format("субтаблица: %s = %s", key, value)) end get_console():execute("load ~ ".."КОНЕЦ СУБТАБЛИЦЫ") end end end Что хотелось бы узнать: 1) Как это можно использовать в игровых целях? 2) Как можно загрузить в эту таблицу модуль который туда еще не был кэширован (есть мнение, что пока к своему (не дефолтному) файлу(точнее к функции из него) не обратишься, он туда не кешируется, и следовательно автономный вызов функции из этого файла function Func() body end Func() приводит к вылету ее не вызову так как в _G файла с этой функцией еще нет. Ну и какой-нибудь дoполнительный теорбазис обо всем этом тоже не помешал бы. Изменено 2 Сентября 2010 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 30 Августа 2010 Обычно порядок другой smile.gif Есть игровая цель и думается: "Как это можно сделать?" Обычно я так и делаю Про кеширование: я имел ввиду вот что - берем функцию - например такую - function TestMessage() news_manager.send_tip(db.actor, "Функция вызвана автономно", 0, "default", 180000) end и вставляем ее в файл в котором есть функции вызываемые из апдейта. И пишем под функцией ее автономный вызов TestMessage() При загрузке игры функция благополучно вызывается. Но если ее поместить в файл, который ни откуда не вызывается, то вызова не будет - так как в _G данный файл еще не был загружен. К тому же при попытке обратиться к незагруженному в таблицу _G файлу из xml тегов (это уже пишу на основе чужого опыта) может произойти вылет. Отсюда и вопрос - как этим процессом загрузки данных в метатаблицу _G можно манипулировать. Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 30 Августа 2010 (изменено) прописать вызов функции из start_game_callback Но это уже не будет автономным вызовом функции. Вызов то во внешний файл можно поставить куда угодно. ---------------------------------------------------------------------------------------- По поводу вылетов при обращении к своему файлу из xml -тегов: как я уже отметил - это не мой опыт - но опыт человека многим известного - Artosa(разработчика мультимода Симбион). Вот что он писал по этому поводу: То, что вызов функции из скрипта, имеющего синтаксические ошибки невозможен - это собственно и так понятно. Скрипт не считывается в метатаблицу _G/db и обращение к отсутствующей таблице -> nil. А вот с фактом того, что первичное обращение к 'самописному' скрипту порой приводит к аналогичному результату (nil), заметил еще в давние времена, когда начинал ковыряться в кодах игры. Причем практически 100% это заметно при вызове из диалогов (xml-ек) 'своих' функций из 'своих' скриптов. Предполазаю, что при косвенных вызовах (через xml-тэги или аналогичное) идет обращение НЕ к скрипту, а к метатаблице _G (или даже db!) и если файл скрипта еще не был кеширован в нее - результат ->nil. -------------------------------------------------------------------------------------- И еще - можно чуток поподробнее о функции init ? Заметил, что во всех биндерах есть функция init() или bind() и указывается она в конфиг секциях объектов которые биндятся. Какую функцию ты имел ввиду? --------------------------------------------------------------------------------------------- malandrinus Спасибо за указание на prefetch() - будем тестить. ------------------------------------------------------------- Все работает - один минус - вызов prefetch() нужно куда-то ставить - автономность вызова функций опять же убивается. Изменено 30 Августа 2010 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 1 Сентября 2010 (изменено) Kolmogor Смысл всей этой затеи с автономностью - делать свои разработки как можно менее зависимыми от дефолтных файлов(совместимость модов будет более простая) - в плане вызовов своих функций. Например на данный момент для одной своей разработки я полностью избавился от необходимости использовать bind_stalker как для апдейта, так и в плане некоторых каллбеков - переустановил их на эктора заново в своем биндере. malandrinus Если сильно надо, поставь все необходимые вызовы prefetch в начале модуля _g.script. Так тут дело не в том куда поставить - вариантов то масса - а в том именно, что нАдо кУда То ставить - а это значит опять задейстовать\править дефолтные файлы. Изменено 2 Сентября 2010 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 19 Сентября 2010 (изменено) Распишу немного то, что по работе с физикой объектов освоил: Для начала требуется получить управление над физической оболочкой объекта для чего существует уже описанный в справочнике метод get_physics_shell(). Применяем метод к клиентской юзердате объекта. Далее можно обратиться к методам нижеследующих классов для нужных нам действий. Скрытый текст class physics_shell { get_joints_number() --получить число сочленений у объекта, если они конечно есть. Чаще есть только элементы и кости. is_breaking_blocked() -- возможно проверка на заблокированность разрушаемости объекта. У меня всегда возвращал false - имеется ввиду после применения метода block_breaking(). get_element_by_bone_id(number) -- получить элемент по числовому идентификатору кости. get_linear_vel(vector&) is_breakable() -- разрушаем ли объект. У меня метод всегда возвращал false как для объектов класса O_PHYS_S так и для P_DSTRBL get_elements_number() -- получить число элементов у объекта. У ящиков и контейнеров элементов одна штука. unblock_breaking() -- убрать блокировку ? get_joint_by_bone_name(string) --получить сочленение по строковому идентификатору кости. get_element_by_order(number) -- получить элемент по порядковому номеру. Объекты с которым я работал имели только один элемент и его порядковый номер был соответственно 0. get_element_by_bone_name(string) -- получить элемент по строковому идентификатору кости. apply_force(number, number, number) -- применить импульс к объекту по трем координатным осям - x, y, z. Задавая разные значения для каждой оси можно варьировать направление куда объект будет "пнут" импульсом. get_angular_vel(vector&) block_breaking() -- полагал что блокирует разрушение объектов класса P_DSTRBL - однако тест не принес желаемого эффекта. get_joint_by_order(number) -- получить сочленение по порядковому номеру. get_joint_by_bone_id(number) -- видимо получить сочленение по числовому идентификатору кости. }; Методы класса physics_element следует применять к предварительно полученному объекту элемента физической оболочки предмета. Скрытый текст class physics_element { get_density() -- получить плотность объекта. Весьма любопытные цифирьки дает - к реальной плотности материалов(железо\дерево\ткань\картон и т. д.) отношения не имеют. Тестил на разного рода ящиках и контейнерах. get_mass() -- получить массу . Значение совпадает с тем что возвращает метод mass() для клиентского объекта. is_fixed() -- проверка зафиксирован ли элемент. is_breakable() -- видимо проверка является ли объект разрушаемым - у меня на на объектах класса P_DSTRBL метод возвращал всегда false. -- Для справки - объекты класса O_BRKBL физ. оболочки не имеют - поэтому, хотя метод по названию вроде как для них, на самом деле неприменим к этому классу. get_volume() -- получить физический объем объекта. По результатам теста вполне вменяемые цифры - объекты мелкой вместимости дают маленькие значения, крупной - большие. get_linear_vel(vector&) fix() --зафиксировать элемент физической оболочки(фактически сделать сам объект привязанным к точке). Никто не использует - а зря. Я этот метод для фиксации своих схронов применил, а также мин-растяжек. get_angular_vel(vector&) apply_force(number, number, number) -- применить импульс к элементу объекта по трем координатным осям - x, y, z. release_fixed() -- удалить фиксацию элемента. Побочный эффект - объект переходит в состояние невесомости. Очень прикольно надо сказать выходит. global_transform(physics_element*) -- не дало никакого эффекта. Возможно неправильно применял. }; Пример фиксации объекта - хоть в воздухе, хоть на земле. Фиксация сохраняется и после сейв\лоада. Но у мелких объектов фиксация после сейва\лоада слабая - и может легко разрушаться от приложения к нему силы. До перезагрузки - фиксируется намертво. Скрытый текст function ObjectFixed(id) if id then local obj = level.object_by_id(id) if obj then local pshell = obj:get_physics_shell() if pshell then local element = pshell:get_element_by_order(0) if element then element:fix() end end end end end Кстати насчет метода script_server_object_version() вот для чего он используется: local ss_ver = script_server_object_version() local IS_SOC = (ss_ver <= 7) -- although anything earlier then 1.0004 won't work local IS_CS = (ss_ver > 7 and ss_ver < 12) -- although anything earlier then 1.5.0.4 won't work local IS_COP = (ss_ver >= 12) --(ss_ver == 12) комментарии думаю излишни. Kirag Спасибо. Я так и думал что как то не так их применял. Теперь более менее понятно. Но вот только что они дают интересного(линеарное и угловое ускорение?). И как работать с полученными значениями? Изменено 26 Июля 2024 пользователем Kirgudu 1 Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 29 Сентября 2010 (изменено) malandrinus, Занялся недавно скриптовыми диалогами - на практике. В общем думаю стоит добавить в твои посты про них следующий момент: При использовании метода AddAction(string) функция, которая вызывается им, принимает вот такой набор аргументов: func(oSpeaker1, oSpeaker2, sDlgId, idPhrase) первые два аргумента думаю всем понятны - юзердата собеседников, sDlgId - строковое имя диалога, и самый важный для меня аргумент - idPhrase - айди фразы (строковое или числовое - в 1.0004 используются числовые идентификаторы). Не зная всего этого - потратил лишнее время на изобретение системы отслеживания активированных фраз в диалоге - но все оказалось гораздо проще. Функция, которая вызывается методом AddPrecondition(string) принимает немного другой набор аргументов: precondition(oSpeaker1, oSpeaker2, sDlgId, idParent, idPhrase) как видно тут добавился еще один - idParent, который возвращает айди родительской фразы, то есть фразы идущей перед той, в которой данный прекондишен находится. При динамическом формировании фраз (например как у меня через цикл) - когда число фраз заранее неизвестно - значение аргумента idPhrase просто незаменимо. Без этого я например просто не смог бы передать нужные данные для каждой конкретной фразы. Ну правда я немного схитрил и использовал give_talk_message для некоторых ответных фраз NPC - просто с иконкой фразы красивше смотрелись (и иконка в тему). Вот. Пока все, что выяснил интересного. Работает мой диалог отлично - так что тебе большое спасибо за раскрытие темы. Изменено 29 Сентября 2010 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 30 Сентября 2010 (изменено) malandrinus Там это всё есть в первой части Вот как раз потому, что только в первой части - я и не обратил внимания - поскольку был сосредоточен именно на скриптовых методах. Если продублировать и там - тогда думаю многим будет яснее. Они же не дают практически никаких преимуществ по сравнению с XML. Ну как это не дают преимуществ - еще как дают. Я их применил для динамического создания диалога (у одного NPC ) о продаже кодов к закодированным схронам. Фразы во первых формируются в цикле - что в xml сделать нельзя - то есть их число заранее неизвестно и определяется длиной таблички, которая хранит коды. В момент инициализации диалога специальная функция у меня формирует временную(существующую только до закрытия диалога) табличку со всеми нужными(и свежими данными), а далее в каждую новую фразу подставляются табличные данные. И хотя сами фразы однотипные по структуре - наполнение у всех разное. Что опять же нельзя сделать из xml, где наполнение предустановлено заранее. Ну и на каждую фразу ГГ стоит скриптовый экшен, который выполняет нужное действие ориентируясь на номер фразы. Также использованы скриптовые прекондишены. Диалог динамически меняет - не знаю как правильно сказать - граф не граф - в общем свой состав - каждая активированная фраза о покупке тут же исчезает из диалога(так как больше не нужна), при новой инициации диалога он строится уже в новом составе(с новым числом фраз) и с обновленными данными. В случае, если данных нет - кончились - выводится фраза NPC типа "на сегодня предложений больше нет". Диалог у меня конечно маленький (и развилок всего пара штук)- но работает как надо. Изменено 30 Сентября 2010 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 30 Сентября 2010 (изменено) malandrinus, В противном случае можно нарваться на абсолютно непредсказуемые ошибки, которые зависят от таких вещей, как запустили ли вы программу только что или это уже второй и далее сейв Нда, вот я и нарвался на непредсказуемые ошибки. Во первых, если сделать перед началом диалога сейв, потом поговорить с NPC и купить у него всю инфу(то есть активировать все имеющиеся фразы, которые по использованию больше не выводятся - вместо них будет выводиться развилочная фраза "На сегодня ничего предложить не могу."), то после того как снова - не выходя из игры - загрузить тот же сейв перед началом диалога - получаем такую ситуацию - NPC говорит, что инфы НЕТ! То есть получается, что диалог заново - с нуля - действительно как ты и писал не выстраивается\не инициализируется. Вчера я этот момент даже не проверил. А во вторых странная путаница выходит время от время с номерами фраз и ключами временной таблицы(они же номера фраз) хранящей инфу для фраз - в некоторых случаях они перестают совпадать. И я получаю сравнение числа с nil. В общем требуется серьезный разбор полетов . Поможешь? ----------------------------------------------------------------------- Путаницу с ключами вылечил. Теперь все вроде работает без ошибок - хотя плохо, конечно, что диалог не желает обновляться вторично. У меня так происходит даже если были активированы не все фразы - при загрузке сейва сделанного по итогам диалога, все равно получаю только фразу-концовку "На сегодня ничего предложить не могу.", хотя еще несколько фраз не были использованы. Но если выйти из игры, зайти снова и загрузить этот сейв - тогда появляются все неиспользованные фразы. Исправил и этот момент - надо было просто сохранять табличку с данными для фраз - она ведь у меня с прекондишенами для фраз связана, а так как она не сохранялась, то прекондишены после перезагрузки возвращали false для вывода фраз. Теперь в этом плане все норм. А действительно никак нельзя переинициализировать диалог вручную - принудительно? Ведь граф диалога куда то записывается при инициализации диалога...а если перезаписать...если конечно знать что и как... ---------------------------------------------------------------------------- Кстати, а что полезного дает строковое айди диалога - кроме того, что оно используется при выводе в лог в случае ошибки при построении диалога? Изменено 2 Октября 2010 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 1 Октября 2010 (изменено) malandrinus Окей, насчет инициализации и хранения диалогов понял. (примерно так и думал, что есть какой то движковый storage\ массив для них). Кстати вот и ответ на мой вопрос про айди диалогов - я имел ввиду, когда мы его получаем как входящий аргумент например из прекондишена или экшена - то какая польза от этого параметра? видимо никакой, но диалоги ...помещаются в это хранилище, откуда при дальнейших запросах выбираются по ключу (идентификатору диалога). То бишь назначение айди диалогов - для внутреннего использования функциями игры. Для модмейкера получается ничего не дает. Изменено 1 Октября 2010 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 30 Декабря 2010 (изменено) А теперь, товарищи, дружно забудем такой архаизм как амкашную функцию разделения строки str_explode (и ее варианты в других модах) и начинаем пользоваться быстрыми методами: (несмотря на то, что код может показаться не очень компактным, легко заметить, что там всю основную работу выполняет одна строчка - все прочее - дань универсализму.) Авторы Gun12, Garry_Galler, Artos - изначально был мой вариант с одним шаблоном, потом Gun12 предложил более универсальный паттерн, Artos привел все в божеский вид, ну и общими усилиями получился такой вариант (последняя редакция - чисто моя) Аргументы: sStr -- cтрока для разбора Mode -- режим заполнения таблицы sDiv --сепаратор: если указываем, то обязательно указать режим Mode sPattern -- свой шаблон:если указываем, то в аргументе sDiv передать nil и обязательно указать режим Mode function StringSplit(sStr, Mode, sDiv, sPattern) local tRet = {} local sPatt if sDiv and not sPattern then --// если сепаратор задан: разделяем по нему --// если нет шаблона - используем универсальный sPatt = '[^%s%'..sDiv..']+' --// если сепаратор указан как nil, но указан шаблон: используем его elseif not sDiv and sPattern then sPatt=sPattern else--/ если сепаратор и шаблон не указаны: разделяем слова sPatt = '[%w%_]+' end if Mode == nil then --// обычный массив for sValue in sStr:gmatch(sPatt) do table.insert(tRet, sValue) end elseif Mode == true then --// таблица '[значение]=true' for sValue in sStr:gmatch(sPatt) do tRet[sValue] = true end elseif type(Mode) == "number" then --//таблица '[idx] = число или стринг' for sValue in sStr:gmatch(sPatt) do tRet[#tRet+1] = tonumber(sValue) or sValue end end return tRet end --вызовы local t =StringSplit("vid mode 1024x768", true, nil, "%d+") --используем свой шаблон для получения из строки двух цифр local t =StringSplit("ammo_9x18_fmj, ammo_9x18_pmm, ammo_11.43x23_fmj", 1,",") -- делим строку по разделителю-запятой -- делим строку на слова независимо от имеющихся разделителей local t =StringSplit(" There will come soft rains and the smell of the ground, And swallows circling with their shimmering sound") -- когда в строке имеется несколько видов сепараторов и нужно все их указать, можно сделать так: local s = "ammo_9x18_fmj, ammo_9x39_pab9! ammo_9x39_ap$ ammo_9x39_sp5? ammo_9x18_pmm; ammo_11.43x23_fmj" local t =StringSplit(s, true,",%;%?%!%$") Изменено 30 Декабря 2010 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 14 Января 2011 (изменено) Хотел уточнить: класс CUIStatic действительно не поддерживает вывод анимированных текстур (в формате ogm) ? Попробовал создать экземпляр статика с ogm и вывести на худ (через AddDialogToRender()) свою видеоанимацию - вылетел(ругалась какая то движковая функция связанная с кодеком theora ). Решил попробовать тоже самое сделать с дефолтным ogm - ui\ui_mm_fire (вдруг мое видео нечитабельным было для сталка) - тоже вылетел, правда лог другой был (малоинформативный поэтому не привожу). Насчет CUIStatic я был неправ- он то как раз позволяет использовать анимированные текстуры\видео. Но если вывести их в скриптовое окно проблем нет, то вот на худ - непонятно как - использование AddDialogToRender() приводит к вылету. Изменено 14 Января 2011 пользователем kokkai Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 14 Января 2011 (изменено) malandrinus В точку. Спасибо за подсказку. Я свои прочие статики сохранял во внешней локальной таблице(но не для того, чтобы вылета избежать - о возможности которого даже не подозревал- просто нужно было доступ к ним иметь постоянный), а на этот статик ссылка была внутри функции. Вынес ссылку во внешку - все появилось(использовал для теста видео из игры). Теперь еще осталось разобраться с моим видео, которое сталкер воспроизводить не хочет - конвертил из avi в ogv прогой ffmpeg2theora, расширение сменил на ogm - но вылетает зараза - видимо что то с форматом не то. [spoiler=вот лог -думаю мало кому знакомый ]stack trace: 001B:004AF4B9 XR_3DA.exe, CPerlinNoise3D::Get() 001B:0047BE38 XR_3DA.exe, CTheoraSurface::Update() 001B:0048CB15 XR_3DA.exe, CTexture::apply_theora() PS: Да, вот еще - для расширения так как сказать кругозора - почему игра(компилятор) не видит уже скомпилированный скриптовый файл? Ради теста решил скомпилировать свой игровой скрипт в SCITE - положил потом в в папку script, расширение .script - так не видит в упор, как будто его там и нет вовсе. Изменено 14 Января 2011 пользователем Garry_Galler 1 Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 20 Января 2011 (изменено) есть ли функция закрытия/открытия инвенторя(пда)? Вот так я закрывал окно торговли --// поставить вызов OnTrade(info_id) в начало функции actor_binder:info_callback(npc, info_id) - файл bind_stalker.script local UITradeWnd function OnTrade(info_id) if info_id =="ui_trade" then UITradeWnd = level.main_input_receiver() elseif info_id == "ui_trade_hide" then UITradeWnd = nil end end --// вызов функции закрывает окно торговли - можно ставить куда угодно -хоть на апдейт function HideTradeWnd() if UITradeWnd then UITradeWnd:GetHolder():start_stop_menu(UITradeWnd, true) end end Если вместо инфопоршней на открытие\закрытие окна торговли указать инфопоршни на открытие\закрытие пда -"ui_pda" и "ui_pda_hide - или окна инвентаря - ui_inventory\ui_inventory_hide - будет тоже самое. TRAMP14 Движком - но вполне поддается редактированию в конфиге. Например можно сделать, чтобы шкала заполнялась\убывала не горизонтально, а вертикально, размеры поменять, координаты, и т.д . Вот с цветом вроде никак. Изменено 20 Января 2011 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 31 Января 2011 (изменено) Если кто сможет выяснить условия работы этого метода - обязательно отпишитесь здесь Насчет move_to()-метод работает, хотя не со всеми партиклами корректно. Некоторые не перемещал вообще, либо перемещал, но весьма криво - например часть партикла(если это pg) остается на месте - другая движется, либо вместо движения - создается несколько визуальных объектов, которые никуда не движутся. local bPlay = false local iCountUpdate =0 local iPos local iDir local gObj local oPart= particles_object("static\\zharka_static") --// апдейтим function MoveParticle(sid) gObj = sid and level_object_by_sid(sid) or db.actor if not gObj then return end if bPlay then if not iPos then iPos = gObj:position() iDir = gObj:direction() end iCountUpdate=iCountUpdate+1 if iCountUpdate==20 then --// через каждые 20 циклов апдейта меняем направление движения и позицию (на 1 метр) iDir = vector_rotate_y(iDir, math.random (-15, 15)) iPos=iPos:add(iDir:mul(1)) iCountUpdate=0 end --// перемещаем local val = not oPart:playing() and oPart:play_at_pos(iPos) or oPart:move_to(iPos,iPos); --// выключаем else if oPart and oPart:playing() then oPart:stop() iPos=nil iDir=nil end end end --/ вкл/выкл партикл :-) function StartStop() bPlay = not bPlay end Изменено 31 Января 2011 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 31 Марта 2011 (изменено) _Призрак_ Не уверен, но мне кажется что он должен возвращать nil после выхода врага из определенного радиуса от объекта, к которому метод был применен. По крайне мере аналогичный метод monstr:get_corpse() возвращает юзердату ближайшего трупа только в определенном радиусе от монстра. Изменено 31 Марта 2011 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 18 Мая 2011 Whisper А что делает функция wait() в _g.script? Она там... присутствует. Как памятник нерукотворный гению разрабов. Собственно в оригинале она(если я не ошибаюсь) никак задействована, так как скрипты в которых ее можно найти - тестовый мусор. Впрочем, попробовать применить ее можно - только скрипт нужно запустить как подпрограмму(тогда и малопонятных вылетов не будет) - по идее она должна тормозить выполнение только данного скрипта, а не весь процесс игры. Впрочем, тестил я это дело давно и сейчас даже не помню какие результаты были. ЗЫ: для запуска скрипта как подпрограммы нужно использовать lua пространство имен coroutine. Поделиться этим сообщением Ссылка на сообщение
Garry_Galler 7 Опубликовано 19 Мая 2011 (изменено) Выкладываю небольшой разбор содержимого полей таблицы db.storage, которое относится в NPC. Делал его некоторое время назад в тестовых целях, до конца так все и не разобрал, но думаю и этого будет достаточно для основных нужд модмейкеров. ЗЫ: Оформлено все в виде функции, которая содержит таблицу: строковой идентификатор=значения поля и возвращает значения того или иного поля db.storage по его идентификатору в таблице и айди NPC ( вызов примерно такой - GetData(level_object_by_sid(sid), "target_state") ). Там где используется много операторов and - это способ защиты от вылета при обращении к несуществующему полю таблицы. Распечатку таблицы я делал сразу по всем полям, а так как у разных NPC содержание полей было разным, то такие проверки избавляли меня от вылетов. ЗЗЫ: Данную функцию можно использовать только в тестовых целях, а не для реального применения. --------------------------------------------------------------------------------------------- function GetData(npc, type) local tMgr ={ --------------------------------------------------------------------------------------------- --// поля стейт менеджера --------------------------------------------------------------------------------------------- state_mgr = db.storage[npc:id()].state_mgr, --// юзердата класса state_manager target_state = db.storage[npc:id()].state_mgr.target_state, --// string название состояние из state_lib current_direction = db.storage[npc:id()].state_mgr.current_direction, --// vector или nil - направление взгляда? target_position = db.storage[npc:id()].state_mgr.target_position, --// vector позиция (своя или того на кого смотрит?) или nil current_object = db.storage[npc:id()].state_mgr.current_object, --// number (-1 или nil) combat = db.storage[npc:id()].state_mgr.combat, --// boolean - находится ли в состоянии боя alife = db.storage[npc:id()].state_mgr.alife, --// boolean - под алайфом или нет? emerg = db.storage[npc:id()].state_mgr.emerg, --// table, в которой должны быть поля: animation и animation_nout, однако почему то их нет synsound = db.storage[npc:id()].state_mgr.synsound, --// ?? yaw_delta = db.storage[npc:id()].state_mgr.yaw_delta, --// number угол точности - 5 (градусов вроде) subanim = db.storage[npc:id()].state_mgr.subanim, --// number - 0 глубина рекурсивности анимации need_reweapon = db.storage[npc:id()].state_mgr.need_reweapon, --// boolean look_object = db.storage[npc:id()].state_mgr.look_object, --// number - айди объекта на которого NPC предписано смотреть look_position = db.storage[npc:id()].state_mgr.look_position, --// vector - позиция куда предписано смотреть --------------------------------------------------------------------------------------------- --// прочие поля --------------------------------------------------------------------------------------------- move_mgr = db.storage[npc:id()].move_mgr, --// юзердата класса move_mgr state = db.storage[npc:id()].state, --// должно быть юзердатой класса -- но у меня возвращалось nil --------------------------------------------------------------------------------------------- hit = db.storage[npc:id()].hit, --// table (но у меня таблица была nil - даже после нанесения хита NPC, в ней должно быть поле hit.who - айди того, кто нанес хит --------------------------------------------------------------------------------------------- enemy = db.storage[npc:id()].enemy, --// юзердата текущего врага --------------------------------------------------------------------------------------------- death = db.storage[npc:id()].death, --// table death_section = db.storage[npc:id()].death.section, --// string - имя секции логики death_scheme = db.storage[npc:id()].death.scheme, --// string имя схемы death_npc = db.storage[npc:id()].death.npc, --// userdata death_actions = db.storage[npc:id()].death.actions, --// table death_userdata = db.storage[npc:id()].death.actions.userdata, --// boolean death_info = db.storage[npc:id()].death.info[1], --// table death_info_section = db.storage[npc:id()].death.info[1] and db.storage[npc:id()].death.info[1].section, --//?? death_info_infop_check = db.storage[npc:id()].death.info[1] and db.storage[npc:id()].death.info[1].infop_check and db.storage[npc:id()].death.info[1].infop_check[1], --// table death_info_infop_check_expected = db.storage[npc:id()].death.info[1] and db.storage[npc:id()].death.info[1].infop_check and db.storage[npc:id()].death.info[1].infop_check[1] and db.storage[npc:id()].death.info[1].infop_check[1].expected, --// boolean death_info_infop_check_func = db.storage[npc:id()].death.info[1] and db.storage[npc:id()].death.info[1].infop_check and db.storage[npc:id()].death.info[1].infop_check[1] and db.storage[npc:id()].death.info[1].infop_check[1].func, --//string death_info_infop_set = db.storage[npc:id()].death.info[1] and db.storage[npc:id()].death.info[1].infop_set and db.storage[npc:id()].death.info[1].infop_set[1], --// table death_info_infop_set_name = db.storage[npc:id()].death.info[1] and db.storage[npc:id()].death.info[1].infop_set and db.storage[npc:id()].death.info[1].infop_set[1].name, --// string - имя инфопоршня death_info_infop_required = db.storage[npc:id()].death.info[1] and db.storage[npc:id()].death.info[1].infop_set and db.storage[npc:id()].death.info[1].infop_set[1].required, --//boolean death_info2 = db.storage[npc:id()].death.info[2], --// table death_info_section2 = db.storage[npc:id()].death.info[2] and db.storage[npc:id()].death.info[2].section, --//?? death_info_infop_check2 = db.storage[npc:id()].death.info[2] and db.storage[npc:id()].death.info[2].infop_check, --// table death_info_infop_set2 = db.storage[npc:id()].death.info[2] and db.storage[npc:id()].death.info[2].infop_set, --// table --------------------------------------------------------------------------------------------- danger = db.storage[npc:id()].danger, --// table danger_ini = db.storage[npc:id()].danger.ini, --// userdata danger_npc = db.storage[npc:id()].danger.npc, --// userdata danger_section = db.storage[npc:id()].danger.section, --// string danger_scheme = db.storage[npc:id()].danger.scheme, --// string ignore_types = db.storage[npc:id()].danger.ignore_types, --// table - содержит строки игнорируемых типов объектов --------------------------------------------------------------------------------------------- abuse = db.storage[npc:id()].abuse, --// table abuse_npc = db.storage[npc:id()].abuse.npc, --// userdata abuse_manager = db.storage[npc:id()].abuse.abuse_manager, --// userdata класса CAbuseManager abuse_ini = db.storage[npc:id()].abuse.ini, --// userdata abuse_section = db.storage[npc:id()].abuse.section, --// string имя секции логики abuse_scheme = db.storage[npc:id()].abuse.scheme, --// string имя схемы --------------------------------------------------------------------------------------------- wounded = db.storage[npc:id()].wounded, --// table wounded_set = db.storage[npc:id()].wounded.wounded_set, --// boolean - флажок что скрипт вызывался use_medkit = db.storage[npc:id()].wounded.use_medkit, --// boolean help_dialog = db.storage[npc:id()].wounded.help_dialog, --// string имя диалога помощи wounded_section = db.storage[npc:id()].wounded.wounded_section, --// string wounded_scheme = db.storage[npc:id()].wounded.scheme, --// string wounded_npc = db.storage[npc:id()].wounded.npc, --// userdata wounded_ini = db.storage[npc:id()].wounded.ini, --// userdata wound_manager = db.storage[npc:id()].wounded.wound_manager, --// userdata класса Cwound_manager hp_state_infop_check = db.storage[npc:id()].wounded.hp_fight[1].state.infop_check, --// table hp_state_infop_set = db.storage[npc:id()].wounded.hp_fight[1].state.infop_set, --// table hp_cover_state_infop_check = db.storage[npc:id()].wounded.hp_cover[1].state.infop_check, --// table hp_cover_state_infop_set = db.storage[npc:id()].wounded.hp_cover[1].state.infop_set, --// table hp_victim_state_infop_check = db.storage[npc:id()].wounded.hp_victim[1].state.infop_check , --// table hp_victim_state_infop_set = db.storage[npc:id()].wounded.hp_victim[1].state.infop_set, --// table hp_fight_state_infop_check = db.storage[npc:id()].wounded.hp_fight[1].state.infop_check, --// table hp_fight_state_infop_set = db.storage[npc:id()].wounded.hp_fight[1].state.infop_set, --// table hp_state_see = db.storage[npc:id()].wounded.hp_state_see[1], --// table hp_state_see = db.storage[npc:id()].wounded.hp_state_see[1].dist, --// number --дистанция hp_state_see_state = db.storage[npc:id()].wounded.hp_state_see[1].state[1], --// table hp_state_see_state_section = db.storage[npc:id()].wounded.hp_state_see[1].state[1].section, --// string hp_state_see_state_infop_check = db.storage[npc:id()].wounded.hp_state_see[1].state[1].infop_check, --// table hp_state_see_state_infop_set = db.storage[npc:id()].wounded.hp_state_see[1].state[1].infop_set, --// table hp_state_see_sound = db.storage[npc:id()].wounded.hp_state_see[1].sound[1], --// table hp_state_see_sound_section = db.storage[npc:id()].wounded.hp_state_see[1].sound[1].section, --// string hp_state_see_sound_infop_check = db.storage[npc:id()].wounded.hp_state_see[1].sound[1].infop_check, --// table hp_state_see_sound_infop_set = db.storage[npc:id()].wounded.hp_state_see[1].sound[1].infop_set, --// table psy_state_state = db.storage[npc:id()].wounded.psy_state[1].state[1], --// table psy_state_state_section = db.storage[npc:id()].wounded.psy_state[1].state[1].section, --// string имя состояния psy_state_state_infop_check = db.storage[npc:id()].wounded.psy_state[1].state[1].infop_check and db.storage[npc:id()].wounded.psy_state[1].state[1].infop_check[1], --// table psy_state_state_infop_check_expected = db.storage[npc:id()].wounded.psy_state[1].state[1].infop_check and db.storage[npc:id()].wounded.psy_state[1].state[1].infop_check[1] and db.storage[npc:id()].wounded.psy_state[1].state[1].infop_check[1].expected, --// boolean psy_state_state_infop_check_func = db.storage[npc:id()].wounded.psy_state[1].state[1].infop_check and db.storage[npc:id()].wounded.psy_state[1].state[1].infop_check[1] and db.storage[npc:id()].wounded.psy_state[1].state[1].infop_check[1].func, --// string psy_state_state_infop_set = db.storage[npc:id()].wounded.psy_state[1].state[1].infop_set, --// table psy_state_state2 = db.storage[npc:id()].wounded.psy_state[1].state[2], --// table psy_state_state_section2 = db.storage[npc:id()].wounded.psy_state[1].state[2].section, --// string имя состояния psy_state_state_infop_check2 = db.storage[npc:id()].wounded.psy_state[1].state[2].infop_check, --// table psy_state_state_infop_set2 = db.storage[npc:id()].wounded.psy_state[1].state[2].infop_set, --// table psy_state_sound = db.storage[npc:id()].wounded.psy_state[1].sound[2], --// table psy_state_sound2 = db.storage[npc:id()].wounded.psy_state[1].sound[2], --// table wounded_syndata = db.storage[npc:id()].wounded.syndata, --// table state_wounded = db.storage[npc:id()].wounded.wound_manager.state, --// string состояние физ. ранености wounded_heavy\wounded_heavy_2\wounded_heavy_3 или пси-ранености --------------------------------------------------------------------------------------------- overrides = db.storage[npc:id()].overrides, --// table - оверрайды схем, типа combat_ignore_keep_when_attacked=false или companion_enabled=false --------------------------------------------------------------------------------------------- actor_dialogs = db.storage[npc:id()].actor_dialogs, --// table - видимо список разрешенных диалогов --------------------------------------------------------------------------------------------- actor_disable = db.storage[npc:id()].actor_disable, --// table - это тогда список запрещенных диалогов --------------------------------------------------------------------------------------------- meet = db.storage[npc:id()].meet, --// table meet_npc = db.storage[npc:id()].meet.npc, --// userdata meet_manager = db.storage[npc:id()].meet.meet_manager, --// userdata класса Cmeet_manager meet_precond = db.storage[npc:id()].meet.precond, --// string meet_abuse = db.storage[npc:id()].meet.abuse, --// boolean meet_set = db.storage[npc:id()].meet.meet_set, --// boolean init_meet = db.storage[npc:id()].meet.init_meet, --// ?? пустая строка meet_section = db.storage[npc:id()].meet.meet_section, --// string имя секции логики meet_scheme = db.storage[npc:id()].meet.scheme, --// string meet_ini = db.storage[npc:id()].meet.ini, --// userdata meet_use_section = db.storage[npc:id()].meet.use.section, --// boolean meet_use_infop_check = db.storage[npc:id()].meet.use.infop_check, --// table meet_use_infop_set = db.storage[npc:id()].meet.use.infop_set, --// table meet_use_wpn = db.storage[npc:id()].meet.use_wpn[1], --// table meet_victim = db.storage[npc:id()].meet.victim[1], --// table meet_victim_state = db.storage[npc:id()].meet.victim.state, --// table meet_victim_dist = db.storage[npc:id()].meet.victim.dist, --// number - дистанция meet_victim_wpn = db.storage[npc:id()].meet.victim_wpn[1], --// table meet_victim_wpn_state = db.storage[npc:id()].meet.victim_wpn[1].state, --// table meet_victim_wpn_state1 = db.storage[npc:id()].meet.victim_wpn[1].state and db.storage[npc:id()].meet.victim_wpn[1].state[1], --// table meet_victim_wpn_state1_infop_check = db.storage[npc:id()].meet.victim_wpn[1].state and db.storage[npc:id()].meet.victim_wpn[1].state[1] and db.storage[npc:id()].meet.victim_wpn[1].state[1].infop_check, --// table meet_victim_wpn_state1_infop_set = db.storage[npc:id()].meet.victim_wpn[1].state and db.storage[npc:id()].meet.victim_wpn[1].state[1] and db.storage[npc:id()].meet.victim_wpn[1].state[1].infop_set, --// table meet_victim_wpn_state1_section = db.storage[npc:id()].meet.victim_wpn[1].state and db.storage[npc:id()].meet.victim_wpn[1].state[1] and db.storage[npc:id()].meet.victim_wpn[1].state[1].section, --// string meet_state_state = db.storage[npc:id()].meet.meet_state[1].state[1], --// table meet_state_state_section = db.storage[npc:id()].meet.meet_state[1].state[1] and db.storage[npc:id()].meet.meet_state[1].state[1].section, --// string имя состояния meet_state_sound = db.storage[npc:id()].meet.meet_state[1].sound[1], --// table meet_state_sound_section = db.storage[npc:id()].meet.meet_state[1].sound[1] and db.storage[npc:id()].meet.meet_state[1].sound[1].section, --// string секция звуковой схемы meet_state_state_infop_check = db.storage[npc:id()].meet.meet_state[1].state[1].infop_check and db.storage[npc:id()].meet.meet_state[1].state[1].infop_check[1], --// table meet_state_state_infop_set = db.storage[npc:id()].meet.meet_state[1].state[1].infop_set, --// table meet_state_sound_infop_check = db.storage[npc:id()].meet.meet_state[1].sound[1].infop_check and db.storage[npc:id()].meet.meet_state[1].sound[1].infop_check[1], --// table meet_state_sound_infop_set = db.storage[npc:id()].meet.meet_state[1].sound[1].infop_set, --// table meet_zone = db.storage[npc:id()].meet.zone, --// table meet_state_wpn = db.storage[npc:id()].meet.meet_state_wpn[1], --// table meet_state_wpn_state = db.storage[npc:id()].meet.meet_state_wpn[1].state, --// table meet_state_wpn_state1 = db.storage[npc:id()].meet.meet_state_wpn[1].state and db.storage[npc:id()].meet.meet_state_wpn[1].state[1], --// table meet_state_wpn_state1_infop_check = db.storage[npc:id()].meet.meet_state_wpn[1].state and db.storage[npc:id()].meet.meet_state_wpn[1].state[1] and db.storage[npc:id()].meet.meet_state_wpn[1].state[1].infop_check and db.storage[npc:id()].meet.meet_state_wpn[1].state[1].infop_check[1], --// table meet_state_wpn_state1_infop_set = db.storage[npc:id()].meet.meet_state_wpn[1].state and db.storage[npc:id()].meet.meet_state_wpn[1].state[1] and db.storage[npc:id()].meet.meet_state_wpn[1].state[1].infop_set, --// table meet_state_wpn_state1_section = db.storage[npc:id()].meet.meet_state_wpn[1].state and db.storage[npc:id()].meet.meet_state_wpn[1].state[1] and db.storage[npc:id()].meet.meet_state_wpn[1].state[1].section, --// string - имя анимки meet_state_wpn_state2_infop_check = db.storage[npc:id()].meet.meet_state_wpn[1].state and db.storage[npc:id()].meet.meet_state_wpn[1].state[2] and db.storage[npc:id()].meet.meet_state_wpn[1].state[2].infop_check, --// table meet_state_wpn_state2_infop_set = db.storage[npc:id()].meet.meet_state_wpn[1].state and db.storage[npc:id()].meet.meet_state_wpn[1].state[2] and db.storage[npc:id()].meet.meet_state_wpn[1].state[2].infop_set, --// table meet_state_wpn_state2_section = db.storage[npc:id()].meet.meet_state_wpn[1].state and db.storage[npc:id()].meet.meet_state_wpn[1].state[2] and db.storage[npc:id()].meet.meet_state_wpn[1].state[2].section, --// string - имя анимки meet_state_wpn_sound = db.storage[npc:id()].meet.meet_state_wpn[1].sound, --// table meet_state_wpn_dist = db.storage[npc:id()].meet.meet_state_wpn[1].dist, --// number дистанция meet_dialog = db.storage[npc:id()].meet.meet_dialog[1], --// table meet_dialog_section = db.storage[npc:id()].meet.meet_dialog[1] and db.storage[npc:id()].meet.meet_dialog[1].section, --// string имя диалога встречи meet_dialog_infop_check = db.storage[npc:id()].meet.meet_dialog[1] and db.storage[npc:id()].meet.meet_dialog[1].infop_check,--// table meet_dialog_infop_check1 = db.storage[npc:id()].meet.meet_dialog[1] and db.storage[npc:id()].meet.meet_dialog[1].infop_check and db.storage[npc:id()].meet.meet_dialog[1].infop_check[1],--// table meet_dialog_infop_set = db.storage[npc:id()].meet.meet_dialog[1] and db.storage[npc:id()].meet.meet_dialog[1].infop_set, --// table meet_dialog2 = db.storage[npc:id()].meet.meet_dialog[2], --// table meet_dialog_section2 = db.storage[npc:id()].meet.meet_dialog[2] and db.storage[npc:id()].meet.meet_dialog[2].section, --// string имя диалога встречи meet_dialog_infop_check2 = db.storage[npc:id()].meet.meet_dialog[2] and db.storage[npc:id()].meet.meet_dialog[2].infop_check,--// table meet_dialog_infop_set2 = db.storage[npc:id()].meet.meet_dialog[2] and db.storage[npc:id()].meet.meet_dialog[2].infop_set, --// table meet_syndata = db.storage[npc:id()].meet.syndata, --// table --------------------------------------------------------------------------------------------- section_logic = db.storage[npc:id()].section_logic, --// string имя секции логики --------------------------------------------------------------------------------------------- loaded_section_logic = db.storage[npc:id()].loaded_section_logic, --// string имя секции логики --------------------------------------------------------------------------------------------- active_section = db.storage[npc:id()].active_section, --// string имя активной секции логики --------------------------------------------------------------------------------------------- loaded_active_section = db.storage[npc:id()].loaded_active_section, --// string имя активной секции логики --------------------------------------------------------------------------------------------- active_scheme = db.storage[npc:id()].active_scheme, --// string тип активной схемы логики walker\camper\remark и т.д --------------------------------------------------------------------------------------------- gulag_name = db.storage[npc:id()].gulag_name, --// string - имя гулага NPC --------------------------------------------------------------------------------------------- loaded_gulag_name = db.storage[npc:id()].loaded_gulag_name, --// string - имя гулага NPC --------------------------------------------------------------------------------------------- loaded_ini_filename = db.storage[npc:id()].loaded_ini_filename, --// string - имя файла логики --------------------------------------------------------------------------------------------- ini_filename = db.storage[npc:id()].ini_filename, --// string - имя файла логики --------------------------------------------------------------------------------------------- stype = db.storage[npc:id()].stype, --// number - тип схемы логики 0-4 из файла modules --------------------------------------------------------------------------------------------- zoneguard = db.storage[npc:id()].zoneguard, --// видимо поле для охранников - тип значения неизвестен } return tMgr[type] end Смысловую суть полей можно понять обратившись к файлам xr_схема.script - именно в них и происходит заполнение storage. Изменено 19 Мая 2011 пользователем Garry_Galler Поделиться этим сообщением Ссылка на сообщение