Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -----------------------------------------
- -- spawn_manager.script
- --
- -- Alundaio
- -----------------------------------------
- -- storage for spawned objects
- local Objects = {}
- -- Spawner Table and Index
- local SpawnerIndex = {}
- local Spawner = {}
- local ini = ini_file("spawn_manager\\spawn_manager.ltx")
- local initialized = false
- function init()
- local SpawnerSections = collect_sections(ini,{"sections"})
- for k,v in pairs(SpawnerSections) do
- table.insert(SpawnerIndex,k)
- -- Create a spawn manager for each section
- Spawner[k] = SpawnManager(k)
- end
- initialized = true
- end
- ---------------------------------------------------
- -- class SpawnManager
- ---------------------------------------------------
- class "SpawnManager"
- function SpawnManager:__init(section)
- self.section = section
- self.loaded = false
- end
- function SpawnManager:initialize()
- local section = self.section
- -- Inherit data from ini
- self.sections = str_explode(read_from_ini( ini, section, "sections", "string", "stalker"), "," )
- self.respawn = read_from_ini( ini, section, "respawn", "string", "true" )
- self.respawn_delta = str_explode(read_from_ini( ini, section, "respawn_delta", "string", "60,120"), "," )
- self.respawn_radius = read_from_ini( ini, section, "respawn_radius", "float", 0 )
- self.count = read_from_ini( ini, section, "count", "float", 0 )
- self.position = str_explode(read_from_ini( ini, section, "position", "string", "0,0,0"), "," )
- self.level_vertex_id = read_from_ini( ini, section, "level_vertex_id", "float", 0 )
- self.game_vertex_id = read_from_ini( ini, section, "game_vertex_id", "float", 0 )
- -- set respawn timer
- self.respawn_delta[1] = tonumber(self.respawn_delta[1])
- self.respawn_delta[2] = tonumber(self.respawn_delta[2])
- self.delta = math.random(self.respawn_delta[1],self.respawn_delta[2])
- -- create position vector
- self.position = vector():set( tonumber(self.position[1]) , tonumber(self.position[2]), tonumber(self.position[3]))
- -- create table to hold ids of spawned sections
- self.ids = {}
- self.loaded = true
- end
- function SpawnManager:finalize()
- self:clear_dead()
- end
- function SpawnManager:update(game_time)
- -- Check if time to call a respawn
- if (self.last_respawn_update == nil or game_time:diffSec(self.last_respawn_update) > self.delta) then
- -- Clear Dead
- self:clear_dead()
- -- Set last update
- self.last_respawn_update = game_time
- -- check if max population reached
- if (#self.ids == self.count) then
- return
- end
- -- Parse conditions to allow a respawn
- local actor = alife():actor()
- --if (xr_logic.pick_section_from_condlist(actor, actor, xr_logic.parse_condlist(actor,"","",self.respawn) ) ~= "true") then
- --return
- --end
- -- If actor is on same level, then respawn only if actor outside of respawn raidus
- if (self.respawn_radius > 0 and game_graph():vertex(self.game_vertex_id):level_id() == game_graph():vertex(actor.m_game_vertex_id):level_id()) then
- if (actor.position:distance_to_sqr(self.position) < self.respawn_radius) then
- return
- end
- end
- -- randomize delta
- self.delta = math.random(self.respawn_delta[1],self.respawn_delta[2])
- -- Spawn section for each available slot
- self:spawn()
- end
- end
- function SpawnManager:spawn()
- local se_obj
- local amt = self.count-#self.ids
- for i=1,amt,1 do
- -- Create sections
- se_obj = alife():create(self.sections[math.random(1, #self.sections)],self.position,self.level_vertex_id,self.game_vertex_id)
- -- Remember spawned objects by id
- table.insert(self.ids, se_obj.id)
- register_object(se_obj.id)
- set_object_info(se_obj,"alive",true)
- end
- end
- function SpawnManager:clear_dead()
- if (#self.ids < 1) then
- return
- end
- local se_obj
- local _temp = {}
- for i=1,#self.ids,1 do
- se_obj = alife():object(self.ids[i])
- -- Check if alive or deleted
- if (se_obj == nil or get_object_info(se_obj,"alive") == false) then
- -- unregister object
- unregister_object(self.ids[i])
- else
- table.insert(_temp,self.ids[i])
- end
- self.ids[i] = nil
- end
- self.ids = nil
- self.ids = _temp
- end
- function SpawnManager:save(packet)
- set_save_marker(packet, "save", false, "SpwnManager")
- if (self.last_respawn_update) then
- utils.w_CTime(packet, self.last_respawn_update)
- else
- packet:w_u8(0)
- end
- packet:w_u32(#self.ids)
- for i=1,#self.ids,1 do
- packet:w_u32(self.ids[i])
- end
- set_save_marker(packet, "save", true, "SpwnManager")
- end
- function SpawnManager:load(packet)
- set_save_marker(packet, "load", false, "SpwnManager")
- self.last_respawn_update = utils.r_CTime(packet)
- local count = packet:r_u32()
- for i=1,count,1 do
- self.ids[i] = packet:r_u32()
- end
- set_save_marker(packet, "load", true, "SpwnManager")
- end
- function set_object_info(se_obj,info,val)
- if (Objects[se_obj.id]) then
- --printf("Set[%s] %s = %s",se_obj.id,info,val)
- Objects[se_obj.id][info] = val
- end
- end
- function get_object_info(se_obj,info)
- if (Objects[se_obj.id]) then
- --printf("Get[%s] %s = %s",se_obj.id,info,Objects[se_obj.id][info])
- return Objects[se_obj.id][info]
- end
- end
- function register_object(id)
- --printf("Object registered %s",se_obj.id)
- if not (Objects[se_obj.id]) then
- Objects[id] = {}
- end
- end
- function unregister_object(id)
- --printf("Object unregistered %s",se_obj.id)
- Objects[id] = nil
- end
- ---------------------------------------------------
- -- Callbacks
- ---------------------------------------------------
- -- Callback actor_binder:net_spawn()
- function on_game_load()
- if not (initialized) then
- init()
- end
- end
- -- Callback actor_binder:update()
- function on_actor_update()
- local gt = game.get_game_time()
- for i=1,#SpawnerIndex,1 do
- if not (Spawner[SpawnerIndex[i]].loaded) then
- Spawner[SpawnerIndex[i]]:initialize()
- end
- Spawner[SpawnerIndex[i]]:update(gt)
- end
- end
- -- Callback actor_binder:save()
- function on_actor_save(actor,packet)
- for i=1,#SpawnerIndex,1 do
- Spawner[SpawnerIndex[i]]:finalize()
- Spawner[SpawnerIndex[i]]:save(packet)
- end
- end
- -- Callback actor_binder:load()
- function on_actor_load(actor,reader)
- if not (initialized) then
- init()
- end
- for i=1,#SpawnerIndex,1 do
- Spawner[SpawnerIndex[i]]:initialize()
- Spawner[SpawnerIndex[i]]:load(reader)
- end
- initialized = true
- end
- -- Callback se_stalker:on_death() Can be called also in se_monster
- function on_npc_death(se_obj,who)
- -- flag object as dead
- if (get_object_info(se_obj,"alive")) then
- set_object_info(se_obj,"alive",false)
- end
- end
- --------------------------
- -- Utils
- --------------------------
- function collect_sections(ini,sections)
- local r,p = {},{}
- for k,v in ipairs(sections) do
- if ini:section_exist(v) then
- local n = ini:line_count(v)
- if n > 0 then
- for i = 0,n-1 do
- local res,id,val = ini:r_line(v,i,"","")
- if r[id] == nil then
- r[id] = val
- end
- end
- end
- p[k] = n
- else
- p[k] = 0
- end
- end
- return r,p
- end
- function read_from_ini(ini,section,line,var_type,default)
- if not (ini) then
- ini = system_ini()
- end
- if (section and line and ini:section_exist(section) and ini:line_exist(section,line)) then
- if (var_type == "bool") then
- return ini:r_bool(section,line)
- elseif (var_type == "string") then
- return ini:r_string(section,line)
- elseif (var_type == "float") then
- return ini:r_float(section,line)
- else
- return ini:r_string_wq(section,line)
- end
- else
- return default
- end
- end
- function string:split(pat)
- local st, g = 1, self:gmatch("()("..pat..")")
- local function getter(self, segs, seps, sep, cap1, ...)
- st = sep and seps + #sep
- return self:sub(segs, (seps or 0) - 1), cap1 or sep, ...
- end
- local function splitter(self)
- if st then return getter(self, st, g()) end
- end
- return splitter, self
- end
- function str_explode(str,pattern)
- local t = {}
- if (type(str) ~= "string") then return end
- for word, pat, start in str:split(pattern) do
- t[#t+1] = word
- if (start and pat == pattern) then
- t[#t+1] = str:sub(start)
- break
- end
- end
- return t
- end
- function printf(txt,...)
- if not (text) then return end
- local i = 0
- local p = {...}
- local function sr(a)
- i = i + 1
- return tostring(p[i])
- end
- local output = string.gsub(text,"%%s",sr)
- get_console():execute("load ~#I#:"..output)
- --get_console():execute("flush")
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement