Nazgool 250 Опубликовано 19 Октября 2015 Поделиться Опубликовано 19 Октября 2015 @FonSwong, Оператор # может применяться к любой таблице. Если в таблице есть индексированная часть, то оператор определит её размер. В твоём случае ключами таблицы являются ID, которые не создают индексированного массива. Т.е. ключи таблицы не соответствуют порядку ключей массива 1,2,3,4,5,6, ... и т.д. по порядку. А что-то вроде 1523, 907, 23120 и т.п.Поэтому когда ты определяешь длину массива оператором #, то длина будет равна нулю (если конечно не будет ID с номером 1).А math.random не понимает единственного аргумента 0. Если первым аргументом задан 0 (являющийся началом интервала случайных чисел), то должен быть задан и второй аргумент, обозначающий конец этого интервала. Отсюда и ошибка - bad argument #1 to 'random' (interval is empty) 1 Ссылка на комментарий
Serge! 127 Опубликовано 19 Октября 2015 Поделиться Опубликовано 19 Октября 2015 FonSwong, Charsi дал простой и верный намёк на решение проблемы. Надо всего лишь изменить структуру массива tbl_sos. Сделать его не ассоциативным, а индексированным, т.е. вида tbl_sos = {{npc_id = id1, sos = 'SOS'},{ npc_id = id2, sos = ' '}, . . .} ну и далее получаем по случайному индексу соответствующее ему значение, т.е. ассоциативный массив, а из него чего уж там требуется или tbl_sos[index].npc_id или строку tbl_sos[index].sos Ссылка на комментарий
_Призрак_ 11 Опубликовано 19 Октября 2015 Поделиться Опубликовано 19 Октября 2015 Кстати, давно интересовал момент - как правильно будет получить количество элементов в ассоциативном массиве? Я помню делал полный перебор массива чтобы получить его размер, но может есть более приятный вариант? Freedom Ссылка на комментарий
Карлан 1 049 Опубликовано 19 Октября 2015 Поделиться Опубликовано 19 Октября 2015 (изменено) @_Призрак_, разве что table.keys, но работает медленнее. Изменено 20 Октября 2015 пользователем Карлан Ссылка на комментарий
FonSwong 33 Опубликовано 20 Октября 2015 Поделиться Опубликовано 20 Октября 2015 (изменено) Как правильно достать профиль? Сохраняю npc:id() непися, затем загружаю и мне нужно получить его профиль, но не через npc = level.object_by_id(id), ибо в оффлайне если нпс, то крашится игра затем передать npc другой фунции, а там уже она снова возьмёт npc:id() Пробовал после загрузки профиль вытаскивать через npc = alife():object(a), но он вроде как даёт сид, а дальше нужно передать "npc" с "id()" Изменено 20 Октября 2015 пользователем FonSwong Ссылка на комментарий
Winsor 177 Опубликовано 20 Октября 2015 Поделиться Опубликовано 20 Октября 2015 Кстати, давно интересовал момент - как правильно будет получить количество элементов в ассоциативном массиве? Я помню делал полный перебор массива чтобы получить его размер, но может есть более приятный вариант? Быстрее будет наверное только использование метаданных (setmetatable), в которых в процедурах добавления/удаления управлять списком ключей/количеством элементов. из плюсов - в дальнейшем не надо пробегаться каждый раз по всему массиву для подсчета , а обратится сразу к переменной метаданных, из минусов - накладные вычислительные расходы на эти процедуры. Если массив очень большой - то само собой обращение к метаданным будет быстрее. если часто меняется - то считать количество можно достаточно редко. Вам выбирать Ссылка на комментарий
Nazgool 250 Опубликовано 20 Октября 2015 Поделиться Опубликовано 20 Октября 2015 (изменено) может есть более приятный вариант? Ну это кому и как приятнее будет. Winsor, в принципе уже основное определил. Нужно сделать прокси таблицу в которой хранить ссылку на реальную таблицу. В этой прокси таблице завести уникальные поля, случайный доступ к которым будет максимально исключен. В таких полях можно хранить всякие служебные данные, как например длина таблицы. Также нужно определить для прокси и метатаблицу с полями (как минимум) __index и __newindex. В __newindex сделать слежение за размером таблицы при добавлении\удалении полей. Объявлять таблицу нужно с использованием специальной обёртки. эта обертка, при объявлении таблицы, присвоит переменной значение не реальной, а прокси-таблицы. Теперь при обращении к созданной таблице (а реально к прокси) каждый раз будет вызываться метаметод, так как таких полей в проски, к которым вы обращаетесь нет (на уникальные ключи попасть будет крайне сложно). Но тут минусы не ограничиваются "из минусов - накладные вычислительные расходы на эти процедуры." Для работы с такими таблицами нужно "научить понимать их" соответствующие функции. А именно : все из библиотеки "table" pairs ipairs next rawget rawset unpack getmetatable setmetatable В принципе там изменить быстрее чем говорить об этом Ну и последнее. Я это уже давно написал и пользуюсь. Так что если нужно, то поделюсь примером. Изменено 20 Октября 2015 пользователем Nazgool 1 Ссылка на комментарий
Kirgudu 1 216 Опубликовано 20 Октября 2015 Поделиться Опубликовано 20 Октября 2015 @Nazgool, зачем ждать запроса? Кому-то может пригодиться позже, а своевременно выложить пример возможности не будет. Лучше сейчас, это полезно. Инструмент Ссылка на комментарий
Nazgool 250 Опубликовано 20 Октября 2015 Поделиться Опубликовано 20 Октября 2015 (изменено) Ок. Подготовлю выложу.Ведь я так понимаю, что нужно и расписать всё "по понятиям" Вроде готово. Как-то так local _pairs = pairs local _ipairs = ipairs local _next = next local _rawget = rawget local _rawset = rawset local _unpack = unpack local _getmt = getmetatable local _setmt = setmetatable local _concat = table.concat local _insert = table.insert local _maxn = table.maxn local _remove = table.remove local _sort = table.sort function table.concat(t, ...) return _concat(t.__PROXY_KEY or t, ...) end function table.maxn (t) return _maxn (t.__PROXY_KEY or t) end function table.remove(t, pos) return _remove(t.__PROXY_KEY or t, pos) end function table.insert(t, ...) _insert(t.__PROXY_KEY or t, ...) end function table.sort (t, fun) _sort (t.__PROXY_KEY or t, fun) end function pairs (t) return _pairs (t.__PROXY_KEY or t) end function ipairs(t) return _ipairs(t.__PROXY_KEY or t) end function next (t) return _next (t.__PROXY_KEY or t) end function rawget(t,k) return _rawget(t.__PROXY_KEY or t,k) end function rawset(t,k,v) return _rawset(t.__PROXY_KEY or t,k,v) end function unpack(t,...) return _unpack(t.__PROXY_KEY or t,...) end function getmetatable(t) return _getmt (t.__PROXY_KEY or t) end function setmetatable(t,mt) _setmt(t.__PROXY_KEY or t, mt) return t end -- Получение длины таблицы. -- Если таблица создавалась при помощи функции 'proxy', то просто возвращается значение поля. -- Если таблица создавалась обычным образом, то происходит перебор всей таблицы и подсчет полей. function table.len(t) if t.__PROXY_LEN then return t.__PROXY_LEN else local n = 0 for _ in pairs(t) do n = n + 1 end return n end end -- Метатаблица для прокси-таблицы, определяющая все её возможности. local mt_proxy = {} -- Операция получения по индексу -- '.' or '[]' -- Возвращается значение поля из реальной таблицы. function mt_proxy.__index (t,k) return t.__PROXY_KEY[k] end -- Операция присваивания -- '=' -- Запись, изменение или удаление поля происходит в реальной таблице -- Для примера добавлен учет длины таблицы function mt_proxy.__newindex (t,k,v) local real = t.__PROXY_KEY -- если нужно изменяем счетчик длины таблицы if real[k] == nil then if v ~= nil then t.__PROXY_LEN = t.__PROXY_LEN + 1 end elseif v == nil then t.__PROXY_LEN = t.__PROXY_LEN - 1 end real[k] = v end -- При необходимости можно добавить и другие метаметоды -- Обертка для создания прокси-таблиц -- Может передаваться и заранее созданная таблица. -- Уникальные ключи с именами __PROXY_KEY и __PROXY_LEN выбраны для простоты. -- Ничто не мешает создать ключ типа 'z7vRmv45fUsd78idfJHubnhuHJkj6Gghsd3m5', чтобы наверняка. function proxy(t) local src = t or {} local new = {} new.__PROXY_KEY = src new.__PROXY_LEN = table.len(src) -- Т.е. в таблице 'new' только служебные, уникальные поля, а любые обращения идут именно к ней. -- Поэтому в любом случае вызывается соответствующий метаметод. return _setmt(new, mt_proxy) end -- Создавать таблицу с поддержкой прокси можно несколькими способами. -- 1. Простой вызов функции без аргументов. Возвратиться новая прокси-таблица t = proxy() -- 2. Вызов функции с передачей уже существующей таблицы. local x = {a=5, [3]='s'} t = proxy(x) -- 3. Похож на 1-й, но благодаря возможностям синтаксиса lua более информативный. -- т.е. видно что 't' это таблица, а непонтно что возвращаемое функцией 'proxy' t = proxy {} -- Получить длину таблицы можно либо вызвав table.len(t), либо напрямую обратившись -- к уникальномк ключу : local len = t.__PROXY_LEN -- Всё. Работать с 't' как обычно. -- P.S. Выдирал по кускам из более сложной разработки плюс некоторое редактирование, -- поэтому не исключены и очепятки. Изменено 20 Октября 2015 пользователем Nazgool 4 Ссылка на комментарий
Romz 142 Опубликовано 23 Октября 2015 Поделиться Опубликовано 23 Октября 2015 Нужна помощь. ЗП Имеется выброс. Он случается раз в 2 - 4 дня. Из игры я могу получить дату и время, когда был последний выброс, например, 20 апреля в 13 часов 20 минут. Могу получить промежуток между выбросами, в секундах. Могу получить текущие дату и время, например 21 апреля 11 часов 48 минут. Нужно рассчитать оставшееся до следующего выброса время, в часах и минутах (т.е. до выброса осталось Н часов и м минут) Имеется у меня функция, но она бред выдаёт. Конкретно, отрицательные значения часов и минут. К тому же, не учитывается, что выброс мог произойти в прошлом месяце (т.е. например, выброс был 28 апреля, а сейчас 1 мая) local delta_all = surge_manager.get_delta() local d,h,m = surge_manager.get_last_surge_time() --текущее время local d_t = vergas_lib.return_time(3) local h_t = vergas_lib.return_time(4) local m_t = vergas_lib.return_time(5) --считаю время (сек) прошедшее с последнего выброса local delta_d = 0 local delta_h = 0 if d == d_t then --выброс был в этот же день --считаю прошедшие часы delta_h = h_t - h else --выброс был накануне delta_h = 24 - h + h_t end --считаю прошедшие минуты local delta_m = math.abs(m - m_t) --перевожу все в игровые секунды local delta = delta_all - delta_h*3600 - delta_m*60 local delta_ost = math.fmod(delta,3600) local delta_h = (delta - delta_ost)/3600 delta = math.fmod(delta_ost,60) local delta_m = (delta_ost - delta)/60 return delta_h, delta_m local delta_all = surge_manager.get_delta() local d,h,m = surge_manager.get_last_surge_time() --текущее время local d_t = VS_surge_news.return_time(3) local h_t = VS_surge_news.return_time(4) local m_t = VS_surge_news.return_time(5) local delta_d = 0 local delta_h = 0 local delta_m = 0 --считаю время (сек) прошедшее с последнего выброса delta_d = d_t - d --считаю прошедшие часы if d == d_t then --выброс был в этот же день delta_h = h_t - h else --выброс был накануне delta_h = 24 - h + h_t end --считаю прошедшие минуты delta_m = math.abs(m - m_t) --перевожу все в игровые секунды local delta = delta_all - delta_d*86400 - delta_h*3600 - delta_m*60 local delta_ost = math.fmod(delta,3600) local delta_h = math.abs((delta - delta_ost)/3600) delta = math.fmod(delta_ost,60) local delta_m = math.abs((delta_ost - delta)/60) return delta_h, delta_m Но всё равно не взлетает... Шаман - СисАдмин Всяко-разно: для ЧН Ссылка на комментарий
Kirgudu 1 216 Опубликовано 23 Октября 2015 Поделиться Опубликовано 23 Октября 2015 (изменено) @Romz, у тебя есть все необходимые инструменты, ты же сам недавно подключал модули Артоса. В lua_helper есть метод (импортированный в публичное пространство) Get_PastSeconds. Получаешь им кол-во секунд, прошедшее со времени последнего выброса: local past_seconds = Get_PastSeconds(surge_manager.get_last_surge_time()) Затем из дельты между выбросами (которая тоже в секундах) вычитаешь полученное значение и превращаешь в часы и минуты простой арифметикой. Upd: единственное - твоя добавленная функция surge_manager.get_last_surge_time() должна возвращать объект типа CTime, то есть то, что в оригинальном surge_manager хранится в свойстве self.last_surge_time. Upd2: если интересно, как то же самое можно сделать без lua_helper, то вот: local past_seconds = game.get_game_time():diffSec(surge_manager.get_last_surge_time()) Изменено 23 Октября 2015 пользователем Kirgudu 1 Инструмент Ссылка на комментарий
Romz 142 Опубликовано 23 Октября 2015 Поделиться Опубликовано 23 Октября 2015 единственное - твоя добавленная функция surge_manager.get_last_surge_time() должна возвращать объект типа CTime,Ну это не моя функция, а @Vergas function get_last_surge_time() local Y, M, D, h, m, s, ms = 0, 0, 0, 0, 0, 0, 0 local g_s_m = get_surge_manager() Y, M, D, h, m, s, ms = g_s_m.last_surge_time:get(Y, M, D, h, m, s, ms) return D, h, m end То есть, можно было гораздо проще всё сделать... Просто, для информации и личного развитияА что, в ЛУА регистр названия переменной играет роль?То есть "M" и "m" будут разные переменные? Шаман - СисАдмин Всяко-разно: для ЧН Ссылка на комментарий
Kirgudu 1 216 Опубликовано 23 Октября 2015 Поделиться Опубликовано 23 Октября 2015 (изменено) @Romz, да, Lua регистр различает. То есть, можно было гораздо проще всё сделать... Смотря для чего сам Vergas её писал. А тебе да, можно сделать всё намного проще, по крайней мере в рамках заданного вопроса. Думаю, окончательное решение должно быть уже понятно. Изменено 23 Октября 2015 пользователем Kirgudu 1 Инструмент Ссылка на комментарий
Romz 142 Опубликовано 23 Октября 2015 Поделиться Опубликовано 23 Октября 2015 Да я, собственно, переделываю скрипт Vergas-a, который должен будить ГГ перед выбросом. У него это реализовано таким образом, что при вызове функции сна проверяется, сколько времени осталось до следующего выброса, и если меньше, чем ГГ собрался поспать, то устанавливается время сна равное оставшемуся до выброса времени, в часах. Но у него это сделано под оригинальный выброс, а у меня в сборке Атмосфир прикручен, и период выброса стоит раз в 2-4 дня. Причём, у меня такое ощущение, что промежуток между выбросами тоже может динамически меняться в некоторых пределах. Потому что если проматывать время, часто спать, то можно ловить выбросы на каждом сне, чего быть не должно. Шаман - СисАдмин Всяко-разно: для ЧН Ссылка на комментарий
Gaz24 6 Опубликовано 25 Октября 2015 Поделиться Опубликовано 25 Октября 2015 (изменено) Всем привет. Пытался переадаптировать схему боя НПС с ножом из ЗП в ТЧ. В итоге НПС достает нож, смотрит на ГГ и больше ничего не делает. Возникли вопросы:1. Кто-нибудь разбирал этот скрипт?2. Возможно подправить это баг?Вот еще файл скрипта ---- Rulix aka Bak --- 8.3.2010 function printf(s, ...)-- rx_ai.printf("kn:"..s,...)-- get_console():execute("flush")endlocal kn_ini = ini_file("misc\\rx_knife.ltx")local knife_sets = {forbiddens = {weapons = {},factions = {},npcs = {}},communities = {},ranks = {},check_prd = rx_utils.read_from_ini(kn_ini,"main","check_period",1001),fire_dist = rx_utils.read_from_ini(kn_ini,"main","fire_dist",1.5),enabled = rx_utils.read_from_ini(kn_ini,"main","enabled",false,0)}function init()if not knife_sets.enabled thenkn_ini = nilreturnendlocal ranks = {"novice","experienced","veteran","master"}for k,v in ipairs(ranks) doif kn_ini:section_exist(v) thenknife_sets.ranks[v] = {rate = rx_utils.read_from_ini(kn_ini,v,"rate",1)}endendlocal communities = { "stalker", "dolg", "freedom", "bandit", "military", "ecolog", "killer", "monolith" }for k,v in ipairs(communities) doknife_sets.communities[v] = {rate_add = rx_utils.read_from_ini(kn_ini,v,"rate_add",0),courage = rx_utils.read_from_ini(kn_ini,v,"courage",1),attack_wounded = rx_utils.read_from_ini(kn_ini,v,"attack_wounded",0),mutant_hunt = rx_utils.read_from_ini(kn_ini,v,"mutant_hunt",true,0) or nil}endknife_sets.forbiddens.weapons = rx_utils.parse_list(kn_ini,"main","forbidden_weapons",true)knife_sets.forbiddens.factions = rx_utils.parse_list(kn_ini,"main","forbidden_factions",true)knife_sets.forbiddens.npcs = rx_utils.parse_list(kn_ini,"main","forbidden_npcs",true)kn_ini = nilknife_sets.inited = trueendlocal kill_wounded = 0local sneak_attack = 1local close_attack = 2local mutant_hunt = 3local mutant_defend = 4local mutant_hunt_clsids = {[clsid.bloodsucker_s] = true,[clsid.boar_s] = true,-- [clsid.dog_s] = true,[clsid.flesh_s] = true,-- [clsid.pseudodog_s] = true,-- [clsid.burer_s] = true,-- [clsid.cat_s] = true,-- [clsid.chimera_s] = true,[clsid.controller_s] = true,-- [clsid.fracture_s] = true,-- [clsid.poltergeist_s] = true,-- [clsid.gigant_s] = true,-- [clsid.zombie_s] = true,-- [clsid.snork_s] = true,-- [clsid.tushkano_s] = true,[clsid.psy_dog_s] = true,-- [clsid.psy_dog_phantom_s] = true}}local mutant_defend_clsids = {-- [clsid.bloodsucker_s] = true,[clsid.boar_s] = true,-- [clsid.dog_s] = true,[clsid.flesh_s] = true,[clsid.pseudodog_s] = true,-- [clsid.burer_s] = true,[clsid.cat_s] = true,-- [clsid.chimera_s] = true,-- [clsid.controller_s] = true,[clsid.fracture_s] = true,-- [clsid.poltergeist_s] = true,-- [clsid.gigant_s] = true,-- [clsid.zombie_s] = true,-- [clsid.snork_s] = true,[clsid.tushkano_s] = true,[clsid.psy_dog_s] = true,-- [clsid.psy_dog_phantom_s] = true}}targets = {}local function remove_target(npc_id,st)if st.target and targets[st.target] == npc_id thentargets[st.target] = nilendst.target = nilendclass "evaluator_knife_attack" (property_evaluator)function evaluator_knife_attack:__init(npc,name,storage) super (nil,name)self.st = storageself.st.delay = 0self.st.timer = 0self.check_timer = 0local comm = npc:character_community()if self.attack_wounded == nil thenself.attack_wounded = math.random() < knife_sets.communities[comm].attack_woundedendif not self.courage thenself.courage = math.random(25,npc:character_rank()/4+51)endself.courage = self.courage*knife_sets.communities[comm].courageself.cmhunt = knife_sets.communities[comm].mutant_hunt-- rx_ai.printf("knife_init[%s]:kn_aw %s, courage %s, rank %s",npc:character_name(),tostring(self.attack_wounded),self.courage,npc:character_rank())rx_ai.subscribe_for_events(npc,self)endfunction evaluator_knife_attack:evaluate()local npc = self.objectif rx_utils.IsTrader(npc) thenreturn falseendlocal wm = rx_wmgr and rx_wmgr.get_wm(npc)local knife = npc:object("wpn_knife")if not knife or npc:animation_count() ~= 0 then-- printf("evaluator_knife_attack[%s]:not knife or anims",npc:character_name())remove_target(npc_id,self.st)return falseendlocal npc_id,tg = npc:id(),time_global()if self.st.delay > tg thenremove_target(npc_id,self.st)-- printf("evaluator_knife_attack[%s]:delay",npc:character_name())return falseendlocal be = npc:best_enemy()if not be thenremove_target(npc_id,self.st)return falseendlocal be_id = be:id()local target = self.st.target and level.object_by_id(self.st.target)if not (target and target:alive()) then-- printf("evaluator_knife_attack[%s]:not target",npc:character_name())remove_target(npc_id,self.st)endlocal npc_pos = npc:position()if target then-- printf("evaluator_knife_attack[%s]:target",npc:character_name())local target_pos = be:position()local dist = target_pos:distance_to(npc_pos)if targets[self.st.target] thenif targets[self.st.target] ~= npc_id thenprintf("evaluator_knife_attack[%s]:target gette",npc:character_name())remove_target(npc_id,self.st)elseif self.st.target ~= be_id and dist > 3 or not npc:accessible(target_pos) thenprintf("evaluator_knife_attack[%s]:target not access",npc:character_name())remove_target(npc_id,self.st)elseif self.st.type == kill_wounded and dist > 5 thenremove_target(npc_id,self.st)self.st.delay = tg+15000return falseelseif self.st.type == sneak_attack and target:see(npc) and dist > self.courage/20 thenself.st.type = close_attackreturn trueelseif self.st.type == close_attack and dist > self.courage/10 thenremove_target(npc_id,self.st)self.st.delay = tg+15000return falseelseif self.st.type == mutant_hunt and dist > 15 thenremove_target(npc_id,self.st)self.st.delay = tg+12000return falseelseif self.st.type == mutant_defend and dist > 12 or npc.health < 0.2 then -- or not (target:get_enemy() and target:get_enemy():id() == npc_id)remove_target(npc_id,self.st)self.st.delay = tg+12000return falseendreturn trueendelseif dist > 12 thenprintf("evaluator_knife_attack[%s]:target dist > 12",npc:character_name())self.st.target = nilendendendif self.check_timer > tg thenreturn target ~= nilendself.check_timer = tg+knife_sets.check_prdlocal be_pos = be:position()local dist = npc_pos:distance_to(be_pos)if targets[be_id] or (xr_wounded.is_wounded(be) and not self.attack_wounded) or dist > 10 or not npc:accessible(be_pos) then-- printf("evaluator_knife_attack[%s]:not access %s %s %s %s",npc:character_name(),tostring(targets[be_id]),tostring((xr_wounded.is_wounded(be) and not self.attack_wounded)),tostring(dist > 15),tostring(not npc:accessible(be_pos)))return falseendlocal be_see_me,me_see_be = be:see(npc),npc:see(be)if IsStalker(be) thenif xr_wounded.is_wounded(be) thenif self.attack_wounded and me_see_be and dist < 3.5 thenself.st.target = be_idself.st.type = kill_woundedreturn trueendreturn falseendif me_see_be and not be_see_me and self.courage > 40 and npc:body_state() == move.crouch and dist < 5 and npc.health > 0.5 then-- printf("sneak_attack[%s]:return true",npc:character_name())self.st.target = be_idself.st.type = sneak_attackreturn trueendif self.courage > 33+5*dist and me_see_be thenlocal npc_wpn,be_wpn = npc:active_item(),be:active_item()if not (be_wpn and rx_utils.item_is_fa(be_wpn) and npc_wpn and npc_wpn:section() ~= "wpn_knife" and npc_wpn:get_ammo_in_magazine() ~= 0 and be_wpn:get_ammo_in_magazine() ~= 0) then-- printf("close_attack[%s]:return true",npc:character_name())self.st.target = be_idself.st.type = close_attackself.st.timer = self.st.timer+6000return trueendendelselocal bee = be:get_enemy()-- printf("monster[%s]: %s %s",npc:character_name(),tostring(not (be_see_me and be:get_enemy() and be:get_enemy():id() == npc_id)),tostring(npc.health > 0.8))if self.cmhunt and mutant_hunt_clsids[be:clsid()] and self.courage > 35+5*dist and not (be_see_me and bee and bee:id() == npc_id) and npc.health > 0.8 then-- printf("mutant_hunt[%s]:return true",npc:character_name())self.st.target = be_idself.st.type = mutant_huntself.st.timer = self.st.timer+6000return trueelseif mutant_defend_clsids[be:clsid()] and dist < 6 and self.courage > 40+dist and (be_see_me and bee and bee:id() == npc_id) and npc.health > 0.2 then-- printf("mutant_defend[%s]:return true",npc:character_name())self.st.target = be_idself.st.type = mutant_defendself.st.timer = self.st.timer+4000return trueendendreturn falseendfunction evaluator_knife_attack:death_callback(who)if self.object thenremove_target(self.object:id(),self.st)endendclass "evaluator_knife_defend" (property_evaluator)function evaluator_knife_defend:__init(npc,name,storage) super (nil,name)self.st = storageendfunction evaluator_knife_defend:evaluate()return falseendclass "action_knife_attack" (action_base)function action_knife_attack:__init(npc,action_name,storage) super (nil,action_name)self.st = storageself.rank = ranks.get_obj_rank_name(npc)self.comm = npc:character_community()self.rate = 1000/(knife_sets.ranks[self.rank].rate+knife_sets.communities[self.comm].rate_add)endfunction action_knife_attack:initialize()action_base.initialize(self)local npc = self.objectprintf("knife_attack[%s]:init",npc:character_name())self.st.timer = time_global()+30000self.start_time = time_global()self.fire_time = 0self.mental_time = 0if rx_wmgr thenlocal wm = rx_wmgr.get_wm(npc)-- local knife = wm:get_best_weapon(1)-- wm:return_items(knife and knife:id() or 0)wm:disable(self.st.timer)endnpc:set_desired_position()npc:set_desired_direction()npc:set_mental_state(anim.danger)npc:set_movement_type(move.run)-- state_mgr.set_state(npc,"assault")state_mgr.set_state(npc,"idle")targets[self.st.target] = npc:id()if self.st.type == kill_wounded then--xr_sound.set_sound_play(targets[self.st.target],"kill_wounded")endself.ddr = math.random() > 0.5endfunction action_knife_attack:execute()action_base.execute(self)local npc,tg = self.object,time_global()local npc_id = npc:id()if self.st.timer < tg thenremove_target(npc_id,self.st)self.st.delay = tg+10000printf("knife_attack[%s]:timer < tg",npc:character_name())returnendlocal target = level.object_by_id(self.st.target)local dist = npc:position():distance_to(target:position())local knife = npc:object("wpn_knife")local dir = target:position()dir:sub(npc:position())npc:set_sight(look.direction,dir)local acti = npc:active_item()acti = acti and acti:section() == "wpn_knife"if acti and (dist < knife_sets.fire_dist or self.st.type == mutant_defend and dist < knife_sets.fire_dist*1.5) then-- printf("attack[%s]:set fire",npc:character_name())npc:set_sight(look.fire_point,target:bone_position("bip01_neck"))if self.fire_time < tg thennpc:set_item(object.fire1,knife,1,self.rate)self.fire_time = tg+self.rateendif self.st.type == kill_wounded then-- npc:set_dest_level_vertex_id(npc:level_vertex_id())npc:set_movement_type(move.stand)npc:set_body_state(move.crouch)endelseif not (self.st.type == kill_wounded or self.st.type == sneak_attack or IsMonster(target)) then--xr_sound.set_sound_play(npc_id,"knife_attack")endif self.st.type ~= mutant_defend thennpc:set_movement_type(move.run)endnpc:set_item(object.aim1,knife)endif not acti thenif self.start_time+4000 < tg thenremove_target(npc_id,self.st)self.st.delay = tg+15000printf("knife_attack[%s]:timer < tg",npc:character_name())returnendnpc:set_mental_state(anim.danger)elseif self.st.type == sneak_attack thennpc:set_body_state(move.crouch)npc:set_mental_state(anim.danger)if dist > 6 and target:see(npc) thenprintf("sneak_attack[%s]:abort",npc:character_name())remove_target(npc_id,self.st)returnendelseif self.st.type == mutant_hunt thennpc:set_body_state(move.standing)if self.mental_time < tg thenif dist < 3 and self.mental ~= anim.danger thenself.mental_time = tg+900self.mental = anim.dangerelseif self.mental ~= anim.panic thenself.mental_time = tg+1500self.mental = anim.panicendnpc:set_mental_state(self.mental)end-- printf("mutant_hunt[%s]:send",npc:character_name())elseif self.st.type == close_attack thennpc:set_body_state(move.standing)npc:set_mental_state(anim.danger)-- printf("close_attack[%s]:send",npc:character_name())elseif self.st.type == mutant_defend thennpc:set_body_state(move.standing)npc:set_mental_state(anim.danger)if dist < 3.5 thennpc:set_movement_type(move.run)elsenpc:set_movement_type(move.walk)end-- printf("mutant_defend[%s]:send",npc:character_name())endlocal vertex = self.st.type == mutant_defend and get_dodge_vertex(npc,target,self.ddr) or target:level_vertex_id()utils.send_to_nearest_accessible_vertex(npc,vertex)endfunction action_knife_attack:finalize()local npc = self.objectprintf("knife_attack[%s]:fin",npc:character_name())if rx_wmgr thenrx_wmgr.get_wm(npc):enable()endif not npc:best_enemy() thennpc:set_item(object.idle,npc:object("wpn_knife"))state_mgr.set_state(npc,"guard")endnpc:set_sight(look.direction,npc:direction())remove_target(npc:id(),self.st)self.mental = nilself.ddr = nilaction_base.finalize(self)endclass "action_knife_defend" (action_base)function action_knife_defend:__init (npc,action_name,storage) super (nil,action_name)self.st = storageendfunction action_knife_defend:initialize()action_base.initialize(self)self.wm = db.storage[npc:id()].wmself.wm:set_weapon(npc:object("wpn_knife"))self.wm.disabled_temp = trueendfunction action_knife_defend:execute()action_base.execute(self)endfunction action_knife_defend:finalize()action_base.finalize(self)endfunction get_dodge_vertex(s,o,d)local dir = o:position():sub(s:position())dir = vector_rotate_y(dir,d and 50 or 310)return s:vertex_in_direction(s:level_vertex_id(),dir,3)endfunction npc_update(npc)if knife_sets.enabled thenlocal knife = npc:object("wpn_knife")if not knife thenalife():create("wpn_knife",npc:position(),npc:level_vertex_id(),npc:game_vertex_id(),npc:id())endendendevid_knife_attack=rx_ai.base_id+35--evid_knife_defend=evid_knife_attack+1actid_knife_attack=evid_knife_attack--actid_knife_defend=actid_knife_attack+1function add_to_binder(npc,ini,scheme,section,storage)if not knife_sets.inited theninit()endlocal manager = npc:motivation_action_manager()if not (knife_sets.enabled and not knife_sets.forbiddens.factions[npc:character_community()] and knife_sets.ranks[ranks.get_obj_rank_name(npc)] and not knife_sets.forbiddens.npcs[npc:name()]) thenmanager:add_evaluator(evid_knife_attack,property_evaluator_const(false))returnendmanager:add_evaluator(evid_knife_attack,evaluator_knife_attack(npc,"evaluator_knife_attack",storage))local action = action_knife_attack(npc,"knife_attack",storage)action:add_precondition(world_property(stalker_ids.property_alive,true))action:add_precondition(world_property(xr_evaluators_id.sidor_wounded_base,false))-- action:add_precondition(world_property(xr_evaluators_id.state_mgr+1,true))if rx_gl thenaction:add_precondition(world_property(rx_gl.evid_gl_fire,false))endif rx_bandage thenaction:add_precondition(world_property(rx_bandage.evid_bandage,false))endaction:add_precondition(world_property(evid_knife_attack,true))action:add_effect(world_property(evid_knife_attack,false))manager:add_action(actid_knife_attack,action)for i,id in ipairs({stalker_ids.action_combat_planner,stalker_ids.action_danger_planner,xr_actions_id.stohe_meet_base+1}) doaction = manager:action(id)action:add_precondition(world_property(evid_knife_attack,false))endendfunction set_scheme(npc,ini,scheme,section)local st = xr_logic.assign_storage_and_bind(npc,ini,scheme,section)endfunction disable_scheme(npc,scheme)local st = db.storage[npc:id()][scheme]if st thenst.enabled = falseendend ltx-фаил ;-------------------------------------- ; Модуль knife; Rulix aka Bak;--------------------------------------[main]enabled = truecheck_period = 1001 ;мс ; время между проверкамиforbidden_weapons = none ; запрещенное к использованию оружиеforbidden_factions = zombiedforbidden_npcs = nonefire_dist = 1.5[novice]rate = 0.6 ; ударов в секунду[experienced]rate = 1.1[veteran]rate = 1.3[master]rate = 2;---------------------------------------[stalker]rate_add = 0courage = 0.9attack_wounded = 0.1mutant_hunt = true[bandit]rate_add = 0.1courage = 0.7attack_wounded = 0.2mutant_hunt = false[freedom]rate_add = 0.3courage = 1.4attack_wounded = 0.2mutant_hunt = true[dolg]rate_add = 0courage = 1attack_wounded = 0mutant_hunt = true[killer]rate_add = 0.2courage = 0.8attack_wounded = 0mutant_hunt = true[military]rate_add = 0courage = 0.6attack_wounded = 0mutant_hunt = false[ecolog]rate_add = 0courage = 0.1attack_wounded = 0mutant_hunt = false[monolith]rate_add = 0courage = 1.5attack_wounded = 0.05mutant_hunt = false Скрин Изменено 25 Октября 2015 пользователем Gaz24 Ссылка на комментарий
sergej5500 0 Опубликовано 26 Октября 2015 Поделиться Опубликовано 26 Октября 2015 Добрый день. Для Зова Припяти нужна функция в xr_conditions. Функция вызывается их логики объекта inventiory_box. Функция должна выдать true, если ближе 10 метров к этому inventory_box окажется любой сталкер или монстр. Какой функцией можно воспользоваться? Или как её правильно составить? Ссылка на комментарий
UnLoaded 313 Опубликовано 26 Октября 2015 Поделиться Опубликовано 26 Октября 2015 Функция должна выдать true, если ближе 10 метров к этому inventory_box окажется любой сталкер или монстр Как вариант: если похотелка одноразовая(т.е. для единичного инвентарного ящика), то накрыть его(ящик) спейс-рестриктором, в котором все делается элементарно и без заморочек... Ссылка на комментарий
Romz 142 Опубликовано 27 Октября 2015 Поделиться Опубликовано 27 Октября 2015 И снова здравстуйте. Опять за помощью. ЗП. Имеется инфопоршень. Взводится на пропадание индикаторов ХУДа, сбрасывается при их отображении. Ну, должен, по крайней мере. Взвод и сброс инфопоршня прописал, соответственно, в xr_effects, в disable_ui, disable_ui_only и enable_ui. Если находиться на одной локе, то всё работает, как задумано, а вот если перейти на другую с проводником, то инфопоршень "зависает" во взведённом положении. Где ещё производится проверка на включение\отключение ХУДа? Нашёл ещё в _g show_all_ui, добавил туда взведение и сброс инфопоршня. Всё равно, не срабатывает до тех пор, пока не будет использована функция, в которой явно отключается\включается UI. Например, поспать. Шаман - СисАдмин Всяко-разно: для ЧН Ссылка на комментарий
Kirgudu 1 216 Опубликовано 27 Октября 2015 Поделиться Опубликовано 27 Октября 2015 @Romz, ты можешь его сбрасывать при первом апдейте, ведь сразу после загрузки никакой диалог (в том числе проводника) ещё не открыт. Инструмент Ссылка на комментарий
Romz 142 Опубликовано 27 Октября 2015 Поделиться Опубликовано 27 Октября 2015 сразу после загрузки никакой диалог (в том числе проводника) ещё не открыт.Не всегда это возможно. Например, первый переход на Янов. Там разговоры вначале. Хотя ГГ уже заспавнился, но UI пока отключен.Прикол, вернулся на предыдущую локу - инфопоршень сбросился! Инфопоршни, что ли, сохраняются для каждой локи отдельно? Переведу-ка я проверку с инфопоршней на se_stor Добавлено Kirgudu, 27 Октября 2015 Рекомендую, кстати, глянуть доработанный se_stor, который я выложил вчера в «сборочном цехе». Теперь там полное сохранение всех возможных данных внешних модулей в универсальном хранилище, в том числе и с кастомными методами сохранения/загрузки. Шаман - СисАдмин Всяко-разно: для ЧН Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти