diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm index 495d47129c3..87e0be05820 100644 --- a/code/__DEFINES/robots.dm +++ b/code/__DEFINES/robots.dm @@ -55,3 +55,8 @@ #define ASSEMBLY_FIFTH_STEP 4 #define BORG_LAMP_CD_RESET -1 //special value to reset cyborg's lamp_cooldown + +/// Defines for whether or not module slots are broken. +#define BORG_MODULE_ALL_DISABLED (1<<0) +#define BORG_MODULE_TWO_DISABLED (1<<1) +#define BORG_MODULE_THREE_DISABLED (1<<2) diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index 5de7edc5410..0c1c96a4d53 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -62,11 +62,9 @@ /obj/machinery/computer/aifixer/proc/Fix() use_power(1000) - occupier.adjustOxyLoss(-5, 0) - occupier.adjustFireLoss(-5, 0) - occupier.adjustToxLoss(-5, 0) + occupier.adjustOxyLoss(-5, 0, FALSE) + occupier.adjustFireLoss(-5, 0, FALSE) occupier.adjustBruteLoss(-5, 0) - occupier.updatehealth() if(occupier.health >= 0 && occupier.stat == DEAD) occupier.revive(full_heal = FALSE, admin_revive = FALSE) if(!occupier.radio_enabled) diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm index 15bb5f2f1fa..3f0ce34d971 100644 --- a/code/modules/mob/living/silicon/damage_procs.dm +++ b/code/modules/mob/living/silicon/damage_procs.dm @@ -9,9 +9,6 @@ adjustBruteLoss(damage_amount, forced = forced) if(BURN) adjustFireLoss(damage_amount, forced = forced) - if(OXY) - if(damage < 0 || forced) //we shouldn't be taking oxygen damage through this proc, but we'll let it heal. - adjustOxyLoss(damage_amount, forced = forced) return 1 @@ -30,14 +27,26 @@ /mob/living/silicon/setCloneLoss(amount, updating_health = TRUE, forced = FALSE) return FALSE -/mob/living/silicon/adjustStaminaLoss(amount, updating_health = TRUE, forced = FALSE)//immune to stamina damage. +/mob/living/silicon/adjustStaminaLoss(amount, updating_health = TRUE, forced = FALSE) //immune to stamina damage. return FALSE /mob/living/silicon/setStaminaLoss(amount, updating_health = TRUE) return FALSE -/mob/living/silicon/adjustOrganLoss(slot, amount, maximum = 500) +/mob/living/silicon/adjustOrganLoss(slot, amount, maximum = 500) //immune to organ damage (no organs, duh) return FALSE /mob/living/silicon/setOrganLoss(slot, amount) return FALSE + +/mob/living/silicon/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE) //immune to oxygen damage + if(istype(src, /mob/living/silicon/ai)) //ais are snowflakes and use oxyloss for being in AI cards and having no battery + return ..() + + return FALSE + +/mob/living/silicon/setOxyLoss(amount, updating_health = TRUE, forced = FALSE) + if(istype(src, /mob/living/silicon/ai)) //ditto + return ..() + + return FALSE diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm index 3272173da24..e21b73ad1cd 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -86,15 +86,6 @@ /mob/living/silicon/pai/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE) return take_holo_damage(amount) -/mob/living/silicon/pai/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE) - return FALSE - -/mob/living/silicon/pai/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE) - return FALSE - -/mob/living/silicon/pai/adjustCloneLoss(amount, updating_health = TRUE, forced = FALSE) - return FALSE - /mob/living/silicon/pai/adjustStaminaLoss(amount, updating_health, forced = FALSE) if(forced) take_holo_damage(amount) @@ -106,27 +97,3 @@ /mob/living/silicon/pai/getFireLoss() return emittermaxhealth - emitterhealth - -/mob/living/silicon/pai/getToxLoss() - return FALSE - -/mob/living/silicon/pai/getOxyLoss() - return FALSE - -/mob/living/silicon/pai/getCloneLoss() - return FALSE - -/mob/living/silicon/pai/getStaminaLoss() - return FALSE - -/mob/living/silicon/pai/setCloneLoss() - return FALSE - -/mob/living/silicon/pai/setStaminaLoss(amount, updating_health = TRUE) - return FALSE - -/mob/living/silicon/pai/setToxLoss() - return FALSE - -/mob/living/silicon/pai/setOxyLoss() - return FALSE diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index 60ac3f975cd..e7bed84146c 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -1,215 +1,387 @@ //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) +/** + * Returns the thing in our active hand (whatever is in our active module-slot, in this case) + */ /mob/living/silicon/robot/get_active_held_item() return module_active +/** + * Parent proc - triggers when an item/module is unequipped from a cyborg. + */ /obj/item/proc/cyborg_unequip(mob/user) return -/mob/living/silicon/robot/proc/uneq_module(obj/item/O) - if(!O) - return 0 - O.mouse_opacity = MOUSE_OPACITY_OPAQUE - if(istype(O, /obj/item/borg/sight)) - var/obj/item/borg/sight/S = O - sight_mode &= ~S.sight_mode - update_sight() - else if(istype(O, /obj/item/storage/bag/tray/)) - SEND_SIGNAL(O, COMSIG_TRY_STORAGE_QUICK_EMPTY) - if(client) - client.screen -= O - observer_screen_update(O,FALSE) +/** + * 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(module_active == O) - module_active = null - if(held_items[1] == O) - inv1.icon_state = "inv1" - held_items[1] = null - else if(held_items[2] == O) - inv2.icon_state = "inv2" - held_items[2] = null - else if(held_items[3] == O) - inv3.icon_state = "inv3" - held_items[3] = null + if(!(item_module in module.modules)) + CRASH("activate_module called with item_module not in module.modules") - if(O.item_flags & DROPDEL) - O.item_flags &= ~DROPDEL //we shouldn't HAVE things with DROPDEL_1 in our modules, but better safe than runtiming horribly - - O.forceMove(module) //Return item to module so it appears in its contents, so it can be taken out again. - O.cyborg_unequip(src) - - hud_used.update_robot_modules_display() - return 1 - -/mob/living/silicon/robot/proc/activate_module(obj/item/O) - . = FALSE - if(!(O in module.modules)) - return - if(activated(O)) + if(activated(item_module)) to_chat(src, "That module is already activated.") - return - if(!held_items[1]) - held_items[1] = O - O.screen_loc = inv1.screen_loc - . = TRUE - else if(!held_items[2]) - held_items[2] = O - O.screen_loc = inv2.screen_loc - . = TRUE - else if(!held_items[3]) - held_items[3] = O - O.screen_loc = inv3.screen_loc - . = TRUE - else - to_chat(src, "You need to disable a module first!") - if(.) - O.equipped(src, ITEM_SLOT_HANDS) - O.mouse_opacity = initial(O.mouse_opacity) - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - observer_screen_update(O,TRUE) - O.forceMove(src) - if(istype(O, /obj/item/borg/sight)) - var/obj/item/borg/sight/S = O - sight_mode |= S.sight_mode - update_sight() + return FALSE + + if(disabled_modules & BORG_MODULE_ALL_DISABLED) + to_chat(src, "All modules are disabled!") + 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, "Deactivate a module first!") + 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) + 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) + 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() + + 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("[src] sounds an alarm! \"CRITICAL ERROR: ALL modules OFFLINE.\"") + to_chat(src, "CRITICAL ERROR: ALL modules OFFLINE.") + + 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("[src] sounds an alarm! \"SYSTEM ERROR: Module [module_num] OFFLINE.\"") + to_chat(src, "SYSTEM ERROR: Module [module_num] OFFLINE.") + + 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("[src] sounds an alarm! \"SYSTEM ERROR: Module [module_num] OFFLINE.\"") + to_chat(src, "SYSTEM ERROR: Module [module_num] OFFLINE.") + + return TRUE -/mob/living/silicon/robot/proc/observer_screen_update(obj/item/I,add = 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(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, "ERROR CLEARED: Module [module_num] back online.") + + 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 && observers.len) for(var/M in observers) var/mob/dead/observe = M if(observe.client && observe.client.eye == src) if(add) - observe.client.screen += I + observe.client.screen += item_module else - observe.client.screen -= I + observe.client.screen -= item_module else observers -= observe if(!observers.len) observers = null break +/** + * Unequips the active held item. + */ /mob/living/silicon/robot/proc/uneq_active() - uneq_module(module_active) + unequip_module_from_slot(module_active, get_selected_module()) +/** + * Unequips all held items. + */ /mob/living/silicon/robot/proc/uneq_all() - for(var/obj/item/I in held_items) - uneq_module(I) + for(var/cyborg_slot in 1 to 3) + if(!held_items[cyborg_slot]) + continue + unequip_module_from_slot(held_items[cyborg_slot], cyborg_slot) -/mob/living/silicon/robot/proc/activated(obj/item/O) - if(O in held_items) +/** + * Checks if the item is currently in a slot. + * + * If the item is found in a slot, this returns TRUE. Otherwise, it returns FALSE + * Arguments + * * item_module - the item being checked + */ +/mob/living/silicon/robot/proc/activated(obj/item/item_module) + if(item_module in held_items) return TRUE return FALSE -//Helper procs for cyborg modules on the UI. -//These are hackish but they help clean up code elsewhere. +/** + * 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 -//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() + /// 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 -//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 FALSE + return module_num < 1 || module_num > max_number - if(LAZYLEN(held_items) >= module) - if(held_items[module]) - return TRUE - return FALSE - -//get_selected_module() - Returns the slot number of the currently selected module. Returns 0 if no modules are selected. +/** + * 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 0 -//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 +/** + * 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(!held_items[module_num]) + return FALSE - if(!module_active(module)) - return - - switch(module) + switch(module_num) if(1) - if(module_active != held_items[module]) - inv1.icon_state = "inv1 +a" - inv2.icon_state = "inv2" - inv3.icon_state = "inv3" + if(module_active != held_items[module_num]) + inv1.icon_state = "[initial(inv1.icon_state)] +a" if(2) - if(module_active != held_items[module]) - inv1.icon_state = "inv1" - inv2.icon_state = "inv2 +a" - inv3.icon_state = "inv3" + if(module_active != held_items[module_num]) + inv2.icon_state = "[initial(inv2.icon_state)] +a" if(3) - if(module_active != held_items[module]) - inv1.icon_state = "inv1" - inv2.icon_state = "inv2" - inv3.icon_state = "inv3 +a" - module_active = held_items[module] + if(module_active != held_items[module_num]) + inv3.icon_state = "[initial(inv3.icon_state)] +a" + module_active = held_items[module_num] -//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 - - if(!module_active(module)) - return - - switch(module) +/** + * 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]) - inv1.icon_state = "inv1" + if(module_active == held_items[module_num]) + inv1.icon_state = initial(inv1.icon_state) if(2) - if(module_active == held_items[module]) - inv2.icon_state = "inv2" + if(module_active == held_items[module_num]) + inv2.icon_state = initial(inv2.icon_state) if(3) - if(module_active == held_items[module]) - inv3.icon_state = "inv3" + if(module_active == held_items[module_num]) + inv3.icon_state = initial(inv3.icon_state) module_active = null -//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 +/** + * 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_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 + if(module_num == get_selected_module()) + deselect_module(module_num) + return TRUE -//cycle_modules() - Cycles through the list of selected modules. + 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. - - var/slot_num - if(slot_start == 0) + slot_num = slot_start + 1 + else slot_num = 1 slot_start = 4 - else - slot_num = slot_start + 1 while(slot_num != slot_start) //If we wrap around without finding any free slots, just give up. - if(module_active(slot_num)) - select_module(slot_num) + 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() diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 910a2a6fea0..afad167f231 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -4,7 +4,6 @@ return ..() - adjustOxyLoss(-10) //we're a robot! handle_robot_hud_updates() handle_robot_cell() @@ -100,4 +99,3 @@ mobility_flags = MOBILITY_FLAGS_DEFAULT update_transform() update_action_buttons_icon() - diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 57fa699c111..9ee28f6aeea 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -24,6 +24,8 @@ var/mob/living/silicon/ai/mainframe = null var/datum/action/innate/undeployment/undeployment_action = new + /// the last health before updating - to check net change in health + var/previous_health //Hud stuff var/obj/screen/inv1 = null @@ -41,6 +43,9 @@ 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 + var/mutable_appearance/eye_lights var/mob/living/silicon/ai/connected_ai = null @@ -110,6 +115,8 @@ ident = rand(1, 999) + previous_health = health + if(ispath(cell)) cell = new cell(src) @@ -220,7 +227,6 @@ module.transform_to(modulelist[input_module]) - /mob/living/silicon/robot/proc/updatename(client/C) if(shell) return @@ -705,21 +711,30 @@ /mob/living/silicon/robot/updatehealth() ..() - if(health < maxHealth*0.5) //Gradual break down of modules as more damage is sustained - if(uneq_module(held_items[3])) - playsound(loc, 'sound/machines/warning-buzzer.ogg', 50, TRUE, TRUE) - audible_message("[src] sounds an alarm! \"SYSTEM ERROR: Module 3 OFFLINE.\"") - to_chat(src, "SYSTEM ERROR: Module 3 OFFLINE.") - if(health < 0) - if(uneq_module(held_items[2])) - audible_message("[src] sounds an alarm! \"SYSTEM ERROR: Module 2 OFFLINE.\"") - to_chat(src, "SYSTEM ERROR: Module 2 OFFLINE.") - playsound(loc, 'sound/machines/warning-buzzer.ogg', 60, TRUE, TRUE) - if(health < -maxHealth*0.5) - if(uneq_module(held_items[1])) - audible_message("[src] sounds an alarm! \"CRITICAL ERROR: All modules OFFLINE.\"") - to_chat(src, "CRITICAL ERROR: All modules OFFLINE.") - playsound(loc, 'sound/machines/warning-buzzer.ogg', 75, TRUE, TRUE) + + /// the current percent health of the robot (-1 to 1) + var/percent_hp = health/maxHealth + if(health <= previous_health) //if change in health is negative (we're losing hp) + if(percent_hp <= 0.5) + break_cyborg_slot(3) + + if(percent_hp <= 0) + break_cyborg_slot(2) + + if(percent_hp <= -0.5) + break_cyborg_slot(1) + + else //if change in health is positive (we're gaining hp) + if(percent_hp >= 0.5) + repair_cyborg_slot(3) + + if(percent_hp >= 0) + repair_cyborg_slot(2) + + if(percent_hp >= -0.5) + repair_cyborg_slot(1) + + previous_health = health /mob/living/silicon/robot/update_sight() if(!client) diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 358464b81be..bc872ba0608 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -18,7 +18,6 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real return adjustBruteLoss(-30) - updatehealth() add_fingerprint(user) visible_message("[user] fixes some of the dents on [src].") return @@ -33,8 +32,6 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real return if (coil.use(1)) adjustFireLoss(-30) - adjustToxLoss(-30) - updatehealth() user.visible_message("[user] fixes some of the burnt wires on [src].", "You fix some of the burnt wires on [src].") else to_chat(user, "You need more cable to repair [src]!") @@ -268,7 +265,6 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real damage = rand(5, 35) damage = round(damage / 2) // borgs receive half damage adjustBruteLoss(damage) - updatehealth() return @@ -399,25 +395,3 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real updatehealth() if(prob(75) && Proj.damage > 0) spark_system.start() - - -/mob/living/silicon/robot/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE) - . = ..() - if(isnull(.)) - return - if(. <= (maxHealth * 0.5)) - if(getOxyLoss() > (maxHealth * 0.5)) - ADD_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT) - else if(getOxyLoss() <= (maxHealth * 0.5)) - REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT) - - -/mob/living/silicon/robot/setOxyLoss(amount, updating_health = TRUE, forced = FALSE) - . = ..() - if(isnull(.)) - return - if(. <= (maxHealth * 0.5)) - if(getOxyLoss() > (maxHealth * 0.5)) - ADD_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT) - else if(getOxyLoss() <= (maxHealth * 0.5)) - REMOVE_TRAIT(src, TRAIT_KNOCKEDOUT, OXYLOSS_TRAIT) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index a9cbaf00e81..3a848165d13 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -161,7 +161,8 @@ /obj/item/robot_module/proc/rebuild_modules() //builds the usable module list from the modules we have var/mob/living/silicon/robot/R = loc - var/held_modules = R.held_items.Copy() + var/list/held_modules = R.held_items.Copy() + var/active_module = R.module_active R.uneq_all() modules = list() for(var/obj/item/I in basic_modules) @@ -173,7 +174,9 @@ add_module(I, FALSE, FALSE) for(var/i in held_modules) if(i) - R.activate_module(i) + R.equip_module_to_slot(i, held_modules.Find(i)) + if(active_module) + R.select_module(held_modules.Find(active_module)) if(R.hud_used) R.hud_used.update_robot_modules_display() @@ -225,6 +228,7 @@ R.setDir(SOUTH) R.anchored = FALSE R.notransform = FALSE + R.updatehealth() R.update_headlamp(FALSE, BORG_LAMP_CD_RESET) R.notify_ai(NEW_MODULE) if(R.hud_used) diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 13c4364f73c..5068397f9cd 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -41,14 +41,6 @@ adjustBruteLoss(damage) if(BURN) adjustFireLoss(damage) - if(TOX) - adjustToxLoss(damage) - if(OXY) - adjustOxyLoss(damage) - if(CLONE) - adjustCloneLoss(damage) - if(STAMINA) - adjustStaminaLoss(damage) /mob/living/silicon/attack_paw(mob/living/user) return attack_hand(user) diff --git a/code/modules/modular_computers/file_system/programs/airestorer.dm b/code/modules/modular_computers/file_system/programs/airestorer.dm index c2a1aa4ca75..c1bb40d1b89 100644 --- a/code/modules/modular_computers/file_system/programs/airestorer.dm +++ b/code/modules/modular_computers/file_system/programs/airestorer.dm @@ -72,11 +72,9 @@ restoring = FALSE return ai_slot.locked =TRUE - A.adjustOxyLoss(-5, 0) - A.adjustFireLoss(-5, 0) - A.adjustToxLoss(-5, 0) + A.adjustOxyLoss(-5, 0, FALSE) + A.adjustFireLoss(-5, 0, FALSE) A.adjustBruteLoss(-5, 0) - A.updatehealth() if(A.health >= 0 && A.stat == DEAD) A.revive(full_heal = FALSE, admin_revive = FALSE) // Finished restoring diff --git a/icons/mob/screen_cyborg.dmi b/icons/mob/screen_cyborg.dmi index 2f87e9796f1..c0c112bdeb9 100644 Binary files a/icons/mob/screen_cyborg.dmi and b/icons/mob/screen_cyborg.dmi differ