Divergent/mods/iTheon New Tasks/gamedata/scripts/new_tasks_addon_tasks_utils...

423 lines
12 KiB
Plaintext
Raw Normal View History

2024-03-17 20:18:03 -04:00
-- Adapted the debugger code
function spawn_at_position(section, position_vector, lvid, gvid, is_squad, angle, is_anomaly)
local se_obj = alife_create(section, position_vector, lvid, gvid)
if is_squad then
se_obj:create_npc(nil, position_vector, lvid, gvid)
local sim = alife()
for k in se_obj:squad_members() do
local se_npc = k.object or k.id and sim:object(k.id)
if (se_npc) then
SIMBOARD:setup_squad_and_group(se_npc)
SendScriptCallback("squad_on_npc_creation",se_obj,se_npc)
end
end
end
if angle then
se_obj.angle = angle
end
if is_anomaly then
local data = utils_stpk.get_object_data(se_obj)
if (data) then
data.object_flags = 31
data.restrictor_type = 0
data.shapes = {}
data.shapes[1] = {}
data.shapes[1].shtype = 0
data.shapes[1].offset = VEC_ZERO
data.shapes[1].radius = 10
utils_stpk.set_object_data(data,se_obj)
end
end
return se_obj.id
end
-- TODO: remove second param - it's cancer
-- Second param is mainly used for loop spawning to not have same sections defined in configs
function spawn_helper(spawn_config, section_override)
return spawn_at_position(
spawn_config.section or section_override,
spawn_config.vector,
spawn_config.lvid,
spawn_config.gvid,
spawn_config.is_squad,
spawn_config.angle,
spawn_config.is_anomaly
)
end
function is_dark_night ()
return level.get_time_hours() <= 3 or level.get_time_hours() >= 22
end
function spawn_helicopter(is_strong, pos, lvid, gvid)
local heli = "new_tasks_addon_heli_" .. (is_strong and "strong" or "weak")
local se_obj = alife_create(heli, pos, lvid, gvid)
local visual = utils_data.cfg_get_string(ini_sys, heli,"visual", se_obj, false)
local data = utils_stpk.get_heli_data(se_obj)
if (data) then
data.visual_name = visual and visual ~= "" and visual or [[dynamics\vehicles\mi2\veh_mi2_01]]
data.motion_name = [[helicopter\aaa.anm]]
data.startup_animation = "idle"
data.skeleton_name = "idle"
data.engine_sound = [[vehicles\helicopter\helicopter]]
utils_stpk.set_heli_data(data, se_obj)
else
safe_release_manager.release(se_obj)
end
return se_obj.id
end
function immediate_explosion(actor,obj)
if (obj) then
obj:explode(0)
end
end
function noop() end
function find_index(tab, val)
for index, value in ipairs(tab) do
if value == val then
return index
end
end
return -1
end
function has_value(tab, val)
for index, value in ipairs(tab) do
if value == val then
return true
end
end
return false
end
function shallow_copy(t)
local res = {}
for k,v in pairs(t) do
res[k] = v
end
return res
end
-- No invalid range check - expect to receive the right input
function rand_with_exclusion(min, max, exclude)
local t = {}
for i = min, max do
if i ~= exclude then
table.insert(t, i)
end
end
local rand_i = math.random(#t)
return t[rand_i]
end
function is_strike(shit)
-- IDK why but for some reason hit.strike comes back as 7 sometimes. Something's really fucked up
return shit.type == 5
end
function is_axe()
local item = db.actor:active_item()
return item and string.find(item:section(), "axe")
end
function is_melee(item)
return string.find(item:section(), "axe") or string.find(item:section(), "knife")
end
function teleport_visual()
level.add_pp_effector ("teleport.ppe", 2006, false)
local snd_obj = sound_object("affects\\tinnitus3a")
snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, VEC_ZERO, 1.0, 1.0)
end
-- Used to push dead bodies that should disappear below the textures to avoid errors caused by on_death callbacks from other mods
function hide_through_teleport(id)
CreateTimeEvent(0,"nta_hide_body_teleport_" .. id,0, function ()
local obj = level.object_by_id(id)
local pos = obj:position()
pos.y = pos.y - 40
obj:force_set_position(pos, false)
return true
end)
end
function spawn_companion_squad(sq_section, vector, lvid, gvid)
local id = spawn_at_position(sq_section, vector, lvid, gvid, true)
local squad = alife_object(id)
axr_companions.companion_squads[squad.id] = squad
for k in squad:squad_members() do
local se_obj = k.object or k.id and sim:object(k.id)
if (se_obj) then
se_save_var(se_obj.id,se_obj:name(),"companion",true)
se_save_var(se_obj.id,se_obj:name(),"companion_cannot_dismiss",true)
SIMBOARD:setup_squad_and_group(se_obj)
end
end
-- Add to ignore offline combat simulation list
sim_offline_combat.task_squads[squad.id] = true
return id
end
function squad_alive(id)
local sim = alife()
local squad = sim:object(id)
local alive = false
for k in squad:squad_members() do
local se_npc = k.object or k.id and sim:object(k.id)
if (se_npc:alive()) then
alive = true
end
end
return alive
end
-- Excluded Bar
southern_maps = {
"k00_marsh",
"k01_darkscape",
"k02_trucks_cemetery",
"l01_escape",
"l02_garbage",
"l03_agroprom",
"l04_darkvalley",
"l06_rostok",
"l07_military",
"l08_yantar",
"l09_deadcity",
"y04_pole",
}
nothern_maps = {
"l10_red_forest",
"jupiter",
"pripyat",
"zaton",
"l13_generators",
"l12_stancia_2",
"l12_stancia",
"l11_pripyat",
"l10_radar",
}
sim_stalkers = nil
function prefetch_sim_stalkers()
sim_stalkers = {}
for i = 1, 65534 do
local se_obj = alife_object(i)
if
se_obj
and (IsStalker(nil,se_obj:clsid()) and se_obj:alive() and string.find(se_obj:section_name(),"sim_default") and get_object_story_id(id) == nil)
and (se_obj.group_id ~= 65535 and get_object_story_id(se_obj.group_id) == nil)
then
local comm = alife_character_community(se_obj)
if not sim_stalkers[comm] then
sim_stalkers[comm] = {}
end
table.insert(sim_stalkers[comm], se_obj.id)
end
end
end
function find_random_stalker(factions, maps)
local limit = 60
-- Check 60 random stalkers at most and make it completely random
for i = 1, limit do
local faction = factions[math.random(1, #factions)]
local faction_stalkers = sim_stalkers[faction]
-- It might happen that there's no stalker of a given faction on the map and the entry for that faction won't be created
if faction_stalkers then
local stalker_id = faction_stalkers[math.random(1, #faction_stalkers)]
local se_obj = alife_object(stalker_id)
if se_obj then
local level = get_object_level_id(se_obj)
if
(not maps or has_value(maps, level))
and IsStalker(nil,se_obj:clsid()) and se_obj:alive() and alife_character_community(se_obj) == faction
then
return {
id = stalker_id,
level = level,
faction = faction,
name = se_obj:character_name()
}
end
end
end
end
end
function get_object_level_id(se_obj)
local gg = game_graph()
local sim = alife()
return sim:level_name(gg:vertex(se_obj.m_game_vertex_id):level_id())
end
local earthquake_cam_eff = 3
function earthquake_screen_effect_gradual(duration_multiplier)
local phase_duration_multiplier = duration_multiplier or 2
local effector_names = {
"camera_effects\\earthquake_20.anm",
"camera_effects\\earthquake_40.anm",
"camera_effects\\earthquake_60.anm",
"camera_effects\\earthquake_80.anm",
"camera_effects\\earthquake.anm",
"camera_effects\\earthquake_80.anm",
"camera_effects\\earthquake_60.anm",
"camera_effects\\earthquake_40.anm",
"camera_effects\\earthquake_20.anm"
}
for index, name in ipairs(effector_names) do
CreateTimeEvent(0,"nta_earthquake_screen_" .. index, (index - 1) * phase_duration_multiplier, function ()
level.remove_cam_effector(earthquake_cam_eff)
level.add_cam_effector(name, earthquake_cam_eff, true, "", 0, false)
return true
end)
end
CreateTimeEvent(0,"nta_earthquake_screen_remove", #effector_names * phase_duration_multiplier, function ()
level.remove_cam_effector(earthquake_cam_eff)
return true
end)
end
function earthquake_screen_effect_strong(duration)
level.add_cam_effector("camera_effects\\earthquake.anm", earthquake_cam_eff, true, "", 0, false)
CreateTimeEvent(0,"nta_earthquake_screen_remove", duration or 6, function ()
level.remove_cam_effector(earthquake_cam_eff)
return true
end)
end
function actor_in_range(vector, dist)
return db.actor:position():distance_to(vector) < dist
end
function actor_icon()
return db.actor:character_icon()
end
function actor_name()
return db.actor:character_name()
end
function obj_position_to_spawn_config_partial(obj)
return {
vector = obj:position(),
lvid = obj:level_vertex_id(),
gvid = obj:game_vertex_id()
}
end
levels = {
swamp = "k00_marsh",
darkscape = "k01_darkscape",
truck_cemetery = "k02_trucks_cemetery",
cordon = "l01_escape",
garbage = "l02_garbage",
agroprom = "l03_agroprom",
dark_valley = "l04_darkvalley",
wild_territory = "l06_rostok",
army_warehouses = "l07_military",
yantar = "l08_yantar",
dead_city = "l09_deadcity",
meadow = "y04_pole",
x16 = 'l08u_brainlab',
x18 = 'l04u_labx18',
red_forest = 'l10_red_forest',
outskirts = 'pripyat'
}
-- TODO: Remove separate functions from task files and use this one instead
function actor_on_level(lvl)
return level.name() == lvl
end
local function load_defaults()
local t = {}
local op = new_tasks_addon_mcm.op
for _, v in ipairs(op.gr) do
if v.def ~= nil then
t[v.id] = v.def
end
end
return t
end
mcm_config = load_defaults()
local function load_settings()
mcm_config = load_defaults()
if ui_mcm then
for k, v in pairs(mcm_config) do
mcm_config[k] = ui_mcm.get("new_tasks_addon/" .. k)
end
end
end
xr_effects.dispatch_nta_task_details = function(actor, npc, p)
CreateTimeEvent(0,"nta_task_details",0, function ()
local task_id = p[1]
-- Build News
local news_caption = game.translate_string(task_manager.task_ini:r_string_ex(task_id, "title")) or "error"
local news_text = game.translate_string(task_manager.task_ini:r_string_ex(task_id, "nta_task_details")) or ""
local news_ico = task_manager.task_ini:r_string_ex(task_id, "icon")
db.actor:give_talk_message2(news_caption, news_text, news_ico, "iconed_answer_item")
return true
end)
end
xr_conditions.check_nta_replayability = function(actor, npc, p)
local task_id = p[1]
if not db.actor:has_info(task_id .. '_completed') then
return true
else
return mcm_config["repl_" .. task_id]
end
end
function check_nta_auto_assignment(task_id)
return mcm_config["auto_assignment_" .. task_id]
end
function actor_on_first_update()
prefetch_sim_stalkers()
end
add_console_command("chopper", function()
se_id = spawn_helicopter(true, vector():set(-178.07975769043,5.3180623054504,-181.78283691406))
end)
function change_level(configs)
change_level_now(configs.vector, configs.lvid, configs.gvid, configs.angle or vector():set(0, 0, 0))
end
function on_game_start()
RegisterScriptCallback("on_game_load", load_settings)
RegisterScriptCallback("on_option_change", load_settings)
RegisterScriptCallback("actor_on_first_update",actor_on_first_update)
end