diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
index 00751f2cab..3024d9f4fe 100644
--- a/code/__DEFINES/antagonists.dm
+++ b/code/__DEFINES/antagonists.dm
@@ -75,6 +75,9 @@ GLOBAL_LIST_EMPTY(living_heart_cache) //A list of all living hearts in existance
#define IS_HERETIC(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic))
#define IS_HERETIC_MONSTER(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic_monster))
+/// Checks if the given mob is a malf ai.
+#define IS_MALF_AI(mob) (isAI(mob) && mob?.mind?.has_antag_datum(/datum/antagonist/traitor))
+
#define PATH_SIDE "Side"
#define PATH_ASH "Ash"
diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm
index 96201d71c2..84d6d0ae21 100644
--- a/code/__DEFINES/logging.dm
+++ b/code/__DEFINES/logging.dm
@@ -1,25 +1,26 @@
//Investigate logging defines
-#define INVESTIGATE_ATMOS "atmos"
-#define INVESTIGATE_BOTANY "botany"
-#define INVESTIGATE_CARGO "cargo"
-#define INVESTIGATE_EXPERIMENTOR "experimentor"
-#define INVESTIGATE_GRAVITY "gravity"
-#define INVESTIGATE_RECORDS "records"
-#define INVESTIGATE_SINGULO "singulo"
-#define INVESTIGATE_SUPERMATTER "supermatter"
-#define INVESTIGATE_TELESCI "telesci"
-#define INVESTIGATE_WIRES "wires"
-#define INVESTIGATE_PORTAL "portals"
-#define INVESTIGATE_RESEARCH "research"
-#define INVESTIGATE_HALLUCINATIONS "hallucinations"
-#define INVESTIGATE_RADIATION "radiation"
-#define INVESTIGATE_EXONET "exonet"
-#define INVESTIGATE_NANITES "nanites"
-#define INVESTIGATE_CIRCUIT "circuit"
-#define INVESTIGATE_FERMICHEM "fermichem"
-#define INVESTIGATE_RCD "rcd"
-#define INVESTIGATE_CRYOGENICS "cryogenics"
-#define INVESTIGATE_GHOST "ghost"
+#define INVESTIGATE_ATMOS "atmos"
+#define INVESTIGATE_BOTANY "botany"
+#define INVESTIGATE_CARGO "cargo"
+#define INVESTIGATE_CIRCUIT "circuit"
+#define INVESTIGATE_CRYOGENICS "cryogenics"
+#define INVESTIGATE_DEATHS "deaths"
+#define INVESTIGATE_EXONET "exonet"
+#define INVESTIGATE_EXPERIMENTOR "experimentor"
+#define INVESTIGATE_FERMICHEM "fermichem"
+#define INVESTIGATE_GHOST "ghost"
+#define INVESTIGATE_GRAVITY "gravity"
+#define INVESTIGATE_HALLUCINATIONS "hallucinations"
+#define INVESTIGATE_NANITES "nanites"
+#define INVESTIGATE_PORTAL "portals"
+#define INVESTIGATE_RADIATION "radiation"
+#define INVESTIGATE_RCD "rcd"
+#define INVESTIGATE_RECORDS "records"
+#define INVESTIGATE_RESEARCH "research"
+#define INVESTIGATE_SINGULO "singulo"
+#define INVESTIGATE_SUPERMATTER "supermatter"
+#define INVESTIGATE_TELESCI "telesci"
+#define INVESTIGATE_WIRES "wires"
// Logging types for log_message()
#define LOG_ATTACK (1 << 0)
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index 5b457dd9cc..d7f689d7a6 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -495,10 +495,10 @@
return sortTim(L, order >= 0 ? /proc/cmp_records_asc : /proc/cmp_records_dsc)
//any value in a list
-/proc/sortList(list/L, cmp=/proc/cmp_text_asc)
+/proc/sort_list(list/L, cmp=/proc/cmp_text_asc)
return sortTim(L.Copy(), cmp)
-//uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead
+//uses sort_list() but uses the var's name specifically. This should probably be using mergeAtom() instead
/proc/sortNames(list/L, order=1)
return sortTim(L.Copy(), order >= 0 ? /proc/cmp_name_asc : /proc/cmp_name_dsc)
diff --git a/code/__HELPERS/type_processing.dm b/code/__HELPERS/type_processing.dm
index ac7e5cab45..2b08b6d586 100644
--- a/code/__HELPERS/type_processing.dm
+++ b/code/__HELPERS/type_processing.dm
@@ -47,7 +47,7 @@
/proc/get_fancy_list_of_datum_types()
var/static/list/pre_generated_list
if (!pre_generated_list) //init
- pre_generated_list = make_types_fancy(sortList(typesof(/datum) - typesof(/atom)))
+ pre_generated_list = make_types_fancy(sort_list(typesof(/datum) - typesof(/atom)))
return pre_generated_list
diff --git a/code/controllers/subsystem/dcs.dm b/code/controllers/subsystem/dcs.dm
index 6be5a4bdfa..0d5b59bfa9 100644
--- a/code/controllers/subsystem/dcs.dm
+++ b/code/controllers/subsystem/dcs.dm
@@ -55,6 +55,6 @@ PROCESSING_SUBSYSTEM_DEF(dcs)
fullid += "[key]"
if(length(named_arguments))
- named_arguments = sortList(named_arguments)
+ named_arguments = sort_list(named_arguments)
fullid += named_arguments
return list2params(fullid)
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index a6c306e4d4..d8d0849ed7 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -423,7 +423,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
banned += generateMapList("[global.config.directory]/iceruinblacklist.txt")
banned += generateMapList("[global.config.directory]/stationruinblacklist.txt")
- for(var/item in sortList(subtypesof(/datum/map_template/ruin), /proc/cmp_ruincost_priority))
+ for(var/item in sort_list(subtypesof(/datum/map_template/ruin), /proc/cmp_ruincost_priority))
var/datum/map_template/ruin/ruin_type = item
// screen out the abstract subtypes
if(!initial(ruin_type.id))
diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm
index 582d2eb9dc..14c6c8aa26 100644
--- a/code/controllers/subsystem/processing/quirks.dm
+++ b/code/controllers/subsystem/processing/quirks.dm
@@ -22,7 +22,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
/datum/controller/subsystem/processing/quirks/proc/SetupQuirks()
// Sort by Positive, Negative, Neutral; and then by name
- var/list/quirk_list = sortList(subtypesof(/datum/quirk), /proc/cmp_quirk_asc)
+ var/list/quirk_list = sort_list(subtypesof(/datum/quirk), /proc/cmp_quirk_asc)
for(var/V in quirk_list)
var/datum/quirk/T = V
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index dbec272fe8..20d3ffd971 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -825,7 +825,7 @@ SUBSYSTEM_DEF(shuttle)
templates[S.port_id]["templates"] += list(L)
- data["templates_tabs"] = sortList(data["templates_tabs"])
+ data["templates_tabs"] = sort_list(data["templates_tabs"])
data["existing_shuttle"] = null
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index c75febedef..6f856f3edb 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -273,7 +273,7 @@ SUBSYSTEM_DEF(ticker)
var/list/modes = new
for (var/datum/game_mode/M in runnable_modes)
modes += M.name
- modes = sortList(modes)
+ modes = sort_list(modes)
to_chat(world, "The gamemode is: secret!\nPossibilities: [english_list(modes)]")
else
mode.announce()*/
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
index 7e3ac29b2d..1ca07bf502 100644
--- a/code/datums/diseases/advance/advance.dm
+++ b/code/datums/diseases/advance/advance.dm
@@ -361,7 +361,7 @@
L += "[S.id]N"
else
L += S.id
- L = sortList(L) // Sort the list so it doesn't matter which order the symptoms are in.
+ L = sort_list(L) // Sort the list so it doesn't matter which order the symptoms are in.
var/result = jointext(L, ":")
id = result
return id
diff --git a/code/datums/elements/object_reskinning.dm b/code/datums/elements/object_reskinning.dm
index 87f5f13385..63e8a35d05 100644
--- a/code/datums/elements/object_reskinning.dm
+++ b/code/datums/elements/object_reskinning.dm
@@ -65,7 +65,7 @@
icon = to_reskin.unique_reskin[reskin_option]["icon"] ? to_reskin.unique_reskin[reskin_option]["icon"] : to_reskin.icon,
icon_state = to_reskin.unique_reskin[reskin_option]["icon_state"] ? to_reskin.unique_reskin[reskin_option]["icon_state"] : to_reskin.icon_state)
items += list("[reskin_option]" = item_image)
- sortList(items)
+ sort_list(items)
// Display to the user
var/pick = show_radial_menu(user, to_reskin, items, custom_check = CALLBACK(src, .proc/check_reskin_menu, user, to_reskin), radius = 38, require_near = TRUE)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 9f6ccb742d..822da27923 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -67,6 +67,8 @@
var/datum/language_holder/language_holder
var/unconvertable = FALSE
var/late_joiner = FALSE
+ ///has this mind ever been an AI
+ var/has_ever_been_ai = FALSE
var/force_escaped = FALSE // Set by Into The Sunset command of the shuttle manipulator
var/list/learned_recipes //List of learned recipe TYPES.
@@ -286,6 +288,13 @@
if(O)
O.unlock_code = null
+/// Remove the antagonists that should not persist when being borged
+/datum/mind/proc/remove_antags_for_borging()
+ remove_antag_datum(/datum/antagonist/cult)
+
+ var/datum/antagonist/rev/revolutionary = has_antag_datum(/datum/antagonist/rev)
+ revolutionary?.remove_revolutionary()
+
/datum/mind/proc/remove_all_antag() //For the Lazy amongst us.
remove_changeling()
remove_traitor()
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 4f876b97e1..6c4542bfd1 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -210,7 +210,7 @@
if(materials.materials[i] > 0)
list_to_show += i
- used_material = tgui_input_list(usr, "Choose [used_material]", "Custom Material", sortList(list_to_show, /proc/cmp_typepaths_asc))
+ used_material = tgui_input_list(usr, "Choose [used_material]", "Custom Material", sort_list(list_to_show, /proc/cmp_typepaths_asc))
if(isnull(used_material))
return //Didn't pick any material, so you can't build shit either.
custom_materials[used_material] += amount_needed
diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm
index bf1b84fe5d..157ccfe01f 100644
--- a/code/game/machinery/camera/tracking.dm
+++ b/code/game/machinery/camera/tracking.dm
@@ -53,7 +53,7 @@
else
track.others[name] = L
- var/list/targets = sortList(track.humans) + sortList(track.others)
+ var/list/targets = sort_list(track.humans) + sort_list(track.others)
return targets
diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm
index 7eb6c79eef..c8add9e690 100644
--- a/code/game/machinery/computer/atmos_control.dm
+++ b/code/game/machinery/computer/atmos_control.dm
@@ -251,7 +251,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
IO |= text[1]
if(!IO.len)
to_chat(user, "No machinery detected.")
- var/S = input("Select the device set: ", "Selection", IO[1]) as anything in sortList(IO)
+ var/S = input("Select the device set: ", "Selection", IO[1]) as anything in sort_list(IO)
if(src)
src.input_tag = "[S]_in"
src.output_tag = "[S]_out"
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index d9d6f65e93..c3ec2dff21 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1276,7 +1276,7 @@
return
// reads from the airlock painter's `available paintjob` list. lets the player choose a paint option, or cancel painting
- var/current_paintjob = tgui_input_list(user, "Paintjob for this airlock", "Customize", sortList(painter.available_paint_jobs))
+ var/current_paintjob = tgui_input_list(user, "Paintjob for this airlock", "Customize", sort_list(painter.available_paint_jobs))
if(isnull(current_paintjob)) // if the user clicked cancel on the popup, return
return
diff --git a/code/game/machinery/telecomms/computers/logbrowser.dm b/code/game/machinery/telecomms/computers/logbrowser.dm
index c39c4667a6..e40b3d00be 100644
--- a/code/game/machinery/telecomms/computers/logbrowser.dm
+++ b/code/game/machinery/telecomms/computers/logbrowser.dm
@@ -36,7 +36,7 @@
ref = REF(T)
)
data_out["servers"] += list(data)
- data_out["servers"] = sortList(data_out["servers"]) //a-z sort
+ data_out["servers"] = sort_list(data_out["servers"]) //a-z sort
if(!SelectedMachine) //null is bad.
data_out["selected"] = null //but in js, null is good.
diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm
index b4f4b495f8..f3726c4245 100644
--- a/code/game/machinery/telecomms/computers/message.dm
+++ b/code/game/machinery/telecomms/computers/message.dm
@@ -107,7 +107,7 @@
ref = REF(T)
)
data_out["servers"] += list(data) // This /might/ cause an oom. Too bad!
- data_out["servers"] = sortList(data_out["servers"]) //a-z sort
+ data_out["servers"] = sort_list(data_out["servers"]) //a-z sort
data_out["fake_message"] = list(
sender = customsender,
diff --git a/code/game/machinery/telecomms/computers/telemonitor.dm b/code/game/machinery/telecomms/computers/telemonitor.dm
index b711b9fa40..b181e91667 100644
--- a/code/game/machinery/telecomms/computers/telemonitor.dm
+++ b/code/game/machinery/telecomms/computers/telemonitor.dm
@@ -37,12 +37,12 @@
ref = REF(T)
)
data_out["servers"] += list(data)
- data_out["servers"] = sortList(data_out["servers"])
+ data_out["servers"] = sort_list(data_out["servers"])
if(!SelectedMachine) //null is bad.
data_out["selected"] = null //but in js, null is good.
return data_out
-
+
data_out["selected"] = list(
name = SelectedMachine.name,
id = SelectedMachine.id,
@@ -90,7 +90,7 @@
if(LAZYLEN(machinelist) > 0)
notice = "FAILED: Cannot probe when buffer full"
return
-
+
for(var/obj/machinery/telecomms/T in GLOB.telecomms_list)
if(T.network == network)
LAZYADD(machinelist, T)
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index 22a9e86bb0..5e533888f9 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -205,7 +205,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark)
/obj/effect/landmark/start/ai/after_round_start()
if(latejoin_active && !used)
- new /obj/structure/AIcore/latejoin_inactive(loc)
+ new /obj/structure/ai_core/latejoin_inactive(loc)
return ..()
/obj/effect/landmark/start/ai/secondary
diff --git a/code/game/objects/items/cardboard_cutouts.dm b/code/game/objects/items/cardboard_cutouts.dm
index 00fde9f9f5..f4fe339c7b 100644
--- a/code/game/objects/items/cardboard_cutouts.dm
+++ b/code/game/objects/items/cardboard_cutouts.dm
@@ -19,7 +19,7 @@
. = ..()
if(possible_appearances)
return
- possible_appearances = sortList(list(
+ possible_appearances = sort_list(list(
"Assistant" = image(icon = src.icon, icon_state = "cutout_greytide"),
"Clown" = image(icon = src.icon, icon_state = "cutout_clown"),
"Mime" = image(icon = src.icon, icon_state = "cutout_mime"),
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 078839bcd1..c901e82b8d 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -654,7 +654,7 @@
display_vending_names_paths = list()
for(var/path in vending_names_paths)
display_vending_names_paths[vending_names_paths[path]] = path
- var/choice = input(user,"Choose a new brand","Select an Item") as null|anything in sortList(display_vending_names_paths)
+ var/choice = input(user,"Choose a new brand","Select an Item") as null|anything in sort_list(display_vending_names_paths)
set_type(display_vending_names_paths[choice])
else
return ..()
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 30877750f6..bd8a57c850 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -1180,7 +1180,7 @@ GLOBAL_LIST_EMPTY(PDAs)
plist[avoid_assoc_duplicate_keys(P.owner, namecounts)] = P
- var/c = input(user, "Please select a PDA") as null|anything in sortList(plist)
+ var/c = input(user, "Please select a PDA") as null|anything in sort_list(plist)
if (!c)
return
@@ -1268,7 +1268,7 @@ GLOBAL_LIST_EMPTY(PDAs)
plist[avoid_assoc_duplicate_keys(P.owner, namecounts)] = P
- var/c = input(user, "Please select a PDA") as null|anything in sortList(plist)
+ var/c = input(user, "Please select a PDA") as null|anything in sort_list(plist)
if (!c)
return
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index 34f8202898..be9244d245 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -600,7 +600,7 @@ Code:
if(!emoji_table)
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat)
var/list/collate = list("
")
- for(var/emoji in sortList(icon_states(icon('icons/emoji.dmi'))))
+ for(var/emoji in sort_list(icon_states(icon('icons/emoji.dmi'))))
var/tag = sheet.icon_tag("emoji-[emoji]")
collate += "| [emoji] | [tag] |
"
collate += "
"
diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm
index da5bed07ce..cbe795ca76 100644
--- a/code/game/objects/items/devices/camera_bug.dm
+++ b/code/game/objects/items/devices/camera_bug.dm
@@ -82,7 +82,7 @@
continue
if(length(list("ss13","mine", "rd", "labor", "toxins", "minisat")&camera.network))
bugged_cameras[camera.c_tag] = camera
- return sortList(bugged_cameras)
+ return sort_list(bugged_cameras)
/obj/item/camera_bug/proc/menu(list/cameras)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 7d7e39c41f..35e35485f1 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -973,7 +973,7 @@ GENETICS SCANNER
for(var/A in buffer)
options += get_display_name(A)
- var/answer = input(user, "Analyze Potential", "Sequence Analyzer") as null|anything in sortList(options)
+ var/answer = input(user, "Analyze Potential", "Sequence Analyzer") as null|anything in sort_list(options)
if(answer && ready && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
var/sequence
for(var/A in buffer) //this physically hurts but i dont know what anything else short of an assoc list
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index 9fae1496fd..1bfe0f21ca 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -260,7 +260,7 @@
display_names[initial(rodtype.name)] = rodtype
nullrod_icons += list(initial(rodtype.name) = image(icon = initial(rodtype.icon), icon_state = initial(rodtype.icon_state)))
- nullrod_icons = sortList(nullrod_icons)
+ nullrod_icons = sort_list(nullrod_icons)
var/choice = show_radial_menu(L, src , nullrod_icons, custom_check = CALLBACK(src, .proc/check_menu, L), radius = 42, require_near = TRUE)
if(!choice || !check_menu(L))
diff --git a/code/game/objects/items/robot/ai_upgrades.dm b/code/game/objects/items/robot/ai_upgrades.dm
index acfc1353b9..dc1eef53ad 100644
--- a/code/game/objects/items/robot/ai_upgrades.dm
+++ b/code/game/objects/items/robot/ai_upgrades.dm
@@ -25,7 +25,7 @@
AI.hack_software = TRUE
log_game("[key_name(user)] has upgraded [key_name(AI)] with a [src].")
message_admins("[ADMIN_LOOKUPFLW(user)] has upgraded [ADMIN_LOOKUPFLW(AI)] with a [src].")
- to_chat(user, "You upgrade [AI]. [src] is consumed in the process.")
+ to_chat(user, span_notice("You install [src], upgrading [AI]."))
qdel(src)
@@ -46,7 +46,7 @@
AI.eyeobj.relay_speech = TRUE
to_chat(AI, "[user] has upgraded you with surveillance software!")
to_chat(AI, "Via a combination of hidden microphones and lip reading software, you are able to use your cameras to listen in on conversations.")
- to_chat(user, "You upgrade [AI]. [src] is consumed in the process.")
+ to_chat(user, span_notice("You install [src], upgrading [AI]."))
log_game("[key_name(user)] has upgraded [key_name(AI)] with a [src].")
message_admins("[ADMIN_LOOKUPFLW(user)] has upgraded [ADMIN_LOOKUPFLW(AI)] with a [src].")
qdel(src)
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 43ed3b9213..b3c5cf4293 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -178,7 +178,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
* Plasteel
*/
GLOBAL_LIST_INIT(plasteel_recipes, list ( \
- new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = TRUE), \
+ new/datum/stack_recipe("AI core", /obj/structure/ai_core, 4, time = 50, one_per_turf = TRUE), \
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \
new/datum/stack_recipe("plasteel keg", /obj/structure/custom_keg, 10, time = 50), \
new/datum/stack_recipe("micro powered fan assembly", /obj/machinery/fan_assembly, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm
index a2ab0c2ff4..4465a4eb8b 100644
--- a/code/game/objects/items/storage/boxes.dm
+++ b/code/game/objects/items/storage/boxes.dm
@@ -886,7 +886,7 @@
/obj/item/storage/box/papersack/Initialize(mapload)
. = ..()
- papersack_designs = sortList(list(
+ papersack_designs = sort_list(list(
"None" = image(icon = src.icon, icon_state = "paperbag_None"),
"NanotrasenStandard" = image(icon = src.icon, icon_state = "paperbag_NanotrasenStandard"),
"SyndiSnacks" = image(icon = src.icon, icon_state = "paperbag_SyndiSnacks"),
diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm
index 85ee3f9f56..4accadfab4 100644
--- a/code/game/objects/structures/ai_core.dm
+++ b/code/game/objects/structures/ai_core.dm
@@ -1,4 +1,6 @@
-/obj/structure/AIcore
+#define AI_CORE_BRAIN(X) X.braintype == "Android" ? "brain" : "MMI"
+
+/obj/structure/ai_core
density = TRUE
anchored = FALSE
name = "\improper AI core"
@@ -8,28 +10,76 @@
max_integrity = 500
var/state = 0
var/datum/ai_laws/laws
- var/obj/item/circuitboard/circuit = null
- var/obj/item/mmi/brain = null
- var/can_deconstruct = TRUE
+ var/obj/item/circuitboard/aicore/circuit = null
+ var/obj/item/mmi/core_mmi
-/obj/structure/AIcore/Initialize(mapload)
+/obj/structure/ai_core/Initialize(mapload)
. = ..()
laws = new
laws.set_laws_config()
-/obj/structure/AIcore/Destroy()
- if(circuit)
- qdel(circuit)
+/obj/structure/ai_core/examine(mob/user)
+ . = ..()
+ if(!anchored)
+ if(state != EMPTY_CORE)
+ . += span_notice("It has some bolts that could be tightened.")
+ else
+ . += span_notice("It has some bolts that could be tightened. The frame can be melted down.")
+ else
+ switch(state)
+ if(EMPTY_CORE)
+ . += span_notice("There is a slot for a circuit board, its bolts can be loosened.")
+ if(CIRCUIT_CORE)
+ . += span_notice("The circuit board can be screwed into place or pried out.")
+ if(SCREWED_CORE)
+ . += span_notice("The frame can be wired, the circuit board can be unfastened.")
+ if(CABLED_CORE)
+ if(!core_mmi)
+ . += span_notice("There are wires which could be hooked up to an MMI or positronic brain, or cut.")
+ else
+ var/accept_laws = TRUE
+ if(core_mmi.laws.id != DEFAULT_AI_LAWID || !core_mmi.brainmob || !core_mmi.brainmob?.mind)
+ accept_laws = FALSE
+ . += span_notice("There is a slot for a reinforced glass panel, the [AI_CORE_BRAIN(core_mmi)] could be pried out.[accept_laws ? " A law module can be swiped across." : ""]")
+ if(GLASS_CORE)
+ . += span_notice("The monitor [core_mmi?.brainmob?.mind && !core_mmi?.brainmob?.suiciding ? "and neural interface " : ""]can be screwed in, the panel can be pried out.")
+ if(AI_READY_CORE)
+ . += span_notice("The monitor's connection can be cut[core_mmi?.brainmob?.mind && !core_mmi?.brainmob?.suiciding ? " the neural interface can be screwed in." : "."]")
+
+/obj/structure/ai_core/handle_atom_del(atom/A)
+ if(A == circuit)
circuit = null
- if(brain)
- qdel(brain)
- brain = null
+ if((state != GLASS_CORE) && (state != AI_READY_CORE))
+ state = EMPTY_CORE
+ update_appearance()
+ if(A == core_mmi)
+ core_mmi = null
return ..()
-/obj/structure/AIcore/latejoin_inactive
- name = "Networked AI core"
+/obj/structure/ai_core/Destroy()
+ QDEL_NULL(circuit)
+ QDEL_NULL(core_mmi)
+ QDEL_NULL(laws)
+ return ..()
+
+/obj/structure/ai_core/deactivated
+ icon_state = "ai-empty"
+ anchored = TRUE
+ state = AI_READY_CORE
+
+/obj/structure/ai_core/deactivated/Initialize(mapload, posibrain = FALSE)
+ . = ..()
+ circuit = new(src)
+ if(posibrain)
+ core_mmi = new/obj/item/mmi/posibrain(src)
+ else
+ core_mmi = new(src)
+ core_mmi.brain = new(core_mmi)
+ core_mmi.update_appearance()
+
+/obj/structure/ai_core/latejoin_inactive
+ name = "networked AI core"
desc = "This AI core is connected by bluespace transmitters to NTNet, allowing for an AI personality to be downloaded to it on the fly mid-shift."
- can_deconstruct = FALSE
icon_state = "ai-empty"
anchored = TRUE
state = AI_READY_CORE
@@ -37,11 +87,24 @@
var/safety_checks = TRUE
var/active = TRUE
-/obj/structure/AIcore/latejoin_inactive/examine(mob/user)
+/obj/structure/ai_core/latejoin_inactive/Initialize(mapload)
. = ..()
- . += "Its transmitter seems to be [active? "on" : "off"]."
+ circuit = new(src)
+ core_mmi = new(src)
+ core_mmi.brain = new(core_mmi)
+ core_mmi.update_appearance()
+ GLOB.latejoin_ai_cores += src
-/obj/structure/AIcore/latejoin_inactive/proc/is_available() //If people still manage to use this feature to spawn-kill AI latejoins ahelp them.
+/obj/structure/ai_core/latejoin_inactive/Destroy()
+ GLOB.latejoin_ai_cores -= src
+ return ..()
+
+/obj/structure/ai_core/latejoin_inactive/examine(mob/user)
+ . = ..()
+ . += "Its transmitter seems to be [active? "on" : "off"]."
+ . += span_notice("You could [active? "deactivate" : "activate"] it with a multitool.")
+
+/obj/structure/ai_core/latejoin_inactive/proc/is_available() //If people still manage to use this feature to spawn-kill AI latejoins ahelp them.
if(!available)
return FALSE
if(!safety_checks)
@@ -56,42 +119,61 @@
return FALSE
if(!SSmapping.level_trait(T.z,ZTRAIT_STATION))
return FALSE
- if(!istype(T, /turf/open/floor))
+ if(!isfloorturf(T))
return FALSE
return TRUE
-/obj/structure/AIcore/latejoin_inactive/attackby(obj/item/P, mob/user, params)
+/obj/structure/ai_core/latejoin_inactive/attackby(obj/item/P, mob/user, params)
if(P.tool_behaviour == TOOL_MULTITOOL)
active = !active
to_chat(user, "You [active? "activate" : "deactivate"] [src]'s transmitters.")
return
return ..()
-/obj/structure/AIcore/latejoin_inactive/Initialize(mapload)
+/obj/structure/ai_core/wrench_act(mob/living/user, obj/item/tool)
. = ..()
- GLOB.latejoin_ai_cores += src
+ default_unfasten_wrench(user, tool)
+ return TRUE
-/obj/structure/AIcore/latejoin_inactive/Destroy()
- GLOB.latejoin_ai_cores -= src
- return ..()
+/obj/structure/ai_core/screwdriver_act(mob/living/user, obj/item/tool)
+ . = ..()
+ if(state == AI_READY_CORE)
+ if(!core_mmi)
+ balloon_alert(user, "no brain installed!")
+ return TRUE
+ else if(!core_mmi.brainmob?.mind || core_mmi.brainmob?.suiciding)
+ balloon_alert(user, "brain is inactive!")
+ return TRUE
+ else
+ balloon_alert(user, "connecting neural network...")
+ if(!tool.use_tool(src, user, 10 SECONDS))
+ return TRUE
+ if(!ai_structure_to_mob())
+ return TRUE
+ balloon_alert(user, "connected neural network")
+ return TRUE
-/obj/structure/AIcore/attackby(obj/item/P, mob/user, params)
- if(P.tool_behaviour == TOOL_WRENCH)
- return default_unfasten_wrench(user, P, 20)
+/obj/structure/ai_core/attackby(obj/item/P, mob/user, params)
if(!anchored)
- if(P.tool_behaviour == TOOL_WELDER && can_deconstruct)
+ if(P.tool_behaviour == TOOL_WELDER)
if(state != EMPTY_CORE)
- to_chat(user, "The core must be empty to deconstruct it!")
+ balloon_alert(user, "core must be empty to deconstruct it!")
return
if(!P.tool_start_check(user, amount=0))
return
- to_chat(user, "You start to deconstruct the frame...")
+ balloon_alert(user, "deconstructing frame...")
if(P.use_tool(src, user, 20, volume=50) && state == EMPTY_CORE)
- to_chat(user, "You deconstruct the frame.")
+ balloon_alert(user, "deconstructed frame")
deconstruct(TRUE)
return
+ else
+ if(user.a_intent != INTENT_HARM)
+ balloon_alert(user, "bolt it down first!")
+ return
+ else
+ return ..()
else
switch(state)
if(EMPTY_CORE)
@@ -99,7 +181,7 @@
if(!user.transferItemToLoc(P, src))
return
playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
- to_chat(user, "You place the circuit board inside the frame.")
+ balloon_alert(user, "circuit board inserted")
update_icon()
state = CIRCUIT_CORE
circuit = P
@@ -107,13 +189,13 @@
if(CIRCUIT_CORE)
if(P.tool_behaviour == TOOL_SCREWDRIVER)
P.play_tool_sound(src)
- to_chat(user, "You screw the circuit board into place.")
+ balloon_alert(user, "board screwed into place")
state = SCREWED_CORE
update_icon()
return
if(P.tool_behaviour == TOOL_CROWBAR)
P.play_tool_sound(src)
- to_chat(user, "You remove the circuit board.")
+ balloon_alert(user, "circuit board removed")
state = EMPTY_CORE
update_icon()
circuit.forceMove(loc)
@@ -122,7 +204,7 @@
if(SCREWED_CORE)
if(P.tool_behaviour == TOOL_SCREWDRIVER && circuit)
P.play_tool_sound(src)
- to_chat(user, "You unfasten the circuit board.")
+ balloon_alert(user, "circuit board unfastened")
state = CIRCUIT_CORE
update_icon()
return
@@ -130,61 +212,73 @@
var/obj/item/stack/cable_coil/C = P
if(C.get_amount() >= 5)
playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
- to_chat(user, "You start to add cables to the frame...")
- if(do_after(user, 20, target = src) && state == SCREWED_CORE && C.use_tool(src, user, 0, 5))
- to_chat(user, "You add cables to the frame.")
+ balloon_alert(user, "adding cables to frame...")
+ if(do_after(user, 20, target = src) && state == SCREWED_CORE && C.use(5))
+ balloon_alert(user, "added cables to frame.")
state = CABLED_CORE
update_icon()
else
- to_chat(user, "You need five lengths of cable to wire the AI core!")
+ balloon_alert(user, "need five lengths of cable!")
return
if(CABLED_CORE)
if(P.tool_behaviour == TOOL_WIRECUTTER)
- if(brain)
- to_chat(user, "Get that [brain.name] out of there first!")
+ if(core_mmi)
+ balloon_alert(user, "remove the [AI_CORE_BRAIN(core_mmi)] first!")
else
P.play_tool_sound(src)
- to_chat(user, "You remove the cables.")
+ balloon_alert(user, "cables removed")
state = SCREWED_CORE
update_icon()
new /obj/item/stack/cable_coil(drop_location(), 5)
return
if(istype(P, /obj/item/stack/sheet/rglass))
+ if(!core_mmi)
+ balloon_alert(user, "add a brain first!")
+ return
var/obj/item/stack/sheet/rglass/G = P
if(G.get_amount() >= 2)
playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
- to_chat(user, "You start to put in the glass panel...")
+ balloon_alert(user, "adding glass panel...")
if(do_after(user, 20, target = src) && state == CABLED_CORE && G.use(2))
- to_chat(user, "You put in the glass panel.")
+ balloon_alert(user, "added glass panel")
state = GLASS_CORE
update_icon()
else
- to_chat(user, "You need two sheets of reinforced glass to insert them into the AI core!")
+ balloon_alert(user, "need two sheets of reinforced glass!")
return
if(istype(P, /obj/item/aiModule))
- if(brain && brain.laws.id != DEFAULT_AI_LAWID)
- to_chat(user, "The installed [brain.name] already has set laws!")
+ if(!core_mmi)
+ balloon_alert(user, "no brain installed!")
+ return
+ if(!core_mmi.brainmob || !core_mmi.brainmob?.mind || core_mmi.brainmob?.suiciding)
+ balloon_alert(user, "[AI_CORE_BRAIN(core_mmi)] is inactive!")
+ return
+ if(core_mmi.laws.id != DEFAULT_AI_LAWID)
+ balloon_alert(user, "[AI_CORE_BRAIN(core_mmi)] already has set laws!")
return
var/obj/item/aiModule/module = P
module.install(laws, user)
return
- if(istype(P, /obj/item/mmi) && !brain)
+ if(istype(P, /obj/item/mmi) && !core_mmi)
var/obj/item/mmi/M = P
- if(!M.brainmob)
- to_chat(user, "Sticking an empty [M.name] into the frame would sort of defeat the purpose!")
- return
- if(M.brainmob.stat == DEAD)
- to_chat(user, "Sticking a dead [M.name] into the frame would sort of defeat the purpose!")
- return
+ if(!M.brain_check(user))
+ var/install = tgui_alert(user, "This [AI_CORE_BRAIN(M)] is inactive, would you like to make an inactive AI?", "Installing AI [AI_CORE_BRAIN(M)]", list("Yes", "No"))
+ if(install != "Yes")
+ return
+ if(M.brainmob?.suiciding)
+ to_chat(user, span_warning("[M.name] is completely useless!"))
+ return
+ if(!user.transferItemToLoc(M, src))
+ return
+ core_mmi = M
+ balloon_alert(user, "added [AI_CORE_BRAIN(core_mmi)] to frame")
+ update_appearance()
- if(!M.brainmob.client)
- to_chat(user, "Sticking an inactive [M.name] into the frame would sort of defeat the purpose.")
- return
-
- if(!CONFIG_GET(flag/allow_ai) || (jobban_isbanned(M.brainmob, "AI") && !QDELETED(src) && !QDELETED(user) && !QDELETED(M) && !QDELETED(user) && Adjacent(user)))
+ var/mob/living/brain/B = M.brainmob
+ if(!CONFIG_GET(flag/allow_ai) || (jobban_isbanned(B, "AI") && !QDELETED(src) && !QDELETED(user) && !QDELETED(M) && !QDELETED(user) && Adjacent(user)))
if(!QDELETED(M))
to_chat(user, "This [M.name] does not seem to fit!")
return
@@ -196,47 +290,36 @@
if(!user.transferItemToLoc(M,src))
return
- brain = M
- to_chat(user, "You add [M.name] to the frame.")
+ core_mmi = M
+ balloon_alert(user, "added [AI_CORE_BRAIN(core_mmi)] to frame")
update_icon()
return
- if(P.tool_behaviour == TOOL_CROWBAR && brain)
+ if(P.tool_behaviour == TOOL_CROWBAR && core_mmi)
P.play_tool_sound(src)
- to_chat(user, "You remove the brain.")
- brain.forceMove(loc)
- brain = null
+ balloon_alert(user, "removed [AI_CORE_BRAIN(core_mmi)]")
+ core_mmi.forceMove(loc)
+ core_mmi = null
update_icon()
return
if(GLASS_CORE)
if(P.tool_behaviour == TOOL_CROWBAR)
P.play_tool_sound(src)
- to_chat(user, "You remove the glass panel.")
+ balloon_alert(user, "removed glass panel")
state = CABLED_CORE
update_icon()
new /obj/item/stack/sheet/rglass(loc, 2)
return
if(P.tool_behaviour == TOOL_SCREWDRIVER)
+ if(core_mmi?.brainmob?.suiciding)
+ to_chat(user, span_warning("The brain installed is completely useless."))
+ return
P.play_tool_sound(src)
- to_chat(user, "You connect the monitor.")
- if(brain)
- SSticker.mode.remove_antag_for_borging(brain.brainmob.mind)
- if(!istype(brain.laws, /datum/ai_laws/ratvar))
- remove_servant_of_ratvar(brain.brainmob, TRUE)
-
- var/mob/living/silicon/ai/A = null
-
- if (brain.overrides_aicore_laws)
- A = new /mob/living/silicon/ai(loc, brain.laws, brain.brainmob)
- else
- A = new /mob/living/silicon/ai(loc, laws, brain.brainmob)
-
- if(brain.force_replace_ai_name)
- A.fully_replace_character_name(A.name, brain.replacement_ai_name())
- SSblackbox.record_feedback("amount", "ais_created", 1)
- qdel(src)
+ balloon_alert(user, "connected monitor[core_mmi?.brainmob?.mind ? " and neural network" : ""]")
+ if(core_mmi.brainmob?.mind)
+ ai_structure_to_mob()
else
state = AI_READY_CORE
update_icon()
@@ -247,15 +330,39 @@
P.transfer_ai("INACTIVE", "AICARD", src, user)
return
- if(P.tool_behaviour == TOOL_SCREWDRIVER)
+ if(P.tool_behaviour == TOOL_WIRECUTTER)
P.play_tool_sound(src)
- to_chat(user, "You disconnect the monitor.")
+ balloon_alert(user, "disconnected monitor")
state = GLASS_CORE
update_icon()
return
return ..()
-/obj/structure/AIcore/update_icon_state()
+/obj/structure/ai_core/proc/ai_structure_to_mob()
+ var/mob/living/brain/the_brainmob = core_mmi.brainmob
+ if(!the_brainmob.mind || the_brainmob.suiciding)
+ return FALSE
+ the_brainmob.mind.remove_antags_for_borging()
+ if(!the_brainmob.mind.has_ever_been_ai)
+ SSblackbox.record_feedback("amount", "ais_created", 1)
+ var/mob/living/silicon/ai/ai_mob = null
+
+ if(core_mmi.overrides_aicore_laws)
+ ai_mob = new /mob/living/silicon/ai(loc, core_mmi.laws, the_brainmob)
+ core_mmi.laws = null //MMI's law datum is being donated, so we need the MMI to let it go or the GC will eat it
+ else
+ ai_mob = new /mob/living/silicon/ai(loc, laws, the_brainmob)
+ laws = null //we're giving the new AI this datum, so let's not delete it when we qdel(src) 5 lines from now
+
+ if(core_mmi.force_replace_ai_name)
+ ai_mob.fully_replace_character_name(ai_mob.name, core_mmi.replacement_ai_name())
+ if(core_mmi.braintype == "Android")
+ ai_mob.posibrain_inside = TRUE
+ deadchat_broadcast(" has been brought online at [get_area_name(ai_mob, format_text = TRUE)].", span_name("[ai_mob]"), follow_target = ai_mob, message_type = DEADCHAT_ANNOUNCEMENT)
+ qdel(src)
+ return TRUE
+
+/obj/structure/ai_core/update_icon_state()
switch(state)
if(EMPTY_CORE)
icon_state = "0"
@@ -264,7 +371,7 @@
if(SCREWED_CORE)
icon_state = "2"
if(CABLED_CORE)
- if(brain)
+ if(core_mmi)
icon_state = "3b"
else
icon_state = "3"
@@ -273,8 +380,8 @@
if(AI_READY_CORE)
icon_state = "ai-empty"
-/obj/structure/AIcore/deconstruct(disassembled = TRUE)
- if(state == GLASS_CORE)
+/obj/structure/ai_core/deconstruct(disassembled = TRUE)
+ if(state >= GLASS_CORE)
new /obj/item/stack/sheet/rglass(loc, 2)
if(state >= CABLED_CORE)
new /obj/item/stack/cable_coil(loc, 5)
@@ -284,13 +391,13 @@
new /obj/item/stack/sheet/plasteel(loc, 4)
qdel(src)
-/obj/structure/AIcore/deactivated
+/obj/structure/ai_core/deactivated
name = "inactive AI"
icon_state = "ai-empty"
anchored = TRUE
state = AI_READY_CORE
-/obj/structure/AIcore/deactivated/New()
+/obj/structure/ai_core/deactivated/New()
..()
circuit = new(src)
@@ -310,20 +417,35 @@ That prevents a few funky behaviors.
return 0
return 1
-/obj/structure/AIcore/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
+/obj/structure/ai_core/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
if(state != AI_READY_CORE || !..())
return
- //Transferring a carded AI to a core.
+ if(core_mmi && core_mmi.brainmob)
+ if(core_mmi.brainmob.mind)
+ to_chat(user, span_warning("[src] already contains an active mind!"))
+ return
+ else if(core_mmi.brainmob.suiciding)
+ to_chat(user, span_warning("[AI_CORE_BRAIN(core_mmi)] installed in [src] is completely useless!"))
+ return
+ //Transferring a carded AI to a core.
if(interaction == AI_TRANS_FROM_CARD)
- AI.control_disabled = 0
- AI.radio_enabled = 1
+ AI.control_disabled = FALSE
+ AI.radio_enabled = TRUE
AI.forceMove(loc) // to replace the terminal.
- to_chat(AI, "You have been uploaded to a stationary terminal. Remote device connection restored.")
- to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
+ to_chat(AI, span_notice("You have been uploaded to a stationary terminal. Remote device connection restored."))
+ to_chat(user, "[span_boldnotice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
card.AI = null
+ AI.battery = circuit.battery
+ if(core_mmi.braintype == "Android")
+ AI.posibrain_inside = TRUE
+ else
+ AI.posibrain_inside = FALSE
qdel(src)
else //If for some reason you use an empty card on an empty AI terminal.
- to_chat(user, "There is no AI loaded on this terminal!")
+ to_chat(user, span_alert("There is no AI loaded on this terminal."))
/obj/item/circuitboard/aicore
name = "AI core (AI Core Board)" //Well, duh, but best to be consistent
+ var/battery = 200 //backup battery for when the AI loses power. Copied to/from AI mobs when carding, and placed here to avoid recharge via deconning the core
+
+#undef AI_CORE_BRAIN
diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm
index e49de85cf9..5075ecd074 100644
--- a/code/game/objects/structures/janicart.dm
+++ b/code/game/objects/structures/janicart.dm
@@ -110,7 +110,7 @@
if(!length(items))
return
- items = sortList(items)
+ items = sort_list(items)
var/pick = show_radial_menu(user, src, items, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 38, require_near = TRUE)
if(!pick)
return
diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm
index 52be445120..9343e716ef 100644
--- a/code/modules/admin/admin_investigate.dm
+++ b/code/modules/admin/admin_investigate.dm
@@ -22,7 +22,7 @@
else
logs_missing += "[subject] (empty)"
- var/list/combined = sortList(logs_present) + sortList(logs_missing)
+ var/list/combined = sort_list(logs_present) + sort_list(logs_missing)
var/selected = input("Investigate what?", "Investigate") as null|anything in combined
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 47be7353fe..27e08aec58 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -694,7 +694,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
// if(!SStrading_card_game.loaded)
// message_admins("The card subsystem is not currently loaded")
// return
-// var/pack = input("Which pack should we test?", "You fucked it didn't you") as null|anything in sortList(SStrading_card_game.card_packs)
+// var/pack = input("Which pack should we test?", "You fucked it didn't you") as null|anything in sort_list(SStrading_card_game.card_packs)
// var/batchCount = input("How many times should we open it?", "Don't worry, I understand") as null|num
// var/batchSize = input("How many cards per batch?", "I hope you remember to check the validation") as null|num
// var/guar = input("Should we use the pack's guaranteed rarity? If so, how many?", "We've all been there. Man you should have seen the old system") as null|num
@@ -714,7 +714,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
var/type_length = length_char("/obj/effect/proc_holder/spell") + 2
for(var/A in GLOB.spells)
spell_list[copytext_char("[A]", type_length)] = A
- var/obj/effect/proc_holder/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in sortList(spell_list)
+ var/obj/effect/proc_holder/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in sort_list(spell_list)
if(!S)
return
@@ -735,7 +735,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
set desc = "Remove a spell from the selected mob."
if(T?.mind)
- var/obj/effect/proc_holder/spell/S = input("Choose the spell to remove", "NO ABRAKADABRA") as null|anything in sortList(T.mind.spell_list)
+ var/obj/effect/proc_holder/spell/S = input("Choose the spell to remove", "NO ABRAKADABRA") as null|anything in sort_list(T.mind.spell_list)
if(S)
T.mind.RemoveSpell(S)
log_admin("[key_name(usr)] removed the spell [S] from [key_name(T)].")
@@ -749,7 +749,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
if(!istype(T))
to_chat(src, "You can only give a disease to a mob of type /mob/living.", confidential = TRUE)
return
- var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in sortList(SSdisease.diseases, /proc/cmp_typepaths_asc)
+ var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in sort_list(SSdisease.diseases, /proc/cmp_typepaths_asc)
if(!D)
return
T.ForceContractDisease(new D, FALSE, TRUE)
diff --git a/code/modules/admin/playtimes.dm b/code/modules/admin/playtimes.dm
index 7cf24d9746..ac9a0db79b 100644
--- a/code/modules/admin/playtimes.dm
+++ b/code/modules/admin/playtimes.dm
@@ -32,7 +32,7 @@
clients += list(client)
- clients = sortList(clients, /proc/cmp_playtime)
+ clients = sort_list(clients, /proc/cmp_playtime)
data["clients"] = clients
return data
diff --git a/code/modules/admin/stickyban.dm b/code/modules/admin/stickyban.dm
index 57487f3144..c5c7a278d2 100644
--- a/code/modules/admin/stickyban.dm
+++ b/code/modules/admin/stickyban.dm
@@ -403,7 +403,7 @@
if (SSstickyban.dbcacheexpire)
return SSstickyban.dbcache.Copy()
- return sortList(world.GetConfig("ban"))
+ return sort_list(world.GetConfig("ban"))
/proc/get_stickyban_from_ckey(ckey)
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index c6b2437da4..34afce6aa2 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1351,7 +1351,7 @@
for (var/rule in subtypesof(/datum/dynamic_ruleset/roundstart))
var/datum/dynamic_ruleset/roundstart/newrule = new rule()
roundstart_rules[newrule.name] = newrule
- var/added_rule = input(usr,"What ruleset do you want to force? This will bypass threat level and population restrictions.", "Rigging Roundstart", null) as null|anything in sortList(roundstart_rules)
+ var/added_rule = input(usr,"What ruleset do you want to force? This will bypass threat level and population restrictions.", "Rigging Roundstart", null) as null|anything in sort_list(roundstart_rules)
if (added_rule)
GLOB.dynamic_forced_roundstart_ruleset += roundstart_rules[added_rule]
log_admin("[key_name(usr)] set [added_rule] to be a forced roundstart ruleset.")
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index 3a708ef182..09219e05ee 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -30,7 +30,7 @@
targets["[T.mob.real_name](as [T.mob.name]) - [T]"] = T
else
targets["(No Mob) - [T]"] = T
- var/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sortList(targets)
+ var/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sort_list(targets)
cmd_admin_pm(targets[target],null)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin PM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 7957a6d638..199ac646d9 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -238,7 +238,7 @@
if(M.ckey)
if(alert("This mob is being controlled by [M.key]. Are you sure you wish to give someone else control of it? [M.key] will be made a ghost.",,"Yes","No") != "Yes")
return
- var/client/newkey = input(src, "Pick the player to put in control.", "New player") as null|anything in sortList(GLOB.clients)
+ var/client/newkey = input(src, "Pick the player to put in control.", "New player") as null|anything in sort_list(GLOB.clients)
var/mob/oldmob = newkey.mob
var/delmob = FALSE
if((isobserver(oldmob) || alert("Do you want to delete [newkey]'s old mob?","Delete?","Yes","No") != "No"))
@@ -494,7 +494,7 @@
var/datum/outfit/O = path //not much to initalize here but whatever
outfits[initial(O.name)] = path
- var/dresscode = input("Select outfit", "Robust quick dress shop") as null|anything in baseoutfits + sortList(outfits)
+ var/dresscode = input("Select outfit", "Robust quick dress shop") as null|anything in baseoutfits + sort_list(outfits)
if (isnull(dresscode))
return
@@ -508,7 +508,7 @@
var/datum/outfit/O = path
job_outfits[initial(O.name)] = path
- dresscode = input("Select job equipment", "Robust quick dress shop") as null|anything in sortList(job_outfits)
+ dresscode = input("Select job equipment", "Robust quick dress shop") as null|anything in sort_list(job_outfits)
dresscode = job_outfits[dresscode]
if(isnull(dresscode))
return
@@ -520,7 +520,7 @@
var/datum/outfit/O = path
plasmaman_outfits[initial(O.name)] = path
- dresscode = input("Select plasmeme equipment", "Robust quick dress shop") as null|anything in sortList(plasmaman_outfits)
+ dresscode = input("Select plasmeme equipment", "Robust quick dress shop") as null|anything in sort_list(plasmaman_outfits)
dresscode = plasmaman_outfits[dresscode]
if(isnull(dresscode))
return
@@ -529,7 +529,7 @@
var/list/custom_names = list()
for(var/datum/outfit/D in GLOB.custom_outfits)
custom_names[D.name] = D
- var/selected_name = input("Select outfit", "Robust quick dress shop") as null|anything in sortList(custom_names)
+ var/selected_name = input("Select outfit", "Robust quick dress shop") as null|anything in sort_list(custom_names)
dresscode = custom_names[selected_name]
if(isnull(dresscode))
return
@@ -828,15 +828,15 @@
set name = "Show Line Profiling"
set desc = "Shows tracked profiling info from code lines that support it"
- var/sortlist = list(
+ var/sort_list = list(
"Avg time" = /proc/cmp_profile_avg_time_dsc,
"Total Time" = /proc/cmp_profile_time_dsc,
"Call Count" = /proc/cmp_profile_count_dsc
)
- var/sort = input(src, "Sort type?", "Sort Type", "Avg time") as null|anything in sortlist
+ var/sort = input(src, "Sort type?", "Sort Type", "Avg time") as null|anything in sort_list
if (!sort)
return
- sort = sortlist[sort]
+ sort = sort_list[sort]
profile_show(src, sort)
/client/proc/reload_configuration()
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 596d235b0a..2d7f1e8e9f 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -1672,7 +1672,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/name = GLOB.trait_name_map[trait] || trait
availible_traits[name] = trait
- var/chosen_trait = input("Select trait to modify", "Trait") as null|anything in sortList(availible_traits)
+ var/chosen_trait = input("Select trait to modify", "Trait") as null|anything in sort_list(availible_traits)
if(!chosen_trait)
return
chosen_trait = availible_traits[chosen_trait]
@@ -1689,7 +1689,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
if("All")
source = null
if("Specific")
- source = input("Source to be removed","Trait Remove/Add") as null|anything in sortList(D.status_traits[chosen_trait])
+ source = input("Source to be removed","Trait Remove/Add") as null|anything in sort_list(D.status_traits[chosen_trait])
if(!source)
return
REMOVE_TRAIT(D,chosen_trait,source)
diff --git a/code/modules/admin/verbs/secrets.dm b/code/modules/admin/verbs/secrets.dm
index e3c084b161..24e286310d 100644
--- a/code/modules/admin/verbs/secrets.dm
+++ b/code/modules/admin/verbs/secrets.dm
@@ -246,7 +246,7 @@
var/datum/round_event_control/disease_outbreak/DC = locate(/datum/round_event_control/disease_outbreak) in SSevents.control
E = DC.runEvent()
if("Choose")
- var/virus = input("Choose the virus to spread", "BIOHAZARD") as null|anything in sortList(typesof(/datum/disease), /proc/cmp_typepaths_asc)
+ var/virus = input("Choose the virus to spread", "BIOHAZARD") as null|anything in sort_list(typesof(/datum/disease), /proc/cmp_typepaths_asc)
var/datum/round_event_control/disease_outbreak/DC = locate(/datum/round_event_control/disease_outbreak) in SSevents.control
var/datum/round_event/disease_outbreak/DO = DC.runEvent()
DO.virus_type = virus
diff --git a/code/modules/admin/view_variables/mass_edit_variables.dm b/code/modules/admin/view_variables/mass_edit_variables.dm
index 5b120b6cef..ba9a4d278c 100644
--- a/code/modules/admin/view_variables/mass_edit_variables.dm
+++ b/code/modules/admin/view_variables/mass_edit_variables.dm
@@ -29,7 +29,7 @@
for (var/V in O.vars)
names += V
- names = sortList(names)
+ names = sort_list(names)
variable = input("Which var?", "Var") as null|anything in names
else
diff --git a/code/modules/admin/view_variables/modify_variables.dm b/code/modules/admin/view_variables/modify_variables.dm
index 54af2a9481..bfa8fb146c 100644
--- a/code/modules/admin/view_variables/modify_variables.dm
+++ b/code/modules/admin/view_variables/modify_variables.dm
@@ -306,7 +306,7 @@ GLOBAL_PROTECT(VVpixelmovement)
for (var/V in O.vars)
names += V
- names = sortList(names)
+ names = sort_list(names)
variable = input("Which var?","Var") as null|anything in names
if(!variable)
diff --git a/code/modules/admin/view_variables/topic_basic.dm b/code/modules/admin/view_variables/topic_basic.dm
index 230c86dd2d..21c79eeda0 100644
--- a/code/modules/admin/view_variables/topic_basic.dm
+++ b/code/modules/admin/view_variables/topic_basic.dm
@@ -65,11 +65,11 @@
if(!check_rights(NONE))
return
var/list/names = list()
- var/list/componentsubtypes = sortList(subtypesof(/datum/component), /proc/cmp_typepaths_asc)
+ var/list/componentsubtypes = sort_list(subtypesof(/datum/component), /proc/cmp_typepaths_asc)
names += "---Components---"
names += componentsubtypes
names += "---Elements---"
- names += sortList(subtypesof(/datum/element), /proc/cmp_typepaths_asc)
+ names += sort_list(subtypesof(/datum/element), /proc/cmp_typepaths_asc)
var/result = input(usr, "Choose a component/element to add","better know what ur fuckin doin pal") as null|anything in names
if(!usr || !result || result == "---Components---" || result == "---Elements---")
return
diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm
index 6039e88d9d..a7faea2553 100644
--- a/code/modules/admin/view_variables/view_variables.dm
+++ b/code/modules/admin/view_variables/view_variables.dm
@@ -88,7 +88,7 @@
value = L[key]
variable_html += debug_variable(i, value, 0, L)
else
- names = sortList(names)
+ names = sort_list(names)
for(var/V in names)
if(D.can_vv_get(V))
variable_html += D.vv_get_var(V)
diff --git a/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm b/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm
index 53e70e1404..360ddabe72 100644
--- a/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm
+++ b/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm
@@ -40,7 +40,7 @@
/proc/generate_all_scripture()
if(GLOB.all_scripture.len)
return
- for(var/V in sortList(subtypesof(/datum/clockwork_scripture) - list(/datum/clockwork_scripture/channeled, /datum/clockwork_scripture/create_object, /datum/clockwork_scripture/create_object/construct), /proc/cmp_clockscripture_priority))
+ for(var/V in sort_list(subtypesof(/datum/clockwork_scripture) - list(/datum/clockwork_scripture/channeled, /datum/clockwork_scripture/create_object, /datum/clockwork_scripture/create_object/construct), /proc/cmp_clockscripture_priority))
var/datum/clockwork_scripture/S = new V
GLOB.all_scripture[S.type] = S
diff --git a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm
index 33a17c3278..2ac9cedaaa 100644
--- a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm
+++ b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm
@@ -170,7 +170,7 @@
to_chat(user, "These items don't possess the required fingerprints or DNA.")
return FALSE
- var/chosen_mob = input("Select the person you wish to curse","Your target") as null|anything in sortList(compiled_list, /proc/cmp_mob_realname_dsc)
+ var/chosen_mob = input("Select the person you wish to curse","Your target") as null|anything in sort_list(compiled_list, /proc/cmp_mob_realname_dsc)
if(!chosen_mob)
return FALSE
curse(compiled_list[chosen_mob])
diff --git a/code/modules/asset_cache/asset_list.dm b/code/modules/asset_cache/asset_list.dm
index f88f57eacc..fc9b6527d2 100644
--- a/code/modules/asset_cache/asset_list.dm
+++ b/code/modules/asset_cache/asset_list.dm
@@ -331,7 +331,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
if (legacy)
assets |= parents
var/list/hashlist = list()
- var/list/sorted_assets = sortList(assets)
+ var/list/sorted_assets = sort_list(assets)
for (var/asset_name in sorted_assets)
var/datum/asset_cache_item/ACI = new(asset_name, sorted_assets[asset_name])
diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm
index f7bdc173f3..bcd8d381fe 100644
--- a/code/modules/atmospherics/machinery/portable/canister.dm
+++ b/code/modules/atmospherics/machinery/portable/canister.dm
@@ -388,7 +388,7 @@
return
switch(action)
if("relabel")
- var/label = input("New canister label:", name) as null|anything in sortList(label2types)
+ var/label = input("New canister label:", name) as null|anything in sort_list(label2types)
if(label && !..())
var/newtype = label2types[label]
if(newtype)
diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm
index 37f39793af..e16f7d759f 100644
--- a/code/modules/cargo/centcom_podlauncher.dm
+++ b/code/modules/cargo/centcom_podlauncher.dm
@@ -344,7 +344,7 @@
if (temp_pod.effectShrapnel == TRUE) //If already doing custom damage, set back to default (no shrapnel)
temp_pod.effectShrapnel = FALSE
return
- var/shrapnelInput = input("Please enter the type of pellet cloud you'd like to create on landing (Can be any projectile!)", "Projectile Typepath", 0) in sortList(subtypesof(/obj/item/projectile), /proc/cmp_typepaths_asc)
+ var/shrapnelInput = input("Please enter the type of pellet cloud you'd like to create on landing (Can be any projectile!)", "Projectile Typepath", 0) in sort_list(subtypesof(/obj/item/projectile), /proc/cmp_typepaths_asc)
if (isnull(shrapnelInput))
return
var/shrapnelMagnitude = input("Enter the magnitude of the pellet cloud. This is usually a value around 1-5. Please note that Ryll-Ryll has asked me to tell you that if you go too crazy with the projectiles you might crash the server. So uh, be gentle!", "Shrapnel Magnitude", 0) as null|num
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 40011ccbf2..e50539f91d 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -1429,7 +1429,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
//The job before the current job. I only use this to get the previous jobs color when I'm filling in blank rows.
var/datum/job/lastJob
- for(var/datum/job/job in sortList(SSjob.occupations, /proc/cmp_job_display_asc))
+ for(var/datum/job/job in sort_list(SSjob.occupations, /proc/cmp_job_display_asc))
index += 1
if((index >= limit) || (job.title in splitJobs))
@@ -2981,7 +2981,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(!length(key_bindings[old_key]))
key_bindings -= old_key
key_bindings[full_key] += list(kb_name)
- key_bindings[full_key] = sortList(key_bindings[full_key])
+ key_bindings[full_key] = sort_list(key_bindings[full_key])
if(href_list["special"]) // special keys need a full reset
user.client.ensure_keys_set(src)
user << browse(null, "window=capturekeypress")
diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm
index 93f91ad3a0..3485a45771 100644
--- a/code/modules/client/verbs/ooc.dm
+++ b/code/modules/client/verbs/ooc.dm
@@ -237,7 +237,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
choices["[C.mob]([C])"] = C
else
choices[C] = C
- choices = sortList(choices)
+ choices = sort_list(choices)
var/selection = input("Please, select a player!", "Ignore", null, null) as null|anything in choices
if(!selection || !(selection in choices))
return
diff --git a/code/modules/client/verbs/who.dm b/code/modules/client/verbs/who.dm
index 5786191f4d..fe445973ad 100644
--- a/code/modules/client/verbs/who.dm
+++ b/code/modules/client/verbs/who.dm
@@ -50,7 +50,7 @@
else
Lines += "[C.key] ([round(C.avgping, 1)]ms)"
- for(var/line in sortList(Lines))
+ for(var/line in sort_list(Lines))
msg += "[line]\n"
msg += "Total Players: [length(Lines)]"
diff --git a/code/modules/events/wizard/madness.dm b/code/modules/events/wizard/madness.dm
index de2c30a032..b960b07467 100644
--- a/code/modules/events/wizard/madness.dm
+++ b/code/modules/events/wizard/madness.dm
@@ -13,7 +13,7 @@
var/suggested = pick(strings(REDPILL_FILE, "redpill_questions"))
- forced_secret = (input(usr, "What horrifying truth will you reveal?", "Curse of Madness", sortList(suggested)) as text|null) || suggested
+ forced_secret = (input(usr, "What horrifying truth will you reveal?", "Curse of Madness", sort_list(suggested)) as text|null) || suggested
/datum/round_event/wizard/madness/start()
var/datum/round_event_control/wizard/madness/C = control
diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
index 08020f708d..854c88401e 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
@@ -188,7 +188,7 @@
listofitems[md5name]["amount"]++ // The good news is, #30519 made smartfridge UIs non-auto-updating
else
listofitems[md5name] = list("name" = O.name, "type" = O.type, "amount" = 1)
- sortList(listofitems)
+ sort_list(listofitems)
.["contents"] = listofitems
.["name"] = name
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index a91e3ddfd8..839e90c2df 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -626,7 +626,7 @@
for(var/muties in myseed.mutatelist)
var/obj/item/seeds/another_mut = new muties
fresh_mut_list[another_mut.plantname] = muties
- var/locked_mutation = (input(user, "Select a mutation to lock.", "Plant Mutation Locks") as null|anything in sortList(fresh_mut_list))
+ var/locked_mutation = (input(user, "Select a mutation to lock.", "Plant Mutation Locks") as null|anything in sort_list(fresh_mut_list))
if(!user.canUseTopic(src, BE_CLOSE) || !locked_mutation)
return
myseed.mutatelist = list(fresh_mut_list[locked_mutation])
diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm
index 6bf2764ba8..9b649135ae 100644
--- a/code/modules/jobs/job_types/ai.dm
+++ b/code/modules/jobs/job_types/ai.dm
@@ -30,8 +30,8 @@
/datum/job/ai/after_spawn(mob/H, client/C, latejoin)
. = ..()
if(latejoin)
- var/obj/structure/AIcore/latejoin_inactive/lateJoinCore
- for(var/obj/structure/AIcore/latejoin_inactive/P in GLOB.latejoin_ai_cores)
+ var/obj/structure/ai_core/latejoin_inactive/lateJoinCore
+ for(var/obj/structure/ai_core/latejoin_inactive/P in GLOB.latejoin_ai_cores)
if(P.is_available())
lateJoinCore = P
GLOB.latejoin_ai_cores -= P
@@ -60,7 +60,7 @@
if(!do_special_check)
return TRUE
for(var/i in GLOB.latejoin_ai_cores)
- var/obj/structure/AIcore/latejoin_inactive/LAI = i
+ var/obj/structure/ai_core/latejoin_inactive/LAI = i
if(istype(LAI))
if(LAI.is_available())
return TRUE
diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm
index 97953e6297..ef1fed4a18 100644
--- a/code/modules/mining/laborcamp/laborstacker.dm
+++ b/code/modules/mining/laborcamp/laborstacker.dm
@@ -28,7 +28,7 @@ GLOBAL_LIST(labor_sheet_values)
if(!initial(sheet.point_value) || (initial(sheet.merge_type) && initial(sheet.merge_type) != sheet_type)) //ignore no-value sheets and x/fifty subtypes
continue
sheet_list += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value)))
- GLOB.labor_sheet_values = sortList(sheet_list, /proc/cmp_sheet_list)
+ GLOB.labor_sheet_values = sort_list(sheet_list, /proc/cmp_sheet_list)
/proc/cmp_sheet_list(list/a, list/b)
return a["value"] - b["value"]
diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm
index f5a2368a60..847d3370c1 100644
--- a/code/modules/mob/living/brain/MMI.dm
+++ b/code/modules/mob/living/brain/MMI.dm
@@ -47,8 +47,20 @@
if(brain)
to_chat(user, "There's already a brain in the MMI!")
return
- if(!newbrain.brainmob)
- to_chat(user, "You aren't sure where this brain came from, but you're pretty sure it's a useless brain!")
+ if(newbrain.brainmob?.suiciding)
+ to_chat(user, span_warning("[newbrain] is completely useless."))
+ return
+ if(!newbrain.brainmob?.mind || !newbrain.brainmob)
+ var/install = tgui_alert(user, "[newbrain] is inactive, slot it in anyway?", "Installing Brain", list("Yes", "No"))
+ if(install != "Yes")
+ return
+ if(!user.transferItemToLoc(newbrain, src))
+ return
+ user.visible_message(span_notice("[user] sticks [newbrain] into [src]."), span_notice("[src]'s indicator light turns red as you insert [newbrain]. Its brainwave activity alarm buzzes."))
+ brain = newbrain
+ brain.organ_flags |= ORGAN_FROZEN
+ name = "[initial(name)]: [copytext(newbrain.name, 1, -8)]"
+ update_appearance()
return
if(!user.transferItemToLoc(O, src))
@@ -97,15 +109,15 @@
name = initial(name)
/obj/item/mmi/proc/eject_brain(mob/user)
- brainmob.container = null //Reset brainmob mmi var.
- brainmob.forceMove(brain) //Throw mob into brain.
- brainmob.stat = DEAD
- brainmob.emp_damage = 0
- brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision
- brainmob.remove_from_alive_mob_list() //Get outta here
- brainmob.add_to_dead_mob_list()
- brain.brainmob = brainmob //Set the brain to use the brainmob
- brainmob = null //Set mmi brainmob var to null
+ if(brain.brainmob)
+ brainmob.container = null //Reset brainmob mmi var.
+ brainmob.forceMove(brain) //Throw mob into brain.
+ brainmob.stat = DEAD
+ brainmob.emp_damage = 0
+ brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision
+ brain.brainmob = brainmob //Set the brain to use the brainmob
+ log_game("[key_name(user)] has ejected the brain of [key_name(brainmob)] from an MMI at [AREACOORD(src)]")
+ brainmob = null //Set mmi brainmob var to null
if(user)
user.put_in_hands(brain) //puts brain in the user's hand or otherwise drops it on the user's turf
else
@@ -210,6 +222,38 @@
/obj/item/mmi/relaymove(mob/user)
return //so that the MMI won't get a warning about not being able to move if it tries to move
+/obj/item/mmi/proc/brain_check(mob/user)
+ var/mob/living/brain/B = brainmob
+ if(!B)
+ if(user)
+ to_chat(user, span_warning("\The [src] indicates that there is no mind present!"))
+ return FALSE
+ if(brain?.decoy_override)
+ if(user)
+ to_chat(user, span_warning("This [name] does not seem to fit!"))
+ return FALSE
+ if(!B.key || !B.mind)
+ if(user)
+ to_chat(user, span_warning("\The [src] indicates that their mind is completely unresponsive!"))
+ return FALSE
+ if(!B.client)
+ if(user)
+ to_chat(user, span_warning("\The [src] indicates that their mind is currently inactive."))
+ return FALSE
+ if(B.suiciding)
+ if(user)
+ to_chat(user, span_warning("\The [src] indicates that their mind has no will to live!"))
+ return FALSE
+ if(B.stat == DEAD)
+ if(user)
+ to_chat(user, span_warning("\The [src] indicates that the brain is dead!"))
+ return FALSE
+ if(brain?.organ_flags & ORGAN_FAILING)
+ if(user)
+ to_chat(user, span_warning("\The [src] indicates that the brain is damaged!"))
+ return FALSE
+ return TRUE
+
/obj/item/mmi/syndie
name = "Syndicate Man-Machine Interface"
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs and AIs created with it."
diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm
index d59978d993..69a6972194 100644
--- a/code/modules/mob/living/emote.dm
+++ b/code/modules/mob/living/emote.dm
@@ -489,7 +489,7 @@
if(E.can_run_emote(user, status_check = FALSE))
keys += E.key
- keys = sortList(keys)
+ keys = sort_list(keys)
for(var/emote in keys)
if(LAZYLEN(message) > 1)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 08098b818f..0db472bb9d 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -30,6 +30,7 @@
d_hud = DATA_HUD_DIAGNOSTIC_ADVANCED
mob_size = MOB_SIZE_LARGE
has_field_of_vision = FALSE //Vision through cameras.
+ var/battery = 200 //emergency power if the AI's APC is off
var/list/network = list("ss13")
var/obj/machinery/camera/current
var/list/connected_robots = list()
@@ -46,7 +47,7 @@
var/obj/item/multitool/aiMulti
var/mob/living/simple_animal/bot/Bot
var/tracking = FALSE //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed.
- var/datum/effect_system/spark_spread/spark_system//So they can initialize sparks whenever/N
+ var/datum/effect_system/spark_spread/spark_system //So they can initialize sparks whenever/N
var/obj/machinery/status_display/controlled_display
//MALFUNCTION
@@ -83,7 +84,7 @@
var/cooldown = 0
var/acceleration = 1
- var/obj/structure/AIcore/deactivated/linked_core //For exosuit control
+ var/obj/structure/ai_core/deactivated/linked_core //For exosuit control
var/mob/living/silicon/robot/deployed_shell = null //For shell control
var/datum/action/innate/deploy_shell/deploy_action = new
var/datum/action/innate/deploy_last_shell/redeploy_action = new
@@ -105,11 +106,17 @@
///remember AI's last location
var/atom/lastloc
interaction_range = INFINITY
+ ///whether its mmi is a posibrain or regular mmi when going ai mob to ai core structure
+ var/posibrain_inside = TRUE
+ ///whether its cover is opened, so you can wirecut it for deconstruction
+ var/opened = FALSE
+ ///whether AI is anchored or not, used for checks
+ var/is_anchored = TRUE
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
. = ..()
if(!target_ai) //If there is no player/brain inside.
- new/obj/structure/AIcore/deactivated(loc) //New empty terminal.
+ new/obj/structure/ai_core/deactivated(loc) //New empty terminal.
return INITIALIZE_HINT_QDEL //Delete AI.
ADD_TRAIT(src, TRAIT_NO_TELEPORT, src)
@@ -125,6 +132,8 @@
mind.store_memory("As an AI, you must obey your silicon laws above all else. Your objectives will consider you to be dead.")
to_chat(src, "You have been installed as an AI! ")
to_chat(src, "You must obey your silicon laws above all else. Your objectives will consider you to be dead.")
+ if(!mind.has_ever_been_ai)
+ mind.has_ever_been_ai = TRUE
to_chat(src, "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).")
to_chat(src, "To look at other parts of the station, click on yourself to get a camera menu.")
@@ -237,6 +246,8 @@
. += text("Systems nonfunctional")
return
. += text("System integrity: [(health + 100) * 0.5]%")
+ if(isturf(loc)) //only show if we're "in" a core
+ . += "Backup Power: [battery * 0.5]%"
. += text("Connected cyborgs: [length(connected_robots)]")
for(var/r in connected_robots)
var/mob/living/silicon/robot/connected_robot = r
@@ -333,18 +344,64 @@
if(!isturf(loc)) // if their location isn't a turf
return // stop
if(incapacitated())
- return
- var/is_anchored = FALSE
- if(move_resist == MOVE_FORCE_OVERPOWERING)
+ if(battery < 50)
+ to_chat(src, span_warning("Insufficient backup power!"))
+ return
+ battery = battery - 50
+ to_chat(src, span_notice("You route power from your backup battery to move the bolts."))
+ flip_anchored()
+ to_chat(src, "You are now [is_anchored ? "" : "un"]anchored.")
+
+/mob/living/silicon/ai/proc/flip_anchored()
+ if(is_anchored)
+ is_anchored = !is_anchored
move_resist = MOVE_FORCE_NORMAL
+ status_flags |= CANPUSH
REMOVE_TRAIT(src, TRAIT_NO_TELEPORT, src)
else
- is_anchored = TRUE
+ is_anchored = !is_anchored
move_resist = MOVE_FORCE_OVERPOWERING
+ status_flags &= ~CANPUSH
ADD_TRAIT(src, TRAIT_NO_TELEPORT, src)
- to_chat(src, "You are now [is_anchored ? "" : "un"]anchored.")
- // the message in the [] will change depending whether or not the AI is anchored
+/mob/living/silicon/ai/proc/ai_mob_to_structure()
+ disconnect_shell()
+ ShutOffDoomsdayDevice()
+ var/obj/structure/ai_core/deactivated/ai_core = new(get_turf(src), /* skip_mmi_creation = */ TRUE)
+ if(make_mmi_drop_and_transfer(ai_core.core_mmi, the_core = ai_core))
+ qdel(src)
+ return ai_core
+
+/mob/living/silicon/ai/proc/make_mmi_drop_and_transfer(obj/item/mmi/the_mmi, the_core)
+ var/mmi_type
+ if(posibrain_inside)
+ mmi_type = new/obj/item/mmi/posibrain(src, /* autoping = */ FALSE)
+ else
+ mmi_type = new/obj/item/mmi(src)
+ if(hack_software)
+ new/obj/item/malf_upgrade(get_turf(src))
+ the_mmi = mmi_type
+ the_mmi.brain = new /obj/item/organ/brain(the_mmi)
+ the_mmi.brain.organ_flags |= ORGAN_FROZEN
+ the_mmi.brain.name = "[real_name]'s brain"
+ the_mmi.name = "[initial(the_mmi.name)]: [real_name]"
+ the_mmi.brainmob = new /mob/living/brain(the_mmi)
+ the_mmi.brainmob.name = src.real_name
+ the_mmi.brainmob.real_name = src.real_name
+ the_mmi.brainmob.container = the_mmi
+ the_mmi.brainmob.suiciding = suiciding
+ if(the_core)
+ var/obj/structure/ai_core/core = the_core
+ core.core_mmi = the_mmi
+ the_mmi.forceMove(the_core)
+ else
+ the_mmi.forceMove(get_turf(src))
+ if(the_mmi.brainmob.stat == DEAD && !suiciding)
+ the_mmi.brainmob.stat = CONSCIOUS
+ if(mind)
+ mind.transfer_to(the_mmi.brainmob)
+ the_mmi.update_appearance()
+ return TRUE
// AIs are immobile
/mob/living/silicon/ai/update_mobility()
@@ -427,18 +484,30 @@
return
if (href_list["ai_take_control"]) //Mech domination
- var/obj/vehicle/sealed/mecha/M = locate(href_list["ai_take_control"])
+ var/obj/vehicle/sealed/mecha/M = locate(href_list["ai_take_control"]) in GLOB.mechas_list
+ if (!M)
+ return
+
+ var/mech_has_controlbeacon = FALSE
+ for(var/obj/item/mecha_parts/mecha_tracking/ai_control/A in M.trackers)
+ mech_has_controlbeacon = TRUE
+ break
+ if(!can_dominate_mechs && !mech_has_controlbeacon)
+ message_admins("Warning: possible href exploit by [key_name(usr)] - attempted control of a mecha without can_dominate_mechs or a control beacon in the mech.")
+ usr.log_message("possibly attempting href exploit - attempted control of a mecha without can_dominate_mechs or a control beacon in the mech.", LOG_ADMIN)
+ return
+
if(controlled_equipment)
- to_chat(src, "You are already loaded into an onboard computer!")
+ to_chat(src, span_warning("You are already loaded into an onboard computer!"))
return
if(!GLOB.cameranet.checkCameraVis(M))
- to_chat(src, "Exosuit is no longer near active cameras.")
+ to_chat(src, span_warning("Exosuit is no longer near active cameras."))
return
if(!isturf(loc))
- to_chat(src, "You aren't in your core!")
+ to_chat(src, span_warning("You aren't in your core!"))
return
if(M)
- M.transfer_ai(AI_MECH_HACK,src, usr) //Called om the mech itself.
+ M.transfer_ai(AI_MECH_HACK, src, usr) //Called on the mech itself.
/mob/living/silicon/ai/proc/switchCamera(obj/machinery/camera/C)
@@ -825,10 +894,12 @@
to_chat(user, "No intelligence patterns detected." )
return
ShutOffDoomsdayDevice()
- new /obj/structure/AIcore/deactivated(loc)//Spawns a deactivated terminal at AI location.
+ var/obj/structure/ai_core/new_core = new /obj/structure/ai_core/deactivated(loc, posibrain_inside)//Spawns a deactivated terminal at AI location.
+ new_core.circuit.battery = battery
ai_restore_power()//So the AI initially has power.
- control_disabled = 1//Can't control things remotely if you're stuck in a card!
- radio_enabled = 0 //No talking on the built-in radio for you either!
+ control_disabled = TRUE //Can't control things remotely if you're stuck in a card!
+ interaction_range = 0
+ radio_enabled = FALSE //No talking on the built-in radio for you either!
forceMove(card)
card.AI = src
to_chat(src, "You have been downloaded to a mobile storage device. Remote device connection severed.")
@@ -1063,7 +1134,7 @@
// Sends an announcement the AI has cryoed.
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
announcer.announce("CRYOSTORAGE", src.real_name, announce_rank, list())
- new /obj/structure/AIcore/latejoin_inactive(loc)
+ new /obj/structure/ai_core/latejoin_inactive(loc)
if(src.mind)
//Handle job slot/tater cleanup.
if(src.mind.assigned_role == "AI")
diff --git a/code/modules/mob/living/silicon/ai/ai_defense.dm b/code/modules/mob/living/silicon/ai/ai_defense.dm
index b8a0a15e70..17d4e9d129 100644
--- a/code/modules/mob/living/silicon/ai/ai_defense.dm
+++ b/code/modules/mob/living/silicon/ai/ai_defense.dm
@@ -2,7 +2,7 @@
. = ..()
if(!.)
return FALSE
- if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt.
+ if(I.force && I.damtype != STAMINA && stat != DEAD && !QDELETED(src)) //only sparks if real damage is dealt.
spark_system.start()
/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
@@ -48,3 +48,105 @@
/mob/living/silicon/ai/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
return // no eyes, no flashing
+
+/mob/living/silicon/ai/emag_act(mob/user, obj/item/card/emag/emag_card) ///emags access panel lock, so you can crowbar it without robotics access or consent
+ . = ..()
+ if(emagged)
+ balloon_alert(user, "access panel lock already shorted!")
+ return
+ balloon_alert(user, "access panel lock shorted")
+ var/message = (user ? "[user] shorts out your access panel lock!" : "Your access panel lock was short circuited!")
+ to_chat(src, span_warning(message))
+ do_sparks(3, FALSE, src) // just a bit of extra "oh shit" to the ai - might grab its attention
+ emagged = TRUE
+ return TRUE
+
+/mob/living/silicon/ai/wrench_act(mob/living/user, obj/item/tool)
+ . = ..()
+ if(user.a_intent == INTENT_HARM)
+ return
+ balloon_alert(user, "[!is_anchored ? "tightening" : "loosening"] bolts...")
+ balloon_alert(src, "bolts being [!is_anchored ? "tightened" : "loosened"]...")
+ if(!tool.use_tool(src, user, 4 SECONDS))
+ return TRUE
+ flip_anchored()
+ balloon_alert(user, "bolts [is_anchored ? "tightened" : "loosened"]")
+ balloon_alert(src, "bolts [is_anchored ? "tightened" : "loosened"]")
+ return TRUE
+
+/mob/living/silicon/ai/crowbar_act(mob/living/user, obj/item/tool)
+ . = ..()
+ if(user.a_intent == INTENT_HARM)
+ return
+ if(!is_anchored)
+ balloon_alert(user, "bolt it down first!")
+ return TRUE
+ if(opened)
+ if(emagged)
+ balloon_alert(user, "access panel lock damaged!")
+ return TRUE
+ balloon_alert(user, "closing access panel...")
+ balloon_alert(src, "access panel being closed...")
+ if(!tool.use_tool(src, user, 5 SECONDS))
+ return TRUE
+ balloon_alert(src, "access panel closed")
+ balloon_alert(user, "access panel closed")
+ opened = FALSE
+ return TRUE
+ if(stat == DEAD)
+ to_chat(user, span_warning("The access panel looks damaged, you try dislodging the cover."))
+ else
+ var/consent
+ var/consent_override = FALSE
+ if(ishuman(user))
+ var/mob/living/carbon/human/human_user = user
+ if(human_user.wear_id)
+ var/list/access = human_user.wear_id.GetAccess()
+ if(ACCESS_ROBOTICS in access)
+ consent_override = TRUE
+ if(mind)
+ consent = tgui_alert(src, "[user] is attempting to open your access panel, unlock the cover?", "AI Access Panel", list("Yes", "No"))
+ if(consent == "No" && !consent_override && !emagged)
+ to_chat(user, span_notice("[src] refuses to unlock its access panel."))
+ return TRUE
+ if(consent != "Yes" && (consent_override || emagged))
+ to_chat(user, span_warning("[src] refuses to unlock its access panel...so you[!emagged ? " swipe your ID and " : " "]open it anyway!"))
+ else
+ if(!consent_override && !emagged)
+ to_chat(user, span_notice("[src] did not respond to your request to unlock its access panel cover lock."))
+ return TRUE
+ else
+ to_chat(user, span_notice("[src] did not respond to your request to unlock its access panel cover lock. You[!emagged ? " swipe your ID and " : " "]open it anyway."))
+
+ balloon_alert(user, "prying open access panel...")
+ balloon_alert(src, "access panel being pried open...")
+ if(!tool.use_tool(src, user, (stat == DEAD ? 40 SECONDS : 5 SECONDS)))
+ return TRUE
+ balloon_alert(src, "access panel opened")
+ balloon_alert(user, "access panel opened")
+ opened = TRUE
+ return TRUE
+
+/mob/living/silicon/ai/wirecutter_act(mob/living/user, obj/item/tool)
+ . = ..()
+ if(user.a_intent == INTENT_HARM)
+ return
+ if(!is_anchored)
+ balloon_alert(user, "bolt it down first!")
+ return TRUE
+ if(!opened)
+ balloon_alert(user, "open the access panel first!")
+ return TRUE
+ balloon_alert(src, "neural network being disconnected...")
+ balloon_alert(user, "disconnecting neural network...")
+ if(!tool.use_tool(src, user, (stat == DEAD ? 40 SECONDS : 5 SECONDS)))
+ return TRUE
+ if(IS_MALF_AI(src))
+ to_chat(user, span_userdanger("The voltage inside the wires rises dramatically!"))
+ user.electrocute_act(120, src)
+ opened = FALSE
+ return TRUE
+ to_chat(src, span_danger("You feel incredibly confused and disorientated."))
+ var/atom/ai_structure = ai_mob_to_structure()
+ ai_structure.balloon_alert(user, "disconnected neural network")
+ return TRUE
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index ed969e49fb..892fa6955b 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -28,11 +28,15 @@
// Handle power damage (oxy)
if(aiRestorePowerRoutine)
// Lost power
- adjustOxyLoss(1)
+ if (!battery)
+ to_chat(src, span_warning("Your backup battery's output drops below usable levels. It takes only a moment longer for your systems to fail, corrupted and unusable."))
+ adjustOxyLoss(200)
+ else
+ battery--
else
// Gain Power
- if(getOxyLoss())
- adjustOxyLoss(-1)
+ if (battery < 200)
+ battery++
if(!lacks_power())
var/area/home = get_area(src)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 77a88960d5..dbc2c3f587 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -162,7 +162,7 @@
if(BORG_SEC_AVAILABLE)
modulelist["Security"] = /obj/item/robot_module/security
- var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in sortList(modulelist)
+ var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in sort_list(modulelist)
if(!input_module || module.type != /obj/item/robot_module)
return
diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm
index 612298e526..b54473f7a6 100644
--- a/code/modules/mob/living/silicon/robot/robot_defines.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defines.dm
@@ -50,7 +50,6 @@
var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high ///If this is a path, this gets created as an object in Initialize.
var/opened = FALSE
- var/emagged = FALSE
var/emag_cooldown = 0
var/wiresexposed = FALSE
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index de2f4635d4..4459bd4413 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -380,7 +380,7 @@
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-med")
bad_snowflake.pixel_x = -16
med_icons["Alina"] = bad_snowflake
- med_icons = sortList(med_icons)
+ med_icons = sort_list(med_icons)
var/med_borg_icon = show_radial_menu(R, R , med_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(med_borg_icon)
if("Default")
@@ -498,7 +498,7 @@
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-eng")
bad_snowflake.pixel_x = -16
engi_icons["Alina"] = bad_snowflake
- engi_icons = sortList(engi_icons)
+ engi_icons = sort_list(engi_icons)
var/engi_borg_icon = show_radial_menu(R, R , engi_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(engi_borg_icon)
if("Default")
@@ -595,7 +595,7 @@
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-sec")
bad_snowflake.pixel_x = -16
sec_icons["Alina"] = bad_snowflake
- sec_icons = sortList(sec_icons)
+ sec_icons = sort_list(sec_icons)
var/sec_borg_icon = show_radial_menu(R, R , sec_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(sec_borg_icon)
if("Default")
@@ -681,7 +681,7 @@
/obj/item/robot_module/peacekeeper/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
- var/static/list/peace_icons = sortList(list(
+ var/static/list/peace_icons = sort_list(list(
"Default" = image(icon = 'icons/mob/robots.dmi', icon_state = "peace"),
"Borgi" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "borgi"),
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "whitespider")
@@ -852,7 +852,7 @@
var/image/bad_snowflake = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = "alina-sec")
bad_snowflake.pixel_x = -16
service_icons["Alina"] = bad_snowflake
- service_icons = sortList(service_icons)
+ service_icons = sort_list(service_icons)
var/service_robot_icon = show_radial_menu(R, R , service_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(service_robot_icon)
if("(Service) Waitress")
@@ -966,7 +966,7 @@
var/image/wide = image(icon = 'modular_citadel/icons/mob/widerobot.dmi', icon_state = L[a])
wide.pixel_x = -16
mining_icons[a] = wide
- mining_icons = sortList(mining_icons)
+ mining_icons = sort_list(mining_icons)
var/mining_borg_icon = show_radial_menu(R, R , mining_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
switch(mining_borg_icon)
if("Lavaland")
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 83ce09b315..347c71673e 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -44,6 +44,8 @@
var/obj/machinery/camera/builtInCamera = null
var/updating = FALSE //portable camera camerachunk update
+ ///Whether we have been emagged
+ var/emagged = FALSE
var/hack_software = FALSE //Will be able to use hacking actions
var/interaction_range = 7 //wireless control range
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index e2345a6384..2d82988997 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -454,7 +454,7 @@
var/obj/item/computer_hardware/H = all_components[h]
component_names.Add(H.name)
- var/choice = input(user, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in sortList(component_names)
+ var/choice = input(user, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in sort_list(component_names)
if(!choice)
return
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 8c81792d27..a0f98f4046 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -137,7 +137,7 @@
burst_size = 1
- sortList(fire_select_modes, /proc/cmp_numeric_asc)
+ sort_list(fire_select_modes, /proc/cmp_numeric_asc)
if(fire_select_modes.len > 1)
firemode_action = new(src)
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 1a64045ed0..779be376dd 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -94,16 +94,16 @@
/obj/machinery/chem_dispenser/Initialize(mapload)
. = ..()
- dispensable_reagents = sortList(dispensable_reagents, /proc/cmp_reagents_asc)
+ dispensable_reagents = sort_list(dispensable_reagents, /proc/cmp_reagents_asc)
if(emagged_reagents)
- emagged_reagents = sortList(emagged_reagents, /proc/cmp_reagents_asc)
+ emagged_reagents = sort_list(emagged_reagents, /proc/cmp_reagents_asc)
if(upgrade_reagents)
- upgrade_reagents = sortList(upgrade_reagents, /proc/cmp_reagents_asc)
+ upgrade_reagents = sort_list(upgrade_reagents, /proc/cmp_reagents_asc)
if(upgrade_reagents2)
- upgrade_reagents2 = sortList(upgrade_reagents2, /proc/cmp_reagents_asc)
+ upgrade_reagents2 = sort_list(upgrade_reagents2, /proc/cmp_reagents_asc)
if(upgrade_reagents3)
- upgrade_reagents3 = sortList(upgrade_reagents3, /proc/cmp_reagents_asc)
- dispensable_reagents = sortList(dispensable_reagents, /proc/cmp_reagents_asc)
+ upgrade_reagents3 = sort_list(upgrade_reagents3, /proc/cmp_reagents_asc)
+ dispensable_reagents = sort_list(dispensable_reagents, /proc/cmp_reagents_asc)
create_reagents(200, NO_REACT)
update_icon()
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index f4ffda302e..e0c4ce81e4 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -198,7 +198,8 @@
/obj/vehicle/sealed/mecha/Destroy()
for(var/ejectee in occupants)
- mob_exit(ejectee, TRUE, TRUE)
+ mob_exit(ejectee, silent = TRUE)
+
if(LAZYLEN(equipment))
for(var/obj/item/mecha_parts/mecha_equipment/equip as anything in equipment)
equip.detach(loc)
@@ -215,6 +216,8 @@
QDEL_NULL(cabin_air)
QDEL_NULL(spark_system)
QDEL_NULL(smoke_system)
+ QDEL_NULL(trackers)
+ QDEL_NULL(wires)
GLOB.poi_list -= src
GLOB.mechas_list -= src //global mech list
@@ -223,14 +226,39 @@
return ..()
/obj/vehicle/sealed/mecha/obj_destruction()
+ spark_system?.start()
loc.assume_air(cabin_air)
air_update_turf(FALSE, FALSE)
+
+ var/mob/living/silicon/ai/unlucky_ai
for(var/mob/living/occupant as anything in occupants)
if(isAI(occupant))
- occupant.gib() //No wreck, no AI to recover
+ var/mob/living/silicon/ai/ai = occupant
+ if(!ai.linked_core) // we probably shouldnt gib AIs with a core
+ unlucky_ai = occupant
+ ai.investigate_log("has been gibbed by having their mech destroyed.", INVESTIGATE_DEATHS)
+ ai.gib() //No wreck, no AI to recover
+ else
+ mob_exit(ai,silent = TRUE, forced = TRUE) // so we dont ghost the AI
continue
- mob_exit(occupant, FALSE, TRUE)
- occupant.SetSleeping(destruction_sleep_duration)
+ mob_exit(occupant, forced = TRUE)
+ if(!isbrain(occupant)) // who would win.. 1 brain vs 1 sleep proc..
+ occupant.SetSleeping(destruction_sleep_duration)
+
+ if(wreckage)
+ var/obj/structure/mecha_wreckage/WR = new wreckage(loc, unlucky_ai)
+ for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
+ if(E.detachable && prob(30))
+ WR.crowbar_salvage += E
+ E.detach(WR) //detaches from src into WR
+ else
+ E.detach(loc)
+ qdel(E)
+ if(cell)
+ WR.crowbar_salvage += cell
+ cell.forceMove(WR)
+ cell.use(rand(0, cell.charge), TRUE)
+ cell = null
return ..()
/obj/vehicle/sealed/mecha/update_icon()
@@ -480,7 +508,7 @@
var/mob/living/occupant = b
if(!enclosed && occupant?.incapacitated()) //no sides mean it's easy to just sorta fall out if you're incapacitated.
visible_message("[occupant] tumbles out of the cockpit!")
- mob_try_exit(occupant, TRUE, TRUE) //bye bye
+ mob_exit(occupant, randomstep = TRUE) //bye bye
//Diagnostic HUD updates
diag_hud_set_mechhealth()
@@ -796,19 +824,31 @@
to_chat(user, "Take control of exosuit?
")
/obj/vehicle/sealed/mecha/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
- if(!..())
+ . = ..()
+ if(!.)
return
//Transfer from core or card to mech. Proc is called by mech.
switch(interaction)
if(AI_TRANS_TO_CARD) //Upload AI from mech to AI card.
if(!construction_state) //Mech must be in maint mode to allow carding.
- to_chat(user, "[name] must have maintenance protocols active in order to allow a transfer.")
+ to_chat(user, span_warning("[name] must have maintenance protocols active in order to allow a transfer."))
return
- if(!locate(AI) in occupants) //Mech does not have an AI for a pilot
- to_chat(user, "No AI detected in the [name] onboard computer.")
+ var/list/ai_pilots = list()
+ for(var/mob/living/silicon/ai/aipilot in occupants)
+ ai_pilots += aipilot
+ if(!length(ai_pilots)) //Mech does not have an AI for a pilot
+ to_chat(user, span_warning("No AI detected in the [name] onboard computer."))
return
- for(var/mob/living/silicon/ai in occupants)
+ if(length(ai_pilots) > 1) //Input box for multiple AIs, but if there's only one we'll default to them.
+ AI = tgui_input_list(user, "Which AI do you wish to card?", "AI Selection", sort_list(ai_pilots))
+ else
+ AI = ai_pilots[1]
+ if(isnull(AI))
+ return
+ if(!(AI in occupants) || !user.Adjacent(src))
+ return //User sat on the selection window and things changed.
+
AI.ai_restore_power()//So the AI initially has power.
AI.control_disabled = TRUE
AI.radio_enabled = FALSE
@@ -819,36 +859,37 @@
card.AI = AI
AI.controlled_equipment = null
AI.remote_control = null
- to_chat(AI, "You have been downloaded to a mobile storage device. Wireless connection offline.")
- to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) removed from [name] and stored within local memory.")
+ to_chat(AI, span_notice("You have been downloaded to a mobile storage device. Wireless connection offline."))
+ to_chat(user, "[span_boldnotice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) removed from [name] and stored within local memory.")
+ return
if(AI_MECH_HACK) //Called by AIs on the mech
- AI.linked_core = new /obj/structure/AIcore/deactivated(AI.loc)
- if(AI.can_dominate_mechs)
- if(LAZYLEN(occupants)) //Oh, I am sorry, were you using that?
- to_chat(AI, "Occupants detected! Forced ejection initiated!")
- to_chat(occupants, "You have been forcibly ejected!")
- ejectall() //IT IS MINE, NOW. SUCK IT, RD!
- ai_enter_mech(AI, interaction)
+ AI.linked_core = new /obj/structure/ai_core/deactivated(AI.loc)
+ if(AI.can_dominate_mechs && LAZYLEN(occupants)) //Oh, I am sorry, were you using that?
+ to_chat(AI, span_warning("Occupants detected! Forced ejection initiated!"))
+ to_chat(occupants, span_danger("You have been forcibly ejected!"))
+ for(var/ejectee in occupants)
+ mob_exit(ejectee, silent = TRUE, randomstep = TRUE, forced = TRUE) //IT IS MINE, NOW. SUCK IT, RD!
+ AI.can_shunt = FALSE //ONE AI ENTERS. NO AI LEAVES.
if(AI_TRANS_FROM_CARD) //Using an AI card to upload to a mech.
AI = card.AI
if(!AI)
- to_chat(user, "There is no AI currently installed on this device.")
+ to_chat(user, span_warning("There is no AI currently installed on this device."))
return
if(AI.deployed_shell) //Recall AI if shelled so it can be checked for a client
AI.disconnect_shell()
if(AI.stat || !AI.client)
- to_chat(user, "[AI.name] is currently unresponsive, and cannot be uploaded.")
+ to_chat(user, span_warning("[AI.name] is currently unresponsive, and cannot be uploaded."))
return
if((LAZYLEN(occupants) >= max_occupants) || dna_lock) //Normal AIs cannot steal mechs!
- to_chat(user, "Access denied. [name] is [LAZYLEN(occupants) >= max_occupants ? "currently fully occupied" : "secured with a DNA lock"].")
+ to_chat(user, span_warning("Access denied. [name] is [LAZYLEN(occupants) >= max_occupants ? "currently fully occupied" : "secured with a DNA lock"]."))
return
AI.control_disabled = FALSE
AI.radio_enabled = TRUE
- to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
+ to_chat(user, "[span_boldnotice("Transfer successful")]: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
card.AI = null
- ai_enter_mech(AI, interaction)
+ ai_enter_mech(AI)
//Hack and From Card interactions share some code, so leave that here for both to use.
/obj/vehicle/sealed/mecha/proc/ai_enter_mech(mob/living/silicon/ai/AI, interaction)
@@ -865,7 +906,6 @@
"You have been uploaded to a mech's onboard computer.")
to_chat(AI, "Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions.")
-
///Handles an actual AI (simple_animal mecha pilot) entering the mech
/obj/vehicle/sealed/mecha/proc/aimob_enter_mech(mob/living/simple_animal/hostile/syndicate/mecha_pilot/pilot_mob)
if(pilot_mob && pilot_mob.Adjacent(src))
@@ -1042,47 +1082,45 @@
if(isAI(user))
var/mob/living/silicon/ai/AI = user
if(!AI.can_shunt)
- to_chat(AI, "You can't leave a mech after dominating it!.")
+ to_chat(AI, span_notice("You can't leave a mech after dominating it!."))
return FALSE
- to_chat(user, "You begin the ejection procedure. Equipment is disabled during this process. Hold still to finish ejecting.")
+ to_chat(user, span_notice("You begin the ejection procedure. Equipment is disabled during this process. Hold still to finish ejecting."))
is_currently_ejecting = TRUE
- if(do_after(user, exit_delay , target = src))
- to_chat(user, "You exit the mech.")
- mob_try_exit(user, silent = FALSE)
+ if(do_after(user, has_gravity() ? exit_delay : 0 , target = src))
+ to_chat(user, span_notice("You exit the mech."))
+ mob_exit(user, silent = TRUE)
else
- to_chat(user, "You stop exiting the mech. Weapons are enabled again.")
+ to_chat(user, span_notice("You stop exiting the mech. Weapons are enabled again."))
is_currently_ejecting = FALSE
-/obj/vehicle/sealed/mecha/proc/ejectall()
- for(var/ejectee in occupants)
- mob_try_exit(ejectee, TRUE, TRUE)
-
-/obj/vehicle/sealed/mecha/mob_try_exit(mob/M, silent, randomstep)
- mob_exit(M, silent, randomstep)
-
-/obj/vehicle/sealed/mecha/mob_exit(mob/M, silent, forced)
- var/newloc = get_turf(src)
+/obj/vehicle/sealed/mecha/mob_exit(mob/M, silent = FALSE, randomstep = FALSE, forced = FALSE)
var/atom/movable/mob_container
+ var/turf/newloc = get_turf(src)
if(ishuman(M))
- remove_occupant(M)
- ..()
- return
+ mob_container = M
else if(isbrain(M))
var/mob/living/brain/brain = M
mob_container = brain.container
else if(isAI(M))
var/mob/living/silicon/ai/AI = M
+ //stop listening to this signal, as the static update is now handled by the eyeobj's setLoc
+ AI.eyeobj?.UnregisterSignal(src, COMSIG_MOVABLE_MOVED)
+ AI.eyeobj?.forceMove(newloc) //kick the eye out as well
if(forced)//This should only happen if there are multiple AIs in a round, and at least one is Malf.
- AI.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
+ if(!AI.linked_core) //if the victim AI has no core
+ AI.investigate_log("has been gibbed by being forced out of their mech by another AI.", INVESTIGATE_DEATHS)
+ AI.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced.
AI = null
mecha_flags &= ~SILICON_PILOT
return
else
if(!AI.linked_core)
- to_chat(AI, "Inactive core destroyed. Unable to return.")
+ if(!silent)
+ to_chat(AI, span_userdanger("Inactive core destroyed. Unable to return."))
AI.linked_core = null
return
- to_chat(AI, "Returning to core...")
+ if(!silent)
+ to_chat(AI, span_notice("Returning to core..."))
AI.controlled_equipment = null
AI.remote_control = null
mob_container = AI
@@ -1090,21 +1128,20 @@
qdel(AI.linked_core)
else
return ..()
- var/mob/living/L = M
+ var/mob/living/ejector = M
mecha_flags &= ~SILICON_PILOT
- if(mob_container.forceMove(newloc))
- log_message("[mob_container] moved out.", LOG_MECHA)
- L << browse(null, "window=exosuit")
+ mob_container.forceMove(newloc)//ejecting mob container
+ log_message("[mob_container] moved out.", LOG_MECHA)
+ SStgui.close_user_uis(M, src)
if(istype(mob_container, /obj/item/mmi))
var/obj/item/mmi/mmi = mob_container
if(mmi.brainmob)
- L.forceMove(mmi)
- L.reset_perspective()
- remove_occupant(L)
+ ejector.forceMove(mmi)
+ ejector.reset_perspective()
+ remove_occupant(ejector)
mmi.mecha = null
- mmi.update_icon()
- L.mobility_flags = NONE
- setDir(dir_in)
+ mmi.update_appearance()
+ setDir(SOUTH)
return ..()
diff --git a/code/modules/vehicles/mecha/combat/neovgre.dm b/code/modules/vehicles/mecha/combat/neovgre.dm
index d8704e0318..7e40a1c352 100644
--- a/code/modules/vehicles/mecha/combat/neovgre.dm
+++ b/code/modules/vehicles/mecha/combat/neovgre.dm
@@ -25,7 +25,7 @@
else
add_control_flags(M, VEHICLE_CONTROL_MELEE|VEHICLE_CONTROL_EQUIPMENT)
-/obj/vehicle/sealed/mecha/combat/neovgre/mob_exit(mob/M, silent, forced)
+/obj/vehicle/sealed/mecha/combat/neovgre/mob_exit(mob/M, silent, randomstep, forced)
if(forced)
..()
diff --git a/modular_citadel/code/modules/client/verbs/who.dm b/modular_citadel/code/modules/client/verbs/who.dm
index 7640595e18..390c167365 100644
--- a/modular_citadel/code/modules/client/verbs/who.dm
+++ b/modular_citadel/code/modules/client/verbs/who.dm
@@ -38,7 +38,7 @@
var/client/C = X
if(C && C.holder && !C.holder.fakekey)
assembled += "\t [C.key][admin_mode? "[show_admin_info(C)]":""] ([round(C.avgping, 1)]ms)"
- Lines += sortList(assembled)
+ Lines += sort_list(assembled)
assembled.len = 0
if(length(GLOB.mentors))
Lines += "Mentors:"
@@ -46,10 +46,10 @@
var/client/C = X
if(C && (!C.holder || (C.holder && !C.holder.fakekey))) //>using stuff this complex instead of just using if/else lmao
assembled += "\t [C.key][admin_mode? "[show_admin_info(C)]":""] ([round(C.avgping, 1)]ms)"
- Lines += sortList(assembled)
+ Lines += sort_list(assembled)
assembled.len = 0
Lines += "Players:"
- for(var/X in sortList(GLOB.clients))
+ for(var/X in sort_list(GLOB.clients))
var/client/C = X
if(!C)
continue
@@ -57,8 +57,8 @@
if(C.holder && C.holder.fakekey)
key = C.holder.fakekey
assembled += "\t [key][admin_mode? "[show_admin_info(C)]":""] ([round(C.avgping, 1)]ms)"
- Lines += sortList(assembled)
-
+ Lines += sort_list(assembled)
+
for(var/line in Lines)
msg += "[line]\n"
diff --git a/modular_citadel/code/modules/mentor/mentorpm.dm b/modular_citadel/code/modules/mentor/mentorpm.dm
index 3260e96767..ba9a951b98 100644
--- a/modular_citadel/code/modules/mentor/mentorpm.dm
+++ b/modular_citadel/code/modules/mentor/mentorpm.dm
@@ -9,7 +9,7 @@
for(var/client/T)
targets["[T]"] = T
- var/list/sorted = sortList(targets)
+ var/list/sorted = sort_list(targets)
var/target = input(src,"To whom shall we send a message?","Mentor PM",null) in sorted|null
cmd_mentor_pm(targets[target],null)
SSblackbox.record_feedback("tally", "Mentor_verb", 1, "APM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!