2911 lines
96 KiB
Plaintext
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
|