1733 lines
50 KiB
Plaintext
1733 lines
50 KiB
Plaintext
|
-- demonized Mugging Squads
|
|||
|
-- Generated with AnomalyModCreator
|
|||
|
|
|||
|
-- ; Original description by billwa
|
|||
|
-- ; Basically they yell a quote, surround you and a guy comes up to talk and you have 3 dialogue [ptions. Pay mugging fee, get forced into kidnapping and the classic resist.
|
|||
|
-- ; Obviously when if you start shooting them before you're they're able to open up their yappers, all bets are off and it's a normal gun fight
|
|||
|
-- ; Monolith and sin will try kidnapping you always, no mugging. If you agree, it should bring you back to a base where all of your gear is removed until you convert and you have two options before you do, agree or fight, but lmao with no gear.
|
|||
|
-- ; It is entirely random and happens anywhere on the map except interiors like labs or main
|
|||
|
|
|||
|
-- For the give me stuff part, it is possible to have the most common outcome being money/one item and then a rare chance of them taking all your shit
|
|||
|
-- Oh, and playing a sound upon mugging, can you make it like only a 50% chance that it happens
|
|||
|
|
|||
|
-- Settings
|
|||
|
delaySpawn = 30 -- real seconds
|
|||
|
delayState = 5 -- real seconds
|
|||
|
|
|||
|
local id = 70000
|
|||
|
local idOffset = 0
|
|||
|
local gizmos = {
|
|||
|
sphereSquad = nil,
|
|||
|
}
|
|||
|
local debugMode = false
|
|||
|
local function printf(s, ...)
|
|||
|
if debugMode then
|
|||
|
_G.printf(s, ...)
|
|||
|
end
|
|||
|
return string.format(s, ...)
|
|||
|
end
|
|||
|
local function print_tip(...)
|
|||
|
if debugMode and _G.print_tip then
|
|||
|
return _G.print_tip(...)
|
|||
|
end
|
|||
|
end
|
|||
|
local function print_err(s, ...)
|
|||
|
s = "!" .. s
|
|||
|
if debugMode and _G.print_tip then
|
|||
|
_G.print_tip(s, ...)
|
|||
|
else
|
|||
|
_G.printf(s, ...)
|
|||
|
end
|
|||
|
return string.format(s, ...)
|
|||
|
end
|
|||
|
|
|||
|
local gizmosInitialized = false
|
|||
|
function initializeGizmos()
|
|||
|
if gizmosInitialized then return end
|
|||
|
gizmosInitialized = true
|
|||
|
|
|||
|
gizmos.sphereSquad = debug_render.add_object(id + idOffset, DBG_ScriptObject.sphere):cast_dbg_sphere()
|
|||
|
end
|
|||
|
function reset(gizmosArr, force)
|
|||
|
if debugMode or force then
|
|||
|
if gizmosArr then
|
|||
|
for i = 1, #gizmosArr do
|
|||
|
local gizmo = gizmosArr[i]
|
|||
|
if gizmos[gizmo] then
|
|||
|
local v = gizmos[gizmo]
|
|||
|
if type(v) == "table" then
|
|||
|
for i = 1, #v do
|
|||
|
local p = v[i]
|
|||
|
p.visible = false
|
|||
|
end
|
|||
|
else
|
|||
|
v.visible = false
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
else
|
|||
|
for k, v in pairs(gizmos) do
|
|||
|
if type(v) == "table" then
|
|||
|
for i = 1, #v do
|
|||
|
local p = v[i]
|
|||
|
p.visible = false
|
|||
|
end
|
|||
|
else
|
|||
|
v.visible = false
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
function toggleDebugMode()
|
|||
|
debugMode = not debugMode
|
|||
|
if debugMode then
|
|||
|
initializeGizmos()
|
|||
|
else
|
|||
|
reset(nil, true)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
-- MCM
|
|||
|
function load_defaults()
|
|||
|
local t = {}
|
|||
|
local op = demonized_mugging_squads_mcm.op
|
|||
|
for i, v in ipairs(op.gr) do
|
|||
|
if v.def ~= nil then
|
|||
|
t[v.id] = v.def
|
|||
|
end
|
|||
|
end
|
|||
|
return t
|
|||
|
end
|
|||
|
|
|||
|
settings = load_defaults()
|
|||
|
|
|||
|
function load_settings()
|
|||
|
settings = load_defaults()
|
|||
|
if ui_mcm then
|
|||
|
for k, v in pairs(settings) do
|
|||
|
settings[k] = ui_mcm.get("demonized_mugging_squads/" .. k)
|
|||
|
end
|
|||
|
end
|
|||
|
return settings
|
|||
|
end
|
|||
|
|
|||
|
local function roundVec(v, num)
|
|||
|
return vector():set(
|
|||
|
round_idp(v.x, num),
|
|||
|
round_idp(v.y, num),
|
|||
|
round_idp(v.z, num)
|
|||
|
)
|
|||
|
end
|
|||
|
|
|||
|
local function shuffle(t)
|
|||
|
local random = math.random
|
|||
|
for i = #t, 2, -1 do
|
|||
|
local j = random(i)
|
|||
|
t[i], t[j] = t[j], t[i]
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
activeSquads = {} -- current active mugging squads
|
|||
|
|
|||
|
local lastSpawnTime -- the last time a mugging squad has been spawned
|
|||
|
local currentLevelSmarts = {}
|
|||
|
local linkedLevelSmarts = {}
|
|||
|
|
|||
|
squadStages = {
|
|||
|
approach = 1,
|
|||
|
talk = 2,
|
|||
|
done = 3,
|
|||
|
}
|
|||
|
|
|||
|
--====================================< Utilities >====================================--
|
|||
|
function addToActiveSquads(squad)
|
|||
|
activeSquads[squad.id] = {
|
|||
|
name = squad:section_name(),
|
|||
|
stage = squadStages.approach
|
|||
|
}
|
|||
|
end
|
|||
|
|
|||
|
function setSquadStage(squad, num)
|
|||
|
activeSquads[squad.id].stage = num
|
|||
|
end
|
|||
|
|
|||
|
function invalidateSquad(squad)
|
|||
|
print_tip("-demonized_mugging_squads squad %s is invalidated", squad.id)
|
|||
|
activeSquads[squad.id] = nil
|
|||
|
end
|
|||
|
|
|||
|
function setSquadAsEnemy(squad)
|
|||
|
print_tip("-demonized_mugging_squads squad %s is enemy!", squad.id)
|
|||
|
if squad.force_set_goodwill then
|
|||
|
squad:force_set_goodwill(-5000, db.actor)
|
|||
|
end
|
|||
|
for k in squad:squad_members() do
|
|||
|
local obj = level.object_by_id(k.id)
|
|||
|
local se_obj = alife_object(k.id)
|
|||
|
if obj then
|
|||
|
obj:set_relation(game_object.enemy, db.actor)
|
|||
|
obj:force_set_goodwill(-5000, db.actor)
|
|||
|
end
|
|||
|
if se_obj then
|
|||
|
se_obj:force_set_goodwill(-5000, db.actor)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function getFactions()
|
|||
|
local factions = {}
|
|||
|
for k, v in pairs(settings) do
|
|||
|
if k:find("^muggingFactionsCanSpawn_") and v == true then
|
|||
|
local faction = k:gsub("^muggingFactionsCanSpawn_", "")
|
|||
|
factions[#factions + 1] = faction
|
|||
|
end
|
|||
|
end
|
|||
|
return factions
|
|||
|
end
|
|||
|
|
|||
|
function isFactionsEnemies(f1, f2)
|
|||
|
return not game_relations.is_factions_friends(f1, f2)
|
|||
|
end
|
|||
|
|
|||
|
function getSafeLevels()
|
|||
|
return demonized_mugging_squads_options.safe_levels
|
|||
|
end
|
|||
|
|
|||
|
function getSafeSmarts()
|
|||
|
return demonized_mugging_squads_options.safe_smarts
|
|||
|
end
|
|||
|
|
|||
|
function getFactionSquads()
|
|||
|
local squads = {}
|
|||
|
for k, v in pairs(demonized_mugging_squads_options.faction_squads) do
|
|||
|
squads[k] = str_explode(v, ",")
|
|||
|
end
|
|||
|
return squads
|
|||
|
end
|
|||
|
|
|||
|
function getDangerRanks()
|
|||
|
return demonized_mugging_squads_options.danger_ranks
|
|||
|
end
|
|||
|
|
|||
|
function getDangerReputations()
|
|||
|
return demonized_mugging_squads_options.danger_reputations
|
|||
|
end
|
|||
|
|
|||
|
function trySpawn()
|
|||
|
-- gather factions
|
|||
|
local enemy_factions = {}
|
|||
|
local factions = getFactions()
|
|||
|
for i, faction in ipairs(factions) do
|
|||
|
if settings.allowSameSquads or get_actor_true_community() ~= faction then
|
|||
|
if settings.allowFriendlySquads or isFactionsEnemies(get_actor_true_community(), faction) then
|
|||
|
enemy_factions[#enemy_factions + 1] = faction
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
if is_empty(enemy_factions) then
|
|||
|
print_err("-demonized_mugging_squads.trySpawn / no faction is possible to spawn, skip")
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
local picked_squad = enemy_factions[math.random(#enemy_factions)]
|
|||
|
|
|||
|
-- gather smarts
|
|||
|
local spawn_smrts = {}
|
|||
|
for name, smart in pairs(currentLevelSmarts) do
|
|||
|
local dist = smart.position:distance_to_sqr(db.actor:position())
|
|||
|
local spawnDistance = settings.spawnDistance * settings.spawnDistance
|
|||
|
if dist > spawnDistance then
|
|||
|
local smrt = SIMBOARD.smarts[smart.id]
|
|||
|
if smrt then
|
|||
|
local pass = true
|
|||
|
for k, v in pairs(smrt.squads) do
|
|||
|
local squad = alife_object(k)
|
|||
|
if squad and squad.current_target_id and squad.current_target_id == smart.id and not squad:get_script_target() then
|
|||
|
pass = false
|
|||
|
break
|
|||
|
end
|
|||
|
end
|
|||
|
if pass then
|
|||
|
-- print_tip("-demonized_mugging_squads.trySpawn / [%s] is a possible smart found, distance: %s", name, dist)
|
|||
|
spawn_smrts[#spawn_smrts+1] = name
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
if #spawn_smrts > 0 then
|
|||
|
local squads = getFactionSquads()[picked_squad]
|
|||
|
|
|||
|
if is_empty(squads) then
|
|||
|
print_err("-demonized_mugging_squads.trySpawn / no squad can be found for faction %s, skip", picked_squad)
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
local squad = squads[math.random(#squads)]
|
|||
|
local spawn_smrt = spawn_smrts[math.random(#spawn_smrts)]
|
|||
|
local level = alife():level_name(game_graph():vertex(alife_object(SIMBOARD.smarts_by_names[spawn_smrt].id).m_game_vertex_id):level_id())
|
|||
|
print_err("-demonized_mugging_squads.trySpawn / [%s] has been spawned in [%s], level [%s]", squad, spawn_smrt, level)
|
|||
|
|
|||
|
-- Spawn squad and target the player
|
|||
|
local sq = SIMBOARD:create_squad(SIMBOARD.smarts_by_names[spawn_smrt], squad)
|
|||
|
sq.scripted_target = "actor"
|
|||
|
sq.rush_to_target = true
|
|||
|
|
|||
|
addToActiveSquads(sq)
|
|||
|
lastSpawnTime = game.get_game_time()
|
|||
|
else
|
|||
|
print_err("-demonized_mugging_squads.trySpawn / no smart can be found to spawn squad of %s", picked_squad)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function attack(state, rush)
|
|||
|
for k, v in pairs(activeSquads) do
|
|||
|
local se = alife_object(k)
|
|||
|
if se and se:section_name() == v.name then
|
|||
|
se.scripted_target = state and v.stage == squadStages.approach and "actor" or nil
|
|||
|
se.rush_to_target = rush == true and v.stage == squadStages.approach
|
|||
|
|
|||
|
print_tip("-demonized_mugging_squads. - target: %s - rush: %s, %s",
|
|||
|
se.scripted_target,
|
|||
|
se.rush_to_target,
|
|||
|
(function()
|
|||
|
local commander = se:commander_id() and level.object_by_id(se:commander_id())
|
|||
|
if commander then
|
|||
|
return ("dist %s"):format(commander:position():distance_to(db.actor:position()))
|
|||
|
else
|
|||
|
local se_obj = alife_object(se:commander_id())
|
|||
|
if se_obj then
|
|||
|
local actor_level = level.name()
|
|||
|
local squad_level = alife():level_name(game_graph():vertex(se_obj.m_game_vertex_id):level_id())
|
|||
|
return ("level %s, actor level %s"):format(squad_level, actor_level)
|
|||
|
else
|
|||
|
return "failed to get distance, no commander se_obj"
|
|||
|
end
|
|||
|
end
|
|||
|
end)()
|
|||
|
)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function updateTalk()
|
|||
|
if not load_var(db.actor, "force_all_talk", false) then
|
|||
|
print_err("-demonized_mugging_squads actor not talking, updateTalk stop")
|
|||
|
UnregisterScriptCallback("actor_on_update", updateTalk)
|
|||
|
return
|
|||
|
end
|
|||
|
if not db.actor:is_talking() then
|
|||
|
print_err("-demonized_mugging_squads actor stop talking, force_all_talk false and updateTalk stop")
|
|||
|
save_var(db.actor, "force_all_talk", false)
|
|||
|
UnregisterScriptCallback("actor_on_update", updateTalk)
|
|||
|
return
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function forceTalk(npc)
|
|||
|
if not npc:is_talking() then
|
|||
|
local meet = db.storage[npc:id()].meet
|
|||
|
if meet then
|
|||
|
local use = meet.meet_manager.use
|
|||
|
meet.meet_manager.use = "true"
|
|||
|
end
|
|||
|
|
|||
|
npc:enable_talk()
|
|||
|
npc:set_start_dialog("muggingDialogGiveMeYourShit")
|
|||
|
RegisterScriptCallback("actor_on_update", updateTalk)
|
|||
|
save_var(db.actor, "force_all_talk", true)
|
|||
|
npc:allow_break_talk_dialog(false)
|
|||
|
db.actor:run_talk_dialog(npc, true)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--====================================< Callbacks >====================================--
|
|||
|
function spawnTimer()
|
|||
|
--printf("-mugging_squads.spawnTimer called")
|
|||
|
ResetTimeEvent("demonized_mugging_squads", "mugging_squad_spawn", delaySpawn)
|
|||
|
|
|||
|
local num = settings.maxActiveSquads
|
|||
|
|
|||
|
-- -- check rank
|
|||
|
-- local rank = ranks.get_obj_rank_name(db.actor)
|
|||
|
-- if getDangerRanks()[rank] then
|
|||
|
-- num = num + getDangerRanks()[rank]
|
|||
|
-- end
|
|||
|
|
|||
|
-- -- check reputaion
|
|||
|
-- local reputaion = utils_obj.get_reputation_name(db.actor:character_reputation())
|
|||
|
-- if getDangerReputations()[reputaion] then
|
|||
|
-- num = num + getDangerReputations()[reputaion]
|
|||
|
-- end
|
|||
|
|
|||
|
-- -- ignore if rank or rep doesn't meet the requirements
|
|||
|
-- if (num == 0) then
|
|||
|
-- return false
|
|||
|
-- end
|
|||
|
|
|||
|
-- read date
|
|||
|
local current_time = game.get_game_time()
|
|||
|
if not lastSpawnTime then
|
|||
|
lastSpawnTime = current_time
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
-- ignore if timer hasn't been reached yet
|
|||
|
local delay = settings.delayBetweenSpawns * 60 * 60
|
|||
|
if current_time:diffSec(lastSpawnTime) < delay then
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
-- try to spawn if there isn't enough mugging squads
|
|||
|
if size_table(activeSquads) < num then
|
|||
|
print_tip("-demonized_mugging_squads.spawnTimer, is valid to spawn")
|
|||
|
trySpawn()
|
|||
|
end
|
|||
|
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
function isSquadCommanderVisible(squad)
|
|||
|
local obj = squad:commander_id() and level.object_by_id(squad:commander_id())
|
|||
|
if obj then
|
|||
|
if obj:position():distance_to_sqr(db.actor:position()) < 50^2 then
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
local screenpos = game.world2ui(obj)
|
|||
|
if screenpos.x > 0 and screenpos.x < 1024 and screenpos.y > 0 and screenpos.y < 768 then
|
|||
|
if db.actor:see(obj) then
|
|||
|
return true
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
function addMoreMembersToSquad(squad, num)
|
|||
|
-- get squad positions
|
|||
|
local commander = alife_object(squad:commander_id())
|
|||
|
local pos = commander.position
|
|||
|
local lvid = commander.m_level_vertex_id
|
|||
|
local gvid = commander.m_game_vertex_id
|
|||
|
|
|||
|
local g_obj = level.object_by_id(squad:commander_id())
|
|||
|
|
|||
|
-- Spawn procedure when game object is available
|
|||
|
if g_obj then
|
|||
|
print_tip("-demonized_mugging_squads.addMoreMembersToSquad, game_object is available %s : %s", squad:name(), g_obj:name())
|
|||
|
|
|||
|
-- get npc to spawn section
|
|||
|
local random_spawn = ini_sys:r_string_ex(squad:section_name(), "npc_random")
|
|||
|
if not random_spawn then
|
|||
|
print_err("-demonized_mugging_squads.addMoreMembersToSquad, cant add members to %s, no random_spawn", squad:name())
|
|||
|
return
|
|||
|
end
|
|||
|
random_spawn = parse_names(random_spawn)
|
|||
|
|
|||
|
print_tip("-demonized_mugging_squads.addMoreMembersToSquad, add members to %s : %s", squad:name(), num)
|
|||
|
for i = 1, num do
|
|||
|
local random_sec = random_spawn[math.random(1, #random_spawn)]
|
|||
|
|
|||
|
-- add and setup new npc
|
|||
|
local sim = alife()
|
|||
|
local pos = g_obj:position()
|
|||
|
local lvid = g_obj:level_vertex_id()
|
|||
|
local gvid = g_obj:game_vertex_id()
|
|||
|
local obj = alife_create(random_sec, pos, lvid, gvid)
|
|||
|
|
|||
|
if obj then
|
|||
|
squad:register_member(obj.id)
|
|||
|
|
|||
|
local actor = sim:actor()
|
|||
|
if (simulation_objects.is_on_the_same_level(obj, actor) and pos:distance_to_sqr(actor.position) <= sim:switch_distance()^2) then
|
|||
|
db.spawned_vertex_by_id[obj.id] = lvid
|
|||
|
end
|
|||
|
|
|||
|
print_tip("-demonized_mugging_squads.addMoreMembersToSquad, spawned member %s of %s", random_sec, squad:name())
|
|||
|
else
|
|||
|
print_err("-demonized_mugging_squads.addMoreMembersToSquad, failed to spawn member %s of %s", random_sec, squad:name())
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
-- When isn't
|
|||
|
else
|
|||
|
print_tip("-demonized_mugging_squads.addMoreMembersToSquad, game_object is not available, use server object : %s", squad:name())
|
|||
|
|
|||
|
-- get squad smart
|
|||
|
local squad_smart = squad.smart_id and SIMBOARD.smarts[squad.smart_id].smrt
|
|||
|
if not squad_smart then
|
|||
|
print_err("-demonized_mugging_squads.addMoreMembersToSquad, cant add members to %s, no smart", squad:name())
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
-- get npc to spawn section
|
|||
|
local random_spawn = ini_sys:r_string_ex(squad:section_name(), "npc_random")
|
|||
|
if not random_spawn then
|
|||
|
print_err("-demonized_mugging_squads.addMoreMembersToSquad, cant add members to %s, no random_spawn", squad:name())
|
|||
|
return
|
|||
|
end
|
|||
|
random_spawn = parse_names(random_spawn)
|
|||
|
|
|||
|
print_tip("-demonized_mugging_squads.addMoreMembersToSquad, add members to %s : %s", squad:name(), num)
|
|||
|
for i = 1, num do
|
|||
|
local random_sec = random_spawn[math.random(1, #random_spawn)]
|
|||
|
|
|||
|
-- add and setup new npc
|
|||
|
local new_member_id = squad:add_squad_member(random_sec, pos, lvid, gvid)
|
|||
|
local se_obj = new_member_id and alife_object(new_member_id)
|
|||
|
if (se_obj) then
|
|||
|
print_tip("-demonized_mugging_squads.addMoreMembersToSquad, spawned member %s of %s", random_sec, squad:name())
|
|||
|
squad_smart:register_npc(se_obj)
|
|||
|
SIMBOARD:setup_squad_and_group(se_obj)
|
|||
|
else
|
|||
|
print_err("-demonized_mugging_squads.addMoreMembersToSquad, failed to spawn member %s of %s", random_sec, squad:name())
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
squad:update()
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
-- Simplified parsing of condition list
|
|||
|
defaultUseCond = "{=is_wounded} false, {!is_squad_commander} false, {=actor_enemy} false, {=has_enemy} false, {=dist_to_actor_le(3)} true, false"
|
|||
|
local function parseConditionTable(npc, conditions)
|
|||
|
for _, v in ipairs(conditions) do
|
|||
|
local functions = v[2]
|
|||
|
local val = v[1]
|
|||
|
if functions then
|
|||
|
for _, func in ipairs(functions) do
|
|||
|
local f = func[1]
|
|||
|
local args = func[3] or {}
|
|||
|
local requiredResult = func[2] == 3
|
|||
|
if xr_conditions[f] then
|
|||
|
local result = not not xr_conditions[f](db.actor, npc, args)
|
|||
|
local r = result == requiredResult
|
|||
|
if r then
|
|||
|
return val
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
else
|
|||
|
return val
|
|||
|
end
|
|||
|
end
|
|||
|
return false
|
|||
|
end
|
|||
|
function parseCondition(npc, condString)
|
|||
|
local conditions = xr_logic.parse_condlist(npc, nil, nil, condString)
|
|||
|
local result = parseConditionTable(npc, conditions)
|
|||
|
if result == "true" then
|
|||
|
result = true
|
|||
|
elseif result == "false" then
|
|||
|
result = false
|
|||
|
end
|
|||
|
return result
|
|||
|
end
|
|||
|
|
|||
|
-- Check if mugging squad is still valid for mugging
|
|||
|
function isValidActiveSquad(activeSquadId, activeSquadValue)
|
|||
|
local id = activeSquadId
|
|||
|
local v = activeSquadValue
|
|||
|
local se = alife_object(id)
|
|||
|
local squad = se
|
|||
|
|
|||
|
if not se then return false end
|
|||
|
if se:section_name() ~= v.name then return false end
|
|||
|
if squad:npc_count() == 0 then return false end
|
|||
|
|
|||
|
local allDead = true
|
|||
|
for k in squad:squad_members() do
|
|||
|
local npc_se = alife_object(k.id)
|
|||
|
if npc_se and npc_se:alive() then
|
|||
|
allDead = false
|
|||
|
break
|
|||
|
end
|
|||
|
end
|
|||
|
if allDead then return false end
|
|||
|
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
function stateTimer()
|
|||
|
ResetTimeEvent("demonized_mugging_squads", "mugging_squad_state", delayState)
|
|||
|
|
|||
|
-- clean
|
|||
|
local currentActorStage
|
|||
|
for id, v in pairs(activeSquads) do
|
|||
|
local se = alife_object(id)
|
|||
|
local squad = se
|
|||
|
|
|||
|
if not isValidActiveSquad(id, v) then
|
|||
|
print_tip("-demonized_mugging_squads.stateTimer cleaning [%s] | section: %s - actual: %s", id, v.name, se and se:section_name())
|
|||
|
invalidateSquad(se)
|
|||
|
else
|
|||
|
-- If squad is one man -- fill them up to random 2-5
|
|||
|
if squad:npc_count() <= 1 and not isSquadCommanderVisible(squad) and v.stage == squadStages.approach then
|
|||
|
local min = 3 - squad:npc_count()
|
|||
|
local max = 4
|
|||
|
addMoreMembersToSquad(squad, math.random(min, max))
|
|||
|
end
|
|||
|
|
|||
|
if v.stage == squadStages.talk then
|
|||
|
currentActorStage = squadStages.talk
|
|||
|
elseif v.stage == squadStages.done then
|
|||
|
if not (
|
|||
|
simulation_objects.is_on_the_same_level(alife():actor(), squad)
|
|||
|
and isSquadCommanderVisible(squad)
|
|||
|
) then
|
|||
|
SIMBOARD:remove_squad(squad)
|
|||
|
invalidateSquad(squad)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
if is_empty(activeSquads) then
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
-- Don't attack if actor is talking to mugging squad
|
|||
|
if currentActorStage == squadStages.talk then
|
|||
|
attack(false, false)
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
-- don't attack if actor is in a safe level
|
|||
|
if getSafeLevels()[level.name()] then
|
|||
|
attack(false, false)
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
-- don't attack if actor is in a safe smart
|
|||
|
local pos = db.actor:position()
|
|||
|
local se_actor = alife():actor()
|
|||
|
local safeSmarts = getSafeSmarts()
|
|||
|
for name, smart in pairs(currentLevelSmarts) do
|
|||
|
if safeSmarts[name] then
|
|||
|
local dist = smart.position:distance_to_sqr(pos)
|
|||
|
local safeSmartDistance = settings.safeSmartDistance * settings.safeSmartDistance
|
|||
|
if dist < safeSmartDistance then
|
|||
|
attack(false, false)
|
|||
|
return false
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
print_tip("-demonized_mugging_squads player is vulnerable to mugging, attack")
|
|||
|
attack(true, true)
|
|||
|
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
function load_state(m_data)
|
|||
|
local demonized_mugging_squads = m_data.demonized_mugging_squads
|
|||
|
if not demonized_mugging_squads then
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
if DEV_DEBUG and demonized_mugging_squads then
|
|||
|
for k, v in pairs(demonized_mugging_squads) do
|
|||
|
print_err("-demonized_mugging_squads # LOADING: Mugging Squad | [%s]: %s", k, v)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
lastSpawnTime = demonized_mugging_squads.last_spawn_time and utils_data.CTime_from_table(demonized_mugging_squads.last_spawn_time) or game.get_game_time()
|
|||
|
activeSquads = demonized_mugging_squads.active_squads or {}
|
|||
|
for k, v in pairs(activeSquads) do
|
|||
|
if type(v) ~= "table" then
|
|||
|
activeSquads[k] = {
|
|||
|
name = v,
|
|||
|
stage = 1
|
|||
|
}
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function save_state(m_data)
|
|||
|
if not lastSpawnTime then
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
local demonized_mugging_squads = {}
|
|||
|
demonized_mugging_squads.last_spawn_time = utils_data.CTime_to_table(lastSpawnTime)
|
|||
|
demonized_mugging_squads.active_squads = activeSquads or {}
|
|||
|
|
|||
|
if DEV_DEBUG then
|
|||
|
for k, v in pairs(demonized_mugging_squads) do
|
|||
|
print_err("-demonized_mugging_squads # SAVING: Mugging Squad | [%s]: %s", k, v)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
m_data.demonized_mugging_squads = demonized_mugging_squads
|
|||
|
end
|
|||
|
|
|||
|
function server_entity_on_unregister(se_obj, typ)
|
|||
|
activeSquads[se_obj.id] = nil
|
|||
|
end
|
|||
|
|
|||
|
function actor_on_first_update()
|
|||
|
if debugMode then
|
|||
|
initializeGizmos()
|
|||
|
end
|
|||
|
for name, smart in pairs(SIMBOARD.smarts_by_names) do
|
|||
|
if smart and simulation_objects.is_on_the_same_level(alife():actor(), smart) then
|
|||
|
currentLevelSmarts[name] = smart
|
|||
|
end
|
|||
|
if smart and simulation_objects.is_on_the_linked_level(alife():actor(), smart) then
|
|||
|
linkedLevelSmarts[name] = smart
|
|||
|
end
|
|||
|
end
|
|||
|
CreateTimeEvent("demonized_mugging_squads", "mugging_squad_spawn", delaySpawn, spawnTimer)
|
|||
|
CreateTimeEvent("demonized_mugging_squads", "mugging_squad_state", delayState, stateTimer)
|
|||
|
end
|
|||
|
|
|||
|
function squad_on_update(squad)
|
|||
|
local id = squad.id
|
|||
|
if not activeSquads[id] then return end
|
|||
|
|
|||
|
local commander = squad:commander_id() and level.object_by_id(squad:commander_id())
|
|||
|
local requiredGoodwill = 0
|
|||
|
|
|||
|
if commander then
|
|||
|
if debugMode then
|
|||
|
gizmos.sphereSquad.visible = true
|
|||
|
gizmos.sphereSquad.color = fcolor():set(1, 0, 0, 1)
|
|||
|
local scale_mat = matrix():identity():scale(0.1, 0.1, 0.1)
|
|||
|
local pos_mat = matrix():translate(commander:position())
|
|||
|
local mat = matrix():mul(pos_mat, scale_mat)
|
|||
|
gizmos.sphereSquad.matrix = mat
|
|||
|
end
|
|||
|
requiredGoodwill = math.max(0, -relation_registry.community_relation(character_community(commander), character_community(db.actor)))
|
|||
|
-- print_tip("setting goodwill to %s", requiredGoodwill)
|
|||
|
end
|
|||
|
|
|||
|
if squad.force_set_goodwill then
|
|||
|
squad:force_set_goodwill(requiredGoodwill, db.actor)
|
|||
|
end
|
|||
|
for k in squad:squad_members() do
|
|||
|
local obj = level.object_by_id(k.id)
|
|||
|
local se_obj = alife_object(k.id)
|
|||
|
if obj then
|
|||
|
obj:set_relation(game_object.neutral, db.actor)
|
|||
|
obj:force_set_goodwill(requiredGoodwill, db.actor)
|
|||
|
end
|
|||
|
if se_obj then
|
|||
|
se_obj:force_set_goodwill(requiredGoodwill, db.actor)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
if activeSquads[id].stage == squadStages.approach then
|
|||
|
local commander = squad:commander_id() and level.object_by_id(squad:commander_id())
|
|||
|
if commander then
|
|||
|
local condition = parseCondition(commander, defaultUseCond)
|
|||
|
if condition then
|
|||
|
print_err("-demonized_mugging_squads npc %s start to talk, pos %s, actor %s, distance %s",
|
|||
|
commander:id(),
|
|||
|
utils_data.vector_to_string(roundVec(commander:position())),
|
|||
|
utils_data.vector_to_string(roundVec(db.actor:position())),
|
|||
|
commander:position():distance_to_sqr(db.actor:position())
|
|||
|
)
|
|||
|
attack(false, false)
|
|||
|
setSquadStage(squad, squadStages.talk)
|
|||
|
if math.random() < settings.talkChance then
|
|||
|
xr_sound.stop_sounds_by_id(commander:id())
|
|||
|
xr_sound.set_sound_play(commander:id(), "mugging_hello")
|
|||
|
end
|
|||
|
forceTalk(commander)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function npc_on_before_hit(npc, shit, bone_id, flags)
|
|||
|
if shit.draftsman:id() ~= AC_ID then return end
|
|||
|
|
|||
|
local squad = get_object_squad(npc)
|
|||
|
if not squad then return end
|
|||
|
if not activeSquads[squad.id] then return end
|
|||
|
|
|||
|
invalidateSquad(squad)
|
|||
|
setSquadAsEnemy(squad)
|
|||
|
end
|
|||
|
|
|||
|
function on_game_start()
|
|||
|
RegisterScriptCallback("save_state", save_state)
|
|||
|
RegisterScriptCallback("load_state", load_state)
|
|||
|
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
|
|||
|
RegisterScriptCallback("server_entity_on_unregister", server_entity_on_unregister)
|
|||
|
|
|||
|
RegisterScriptCallback("squad_on_update", squad_on_update)
|
|||
|
RegisterScriptCallback("npc_on_before_hit", npc_on_before_hit)
|
|||
|
|
|||
|
RegisterScriptCallback("actor_on_first_update", load_settings)
|
|||
|
RegisterScriptCallback("on_option_change", load_settings)
|
|||
|
end
|
|||
|
|
|||
|
-- Scheme
|
|||
|
actid = 188125
|
|||
|
evaid = 188125
|
|||
|
class "evaluator_muggingSquadBehaviour" (property_evaluator)
|
|||
|
function evaluator_muggingSquadBehaviour:__init(npc, name, storage) super (nil, name)
|
|||
|
self.st = storage
|
|||
|
end
|
|||
|
|
|||
|
function evaluator_muggingSquadBehaviour:evaluate()
|
|||
|
local npc = self.object
|
|||
|
|
|||
|
if not npc:alive() then
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
if IsWounded(npc) then
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
if not db.actor then
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
if not db.actor:alive() then
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
local squad = get_object_squad(npc)
|
|||
|
if not squad then return false end
|
|||
|
if not activeSquads[squad.id] then return false end
|
|||
|
|
|||
|
local sq = activeSquads[squad.id]
|
|||
|
if sq.stage == squadStages.talk or sq.stage == squadStages.done then
|
|||
|
return true
|
|||
|
end
|
|||
|
|
|||
|
return false
|
|||
|
end
|
|||
|
|
|||
|
class "action_muggingSquadBehaviour" (action_base)
|
|||
|
function action_muggingSquadBehaviour:__init (npc, name, storage)
|
|||
|
super(nil, name)
|
|||
|
self.st = storage
|
|||
|
end
|
|||
|
function action_muggingSquadBehaviour:initialize()
|
|||
|
action_base.initialize(self)
|
|||
|
|
|||
|
local npc = self.object
|
|||
|
self.squad = get_object_squad(npc)
|
|||
|
self.movement_type = npc:movement_type()
|
|||
|
self.body_state = npc:body_state()
|
|||
|
self.mental_state = npc:mental_state()
|
|||
|
self.path = npc:path_type()
|
|||
|
|
|||
|
self.isCommander = self.squad:commander_id() and level.object_by_id(self.squad:commander_id()) and level.object_by_id(self.squad:commander_id()) == npc:id()
|
|||
|
|
|||
|
local activeMembers = {}
|
|||
|
local squad = self.squad
|
|||
|
for k in squad:squad_members() do
|
|||
|
local obj = level.object_by_id(k.id)
|
|||
|
if obj then
|
|||
|
table.insert(activeMembers, obj)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
self.squadMembersCount = 0
|
|||
|
self.squadMemberNum = 1
|
|||
|
for i, obj in ipairs(activeMembers) do
|
|||
|
self.squadMembersCount = self.squadMembersCount + 1
|
|||
|
if obj:id() == npc:id() then
|
|||
|
self.squadMemberNum = self.squadMembersCount
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
npc:set_desired_position()
|
|||
|
npc:set_desired_direction()
|
|||
|
self.first_update = true
|
|||
|
end
|
|||
|
|
|||
|
function action_muggingSquadBehaviour:validate(vid)
|
|||
|
local npc = self.object
|
|||
|
return vid and vid < 4294967295 and vid >= 0 -- Is existing lvid
|
|||
|
and npc:accessible(vid) -- Accessible by npc
|
|||
|
and vid ~= npc:level_vertex_id() -- Not current npc lvid
|
|||
|
and not db.used_level_vertex_ids[vid] -- Not taken by another entity
|
|||
|
and math.abs(level.vertex_position(vid).y - npc:position().y) < 2 -- Not higher or lower from npc position than this threshold so npcs wont run vertically
|
|||
|
end
|
|||
|
|
|||
|
function action_muggingSquadBehaviour:lmove(vid)
|
|||
|
-- Return if not valid
|
|||
|
if not self:validate(vid) then
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
local npc = self.object
|
|||
|
local st = self.st
|
|||
|
|
|||
|
if st.vid then
|
|||
|
db.used_level_vertex_ids[st.vid] = nil
|
|||
|
st.vid = nil
|
|||
|
end
|
|||
|
|
|||
|
db.used_level_vertex_ids[vid] = npc:id()
|
|||
|
npc:set_dest_level_vertex_id(vid)
|
|||
|
st.vid = vid
|
|||
|
return vid
|
|||
|
end
|
|||
|
|
|||
|
function action_muggingSquadBehaviour:findPos()
|
|||
|
local npc = self.object
|
|||
|
local id = npc:id()
|
|||
|
local base_point = npc:level_vertex_id()
|
|||
|
local base_point_pos = npc:position()
|
|||
|
local tries = 10
|
|||
|
|
|||
|
for i = 1, tries do
|
|||
|
-- Set new lvid and direction
|
|||
|
-- Commander stays at the front and talks
|
|||
|
-- Member #2 goes to the left of player
|
|||
|
-- Member #3 goes to the right
|
|||
|
-- Additional members surround player from the front
|
|||
|
local dir = db.actor:direction()
|
|||
|
|
|||
|
if self.squadMemberNum == 2 then
|
|||
|
dir = vector_rotate_y(dir, math.random(-90, -60))
|
|||
|
elseif self.squadMemberNum == 3 then
|
|||
|
dir = vector_rotate_y(dir, math.random(60, 90))
|
|||
|
else
|
|||
|
dir = vector_rotate_y(dir, random_choice(math.random(-55, -15), math.random(15, 55)))
|
|||
|
end
|
|||
|
|
|||
|
dir:normalize()
|
|||
|
local pos = db.actor:position():mad(dir, 2)
|
|||
|
local dist = pos:distance_to(base_point_pos)
|
|||
|
dir = vector():set(pos):sub(base_point_pos):normalize()
|
|||
|
|
|||
|
for radius = dist, 1, -1 do
|
|||
|
local lvid = level.vertex_in_direction(base_point, dir, radius)
|
|||
|
if self:validate(lvid) then
|
|||
|
self.initial_dir = level.vertex_position(lvid):sub(npc:position()):normalize()
|
|||
|
return self:lmove(lvid)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function action_muggingSquadBehaviour:execute()
|
|||
|
action_base.execute(self)
|
|||
|
|
|||
|
local npc = self.object
|
|||
|
|
|||
|
-- ensure and enforce path type
|
|||
|
if npc:path_type() ~= game_object.level_path then
|
|||
|
npc:set_path_type(game_object.level_path)
|
|||
|
end
|
|||
|
|
|||
|
local squad = activeSquads[self.squad.id]
|
|||
|
if squad.stage == squadStages.talk then
|
|||
|
-- Set panic state
|
|||
|
local bw = npc:active_item()
|
|||
|
local new_state = "panic"
|
|||
|
local lvid = self.isCommander and npc:level_vertex_id()
|
|||
|
|
|||
|
-- Find new lvid to reach
|
|||
|
if not self.isCommander then
|
|||
|
if self.st.vid then
|
|||
|
if npc:level_vertex_id() == self.st.vid then
|
|||
|
new_state = "threat_na"
|
|||
|
else
|
|||
|
npc:set_dest_level_vertex_id(self.st.vid)
|
|||
|
end
|
|||
|
lvid = self.st.vid
|
|||
|
else
|
|||
|
lvid = self:findPos()
|
|||
|
end
|
|||
|
else
|
|||
|
new_state = "threat_na"
|
|||
|
end
|
|||
|
|
|||
|
-- Set sight in direction of new lvid and confirm the state
|
|||
|
-- npc:set_sight(look.direction, lvid and level.vertex_position(lvid):sub(npc:position()):normalize() or npc:direction())
|
|||
|
state_mgr.set_state(npc, new_state, nil, nil, {
|
|||
|
-- look_position = utils_obj.safe_bone_pos(db.actor, "bip01_head"),
|
|||
|
look_object = db.actor,
|
|||
|
-- look_dir = utils_obj.safe_bone_pos(npc, "bip01_head"):sub(utils_obj.safe_bone_pos(db.actor, "bip01_head")):normalize(),
|
|||
|
}, {
|
|||
|
fast_set = true,
|
|||
|
animation = false,
|
|||
|
})
|
|||
|
elseif squad.stage == squadStages.done then
|
|||
|
-- Find a smart for mugging squad to move
|
|||
|
if not self.chosenSmart then
|
|||
|
local safeSmarts = getSafeSmarts()
|
|||
|
local smartCandidates = {}
|
|||
|
local dir = db.actor:direction()
|
|||
|
dir.y = 0
|
|||
|
dir:normalize()
|
|||
|
|
|||
|
for name, smart in pairs(currentLevelSmarts) do
|
|||
|
if not safeSmarts[name] then
|
|||
|
local pos = vector():set(smart.position)
|
|||
|
local dirToActor = pos:sub(db.actor:position()):normalize()
|
|||
|
dirToActor.y = 0
|
|||
|
dirToActor:normalize()
|
|||
|
if dirToActor:dotproduct(dir) > 0 then
|
|||
|
smartCandidates[#smartCandidates + 1] = smart
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
if is_empty(smartCandidates) then
|
|||
|
for name, smart in pairs(currentLevelSmarts) do
|
|||
|
if not safeSmarts[name] then
|
|||
|
smartCandidates[#smartCandidates + 1] = smart
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
if is_empty(smartCandidates) then
|
|||
|
for name, smart in pairs(currentLevelSmarts) do
|
|||
|
smartCandidates[#smartCandidates + 1] = smart
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
local minDist = 0
|
|||
|
for i, smart in ipairs(smartCandidates) do
|
|||
|
local dist = smart.position:distance_to_sqr(db.actor:position())
|
|||
|
if dist > minDist then
|
|||
|
minDist = dist
|
|||
|
self.chosenSmart = smart
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
if self.chosenSmart then
|
|||
|
if self.isCommander then
|
|||
|
if npc:level_vertex_id() == self.chosenSmart.m_level_vertex_id then
|
|||
|
invalidateSquad(self.squad)
|
|||
|
return
|
|||
|
end
|
|||
|
end
|
|||
|
local se = alife_object(self.squad.id)
|
|||
|
se.scripted_target = self.chosenSmart:name()
|
|||
|
se.rush_to_target = true
|
|||
|
|
|||
|
local smart = self.chosenSmart
|
|||
|
local new_state = "panic"
|
|||
|
local lvid = smart.m_level_vertex_id
|
|||
|
self.st.vid = lvid
|
|||
|
|
|||
|
npc:set_dest_level_vertex_id(lvid)
|
|||
|
|
|||
|
state_mgr.set_state(npc, new_state, nil, nil, {
|
|||
|
-- look_position = utils_obj.safe_bone_pos(db.actor, "bip01_head"),
|
|||
|
-- look_object = db.actor,
|
|||
|
-- look_dir = utils_obj.safe_bone_pos(npc, "bip01_head"):sub(utils_obj.safe_bone_pos(db.actor, "bip01_head")):normalize(),
|
|||
|
}, {
|
|||
|
fast_set = false,
|
|||
|
animation = true,
|
|||
|
})
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
-- First update force movement
|
|||
|
if self.first_update then
|
|||
|
npc:clear_animations()
|
|||
|
npc:movement_enabled(true)
|
|||
|
npc:set_movement_type(move.run)
|
|||
|
npc:set_body_state(move.standing)
|
|||
|
npc:set_mental_state(anim.panic)
|
|||
|
self.first_update = false
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function action_muggingSquadBehaviour:finalize()
|
|||
|
action_base.finalize(self)
|
|||
|
self.first_update = true
|
|||
|
self.initial_dir = nil
|
|||
|
if (self.st.vid) then
|
|||
|
db.used_level_vertex_ids[self.st.vid] = nil
|
|||
|
end
|
|||
|
self.st.vid = nil
|
|||
|
self.chosenSmart = nil
|
|||
|
|
|||
|
local npc = self.object
|
|||
|
npc:clear_animations()
|
|||
|
npc:movement_enabled(true)
|
|||
|
npc:set_movement_type(self.movement_type)
|
|||
|
npc:set_body_state(self.body_state)
|
|||
|
npc:set_mental_state(self.mental_state)
|
|||
|
-- npc:set_path_type(self.path)
|
|||
|
end
|
|||
|
|
|||
|
function setup_generic_scheme(npc, ini, scheme, section, stype, temp)
|
|||
|
local st = xr_logic.assign_storage_and_bind(npc, ini, "muggingSquadBehaviour", section, temp)
|
|||
|
end
|
|||
|
|
|||
|
function add_to_binder(npc, ini, scheme, section, storage, temp)
|
|||
|
if not npc then return end
|
|||
|
local manager = npc:motivation_action_manager()
|
|||
|
if not manager then return end
|
|||
|
|
|||
|
if not npc:alive() or npc:section() == "actor_visual_stalker" then
|
|||
|
manager:add_evaluator(evaid, property_evaluator_const(false))
|
|||
|
temp.needs_configured = false
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
local evaluator = evaluator_muggingSquadBehaviour(npc, "eva_muggingSquadBehaviour", storage)
|
|||
|
temp.action = action_muggingSquadBehaviour(npc, "act_muggingSquadBehaviour", storage)
|
|||
|
|
|||
|
if not evaluator or not temp.action then return end
|
|||
|
manager:add_evaluator(evaid, evaluator)
|
|||
|
|
|||
|
temp.action:add_precondition(world_property(stalker_ids.property_alive, true))
|
|||
|
-- temp.action:add_precondition(world_property(stalker_ids.property_danger, false))
|
|||
|
temp.action:add_precondition(world_property(evaid, true))
|
|||
|
|
|||
|
temp.action:add_effect(world_property(evaid, false))
|
|||
|
|
|||
|
manager:add_action(actid, temp.action)
|
|||
|
|
|||
|
--xr_logic.subscribe_action_for_events(npc, storage, temp.action)
|
|||
|
end
|
|||
|
|
|||
|
function configure_actions(npc, ini, scheme, section, stype, temp)
|
|||
|
if not npc then return end
|
|||
|
local manager = npc:motivation_action_manager()
|
|||
|
if not manager or not temp.action then return end
|
|||
|
|
|||
|
temp.action:add_precondition(world_property(xr_evaluators_id.sidor_wounded_base, false))
|
|||
|
temp.action:add_precondition(world_property(xr_evaluators_id.wounded_exist, false))
|
|||
|
|
|||
|
-- if (_G.schemes["rx_ff"]) then
|
|||
|
-- temp.action:add_precondition(world_property(rx_ff.evaid, false))
|
|||
|
-- end
|
|||
|
if (_G.schemes["gl"]) then
|
|||
|
temp.action:add_precondition(world_property(rx_gl.evid_gl_reload, false))
|
|||
|
end
|
|||
|
-- if (_G.schemes["facer"]) then
|
|||
|
-- temp.action:add_precondition(world_property(xrs_facer.evid_facer, false))
|
|||
|
-- temp.action:add_precondition(world_property(xrs_facer.evid_steal_up_facer, false))
|
|||
|
-- end
|
|||
|
|
|||
|
local action
|
|||
|
local p = {xr_danger.actid, stalker_ids.action_combat_planner, stalker_ids.action_danger_planner, xr_actions_id.state_mgr + 2, xr_actions_id.alife}
|
|||
|
|
|||
|
for i=1,#p do
|
|||
|
--printf("ACTION_ALIFE_ID(demonized_muggingSquadBehaviour.configure_actions): " .. tostring(p[i]))
|
|||
|
action = manager:action(p[i])
|
|||
|
if (action) then
|
|||
|
action:add_precondition(world_property(evaid, false))
|
|||
|
else
|
|||
|
printf("-demonized_mugging_squads axr_panic: no action id p[%s]", i)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function disable_generic_scheme(npc, scheme, stype)
|
|||
|
local st = db.storage[npc:id()][scheme]
|
|||
|
if st then
|
|||
|
st.enabled = false
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function npc_add_precondition(action)
|
|||
|
if not action then return end
|
|||
|
action:add_precondition(world_property(evaid, false))
|
|||
|
end
|
|||
|
|
|||
|
LoadScheme(script_name(), "muggingSquadBehaviour", modules.stype_stalker)
|
|||
|
|
|||
|
-- Dialogs
|
|||
|
local gt = game.translate_string
|
|||
|
|
|||
|
local function getNpcAndActor(a, b)
|
|||
|
local npc = a:id() == AC_ID and b or a
|
|||
|
local actor = a:id() == AC_ID and a or b
|
|||
|
return npc, actor
|
|||
|
end
|
|||
|
|
|||
|
local talkingMuggingSquadInfo
|
|||
|
local function clearTalkingMuggingSquadInfo()
|
|||
|
talkingMuggingSquadInfo = nil
|
|||
|
math.randomseed(os.time())
|
|||
|
end
|
|||
|
|
|||
|
function getRandomTranslatedText(st, faction, defaultSt)
|
|||
|
faction = faction:gsub("_npc$", "")
|
|||
|
local s = utils_data.collect_translations(st .. (faction or "") .. "_")
|
|||
|
if is_empty(s) then
|
|||
|
return gt(defaultSt) or ""
|
|||
|
else
|
|||
|
return gt(s[math.random(#s)]) or ""
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
-- These items will never be requested
|
|||
|
ignoreItemsToMug = {
|
|||
|
bolt = true,
|
|||
|
bolt_bullet = true,
|
|||
|
cash = true,
|
|||
|
}
|
|||
|
|
|||
|
function relocateEverythingFromActor(npc)
|
|||
|
local actor = db.actor
|
|||
|
local function itr(_, obj)
|
|||
|
if not ignoreItemsToMug[obj:section()] then
|
|||
|
local amount = IsItem("multiuse", obj:section()) and obj:get_remaining_uses() or 1
|
|||
|
news_manager.relocate_item(actor, "out", obj:section(), amount)
|
|||
|
actor:transfer_item(obj, npc)
|
|||
|
end
|
|||
|
end
|
|||
|
actor:iterate_inventory(itr, actor)
|
|||
|
dialogs.relocate_money(npc, actor:money(), "out")
|
|||
|
end
|
|||
|
|
|||
|
|
|||
|
function chooseRandomItemsFromActor(npc, amount)
|
|||
|
local actor = db.actor
|
|||
|
local items = {}
|
|||
|
|
|||
|
local function itr(_, obj)
|
|||
|
if not ignoreItemsToMug[obj:section()] then
|
|||
|
items[#items + 1] = obj
|
|||
|
end
|
|||
|
end
|
|||
|
actor:iterate_inventory(itr, actor)
|
|||
|
|
|||
|
--50% chance that they want max cost items
|
|||
|
if math.random() < 0.5 then
|
|||
|
table.sort(items, function(a, b) return a:cost() < b:cost() end)
|
|||
|
else
|
|||
|
shuffle(items)
|
|||
|
end
|
|||
|
|
|||
|
talkingMuggingSquadInfo.chosenItems = {}
|
|||
|
while is_not_empty(items) and amount > 0 do
|
|||
|
table.insert(talkingMuggingSquadInfo.chosenItems, table.remove(items))
|
|||
|
amount = amount - 1
|
|||
|
end
|
|||
|
return talkingMuggingSquadInfo.chosenItems
|
|||
|
end
|
|||
|
|
|||
|
function relocateChosenItemsFromActor(npc, items)
|
|||
|
local actor = db.actor
|
|||
|
items = items or {}
|
|||
|
for _, obj in ipairs(items) do
|
|||
|
local amount = IsItem("multiuse", obj:section()) and obj:get_remaining_uses() or 1
|
|||
|
news_manager.relocate_item(actor, "out", obj:section(), amount)
|
|||
|
actor:transfer_item(obj, npc)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
function relocateRandomMoneyFromActor(npc)
|
|||
|
local actor = db.actor
|
|||
|
|
|||
|
-- 15% chance to request all money
|
|||
|
if math.random() < 0.15 then
|
|||
|
dialogs.relocate_money(npc, actor:money(), "out")
|
|||
|
else
|
|||
|
--Up to 50% of money, minimum 1000, in 100 fractions
|
|||
|
local money = actor:money()
|
|||
|
if money <= 1000 then
|
|||
|
dialogs.relocate_money(npc, money, "out")
|
|||
|
else
|
|||
|
money = math.random(1000, math.floor(money / 2))
|
|||
|
money = math.max(1000, math.floor(money / 100) * 100)
|
|||
|
dialogs.relocate_money(npc, money, "out")
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
-- Determine what squad wants from actor
|
|||
|
-- Below are lists of functions that returns a table with texts that will determine what squad wants and a function that will be applied in demonized_mugging_squads_give_my_stuff function
|
|||
|
-- Defaults
|
|||
|
function defaultMuggingOption(squad, npc, actor)
|
|||
|
local faction = character_community(npc)
|
|||
|
|
|||
|
local whoAreYouText
|
|||
|
local requestText
|
|||
|
local requestFunc
|
|||
|
local agreeText
|
|||
|
local rejectText
|
|||
|
local GTFOText
|
|||
|
local GTFOOkText
|
|||
|
|
|||
|
whoAreYouText = function()
|
|||
|
return getRandomTranslatedText("mugging_who_are_you_", faction, "mugging_who_are_you")
|
|||
|
end
|
|||
|
requestText = function()
|
|||
|
return gt("mugging_give_me_stuff") or ""
|
|||
|
end
|
|||
|
requestFunc = function()
|
|||
|
relocateRandomMoneyFromActor(npc)
|
|||
|
end
|
|||
|
agreeText = function()
|
|||
|
return gt("mugging_here_is_my_stuff") or ""
|
|||
|
end
|
|||
|
rejectText = function()
|
|||
|
return gt("mugging_fuck_you_and_start_fight") or ""
|
|||
|
end
|
|||
|
GTFOText = function()
|
|||
|
return gt("mugging_thank_you") or ""
|
|||
|
end
|
|||
|
GTFOOkText = function()
|
|||
|
return gt("mugging_ok") or ""
|
|||
|
end
|
|||
|
|
|||
|
return {
|
|||
|
whoAreYouText = whoAreYouText,
|
|||
|
requestText = requestText,
|
|||
|
requestFunc = requestFunc,
|
|||
|
agreeText = agreeText,
|
|||
|
rejectText = rejectText,
|
|||
|
GTFOText = GTFOText,
|
|||
|
GTFOOkText = GTFOOkText,
|
|||
|
}
|
|||
|
end
|
|||
|
|
|||
|
-- Get all items from actor
|
|||
|
function allItemsMuggingOption(squad, npc, actor)
|
|||
|
local faction = character_community(npc)
|
|||
|
|
|||
|
local whoAreYouText
|
|||
|
local requestText
|
|||
|
local requestFunc
|
|||
|
local agreeText
|
|||
|
local rejectText
|
|||
|
local GTFOText
|
|||
|
local GTFOOkText
|
|||
|
|
|||
|
whoAreYouText = function()
|
|||
|
return getRandomTranslatedText("mugging_who_are_you_", faction, "mugging_who_are_you")
|
|||
|
end
|
|||
|
requestText = function()
|
|||
|
return getRandomTranslatedText("mugging_give_me_all_stuff_", faction, "mugging_give_me_all_stuff")
|
|||
|
end
|
|||
|
requestFunc = function()
|
|||
|
relocateEverythingFromActor(npc)
|
|||
|
end
|
|||
|
agreeText = function()
|
|||
|
return getRandomTranslatedText("mugging_here_is_all_my_stuff_", faction, "mugging_here_is_all_my_stuff")
|
|||
|
end
|
|||
|
rejectText = function()
|
|||
|
return getRandomTranslatedText("mugging_fuck_you_and_start_fight_", faction, "mugging_fuck_you_and_start_fight")
|
|||
|
end
|
|||
|
GTFOText = function()
|
|||
|
return getRandomTranslatedText("mugging_thank_you_", faction, "mugging_thank_you")
|
|||
|
end
|
|||
|
GTFOOkText = function()
|
|||
|
return getRandomTranslatedText("mugging_finish_", faction, "mugging_finish")
|
|||
|
end
|
|||
|
|
|||
|
return {
|
|||
|
whoAreYouText = whoAreYouText,
|
|||
|
requestText = requestText,
|
|||
|
requestFunc = requestFunc,
|
|||
|
agreeText = agreeText,
|
|||
|
rejectText = rejectText,
|
|||
|
GTFOText = GTFOText,
|
|||
|
GTFOOkText = GTFOOkText,
|
|||
|
}
|
|||
|
end
|
|||
|
|
|||
|
function moneyMuggingOption(squad, npc, actor)
|
|||
|
local faction = character_community(npc)
|
|||
|
|
|||
|
local whoAreYouText
|
|||
|
local requestText
|
|||
|
local requestFunc
|
|||
|
local agreeText
|
|||
|
local rejectText
|
|||
|
local GTFOText
|
|||
|
local GTFOOkText
|
|||
|
|
|||
|
whoAreYouText = function()
|
|||
|
return getRandomTranslatedText("mugging_who_are_you_", faction, "mugging_who_are_you")
|
|||
|
end
|
|||
|
requestText = function()
|
|||
|
return getRandomTranslatedText("mugging_give_me_money_", faction, "mugging_give_me_money")
|
|||
|
end
|
|||
|
requestFunc = function()
|
|||
|
relocateRandomMoneyFromActor(npc)
|
|||
|
end
|
|||
|
agreeText = function()
|
|||
|
return getRandomTranslatedText("mugging_here_is_my_stuff_", faction, "mugging_here_is_my_stuff")
|
|||
|
end
|
|||
|
rejectText = function()
|
|||
|
return getRandomTranslatedText("mugging_fuck_you_and_start_fight_", faction, "mugging_fuck_you_and_start_fight")
|
|||
|
end
|
|||
|
GTFOText = function()
|
|||
|
return getRandomTranslatedText("mugging_thank_you_", faction, "mugging_thank_you")
|
|||
|
end
|
|||
|
GTFOOkText = function()
|
|||
|
return getRandomTranslatedText("mugging_finish_", faction, "mugging_finish")
|
|||
|
end
|
|||
|
|
|||
|
return {
|
|||
|
whoAreYouText = whoAreYouText,
|
|||
|
requestText = requestText,
|
|||
|
requestFunc = requestFunc,
|
|||
|
agreeText = agreeText,
|
|||
|
rejectText = rejectText,
|
|||
|
GTFOText = GTFOText,
|
|||
|
GTFOOkText = GTFOOkText,
|
|||
|
}
|
|||
|
end
|
|||
|
|
|||
|
function someItemsMuggingOption(squad, npc, actor)
|
|||
|
local faction = character_community(npc)
|
|||
|
|
|||
|
local whoAreYouText
|
|||
|
local requestText
|
|||
|
local requestFunc
|
|||
|
local agreeText
|
|||
|
local rejectText
|
|||
|
local GTFOText
|
|||
|
local GTFOOkText
|
|||
|
|
|||
|
whoAreYouText = function()
|
|||
|
return getRandomTranslatedText("mugging_who_are_you_", faction, "mugging_who_are_you")
|
|||
|
end
|
|||
|
requestText = function()
|
|||
|
local items = chooseRandomItemsFromActor(npc, math.random(5))
|
|||
|
local s = getRandomTranslatedText("mugging_give_me_some_item_", faction, "mugging_give_me_some_item")
|
|||
|
for _, item in ipairs(items) do
|
|||
|
s = s .. "\\n <20> " .. ui_item.get_sec_name(item:section())
|
|||
|
end
|
|||
|
return s
|
|||
|
end
|
|||
|
requestFunc = function()
|
|||
|
relocateChosenItemsFromActor(npc, talkingMuggingSquadInfo.chosenItems)
|
|||
|
end
|
|||
|
agreeText = function()
|
|||
|
return getRandomTranslatedText("mugging_here_is_my_stuff_", faction, "mugging_here_is_my_stuff")
|
|||
|
end
|
|||
|
rejectText = function()
|
|||
|
return getRandomTranslatedText("mugging_fuck_you_and_start_fight_", faction, "mugging_fuck_you_and_start_fight")
|
|||
|
end
|
|||
|
GTFOText = function()
|
|||
|
return getRandomTranslatedText("mugging_thank_you_", faction, "mugging_thank_you")
|
|||
|
end
|
|||
|
GTFOOkText = function()
|
|||
|
return getRandomTranslatedText("mugging_finish_", faction, "mugging_finish")
|
|||
|
end
|
|||
|
|
|||
|
return {
|
|||
|
whoAreYouText = whoAreYouText,
|
|||
|
requestText = requestText,
|
|||
|
requestFunc = requestFunc,
|
|||
|
agreeText = agreeText,
|
|||
|
rejectText = rejectText,
|
|||
|
GTFOText = GTFOText,
|
|||
|
GTFOOkText = GTFOOkText,
|
|||
|
}
|
|||
|
end
|
|||
|
|
|||
|
function convertToNewFaction(squad, npc, actor)
|
|||
|
dialogs.break_dialog(npc, actor)
|
|||
|
invalidateSquad(squad)
|
|||
|
|
|||
|
-- Set new community
|
|||
|
local faction = character_community(npc)
|
|||
|
|
|||
|
-- Give default armor
|
|||
|
local armorPriority = {
|
|||
|
outfit_novice = 1,
|
|||
|
outfit_light = 2,
|
|||
|
outfit_medium = 3,
|
|||
|
outfit_heavy = 4,
|
|||
|
outfit_exo = 5,
|
|||
|
}
|
|||
|
local currentBestArmor
|
|||
|
local currentBestArmorPriority = 1
|
|||
|
local function itr(_, obj)
|
|||
|
if IsOutfit(obj) then
|
|||
|
local outfit = obj
|
|||
|
local repair_type = SYS_GetParam(0, outfit:section(), "repair_type", "")
|
|||
|
local priority = armorPriority[repair_type] or 1
|
|||
|
if outfit:condition() >= 0.5 and priority >= currentBestArmorPriority then
|
|||
|
currentBestArmor = outfit
|
|||
|
currentBestArmorPriority = priority
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
actor:iterate_inventory(itr, actor)
|
|||
|
|
|||
|
-- Find best suited armor given initial armor
|
|||
|
local newArmorCandidates = {}
|
|||
|
local newArmor
|
|||
|
ini_sys:section_for_each(function(section)
|
|||
|
local community = SYS_GetParam(0, section, "community", "")
|
|||
|
local repair_type = SYS_GetParam(0, section, "repair_type", "")
|
|||
|
if community == faction and armorPriority[repair_type] and armorPriority[repair_type] <= currentBestArmorPriority then
|
|||
|
newArmorCandidates[#newArmorCandidates + 1] = {
|
|||
|
section = section,
|
|||
|
priority = armorPriority[repair_type]
|
|||
|
}
|
|||
|
end
|
|||
|
end)
|
|||
|
|
|||
|
-- Filter armor by the best
|
|||
|
if is_not_empty(newArmorCandidates) then
|
|||
|
local newArmors = {}
|
|||
|
local newBestPriority = 1
|
|||
|
table.sort(newArmorCandidates, function(a, b) return a.priority > b.priority end)
|
|||
|
|
|||
|
for i, v in ipairs(newArmorCandidates) do
|
|||
|
if is_not_empty(newArmors) then
|
|||
|
if v.priority == newBestPriority then
|
|||
|
newArmors[#newArmors + 1] = v.section
|
|||
|
else
|
|||
|
break
|
|||
|
end
|
|||
|
else
|
|||
|
if v.priority <= currentBestArmorPriority then
|
|||
|
newBestPriority = v.priority
|
|||
|
newArmors[#newArmors + 1] = v.section
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
if is_empty(newArmors) then
|
|||
|
print_err("-demonized_mugging_squads Failed to find best suited armor of faction %s, pick random", faction)
|
|||
|
newArmors[#newArmors + 1] = newArmorCandidates[math.random(#newArmorCandidates)].section
|
|||
|
end
|
|||
|
|
|||
|
newArmor = newArmors[math.random(#newArmors)]
|
|||
|
else
|
|||
|
print_err("-demonized_mugging_squads Failed to find any armors of faction %s, dont do anything", faction)
|
|||
|
end
|
|||
|
|
|||
|
-- Set teleport to main faction base
|
|||
|
local startLocationCandidates = {}
|
|||
|
local startLocation
|
|||
|
local ini_map = ini_file("plugins\\new_game_start_locations.ltx")
|
|||
|
ini_map:section_for_each(function(section)
|
|||
|
if section:find("^" .. faction .. "_start_location") then
|
|||
|
local n = ini_map:line_count(section)
|
|||
|
if n > 0 then
|
|||
|
for i = 0,n-1 do
|
|||
|
local res,id,val = ini_map:r_line(section,i,"","")
|
|||
|
local levelParams = str_explode(val, ",")
|
|||
|
|
|||
|
-- Only levels with defined story_only variable is available to ensure same location as in new game screen
|
|||
|
if levelParams[2] == "true" or levelParams[2] == "false" then
|
|||
|
print_err("-demonized_mugging_squads add location candidate for %s: %s, %s", faction, id, val)
|
|||
|
startLocationCandidates[#startLocationCandidates + 1] = {
|
|||
|
name = id,
|
|||
|
params = val
|
|||
|
}
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end)
|
|||
|
|
|||
|
if is_not_empty(startLocationCandidates) then
|
|||
|
local location = startLocationCandidates[1]
|
|||
|
local level = str_explode(location.params, ",")[1]
|
|||
|
local params = utils_data.collect_section(ini_map, location.name, true)
|
|||
|
startLocation = {
|
|||
|
name = location.name,
|
|||
|
level = level,
|
|||
|
lvid = tonumber(params.lvid),
|
|||
|
gvid = tonumber(params.gvid),
|
|||
|
x = tonumber(params.x),
|
|||
|
y = tonumber(params.y),
|
|||
|
z = tonumber(params.z)
|
|||
|
}
|
|||
|
else
|
|||
|
print_err("-demonized_mugging_squads failed to find start location for faction %s", faction)
|
|||
|
end
|
|||
|
|
|||
|
if not startLocation then
|
|||
|
return
|
|||
|
end
|
|||
|
|
|||
|
-- If all is well - do it
|
|||
|
if newArmor then
|
|||
|
if currentBestArmor then
|
|||
|
alife_release(currentBestArmor)
|
|||
|
end
|
|||
|
local se_obj = alife_create_item(newArmor, actor)
|
|||
|
CreateTimeEvent("newArmorMoveToRuck", 0, 0, function()
|
|||
|
local obj = level.object_by_id(se_obj.id)
|
|||
|
if obj then
|
|||
|
actor:move_to_slot(obj, 7)
|
|||
|
return true
|
|||
|
end
|
|||
|
return false
|
|||
|
end)
|
|||
|
end
|
|||
|
|
|||
|
print_err("-demonized_mugging_squads change faction to %s", faction)
|
|||
|
set_actor_true_community(faction, true)
|
|||
|
relation_registry.set_community_goodwill(faction, AC_ID, 200)
|
|||
|
|
|||
|
-- Give psy helmet if factions are Sin or Monolith
|
|||
|
if (faction == "greh" or faction == "monolith") and not (db.actor:object("good_psy_helmet") or db.actor:object("bad_psy_helmet")) then
|
|||
|
alife_create_item("good_psy_helmet", actor)
|
|||
|
news_manager.relocate_item(actor, "in", "good_psy_helmet")
|
|||
|
end
|
|||
|
|
|||
|
CreateTimeEvent("muggingConvertionChangeLevel", 0, 0.5, function()
|
|||
|
print_err("-demonized_mugging_squads commence change location to %s: %s: %s;%s;%s, %s, %s", startLocation.name, startLocation.level, round_idp(startLocation.x, 2), round_idp(startLocation.y, 2), round_idp(startLocation.z, 2), startLocation.lvid, startLocation.gvid)
|
|||
|
ChangeLevel(vector():set(startLocation.x, startLocation.y, startLocation.z), startLocation.lvid, startLocation.gvid, VEC_ZERO, true)
|
|||
|
clearTalkingMuggingSquadInfo()
|
|||
|
return true
|
|||
|
end)
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
function factionConvertionOption(squad, npc, actor)
|
|||
|
local faction = character_community(npc)
|
|||
|
|
|||
|
local whoAreYouText
|
|||
|
local requestText
|
|||
|
local requestFunc
|
|||
|
local agreeText
|
|||
|
local rejectText
|
|||
|
local GTFOText
|
|||
|
local GTFOOkText
|
|||
|
|
|||
|
whoAreYouText = function()
|
|||
|
return getRandomTranslatedText("mugging_who_are_you_", faction, "mugging_who_are_you")
|
|||
|
end
|
|||
|
requestText = function()
|
|||
|
return getRandomTranslatedText("mugging_convert_to_us_", faction, "mugging_convert_to_us")
|
|||
|
end
|
|||
|
requestFunc = function()
|
|||
|
convertToNewFaction(squad, npc, actor)
|
|||
|
end
|
|||
|
agreeText = function()
|
|||
|
return getRandomTranslatedText("mugging_convert_agree_", faction, "mugging_convert_agree")
|
|||
|
end
|
|||
|
rejectText = function()
|
|||
|
return getRandomTranslatedText("mugging_fuck_you_and_start_fight_", faction, "mugging_fuck_you_and_start_fight")
|
|||
|
end
|
|||
|
GTFOText = function()
|
|||
|
return getRandomTranslatedText("mugging_thank_you_", faction, "mugging_thank_you")
|
|||
|
end
|
|||
|
GTFOOkText = function()
|
|||
|
return getRandomTranslatedText("mugging_finish_", faction, "mugging_finish")
|
|||
|
end
|
|||
|
|
|||
|
return {
|
|||
|
whoAreYouText = whoAreYouText,
|
|||
|
requestText = requestText,
|
|||
|
requestFunc = requestFunc,
|
|||
|
agreeText = agreeText,
|
|||
|
rejectText = rejectText,
|
|||
|
GTFOText = GTFOText,
|
|||
|
GTFOOkText = GTFOOkText,
|
|||
|
}
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_prepare_dialog_info(a, b)
|
|||
|
local gameTime = game.get_game_time()
|
|||
|
local Y, M, D, h, m, s, ms = 0, 0, 0, 0, 0, 0, 0
|
|||
|
Y, M, D, h, m, s, ms = gameTime:get(Y, M, D, h, m, s, ms)
|
|||
|
local seed = tonumber(Y .. M .. D .. h)
|
|||
|
math.randomseed(seed)
|
|||
|
|
|||
|
local npc, actor = getNpcAndActor(a, b)
|
|||
|
local squad = get_object_squad(npc)
|
|||
|
talkingMuggingSquadInfo = {
|
|||
|
count = squad:npc_count(),
|
|||
|
squad = squad,
|
|||
|
faction = character_community(npc),
|
|||
|
option = pickMuggingOption(squad, npc, actor),
|
|||
|
seed = seed
|
|||
|
}
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_text_stop_right_there()
|
|||
|
local npc = mob_trade.GetTalkingNpc()
|
|||
|
if npc then
|
|||
|
local faction = character_community(npc)
|
|||
|
return getRandomTranslatedText("mugging_stop_right_there_", faction, "mugging_stop_right_there")
|
|||
|
end
|
|||
|
return gt("mugging_stop_right_there") or ""
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_text_who_are_you()
|
|||
|
return talkingMuggingSquadInfo.option.whoAreYouText()
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_text_give_me_stuff()
|
|||
|
return talkingMuggingSquadInfo.option.requestText()
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_text_here_is_my_stuff()
|
|||
|
return talkingMuggingSquadInfo.option.agreeText()
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_give_my_stuff()
|
|||
|
talkingMuggingSquadInfo.option.requestFunc()
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_text_thank_you_and_gtfo()
|
|||
|
return talkingMuggingSquadInfo.option.GTFOText()
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_text_ok()
|
|||
|
return talkingMuggingSquadInfo.option.GTFOOkText()
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_text_fuck_you_and_start_fight()
|
|||
|
return talkingMuggingSquadInfo.option.rejectText()
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_break_dialog(a, b)
|
|||
|
dialogs.break_dialog(a, b)
|
|||
|
local npc, actor = getNpcAndActor(a, b)
|
|||
|
local squad = get_object_squad(npc)
|
|||
|
setSquadStage(squad, squadStages.done)
|
|||
|
clearTalkingMuggingSquadInfo()
|
|||
|
end
|
|||
|
|
|||
|
function dialogs.demonized_mugging_squads_fuck_you_and_start_fight(a, b)
|
|||
|
dialogs.break_dialog(a, b)
|
|||
|
local npc, actor = getNpcAndActor(a, b)
|
|||
|
local squad = get_object_squad(npc)
|
|||
|
invalidateSquad(squad)
|
|||
|
setSquadAsEnemy(squad)
|
|||
|
if math.random() < settings.talkChance then
|
|||
|
xr_sound.stop_sounds_by_id(npc:id())
|
|||
|
xr_sound.set_sound_play(npc:id(), "mugging_fight")
|
|||
|
end
|
|||
|
clearTalkingMuggingSquadInfo()
|
|||
|
end
|
|||
|
|
|||
|
-- Set mugging options per squad here
|
|||
|
factionToMuggingOptions = {}
|
|||
|
factionToMuggingOptions.bandit = function(squad, npc, actor)
|
|||
|
-- 15% chance that they want all items
|
|||
|
if math.random() < 0.15 then
|
|||
|
return allItemsMuggingOption(squad, npc, actor)
|
|||
|
else
|
|||
|
-- choose either money or one item
|
|||
|
if math.random() < 0.5 then
|
|||
|
return someItemsMuggingOption(squad, npc, actor)
|
|||
|
else
|
|||
|
return moneyMuggingOption(squad, npc, actor)
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
factionToMuggingOptions.renegade = factionToMuggingOptions.bandit
|
|||
|
factionToMuggingOptions.killer = function(squad, npc, actor)
|
|||
|
return moneyMuggingOption(squad, npc, actor)
|
|||
|
end
|
|||
|
factionToMuggingOptions.isg = factionToMuggingOptions.killer
|
|||
|
factionToMuggingOptions.monolith = function(squad, npc, actor)
|
|||
|
return factionConvertionOption(squad, npc, actor)
|
|||
|
end
|
|||
|
factionToMuggingOptions.greh = factionToMuggingOptions.monolith
|
|||
|
|
|||
|
function pickMuggingOption(squad, npc, actor)
|
|||
|
local faction = character_community(npc)
|
|||
|
local result = factionToMuggingOptions[faction] and factionToMuggingOptions[faction](squad, npc, actor) or defaultMuggingOption(squad, npc, actor)
|
|||
|
return result
|
|||
|
end
|