461 lines
12 KiB
Plaintext
461 lines
12 KiB
Plaintext
|
--[[
|
||
|
------------------------------------------------------------
|
||
|
-- Survival Mode Remade - Extra items from stash boxes
|
||
|
------------------------------------------------------------
|
||
|
-- MCM-configurable script to give the player a chance to get some extra items whenever they open a stash box.
|
||
|
-- by dph-hcl
|
||
|
------------------------------------------------------------
|
||
|
]]--
|
||
|
|
||
|
-- REPAIR KITS
|
||
|
local repair_tier1 = {
|
||
|
"glue_a",
|
||
|
"glue_b",
|
||
|
"glue_e",
|
||
|
"gun_oil",
|
||
|
"gun_oil_ru",
|
||
|
"gun_oil_ru_d",
|
||
|
"armor_repair_fa",
|
||
|
"sharpening_stones",
|
||
|
}
|
||
|
|
||
|
local repair_tier2 = {
|
||
|
"sharpening_stones",
|
||
|
"cleaning_kit_p",
|
||
|
"cleaning_kit_s",
|
||
|
"cleaning_kit_r5",
|
||
|
"cleaning_kit_r7",
|
||
|
"sewing_kit_b",
|
||
|
"sewing_kit_a",
|
||
|
}
|
||
|
|
||
|
local repair_tier3 = {
|
||
|
"cleaning_kit_u",
|
||
|
"toolkit_p",
|
||
|
"toolkit_s",
|
||
|
"sewing_kit_h",
|
||
|
"medium_repair_kit",
|
||
|
"helmet_repair_kit",
|
||
|
"light_repair_kit",
|
||
|
}
|
||
|
|
||
|
local repair_tier4 = {
|
||
|
"toolkit_r5",
|
||
|
"toolkit_r7",
|
||
|
"heavy_repair_kit",
|
||
|
"exo_repair_kit",
|
||
|
}
|
||
|
|
||
|
-- BASIC AMMO
|
||
|
local basic_ammo = {
|
||
|
"ammo_11.43x23_fmj",
|
||
|
"ammo_12x70_buck",
|
||
|
"ammo_7.62x25_p",
|
||
|
"ammo_12x76_zhekan",
|
||
|
"ammo_5.45x39_fmj",
|
||
|
"ammo_5.45x39_ep",
|
||
|
"ammo_5.56x45_fmj",
|
||
|
"ammo_5.56x45_ss190",
|
||
|
"ammo_9x18_fmj",
|
||
|
"ammo_9x19_fmj",
|
||
|
"ammo_11.43x23_hydro",
|
||
|
"ammo_12x76_dart",
|
||
|
"ammo_7.62x25_ps",
|
||
|
"ammo_5.45x39_ap",
|
||
|
"ammo_5.56x45_ap",
|
||
|
"ammo_9x18_ap",
|
||
|
"ammo_9x18_pmm",
|
||
|
"ammo_9x19_ap",
|
||
|
"ammo_9x19_pbp",
|
||
|
}
|
||
|
|
||
|
-- ADVANCED AMMO
|
||
|
local advanced_ammo = {
|
||
|
"ammo_357_hp_mag",
|
||
|
"ammo_7.62x39_fmj",
|
||
|
"ammo_7.62x51_fmj",
|
||
|
"ammo_7.62x54_7h1",
|
||
|
"ammo_9x39_pab9",
|
||
|
"ammo_7.62x39_ap",
|
||
|
"ammo_7.62x51_ap",
|
||
|
"ammo_7.62x54_7h14",
|
||
|
"ammo_7.62x54_ap",
|
||
|
"ammo_9x39_ap",
|
||
|
}
|
||
|
|
||
|
-- EXOTIC AMMO
|
||
|
local exotic_ammo = {
|
||
|
"ammo_12.7x55_fmj",
|
||
|
"ammo_4.6x30_fmj",
|
||
|
"ammo_5.7x28_ss195",
|
||
|
"ammo_7.92x33_fmj",
|
||
|
"ammo_m209",
|
||
|
"ammo_vog-25",
|
||
|
"ammo_12.7x55_ap",
|
||
|
"ammo_5.7x28_ss190",
|
||
|
"ammo_50_bmg",
|
||
|
"ammo_7.92x33_ap",
|
||
|
"ammo_magnum_300",
|
||
|
"ammo_pkm_100",
|
||
|
"ammo_gauss",
|
||
|
}
|
||
|
|
||
|
-- USEFUL ITEMS
|
||
|
local useful_tier1 = {
|
||
|
"device_torch_dummy",
|
||
|
"batteries_dead", "batteries_dead", "batteries_dead",
|
||
|
"detector_simple",
|
||
|
"af_iam",
|
||
|
"itm_sleepbag",
|
||
|
"wpn_knife2",
|
||
|
"wpn_axe",
|
||
|
"kit_hunt",
|
||
|
"wpn_binoc_inv",
|
||
|
"itm_actor_backpack",
|
||
|
"leatherman_tool",
|
||
|
"itm_sleepbag",
|
||
|
"equ_small_pack",
|
||
|
"af_aac",
|
||
|
}
|
||
|
|
||
|
local useful_tier2 = {
|
||
|
"device_torch_nv_1",
|
||
|
"detector_advanced",
|
||
|
"wpn_knife3",
|
||
|
"wpn_axe2",
|
||
|
"equ_small_military_pack",
|
||
|
"itm_tent",
|
||
|
}
|
||
|
|
||
|
local useful_tier3 = {
|
||
|
"device_torch_nv_2",
|
||
|
"detector_scientific",
|
||
|
"wpn_knife4",
|
||
|
"wpn_knife5",
|
||
|
"wpn_axe3",
|
||
|
"equ_military_pack",
|
||
|
}
|
||
|
|
||
|
local useful_tier4 = {
|
||
|
"device_torch_nv_3",
|
||
|
"detector_elite",
|
||
|
"af_aam",
|
||
|
"equ_tourist_pack",
|
||
|
}
|
||
|
|
||
|
-- MEDICAL ITEMS
|
||
|
|
||
|
local meds_tier1 = {
|
||
|
"bandage",
|
||
|
"caffeine",
|
||
|
"drug_sleepingpills",
|
||
|
"drug_coagulant",
|
||
|
"yadylin",
|
||
|
"medkit",
|
||
|
"jgut",
|
||
|
"glucose_s",
|
||
|
"antirad",
|
||
|
"antirad_cystamine",
|
||
|
}
|
||
|
|
||
|
local meds_tier2 = {
|
||
|
"medkit_army",
|
||
|
"stimpack",
|
||
|
"salicidic_acid",
|
||
|
"glucose",
|
||
|
"drug_psy_blockade",
|
||
|
"antirad_kalium",
|
||
|
"medkit_ai1",
|
||
|
"akvatab",
|
||
|
}
|
||
|
|
||
|
local meds_tier3 = {
|
||
|
"medkit_scientic",
|
||
|
"stimpack_army",
|
||
|
"morphine",
|
||
|
"drug_radioprotector",
|
||
|
"medkit_ai3",
|
||
|
"adrenalin",
|
||
|
"drug_anabiotic",
|
||
|
}
|
||
|
|
||
|
local meds_tier4 = {
|
||
|
"stimpack_scientic",
|
||
|
"survival_kit",
|
||
|
"medkit_ai2",
|
||
|
}
|
||
|
|
||
|
local lootboxes_tier1 = {
|
||
|
"lootbox_1",
|
||
|
"lootbox_11",
|
||
|
"lootbox_2",
|
||
|
"lootbox_5",
|
||
|
"lootbox_51",
|
||
|
}
|
||
|
|
||
|
local lootboxes_tier2 = {
|
||
|
"lootbox_7",
|
||
|
"lootbox_4",
|
||
|
"lootbox_41",
|
||
|
"lootbox_6",
|
||
|
"lootbox_61",
|
||
|
"lootbox_71",
|
||
|
"lootbox_3",
|
||
|
}
|
||
|
|
||
|
local lootboxes_tier3 = {
|
||
|
"lootbox_8",
|
||
|
"lootbox_81",
|
||
|
"lootbox_9",
|
||
|
}
|
||
|
|
||
|
|
||
|
-- table of already looted boxes
|
||
|
local boxes = {}
|
||
|
-- table of already looted npcs
|
||
|
local npcs = {}
|
||
|
|
||
|
local pda_msg_status = true
|
||
|
|
||
|
local function pda_message(type)
|
||
|
local strs = {
|
||
|
["repair"] = "st_smr_loot_found_repair",
|
||
|
["ammo"] = "st_smr_loot_found_ammo",
|
||
|
["meds"] = "st_smr_loot_found_meds",
|
||
|
["useful"] = "st_smr_loot_found_useful",
|
||
|
["mags"] = "st_smr_loot_found_mags",
|
||
|
["lootbox"] = "st_smr_loot_found_lootbox",
|
||
|
|
||
|
}
|
||
|
if (not smr_loot_mcm.get_config("send_message")) or (not pda_msg_status) then
|
||
|
return
|
||
|
end
|
||
|
db.actor:give_game_news(game.translate_string(strs[type]), "", "ui_inGame2_Polucheni_koordinaty_taynika", 0, 3000)
|
||
|
smr_debug.get_log().info("loot/general", "PDA message sent: %s", strs[type])
|
||
|
xr_sound.set_sound_play(AC_ID, "pda_tips")
|
||
|
end
|
||
|
|
||
|
-- creates an item with a random amount of uses or condition
|
||
|
local function create_item_random_uses(i, box)
|
||
|
smr_debug.get_log().info("loot/general", "Creating item with random uses: %s", i)
|
||
|
local max_uses = ini_sys:r_float_ex(i, "max_uses")
|
||
|
local se_item = alife_create_item(i, box)
|
||
|
if max_uses then
|
||
|
alife_process_item(i, se_item.id, {uses = (math.random(1, max_uses))})
|
||
|
elseif utils_item.is_degradable(nil, se_item.id) then
|
||
|
alife_process_item(i, se_item.id, {cond = (math.random(50,100)/100)})
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function roll_item_tiered(t, box)
|
||
|
local r = math.random(1,100)
|
||
|
table.sort(t, function(a, b) return a[1] > b[1] end)
|
||
|
for i, n in ipairs(t) do
|
||
|
if (r >= n[1]) then
|
||
|
local itm = n[2][math.random(#n[2])]
|
||
|
smr_debug.get_log().info("loot/rolls", "Rolled succesfully for %s (%s >= %s)", itm, r, n[1])
|
||
|
create_item_random_uses(itm, box)
|
||
|
return true
|
||
|
end
|
||
|
end
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
function try_spawn_lootbox(box)
|
||
|
if math.random(1,100) <= smr_zzintegration_mcm.get_config("lootboxes_chance") then
|
||
|
pda_message("lootbox")
|
||
|
local tbl = {
|
||
|
{ 90, lootboxes_tier3},
|
||
|
{ 50, lootboxes_tier2},
|
||
|
{ 0, lootboxes_tier1},
|
||
|
}
|
||
|
roll_item_tiered(tbl, box)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function try_spawn_mag(box)
|
||
|
if math.random(1,100) <= smr_zzintegration_mcm.get_config("mags_redux_chance") then
|
||
|
smr_debug.get_log().info("integration", "Rolling for magazine")
|
||
|
local mags = {}
|
||
|
for i=1,3 do
|
||
|
local wpn = db.actor:item_in_slot(i)
|
||
|
if wpn and magazine_binder.is_supported_weapon(wpn) then
|
||
|
mags = magazine_binder.get_mags_for_basetype(magazine_binder.get_weapon_base_type(wpn))
|
||
|
end
|
||
|
end
|
||
|
if (next(mags) == nil) then
|
||
|
return
|
||
|
end
|
||
|
pda_message("mags")
|
||
|
alife_create_item(mags[math.random(#mags)], box)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- rolls for a repair kit, and spawns if sucessful
|
||
|
function try_spawn_repair(box)
|
||
|
if math.random(1,100) <= smr_loot_mcm.get_config("repair_chance") then
|
||
|
pda_message("repair")
|
||
|
local tbl = {
|
||
|
{ 90, repair_tier4},
|
||
|
{ 50, repair_tier3},
|
||
|
{ 0, repair_tier2},
|
||
|
}
|
||
|
roll_item_tiered(tbl, box)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function try_spawn_repair_minor(box)
|
||
|
if math.random(1,100) <= smr_loot_mcm.get_config("repair_minor_chance") then
|
||
|
pda_message("repair")
|
||
|
create_item_random_uses(repair_tier1[math.random(#repair_tier1)], box)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- rolls for ammo, and spawns if sucessful
|
||
|
function try_spawn_ammo(box)
|
||
|
if math.random(1,100) <= smr_loot_mcm.get_config("ammo_chance") then
|
||
|
pda_message("ammo")
|
||
|
local r = math.random(1,100)
|
||
|
if r > 90 then create_ammo(exotic_ammo[math.random(#exotic_ammo)], box)
|
||
|
elseif r > 60 then create_ammo(advanced_ammo[math.random(#advanced_ammo)], box)
|
||
|
else create_ammo(basic_ammo[math.random(#basic_ammo)], box)end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- rolls for an medical item, and spawns if sucessful
|
||
|
function try_spawn_meds(box)
|
||
|
if math.random(1,100) <= smr_loot_mcm.get_config("meds_chance") then
|
||
|
pda_message("meds")
|
||
|
local tbl = {
|
||
|
{ 90, meds_tier4},
|
||
|
{ 70, meds_tier3},
|
||
|
{ 40, meds_tier2},
|
||
|
{ 0, meds_tier1},
|
||
|
}
|
||
|
roll_item_tiered(tbl, box)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- rolls for a useful item, and spawns if sucessful
|
||
|
function try_spawn_useful(box)
|
||
|
local f = factor or 1
|
||
|
if math.random(1,100) <= smr_loot_mcm.get_config("useful_chance") then
|
||
|
pda_message("useful")
|
||
|
local tbl = {
|
||
|
{ 90, useful_tier4},
|
||
|
{ 70, useful_tier3},
|
||
|
{ 40, useful_tier2},
|
||
|
{ 0, useful_tier1},
|
||
|
}
|
||
|
roll_item_tiered(tbl, box)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- creates a random amount of ammo in a box
|
||
|
function create_ammo(i, box)
|
||
|
local se_item
|
||
|
if smr_loot_mcm.get_config("ammo_bad_spawn") and (math.random(1,100) <= smr_loot_mcm.get_config("ammo_bad_chance"))
|
||
|
then se_item = alife_create_item(i .. "_bad", box)
|
||
|
else se_item = alife_create_item(i, box) end
|
||
|
local bs = ini_sys:r_float_ex(i, "box_size") or 10
|
||
|
local r = math.ceil(math.random(bs/2, bs*2) * smr_loot_mcm.get_config("ammo_amount"))
|
||
|
alife_process_item(i, se_item.id, {ammo = r})
|
||
|
end
|
||
|
|
||
|
function try_spawn(box)
|
||
|
if smr_zzintegration_mcm.get_config("mags_redux") and magazines then smr_loot.try_spawn_mag(box) end
|
||
|
if smr_zzintegration_mcm.get_config("lootboxes") and arti_lootboxes_mcm then smr_loot.try_spawn_lootbox(box) end
|
||
|
if smr_loot_mcm.get_config("repair_spawn") then smr_loot.try_spawn_repair(box) end
|
||
|
if smr_loot_mcm.get_config("repair_minor_spawn") then smr_loot.try_spawn_repair_minor(box) end
|
||
|
if smr_loot_mcm.get_config("ammo_spawn") then smr_loot.try_spawn_ammo(box) end
|
||
|
if smr_loot_mcm.get_config("useful_spawn") then smr_loot.try_spawn_useful(box) end
|
||
|
if smr_loot_mcm.get_config("meds_spawn") then smr_loot.try_spawn_meds(box) end
|
||
|
end
|
||
|
-- ---
|
||
|
-- ENTRY POINTS
|
||
|
-- ---
|
||
|
|
||
|
-- callback, used to write box table to save
|
||
|
local function save_state(data)
|
||
|
if not (data.smr_loot) then
|
||
|
data.smr_loot = {}
|
||
|
end
|
||
|
data.smr_loot.npcs = npcs
|
||
|
data.smr_loot.boxes = boxes
|
||
|
end
|
||
|
|
||
|
-- callback, used to load box table from save
|
||
|
local function load_state(data)
|
||
|
if not (data.smr_loot) then
|
||
|
return
|
||
|
end
|
||
|
boxes = data.smr_loot.boxes or {}
|
||
|
data.smr_loot.boxes = {}
|
||
|
npcs = data.smr_loot.npcs or {}
|
||
|
data.smr_loot.npcs = {}
|
||
|
end
|
||
|
-- callback, when opening boxes
|
||
|
local function physic_object_on_use_callback(box)
|
||
|
local id = box:id()
|
||
|
local player_stashes = alife_storage_manager.get_state().player_created_stashes
|
||
|
if (id and boxes and boxes[id]) or (player_stashes and player_stashes[id]) then
|
||
|
return
|
||
|
end
|
||
|
if (IsInvbox(box)) then
|
||
|
try_spawn(box)
|
||
|
boxes[id] = true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function npc_on_death_callback(obj, who)
|
||
|
local id = obj:id()
|
||
|
if id and npcs and npcs[id] then
|
||
|
return
|
||
|
end
|
||
|
if math.random(1,100) <= smr_loot_mcm.get_config("npc_chance") then
|
||
|
pda_msg_status = false
|
||
|
try_spawn(obj)
|
||
|
pda_msg_status = true
|
||
|
npcs[id] = true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- register callback for box opening
|
||
|
local function actor_on_first_update()
|
||
|
if smr_amain_mcm.get_config("smr_enabled") then
|
||
|
RegisterScriptCallback("physic_object_on_use_callback", physic_object_on_use_callback)
|
||
|
if smr_loot_mcm.get_config("npc_spawn") then
|
||
|
RegisterScriptCallback("npc_on_death_callback", npc_on_death_callback)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- register callbacks for saving/loading
|
||
|
function on_game_start()
|
||
|
if not smr_amain_mcm.get_config("smr_enabled") then
|
||
|
return
|
||
|
end
|
||
|
if smr_zzintegration_mcm.get_config("glowsticks") and zz_glowstick_mcm then
|
||
|
table.insert(useful_tier1, "device_glowstick_orange")
|
||
|
table.insert(useful_tier1, "device_glowstick_red")
|
||
|
table.insert(useful_tier1, "device_glowstick_blue")
|
||
|
table.insert(useful_tier1, "device_glowstick")
|
||
|
end
|
||
|
if smr_zzintegration_mcm.get_config("lootboxes") and arti_lootboxes_mcm then
|
||
|
table.insert(useful_tier1, "lockpick")
|
||
|
table.insert(useful_tier1, "bundle_lockpick")
|
||
|
table.insert(useful_tier2, "lockpick_set")
|
||
|
table.insert(useful_tier4, "skeleton_key")
|
||
|
end
|
||
|
if smr_loot_mcm.get_config("repair_parts_spawn") then
|
||
|
table.insert(repair_tier1, "ramrod_tool")
|
||
|
table.insert(repair_tier1, "rasp_tool")
|
||
|
table.insert(repair_tier1, "sewing_thread")
|
||
|
table.insert(repair_tier2, "heavy_sewing_thread")
|
||
|
end
|
||
|
|
||
|
RegisterScriptCallback("save_state", save_state)
|
||
|
RegisterScriptCallback("load_state", load_state)
|
||
|
RegisterScriptCallback("npc_on_death_callback", npc_on_death_callback)
|
||
|
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
|
||
|
end
|