diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index a8ea046657..18db6de769 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -543,9 +543,6 @@ GLOBAL_LIST_INIT(pda_reskins, list( #define FALL_NO_MESSAGE (1<<1) //Used to suppress the "[A] falls through [old_turf]" messages where it'd make little sense at all, like going downstairs. #define FALL_STOP_INTERCEPTING (1<<2) //Used in situations where halting the whole "intercept" loop would be better, like supermatter dusting (and thus deleting) the atom. -//Misc text define. Does 4 spaces. Used as a makeshift tabulator. -#define FOURSPACES "    " - #define CRYOMOBS 'icons/obj/cryo_mobs.dmi' #define CUSTOM_HOLOFORM_DELAY 10 SECONDS //prevents spamming to make lag. it's pretty expensive to do this. diff --git a/code/__DEFINES/text.dm b/code/__DEFINES/text.dm index 58c24747e0..bf60d6e725 100644 --- a/code/__DEFINES/text.dm +++ b/code/__DEFINES/text.dm @@ -1,5 +1,50 @@ +/// Does 4 spaces. Used as a makeshift tabulator. +#define FOURSPACES "    " + +/// Standard maptext /// Prepares a text to be used for maptext. Use this so it doesn't look hideous. #define MAPTEXT(text) {"[##text]"} -/// Macro from Lummox used to get height from a MeasureText proc -#define WXH_TO_HEIGHT(x) text2num(copytext(x, findtextEx(x, "x") + 1)) +/** + * Pixel-perfect scaled fonts for use in the MAP element as defined in skin.dmf + * + * Four sizes to choose from, use the sizes as mentioned below. + * Between the variations and a step there should be an option that fits your use case. + * BYOND uses pt sizing, different than px used in TGUI. Using px will make it look blurry due to poor antialiasing. + * + * Default sizes are prefilled in the macro for ease of use and a consistent visual look. + * To use a step other than the default in the macro, specify it in a span style. + * For example: MAPTEXT_PIXELLARI("Some large maptext here") + */ +/// Large size (ie: context tooltips) - Size options: 12pt 24pt. +#define MAPTEXT_PIXELLARI(text) {"[##text]"} + +/// Standard size (ie: normal runechat) - Size options: 6pt 12pt 18pt. +#define MAPTEXT_GRAND9K(text) {"[##text]"} + +/// Small size. (ie: context subtooltips, spell delays) - Size options: 12pt 24pt. +#define MAPTEXT_TINY_UNICODE(text) {"[##text]"} + +/// Smallest size. (ie: whisper runechat) - Size options: 6pt 12pt 18pt. +#define MAPTEXT_SPESSFONT(text) {"[##text]"} + +/** + * Prepares a text to be used for maptext, using a variable size font. + * + * More flexible but doesn't scale pixel perfect to BYOND icon resolutions. + * (May be blurry.) Can use any size in pt or px. + * + * You MUST Specify the size when using the macro + * For example: MAPTEXT_VCR_OSD_MONO("Some large maptext here") + */ +/// Prepares a text to be used for maptext, using a variable size font. +/// Variable size font. More flexible but doesn't scale pixel perfect to BYOND icon resolutions. (May be blurry.) Can use any size in pt or px. +#define MAPTEXT_VCR_OSD_MONO(text) {"[##text]"} + +/// Macro from Lummox used to get height from a MeasureText proc. +/// resolves the MeasureText() return value once, then resolves the height, then sets return_var to that. +#define WXH_TO_HEIGHT(measurement, return_var) \ + do { \ + var/_measurement = measurement; \ + return_var = text2num(copytext(_measurement, findtextEx(_measurement, "x") + 1)); \ + } while(FALSE); diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 579126257f..2ccd9deaf2 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -992,7 +992,7 @@ world letter = lowertext(letter) var/image/text_image = new(loc = A) - text_image.maptext = MAPTEXT("[letter]") + text_image.maptext = MAPTEXT("[letter]") text_image.pixel_x = 7 text_image.pixel_y = 5 qdel(atom_icon) diff --git a/code/__HELPERS/yelling.dm b/code/__HELPERS/yelling.dm index 4383a245d4..25ec9580a1 100644 --- a/code/__HELPERS/yelling.dm +++ b/code/__HELPERS/yelling.dm @@ -30,7 +30,7 @@ #define RUN_YELL(_T, _P, _D) \ returned = max(_P - max(_T.get_yelling_resistance(_P), 0) - 1, 0); \ processed[_T] = returned; - // _T.maptext = "[returned]"; + // _T.maptext = MAPTEXT(returned); var/list/turf/edges_next var/list/turf/powers_next diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 6f390fc19a..302edcc54b 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -133,24 +133,27 @@ #define ui_construct_pull "EAST,CENTER-2:15" #define ui_construct_health "EAST,CENTER:15" -// AI -#define ui_ai_core "SOUTH:6,WEST" -#define ui_ai_camera_list "SOUTH:6,WEST+1" -#define ui_ai_track_with_camera "SOUTH:6,WEST+2" -#define ui_ai_camera_light "SOUTH:6,WEST+3" -#define ui_ai_crew_monitor "SOUTH:6,WEST+4" -#define ui_ai_crew_manifest "SOUTH:6,WEST+5" -#define ui_ai_alerts "SOUTH:6,WEST+6" -#define ui_ai_announcement "SOUTH:6,WEST+7" -#define ui_ai_shuttle "SOUTH:6,WEST+8" -#define ui_ai_state_laws "SOUTH:6,WEST+9" -#define ui_ai_pda_send "SOUTH:6,WEST+10" -#define ui_ai_pda_log "SOUTH:6,WEST+11" -#define ui_ai_take_picture "SOUTH:6,WEST+12" -#define ui_ai_view_images "SOUTH:6,WEST+13" -#define ui_ai_sensor "SOUTH:6,WEST+14" -#define ui_ai_multicam "SOUTH+1:6,WEST+13" -#define ui_ai_add_multicam "SOUTH+1:6,WEST+14" +//AI +#define ui_ai_core "BOTTOM:6,RIGHT-4" +#define ui_ai_shuttle "BOTTOM:6,RIGHT-3" +#define ui_ai_announcement "BOTTOM:6,RIGHT-2" +#define ui_ai_state_laws "BOTTOM:6,RIGHT-1" +#define ui_ai_pda_log "BOTTOM:6,RIGHT" +#define ui_ai_pda_send "BOTTOM+1:6,RIGHT" +#define ui_ai_language_menu "BOTTOM+1:8,RIGHT-2:30" + +#define ui_ai_crew_monitor "BOTTOM:6,CENTER-1" +#define ui_ai_crew_manifest "BOTTOM:6,CENTER" +#define ui_ai_alerts "BOTTOM:6,CENTER+1" + +#define ui_ai_view_images "BOTTOM:6,LEFT+4" +#define ui_ai_camera_list "BOTTOM:6,LEFT+3" +#define ui_ai_track_with_camera "BOTTOM:6,LEFT+2" +#define ui_ai_camera_light "BOTTOM:6,LEFT+1" +#define ui_ai_sensor "BOTTOM:6,LEFT" +#define ui_ai_multicam "BOTTOM+1:6,LEFT+1" +#define ui_ai_add_multicam "BOTTOM+1:6,LEFT" +#define ui_ai_take_picture "BOTTOM+2:6,LEFT" // pAI diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm index 17b5a9ed61..5f8b10fd31 100644 --- a/code/_onclick/hud/ai.dm +++ b/code/_onclick/hud/ai.dm @@ -194,7 +194,7 @@ // Language menu using = new /atom/movable/screen/language_menu - using.screen_loc = ui_borg_language_menu + using.screen_loc = ui_ai_language_menu using.hud = src static_inventory += using diff --git a/code/_onclick/hud/credits.dm b/code/_onclick/hud/credits.dm index aaf423ecbc..3d6bbdc277 100644 --- a/code/_onclick/hud/credits.dm +++ b/code/_onclick/hud/credits.dm @@ -44,7 +44,7 @@ icon = I parent = P icon_state = credited - maptext = MAPTEXT(credited) + maptext = MAPTEXT_PIXELLARI(credited) maptext_x = world.icon_size + 8 maptext_y = (world.icon_size / 2) - 4 maptext_width = world.icon_size * 3 diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 88451a2c3b..eac3ab807b 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -78,7 +78,7 @@ /atom/movable/screen/devil/soul_counter/proc/update_counter(souls = 0) invisibility = 0 - maptext = "
[souls]
" + maptext = MAPTEXT("
[souls]
") switch(souls) if(0,null) icon_state = "Devil-1" @@ -137,7 +137,7 @@ ..() var/valuecolor = "#ff2525" if(owner.stat == DEAD) - maptext = "
ERR-0F
" + maptext = MAPTEXT("
ERR-0F
") icon_state = "coolant-3-1" return var/coolant_efficiency @@ -157,7 +157,7 @@ valuecolor = "#dd8109" else if(coolant > BLOOD_VOLUME_SURVIVE * owner.blood_ratio) valuecolor = "#e7520d" - maptext = "
[round((coolant / (BLOOD_VOLUME_NORMAL * owner.blood_ratio)) * 100, 1)]
" + maptext = MAPTEXT("
[round((coolant / (BLOOD_VOLUME_NORMAL * owner.blood_ratio)) * 100, 1)]
") var/efficiency_suffix var/state_suffix diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index eeb56d67f5..a00687e263 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -59,7 +59,7 @@ var/atom/movable/screen/movable/M = new() M.name = "Movable UI Object" M.icon_state = "block" - M.maptext = "Movable" + M.maptext = MAPTEXT("Movable") M.maptext_width = 64 var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Movable UI Object") as text @@ -78,7 +78,7 @@ var/atom/movable/screen/movable/snap/S = new() S.name = "Snap UI Object" S.icon_state = "block" - S.maptext = "Snap" + S.maptext = MAPTEXT("Snap") S.maptext_width = 64 var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Snap UI Object") as text diff --git a/code/datums/action.dm b/code/datums/action.dm index aa33c68f22..9e3acf562c 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -730,7 +730,7 @@ /datum/action/cooldown/proc/StartCooldown() next_use_time = world.time + cooldown_time - button.maptext = "[round(cooldown_time/10, 0.1)]" + button.maptext = MAPTEXT_TINY_UNICODE("[round(cooldown_time/10, 0.1)]") UpdateButtonIcon() START_PROCESSING(SSfastprocess, src) @@ -744,7 +744,7 @@ UpdateButtonIcon() STOP_PROCESSING(SSfastprocess, src) else - button.maptext = "[round(timeleft/10, 0.1)]" + button.maptext = MAPTEXT_TINY_UNICODE("[round(cooldown_time/10, 0.1)]") /datum/action/cooldown/Grant(mob/M) ..() diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm index 07c55bd6ef..81db2cae19 100644 --- a/code/datums/chatmessage.dm +++ b/code/datums/chatmessage.dm @@ -166,7 +166,9 @@ // Approximate text height var/complete_text = "[owner.say_emphasis(text)]" - var/mheight = WXH_TO_HEIGHT(owned_by.MeasureText(complete_text, null, CHAT_MESSAGE_WIDTH)) + + var/mheight + WXH_TO_HEIGHT(owned_by.MeasureText(complete_text, null, CHAT_MESSAGE_WIDTH), mheight) approx_lines = max(1, mheight / CHAT_MESSAGE_APPROX_LHEIGHT) // Translate any existing messages upwards, apply exponential decay factors to timers diff --git a/code/datums/components/storage/ui.dm b/code/datums/components/storage/ui.dm index d41d82ae75..4d61d569c3 100644 --- a/code/datums/components/storage/ui.dm +++ b/code/datums/components/storage/ui.dm @@ -48,7 +48,7 @@ var/datum/numbered_display/ND = numbered_contents[type] ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE ND.sample_object.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" - ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]" + ND.sample_object.maptext = MAPTEXT("[(ND.number > 1)? "[ND.number]" : ""]") ND.sample_object.layer = ABOVE_HUD_LAYER ND.sample_object.plane = ABOVE_HUD_PLANE . += ND.sample_object diff --git a/code/datums/explosion.dm b/code/datums/explosion.dm index ec0d35b5a3..dabfcea52c 100644 --- a/code/datums/explosion.dm +++ b/code/datums/explosion.dm @@ -436,13 +436,13 @@ GLOBAL_LIST_EMPTY(explosions) if(dist < dev) T.color = "red" - T.maptext = "Dev" + T.maptext = MAPTEXT("Dev") else if (dist < heavy) T.color = "yellow" - T.maptext = "Heavy" + T.maptext = MAPTEXT("Heavy") else if (dist < light) T.color = "blue" - T.maptext = "Light" + T.maptext = MAPTEXT("Light") else continue diff --git a/code/game/objects/effects/countdown.dm b/code/game/objects/effects/countdown.dm index 0722f3bd18..a416766b1b 100644 --- a/code/game/objects/effects/countdown.dm +++ b/code/game/objects/effects/countdown.dm @@ -9,6 +9,8 @@ anchored = TRUE layer = GHOST_LAYER color = "#ff0000" // text color + appearance_flags = NO_CLIENT_COLOR | RESET_ALPHA | RESET_COLOR | RESET_TRANSFORM + vis_flags = VIS_INHERIT_ID var/text_size = 3 // larger values clip when the displayed text is larger than 2 digits. var/started = FALSE var/displayed_text @@ -17,6 +19,10 @@ /obj/effect/countdown/Initialize(mapload) . = ..() attach(loc) + RegisterSignal(loc, COMSIG_PARENT_QDELETING, .proc/on_parent_deleting) + +/obj/effect/countdown/proc/on_parent_deleting(atom/being_deleted, force) + qdel(src) /obj/effect/countdown/examine(mob/user) . = ..() @@ -24,7 +30,12 @@ /obj/effect/countdown/proc/attach(atom/A) attached_to = A - forceMove(get_turf(A)) + if(ismovable(A)) + var/atom/movable/M = A + moveToNullspace() + M.vis_contents |= src + else + forceMove(get_turf(A)) /obj/effect/countdown/proc/start() if(!started) @@ -44,20 +55,22 @@ /obj/effect/countdown/process() if(!attached_to || QDELETED(attached_to)) qdel(src) - forceMove(get_turf(attached_to)) + if(!ismovable(attached_to)) + forceMove(get_turf(attached_to)) var/new_val = get_value() if(new_val == displayed_text) return displayed_text = new_val if(displayed_text) - maptext = "[displayed_text]" + maptext = MAPTEXT("[displayed_text]") else maptext = null /obj/effect/countdown/Destroy() - attached_to = null STOP_PROCESSING(SSfastprocess, src) + UnregisterSignal(attached_to, COMSIG_PARENT_QDELETING) + attached_to = null . = ..() /obj/effect/countdown/ex_act(severity, target, origin) //immune to explosions diff --git a/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm b/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm index 9c06c92108..5ed2cbd481 100644 --- a/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm +++ b/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm @@ -13,7 +13,7 @@ /obj/item/electroadaptive_pseudocircuit/Initialize(mapload) . = ..() - maptext = "[circuits]" + maptext = MAPTEXT("[circuits]") /obj/item/electroadaptive_pseudocircuit/examine(mob/user) . = ..() @@ -40,7 +40,7 @@ playsound(R, 'sound/items/rped.ogg', 50, TRUE) recharging = TRUE circuits-- - maptext = "[circuits]" + maptext = MAPTEXT("[circuits]") icon_state = "[initial(icon_state)]_recharging" var/recharge_time = min(600, circuit_cost * 5) //40W of cost for one fabrication = 20 seconds of recharge time; this is to prevent spamming addtimer(CALLBACK(src, .proc/recharge), recharge_time) @@ -53,7 +53,7 @@ if(!is_type_in_typecache(target, recycleable_circuits)) return circuits++ - maptext = "[circuits]" + maptext = MAPTEXT("[circuits]") user.visible_message("User breaks down [target] with [src].", \ "You recycle [target] into [src]. It now has material for [circuits] circuits.") playsound(user, 'sound/items/deconstruct.ogg', 50, TRUE) diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm index e2dc7b0f91..579f9e888d 100644 --- a/code/game/objects/items/devices/gps.dm +++ b/code/game/objects/items/devices/gps.dm @@ -86,7 +86,7 @@ // I assume it's faster to color,tag and OR the turf in, rather // then checking if its there T.color = RANDOM_COLOUR - T.maptext = "[T.x],[T.y],[T.z]" + T.maptext = MAPTEXT("[T.x],[T.y],[T.z]") tagged |= T /obj/item/gps/visible_debug/proc/clear() diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index fbb3297f89..760c58b533 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -312,6 +312,7 @@ qdel(O.mmi) O.mmi = W //and give the real mmi to the borg. O.updatename() + playsound(O.loc, 'sound/voice/liveagain.ogg', 75, TRUE) SSblackbox.record_feedback("amount", "cyborg_birth", 1) forceMove(O) O.robot_suit = src diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index ad4d1563a8..c283eff2cb 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -8,32 +8,29 @@ icon_state = "cyborg_upgrade" w_class = WEIGHT_CLASS_SMALL var/locked = FALSE - var/installed = 0 - var/require_module = 0 - var/list/module_type + var/installed = FALSE + var/require_module = FALSE + var/list/module_type = null /// Bitflags listing module compatibility. Used in the exosuit fabricator for creating sub-categories. var/module_flags = NONE // if true, is not stored in the robot to be ejected // if module is reset var/one_use = FALSE + /// Means this is a basetype and should not be used + var/abstract_type = /obj/item/borg/upgrade + /// Show the amount of this module that is installed + var/show_amount = FALSE /obj/item/borg/upgrade/proc/action(mob/living/silicon/robot/R, user = usr) if(R.stat == DEAD) - to_chat(user, "[src] will not function on a deceased cyborg.") + to_chat(user, span_warning("[src] will not function on a deceased cyborg!")) return FALSE if(module_type && !is_type_in_list(R.module, module_type)) - to_chat(R, "Upgrade mounting error! No suitable hardpoint detected.") - to_chat(user, "There's no mounting point for the module!") + to_chat(R, span_alert("Upgrade mounting error! No suitable hardpoint detected.")) + to_chat(user, span_warning("There's no mounting point for the module!")) return FALSE return TRUE -/* -This proc gets called by upgrades after installing them. Use this for things that for example need to be moved into a specific borg item, -as performing this in action() will cause the upgrade to end up in the borg instead of its intended location due to forceMove() being called afterwards.. -*/ -/obj/item/borg/upgrade/proc/afterInstall(mob/living/silicon/robot/R, user = usr) - return - /obj/item/borg/upgrade/proc/deactivate(mob/living/silicon/robot/R, user = usr) if (!(src in R.upgrades)) return FALSE @@ -324,12 +321,12 @@ as performing this in action() will cause the upgrade to end up in the borg inst /obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R, user = usr) . = ..() if(.) - ADD_TRAIT(src, TRAIT_LAVA_IMMUNE, type) + ADD_TRAIT(R, TRAIT_LAVA_IMMUNE, type) /obj/item/borg/upgrade/lavaproof/deactivate(mob/living/silicon/robot/R, user = usr) . = ..() if (.) - REMOVE_TRAIT(src, TRAIT_LAVA_IMMUNE, type) + REMOVE_TRAIT(R, TRAIT_LAVA_IMMUNE, type) /obj/item/borg/upgrade/selfrepair name = "self-repair module" @@ -440,6 +437,7 @@ as performing this in action() will cause the upgrade to end up in the borg inst /obj/item/robot_module/syndicate_medical) var/list/additional_reagents = list() module_flags = BORG_MODULE_MEDICAL + abstract_type = /obj/item/borg/upgrade/hypospray /obj/item/borg/upgrade/hypospray/action(mob/living/silicon/robot/R, user = usr) . = ..() diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index 943f60e752..3cd08ff419 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -201,6 +201,7 @@ var/obj/structure/closet/burn_closet = burn_obj for(var/burn_content in burn_closet.contents) burn_stuff(burn_content) + return var/mob/living/burn_living = burn_target burn_living.update_fire() diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 826132e860..85fbbc5c77 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -480,7 +480,7 @@ GLOBAL_LIST_EMPTY(station_turfs) A = i if(!QDELETED(A) && A.level >= affecting_level) . = A.wave_explode(., explosion, dir) - maptext = "[.]" + maptext = MAPTEXT("[.]") /turf/narsie_act(force, ignore_mobs, probability = 20) . = (prob(probability) || force) diff --git a/code/modules/admin/sound_emitter.dm b/code/modules/admin/sound_emitter.dm index ad9c995aa1..388a8e42af 100644 --- a/code/modules/admin/sound_emitter.dm +++ b/code/modules/admin/sound_emitter.dm @@ -81,7 +81,7 @@ var/new_label = stripped_input(user, "Choose a new label.", "Sound Emitter") if(!new_label) return - maptext = new_label + maptext = MAPTEXT(new_label) to_chat(user, "Label set to [maptext].", confidential = TRUE) if(href_list["edit_sound_file"]) var/new_file = input(user, "Choose a sound file.", "Sound Emitter") as null|sound diff --git a/code/modules/admin/verbs/borgpanel.dm b/code/modules/admin/verbs/borgpanel.dm index ec03afff36..a41a493feb 100644 --- a/code/modules/admin/verbs/borgpanel.dm +++ b/code/modules/admin/verbs/borgpanel.dm @@ -50,15 +50,12 @@ "lockdown" = borg.locked_down, "scrambledcodes" = borg.scrambledcodes ) - .["upgrades"] = list() - for (var/upgradetype in subtypesof(/obj/item/borg/upgrade)-/obj/item/borg/upgrade/hypospray) //hypospray is a dummy parent for hypospray upgrades - var/obj/item/borg/upgrade/upgrade = upgradetype - if (initial(upgrade.module_type) && !is_type_in_list(borg.module, initial(upgrade.module_type))) // Upgrade requires a different module - continue - var/installed = FALSE - if (locate(upgradetype) in borg) - installed = TRUE - .["upgrades"] += list(list("name" = initial(upgrade.name), "installed" = installed, "type" = upgradetype)) + var/obj/item/gun/energy/kinetic_accelerator/kinetic_accelerator = locate(/obj/item/gun/energy/kinetic_accelerator) in borg.module + if(kinetic_accelerator) + .["ka_remaining_capacity"] = kinetic_accelerator.get_remaining_mod_capacity() + .["active_upgrades"] = list() + for (var/obj/item/borg/upgrade/upgrade as anything in borg.upgrades) // put a non-upgrade here, i dare you. + .["active_upgrades"] += list(list("type" = upgrade.type)) .["laws"] = borg.laws ? borg.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE) : list() .["channels"] = list() for (var/k in GLOB.radiochannels) @@ -77,6 +74,28 @@ for(var/mob/living/silicon/ai/ai in GLOB.ai_list) .["ais"] += list(list("name" = ai.name, "ref" = REF(ai), "connected" = (borg.connected_ai == ai))) +/datum/borgpanel/ui_static_data(mob/user) + . = ..() + .["upgrades"] = list() + for(var/obj/item/borg/upgrade/upgrade as anything in GLOB.borg_upgrades) + if(upgrade.type == upgrade.abstract_type) + continue + var/obj/item/borg/upgrade/modkit/modkit + if(istype(upgrade, /obj/item/borg/upgrade/modkit)) + modkit = upgrade + if(modkit.minebot_exclusive) + continue + modkit = upgrade + .["upgrades"] += list( + list( + "name" = upgrade.name, + "type" = upgrade.type, + "module_type" = upgrade.module_type, + "maximum_of_type" = modkit ? modkit.maximum_of_type : null, + "denied_type" = modkit ? modkit.denied_type : null, + "cost" = modkit ? modkit.cost : null + ) + ) /datum/borgpanel/ui_act(action, params) if(..()) @@ -148,17 +167,31 @@ var/upgradepath = text2path(params["upgrade"]) var/obj/item/borg/upgrade/installedupgrade = locate(upgradepath) in borg if (installedupgrade) - installedupgrade.deactivate(borg, user) - borg.upgrades -= installedupgrade + qdel(installedupgrade) message_admins("[key_name_admin(user)] removed the [installedupgrade] upgrade from [ADMIN_LOOKUPFLW(borg)].") log_admin("[key_name(user)] removed the [installedupgrade] upgrade from [key_name(borg)].") - qdel(installedupgrade) else - var/obj/item/borg/upgrade/upgrade = new upgradepath(borg) - upgrade.action(borg, user) - borg.upgrades += upgrade + var/obj/item/borg/upgrade/upgrade = new upgradepath() + if(!borg.apply_upgrade(upgrade, user, TRUE)) + to_chat(user, span_danger("Upgrade error.")) + return message_admins("[key_name_admin(user)] added the [upgrade] borg upgrade to [ADMIN_LOOKUPFLW(borg)].") log_admin("[key_name(user)] added the [upgrade] borg upgrade to [key_name(borg)].") + if ("add_upgrade") + var/upgradepath = text2path(params["upgrade"]) + var/obj/item/borg/upgrade/upgrade = new upgradepath() + if(!borg.apply_upgrade(upgrade, user, TRUE)) + to_chat(user, span_danger("Upgrade error.")) + return + message_admins("[key_name_admin(user)] added the [upgrade] borg upgrade to [ADMIN_LOOKUPFLW(borg)].") + log_admin("[key_name(user)] added the [upgrade] borg upgrade to [key_name(borg)].") + if ("remove_upgrade") + var/upgradepath = text2path(params["upgrade"]) + var/obj/item/borg/upgrade/installedupgrade = locate(upgradepath) in borg + if (installedupgrade) + qdel(installedupgrade) + message_admins("[key_name_admin(user)] removed the [installedupgrade] upgrade from [ADMIN_LOOKUPFLW(borg)].") + log_admin("[key_name(user)] removed the [installedupgrade] upgrade from [key_name(borg)].") if ("toggle_radio") var/channel = params["channel"] if (channel in borg.radio.channels) // We're removing a channel @@ -236,3 +269,10 @@ message_admins("[key_name_admin(usr)] added [chosenboard] to [ADMIN_LOOKUPFLW(beepboop)].") log_admin("[key_name(usr)] added [chosenboard] to [key_name(beepboop)].") qdel(new_board) + +GLOBAL_LIST_INIT(borg_upgrades, populate_borg_upgrades()) + +/proc/populate_borg_upgrades() + . = list() + for(var/type in typesof(/obj/item/borg/upgrade)) + . += new type diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 0dfee4c38c..532a361ba0 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -83,7 +83,7 @@ GLOBAL_PROTECT(admin_verbs_debug_mapping) for(var/turf/T in C.can_see()) seen[T]++ for(var/turf/T in seen) - T.maptext = "[seen[T]]" + T.maptext = MAPTEXT("[seen[T]]") SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Camera Range") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Camera Range") diff --git a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm index 1c98060d9b..55a44b70de 100644 --- a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm +++ b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm @@ -275,7 +275,7 @@ /mob/living/simple_animal/hostile/blob/blobbernaut/update_health_hud() if(hud_used) - hud_used.healths.maptext = "
[round((health / maxHealth) * 100, 0.5)]%
" + hud_used.healths.maptext = MAPTEXT("
[round((health / maxHealth) * 100, 0.5)]%
") /mob/living/simple_animal/hostile/blob/blobbernaut/AttackingTarget() . = ..() diff --git a/code/modules/antagonists/blob/blob/overmind.dm b/code/modules/antagonists/blob/blob/overmind.dm index 5515c67e6b..ec95d32fd4 100644 --- a/code/modules/antagonists/blob/blob/overmind.dm +++ b/code/modules/antagonists/blob/blob/overmind.dm @@ -197,14 +197,14 @@ GLOBAL_LIST_EMPTY(blob_nodes) /mob/camera/blob/update_health_hud() if(blob_core) - hud_used.healths.maptext = "
[round(blob_core.obj_integrity)]
" + hud_used.healths.maptext = MAPTEXT("
[round(blob_core.obj_integrity)]
") for(var/mob/living/simple_animal/hostile/blob/blobbernaut/B in blob_mobs) if(B.hud_used && B.hud_used.blobpwrdisplay) - B.hud_used.blobpwrdisplay.maptext = "
[round(blob_core.obj_integrity)]
" + B.hud_used.blobpwrdisplay.maptext = MAPTEXT("
[round(blob_core.obj_integrity)]
") /mob/camera/blob/proc/add_points(points) blob_points = clamp(blob_points + points, 0, max_blob_points) - hud_used.blobpwrdisplay.maptext = "
[round(blob_points)]
" + hud_used.blobpwrdisplay.maptext = MAPTEXT("
[round(blob_points)]
") /mob/camera/blob/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null) if (!message) diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index 07c92bfd97..73625c894d 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -725,7 +725,7 @@ /atom/movable/screen/bloodsucker/blood_counter/update_counter(value, valuecolor) ..() - maptext = "
[round(value,1)]
" + maptext = MAPTEXT("
[round(value,1)]
") /atom/movable/screen/bloodsucker/rank_counter name = "Bloodsucker Rank" @@ -735,7 +735,7 @@ /atom/movable/screen/bloodsucker/rank_counter/update_counter(value, valuecolor) ..() - maptext = "
[round(value,1)]
" + maptext = MAPTEXT("
[round(value,1)]
") /atom/movable/screen/bloodsucker/sunlight_counter icon = 'icons/mob/actions/bloodsucker.dmi' @@ -763,7 +763,7 @@ /atom/movable/screen/bloodsucker/sunlight_counter/update_counter(value, valuecolor) ..() - maptext = "
[value]
" + maptext = MAPTEXT("
[value]
") /datum/antagonist/bloodsucker/proc/count_vassals(datum/mind/master) var/datum/antagonist/bloodsucker/B = master.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) diff --git a/code/modules/antagonists/clockcult/clock_mobs/clockwork_guardian.dm b/code/modules/antagonists/clockcult/clock_mobs/clockwork_guardian.dm index c937b27f16..b3365e6e70 100644 --- a/code/modules/antagonists/clockcult/clock_mobs/clockwork_guardian.dm +++ b/code/modules/antagonists/clockcult/clock_mobs/clockwork_guardian.dm @@ -180,8 +180,8 @@ resulthealth = "[round((host.health / host.maxHealth) * 100, 0.5)]%" else resulthealth = "NONE" - G.hosthealth.maptext = "
HOST
[resulthealth]
" - hud_used.healths.maptext = "
[round((health / maxHealth) * 100, 0.5)]%" + G.hosthealth.maptext = MAPTEXT("
HOST
[resulthealth]
") + hud_used.healths.maptext = MAPTEXT("
[round((health / maxHealth) * 100, 0.5)]%") /mob/living/simple_animal/hostile/clockwork/guardian/proc/update_stats() if(GLOB.ratvar_awakens) diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm index f05321487f..41fc16c922 100644 --- a/code/modules/antagonists/revenant/revenant.dm +++ b/code/modules/antagonists/revenant/revenant.dm @@ -150,7 +150,7 @@ essencecolor = "#9A5ACB" //oh boy you've got a lot of essence else if(!essence) essencecolor = "#1D2953" //oh jeez you're dying - hud_used.healths.maptext = "
[essence]E
" + hud_used.healths.maptext = MAPTEXT("
[essence]E
") /mob/living/simple_animal/revenant/med_hud_set_health() return //we use no hud diff --git a/code/modules/balloon_alert/balloon_alert.dm b/code/modules/balloon_alert/balloon_alert.dm index c273722607..f529768b1d 100644 --- a/code/modules/balloon_alert/balloon_alert.dm +++ b/code/modules/balloon_alert/balloon_alert.dm @@ -48,7 +48,7 @@ balloon_alert.appearance_flags = RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM balloon_alert.maptext = MAPTEXT("[text]") balloon_alert.maptext_x = (BALLOON_TEXT_WIDTH - bound_width) * -0.5 - balloon_alert.maptext_height = WXH_TO_HEIGHT(viewer_client?.MeasureText(text, null, BALLOON_TEXT_WIDTH)) + WXH_TO_HEIGHT(viewer_client?.MeasureText(text, null, BALLOON_TEXT_WIDTH), balloon_alert.maptext_height) balloon_alert.maptext_width = BALLOON_TEXT_WIDTH viewer_client?.images += balloon_alert diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm index 461648c270..013084e38f 100644 --- a/code/modules/clothing/glasses/engine_goggles.dm +++ b/code/modules/clothing/glasses/engine_goggles.dm @@ -99,7 +99,7 @@ var/strength = round(rad_places[i] / 1000, 0.1) var/image/pic = image(loc = place) var/mutable_appearance/MA = new() - MA.maptext = "[strength]k" + MA.maptext = MAPTEXT("[strength]k") MA.color = "#04e604" MA.layer = RAD_TEXT_LAYER MA.plane = GAME_PLANE diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 69b5de963d..75b647809a 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -82,8 +82,7 @@ Field repairs can be done with a welder." if(stored_gun && stored_gun.max_mod_capacity) . += "[stored_gun.get_remaining_mod_capacity()]% mod capacity remaining." - for(var/A in stored_gun.get_modkits()) - var/obj/item/borg/upgrade/modkit/M = A + for(var/obj/item/borg/upgrade/modkit/M in stored_gun.modkits) . += "There is \a [M] installed, using [M.cost]% capacity." /mob/living/simple_animal/hostile/mining_drone/welder_act(mob/living/user, obj/item/I) @@ -136,8 +135,7 @@ if(istype(O, /obj/item/projectile/kinetic)) var/obj/item/projectile/kinetic/K = O if(K.kinetic_gun) - for(var/A in K.kinetic_gun.get_modkits()) - var/obj/item/borg/upgrade/modkit/M = A + for(var/obj/item/borg/upgrade/modkit/M in K.kinetic_gun.modkits) if(istype(M, /obj/item/borg/upgrade/modkit/minebot_passthrough)) return TRUE if(istype(O, /obj/item/projectile/destabilizer)) diff --git a/code/modules/mob/living/carbon/alien/screen.dm b/code/modules/mob/living/carbon/alien/screen.dm index 4d90fd4b32..1f8902a584 100644 --- a/code/modules/mob/living/carbon/alien/screen.dm +++ b/code/modules/mob/living/carbon/alien/screen.dm @@ -1,7 +1,7 @@ /mob/living/carbon/alien/proc/updatePlasmaDisplay() if(hud_used) //clientless aliens - hud_used.alien_plasma_display.maptext = "
[round(getPlasma())]
" + hud_used.alien_plasma_display.maptext = MAPTEXT("
[round(getPlasma())]
") /mob/living/carbon/alien/larva/updatePlasmaDisplay() return diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index d83907be9c..8705a83681 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -28,11 +28,13 @@ inv2 = new /atom/movable/screen/robot/module2() inv3 = new /atom/movable/screen/robot/module3() + ident = rand(1, 999) + if(!shell) aiPDA = new/obj/item/pda/ai(src) aiPDA.owner = real_name aiPDA.ownjob = "Cyborg" - aiPDA.name = real_name + " (" + aiPDA.ownjob + ")" + aiPDA.name = real_name + " ([aiPDA.ownjob])" previous_health = health @@ -59,26 +61,29 @@ update_icons() . = ..() + //If this body is meant to be a borg controlled by the AI player //If this body is meant to be a borg controlled by the AI player if(shell) - make_shell() - - //MMI stuff. Held togheter by magic. ~Miauw - else if(!mmi || !mmi.brainmob) - mmi = new (src) - mmi.brain = new /obj/item/organ/brain(mmi) - mmi.brain.organ_flags |= ORGAN_FROZEN - mmi.brain.name = "[real_name]'s brain" - mmi.icon_state = "mmi_full" - mmi.name = "Man-Machine Interface: [real_name]" - mmi.brainmob = new(mmi) - mmi.brainmob.name = src.real_name - mmi.brainmob.real_name = src.real_name - mmi.brainmob.container = mmi + var/obj/item/borg/upgrade/ai/board = new(src) + make_shell(board) + add_to_upgrades(board) + else + //MMI stuff. Held togheter by magic. ~Miauw + if(!mmi?.brainmob) + mmi = new (src) + mmi.brain = new /obj/item/organ/brain(mmi) + mmi.brain.organ_flags |= ORGAN_FROZEN + mmi.brain.name = "[real_name]'s brain" + mmi.icon_state = "mmi_full" + mmi.name = "[initial(mmi.name)]: [real_name]" + mmi.brainmob = new(mmi) + mmi.brainmob.name = src.real_name + mmi.brainmob.real_name = src.real_name + mmi.brainmob.container = mmi + mmi.update_appearance() INVOKE_ASYNC(src, .proc/updatename) - playsound(loc, 'sound/voice/liveagain.ogg', 75, TRUE) aicamera = new/obj/item/camera/siliconcam/robot_camera(src) toner = tonermax diag_hud_set_borgcell() @@ -330,194 +335,145 @@ return FALSE return ISINRANGE(T1.x, T0.x - interaction_range, T0.x + interaction_range) && ISINRANGE(T1.y, T0.y - interaction_range, T0.y + interaction_range) -/mob/living/silicon/robot/proc/attempt_welder_repair(obj/item/W, mob/user) - if(!W.tool_behaviour == TOOL_WELDER) - return - if(!getBruteLoss()) - to_chat(user, "[src] is already in good condition!") - return - if(!W.tool_start_check(user, amount=0)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away. - return - user.DelayNextAction(CLICK_CD_MELEE) - if(src == user) - to_chat(user, "You start fixing yourself...") - if(!W.use_tool(src, user, 50)) - return - adjustBruteLoss(-10) - else - to_chat(user, "You start fixing [src]...") - if(!do_after(user, 30, target = src)) - return - adjustBruteLoss(-30) - updatehealth() - add_fingerprint(user) - visible_message("[user] has fixed some of the dents on [src].") - -/mob/living/silicon/robot/proc/attempt_cable_repair(obj/item/stack/cable_coil/W, mob/user) - if (getFireLoss() > 0 || getToxLoss() > 0) - user.DelayNextAction(CLICK_CD_MELEE) - if(src == user) - to_chat(user, "You start fixing yourself...") - if(!W.use_tool(src, user, 50, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT)) - to_chat(user, "You need more cable to repair [src]!") - return - adjustFireLoss(-10) - adjustToxLoss(-10) - else - to_chat(user, "You start fixing [src]...") - if(!W.use_tool(src, user, 30, 1)) - to_chat(user, "You need more cable to repair [src]!") - return - adjustFireLoss(-30) - adjustToxLoss(-30) - updatehealth() - user.visible_message("[user] has fixed some of the burnt wires on [src].", "You fix some of the burnt wires on [src].") - else - to_chat(user, "The wires seem fine, there's no need to fix them.") - /mob/living/silicon/robot/attackby(obj/item/W, mob/user, params) - if(W.tool_behaviour == TOOL_WELDER && (user.a_intent != INTENT_HARM || user == src)) - INVOKE_ASYNC(src, .proc/attempt_welder_repair, W, user) - return - - else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed) - INVOKE_ASYNC(src, .proc/attempt_cable_repair, W, user) - return - - else if(W.tool_behaviour == TOOL_CROWBAR) // crowbar means open or close the cover - if(opened) - to_chat(user, "You close the cover.") - opened = 0 - update_icons() - else - if(locked) - to_chat(user, "The cover is locked and cannot be opened!") + if(istype(W, /obj/item/stack/cable_coil) && wiresexposed) + user.DelayNextAction(CLICK_CD_MELEE) + if (getFireLoss() > 0 || getToxLoss() > 0) + if(src == user) + to_chat(user, span_notice("You start fixing yourself...")) + if(!W.use_tool(src, user, 5 SECONDS, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT)) + to_chat(user, span_warning("You need more cable to repair [src]!")) + return + adjustFireLoss(-10) + adjustToxLoss(-10) else - to_chat(user, "You open the cover.") - opened = 1 - update_icons() + to_chat(user, span_notice("You start fixing [src]...")) + if(!W.use_tool(src, user, 3 SECONDS, 1)) + to_chat(user, span_warning("You need more cable to repair [src]!")) + adjustFireLoss(-30) + adjustToxLoss(-30) + updatehealth() + user.visible_message(span_notice("[user] has fixed some of the burnt wires on [src]."), span_notice("You fix some of the burnt wires on [src].")) + else + to_chat(user, span_warning("The wires seem fine, there's no need to fix them.")) + return - else if(istype(W, /obj/item/stock_parts/cell) && opened) // trying to put a cell inside + if(istype(W, /obj/item/stock_parts/cell) && opened) // trying to put a cell inside if(wiresexposed) - to_chat(user, "Close the cover first!") + to_chat(user, span_warning("Close the cover first!")) else if(cell) - to_chat(user, "There is a power cell already installed!") + to_chat(user, span_warning("There is a power cell already installed!")) else if(!user.transferItemToLoc(W, src)) return cell = W - to_chat(user, "You insert the power cell.") + to_chat(user, span_notice("You insert the power cell.")) update_icons() diag_hud_set_borgcell() + return - else if(is_wire_tool(W)) + if(is_wire_tool(W)) if (wiresexposed) wires.interact(user) else - to_chat(user, "You can't reach the wiring!") + to_chat(user, span_warning("You can't reach the wiring!")) + return - else if(W.tool_behaviour == TOOL_SCREWDRIVER && opened && !cell) // haxing - wiresexposed = !wiresexposed - to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]") - update_icons() - - else if((W.tool_behaviour == TOOL_SCREWDRIVER) && opened && cell) // radio - if(shell) - to_chat(user, "You cannot seem to open the radio compartment") //Prevent AI radio key theft - else if(radio) - radio.attackby(W,user)//Push it to the radio to let it handle everything - else - to_chat(user, "Unable to locate a radio!") - update_icons() - - else if(W.tool_behaviour == TOOL_WRENCH && opened && !cell) //Deconstruction. The flashes break from the fall, to prevent this from being a ghetto reset module. - if(!locked_down) - to_chat(user, "[src]'s bolts spark! Maybe you should lock them down first!") - spark_system.start() - return - else - to_chat(user, "You start to unfasten [src]'s securing bolts...") - if(W.use_tool(src, user, 50, volume=50) && !cell) - user.visible_message("[user] deconstructs [src]!", "You unfasten the securing bolts, and [src] falls to pieces!") - deconstruct() - - else if(istype(W, /obj/item/aiModule)) + if(istype(W, /obj/item/aiModule)) var/obj/item/aiModule/MOD = W if(!opened) - to_chat(user, "You need access to the robot's insides to do that!") + to_chat(user, span_warning("You need access to the robot's insides to do that!")) return if(wiresexposed) - to_chat(user, "You need to close the wire panel to do that!") + to_chat(user, span_warning("You need to close the wire panel to do that!")) return if(!cell) - to_chat(user, "You need to install a power cell to do that!") + to_chat(user, span_warning("You need to install a power cell to do that!")) return if(shell) //AI shells always have the laws of the AI - to_chat(user, "[src] is controlled remotely! You cannot upload new laws this way!") + to_chat(user, span_warning("[src] is controlled remotely! You cannot upload new laws this way!")) return - if(emagged || (connected_ai && lawupdate)) //Can't be sure which, metagamers - emote("buzz-[user.name]") + if(connected_ai && lawupdate) + to_chat(user, span_warning("[src] is receiving laws remotely from a synced AI!")) + return + if(emagged) + to_chat(user, span_warning("The law interface glitches out!")) + emote("buzz") return if(!mind) //A player mind is required for law procs to run antag checks. - to_chat(user, "[src] is entirely unresponsive!") + to_chat(user, span_warning("[src] is entirely unresponsive!")) return MOD.install(laws, user) //Proc includes a success mesage so we don't need another one return - else if(istype(W, /obj/item/encryptionkey/) && opened) + if(istype(W, /obj/item/encryptionkey) && opened) if(radio)//sanityyyyyy radio.attackby(W,user)//GTFO, you have your own procs else - to_chat(user, "Unable to locate a radio!") + to_chat(user, span_warning("Unable to locate a radio!")) + return - else if (istype(W, /obj/item/card/id)||istype(W, /obj/item/pda)) // trying to unlock the interface with an ID card - if(emagged)//still allow them to open the cover - to_chat(user, "The interface seems slightly damaged.") + if (W.GetID()) // trying to unlock the interface with an ID card if(opened) - to_chat(user, "You must close the cover to swipe an ID card!") + to_chat(user, span_warning("You must close the cover to swipe an ID card!")) else if(allowed(usr)) locked = !locked - to_chat(user, "You [ locked ? "lock" : "unlock"] [src]'s cover.") + to_chat(user, span_notice("You [ locked ? "lock" : "unlock"] [src]'s cover.")) update_icons() + if(emagged) + to_chat(user, span_notice("The cover interface glitches out for a split second.")) + logevent("ChÃ¥vÃis cover lock has been [locked ? "engaged" : "released"]") //ChÃ¥vÃis: see above line + else + logevent("Chassis cover lock has been [locked ? "engaged" : "released"]") else - to_chat(user, "Access denied.") + to_chat(user, span_danger("Access denied.")) + return - else if(istype(W, /obj/item/borg/upgrade/)) + if(istype(W, /obj/item/borg/upgrade)) var/obj/item/borg/upgrade/U = W if(!opened) - to_chat(user, "You must access the borg's internals!") - else if(!src.module && U.require_module) - to_chat(user, "The borg must choose a module before it can be upgraded!") - else if(U.locked) - to_chat(user, "The upgrade is locked and cannot be used yet!") - else - if(!user.temporarilyRemoveItemFromInventory(U)) - return - if(U.action(src)) - to_chat(user, "You apply the upgrade to [src].") - if(U.one_use) - U.afterInstall(src) - qdel(U) - else - U.forceMove(src) - upgrades += U - U.afterInstall(src) - else - to_chat(user, "Upgrade error.") - U.forceMove(drop_location()) + to_chat(user, span_warning("You must access the cyborg's internals!")) + return + if(!module && U.require_module) + to_chat(user, span_warning("The cyborg must choose a model before it can be upgraded!")) + return + if(U.locked) + to_chat(user, span_warning("The upgrade is locked and cannot be used yet!")) + return + if(!user.canUnEquip(U)) + to_chat(user, span_warning("The upgrade is stuck to you and you can't seem to let go of it!")) + return + apply_upgrade(U, user) + return - else if(istype(W, /obj/item/toner)) + if(istype(W, /obj/item/toner)) if(toner >= tonermax) - to_chat(user, "The toner level of [src] is at its highest level possible!") - else - if(!user.temporarilyRemoveItemFromInventory(W)) - return - toner = tonermax - qdel(W) - to_chat(user, "You fill the toner level of [src] to its max capacity.") - else - return ..() + to_chat(user, span_warning("The toner level of [src] is at its highest level possible!")) + return + if(!user.temporarilyRemoveItemFromInventory(W)) + return + toner = tonermax + qdel(W) + to_chat(user, span_notice("You fill the toner level of [src] to its max capacity.")) + return + + if(istype(W, /obj/item/flashlight)) + if(!opened) + to_chat(user, span_warning("You need to open the panel to repair the headlamp!")) + return + if(lamp_functional) + to_chat(user, span_warning("The headlamp is already functional!")) + return + if(!user.temporarilyRemoveItemFromInventory(W)) + to_chat(user, span_warning("[W] seems to be stuck to your hand. You'll have to find a different light.")) + return + lamp_functional = TRUE + qdel(W) + to_chat(user, span_notice("You replace the headlamp bulbs.")) + return + + return ..() /mob/living/silicon/robot/crowbar_act(mob/living/user, obj/item/I) //TODO: make fucking everything up there in that attackby() proc use the proper tool_act() procs. But honestly, who has time for that? 'cause I know for sure that you, the person reading this, sure as hell doesn't. var/validbreakout = FALSE @@ -1064,33 +1020,49 @@ *Checking Exited() to detect if a hat gets up and walks off. *Drones and pAIs might do this, after all. */ -/mob/living/silicon/robot/Exited(atom/A) - if(hat && hat == A) +/mob/living/silicon/robot/Exited(atom/movable/gone) + . = ..() + if(hat == gone) hat = null if(!QDELETED(src)) //Don't update icons if we are deleted. update_icons() - return ..() -///Use this to add upgrades to robots. It'll register signals for when the upgrade is moved or deleted, if not single use. -/mob/living/silicon/robot/proc/add_to_upgrades(obj/item/borg/upgrade/new_upgrade, mob/user) + if(gone == cell) + cell = null + + if(gone == mmi) + mmi = null + +///Called when a mob uses an upgrade on an open borg. Checks to make sure the upgrade can be applied +/mob/living/silicon/robot/proc/apply_upgrade(obj/item/borg/upgrade/new_upgrade, mob/user, admin_added) + if(!admin_added && isnull(user)) + return FALSE if(new_upgrade in upgrades) return FALSE - if(!user.temporarilyRemoveItemFromInventory(new_upgrade)) //calling the upgrade's dropped() proc /before/ we add action buttons + if(!admin_added && !user.temporarilyRemoveItemFromInventory(new_upgrade)) //calling the upgrade's dropped() proc /before/ we add action buttons return FALSE if(!new_upgrade.action(src, user)) - to_chat(user, "Upgrade error.") - new_upgrade.forceMove(loc) //gets lost otherwise + to_chat(user, span_danger("Upgrade error.")) + if(admin_added) + qdel(new_upgrade) + else + new_upgrade.forceMove(loc) //gets lost otherwise return FALSE - to_chat(user, "You apply the upgrade to [src].") + to_chat(user, span_notice("You apply the upgrade to [src].")) + add_to_upgrades(new_upgrade) + return TRUE + +///Moves the upgrade inside the robot and registers relevant signals. +/mob/living/silicon/robot/proc/add_to_upgrades(obj/item/borg/upgrade/new_upgrade) to_chat(src, "----------------\nNew hardware detected...Identified as \"[new_upgrade]\"...Setup complete.\n----------------") if(new_upgrade.one_use) logevent("Firmware [new_upgrade] run successfully.") qdel(new_upgrade) - return FALSE + return upgrades += new_upgrade new_upgrade.forceMove(src) - RegisterSignal(new_upgrade, COMSIG_MOVABLE_MOVED, .proc/remove_from_upgrades) - RegisterSignal(new_upgrade, COMSIG_PARENT_QDELETING, .proc/on_upgrade_deleted) + RegisterSignal(new_upgrade, COMSIG_MOVABLE_MOVED, PROC_REF(remove_from_upgrades)) + RegisterSignal(new_upgrade, COMSIG_PARENT_QDELETING, PROC_REF(on_upgrade_deleted)) logevent("Hardware [new_upgrade] installed successfully.") ///Called when an upgrade is moved outside the robot. So don't call this directly, use forceMove etc. @@ -1117,15 +1089,17 @@ * * board - B.O.R.I.S. module board used for transforming the cyborg into AI shell */ /mob/living/silicon/robot/proc/make_shell(obj/item/borg/upgrade/ai/board) - if(!board) - upgrades |= new /obj/item/borg/upgrade/ai(src) + if(isnull(board)) + stack_trace("make_shell was called without a board argument! This is never supposed to happen!") + return FALSE + shell = TRUE braintype = "AI Shell" name = "Empty AI Shell-[ident]" real_name = name GLOB.available_ai_shells |= src if(!QDELETED(builtInCamera)) - builtInCamera.c_tag = real_name //update the camera name too + builtInCamera.c_tag = real_name //update the camera name too diag_hud_set_aishell() notify_ai(AI_SHELL) diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index d5a1058a61..f8217945db 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -94,6 +94,76 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real apply_status_effect(/datum/status_effect/vtec_disabled, time) update_movespeed() +/mob/living/silicon/robot/welder_act(mob/living/user, obj/item/tool) + if(user.a_intent == INTENT_HARM) + return FALSE + . = TRUE + if (!getBruteLoss()) + to_chat(user, span_warning("[src] is already in good condition!")) + return + if (!tool.tool_start_check(user, amount=0)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away. + return + user.DelayNextAction(CLICK_CD_MELEE) + if(src == user) + to_chat(user, span_notice("You start fixing yourself...")) + if(!tool.use_tool(src, user, 50)) + return + adjustBruteLoss(-10) + else + to_chat(user, span_notice("You start fixing [src]...")) + if(!do_after(user, 3 SECONDS, target = src)) + return + adjustBruteLoss(-30) + updatehealth() + add_fingerprint(user) + visible_message(span_notice("[user] has fixed some of the dents on [src].")) + +/mob/living/silicon/robot/crowbar_act(mob/living/user, obj/item/tool) + . = TRUE + if(opened) + to_chat(user, span_notice("You close the cover.")) + opened = FALSE + update_icons() + else + if(locked) + to_chat(user, span_warning("The cover is locked and cannot be opened!")) + else + to_chat(user, span_notice("You open the cover.")) + opened = TRUE + update_icons() + + return TRUE + +/mob/living/silicon/robot/screwdriver_act(mob/living/user, obj/item/tool) + if(!opened) + return FALSE + . = TRUE + if(!cell) // haxing + wiresexposed = !wiresexposed + to_chat(user, span_notice("The wires have been [wiresexposed ? "exposed" : "unexposed"].")) + else // radio + if(shell) + to_chat(user, span_warning("You cannot seem to open the radio compartment!")) //Prevent AI radio key theft + else if(radio) + radio.screwdriver_act(user, tool) // Push it to the radio to let it handle everything + else + to_chat(user, span_warning("Unable to locate a radio!")) + update_icons() + +/mob/living/silicon/robot/wrench_act(mob/living/user, obj/item/tool) + if(!(opened && !cell)) // Deconstruction. The flashes break from the fall, to prevent this from being a ghetto reset module. + return FALSE + . = TRUE + if(!locked_down) + to_chat(user, span_boldannounce("[src]'s bolts spark! Maybe you should lock them down first!")) + spark_system.start() + return + to_chat(user, span_notice("You start to unfasten [src]'s securing bolts...")) + if(tool.use_tool(src, user, 5 SECONDS, volume = 50) && !cell) + user.visible_message(span_notice("[user] deconstructs [src]!"), span_notice("You unfasten the securing bolts, and [src] falls to pieces!")) + deconstruct() + return + /mob/living/silicon/robot/fire_act() if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them IgniteMob() diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 6faf8f0db5..4c8872ffbf 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -257,7 +257,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - summoner.health) / abs(HEALTH_THRESHOLD_DEAD - summoner.maxHealth)) * 100) else resulthealth = round((summoner.health / summoner.maxHealth) * 100, 0.5) - hud_used.healths.maptext = "
[resulthealth]%
" + hud_used.healths.maptext = MAPTEXT("
[resulthealth]%
") /mob/living/simple_animal/hostile/guardian/adjustHealth(amount, updating_health = TRUE, forced = FALSE) //The spirit is invincible, but passes on damage to the summoner . = amount diff --git a/code/modules/paperwork/ticketmachine.dm b/code/modules/paperwork/ticketmachine.dm index 9683601670..6022853fad 100644 --- a/code/modules/paperwork/ticketmachine.dm +++ b/code/modules/paperwork/ticketmachine.dm @@ -142,7 +142,7 @@ maptext_x = 10 if(100) maptext_x = 8 - maptext = "[current_number]" //Finally, apply the maptext + maptext = MAPTEXT("[current_number]") //Finally, apply the maptext /obj/machinery/ticket_machine/attackby(obj/item/I, mob/user, params) ..() @@ -182,11 +182,7 @@ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 100, FALSE) ticket_number ++ to_chat(user, "You take a ticket from [src], looks like you're ticket number #[ticket_number]...") - var/obj/item/ticket_machine_ticket/theirticket = new /obj/item/ticket_machine_ticket(get_turf(src)) - theirticket.name = "Ticket #[ticket_number]" - theirticket.maptext = "[ticket_number]" - theirticket.saved_maptext = "[ticket_number]" - theirticket.ticket_number = ticket_number + var/obj/item/ticket_machine_ticket/theirticket = new /obj/item/ticket_machine_ticket(get_turf(src), ticket_number) theirticket.source = src theirticket.owner = user user.put_in_hands(theirticket) @@ -211,10 +207,25 @@ w_class = WEIGHT_CLASS_TINY resistance_flags = FLAMMABLE max_integrity = 50 + var/number var/saved_maptext = null var/mob/living/carbon/owner var/obj/machinery/ticket_machine/source - var/ticket_number + +/obj/item/ticket_machine_ticket/Initialize(mapload, num) + . = ..() + number = num + if(!isnull(num)) + name += " #[num]" + saved_maptext = MAPTEXT(num) + maptext = saved_maptext + +/obj/item/ticket_machine_ticket/examine(mob/user) + . = ..() + if(!isnull(number)) + . += span_notice("The ticket reads shimmering text that tells you that you are number [number] in queue.") + if(source) + . += span_notice("Below that, you can see that you are [number - source.current_number] spot\s away from being served.") /obj/item/ticket_machine_ticket/attack_hand(mob/user) . = ..() @@ -233,7 +244,7 @@ /obj/item/ticket_machine_ticket/Destroy() if(owner && source) source.ticket_holders -= owner - source.tickets[ticket_number] = null + source.tickets[number] = null owner = null source = null return ..() diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 5fd158c028..9c9ccd2b8d 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -57,25 +57,24 @@ . = ..() if(max_mod_capacity) . += "[get_remaining_mod_capacity()]% mod capacity remaining." - for(var/A in get_modkits()) - var/obj/item/borg/upgrade/modkit/M = A + for(var/obj/item/borg/upgrade/modkit/M in modkits) . += "There is \a [M] installed, using [M.cost]% capacity." /obj/item/gun/energy/kinetic_accelerator/crowbar_act(mob/living/user, obj/item/I) . = TRUE if(modkits.len) - to_chat(user, "You pry the modifications out.") + to_chat(user, span_notice("You pry all the modifications out.")) I.play_tool_sound(src, 100) for(var/obj/item/borg/upgrade/modkit/M in modkits) - M.uninstall(src) + M.forceMove(drop_location()) //uninstallation handled in Exited(), or /mob/living/silicon/robot/remove_from_upgrades() for borgs else - to_chat(user, "There are no modifications currently installed.") + to_chat(user, span_notice("There are no modifications currently installed.")) -/obj/item/gun/energy/kinetic_accelerator/Exited(atom/movable/AM) - . = ..() - if((AM in modkits) && istype(AM, /obj/item/borg/upgrade/modkit)) - var/obj/item/borg/upgrade/modkit/M = AM - M.uninstall(src, FALSE) +/obj/item/gun/energy/kinetic_accelerator/Exited(atom/movable/gone) + if(gone in modkits) + var/obj/item/borg/upgrade/modkit/MK = gone + MK.uninstall(src) + return ..() /obj/item/gun/energy/kinetic_accelerator/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/borg/upgrade/modkit)) @@ -86,20 +85,13 @@ /obj/item/gun/energy/kinetic_accelerator/proc/get_remaining_mod_capacity() var/current_capacity_used = 0 - for(var/A in get_modkits()) - var/obj/item/borg/upgrade/modkit/M = A + for(var/obj/item/borg/upgrade/modkit/M in modkits) current_capacity_used += M.cost return max_mod_capacity - current_capacity_used -/obj/item/gun/energy/kinetic_accelerator/proc/get_modkits() - . = list() - for(var/A in modkits) - . += A - /obj/item/gun/energy/kinetic_accelerator/proc/modify_projectile(obj/item/projectile/kinetic/K) K.kinetic_gun = src //do something special on-hit, easy! - for(var/A in get_modkits()) - var/obj/item/borg/upgrade/modkit/M = A + for(var/obj/item/borg/upgrade/modkit/M in modkits) M.modify_projectile(K) /obj/item/gun/energy/kinetic_accelerator/cyborg @@ -259,7 +251,7 @@ if(!target_turf) target_turf = get_turf(src) if(kinetic_gun) //hopefully whoever shot this was not very, very unfortunate. - var/list/mods = kinetic_gun.get_modkits() + var/list/mods = kinetic_gun.modkits for(var/obj/item/borg/upgrade/modkit/M in mods) M.projectile_strike_predamage(src, target_turf, target, kinetic_gun) for(var/obj/item/borg/upgrade/modkit/M in mods) @@ -278,7 +270,7 @@ icon = 'icons/obj/objects.dmi' icon_state = "modkit" w_class = WEIGHT_CLASS_SMALL - require_module = 1 + require_module = TRUE module_type = list(/obj/item/robot_module/miner) module_flags = BORG_MODULE_MINER var/denied_type = null @@ -298,26 +290,24 @@ else ..() -/obj/item/borg/upgrade/modkit/afterInstall(mob/living/silicon/robot/R) - for(var/obj/item/gun/energy/kinetic_accelerator/H in R.module.modules) - if(install(H, R)) //It worked - return - to_chat(R, "Upgrade error - Aborting Kinetic Accelerator linking.") //No applicable KA found, insufficient capacity, or some other problem. +/obj/item/borg/upgrade/modkit/action(mob/living/silicon/robot/R) + . = ..() + if (.) + for(var/obj/item/gun/energy/kinetic_accelerator/H in R.module.modules) + return install(H, usr, FALSE) -/obj/item/borg/upgrade/modkit/proc/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user) +/obj/item/borg/upgrade/modkit/proc/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user, transfer_to_loc = TRUE) . = TRUE - if(src in KA.modkits) // Sanity check to prevent installing the same modkit twice thanks to occasional click/lag delays. - return FALSE if(minebot_upgrade) if(minebot_exclusive && !istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone)) - to_chat(user, "The modkit you're trying to install is only rated for minebot use.") + to_chat(user, span_notice("The modkit you're trying to install is only rated for minebot use.")) return FALSE else if(istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone)) - to_chat(user, "The modkit you're trying to install is not rated for minebot use.") + to_chat(user, span_notice("The modkit you're trying to install is not rated for minebot use.")) return FALSE if(denied_type) var/number_of_denied = 0 - for(var/A in KA.get_modkits()) + for(var/A in KA.modkits) var/obj/item/borg/upgrade/modkit/M = A if(istype(M, denied_type)) number_of_denied++ @@ -326,21 +316,25 @@ break if(KA.get_remaining_mod_capacity() >= cost) if(.) - if(!user.transferItemToLoc(src, KA)) - return FALSE - to_chat(user, "You install the modkit.") - playsound(loc, 'sound/items/screwdriver.ogg', 100, 1) + if(transfer_to_loc && !user.transferItemToLoc(src, KA)) + return + to_chat(user, span_notice("You install the modkit.")) + playsound(loc, 'sound/items/screwdriver.ogg', 100, TRUE) KA.modkits += src else - to_chat(user, "The modkit you're trying to install would conflict with an already installed modkit. Use a crowbar to remove existing modkits.") + to_chat(user, span_notice("The modkit you're trying to install would conflict with an already installed modkit. Use a crowbar to remove existing modkits.")) else - to_chat(user, "You don't have room([KA.get_remaining_mod_capacity()]% remaining, [cost]% needed) to install this modkit. Use a crowbar to remove existing modkits.") + to_chat(user, span_notice("You don't have room([KA.get_remaining_mod_capacity()]% remaining, [cost]% needed) to install this modkit. Use a crowbar to remove existing modkits.")) . = FALSE -/obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/gun/energy/kinetic_accelerator/KA, forcemove = TRUE) +/obj/item/borg/upgrade/modkit/deactivate(mob/living/silicon/robot/R, user = usr) + . = ..() + if (.) + for(var/obj/item/gun/energy/kinetic_accelerator/KA in R.module.modules) + uninstall(KA) + +/obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/gun/energy/kinetic_accelerator/KA) KA.modkits -= src - if(forcemove) - forceMove(get_turf(KA)) /obj/item/borg/upgrade/modkit/proc/modify_projectile(obj/item/projectile/kinetic/K) @@ -467,6 +461,7 @@ /obj/item/borg/upgrade/modkit/minebot_passthrough name = "minebot passthrough" desc = "Causes kinetic accelerator shots to pass through minebots." + denied_type = /obj/item/borg/upgrade/modkit/minebot_passthrough // If you have something cost zero, you can keep adding forever, why cost = 0 //Tendril-unique modules diff --git a/tgui/packages/tgui-panel/chat/renderer.js b/tgui/packages/tgui-panel/chat/renderer.js index 32a9b74ed0..495ed32228 100644 --- a/tgui/packages/tgui-panel/chat/renderer.js +++ b/tgui/packages/tgui-panel/chat/renderer.js @@ -443,7 +443,9 @@ class ChatRenderer { const cssRules = styleSheets[i].cssRules; for (let i = 0; i < cssRules.length; i++) { const rule = cssRules[i]; - cssText += rule.cssText + '\n'; + if (rule && typeof rule.cssText === 'string') { + cssText += rule.cssText + '\n'; + } } } cssText += 'body, html { background-color: #141414 }\n'; diff --git a/tgui/packages/tgui/interfaces/BorgPanel.js b/tgui/packages/tgui/interfaces/BorgPanel.js index 40d612679f..d92b7dd408 100644 --- a/tgui/packages/tgui/interfaces/BorgPanel.js +++ b/tgui/packages/tgui/interfaces/BorgPanel.js @@ -1,5 +1,5 @@ import { useBackend } from '../backend'; -import { Box, Button, LabeledList, ProgressBar, Section } from '../components'; +import { Box, Button, Icon, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; export const BorgPanel = (props, context) => { @@ -12,6 +12,9 @@ export const BorgPanel = (props, context) => { const upgrades = data.upgrades || []; const ais = data.ais || []; const laws = data.laws || []; + + const active_upgrades = data.active_upgrades || []; + const ka_remaining_capacity = data.ka_remaining_capacity || 0; return ( { ))} - {upgrades.map(upgrade => ( -