-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCore.lua
More file actions
3640 lines (3337 loc) · 103 KB
/
Copy pathCore.lua
File metadata and controls
3640 lines (3337 loc) · 103 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--[[
===== Overview ======
- PRIORITY: Tab autocomplete
- Complete 1.0 parity list
- Make a pass for localization strings
- Complete menus (and re-enable settings loading)
- Fix high-priority bugs
- Develop plan for sustainable module packages
- split Core megaclass into organized files
- the delineations are basically already there; just separate along the seams and dofile them all on core load
-- probably needs smarter concurrent parsing/evaluation
-- eg detecting when typing a command name and starting a subcmd
******************* Bug list [high priority] *******************
- Fix internal/external Log/logall use so that user-made Log/logall calls can safely be used on Console's own objects without causing stack overflows
- [Console] memory crash when using 166k-168k output logs
- [Console] Figure out a memory-safe(r) solution to putting all history output in one continuous string in a single Text object
- [ConsoleModDialog] Prevent "mouse hold" vars from sticking around after the console window is closed, if holding down a key or button when hiding console window
******************* Bug list [low priority] *******************
******************* Feature list todo: *******************
- Re-enable logging before the window is instantiated
- Text input "redirection" (eg. for Y/N response prompts, Text Based Adventure, etc)
- Should also be able to temporarily hide current text history and show a new, non-scrollable field
- Spacing format function, as prototyped in /thread
- save last result to an alias/var
- use coroutines for at-risk loops (ongoing)
- "Debug HUD"
- show aim-at target (tweakdata and health)
- show xyz pos
- straighten out Log/Print/output call flow
- different levels of logging
print/log behavior option checkboxes
- scale scrollbar size to num of history lines
- submit button
- recolor text on mouseover
- center submit button and create its own subpanel
- ConsoleModDialog scroll button click input repeat
Parity with 1.0:
-unit tagging
-hitbox display
-popups (trackers but worldspace)
-search_class()
-commands
-skillname/skillinfo
- organize output strings
-whisper
-rot
-tp
-state
-quit
-bltmods
-gotonav/editnav
-forcestart
-say
-fwd ray
-aim-at unit save to predefined alias/register
******************* Secondary feature todo *******************
- [ConsoleModDialog] clean up mouse drag code (save current mouse drag/hold id)
- var pipelining from command to command
- eg. saving return values of list from /weaponname to $WEAPONS
- optional pause on open console (sp only)
- unpause on settings toggle
- option to disable color coded logs
- allow changing type colors through settings
- [ConsoleModDialog] mouseover tooltips for buttons after n seconds
- [ConsoleModDialog] option to de-focus the console and keep it open while playing without hiding it
- "is holding scroll" for temporary scroll lock
- button-specific mouseover color/texture
- session pref with existing vars
- tab key autocomplete
- preview history in dialog ui
show number of history steps?
- "undo" steps history
-highlight text color for main history panel
- limit number/size of input/output logs (enforced on save and load)
- history line nums + ctrl-G navigation?
- separate session "settings" from normal configuration settings?
- lookup asset loaded table so check when specific assets are loaded without having to make redundant dynresource checks
- "/" key shortcut to open console window
- or other keys; allow other keys as command character
- batch file folder system in saves
autoexec batch-style files
- [ConsoleModDialog] Rewrite to allow multiple window management?
******************* Commands todo *******************
- /bind key collision warning
- /weaponname
-parameters to limit searches for weapon id, bm id, or name
-parameter to search by dlc id
- /dlcname
-search for a dlc name
- /texture
-create console mini-window showing texture
- /help - alphabetize
-s search function
-/commands alias
- print
- echo
- preserve type data while replacing aliases to apply type colorcoding
- escape aliases before applying, so that expanded aliases don't trigger additional expansions
- /alias
- alias reference copying (copy func between aliases)
- alias syntax for functions
- /cvar change advanced client/console vars or behaviors
rework all help/manual/commands text
eg: weaponname
NAME (primary, subsequent aliases listed)
weaponname
PARAMETERS (multiple)
category/cat: only show matching weapons from this weapon category. [snp/ar/pistol/revolver/akimbo/...]
EXAMPLES (multiple)
/weaponname m4
/weaponname new_m4
/weaponname car-4
/weaponname -category pistol -t -c
--> simple command list: (/help)
weaponname - Search for a weapon by name or other parameters
partname - Search for an attachment by name or other parameters
clear - Clear the console
--> detailed command list: (/help weaponname)
weaponname
--]]
Console = Console or {}
do --init mod vars
local save_path = SavePath
local mod_path = ConsoleCore and ConsoleCore:GetPath() or ModPath
Console._mod_core = ConsoleCore
Console._mod_path = mod_path
Console._menu_path = mod_path .. "menu/options.json"
Console._default_localization_path = mod_path .. "l10n/english.json"
Console._save_path = save_path .. "console_settings.ini"
Console._keybinds_path = save_path .. "console_keybinds.ini"
Console._autoexec_menustate_path = save_path .. "autoexec_menustate.lua"
Console._output_log_file_path = save_path .. "console_output_log.txt" --store recent console output; colors and data types are not preserved
Console._input_log_file_path = save_path .. "console_input_log.txt" -- store recent console input
Console.console_window_menu_id = "console_window_menu" --not used
Console.default_palettes = {
"ff0000",
"ffff00",
"00ff00",
"00ffff",
"0000ff",
"880000",
"888800",
"008800",
"008888",
"000088",
"ff8800",
"88ff00",
"00ff88",
"0088ff",
"8800ff",
"884400",
"448800",
"008844",
"004488",
"440088",
"ffffff",
"bbbbbb",
"888888",
"444444",
"000000"
}
Console.color_setting_keys = { --unfortunately, all settings that are hex color strings must be identified here so that they can be properly read/written by the ini parser
"window_text_normal_color",
"window_text_highlight_color",
"window_text_stale_color",
"window_text_selected_color",
"window_input_submit_color", --todo color schemes instead of individual color entries?
"window_button_normal_color",
"window_button_highlight_color",
"window_frame_color",
"window_bg_color",
"window_caret_color",
"window_prompt_color",
"style_color_system",
"style_color_error",
"style_data_color_function",
"style_data_color_string",
"style_data_color_number",
"style_data_color_table",
"style_data_color_boolean",
"style_data_color_nil",
"style_data_color_thread",
"style_data_color_userdata",
"style_data_color_misc",
}
Console.palettes = table.deep_map_copy(Console.default_palettes)
Console.default_settings = {
safe_mode = false,
log_blt_enabled = false,
log_input_enabled = true,
log_output_enabled = false,
log_buffer_enabled = true,
log_buffer_interval = 10, --seconds between flushes
style_color_error = 0xff6262,
style_data_color_function = 0x7fffff,
style_data_color_string = 0x7f7f7f,
style_data_color_number = 0xa8ff00,
style_data_color_table = 0xffff00,
style_data_color_boolean = 0x4c4cff,
style_data_color_nil = 0x4c4c4c,
style_data_color_thread = 0xffff7f,
style_data_color_userdata = 0xff4c4c,
style_data_color_misc = 0x888888,
style_color_system = 0xffd700,
input_mousewheel_scroll_direction_reversed = false,
input_mousewheel_scroll_speed = 1,
console_params_guessing_enabled = true,
console_pause_game_on_focus = true,
console_show_nil_results = false,
console_autocull_dead_threads = true,
window_scrollbar_lock_enabled = false,
window_scroll_direction_reversed = true,
window_text_normal_color = 0xffffff,
window_text_highlight_color = 0xffd700, --the color of the highlight box around the text
window_text_stale_color = 0x777777, --the color of any logs pulled from history log (read from disk, ie from previous state/session)
window_text_selected_color = 0x000000, --the color of highlighted text
window_button_normal_color = 0xffffff, --the color of most ordinary buttons
window_button_highlight_color = 0xffd700, --the color of a button being moused over
window_alpha = 1,
window_x = 50,
window_y = 50,
window_w = 1000,
window_h = 600,
window_font_name = "fonts/font_bitstream_vera_mono",
window_font_size = 10,
window_blur_alpha = 0.75,
window_frame_color = 0x3c3c3c,
window_frame_alpha = 1,
window_input_submit_color = 0x7e5c35, --the color of the submit button
window_bg_color = 0x252525, --the color of the body box bg, and the bg behind the input text box
window_bg_alpha = 0.9,
window_caret_string = "|",
window_caret_color = 0xffffff,
window_caret_alpha = 0.75,
window_prompt_string = "] ",
window_prompt_color = 0xff0000,
window_prompt_alpha = 0.66
}
Console.settings = table.deep_map_copy(Console.default_settings)
Console.settings_sort = {
"safe_mode",
"log_input_enabled",
"log_output_enabled",
"log_buffer_enabled",
"log_buffer_interval",
"console_pause_game_on_focus",
"console_autocull_dead_threads",
"console_params_guessing_enabled",
"console_show_nil_results",
"input_mousewheel_scroll_direction_reversed",
"input_mousewheel_scroll_speed",
"window_scrollbar_lock_enabled",
"window_scroll_direction_reversed",
"window_text_normal_color",
"window_text_highlight_color",
"window_text_selected_color",
"window_text_stale_color",
"window_button_normal_color",
"window_button_highlight_color",
"window_frame_color",
"window_frame_alpha",
"window_input_submit_color",
"window_alpha",
"window_x",
"window_y",
"window_w",
"window_h",
"window_font_name",
"window_font_size",
"window_blur_alpha",
"window_bg_color",
"window_bg_alpha",
"window_caret_string",
"window_caret_color",
"window_caret_alpha",
"window_prompt_string",
"window_prompt_color",
"window_prompt_alpha",
"style_color_error",
"style_color_system",
"style_data_color_function",
"style_data_color_string",
"style_data_color_number",
"style_data_color_table",
"style_data_color_boolean",
"style_data_color_nil",
"style_data_color_thread",
"style_data_color_userdata",
"style_data_color_misc"
}
Console.color_data = {
["error"] = "style_color_error",
["system"] = "style_color_system",
--base data types
["function"] = "style_data_color_function",
["string"] = "style_data_color_string",
["number"] = "style_data_color_number",
["table"] = "style_data_color_table",
["boolean"] = "style_data_color_boolean",
["userdata"] = "style_data_color_userdata",
["thread"] = "style_data_color_thread",
["nil"] = "style_data_color_nil",
["misc"] = "style_data_color_misc"
}
Console._log_buffer_timer = 0
Console._output_log = {}
Console._input_log = {
--[[ ex.
[1] = {
input = "/echo hello -p",
func = function 0xd3adb33f --from loadstring
},
[2] = {
input = "/echo hello -p",
func = function 0xd3adb33f --same direct reference to previous function
},
[3] = {
input = "/print $hello",
func = function 0x1234567 --different direct referencce
},
[4] = {
input = "/print $hello",
reevaluate = true, --cue loadstring of input
func = new function --result of loadstring
},
[5] = {
input = "/set $hello 69", --set var $hello to 69
func = new function --result of loadstring
}
--]]
}
Console._registered_commands = {}
Console._aliases = {
--[[ ex.
test = {
value = 12345
},
time = {
get_value = function()
return os.date("%X")
end
},
nothing = {
--nothing!
}
FOO = { --all instances of $FOO are replaced with the value: 12345
value = 12345
},
CURRENT_TIME = { --since the get_value function is provided, the value parameter is ignored, and all instances of $CURRENT_TIME are replaced with the return value of get_value()
value = 45678,
get_value = function()
return os.date("%X")
end
},
MoCkInG_CaSe_vAR = {
value = "meeee"
}
--]]
}
Console._operation_timeout = 5
Console._coroutine_counter = 0
Console._io_buffer_size = 2^13
Console._buffers = {
input_log = {},
output_log = {}
}
Console.PREFIXES = {
COMMAND = "/",
ALIAS = "$",
SUBCOMMAND = "-"
}
Console.INPUT_DEVICES = {
MOUSE = 1,
KEYBOARD = 2,
CONTROLLER = 3
}
Console._custom_keybinds = {
--[[ ex.
g = {
key_name = "g",
key_raw = "g",
device = 2,
type = "command",
action = "/echo Hello",
-- hold = 0.5,
repeat_delay = 0,
func = function: 0xd3adb33f (compiled from InterpretCommand("/echo Hello") )
}
--]]
}
Console._input_cache = {}
Console._threads = {}
Console._trackers = {}
Console._is_reading_log = false
--placeholder values for things that will be loaded later
Console._restart_data = nil
--[[ ex.
{
restart_t = 71.58935692, -- the time at which the heist will reload (or at which the game state will reload, if in a menu)
duration = 10, --if present and restart_t is not, starts the countdown (sets restart_t to current time + duration)
message_t = 0, --the next time at which a chat message or Console log will be printed, giving the current countdown timer
is_silent = false --if true, outputs the countdown to the chat/console window
}
--]]
Console._colorpicker = nil
Console._is_font_asset_load_done = nil --if font is loaded
Console._is_texture_asset_load_done = nil
end
do --load ini parser
local f,e = blt.vm.loadfile(Console._mod_path .. "utils/LIP.lua")
local lip
if e then
log("[CONSOLE] ERROR: Failed loading LIP module. Try re-installing BeardLib if this error persists.")
elseif f then
lip = f()
end
if lip then
Console._lip = lip
end
end
do --hooks and command registration
Hooks:Register("ConsoleMod_RegisterCommands")
Hooks:Register("ConsoleMod_AutoExec")
Hooks:Add("ConsoleMod_RegisterCommands","consolemod_load_base_commands",function(console)
console:RegisterCommand("restart",{
str = nil,
desc = "Reloads the Lua state. Restart the heist day if in a heist, or reload the menu if at the main menu.",
manual = "/restart [String cancel]",
arg_desc = "(Boolean) Any truthy value as the first argument will cancel the ongoing restart timer.",
parameters = {
timer = {
arg_desc = "[timer]",
short_desc = "(Int) Optional. The number of seconds to delay restarting by. If in-game, will display a timer in chat similar to the one available in the base game. If not supplied, restarts instantly."
},
noclose = {
arg_desc = "[noclose]",
short_desc = "(Boolean) Optional. Any truthy value will prevent the Console window from closing automatically if a restart is performed immediately.\nThis is because the Console window is a dialog, and any open dialog will delay a restart for as long as the dialog is open."
},
silent = {
arg_desc = "[silent]",
short_desc = "Optional. If supplied, does not send a countdown message in the chat. (Countdown messages will still be displayed in the Console.)"
},
vote = {
arg_desc = "[vote]",
short_desc = "Optional. If supplied, ignores any current or supplied timer and triggers a vote-restart instead."
}
},
func = callback(console,console,"cmd_restart")
})
console:RegisterCommand("partname",{
str = nil,
desc = "Search for a part by localized name/description, internal name/description, internal id, or blackmarket id.",
manual = "Usage: /partname [search key]\n\nParameters:\n-type [attachment type]\n-weapon [weapon id]",
arg_desc = "(String) The name of the weapon attachment to search for. Single-term, case insensitive, spaces okay.",
parameters = {
type = {
arg_desc = "[attachment type]",
short_desc = "(String) The attachment type to filter for, eg. silencer, barrel, stock, etc. Must be exact type match."
},
weapon = {
arg_desc = "[weapon]",
short_desc = "(String) The weapon id to filter for, eg. m134, flamethrower, saw, m1911, or new_m4. If supplied, partname will only display attachments that can be applied to this weapon. Must be exact weapon_id match."
},
perks = {
arg_desc = "[perk name, ...]",
short_desc = "If supplied, lists all of the attachments that contain all of the supplied perks. Multiple perks can be supplied using space separators."
},
blueprint = {
arg_desc = "[]",
short_desc = "If supplied, lists the ids of all the weapons that use a given part."
},
npcs = {
arg_desc = "[]",
short_desc = "If supplied, allows NPC weapons (NPC-only weapon variants, typically with a _crew or _npc suffix) to be listed."
}
},
func = callback(console,console,"cmd_partname")
})
console:RegisterCommand("weaponname",{
str = nil,
desc = "Search for a weapon by localized name/description, internal name/description, internal id, or blackmarket id.",
manual = "Usage: /weaponname [search key]",
arg_desc = "(String) The name of the weapon to search for. Single-term, case insensitive, spaces okay.",
parameters = {
name = {
arg_desc = "[name]",
short_desc = "(String) The name to of the weapon search for. Single-term, case insensitive, spaces okay.",
hidden = true
},
category = {
arg_desc = "[category]",
short_desc = "(String) The weapon category to filter for, eg. shotgun, smg, lmg, etc. Must be exact category match."
},
slot = {
arg_desc = "[slot]",
short_desc = "(Integer) The weapon slot number to filter for, eg. 1, 2, etc. Must be exact slot match."
}
},
func = callback(console,console,"cmd_weaponname")
})
console:RegisterCommand("help",{
str = nil,
desc = "Brief list of commands.",
manual = "/help [command name]",
arg_desc = "(String) The name of the command to search for. Single-term, case insensitive, no spaces.",
parameters = {},
func = callback(console,console,"cmd_help")
})
console:RegisterCommand("echo",{
str = nil,
desc = "Prints a string and/or aliases back to the console.",
manual = "/echo [string]",
arg_desc = "(String) The text to print.",
parameters = {},
func = callback(console,console,"cmd_echo")
})
console:RegisterCommand("alias",{
str = nil,
desc = "Assigns a temporary variable with a name and value of your choice. This variable can be accessed with $VARNAME, and is effectively a string substitution/shortcut tool usable in console commands.",
manual = "/alias [var name] [var value] [Optional var function]",
arg_desc = "(String) The text to print.",
parameters = {
loadstring = {
arg_desc = "",
short_desc = "If supplied, attempts to process the function or var through loadstring, instead of only saving the string value. Required if you are supplying a function."
},
noalias = {
arg_desc = "",
short_desc = "If supplied, prevents interpreting aliases in the supplied value, eg. \"/alias a $b\" will interpret the new alias value $a as the literal string \"$b\"."
}
},
func = callback(console,console,"cmd_alias")
})
console:RegisterCommand("unalias",{
str = nil,
desc = "Clears an alias from memory.",
manual = "/unalias [var name]",
arg_desc = "(String) The name of the alias.",
parameters = {
name = {
arg_desc = "[name]",
short_desc = "(String) The name of the alias to remove."
}
},
func = callback(console,console,"cmd_unalias")
})
console:RegisterCommand("clear",{
str = nil,
desc = "Clears the Console window. Can be configured to clear the input/output log data on the hard disk as well.",
manual = "",
parameters = {
input_clear = {
arg_desc = "",
short_desc = "Clears the input log and file."
},
output_clear = {
arg_desc = "",
short_desc = "Clears the output log and file."
}
},
func = callback(console,console,"cmd_clear")
})
console:RegisterCommand("thread",{
str = nil,
desc = "Manage, kill, or create Console operation threads.",
manual = "The id of a coroutine should be a number, or \"all\" to apply to all threads, or \"last\" to apply to the most recently made thread.\nAcceptable formats:\n /thread [subcmd] [id]\n /thread [subcmd] -n [id] \n /thread [id]",
parameters = {
--[[
new = {
arg_desc = "[new]",
short_desc = "Create a new coroutine with the supplied loadstring"
},
--]]
kill = {
arg_desc = "[kill]",
short_desc = "Stops the coroutine with the given id."
},
list = {
arg_desc = "[list]",
short_desc = "If supplied with a specific id, lists all the information about that coroutine. Else, lists all coroutines."
},
pause = {
arg_desc = "[pause]",
short_desc = "If supplied, pauses a running coroutine so that it is not automatically executed on each frame."
},
resume = {
arg_desc = "[resume]",
short_desc = "If supplied, resumes a paused coroutine so that it continues to automatically execute on each frame."
},
priority = {
arg_desc = "[priority]",
short_desc = "When creating a coroutine, you can choose to specify a priority number [0-inf] which determines when your coroutine is run relative to others. Coroutines with larger priority numbers are run earlier."
},
number = {
arg_desc = "[number]",
short_desc = "Specify the id of the thread you want to manage."
}
},
func = callback(console,console,"cmd_thread")
})
console:RegisterCommand("bind",{
str = nil,
desc = "Bind a key to execute a payload (a code chunk, a console command, or an in-game action).",
manual = "",
parameters = {
key = {
arg_desc = "[key]",
short_desc = "The name of the key to bind."
},
type = {
arg_desc = "[type]",
short_desc = "(String) The type of payload for this keybind. Possible types are \"chunk\" (Lua code chunk) \"command\" (console command), or nil.\nIt is strongly recommended to specify the type, as this is much better for performance."
},
list = {
arg_desc = "[list]",
short_desc = "If supplied: lists all keybinds, their types, and their associated payloads."
},
--[[
chunk = {
arg_desc = "[chunk]",
short_desc = ""
},
command = {
arg_desc = "[command]",
short_desc = "This
},
--]]
action = {
arg_desc = "[action]",
short_desc = "A string containing the command or code chunk to execute when the key is pressed."
},
repeat_delay = {
arg_desc = "[repeat_delay]",
short_desc = "(Boolean) If supplied, the keybind will continuously execute its payload while its key is held."
},
hold = {
arg_desc = "[hold]",
short_desc = "(Float) If supplied, the key must be held for this many seconds in order to execute its payload."
},
consoleenabled = {
arg_desc = "",
short_desc = "If supplied, the keybind can be executed while the Console window is open."
},
chatenabled = {
arg_desc = "",
short_desc = "If supplied, the keybind can be executed while typing in the in-game chat."
}
},
func = callback(console,console,"cmd_bind")
})
console:RegisterCommand("unbind",{
str = nil,
desc = "Remove a keybind. Only applies to keybinds bound with /bind; does not apply to base-game keybinds or BLT keybinds.",
manual = "/unbind [keyname]",
parameters = {
key = {
arg_desc = "[key]",
short_desc = "You can also use \"all\" for the key name to unbind all keybinds."
}
},
func = callback(console,console,"cmd_unbind")
})
console:RegisterCommand("unbindall",{
str = nil,
desc = "Remove all keybinds. Only applies to keybinds bound with /bind; does not apply to base-game keybinds or BLT keybinds.",
manual = "/unbindall",
parameters = {},
func = function() return console:cmd_unbind({key = "all"},"",{raw_input = "/unbind -key all",cmd_string = "-key all"}) end
})
console:RegisterCommand("skillname",{
str = nil,
desc = "Search for a skill by name or description.",
manual = "/skillname",
parameters = {},
func = callback(console,console,"cmd_skillname")
})
console:RegisterCommand("maskname",{
str = nil,
desc = "Search for a mask by internal name or localized name.",
manual = "/maskname",
parameters = {},
func = callback(console,console,"cmd_maskname")
})
console:RegisterCommand("bltmods",{
str = nil,
desc = "List your BLT mods, as far as the sharable list goes.",
manual = "/bltmods",
parameters = {},
func = callback(console,console,"cmd_bltmods")
})
console:RegisterCommand("info",{
str = nil,
desc = "Prints basic information about the application and Console mod.",
manual = "/info",
parameters = {},
func = callback(console,console,"cmd_info")
})
console:RegisterCommand("loc",{
str = nil,
desc = "Localizes the given text. Supports macros given as parameters.",
manual = "/loc",
arg_desc = "",
parameters = {},
func = callback(console,console,"cmd_loc")
})
console:RegisterCommand("sv_cheats",{
str = nil,
desc = "Enable cheats",
manual = "/sv_cheats",
arg_desc = "",
parameters = {},
func = function(params,args,meta_params)
if string.find(args,"1") then
console:Log("Why don't you go and cl_somebitches 1",{color=Color.yellow})
end
return
end
})
console:RegisterCommand("cl_somebitches",{
str = nil,
desc = "Enable bitches",
manual = "/cl_somebitches",
arg_desc = "",
parameters = {},
hidden = true,
func = function(params,args,meta_params)
if string.find(args,"1") then
console:Log("Can't use cheat command cl_somebitches in multiplayer, unless the server has sv_cheats set to 1.",{color=Color.yellow})
end
return
end
})
end)
Hooks:Add("ConsoleMod_AutoExec","consolemod_autoexec_listener",function(console,state)
console:AutoExec(state)
end)
end
--utils
function Console.table_concat(tbl,div) --the main difference from table.concat is that this stringifies the values
div = tostring(div or ",")
if type(tbl) ~= "table" then
return "(concat error: non-table value)"
end
local str
for k,v in pairs(tbl) do
str = str and (str .. div .. tostring(v)) or tostring(v)
end
return str or ""
end
function Console.hex_number_to_color(n)
return type(n) == "number" and Color(string.format("%06x",n))
end
function Console.string_replace(str,start,finish,new)
local str_len = string.len(str)
local a,b
if start > 1 then
a = string.sub(str,1,start - 1)
else
a = ""
end
if finish < str_len then
b = string.sub(str,finish + 1)
else
b = ""
end
return a .. new .. b
end
function Console.file_exists(path)
if SystemFS then
return SystemFS:exists(path)
else
return file.FileExists(path)
end
end
function Console.format_time(t,params)
local floor = math.floor
local space_char
if params.divider then
space_char = type(params.divider) == "string" and params.divider or " "
else
space_char = ""
end
local style = params.style
local seconds = t % 60
local _minutes = floor(t / 60)
local minutes = _minutes % 60
local _hours = floor(_minutes / 60)
local hours = _hours % 24
local days = floor(_hours / 24)
local a = {
seconds,
minutes,
hours,
days
}
local b = {
"s",
"m",
"h",
"d"
}
local index
if days > 0 then
index = 4
elseif hours > 0 then
index = 3
elseif minutes > 0 then
index = 2
else
index = 1
end
local str = ""
for i=index,1,-1 do
local new_str
if style == 1 then
new_str = string.format("%i" .. b[i],a[i])
else
new_str = string.format("%i",a[i])
end
if str ~= "" then
new_str = space_char .. new_str
end
str = str .. new_str
end
return str
end
--loggers
Console.blt_log = Console.blt_log or _G.log
function Console:Log(info,params)
local _info = tostring(info)
if self._window_instance then
params = type(params) == "table" and params or {}
if params.skip_window_instance then
--don't feed back to ConsoleModDialog instance
elseif params.color_ranges and type(params.color_ranges) == "table" then
self._window_instance:add_to_history(_info,params.color_ranges)
else
local color
if params.color then
color = params.color
else
local _type = type(info)
color = self:GetColorByName(_type)
end
if color then
local length = utf8.len(_info)
self._window_instance:add_to_history(_info,{
{
start = 0,
finish = 1 + length,
color = color
}
})
else
self._window_instance:add_to_history(_info)
end
end
end
self:AddToOutputLog(_info)
local should_blt_log = self.settings.log_blt_enabled
if should_blt_log then
self.blt_log(string.format(managers.localization:text("menu_consolemod_window_log_prefix_str"),_info))
end
end
_G.Log = callback(Console,Console,"Log")
Console.log = Console.Log
function Console:Print(...)
return self:Log(self.table_concat({...}," "))
end
_G.Print = callback(Console,Console,"Print")
function Console:BLT_Print(...)
log(self.table_concat({...}," "))
end
_G._print = callback(Console,Console,"BLT_Print")
function Console:LogTable(obj,threaded)
if not obj then
local err_col = self:GetColorByName("error")
self:Log("Error: LogTable(" .. tostring(obj) .. ")",{color = err_col})
return
end
if threaded then
return self:LogTable_Threaded(obj)
else
return self:_LogTable(obj)
end
end
_G.logall = callback(Console,Console,"LogTable")
function Console:_LogTable(obj)
for k,v in pairs(obj) do
local data_type = type(v)
local color = self:GetColorByName(data_type,"misc")
self:Log("[" .. tostring(k) .. "] : [" .. tostring(v) .. "]",{color = color})
end
end
function Console:LogTable_Threaded(obj,desc)
--create thread to log table
self:AddCoroutine(callback(self,self,"_LogTable",obj),{
desc = desc or "LogTable(" .. tostring(obj) .. ")",
priority = nil,
paused = false
})
end
_G.logall2 = callback(Console,Console,"LogTable_Threaded")
function Console:_LogTable_Threaded(obj,t,dt)
--generally best used to log all of the properties of a Class:
--functions;
--and values, such as numbers, strings, tables, etc.
--i don't really know how else to do this
--todo save this as a global to Console so that i can create and delete examples but save their references
if not obj then
local err_col = self:GetColorByName("error")
self:Log("Error: LogTable(" .. tostring(obj) .. ")",{color = err_col})
return
end
for k,v in pairs(obj) do
local data_type = type(v)
--[[
if data_type == "userdata" then
for type_name,data in pairs(Console.type_data) do
if data.example then
local a1 = getmetatable(data.example)
local a2 = a1 and a1.__index
local b1 = getmetatable(v)
local b2 = b1 and b1.__index
if (b2 and a2) and (b2 == a2) then
data_type = type_name
break
end
end
end
end
--]]
local color = self:GetColorByName(data_type,"misc")
self:Log("[" .. tostring(k) .. "] : [" .. tostring(v) .. "]",{color = color})
coroutine.yield()
end
end
--core functionality
function Console:SearchTable(tbl,s,case_sensitive,threaded)
local function cb()
return self:_SearchTable(tbl,s,case_sensitive,threaded)