diff --git a/_maps/map_files/NebulaStation/NebulaStation.dmm b/_maps/map_files/NebulaStation/NebulaStation.dmm index c91976bafe3..6675af3f50e 100644 --- a/_maps/map_files/NebulaStation/NebulaStation.dmm +++ b/_maps/map_files/NebulaStation/NebulaStation.dmm @@ -140143,7 +140143,7 @@ /area/station/service/theater) "uQm" = ( /obj/structure/mop_bucket, -/obj/item/mop/cyborg, +/obj/item/mop, /obj/effect/turf_decal/siding/thinplating_new/dark{ dir = 1 }, diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index 762126c3da7..bd374ac0a67 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -24,7 +24,6 @@ /// cannot be removed without admin intervention #define ROUNDSTART_TRAIT "roundstart" #define JOB_TRAIT "job" -#define CYBORG_ITEM_TRAIT "cyborg-item" /// Any traits granted by quirks. #define QUIRK_TRAIT "quirk_trait" /// (B)admins only. diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index ac819b61ce6..698a1372284 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -63,7 +63,6 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( var/atom/movable/screen/sleep_icon var/atom/movable/screen/throw_icon var/atom/movable/screen/resist_icon - var/atom/movable/screen/module_store_icon var/atom/movable/screen/floor_change var/list/static_inventory = list() //the screen objects which are static @@ -252,7 +251,6 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( QDEL_NULL(listed_actions) QDEL_LIST(floating_actions) - QDEL_NULL(module_store_icon) QDEL_LIST(static_inventory) // all already deleted by static inventory clear @@ -459,12 +457,6 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( var/mob/screenmob = viewmob || mymob hidden_inventory_update(screenmob) -/datum/hud/robot/show_hud(version = 0, mob/viewmob) - . = ..() - if(!.) - return - update_robot_modules_display() - /* BUBBER EDIT REMOVAL - We use a different lobby hud /datum/hud/new_player/show_hud(version = 0, mob/viewmob) . = ..() diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index 35319bc89ed..cfdd235a503 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -8,16 +8,21 @@ /atom/movable/screen/robot/Click() if(isobserver(usr)) - return 1 + return TRUE /atom/movable/screen/robot/module/Click() - if(..()) + //observers can look at borg's inventories + var/mob/living/silicon/robot/robot_owner = hud.mymob + if(robot_owner.model.type != /obj/item/robot_model) + if(usr.active_storage == robot_owner.model.atom_storage) + robot_owner.model.atom_storage.hide_contents(usr) + else + robot_owner.model.atom_storage.open_storage(usr) + return TRUE + . = ..() + if(.) return - var/mob/living/silicon/robot/R = usr - if(R.model.type != /obj/item/robot_model) - R.hud_used.toggle_show_robot_modules() - return 1 - R.pick_model() + robot_owner.pick_model() /atom/movable/screen/robot/module1 name = "module1" @@ -62,6 +67,7 @@ /atom/movable/screen/robot/store name = "store" icon_state = "store" + screen_loc = ui_borg_store /atom/movable/screen/robot/store/Click() if(..()) @@ -160,10 +166,6 @@ robit.hands.screen_loc = ui_borg_module static_inventory += robit.hands -//Store - module_store_icon = new /atom/movable/screen/robot/store(null, src) - module_store_icon.screen_loc = ui_borg_store - pull_icon = new /atom/movable/screen/pull(null, src) pull_icon.icon = 'icons/hud/screen_cyborg.dmi' pull_icon.screen_loc = ui_borg_pull @@ -175,74 +177,6 @@ zone_select.update_appearance() static_inventory += zone_select -/datum/hud/proc/toggle_show_robot_modules() - if(!iscyborg(mymob)) - return - - var/mob/living/silicon/robot/R = mymob - - R.shown_robot_modules = !R.shown_robot_modules - update_robot_modules_display() - -/datum/hud/proc/update_robot_modules_display(mob/viewer) - if(!iscyborg(mymob)) - return - - var/mob/living/silicon/robot/R = mymob - - var/mob/screenmob = viewer || R - - if(!R.model) - return - - if(!R.client) - return - - //Module is not currently active - screenmob.client.screen -= R.model.get_inactive_modules() - - if(!R.shown_robot_modules || !screenmob.hud_used.hud_shown) - //Modules display is hidden - screenmob.client.screen -= module_store_icon //"store" icon - - R.shown_robot_modules = 0 - screenmob.client.screen -= R.robot_modules_background - return - - //Modules display is shown - screenmob.client.screen += module_store_icon //"store" icon - - if(!R.model.modules) - to_chat(usr, span_warning("Selected model has no modules to select!")) - return - - if(!R.robot_modules_background) - return - - var/list/usable_modules = R.model.get_usable_modules() - - var/display_rows = max(CEILING(length(usable_modules) / 8, 1),1) - R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7" - screenmob.client.screen += R.robot_modules_background - - for(var/i in 1 to length(usable_modules)) - var/atom/movable/A = usable_modules[i] - if(A in R.held_items) - //Module is currently active - continue - - // Arrange in a grid x=-4 to 3 and y=1 to display_rows - var/x = (i - 1) % 8 - 4 - var/y = floor((i - 1) / 8) + 1 - - screenmob.client.screen += A - if(x < 0) - A.screen_loc = "CENTER[x]:16,SOUTH+[y]:7" - else - A.screen_loc = "CENTER+[x]:16,SOUTH+[y]:7" - SET_PLANE_IMPLICIT(A, ABOVE_HUD_PLANE) - - /datum/hud/robot/persistent_inventory_update(mob/viewer) if(!mymob) return diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index 32a91bf609c..0f5b2b4deb7 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -23,6 +23,8 @@ /// List of all the mobs currently viewing the contents of this storage. VAR_PRIVATE/list/mob/is_using = list() + ///The type of storage interface this datum uses. + var/datum/storage_interface/storage_type = /datum/storage_interface /// Associated list that keeps track of all storage UI datums per person. VAR_PRIVATE/list/datum/storage_interface/storage_interfaces = null @@ -860,9 +862,6 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /// Called directly from the attack chain if [insert_on_attack] is TRUE. /// Handles inserting an item into the storage when clicked. /datum/storage/proc/item_interact_insert(mob/living/user, obj/item/thing) - if(iscyborg(user)) - return ITEM_INTERACT_BLOCKING - attempt_insert(thing, user) return ITEM_INTERACT_SUCCESS @@ -1041,7 +1040,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) var/ui_style = ui_style2icon(to_show.client?.prefs?.read_preference(/datum/preference/choiced/ui_style)) if (isnull(storage_interfaces[to_show])) - storage_interfaces[to_show] = new /datum/storage_interface(ui_style, src) + storage_interfaces[to_show] = new storage_type(ui_style, src, to_show) orient_storage() diff --git a/code/datums/storage/storage_interface.dm b/code/datums/storage/storage_interface.dm index 3381106ee68..6f0543e4e5a 100644 --- a/code/datums/storage/storage_interface.dm +++ b/code/datums/storage/storage_interface.dm @@ -13,25 +13,27 @@ /// Storage that owns us var/datum/storage/parent_storage -/datum/storage_interface/New(ui_style, parent_storage) +/datum/storage_interface/New(ui_style, datum/storage/parent_storage, mob/user) ..() src.parent_storage = parent_storage - closer = new(null, null, parent_storage) - cells = new(null, null, parent_storage) - corner_top_left = new(null, null, parent_storage) - corner_top_right = new(null, null, parent_storage) - corner_bottom_left = new(null, null, parent_storage) - corner_bottom_right = new(null, null, parent_storage) - rowjoin_left = new(null, null, parent_storage) - rowjoin_right = new(null, null, parent_storage) - for (var/atom/movable/screen/ui_elem as anything in list_ui_elements()) + var/datum/hud/owner_hud = user.hud_used + closer = new(null, owner_hud, parent_storage) + cells = new(null, owner_hud, parent_storage) + corner_top_left = new(null, owner_hud, parent_storage) + corner_top_right = new(null, owner_hud, parent_storage) + corner_bottom_left = new(null, owner_hud, parent_storage) + corner_bottom_right = new(null, owner_hud, parent_storage) + rowjoin_left = new(null, owner_hud, parent_storage) + rowjoin_right = new(null, owner_hud, parent_storage) + for (var/atom/movable/screen/ui_elem as anything in list_ui_elements(initializing = TRUE)) ui_elem.icon = ui_style /// Returns all UI elements under this theme -/datum/storage_interface/proc/list_ui_elements() +/datum/storage_interface/proc/list_ui_elements(initializing = FALSE) return list(cells, corner_top_left, corner_top_right, corner_bottom_left, corner_bottom_right, rowjoin_left, rowjoin_right, closer) /datum/storage_interface/Destroy(force) + QDEL_NULL(closer) QDEL_NULL(cells) QDEL_NULL(corner_top_left) QDEL_NULL(corner_top_right) @@ -81,6 +83,20 @@ closer.screen_loc = "[screen_start_x + columns]:[screen_pixel_x - 5],[screen_start_y]:[screen_pixel_y]" + add_items(arglist(args)) + +/datum/storage_interface/proc/add_items( + screen_start_x, + screen_pixel_x, + screen_start_y, + screen_pixel_y, + columns, + rows, + mob/user_looking, + atom/real_location, + list/datum/numbered_display/numbered_contents, +) + var/current_x = screen_start_x var/current_y = screen_start_y var/turf/our_turf = get_turf(real_location) @@ -107,3 +123,67 @@ current_y++ if(current_y - screen_start_y >= rows) break + +///Silicon subtype of storage interface used by their model storage. +/datum/storage_interface/silicon + var/atom/movable/screen/robot/store/store + var/obj/item/robot_model/robot_model + +/datum/storage_interface/silicon/New(ui_style, datum/storage/parent_storage, mob/user) + . = ..() + robot_model = parent_storage.real_location + if(iscyborg(user)) + store = new(null, user.hud_used) + +/datum/storage_interface/silicon/Destroy(force) + QDEL_NULL(store) + return ..() + +/datum/storage_interface/silicon/list_ui_elements(initializing = FALSE) + if(initializing || isnull(store)) + return ..() + //we're purposely excluding 'store' from having its icon changed from initialization. + return ..() + store + +/datum/storage_interface/silicon/add_items( + screen_start_x, + screen_pixel_x, + screen_start_y, + screen_pixel_y, + columns, + rows, + mob/user_looking, + atom/real_location, + list/datum/numbered_display/numbered_contents, +) + var/list/usable_modules = robot_model.get_usable_modules() + + var/current_x = screen_start_x + var/current_y = screen_start_y + var/turf/our_turf = get_turf(real_location) + + for(var/i in 1 to length(usable_modules)) + var/atom/movable/item = usable_modules[i] + if(item in robot_model.robot.held_items) + current_x++ + if(current_x - screen_start_x < columns) + continue + current_x = screen_start_x + + current_y++ + if(current_y - screen_start_y >= rows) + break + //Module is currently active + continue + + item.mouse_opacity = MOUSE_OPACITY_OPAQUE + SET_PLANE(item, ABOVE_HUD_PLANE, our_turf) + item.screen_loc = "[current_x]:[screen_pixel_x],[current_y]:[screen_pixel_y]" + + current_x++ + if(current_x - screen_start_x < columns) + continue + current_x = screen_start_x + current_y++ + if(current_y - screen_start_y >= rows) + break diff --git a/code/datums/storage/subtypes/cyborg.dm b/code/datums/storage/subtypes/cyborg.dm new file mode 100644 index 00000000000..9b77b6c344e --- /dev/null +++ b/code/datums/storage/subtypes/cyborg.dm @@ -0,0 +1,50 @@ +/datum/storage/cyborg_internal_storage + allow_big_nesting = TRUE + max_slots = 99 + max_specific_storage = WEIGHT_CLASS_GIGANTIC + max_total_storage = 99 + do_rustle = FALSE + silent = TRUE + screen_max_columns = 8 + storage_type = /datum/storage_interface/silicon + +/datum/storage/cyborg_internal_storage/can_insert(obj/item/to_insert, mob/living/silicon/robot/user, messages = TRUE, force = STORAGE_NOT_LOCKED) + return (to_insert in user.model.modules) + +/datum/storage/cyborg_internal_storage/attempt_insert(obj/item/to_insert, mob/living/silicon/robot/user, override = FALSE, force = STORAGE_NOT_LOCKED, messages = TRUE) + user.deactivate_module(to_insert) + +/** + * Cyborg internal storage orienting + * We're using the model's total amount of modules as reference for how many slots we fill, + * otherwise having enough items in hand and only 1 item in a row would mean, as we're a static inventory, + * the rows won't fill for all items in the UI. + * We also don't give an additional row if all slots are filled because as a static inventory borgs don't need extra space + * to put items in, you can click on the slot you took it out from, or use the dedicated "store" button. + */ +/datum/storage/cyborg_internal_storage/orient_storage() + var/obj/item/robot_model/model = real_location + + var/adjusted_contents = length(model.modules) + var/list/datum/numbered_display/numbered_contents + if(numerical_stacking) + numbered_contents = process_numerical_display() + adjusted_contents = length(numbered_contents) + + var/columns = clamp(max_slots, 1, screen_max_columns) + var/rows = clamp(CEILING(adjusted_contents / columns, 1), 1, screen_max_rows) + + for (var/mob/ui_user as anything in storage_interfaces) + if (isnull(storage_interfaces[ui_user])) + continue + storage_interfaces[ui_user].update_position( + screen_start_x, + screen_pixel_x, + screen_start_y, + screen_pixel_y, + columns, + rows, + ui_user, + real_location, + numbered_contents, + ) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6548001e09c..0bd8a66511e 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -668,15 +668,12 @@ return attack_paw(ayy, modifiers) -/obj/item/attack_ai(mob/user) - if(istype(src.loc, /obj/item/robot_model)) - //If the item is part of a cyborg module, equip it - if(!iscyborg(user)) - return - var/mob/living/silicon/robot/R = user - if(!R.low_power_mode) //can't equip modules with an empty cell. - R.activate_module(src) - R.hud_used.update_robot_modules_display() +/obj/item/attack_robot(mob/living/silicon/robot/user) + if(!istype(loc, /obj/item/robot_model)) + return + if(user.low_power_mode) //can't equip modules with an empty cell. + return + user.activate_module(src) // afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency diff --git a/code/game/objects/items/broom.dm b/code/game/objects/items/broom.dm index a48dfa1b94c..970bb5a5526 100644 --- a/code/game/objects/items/broom.dm +++ b/code/game/objects/items/broom.dm @@ -105,11 +105,4 @@ playsound(current_item_loc, 'sound/items/weapons/thudswoosh.ogg', 30, TRUE, -1) -/obj/item/pushbroom/cyborg - name = "cyborg push broom" - -/obj/item/pushbroom/cyborg/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT) - #undef BROOM_PUSH_LIMIT diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm index 1870b6dd2ba..1c886ea10e6 100644 --- a/code/game/objects/items/clown_items.dm +++ b/code/game/objects/items/clown_items.dm @@ -71,8 +71,6 @@ cleanspeed = 2.8 SECONDS //janitor gets this uses = 300 -/obj/item/soap/nanotrasen/cyborg - /obj/item/soap/deluxe desc = "A deluxe Waffle Corporation brand bar of soap. Smells of high-class luxury." grind_results = list(/datum/reagent/consumable/aloejuice = 10, /datum/reagent/lye = 10) @@ -153,6 +151,9 @@ to_chat(user, span_warning("[src] crumbles into tiny bits!")) qdel(src) +/obj/item/soap/nanotrasen/cyborg + name = "built-in soap" + /obj/item/soap/nanotrasen/cyborg/noUses(mob/user) to_chat(user, span_warning("[src] has ran out of chemicals! Head to a recharger to refill it.")) diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 2f9c82cea1e..f1a3854fb88 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -421,14 +421,14 @@ return ..() /obj/item/shockpaddles/dropped(mob/user) - . = ..() + if(!req_defib) + return ..() UnregisterSignal(defib, COMSIG_MOVABLE_MOVED) if(user) UnregisterSignal(user, COMSIG_MOVABLE_MOVED) - if(req_defib) - if(user) - to_chat(user, span_notice("The paddles snap back into the main unit.")) - snap_back() + to_chat(user, span_notice("The paddles snap back into the main unit.")) + snap_back() + return ..() /obj/item/shockpaddles/proc/snap_back() if(!defib) diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm index 8103fb491cb..ba2577b6479 100644 --- a/code/game/objects/items/devices/gps.dm +++ b/code/game/objects/items/devices/gps.dm @@ -42,10 +42,6 @@ gpstag = "BORG0" desc = "A mining cyborg internal positioning system. Used as a recovery beacon for damaged cyborg assets, or a collaboration tool for mining teams." -/obj/item/gps/cyborg/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT) - /obj/item/gps/mining/internal icon_state = "gps-m" gpstag = "MINER" diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index dceece6fac9..ab35b3c08fe 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -317,11 +317,7 @@ return TRUE -/obj/item/lightreplacer/cyborg/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT) - -/obj/item/lightreplacer/cyborg/advanced +/obj/item/lightreplacer/advanced name = "high capacity light replacer" desc = "A higher capacity light replacer. Refill with broken or working lightbulbs, or sheets of glass." icon_state = "lightreplacer_high" diff --git a/code/game/objects/items/devices/scanners/t_scanner.dm b/code/game/objects/items/devices/scanners/t_scanner.dm index 931b69bb7bd..0e8e2c44182 100644 --- a/code/game/objects/items/devices/scanners/t_scanner.dm +++ b/code/game/objects/items/devices/scanners/t_scanner.dm @@ -13,8 +13,6 @@ custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT * 1.5) /// Is this T-Ray scanner currently on? var/on = FALSE - /// Will this T-Ray scanner shut off on de-equip? (Cyborgs only) - var/shut_off_on_unequip = TRUE /obj/item/t_scanner/suicide_act(mob/living/carbon/user) user.visible_message(span_suicide("[user] begins to emit terahertz-rays into [user.p_their()] brain with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) @@ -33,8 +31,6 @@ toggle_on() /obj/item/t_scanner/cyborg_unequip(mob/user) - if(!shut_off_on_unequip) - return if(!on) return toggle_on() diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm index beb701facc5..81d3c438ef5 100644 --- a/code/game/objects/items/mop.dm +++ b/code/game/objects/items/mop.dm @@ -20,7 +20,6 @@ var/max_reagent_volume = 50 // SKYRAT EDIT - ORIGINAL: 15 var/mopspeed = 1.5 SECONDS force_string = "robust... against germs" - var/insertable = TRUE var/static/list/clean_blacklist = typecacheof(list( /obj/item/reagent_containers/cup/bucket, /obj/structure/mop_bucket, @@ -72,10 +71,6 @@ val2remove = round(cleaner.mind.get_skill_modifier(/datum/skill/cleaning, SKILL_SPEED_MODIFIER), 0.1) reagents.remove_all(val2remove) //reaction() doesn't use up the reagents -/obj/item/mop/cyborg/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT) - /obj/item/mop/advanced desc = "The most advanced tool in a custodian's arsenal, complete with a condenser for self-wetting! Just think of all the viscera you will clean up with this! Due to the self-wetting technology, it proves very inefficient for cleaning up spills." //SKYRAT EDIT name = "advanced mop" @@ -118,6 +113,3 @@ /obj/item/mop/advanced/Destroy() STOP_PROCESSING(SSobj, src) return ..() - -/obj/item/mop/advanced/cyborg - insertable = FALSE diff --git a/code/game/objects/items/rcd/RPD.dm b/code/game/objects/items/rcd/RPD.dm index d78a56d173c..e5ff17bccca 100644 --- a/code/game/objects/items/rcd/RPD.dm +++ b/code/game/objects/items/rcd/RPD.dm @@ -122,10 +122,6 @@ UnregisterSignal(user, COMSIG_MOUSE_SCROLL_ON) return ..() -/obj/item/pipe_dispenser/cyborg_unequip(mob/user) - UnregisterSignal(user, COMSIG_MOUSE_SCROLL_ON) - return ..() - /obj/item/pipe_dispenser/attack_self(mob/user) ui_interact(user) diff --git a/code/game/objects/items/rcd/RPLD.dm b/code/game/objects/items/rcd/RPLD.dm index 892e0af2d8f..6522e13e358 100644 --- a/code/game/objects/items/rcd/RPLD.dm +++ b/code/game/objects/items/rcd/RPLD.dm @@ -99,10 +99,6 @@ UnregisterSignal(user, COMSIG_MOUSE_SCROLL_ON) return ..() -/obj/item/construction/plumbing/cyborg_unequip(mob/user) - UnregisterSignal(user, COMSIG_MOUSE_SCROLL_ON) - return ..() - /obj/item/construction/plumbing/attack_self(mob/user) . = ..() ui_interact(user) diff --git a/code/game/objects/items/robot/items/food.dm b/code/game/objects/items/robot/items/food.dm index d49991511a2..d72f84cb4d7 100644 --- a/code/game/objects/items/robot/items/food.dm +++ b/code/game/objects/items/robot/items/food.dm @@ -290,7 +290,3 @@ /obj/item/borg/cookbook/dropped(mob/user, silent) SStgui.close_uis(cooking) return ..() - -/obj/item/borg/cookbook/cyborg_unequip(mob/user) - SStgui.close_uis(cooking) - return ..() diff --git a/code/game/objects/items/robot/items/hud.dm b/code/game/objects/items/robot/items/hud.dm index 7ee8a938625..f2d46d29585 100644 --- a/code/game/objects/items/robot/items/hud.dm +++ b/code/game/objects/items/robot/items/hud.dm @@ -1,6 +1,21 @@ /obj/item/borg/sight - var/sight_mode = null icon = 'icons/obj/clothing/glasses.dmi' + ///Define to a sight mode that we give to a cyborg while this item is equipped. + var/sight_mode = null + +/obj/item/borg/sight/equipped(mob/living/silicon/robot/user, slot, initial = FALSE) + . = ..() + if(!iscyborg(user)) + return . + user.sight_mode |= sight_mode + user.update_sight() + +/obj/item/borg/sight/dropped(mob/living/silicon/robot/user, silent) + if(!iscyborg(user)) + return ..() + user.sight_mode &= ~sight_mode + user.update_sight() + return ..() /obj/item/borg/sight/xray name = "\proper X-ray vision" diff --git a/code/game/objects/items/robot/items/tools.dm b/code/game/objects/items/robot/items/tools.dm index 0cf8a7522a8..6c8e124a47d 100644 --- a/code/game/objects/items/robot/items/tools.dm +++ b/code/game/objects/items/robot/items/tools.dm @@ -114,11 +114,11 @@ return host.loc return null -/obj/item/borg/projectile_dampen/dropped() +/obj/item/borg/projectile_dampen/equipped() host = loc return ..() -/obj/item/borg/projectile_dampen/equipped() +/obj/item/borg/projectile_dampen/dropped() host = loc return ..() @@ -228,7 +228,8 @@ //if all else fails just make a new one from scratch tool = new reference(user) - ADD_TRAIT(tool, TRAIT_NODROP, CYBORG_ITEM_TRAIT) + //the internal tool is considered part of the tool itself. + tool.item_flags |= ABSTRACT atoms[reference] = tool return tool diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 197c15ad2e3..e7aebaddeff 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -67,7 +67,7 @@ for(var/item_to_remove in items) var/obj/item/module_item = locate(item_to_remove) in borg.model.modules if (module_item) - borg.model.remove_module(module_item, TRUE) + borg.model.remove_module(module_item) return TRUE /obj/item/borg/upgrade/rename @@ -162,8 +162,8 @@ model_type = list(/obj/item/robot_model/miner) model_flags = BORG_MODEL_MINER - items_to_add = list(/obj/item/pickaxe/drill/cyborg/diamond) - items_to_remove = list(/obj/item/pickaxe/drill/cyborg, /obj/item/shovel) + items_to_add = list(/obj/item/pickaxe/drill/diamonddrill) + items_to_remove = list(/obj/item/pickaxe/drill, /obj/item/shovel) /obj/item/borg/upgrade/soh name = "mining cyborg satchel of holding" @@ -185,7 +185,7 @@ model_flags = BORG_MODEL_JANITOR items_to_add = list(/obj/item/storage/bag/trash/bluespace/cyborg) - items_to_remove = list(/obj/item/storage/bag/trash/cyborg) + items_to_remove = list(/obj/item/storage/bag/trash) /obj/item/borg/upgrade/amop name = "janitor cyborg advanced mop" @@ -195,8 +195,8 @@ model_type = list(/obj/item/robot_model/janitor) model_flags = BORG_MODEL_JANITOR - items_to_add = list(/obj/item/mop/advanced/cyborg) - items_to_remove = list(/obj/item/mop/cyborg) + items_to_add = list(/obj/item/mop/advanced) + items_to_remove = list(/obj/item/mop) /obj/item/borg/upgrade/prt name = "janitor cyborg plating repair tool" @@ -216,7 +216,7 @@ model_type = list(/obj/item/robot_model/janitor) model_flags = BORG_MODEL_JANITOR - items_to_add = list(/obj/item/plunger/cyborg) + items_to_add = list(/obj/item/plunger) /obj/item/borg/upgrade/high_capacity_light_replacer name = "janitor cyborg high capacity replacer" @@ -226,8 +226,8 @@ model_type = list(/obj/item/robot_model/janitor) model_flags = BORG_MODEL_JANITOR - items_to_add = list (/obj/item/lightreplacer/cyborg/advanced) - items_to_remove = list(/obj/item/lightreplacer/cyborg) + items_to_add = list (/obj/item/lightreplacer/advanced) + items_to_remove = list(/obj/item/lightreplacer) /obj/item/borg/upgrade/syndicate name = "illegal equipment module" @@ -749,7 +749,7 @@ model_type = list(/obj/item/robot_model/janitor) model_flags = BORG_MODEL_JANITOR - items_to_add = list(/obj/item/pushbroom/cyborg) + items_to_add = list(/obj/item/pushbroom) /obj/item/borg/upgrade/condiment_synthesizer name = "Service Cyborg Condiment Synthesiser" diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 00da00b89d1..1e09ef9e6e6 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -73,10 +73,6 @@ icon_state = "[initial(icon_state)]" return ..() -/obj/item/storage/bag/trash/cyborg/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT) - /obj/item/storage/bag/trash/filled/PopulateContents() . = ..() for(var/i in 1 to rand(1, 7)) @@ -345,6 +341,10 @@ I_copy.layer = FLOAT_LAYER . += I_copy +/obj/item/storage/bag/tray/cyborg_unequip(mob/user) + . = ..() + atom_storage.remove_all(drop_location()) + /obj/item/storage/bag/tray/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) . = ..() update_appearance() diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 84447ba31e6..c37bad579f0 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -124,6 +124,11 @@ dyn_explosion(src, plasmaAmount/5, explosion_cause = src) // 20 plasma in a standard welder has a 4 power explosion. no breaches, but enough to kill/dismember holder qdel(src) +/obj/item/weldingtool/cyborg_unequip(mob/user) + if(!isOn()) + return + switched_on(user) + /obj/item/weldingtool/use_tool(atom/target, mob/living/user, delay, amount, volume, datum/callback/extra_checks) var/mutable_appearance/sparks = mutable_appearance('icons/effects/welding_effect.dmi', "welding_sparks", GASFIRE_LAYER, src, ABOVE_LIGHTING_PLANE) target.add_overlay(sparks) @@ -344,12 +349,6 @@ icon_state = "indwelder_cyborg" toolspeed = 0.5 -/obj/item/weldingtool/largetank/cyborg/cyborg_unequip(mob/user) - if(!isOn()) - return - switched_on(user) - - /obj/item/weldingtool/mini name = "emergency welding tool" desc = "A miniature welder used during emergencies." diff --git a/code/game/objects/structures/lavaland/geyser.dm b/code/game/objects/structures/lavaland/geyser.dm index f664ee751c4..0e3c8f3b5d6 100644 --- a/code/game/objects/structures/lavaland/geyser.dm +++ b/code/game/objects/structures/lavaland/geyser.dm @@ -193,7 +193,3 @@ layer_mode_sprite = "reinforced_plunger_layer" custom_premium_price = PAYCHECK_CREW * 8 - -/obj/item/plunger/cyborg/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT) diff --git a/code/modules/antagonists/nukeop/equipment/pinpointer.dm b/code/modules/antagonists/nukeop/equipment/pinpointer.dm index 4fe39c3b942..4f8af394c6e 100644 --- a/code/modules/antagonists/nukeop/equipment/pinpointer.dm +++ b/code/modules/antagonists/nukeop/equipment/pinpointer.dm @@ -82,10 +82,6 @@ flags_1 = NONE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF -/obj/item/pinpointer/syndicate_cyborg/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT) - /obj/item/pinpointer/syndicate_cyborg/cyborg_unequip(mob/user) if(!active) return diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm index b8981aec83e..7b7a5b6d94a 100644 --- a/code/modules/assembly/flash.dm +++ b/code/modules/assembly/flash.dm @@ -291,6 +291,7 @@ /obj/item/assembly/flash/cyborg/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers) return + /obj/item/assembly/flash/cyborg/screwdriver_act(mob/living/user, obj/item/I) return diff --git a/code/modules/mining/equipment/mineral_scanner.dm b/code/modules/mining/equipment/mineral_scanner.dm index 53357f8e30a..c84706b3cac 100644 --- a/code/modules/mining/equipment/mineral_scanner.dm +++ b/code/modules/mining/equipment/mineral_scanner.dm @@ -49,8 +49,9 @@ /// The range of the scanner in tiles. var/range = 7 -/obj/item/t_scanner/adv_mining_scanner/cyborg - shut_off_on_unequip = FALSE +//get no effects from the t-ray scanner, which auto-shuts off. +/obj/item/t_scanner/adv_mining_scanner/cyborg_unequip(mob/user) + return /obj/item/t_scanner/adv_mining_scanner/cyborg/Initialize(mapload) . = ..() diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index 23d59fbfb71..c881d9dce45 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -73,15 +73,6 @@ hitsound = 'sound/items/weapons/drill.ogg' desc = "An electric mining drill for the especially scrawny." -/obj/item/pickaxe/drill/cyborg - name = "cyborg mining drill" - desc = "An integrated electric mining drill." - flags_1 = NONE - -/obj/item/pickaxe/drill/cyborg/Initialize(mapload) - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT) - /obj/item/pickaxe/drill/diamonddrill name = "diamond-tipped mining drill" icon_state = "diamonddrill" @@ -89,12 +80,6 @@ toolspeed = 0.2 desc = "Yours is the drill that will pierce the heavens!" -/obj/item/pickaxe/drill/cyborg/diamond //This is the BORG version! - name = "diamond-tipped cyborg mining drill" //To inherit the NODROP_1 flag, and easier to change borg specific drill mechanics. - icon_state = "diamonddrill" - inhand_icon_state = "diamonddrill" - toolspeed = 0.2 - /obj/item/pickaxe/drill/jackhammer name = "sonic jackhammer" icon_state = "jackhammer" diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 9f9a32392ff..0e4096dfd94 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -379,53 +379,63 @@ //visibly unequips I but it is NOT MOVED AND REMAINS IN SRC, newloc is for signal handling checks only which hints where you want to move the object after removal //item MUST BE FORCEMOVE'D OR QDEL'D -/mob/proc/temporarilyRemoveItemFromInventory(obj/item/I, force = FALSE, idrop = TRUE, atom/newloc = src) - return doUnEquip(I, force, newloc, TRUE, idrop, silent = TRUE) -//DO NOT CALL THIS PROC -//use one of the above 4 helper procs -//you may override it, but do not modify the args -/mob/proc/doUnEquip(obj/item/I, force, atom/newloc, no_move, invdrop = TRUE, silent = FALSE) //Force overrides TRAIT_NODROP for things like wizarditis and admin undress. - //Use no_move if the item is just gonna be immediately moved afterward - //Invdrop is used to prevent stuff in pockets dropping. only set to false if it's going to immediately be replaced +/mob/proc/temporarilyRemoveItemFromInventory(obj/item/item_dropping, force = FALSE, idrop = TRUE, atom/newloc = src) + return doUnEquip(item_dropping, force, newloc, TRUE, idrop, silent = TRUE) + +/** + * ## doUnEquip + * First and most importantly, DO NOT CALL THIS PROC + * Use one of the above 4 helper procs instead!! + * you may override it, but do not modify the args. + * Returns TRUE if it managed to unequip, FALSE if it can't. + * Args: + * item_dropping - The item that we're unequipping. + * force - overrides TRAIT_NODROP for things like wizarditis and admin undress. + * newloc - The location we're dropping the item into, this could be a turf, storage, mob, etc. + * no_move - if the item is just gonna be immediately moved afterward + * invdrop - Arg passed to signals, prevents stuff in pockets dropping. Only set to false if it's going to immediately be replaced + * silent - Arg passed to dropped() and signals, muting things like drop sound. + */ +/mob/proc/doUnEquip(obj/item/item_dropping, force, atom/newloc, no_move, invdrop = TRUE, silent = FALSE) PROTECTED_PROC(TRUE) - if(!I) //If there's nothing to drop, the drop is automatically successful. If(unEquip) should generally be used to check for TRAIT_NODROP. + if(!item_dropping) //If there's nothing to drop, the drop is automatically successful. If(unEquip) should generally be used to check for TRAIT_NODROP. return TRUE - if(HAS_TRAIT(I, TRAIT_NODROP) && !force) + if(HAS_TRAIT(item_dropping, TRAIT_NODROP) && !force) return FALSE - if((SEND_SIGNAL(I, COMSIG_ITEM_PRE_UNEQUIP, force, newloc, no_move, invdrop, silent) & COMPONENT_ITEM_BLOCK_UNEQUIP) && !force) + if((SEND_SIGNAL(item_dropping, COMSIG_ITEM_PRE_UNEQUIP, force, newloc, no_move, invdrop, silent) & COMPONENT_ITEM_BLOCK_UNEQUIP) && !force) return FALSE - var/hand_index = get_held_index_of_item(I) + var/hand_index = get_held_index_of_item(item_dropping) if(hand_index) held_items[hand_index] = null update_held_items() - if(!I) + if(!item_dropping) return FALSE if(client) - client.screen -= I + client.screen -= item_dropping if(observers?.len) for(var/mob/dead/observe as anything in observers) if(observe.client) - observe.client.screen -= I + observe.client.screen -= item_dropping - I.layer = initial(I.layer) - SET_PLANE_EXPLICIT(I, initial(I.plane), newloc) - I.appearance_flags &= ~NO_CLIENT_COLOR - if(!no_move && !(I.item_flags & DROPDEL)) //item may be moved/qdel'd immedietely, don't bother moving it + item_dropping.layer = initial(item_dropping.layer) + SET_PLANE_EXPLICIT(item_dropping, initial(item_dropping.plane), newloc) + item_dropping.appearance_flags &= ~NO_CLIENT_COLOR + if(!no_move && !(item_dropping.item_flags & DROPDEL)) //item may be moved/qdel'd immedietely, don't bother moving it if (isnull(newloc)) - I.moveToNullspace() + item_dropping.moveToNullspace() else - I.forceMove(newloc) + item_dropping.forceMove(newloc) - I.dropped(src, silent) - SEND_SIGNAL(I, COMSIG_ITEM_POST_UNEQUIP, force, newloc, no_move, invdrop, silent) - SEND_SIGNAL(src, COMSIG_MOB_UNEQUIPPED_ITEM, I, force, newloc, no_move, invdrop, silent) + item_dropping.dropped(src, silent) + SEND_SIGNAL(item_dropping, COMSIG_ITEM_POST_UNEQUIP, force, newloc, no_move, invdrop, silent) + SEND_SIGNAL(src, COMSIG_MOB_UNEQUIPPED_ITEM, item_dropping, force, newloc, no_move, invdrop, silent) return TRUE /** diff --git a/code/modules/mob/living/basic/drone/inventory.dm b/code/modules/mob/living/basic/drone/inventory.dm index f71d1619827..37f61b2b208 100644 --- a/code/modules/mob/living/basic/drone/inventory.dm +++ b/code/modules/mob/living/basic/drone/inventory.dm @@ -1,12 +1,12 @@ // Drone inventory procs -/mob/living/basic/drone/doUnEquip(obj/item/item, force, newloc, no_move, invdrop = TRUE, silent = FALSE) +/mob/living/basic/drone/doUnEquip(obj/item/item_dropping, force, newloc, no_move, invdrop = TRUE, silent = FALSE) if(..()) update_held_items() - if(item == head) + if(item_dropping == head) head = null update_worn_head() - if(item == internal_storage) + if(item_dropping == internal_storage) internal_storage = null update_inv_internal_storage() return TRUE diff --git a/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm b/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm index 3abafd5be1b..a5e0a9c0272 100644 --- a/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm +++ b/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm @@ -36,12 +36,12 @@ // Bullshit related to having a fake pocket begins here -/mob/living/basic/guardian/dextrous/doUnEquip(obj/item/equipped_item, force, newloc, no_move, invdrop = TRUE, silent = FALSE) +/mob/living/basic/guardian/dextrous/doUnEquip(obj/item/item_dropping, force, newloc, no_move, invdrop = TRUE, silent = FALSE) . = ..() if (!.) return FALSE update_held_items() - if(equipped_item == internal_storage) + if(item_dropping == internal_storage) internal_storage = null update_inv_internal_storage() return TRUE diff --git a/code/modules/mob/living/carbon/alien/larva/inventory.dm b/code/modules/mob/living/carbon/alien/larva/inventory.dm index 23c461aa83c..86ea6d85fb7 100644 --- a/code/modules/mob/living/carbon/alien/larva/inventory.dm +++ b/code/modules/mob/living/carbon/alien/larva/inventory.dm @@ -1,3 +1,3 @@ //can't unequip since it can't equip anything -/mob/living/carbon/alien/larva/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE, silent = FALSE) +/mob/living/carbon/alien/larva/doUnEquip(obj/item/item_dropping, force, newloc, no_move, invdrop = TRUE, silent = FALSE) return diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index c9ab87098dc..dc4fb3fbd9b 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -215,12 +215,12 @@ /mob/living/carbon/human/get_equipped_speed_mod_items() return ..() - list(l_store, r_store, s_store) -/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE, silent = FALSE) +/mob/living/carbon/human/doUnEquip(obj/item/item_dropping, force, newloc, no_move, invdrop = TRUE, silent = FALSE) . = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should. - if(!. || !I) + if(!. || !item_dropping) return var/not_handled = FALSE //if we actually unequipped an item, this is because we dont want to run this proc twice, once for carbons and once for humans - if(I == wear_suit) + if(item_dropping == wear_suit) if(s_store && invdrop) dropItemToGround(s_store, TRUE) //It makes no sense for your suit storage to stay on you if you drop your suit. if(wear_suit.breakouttime) //when unequipping a straightjacket @@ -230,7 +230,7 @@ wear_suit = null if(!QDELETED(src)) //no need to update we're getting deleted anyway update_worn_oversuit() - else if(I == w_uniform) + else if(item_dropping == w_uniform) w_uniform = null update_suit_sensors() if(!QDELETED(src)) @@ -244,7 +244,7 @@ dropItemToGround(wear_id) if(belt && !can_equip(belt, ITEM_SLOT_BELT, TRUE, ignore_equipped = TRUE)) dropItemToGround(belt) - else if(I == gloves) + else if(item_dropping == gloves) //SKYRAT EDIT ADDITION - ERP UPDATE if(gloves.breakouttime) //when unequipping a straightjacket REMOVE_TRAIT(src, TRAIT_RESTRAINED, TRAIT_GLOVES) @@ -254,39 +254,39 @@ gloves = null if(!QDELETED(src)) update_worn_gloves() - else if(I == glasses) + else if(item_dropping == glasses) glasses = null - var/obj/item/clothing/glasses/old_glasses = I + var/obj/item/clothing/glasses/old_glasses = item_dropping if(old_glasses.vision_flags || old_glasses.invis_override || old_glasses.invis_view || !isnull(old_glasses.lighting_cutoff)) update_sight() if(!QDELETED(src)) update_worn_glasses() - else if(I == ears) + else if(item_dropping == ears) ears = null if(!QDELETED(src)) update_worn_ears() - else if(I == shoes) + else if(item_dropping == shoes) shoes = null if(!QDELETED(src)) update_worn_shoes() - else if(I == belt) + else if(item_dropping == belt) belt = null if(!QDELETED(src)) update_worn_belt() - else if(I == wear_id) + else if(item_dropping == wear_id) wear_id = null sec_hud_set_ID() if(!QDELETED(src)) update_worn_id() - else if(I == r_store) + else if(item_dropping == r_store) r_store = null if(!QDELETED(src)) update_pockets() - else if(I == l_store) + else if(item_dropping == l_store) l_store = null if(!QDELETED(src)) update_pockets() - else if(I == s_store) + else if(item_dropping == s_store) s_store = null if(!QDELETED(src)) update_suit_storage() @@ -297,7 +297,7 @@ return update_equipment_speed_mods() - update_obscured_slots(I.flags_inv) + update_obscured_slots(item_dropping.flags_inv) hud_used?.update_locked_slots() /mob/living/carbon/human/toggle_internals(obj/item/tank, is_external = FALSE) diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index ad817e31151..e6d249ec07d 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -215,35 +215,35 @@ /mob/living/carbon/get_equipped_speed_mod_items() return ..() + get_equipped_items() -/mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE, silent = FALSE) +/mob/living/carbon/doUnEquip(obj/item/item_dropping, force, newloc, no_move, invdrop = TRUE, silent = FALSE) . = ..() //Sets the default return value to what the parent returns. - if(!. || !I) //We don't want to set anything to null if the parent returned 0. + if(!. || !item_dropping) //We don't want to set anything to null if the parent returned 0. return var/not_handled = FALSE //if we actually unequipped an item, this is because we dont want to run this proc twice, once for carbons and once for humans - if(I == head) + if(item_dropping == head) head = null if(!QDELETED(src)) update_worn_head() - else if(I == back) + else if(item_dropping == back) back = null if(!QDELETED(src)) update_worn_back() - else if(I == wear_mask) + else if(item_dropping == wear_mask) wear_mask = null if(!QDELETED(src)) update_worn_mask() - else if(I == wear_neck) + else if(item_dropping == wear_neck) wear_neck = null if(!QDELETED(src)) - update_worn_neck(I) - else if(I == handcuffed) + update_worn_neck(item_dropping) + else if(item_dropping == handcuffed) set_handcuffed(null) if(buckled?.buckle_requires_restraints) buckled.unbuckle_mob(src) if(!QDELETED(src)) update_handcuffed() - else if(I == legcuffed) + else if(item_dropping == legcuffed) legcuffed = null if(!QDELETED(src)) update_worn_legcuffs() @@ -251,7 +251,7 @@ not_handled = TRUE // Not an else-if because we're probably equipped in another slot - if(I == internal && (QDELETED(src) || QDELETED(I) || I.loc != src)) + if(item_dropping == internal && (QDELETED(src) || QDELETED(item_dropping) || item_dropping.loc != src)) cutoff_internals() if(!QDELETED(src)) update_mob_action_buttons(UPDATE_BUTTON_STATUS) @@ -260,7 +260,7 @@ return update_equipment_speed_mods() - update_obscured_slots(I.flags_inv) + update_obscured_slots(item_dropping.flags_inv) hud_used?.update_locked_slots() /// Returns TRUE if an air tank compatible helmet is equipped. diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index 50fe16dd435..c981269e22c 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -41,96 +41,56 @@ to_chat(src, span_warning("Deactivate a module first!")) return FALSE - return equip_module_to_slot(item_module, first_free_slot) + return put_in_hand(item_module, first_free_slot) -/** - * Is passed an item and a module slot. Equips the item to that borg slot. - * - * Arguments - * * item_module - the item being equipped to a slot - * * module_num - the slot number being equipped to. - */ -/mob/living/silicon/robot/proc/equip_module_to_slot(obj/item/item_module, module_num) - var/storage_was_closed = FALSE //Just to be consistant and all - //spawning a clientless borg won't init its hud, much like with all mobs, so don't bother showing what's not there - if(hud_used && !shown_robot_modules) //Tools may be invisible if the collection is hidden - hud_used.toggle_show_robot_modules() - storage_was_closed = TRUE - switch(module_num) - if(BORG_CHOOSE_MODULE_ONE) - item_module.screen_loc = inv1.screen_loc - if(BORG_CHOOSE_MODULE_TWO) - item_module.screen_loc = inv2.screen_loc - if(BORG_CHOOSE_MODULE_THREE) - item_module.screen_loc = inv3.screen_loc - - held_items[module_num] = item_module +/mob/living/silicon/robot/put_in_hand(obj/item/item_module, hand_index, forced = FALSE, ignore_anim = TRUE, visuals_only = FALSE) + . = ..() + if(!.) + return item_module.mouse_opacity = initial(item_module.mouse_opacity) - SET_PLANE_EXPLICIT(item_module, ABOVE_HUD_PLANE, src) - item_module.forceMove(src) + observer_screen_update(item_module) - if(istype(item_module, /obj/item/borg/sight)) - var/obj/item/borg/sight/borg_sight = item_module - sight_mode |= borg_sight.sight_mode - update_sight() +///Helper for cyborgs unequipping things. +/mob/living/silicon/robot/proc/deactivate_module(obj/item/item_module) + transferItemToLoc(item_module, newloc = model) - observer_screen_update(item_module, TRUE) +/mob/living/silicon/robot/doUnEquip(obj/item/item_dropping, force, atom/newloc, no_move, invdrop, silent) + //borgs can drop items that aren't part of the module (used for apparatus modules, the stored item isn't a module). + if(isnull(model) || !(item_dropping in model.modules)) + return ..() - if(hud_used && storage_was_closed) - hud_used.toggle_show_robot_modules() - item_module.on_equipped(src, ITEM_SLOT_HANDS) - return TRUE + if(newloc != model) + to_chat(src, span_notice("You can't drop your [item_dropping.name] module.")) + return FALSE -/** - * Unequips item item_module from slot module_num. Deletes it if delete_after = TRUE. - * - * Arguments - * * item_module - the item being unequipped - * * module_num - the slot number being unequipped. - */ -/mob/living/silicon/robot/proc/unequip_module_from_slot(obj/item/item_module, module_num) - if(QDELETED(item_module)) - CRASH("unequip_module_from_slot called with improper item_module") + var/module_num = get_selected_module() + . = ..() + if(!.) + return + item_dropping.mouse_opacity = MOUSE_OPACITY_OPAQUE + //this is the cyborg equivalent of dropped(), though we call that too in doUnEquip. + item_dropping.cyborg_unequip(src) + deselect_module(module_num) - if(!(item_module in model.modules)) - CRASH("unequip_module_from_slot called with item_module not in model.modules") - item_module.mouse_opacity = MOUSE_OPACITY_OPAQUE +/mob/living/silicon/robot/update_held_items() + . = ..() + if(isnull(client) || isnull(hud_used) || hud_used.hud_version == HUD_STYLE_NOHUD) + return + var/turf/our_turf = get_turf(src) - if(istype(item_module, /obj/item/storage/bag/tray/)) - item_module.atom_storage.remove_all(loc) - if(istype(item_module, /obj/item/borg/sight)) - var/obj/item/borg/sight/borg_sight = item_module - sight_mode &= ~borg_sight.sight_mode - update_sight() + for(var/obj/item/held in held_items) + SET_PLANE(held, ABOVE_HUD_PLANE, our_turf) + if(held_items[BORG_CHOOSE_MODULE_ONE] == held) + held.screen_loc = inv1.screen_loc + else if(held_items[BORG_CHOOSE_MODULE_TWO] == held) + held.screen_loc = inv2.screen_loc + else if(held_items[BORG_CHOOSE_MODULE_THREE] == held) + held.screen_loc = inv3.screen_loc + client.screen |= held - if(client) - client.screen -= item_module - - if(module_active == item_module) - module_active = null - - switch(module_num) - if(BORG_CHOOSE_MODULE_ONE) - if(!(disabled_modules & BORG_MODULE_ALL_DISABLED)) - inv1.icon_state = initial(inv1.icon_state) - if(BORG_CHOOSE_MODULE_TWO) - if(!(disabled_modules & BORG_MODULE_TWO_DISABLED)) - inv2.icon_state = initial(inv2.icon_state) - if(BORG_CHOOSE_MODULE_THREE) - if(!(disabled_modules & BORG_MODULE_THREE_DISABLED)) - inv3.icon_state = initial(inv3.icon_state) - - if(item_module.item_flags & DROPDEL) - item_module.item_flags &= ~DROPDEL //we shouldn't HAVE things with DROPDEL_1 in our modules, but better safe than runtiming horribly - - held_items[module_num] = null - item_module.cyborg_unequip(src) - item_module.forceMove(model) //Return item to configuration so it appears in its contents, so it can be taken out again. - - observer_screen_update(item_module, FALSE) - hud_used?.update_robot_modules_display() - return TRUE +/mob/living/silicon/robot/put_in_hand_check(obj/item/item_equipping) + return (item_equipping in model.modules) /** * Breaks the slot number, changing the icon. @@ -143,7 +103,7 @@ return FALSE if(held_items[module_num]) //If there's a held item, unequip it first. - if(!unequip_module_from_slot(held_items[module_num], module_num)) //If we fail to unequip it, then don't continue + if(!deactivate_module(held_items[module_num])) //If we fail to unequip it, then don't continue return FALSE switch(module_num) @@ -238,40 +198,19 @@ for(var/cyborg_slot in 1 to 3) repair_cyborg_slot(cyborg_slot) -/** - * Updates the observers's screens with cyborg itemss. - * Arguments - * * item_module - the item being added or removed from the screen - * * add - whether or not the item is being added, or removed. - */ -/mob/living/silicon/robot/proc/observer_screen_update(obj/item/item_module, add = TRUE) - if(observers?.len) - for(var/M in observers) - var/mob/dead/observe = M - if(observe.client && observe.client.eye == src) - if(add) - observe.client.screen += item_module - else - observe.client.screen -= item_module - else - observers -= observe - if(!observers.len) - observers = null - break - /** * Unequips the active held item, if there is one. */ /mob/living/silicon/robot/proc/uneq_active() if(module_active) - unequip_module_from_slot(module_active, get_selected_module()) + deactivate_module(module_active) // Technically none of the items are dropped, only unequipped /mob/living/silicon/robot/drop_all_held_items() for(var/cyborg_slot in 1 to length(held_items)) if(!held_items[cyborg_slot]) continue - unequip_module_from_slot(held_items[cyborg_slot], cyborg_slot) + deactivate_module(held_items[cyborg_slot]) /** * Checks if the item is currently in a slot. @@ -318,8 +257,7 @@ /mob/living/silicon/robot/proc/get_selected_module() if(module_active) return held_items.Find(module_active) - - return 0 + return FALSE /** * Selects the module in the slot module_num. @@ -351,14 +289,11 @@ /mob/living/silicon/robot/proc/deselect_module(module_num) switch(module_num) if(BORG_CHOOSE_MODULE_ONE) - if(module_active == held_items[module_num]) - inv1.icon_state = initial(inv1.icon_state) + inv1.icon_state = initial(inv1.icon_state) if(BORG_CHOOSE_MODULE_TWO) - if(module_active == held_items[module_num]) - inv2.icon_state = initial(inv2.icon_state) + inv2.icon_state = initial(inv2.icon_state) if(BORG_CHOOSE_MODULE_THREE) - if(module_active == held_items[module_num]) - inv3.icon_state = initial(inv3.icon_state) + inv3.icon_state = initial(inv3.icon_state) module_active = null return TRUE @@ -406,3 +341,23 @@ /mob/living/silicon/robot/can_hold_items(obj/item/I) return (I && (I in model.modules)) //Only if it's part of our model. + +/** + * ## Please do not use + * Updates the observers's screens with cyborg items. + * Currently inventory code handling for observers is tied to carbon (get_held_overlays), meaning this snowflake code for borgs is + * necessary so observers watching borgs don't bug out. Once that's moved to the living, replace this with it. + * Removing from the screen is handled by 'doUnEquip' + * Arg: + * * item_module - the item being added to the screen. + */ +/mob/living/silicon/robot/proc/observer_screen_update(obj/item/item_module) + if(!observers?.len) + return + for(var/mob/dead/observe as anything in observers) + if(!observe.client || observe.client.eye != src) + observers -= observe + if(!observers.len) + observers = null + return + observe.client.screen += item_module diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 7f7c412bfea..3b9acf3ae11 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -22,10 +22,6 @@ RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, PROC_REF(on_light_eater)) RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_GOT_DAMPENED), PROC_REF(on_dampen)) - robot_modules_background = new() - robot_modules_background.icon_state = "block" - SET_PLANE_EXPLICIT(robot_modules_background, HUD_PLANE, src) - inv1 = new /atom/movable/screen/robot/module1() inv2 = new /atom/movable/screen/robot/module2() inv3 = new /atom/movable/screen/robot/module3() @@ -739,15 +735,11 @@ /mob/living/silicon/robot/proc/ResetModel() SEND_SIGNAL(src, COMSIG_BORG_SAFE_DECONSTRUCT) drop_all_held_items() - shown_robot_modules = FALSE for(var/obj/item/storage/bag in model.contents) // drop all of the items that may be stored by the cyborg for(var/obj/item in bag) item.forceMove(drop_location()) - if(hud_used) - hud_used.update_robot_modules_display() - if (hasExpanded) hasExpanded = FALSE //update_transform(0.5) // Original diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 450447deff4..662028f7ad8 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -452,6 +452,8 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real else GLOB.lawchanges.Add("[time] : [name]([key]) emagged by external event.") + model.rebuild_modules() + INVOKE_ASYNC(src, PROC_REF(borg_emag_end), user) return TRUE diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm index 2d016e91364..7f4f7e68ae1 100644 --- a/code/modules/mob/living/silicon/robot/robot_defines.dm +++ b/code/modules/mob/living/silicon/robot/robot_defines.dm @@ -17,6 +17,7 @@ hud_type = /datum/hud/robot unique_name = TRUE mouse_drop_zone = TRUE + held_items = list(null, null, null) //we use held_items for the module holding, because that makes sense to do! default_hand_amount = 3 ///Represents the cyborg's model (engineering, medical, etc.) @@ -74,10 +75,6 @@ var/atom/movable/screen/inv3 = null var/atom/movable/screen/hands = null - ///Used to determine whether they have the module menu shown or not - var/shown_robot_modules = FALSE - var/atom/movable/screen/robot_modules_background - ///Lamp button reference var/atom/movable/screen/robot/lamp/lampButton @@ -90,7 +87,6 @@ // Modules (tool slots) var/obj/item/module_active = null - held_items = list(null, null, null) //we use held_items for the module holding, because that makes sense to do! ///For checking which modules are disabled or not. var/disabled_modules diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm index ed0ee16b03f..0cef2a7e312 100644 --- a/code/modules/mob/living/silicon/robot/robot_model.dm +++ b/code/modules/mob/living/silicon/robot/robot_model.dm @@ -15,6 +15,7 @@ lefthand_file = 'icons/mob/inhands/items/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/items/devices_righthand.dmi' obj_flags = CONDUCTS_ELECTRICITY + ///Host of this model var/mob/living/silicon/robot/robot ///Icon of the module selection screen @@ -56,17 +57,20 @@ /obj/item/robot_model/Initialize(mapload) . = ..() + robot = loc + create_storage(storage_type = /datum/storage/cyborg_internal_storage) + //src is what we store items visible to borgs, we'll store things in the bot itself otherwise. for(var/path in basic_modules) - var/obj/item/new_module = new path(src) + var/obj/item/new_module = new path(robot) basic_modules += new_module basic_modules -= path for(var/path in emag_modules) - var/obj/item/new_module = new path(src) + var/obj/item/new_module = new path(robot) emag_modules += new_module emag_modules -= path if(check_holidays(ICE_CREAM_DAY) && !(locate(/obj/item/borg/lollipop) in basic_modules)) - basic_modules += new /obj/item/borg/lollipop/ice_cream(src) + basic_modules += new /obj/item/borg/lollipop/ice_cream(robot) /obj/item/robot_model/Destroy() basic_modules.Cut() @@ -101,22 +105,21 @@ if(added_module.loc != src) added_module.forceMove(src) modules += added_module - ADD_TRAIT(added_module, TRAIT_NODROP, CYBORG_ITEM_TRAIT) added_module.mouse_opacity = MOUSE_OPACITY_OPAQUE + added_module.obj_flags |= ABSTRACT if(nonstandard) added_modules += added_module if(requires_rebuild) rebuild_modules() return added_module -/obj/item/robot_model/proc/remove_module(obj/item/removed_module, delete_after) +/obj/item/robot_model/proc/remove_module(obj/item/removed_module) basic_modules -= removed_module modules -= removed_module emag_modules -= removed_module added_modules -= removed_module rebuild_modules() - if(delete_after) - qdel(removed_module) + qdel(removed_module) /obj/item/robot_model/proc/rebuild_modules() //builds the usable module list from the modules we have var/mob/living/silicon/robot/cyborg = loc @@ -124,7 +127,9 @@ return var/list/held_modules = cyborg.held_items.Copy() var/active_module = cyborg.module_active - cyborg.drop_all_held_items() + //move everything out of the model's inventory + for(var/obj/item/module as anything in modules) + module.forceMove(robot) modules = list() for(var/obj/item/module as anything in basic_modules) add_module(module, FALSE, FALSE) @@ -134,12 +139,10 @@ for(var/obj/item/module as anything in added_modules) add_module(module, FALSE, FALSE) for(var/obj/item/module as anything in held_modules & modules) - cyborg.equip_module_to_slot(module, held_modules.Find(module)) + cyborg.put_in_hand(module, held_modules.Find(module)) if(active_module) cyborg.select_module(held_modules.Find(active_module)) - if(cyborg.hud_used) - cyborg.hud_used.update_robot_modules_display() - + atom_storage.refresh_views() ///Restocks things that don't take mats, generally at a power cost. Returns True if anything was restocked/replaced, and False otherwise. /obj/item/robot_model/proc/respawn_consumable(mob/living/silicon/robot/cyborg, coeff = 1) @@ -234,7 +237,6 @@ /obj/item/robot_model/proc/transform_to(new_config_type, forced = FALSE, transform = TRUE) var/mob/living/silicon/robot/cyborg = loc var/obj/item/robot_model/new_model = new new_config_type(cyborg) - new_model.robot = cyborg if(!new_model.be_transformed_to(src, forced)) qdel(new_model) return @@ -352,8 +354,6 @@ cyborg.updatehealth() cyborg.update_icons() cyborg.notify_ai(AI_NOTIFICATION_NEW_MODEL) - if(cyborg.hud_used) - cyborg.hud_used.update_robot_modules_display() SSblackbox.record_feedback("tally", "cyborg_modules", 1, cyborg.model) /** @@ -455,13 +455,13 @@ /obj/item/crowbar/cyborg, /obj/item/stack/tile/iron/base/cyborg, // haha jani will have old tiles >:D /obj/item/soap/nanotrasen/cyborg, - /obj/item/storage/bag/trash/cyborg, + /obj/item/storage/bag/trash, /obj/item/melee/flyswatter, /obj/item/extinguisher/mini, - /obj/item/mop/cyborg, + /obj/item/mop, /obj/item/reagent_containers/cup/bucket, /obj/item/paint/paint_remover, - /obj/item/lightreplacer/cyborg, + /obj/item/lightreplacer, /obj/item/holosign_creator, /obj/item/reagent_containers/spray/cyborg_drying, /obj/item/wirebrush, @@ -753,7 +753,7 @@ /obj/item/assembly/flash/cyborg, /obj/item/borg/sight/meson, /obj/item/storage/bag/ore/cyborg, - /obj/item/pickaxe/drill/cyborg, + /obj/item/pickaxe/drill, /obj/item/shovel, /obj/item/kinetic_crusher, //SKYRAT EDIT /obj/item/crowbar/cyborg, @@ -931,7 +931,7 @@ var/mob/living/silicon/robot/cyborg = loc cyborg.faction -= FACTION_SILICON //ai turrets -/obj/item/robot_model/syndicate/remove_module(obj/item/removed_module, delete_after) +/obj/item/robot_model/syndicate/remove_module(obj/item/removed_module) ..() var/mob/living/silicon/robot/cyborg = loc cyborg.faction |= FACTION_SILICON //ai is your bff now! @@ -1015,8 +1015,8 @@ /obj/item/robot_model/syndicate/kiltborg/do_transform_delay() //AUTO-EQUIPPING THESE TOOLS ANY EARLIER CAUSES RUNTIMES OH YEAH . = ..() - robot.equip_module_to_slot(locate(/obj/item/claymore/highlander/robot) in basic_modules, 1) - robot.equip_module_to_slot(locate(/obj/item/pinpointer/nuke) in basic_modules, 2) + robot.equip_to_slot(locate(/obj/item/claymore/highlander/robot) in basic_modules, 1) + robot.equip_to_slot(locate(/obj/item/pinpointer/nuke) in basic_modules, 2) robot.place_on_head(new /obj/item/clothing/head/beret/highlander(robot)) //THE ONLY PART MORE IMPORTANT THAN THE SWORD IS THE HAT ADD_TRAIT(robot.hat, TRAIT_NODROP, HIGHLANDER_TRAIT) diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 5c02044afa4..6109a08b4f7 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -141,11 +141,11 @@ GLOBAL_VAR_INIT(animals_spawned, 0) return if(!user.combat_mode || (I.item_flags & NOBLUDGEON)) - if((I.item_flags & ABSTRACT) || !user.temporarilyRemoveItemFromInventory(I)) + if(I.item_flags & ABSTRACT) return - place_item_in_disposal(I, user) - update_appearance() - return TRUE //no afterattack + if(place_item_in_disposal(I, user)) + update_appearance() + return TRUE //no afterattack else return ..() @@ -182,9 +182,14 @@ GLOBAL_VAR_INIT(animals_spawned, 0) visible_message(span_warning("[new_subject] climbs out of [src]!")) /// Moves an item into the diposal bin -/obj/machinery/disposal/proc/place_item_in_disposal(obj/item/I, mob/user) - I.forceMove(src) - user.visible_message(span_notice("[user.name] places \the [I] into \the [src]."), span_notice("You place \the [I] into \the [src].")) +/obj/machinery/disposal/proc/place_item_in_disposal(obj/item/disposing_item, mob/user) + if(!user.transferItemToLoc(disposing_item, newloc = src)) + return FALSE + user.visible_message( + span_notice("[user.name] places \the [disposing_item] into \the [src]."), + span_notice("You place \the [disposing_item] into \the [src]."), + ) + return TRUE /// Mouse drop another mob or self /obj/machinery/disposal/mouse_drop_receive(atom/target, mob/living/user, params) @@ -712,7 +717,7 @@ GLOBAL_VAR_INIT(animals_spawned, 0) if(!items_to_sweep) return for (var/obj/item/garbage in items_to_sweep) - garbage.forceMove(src) + user.transferItemToLoc(garbage, src) items_to_sweep.Cut() diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index eac960c038a..ce2f3ff5ec3 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -379,10 +379,6 @@ . = ..() UnregisterSignal(user, COMSIG_SURGERY_STARTING) -/obj/item/surgical_processor/cyborg_unequip(mob/user) - . = ..() - UnregisterSignal(user, COMSIG_SURGERY_STARTING) - /obj/item/surgical_processor/interact_with_atom(atom/design_holder, mob/living/user, list/modifiers) if(!istype(design_holder, /obj/item/disk/surgery) && !istype(design_holder, /obj/machinery/computer/operating)) return NONE diff --git a/code/modules/unit_tests/omnitools.dm b/code/modules/unit_tests/omnitools.dm index 930c6a34f0a..3a04ade9b76 100644 --- a/code/modules/unit_tests/omnitools.dm +++ b/code/modules/unit_tests/omnitools.dm @@ -11,8 +11,7 @@ omnitool = tool break TEST_ASSERT_NOTNULL(omnitool, "Could not find /obj/item/borg/cyborg_omnitool/engineering in borg inbuilt modules!") - borg.shown_robot_modules = TRUE //stops hud from updating which would runtime cause our mob does not have one - borg.equip_module_to_slot(omnitool, 1) + borg.put_in_hand(omnitool, 1) borg.select_module(1) //these must match @@ -30,4 +29,4 @@ TEST_ASSERT_EQUAL(test_frame.state, FRAME_STATE_EMPTY, "Machine frame's wires were not cut by the borg omnitool wirecutters!") //unequip - borg.unequip_module_from_slot(omnitool, 1) + borg.drop_all_held_items() diff --git a/tgstation.dme b/tgstation.dme index 667df634194..fe28dc666f3 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2141,6 +2141,7 @@ #include "code\datums\storage\subtypes\bags.dm" #include "code\datums\storage\subtypes\belts.dm" #include "code\datums\storage\subtypes\boxes.dm" +#include "code\datums\storage\subtypes\cyborg.dm" #include "code\datums\storage\subtypes\dufflebags.dm" #include "code\datums\storage\subtypes\holsters.dm" #include "code\datums\storage\subtypes\lockboxes.dm"