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

Прозекторская


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

(изменено)

try_switch_to_another_section можно сократить малость.

Так код читать легче. Заодно и убрать вспомогательную функцию "cond_name" можно

 

function try_switch_to_another_section(npc, st, actor)
    if not actor then
        abort("try_switch_to_another_section(): error in implementation of scheme '%s': actor is nil", st.scheme)
    end
    
    local l = st.logic

    if not l then
        abort("Can't find script switching information in storage, scheme '%s'", st.active_scheme)
    end
    
    local sw = false
    
    for _, c in pairs(l) do
        local name = string.match(c.name, '[%w_]+')
        
        if name == "on_actor_dist_le" then
            sw = see_actor(npc) and distance_between(actor, npc) <= c.v1
        elseif name == "on_actor_dist_le_nvis" then
            sw = distance_between(actor, npc) <= c.v1
        elseif name == "on_actor_dist_ge" then
            sw = see_actor(npc) and distance_between(actor, npc) > c.v1
        elseif name == "on_actor_dist_ge_nvis" then
            sw = distance_between(actor, npc) > c.v1
        elseif name == "on_signal" then
            sw = st.signals and st.signals[c.v1]
        elseif name == "on_info" then
            sw = true
        elseif name == "on_timer" then
            sw = time_global() >= db.storage[npc:id()].activation_time + c.v1
        elseif name == "on_game_timer" then
            sw = game.get_game_time():diffSec(db.storage[npc:id()].activation_game_time) >= c.v1
        elseif name == "on_actor_in_zone" then
            sw = utils.npc_in_zone(actor, db.zone_by_name[c.v1])
        elseif name == "on_actor_not_in_zone" then
            sw = not utils.npc_in_zone(actor, db.zone_by_name[c.v1])
        elseif name == "on_npc_in_zone" then
            sw = utils.npc_in_zone(level.object_by_id(c.npc:id()), db.zone_by_name[c.v2])
        elseif name == "on_npc_not_in_zone" then
            sw = not utils.npc_in_zone(level.object_by_id(c.npc:id()), db.zone_by_name[c.v2])
        elseif name == "on_actor_inside" then
            sw = utils.npc_in_zone(actor, npc)
        elseif name == "on_actor_outside" then
            sw = not utils.npc_in_zone(actor, npc)
        else
            abort("try_switch_to_another_section: invalid condition: [%s] (%s)", c.name, npc:name())
        end

        if sw then
            return switch_to_section(npc, st, pick_section_from_condlist(actor, npc, c.condlist))
        end
    end
    
    return false
end 

 

 


С parse_infop тоже особо ничего не сделаешь.

Там вообще паттерн интересный - "([%-%+%~%=%!])([^%-%+%~%=%!%s]+)"

Тут дело такое.

Я поставил такой шаблон - "(%S)([^%-%+%~%=%!%s]+)" И вылетел. Но КАК !!!

 

Короче. Первый паттерн продолжает чтение данных, если какой-то из захватов не был найден.

Напр. есть запись - "+info1 info2 -info3"

Будут прочитаны +info1 и -info3info2 прочитан не будет, т.к. перед ним нет никакого знака.

На самом деле это ошибка. И, считаю, такие записи нужно пресекать.

 

Что и получилось при использовании шаблона  "(%S)([^%-%+%~%=%!%s]+)"

Еще не нашел где именно, но где-то нашлась запись 'npc_rank(novice)' без знака, которая разбилась на :

sign - 'n'

infop_name - 'pc_rank(novice)'

что и привело к, необходимому имхо, вылету.

 

Что и как нужно пока не знаю, поэтому оставил старый

 

function parse_infop(rslt, str)
    if str then
        local infop_n = 1
        for sign, infop_name in string.gmatch(str, "([%-%+%~%=%!])([^%-%+%~%=%!%s]+)") do
            -- парсим параметры функций
            local func, param = infop_name:match('^(.-)(%b())')
            if param then
                param = parse_func_params(param:match('%((.-)%)'))
                infop_name = func or infop_name
            end
            
            if sign == "+" then
                rslt[infop_n] = { name = infop_name, required = true }
            elseif sign == "-" then
                rslt[infop_n] = { name = infop_name, required = false }
            elseif sign == "~" then
                rslt[infop_n] = { prob = tonumber(infop_name) }
            elseif sign == "=" then
                rslt[infop_n] = { func = infop_name, expected = true, params = param}
            elseif sign == "!" then
                rslt[infop_n] = { func = infop_name, expected = false, params = param}
            else
                abort("function 'parse_infop' --> section '%s': field '%s'",section, field)
            end
            infop_n = infop_n + 1
        end
    end
end 

 

 

Ну и наконец вызов  abort_syntax_error_in_cond(npc, section, field) - это шедевр.   :)

Передается 'npc', которого и в помине тут нет, а в функции abort_syntax_error_in_cond из ничего

хотят получить id !?

 

....

 

