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

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

Всем привет народ! Недавно построил следующую функцию

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. Запрещено оставлять повторные сообщения (или дублировать их) в одной или нескольких темах.

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

Реклама любых модов бесплатно на моём

сайте писать в личку

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

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 и нет никакой твоей озвучки ... ну а про ошибку отсутствия костюма - уже говорилось.

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

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

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

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, а в качестве значения наши переменные.

 

Что-то кончается, что-то начинается...

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

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

 

спасибо

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

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

 

И повторю: :rtfm:Советую почитать материалы Lua (RTFM) по работе с неиндексированными таблицами и ограничения на использование методов table.insert / table.remove.

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

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

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

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 сталкеров получил безголовый вылет. Наверняка счетчик рос и рос, а потом бах и не хватило чего-то. В данном варианте все учтено.

З.Ы. Как ни странно, избавился от таблиц - и стало работать куда быстрее, но не идеально.

Что-то кончается, что-то начинается...

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

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?

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

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

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

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

*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 , кого жахнули.

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

 

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

Что-то кончается, что-то начинается...

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

Vano_Santuri

Тоесть грубо говоря когда какой то сталкер умирает, эта функция генерирует сообщение вида.

"Только что видел как бандит(ы) завалили такого то сталкера."

 

В данном случае здесь ещё считается кол-во нападавших.

Явных ошибок вроде нету, должно работать.

А по поводу вылета без лога, то счётчик тут не причём. Его вообще обнулять не надо.

При каждом вызове функции GiveStalkerEnemy, счётчик у тебя всёравно занаво инициализируется:

function GiveStalkerEnemy(ThisObj,RadMin,RadMax,who)
local t = 0
...
end

 

Т.к он находится внутри функции. Обнулять его имело бы смысл, будь он вне функции

 

local t = 0
function GiveStalkerEnemy(ThisObj,RadMin,RadMax,who)
...
end

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

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

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

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

*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

Как поправить , может кто подскажет?

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

Что-то кончается, что-то начинается...

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

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

 

 

ЗЫ так по идее и чиститься должна...

Изменено пользователем Viнt@rь
Ссылка на комментарий

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 минуты, то о них будет сообщать один и тот же НПС, т.к его таймер уже пройдёт и при условии что он всё ещё будет ближе всех к месту событий.

Но это можно решить, увеличив время блокировки.

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

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

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

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

*Shoker*,

2) #spammers и table.getn корректно сработает только для таблицы где в качестве ключа идут порядковые номера, то есть

ты ошибаешься) даже в таблице со строковым содержимым есть порядковые номера этих строк))) потому эти функции работают корректно

Изменено пользователем Viнt@rь
Ссылка на комментарий

А ты попробуй ;)

Насколько я знаю таблица посчитается только если в качестве КЛЮЧА там идут порядковые номера. Соответственно удалять тоже надо через table.remove

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

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

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

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

*Shoker*, вот тебе пример

... 
local sTime = Time[math.random(#Time)]
...

Таблица:
Time = {"недавно","несколько минут назад","минут десять назад",...}

Ссылка на комментарий
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 спамеров - идет очистка и поять по новой...

Что-то кончается, что-то начинается...

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

Дык, тут же соль в том, что в таблице Time ключи не строки, а цифры. Просто здесь они указаны неявно. То есть твоя таблица эквивалентна этой:

 

Time = {[1] = "недавно", [2] = "несколько минут назад", [3] = "минут десять назад", [n] = ...}

Короче когда так составляют таблицу, её элементы автоматически номируются компилятором или ещё чем то.

 

А вот если бы у тебя было что то вроде:

 

Time = {["недавно"] = true, ["несколько минут назад"] = true, ["минут десять назад"] = true,...}

То тогда бы уже не сработала проверка :)

 

Vano_Santuri

Проверка #spammers всегда будет 0 возвращать.

 

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

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

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

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

*Shoker*, Да ладно, я же переписал. И самое интересное все работает...

Нашлись по порядку 7 сталкеров - затем они стали повторятся в том же порядке...

Что-то кончается, что-то начинается...

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

Ай, протупил. Думал ты всё ещё в качестве ключа используешь id.

Ну если тебя не устраивает вариант с таймером, то тогда вот твой вариант слегка отретушированный:

И здесь был модератор.

 

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

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

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

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

*Shoker*, А можешь объяснить, в чем именно ретушевка. Нет, изменения я вижу, но в чем их смысл? Просто интересно.

Насчет таймера. Просто я хотел, что бы код был как можно проще...

 

З.Ы. Отошел, отвечу не скоро.

Что-то кончается, что-то начинается...

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

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

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

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

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

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

Войти

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

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

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