Last active
July 25, 2023 13:28
-
-
Save zneix/fb99059520fe94cfcfaaefe8d02af6db to your computer and use it in GitHub Desktop.
zneix's DorHUD user.lua file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- zneix's DorHUD configuration, available @ https://gist.github.com/zneix/fb99059520fe94cfcfaaefe8d02af6db or https://cdn.zneix.eu/pdthmods/user.lua | |
-- note to self, view diff compared to what's online with: gh gist view fb99059520fe94cfcfaaefe8d02af6db -f user.lua | git diff - user.lua | |
-- some things in here might require an additional mod of mine; get it here: https://github.com/zneix/zneixs_fixes | |
local is_first_load = ... | |
local always_reload = true -- if true, always use values defined in this file and thus ignoring any dynamic changes; default false | |
local prioritize_gui = false -- if true, config values defined in this file won't overwrite any existing settings set with the gui; default false | |
-- helper functions | |
-- escape left square bracket in s so that they aren't parsed as colours | |
local function clear_string(s) | |
return (string.gsub(s, "%[", "%[%[")) | |
end | |
-- remove leading and trailing spaces from s | |
local function trim(s) | |
return (string.gsub(s, "^%s*(.-)%s*$", "%1")) | |
end | |
-- localize an integer value to make it look prettier to a user | |
local function format_integer(integer) -- returns string | |
local reversed_integer = string.reverse(tostring(integer)) | |
-- insert commas every three digits, remove trailing commas | |
local formatted_integer = reversed_integer:gsub("(%d%d%d)", "%1,"):gsub(",$", "") | |
-- reverse the formatted number back to its original order. keep in mind that returned type is a string | |
return formatted_integer:reverse() | |
end | |
-- iso for the win (to be used as a format for os.date()) | |
local iso8601 = "%Y-%m-%d %H:%M:%S" | |
-- more colours | |
-- [name] sets the color by name, but there's only a handful defined by default (add new with e.g. Color.orange = Color("FF9900")) | |
-- [#aarrggbb] sets the color by hex value (I think some places actually use [#rrggbbaa], e.g. menu_waiting_is_{,not_}ready) | |
-- [] sets the color to the previous value | |
-- [[ escapes the left bracket | |
Color.nice_blue = Color("7DEEFF") | |
Color.orange = Color("FF9900") | |
Color.grey = Color(.7, .7, .7) | |
Color.blueish = Color("B3FCE5") | |
Color.golden = Color("FFCF7D") | |
Color.assault = Color(1, .9, .2, .2) | |
Color.assault_break = Color(.9, 0, 1, 0) | |
Color.cheat = Color("FF8E7C") | |
Color.team_ai = Color(1, 0.2, 0.8, 1) | |
Color.meds = Color("00EFC3") | |
Color.ammo = Color("A85600") | |
Color.regen = Color("6B00EF") | |
Color.down = Color("FC1B6E") | |
Colors = Color -- declare an alias to prevent very rare crashes in some places | |
-- helper variables for localization overrides | |
local loc_peer = "[peer_color]$PLAYER_NAME;[] " | |
local loc_self = "[peer_color]You[] " | |
local loc_meds = "[meds]took MEDS[] [DOWNS;#FC5D5D;#FFFFFF]$REGEN_PERCENT;%[], [meds]($DOWNS_DIFF;/$TOTAL_DOWNS; downs)" | |
local loc_ammo = "[ammo]took AMMO [AMOUNT;#FC5D5D;#FFFFFF]$AMOUNT_PERCENT%.2f;%" | |
local loc_down = "[down]went DOWN [DOWNS;#FFFFFF;#FC5D5D]$DOWNS;[]/$TOTAL_DOWNS;" | |
local localization = { | |
menu_setup_game = "SUFFERING", | |
menu_players_online = "$COUNT; POOR SOULS", | |
menu_start_the_game = "THROW ANOTHER RUN", | |
menu_play_online = "NOOBS", | |
menu_play_with_friends = "GOOD PLAYERS", | |
menu_play_campaign = "MULTIPLAYER", | |
menu_play_single_player = "SINGLEPLAYER", | |
menu_visit_forum = "FORUM", | |
-- mask names | |
menu_mask_gold = "GOLD", | |
menu_mask_platinum = "PLATINUM", | |
menu_mask_pmp1_pbm = "BAG OF SHAME", -- I use this mask whenever I feel very embarassed or sad | |
menu_mask_santa = "DUSSEL", -- yes | |
-- requires "zneixs_fixes" v1.0.2 or newer | |
menu_waiting_is_not_ready = "[#e53333ff]NOT READY", | |
menu_waiting_is_ready = "[#00ff00e5]READY", | |
-- handguns | |
debug_glock = "WATERGUN", | |
debug_raging_bull = "BRONCO", | |
debug_c45 = "CROSSKILL", | |
debug_beretta92 = "B9", | |
-- primary weapons | |
debug_hk21 = "BRENNER", | |
debug_r870_shotgun = "REINBECK", | |
debug_m14 = "M308", | |
debug_ak47 = "AK", | |
debug_test_raycast_weapon = "AMCAR", | |
debug_m4 = "AMCAR", -- used by managers.player | |
-- secondary weapons | |
debug_mossberg = "LOCO", | |
debug_m79 = "GL", | |
debug_mp5 = "COMPACT 5", | |
debug_mac11 = "MARK 11", | |
debug_upgrade_mr_nice_guy = "MS NICE GAL", | |
debug_russian = "RUSSIAN", | |
debug_american = "AMERICAN", | |
debug_german = "GERMAN", | |
debug_spanish = "SPANISH", | |
debug_mugshot_electrified = "TASED", | |
debug_mugshot_downed = "DYING", | |
debug_mugshot_in_custody = "DEAD", | |
debug_low_ammo = "FIVE BULLETS LEFT", | |
debug_no_ammo = "AMMUNITION DEPLETED", -- why not pretend heisters are wearing H.E.V. suits | |
-- heist names | |
debug_bank = "FIRST WORLD DANK", | |
debug_street = "HELL STREET", | |
debug_apartment = "PANIK ROOM", | |
debug_bridge = "GREEN FRIDGE", | |
--debug_diamond_heist = "", | |
--debug_slaughter_house = "", | |
debug_suburbia = "C4UNTERFEIT", | |
--debug_secret_stash = "", | |
--intro_secret_stash = "", | |
--debug_hospital = "", | |
mask_check_cheater = "Player [peer_color]$PLAYER_NAME;[] [[$PLAYER_LEVEL;] [cheat]DOES NOT[] have the $MASK; mask set!", | |
hint_reload = "DON'T FORGET TO RELOAD MR FREEMAN", | |
-- TODO: make player names in the hints below use corresponding colours, see https://discord.com/channels/575788361046818837/575793076291764230/998664262287380562 | |
--hint_you_were_rescued (uncuffed, guessing the id) | |
--hint_you_were_helpedup = "[teammate_color]YOU[] HAVE BEEN HELPED UP BY [helper_color]$HELPER;[]!", | |
--hint_you_were_revived = "[helper_color]$HELPER;[] TRADED A HOSTAGE AND GOT [teammate_color]YOU[] OUT OF CUSTODY!", | |
--hint_you_rescued = "[helper_color]YOU[] UNCUFFED [teammate_color]$TEAMMATE;[]!", | |
--hint_you_helpedup = "", | |
--hint_you_revived = "[helper_color]YOU[] RELEASED [teammate_color]$TEAMMATE[] FROM CUSTODY!", | |
--hint_teammate_rescued = "[teammate_color]$TEAMMATE;[] HAS BEEN UNCUFFED BY [helper_color]$HELPER;[]", | |
--hint_teammate_helpedup = "[teammate_color]$TEAMMATE;[] HAS BEEN HELPED UP BY [helper_color]$HELPER;[]!", | |
--hint_teammate_revived = "[teammate_color]$TEAMMATE;[] HAS BEEN RELEASED FROM CUSTODY THANKS TO [helper_color]$HELPER;[]!", | |
-- hint_teammate_arrested (has been cuffed) | |
-- hint_teammate_downed = "$TEAMMATE; WAS DOWNED IN $LOCATION;!", | |
-- hint_teammate_dead = "$TEAMMATE; IS IN CUSTODY!", | |
-- also show amount of unacknowledged packets on the extras panel | |
hud_player_ping = "$PING;ms $UNACKNOWLEDGED;", | |
-- taking meds | |
hud_chat_used_med_bag = loc_peer .. loc_meds, | |
hud_chat_player_used_med_bag = loc_self .. loc_meds, | |
-- regenerating, most likely due leveling up (same result as if you'd take meds + take ammo) | |
hud_chat_downs_restore = loc_peer .. "[regen]has regenerated", | |
hud_chat_player_downs_restore = loc_self .. "[regen]have regenerated", | |
-- taking ammo | |
hud_chat_ammo_taken = loc_peer .. loc_ammo, | |
hud_chat_player_ammo_taken = loc_self .. loc_ammo, | |
-- getting downed | |
hud_chat_downs = loc_peer .. loc_down, | |
hud_chat_player_downs = loc_self .. loc_down, | |
} | |
local welcome_text = "Welcome, my lobby is using DAHM, version " .. D:version() -- re-used by the main welcome message, used in a hacky way inside pre_show_callback but works | |
local config = { | |
override_user_config_with_gui_settings = prioritize_gui, -- prioritize this file instead of the gui config if set to false | |
framerate_limit = 130, -- sets maximum FPS to this value; vanilla game has an cap of 130 FPS which is most optimal to use. Going far above said cap may have impact on the gameplay. | |
--debug_show_raw_text_strings = true, -- makes game show string IDs instead of actual strings, useful while finding string IDs to later replace them in "localization" table | |
banlist_path = "mods/banlist.csv", -- custom path to the banlist; I like keeping things organized under the same directory | |
chat_log_to_file = "logs/chat.log", -- logs ALL chat output to this file | |
updater_allow_beta_versions = true, -- check for beta updates / prefer beta version of dorhud | |
notify_outdated = true, | |
notify_self = true, | |
-- messages shown to other players (and me) whenever they join my lobby | |
welcome_messages = { | |
{ | |
text = welcome_text, | |
new_peers_only = true, | |
host_only = true, | |
as_lobby = true, | |
options = { | |
--dummy_message = true, | |
--skip_local = false, | |
pre_show_callback = function(peer, is_new) | |
if Util:is_in_state("any_ingame_playing") then | |
return welcome_text .. "\n The heist has already started.", nil -- text override, options object override | |
end | |
end | |
} | |
}, | |
-- inform peers if we're playing unpatched UC | |
{ | |
text = "WARNING: this lobby has disabled DAHM's Undercover fix! Expect bugged specials.", | |
new_peers_only = false, -- show this to everyone regardless of whether they've already been in the lobby (similar to ovk_193/mutator motds) | |
host_only = true, | |
as_lobby = true, | |
options = { | |
priority = 10, -- better if it's sent later, I think... | |
visibility_fn = function(peer, is_new) | |
return (D:conf("disable_mission_fixes_undercover") or D:conf("disable_mission_fixes")) and (Global.level_data and Global.level_data.level_id == "secret_stash") | |
end, | |
}, | |
}, | |
}, | |
--== chat interface | |
debug_cml_show_add_character_calls = false, -- prints calls to "add_character" game function, requires "character_n_mask_in_loadout" mod | |
cml_always_show_chat = true, -- always shows chat while in loadout menu, requires "character_n_mask_in_loadout" mod | |
chat_enable_singleplayer_input = true, -- enable chat (while in-game) in singleplayer | |
chat_alt_clipboard_mode = true, -- enables Ctrl+C, Ctrl+V, Ctrl+X, Ctrl+A in chat, requires DAHM 1.15.2.0 or newer | |
chat_input_history_limit = 80, | |
chat_height_multiplier = 3.6, -- general chat height multiplier | |
chat_height_multiplier_ingame = 5, -- chat height multiplier (ingame chat only) | |
chat_input_width_multiplier = 2.5, -- chat width multiplier (ingame chat only) | |
--chat_output_position_override = { x = 100, y = 250, is_relative_offset = false }, -- move chat output too (100;250) (ingame chat only) | |
invalid_chat_command_notify = true, -- don't send invalid commands to chat | |
chat_split_uc_sender = true, -- reference: https://discord.com/channels/575788361046818837/575793146987020292/1096352936117932123 | |
zfx_chat_lobby_message_title_color = Color("00FFFF"), -- set custom message title's colour for non-player messages, requires "zneixs_fixes" v1.0.3 or newer | |
--== player verification/checking/in-game anticheat | |
profile_checker_ban_days_to_report = nil, -- by default, VAC bans older than 1111 days are ignored, but I don't want to ignore these at all | |
--profile_checker_ignore_fail_callback = true, | |
perform_playtime_check = true, -- check total players' playtime when we first see them | |
check_result_always_visible = false, -- spammy if true; show all profile check results, even the valid ones | |
--anticheat_extra_desync_time = 0, -- some events happen in the wrong order and desync can mess up the detection | |
anticheat_notify_sender = false, -- don't send a message to a cheater if we detect something, they don't need to know | |
anticheat_verify_bullet_damage = true, -- verify that bullet damage does not exceed weapon limits | |
anticheat_verify_damage_against_loadout = true, -- use equipped weapons for damage calculations | |
anticheat_invalid_bullet_damage_publish = true, -- publish incorrect bullet damage | |
--== bugfixes/mission-related | |
ovk_193_ammo_respawn = false, -- controls the amount of ammo clients respawn with, default: nil (ovk_193 mod explicitly checks for this being set to false to not respawn with full ammo) | |
bugfixes_show_time_correction_in_chat = true, -- at the end of the heist show corrected endgame time | |
--disable_mission_fixes = true, -- disables all DAHM's mission fixes on all heists | |
--disable_mission_fixes_undercover = true, -- for true hell on undercover | |
--== in-heist interface/misc options | |
ai_mask_set_override = { | |
--[[dallas]] russian = { "troll", "tester", "santa" }, | |
--[[hoxton]] american = { "tester", "clowns" }, | |
--[=[wolf]=] german = { "troll", "halloween" }, | |
--[[chains]] spanish = { "troll", "bf3" }, | |
}, -- makes team AI wear specified mask set (option can be set to a simple string with mask set name for all team AI) | |
hints_blacklist = { | |
"take_hostages", -- bad advice in general, it's blacklisted by default | |
"cant_stand_up", -- most annoying yet useless hint EVER | |
"civilian_escaped", -- brings more confusion (e.g. making you think a teammate was downed) than benefit | |
}, | |
zfx_always_full_reload_ak = true, -- requires "zneixs_fixes" v1.0.4 or newer | |
skip_intro_auto_skip_on_level = true, -- always skip all intros, some people might not like it but it fits me | |
--== pre-heist interface options (lobby/game browser) | |
--create_ban_player_menu_item = true, -- bugged, TODO: I should investigate this | |
lobby_show_recreate_button = true, -- shows 'RE-REGISTER LOBBY' button | |
replace_ingame_invite = true, -- collapses 2 silly vanilla menu entries into 1 | |
debug_add_reputation_permission = { "146", "169" }, -- adds an extra reputation requirement(s) which can be used while hosting | |
zfx_show_difficulty_in_lobby_browser = true, -- shows the heist difficulty in lobby browser, requires "zneixs_fixes" v1.0.3 or newer | |
--debug_insert_dummy_lobby = true, -- shows a fake lobby in the lobby browser | |
player_verification_mugshot_local_peer_color = "orange", -- sets outline of my own mugshot in the lobby/kitmenu to a nice orange colour | |
--== HUD-related options | |
hud_prefer_virtual_reps = true, | |
hud_present_virtual_level_up = true, -- show own virtual levelups | |
--hud_allow_virtual_rep_sync = true, | |
hud_show_all_completed_challenges = true, | |
--hud_show_all_completed_challenges_inclusion_list = false, -- we use an exclusion list instead to display everything except the ones below | |
hud_show_all_completed_challenges_exclusion_list = "civil_disobedience eagle_eyes bullet_to_bleed_out intimidating revived diplomatic arrested deploy_.+ tiedown_%w+ fall_to_bleed_out .+_no_civilians_hard .+_no_deaths_hard .+_no_bleedouts_hard .+_success_overkill .+_overkill_no_trade .+_success_overkill_%d+ christmas_present.* duck_hunting det_gadget saviour five_five_five citys_finest akimbo", -- counter stuff is ignored anyway | |
hud_bleedout_time_threshold = 5, -- a down is considered critical if at most this many seconds | |
hud_show_multikills = 3, -- minimal required amount of enemies killed at once to trigger multikill indicator (e.g. "x5") for a brief moment | |
hud_show_collected_money_at_max_level = true, -- show cash pickups even if at 193/194 reputation | |
hud_hide_name_labels_in_steelsight = false, | |
hud_hide_waypoints_in_steelsight = true, | |
-- player's hud | |
hud_show_loadout_deployable = true, | |
hud_show_loadout_weapons = true, | |
hud_xp_panel_style = "virtual_rep_with_progress2", | |
hud_hidden_gui = "-ammo_clip_icons", | |
hud_ammo_format = "%2$s / %1$s", -- "payday ammo" format: remaining bullets left in clip / remaining bullets total (just like in pd2) | |
-- mugshot | |
hud_show_mugshot_timers = true, -- show downed timers on the mugshots as well | |
hud_show_peer_ids = true, -- show ID in front of peer names on mugshots | |
hud_name_marker_obj_override = { use_chat_colors = true }, -- override object for showing peer IDs in respective chat colours | |
hud_show_host_mark = ">> ", -- add an indicator to the host's name on their mugshot (suppressed if "hud_show_peer_ids" is set to true) | |
hud_name_label_format = "$NAME; [[[peer_color]$LEVEL;[]]", -- add colors to the name (above player) label | |
hud_mugshot_name_format = "$NAME; [[[peer_color]$LEVEL;[]]", -- add colors to the mugshot (on hud) name | |
hud_ai_mugshot_name_format = "[team_ai]$NAME;[]", | |
--hud_mugshot_ai_test = true, -- makes AI's mugshots behave like regular player's while hosting or smth, for testing purposes | |
--hud_name_label_ai_test = true, | |
--hud_extras_panel_show_chat_colors = true, | |
hud_equipment_weapon_mark_enabled = true, -- show an indicator for currently selected weapon by the criminal on the corresponding mugshot | |
hud_hide_deployable_when_used = "transparent", -- accepts: "transparent", "darken", "remove"(? check hud/modhooks.lua:"OnCommand deployed") | |
hud_equipment_disabled_alpha = .3, | |
hud_equipment_disabled_rgb = .7, | |
-- show teammates' (and own) actions in chat | |
hud_show_peer_downs = "always", -- shows others' downs on mugshot | |
hud_show_player_downs = "always", -- shown own downs on mugshot | |
hud_show_downs_restore_in_chat = "all", -- show meds taken / levelup regenerations in chat (everyone) | |
hud_show_ammo_taken_in_chat = "all", -- shows ammo taken in chat (everyone) | |
hud_show_downs_in_chat = "all", -- shows downs in chat (others); can also be true | |
hud_show_player_downs_in_chat = "all", -- shows downs in chat (own) | |
hud_chat_critical_downs_only = false, -- don't ignore any downs | |
hud_hide_player_downs = false, -- we don't want to ignore our own downs | |
-- overriding all sorts of colours in the hud, only available since DAHM 1.16.1.4 | |
hud_color_overrides = { | |
mugshot = { | |
weapon_outline = Color.orange, | |
weapon = Color.white:with_alpha(.7), | |
deployable = {}, -- seems like nested values are needed to be reposted or else tablex.merge will unset/delete dor pls fix (or not) | |
}, | |
health = { | |
name = Color(0, 0, 0, 0), -- just give it zero opacity to simply "hide it" | |
}, | |
}, | |
--== stats line | |
-- hud_str vars: | |
-- 1: session timer | |
-- 2: "hud_kills_str" variable | |
-- 3: assault timer | |
-- 4: difficulty | |
-- 5: heist name | |
-- hud_kills_str vars: | |
-- 1: total kills | |
-- 2: total specials kills | |
-- 3: civs killed (str, conf:hud_kills_civs_str) | |
-- 4: total head shots | |
-- 5: accuracy (float) | |
-- 6: shield kills | |
-- 7: spooc kills | |
-- 8: taser kills | |
-- 9: tank kills | |
-- 10: total head shots ratio (float) | |
-- 11: kills per minute (float) | |
-- 12: total shots | |
-- 13: total hits | |
-- 14: weapon accuracy (float) | |
-- 15: weapon shots | |
-- 16: weapon hits | |
-- new variables introduced in 1.15.2.0-beta5 (on earlier versions using these will crash!) | |
-- 17: weapon damage | |
-- 18: weapon damage per minute | |
-- 19: weapon damage per shot | |
-- 20: damage | |
-- 21: damage per minute | |
-- 22: damage per shot | |
-- 23: weapon total kills | |
-- xx: weapon total specials kills -- unused(?) | |
-- 24: weapon head shots | |
-- 25: weapon head shot ratio | |
-- 26: weapon kills per minute | |
--hud_offset_x = 62, -- integer pixel offset from the left | |
--hud_offset_y = 30, -- integer pixel offset from the bottom | |
hud_str = "[white]%5$s[] %4$s %2$s %1$s %3$s", | |
hud_kills_str = "[blueish]kills[] [white]%1$i[] [[[orange]kpm %11$.1f[] [#00ffff]hs %10$.1f%%[]] [blueish]specs[] [white]%2$i[] [[[#adcad9]S %6$i[] [#ffff00]T %8$i[] [#00ff00]C %7$i[] [#E67300]D %9$i[]] [#80A0FF]civ %3$s[] [blueish]accuracy[] [[%16$i/%15$i [white]%14$.1f%%[] %13$i/%12$i [white]%5$.1f%%[]]", | |
hud_assault_timer_str = "[assault]/// [#fc9b99]%1$s[] /// ASSAULT[]", -- "/// 00:00:00 ///", everything is red, but the timer is lighter | |
hud_enable_assault_break_timer = true, -- makes the assault timer also count time during assault breaks | |
zfx_assault_break_timer_str = "[assault_break]/// [#6cfc6c]%1$s[] /// CONTROL[]", -- (check #50fc50 as well) | |
hud_kills_civs_relevant_str = "%2$i/%1$i", -- relevant/total (opposite of what's by default) | |
hud_sl_time_precision = 0, -- amount of decimal precision in the 'session timer' in "hud_str" (max 3) | |
zfx_disable_assault_image = true, -- we already have the assault timer on the stats line, so there's no need for an another indicator | |
-- short abbreviations for map names (used by stats line) | |
hud_level_names = { | |
bank = "FWB", | |
heat_street = "HS", | |
bridge = "GB", | |
apartment = "PR", | |
diamond_heist = "DH", | |
slaughter_house = "SH", | |
suburbia = "CF", | |
secret_stash = "UC", | |
hospital = "NM", | |
}, | |
-- short abbreviations of difficulty names (used by stats line), colours taken from Steam statistics page (and https://pdthlbs.net/stats_hsr.php) | |
hud_difficulty_names = { | |
easy = "[#0099cc]EASY[]", | |
normal = "[#99cc00]NORM[]", | |
hard = "[#ffcc00]HARD[]", | |
overkill = "[#ff6600]OVKL[]", | |
overkill_145 = "[#cc0000]145+[]", | |
overkill_193 = "[#dccc00]193+[]", | |
}, | |
--== rich presence, always publish all sorts of information about the currently played heist to both Discord and Steam (because why not, I have nothing to hide) | |
discord_rpc_set_character = true, | |
discord_rpc_set_time = true, | |
steam_publish_game_status = true, | |
steam_publish_party_details = true, | |
steam_publish_player_names_in_private_lobbies = true, | |
steam_publish_player_names = true, | |
steam_publish_game_override = true, | |
steam_publish_singleplayer = true, | |
steam_publish_details_in_singleplayer_mode = true, | |
--== logging options, be careful | |
log_level = 5, -- 6 is highest, but it's too dank, 3/4 is optimal | |
--hud_log_level = 3, | |
--debug_hook_call_logging = 45, | |
--debug_hook_call_orig_logging = true, | |
debug_print_to_log = true, -- shows output of "print" function calls | |
debug_hook_call_blacklist = { | |
module = { ["interact_toggle"] = 1 }, | |
fname = { | |
["update"] = 1, | |
["update_queue"] = 1, | |
["paused_update"] = 1, | |
["update_timers"] = 1, | |
["input_multi_choice"] = 1, | |
["input_kitslot"] = 1, | |
["input_text"] = 1, | |
["is_active"] = 1, | |
["mouse_moved"] = 1, | |
["dropin_progress"] = 1, | |
}, | |
class = { | |
["LocalizationManager"] = 1, | |
["hud:StatisticsManager"] = 1 | |
}, | |
class_fn = { | |
["MenuInput.mouse_moved"] = 1, | |
["MenuInput.input_item"] = 1, | |
["?.script_data"] = 1, | |
["HUDManager._update_name_labels"] = 1, | |
["MenuNodeGui._highlight_row_item"] = 1, | |
["MenuNodeGui._fade_row_item"] = 1, | |
["HUDManager.update_hud_text"] = 1, | |
["ConnectionNetworkHandler:dropin_progress"] = 1, | |
}, | |
}, | |
} | |
-- Explicitly disable some mods without having to remove/delete them: | |
local blacklisted_modules = { | |
"reset_stats_achievements", | |
"ak_for_teamai", -- only made it for SkullHD, not gonna use it personally though | |
"every_drill_7000", -- xd | |
} | |
-- Chat commands which just print text to chat and do nothing else | |
local commands = { | |
dz = "Watch out! Buldozer!", | |
escort = "when you shout at an escort once and stay close to him you don't have to shout again (as long as there's no cops near it)", | |
bags = "Rule #1, always double check your load out before going on a heist. One of you idiots must have switch the bag. How can you guys fucked this up?!?!?! You play this everyday.", | |
dussel = "Each team needs a leader. Listen to him. Do what he says. If he's an idiot you still can choose not to listen, but because you've checked his profile you know if he succeeded this heist in the past or not.", | |
} | |
-- Show in chat how much ammo I have left | |
D:register_chat_command("ammo", "GAME", function(args) | |
local player_unit = managers.player:player_unit() | |
if not alive(player_unit) then | |
return true | |
end | |
local inventory = player_unit:inventory() | |
if not inventory then | |
return true | |
end | |
local chat_msg = "" | |
for _, weapon in ipairs(inventory._available_selections) do | |
local weapon_base = weapon.unit:base() | |
chat_msg = chat_msg .. string.format("%s %s/%s ", localization["debug_" .. weapon_base.name_id] or weapon_base.name_id, weapon_base._ammo_total, weapon_base._ammo_max) | |
end | |
Util:chat_message(trim(chat_msg), true, false) -- change second argument to false to send the message only locally (e.g. for debugging purposes) | |
return true | |
end) | |
-- Sometimes, dunno why, "hud" module does not send a request to some peers for dispatching interation progress information to our client | |
-- This command sends such request manually, helpful if you can't see interaction progress of some players even if they have DAHM installed | |
D:register_chat_command("rqi", "GAME", function(args) | |
local peer_id = tonumber(args:match("%S+")) | |
if not peer_id or not managers.network or not managers.network:session() then | |
return | |
end | |
local peer = managers.network:session():peer(peer_id) | |
if peer ~= nil and not peer:is_local_user() then | |
DNet:send_to_peer(peer, "ModEvent", { module = "hud", event = "EnableInteractionEvents" }, false, false) | |
end | |
end) | |
-- little something for CZ to easily toggle vrep being shown to others | |
D:register_chat_command("vrep", function(args) | |
local vrep_setting = "hud_allow_virtual_rep_sync" | |
local cmd_prefix = D:conf('chat_command_prefix') or '/' | |
local first_arg = args:match("%S+") | |
local setting_value = nil | |
if first_arg == nil or first_arg == "" then | |
Util:chat_message("your vrep sync is: " .. (D:conf(vrep_setting) and "[#00ff00]enabled" or "[#ff0000]disabled"), false, "LOCAL") | |
return | |
end | |
if first_arg == "yes" or first_arg == "true" or first_arg == "1" or first_arg == "on" then | |
setting_value = true | |
elseif first_arg == "no" or first_arg == "false" or first_arg == "0" or first_arg == "off" then | |
setting_value = false | |
end | |
if setting_value == nil then | |
Util:chat_message("bad arguments, syntax: " .. cmd_prefix .. "vrep <on|off>", false, "LOCAL") | |
return | |
end | |
D:process_chat_input(cmd_prefix .. "set " .. vrep_setting .. " = " .. tostring(setting_value)) | |
D:process_chat_input(cmd_prefix .. "persist") | |
end) | |
D:register_chat_command("calc_rep", function(args) | |
if not managers.experience._calculate_vrep_from_money then -- just to not make people's game crash in some places, maybe... not gonna keep this check for a long while anyway | |
Util:chat_message("update your DAHM, silly. this piece of code needs version 1.16.1.3 or above", false, "LOCAL") | |
return | |
end | |
local cmd_prefix = D:conf('chat_command_prefix') or '/' | |
local value = tonumber(args and args:match("^(%d+)")) | |
if value == nil then | |
Util:chat_message("bad arguments, syntax " .. cmd_prefix .. "calc_rep <cash amount|level>", false, "LOCAL") | |
return | |
end | |
-- assume we're giving a level and want cash if it's 5000 or below (since that's maximum vrep anyway) | |
-- or otherwise, giving cash and seeing which level it gets up otherwise | |
if value > 5000 then | |
local rep = managers.experience:_calculate_vrep_from_money(value) | |
Util:chat_message("Reputation achieved with [#00ff00]" .. format_integer(value) .. "[] cash: [#ff0000]" .. rep, false, "LOCAL") | |
elseif value > 0 then | |
local cash = managers.experience:_get_required_money_for_level(value) | |
Util:chat_message("Cash needed to reach rep [#ff0000]" .. tostring(value) .. "[]: [#00ff00]" .. format_integer(cash), false, "LOCAL") | |
else | |
-- silly goose, invalid value (maybe give some feedback in chat? prob not needed) | |
end | |
end) | |
-- /r command for reloading config | |
D:register_command("r", function() | |
local userfile, err = D:root_path() .. 'user.lua' | |
if io.is_readable(userfile) then | |
local userfile_f | |
userfile_f, err = loadfile(userfile) | |
if userfile_f then | |
local success, ret = pcall(userfile_f, true) | |
if success then | |
-- update some stuff to make use of newly loaded config | |
if managers.hud then | |
managers.hud:update_hud_settings() | |
end | |
Util:chat_message("Config has been reloaded.", false, "DEBUG") | |
else | |
err = ret | |
end | |
end | |
else | |
err = "user.lua file is not readable" | |
end | |
if err then | |
Util:chat_message("Config cannot be reloaded: " .. tostring(err), false, "DEBUG") | |
end | |
end) | |
-- Override existing keybinds and add new ones | |
local keybind_overrides = { | |
hud_scroll_chat_up = "left alt + k", | |
hud_scroll_chat_down = "left alt + j", | |
hud_toggle_grayscreen = "num 5", | |
} | |
--module:hook("OnKeyPressed", "hud_scroll_chat_up", nil, { run_in_chat = true }, function() scroll_chat("up") end, false) | |
--module:hook("OnKeyPressed", "hud_scroll_chat_down", nil, { run_in_chat = true }, function() scroll_chat("down") end, false) | |
D:register_keybind("toggle_sfx_mute", "f3", function() | |
if not MenuCallbackHandler then return end -- make sure MCH is available | |
D._menu_cb_handler = D._menu_cb_handler or MenuCallbackHandler:new() | |
D._menu_cb_handler:set_sfx_volume({ value = function() | |
if D._sfx_volume_level then | |
local lvl = D._sfx_volume_level | |
D._sfx_volume_level = nil | |
return lvl | |
else | |
D._sfx_volume_level = 3 | |
return 0 | |
end | |
end}) | |
end) | |
D:register_keybind("kb_toggle_fullscreen", "f11 - left alt", function() | |
local fullscreen = not RenderSettings.fullscreen | |
managers.viewport:set_fullscreen(fullscreen) | |
setup:add_end_frame_clbk(function() | |
local brightness = managers.user:get_setting("brightness") | |
Application:set_brightness(brightness) | |
end) | |
end) | |
local fov_zoom_values = { 25, 50, 67, 75 } | |
local function get_fov_value(should_decrease) | |
local zoom_lvl | |
if type(D._fov_zoom_lvl) ~= "number" then | |
zoom_lvl = 0 | |
elseif should_decrease then | |
if D._fov_zoom_lvl == 0 then | |
return nil -- prevent overlapping | |
end | |
zoom_lvl = (D._fov_zoom_lvl + #fov_zoom_values - 1) % #fov_zoom_values | |
else | |
if D._fov_zoom_lvl + 1 == #fov_zoom_values then | |
return nil -- prevent overlapping | |
end | |
zoom_lvl = (D._fov_zoom_lvl + 1) % #fov_zoom_values | |
end | |
D._fov_zoom_lvl = zoom_lvl | |
return fov_zoom_values[zoom_lvl + 1] -- lua indices, my favourite... | |
end | |
local function change_fov_zoom(fov) | |
if not fov then | |
return | |
end | |
if not managers.user then | |
dlog_ll(1, "UserLua", "> WARNING: UserManager isn't available?!") | |
end | |
dlog_ll(3, "UserLua", "> setting fov_zoom to", fov) | |
managers.user:set_setting("fov_zoom", fov) | |
-- give some visual feedback about the change we've made | |
managers.hud:show_hint({ | |
text = "zoom fov set to: " .. tostring(fov), | |
time = 1, | |
}) | |
-- update the zoom fov in game, copied from "lib/managers/menumanager.lua" MenuCallbackHandler:set_fov_zoom | |
if alive(managers.player:player_unit()) then | |
local plr_state = managers.player:player_unit():movement():current_state() | |
local stance = plr_state._in_steelsight and "steelsight" or plr_state._ducking and "crouched" or "standard" | |
plr_state._camera_unit:base():set_stance_fov_instant(stance) | |
end | |
end | |
-- in order for the above to work, you have to unbind the "change weapon" keybinds | |
D:register_keybind("kb_fov_zoom_increase", "mouse wheel down", "GAME", "PRESSED", function() change_fov_zoom(get_fov_value(false)) end) | |
D:register_keybind("kb_fov_zoom_decrease", "mouse wheel up", "GAME", "PRESSED", function() change_fov_zoom(get_fov_value(true)) end) | |
local visual_upgrades = { | |
["hk21"] = "hk21_recoil2", -- brenner scope | |
["m4"] = "m4_spread4", -- amcar scope (my beloved) | |
["m14"] = "m14_spread2", -- m308 scope | |
["ak47"] = "ak47_spread1", -- ak scope | |
["m79"] = "m79_expl_range2", -- gl40 range finder (thing on the left) | |
} | |
-- toggle currently held weapon's sight with a keybind | |
D:register_keybind("toggle_visual_weapon_upgrade", "num 4", "GAME", function() | |
if not MenuCallbackHandler then | |
return | |
end | |
local player_unit = managers.player:player_unit() | |
if not alive(player_unit) then | |
return | |
end | |
local inventory = player_unit:inventory() | |
if not inventory then | |
return | |
end | |
local weapon = inventory._available_selections[inventory._equipped_selection] | |
if not weapon then | |
return | |
end | |
local weapon_base = weapon.unit:base() | |
local upgrade = visual_upgrades[weapon_base.name_id] | |
if not upgrade then | |
dlog_ll(3, "UserLua", "no visual upgrade for", weapon_base.name_id) | |
return | |
end | |
dlog_ll(1, "UserLua", "toggling visual upgrade", upgrade) | |
D._menu_cb_handler = D._menu_cb_handler or MenuCallbackHandler:new() | |
D._menu_cb_handler:toggle_visual_upgrade({ | |
parameters = function() | |
return { upgrade_id = upgrade } | |
end | |
}) | |
end) | |
dlog("Loading user script") | |
-- list of some game-altering mods which are not suspicious and considered normal/ok to use | |
local GAMods_whitelist = { | |
["interact_toggle"] = true, | |
["restart_end_job"] = true, | |
["restore_deployables"] = true, | |
["corpse_despawn"] = true, | |
["overdrill7200"] = true, | |
["crybaby"] = true, | |
["Warmod"] = true, | |
["ovk_193"] = true, -- older versions of DorHUD (<=1.11) report this as a GA mod | |
["Flashlight"] = true, -- PlayingHazard has a mod for toggling flashlight state client-side for his testing purposes | |
--["wtfbm"] = true, -- I like to know whenever someone I am playing with uses this, so I keep this commented out | |
} | |
-- my hooks | |
-- locally show DAHM version of others when their clients send it; TODO: make it print only 1 message but reset it when chat clears | |
local function handle_DorHUDModVersion(peer, data) | |
if peer:preference("userlua_shown_version_msg") then | |
return | |
end | |
peer:set_preference("userlua_shown_version_msg", true) | |
Util:chat_message(string.format("[golden][peer_color]%s[] is using DAHM, version [][nice_blue]%s", clear_string(peer:name()), tostring(data)), false, true, { subject_peer = peer }) | |
end | |
-- locally show whenever a lobby is re-registered | |
local function handle_UpdatedLobbyID(peer, data) | |
Util:chat_message("[golden]lobby has been re-registered to [nice_blue]steam://joinlobby/24240/" .. tostring(data), false, "DEBUG") | |
end | |
-- report whenever someone has some Gameplay Altering mods loaded (NOTE: it doesn't mean they're using them RIGHT NOW, but they have reported mods loaded through DAHM) | |
local function handle_GAMods(peer, data) | |
if type(data) ~= "table" then | |
return -- received malformed data | |
end | |
local sus_mods = "" -- string containing list of suspicious mod names | |
for k, _ in pairs(data) do | |
if not GAMods_whitelist[k] then | |
sus_mods = string.format("%s %q", sus_mods, k) | |
end | |
end | |
if sus_mods ~= "" then | |
dlog_ll(2, "UserLua", "> sus mods: ", trim(sus_mods)) | |
Util:chat_message(string.format("[golden][peer_color]%s[] has suspicious Gameplay Altering mod(s) active: [nice_blue]%s", clear_string(peer:name()), trim(sus_mods)), false, "DEBUG", { subject_peer = peer }) | |
end | |
end | |
-- use one hook for all DAHM's events to be more efficient than hooking each function separetly | |
D:hook("OnNetworkDataRecv", "OnNetworkDataRecv_UserLuaHooks", | |
{ | |
"DorHUDModVersion", | |
"UpdatedLobbyID", | |
"GAMods", | |
}, function(peer, data_type, data) | |
if data_type == "DorHUDModVersion" then | |
handle_DorHUDModVersion(peer, data) | |
elseif data_type == "UpdatedLobbyID" then | |
handle_UpdatedLobbyID(peer, data) | |
elseif data_type == "GAMods" then | |
handle_GAMods(peer, data) | |
end | |
end) | |
-- stats logging, mostly copied from https://www.st0rm.de/dussel.lua.txt + Cloaker Hater's config | |
-- TODO: Make the chat output nicer, more colorful but also keep detailed logs in the chat logfile | |
local function stats_logger(peer, result) | |
dlog_ll(0, "UserLua", string.format("game_stats data from %s '%s' (%s)", peer:id(), peer:name(), peer:user_id())) | |
dump_table(result) | |
if type(peer) ~= "table" or not result.time_played then | |
return -- invalid or incomplete data has been received | |
end | |
local stats = table.merge({ peer_id = peer:id() }, result) | |
if stats.accuracy_f then | |
stats.accuracy = stats.accuracy_f | |
stats.accuracy_f = nil | |
end | |
local criminal_name_curr = managers.criminals:character_name_by_peer_id(peer:id()) | |
local criminal_name = managers.statistics:session_criminal_assigned_to_user(peer:user_id()) -- if they left already | |
criminal_name = criminal_name or criminal_name_curr | |
local ammo_bag_use = criminal_name and managers.statistics:local_criminal_member_stat(criminal_name, "ammo_bag_interacts") or { amount = 0 } | |
local doctor_bag_use = criminal_name and managers.statistics:local_criminal_member_stat(criminal_name, "doctor_bag_interacts") or { amount = 0 } | |
stats.ammo_bag_use = ammo_bag_use.amount * 100 | |
stats.doctor_bag_use = doctor_bag_use.amount | |
local msg = string.format("statistics for [peer_color]%s[] (%s) = %s", clear_string(peer:name()), peer:id(), JSON:encode(stats, nil, { decimal_precision = 2 })) | |
-- save to file like it was sent in the chat | |
-- managers.menu:_log_message_to_file(string.format("%s -- %s\n", os.date(iso8601), lobby_title .. msg)) | |
Util:chat_message(msg, false, true, { subject_peer = peer }) | |
peer:remove_listener("OnGameStatsEvent_LogStats") | |
end | |
do | |
-- handle the statistics we've requested before | |
D:hook("OnNetworkDataRecv", "OnNetworkDataRecv_ShowGameStats", "GameStats", function(peer, data_type, data) | |
dlog_ll(0, "UserLua", string.format("GameStats data from %s '%s' (%s)", peer:id(), peer:name(), peer:user_id())) | |
dump_table(data) | |
if data_type ~= "GameStats" or not data or not data.peer_id then | |
return -- wrong event or partial / invalid data received | |
end | |
if peer:id() ~= data.peer_id and not peer:is_server() then | |
return -- ignore data regarding mismatched peers as a client | |
end | |
local target_peer = peer | |
if peer:id() ~= data.peer_id then | |
target_peer = managers.network:session() and managers.network:session():peer(data.peer_id) | |
end | |
if target_peer and (not target_peer:has_statistics() or not target_peer:statistics().time_played) then | |
if target_peer.set_statistics2 and target_peer._stats_translation_map then | |
target_peer:set_statistics2(table.remap_keys(data, target_peer._stats_translation_map)) | |
else | |
target_peer:set_statistics(data.kills, data.sp_kills, data.headshots, data.accuracy, data.downs, data.time, data.is_dropin) | |
--target_peer:set_statistics(data) | |
end | |
end | |
end) | |
-- tell our own client to send us stats later | |
D:hook("OnEnteredLobby", "OnEnteredLobby_LogLocalPeerStats", function(state, level) | |
managers.network:session():local_peer():add_listener("OnGameStatsEvent_LogStats", "game_stats", stats_logger) | |
end) | |
-- tell other clients to send us stats later | |
D:hook("OnPeerAdded", "OnPeerAdded_LogPeerStats", function(peer, is_new) | |
peer:add_listener("OnGameStatsEvent_LogStats", "game_stats", stats_logger) | |
-- save peer's information to chat's log file | |
if is_new and managers.menu and D:has_module("enhanced_chat") then | |
managers.menu:_log_message_to_file(string.format( | |
"%s -- '%s' has joined. Steam ID: %s, IP: %s\n", | |
os.date(iso8601), | |
tostring(peer:name()), | |
tostring(peer:user_id()), | |
tostring(Network:get_ip_address_from_user_id(peer:user_id())) | |
)) | |
end | |
end) | |
end | |
-- hide some menu entries from the main menu | |
D:hook("OnMenuSetup", "OnMenuSetup_UserLuaHideItems", "menu_main", function(self, menu, nodes) | |
self:update_menu_item(nodes, "main", "forum", { | |
visible_callback = "hide_unless_option_set", | |
}) | |
self:update_menu_item(nodes, "main", "eula", { | |
visible_callback = "hide_unless_option_set", | |
}) | |
self:update_menu_item(nodes, "main", "group_page", { | |
visible_callback = "hide_unless_option_set", | |
}) | |
end) | |
D:hook("OnModuleInit", "OnModuleLoaed_UserLuaOverwriteChatLogFormat", function(module, params) | |
if module:id() == "enhanced_chat" then | |
module.chat_log_format = function(name, message, peer, state) | |
return string.format("%s -- \"%s\" ", os.date(iso8601), state or "?") .. "%n%s: %s\n" | |
end | |
end | |
end) | |
do | |
-- Load other config options which I don't want to keep in this file - like "steam_web_api_key" or "hardcoded_verified_users" | |
-- file contents should be literally just: return { foo = "bar", } | |
dlog_ll(0, "UserLua", "Loading user script secrets") | |
local secret_config = dofile("mods/.user-secret.lua") | |
if secret_config ~= nil then | |
tablex.merge(config, secret_config) | |
else | |
dlog_ll(3, "UserLua", "Failed to load .user-secret.lua file") | |
end | |
-- load debug things, but only while on debug account | |
local steam_id = Steam and Steam:userid() | |
if steam_id == "76561199255798139" then | |
dlog_ll(1, "UserLua", "Loading debug file") | |
local f, err = loadfile("mods/user-debug.lua") | |
if f ~= nil then | |
err = f(...) | |
else | |
Util:chat_message("Failed to load debug file: " .. tostring(err), false, "DEBUG") | |
end | |
end | |
end | |
--- apply table values | |
local overwrite = not prioritize_gui and (is_first_load or always_reload) | |
for key, value in pairs(config) do | |
D:set_config_option(key, value, overwrite) | |
end | |
for key, value in pairs(localization) do | |
D:add_localization_override(key, value) | |
end | |
for id, key in pairs(keybind_overrides) do | |
D:update_keybind(id, key) | |
end | |
for key, text in pairs(commands) do | |
D:register_chat_command(key, function() | |
Util:chat_message(text) | |
return true | |
end) | |
end | |
for _, module in ipairs(blacklisted_modules) do | |
D:blacklist_module(module) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment