Files
2024-01-05 00:28:56 -03:00

441 lines
14 KiB
Plaintext

//These procs handle putting stuff in your hand. It's probably best to use these rather than setting stuff manually
//as they handle all relevant stuff like adding it to the player's screen and such
/**
* Returns the thing in our active hand (whatever is in our active module-slot, in this case)
*
* Arguments
* * get_gripper - If the active module is a gripper, should we return the gripper or the contained item? (if the gripper contains nothing, returns the gripper anyways)
*/
/mob/living/silicon/robot/get_active_held_item(get_gripper = FALSE)
var/item = module_active
// snowflake handler for the gripper
if(istype(item, /obj/item/gripper) && !get_gripper)
var/obj/item/gripper/G = item
if(G.wrapped)
if(G.wrapped.loc != G)
G.wrapped = null
return module_active
item = G.wrapped
return item
return module_active
/**
* Parent proc - triggers when an item/module is unequipped from a cyborg.
*/
/obj/item/proc/cyborg_unequip(mob/user)
return
/**
* Finds the first available slot and attemps to put item item_module in it.
*
* Arguments
* * item_module - the item being equipped to a slot.
*/
/mob/living/silicon/robot/proc/activate_module(obj/item/item_module)
if(QDELETED(item_module))
CRASH("activate_module called with improper item_module")
if(!(item_module in module.modules))
CRASH("activate_module called with item_module not in module.modules")
if(activated(item_module))
to_chat(src, "<span class='warning'>That module is already activated.</span>")
return FALSE
if(disabled_modules & BORG_MODULE_ALL_DISABLED)
to_chat(src, "<span class='warning'>All modules are disabled!</span>")
return FALSE
/// What's the first free slot for the borg?
var/first_free_slot = !held_items[1] ? 1 : (!held_items[2] ? 2 : (!held_items[3] ? 3 : null))
if(!first_free_slot || is_invalid_module_number(first_free_slot))
to_chat(src, "<span class='warning'>Deactivate a module first!</span>")
return FALSE
return equip_module_to_slot(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
if(!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(1)
item_module.screen_loc = inv1.screen_loc
if(2)
item_module.screen_loc = inv2.screen_loc
if(3)
item_module.screen_loc = inv3.screen_loc
held_items[module_num] = item_module
item_module.equipped(src, ITEM_SLOT_HANDS)
item_module.mouse_opacity = initial(item_module.mouse_opacity)
item_module.layer = ABOVE_HUD_LAYER
item_module.plane = ABOVE_HUD_PLANE
item_module.forceMove(src)
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()
observer_screen_update(item_module, TRUE)
if(storage_was_closed)
hud_used.toggle_show_robot_modules()
return TRUE
/**
* 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")
if(!(item_module in module.modules))
CRASH("unequip_module_from_slot called with item_module not in module.modules")
item_module.mouse_opacity = MOUSE_OPACITY_OPAQUE
if(istype(item_module, /obj/item/storage/bag/tray/))
SEND_SIGNAL(item_module, COMSIG_TRY_STORAGE_QUICK_EMPTY)
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()
//CITADEL EDIT reee proc, Dogborg modules
if(istype(item_module, /obj/item/gun/energy/laser/cyborg))
laser = FALSE
update_icons()
if(istype(item_module, /obj/item/gun/energy/disabler/cyborg) || istype(item_module, /obj/item/gun/energy/e_gun/advtaser/cyborg))
disabler = FALSE
update_icons() //PUT THE GUN AWAY
if(istype(item_module, /obj/item/dogborg/sleeper))
sleeper_g = FALSE
sleeper_r = FALSE
update_icons()
var/obj/item/dogborg/sleeper/S = item_module
S.go_out() //this should stop edgecase deletions
//END CITADEL EDIT
if(client)
client.screen -= item_module
if(module_active == item_module)
module_active = null
switch(module_num)
if(1)
if(!(disabled_modules & BORG_MODULE_ALL_DISABLED))
inv1.icon_state = initial(inv1.icon_state)
if(2)
if(!(disabled_modules & BORG_MODULE_TWO_DISABLED))
inv2.icon_state = initial(inv2.icon_state)
if(3)
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(module) //Return item to module 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
/**
* Breaks the slot number, changing the icon.
*
* Arguments
* * module_num - the slot number being repaired.
*/
/mob/living/silicon/robot/proc/break_cyborg_slot(module_num)
if(is_invalid_module_number(module_num, TRUE))
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
return FALSE
switch(module_num)
if(1)
if(disabled_modules & BORG_MODULE_ALL_DISABLED)
return FALSE
inv1.icon_state = "[initial(inv1.icon_state)] +b"
disabled_modules |= BORG_MODULE_ALL_DISABLED
playsound(src, 'sound/machines/warning-buzzer.ogg', 75, TRUE, TRUE)
audible_message("<span class='warning'>[src] sounds an alarm! \"CRITICAL ERROR: ALL modules OFFLINE.\"</span>")
if(builtInCamera)
builtInCamera.status = FALSE
to_chat(src, "<span class='userdanger'>CRITICAL ERROR: Built in security camera OFFLINE.</span>")
to_chat(src, "<span class='userdanger'>CRITICAL ERROR: ALL modules OFFLINE.</span>")
if(2)
if(disabled_modules & BORG_MODULE_TWO_DISABLED)
return FALSE
inv2.icon_state = "[initial(inv2.icon_state)] +b"
disabled_modules |= BORG_MODULE_TWO_DISABLED
playsound(src, 'sound/machines/warning-buzzer.ogg', 60, TRUE, TRUE)
audible_message("<span class='warning'>[src] sounds an alarm! \"SYSTEM ERROR: Module [module_num] OFFLINE.\"</span>")
to_chat(src, "<span class='userdanger'>SYSTEM ERROR: Module [module_num] OFFLINE.</span>")
if(3)
if(disabled_modules & BORG_MODULE_THREE_DISABLED)
return FALSE
inv3.icon_state = "[initial(inv3.icon_state)] +b"
disabled_modules |= BORG_MODULE_THREE_DISABLED
playsound(src, 'sound/machines/warning-buzzer.ogg', 50, TRUE, TRUE)
audible_message("<span class='warning'>[src] sounds an alarm! \"SYSTEM ERROR: Module [module_num] OFFLINE.\"</span>")
to_chat(src, "<span class='userdanger'>SYSTEM ERROR: Module [module_num] OFFLINE.</span>")
return TRUE
/**
* Breaks all of a cyborg's slots.
*/
/mob/living/silicon/robot/proc/break_all_cyborg_slots()
for(var/cyborg_slot in 1 to 3)
break_cyborg_slot(cyborg_slot)
/**
* Repairs the slot number, updating the icon.
*
* Arguments
* * module_num - the module number being repaired.
*/
/mob/living/silicon/robot/proc/repair_cyborg_slot(module_num)
if(is_invalid_module_number(module_num, TRUE))
return FALSE
switch(module_num)
if(1)
if(!(disabled_modules & BORG_MODULE_ALL_DISABLED))
return FALSE
inv1.icon_state = initial(inv1.icon_state)
disabled_modules &= ~BORG_MODULE_ALL_DISABLED
if(builtInCamera)
builtInCamera.status = TRUE
to_chat(src, "<span class='notice'>You hear your built in security camera focus adjust as it comes back online!</span>")
if(2)
if(!(disabled_modules & BORG_MODULE_TWO_DISABLED))
return FALSE
inv2.icon_state = initial(inv2.icon_state)
disabled_modules &= ~BORG_MODULE_TWO_DISABLED
if(3)
if(!(disabled_modules & BORG_MODULE_THREE_DISABLED))
return FALSE
inv3.icon_state = initial(inv3.icon_state)
disabled_modules &= ~BORG_MODULE_THREE_DISABLED
to_chat(src, "<span class='notice'>ERROR CLEARED: Module [module_num] back online.</span>")
return TRUE
/**
* Repairs all slots. Unbroken slots are unaffected.
*/
/mob/living/silicon/robot/proc/repair_all_cyborg_slots()
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.
*
* Will always consider dropping gripper contents first.
*/
/mob/living/silicon/robot/proc/uneq_active()
if(module_active)
var/obj/item/gripper/gripper = get_active_held_item(TRUE)
if(istype(gripper) && gripper.drop_held())
return
unequip_module_from_slot(module_active, get_selected_module())
/**
* Unequips all held items.
*/
/mob/living/silicon/robot/proc/uneq_all()
for(var/cyborg_slot in 1 to 3)
if(!held_items[cyborg_slot])
continue
unequip_module_from_slot(held_items[cyborg_slot], cyborg_slot)
/**
* Checks if the item is currently in a slot.
*
* If the item is found in a slot, this returns TRUE. Otherwise, it returns FALSE
* Modified to accept items inside of grippers, used for `code\modules\tgui\states\hands.dm:27`
* Arguments
* * item_module - the item being checked
*/
/mob/living/silicon/robot/proc/activated(obj/item/item_module)
if(get_active_held_item() == item_module || (item_module in held_items))
return TRUE
return FALSE
/**
* Checks if the provided module number is a valid number.
*
* If the number is between 1 and 3 (if check_all_slots is true) or between 1 and the number of disabled
* modules (if check_all_slots is false), then it returns FALSE. Otherwise, it returns TRUE.
* Arguments
* * module_num - the passed module num that is checked for validity.
* * check_all_slots - TRUE = the proc checks all slots | FALSE = the proc only checks un-disabled slots
*/
/mob/living/silicon/robot/proc/is_invalid_module_number(module_num, check_all_slots = FALSE)
if(!module_num)
return TRUE
/// The number of module slots we're checking
var/max_number = 3
if(!check_all_slots)
if(disabled_modules & BORG_MODULE_ALL_DISABLED)
max_number = 0
else if(disabled_modules & BORG_MODULE_TWO_DISABLED)
max_number = 1
else if(disabled_modules & BORG_MODULE_THREE_DISABLED)
max_number = 2
return module_num < 1 || module_num > max_number
/**
* Returns the slot number of the selected module, or zero if no modules are selected.
*/
/mob/living/silicon/robot/proc/get_selected_module()
if(module_active)
return held_items.Find(module_active)
return FALSE
/**
* Selects the module in the slot module_num.
* Arguments
* * module_num - the slot number being selected
*/
/mob/living/silicon/robot/proc/select_module(module_num)
if(is_invalid_module_number(module_num) || !held_items[module_num]) //If the slot number is invalid, or there's nothing there, we have nothing to equip
return FALSE
switch(module_num)
if(1)
if(module_active != held_items[module_num])
inv1.icon_state = "[initial(inv1.icon_state)] +a"
if(2)
if(module_active != held_items[module_num])
inv2.icon_state = "[initial(inv2.icon_state)] +a"
if(3)
if(module_active != held_items[module_num])
inv3.icon_state = "[initial(inv3.icon_state)] +a"
module_active = held_items[module_num]
return TRUE
/**
* Deselects the module in the slot module_num.
* Arguments
* * module_num - the slot number being de-selected
*/
/mob/living/silicon/robot/proc/deselect_module(module_num)
switch(module_num)
if(1)
if(module_active == held_items[module_num])
inv1.icon_state = initial(inv1.icon_state)
if(2)
if(module_active == held_items[module_num])
inv2.icon_state = initial(inv2.icon_state)
if(3)
if(module_active == held_items[module_num])
inv3.icon_state = initial(inv3.icon_state)
module_active = null
return TRUE
/**
* Toggles selection of the module in the slot module_num.
* Arguments
* * module_num - the slot number being toggled
*/
/mob/living/silicon/robot/proc/toggle_module(module_num)
if(is_invalid_module_number(module_num))
return FALSE
if(module_num == get_selected_module())
deselect_module(module_num)
return TRUE
if(module_active != held_items[module_num])
deselect_module(get_selected_module())
return select_module(module_num)
/**
* Cycles through the list of enabled modules, deselecting the current one and selecting the next one.
*/
/mob/living/silicon/robot/proc/cycle_modules()
var/slot_start = get_selected_module()
var/slot_num
if(slot_start)
deselect_module(slot_start) //Only deselect if we have a selected slot.
slot_num = slot_start + 1
else
slot_num = 1
slot_start = 4
while(slot_num != slot_start) //If we wrap around without finding any free slots, just give up.
if(select_module(slot_num))
return
slot_num++
if(slot_num > 4) // not >3 otherwise cycling with just one item on module 3 wouldn't work
slot_num = 1 //Wrap around.
/mob/living/silicon/robot/swap_hand()
cycle_modules()
/mob/living/silicon/robot/can_hold_items(obj/item/I)
return (I && (I in module.modules)) //Only if it's part of our module.