Ага Нашел где 'npc_rank(novice)' без знака (это в оригинале).

Исправил и уже не вылетает ))

 

файл treasure_manager.ltx

[esc_secret_box_bridge]
...
condlist = {=actor_on_level(l01_escape) npc_rank(novice)} 3
...

и

[esc_secret_village_rucksack]
...
condlist = {npc_rank(novice)} 3
... 

 

 

Так что у себя однозначно ставлю шаблон "(%S)([^%-%+%~%=%!%s]+)"
Изменено пользователем Nazgool
  • Нравится 2

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


Ссылка на сообщение
(изменено)
И мне не нравится elseif-простыня, ПЕРЕД которой дергается parse_func_params.

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

 

Но если хочется, то можно записать и несколько по-другому, но более запутано что-ли

 

function parse_infop(rslt, str)
    if str then
        local infop_n = 1
        for sign, infop_name in string.gmatch(str, "(%S)([^%-%+%~%=%!%s]+)") do
            if sign == "+" then
                rslt[infop_n] = { name = infop_name, required = true }
            elseif sign == "-" then
                rslt[infop_n] = { name = infop_name, required = false }
            elseif sign == "~" then
                rslt[infop_n] = { prob = tonumber(infop_name) }
            elseif sign == "=" or sign == "!" then
                -- парсим параметры функций
                local func, param = infop_name:match('^(.-)(%b())')
                if param then
                    param = parse_func_params(param:match('%((.-)%)'))
                    infop_name = func or infop_name
                end
                rslt[infop_n] = { func = infop_name, expected = (sign == "="), params = param}
            else
                abort("function 'parse_infop' --> sign '%s': infop_name '%s':", sign, infop_name)
            end
            infop_n = infop_n + 1
        end
    end
end 

 

.....

 

 

Ну тут уже на вкус и цвет. Как по мне, то простыня понятнее.

Тогда уже нужно доделывать и инфопорции в этом стиле

 

 function parse_infop(rslt, str)
    if str then
        local infop_n = 1
        for sign, infop_name in string.gmatch(str, "(%S)([^%-%+%~%=%!%s]+)") do
            if sign == "+" or sign == "-" then
                rslt[infop_n] = { name = infop_name, required = (sign == "+") }
            elseif sign == "~" then
                rslt[infop_n] = { prob = tonumber(infop_name) }
            elseif sign == "=" or sign == "!" then
                -- парсим параметры функций
                local func, param = infop_name:match('^(.-)(%b())')
                if param then
                    param = parse_func_params(param:match('%((.-)%)'))
                    infop_name = func or infop_name
                end
                rslt[infop_n] = { func = infop_name, expected = (sign == "="), params = param}
            else
                abort("function 'parse_infop' --> sign '%s': infop_name '%s':", sign, infop_name)
            end
            infop_n = infop_n + 1
        end
    end
end 

 

 

 

@Dennis_Chikin

Когда будет готово, перезалей xr_logic с новыми правками. А то не ясно, что ты изменил(изменишь) а что нет.

В switch_to_section нужно кэшировать db.storage[npc:id()]

 

function switch_to_section( npc, st, section )
    if section == nil or section == "" or
    (section == "sr_aes_deadzone" and has_alife_info( "strelok_pda_have" )) then return false end
        
    local npc_storage    = db.storage[npc:id()]
    local active_section = npc_storage.active_section
        
    if active_section == section then return false end

    if active_section then
        issue_event(npc, npc_storage[npc_storage.active_scheme], "deactivate", npc)
    end
        
    npc_storage.active_section = nil
    npc_storage.active_scheme  = nil
        
    activate_by_section( npc, st.ini, section, false )
    
    return true
end 

 

 

В функции parse_func_params у меня используется шаблон '[^%s:]+'

Я не проверял, поверил разработчикам lua на слово, но элемент '*' (звездочка) называют "прожорливым".

Сначала считывается вся строка, а потом уже идет разбор.

При '[^%s:]+' сразу идет разбор строки.

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

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


Ссылка на сообщение
(изменено)
Да, еще неплохо бы спавн не сразу по 100 штук всего и по-больше, а по 1 штук за апдейт

Это вопрос решался (и решился) достаточно давно.

Поищите сами, ну или я найду дам ссылку на посты мои (про coroutine) и её возможности и Artos-а о реализации этой возможности.

Речь идет о распределении с помощью coroutine по времени или объеме обрабатываемых данных.

Будь то массовый спавн, перебор for i=1, какое-то очень большое число, или ещё что-то тяжелое, всё это распределяется на выбранное время, кол-во апдейтов, объем информации...или как-то ещё.

.....

Ссылку на пост Artos-a нашел http://www.amk-team.ru/forum/index.php?showtopic=11584&page=6#entry641931

О. а вот что и я накалякал http://www.amk-team.ru/forum/index.php?showtopic=7450&page=16#entry622983

Всего 4 года прошло :)

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

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


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

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

AMK-Team.ru

×
×
  • Создать...