Nazgool 250 Опубликовано 30 Июля 2015 (изменено) 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 и -info3. info2 прочитан не будет, т.к. перед ним нет никакого знака. На самом деле это ошибка. И, считаю, такие записи нужно пресекать. Что и получилось при использовании шаблона "(%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]+)" Изменено 30 Июля 2015 пользователем Nazgool 2 Поделиться этим сообщением Ссылка на сообщение
Nazgool 250 Опубликовано 30 Июля 2015 (изменено) И мне не нравится 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:]+' сразу идет разбор строки. Изменено 30 Июля 2015 пользователем Nazgool 1 Поделиться этим сообщением Ссылка на сообщение
Nazgool 250 Опубликовано 17 Ноября 2015 (изменено) Да, еще неплохо бы спавн не сразу по 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 года прошло Изменено 17 Ноября 2015 пользователем Nazgool 1 1 Поделиться этим сообщением Ссылка на сообщение