283 lines
8.2 KiB
Plaintext
283 lines
8.2 KiB
Plaintext
|
|
||
|
math_random = math.random
|
||
|
math_floor = math.floor
|
||
|
gc = game.translate_string
|
||
|
ini_ammo = ballistics_utils.ini_ammo
|
||
|
get_ammo_data = arti_handlers.get_ammo_data
|
||
|
print_dbg = ballistics_mcm.print_dbg
|
||
|
|
||
|
local modes = {
|
||
|
["inventory"] = true,
|
||
|
}
|
||
|
local bags = {
|
||
|
["actor_bag"] = true,
|
||
|
["actor_equ"] = true,
|
||
|
["actor_belt"] = true,
|
||
|
}
|
||
|
function try_mg_link(obj, bag, mode)
|
||
|
if obj and bags[bag] and modes[mode] then
|
||
|
if obj:section() == "ammo_7.62x54_7h1" then
|
||
|
return gc("st_link")
|
||
|
elseif obj:section() == "ammo_pkm_100" then
|
||
|
return gc("st_unlink")
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function mg_link(obj)
|
||
|
-- grab up to 5 and try to link them together
|
||
|
if obj:section() == "ammo_7.62x54_7h1" then
|
||
|
local to_link = {}
|
||
|
local count = 0
|
||
|
db.actor:iterate_inventory(function(npc, item)
|
||
|
if item:section() == "ammo_7.62x54_7h1" and count < 5 then
|
||
|
to_link[item:id()] = item
|
||
|
count = count + 1
|
||
|
end
|
||
|
end)
|
||
|
local total = 0
|
||
|
for k,v in pairs(to_link) do
|
||
|
total = total + v:ammo_get_count()
|
||
|
alife_release_id(k)
|
||
|
end
|
||
|
if total > 0 then
|
||
|
alife_create_item("ammo_pkm_100", db.actor, {ammo = total})
|
||
|
end
|
||
|
elseif obj:section() == "ammo_pkm_100" then
|
||
|
local count = obj:ammo_get_count()
|
||
|
create_ammo("ammo_7.62x54_7h1", db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), AC_ID, count)
|
||
|
alife_release(obj)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function downgrade_ammo(sec, bypass, mult)
|
||
|
mult = mult or 1
|
||
|
local dg_ammo = ini_ammo:r_string_ex(sec, "dg_ammo")
|
||
|
local dg_chance = ini_ammo:r_float_ex(sec, "dg_chance") or 0
|
||
|
dg_chance = dg_chance * mult
|
||
|
-- print_dbg("Attempt downgrade ammo %s to %s", sec, dg_ammo)
|
||
|
if dg_ammo and (math_random() < (dg_chance) or bypass) then
|
||
|
-- print_dbg("Downgrading ammo %s to %s", sec, dg_ammo)
|
||
|
return dg_ammo
|
||
|
else
|
||
|
return sec
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function process_wpn(wpn, bypass)
|
||
|
local ammo_data = utils_item.get_ammo(wpn:section(), wpn:id())
|
||
|
local ammo_data_inv = invert_table(ammo_data)
|
||
|
if is_empty(ammo_data) then return end
|
||
|
local ammo_type = ammo_data[wpn:get_ammo_type() + 1]
|
||
|
local dg_ammo = ini_ammo:r_string_ex(ammo_type, "dg_ammo") or ""
|
||
|
local dg_chance = ini_ammo:r_float_ex(ammo_type, "dg_chance") or 0
|
||
|
if ammo_data_inv[dg_ammo] and (bypass or math_random() < dg_chance) then
|
||
|
-- print_dbg("Downgrading ammo for weapon %s", wpn:section())
|
||
|
local cnt = wpn:get_ammo_in_magazine()
|
||
|
wpn:unload_magazine(true)
|
||
|
wpn:set_ammo_type(ammo_data_inv[dg_ammo] - 1)
|
||
|
wpn:set_ammo_elapsed(cnt)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local recipe_trader = {
|
||
|
killer = {
|
||
|
"recipe_ammo_nato",
|
||
|
"recipe_ammo_pistol",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
army = {
|
||
|
"recipe_ammo_ru1",
|
||
|
"recipe_ammo_ru2",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
ecolog = {
|
||
|
"recipe_ammo_arty2",
|
||
|
"recipe_ammo_arty1",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
monolith = {
|
||
|
"recipe_ammo_ru2",
|
||
|
"recipe_ammo_fire",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
dolg = {
|
||
|
"recipe_ammo_ru1",
|
||
|
"recipe_ammo_shotgun",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
freedom = {
|
||
|
"recipe_ammo_nato",
|
||
|
"recipe_ammo_fire",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
csky = {
|
||
|
"recipe_ammo_shotgun",
|
||
|
"recipe_ammo_arty1",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
stalker = {
|
||
|
"recipe_ammo_pistol",
|
||
|
"recipe_ammo_shotgun",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
bandit = {
|
||
|
"recipe_ammo_ru1",
|
||
|
"recipe_ammo_pistol",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
greh = {
|
||
|
"recipe_ammo_arty2",
|
||
|
"recipe_ammo_nato",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
isg = {
|
||
|
"recipe_ammo_ru1",
|
||
|
"recipe_ammo_ru2",
|
||
|
"recipe_ammo_pistol",
|
||
|
"recipe_ammo_shotgun",
|
||
|
"recipe_ammo_nato",
|
||
|
"recipe_ammo_arty1",
|
||
|
"recipe_ammo_arty2",
|
||
|
"recipe_ammo_fire",
|
||
|
"recipe_ammo_powder",
|
||
|
"recipe_ammo_bullet"
|
||
|
},
|
||
|
}
|
||
|
|
||
|
function trader_on_restock(npc)
|
||
|
|
||
|
if trader_autoinject.get_trader_type(npc) == 1 then
|
||
|
trader_autoinject.spawn_items(npc, {
|
||
|
powder_fire = 10
|
||
|
}, true)
|
||
|
end
|
||
|
|
||
|
to_create = {}
|
||
|
npc:iterate_inventory(function(npc, item)
|
||
|
if not IsAmmo(item) then return end
|
||
|
local sec = item:section()
|
||
|
dg = downgrade_ammo(sec)
|
||
|
if sec ~= dg then
|
||
|
to_create[item:id()] = {
|
||
|
sec = dg,
|
||
|
cnt = item:ammo_get_count()
|
||
|
}
|
||
|
end
|
||
|
end)
|
||
|
for k,v in pairs(to_create) do
|
||
|
alife_release_id(k)
|
||
|
alife_create_item(v.sec, npc, {ammo = v.cnt})
|
||
|
end
|
||
|
|
||
|
|
||
|
local level = trader_autoinject.supply_level(npc, true) or 1
|
||
|
local chance = clamp(30 * (level - 1), 0, 100)
|
||
|
local comm = trader_autoinject.get_real_community(npc, "stalker")
|
||
|
if not recipe_trader[comm] then return end
|
||
|
for k,v in pairs(recipe_trader[comm]) do
|
||
|
if math.random(100) <= chance then
|
||
|
alife_create_item(v, npc)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local downgrade = false
|
||
|
|
||
|
SpawnAmmo = death_manager.try_spawn_ammo
|
||
|
function death_manager.try_spawn_ammo(npc)
|
||
|
downgrade = true
|
||
|
SpawnAmmo(npc)
|
||
|
downgrade = false
|
||
|
end
|
||
|
-- catch the guys that already exist
|
||
|
SetDrop = death_manager.set_weapon_drop_condition
|
||
|
function death_manager.set_weapon_drop_condition(npc,itm)
|
||
|
downgrade = true
|
||
|
SetDrop(npc,itm)
|
||
|
-- process_wpn(itm)
|
||
|
downgrade = false
|
||
|
end
|
||
|
AlifeCreate = _G.alife_create_item
|
||
|
function _G.alife_create_item(section, obj, t)
|
||
|
if downgrade and IsItem("ammo",section) and obj:id() ~= AC_ID then
|
||
|
section = downgrade_ammo(section, true)
|
||
|
end
|
||
|
return AlifeCreate(section, obj, t)
|
||
|
end
|
||
|
|
||
|
-- this happens whenever npc comes online, currently guarantees that the npc will never have access to better ammo in the wapon
|
||
|
function npc_on_net_spawn(npc)
|
||
|
CreateTimeEvent("downgrade_ammos",npc:id(), 0,function()
|
||
|
npc:iterate_inventory(function(t, item)
|
||
|
if IsWeapon(item) then process_wpn(item, true) end
|
||
|
end)
|
||
|
return true
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
-- spawn recipes with random weights
|
||
|
local recipe_weights = {
|
||
|
recipe_ammo_ru1 = 20,
|
||
|
recipe_ammo_ru2 = 10,
|
||
|
recipe_ammo_pistol = 20,
|
||
|
recipe_ammo_shotgun = 15,
|
||
|
recipe_ammo_nato = 10,
|
||
|
recipe_ammo_arty1 = 5,
|
||
|
recipe_ammo_arty2 = 5,
|
||
|
recipe_ammo_fire = 5,
|
||
|
}
|
||
|
|
||
|
SpawnTreasure = treasure_manager.try_spawn_treasure
|
||
|
|
||
|
function treasure_manager.try_spawn_treasure(box)
|
||
|
local id = box:id()
|
||
|
|
||
|
-- no spawn if the cache is already looted
|
||
|
if not (treasure_manager.caches[id]) then
|
||
|
return
|
||
|
end
|
||
|
SpawnTreasure(box)
|
||
|
local k = random_key_table(recipe_weights)
|
||
|
if math.random(100) <= recipe_weights[k] then
|
||
|
alife_create_item(k, box)
|
||
|
end
|
||
|
end
|
||
|
if magazines then
|
||
|
RollAmmo = magazines_loot.determine_ammo
|
||
|
-- subject the ammo pop in mags to downgrade
|
||
|
function magazines_loot.determine_ammo(ammo_to_pick, mag_sec, rank)
|
||
|
if RollAmmo then
|
||
|
print_dbg("Roll to downgrade %s in %s", ammo_to_pick, mag_sec)
|
||
|
ammo_to_pick = RollAmmo(ammo_to_pick, mag_sec, rank)
|
||
|
ammo_to_pick = downgrade_ammo(ammo_to_pick)
|
||
|
end
|
||
|
return ammo_to_pick
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function on_get_item_cost(kind, obj, profile, calculated_cost, ret)
|
||
|
local sec = obj:section()
|
||
|
if SYS_GetParam(1, sec, "is_component") and profile.mode == 1 then
|
||
|
local calculated_cost = ret.new_cost or calculated_cost -- in case someone adjusted the price of the weapon
|
||
|
calculated_cost = calculated_cost * 0.1
|
||
|
ret.new_cost = calculated_cost
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function on_game_start()
|
||
|
custom_functor_autoinject.add_functor("mg_link", try_mg_link, try_mg_link, nil, mg_link, true)
|
||
|
RegisterScriptCallback("npc_on_net_spawn",npc_on_net_spawn)
|
||
|
RegisterScriptCallback("on_get_item_cost",on_get_item_cost)
|
||
|
RegisterScriptCallback("trader_on_restock",trader_on_restock)
|
||
|
end
|