From 4fdc79ca9056afbe393045dbe8192b98a877bee3 Mon Sep 17 00:00:00 2001 From: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com> Date: Wed, 12 Feb 2025 16:55:11 -0500 Subject: [PATCH] Cyborg Inventory Refactor (#27788) * Initial variable changes * Add defines * oh my god huds * Removes update_items(), it seems useless but this might need reverting later * the hud doesn't work but the inventory itself seems to * Renames a var, gets inventory working properly * Activation/Deactivation support, ore bag fixed * Fixes CL and also this would have been a massive, hilarious bug * Apply suggestions from code review Dr and Lewc reviews Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Co-authored-by: Drsmail <60036448+Drsmail@users.noreply.github.com> Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com> * Update code/_onclick/hud/robot_hud.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com> * Fixes a comment * Wait I forgot this worked like this for a reason * Lewc Suggestions Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com> * Burza Suggestions Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com> Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com> --------- Signed-off-by: BiancaWilkson <42818125+BiancaWilkson@users.noreply.github.com> Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Co-authored-by: Drsmail <60036448+Drsmail@users.noreply.github.com> Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com> --- code/__DEFINES/dcs/item_signals.dm | 7 + code/__DEFINES/silicon_defines.dm | 10 + code/_onclick/hud/robot_hud.dm | 140 ++++------ code/game/objects/items.dm | 2 +- .../objects/items/weapons/storage/bags.dm | 23 +- .../game/turfs/simulated/floor/transparent.dm | 9 +- code/game/turfs/simulated/minerals.dm | 4 +- code/modules/admin/topic.dm | 2 +- .../living/silicon/robot/robot_inventory.dm | 263 ++++++++---------- .../mob/living/silicon/robot/robot_life.dm | 12 - .../mob/living/silicon/robot/robot_mob.dm | 81 +++--- .../living/silicon/robot/robot_movement.dm | 2 +- code/modules/tgui/states/inventory_state.dm | 2 +- paradise.dme | 1 + 14 files changed, 250 insertions(+), 308 deletions(-) create mode 100644 code/__DEFINES/silicon_defines.dm diff --git a/code/__DEFINES/dcs/item_signals.dm b/code/__DEFINES/dcs/item_signals.dm index 922682352c7..68ab7cc4f26 100644 --- a/code/__DEFINES/dcs/item_signals.dm +++ b/code/__DEFINES/dcs/item_signals.dm @@ -116,3 +116,10 @@ #define COMSIG_SPEED_POTION_APPLIED "speed_potion" #define SPEED_POTION_STOP (1<<0) +// Cyborg specific items + +/// from /mob/living/silicon/robot/proc/activate_item() (mob/user), A general signal for if a specific borg item needs something done when being activated. +#define COMSIG_CYBORG_ITEM_ACTIVATED "cyborg_activation" + +/// from /mob/living/silicon/robot/proc/deactivate_item() (mob/user), A general signal for if a specific borg item needs something done when being deactivated. +#define COMSIG_CYBORG_ITEM_DEACTIVATED "cyborg_deactivation" diff --git a/code/__DEFINES/silicon_defines.dm b/code/__DEFINES/silicon_defines.dm new file mode 100644 index 00000000000..2cc02a4a9cf --- /dev/null +++ b/code/__DEFINES/silicon_defines.dm @@ -0,0 +1,10 @@ +#define CYBORG_MODULE_ONE 1 +#define CYBORG_MODULE_TWO 2 +#define CYBORG_MODULE_THREE 3 +#define CYBORG_EMPTY_MODULE 0 + +#define CYBORG_MAX_MODULES 3 + +/// These are the screen locations of a cyborg's modules 1, 2, and 3 in that order. +#define CYBORG_HUD_LOCATIONS list("CENTER-2:16,SOUTH:5", "CENTER-1 :16,SOUTH:5", "CENTER :16,SOUTH:5") + diff --git a/code/_onclick/hud/robot_hud.dm b/code/_onclick/hud/robot_hud.dm index 95c2861049e..b64544afefe 100644 --- a/code/_onclick/hud/robot_hud.dm +++ b/code/_onclick/hud/robot_hud.dm @@ -22,39 +22,42 @@ return TRUE -/atom/movable/screen/robot/module1 - name = "module1" - icon_state = "inv1" +/atom/movable/screen/robot/active_module + name = "module" + icon_state = "inv" + /// If it's slot 1, 2, or 3 + var/module_number = CYBORG_MODULE_ONE + /// Where the string for the deactivated icon state is stored + var/deactivated_icon_string + /// Where the string for the activated icon state is stored + var/activated_icon_string + /// If it should have a green background + var/active = FALSE -/atom/movable/screen/robot/module1/Click() - if(..()) +/atom/movable/screen/robot/active_module/Initialize(mapload, slot_number) + . = ..() + module_number = slot_number + name = name + "[module_number]" + icon_state = icon_state + "[module_number]" + deactivated_icon_string = icon_state + activated_icon_string = icon_state + " +a" + +/// Updates the background of the module to be active +/atom/movable/screen/robot/active_module/proc/activate() + icon_state = activated_icon_string + active = TRUE + +/// Updates the background of the module to be inactive +/atom/movable/screen/robot/active_module/proc/deactivate() + icon_state = deactivated_icon_string + active = FALSE + +/atom/movable/screen/robot/active_module/Click() + if(..() || !module_number) return if(isrobot(usr)) var/mob/living/silicon/robot/R = usr - R.toggle_module(1) - -/atom/movable/screen/robot/module2 - name = "module2" - icon_state = "inv2" - -/atom/movable/screen/robot/module2/Click() - if(..()) - return - if(isrobot(usr)) - var/mob/living/silicon/robot/R = usr - R.toggle_module(2) - -/atom/movable/screen/robot/module3 - name = "module3" - icon_state = "inv3" - -/atom/movable/screen/robot/module3/Click() - if(..()) - return - if(isrobot(usr)) - var/mob/living/silicon/robot/R = usr - R.toggle_module(3) - + R.toggle_module(module_number) /atom/movable/screen/robot/radio name = "radio" @@ -114,6 +117,7 @@ var/shown_robot_modules = FALSE // Used to determine whether they have the module menu shown or not var/atom/movable/screen/robot_modules_background + /datum/hud/robot/New(mob/user) ..() @@ -137,22 +141,11 @@ static_inventory += using //Module select - using = new /atom/movable/screen/robot/module1() - using.screen_loc = ui_inv1 - static_inventory += using - mymobR.inv1 = using - - using = new /atom/movable/screen/robot/module2() - using.screen_loc = ui_inv2 - static_inventory += using - mymobR.inv2 = using - - using = new /atom/movable/screen/robot/module3() - using.screen_loc = ui_inv3 - static_inventory += using - mymobR.inv3 = using - -//End of module select + for(var/i in 1 to CYBORG_MAX_MODULES) + using = new /atom/movable/screen/robot/active_module(src, i) + using.screen_loc = CYBORG_HUD_LOCATIONS[i] + static_inventory += using + mymobR.inventory_screens += using //Sec/Med HUDs using = new /atom/movable/screen/ai/sensors() @@ -212,10 +205,8 @@ /datum/hud/robot/Destroy() var/mob/living/silicon/robot/myrob = mymob - myrob.inv1 = null myrob.hands = null - myrob.inv2 = null - myrob.inv3 = null + QDEL_LAZYLIST(myrob.inventory_screens) myrob.lamp_button = null myrob.thruster_button = null @@ -271,29 +262,29 @@ var/y = 1 for(var/atom/movable/A in R.module.modules) - if((A != R.module_state_1) && (A != R.module_state_2) && (A != R.module_state_3)) - //Module is not currently active - 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" - A.layer = ABOVE_HUD_LAYER - A.plane = ABOVE_HUD_PLANE + if(A in R.all_active_items) // Don't need to display it if it's already active + continue + 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" + A.layer = ABOVE_HUD_LAYER + A.plane = ABOVE_HUD_PLANE - x++ - if(x == 4) - x = -4 - y++ + x++ + if(x == 4) + x = -4 + y++ else //Modules display is hidden screenmob.client.screen -= module_store_icon for(var/atom/A in R.module.modules) - if((A != R.module_state_1) && (A != R.module_state_2) && (A != R.module_state_3)) - //Module is not currently active - screenmob.client.screen -= A + if(A in R.all_active_items) // Don't need to display it if it's already active + continue + screenmob.client.screen -= A shown_robot_modules = FALSE screenmob.client.screen -= robot_modules_background @@ -304,23 +295,14 @@ var/mob/screenmob = viewer || R - var/held_items = list(R.module_state_1, R.module_state_2, R.module_state_3) if(!screenmob.hud_used) return if(screenmob.hud_used.hud_shown) - for(var/i in 1 to length(held_items)) - var/obj/item/I = held_items[i] - if(I) - switch(i) - if(1) - I.screen_loc = ui_inv1 - if(2) - I.screen_loc = ui_inv2 - if(3) - I.screen_loc = ui_inv3 - else - return - screenmob.client.screen += I + for(var/i in 1 to length(R.all_active_items)) + var/obj/item/active_item = R.all_active_items[i] + if(active_item) + active_item.screen_loc = CYBORG_HUD_LOCATIONS[i] + screenmob.client.screen |= active_item else - for(var/obj/item/I in held_items) + for(var/obj/item/I in R.all_active_items) screenmob.client.screen -= I diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 270e46c314b..e98cfecc048 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -383,7 +383,7 @@ GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons 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.activate_item(src) R.hud_used.update_robot_modules_display() // Due to storage type consolidation this should get used more now. diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 8205c863ce0..e3e5471f68e 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -179,17 +179,26 @@ . = ..() if(listening_to == user) return + begin_listening(src, user) + +/obj/item/storage/bag/ore/proc/begin_listening(datum/source, mob/user) // Even though its unused, the datum/source argument is required to make the signals work. + SIGNAL_HANDLER // COMSIG_CYBORG_ITEM_ACTIVATED if(listening_to) UnregisterSignal(listening_to, COMSIG_MOVABLE_MOVED) RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(pickup_ores)) listening_to = user -/obj/item/storage/bag/ore/dropped() - . = ..() +/obj/item/storage/bag/ore/proc/end_listening() + SIGNAL_HANDLER // COMSIG_CYBORG_ITEM_DEACTIVATED if(listening_to) UnregisterSignal(listening_to, COMSIG_MOVABLE_MOVED) listening_to = null + +/obj/item/storage/bag/ore/dropped() + . = ..() + end_listening() + /obj/item/storage/bag/ore/proc/pickup_ores(mob/living/user) SIGNAL_HANDLER // COMSIG_MOVABLE_MOVED var/turf/simulated/floor/plating/asteroid/tile = get_turf(user) @@ -208,6 +217,16 @@ name = "cyborg mining satchel" flags = NODROP +/obj/item/storage/bag/ore/cyborg/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_CYBORG_ITEM_ACTIVATED, PROC_REF(begin_listening)) + RegisterSignal(src, COMSIG_CYBORG_ITEM_DEACTIVATED, PROC_REF(end_listening)) + +/obj/item/storage/bag/ore/cyborg/Destroy() + UnregisterSignal(src, COMSIG_CYBORG_ITEM_ACTIVATED) + UnregisterSignal(src, COMSIG_CYBORG_ITEM_DEACTIVATED) + return ..() + /// miners, your messiah has arrived /obj/item/storage/bag/ore/holding name = "mining satchel of holding" diff --git a/code/game/turfs/simulated/floor/transparent.dm b/code/game/turfs/simulated/floor/transparent.dm index ba8a4c85d6c..813d5cd8c5e 100644 --- a/code/game/turfs/simulated/floor/transparent.dm +++ b/code/game/turfs/simulated/floor/transparent.dm @@ -50,12 +50,9 @@ R = user.get_inactive_hand() else if(isrobot(user)) var/mob/living/silicon/robot/robouser = user - if(istype(robouser.module_state_1, /obj/item/stack/sheet/metal)) - R = robouser.module_state_1 - else if(istype(robouser.module_state_2, /obj/item/stack/sheet/metal)) - R = robouser.module_state_2 - else if(istype(robouser.module_state_3, /obj/item/stack/sheet/metal)) - R = robouser.module_state_3 + var/metal_slot = robouser.get_module_by_item(/obj/item/stack/sheet/metal) + if(metal_slot) + R = robouser.all_active_items[metal_slot] if(!istype(R, /obj/item/stack/sheet/metal) || R.get_amount() < 2) to_chat(user, "You also need to hold two sheets of metal to dismantle \the [src]!") diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index ce008def807..e73bc76d7f5 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -143,8 +143,8 @@ else if(isrobot(AM)) var/mob/living/silicon/robot/R = AM - if(istype(R.module_active, /obj/item/pickaxe)) - attack_by(R.module_active, R) + if(istype(R.selected_item, /obj/item/pickaxe)) + attack_by(R.selected_item, R) else if(ismecha(AM)) var/obj/mecha/M = AM diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 1d0afd9fbfc..8065f2ad30c 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2845,7 +2845,7 @@ R.module.modules += I I.loc = R.module R.module.rebuild_modules() - R.activate_module(I) + R.activate_item(I) R.module.fix_modules() if(number == 1) diff --git a/code/modules/mob/living/silicon/robot/robot_inventory.dm b/code/modules/mob/living/silicon/robot/robot_inventory.dm index 49f38ab2fd2..7397f30a6b7 100644 --- a/code/modules/mob/living/silicon/robot/robot_inventory.dm +++ b/code/modules/mob/living/silicon/robot/robot_inventory.dm @@ -3,15 +3,18 @@ //Returns the thing in our active hand (whatever is in our active module-slot, in this case) /mob/living/silicon/robot/get_active_hand() - return module_active + return selected_item /mob/living/silicon/robot/get_all_slots() - return list(module_state_1, module_state_2, module_state_3) + return all_active_items /*-------TODOOOOOOOOOO--------*/ /mob/living/silicon/robot/proc/uneq_module(obj/item/O) if(!O) - return 0 + return FALSE + var/index = all_active_items.Find(O) + if(!index) + return FALSE O.mouse_opacity = MOUSE_OPACITY_OPAQUE @@ -24,23 +27,25 @@ for(var/X in O.actions) // Remove assocated actions var/datum/action/A = X A.Remove(src) + all_active_items[index] = CYBORG_EMPTY_MODULE + SEND_SIGNAL(O, COMSIG_CYBORG_ITEM_DEACTIVATED, src) + selected_item = null + var/atom/movable/screen/robot/active_module/screen = inventory_screens[index] + screen.icon_state = screen.deactivated_icon_string - if(module_active == O) - module_active = null - if(module_state_1 == O) - inv1.icon_state = "inv1" - module_state_1 = null - else if(module_state_2 == O) - inv2.icon_state = "inv2" - module_state_2 = null - else if(module_state_3 == O) - module_state_3 = null - inv3.icon_state = "inv3" if(hud_used) hud_used.update_robot_modules_display() - return 1 + return TRUE +/* +* Returns the index of the first open module slot a borg has, or FALSE if they already have a full hotbar. +*/ +/mob/living/silicon/robot/proc/get_open_slot() + for(var/i in 1 to CYBORG_MAX_MODULES) + if(!all_active_items[i]) // Since CYBORG_EMPTY_MODULE is 0 this has to be a ! check. + return i + return FALSE -/mob/living/silicon/robot/proc/activate_module(obj/item/O) +/mob/living/silicon/robot/proc/activate_item(obj/item/O) if(!(locate(O) in module.modules) && !(O in module.emag_modules)) return if(activated(O)) @@ -53,32 +58,22 @@ if((cell.charge * 100 / cell.maxcharge) < B.powerneeded) to_chat(src, "Not enough power to activate [B.name]!") return - if(!module_state_1) - O.mouse_opacity = initial(O.mouse_opacity) - module_state_1 = O - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - O.screen_loc = inv1.screen_loc - contents += O - set_actions(O) - else if(!module_state_2) - O.mouse_opacity = initial(O.mouse_opacity) - module_state_2 = O - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - O.screen_loc = inv2.screen_loc - contents += O - set_actions(O) - else if(!module_state_3) - O.mouse_opacity = initial(O.mouse_opacity) - module_state_3 = O - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - O.screen_loc = inv3.screen_loc - contents += O - set_actions(O) - else + var/slot = get_open_slot() + if(!slot) to_chat(src, "You need to disable a module first!") + return + SEND_SIGNAL(O, COMSIG_CYBORG_ITEM_ACTIVATED, src) + O.mouse_opacity = initial(O.mouse_opacity) + all_active_items[slot] = O + deactivate_all() + var/atom/movable/screen/robot/active_module/to_activate = inventory_screens[slot] + to_activate.activate() + selected_item = O + O.layer = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_PLANE + O.screen_loc = CYBORG_HUD_LOCATIONS[slot] + contents += O + set_actions(O) observer_screen_update(O, add = TRUE) check_module_damage(FALSE) update_icons() @@ -89,33 +84,25 @@ A.Grant(src) /mob/living/silicon/robot/proc/uneq_active() - uneq_module(module_active) + uneq_module(selected_item) /mob/living/silicon/robot/proc/uneq_all() - uneq_module(module_state_1) - uneq_module(module_state_2) - uneq_module(module_state_3) + for(var/obj/item/O in all_active_items) + uneq_module(O) -/mob/living/silicon/robot/proc/uneq_numbered(module) - if(module < 1 || module > 3) return +/// Deactivate all the screen objects, removing the green background from all of them +/mob/living/silicon/robot/proc/deactivate_all() + for(var/atom/movable/screen/robot/active_module/to_deactivate in inventory_screens) + to_deactivate.deactivate() - switch(module) - if(1) - uneq_module(module_state_1) - if(2) - uneq_module(module_state_2) - if(3) - uneq_module(module_state_3) +/mob/living/silicon/robot/proc/uneq_numbered(index) + if(module < 1 || module > CYBORG_MAX_MODULES) + return + uneq_module(all_active_items[index]) +/// Returns true if O is in the cyborg's hotbar, false otherwise /mob/living/silicon/robot/proc/activated(obj/item/O) - if(module_state_1 == O) - return 1 - else if(module_state_2 == O) - return 1 - else if(module_state_3 == O) - return 1 - else - return 0 + return (O in all_active_items) /mob/living/silicon/robot/drop_item() var/obj/item/gripper/G = get_active_hand() @@ -126,124 +113,94 @@ //Helper procs for cyborg modules on the UI. //These are hackish but they help clean up code elsewhere. -//module_selected(module) - Checks whether the module slot specified by "module" is currently selected. -/mob/living/silicon/robot/proc/module_selected(module) //Module is 1-3 - return module == get_selected_module() +//module_selected(module) - Checks whether the module slot specified by "index" is currently selected. +/mob/living/silicon/robot/proc/module_selected(index) //Index is 1-3 + return index == get_selected_module() -//module_active(module) - Checks whether there is a module active in the slot specified by "module". -/mob/living/silicon/robot/proc/module_active(module) //Module is 1-3 - if(module < 1 || module > 3) return 0 +//is_module_active(module) - Checks whether there is a item active in the slot specified by "index". +/mob/living/silicon/robot/proc/is_module_active(index) //Index is 1-3 + return all_active_items[index] - switch(module) - if(1) - if(module_state_1) - return 1 - if(2) - if(module_state_2) - return 1 - if(3) - if(module_state_3) - return 1 - return 0 - -//get_selected_module() - Returns the slot number of the currently selected module. Returns 0 if no modules are selected. +//get_selected_module() - Returns the slot number of the currently selected item. Returns 0 if no items are selected. /mob/living/silicon/robot/proc/get_selected_module() - if(module_state_1 && module_active == module_state_1) - return 1 - else if(module_state_2 && module_active == module_state_2) - return 2 - else if(module_state_3 && module_active == module_state_3) - return 3 + if(!selected_item) + return FALSE + return all_active_items.Find(selected_item) - return 0 +/* +* Returns a list of the slots of a cyborg's hotbar that have an item in it, or false if all are empty +*/ +/mob/living/silicon/robot/proc/get_filled_modules() + var/list/indicies = list() + for(var/i in 1 to length(all_active_items)) + if(!all_active_items[i]) + continue + indicies += i + if(!length(indicies)) + return FALSE + return indicies //select_module(module) - Selects the module slot specified by "module" /mob/living/silicon/robot/proc/select_module(module) //Module is 1-3 - if(module < 1 || module > 3) return - - if(!module_active(module)) return - - switch(module) - if(1) - if(module_active != module_state_1) - inv1.icon_state = "inv1 +a" - inv2.icon_state = "inv2" - inv3.icon_state = "inv3" - module_active = module_state_1 - if(2) - if(module_active != module_state_2) - inv1.icon_state = "inv1" - inv2.icon_state = "inv2 +a" - inv3.icon_state = "inv3" - module_active = module_state_2 - if(3) - if(module_active != module_state_3) - inv1.icon_state = "inv1" - inv2.icon_state = "inv2" - inv3.icon_state = "inv3 +a" - module_active = module_state_3 + if(module < 1 || module > CYBORG_MAX_MODULES) + return + selected_item = null + for(var/i in 1 to CYBORG_MAX_MODULES) + var/atom/movable/screen/robot/active_module/inventory = inventory_screens[i] + if(module == i) + inventory.activate() + selected_item = all_active_items[module] + else + inventory.deactivate() update_icons() return //deselect_module(module) - Deselects the module slot specified by "module" /mob/living/silicon/robot/proc/deselect_module(module) //Module is 1-3 - if(module < 1 || module > 3) return - - switch(module) - if(1) - if(module_active == module_state_1) - inv1.icon_state = "inv1" - module_active = null - if(2) - if(module_active == module_state_2) - inv2.icon_state = "inv2" - module_active = null - if(3) - if(module_active == module_state_3) - inv3.icon_state = "inv3" - module_active = null + if(module < 1 || module > CYBORG_MAX_MODULES) + return + selected_item = null + for(var/i in 1 to CYBORG_MAX_MODULES) + var/atom/movable/screen/robot/active_module/inventory = inventory_screens[i] + inventory.deactivate() update_icons() return //toggle_module(module) - Toggles the selection of the module slot specified by "module". /mob/living/silicon/robot/proc/toggle_module(module) //Module is 1-3 - if(module < 1 || module > 3) return - + if(module < 1 || module > CYBORG_MAX_MODULES) + return if(module_selected(module)) deselect_module(module) - else - if(module_active(module)) - select_module(module) - else - deselect_module(get_selected_module()) //If we can't do select anything, at least deselect the current module. - return + return + select_module(module) -//cycle_modules() - Cycles through the list of selected modules. +//cycle_modules() - Cycles through the cyborg's modules, or selects the first module if none are selected. /mob/living/silicon/robot/proc/cycle_modules() - var/slot_start = get_selected_module() - if(slot_start) deselect_module(slot_start) //Only deselect if we have a selected slot. + var/active_slot = 0 + for(var/atom/movable/screen/robot/active_module/item in inventory_screens) + if(item.active) + active_slot = item.module_number + var/next_slot = (active_slot % CYBORG_MAX_MODULES) + 1 + select_module(next_slot) - var/slot_num - if(slot_start == 0) - slot_num = 0 - slot_start = 3 - else - slot_num = slot_start - - do - slot_num++ - if(slot_num > 3) slot_num = 1 //Wrap around. - if(module_active(slot_num)) - select_module(slot_num) - return - while(slot_start != slot_num) //If we wrap around without finding any free slots, just give up. - return /mob/living/silicon/robot/unequip_to(obj/item/target, atom/destination, force = FALSE, silent = FALSE, drop_inventory = TRUE, no_move = FALSE) - if(target == module_active) + if(target == selected_item) uneq_active(target) return ..() +/* +* Tries to find and return the module number/index of an item in a borg's inventory using a path +* to_find - ther path of an item that you want to check if it is in any of the borg's 3 active slots +* Returns the index, or FALSE if it's not active +*/ +/mob/living/silicon/robot/proc/get_module_by_item(obj/item/to_check) + for(var/i in 1 to CYBORG_MAX_MODULES) + if(istype(all_active_items[i], to_check.type)) + return i + return FALSE + /mob/living/silicon/robot/proc/update_module_icon() if(!hands) return diff --git a/code/modules/mob/living/silicon/robot/robot_life.dm b/code/modules/mob/living/silicon/robot/robot_life.dm index f87709d72f1..d55508fdbea 100644 --- a/code/modules/mob/living/silicon/robot/robot_life.dm +++ b/code/modules/mob/living/silicon/robot/robot_life.dm @@ -11,7 +11,6 @@ if(.) handle_robot_hud_updates() handle_robot_cell() - update_items() /mob/living/silicon/robot/proc/handle_robot_cell() @@ -109,17 +108,6 @@ -/mob/living/silicon/robot/proc/update_items() // What in the Sam hell is this? - if(client) - for(var/obj/I in get_all_slots()) - client.screen |= I - if(module_state_1) - module_state_1:screen_loc = ui_inv1 - if(module_state_2) - module_state_2:screen_loc = ui_inv2 - if(module_state_3) - module_state_3:screen_loc = ui_inv3 - //Robots on fire /mob/living/silicon/robot/handle_fire() . = ..() diff --git a/code/modules/mob/living/silicon/robot/robot_mob.dm b/code/modules/mob/living/silicon/robot/robot_mob.dm index 40e5b89fe36..5ec02a9d637 100644 --- a/code/modules/mob/living/silicon/robot/robot_mob.dm +++ b/code/modules/mob/living/silicon/robot/robot_mob.dm @@ -21,18 +21,16 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( // HUD stuff. var/atom/movable/screen/hands = null - var/atom/movable/screen/inv1 = null - var/atom/movable/screen/inv2 = null - var/atom/movable/screen/inv3 = null + var/list/inventory_screens = list() var/atom/movable/screen/lamp_button = null var/atom/movable/screen/thruster_button = null - // 3 Modules can be activated at any one time. + /// A reference to the type of cyborg it is, i.e. Engineering, Security, Medical etc. var/obj/item/robot_module/module = null - var/module_active = null - var/module_state_1 = null - var/module_state_2 = null - var/module_state_3 = null + /// The item the borg currently has selected, or null if nothing is selected + var/selected_item + /// The list of up to 3 items the borg can have "equipped". The contents will either be CYBORG_EMPTY_MODULE for nothing, or the item selected + var/list/all_active_items = list(CYBORG_EMPTY_MODULE, CYBORG_EMPTY_MODULE, CYBORG_EMPTY_MODULE) var/obj/item/radio/borg/radio = null var/mob/living/silicon/ai/connected_ai = null @@ -1292,29 +1290,29 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( /mob/living/silicon/robot/Topic(href, href_list) if(..()) - return 1 + return TRUE if(usr != src) - return 1 + return TRUE if(href_list["mach_close"]) var/t1 = "window=[href_list["mach_close"]]" unset_machine() src << browse(null, t1) - return 1 + return TRUE if(href_list["mod"]) var/obj/item/O = locate(href_list["mod"]) if(istype(O) && (O.loc == src)) O.attack_self__legacy__attackchain(src) - return 1 + return TRUE if(href_list["act"]) var/obj/item/O = locate(href_list["act"]) if(!istype(O) || !(O.loc == src || O.loc == src.module)) - return 1 + return TRUE - activate_module(O) + activate_item(O) //Show alerts window if user clicked on "Show alerts" in chat if(href_list["showalerts"]) @@ -1324,22 +1322,11 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( if(href_list["deact"]) var/obj/item/O = locate(href_list["deact"]) if(activated(O)) - if(module_state_1 == O) - module_state_1 = null - contents -= O - else if(module_state_2 == O) - module_state_2 = null - contents -= O - else if(module_state_3 == O) - module_state_3 = null - contents -= O - else - to_chat(src, "Module isn't activated.") + uneq_module(O) else to_chat(src, "Module isn't activated") - return 1 - - return 1 + return TRUE + return TRUE /mob/living/silicon/robot/proc/radio_menu() radio.interact(src) @@ -1660,7 +1647,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( /mob/living/silicon/robot/destroyer/borg_icons() if(base_icon == "") base_icon = icon_state - if(module_active && istype(module_active,/obj/item/borg/destroyer/mobility)) + if(selected_item && istype(selected_item, /obj/item/borg/destroyer/mobility)) icon_state = "[base_icon]-roll" else icon_state = base_icon @@ -1738,27 +1725,21 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( return /mob/living/silicon/robot/proc/check_module_damage(makes_sound = TRUE) - if(modules_break) - if(health < 50) //Gradual break down of modules as more damage is sustained - if(uneq_module(module_state_3)) - if(makes_sound) - audible_message("[src] sounds an alarm! \"SYSTEM ERROR: Module 3 OFFLINE.\"") - playsound(loc, 'sound/machines/warning-buzzer.ogg', 50, TRUE) - to_chat(src, "SYSTEM ERROR: Module 3 OFFLINE.") - - if(health < 0) - if(uneq_module(module_state_2)) - if(makes_sound) - audible_message("[src] sounds an alarm! \"SYSTEM ERROR: Module 2 OFFLINE.\"") - playsound(loc, 'sound/machines/warning-buzzer.ogg', 60, TRUE) - to_chat(src, "SYSTEM ERROR: Module 2 OFFLINE.") - - if(health < -50) - if(uneq_module(module_state_1)) - if(makes_sound) - audible_message("[src] sounds an alarm! \"CRITICAL ERROR: All modules OFFLINE.\"") - playsound(loc, 'sound/machines/warning-buzzer.ogg', 75, TRUE) - to_chat(src, "CRITICAL ERROR: All modules OFFLINE.") + if(!modules_break) + return + var/list/broken_modules = list() + if(health < 50) //Gradual break down of modules as more damage is sustained + broken_modules += CYBORG_MODULE_THREE + if(health < 0) + broken_modules += CYBORG_MODULE_TWO + if(health < -50) + broken_modules += CYBORG_MODULE_ONE + for(var/i in 1 to length(broken_modules)) + if(uneq_module(all_active_items[broken_modules[i]])) // Since a full list of broken modules would be (3, 2, 1) it has to be a bit wonky + if(makes_sound) + audible_message("[src] sounds an alarm! \"SYSTEM ERROR: Module [broken_modules[i]] OFFLINE.\"") + playsound(loc, 'sound/machines/warning-buzzer.ogg', 50, TRUE) + to_chat(src, "SYSTEM ERROR: Module [broken_modules[i]] OFFLINE.") /mob/living/silicon/robot/advanced_reagent_vision() return has_advanced_reagent_vision diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index 96486d79894..9c2d41c8802 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -14,7 +14,7 @@ // Counteract magboot slow in 0G. if(!has_gravity(src) && HAS_TRAIT(src, TRAIT_MAGPULSE)) . -= 2 // The slowdown value on the borg magpulse. - if(module_active && istype(module_active,/obj/item/borg/destroyer/mobility)) + if(selected_item && istype(selected_item, /obj/item/borg/destroyer/mobility)) . -= 3 . = min(., slowdown_cap) diff --git a/code/modules/tgui/states/inventory_state.dm b/code/modules/tgui/states/inventory_state.dm index 7c4002b6c7d..3f8e1db5413 100644 --- a/code/modules/tgui/states/inventory_state.dm +++ b/code/modules/tgui/states/inventory_state.dm @@ -10,7 +10,7 @@ GLOBAL_DATUM_INIT(inventory_state, /datum/ui_state/inventory_state, new) if(!(src_object in user)) if(issilicon(user)) var/mob/living/silicon/robot/R = user - if(src_object in R.module_active) // Magnetic grippers + if(src_object in R.selected_item) // Magnetic grippers return user.shared_ui_interaction(src_object) return UI_CLOSE return user.shared_ui_interaction(src_object) diff --git a/paradise.dme b/paradise.dme index 8f90f806874..a6e2dc64d22 100644 --- a/paradise.dme +++ b/paradise.dme @@ -118,6 +118,7 @@ #include "code\__DEFINES\rust_g.dm" #include "code\__DEFINES\shuttle_defines.dm" #include "code\__DEFINES\sight.dm" +#include "code\__DEFINES\silicon_defines.dm" #include "code\__DEFINES\sound_defines.dm" #include "code\__DEFINES\speech_channels.dm" #include "code\__DEFINES\spell_defines.dm"