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"