--' Ключем является группировка персонажа. Значением является таблица, содержашая имена секций предметов. local item_by_community = {} --' Зависимости в спауне предметов. Предмет спауниться только если есть хотя бы один из зависимых. local item_dependence = {} --' Множители и минимаксы для выпадения вещей в зависимости от уровня local mul_by_level = {} local count_by_level = {} --' Предметы, которые нельзя удалять (квестовые например) local always_keep_item = {} --' Предметы, относящиеся к патронам. Их надо спаунить другим методом. ammo_sections = {} local death_ini = ini_file("misc\\death_generic.ltx") function init_drop_settings() local community_list = { "stalker", "dolg", "freedom", "bandit", "army", "zombied", "ecolog", "killer", "monolith" } for k,v in pairs(community_list) do --' Необходимо заполнить таблицу item_by_community[v] = {} if death_ini:section_exist(v) then local n = death_ini:line_count(v) local id, value = "", "" for i=0,n-1 do result, id, value = death_ini:r_line(v,i,"","") item_by_community[v][id] = 100*tonumber(value) end end end --' Заполняем таблицу зависимостей local n = death_ini:line_count("item_dependence") local id, value = "", "" for i=0,n-1 do result, id, value = death_ini:r_line("item_dependence",i,"","") item_dependence[id] = {} local vvv = parse_names(value) for k,v in pairs(vvv) do item_dependence[id][v] = true end end --' Множители и минимаксы для выпадения вещей в зависимости от уровня local level_name = level.name() if not death_ini:section_exist(level_name) then level_name = "default" end local n = death_ini:line_count(level_name) local id, value = "", "" for i=0,n-1 do result, id, value = death_ini:r_line(level_name,i,"","") mul_by_level[id] = tonumber(value) end local item_count_section = "item_count_" .. level.get_game_difficulty() local n = death_ini:line_count(item_count_section) for i=0,n-1 do result, id, value = death_ini:r_line(item_count_section,i,"","") --' Нужно распарсить value в два значения local t = parse_nums(value) if t[1] == nil then abort("Error on [death_ini] declaration. Section [%s], line [%s]", item_count_section, tostring(id)) end local min = t[1] local max = t[2] if max == nil then max = min end if mul_by_level[id] == nil then mul_by_level[id] = 0 end min = tonumber(min) * mul_by_level[id] max = tonumber(max) * mul_by_level[id] count_by_level[id] = {min = min, max = max} end --' Предметы, которые нельзя удалять (квестовые например) local n = death_ini:line_count("keep_items") for i=0,n-1 do result, id, value = death_ini:r_line("keep_items",i,"","") if value == "true" then always_keep_item[id] = true end end --' Предметы, относящиеся к патронам. Их надо спаунить другим методом. ammo_sections = {} local n = death_ini:line_count("ammo_sections") local id, value = "", "" for i=0,n-1 do result, id, value = death_ini:r_line("ammo_sections",i,"","") ammo_sections[id] = true end end class "drop_manager" function drop_manager:__init(npc) self.npc = npc end function drop_manager:create_release_item() --' Спрашиваем у серверного объекта генерились ли предметы local se_obj = alife():object(self.npc:id()) if se_obj == nil or se_obj.death_droped == true then return end se_obj.death_droped = true --' Запускаем итератор на удаление предметов self.npc:iterate_inventory(keep_item, self.npc) --' Проверка на отсутствие спауна лута local ini = self.npc:spawn_ini() if ini and ini:section_exist("dont_spawn_loot") then return end local st = db.storage[self.npc:id()] local st_ini = st and st.ini if st_ini and st_ini:line_exist(st.section_logic , "dont_spawn_loot") then return end --' Доспавниваем необходимое количество итемов: --' Необходимо составить список объектов которые могут быть заспавнены для персонажа local spawn_items = item_by_community[character_community(self.npc)] if spawn_items == nil then return end for k,v in pairs(spawn_items) do --' По каждому объекту необходимо получить зависимости if check_item_dependence(self.npc, k) == true then --' По каждому объекту необходимо получить количество if count_by_level[k] == nil then abort("Incorrect count settings in death_manager for object[%s]", k) end local number = math.ceil(math.random(count_by_level[k].min, count_by_level[k].max)) --' Необходимо заспавнить нужное количество. create_items(self.npc, k, number, v) end end end --' Функция вызывается для каждого предмета, если вернет false то предмет удалится. function keep_item(npc, item) local section = item:section() local ini = npc:spawn_ini() if ini and ini:section_exist("keep_items") and section ~= "guitar_a" and section ~= "harmonica_a" and section ~= "wpn_binoc" and section ~= "device_torch" and section ~= "device_pda" then return end if isArtefact(item) then return end -- printf("keep_item:item ["..item:name().."] npc_name ["..npc:name().."]") if section == "bolt" then return end if always_keep_item[section] == true then return end --printf("item name [%s]", item:name()) if isWeapon(item) and not(get_clsid(item)==clsid.wpn_grenade_rgd5_s or get_clsid(item)==clsid.wpn_grenade_f1_s) then set_weapon_drop_condition(item) return end if xr_corpse_detection.lootable_table[section] == true and ammo_sections[section] == nil then return end alife():release(alife():object(item:id()), true) --[[ local item_id = item:id() local item_in_slot = npc:item_in_slot(2) if item_in_slot ~= nil and item_in_slot:id() == item_id then --' Тут надо уменьшить кондишн оружия item:set_condition((math.random(40)+40)/100) return end item_in_slot = npc:item_in_slot(3) if item_in_slot ~= nil and item_in_slot:id() == item_id then --' Тут надо уменьшить кондишн оружия item:set_condition((math.random(40)+40)/100) return end -- npc:mark_item_dropped(item) local item_in_slot = npc:item_in_slot(4) if item_in_slot ~= nil and item_in_slot:id() == item_id then return end if not npc:marked_dropped(item) then -- printf("releasing object ["..item:name().."]") alife():release(alife():object(item:id()), true) end ]] end function set_weapon_drop_condition(item) local condition = (math.random(40)+40)/100 --printf("condition [%s]", tostring(condition)) item:set_condition(condition) end --' Функция спавнит необходимое число предметов function create_items(npc, section, number, rnd) --'printf("create %s of %s", tostring(number), tostring(section)) if ammo_sections[section] == true then if number > 0 then create_ammo(section, npc:position(), npc:level_vertex_id(), npc:game_vertex_id(), npc:id(), number) end else for i=1,number do --' Проверяем вероятность появить каждый объект в отдельности if math.random(100) <= rnd then alife():create(section, npc:position(), npc:level_vertex_id(), npc:game_vertex_id(), npc:id()) end end end end --' Функция проверяет есть ли хоть один из зависимых объектов у персонажа function check_item_dependence(npc, section) if item_dependence[section] == nil then return true end local d_flag = true for k,v in pairs(item_dependence[section]) do local obj = npc:object(k) if obj ~= nil and npc:marked_dropped(obj) ~= true then return true end d_flag = false end return d_flag end