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

470 lines
No EOL
16 KiB
Text

--'******************************************************
--'* Áèíäåð îáúåêòà çîíû àíîìàëèé .
--'******************************************************
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