Added New Mods and Profiles Folders

This is a complete rebuild of the modpack, with all new mods and updates for 1.5.3 of Anomaly.
This commit is contained in:
2025-01-14 05:07:53 -05:00
parent 85c665b107
commit 376b4b9689
21217 changed files with 546254 additions and 0 deletions
@@ -0,0 +1,182 @@
-- If you don't use MCM, change your defaults from here.
local defaults = {
["jamchance"] = 1,
["superjam"] = true,
["simplejam"] = false,
-- ["heat"] = false,
["oldammo"] = true,
["degradation"] = 1.4,
["threshold"] = 85,
["repairkit"] = true,
["altroll"] = false,
["altpartroll"] = false,
["saletype"] = 1,
-- ["fullservice"] = 2,
["easybarrel"] = false,
["easytrigger"] = true,
["profanity"] = true,
["profanity_timeout"] = true,
["profanity_language"] = "rus",
["verbosity"] = true,
["debug"] = false,
["fun"] = 0
}
local mcm_map = {
["jamchance"] = "wpojam",
["superjam"] = "wpojam",
["simplejam"] = "wpojam",
-- ["heat"] = "wpojam",
["oldammo"] = "wpojam",
["degradation"] = "wpoecon",
["threshold"] = "wpoecon",
["repairkit"] = "wpoecon",
["altroll"] = "wpoecon",
["altpartroll"] = "wpoecon",
["saletype"] = "wpoecon",
-- ["fullservice"] = "wpoecon",
["easybarrel"] = "wpoecon",
["easytrigger"] = "wpoecon",
["profanity"] = "wpomisc",
["profanity_timeout"] = "wpomisc",
["profanity_language"] = "wpomisc",
["verbosity"] = "wpomisc",
["debug"] = "wpomisc",
["fun"] = "wpomisc",
["display"] = "wpomisc"
}
local last_click = nil
local mcm_key = DIK_keys.DIK_F -- your default key
local key_function = "key_func" -- this too if you renamed the function
function key_func()
arti_jamming.unjam()
end
local mcm_id = "clear_jam"
local mcm_keybinds = ui_mcm and ui_mcm.key_hold
local modifier = 0
local second_key = 0
function get_config(key)
if ui_mcm then return ui_mcm.get("wpo/"..mcm_map[key].."/"..key) else return defaults[key] end
end
function on_mcm_load()
op = { id= "wpo" ,gr={
{
id="wpojam",sh=true,gr={
{id= "jamtitle",type= "slide",text="ui_mcm_wpo_wpojam",link= "ui_options_slider_player",size= {512,50},spacing= 20},
{id = "jamchance", type = "track", val = 2, min=0.5,max=2,step=0.01, def = 1},
{id = "superjam", type = "check", val = 1, def = true},
{id = "simplejam", type = "check", val = 1, def = false},
{id = "oldammo", type = "check", val = 1, def = true},
{ id = "keybind", type = "key_bind" , val = 2, def = mcm_key },
{ id = "modifier", type = ui_mcm.kb_mod_radio , val = 2, def = 1, hint = "mcm_kb_mode" ,
content = {
{ 0, "mcm_kb_mode_press"},
{ 1, "mcm_kb_mode_dtap"},
{ 2, "mcm_kb_mode_hold"}
}
},
{ id = "second_key", type = ui_mcm.kb_mod_radio, val = 2, def = 0, hint = "mcm_kb_modifier" ,
content = {
{0,"mcm_kb_mod_none"} ,
{1,"mcm_kb_mod_shift"} ,
{2,"mcm_kb_mod_ctrl"},
{3,"mcm_kb_mod_alt"}
}},
{ id = "desc_mcm", type = "desc", text = "ui_mcm_unjam_mcm", clr = {255, 175 ,0 ,0}, precondition = {function() return not mcm_keybinds end} }
}
},
{
id="wpoecon",sh=true,gr={
{id= "econtitle",type= "slide",text="ui_mcm_wpo_wpoecon",link="ui_options_slider_player",size= {512,50},spacing= 20},
{id = "degradation", type = "track", val = 2, min=1,max=3,step=0.1, def = 1.4},
{id = "threshold", type = "track", val = 2, min=60,max=99,step=1, def = 85},
{id = "repairkit", type = "check", val = 1, def = true},
{id = "altroll", type = "check", val = 1, def = false},
{id = "altpartroll", type = "check", val = 1, def = false},
-- {id = "fullservice", type = "radio_h", content={ {0, "clean"} , {1, "parts"}, {2, "full"}} ,val = 2, def = 2},
{id = "saletype", type = "list", val = 2, content={ {0,"vanilla"} , {1,"easy"}, {2,"hard"}}, def=1},
{id = "easybarrel", type = "check", val = 1, def = false},
{id = "easytrigger", type = "check", val = 1, def = true},
}
},
{
id="wpomisc",sh=true,gr={
{id= "misctitle",type= "slide",text="ui_mcm_wpo_wpomisc",link= "ui_options_slider_player",size= {512,50},link="",spacing= 20},
{id = "debug", type = "check", val = 1, def=false},
{id = "profanity", type = "check", val = 1, def = true},
{id = "profanity_timeout", type = "check", val = 1, def = true},
{id = "profanity_language", type = "radio_h", content={ {"eng","eng"} , {"rus","rus"}} ,val = 0, def ="rus"},
{id = "display", type = "check", val = 1, def = true},
{id = "verbosity", type = "check", val = 1, def = true},
{id = "fun", type = "list", val = 2, content={ {0,"no"} , {1,"yes"}, {2,"ofc"}}, def=0},
}
}
}
}
return op
end
local modes = {
[0] = { ["call"] = {"on_key_press", "on_key_hold"}, ["function"] = function(key) ui_mcm.simple_press(mcm_id, key, key_function) end },
[1] = { ["call"] = {"on_key_press", "on_key_hold"}, ["function"] = function(key) if ui_mcm.double_tap(mcm_id, key) then key_function() end end },
[2] = { ["call"] = {"on_key_hold", "on_key_press"}, ["function"] = function(key) if ui_mcm.key_hold(mcm_id, key) then key_function() end end }
}
function on_key_press(key)
if not ui_mcm then
local bind = dik_to_bind(key)
local tg = time_global()
if bind == key_bindings.kUSE then
if not last_click then last_click = tg
else
if tg < last_click + 400 then
key_func()
end
last_click = nil
end
end
end
if key ~= mcm_key then return end
if not mcm_keybinds then
key_function()
return
end
if ui_mcm.get_mod_key(second_key) then
modes[modifier]["function"](key)
end
end
function on_key_hold(key)
if key ~= mcm_key then return end
if ui_mcm.get_mod_key(second_key) then
modes[modifier]["function"](key)
end
end
function on_option_change(mcm)
if mcm then
mcm_key = ui_mcm.get("wpo/wpojam/keybind")
modifier = ui_mcm.get("wpo/wpojam/modifier")
second_key = ui_mcm.get("wpo/wpojam/second_key")
RegisterScriptCallback(modes[modifier]["call"][1], this[modes[modifier]["call"][1]])
UnregisterScriptCallback(modes[modifier]["call"][2], this[modes[modifier]["call"][2]])
end
end
function on_game_start()
RegisterScriptCallback("on_option_change", on_option_change)
RegisterScriptCallback("on_key_press", on_key_press)
key_function = this[key_function]
on_option_change(mcm_keybinds)
end
@@ -0,0 +1,178 @@
local ini_custom_repair = ini_file("repair\\importer.ltx")
-- Simple injector to replace min condition, add condition repair type and repair only, so we don't need to conflict over LTX files
function get_prop(section, prop, type)
type = type or 0
local ini_to_check = ini_custom_repair:section_exist(section) and ini_custom_repair or ini_sys
if type == 0 then
return ini_to_check:r_string_ex(section, prop) or ini_sys:r_string_ex(section, prop, "")
elseif type == 1 then
return ini_to_check:r_bool_ex(section, prop) or ini_sys:r_bool_ex(section, prop, false)
else
return ini_to_check:r_float_ex(section, prop) or ini_sys:r_float_ex(section, prop, 0)
end
end
-- Override props from LTX
function item_repair.UIRepair:Reset(obj,section)
self.section = section
self.obj = obj
-- Settings
self.repair_frame = ini_sys:r_string_ex(section,"repair_ui") or "ui_itm_repair_1"
self.use_condition = ini_sys:r_bool_ex(section,"use_condition") or false
self.min_condition = get_prop(section,"repair_min_condition", 2) or 0
self.max_condition = ini_sys:r_float_ex(section,"repair_max_condition") or 0
self.add_condition = get_prop(section,"repair_add_condition", 2) or 0
self.part_bonus = get_prop(section,"repair_part_bonus", 2) or 0
self.use_parts = ini_sys:r_bool_ex(section,"repair_use_parts") or false
self.repair_type = ini_sys:r_string_ex(section,"repair_type") or "all"
self.repair_only = parse_list(ini_sys,section,"repair_only",true)
self.parts_multi = ini_sys:r_float_ex(section,"repair_parts_multi") or 1
self.parts_sections = parse_list(ini_sys,section,"repair_parts_sections",true)
self.parts_match = get_prop(section,"repair_parts_match",1)
self.use_actor_effects = ini_sys:r_bool_ex(section,"repair_use_actor_effects",false)
self.con_val = {}
-- Elements
self.CC[2]:Reset()
self.con_txt[1]:SetText("")
self.con_txt[2]:SetText("")
self.text_item[1]:SetText("")
self.text_item[2]:SetText("")
self.cell_item[1]:Reset()
self.cell_item[2]:Reset()
self.con_txt_base:SetText("")
self.con_txt_new:SetText("")
self.btn_repair:Enable(false)
local to_show = self.use_parts and true or false
self.cap[2]:Show(to_show)
self.b_inv[2]:Show(to_show)
self.b_item[2]:Show(to_show)
self.text_item[2]:Show(to_show)
self.con_txt[2]:Show(to_show)
self.CC[2]:Show(to_show)
-- Set Repair kit icon
utils_xml.set_upgr_icon(self.obj, self.section, self.box_item_main, self.box_item_main_temp)
-- Set Repair kit name
self.cap_menu:SetText(ui_item.get_sec_name(self.section))
-- Show damaged items
self:InitInventory(1)
-- Hide active item
actor_effects.toggle_active_slot(0)
-- Play sound
if (self.repair_frame == "ui_itm_repair_1") or (self.repair_frame == "ui_itm_repair_2") then
utils_obj.play_sound("interface\\inv_zipper_open")
else
utils_obj.play_sound("interface\\inv_briefcase_light_open")
end
end
local str_tbl = {}
gc = game.translate_string
function refresh_strings()
str_tbl.workshop_tool = gc("st_itm_desc_workshop_tool")
str_tbl.repair_bonus = gc("st_itm_desc_outfit_repair_bonus")
str_tbl.repair_base_con = gc("st_itm_desc_repair_base_con")
str_tbl.repair_min_con = gc("st_itm_desc_repair_min_con")
str_tbl.require_tool = gc("st_itm_desc_outfit_required_tool")
str_tbl.repair_match = gc("st_itm_desc_repair_match")
end
math_ceil = math.ceil
local clr_o = utils_xml.get_color("d_orange")
local clr_1 = utils_xml.get_color("ui_gray_2")
local clr_2 = utils_xml.get_color("ui_gray_1")
local clr_p = utils_xml.get_color("d_purple")
local clr_b = utils_xml.get_color("d_cyan")
BuildFooter = ui_item.build_desc_footer
-- Override from UI
function ui_item.build_desc_footer(obj, sec, str)
if not ini_custom_repair:section_exist(sec) then return BuildFooter(obj, sec, str) end
str = str or gc(ini_sys:r_string_ex(sec,"description"))
if (not str) then return "" end
local _str = ""
if is_empty(str_tbl) then
refresh_strings()
end
-- Repair base condition
local repair_base = get_prop(sec,"repair_add_condition", 2)
if repair_base then
_str = _str .. clr_o .. " ".. gc("st_dot") .." " .. clr_1 .. " " .. str_tbl.repair_base_con .. ": " .. clr_2 .. " +" .. tostring(math_ceil(repair_base*100)) .. "% \\n"
end
-- Repair min condition
local repair_min = get_prop(sec,"repair_min_condition", 2)
if repair_min then
_str = _str .. clr_o .. " ".. gc("st_dot") .." " .. clr_1 .. " " .. str_tbl.repair_min_con .. ": " .. clr_2 .. " " .. tostring(math_ceil(repair_min*100)) .. "% \\n"
end
-- Repair bonus part
local repair_bonus = get_prop(sec,"repair_part_bonus", 2)
if repair_bonus then
_str = _str .. clr_o .. " ".. gc("st_dot") .." " .. clr_1 .. " " .. str_tbl.repair_bonus .. ": " .. clr_2 .. " +" .. tostring(math_ceil(repair_bonus*100)) .. "% \\n"
end
-- Repair match parts
local is_part_match = get_prop(sec,"repair_parts_match", 1)
if is_part_match then
_str = _str .. clr_b .. " ".. gc("st_dot") .." " .. clr_1 .. " " .. str_tbl.repair_match .. " \\n"
end
-- Workshop tool
local is_workshop_tool = get_prop(sec,"workshop_tool", 1)
if is_workshop_tool then
_str = _str .. clr_p .. " ".. gc("st_dot") .." " .. clr_1 .. " " .. str_tbl.workshop_tool .. " \\n"
end
str = str .. _str .. " \\n"
return str
end
ParseList = _G.parse_list
local override_secs = {
repair_parts_sections = true,
repair_only = true,
repair_parts_sections = true
}
function _G.parse_list(ini, key, val, convert)
--printf("Parsing key %s, val %s", key, val)
local ini_to_use = (override_secs[val] and ini_custom_repair:section_exist(key) and ini_custom_repair:r_string_ex(key, val)) and ini_custom_repair or ini
return ParseList(ini_to_use, key, val, convert)
end
-- mother fuck
GetList = _G.GetItemList
function _G.GetItemList(typ)
list = GetList(typ)
if typ == "repair" then
for k,v in pairs(list) do
if ini_custom_repair:section_exist(k) and ini_custom_repair:r_string_ex(k, "repair_only") then
list[k] = parse_list(ini_custom_repair, k, "repair_only", true)
end
end
end
return list
end
function on_game_start()
refresh_strings()
RegisterScriptCallback("on_localization_change",refresh_strings)
end
@@ -0,0 +1,57 @@
parts_list = {}
local ini_parts = itms_manager.ini_parts
-- GetCost = utils_item.get_item_cost
-- -- for mechanics, part prices are very high to buy
-- function utils_item.get_item_cost(obj, profile)
-- if not (obj and profile) or utils_item.on_get_item_cost then
-- return GetCost(obj, profile)
-- end
-- local sec = obj:section()
-- -- printf("profile cfg = %s, sec = %s, parent id %s", profile.cfg, sec, obj:parent() and obj:parent():id() or 0)
-- if profile.cfg == "items\\trade\\trade_generic_mechanic.ltx" and parts_list[sec] and obj:parent() and obj:parent():id() ~= 0 then
-- local discount = profile.discount
-- local cost_final = discount * parts_list[sec]
-- -- printf("Set sale cost of %s to be %s", sec, cost_final)
-- return cost_final
-- else
-- return GetCost(obj, profile)
-- end
-- end
GetStatus = utils_item.get_item_trade_status
function utils_item.get_item_trade_status(obj, profile)
if not (obj and profile) or profile.mode == 2 then
return GetStatus(obj, profile)
end
if not (IsWeapon(obj) and (not IsItem("fake_ammo_wpn",obj:section()))) or (obj:parent() and obj:parent():id() ~= 0) then return GetStatus(obj, profile) end
local parts = se_load_var(obj:id(), obj:name(), "parts")
-- printf("Checking parts for %s", obj:section())
if not parts then return GetStatus(obj, profile) end
local has_broken, has_missing = false, false
for k,v in pairs(parts) do
if parts_list[k] and v < 60 then
-- printf("weapon %s has busted part %s", obj:section(), k)
has_broken = true
if v == -1 then has_missing = true end
end
end
if has_missing or ( a_arti_jamming_mcm.get_config("saletype") == 2 and has_broken) then
return 2
else
return GetStatus(obj, profile)
end
end
function on_game_start()
local prices = ini_file("items\\settings\\part_prices.ltx")
local part_section = utils_data.collect_section(prices, "wpo_part_prices")
local n = prices:line_count("wpo_part_prices") or 0
for i=0, n-1 do
local result, sec, value = prices:r_line("wpo_part_prices" , i , "", "")
parts_list[sec] = value
end
end
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,62 @@
-- Currently unimplemented.
-- Project heat bar and automatically jam gun when it fills.
local time_quant
local decrease_quant
local heat_per_shot = 10
-- return overheat base amount (factor in section and suppressor)
function get_overheat_base(weapon)
if not weapon then return end
local sec_p = parent_section(weapon:section())
local overheat_base = ini_overheat:r_float_ex("custom_overheat", sec_p) or overheat_data.base
if weapon:weapon_is_silencer() then overheat_base = overheat_base * overheat_data.suppressor_mult end
return overheat_base
end
function get_heat()
return cgd.heat.level
end
function actor_on_update()
-- overheat checks
if db.actor:active_item() and cgd.has_parts then
manage_overheat(db.actor:active_item())
end
end
-- this should only be invoked if the weapon can be overheated
function manage_overheat(wpn)
-- ignore if not current (somehow)
if not wpn or wpn:id() ~= cgd.id then return end
if cgd.heat.level < cgd.heat.overheat_threshold then
decrease_quant = 0.15
else
decrease_quant = 0.05
end
local sec = wpn:section()
if not wpn then return end
if (string.match(tostring(sec),"knife") or string.match(tostring(sec),"axe")) then return end
if IsWeapon(wpn) and cgd.heat.level > 0 and data.weapon_state ~= 5 then
-- decrease quantity over time when not shooting
cgd.heat.level = clamp(cgd.heat.level - decrease_quant, 0, cgd.heat.overheat_max)
end
end
-- return overheat damage modifier for current weapon, weapon itself is passed to get some convenience things
-- if you are not passing current, return just 1
-- eval returns multiplier, pass false gives just level
function get_overheat_modifier(weapon, eval)
if true--not get_config("heat")
then return eval and 1 or 0 end
local id = weapon:id()
if eval == nil then eval = true end
if id ~= cgd.id then return 1 end
local overheat_base = cgd.heat.overheat_base
local heat_severity = math.floor(cgd.heat.level/overheat_base)
if heat_severity > 0 then
return eval and overheat_data.damage[heat_severity] or heat_severity
else return eval and 1 or 0 end
end
@@ -0,0 +1,24 @@
-- Placeholder for older versions
-- local last_click = nil
-- local function on_key_press(key)
-- local bind = dik_to_bind(key)
-- local tg = time_global()
-- if bind == key_bindings.kUSE then
-- if not last_click then last_click = tg
-- else
-- if tg < last_click + 400 then
-- arti_jamming.unjam()
-- end
-- last_click = nil
-- end
-- end
-- end
-- function on_game_start()
-- RegisterScriptCallback("on_key_press",on_key_press)
-- end
@@ -0,0 +1,538 @@
--[[
Custom Dynamic Functors, written by demonized
Allows to add/remove item functors dynamically from script
Can override ltx-defined functors and can remove the override to return back to ltx functor
To use in your script look at example below
---------------------------------------------------------------------------------------------------------------------
local function name_condition_function(obj, bag, mode)
if obj then
return true
end
end
local function name_function(obj, bag, mode)
return "st_my_functor_string_in_xml"
end
local function action_condition_function(obj, bag, mode)
if obj then
return true
end
end
local function action_function(obj, bag, mode)
alife_create_item(obj:section(), db.actor)
end
local add_functor = custom_functor_autoinject.add_functor
add_functor("my_name_of_functor", name_condition_function, name_function, action_condition_function, action_function, override_bags<true, false>)
---------------------------------------------------------------------------------------------------------------------
to add your functor you use add_functor function which requires these arguments in order:
name: string, your name of your functor, can be any string.
If the name of functor already exists this function will overwrite functions for it
name_condition_function: function, the condition at which you will get your right-click option for item
name_function: function, the name itself, must return string ID defined in XML files for your option.
if set to return nil, the option won't appear
action_condition_function: function, the condition at which the action will be performed, usually its the same as name_condition_function
you can put nil into argument to use the same function as name_condition_function
action_function: function, the action itself to perform
override_bags: boolean. If its true, then you can override bags and modes to check for condition, otherwise it will use defaults (mode == "inventory" and bag == "actor_bag" or bag == "actor_equ" or bag == "actor_belt")
functions themselves accept obj, bag and mode arguments
obj: current object you right-clicked
bag: current bag, list of possible bags: {"actor_equ","actor_belt","actor_bag","actor_trade_bag","actor_trade","npc_bag","npc_trade","npc_trade_bag"}
mode: current mode, list of possible modes: {"inventory" , "loot" , "trade" , "repair"}
bag and mode is not enabled unless you set override_bags flag to true
removal of functor is done by calling this
--------------------------------------------------------------------------------------
local remove_functor = custom_functor_autoinject.remove_functor
remove_functor("my_name_of_functor")
--------------------------------------------------------------------------------------
you can also override existing functors defined in item's ltx by using this
---------------------------------------------------------------------------------------------------------------------
local override_functor = custom_functor_autoinject.override_functor
override_functor(slot, name_condition_function, name_function, action_condition_function, action_function, override_bags<true, false>)
---------------------------------------------------------------------------------------------------------------------
arguments are same, except you have to provide the slot (first argument) for your override. The slots are 1-10
for example if item's ltx have use1_functor and use1_action_functor then
if you want to override it you have to provide slot 1
be aware that if your name_condition_function or action_condition_function may return false
then old functor will be fired
if you don't want that behaviour, you can define generic "return true" function for those
and check condition for firing in name_function and action_function
removal of override is done by calling this
--------------------------------------------------------------------------------------
local remove_override = custom_functor_autoinject.remove_override
remove_override(slot)
--------------------------------------------------------------------------------------
--]]
local function func_index(t,a,b)
return (t[a].index) < (t[b].index)
end
local function func_index_reverse(t,a,b)
return (t[a].index) > (t[b].index)
end
local function func_value(t, a, b)
return t[a] < t[b]
end
local spairs = spairs
local string_find = string.find
local string_gsub = string.gsub
local table_remove = table.remove
local tonumber = tonumber
local unpack = unpack
--Recursive print of tables similar to PHP print_r function
local function print_r(t)
local print_r_cache={}
local function sub_print_r(t,indent)
if (print_r_cache[tostring(t)]) then
printf(indent.."*"..tostring(t))
else
print_r_cache[tostring(t)]=true
if (type(t)=="table") then
for pos,val in pairs(t) do
if (type(val)=="table") then
printf(indent.."["..pos.."] => "..tostring(t).." {")
sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
printf(indent..string.rep(" ",string.len(pos)+6).."}")
else
printf(indent.."["..pos.."] => "..tostring(val))
end
end
else
printf(indent..tostring(t))
end
end
end
sub_print_r(t," ")
end
local function print_table(table, subs)
local sub
if subs ~= nil then
sub = subs
else
sub = ""
end
for k,v in pairs(table) do
if type(v) == "table" then
print_table(v, sub.."["..k.."]----->")
elseif type(v) == "function" then
printf(sub.."%s = function",k)
elseif type(v) == "userdata" then
if (v.x) then
printf(sub.."%s = %s",k,utils_data.vector_to_string(v))
else
printf(sub.."%s = userdata", k)
end
elseif type(v) == "boolean" then
if v == true then
if(type(k)~="userdata") then
printf(sub.."%s = true",k)
else
printf(sub.."userdata = true")
end
else
if(type(k)~="userdata") then
printf(sub.."%s = false", k)
else
printf(sub.."userdata = false")
end
end
else
if v ~= nil then
printf(sub.."%s = %s", k,v)
else
printf(sub.."%s = nil", k,v)
end
end
end
end
-- Removing element from table and shifting down both key and value
-- Modes: 0 - index, 1 - value, 2 - key, 3 - key-index
local function table_remove_shift(t, val, mode)
local removed = false
local res
if mode == 0 then
for k, v in spairs(t, func_index) do
if removed then
t[k - 1] = v
if t[k - 1].index then
t[k - 1].index = t[k - 1].index - 1
end
if t[k - 1].properties_index then
t[k - 1].properties_index = t[k - 1].properties_index - 1
end
t[k] = nil
elseif v.index and v.index == val then
res = t[k]
t[k] = nil
removed = true
end
end
elseif mode == 1 then
for k, v in spairs(t, func_value) do
if removed then
t[k - 1] = v - 1
t[k] = nil
elseif v == val then
res = t[k]
t[k] = nil
removed = true
end
end
elseif mode == 2 then
for k, v in spairs(t, func_value) do
if removed then
t[k] = v - 1
elseif v == val then
res = t[k]
t[k] = nil
removed = true
end
end
elseif mode == 3 then
for k, v in spairs(t, func_index) do
if removed then
if t[k].index then
t[k].index = t[k].index - 1
end
elseif v.index and v.index == val then
res = t[k]
t[k] = nil
removed = true
end
end
end
return res
end
local ui_inventory_init = ui_inventory.UIInventory.__init
ui_inventory.UIInventory.__init = function(self)
ui_inventory_init(self)
self.custom_functor = {}
self.custom_functor_names = {}
end
local NameCustom = ui_inventory.UIInventory.Name_Custom
function ui_inventory.UIInventory:Name_Custom(obj, bag, temp, i)
obj = self:CheckItem(obj,"Name_Custom " .. i)
if self.custom_functor[i] and self.custom_functor[i].cond_name(obj, bag, self.mode) then
return self.custom_functor[i].func_name(obj, bag, self.mode)
else
return NameCustom(self, obj, bag, temp, i)
end
end
local ActionCustom = ui_inventory.UIInventory.Action_Custom
function ui_inventory.UIInventory:Action_Custom(obj, bag, temp, i)
obj = self:CheckItem(obj,"Action_Custom " .. i)
if self.custom_functor[i] and self.custom_functor[i].cond_action(obj, bag, self.mode) then
return self.custom_functor[i].func_action(obj, bag, self.mode)
else
return ActionCustom(self, obj, bag, temp, i)
end
end
ui_inventory.UIInventory.get_max_custom_functor = function(self)
local max = 0
local max_custom = {}
local max_index = 0
for k, v in pairs(self.properties) do
if string_find(k, "custom_.*") then
if v.index > max_index then
max_index = v.index
end
local x = tonumber(string_gsub(k, "custom_(.*)", "%1"), nil)
if x > max then
max = x
max_custom = v
end
end
end
return max, max_custom, max_index
end
local modes = {
["inventory"] = true,
["loot"] = true,
["trade"] = true,
["repair"] = true
}
local bags = {
["actor_equ"] = true,
["actor_belt"] = true,
["actor_bag"] = true,
["actor_trade_bag"] = true,
["actor_trade"] = true,
["npc_bag"] = true,
["npc_trade"] = true,
["npc_trade_bag"] = true
}
ui_inventory.UIInventory.Mode_Custom_Functor = function(self, obj, bag, temp, i)
return modes[self.mode]
end
ui_inventory.UIInventory.Cont_Custom_Functor = function(self, obj, bag, temp, i)
return bags[bag]
end
ui_inventory.UIInventory.add_custom_functor = function(self, name, cond_name, func_name, cond_action, func_action, override_bags)
local custom_functor_slot
if self.custom_functor_names[name] then
custom_functor_slot = self.custom_functor_names[name]
self.custom_functor[custom_functor_slot].cond_name = cond_name
self.custom_functor[custom_functor_slot].func_name = func_name
self.custom_functor[custom_functor_slot].cond_action = cond_action
self.custom_functor[custom_functor_slot].func_action = func_action
self.properties["custom_" .. custom_functor_slot].mode_func[1] = override_bags and "Mode_Custom_Functor" or "Mode_Custom"
self.properties["custom_" .. custom_functor_slot].cont_func[1] = override_bags and "Cont_Custom_Functor" or "Cont_Custom"
else
local max, max_custom, max_index = self:get_max_custom_functor()
local custom_num = max + 1
local properties_num = max_index + 1
for k, v in spairs(self.properties, func_index_reverse) do
if v.index > max_index then
printf("%s, %s", k, v.index)
v.index = v.index + 1
else
printf("%s, %s, max custom_functor reached", k, v.index)
break
end
end
self.properties["custom_" .. custom_num] = {
index = properties_num,
name_func = {"Name_Custom", max_custom["name_func"][2] + 1},
mode_func = {override_bags and "Mode_Custom_Functor" or "Mode_Custom", max_custom["mode_func"][2] + 1},
cont_func = {override_bags and "Cont_Custom_Functor" or "Cont_Custom", max_custom["cont_func"][2] + 1},
precondition1 = {"Name_Custom", max_custom["precondition1"][2] + 1},
action = {"Action_Custom", max_custom["action"][2] + 1}
}
custom_functor_slot = custom_num
self.custom_functor[custom_functor_slot] = {
index = custom_functor_slot,
properties_index = properties_num,
name = name,
cond_name = cond_name,
func_name = func_name,
cond_action = cond_action,
func_action = func_action
}
self.custom_functor_names[name] = custom_functor_slot
end
end
ui_inventory.UIInventory.remove_custom_functor = function(self, name)
if not self.custom_functor_names[name] then return end
local index = table_remove_shift(self.custom_functor_names, self.custom_functor_names[name], 2)
if not index then return end
local custom_functor = table_remove_shift(self.custom_functor, index, 0)
if not custom_functor then return end
local removed = false
for k, v in spairs(self.properties, func_index) do
if string_find(k, "custom_.*") then
if removed then
local x = tonumber(string_gsub(k, "custom_(.*)", "%1"), nil) - 1
self.properties["custom_" .. x] = self.properties[k]
self.properties["custom_" .. x].index = self.properties["custom_" .. x].index - 1
self.properties["custom_" .. x].name_func[2] = self.properties["custom_" .. x].name_func[2] - 1
self.properties["custom_" .. x].mode_func[2] = self.properties["custom_" .. x].mode_func[2] - 1
self.properties["custom_" .. x].cont_func[2] = self.properties["custom_" .. x].cont_func[2] - 1
self.properties["custom_" .. x].precondition1[2] = self.properties["custom_" .. x].precondition1[2] - 1
self.properties["custom_" .. x].action[2] = self.properties["custom_" .. x].action[2] - 1
self.properties[k] = nil
elseif v.index == custom_functor.properties_index then
self.properties[k] = nil
removed = true
end
elseif removed then
v.index = v.index - 1
end
end
end
ui_inventory.UIInventory.override_functor = function(self, slot, cond_name, func_name, cond_action, func_action, override_bags)
self.custom_functor[slot] = {
cond_name = cond_name,
func_name = func_name,
cond_action = cond_action,
func_action = func_action
}
self.properties["custom_" .. slot].mode_func[1] = override_bags and "Mode_Custom_Functor" or "Mode_Custom"
self.properties["custom_" .. slot].cont_func[1] = override_bags and "Cont_Custom_Functor" or "Cont_Custom"
end
ui_inventory.UIInventory.remove_override = function(self, slot)
self.custom_functor[slot] = nil
self.properties["custom_" .. slot].mode_func[1] = "Mode_Custom"
self.properties["custom_" .. slot].cont_func[1] = "Cont_Custom"
end
ui_inventory.UIInventory.get_functor_at_slot = function(self, slot)
return self.custom_functor[slot]
end
ui_inventory.UIInventory.get_functor_by_name = function(self, name)
if self.custom_functor_names[name] then
return self.custom_functor[self.custom_functor_names[name]], self.custom_functor_names[name]
end
end
-- Adding
local first_update_pending = true
local functor_queue = {}
local function add_to_queue(type, ...)
functor_queue[#functor_queue + 1] = {
type = type,
data = {...}
}
end
local function process_queue()
if not ui_inventory.GUI then
ui_inventory.GUI = ui_inventory.UIInventory()
end
printf("Custom functors, processing queue")
for i, v in ipairs(functor_queue) do
printf("Custom functors, type %s", v.type)
ui_inventory.GUI[v.type](ui_inventory.GUI, unpack(v.data))
end
functor_queue = {}
first_update_pending = false
end
local function actor_on_first_update()
process_queue()
end
function add_functor(name, cond_name, func_name, cond_action, func_action, override_bags)
if not name then return end
local cond_action = cond_action or cond_name
if first_update_pending then
add_to_queue("add_custom_functor", name, cond_name, func_name, cond_action, func_action, override_bags)
return
end
ui_inventory.GUI:add_custom_functor(name, cond_name, func_name, cond_action, func_action, override_bags)
end
function remove_functor(name)
if not name then return end
if first_update_pending then
add_to_queue("remove_custom_functor", name)
return
end
ui_inventory.GUI:remove_custom_functor(name)
end
function override_functor(slot, cond_name, func_name, cond_action, func_action, override_bags)
if slot < 1 or slot > 10 then
printf("functor slot is not valid, min 1, max 10, your slot: %s", slot)
return
end
local cond_action = cond_action or cond_name
if first_update_pending then
add_to_queue("override_functor", slot, cond_name, func_name, cond_action, func_action, override_bags)
return
end
ui_inventory.GUI:override_functor(slot, cond_name, func_name, cond_action, func_action, override_bags)
end
function remove_override(slot)
if slot < 1 or slot > 10 then
printf("functor slot is not valid min 1, max 10, your slot: %s", slot)
return
end
if first_update_pending then
add_to_queue("remove_override", slot)
return
end
ui_inventory.GUI:remove_override(slot)
end
function get_functor_at_slot(slot)
if first_update_pending then
add_to_queue("get_functor_at_slot", slot)
return
end
return ui_inventory.GUI:get_functor_at_slot(slot)
end
function get_functor_by_name(name)
if first_update_pending then
add_to_queue("get_functor_by_name", name)
return
end
return ui_inventory.GUI:get_functor_by_name(name)
end
function print_properties()
if not ui_inventory.GUI then
ui_inventory.GUI = ui_inventory.UIInventory()
end
for k, v in spairs(ui_inventory.GUI.properties, func_index) do
printf("[" .. k .. "] => ")
print_r(v)
end
end
function print_custom_functor()
if not ui_inventory.GUI then
ui_inventory.GUI = ui_inventory.UIInventory()
end
print_r(ui_inventory.GUI.custom_functor)
end
function print_custom_functor_names()
if not ui_inventory.GUI then
ui_inventory.GUI = ui_inventory.UIInventory()
end
print_r(ui_inventory.GUI.custom_functor_names)
end
function on_game_start()
RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
end
@@ -0,0 +1,6 @@
GetEcoFactor = game_difficulties.get_eco_factor
function game_difficulties.get_eco_factor(str)
if (str == "percentage_parts") then return true
else return GetEcoFactor(str) end
end
@@ -0,0 +1,107 @@
-- monkeypatchable inv upgrades to effect repair cost
-- inv upgrades
ini_parts = itms_manager.ini_parts
function section_has_parts(sec)
local psec = ini_sys:r_string_ex(sec,"parent_section") or sec
local parts = ini_parts:r_string_ex("con_parts_list", psec)
return parts ~= nil
end
-- mp meeeee
function how_much_repair( item_name, item_condition )
local cost = ini_sys:r_u32(item_name, "cost")
local class = ini_sys:r_string_ex(item_name, "class")
local cof = game_difficulties.get_eco_factor("repair") or 1.67
--return math.floor( cost * factor * math.pow(1 - item_condition , 1.63) )
return math.floor( cost * (1 - item_condition) * cof ) -- CoP formula
end
function inventory_upgrades.can_afford_repair_item( item_name, item_condition )
local price = how_much_repair( item_name, item_condition )
if db.actor:money() < price then
return false
end
return true
end
function inventory_upgrades.question_repair_item( item_name, item_condition, can, mechanic ) --( string, float, bool, string )
if(item_name=="pri_a17_gauss_rifle") then
return game.translate_string("st_gauss_cannot_be_repaired")
end
if can then
local price = how_much_repair( item_name, item_condition )
if db.actor:money() < price then
return game.translate_string("st_upgr_cost")..": "..price.." RU\\n"..game.translate_string("ui_inv_not_enought_money")..": "..price-db.actor:money().." RU"
end
return game.translate_string("st_upgr_cost").." "..price.." RU. "..game.translate_string("ui_st_inv_repair").."?"
end
return nil
end
function inventory_upgrades.effect_repair_item( item_name, item_condition)
local price = how_much_repair( item_name, item_condition )
db.actor:give_money(-price)
if (ui_options.get("gameplay/general/mechanic_feature") ~= true) then
return
end
local item
local function itr(actor,itm)
if (itm and itm:section() == item_name and itm:condition() == item_condition) then
item = itm
return true
end
return false
end
db.actor:iterate_inventory(itr,db.actor)
if (item) then
local cls = item:clsid()
if (cls == "WP_BINOC") then
return
end
local victim = get_speaker()
if (victim) then
local damage_factor = 1.0 - clamp(item_condition, 0.0, 1.0)
inventory_upgrades.lend_item_for_repair(item,victim:section(),6000*damage_factor)
end
end
end
local repair_id
OnRepair = ui_inventory.UIInventory.RMode_OnRepair
function ui_inventory.UIInventory:RMode_OnRepair()
self:Print(nil, "RMode_OnRepair")
if (not self.upgr.id) then
return
end
local obj = level.object_by_id(self.upgr.id)
if (not obj) then
return
end
repair_id = self.upgr.id
OnRepair(self)
end
RepairYes = ui_inventory.UIInventory.RMode_RepairYes
function ui_inventory.UIInventory:RMode_RepairYes()
RepairYes(self)
repair_id = nil
end
function get_repair_id()
return repair_id
end
@@ -0,0 +1,125 @@
-- LAgrange inteRPolation library
-- algorithm by peete-q
-- Migrated to Anomaly by Asshall
-- Modified and modularized by arti
-- To calculate non linear probability I used a type of interpolation called "Lagrange interpolation".
-- The basic premise is that you input coordinates for x and y, for the exemple of loot x is the condition of the item to drop and y is the probability to drop such condition
-- For exemple if I input :
-- x | y
-- 2 | 0
-- 25 | 85
-- The probability of getting an item between 2 and 25 % condition is distributed between 0% proba and 85%
-- So in theory there is a 0 percent chance to get a 2% condition drop
-- and a 85% chance to get a 25% condition item with the probalities smoothly distributed between those two
-- This is an overly simplified explication because it's the best I can do, but the gist is that by interpolating n point in a curve you can get an approximation of the y value for all x
-- In this case x represents the condition and y the number to beat to drop.
-- Here is a table exemple
-- [weapon_coords]
-- novice = 2, 25, 50 : 5, 85, 99
-- trainee = 2, 25, 50 : 10, 81 ,99
-- experienced = 2, 25, 50 : 15, 76 ,98
-- professional = 2, 25, 50, 65 : 20 ,71 ,97, 99
-- veteran = 2, 25, 50, 65 : 20 ,68 ,96, 99
-- expert = 2, 25, 50, 65 : 20 ,64 ,95, 99
-- master = 2, 25, 50, 65 : 20 ,62 ,95, 98
-- legend = 2, 25, 50, 65 : 20 ,57 ,94, 98
-- I did not implement that, peete-q did : https://github.com/peete-q/assets/blob/master/lua-modules/lib/interpolate.lua All credits goes to them
function lagrange(data, xi)
local x = data["x"]
local y = data["y"]
xi = tonumber(xi)
local n = #x
-- Need the same number of points otherwise exit out
if n ~= #y then return end
-- Brilliant optimisation by peete-q
local i = 1
while i <= n and x[i] < xi do
i = i + 1
end
local m = math.min(i + 3, n)
local k = math.max(i - 4, 1)
local result = 0
for i=k, m do
local term = y[i]
for j=k, m do
if j ~= i then
term = term*( (xi - x[j]) / (x[i] - x[j]) )
end
end
result = result + term -- term used to be on at the start multiplied by y[i] on this line. Don't know if that makes a difference. It's more lisible for me and I'm a dumb ape
end
return clamp(result,math.min(unpack(y)),math.max(unpack(y))) -- Here I clamp the result cause largrange interp can do some weird sutff and go above maxy/bellow miny between two xs
-- This is suboptimal... Maybe i'm not using the right interp for some data sets or I shouldn't be using interp for those at all. It'll do for now.
end
-- Return min a max of data set of format {x,y} in order minx, maxx, miny, maxy
function get_min_max(coords)
return math.min(unpack(coords["x"])), math.max(unpack(coords["x"])), math.min(unpack(coords["y"])), math.max(unpack(coords["y"]))
end
-- str_explode but they get parsed into numbers
function str_explode_num(str, sep, plain)
if not (str and sep) then
printe("!ERROR str_explode | missing parameter str = %s, sep = %s",str,sep)
callstack()
end
if not (sep ~= "" and str:find(sep,1,plain)) then
return { tonumber(str) }
end
local t = {}
local size = 0
for s in str:gsplit(sep,plain) do
size = size + 1
t[size] = tonumber(trim(s))
end
return t
end
-- input:
-- coords is a table with x and y, each a list of integers
-- iterations is how many times to run, pass nil to run until we get something
-- returns a weighted value within the x range based on weights in y
function pick(coords, max_iterations)
if is_empty(coords) then return 0 end
if #coords["x"] ~= #coords["y"] then
printe("Input for coord string %s produced inequal output, returning", str)
return 0
end
local minx, maxx, miny, maxy = get_min_max(coords)
local iter = 0
while true do
rnd_x = math.random(minx, maxx)
local y = lagrange(coords, rnd_x)
if math.random(miny, maxy) + math.random() > y then
return round(rnd_x)
end
iter = iter + 1
if max_iterations and iter >= max_iterations then
return rnd_x
end
end
end
-- input: str of format:
-- X1, X2, X3...XN : Y1, Y2, Y3...Yn
function str_to_coords(str)
coords = {
["x"] = {},
["y"] = {},
}
buffer = str_explode(str, ":")
coords["x"] = str_explode_num(buffer[1], ",")
coords["y"] = str_explode_num(buffer[2], ",")
if #coords["x"] ~= #coords["y"] then
printe("Input for coord string %s produced inequal output, returning", str)
return nil
end
return coords
end
@@ -0,0 +1,25 @@
-- mag support wrapper
local function supports_mags(wpn)
if wuut_mags then
local defaultMagSection = wuut_mags.WeaponGetDefaulMagSection(wpn)
local defaultMagSectionExists = system_ini():section_exist(defaultMagSection)
return defaultMagSectionExists
elseif magazines then
return magazine_binder.is_supported_weapon(wpn)
else return false
end
end
function eject_mag(wpn)
if not supports_mags(wpn) then
wpn:force_unload_magazine(true)
return
end
if wuut_mags and wuut_mags.MagazineInWeaponIsValid(wpn) then
return wuut_mags.weapon_eject_mag_functor(wpn)
elseif magazines then
magazines.eject_magazine(wpn)
else wpn:force_unload_magazine(true) end
end
@@ -0,0 +1,201 @@
--[[
Wrapper class to let you autoinject things via monkey patch to all traders, respecting the restock time.
How to use: Monkey patch the update function here in your script.
ex:
TraderAuto = trader_autoinject.update
function trader_autoinject.update(npc)
TraderAuto(npc)
add_custom_crap(npc) -- you define this function ok
end
Some functions provided below for convenience.
Note: If you want to iterate NPC inventory to check for items, fire a time event to allow the items to register on new game.
--]] --
find = string.find
local function t2c(t)
if not t then return nil end
local ct = game.CTime()
ct:set(t.Y,t.M,t.D,t.h,t.m,t.s,t.ms)
return ct
end
local function c2t(ct)
if not ct then return nil end
-- printf('%s, %s',ct,type(ct))
local Y, M, D, h, m, s, ms = 0, 0, 0, 0, 0, 0, 0
Y, M, D, h, m, s, ms = ct:get(Y, M, D, h, m, s, ms)
return { Y=Y, M=M, D=D, h=h, m=m, s=s, ms=ms }
end
TraderUpdate = trade_manager.update
function trade_manager.update(npc, force_refresh)
local id = npc:id()
if not npc or not npc:alive() then
return
end
local reup_time = trade_manager.get_trade_profile(id, "resupply_time")
TraderUpdate(npc, force_refresh)
local restock_time = game_difficulties.get_eco_factor("restock") or 24
if force_refresh then restock_time = 0 end
if reup_time and game.get_game_time():diffSec(t2c(reup_time)) < (restock_time * 3600) then
-- print_dbg("Not time to resupply yet!")
return
end
disable_info("sleep_active")
CreateTimeEvent("custom_update"..npc:id(), "custom_resupply"..npc:id(), 0.1, timed_update, npc)
end
-- Add easier to trace callback
function timed_update(npc)
update(npc)
SendScriptCallback("trader_on_restock",npc)
return true
end
-- monkeypatch me
function update(npc)
end
-- util functions to help with monkey patching
function get_faction_goodwill(faction)
end
COMPANION = 0 -- companions got special trade logic, this is just to catch errors
MECHANIC = 1 -- mechanics/techs
BARMAN = 2 -- exclusive food suppliers like Spirit
MEDIC = 3 -- medics
SUPPLIER = 4 -- everyone else that sells crap
-- return trader type as int, or nil if error
function get_trader_type(npc)
local st = db.storage[npc:id()]
if not st then return -1 end
local trader = false
if npc:character_community() == "trader" or npc:clsid() == clsid.script_trader or npc:clsid() == clsid.trader then
trader = true
end
if find(npc:section(),"trader") then
trader = true
end
local cini = st.ini
local logic = st.section_logic
if not logic and not trader then return -1 end
local trade_logic = cini and cini:r_string_ex(logic, "trade")
if not trade_logic then return -1 end
if find(trade_logic, "companion") then
return COMPANION
elseif find(trade_logic, "trade_generic_mechanic") then
return MECHANIC
elseif find(trade_logic, "trade_generic_barman") then
return BARMAN
elseif find(trade_logic, "trade_generic_medic") then
return MEDIC
else
return SUPPLIER
end
end
-- return supply level of npc, like suppy_1, supply_2, etc
-- as_number removes the supply_ prefix and only returns as int
function supply_level(npc, as_number)
local profile = trade_manager.get_trade_profile(npc:id(), "cfg_ltx")
-- printf("Profile is %s", profile)
local config = trade_manager.get_trade_cfg(profile)
if not config then return end
local str = config:r_string_ex("trader", "buy_supplies")
if not (str) then
return -- no buy_supplies this is normal
end
local condlist = xr_logic.parse_condlist(npc, "trader", "buy_supplies", str)
str = condlist and xr_logic.pick_section_from_condlist(db.actor, npc, condlist)
if as_number then
local num = str_explode(str, "_")
return tonumber(num[2])
else
return str
end
end
-- collapse several tables into one table, the way sections work in ltx files
-- tables should be in section -> amount format
-- precedence goes up to last table, meaning whatever is in the last table will be the last changes applied
function merge_tables(tables)
local final_table = {}
if #tables > 0 then
copy_table(final_table, tables[1])
if #tables > 1 then
for i=2, #tables do
for k,v in pairs(tables[i]) do
final_table[k] = v
end
end
end
end
return final_table
end
local furniture = {
["esc_m_trader"] = true,
["red_m_lesnik"] = true
}
local blacklisted_comms = {
["trader"] = true,
["monster"] = true
}
-- used to get the real community of the NPC by checking spawn id
-- author: HarukaSai
function get_real_community(npc, default)
if furniture[npc:name()] then
return "stalker"
end
local community = character_community(npc)
if not blacklisted_comms[community] then
return community
end
local squad_community = get_object_squad(npc):get_squad_community()
if not blacklisted_comms[squad_community] then
return squad_community
else
return default
end
end
-- to_spawn should be table of sections to amount
-- if check_existing is true, only spawns up to that amount in trader inventory. else arbitrarily spawns
function spawn_items(npc, to_spawn, check_existing)
local npc_name = npc:name()
local alive_or_furniture = xr_conditions.is_alive(db.actor, npc) or furniture[npc_name]
if not alive_or_furniture then return end
local supply_table = {}
copy_table(supply_table, to_spawn)
if check_existing then
local function itr_inv(temp, item)
if supply_table[item:section()] and supply_table[item:section()] > 0 then
-- printf("Found 1 of %s", item:section())
supply_table[item:section()] = supply_table[item:section()] - 1
end
end
npc:iterate_inventory(itr_inv)
end
for k,v in pairs(supply_table) do
-- printf("Creating %s of %s", v, k)
for i=1, v do
-- printf("Created %s", k)
alife_create_item(k, npc)
end
end
end
AddScriptCallback("trader_on_restock")
@@ -0,0 +1,74 @@
local new_art = {}
--[[
categories:
section -> {
section = name of category
articles = section name (title, append _text for info)
}
]]
-- just holds the new categories
local new_cat = {}
_g.ui_pda_autoinject = "blocked" --blocks this script under old name from being loaded.
function parse_cat()
local ini_cat = ini_file("plugins\\encyclopedia_custom\\categories\\importer.ltx")
ini_cat:section_for_each(function(section)
printf("category: processing %s", section)
table.insert(new_cat, section)
end)
local ini_art = ini_file("plugins\\encyclopedia_custom\\articles\\importer.ltx")
ini_art:section_for_each(function(section)
printf("article: processing %s", section)
local line_count = ini_art:line_count(section) or 0
for i=0,line_count-1 do
local junk1, article, category = ini_art:r_line(section, i, "", "")
if not new_art[category] then new_art[category] = {section = category} end
if not new_art[category].articles then new_art[category].articles = {} end
table.insert(new_art[category].articles, article)
end
end)
end
InitArticles = ui_pda_encyclopedia_tab.pda_encyclopedia_tab.InitArticles
function ui_pda_encyclopedia_tab.pda_encyclopedia_tab:InitArticles(section_c)
InitArticles(self, section_c)
if new_art[section_c] then
local category = new_art[section_c]
local articles = category and category.articles or nil
if (not articles) then return end
-- Create each article item and add it to the category.
local item = nil
local section = nil
local n = 1
for i = 1, #articles do
section = articles[i]
if (section) then
local clr = ui_pda_encyclopedia_tab.UpdateColor(section)
item = ui_pda_encyclopedia_tab.pda_encyclopedia_entry(section, n, clr)
self.article_list:AddExistingItem(item)
n = n + 1
end
end
end
end
InitCategories = ui_pda_encyclopedia_tab.pda_encyclopedia_tab.InitCategories
function ui_pda_encyclopedia_tab.pda_encyclopedia_tab:InitCategories()
InitCategories(self)
printf("there are %s new categories", #new_cat)
for k,v in pairs(new_cat) do
local clr = ui_pda_encyclopedia_tab.UpdateColor(v)
item = ui_pda_encyclopedia_tab.pda_encyclopedia_entry(v, k, clr)
self.category_list:AddExistingItem(item)
end
end
function on_game_load()
parse_cat()
end
function on_game_start()
RegisterScriptCallback("on_game_load",on_game_load)
end
@@ -0,0 +1,29 @@
-- standalone class to enable custom code on rclick props
class "UICellPropertiesCustom" (utils_ui.UICellProperties)
function UICellPropertiesCustom:__init(functor) super()
self.functor = functor
end
function UICellPropertiesCustom:OnListItemDbClicked()
if self.list_box:GetSize()==0 then return end
local item = self.list_box:GetSelectedItem()
if not (item) then
return
end
if item.func then
if item.params then
pcall(self.functor, unpack(item.params))
else
pcall(self.functor)
end
self.action_moment = time_continual()
end
if (self:IsShown()) then
self:OnHide()
end
end
@@ -0,0 +1,131 @@
ini_drops = ini_file("items\\settings\\wpo_drop_cond.ltx")
ini_prices = ini_file("items\\settings\\part_prices.ltx")
ini_parts = itms_manager.ini_parts
-- temp condition for trade
print_dbg = arti_jamming.print_dbg
has_parts = arti_jamming.has_parts
is_part = arti_jamming.is_part
get_parts_list = arti_jamming.get_parts_list
get_config = a_arti_jamming_mcm.get_config
math_ceil = math.ceil
parts_list = a_wpo_parts.parts_list
TraderAuto = trader_autoinject.update
function trader_autoinject.update(npc)
TraderAuto(npc)
add_parts(npc) -- you define this function ok
end
local BASE_AMT = 15
function add_parts(npc)
if trader_autoinject.get_trader_type(npc) == trader_autoinject.MECHANIC then
-- purge any existing parts
function itr(temp, item)
if item and is_part(item:section()) then
local se_itm = alife_object(item:id())
if se_item then
alife_release_id(item:id())
end
end
end
npc:iterate_inventory(itr)
-- generate an amount of parts based on trader type
local tbl = {}
local supply_level = trader_autoinject.supply_level(npc, true) or 1
print_dbg("npc %s has supply level %s", npc:name(), supply_level)
for i=1,supply_level * BASE_AMT do
local part = random_key_table(parts_list)
print_dbg("Adding %s to trader %s", part, npc:name())
if tbl[part] then
tbl[part] = tbl[part] + 1
else
tbl[part] = 1
end
end
if supply_level > 1 then
tbl["partskit_tool"] = 1
end
-- add the parts
trader_autoinject.spawn_items(npc, tbl, true)
end
end
function on_get_item_cost(kind, obj, profile, calculated_cost, ret)
-- ret.new_cost = 500
if profile.mode == 2 then
local sec = obj:section()
local price = ini_prices:r_float_ex("wpo_part_prices", sec) or 0
if price and price > 0 then
ret.new_cost = price * profile.discount
end
elseif has_parts(obj) and get_config("saletype") == 1 then
local parts = se_load_var(obj:id(), obj:name(), "parts")
local count, count_dmg = 0, 0
calculated_cost = ret.new_cost or calculated_cost
for k,v in pairs(parts) do
if is_part(k) then
count = count + 1
if v < 60 then
count_dmg = count_dmg + 1
end
end
end
ret.new_cost = clamp(calculated_cost * (1 - count_dmg/count), 1, calculated_cost)
end
end
DeathWeaponDrop = death_manager.set_weapon_drop_condition
-- weapon drop patching
-- read the custom drop configs and apply lagrange formula to decide condition
function death_manager.set_weapon_drop_condition(npc,itm)
DeathWeaponDrop(npc, itm)
local has_part = has_parts(itm)
if not has_part then return end
local rank = npc:character_community() == "zombied" and "novice" or ranks.get_obj_rank_name(npc)
local condition = 0
local drop_sec = get_config("altroll") and "weapons_larp" or "weapons"
local rank_drops = ini_drops:r_string_ex(drop_sec, rank)
if get_config("altroll") then
print_dbg("Using larp eval")
condition = larp.pick(larp.str_to_coords(rank_drops), 10)
else
conds = larp.str_explode_num(rank_drops, ",")
condition = math.random(conds[1], conds[2])
end
print_dbg("New custom condition for item %s, rank %s is %s", itm:section(), rank, condition)
condition = clamp(condition,5,100)
condition = condition / 100
itm:set_condition(condition)
-- custom eval parts
if has_part and get_config("altpartroll") then
print_dbg("alt eval for weapon")
weapon_eval_parts(itm)
end
end
function weapon_eval_parts(wpn)
local parts = get_parts_list(wpn)
local con = math_ceil(wpn:condition()*100)
local parts_data = {}
local final_chance = 25 + math_ceil(con/2.5)
print_dbg("Chance to beat is %s", final_chance)
for i,part in pairs(str_explode(parts, ",")) do
drop = math.random(100) < final_chance and "above" or "below"
coords = ini_drops:r_string_ex("weapon_parts", drop)
parts_data[part] = larp.pick(larp.str_to_coords(coords), 10)
end
se_save_var( wpn:id(), wpn:name(), "parts", parts_data )
end
function on_game_start()
if utils_item.on_get_item_cost then
RegisterScriptCallback("on_get_item_cost", on_get_item_cost)
end
end
File diff suppressed because it is too large Load Diff