serega-gamer 0 Опубликовано 15 Марта 2012 Поделиться Опубликовано 15 Марта 2012 (изменено) Всем привет народ! Недавно построил следующую функцию local cond_1 local cond_2 local cond_3 local cond_4 function suit_condition() local suit_active = nil local act_suit = db.actor:item_in_slot(6) if (act_suit and act_suit:section() == "nonos_kostum") or (act_suit and act_suit:section() == "nano_outfit") then suit_active = true end if suit_active then db.actor:give_info_portion("suit_v1_or_v2_active") elseif not suit_active then db.actor:disable_info_portion("suit_v1_or_v2_active") end if suit_active and act_suit:condition() == 1.00 and has_alife_info("hev_energy_0") then db.actor:give_info_portion("hev_restore") elseif not suit_active then db.actor:disable_info_portion("hev_energy_0") db.actor:disable_info_portion("hev_restore") end if suit_active and act_suit:condition() <= 0.80 then db.actor:give_info_portion("hev_batery_repair") elseif (suit_active and act_suit:condition() > 0.80) or (not suit_active) then db.actor:disable_info_portion("hev_batery_repair") end if has_alife_info("hev_batery_repair") and act_suit:condition() >= 0.01 then db.actor:give_info_portion("hev_energy_less_than_100") elseif suit_active and act_suit:condition() < 0.01 then db.actor:disable_info_portion("hev_energy_less_than_100") end if suit_active and has_alife_info("hev_energy_less_than_100") and act_suit:condition() == 1.00 then snd_obj = xr_sound.get_safe_sound_object( [[HEV\hev_energy_100]] ) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) db.actor:give_game_news(hev_cond_100, "ui\\ui_iconsTotal", Frect():set(0,188,83,47), 0, 3000) db.actor:disable_info_portion("hev_energy_less_than_100") end if has_alife_info("hev_batery_repair") and act_suit:condition() >= 0.61 then if not cond_1 then snd_obj = xr_sound.get_safe_sound_object( [[HEV\hev_energy_80]] ) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) db.actor:give_game_news(hev_cond_80, "ui\\ui_iconsTotal", Frect():set(0,188,83,47), 0, 3000) cond_1 = true end elseif suit_active and act_suit:condition() > 0.80 then cond_1 = nil end if suit_active and act_suit:condition() <= 0.60 and act_suit:condition() >= 0.41 then if not cond_2 then snd_obj = xr_sound.get_safe_sound_object( [[HEV\hev_energy_60]] ) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) db.actor:give_game_news(hev_cond_60, "ui\\ui_iconsTotal", Frect():set(0,188,83,47), 0, 3000) cond_2 = true end elseif suit_active and act_suit:condition() > 0.60 then cond_2 = nil end if suit_active and act_suit:condition() <= 0.40 and act_suit:condition() >= 0.21 then if not cond_3 then snd_obj = xr_sound.get_safe_sound_object( [[HEV\hev_energy_40]] ) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) db.actor:give_game_news(hev_cond_40, "ui\\ui_iconsTotal", Frect():set(0,188,83,47), 0, 3000) cond_3 = true end elseif suit_active and act_suit:condition() > 0.40 then cond_3 = nil end if suit_active and act_suit:condition() <= 0.20 and act_suit:condition() >= 0.01 then if not cond_4 then snd_obj = xr_sound.get_safe_sound_object( [[HEV\hev_energy_20]] ) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) db.actor:give_game_news(hev_cond_20, "ui\\ui_iconsTotal", Frect():set(0,188,83,47), 0, 3000) cond_4 = true end elseif suit_active and act_suit:condition() > 0.20 then cond_4 = nil end end и у меня при стопроцентной кондиции костюма перестали работать диалоги тупо не нажимается на текст, а когда кондиция меньше 80 % то всё ок всё работает, посмотрите, кому не сложно, может найдёте ошибку заранее спасибо! Строгое предупреждение от модератора ColR_iT Раз тебе ответили, то содержимое поста оставлю, но чтобы подобное желание не повторялось, вот тебе выписка из правил форума: 2.1.2. Запрещено оставлять повторные сообщения (или дублировать их) в одной или нескольких темах. Изменено 16 Марта 2012 пользователем ColR_iT Реклама любых модов бесплатно на моём сайте писать в личку Ссылка на комментарий
Artos 99 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) Viнt@rь, во-первых или уточняй понятия о которых спрашиваешь или снимай шоры. ;-) 1. Тебе что-то мешает хранить в табличках ссылки, а не сами значения? Т.о. дополнительные таблицы - всего лишь организационные объекты хранения именно нужных данных и их актуализация может быть и автоматической. Можно вполне то, о чем сказал выше хранить и в той же db.storage, т.к. никто нас не ограничивает наращивание ее нашими данными ... Но, если из этого массива можно организовать свои субтаблици с линками на исходные данные и сканировать таблицу в которой на порядо меньше полей - не это ли даст экономию?! 2. Мы все же сейчас говорим о новостном алгоритме и используемых для этого данных. Что тут важно? Список сендеров, которые выбираются в зависимости от места и иных условий. А так ли важно, что 15 секунд назад его убили? Иль он сменил группировку или его зомбировали? Иль что иные условия у него изменились? В абсолютном большинстве случаев это НЕ важно, если конечно и событие и сендер не находится перед ГГ в "паре шагов" ... Т.о. эти "частные" узкоспециализированные таблички могут актуализироваться по достаточно простому алгоритму: - если нет события и прошло, например, более минуты - проверить и актуализировать 20% спец.таблицы; - если в момент события вся спец.табличка не актуализировалаь более чем XXX ctr (например, >5мин) - то запустить процесс (до)актуализации и после этого выбирать из нее. Т.о. процесс актуализации не критично растянут во времени, но каждый раз забирает на себя не более чем, например 20% нужного времени, что снижает вероятность возникновения лагов в игре. Это всего лишь один из многих вариантов и, как уже сказал ранее, оптимизация выбирается исходя из потребностей и начальных условий. Если же делать "универсально" - то в данном случае про оптимизацию можно говорить только вскользь и конечно же по конкретным кодам, а не по шаблонным приемам. А вообще, то, по новостям именно он-лайн событий, ведем доостаточно беспредметный разговор и то, что писал ранее - это вам на вырост, когда онлайн-рамки станут тесными. :-) Даже выборка из всей db.storage при правильно организованном цикле выборки(!) - копейки по сравнению со всеми остальными потерями. Вынеся все общие и/или тяжелые перепроверки из цикла выборки "наружу" - вполне можно на какое-то время забыть о лагах из-за новостей. Добавлено через 40 мин.: serega-gamer, ну что же, если просишь все же ответа, то вот НЕ от 'народа' (и на будущее, избегай обращаться к толпе): 1. Грязно оформленный код, когда отступы простаавлены абы были - приводит к трудному восприятию кода "на взгляд". 2. Многочисленные проверки одного и того же да еще и последовательно могут приводить в совершенно непредусмотренным ветвлениям и проанализировать/прсчитать подобное достаточно затруднительно. 3. В твоей куче условий столько много переплетений, что проще переписать скрипт чем указать на каждую ... Но для этого нужны все же исходные данные о том, что же ты захотел сделать. 4. В отдельных местах пропущены проверки на существование костюма, например тут: if has_alife_info("hev_batery_repair") and act_suit:condition() >= 0.01 then и это ( nil:condition() ) может приводить к зависанию функции/потока. В общем, или кто-то перепишет код так, чтобы он читался и тогда можно говорить об ошибках. Или приводи лог/описание ошибки, чтобы не гадать о всевозможных вариантах. Добавлено через 29 мин.: P.S. Вот, переписав по-возможности с сохранением исходного: local cond_80 local cond_60 local cond_40 local cond_20 function suit_condition() local condition = nil local suit = db.actor:item_in_slot(6) if suit and (suit:section() == "nonos_kostum") or and suit:section() == "nano_outfit") then condition = suit:condition() end if condition then db.actor:give_info_portion("suit_v1_or_v2_active") else db.actor:disable_info_portion("suit_v1_or_v2_active") end if not condition then db.actor:disable_info_portion("hev_energy_0") db.actor:disable_info_portion("hev_restore") elseif condition == 1.00 and has_alife_info("hev_energy_0") then db.actor:give_info_portion("hev_restore") end if not condition or condition > 0.80 then db.actor:disable_info_portion("hev_batery_repair") else db.actor:give_info_portion("hev_batery_repair") end if condition then if condition < 0.01 then db.actor:disable_info_portion("hev_energy_less_than_100") elseif has_alife_info("hev_batery_repair") then db.actor:give_info_portion("hev_energy_less_than_100") end else return --/> end if condition == 1.00 and has_alife_info("hev_energy_less_than_100") then snd_obj = xr_sound.get_safe_sound_object( [[HEV\hev_energy_100]] ) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) db.actor:give_game_news(hev_cond_100, "ui\\ui_iconsTotal", Frect():set(0,188,83,47), 0, 3000) db.actor:disable_info_portion("hev_energy_less_than_100") elseif condition > 0.80 then cond_80 = nil --/ тут чего-то не хватает ... elseif condition > 0.60 then cond_60 = nil if condition >= 0.61 then if not cond_80 and has_alife_info("hev_batery_repair") then snd_obj = xr_sound.get_safe_sound_object( [[HEV\hev_energy_80]] ) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) db.actor:give_game_news(hev_cond_80, "ui\\ui_iconsTotal", Frect():set(0,188,83,47), 0, 3000) cond_80 = true end end elseif condition > 0.40 then cond_40 = nil if condition >= 0.41 then if not cond_60 then snd_obj = xr_sound.get_safe_sound_object( [[HEV\hev_energy_60]] ) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) db.actor:give_game_news(hev_cond_60, "ui\\ui_iconsTotal", Frect():set(0,188,83,47), 0, 3000) cond_60 = true end end elseif condition > 0.20 then cond_20 = nil if condition >= 0.21 then if not cond_40 then snd_obj = xr_sound.get_safe_sound_object( [[HEV\hev_energy_40]] ) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) db.actor:give_game_news(hev_cond_40, "ui\\ui_iconsTotal", Frect():set(0,188,83,47), 0, 3000) cond_40 = true end end elseif condition >= 0.01 then if not cond_20 then snd_obj = xr_sound.get_safe_sound_object( [[HEV\hev_energy_20]] ) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) db.actor:give_game_news(hev_cond_20, "ui\\ui_iconsTotal", Frect():set(0,188,83,47), 0, 3000) cond_20 = true end end end - сразу видно, что при > 80 и нет никакой твоей озвучки ... ну а про ошибку отсутствия костюма - уже говорилось. Изменено 16 Марта 2012 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Vano_Santuri 33 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 Artos, Посмотрел твой алгоритм "Возобновляемые циклы сканирования с ограничением времени работы". Решил все-таки за него взяться. Но у меня вопрос по реализации сохранение в табличку объектов и их параметров. У меня такая идея. Допустим мы собираем данные о сталкерах. У нас имеется 2 таблицы Obj = {} и Properties ={} В одну мы сохраняем объект, а во вторую нужные нам свойтсва t={Pos=p,Char=c и т.д.} Во время проверки мы ищем идекс ключа объекта в таблице Obj, по том по этому ключу удаляем запись в таблице Properties, а затем и сам obj, и перезаписываем данные, как Obj, так и в Properties. Теперь вопрос, как определить ключ по его значению (Так возможно?) Если моя идея опять про велосипед, покажи пожалуйста пример , где в качестве ключа идет obj, а в качестве значения наши переменные. Как сохранить в таблицу вот таким образом local t = { val_b2_accompany_guider = true, val_b2_base_leader = true, val_b2_assault_b1_commander = true, val_b11_outpost_commander = true, val_b12_outpost_commander = true, val_b14_outpost_commander = true } Т.е. моя идея возникла из=за того, что я не наю как сохранить где в качестве ключа идет obj, а в качестве значения наши переменные. Что-то кончается, что-то начинается... Ссылка на комментарий
olaf1 0 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 Artos, Извините, но я не могу понять, что вы говорите с Вашими ответами russic. respwan_npc = { ["mar_clear_sky_respawn_1"] = true, [2] = false, [3] = false, ... [NNN] = false, ["mar_clear_sky_respawn_2"] = true, ["mar_clear_sky_respawn_3"] = true, } Что я могу участвовать в этом? что это [NNN] = false спасибо Ссылка на комментарий
Artos 99 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) Vano_Santuri, не очень понял про две таблицы, т.к. ... дробить конечно можно до бесконечности, но зачем? Если имеются объекты и их свойства - то каков смыл в существовании двух разобщенных таблиц? Все одно они как-то должны друг другу соответствовать и сама логика подсказывает иметь их в одной таблице. Возможно, что ты еще не в курсе, что ключами таблиц могут быть как и обычные строки/числа/... так и объекты/функции и т.п. Это все является типом данных и в Lua также может применяться к таблицам не только в качестве значений, но и ключей (почитай об этом например в топике "Язык Lua. Общие вопросы программирования."). Т.о. ничто в общем-то не запрещает иметь в качестве одного из полей типа: [obj_npc] = {pos= obj_npc:position(), name=obj_npc:character_name(),alive=obj_npc:alive(), ...}, и не нужно сохранять поотдельности, чтобы потом сливать воедино. Однако(!) я все же не советовал бы это делать без особой нужды/причины. Все же и выборка и сравнение для объектов/функций/ ... т.е. "объемных ко коду/данным" не сравнима с выборкой/сравнению чисел/строк/... Не зря, в основном запоминают не объекты, а их игровые ID. И, дополнительно, я бы не советовал сохранять в таблицах собственно объекты, тем более их клиентские копии. Удаление серверного копии этого объекта может при отсутствии соответствующих перепроверок понаделать немало ошибок ... Ну а если все одно треуются перепроверки - ну так и хранить или игровые идентификаторы (что тоже имеет ограничение/оговорки) или полное имя объекта. Определить табличный ключ по значению этого ключа конечно возможно, но в общем случае только перебором таблицы до совпадения искомого значения с соответствующим полем таблицы. Но порою используют иной вариант, делая "зеркальную" копию таблицы, в которой ключ и значение меняются местами. Но это конечно для статичных таблиц и не имеющих дубли ключей/значений. Ну а как сохранять в таблице объекты в качестве ключей - да почти также как и все остальное. Конечно с числами иль готовыми строками все проще, но и тут нет особой морки, посто сними очередные шоры. Как создается тот же db.storage? Например из биндера сталкеров вызывается при спавне этого объекта(!) -> db.add_obj(self.object) что в свою очередь приводит к: storage[obj:id()].object = obj Ну и что мешает сделать в другой табличке так: storage[obj] = obj:id() ? И у тебя ключом стал именно клиентский объект, ну а вместо obj:id() можешь создать что-то посложнее = ( id=obj:id() , pos=obj:position() , ... }. Но, все же, советую по возможности не злоупотреблять и, там, где можно использовать те-же ID в качестве ключей - их и использовать. P.S. Учитывая, что это уже почти чистый луа - вероятно уточнения (если потребуется) все же стОит делать в топике именно по Lua. Добавлено через 19 мин.: olaf1, Извините, но я с трудом и далеко не все понимаю в Ваших вопросах на языке Lua. Поясняю: [NNN] = false - где NNN - любое число. Т. е. это просто продолжение ряда 2,3,4, ... ,9,10, ... ,N,N+1,N+2, ... , NNN-1,NNN,NNN+1, ... и так до => переполнения стека (stack overflow). 1. НЕЛЬЗЯ использовать метод table.insert НЕ удаляя прежние данные (применительно к Вашему примеру). 2. Нельзя использовать что-то типа: table.insert(respwan_npc,2,false) - т.к. Вы ТЕРЯЕТЕ ключ и, вместо изменения значения флага для данного ключа, постоянно по индексу 2 в таблицу заносите булево значение этого флага, сдвигая(!) все уже имеющиеся в таблице значения выше. Далее объяснять что 'ошибка' является 'ошибкой' не имею ... возможности. Вам дан рабочий вариант "как в таблице менять значение флага для соответствующей секции спавна". Т.е. рабочим является вариант изменения нужных флагов при итерации по таблице это: for npc,spwan in pairs(respwan_npc) do if spwan == true then respwan_table[alife():create("mar_clear_sky_respawn_1", pos, lvi, gvi).id] = true respwan_npc[npc] = false --/!!! end end И повторю: Советую почитать материалы Lua (RTFM) по работе с неиндексированными таблицами и ограничения на использование методов table.insert / table.remove. Изменено 16 Марта 2012 пользователем Artos "Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени Ссылка на комментарий
Vano_Santuri 33 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 Artos, Спасибо. Все встало на свои места. В даный момент сделал временное отключение таблиц, т.к новая версия на твоем способе апдейта выйдет не скоро. Решил пока убрать нагрузку и исправить кое-какие баги. Вот код function GiveStalkerEnemy(ThisObj,RadMin,RadMax,who) local t = 0 for k, v in pairs(db.storage) do local obj = level.object_by_id(k) if (obj) and (IsStalker(obj)) then -- Убрал привязку на то, живой объект или нет - хер с ним, тут не нужно. local ComObj = obj:character_community() local ComWho = who:character_community() if (ComObj == ComWho) then local Pos = ThisObj:position() local Dist = Pos:distance_to(obj:position()) if (Dist < RadMax) and (Dist > RadMin) then t=t+1 end end end end local WhoCom = who:character_community() if t<2 then local EnemyWord = GetComName(WhoCom,math.random(7,8)) local WordEnemy = GetWordEnemy("one",math.random(1,3)) return WordEnemy,EnemyWord -- на случай если все сдохли. else local WordEnemy = GetWordEnemy("more",math.random(1,3)) local EnemyWord = GetComName(WhoCom,math.random(9,10)) return WordEnemy,EnemyWord end t = 0 -- Обнуляем счетчик end Код ищет количество врагов в определенном радиусе и в зависимости от количества выводит инфу. У меня вопрос касательно того, как я организовал счетчик local t = 0 -- объявил переменную t=t+1 --В цикле - если объект нам подходит проводим суммирование. if t<2 then local EnemyWord = GetComName(WhoCom,math.random(7,8)) local WordEnemy = GetWordEnemy("one",math.random(1,3)) return WordEnemy,EnemyWord -- на случай если все сдохли. else local WordEnemy = GetWordEnemy("more",math.random(1,3)) local EnemyWord = GetComName(WhoCom,math.random(9,10)) return WordEnemy,EnemyWord end здесь собственно соответствие. t = 0 -- Обнуляем счетчик Я все правильно делал относительно счетчика? Нигде ничего не забыл. Спрашиваю почему. в конце я забыл обнулить счетчик t = 0 -- Обнуляем счетчик. И после убийства 20 сталкеров получил безголовый вылет. Наверняка счетчик рос и рос, а потом бах и не хватило чего-то. В данном варианте все учтено. З.Ы. Как ни странно, избавился от таблиц - и стало работать куда быстрее, но не идеально. Что-то кончается, что-то начинается... Ссылка на комментарий
*Shoker* 322 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) Vano_Santuri 1) Чтобы совсем ускорить работу, можно использовать не db.storage, а свою собственную глоб. таблицу. В частности в xr_motivator.script есть функции net_spawn\net_destroy, суть в том что они вызываются на выходе НПС в онлайн и в оффлайн соответственно. И именно там кстати НПС добавляется в db.storage, аналогично для монстров в bind_monster.script. Также есть вариант просто для серверного объекта (скрипты с приставкой se_) Таким образом ты можешь там добавлять в свою собственную таблицу всех онлайн сталкеров в net_spawn (не нужна проверка на то, что объект сталкер, в таблицу можно занести свои данные) и там же их от туда удалять в net_destroy Если верить Artos-у (а не верить причин нет) и db.storage в ЗП в среднем при запуске около 700 объектов, то в твоей таблице их будет одновременно в среднем всего от 0 до 20. 2) В твоём коде два раза идёт получение группировки объекта "who" Это ComWho и WhoCom Имеет смысл получать группировку в самом начале скрипта, сразу после local t = 0 function GiveStalkerEnemy(ThisObj,RadMin,RadMax,who) local t = 0 local ComWho = who:character_community() --<<< local WhoCom соответственно убираешь и в коде заменяешь на ComWho 3) Я так понял из твоего кода, здесь идёт перебор всех "свидетелей" вокруг объекта (трупа сталкера?) ThisObject Что должно передаваться в who? Опиши если не сложно что должна делать функция GiveStalkerEnemy, и что за ThisObj и Who? Изменено 16 Марта 2012 пользователем *Shoker* Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Vano_Santuri 33 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) *Shoker*, 1) Чтобы совсем ускорить работу, можно использовать не db.storage, а свою собственную глоб. таблицу. В частности в xr_motivator.script есть функции net_spawn\net_destroy, суть в том что они вызываются на выходе НПС в онлайн и в оффлайн соответственно. И именно там кстати НПС добавляется в db.storage, аналогично для монстров в bind_monster.script. Также есть вариант просто для серверного объекта (скрипты с приставкой se_) Уже на прошлой странице обсудили - я даже наклепал, осталось подключить метод обновления объектов, размазанный во времени от Artos. local WhoCom соответственно убираешь и в коде заменяешь на ComWho Да я на скорую руку клепал и проглядел, что объявлял уже , это не принципиально, хочу быстрее добить версию 1.02 , и все. Так как в разработке уже другая, на алгоритме, написанном на бумажке, многое отрезал. Что должно передаваться в who? Это убийца (колбек на смерть) Опиши если не сложно что должна делать функция GiveStalkerEnemy, и что за ThisObj и Who? Изначально эта функция должна была находит врагов, возле точки ,и враги отслылись в табличку, считалось количество ключей и т.д. Т.е. это был полный гемор,реальный. В данный момент - функция считает количество врагов возле точки, посредством незатейливого счетчика , затем Если нападавший один , то local EnemyWord = GetComName(WhoCom,math.random(7,8))--Дается фраза типа "наеник, талкер и т.д в ед.числе Ели группа, то local EnemyWord = GetComName(WhoCom,math.random(9,10)) local WordEnemy = GetWordEnemy("one",math.random(1,3)) local WordEnemy = GetWordEnemy("more",math.random(1,3)) - аналогично в зависимости от количества - разные фразы, уточняющие количество напавших. ThisObj - это victim , кого жахнули. З,Ы. - прикрутил проверку на спамеров, теперь перебор идет до первого неспамера - тобишь уже отрезается больше половины циклов. Изменено 16 Марта 2012 пользователем Vano_Santuri Что-то кончается, что-то начинается... Ссылка на комментарий
*Shoker* 322 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) Vano_Santuri Тоесть грубо говоря когда какой то сталкер умирает, эта функция генерирует сообщение вида. "Только что видел как бандит(ы) завалили такого то сталкера." В данном случае здесь ещё считается кол-во нападавших. Явных ошибок вроде нету, должно работать. А по поводу вылета без лога, то счётчик тут не причём. Его вообще обнулять не надо. При каждом вызове функции GiveStalkerEnemy, счётчик у тебя всёравно занаво инициализируется: function GiveStalkerEnemy(ThisObj,RadMin,RadMax,who) local t = 0 ... end Т.к он находится внутри функции. Обнулять его имело бы смысл, будь он вне функции local t = 0 function GiveStalkerEnemy(ThisObj,RadMin,RadMax,who) ... end Изменено 16 Марта 2012 пользователем *Shoker* Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Vano_Santuri 33 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) *Shoker*, Значит мне нужна орда тесторов. Мое лаконичное решение по поводу переборов. local spammers = {} -- Таблица спамеров. function GiveStalker() for k, v in pairs(db.storage) do local obj = level.object_by_id(k) if (obj) and (IsStalker(obj)) and (obj:alive()) and (obj:id() ~= db.actor:id()) then local ComObj = obj:character_community() if VS_send_news.CommunityChenalStatus(ComObj,1) then --Проверка на открытость канала if ValNpc(obj)~=true then --Отсекаем квестовых нпс local objId = obj:id() if (give_spamm(objId) ~= "spammer") then spammers[objId] = "spammer" -- Добавляем спамера. return obj -- нашли не спамера - отлично. end end end end end end function give_spamm(objId) if spammers and #spammers > 7 then spammers = {} -- Читим таблицу спамеров. end if spammers[objId] then return spammers[objId] else return "not_spammer" end end Что то такое. Лаконичность заключается в краткости и дееспособности... Цикл обрубается на первом не спамере. Кто может предложить более лучшее решение? Только почему-то табличка не чистится function give_spamm(objId) if spammers and #spammers > 7 then spammers = {} -- Читим таблицу спамеров. end if spammers[objId] then return spammers[objId] else return "not_spammer" end end Как поправить , может кто подскажет? Изменено 16 Марта 2012 пользователем Vano_Santuri Что-то кончается, что-то начинается... Ссылка на комментарий
Viнt@rь 50 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) Vano_Santuri, небольшое предложение по function give_spamm(objId) local spammers = {} -- Таблица спамеров. function GiveStalker() for k, v in pairs(db.storage) do local obj = level.object_by_id(k) if (obj) and (IsStalker(obj)) and (obj:alive()) and (obj:id() ~= db.actor:id()) then local ComObj = obj:character_community() if VS_send_news.CommunityChenalStatus(ComObj,1) then --Проверка на открытость канала if ValNpc(obj)~=true then --Отсекаем квестовых нпс local objId = obj:id() if not CheckSpamm(objId) then spammers[objId] = true -- Добавляем спамера. return obj -- нашли не спамера - отлично. end end end end end end function CheckSpamm(objId) if #spammers > 7 then spammers = {} -- чистим таблицу спамеров. elseif spammers[objId] then return true end return nil end ЗЫ так по идее и чиститься должна... Изменено 16 Марта 2012 пользователем Viнt@rь GUI для конвертера от бардака(всего и вся в форматы сдк) Полезный утиль-"Utilits pack(mod)" Ссылка на комментарий
*Shoker* 322 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) 1) local objId = obj:id() - это тебе не нужно, у тебя уже есть id, это переменная k. Кстати obj:id() это тоже касается. 2) #spammers и table.getn корректно сработает только для таблицы где в качестве ключа идут порядковые номера, то есть 1 = id спамера 2 = id спамере 3 = ... В твоём случае оно по моему ноль всегда возвращать будет. Поэтому табличка не чистится. Чтобы она чистилась, ты должен добавлять в табличку всё через table.insert, только тогда ключами таблицы у тебя будут не id а просто порядковые номера, и для проверки, есть ли НПС в таблице тебе придётся всю эту таблицу спамеров перебирать в цикле. Предлагаю такой вариант: Здесь был модератор. В данном случае используется не таблица, а таймер. Тоесть после того, как НПС "сообщит" о том, что видел нападавших, он "блокируется" на определённое кол-во секунд (SPAMMER_BLOCK_TIMER) Само собой при сохранении\загрузки или уходе НПС в оффлайн этот таймер сбивается. Минус: если например в одном и том же месте будут происходить убийства раз в 4 минуты, то о них будет сообщать один и тот же НПС, т.к его таймер уже пройдёт и при условии что он всё ещё будет ближе всех к месту событий. Но это можно решить, увеличив время блокировки. Изменено 16 Марта 2012 пользователем ColR_iT Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Viнt@rь 50 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) *Shoker*, 2) #spammers и table.getn корректно сработает только для таблицы где в качестве ключа идут порядковые номера, то есть ты ошибаешься) даже в таблице со строковым содержимым есть порядковые номера этих строк))) потому эти функции работают корректно Изменено 16 Марта 2012 пользователем Viнt@rь GUI для конвертера от бардака(всего и вся в форматы сдк) Полезный утиль-"Utilits pack(mod)" Ссылка на комментарий
*Shoker* 322 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) А ты попробуй Насколько я знаю таблица посчитается только если в качестве КЛЮЧА там идут порядковые номера. Соответственно удалять тоже надо через table.remove Изменено 16 Марта 2012 пользователем *Shoker* Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Viнt@rь 50 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 *Shoker*, вот тебе пример ... local sTime = Time[math.random(#Time)] ... Таблица: Time = {"недавно","несколько минут назад","минут десять назад",...} GUI для конвертера от бардака(всего и вся в форматы сдк) Полезный утиль-"Utilits pack(mod)" Ссылка на комментарий
Vano_Santuri 33 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 local spammers = {} -- Таблица спамеров. function GiveStalker() for k, v in pairs(db.storage) do local obj = level.object_by_id(k) if (obj) and (IsStalker(obj)) and (obj:alive()) and (obj:id() ~= db.actor:id()) then local ComObj = obj:character_community() if VS_send_news.CommunityChenalStatus(ComObj,1) then --Проверка на открытость канала if ValNpc(obj)~=true then --Отсекаем квестовых нпс local objId = obj:id() if (give_spamm(objId) ~= "spammer") then table.insert(spammers, objId) -- Добавляем спамера. return obj -- нашли не спамера - отлично. end end end end end end function give_spamm(objId) if spammers and #spammers > 7 then spammers = {} -- Чиcтим таблицу спамеров. end for k, v in pairs(spammers) do local spammer = spammers[k] if objId == spammer then return "spammer" end end end Ну как? Так сойдет? Или я чего-то лишнего засунул? Через 7 спамеров - идет очистка и поять по новой... Что-то кончается, что-то начинается... Ссылка на комментарий
*Shoker* 322 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) Дык, тут же соль в том, что в таблице Time ключи не строки, а цифры. Просто здесь они указаны неявно. То есть твоя таблица эквивалентна этой: Time = {[1] = "недавно", [2] = "несколько минут назад", [3] = "минут десять назад", [n] = ...} Короче когда так составляют таблицу, её элементы автоматически номируются компилятором или ещё чем то. А вот если бы у тебя было что то вроде: Time = {["недавно"] = true, ["несколько минут назад"] = true, ["минут десять назад"] = true,...} То тогда бы уже не сработала проверка Vano_Santuri Проверка #spammers всегда будет 0 возвращать. Изменено 16 Марта 2012 пользователем *Shoker* Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Vano_Santuri 33 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 *Shoker*, Да ладно, я же переписал. И самое интересное все работает... Нашлись по порядку 7 сталкеров - затем они стали повторятся в том же порядке... Что-то кончается, что-то начинается... Ссылка на комментарий
*Shoker* 322 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 (изменено) Ай, протупил. Думал ты всё ещё в качестве ключа используешь id. Ну если тебя не устраивает вариант с таймером, то тогда вот твой вариант слегка отретушированный: И здесь был модератор. Изменено 16 Марта 2012 пользователем ColR_iT Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Vano_Santuri 33 Опубликовано 16 Марта 2012 Поделиться Опубликовано 16 Марта 2012 *Shoker*, А можешь объяснить, в чем именно ретушевка. Нет, изменения я вижу, но в чем их смысл? Просто интересно. Насчет таймера. Просто я хотел, что бы код был как можно проще... З.Ы. Отошел, отвечу не скоро. Что-то кончается, что-то начинается... Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти