e4s-sdk/gamedata/scripts/treasure_manager.script
2026-06-17 23:06:51 +03:00

291 lines
9 KiB
Text

local treasure_manager = nil
class "CTreasureManager"
function CTreasureManager:__init()
self.items_spawned = false
self.check_time = nil
self.secrets = {}
self.secret_restrs = {}
self.items_from_secrets = {}
end
function CTreasureManager:initialize()
local ini = ini_file("misc\\secrets.ltx")
local n = ini:line_count("list")
for i=0,n-1 do
local result, id, value = ini:r_line("list",i,"","")
if(ini:section_exist(id)) then
self.secrets[id] = {items = {}, given = false, empty = nil, refreshing = false, checked = false, to_find = 0}
local items_count = ini:line_count(id)
local item_section = ""
for i=0,items_count-1 do
result, item_section, str = ini:r_line(id,i,"","")
if(item_section=="empty") then
local parsed_condlist = xr_logic.parse_condlist(nil, "treasure_manager", "empty_cond", str)
self.secrets[id].empty = parsed_condlist
elseif(item_section=="refreshing") then
local parsed_condlist = xr_logic.parse_condlist(nil, "treasure_manager", "refreshing_cond", str)
self.secrets[id].refreshing = parsed_condlist
else
self.secrets[id].items[item_section] = {}
local tbl = utils.parse_spawns(str)
if(#tbl==0) then
abort("There is no items count set for treasure [%s], item [%s]", id, item_section)
end
for i=1,#tbl do
local tbl = {count = tonumber(tbl[i].section), prob = tonumber(tbl[i].prob or 1)}
table.insert(self.secrets[id].items[item_section], tbl)
end
end
end
else
abort("There is no section [%s] in secrets.ltx", tostring(id))
end
end
end
function CTreasureManager:fill(se_obj, treasure_id)
if(self.secrets[treasure_id]) then
local item = self.secrets[treasure_id].items[se_obj:section_name()]
if(item) then
for i=1,#item do
if not(item[i].item_ids) then
item[i].item_ids = {}
end
local count = #item[i].item_ids
if(count<item[i].count) then
item[i].item_ids[count+1] = se_obj.id
return true
end
end
else
abort("Attempt to register unknown item [%s] in secret [%s]", se_obj:section_name(), treasure_id)
end
else
abort("Attempt to register item [%s] in unexistent secret [%s]", se_obj:name(), treasure_id)
end
end
function CTreasureManager:register_item(se_obj)
local spawn_ini = se_obj:spawn_ini()
if(spawn_ini:section_exist("secret")) then
local result, id, value
result, id, value = spawn_ini:r_line("secret",0,"","")
if id ~= "name" then
abort("There is no 'name' field in [secret] section for object [%s]", se_obj:name())
end
if value == "" then
abort("Field 'name' in [secret] section got no value for object [%s]", se_obj:name())
end
return self:fill(se_obj, value)
end
end
function CTreasureManager:register_restrictor(se_obj)
local spawn_ini = se_obj:spawn_ini()
if(spawn_ini:section_exist("secret")) then
self.secret_restrs[se_obj:name()] = se_obj.id
end
end
function CTreasureManager:update()
if not(self.items_spawned) then
for k,v in pairs(self.secrets) do
self:spawn_treasure(k)
end
self.items_spawned = true
end
local global_time = time_global()
if(self.check_time and global_time-self.check_time<=500) then
return
end
self.check_time = global_time
for k,v in pairs(self.secrets) do
if(v.given) then
if(v.empty) then
local sect = xr_logic.pick_section_from_condlist(db.actor, nil, v.empty)
if(sect=="true") and not v.checked then
level.map_remove_object_spot(self.secret_restrs[k], "treasure")
xr_statistic.inc_founded_secrets_counter()
v.empty = nil
v.checked = true
printf("Empty secret [%s] remove map spot!", k)
end
elseif(v.refreshing and v.checked) then
local sect = xr_logic.pick_section_from_condlist(db.actor, nil, v.refreshing)
if(sect=="true") then
v.given = false
v.checked = false
printf("Given secret [%s] now is avaliable!", k)
end
end
end
end
end
function CTreasureManager:spawn_treasure(treasure_id)
if not(self.secrets[treasure_id]) then
abort("There is no stored secret [%s]", tostring(treasure_id))
end
if(self.secrets[treasure_id].given) then
printf("Secret [%s] already given!", treasure_id)
return
end
for item_section,item_params in pairs(self.secrets[treasure_id].items) do
for num = 1,#item_params do
for i = 1,item_params[num].count do
local prob = math.random()
if(prob<item_params[num].prob) then
if(item_params[num].item_ids and item_params[num].item_ids[i]) then
local se_obj = alife():object(item_params[num].item_ids[i])
local obj = alife():create( item_section,
se_obj.position,
se_obj.m_level_vertex_id,
se_obj.m_game_vertex_id)
obj.angle = se_obj.angle
obj:use_ai_locations(se_obj:used_ai_locations())
self.items_from_secrets[obj.id] = self.secret_restrs[treasure_id]
self.secrets[treasure_id].to_find = self.secrets[treasure_id].to_find + 1
else
--[[
log("----------->error id="..treasure_id)
print_table(self.secrets[treasure_id])
log("----------->item_section="..tostring(item_section))
log("----------->num="..tostring(num))
log("----------->i="..tostring(i))
log("----------->prob="..tostring(prob))
]]
end
end
end
end
end
end
function CTreasureManager:give_treasure(treasure_id, spawn)
if not(self.secrets[treasure_id]) then
abort("There is no stored secret [%s]", tostring(treasure_id))
end
if(self.secrets[treasure_id].given) then
printf("Secret [%s] already given!", treasure_id)
return
end
if(self.secrets[treasure_id].to_find==0 and not(self.secrets[treasure_id].empty)) then
news_manager.send_treasure(2)
printf("Secret [%s] already empty", treasure_id)
return
end
if(spawn) then
self:spawn_treasure(treasure_id)
end
level.map_add_object_spot_ser(self.secret_restrs[treasure_id], "treasure", "")
self.secrets[treasure_id].given = true
news_manager.send_treasure(0)
printf("Give secret [%s]", treasure_id)
end
function CTreasureManager:give_random()
local rnd_tbl = {}
for k,v in pairs(self.secrets) do
if not(v.given) then
table.insert(rnd_tbl, k)
end
end
if(#rnd_tbl~=0) then
self:give_treasure(rnd_tbl[math.random(1,#rnd_tbl)])
return
end
printf("There are no treasures avaliable!")
end
function CTreasureManager:on_item_take(obj_id)
local restr_id = self.items_from_secrets[obj_id]
local treasure_id = nil
for k,v in pairs(self.secret_restrs) do
if(restr_id==v) then
treasure_id = k
end
end
if(treasure_id) then
self.secrets[treasure_id].to_find = self.secrets[treasure_id].to_find - 1
if(self.secrets[treasure_id].to_find==0) then
level.map_remove_object_spot(self.secret_restrs[treasure_id], "treasure")
xr_statistic.inc_founded_secrets_counter()
printf("Secret [%s] now is empty!", treasure_id)
self.secrets[treasure_id].checked = true
news_manager.send_treasure(1)
end
self.items_from_secrets[obj_id] = nil
end
end
function CTreasureManager:save(package)
set_save_marker(package, "save", false, "CTreasureManager")
package:w_bool(self.items_spawned)
local num = 0
for k,v in pairs(self.items_from_secrets) do
num = num + 1
end
package:w_u16(num)
for k,v in pairs(self.items_from_secrets) do
package:w_u16(k)
package:w_u16(v)
end
num = 0
for k,v in pairs(self.secrets) do
num = num + 1
end
package:w_u16(num)
for k,v in pairs(self.secrets) do
if not(self.secret_restrs[k]) then
package:w_u16(-1)
else
package:w_u16(self.secret_restrs[k])
end
package:w_bool(v.given)
package:w_bool(v.checked)
package:w_u8(v.to_find)
end
set_save_marker(package, "save", true, "CTreasureManager")
end
function CTreasureManager:load(package)
set_save_marker(package, "load", false, "CTreasureManager")
self.items_spawned = package:r_bool()
self.items_from_secrets = {}
local num = package:r_u16()
for i=1,num do
local k = package:r_u16()
local v = package:r_u16()
self.items_from_secrets[k] = v
end
local num = package:r_u16()
for i=1,num do
local id = package:r_u16()
for k,v in pairs(self.secret_restrs) do
if(v==id) then
id = k
break
end
end
local given = package:r_bool()
local checked = package:r_bool()
local to_find = package:r_u8()
if(id~=65535 and self.secrets[id]) then
self.secrets[id].given = given
self.secrets[id].checked = checked
self.secrets[id].to_find = to_find
end
end
set_save_marker(package, "load", true, "CTreasureManager")
end
--------------------------------------------------------------------------------
function get_treasure_manager()
if(treasure_manager==nil) then
treasure_manager = CTreasureManager()
treasure_manager:initialize()
end
return treasure_manager
end