Divergent/mods/Neutral Zone/gamedata/scripts/z_neutral_zone.script

238 lines
7.0 KiB
Plaintext
Raw Permalink Normal View History

2024-03-17 20:18:03 -04:00
--[[
=====================================================================
Addon : Neutral Zone
Link : https://www.moddb.com/mods/stalker-anomaly/addons/neutral-zone
Author : party_50
Date : 07.02.2024
Last Edit : 09.02.2024
=====================================================================
--]]
local NEUTRAL_ZONES = {}
local warning_sent = {}
local crime_timer = {}
local warning_timer = 0
function on_option_change()
NEUTRAL_ZONES = {}
if z_neutral_zone_mcm.get_config("yantar_bunker") then
table.insert(NEUTRAL_ZONES, {
level_name = "l08_yantar",
smart_name = "yan_smart_terrain_6_4",
radius = 100,
faction = "ecolog",
cooldown = 8,
warn = true,
warn_sender = "yan_stalker_sakharov",
warn_text = "st_yan_sakharov_neutral_zone_warning"
})
end
if z_neutral_zone_mcm.get_config("jupiter_bunker") then
table.insert(NEUTRAL_ZONES, {
level_name = "jupiter",
smart_name = "jup_b41",
radius = 50,
faction = "ecolog",
cooldown = 8
})
end
if z_neutral_zone_mcm.get_config("rostok") then
table.insert(NEUTRAL_ZONES, {
level_name = "l05_bar",
smart_name = "bar_dolg_bunker",
radius = 160,
faction = "dolg",
cooldown = 8,
warn = true,
warn_sender = "bar_duty_security_squad_leader",
warn_text = "st_bar_duty_neutral_zone_warning"
})
end
if z_neutral_zone_mcm.get_config("yanov") then
table.insert(NEUTRAL_ZONES, {
level_name = "jupiter",
smart_name = "jup_a6",
radius = 50,
faction = "freedom",
cooldown = 8
})
end
end
function are_npc_enemies_to_faction(npc1, npc2, faction)
return game_relations.is_factions_enemies(character_community(npc1), faction)
or game_relations.is_factions_enemies(character_community(npc2), faction)
end
function are_npc_within_neutral_zone(npc1, npc2, zone)
local smart = SIMBOARD.smarts_by_names[zone.smart_name]
local npc1_dist = smart.position:distance_to(npc1:position());
local npc2_dist = smart.position:distance_to(npc2:position());
return npc1_dist < zone.radius or npc2_dist < zone.radius
end
function npc_on_before_hit(npc, shit, bone_id, flags)
if shit.draftsman:id() ~= db.actor:id() then
return
end
if character_community(npc) == "arena_enemy" then
return
end
for _, zone in ipairs(NEUTRAL_ZONES) do
if level.name() ~= zone.level_name then
goto continue
end
if are_npc_enemies_to_faction(npc, shit.draftsman, zone.faction) then
goto continue
end
if are_npc_within_neutral_zone(npc, shit.draftsman, zone) then
crime_timer[zone.smart_name] = game.get_game_time()
end
::continue::
end
end
function on_enemy_eval(obj, enemy, flags)
if character_community(obj) == "arena_enemy" then
return
end
for _, zone in ipairs(NEUTRAL_ZONES) do
if level.name() ~= zone.level_name then
goto continue
end
if are_npc_enemies_to_faction(obj, enemy, zone.faction) then
goto continue
end
if enemy:id() == db.actor:id() and crime_timer[zone.smart_name] then
if game.get_game_time():diffSec(crime_timer[zone.smart_name]) < 60 * 60 * zone.cooldown then
if are_npc_within_neutral_zone(obj, enemy, zone) then
crime_timer[zone.smart_name] = game.get_game_time()
end
goto continue
else
crime_timer[zone.smart_name] = nil
end
end
if are_npc_within_neutral_zone(obj, enemy, zone) then
flags.override = true
flags.result = false
end
::continue::
end
end
gameplay_disguise.expose_actor = function(npc, comm, is_enem)
gameplay_disguise.set_msg("st_disguse_actor_exposed",gameplay_disguise.default_comm)
gameplay_disguise.set_comm(gameplay_disguise.default_comm)
-- News
if npc and (not gameplay_disguise.inside_disguise_zone()) then
local str = ""
local flags = {}
on_enemy_eval(npc, db.actor, flags)
if is_enem and flags.result ~= false then
str = "st_news_disguse_enemy_expose_"
else
str = "st_news_disguse_natural_expose_"
if (comm ~= gameplay_disguise.default_comm) then
if (ui_options.get("alife/general/dynamic_relations") == true)
and (not game_relations.is_faction_unaffected(comm))
and (not game_relations.is_faction_unaffected(gameplay_disguise.default_comm))
and (not game_relations.is_faction_pair_unaffected(comm, gameplay_disguise.default_comm))
then
game_relations.change_faction_relations(comm, gameplay_disguise.default_comm, gameplay_disguise.relation_hit)
end
game_relations.change_factions_community_num(comm, gameplay_disguise.default_comm, gameplay_disguise.goodwill_hit)
game_statistics.increment_reputation(gameplay_disguise.reputation_hit)
end
end
local msg = game.translate_string(str .. tostring(math.random(1,4)))
local comm_name = ", " .. game.translate_string("st_dyn_news_comm_" .. comm .. "_6")
local se = strformat("%s%s", npc:character_name(), string.find(comm_name,"_6") and comm_name or "")
dynamic_news_helper.send_tip(msg,se,2,nil,npc:character_icon(),nil,"npc")
end
-- long-term memory
for k,v in pairs(gameplay_disguise.npcs_memory) do
if v then
v.memo = v.memo * gameplay_disguise.memory_multi
end
end
gameplay_disguise.is_disguised = nil
end
function send_warning(sender, text)
local se_npc = get_story_se_object(sender)
if se_npc and se_npc:alive() then
local msg = game.translate_string(text)
dynamic_news_helper.send_tip(msg, se_npc:character_name(), 0, 10, se_npc:character_icon(), "news", "npc")
end
end
function actor_on_update()
local tg = time_global()
if warning_timer > tg then
return
end
warning_timer = tg + 1000
-- Following code is executed once per second
for _, zone in ipairs(NEUTRAL_ZONES) do
if level.name() ~= zone.level_name then
goto continue
end
if warning_sent[zone.smart_name] or not zone.warn then
goto continue
end
local smart = SIMBOARD.smarts_by_names[zone.smart_name]
local dist = smart.position:distance_to(db.actor:position())
if dist > zone.radius and dist < zone.radius + 50 then
local actor_community = character_community(db.actor)
if not game_relations.is_factions_enemies(actor_community, zone.faction) and actor_community ~= "actor_" .. zone.faction then
send_warning(zone.warn_sender, zone.warn_text)
end
warning_sent[zone.smart_name] = true
elseif dist < zone.radius then
warning_sent[zone.smart_name] = true
end
::continue::
end
end
function save_state(m_data)
m_data.neutral_zone_warning_sent = warning_sent
m_data.neutral_zone_crime_timer = crime_timer
end
function load_state(m_data)
warning_sent = type(m_data.neutral_zone_warning_sent) == "table" and m_data.neutral_zone_warning_sent or {}
crime_timer = type(m_data.neutral_zone_crime_timer) == "table" and m_data.neutral_zone_crime_timer or {}
end
function on_game_start()
on_option_change()
RegisterScriptCallback("on_option_change", on_option_change)
RegisterScriptCallback("npc_on_before_hit", npc_on_before_hit)
RegisterScriptCallback("on_enemy_eval", on_enemy_eval)
RegisterScriptCallback("actor_on_update", actor_on_update)
RegisterScriptCallback("save_state", save_state)
RegisterScriptCallback("load_state", load_state)
end