local DEBUG = false local ini_speed = ini_file("items\\outfit_speed\\importer.ltx") function print_dbg(txt, ...) if get_config("debug") then printf("speed | %s | " .. txt, time_global(), ...) end end local last_check = nil local check_freq = 1000 local function actor_on_update() local tg = time_global() if not last_check then last_check = tg end if tg < last_check + check_freq then return end last_check = tg manage_weapon_speed() manage_encumbrance() end function actor_item_to_ruck() manage_outfit_speed() manage_encumbrance() end function actor_item_to_slot() manage_outfit_speed() manage_encumbrance() end function actor_item_to_belt() manage_encumbrance() end function actor_on_item_use() manage_encumbrance() end local last_outfit = 0 function manage_outfit_speed() local outfit = db.actor:item_in_slot(7) local outfit_id = outfit and outfit:id() or 0 local outfit_sec = outfit and outfit:section() or "no outfit" if last_outfit ~= outfit_id then last_outfit = outfit_id local coef = outfit and get_outfit_speed(outfit, outfit_sec, false) or 1 local sprint_coef = outfit and get_outfit_speed(outfit, outfit_sec, true) or 1 print_dbg("Speed for %s is %s, sprint speed is %s", outfit_sec, coef, sprint_coef) speed.add_speed("outfit_speed", coef, false, true) speed.add_speed("outfit_sprint_speed", sprint_coef, true, true) end end local last_weapon = 0 function manage_weapon_speed() if not get_config("weapon") then speed.remove_speed("weapon_speed", coef, true, true) return end local weapon = db.actor:active_item() local weapon_id = weapon and weapon:id() or 0 if weapon_id ~= last_weapon then local coef = 1 last_weapon = weapon_id weapon_sec = (weapon and IsWeapon(weapon)) and weapon:section() or "no weapon" local kind = weapon_sec == "no weapon" and weapon_sec or ini_sys:r_string_ex(weapon_sec,"kind") if kind == "w_pistol" or kind == "w_melee" or kind == "no weapon" then coef = 1.08 elseif kind == "w_smg" then coef = 1.04 else local weight = weapon:weight() if weight <= 3.5 then coef = 1 elseif weight <= 5.86 then coef = 0.96 else coef = 0.92 end end speed.add_speed("weapon_speed", coef, true, true) end end local enc_table = { 1.08, -- 12% boost light 1, 0.92, -- 12% penalty heavy 0.84, -- 24% penalty fat -- exos 1.04, -- 6% boost light 1, 0.96, -- 6% penalty heavy 0.92 -- 12% penalty fat } local last_tot_weight = 0 local last_max_weight = 0 function manage_encumbrance() if not get_config("encumbrance") then speed.remove_speed("encumbrance", coef, false, true) return end local actor = db.actor local tot_weight = actor:get_total_weight() local max_weight = actor:get_actor_max_weight() local outfit = actor:item_in_slot(7) local backpack = actor:item_in_slot(13) max_weight = max_weight + (outfit and outfit:get_additional_max_weight() or 0) max_weight = max_weight + (backpack and backpack:get_additional_max_weight() or 0) actor:iterate_belt( function(owner, obj) local c_arty = obj:cast_Artefact() max_weight = max_weight + (c_arty and c_arty:AdditionalInventoryWeight() or 0) end) actor:cast_Actor():conditions():BoosterForEach( function(booster_type, booster_time, booster_value) if (booster_type == 4) then --eBoostMaxWeight max_weight = max_weight + booster_value end end) if (tot_weight == last_tot_weight) and (max_weight == last_max_weight) then return else last_tot_weight = tot_weight last_max_weight = max_weight end local coef = tot_weight / max_weight -- printf("Total weight is %s, max weight is %s.", tot_weight, max_weight) local state = 0 if coef < 0.25 then state = 1 elseif coef < 0.71 then state = 2 elseif coef < 1 then state = 3 else state = 4 end if outfit and SYS_GetParam(0, outfit:section(), "repair_type") == "outfit_exo" then state = state + 4 end -- printf("Actor did something. Weight coef is %s. Update speed to %s",coef, speed_table[state]) speed.add_speed("encumbrance", enc_table[state], false, true) end -- local outfits = {} function get_outfit_speed(obj, sec, sprint) if not sec then sec = obj:section() end local kind = SYS_GetParam(0, sec, "kind") -- check for specific outfit if ini_speed:section_exist(sec) then -- do nothing print_dbg("%s has custom speed", sec) elseif ini_speed:section_exist(kind) then sec = kind end local to_search = sprint and "sprint_speed" or "speed" return ini_speed:r_float_ex(sec, to_search) or 1 end PrepStats = utils_ui.prepare_stats_table function utils_ui.prepare_stats_table() PrepStats() if not utils_ui.stats_table.outfit.speed then utils_ui.stats_table.outfit.speed = { index= 19, typ= "float", name= "ui_inv_outfit_speed", icon_p= "ui_am_prop_sprint", icon_n= "", track= false, magnitude= 100, unit= "%", compare= false, sign= false, show_always= false , value_functor= {"outfit_speed_mcm","get_outfit_speed"}} end end -- If you don't use MCM, change your defaults from here. local defaults = { ["weapon"] = true, ["encumbrance"] = true, ["debug"] = false } function get_config(key) if ui_mcm then return ui_mcm.get("speed/"..key) else return defaults[key] end end function on_mcm_load() op = { id= "speed",sh=true ,gr={ { id= "title",type= "slide",link= "ui_options_slider_player",text="ui_mcm_speed_title",size= {512,50},spacing= 20 }, {id = "weapon", type = "check", val = 1, def = true}, {id = "encumbrance", type = "check", val = 1, def = false}, {id = "debug", type = "check", val = 1, def = false} } } return op end function on_game_start() RegisterScriptCallback("actor_on_update",actor_on_update) RegisterScriptCallback("actor_item_to_ruck",actor_item_to_ruck) RegisterScriptCallback("actor_item_to_slot",actor_item_to_slot) RegisterScriptCallback("actor_item_to_belt",actor_item_to_belt) RegisterScriptCallback("actor_on_item_use",actor_on_item_use) end