--'****************************************************** --'* Биндер объекта зоны аномалий . --'****************************************************** artefact_ways_by_id = {} artefact_points_by_id = {} parent_zones_by_artefact_id = {} ANOMAL_ZONE_SECT = "anomal_zone" function bind(obj) obj:bind_object(anomaly_zone_binder(obj)) end class "anomaly_zone_binder" (object_binder) function anomaly_zone_binder:__init(obj) super(obj) self.ini = obj:spawn_ini() if not self.ini:section_exist(ANOMAL_ZONE_SECT) then printf( "[anomal_zone %s] no configuration!", obj:name() ) self.disabled = true return end local filename = utils.cfg_get_string(self.ini, ANOMAL_ZONE_SECT, "cfg", nil, false, "", nil) if filename then self.ini = ini_file(filename) end local ini = self.ini self.artefact_ways_by_id = {} self.artefact_points_by_id = {} self.disabled = false self.turned_off = false self.artefacts_table = {} self.start_artefacts_table = {} self.artefacts_coeff_table = {} self.path_table = {} self.fields_table = {} self.mines_table = {} self.respawn_tries_table = {} self.max_artefacts_table = {} self.forces_table = {} self.spawned_count = 0 self.respawn_artefacts = true self.forced_spawn = false self.forced_spawn_override = false self.forced_artefact = "" self.layers_count = utils.cfg_get_number(ini, ANOMAL_ZONE_SECT, "layers_count", nil, false, 1) self.cur_layer = "layer_"..math.random(1,self.layers_count) self.custom_placement = self.layers_count>1 local def_respawn_tries = utils.cfg_get_number(ini, ANOMAL_ZONE_SECT, "respawn_tries", nil, false, 2) local def_max_artefacts = utils.cfg_get_number(ini, ANOMAL_ZONE_SECT, "max_artefacts", nil, false, 3) local def_app_force_xz = utils.cfg_get_number(ini, ANOMAL_ZONE_SECT, "applying_force_xz", nil, false, 200) local def_app_force_y = utils.cfg_get_number(ini, ANOMAL_ZONE_SECT, "applying_force_y", nil, false, 400) local def_arts = utils.cfg_get_string(ini, ANOMAL_ZONE_SECT, "artefacts", nil, false, "", nil) local def_start_arts = utils.cfg_get_string(ini, ANOMAL_ZONE_SECT, "start_artefact",nil, false, "", nil) local def_ways = utils.cfg_get_string(ini, ANOMAL_ZONE_SECT, "artefact_ways", nil, false, "", nil) local def_field_name = utils.cfg_get_string(ini, ANOMAL_ZONE_SECT, "field_name", nil, false, "", nil) local def_coeff_sect_name= utils.cfg_get_string(ini, ANOMAL_ZONE_SECT, "coeffs_section",nil, false, "", "{+actor_was_in_many_bad_places} coeff2, coeff") local def_coeffs = utils.cfg_get_string(ini, ANOMAL_ZONE_SECT, "coeff", nil, false, "", nil) for i = 1, self.layers_count do local section = "layer_"..i self.respawn_tries_table[section] = utils.cfg_get_number(ini, section, "artefact_count", nil, false, def_respawn_tries) self.respawn_tries_table[section] = utils.cfg_get_number(ini, section, "respawn_tries", nil, false, self.respawn_tries_table[section]) self.max_artefacts_table[section] = utils.cfg_get_number(ini, section, "max_artefacts", nil, false, def_max_artefacts) self.forces_table[section] = {} self.forces_table[section].xz = utils.cfg_get_number(ini, section, "applying_force_xz", nil, false, def_app_force_xz) self.forces_table[section].y = utils.cfg_get_number(ini, section, "applying_force_y", nil, false, def_app_force_y) local arts = utils.cfg_get_string(ini, section, "artefacts", nil, false, "", def_arts) if arts == nil then abort("There is no field 'artefacts' in section [%s] in obj [%s]", section, obj:name()) end self.artefacts_table[section] = parse_names(arts) local start_arts = utils.cfg_get_string(ini, section, "start_artefact", nil, false, "", def_start_arts) if start_arts ~= nil then self.forced_spawn = true self.start_artefacts_table[section] = parse_names(start_arts) end local coeffs_section = utils.cfg_get_string(ini, section, "coeffs_section", nil, false, "", def_coeff_sect_name) local parsed_condlist = xr_logic.parse_condlist(nil, "anomal_zone_binder", "coeff_condlist", coeffs_section) local coeffs_sect_name = xr_logic.pick_section_from_condlist(get_story_object("actor"), nil, parsed_condlist) local coeffs = utils.cfg_get_string(ini, section, coeffs_sect_name, nil, false, "", def_coeffs) if coeffs ~= nil then self.artefacts_coeff_table[section] = parse_nums(coeffs) else self.artefacts_coeff_table[section] = {} end local path = utils.cfg_get_string(ini, section, "artefact_ways", nil, false, "", def_ways) if path == nil then abort("There is no field 'artefact_ways' in section [%s] in obj [%s]", section, obj:name()) end self.path_table[section] = parse_names(path) if #self.path_table[section] < self.max_artefacts_table[section] then --abort("Not enough ways for anomal zone [%s], in section [%s], must be at least [%s]", tostring(obj:name()), tostring(section), tostring(self.max_artefacts_table[section])) end if(self.custom_placement) then local field = utils.cfg_get_string(ini, section, "field_name", nil, false, "", def_field_name) if field == nil then --abort("There is no field 'field_name' in section [%s] in obj [%s]", section, obj:name()) self.fields_table[section] = {} else self.fields_table[section] = parse_names(field)--field end local mines_section = utils.cfg_get_string(ini, section, "mines_section", nil, true, "", nil) if mines_section == nil then abort("There is no field 'mines_section' in section [%s] in obj [%s]", section, obj:name()) end if ini:line_count(mines_section) == 0 then --abort("There is no 'mines_names' in section [%s] in obj [%s]", mines_section, obj:name()) end self.mines_table[section] = {} if ini:line_count(mines_section) > 0 then for i = 0, ini:line_count(mines_section)-1 do temp1, mine_name, temp2 = ini:r_line(mines_section, i, "", "") table.insert(self.mines_table[section],mine_name) end end end end self.respawn_tries = self.respawn_tries_table[self.cur_layer] self.max_artefacts = self.max_artefacts_table[self.cur_layer] self.applying_force_xz = self.forces_table[self.cur_layer].xz self.applying_force_y = self.forces_table[self.cur_layer].y end function anomaly_zone_binder:disable_anomaly_fields() if not(self.custom_placement) then self.disabled = true return end local layer = self.cur_layer local anom_fields = bind_anomaly_field.fields_by_names local counter = 0 for k,v in pairs(self.fields_table) do if(k~=layer) then for kk, vv in pairs(self.fields_table[k]) do if(anom_fields[vv]~=nil) then anom_fields[vv]:set_enable(false) else counter = counter + 1 end end end end for k,v in pairs(self.mines_table) do if(k~=layer) then for kk,vv in pairs(self.mines_table[k]) do if(anom_fields[vv]~=nil) then anom_fields[vv]:set_enable(false) else counter = counter + 1 end end end end if(counter==0) then self.disabled = true end if not self.turned_off then for kk, vv in pairs(self.fields_table[layer]) do if(anom_fields[vv]~=nil) then anom_fields[vv]:set_enable(true) end end for kk,vv in pairs(self.mines_table[layer]) do if(anom_fields[vv]~=nil) then anom_fields[vv]:set_enable(true) end end end end function anomaly_zone_binder:respawn_artefacts_and_replace_anomaly_zone() local anom_fields = bind_anomaly_field.fields_by_names self.respawn_artefacts = true if(self.custom_placement) then local layer = self.cur_layer for k,v in pairs(self.fields_table[layer]) do if(anom_fields[v]~=nil) then anom_fields[v]:set_enable(false) end end for k,v in pairs(self.mines_table[layer]) do if(anom_fields[v]~=nil) then anom_fields[v]:set_enable(false) end end layer = "layer_"..math.random(1,self.layers_count) for k,v in pairs(self.fields_table[layer]) do if(anom_fields[v]~=nil) then anom_fields[v]:set_enable(true) end end for k,v in pairs(self.mines_table[layer]) do if(anom_fields[v]~=nil) then anom_fields[v]:set_enable(true) end end self.cur_layer = layer self.respawn_tries = self.respawn_tries_table[self.cur_layer] self.max_artefacts = self.max_artefacts_table[self.cur_layer] self.applying_force_xz = self.forces_table[self.cur_layer].xz self.applying_force_y = self.forces_table[self.cur_layer].y end end function anomaly_zone_binder:spawn_artefact_randomly() local layer = self.cur_layer local rnd_artefact if self.forced_spawn_override then rnd_artefact = self.forced_artefact self.forced_spawn_override = false elseif self.forced_spawn then rnd_artefact = self.start_artefacts_table[layer][#self.start_artefacts_table[layer]] self.forced_spawn = false else if math.random(1,100) > 17 then return end local coeff_total = 0 for k, v in pairs(self.artefacts_coeff_table[layer]) do coeff_total = coeff_total + v end if coeff_total == 0 then for i = 1, #self.artefacts_table[layer] do self.artefacts_coeff_table[layer][i] = 1 coeff_total = coeff_total + 1 end end local rnd = math.random(1, coeff_total) for i = 1, #self.artefacts_table[layer] do local chance = self.artefacts_coeff_table[layer][i] if rnd <= chance then rnd_artefact = self.artefacts_table[layer][i] break end rnd = rnd - chance end end local rnd_path_name = self:get_artefact_path() local rnd_path = patrol(rnd_path_name) local rnd_path_point = math.random(0, rnd_path:count() - 1) local artefact_obj = alife():create( rnd_artefact, rnd_path:point(rnd_path_point), self.object:level_vertex_id(), self.object:game_vertex_id()) artefact_ways_by_id[artefact_obj.id] = rnd_path_name artefact_points_by_id[artefact_obj.id] = rnd_path_point self.artefact_ways_by_id[artefact_obj.id] = rnd_path_name self.artefact_points_by_id[artefact_obj.id] = rnd_path_point parent_zones_by_artefact_id[artefact_obj.id] = self self.spawned_count = self.spawned_count + 1 end function anomaly_zone_binder:get_artefact_path() local temp_table = {} for k,v in pairs(self.path_table[self.cur_layer]) do local f_spawned = false for kk,vv in pairs(self.artefact_ways_by_id) do if vv ~= nil and v == vv then f_spawned = true end end if not f_spawned then table.insert(temp_table, v) end end if #temp_table < 1 then --abort("No free way to spawn artefact in anomal zone [%s]", tostring(self.object:name())) return self.path_table[self.cur_layer][math.random(1, #self.path_table[self.cur_layer])] end local rnd_path_name = temp_table[math.random(1, #temp_table)] return rnd_path_name end function anomaly_zone_binder:set_forced_override(artefact_name) self.forced_artefact = artefact_name self.forced_spawn_override = true printf("set forced override for zone [%s], artefact [%s]", tostring(self.object:name()), tostring(artefact_name)) end function anomaly_zone_binder:reload(section) object_binder.reload(self, section) end function anomaly_zone_binder:reinit() object_binder.reinit(self) db.storage[self.object:id()] = {} self.st = db.storage[self.object:id()] end function anomaly_zone_binder:net_spawn(server_object) if not object_binder.net_spawn(self, server_object) then return false end db.add_anomaly(self) db.add_obj(self.object) return true end function anomaly_zone_binder:net_destroy() db.del_anomaly(self) db.del_obj(self.object) db.storage[self.object:id()] = nil object_binder.net_destroy(self) end function anomaly_zone_binder:update(delta) object_binder.update(self, delta) if (not self.turned_off) and (self.spawned_count < self.max_artefacts) and self.respawn_artefacts then local cnt = self.respawn_tries if cnt > self.max_artefacts - self.spawned_count then cnt = self.max_artefacts - self.spawned_count end if cnt ~= 0 then for i=1, cnt do self:spawn_artefact_randomly() end end self.respawn_artefacts = false elseif (not self.turned_off) and (self.spawned_count >= self.max_artefacts) and self.respawn_artefacts then self.respawn_artefacts = false end if not(self.disabled) then self:disable_anomaly_fields() end end function anomaly_zone_binder:turn_off() self.turned_off = true self:disable_anomaly_fields() for k,v in pairs(self.artefact_ways_by_id) do alife():release(alife():object(tonumber(k)), true) artefact_ways_by_id[k] = nil artefact_points_by_id[k] = nil parent_zones_by_artefact_id[k] = nil end self.spawned_count = 0 self.artefact_ways_by_id = {} self.artefact_points_by_id = {} end function anomaly_zone_binder:turn_on(f_af) self.turned_off = false self:disable_anomaly_fields() if f_af then self.respawn_artefacts = true else self.respawn_artefacts = false end end function anomaly_zone_binder:on_artefact_take(obj) local id if(type(obj.id)=="number") then id = obj.id else id = obj:id() end artefact_ways_by_id[id] = nil artefact_points_by_id[id] = nil self.artefact_ways_by_id[id] = nil self.artefact_points_by_id[id] = nil self.spawned_count = self.spawned_count - 1 pda.change_anomalies_names() end -- Standart function for save function anomaly_zone_binder:net_save_relevant() return true end -- Saving anomaly zone function anomaly_zone_binder:save(thread) set_save_marker(thread, "save", false, "anomaly_zone_binder") object_binder.save(self, thread) local count = 0 for k,v in pairs(self.artefact_ways_by_id) do count = count + 1 end thread:w_u16(count) for k,v in pairs(self.artefact_ways_by_id) do thread:w_u16(k) thread:w_stringZ(v) end ----------------optimize this--------------------------------------------------- local count = 0 for k,v in pairs(self.artefact_points_by_id) do count = count + 1 end thread:w_u16(count) for k,v in pairs(self.artefact_points_by_id) do thread:w_u16(k) thread:w_u8(v) end -------------------------------------------------------------------------------- thread:w_u8(self.spawned_count) thread:w_bool(self.respawn_artefacts) thread:w_bool(self.forced_spawn) thread:w_bool(self.forced_spawn_override) thread:w_stringZ(self.forced_artefact) local layer_num = tonumber(string.sub(self.cur_layer, string.find(self.cur_layer, "_")+1, string.len(self.cur_layer))) if(layer_num) then thread:w_u8(layer_num) else thread:w_u8(-1) end thread:w_bool(self.turned_off) set_save_marker(thread, "save", true, "anomaly_zone_binder") end -- Loading anomaly zone function anomaly_zone_binder:load(thread) set_save_marker(thread, "load", false, "anomaly_zone_binder") object_binder.load(self, thread) local count = thread:r_u16() for i=1,count do local art_id = thread:r_u16() local way_name = thread:r_stringZ() artefact_ways_by_id[art_id] = way_name self.artefact_ways_by_id[art_id] = way_name parent_zones_by_artefact_id[art_id] = self end ----------------optimize this--------------------------------------------------- local count = thread:r_u16() for i=1,count do local art_id = thread:r_u16() local point_name = thread:r_u8() artefact_points_by_id[art_id] = point_name self.artefact_points_by_id[art_id] = point_name end -------------------------------------------------------------------------------- self.spawned_count = thread:r_u8() self.respawn_artefacts = thread:r_bool() self.forced_spawn = thread:r_bool() self.forced_spawn_override = thread:r_bool() self.forced_artefact = thread:r_stringZ() local layer_num = thread:r_u8() if(layer_num~=255) then self.cur_layer = "layer_"..layer_num end self.turned_off = thread:r_bool() set_save_marker(thread, "load", true, "anomaly_zone_binder") end