Divergent/mods/Ultimate Dialogue Expansion/gamedata/scripts/dynamic_news_manager.script

2911 lines
96 KiB
Plaintext

--[[
> Dynamic News by ARS Team, xStream, Red75, Dexxx, Skunk, Xmk
> Re-vamped by Alundaio for Call of Chernobyl
> Re-vamped by First_Lieutenant_Skelja, senyaGTA, Letozz, Skeli, VanoSanturi, SashaRad, RadioactiveToilet for MLR 8.3
> Re-vamped by Tronex for Call of Chernobyl, Call of Misery, Last Day, Anomaly, Dead Air. Last edit (2018/8/3)
--]]
------------------------------------------------------------
-- Control
------------------------------------------------------------
enable_news = true -- useful for pausing news if set to false
local TimeFactor = 1 -- don't touch
local shw_death_stalker, shw_death_mutant, shw_death_generic, shw_kill_wounded, shw_death_report, shw_found_artifact, shw_heli_call, shw_loot, shw_stash
local shw_reaction
local shw_weather, shw_time, shw_nearby_activity, shw_zombie
local shw_bounty
local shw_random_msg, shw_factions_report, shw_zone_activity, shw_found_dead, shw_surge
local shw_companions
local cycle_TickSpecial, cycle_TickRandom, cycle_TickCompanion, cycle_TickTask = 120,120,120,150
local msg_duration
local SOS_offline_time
local SOS_offline_period = 60*4
local SOS_warfare_cap_time
local SOS_warfare_cap_period = 60*2
local story_LL_trigger, story_MS_trigger = true, true
function update_settings()
shw_death_stalker = ui_options.get("alife/dynamic_news/death_stalker_news")
shw_death_mutant = ui_options.get("alife/dynamic_news/death_mutant_news")
shw_death_generic = ui_options.get("alife/dynamic_news/generic_death_news")
shw_death_report = ui_options.get("alife/dynamic_news/death_report_news")
shw_kill_wounded = ui_options.get("alife/dynamic_news/kill_wounded_news")
shw_found_artifact = ui_options.get("alife/dynamic_news/found_artifact_news")
shw_heli_call = ui_options.get("alife/dynamic_news/heli_call_news")
shw_loot = ui_options.get("alife/dynamic_news/loot_news")
shw_stash = false
shw_reaction = ui_options.get("alife/dynamic_news/reaction_news")
shw_weather = ui_options.get("alife/dynamic_news/weather_news")
shw_time = ui_options.get("alife/dynamic_news/time_news")
shw_nearby_activity = ui_options.get("alife/dynamic_news/nearby_activity_news")
shw_zombie = ui_options.get("alife/dynamic_news/dumb_zombie_news")
shw_bounty = ui_options.get("alife/dynamic_news/bounty_news")
shw_random_msg = ui_options.get("alife/dynamic_news/random_msg_news")
shw_factions_report = ui_options.get("alife/dynamic_news/factions_report_news")
shw_zone_activity = ui_options.get("alife/dynamic_news/zone_activity_news")
shw_found_dead = ui_options.get("alife/dynamic_news/found_dead_news")
shw_surge = ui_options.get("alife/dynamic_news/surge_news")
shw_companions = ui_options.get("alife/dynamic_news/companions_news")
cycle_TickSpecial = ui_options.get("alife/dynamic_news/cycle_of_special_news") -- Time range: (value + 1) to (value x 2 + 1)
cycle_TickTask = ui_options.get("alife/dynamic_news/cycle_of_task_news") -- Time range: (value + 1) to (value x 2 + 1)
cycle_TickRandom = ui_options.get("alife/dynamic_news/cycle_of_random_news") -- Time range: (value + 1) to (value x 2 + 1)
cycle_TickCompanion = ui_options.get("alife/dynamic_news/cycle_of_companions_news") -- Time range: (value + 1) to (value x 2 + 1)
msg_duration = ui_options.get("alife/dynamic_news/message_duration")
if (level.present()) then
ResetTimeEvent("DynamicNewsManager","TickSpecial",math.random(cycle_TickSpecial + 1, cycle_TickSpecial*2 + 1))
ResetTimeEvent("DynamicNewsManager","TickTask",math.random(cycle_TickTask + 1, cycle_TickTask*2 + 1))
ResetTimeEvent("DynamicNewsManager","TickRandom",math.random(cycle_TickRandom + 1, cycle_TickRandom*2 + 1))
ResetTimeEvent("DynamicNewsManager","TickCompanion",math.random(cycle_TickCompanion + 1, cycle_TickCompanion*2 + 1))
end
end
------------------------------------------------------------
-- Preparing / Delay
------------------------------------------------------------
local delay = nil
local delay_start = nil
local instance = nil -- don't touch
function get_dynamic_news()
instance = instance or DynamicNewsManager()
return instance
end
function destroy_dynamic_news()
if (instance) then
instance:destroy()
end
instance = nil
end
function actor_on_first_update()
delay = delay or time_global() + 7500
end
function actor_on_update()
if (delay and delay <= time_global()) then
if (not delay_start) then
delay_start = time_global() + 20000
elseif (delay_start and delay_start <= time_global()) then
UnregisterScriptCallback("actor_on_first_update", actor_on_first_update)
UnregisterScriptCallback("actor_on_update", actor_on_update)
get_dynamic_news()
update_settings()
-- DRX Questlines trigger, runs once
if (not has_alife_info("drx_sl_start_news")) and IsStoryMode() then
get_dynamic_news():GossipTaskDRX()
db.actor:give_info_portion("drx_sl_start_news")
end
end
end
end
function on_game_start()
destroy_dynamic_news()
local function on_game_load()
TimeFactor = level.get_time_factor()
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
RegisterScriptCallback("actor_on_update", actor_on_update)
end
RegisterScriptCallback("on_game_load",on_game_load)
RegisterScriptCallback("on_option_change",update_settings)
end
--=========================================================================
--///////////////////////////// Dynamic News //////////////////////////////
--=========================================================================
class "DynamicNewsManager"
function DynamicNewsManager:__init()
-- Get player's faction
local comm = get_actor_true_community()
self.channel_status = {
["general"] = true,
["stalker"] = true,
["monolith"] = (comm == "monolith"),
["csky"] = true,
["army"] = (comm == "army"),
["killer"] = true,
["ecolog"] = true,
["dolg"] = true,
["freedom"] = true,
["bandit"] = true,
["greh"] = (comm == "greh"),
["isg"] = (comm == "isg"),
["renegade"] = true,
["greh_npc"] = true,
["army_npc"] = true,
}
self.queue = {
["general"] = {},
["stalker"] = {},
["monolith"] = {},
["csky"] = {},
["army"] = {},
["killer"] = {},
["ecolog"] = {},
["dolg"] = {},
["freedom"] = {},
["bandit"] = {},
["greh"] = {},
["isg"] = {},
["renegade"] = {},
["greh_npc"] = {},
["army_npc"] = {}
}
-- serious factions, no spam news
self.mono = {
["army_npc"] = true,
["greh_npc"] = true,
["greh"] = true,
["isg"] = true,
["trader"] = true,
["monolith"] = true,
}
-- mysterious factions, their identity is not known to stalkers
self.unknown = {
["isg"] = true,
}
self.response = {
["type"] = false,
["who"] = false,
["message"] = false
}
self.spammer = {
["show_about_death"] = 0,
["show_about_kill_wounded"] = 0,
["show_about_death_mutant"] = 0,
["show_about_death_response"] = 0,
["show_about_loot"] = 0
}
self.counter = 0
self.max_cnt = 3 -- don't allow more than 3 messages in channels
self.loot = {}
self.companions_list = dynamic_news_helper.list_actor_squad_by_id()
self.news_toggle = xr_conditions.surge_complete()
self.surge_shift = not xr_conditions.surge_started()
self.surge_type = ""
self.sentences_fnames = utils_data.collect_translations("name_stalker_",true)
self.sentences_snames = utils_data.collect_translations("lname_private_",true)
CreateTimeEvent("DynamicNewsManager","TickNews",10,self.TickNews,self)
CreateTimeEvent("DynamicNewsManager","TickQuick",10,self.TickQuick,self)
CreateTimeEvent("DynamicNewsManager","TickSpecial",10,self.TickSpecial,self)
CreateTimeEvent("DynamicNewsManager","TickTask",10,self.TickTask,self)
CreateTimeEvent("DynamicNewsManager","TickRandom",10,self.TickRandom,self)
CreateTimeEvent("DynamicNewsManager","TickCompanion",10,self.TickCompanion,self)
RegisterScriptCallback("monster_on_death_callback",self)
--RegisterScriptCallback("monster_on_net_spawn",self)
RegisterScriptCallback("npc_on_death_callback",self)
--RegisterScriptCallback("npc_on_hear_callback",self)
RegisterScriptCallback("npc_on_get_all_from_corpse",self)
end
function DynamicNewsManager:destroy()
RemoveTimeEvent("DynamicNewsManager","TickNews")
RemoveTimeEvent("DynamicNewsManager","TickQuick")
RemoveTimeEvent("DynamicNewsManager","TickSpecial")
RemoveTimeEvent("DynamicNewsManager","TickTask")
RemoveTimeEvent("DynamicNewsManager","TickRandom")
RemoveTimeEvent("DynamicNewsManager","TickCompanion")
UnregisterScriptCallback("monster_on_death_callback",self)
--UnregisterScriptCallback("monster_on_net_spawn",self)
UnregisterScriptCallback("npc_on_death_callback",self)
--UnregisterScriptCallback("npc_on_hear_callback",self)
UnregisterScriptCallback("npc_on_get_all_from_corpse",self)
end
function DynamicNewsManager:TickNews()
if (enable_news == false) then
return true
end
ResetTimeEvent("DynamicNewsManager","TickNews",math.random(5,20)) -- reset the timer, the function will get called again after 5 ~ 20 sec
--printf(">>> Dyn News: TickNews call")
-- news state check
if self:NewsToggle() or (not item_device.is_pda_charged(true)) then
return false
end
-- sending news
self.counter = self.counter - 1
if (self.counter < 0) then
self.counter = 0
end
for ch,messages in pairs(self.queue) do
local c = #messages
local message = messages[c]
if (message) then
dynamic_news_helper.send_tip(message.Mg,message.Se, message.Dl, msg_duration,message.Ic,message.Snd,message.It) -- send the news
-- Prepare proper reaction
if message.Ty then -- if a (type) exists, send reaction message
self.response["type"] = message.Ty
if message.Id then
self.response["who"] = message.Id
end
ResetTimeEvent("DynamicNewsManager","TickQuick",math.random(5,6))
end
messages[c] = nil -- dump the message
return false
end
end
return false
end
function DynamicNewsManager:TickQuick()
if (enable_news == false) then
return true
end
ResetTimeEvent("DynamicNewsManager","TickQuick",3600)
--printf(">>> Dyn News: TickQuick call")
-- news state check
if self:NewsToggle() or (not item_device.is_pda_charged(true)) then
return false
end
-- pick news
if (self.response["type"] == "artifact") and (self.response["who"]) and (shw_reaction) then
if (math.random(100) < 70) then
self:ResponseOnFoundArtefact(self.response["who"])
end
elseif (self.response["type"] == "trade") and (self.response["who"]) and (shw_reaction) then
if (math.random(100) < 70) then
self:ResponseOnBoughtItems(self.response["who"])
end
elseif (self.response["type"] == "loot") and (self.response["who"]) and (#self.loot > 0) then
self:GossipLoot(self.response["who"],self:GetLootBestItem(self.loot),self:GetLootValue(self.loot))
local c = #self.loot
if (c > 0) then
for i=1,c do
self.loot[i] = nil
end
end
elseif (self.response["type"]) and (string.find(self.response["type"], "enemy_activity_")) and (self.response["who"]) and (shw_reaction) then
if (math.random(100) < 70) then
self:ResponseOnGossipNearbyActivity(self.response["who"],self.response["type"])
end
elseif (self.response["type"] == "found_stash") and (shw_reaction) then
if (math.random(100) < 60) then
self:ResponseOnFoundStash()
end
elseif (self.response["type"] == "dumb_zombie") and (shw_reaction) then
if (math.random(100) < 70) then
self:ResponseOnDumbZombie()
end
elseif (self.response["type"] == "death_by_stalker") and (shw_reaction) then
local l = math.random(100)
if (l < 45) then -- %45 chance
if (self.response["who"]) then
self:ResponseOnDeathByStalker(self.response["who"])
end
elseif (l > 60) then -- %40 chance
self:ResponseOnDeathByStalker_Fake()
end
elseif (self.response["type"] == "death_by_mutant") and (shw_reaction) then
local l = math.random(100)
if (l < 45) then
if (self.response["who"]) then
self:ResponseOnDeathByMutant(self.response["who"])
end
elseif (l > 60) then
self:ResponseOnDeathByMutant_Fake()
end
elseif (self.response["type"] == "death_by_surge") and (shw_reaction) then
--if math.random(2) == 1 then -- %50 chance
--if (self.response["who"]) then
--self:ResponseOnDeathBySurges(self.response["who"])
--end
--else
self:ResponseOnDeathBySurges_Fake()
--end
end
-- send news
local message = self.response["message"]
if (message) then
dynamic_news_helper.send_tip(message.Mg, message.Se, message.To, message.St, message.Ic, message.Snd, message.It) -- (message,name,nil,nil,faction (default),sound,icon (use default icon))
end
-- reset
self.response["type"] = false
self.response["who"] = false
self.response["message"] = false
return false
end
function DynamicNewsManager:TickSpecial()
if (enable_news == false) then
return true
end
ResetTimeEvent("DynamicNewsManager","TickSpecial",math.random(cycle_TickSpecial + 1, cycle_TickSpecial*2 + 1))
--printf(">>> Dyn News: TickSpecial call - time cycle: " .. cycle_TickSpecial)
-- news state check
if self:NewsToggle() or (not item_device.is_pda_charged(true)) then
return false
end
-- pick news
local pick_tbl = {
shw_weather, shw_time, shw_nearby_activity, shw_zombie,
shw_broadcast_distress, shw_start_conversation, shw_faction_propaganda,
shw_survivor_checkin, shw_contraband_alert, shw_technical_advice,
shw_cryptid_sighting, shw_creepypasta_horror
}
local picked_tbl = {}
for i=1,#pick_tbl do
if (pick_tbl[i] == true) then
table.insert(picked_tbl, i)
end
end
if #picked_tbl == 0 then
return false
end
local pick = picked_tbl[math.random(#picked_tbl)]
if (pick == 1) then
self:GossipWeather()
elseif (pick == 2) then
self:GossipTime()
elseif (pick == 3) then
self:GossipNearbyActivity()
elseif (pick == 4) then
self:DumbZombie()
end
return false
end
function DynamicNewsManager:TickTask()
if (enable_news == false) then
return true
end
ResetTimeEvent("DynamicNewsManager","TickTask",math.random(cycle_TickTask + 1, cycle_TickTask*2 + 1))
--printf(">>> Dyn News: TickTask call - time cycle: " .. cycle_TickSpecial)
-- news state check
if self:NewsToggle() or (not item_device.is_pda_charged(true)) then
return false
end
if (shw_bounty) then
if (sim_squad_bounty.check_close_squads()) then
self:GossipAlphaSquad()
else
self:GossipBounty()
end
end
if IsStoryMode() and IsStoryPlayer() then
if (not has_alife_info("living_legend")) and story_LL_trigger then
self:GossipTaskLL()
elseif (not has_alife_info("mortal_sin")) and has_alife_info("living_legend_done") and story_MS_trigger then
self:GossipTaskMS()
elseif (not has_alife_info("operation_afterglow_info_about_done")) and has_alife_info("mortal_sin_zone_hero") then
self:GossipTaskOA()
db.actor:give_info_portion("operation_afterglow_info_about_done")
elseif (has_alife_info("operation_afterglow_transmission_report")) and (not has_alife_info("lttz_oa_army_degtyarev_jup_meet_msg")) then
local Ico = "ui_inGame2_Hero"
local Se = game.translate_string("army_degtyarev_jup_name")
local player_name = alife():actor():character_name()
local msg = game.translate_string("st_lttz_oa_army_degtyarev_jup_meet_msg")
msg = strformat(msg, player_name, Se)
dynamic_news_helper.send_tip(msg, Se, math.random(10,20), 20, Ico, "news", "npc")
db.actor:give_info_portion("lttz_oa_army_degtyarev_jup_meet_msg")
elseif (not has_alife_info("unlock_x18")) and has_alife_info("lttz_oa_loose_ends_done") then
self:GossipTaskDP()
end
end
return false
end
function DynamicNewsManager:TickRandom()
if (enable_news == false) then
return true
end
ResetTimeEvent("DynamicNewsManager","TickRandom",math.random(cycle_TickRandom + 1, cycle_TickRandom*2 + 1))
--printf(">>> Dyn News: TickRandom call - time cycle: " .. cycle_TickRandom)
-- news state check
if self:NewsToggle() or (not item_device.is_pda_charged(true)) then
return false
end
-- pick news
local pick_tbl = {shw_surge, shw_factions_report, shw_zone_activity, shw_found_dead, shw_random_msg}
local picked_tbl = {}
for i=1,#pick_tbl do
if (pick_tbl[i] == true) then
table.insert(picked_tbl, i)
end
end
if #picked_tbl == 0 then
return false
end
local pick = picked_tbl[math.random(#picked_tbl)]
if (pick == 1) then
self:ReportNextEmission()
elseif (pick == 2) then
self:ReportByFaction()
elseif (pick == 3) then
self:ReportZoneActivity()
elseif (pick == 4) then
self:FoundDead()
elseif (pick == 5) then
self:SpamRandom()
elseif (pick == 6) then
end
return false
end
function DynamicNewsManager:TickCompanion()
if (enable_news == false) then
return true
end
if not shw_companions then
return true
end
ResetTimeEvent("DynamicNewsManager","TickCompanion",math.random(cycle_TickCompanion + 1, cycle_TickCompanion*2 + 1))
--printf(">>> Dyn News: TickCompanion call - time cycle: " .. cycle_TickCompanion)
-- news state check
if self:NewsToggle() or (not item_device.is_pda_charged(true)) then
return false
end
-- check new and older companions
local is_new, sender, st, npc
is_new = true
sender = self:PickNewCompanion()
if not sender then
is_new = false
sender = self:PickCompanion()
end
if (not sender) then
return false
end
-- pick news
if is_new then -- new companions news
self:CompanionAboutActor(sender)
elseif (sender:position():distance_to(db.actor:position()) < 15) and (not sender:best_enemy()) then -- companions news
if (math.random(3) == 2) then -- %30
self:CompanionAboutLevel(sender)
else
self:CompanionAboutLife(sender)
end
end
return false
end
------------------------------------------------------------
-- Callbacks
------------------------------------------------------------
function DynamicNewsManager:monster_on_net_spawn(npc,se_obj)
end
function DynamicNewsManager:monster_on_death_callback(victim,who)
--printf(">>> Dyn News: monster_on_death_callback callback")
if not (who and IsStalker(who) and shw_death_mutant) then -- if the killer is unknown, go back
return
end
local say = false
if (self.spammer.show_about_death_mutant == 0) then
local l = math.random(1,2) -- %50 chance
if l == 1 then
say = self:GossipDeathOfMutant(victim,who)
elseif l == 2 then
say = self:SeenDeathOfMutant(victim,who)
end
end
if (say) then
self.spammer.show_about_death_mutant = self.spammer.show_about_death_mutant + 1
if (self.spammer.show_about_death_mutant > 3) then
self.spammer.show_about_death_mutant = 0
end
end
end
function DynamicNewsManager:npc_on_death_callback(victim,who)
--printf(">>> Dyn News: npc_on_death_callback callback")
if not (db.actor and victim) then
return
end
-- don't show victim info of private faction if actor is not one of them (SOS will be affected)
local comm = character_community(victim)
if not (self.channel_status[comm]) then
return
end
-- don't show killer info if he's from a mysterious faction
if self:IsUnknownCommunity(who) then
return
end
if not (who and who.clsid) then
if (shw_death_generic and surge_manager.is_killing_all()) then
self:DeathBySurge(victim,who,comm)
end
return
end
if (shw_death_report) and (self.spammer.show_about_death_response == 1) then
if IsStalker(who) then
self:ReportDeathByStalker(victim,who)
elseif IsMonster(who) then
self:ReportDeathByMutant(victim,who)
end
end
local say = false
if (shw_death_stalker) and (self.spammer.show_about_death == 0) then
if IsStalker(who) then
say = self:SOSDeathByStalker(victim,who,comm)
if not (say) then -- if a stalker is NOT reporting on-going attack on him
local i = shw_death_generic and math.random(1,3)
if i == 1 then
self:DeathByStalker(victim,who,comm)
else
local sender = self:FindSpeaker(victim,who,false,nil,true)
if sender then
if sender:see(who) or sender:see(victim) then -- actually seeing
self:SeenDeathOfStalker(sender,victim,who,comm)
else
self:GossipDeathByStalker(sender,victim,who)
end
end
end
end
elseif IsMonster(who) then
say = self:SOSDeathByMutant(victim,who,comm)
if not (say) then
local i = shw_death_generic and math.random(1,2)
if i == 1 then
self:DeathByMutant(victim,who,comm)
else
local sender = self:FindSpeaker(victim,who,false,nil,true)
if sender and (sender:see(who) or sender:see(victim)) then
self:SeenDeathByMutant(sender,victim,who,comm)
end
end
end
end
end
-- reset
if (say) then
self.spammer.show_about_death = self.spammer.show_about_death + 1 -- 0,1,2,3,4
if (self.spammer.show_about_death > 3) then
self.spammer.show_about_death = 0
end
end
self.spammer.show_about_death_response = self.spammer.show_about_death_response + 1 --0,1,2
if (self.spammer.show_about_death_response > 2) then
self.spammer.show_about_death_response = 0
end
end
function DynamicNewsManager:npc_on_hear_callback(npc,who_id,s_type,sound_dist,sound_power,sound_position)
end
function DynamicNewsManager:npc_on_get_all_from_corpse(npc,corpse_npc,item,lootable_table) -- The looter, the looted and the loot.
--printf(">>> Dyn News: npc_on_get_all_from_corpse callback")
if not (shw_loot and db.actor and npc and item) then
return
end
-- using reaction channel cause we want a single loot message per corpse.
table.insert(self.loot,item)
self.response["who"] = npc
self.response["type"] = "loot"
ResetTimeEvent("DynamicNewsManager","TickQuick",4)
end
------------------------------------------------------------
-- Utilities
------------------------------------------------------------
function DynamicNewsManager:PushToChannel(name,t,fifo) -- (name = faction , t = {message (translated), sender icon, news sound, name and faction of the sender, icon indicator (if its "npc" then use sender's icon), Type of news, Id of sender} , fifo = not used)
--printf(">>> Dyn News: PushToChannel call")
-- news state check
if (not enable_news)
or self:NewsToggle() -- necessary to prevent news stacking after surges.
or (not item_device.is_pda_charged(true))
or (self.counter > self.max_cnt)
then
return false
end
local q = self.queue[name] -- load the faction table in queue table
if (q) then
if (t.Mg) then
for s in string.gmatch(t.Mg,"(st_dyn_news_ch_[%w%d_]*)") do
t.Mg = string.gsub(t.Mg,s,game.translate_string(s))
end
end
if (fifo) then
q[#q+1] = t
else
table.insert(q,1,t)
end
self.counter = self.counter + 1
end
end
function DynamicNewsManager:FindSpeakerNoVictim(who,same_as_who,not_in_combat) -- Find a speaker ( [game_object] the guy of interest | [boolean] if true, speaker must be from guy's community | [boolean] if true, speaker must not be in combat )
local comm_sender
local comm_who = who and character_community(who) or nil
local who_id = who and who:id() or nil
local t = {}
for i=1, #db.OnlineStalkers do
if (who_id == nil) or (db.OnlineStalkers[i] ~= who_id) then
local st = db.storage[db.OnlineStalkers[i]]
local npc = st and st.object or level.object_by_id(db.OnlineStalkers[i])
if (npc and IsStalker(npc,npc:clsid()) and npc:alive() and not get_object_story_id(db.OnlineStalkers[i])) then
if (not_in_combat == nil) or (not_in_combat == true and not npc:best_enemy()) or (not_in_combat ~= true) then
comm_sender = npc:character_community()
if (same_as_who == nil) or (comm_who == nil) or (same_as_who == true and comm_sender == comm_who) or (same_as_who == false and comm_sender ~= comm_who) then
if (self.channel_status[comm_sender]) then
t[#t+1] = npc
end
end
end
end
end
end
--printf(">>> Dyn News: FindSpeakerNoVictim pass - valid speakers: " .. #t)
if (#t == 0) then
return nil
end
return t[math.random(#t)]
end
function DynamicNewsManager:FindSpeaker(victim,who,same_as_victim,same_as_who,not_in_combat,can_see) -- Find a speaker ( [game_object] the victim | [game_object] the killer | [boolean] if true, speaker must be from victim's community | [boolean] if true, speaker must be from killer's community | [boolean] if true, speaker must not be in combat | [boolean] if true, speaker must see the victim )
local comm = character_community(victim)
local comm_sender
local comm_who = character_community(who)
local who_id = who:id()
local t = {}
for i=1, #db.OnlineStalkers do
if (db.OnlineStalkers[i] ~= who_id) then
local st = db.storage[db.OnlineStalkers[i]]
local npc = st and st.object
if (npc and IsStalker(npc,npc:clsid()) and npc:alive() and not get_object_story_id(db.OnlineStalkers[i])) then
if (not_in_combat == nil) or (not_in_combat == true and not npc:best_enemy()) or (not_in_combat ~= true) then
comm_sender = npc:character_community()
if (same_as_victim == nil) or (same_as_victim == true and comm_sender == comm) or (same_as_victim == false and comm_sender ~= comm) then
if (same_as_who == nil) or (same_as_who == true and comm_sender == comm_who) or (same_as_who == false and comm_sender ~= comm_who) then
if (self.channel_status[comm_sender]) then
if (can_see == nil) or (can_see and npc:see(victim)) or (can_see == false) then
t[#t+1] = npc
end
end
end
end
end
end
end
end
--printf(">>> Dyn News: FindSpeaker pass - valid speakers: " .. #t)
if (#t == 0) then
return nil
end
return t[math.random(#t)]
end
function DynamicNewsManager:FindSpeakerWithEnemy(victim,who,same_as_victim,same_as_who,can_see) -- Find a speaker under attack ( [game_object] the victim | [game_object] the killer | [boolean] if true, speaker must be from victim's community | [boolean] if true, speaker must be from killer's community | [boolean] if true, speaker must see the victim )
local comm = character_community(victim)
local comm_sender
local comm_who = character_community(who)
local who_id = who:id()
local t = {}
for i=1, #db.OnlineStalkers do
if (db.OnlineStalkers[i] ~= who_id) then
local st = db.storage[db.OnlineStalkers[i]]
local npc = st and st.object
if (npc and IsStalker(npc,npc:clsid()) and npc:alive() and not get_object_story_id(db.OnlineStalkers[i]) and npc:best_enemy()) then
comm_sender = npc:character_community()
if (same_as_victim == nil) or (same_as_victim == true and comm_sender == comm) or (same_as_victim == false and comm_sender ~= comm) then
if (same_as_who == nil) or (same_as_who == true and comm_sender == comm_who) or (same_as_who == false and comm_sender ~= comm_who) then
if (self.channel_status[comm_sender]) then
if (can_see == nil) or (can_see and npc:see(victim)) or (can_see == false) then
t[#t+1] = npc
end
end
end
end
end
end
end
--printf(">>> Dyn News: FindSpeakerWithEnemy pass - valid speakers: " .. #t)
if (#t == 0) then
return nil
end
return t[math.random(#t)]
end
function DynamicNewsManager:FindSpeakerRandom(not_in_combat, speaker_community, exclude_npc_id)
local t = {}
local origin_npc = db.storage[exclude_npc_id] and db.storage[exclude_npc_id].object or level.object_by_id(exclude_npc_id)
local origin_npc_name = origin_npc and origin_npc:character_name() or "Unknown"
for i=1, #db.OnlineStalkers do
local st = db.storage[db.OnlineStalkers[i]]
local npc = st and st.object or level.object_by_id(db.OnlineStalkers[i])
if npc and npc:id() ~= exclude_npc_id and not npc:best_enemy() and (speaker_community == nil or npc:character_community() == speaker_community) then
if not_in_combat and npc:best_enemy() then
-- Skip if the NPC is in combat
else
t[#t+1] = npc
end
end
end
if #t == 0 then
return nil, origin_npc_name -- Ensure we return 'Unknown' if no NPC found
end
return t[math.random(#t)], origin_npc_name -- Correctly return a random NPC and the origin NPC's name
end
function DynamicNewsManager:FindSpeakerAndTarget(not_in_combat,distance,speaker_community) -- Find a random speaker ([boolean] if true, speaker must not be in combat | [string] if declared, speaker must belong to this community)
local sender,target,comm_sender
local dis = distance or 300
local t1,t2 = {},{}
-- Find a sender
for i=1, #db.OnlineStalkers do
local st = db.storage[db.OnlineStalkers[i]]
local npc = st and st.object or level.object_by_id(db.OnlineStalkers[i])
if (npc and IsStalker(npc,npc:clsid()) and npc:alive() and not get_object_story_id(db.OnlineStalkers[i])) then
if (not_in_combat == nil) or (not_in_combat == true and not npc:best_enemy()) or (not_in_combat ~= true) then
if (speaker_community == nil) or (speaker_community and npc:character_community() == speaker_community) then
comm_sender = npc:character_community()
if (self.channel_status[comm_sender]) then
t1[#t1+1] = npc
end
end
end
end
end
if (#t1 == 0) then
return nil
end
sender = t1[math.random(#t1)]
if (not sender) then
return nil
end
-- Find an enemy to sender
local sender_pos = sender:position()
local sender_comm = sender:character_community()
local sim = alife()
local se_obj,clsid
for i=1,65534 do
se_obj = sim:object(i)
clsid = se_obj and se_obj:clsid()
if clsid then
-- Check if its enemy stalker or monester
if ( IsStalker(nil,clsid) and (se_obj:community() ~= "trader") and game_relations.is_factions_enemies(sender_comm, se_obj:community()) ) or (IsMonster(nil,clsid)) then
-- Check if its close to sender
if (se_obj.position:distance_to(sender_pos) < dis) and (se_obj.group_id ~= 65535) then
-- Check if its alive
if (se_obj:alive()) then
local st = db.storage[se_obj.id]
local npc = st and st.object or level.object_by_id(se_obj.id)
if npc then
t2[#t2+1] = npc
end
end
end
end
end
end
if (#t2 == 0) then
return nil
end
target = t2[math.random(#t2)]
--printf(">>> Dyn News: FindSpeakerAndTarget pass - valid speakers: " .. #t1 .. " - valid enemies to speaker: " .. #t2)
return sender,target
end
function DynamicNewsManager:FindSpeakerAnywhere(natural_only,faction) -- Find a random speaker ([boolean] if true, speaker must not be in combat | [string] if declared, speaker must belong to this community)
local t = {}
local size_t = 0
local sim = alife()
local act_comm = get_actor_true_community()
for i=1,65534 do
local se_obj = sim:object(i)
if (se_obj and se_obj.group_id ~= 65535) then
if IsStalker(nil,se_obj:clsid()) and se_obj:alive() and (se_obj:community() ~= "trader") then
local comm = se_obj:community()
if faction then
if (faction == comm) then
size_t = size_t + 1
t[size_t] = i
end
else
if natural_only then
if (not game_relations.is_factions_enemies(act_comm, comm)) then
size_t = size_t + 1
t[size_t] = i
end
else
size_t = size_t + 1
t[size_t] = i
end
end
end
end
end
return (size_t > 0) and t[math.random(size_t)] or nil
end
function DynamicNewsManager:IsCommunitySame(npc_1,npc_2) -- Check if both npcs are from the same factions
local comm_1 = npc_1:character_community()
if (npc_1:id() == AC_ID and comm_1 ~= "actor") then
comm_1 = comm_1:sub(7)
end
local comm_2 = npc_2:character_community()
if (npc_2:id() == AC_ID and comm_2 ~= "actor") then
comm_2 = comm_2:sub(7)
end
--printf(">>> Dyn News: IsCommunitySame | npc_1 community = " .. comm_1 .. " | npc_2 community = " .. comm_2)
return (comm_1 == comm_2)
end
function DynamicNewsManager:PickCompanion() -- pick a random companion
local npcs = dynamic_news_helper.list_actor_squad_by_id()
if #npcs == 0 then
return nil
end
local picked = npcs[math.random(#npcs)]
--printf(">>> Dyn News: help PickCompanion | #npcs = " .. #npcs)
return db.storage[picked] and db.storage[picked].object
end
function DynamicNewsManager:PickNewCompanion() -- pick a random "new" companion
local new_npcs = {}
local tbl_1 = dynamic_news_helper.list_actor_squad_by_id()
local tbl_2 = self.companions_list
local count = 1
local is_same = false
if (#tbl_1 == 0) then
return false
end
-- If there's new companions, put them in (new_npcs) table
for i=1,#tbl_1 do
if #tbl_2 > 0 then
for j=1,#tbl_2 do
if tbl_1[i] == tbl_2[j] then
is_same = true
break
end
end
end
if (not is_same) and tbl_1[i] then
new_npcs[count] = tbl_1[i]
count = count + 1
--printf(">>> Dyn News: help PickNewCompanion - found new companion!")
end
is_same = false
end
if (#new_npcs == 0) then
return false
end
-- If there's new companions, update the companions list
self.companions_list = dynamic_news_helper.list_actor_squad_by_id()
local picked = new_npcs[math.random(#new_npcs)]
--printf(">>> Dyn News: help PickNewCompanion | #new_npcs = " .. #new_npcs)
return db.storage[picked] and db.storage[picked].object
end
function DynamicNewsManager:GetLootValue(item_tbl) -- get value of whole loot
local value = 0
for i=1,#item_tbl do
value = value + item_tbl[i]:cost()
end
--printf(">>> Dyn News: help GetLootValue | value = " .. value)
return value
end
function DynamicNewsManager:GetLootBestItem(item_tbl) -- get value of best looted item
local value = 0
local best_item
for i=1,#item_tbl do
if item_tbl[i]:cost() > value then
value = item_tbl[i]:cost()
best_item = item_tbl[i]
end
end
--printf(">>> Dyn News: help GetLootBestItem | best item's value: " .. value)
return best_item
end
function DynamicNewsManager:NewsToggle() -- turn off news if there is an emission, or player is underground
--printf(">>> Dyn News: help NewsToggle - self.surge_shift = " .. tostring(self.surge_shift) .. " - self.news_toggle = " .. tostring(self.news_toggle))
-- necessary, otherwise the game will crash due to playing news sound before completely loading.
if device():is_paused() then
return true
end
-- disable news if player inside an invalid map.
if dynamic_news_helper.IsInvalidMap(level.name()) then
return true
end
-- welcome message on new game, run once
if (not has_alife_info("trx_dynamic_news_welcome_to_network")) then
self:WelcomeToNetwork()
db.actor:give_info_portion("trx_dynamic_news_welcome_to_network")
return true
end
local news_state = true
-- if a surge has started, or is underground ---> news go off, erase stored messages, set surge_type
if xr_conditions.surge_started() then
news_state = false
if surge_manager and surge_manager.is_started() then
self.surge_type = "emission"
elseif psi_storm_manager and psi_storm_manager.is_started() then
self.surge_type = "storm"
end
for ch,messages in pairs(self.queue) do
local c = #messages
while c > 0 do
local message = messages[c]
if (message) then
messages[c] = nil
end
c = c - 1
end
end
end
-- if surge started (even on load) ---> set up surge_type, otherwise if surge finished (even on load) ---> send 'surge end' news
if self.surge_shift and xr_conditions.surge_started() then
self.surge_shift = false
elseif (not self.surge_shift) and xr_conditions.surge_complete() then
self.surge_shift = true
self:GossipEmissionEnd(self.surge_type)
self:ReportDeathBySurge()
end
-- run once at each surge
if news_state == (not self.news_toggle) then
self.news_toggle = news_state
local Msg
local num = math.random(5,10)
local Se = game.translate_string("st_dyn_news_sender_com_centre")
if news_state then
Msg = game.translate_string("st_dyn_news_spc_commu_on")
dynamic_news_helper.send_tip(Msg,Se,num,msg_duration,"communication","welcome","gr")
else
Msg = game.translate_string("st_dyn_news_spc_commu_off")
dynamic_news_helper.send_tip(Msg,Se,num,msg_duration,"communication","communication_lost","gr")
end
end
return (not news_state)
end
------------------------------------------------------------
-- News
------------------------------------------------------------
function DynamicNewsManager:WelcomeToNetwork() -- Welcome message on new game
--printf(">>> Dyn News: WelcomeToNetwork - call")
local clr_1 = "%" .. "%c[255,160,160,190]"
local clr_2 = "%" .. "%c[255,220,220,220]"
-- Count the number of stalkers across the zone, except monolith and zombies
local c = 1
local sim = alife()
for i=1,65534 do
local se_obj = sim:object(i)
if (se_obj and IsStalker(nil,se_obj:clsid()) and se_obj:alive() and se_obj:community() ~= "zombied" and se_obj:community() ~= "monolith" and se_obj.group_id ~= 65535) then
c = c + 1
end
end
local se_actor = sim:actor()
local Se = game.translate_string("st_dyn_news_sender_com_centre")
local msg = utils_data.parse_string_keys( game.translate_string("st_dyn_news_welcome_stalker") , {["clr_1"]=clr_1 , ["clr_2"]=clr_2 , ["name"]=se_actor:character_name() , ["number"]=tostring(c)} )
dynamic_news_helper.send_tip(msg,Se, 0, 20,"communication","welcome","gr")
-- Reset
ResetTimeEvent("DynamicNewsManager","TickSpecial",math.random(cycle_TickSpecial + 1, cycle_TickSpecial*2 + 1))
ResetTimeEvent("DynamicNewsManager","TickTask",math.random(cycle_TickTask + 1, cycle_TickTask*2 + 1))
ResetTimeEvent("DynamicNewsManager","TickRandom",math.random(cycle_TickRandom + 1, cycle_TickRandom*2 + 1))
ResetTimeEvent("DynamicNewsManager","TickCompanion",math.random(cycle_TickCompanion + 1, cycle_TickCompanion*2 + 1))
end
--< Report News >--
function DynamicNewsManager:DeathBySurge(victim,who,comm) -- Death by blowouts reports
--printf(">>> Dyn News: DeathBySurge - call")
local msg = strformat("%c[255,160,160,160]%s, %s.\\n%c[default]st_dyn_news_ch_found %s. st_dyn_news_ch_blowout.",victim:character_name(),game.translate_string(comm),dynamic_news_helper.GetPointDescription(victim))
self:PushToChannel("general",{Mg=msg,Ic="deth",Snd="news",Se=game.translate_string("st_dyn_news_ch_died"),It="gr",Ty="death_by_surge",Id=victim})
return true
end
function DynamicNewsManager:ReportDeathBySurge() -- Report casualties of surges (fake)
--printf(">>> Dyn News: ReportDeathBySurge - call")
if (not shw_death_report) and ((not self.sentences_fnames) or (not self.sentences_fnames)) then
return false
end
local clr_1 = "%c[255,160,160,190]"
local clr_2 = "%c[255,220,220,220]"
local known_num = math.random (1,6)
local msg = clr_1 .. game.translate_string("st_dyn_news_death_by_surge_start") .. clr_2
local finish = utils_data.parse_string_keys( game.translate_string("st_dyn_news_death_by_surge_end") , { ["num"] = tostring(math.random(3,16)) } )
local a,b,c,y1,y2,z1,z2,z3
for i=1,known_num do
a = self.sentences_fnames[math.random(#self.sentences_fnames)]
b = self.sentences_snames[math.random(#self.sentences_snames)]
c = dynamic_news_helper.PickMap(level.name())
c = game.translate_string(c)
y1 = string.char(math.random(65,90))
y2 = string.char(math.random(65,90))
z1 = tostring(math.random(9))
z2 = tostring(math.random(9))
z3 = tostring(math.random(9))
msg = msg .. strformat("\\n%s-%s %s%s-%s%s%s, %s %s, %s.",clr_1,clr_2,y1,y2,z1,z2,z3,a,b,c)
end
local Se = game.translate_string("st_dyn_news_sender_obituary")
msg = msg .. "\\n" .. clr_1 .. finish
--dynamic_news_helper.send_tip(msg,Se,30,msg_duration,"death","beep_2","gr")
self:PushToChannel("general",{Mg=msg,Ic="death",Snd="beep_2",Se=Se,It="gr",Ty="death_by_surge",Dl=30})
-- special case for response message
self.response["type"] = "death_by_surge"
ResetTimeEvent("DynamicNewsManager","TickQuick",math.random(5,6))
return true
end
function DynamicNewsManager:DeathByStalker(victim,who,comm) -- Found dead stalker by stalker
--printf(">>> Dyn News: DeathByStalker - call")
local cls = dynamic_news_helper.GetWeaponClass(who)
if (cls == 1 or cls == 9) then
return false
end
local msg = strformat("%c[255,160,160,160]%s, %s.\\n%c[default]st_dyn_news_ch_found %s. %s.",victim:character_name(),game.translate_string(comm),dynamic_news_helper.GetPointDescription(victim),dynamic_news_helper.GetWeaponDescription(who,1))
self:PushToChannel("general",{Mg=msg,Ic="deth",Snd="news",Se=game.translate_string("st_dyn_news_ch_died"),It="gr",Ty="death_by_stalker",Id=victim})
return true
end
function DynamicNewsManager:ReportDeathByStalker(victim,who) -- Death Report of stalker killing stalker
--printf(">>> Dyn News: ReportDeathByStalker - call")
if self:IsCommunitySame(victim,who) then
return false
end
if self:IsUnknownCommunity(who) or self:IsUnknownCommunity(victim) then
return false
end
local clr_1 = "%" .. "%c[255,160,160,190]"
local clr_2 = "%" .. "%c[255,220,220,220]"
local a = game.translate_string(who:character_community())
local b = game.translate_string(victim:character_community())
local c = dynamic_news_helper.GetPointDescription(victim)
local who_name = who:character_name()
if (who:id() == AC_ID) then
local sim = alife()
local se_actor = sim:actor()
who_name = se_actor:character_name()
end
local Se = game.translate_string("st_dyn_news_sender_obituary")
local msg = utils_data.parse_string_keys( game.translate_string("st_dyn_news_spc_obituary_s") , {["clr_1"]=clr_1 , ["clr_2"]=clr_2 , ["who_name"]=who_name , ["who_comm"]=a , ["victim_name"]=victim:character_name() , ["victim_comm"]=b , ["where"]=c} )
self:PushToChannel("general",{Mg=msg,Ic="death",Snd="no_sound",Se=Se,It="gr",Ty="death_by_stalker",Id=victim})
return true
end
function DynamicNewsManager:DeathByMutant(victim,who,comm) -- Found dead stalker by mutant
--printf(">>> Dyn News: DeathByMutant - call")
local a = victim:character_name()
local b = game.translate_string(comm)
local c = dynamic_news_helper.GetPointDescription(victim)
local d
if (ini_sys:r_string_ex("string_table","language") == "rus") then
d = dynamic_news_helper.GetMonsterDescription(who,7)
else
d = string.gsub(dynamic_news_helper.GetMonsterDescription(who,1),"(%l)?",string.upper("%1"),1)
end
local msg = strformat("%c[255,160,160,160]%s, %s.\\n%c[default]st_dyn_news_ch_found %s. %s.",a,b,c,d)
self:PushToChannel("general",{Mg=msg,Ic="deth",Snd="news",Se=game.translate_string("st_dyn_news_ch_died"),It="gr",Ty="death_by_mutant",Id=victim})
return true
end
function DynamicNewsManager:ReportDeathByMutant(victim,who) -- Death Report by mutant killing stalker
--printf(">>> Dyn News: ReportDeathByMutant - call")
local clr_1 = "%" .. "%c[255,160,160,190]"
local clr_2 = "%" .. "%c[255,220,220,220]"
local a = string.gsub(dynamic_news_helper.GetMonsterDescription(who,1),"(%l)?",string.upper("%1"),1)
local b = game.translate_string(victim:character_community())
local c = dynamic_news_helper.GetPointDescription(victim)
local Se = game.translate_string("st_dyn_news_sender_obituary")
local msg = utils_data.parse_string_keys( game.translate_string("st_dyn_news_spc_obituary_m") , {["clr_1"]=clr_1 , ["clr_2"]=clr_2 , ["victim_name"]=victim:character_name() , ["victim_comm"]=b , ["who"]=a , ["where"]=c} )
self:PushToChannel("general",{Mg=msg,Ic="death",Snd="no_sound",Se=Se,It="gr",Ty="death_by_mutant",Id=victim})
return true
end
function DynamicNewsManager:GossipDeathByStalker(sender,victim,who) -- hearing stalker killing a stalker
--printf(">>> Dyn News: GossipDeathByStalker - call")
local cls = dynamic_news_helper.GetWeaponClass(who)
if (cls == 1 or cls == 9) then
return false
end
if self:IsCommunitySame(victim,who) then
return false
end
local sender = sender or self:FindSpeaker(victim,who,false,nil,true)
if self:IsSpecialNPC(sender) then
return false
end
local tbl_1 = utils_data.collect_translations("st_dyn_news_builder_hear_",true)
local tbl_2 = utils_data.collect_translations("st_dyn_news_builder_ending_",true)
if (not tbl_1) or (not tbl_2) then
return false
end
local a = tbl_1[math.random(#tbl_1)]
local b = dynamic_news_helper.GetWeaponDescription(who,2)
local c = dynamic_news_helper.GetPointDescription(victim)
local d = tbl_2[math.random(#tbl_2)]
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = strformat("%s %s %s. %s",a,b,c,d)
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:SOSDeathByStalker(victim,who,comm) -- stalker under stalkers attack
--printf(">>> Dyn News: SOSDeathByStalker - call")
local cls = dynamic_news_helper.GetWeaponClass(who)
if (cls == 1 or cls == 9) then
return false
end
if self:IsCommunitySame(victim,who) then
return false
end
local sender = self:FindSpeakerWithEnemy(victim,who,true,false)
if self:IsSpecialNPC(sender) then
return false
end
local a = dynamic_news_helper.GetCommunityDescription(sender,math.random(11,14))
local b,c = self:BuildSentenceStalkerEnemy(victim,who,0,30)
local d = dynamic_news_helper.GetPointDescription(victim)
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = strformat("%s %s %s %s!",a,b,c,d)
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="danger",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:SeenDeathOfStalker(sender,victim,who,comm) -- seeing stalker killing a stalker
--printf(">>> Dyn News: SeenDeathOfStalker - call")
local cls = dynamic_news_helper.GetWeaponClass(who)
if (cls == 1 or cls == 9) then
return false
end
if self:IsCommunitySame(victim,who) then
return false
end
local sender = sender or self:FindSpeaker(victim,who,false,false,true)
if self:IsSpecialNPC(sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_builder_sight_",true)
if (not tbl) then
return false
end
local a = tbl[math.random(#tbl)]
local b = dynamic_news_helper.GetCommunityDescription(who,math.random(1,2))
local c = dynamic_news_helper.GetWeaponDescription(who,math.random(4,8))
local d = dynamic_news_helper.GetCommunityDescription(victim,math.random(3,4))
local e = dynamic_news_helper.GetPointDescription(victim)
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = strformat("%s %s %s %s %s.",a,b,c,d,e)
self:PushToChannel("general",{Mg=msg,Ic=sender:character_icon(),Snd="danger",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:SeenDeathOfMutant(victim,who) -- seeing stalker killing a mutant
--printf(">>> Dyn News: SeenDeathOfMutant - call")
local cls = dynamic_news_helper.GetWeaponClass(who)
if (cls == 1 or cls == 9) then
return false
end
local sender = self:FindSpeaker(victim,who,nil,false,true)
if self:IsSpecialNPC(sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_builder_sight_",true)
if (not tbl) then
return false
end
local a = tbl[math.random(#tbl)]
local b = dynamic_news_helper.GetCommunityDescription(who,math.random(1,2))
local c = dynamic_news_helper.GetWeaponDescription(who,math.random(4,6))
local d = dynamic_news_helper.GetMonsterDescription(victim,1)
local e = dynamic_news_helper.GetPointDescription(victim)
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = strformat("%s %s %s %s %s.",a,b,c,d,e) -- example "I just saw" "a loner" "shots" "a bloodsucker" "north east of road to rostok"
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="danger",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:SeenDeathByMutant(sender,victim,who,comm) -- seeing stalker killed by a mutant
--printf(">>> Dyn News: SeenDeathByMutant - call")
local sender = sender or self:FindSpeaker(victim,who,false,nil,true)
if self:IsSpecialNPC(sender) then
return false
end
local tbl_1 = utils_data.collect_translations("st_dyn_news_builder_hear_",true) -- was sight
local tbl_2 = utils_data.collect_translations("st_dyn_news_builder_middle_",true)
local tbl_3 = utils_data.collect_translations("st_dyn_news_builder_ending_",true)
if (not tbl_1) or (not tbl_2) or (not tbl_3) then
return false
end
local a = tbl_1[math.random(#tbl_1)]
local b = tbl_2[math.random(#tbl_2)]
local c = dynamic_news_helper.GetPointDescription(victim)
local d = tbl_3[math.random(#tbl_3)]
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = strformat("%s %s %s.\\n%s",a,b,c,d)
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="danger",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:GossipDeathOfMutant(victim,who,comm) -- hearing stalker killing a mutant
--printf(">>> Dyn News: GossipDeathOfMutant - call")
local cls = dynamic_news_helper.GetWeaponClass(who)
if (cls == 1 or cls == 9) then
return false
end
local sender = self:FindSpeaker(victim,who,nil,false,true)
if self:IsSpecialNPC(sender) then
return false
end
local tbl_1 = utils_data.collect_translations("st_dyn_news_builder_hear_",true)
local tbl_2 = utils_data.collect_translations("st_dyn_news_builder_ending_",true)
if (not tbl_1) or (not tbl_2) then
return false
end
local a = tbl_1[math.random(#tbl_1)]
local b = dynamic_news_helper.GetWeaponDescription(who,2)
local c = dynamic_news_helper.GetPointDescription(victim)
local d = tbl_2[math.random(#tbl_2)]
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = strformat("%s %s %s. %s",a,b,c,d)
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:SOSDeathByMutant(victim,who) -- stalker under mutants attack
--printf(">>> Dyn News: SOSDeathByMutant - call")
local sender = self:FindSpeakerWithEnemy(victim,who,true,nil)
if self:IsSpecialNPC(sender) then
return false
end
local a = dynamic_news_helper.GetCommunityDescription(sender,math.random(11,14))
local b = dynamic_news_helper.GetMonsterDescription(who,math.random(2,5))
local c = dynamic_news_helper.GetPointDescription(victim)
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = strformat("%s %s %s!",a,b,c)
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="danger",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:SOSBattleOffline(sq_v,sq_w) -- stalker under mutants/stalker attack in other maps
--printf(">>> Dyn News: SOSBattleOffline - call")
if (not shw_death_stalker) then return end
if self:NewsToggle() or (not item_device.is_pda_charged(true)) then -- necessary to prevent news stacking after surges.
return
end
if (not sq_v) or (not sq_w) then return end
-- To prevent news spam
local curr_time = game.get_game_time()
if SOS_offline_time and (curr_time:diffSec(SOS_offline_time) < (SOS_offline_period * TimeFactor)) then
return
end
SOS_offline_time = curr_time
if (not enable_news) then
return
end
local members_v, members_w = {},{}
for k in sq_v:squad_members() do
members_v[#members_v + 1] = k.id
end
for k in sq_w:squad_members() do
members_w[#members_w + 1] = k.id
end
if (#members_w == 0) or (#members_v == 0) then
return
end
local comm_v = sq_v:get_squad_community()
local comm_w = sq_w:get_squad_community()
local se_v = alife_object(members_v[math.random(#members_v)])
local se_w = alife_object(members_w[math.random(#members_w)])
local cls_v = se_v:clsid()
local cls_w = se_w:clsid()
if IsMonster(nil,cls_v) or (not (self.channel_status[comm_v])) then
return
end
if self.unknown[comm_w] then
return
end
local comm_desc = game.translate_string("st_dyn_news_comm_" .. comm_v .. "_" .. tostring(6))
local a = game.translate_string("st_dyn_news_comm_" .. comm_v .. "_" .. tostring(math.random(11,14)))
local c = dynamic_news_helper.GetPointDescription(se_v)
local b
if IsMonster(nil,cls_w) then
b = dynamic_news_helper.GetMonsterDescription(nil,math.random(2,5),se_w:section_name(),cls_w)
else
local b1,b2 = self:BuildSentenceStalkerEnemy_Offline(comm_w)
b = strformat("%s %s",b1,b2)
end
local Se = strformat("%s, %s",se_v:character_name(),comm_desc)
local msg = strformat("%s %s %s!",a,b,c)
--dynamic_news_helper.send_tip(msg,Se, nil, msg_duration,comm_v,"beep_1","gr")
self:PushToChannel(comm_v, {Mg=msg,Ic=comm_v,Snd="beep_1",Se=Se,It="gr"})
end
function DynamicNewsManager:SOSWarfareCapture(sq) -- stalker under mutants/stalker attack in other maps
--printf(">>> Dyn News: SOSBattleOffline - call")
if self:NewsToggle() or (not item_device.is_pda_charged(true)) then -- necessary to prevent news stacking after surges.
return
end
if (not sq) then return end
-- To prevent news spam
local curr_time = game.get_game_time()
if SOS_warfare_cap_time and (curr_time:diffSec(SOS_warfare_cap_time) < (SOS_warfare_cap_period * TimeFactor)) then
return
end
SOS_warfare_cap_time = curr_time
local members = {}
for k in sq:squad_members() do
members[#members + 1] = k.id
end
if (#members == 0)then
return
end
local comm = sq:get_squad_community()
local se_npc = alife_object(members[math.random(#members)])
local cls = se_npc:clsid()
local sender_name = se_npc:character_name()
local sender_comm = game.translate_string("st_dyn_news_comm_" .. comm .. "_" .. tostring(6))
local fac_profile = dynamic_news_helper.GetFaction(sender_comm)
if (not fac_profile) then
return false
end
local sender_type = fac_profile["type"]
local location = dynamic_news_helper.GetPointDescription(se_npc)
local lvl = alife():level_name(game_graph():vertex(se_npc.m_game_vertex_id):level_id())
local level_name = game.translate_string(lvl)
local tbl = utils_data.collect_translations("st_dyn_news_warfare_capture_" .. sender_type .. "_", true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender_name,sender_comm)
local msg = utils_data.parse_string_keys( tbl[math.random(#tbl)] , { ["speaker"]=sender_name , ["map"]=level_name , ["location"]=location } )
--dynamic_news_helper.send_tip(msg,Se, nil, msg_duration,comm,"beep_1","gr")
self:PushToChannel(comm, {Mg=msg,Ic=comm,Snd="beep_1",Se=Se,It="gr"})
end
function DynamicNewsManager:KillWounded(sender,victim,is_hostage) -- killing a wounded stalker
--printf(">>> Dyn News: KillWounded - call")
if not (shw_kill_wounded) then
return false
end
local squad = get_object_squad(sender)
if not (squad and squad:commander_id() == sender:id()) then
return false
end
if (self.spammer.show_about_kill_wounded == 0) then
local tbl
if not (is_hostage) then
tbl = utils_data.collect_translations("st_dyn_news_gossip_kill_wounded_",true)
else
tbl = utils_data.collect_translations("st_dyn_news_gossip_hostage_",true)
end
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self:PushToChannel(sender:character_community(),{Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="news",Se=Se,It="npc"})
return true
end
self.spammer.show_about_kill_wounded = self.spammer.show_about_kill_wounded + 1
if (self.spammer.show_about_kill_wounded > 10) then
self.spammer.show_about_kill_wounded = 0
end
end
function DynamicNewsManager:RadioInHeli(sender,who) -- requesting chopper assistance
--printf(">>> Dyn News: RadioInHeli - call")
if (not shw_heli_call) then
return false
end
if self:IsSpecialNPC(sender) then
return false
end
local a = dynamic_news_helper.GetPointDescription(who)
local b = IsStalker(who) and dynamic_news_helper.GetCommunityDescription(who,math.random(1,2)) or dynamic_news_helper.GetMonsterDescription(who,6)
local tbl = utils_data.collect_translations("st_dyn_news_gossip_heli_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = utils_data.parse_string_keys( tbl[math.random(#tbl)] , { ["where"]=a , ["what"]=b } )
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:FoundArtefact(sender,itm) -- stalker found an artifact
--printf(">>> Dyn News: FoundArtefact - call")
if (not shw_found_artifact) then
return false
end
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local inv_name = ui_item.get_sec_name(itm:section())
local tbl = utils_data.collect_translations("st_dyn_news_gossip_arte_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = utils_data.parse_string_keys( tbl[math.random(#tbl)] , { ["what"]=inv_name } )
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc",Ty="artifact", Id=sender})
return true
end
function DynamicNewsManager:FoundStash() -- reaction of angry stash owners
--printf(">>> Dyn News: FoundStash - call")
if not (shw_stash and self.sentences_fnames and self.sentences_snames) then
return false
end
if (math.random(100) < 40) then -- %60 chance to ignore
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_found_stash_",true)
if (not tbl) then
return false
end
local Se = strformat("%s %s" , self.sentences_fnames[math.random(#self.sentences_fnames)] , self.sentences_snames[math.random(#self.sentences_snames)])
self:PushToChannel("general",{Mg=tbl[math.random(#tbl)],Ic="common",Snd="beep_2",Se=Se,It="gr",Ty="found_stash"})
return true
end
function DynamicNewsManager:BoughtItems(sender,who,list) -- trading
--printf(">>> Dyn News: BoughtItems - call")
local sec = list[math.random(#list)]
local inv_name = ui_item.get_sec_name(sec)
local tbl = utils_data.collect_translations("st_dyn_news_gossip_buy_",true)
if (not tbl) then
return false
end
inv_name = ui_item.get_plural_name(inv_name)
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = utils_data.parse_string_keys( tbl[math.random(#tbl)] , { ["who"]=who:character_name() , ["what"]=inv_name } )
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc",Ty="trade", Id=sender})
return true
end
function DynamicNewsManager:UpgradedItems(sender,who,wpn_sec,list) -- upgrading
--printf(">>> Dyn News: UpgradedItems - call")
local upgrade = list[math.random(#list)]
local upg_str = upgrade and ini_sys:r_string_ex(upgrade,"name")
local upg_name = upg_str and game.translate_string(upg_str)
local inv_name = wpn_sec and ui_item.get_sec_name(wpn_sec)
if not (upg_name and inv_name) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_gossip_upgrade_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = utils_data.parse_string_keys( tbl[math.random(#tbl)] , { ["who"]=who:character_name() , ["what"]=inv_name , ["upgrade"]=upg_name } )
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc",Ty="upgrade", Id=sender})
return true
end
function DynamicNewsManager:GossipLoot(sender, best_item, all_value)
--printf(">>> Dyn News: GossipLoot - call")
if not (sender and best_item and all_value) then
return false
end
if (sender:character_community() == "monolith") then
return false
end
-- Limit the spam
self.spammer.show_about_loot = self.spammer.show_about_loot + 1
if (self.spammer.show_about_loot > 1) then
self.spammer.show_about_loot = 0
end
if (self.spammer.show_about_loot == 0) then
return false
end
local tbl, msg
if (math.random(2) == 1) then
if all_value >= 1200 then
tbl = utils_data.collect_translations("st_dyn_news_loot_good_", true)
else
tbl = utils_data.collect_translations("st_dyn_news_loot_bad_", true)
end
if (not tbl) then
return false
end
msg = tbl[math.random(#tbl)]
elseif best_item then
-- Get the item's display name using get_sec_name
local item_name = ui_item.get_sec_name(best_item:section())
local tbl = utils_data.collect_translations("st_dyn_news_loot_item_", true)
if (not tbl) then
return false
end
msg = utils_data.parse_string_keys(tbl[math.random(#tbl)], { ["what"] = item_name })
end
local Se = string.format("%s, %s", sender:character_name(), dynamic_news_helper.GetCommunityDescription(sender, 6))
-- Push the message to the appropriate channel
self:PushToChannel(sender:character_community(), {
Mg = msg,
Ic = sender:character_icon(),
Snd = "beep_1",
Se = Se,
It = "npc"
})
return true
end
--< Random News >--
function DynamicNewsManager:ReportNextEmission() -- news about expected surge's date
--printf(">>> Dyn News: ReportNextEmission - call")
local SM, SurgeType, last_surge_time, AccuracyTier, comm, Se, clr, msg, a, b, c, d, Tbl_msg
local IsEmission, IsPsiStorm = false, false
-- %50 chance to pick blowout or psi-storm
if (math.random(2) == 1) then
SurgeType = game.translate_string("st_dyn_news_surge_type_emission")
SM = surge_manager and surge_manager.SurgeManager
if (ui_options.get("alife/event/emission_state")) and (SM ~= nil and SM._delta ~= nil and not SM.started) then -- if blowouts are enabled
last_surge_time = SM and SM.last_surge_time or game.get_game_time()
IsEmission = true
end
else
SurgeType = game.translate_string("st_dyn_news_surge_type_psi")
SM = psi_storm_manager and psi_storm_manager.PsiStormManager
if (ui_options.get("alife/event/psi_storm_state")) and (SM ~= nil and SM._delta ~= nil and not SM.started) then
last_surge_time = SM and SM.last_psi_storm_time or game.get_game_time()
IsPsiStorm = true
end
end
-- preparing the news
if IsEmission or IsPsiStorm then
local g_time = game.get_game_time()
local surge_start = SM and math.floor(SM._delta - g_time:diffSec(last_surge_time)) -- time "till" next blowout (in second) = ( time of next surge[SCOPED] - (current time - last surge time)[SCOPED] )
-- %50 chance to pick News from people or natural faction
if math.random(2) == 1 then
if (not self.sentences_fnames) or (not self.sentences_fnames) then
return false
end
comm = "common"
Se = strformat("%s %s", self.sentences_fnames[math.random(#self.sentences_fnames)] , self.sentences_snames[math.random(#self.sentences_snames)] )
Tbl_msg = utils_data.collect_translations("st_dyn_news_surge_template_",true)
if (not Tbl_msg) then return false end
a = Tbl_msg[math.random(#Tbl_msg)]
b = dynamic_news_helper.GetTimeString(math.floor(surge_start/3600), math.random(4))
if (a and b and SurgeType) then
msg = utils_data.parse_string_keys( a , {["what"]=SurgeType , ["when"]=b} )
end
else
comm = dynamic_news_helper.PickFaction(true)
if (not comm) then return false end
Se = strformat("%s, %s" , game.translate_string("st_faction_" .. comm) , game.translate_string("st_dyn_news_sender_private_ch"))
if ((comm == "ecolog") or (comm == "csky") or (comm == "dolg") or (comm == "army")) then
AccuracyTier = 5
else
AccuracyTier = math.random(5)
end
Tbl_msg = utils_data.collect_translations("st_dyn_news_surge_builder_start_" .. comm .. "_",true)
if (not Tbl_msg) then return false end
a = Tbl_msg[math.random(#Tbl_msg)]
Tbl_msg = utils_data.collect_translations("st_dyn_news_surge_builder_mid_",true)
if (not Tbl_msg) then return false end
b = Tbl_msg[math.random(#Tbl_msg)]
Tbl_msg = utils_data.collect_translations("st_dyn_news_surge_builder_end_" .. comm .. "_",true)
if (not Tbl_msg) then return false end
d = Tbl_msg[math.random(#Tbl_msg)]
c = dynamic_news_helper.GetTimeString(math.floor(surge_start/3600), AccuracyTier)
if (a and b and c and d and SurgeType) then
local msg_mid = utils_data.parse_string_keys( b , {["what"]=SurgeType , ["when"]=c} )
msg = utils_data.parse_string_keys( "$start $mid. $end." , {["start"]=a , ["mid"]=msg_mid , ["end"]=d} )
end
end
end
if not (msg and comm and Se) then
return false
end
--dynamic_news_helper.send_tip(msg,Se, nil, msg_duration,comm,"beep_1","gr")
self:PushToChannel("general",{Mg=msg,Ic=comm,Snd="beep_1",Se=Se,It="gr"})
return true
end
function DynamicNewsManager:ReportByFaction() -- faction's news
--printf(">>> Dyn News: ReportByFaction - call")
local comm = dynamic_news_helper.PickFaction()
local Se = game.translate_string("st_faction_" .. comm)
local tbl = utils_data.collect_translations("st_dyn_news_spam_faction_" .. comm .. "_",true)
if (not tbl) then
return false
end
local msg = tbl[math.random(#tbl)]
--dynamic_news_helper.send_tip(tbl[math.random(#tbl)],Se, nil, msg_duration,comm,"beep_1","gr")
self:PushToChannel(comm, {Mg=msg,Ic=comm,Snd="beep_1",Se=Se,It="gr"})
return true
end
function DynamicNewsManager:ReportZoneActivity() -- report activity of squads in other maps
local stalkers = {} -- id
local enemies = {} -- community
local naturals = {} -- community
local monsters = {} -- clsid
local sim = alife()
local gg = game_graph()
local sfind = string.find
local monster_tiers = faction_expansions.mutant_tier_by_clsid
local lvl_name = dynamic_news_helper.PickMap(level.name())
for i=1,65534 do
local se_obj = sim:object(i)
if se_obj and (lvl_name == sim:level_name(gg:vertex(se_obj.m_game_vertex_id):level_id())) then
local cls = se_obj:clsid()
local sec = se_obj:section_name()
if IsStalker(nil,cls) and sfind(sec,"sim_default_") then
local comm = se_obj:community()
if (comm ~= "trader") and (comm ~= "zombied") then
stalkers[#stalkers + 1] = i
end
elseif IsMonster(nil,cls) and monster_tiers[cls] and (monster_tiers[cls] > 0) then
monsters[#monsters + 1] = cls
end
end
end
if (#stalkers == 0) then
return
end
local sender_id = stalkers[math.random(#stalkers)]
local sender_se = alife_object(sender_id)
if (not sender_se) then
return false
end
local sender_comm = sender_se:community()
local fac_profile = dynamic_news_helper.GetFaction(sender_comm)
if (not fac_profile) then
return false
end
if not (self.channel_status[sender_comm]) then
return
end
local sender_name = sender_se:character_name()
local sender_desc = game.translate_string("st_dyn_news_comm_" .. sender_comm .. "_" .. tostring(6))
local map = game.translate_string(lvl_name)
local location = dynamic_news_helper.GetPointDescription(sender_se)
local sender_type = fac_profile["type"]
if (ini_sys:r_string_ex("string_table","language") == "rus") then
map = game.translate_string("st_dyn_news_" .. lvl_name)
end
for i=1,#stalkers do
local se_obj = sim:object(stalkers[i])
if se_obj then
local comm = se_obj:community()
if game_relations.is_factions_enemies(sender_comm, comm) then
enemies[#enemies + 1] = comm
elseif (sender_comm ~= comm) then
naturals[#naturals + 1] = comm
end
end
end
local types = {"none"}
local target_desc = {}
target_desc["none"] = ""
if (#enemies > 0) then
local enemy_comm = enemies[math.random(#enemies)]
target_desc["enemy"] = game.translate_string("st_dyn_news_comm_" .. enemy_comm .. "_8")
if (not self.unknown[enemy_comm]) then
types[#types + 1] = "enemy"
end
end
if (#naturals > 0) then
local natural_comm = naturals[math.random(#naturals)]
target_desc["friend"] = game.translate_string("st_dyn_news_comm_" .. natural_comm .. "_8")
types[#types + 1] = "friend"
end
if (#monsters > 0) then
local mutant_cls = monsters[math.random(#monsters)]
target_desc["mutant"] = dynamic_news_helper.GetMonsterDescription(nil,7,nil,mutant_cls)
if (ini_sys:r_string_ex("string_table","language") == "rus") then
target_desc["mutant"] = dynamic_news_helper.GetMonsterDescription(nil,6,nil,mutant_cls)
end
types[#types + 1] = "mutant"
end
local target_type = types[math.random(#types)]
local target = target_desc[target_type]
-- preparing the news
local tbl = utils_data.collect_translations("st_dyn_news_zone_activity_" .. sender_type .. "_" .. target_type .. "_",true)
if (not tbl) then
return false
end
local msg_pick = tbl[math.random(#tbl)]
-- if news involving special character, see if they are alive
local special = {
["leader"] = "",
["trader"] = "",
["mechanic"] = "",
--["medic"] = "",
--["barman"] = "",
--["guide"] = "",
}
for k,v in pairs(special) do
if string.find(msg_pick,"$"..k) then
local npc_info = get_story_npc_info(fac_profile[k])
if npc_info then
special[k] = npc_info.name
else
printf("~ News couldn't be sent because it involves special character [%s], he's missing? \nMessage: %s", fac_profile[k], msg_pick)
return false
end
end
end
local Se = game.translate_string("st_faction_" .. sender_comm)
local msg = utils_data.parse_string_keys( msg_pick , { ["speaker"]=sender_name , ["target"]=target , ["map"]=map , ["location"]=location , ["leader"]=special["leader"] , ["trader"]=special["trader"] , ["mechanic"]=special["mechanic"] } )
--dynamic_news_helper.send_tip(msg,Se, nil, msg_duration,sender_comm,"beep_1","gr")
self:PushToChannel(sender_comm, {Mg=msg,Ic=sender_comm,Snd="beep_1",Se=Se,It="gr"})
end
function DynamicNewsManager:SpamRandom() -- random news from all over the zone
local clr_1 = "%" .. "%c[255,160,160,190]"
local clr_2 = "%" .. "%c[255,220,220,220]"
local tbl = utils_data.collect_translations("st_dyn_news_spam_", true)
if not tbl then
return false
end
local Se = game.translate_string("st_dyn_news_sender_com_centre")
local msg = utils_data.parse_string_keys(tbl[math.random(#tbl)], {["clr_1"]=clr_1, ["clr_2"]=clr_2})
-- Push spam news to the general channel
self:PushToChannel("general", {Mg=msg, Ic="common", Snd="beep_2", Se=Se, It="gr"})
return true
end
function DynamicNewsManager:FoundDead() -- report dead body findings
--printf(">>> Dyn News: FoundDead - call")
if (not self.sentences_fnames) or (not self.sentences_fnames) then
return false
end
local clr_1 = "%" .. "%c[255,160,160,190]"
local clr_2 = "%" .. "%c[255,220,220,220]"
local a1 = self.sentences_fnames[math.random(#self.sentences_fnames)]
local b1 = self.sentences_snames[math.random(#self.sentences_snames)]
local a2 = self.sentences_fnames[math.random(#self.sentences_fnames)]
local b2 = self.sentences_snames[math.random(#self.sentences_snames)]
local c = dynamic_news_helper.PickMap(level.name())
c = game.translate_string(c)
local tbl = utils_data.collect_translations("st_dyn_news_death_reason_",true)
if (not tbl) then
return false
end
local y1 = string.char(math.random(65,90))
local y2 = string.char(math.random(65,90))
local z1 = tostring(math.random(9))
local z2 = tostring(math.random(9))
local z3 = tostring(math.random(9))
local Se = strformat("%s %s",a1,b1)
local msg = utils_data.parse_string_keys( "$clr_1$death_report -$clr_2 $fname $sname, $map, $death_reason, $y1$y2-$z1$z2$z3" , {["clr_1"]=clr_1 , ["clr_2"]=clr_2 , ["death_report"]=game.translate_string("st_dyn_news_spc_death_report") , ["fname"]=a2 , ["sname"]=b2 , ["map"]=c , ["death_reason"]=tbl[math.random(#tbl)] , ["y1"]=y1 , ["y2"]=y2 , ["z1"]=z1 , ["z2"]=z2 , ["z3"]=z3})
--dynamic_news_helper.send_tip(msg,Se, nil, msg_duration,"common","no_sound","gr")
self:PushToChannel("general",{Mg=msg,Ic="common",Snd="no_sound",Se=Se,It="gr"})
return true
end
--< Special News >--
function DynamicNewsManager:GossipTime() -- talk about time of day
--printf(">>> Dyn News: GossipTime - call")
if (not shw_time) then
return false
end
local sender = self:FindSpeakerRandom()
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local TimeStringPharse = dynamic_news_helper.GetTimePharseAsString()
local tbl = utils_data.collect_translations("st_dyn_news_time_" .. TimeStringPharse .. "_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self:PushToChannel(sender:character_community(),{Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:GossipWeather() -- talk about the weather
--printf(">>> Dyn News: GossipWeather - call")
-- no weather news in night
local hrs = level.get_time_hours()
if (hrs >= 21) or (hrs < 5) then
return false
end
local sender = self:FindSpeakerRandom()
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
--type of weather: {"clear","partly","cloudy","foggy","rain","storm"}
local WeatherNews
local _WM = level_weathers.get_weather_manager()
local WeatherType = _WM:get_curr_weather()
if not (WeatherType) then
return false
end
-- weather accurate check
if (WeatherType == "rain") or (WeatherType == "storm") then
local RainFactor = level.rain_factor()
if (RainFactor >= 0.5) then
WeatherNews = "storm"
elseif (RainFactor > 0) and (RainFactor < 0.5) then
WeatherNews = "rain"
else -- if rainy weather but there's no actual rain
return false
end
elseif (WeatherType == "foggy") then
local FarDistance = weather.get_value_numric("fog_distance")
if FarDistance and (FarDistance < 200) then
WeatherNews = "foggy"
else -- if foggy weather but there's no actual fog
return false
end
elseif (level.rain_factor() <= 0) then
WeatherNews = WeatherType
else
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_weather_" .. WeatherNews .. "_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self:PushToChannel(sender:character_community(),{Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:GossipNearbyActivity() -- talk about movement of nearby enemy
--printf(">>> Dyn News: GossipNearbyActivity - call")
local sender,target = self:FindSpeakerAndTarget(true,250)
if (not sender) or (not target) then
return false
end
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local who
local activity = "enemy_activity_"
if IsStalker(target,target:clsid()) then
local target_comm = target:character_community()
if self.unknown[target_comm] then
return false
end
if target_comm == "zombied" then
activity = activity .. "zombied"
else
activity = activity .. "stalker"
end
if (ini_sys:r_string_ex("string_table","language") == "rus") then
who = dynamic_news_helper.GetCommunityDescription(target,math.random(3,4))
else
who = dynamic_news_helper.GetCommunityDescription(target,math.random(1,4))
end
elseif IsMonster(target,target:clsid()) then
local cls = dynamic_news_helper.GetMonsterDescription(target)
local tier = dynamic_news_helper.GetMutant(cls,"tier")
activity = activity .. "mutant_" .. tostring(tier)
who = dynamic_news_helper.GetMonsterDescription(target,1)
end
local tbl = utils_data.collect_translations("st_dyn_news_" .. activity .. "_",true)
if (not tbl) or (not who) then
return false
end
local msg = utils_data.parse_string_keys( tbl[math.random(#tbl)] , {["who"]=who} )
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="beep_2",Se=Se,It="npc",Ty=activity,Id=sender})
return true
end
function DynamicNewsManager:DumbZombie() -- zombies trying to talk over the radio
--printf(">>> Dyn News: DumbZombie - call")
local sender = self:FindSpeakerRandom(true,"zombied") -- must use channel_status["general"] for intended zombied case
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_dumb_zombie_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self:PushToChannel(sender:character_community(),{Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_2",Se=Se,It="npc",Ty="dumb_zombie"})
return true
end
function DynamicNewsManager:monster_on_respawn(npc,near) -- report mutant activity [empty]
end
--< Task News >--
function DynamicNewsManager:GossipBounty() -- talk about the player's bounty
--printf(">>> Dyn News: GossipBounty - call")
local bounty
for task_id,npc_id in pairs(axr_task_manager.bounties_by_id) do -- loop across npcs on task list
bounty = db.storage[npc_id] and db.storage[npc_id].object
if (bounty and bounty:alive()) then
break
end
end
if not (bounty and bounty:alive()) then -- if the bounty npc is dead, return
return false
end
local sender = self:FindSpeakerNoVictim(bounty,false,true)
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_gossip_bounty_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = utils_data.parse_string_keys( tbl[math.random(#tbl)] , { ["who"]=bounty:character_name() , ["where"]=dynamic_news_helper.GetPointDescription(bounty) } )
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:GossipAlphaSquad() -- talk about the player being a bounty
--printf(">>> Dyn News: GossipAlphaSquad - call")
local se_actor = alife():actor()
actor_name = se_actor:character_name()
local sq = sim_squad_bounty.get_active_squads()
if (not sq) then return false end
local alpha_npcs
for k,v in pairs(sq) do
alpha_npcs = alpha_npcs or {}
local se_sq = alife_object(k)
if se_sq and (se_sq:section_name() == v) and (simulation_objects.is_on_the_same_level(se_actor, se_sq)) then
for j in se_sq:squad_members() do
local npc = db.storage[j.id] and db.storage[j.id].object
if npc and npc:alive() then
alpha_npcs[npc:id()] = true
end
end
end
end
if (not alpha_npcs) then -- if no alpha squad nearby, return
return false
end
local sender = self:FindSpeakerNoVictim(db.actor,false,true)
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
if alpha_npcs[sender:id()] then
return
end
local tbl = utils_data.collect_translations("st_dyn_news_gossip_bounty_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = utils_data.parse_string_keys( tbl[math.random(#tbl)] , { ["who"]=actor_name , ["where"]=dynamic_news_helper.GetPointDescription(db.actor) } )
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:GossipTaskRepeatTimeout(task_id)
--printf(">>> Dyn News: GossipTaskRepeatTimeout - call")
local story_id = task_id:sub(1,-8)
local obj = get_story_object(story_id)
if not (obj) then
return false
end
local sender = self:FindSpeakerNoVictim(nil,nil,true)
if (not sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_gossip_hostage_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = strformat(tbl[math.random(#tbl)],obj:character_name())
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:GossipTaskLL()
local actor_comm = get_actor_true_community()
local sender = self:FindSpeakerRandom(false,actor_comm)
if (not sender) then
return false
end
local comm = sender:character_community()
if (not self.channel_status[comm]) or self.mono[comm] or self.unknown[comm] then
return
end
local tbl = utils_data.collect_translations("st_dyn_news_gossip_task_LL_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = tbl[math.random(#tbl)]
self:PushToChannel(comm,{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc"})
story_LL_trigger = false
return true
end
function DynamicNewsManager:GossipTaskMS()
local actor_comm = get_actor_true_community()
local sender = self:FindSpeakerRandom(false,actor_comm)
if (not sender) then
return false
end
local comm = sender:character_community()
if (not self.channel_status[comm]) or self.mono[comm] or self.unknown[comm] then
return
end
local tbl = utils_data.collect_translations("st_dyn_news_gossip_task_MS_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = tbl[math.random(#tbl)]
self:PushToChannel(comm,{Mg=msg,Ic=sender:character_icon(),Snd="news",Se=Se,It="npc"})
story_MS_trigger = false
return true
end
function DynamicNewsManager:GossipTaskOA()
local actor_comm = get_actor_true_community()
local f = faction_expansions.faction[actor_comm]
local leader = f and f["leader"]
local npc_info = leader and get_story_npc_info(leader)
local Se = npc_info and npc_info.name
local Ico = npc_info and npc_info.icon
if not (Se and Ico) then
return
end
local msg = game.translate_string("st_dyn_news_gossip_task_oa_" .. actor_comm)
dynamic_news_helper.send_tip(msg, Se, math.random(20,30), 20, Ico, "news", "npc")
end
function DynamicNewsManager:GossipTaskDP()
local tbl = utils_data.collect_translations("st_dyn_news_gossip_task_dp_",true)
if (not tbl) then
return false
end
local msg = tbl[math.random(#tbl)]
local player_name = alife():actor():character_name()
msg = strformat(msg, player_name, Se)
dynamic_news_helper.send_tip(msg, Se, math.random(20,30), 20, "ui_inGame2_D_gonets_pravosudiya", "news", "npc")
end
function DynamicNewsManager:GossipTaskDRX()
local actor_comm = get_actor_true_community()
local f = faction_expansions.faction[actor_comm]
local leader = f and f["leader"]
local npc_info = leader and get_story_npc_info(leader)
local Se = npc_info and npc_info.name
local Ico = npc_info and npc_info.icon
if not (Se and Ico) then
return
end
local msg = game.translate_string("drx_sl_start_msg_" .. actor_comm)
local actor_name = alife():actor():character_name()
msg = strformat(msg,actor_name)
dynamic_news_helper.send_tip(msg,Se, 0, 20,Ico,"news","npc")
end
--< Companions News >--
function DynamicNewsManager:CompanionAboutLife(sender) -- companion chitchat
--printf(">>> Dyn News: CompanionAboutLife - call")
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local alife = alife()
local se_actor = alife:actor()
local tbl
if (math.random(2) == 1) then
tbl = utils_data.collect_translations("st_dyn_news_companion_life_all_",true)
else
tbl = utils_data.collect_translations("st_dyn_news_companion_life_" .. sender:character_community() .. "_",true)
end
if (not tbl) then
return false
end
local msg = tbl[math.random(#tbl)]
if string.match(msg,"$name") then
msg = utils_data.parse_string_keys( msg , { ["name"]=se_actor:character_name() } )
end
local Se = strformat("%s, %s",sender:character_name(),game.translate_string("st_dyn_news_sender_companion"))
self:PushToChannel(sender:character_community(),{Mg=msg,Ic=sender:character_icon(),Snd="beep_2",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:CompanionAboutLevel(sender) -- companion talk about the current map
--printf(">>> Dyn News: CompanionAboutLevel call")
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local lvl = level.name()
local tbl
if (dynamic_news_helper.GetFaction(sender:character_community(),"territory") == level.name()) then
tbl = utils_data.collect_translations("st_dyn_news_companion_level_home_",true)
else
tbl = utils_data.collect_translations("st_dyn_news_companion_level_" .. lvl .. "_",true)
end
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),game.translate_string("st_dyn_news_sender_companion"))
self:PushToChannel(sender:character_community(),{Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc"})
return true
end
function DynamicNewsManager:CompanionAboutActor(sender) -- companion talk about player's rank and reputation
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local alife = alife()
local se_actor = alife:actor()
local a,b
local rep_tbl = {"terrible","really_bad","very_bad","bad","neutral","good","very_good","really_good","excellent"}
local rank_tbl = {"novice","trainee","experienced","professional","veteran","expert","master","legend"}
local actor_rep = utils_obj.get_reputation_name(db.actor:character_reputation())
local actor_rank = ranks.get_obj_rank_name(db.actor)
for i=1,#rep_tbl do
if string.match(actor_rep,rep_tbl[i]) then
if (i <= 4) then a = 1
elseif (i > 4) and (i < 7) then a = 2
elseif (i >= 7) then a = 3
end
break
end
end
for i=1,#rank_tbl do
if string.match(actor_rank,rank_tbl[i]) then
if (i < 3) then b = 1
elseif (i >= 3) and (i < 5) then b = 2
elseif (i >= 5) and (i < 7) then b = 3
elseif (i == 7) then b = 4
end
break
end
end
local tbl
if (math.random(2) == 1) then
tbl = utils_data.collect_translations("st_dyn_news_companion_rep_" .. tostring(a) .. "_",true)
else
tbl = utils_data.collect_translations("st_dyn_news_companion_rank_" .. tostring(b) .. "_",true)
end
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),game.translate_string("st_dyn_news_sender_companion"))
local msg = utils_data.parse_string_keys( tbl[math.random(#tbl)] , { ["name"]=se_actor:character_name() } )
--printf(">>> Dyn News: CompanionAboutActor | Rank: " .. actor_rank .. ", Reputation: " .. actor_rep)
self:PushToChannel("general",{Mg=msg,Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc"})
return true
end
--< Reaction News >--
function DynamicNewsManager:GossipEmissionEnd(what) -- stalkers reacting about the surge
--printf(">>> Dyn News: GossipEmissionEnd - call")
if (not shw_reaction) or ((what ~= "emission") and (what ~= "storm")) then
return false
end
local sender = self:FindSpeakerRandom()
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_surge_after_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
local msg = utils_data.parse_string_keys( tbl[math.random(#tbl)] , { ["what"]=what } )
dynamic_news_helper.send_tip(msg,Se,math.random(10,15),msg_duration,sender:character_icon(),"beep_1","npc") -- no need for push to channel
self.surge_type = "" -- reset
return true
end
function DynamicNewsManager:ResponseOnFoundArtefact(who) -- react to people who found artifacts recently
--printf(">>> Dyn News: ResponseOnFoundArtefact - call")
local sender = self:FindSpeakerNoVictim(who,true,true)
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_artefact_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc",To=false,St=msg_duration}
return true
end
function DynamicNewsManager:ResponseOnFoundStash() -- react to people who lost their stashes
--printf(">>> Dyn News: ResponseOnFoundStash - call")
if (not self.sentences_fnames) or (not self.sentences_fnames) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_found_stash_",true)
if (not tbl) then
return false
end
local Se = strformat("%s %s" , self.sentences_fnames[math.random(#self.sentences_fnames)] , self.sentences_snames[math.random(#self.sentences_snames)])
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic="common",Snd="no_sound",Se=Se,It="gr",To=false,St=msg_duration}
return true
end
function DynamicNewsManager:ResponseOnBoughtItems(who) -- react to people who bought items recently
--printf(">>> Dyn News: ResponseOnBoughtItems - call")
local sender = self:FindSpeakerNoVictim(who,true,true)
if (not sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_trade_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc",To=false,St=msg_duration}
return true
end
function DynamicNewsManager:ResponseOnGossipNearbyActivity(who,activity) -- react to people reporting nearby activity
--printf(">>> Dyn News: ResponseOnGossipNearbyActivity - call")
local sender = self:FindSpeakerNoVictim(who,true,true)
if (not sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_" .. activity .. "_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc",To=false,St=msg_duration}
return true
end
function DynamicNewsManager:ResponseOnDumbZombie() -- react to dumb zombies being dumb
--printf(">>> Dyn News: ResponseOnDumbZombie - call")
local sender = self:FindSpeakerRandom(true)
if self:IsSpecialNPC(sender) or self:IsMonoCommunity(sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_dumb_zombie_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc",To=false,St=msg_duration}
return true
end
function DynamicNewsManager:ResponseOnDeathByStalker(who) -- react to stalker's death by another stalker
--printf(">>> Dyn News: ResponseOnDeathByStalker - call")
local sender = self:FindSpeakerNoVictim(who,true,true)
if (not sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_death_stalker_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc",To=false,St=msg_duration}
return true
end
function DynamicNewsManager:ResponseOnDeathByMutant(who) -- react to stalker's death by mutants
--printf(">>> Dyn News: ResponseOnDeathByMutant - call")
local sender = self:FindSpeakerNoVictim(who,true,true)
if (not sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_death_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc",To=false,St=msg_duration}
return true
end
function DynamicNewsManager:ResponseOnDeathBySurges(who) -- react to stalker's death by surges [NOT USED]
--printf(">>> Dyn News: ResponseOnDeathBySurges - call")
local sender = self:FindSpeakerNoVictim(who,true,true)
if (not sender) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_death_surge_",true)
if (not tbl) then
return false
end
local Se = strformat("%s, %s",sender:character_name(),dynamic_news_helper.GetCommunityDescription(sender,6))
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic=sender:character_icon(),Snd="beep_1",Se=Se,It="npc",To=false,St=msg_duration}
return true
end
function DynamicNewsManager:ResponseOnDeathByStalker_Fake() -- react to stalker's death by another stalker (fake)
--printf(">>> Dyn News: ResponseOnDeathByStalker_Fake - call")
if (not self.sentences_fnames) or (not self.sentences_fnames) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_fake_death_stalker_",true)
if (not tbl) then
return false
end
local Se = strformat("%s %s" , self.sentences_fnames[math.random(#self.sentences_fnames)] , self.sentences_snames[math.random(#self.sentences_snames)])
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic="common",Snd="no_sound",Se=Se,It="gr",To=false,St=msg_duration}
return true
end
function DynamicNewsManager:ResponseOnDeathByMutant_Fake() -- react to stalker's death by mutants (fake)
--printf(">>> Dyn News: ResponseOnDeathByMutant_Fake - call")
if (not self.sentences_fnames) or (not self.sentences_fnames) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_fake_death_mutant_",true)
if (not tbl) then
return false
end
local Se = strformat("%s %s" , self.sentences_fnames[math.random(#self.sentences_fnames)] , self.sentences_snames[math.random(#self.sentences_snames)])
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic="common",Snd="no_sound",Se=Se,It="gr",To=false,St=msg_duration}
return true
end
function DynamicNewsManager:ResponseOnDeathBySurges_Fake() -- react to stalker's death by surges (fake)
--printf(">>> Dyn News: ResponseOnDeathBySurges_Fake - call")
if (not self.sentences_fnames) or (not self.sentences_fnames) then
return false
end
local tbl = utils_data.collect_translations("st_dyn_news_res_fake_death_surge_",true)
if (not tbl) then
return false
end
local Se = strformat("%s %s" , self.sentences_fnames[math.random(#self.sentences_fnames)] , self.sentences_snames[math.random(#self.sentences_snames)])
self.response["message"] = {Mg=tbl[math.random(#tbl)],Ic="common",Snd="no_sound",Se=Se,It="gr",To=30,St=msg_duration}
return true
end
------------------------------------------------------------
-- U.D.E - Pandablyat 18/05/2024
------------------------------------------------------------
------------------------------------------------------------
-- Helpers
------------------------------------------------------------
function DynamicNewsManager:BuildSentenceStalkerEnemy(victim,who,mn,mx)
local comm_victim = victim:character_community()
local comm_who = who:character_community()
local comm, dist
local c = 0
for i=1, #db.OnlineStalkers do
if (db.OnlineStalkers[i] ~= who_id) then
local st = db.storage[db.OnlineStalkers[i]]
local npc = st and st.object or level.object_by_id(db.OnlineStalkers[i])
if (npc and IsStalker(npc,npc:clsid()) and npc:alive() and not get_object_story_id(db.OnlineStalkers[i])) then
comm = npc:character_community() -- remove local
if (comm == comm_who) then
dist = victim:position():distance_to(npc:position())
if (dist < mx) or (dist > mn) then
c = c + 1
end
end
end
end
if (c >= 2) then
break
end
end
local sentences = {}
local string_count = 1
while true do
local tr_s = game.translate_string("st_dyn_news_builder_attacked_"..string_count)
if (tr_s == "st_dyn_news_builder_attacked_"..string_count) then
break
else
table.insert(sentences,tr_s)
end
string_count = string_count + 1
end
if (#sentences == 0) then
return false
end
if (c >= 2) then
return sentences[math.random(#sentences)], dynamic_news_helper.GetCommunityDescription(who,math.random(9,10))
end
return sentences[math.random(#sentences)], dynamic_news_helper.GetCommunityDescription(who,math.random(7,8))
end
function DynamicNewsManager:BuildSentenceStalkerEnemy_Offline(comm_w)
local index = math.random(7,8)
if (math.random(100) < 50) then
index = math.random(9,10)
end
local sentences = utils_data.collect_translations("st_dyn_news_builder_attacked_",true)
if (not sentences) then return false end
local comm_w_desc = game.translate_string("st_dyn_news_comm_" .. comm_w .. "_" .. index)
return sentences[math.random(#sentences)], comm_w_desc
end
function DynamicNewsManager:IsSpecialNPC(npc)
if (not npc) then return true end
if string.find(npc:section(),"sim_default") then
return false
end
return true
end
function DynamicNewsManager:IsMonoCommunity(npc)
if (not npc) then return true end
local comm = character_community(npc)
if (npc:id() == AC_ID and comm ~= "actor") then
comm = comm:sub(7)
end
if self.mono[comm] then
return true
end
return false
end
function DynamicNewsManager:IsUnknownCommunity(npc)
if (not npc) then return true end
local comm = character_community(npc)
if (npc:id() == AC_ID and comm ~= "actor") then
comm = comm:sub(7)
end
if self.unknown[comm] then
return true
end
return false
end
function get_story_npc_info(section)
if not (section and section ~= "") then
return
end
local se_npc = get_story_se_object(section)
if se_npc then
local name = se_npc:character_name()
local icon = se_npc:character_icon()
return { name = name , icon = icon }
end
return
end