diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index ff68f18408..faffea0e6e 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -67,17 +67,19 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isslimeperson(A) (is_species(A, /datum/species/jelly/slime)) #define isluminescent(A) (is_species(A, /datum/species/jelly/luminescent)) #define iszombie(A) (is_species(A, /datum/species/zombie)) +#define isskeleton(A) (is_species(A, /datum/species/skeleton)) +#define ismoth(A) (is_species(A, /datum/species/moth)) #define ishumanbasic(A) (is_species(A, /datum/species/human)) #define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid)) -#define isdwarf(A) (is_species(A, /datum/species/dwarf)) +#define isethereal(A) (is_species(A, /datum/species/ethereal)) +#define isvampire(A) (is_species(A,/datum/species/vampire)) #define isdullahan(A) (is_species(A, /datum/species/dullahan)) + #define isangel(A) (is_species(A, /datum/species/angel)) -#define isvampire(A) (is_species(A, /datum/species/vampire)) #define ismush(A) (is_species(A, /datum/species/mush)) #define isshadow(A) (is_species(A, /datum/species/shadow)) -#define isskeleton(A) (is_species(A, /datum/species/skeleton)) #define isrobotic(A) (is_species(A, /datum/species/ipc) || is_species(A, /datum/species/synthliz)) -#define isethereal(A) (is_species(A, /datum/species/ethereal)) +#define isdwarf(A) (is_species(A, /datum/species/dwarf)) // Citadel specific species #define isipcperson(A) (is_species(A, /datum/species/ipc)) @@ -143,6 +145,10 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define ishostile(A) (istype(A, /mob/living/simple_animal/hostile)) +// #define israt(A) (istype(A, /mob/living/simple_animal/hostile/rat)) + +// #define isregalrat(A) (istype(A, /mob/living/simple_animal/hostile/regalrat)) + #define isswarmer(A) (istype(A, /mob/living/simple_animal/hostile/swarmer)) #define isguardian(A) (istype(A, /mob/living/simple_animal/hostile/guardian)) @@ -155,6 +161,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isclown(A) (istype(A, /mob/living/simple_animal/hostile/retaliate/clown)) + //Misc mobs #define isobserver(A) (istype(A, /mob/dead/observer)) @@ -184,6 +191,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isitem(A) (istype(A, /obj/item)) +#define isstack(A) (istype(A, /obj/item/stack)) + #define isgrenade(A) (istype(A, /obj/item/grenade)) #define islandmine(A) (istype(A, /obj/effect/mine)) @@ -206,6 +215,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isclothing(A) (istype(A, /obj/item/clothing)) +#define iscash(A) (istype(A, /obj/item/coin) || istype(A, /obj/item/stack/spacecash) || istype(A, /obj/item/holochip)) + #define isbodypart(A) (istype(A, /obj/item/bodypart)) #define isprojectile(A) (istype(A, /obj/item/projectile)) @@ -240,3 +251,9 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list( #define isshuttleturf(T) (length(T.baseturfs) && (/turf/baseturf_skipover/shuttle in T.baseturfs)) #define isProbablyWallMounted(O) (O.pixel_x > 20 || O.pixel_x < -20 || O.pixel_y > 20 || O.pixel_y < -20) +#define isbook(O) (is_type_in_typecache(O, GLOB.book_types)) + +GLOBAL_LIST_INIT(book_types, typecacheof(list( + /obj/item/book, + /obj/item/spellbook, + /obj/item/storage/book))) diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm index a0fded3798..bab38bc825 100644 --- a/code/__DEFINES/robots.dm +++ b/code/__DEFINES/robots.dm @@ -8,7 +8,7 @@ #define DEFAULT_SCAN_RANGE 7 //default view range for finding targets. -//Mode defines +//Mode defines. If you add a new one make sure you update mode_name in /mob/living/simple_animal/bot #define BOT_IDLE 0 // idle #define BOT_HUNT 1 // found target, hunting #define BOT_PREP_ARREST 2 // at target, preparing to arrest @@ -27,7 +27,8 @@ #define BOT_NAV 15 // computing navigation #define BOT_WAIT_FOR_NAV 16 // waiting for nav computation #define BOT_NO_ROUTE 17 // no destination beacon found (or no route) -#define BOT_TIPPED 18 // someone tipped a medibot over ;_; +#define BOT_SHOWERSTANCE 18 // cleaning unhygienic humans +#define BOT_TIPPED 19 // someone tipped a medibot over ;_; //Bot types #define SEC_BOT (1<<0) // Secutritrons (Beepsky) and ED-209s @@ -37,6 +38,7 @@ #define MED_BOT (1<<4) // Medibots #define HONK_BOT (1<<5) // Honkbots & ED-Honks #define FIRE_BOT (1<<6) // Firebots +#define HYGIENE_BOT (1<<7) // Hygienebots //AI notification defines #define NEW_BORG 1 @@ -74,3 +76,10 @@ #define PRIVILEDGES_PAI (1<<1) #define PRIVILEDGES_BOT (1<<2) #define PRIVILEDGES_DRONE (1<<3) + +#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/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 467c67e0c3..5a69f26460 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -17,21 +17,6 @@ Therefore, the top right corner (except during admin shenanigans) is at "15,15" */ -//Lower left, persistent menu -#define ui_inventory "WEST:6,SOUTH:5" - -//Middle left indicators -#define ui_lingchemdisplay "WEST,CENTER-1:15" -#define ui_lingstingdisplay "WEST:6,CENTER-3:11" - -#define ui_devilsouldisplay "WEST:6,CENTER-1:15" - -//Lower center, persistent menu -#define ui_sstore1 "CENTER-5:10,SOUTH:5" -#define ui_id "CENTER-4:12,SOUTH:5" -#define ui_belt "CENTER-3:14,SOUTH:5" -#define ui_back "CENTER-2:14,SOUTH:5" - /proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5) var/x_off = -(!(i % 2)) var/y_off = round((i-1) / 2) @@ -46,35 +31,23 @@ var/y_off = round((M.held_items.len-1) / 2) return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5" +//Lower left, persistent menu +#define ui_inventory "WEST:6,SOUTH:5" + +//Middle left indicators +#define ui_lingchemdisplay "WEST,CENTER-1:15" +#define ui_lingstingdisplay "WEST:6,CENTER-3:11" + +#define ui_devilsouldisplay "WEST:6,CENTER-1:15" + +//Lower center, persistent menu +#define ui_sstore1 "CENTER-5:10,SOUTH:5" +#define ui_id "CENTER-4:12,SOUTH:5" +#define ui_belt "CENTER-3:14,SOUTH:5" +#define ui_back "CENTER-2:14,SOUTH:5" #define ui_storage1 "CENTER+1:18,SOUTH:5" #define ui_storage2 "CENTER+2:20,SOUTH:5" -#define ui_borg_sensor "CENTER-3:15, SOUTH:5" //borgs -#define ui_borg_lamp "CENTER-4:15, SOUTH:5" //borgs -#define ui_borg_thrusters "CENTER-5:15, SOUTH:5" //borgs -#define ui_inv1 "CENTER-2:16,SOUTH:5" //borgs -#define ui_inv2 "CENTER-1 :16,SOUTH:5" //borgs -#define ui_inv3 "CENTER :16,SOUTH:5" //borgs -#define ui_borg_module "CENTER+1:16,SOUTH:5" //borgs -#define ui_borg_store "CENTER+2:16,SOUTH:5" //borgs -#define ui_borg_camera "CENTER+3:21,SOUTH:5" //borgs -#define ui_borg_album "CENTER+4:21,SOUTH:5" //borgs -#define ui_borg_language_menu "EAST-1:27,SOUTH+2:8" //borgs - -#define ui_monkey_head "CENTER-5:13,SOUTH:5" //monkey -#define ui_monkey_mask "CENTER-4:14,SOUTH:5" //monkey -#define ui_monkey_neck "CENTER-3:15,SOUTH:5" //monkey -#define ui_monkey_back "CENTER-2:16,SOUTH:5" //monkey - -//#define ui_alien_storage_l "CENTER-2:14,SOUTH:5"//alien -#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"//alien -#define ui_alien_language_menu "EAST-3:26,SOUTH:5" //alien - -#define ui_drone_drop "CENTER+1:18,SOUTH:5" //maintenance drones -#define ui_drone_pull "CENTER+2:2,SOUTH:5" //maintenance drones -#define ui_drone_storage "CENTER-2:14,SOUTH:5" //maintenance drones -#define ui_drone_head "CENTER-3:14,SOUTH:5" //maintenance drones - //Lower right, persistent menu #define ui_drop_throw "EAST-1:28,SOUTH+1:7" #define ui_pull_resist "EAST-2:26,SOUTH+1:7" @@ -88,11 +61,6 @@ #define ui_language_menu "EAST-5:4,SOUTH:21"//CIT CHANGE - ditto #define ui_voremode "EAST-5:20,SOUTH:5" -#define ui_borg_pull "EAST-2:26,SOUTH+1:7" -#define ui_borg_radio "EAST-1:28,SOUTH+1:7" -#define ui_borg_intents "EAST-2:26,SOUTH:5" - - //Upper-middle right (alerts) #define ui_alert1 "EAST-1:28,CENTER+5:27" #define ui_alert2 "EAST-1:28,CENTER+4:25" @@ -100,31 +68,70 @@ #define ui_alert4 "EAST-1:28,CENTER+2:21" #define ui_alert5 "EAST-1:28,CENTER+1:19" - //Middle right (status indicators) #define ui_healthdoll "EAST-1:28,CENTER-2:13" #define ui_health "EAST-1:28,CENTER-1:15" #define ui_internal "EAST-1:28,CENTER+1:19"//CIT CHANGE - moves internal icon up a little bit to accommodate for the stamina meter #define ui_mood "EAST-1:28,CENTER-3:10" +// #define ui_spacesuit "EAST-1:28,CENTER-4:10" -//living +//Pop-up inventory +#define ui_shoes "WEST+1:8,SOUTH:5" +#define ui_iclothing "WEST:6,SOUTH+1:7" +#define ui_oclothing "WEST+1:8,SOUTH+1:7" +#define ui_gloves "WEST+2:10,SOUTH+1:7" +#define ui_glasses "WEST:6,SOUTH+3:11" +#define ui_mask "WEST+1:8,SOUTH+2:9" +#define ui_ears "WEST+2:10,SOUTH+2:9" +#define ui_neck "WEST:6,SOUTH+2:9" +#define ui_head "WEST+1:8,SOUTH+3:11" + +//Generic living #define ui_living_pull "EAST-1:28,CENTER-2:15" #define ui_living_health "EAST-1:28,CENTER:15" -//borgs -#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator. +//Monkeys +#define ui_monkey_head "CENTER-5:13,SOUTH:5" +#define ui_monkey_mask "CENTER-4:14,SOUTH:5" +#define ui_monkey_neck "CENTER-3:15,SOUTH:5" +#define ui_monkey_back "CENTER-2:16,SOUTH:5" -//aliens -#define ui_alien_health "EAST,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator. +//Drones +#define ui_drone_drop "CENTER+1:18,SOUTH:5" +#define ui_drone_pull "CENTER+2:2,SOUTH:5" +#define ui_drone_storage "CENTER-2:14,SOUTH:5" +#define ui_drone_head "CENTER-3:14,SOUTH:5" + +//Cyborgs +#define ui_borg_health "EAST-1:28,CENTER-1:15" +#define ui_borg_pull "EAST-2:26,SOUTH+1:7" +#define ui_borg_radio "EAST-1:28,SOUTH+1:7" +#define ui_borg_intents "EAST-2:26,SOUTH:5" +#define ui_borg_lamp "CENTER-3:16, SOUTH:5" +#define ui_borg_tablet "CENTER-4:16, SOUTH:5" +#define ui_inv1 "CENTER-2:16,SOUTH:5" +#define ui_inv2 "CENTER-1 :16,SOUTH:5" +#define ui_inv3 "CENTER :16,SOUTH:5" +#define ui_borg_module "CENTER+1:16,SOUTH:5" +#define ui_borg_store "CENTER+2:16,SOUTH:5" +#define ui_borg_camera "CENTER+3:21,SOUTH:5" +#define ui_borg_alerts "CENTER+4:21,SOUTH:5" +#define ui_borg_language_menu "CENTER+4:21,SOUTH+1:5" +#define ui_borg_sensor "CENTER-3:15, SOUTH:5" //LEGACY +#define ui_borg_thrusters "CENTER-5:15, SOUTH:5" //LEGACY + +//Aliens +#define ui_alien_health "EAST,CENTER-1:15" #define ui_alienplasmadisplay "EAST,CENTER-2:15" #define ui_alien_queen_finder "EAST,CENTER-3:15" +#define ui_alien_storage_r "CENTER+1:18,SOUTH:5" +#define ui_alien_language_menu "EAST-3:26,SOUTH:5" -//constructs +//Constructs #define ui_construct_pull "EAST,CENTER-2:15" -#define ui_construct_health "EAST,CENTER:15" //same as borgs and humans +#define ui_construct_health "EAST,CENTER:15" // AI - #define ui_ai_core "SOUTH:6,WEST" #define ui_ai_camera_list "SOUTH:6,WEST+1" #define ui_ai_track_with_camera "SOUTH:6,WEST+2" @@ -143,26 +150,32 @@ #define ui_ai_multicam "SOUTH+1:6,WEST+13" #define ui_ai_add_multicam "SOUTH+1:6,WEST+14" -//Pop-up inventory -#define ui_shoes "WEST+1:8,SOUTH:5" -#define ui_iclothing "WEST:6,SOUTH+1:7" -#define ui_oclothing "WEST+1:8,SOUTH+1:7" -#define ui_gloves "WEST+2:10,SOUTH+1:7" - -#define ui_glasses "WEST:6,SOUTH+3:11" -#define ui_mask "WEST+1:8,SOUTH+2:9" -#define ui_ears "WEST+2:10,SOUTH+2:9" -#define ui_neck "WEST:6,SOUTH+2:9" -#define ui_head "WEST+1:8,SOUTH+3:11" +// pAI +// #define ui_pai_software "SOUTH:6,WEST" +// #define ui_pai_shell "SOUTH:6,WEST+1" +// #define ui_pai_chassis "SOUTH:6,WEST+2" +// #define ui_pai_rest "SOUTH:6,WEST+3" +// #define ui_pai_light "SOUTH:6,WEST+4" +// #define ui_pai_newscaster "SOUTH:6,WEST+5" +// #define ui_pai_host_monitor "SOUTH:6,WEST+6" +// #define ui_pai_crew_manifest "SOUTH:6,WEST+7" +// #define ui_pai_state_laws "SOUTH:6,WEST+8" +// #define ui_pai_pda_send "SOUTH:6,WEST+9" +// #define ui_pai_pda_log "SOUTH:6,WEST+10" +// #define ui_pai_take_picture "SOUTH:6,WEST+12" +// #define ui_pai_view_images "SOUTH:6,WEST+13" //Ghosts +#define ui_ghost_jumptomob "SOUTH:6,CENTER-3:24" +#define ui_ghost_orbit "SOUTH:6,CENTER-2:24" +#define ui_ghost_reenter_corpse "SOUTH:6,CENTER-1:24" +#define ui_ghost_teleport "SOUTH:6,CENTER:24" +#define ui_ghost_pai "SOUTH: 6, CENTER+1:24" +#define ui_ghost_mafia "SOUTH: 6, CENTER+2:24" +#define ui_ghost_spawners "SOUTH: 6, CENTER+1:24" // LEGACY. SAME LOC AS PAI -#define ui_ghost_jumptomob "SOUTH:6,CENTER-2:24" -#define ui_ghost_orbit "SOUTH:6,CENTER-1:24" -#define ui_ghost_reenter_corpse "SOUTH:6,CENTER:24" -#define ui_ghost_teleport "SOUTH:6,CENTER+1:24" -#define ui_ghost_spawners "SOUTH: 6, CENTER+2:24" +// #define ui_wanted_lvl "NORTH,11" //UI position overrides for 1:1 screen layout. (default is 7:5) diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index 9859e7acdf..2d73437f6e 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -68,57 +68,17 @@ var/mob/living/silicon/robot/R = usr R.uneq_active() -/obj/screen/robot/lamp - name = "headlamp" - icon_state = "lamp0" - -/obj/screen/robot/lamp/Click() - if(..()) - return - var/mob/living/silicon/robot/R = usr - R.control_headlamp() - -/obj/screen/robot/thrusters - name = "ion thrusters" - icon_state = "ionpulse0" - -/obj/screen/robot/thrusters/Click() - if(..()) - return - var/mob/living/silicon/robot/R = usr - R.toggle_ionpulse() - -/obj/screen/robot/sensors - name = "Sensor Augmentation" - icon_state = "cyborg_sensor" - -/obj/screen/robot/sensors/Click() - if(..()) - return - var/mob/living/silicon/S = usr - S.toggle_sensors() - -/obj/screen/robot/language_menu - name = "silicon language selection" - icon_state = "talk_wheel" - -/obj/screen/robot/language_menu/Click() - if(..()) - return - var/mob/living/silicon/S = usr - S.open_language_menu(usr) - /datum/hud/robot ui_style = 'icons/mob/screen_cyborg.dmi' /datum/hud/robot/New(mob/owner) ..() - var/mob/living/silicon/robot/mymobR = mymob + // i, Robit + var/mob/living/silicon/robot/robit = mymob var/obj/screen/using - using = new/obj/screen/robot/language_menu + using = new/obj/screen/language_menu using.screen_loc = ui_borg_language_menu - using.hud = src static_inventory += using //Radio @@ -128,56 +88,72 @@ static_inventory += using //Module select - using = new /obj/screen/robot/module1() - using.screen_loc = ui_inv1 - using.hud = src - static_inventory += using - mymobR.inv1 = using + if(!robit.inv1) + robit.inv1 = new /obj/screen/robot/module1() - using = new /obj/screen/robot/module2() - using.screen_loc = ui_inv2 - using.hud = src - static_inventory += using - mymobR.inv2 = using + robit.inv1.screen_loc = ui_inv1 + robit.inv1.hud = src + static_inventory += robit.inv1 - using = new /obj/screen/robot/module3() - using.screen_loc = ui_inv3 - using.hud = src - static_inventory += using - mymobR.inv3 = using + if(!robit.inv2) + robit.inv2 = new /obj/screen/robot/module2() + + robit.inv2.screen_loc = ui_inv2 + robit.inv2.hud = src + static_inventory += robit.inv2 + + if(!robit.inv3) + robit.inv3 = new /obj/screen/robot/module3() + + robit.inv3.screen_loc = ui_inv3 + robit.inv3.hud = src + static_inventory += robit.inv3 //End of module select + using = new /obj/screen/robot/lamp() + using.screen_loc = ui_borg_lamp + using.hud = src + static_inventory += using + robit.lampButton = using + var/obj/screen/robot/lamp/lampscreen = using + lampscreen.robot = robit + //Photography stuff using = new /obj/screen/ai/image_take() using.screen_loc = ui_borg_camera using.hud = src static_inventory += using - using = new /obj/screen/ai/image_view() - using.screen_loc = ui_borg_album - using.hud = src - static_inventory += using - //Sec/Med HUDs using = new /obj/screen/robot/sensors() using.screen_loc = ui_borg_sensor using.hud = src static_inventory += using -//Headlamp control - using = new /obj/screen/robot/lamp() - using.screen_loc = ui_borg_lamp +//Borg Integrated Tablet + using = new /obj/screen/robot/modPC() + using.screen_loc = ui_borg_tablet + using.hud = src + static_inventory += using + robit.interfaceButton = using + if(robit.modularInterface) + using.vis_contents += robit.modularInterface + var/obj/screen/robot/modPC/tabletbutton = using + tabletbutton.robot = robit + +//Alerts + using = new /obj/screen/robot/alerts() + using.screen_loc = ui_borg_alerts using.hud = src static_inventory += using - mymobR.lamp_button = using //Thrusters using = new /obj/screen/robot/thrusters() using.screen_loc = ui_borg_thrusters using.hud = src static_inventory += using - mymobR.thruster_button = using + robit.thruster_button = using //Intent action_intent = new /obj/screen/act_intent/robot() @@ -191,20 +167,21 @@ infodisplay += healths //Installed Module - mymobR.hands = new /obj/screen/robot/module() - mymobR.hands.screen_loc = ui_borg_module - static_inventory += mymobR.hands + robit.hands = new /obj/screen/robot/module() + robit.hands.screen_loc = ui_borg_module + robit.hands.hud = src + static_inventory += robit.hands //Store module_store_icon = new /obj/screen/robot/store() - module_store_icon.hud = src module_store_icon.screen_loc = ui_borg_store + module_store_icon.hud = src pull_icon = new /obj/screen/pull() pull_icon.icon = 'icons/mob/screen_cyborg.dmi' + pull_icon.screen_loc = ui_borg_pull pull_icon.hud = src pull_icon.update_icon() - pull_icon.screen_loc = ui_borg_pull hotkeybuttons += pull_icon @@ -242,13 +219,13 @@ screenmob.client.screen += module_store_icon //"store" icon if(!R.module.modules) - to_chat(usr, "Selected module has no modules to select") + to_chat(usr, "Selected module has no modules to select!") return if(!R.robot_modules_background) return - var/display_rows = CEILING(length(R.module.get_inactive_modules()) / 8, 1) + var/display_rows = max(CEILING(length(R.module.get_inactive_modules()) / 8, 1),1) R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7" screenmob.client.screen += R.robot_modules_background @@ -305,3 +282,63 @@ else for(var/obj/item/I in R.held_items) screenmob.client.screen -= I + +/obj/screen/robot/lamp + name = "headlamp" + icon_state = "lamp0" + var/mob/living/silicon/robot/robot + +/obj/screen/robot/lamp/Click() + . = ..() + if(.) + return + robot?.toggle_headlamp() + update_icon() + +/obj/screen/robot/lamp/update_icon() + if(robot?.lamp_enabled) + icon_state = "lamp_on" + else + icon_state = "lamp_off" + +/obj/screen/robot/alerts + name = "Alert Panel" + icon = 'icons/mob/screen_ai.dmi' + icon_state = "alerts" + +/obj/screen/robot/alerts/Click() + . = ..() + if(.) + return + var/mob/living/silicon/robot/borgo = usr + borgo.robot_alerts() + +/obj/screen/robot/thrusters + name = "ion thrusters" + icon_state = "ionpulse0" + +/obj/screen/robot/thrusters/Click() + if(..()) + return + var/mob/living/silicon/robot/R = usr + R.toggle_ionpulse() + +/obj/screen/robot/sensors + name = "Sensor Augmentation" + icon_state = "cyborg_sensor" + +/obj/screen/robot/sensors/Click() + if(..()) + return + var/mob/living/silicon/S = usr + S.toggle_sensors() +/obj/screen/robot/modPC + name = "Modular Interface" + icon_state = "template" + var/mob/living/silicon/robot/robot + +/obj/screen/robot/modPC/Click() + . = ..() + if(.) + return + robot.modularInterface?.interact(robot) diff --git a/code/datums/components/storage/concrete/stack.dm b/code/datums/components/storage/concrete/stack.dm index a3f1e526a0..d7b118cee4 100644 --- a/code/datums/components/storage/concrete/stack.dm +++ b/code/datums/components/storage/concrete/stack.dm @@ -40,7 +40,8 @@ _S.add(can_insert) S.use(can_insert, TRUE) return TRUE - return ..(S.change_stack(null, can_insert), override) + I = S.split_stack(null, can_insert) + return ..() /datum/component/storage/concrete/stack/remove_from_storage(obj/item/I, atom/new_location) var/atom/real_location = real_location() diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index c426f02733..503a183064 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -444,14 +444,14 @@ . = ..() if(isturf(loc)) // to prevent people that are alt clicking a tile to see its content from getting undesidered pop ups return - if(is_cyborg || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE) || zero_amount()) //, !iscyborg(user) + if(is_cyborg || !user.canUseTopic(src, BE_CLOSE, TRUE, FALSE) || zero_amount()) //, !iscyborg(user) return //get amount from user var/max = get_amount() var/stackmaterial = round(input(user,"How many sheets do you wish to take out of this stack? (Maximum [max])") as null|num) max = get_amount() stackmaterial = min(max, stackmaterial) - if(stackmaterial == null || stackmaterial <= 0 || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERITY, FALSE)) //, !iscyborg(user) + if(stackmaterial == null || stackmaterial <= 0 || !user.canUseTopic(src, BE_CLOSE, TRUE, FALSE)) //, !iscyborg(user) return split_stack(user, stackmaterial) to_chat(user, "You take [stackmaterial] sheets out of the stack.") @@ -485,10 +485,13 @@ . = ..() /obj/item/stack/proc/copy_evidences(obj/item/stack/from) - add_blood_DNA(from.return_blood_DNA()) - add_fingerprint_list(from.return_fingerprints()) - add_hiddenprint_list(from.return_hiddenprints()) - fingerprintslast = from.fingerprintslast + if(from.blood_DNA) + blood_DNA = from.blood_DNA.Copy() + if(from.fingerprints) + fingerprints = from.fingerprints.Copy() + if(from.fingerprintshidden) + fingerprintshidden = from.fingerprintshidden.Copy() + fingerprintslast = from.fingerprintslast //TODO bloody overlay /obj/item/stack/microwave_act(obj/machinery/microwave/M) diff --git a/code/modules/antagonists/devil/true_devil/inventory.dm b/code/modules/antagonists/devil/true_devil/inventory.dm index 579dfb4fb1..e98cb5ca72 100644 --- a/code/modules/antagonists/devil/true_devil/inventory.dm +++ b/code/modules/antagonists/devil/true_devil/inventory.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/true_devil/doUnEquip(obj/item/I, force) +/mob/living/carbon/true_devil/doUnEquip(obj/item/I, force, silent = FALSE) if(..()) update_inv_hands() return 1 diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm index e646d3b202..6ad3a19694 100644 --- a/code/modules/clothing/head/_head.dm +++ b/code/modules/clothing/head/_head.dm @@ -40,11 +40,11 @@ if(iscyborg(hit_atom)) var/mob/living/silicon/robot/R = hit_atom ///hats in the borg's blacklist bounce off - if(!is_type_in_typecache(src, R.equippable_hats) || R.hat_offset == INFINITY) - R.visible_message("[src] bounces off [R]!", "[src] bounces off you, falling to the floor.") + if(is_type_in_typecache(src, GLOB.blacklisted_borg_hats)) + R.visible_message("[src] bounces off [R]!", "[src] bounces off you, falling to the floor.") return else - R.visible_message("[src] lands neatly on top of [R].", "[src] lands perfectly on top of you.") + R.visible_message("[src] lands neatly on top of [R]!", "[src] lands perfectly on top of you.") R.place_on_head(src) //hats aren't designed to snugly fit borg heads or w/e so they'll always manage to knock eachother off diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 9cf3f44cb8..0baa78f0ea 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -298,20 +298,21 @@ return doUnEquip(I, force, drop_location(), FALSE) //for when the item will be immediately placed in a loc other than the ground -/mob/proc/transferItemToLoc(obj/item/I, newloc = null, force = FALSE) - return doUnEquip(I, force, newloc, FALSE) +/mob/proc/transferItemToLoc(obj/item/I, newloc = null, force = FALSE, silent = TRUE) + return doUnEquip(I, force, newloc, FALSE, silent = silent) //visibly unequips I but it is NOT MOVED AND REMAINS IN SRC //item MUST BE FORCEMOVE'D OR QDEL'D /mob/proc/temporarilyRemoveItemFromInventory(obj/item/I, force = FALSE, idrop = TRUE) - return doUnEquip(I, force, null, TRUE, idrop) + return doUnEquip(I, force, null, TRUE, idrop, silent = TRUE) //DO NOT CALL THIS PROC //use one of the above 3 helper procs //you may override it, but do not modify the args -/mob/proc/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE) //Force overrides TRAIT_NODROP for things like wizarditis and admin undress. +/mob/proc/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE, silent = FALSE) //Force overrides TRAIT_NODROP for things like wizarditis and admin undress. //Use no_move if the item is just gonna be immediately moved afterward //Invdrop is used to prevent stuff in pockets dropping. only set to false if it's going to immediately be replaced + PROTECTED_PROC(TRUE) if(!I) //If there's nothing to drop, the drop is automatically succesfull. If(unEquip) should generally be used to check for TRAIT_NODROP. return TRUE @@ -333,9 +334,7 @@ I.moveToNullspace() else I.forceMove(newloc) - on_item_dropped(I) - if(I.dropped(src) == ITEM_RELOCATED_BY_DROPPED) - return FALSE + I.dropped(src, silent) return TRUE //This is a SAFE proc. Use this instead of equip_to_slot()! diff --git a/code/modules/mob/living/carbon/alien/larva/inventory.dm b/code/modules/mob/living/carbon/alien/larva/inventory.dm index 8cfbf21f75..b07bd180f6 100644 --- a/code/modules/mob/living/carbon/alien/larva/inventory.dm +++ b/code/modules/mob/living/carbon/alien/larva/inventory.dm @@ -1,3 +1,3 @@ //can't unequip since it can't equip anything -/mob/living/carbon/alien/larva/doUnEquip(obj/item/W) +/mob/living/carbon/alien/larva/doUnEquip(obj/item/W, silent = FALSE) return diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 523369d10a..c4d023da58 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -164,7 +164,7 @@ var/obj/item/thing = sloties . += thing?.slowdown -/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE) +/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE, silent = FALSE) var/index = get_held_index_of_item(I) . = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should. if(!. || !I) diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 33a2a09b70..329fa5ee65 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -187,12 +187,8 @@ AM.emp_act(50) if(iscyborg(AM)) var/mob/living/silicon/robot/borg = AM - if(borg.lamp_intensity) - borg.update_headlamp(TRUE, INFINITY) - to_chat(borg, "Your headlamp is fried! You'll need a human to help replace it.") - for(var/obj/item/assembly/flash/cyborg/F in borg.held_items) - if(!F.crit_fail) - F.burn_out() + if(borg.lamp_enabled) + borg.smash_headlamp() else for(var/obj/item/O in AM) if(O.light_range && O.light_power) diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index e5ba022277..0447de6064 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -104,7 +104,7 @@ return not_handled -/mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE) +/mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE, silent = FALSE) . = ..() //Sets the default return value to what the parent returns. if(!. || !I) //We don't want to set anything to null if the parent returned 0. return diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index 6a5338c1f5..626382f6bc 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -16,15 +16,16 @@ /mob/living/silicon/robot/death(gibbed) if(stat == DEAD) return - + if(!gibbed) + logevent("FATAL -- SYSTEM HALT") + modularInterface.shutdown_computer() . = ..() locked = FALSE //unlock cover - update_mobility() if(!QDELETED(builtInCamera) && builtInCamera.status) builtInCamera.toggle_cam(src,0) - update_headlamp(1) //So borg lights are disabled when killed. + toggle_headlamp(TRUE) //So borg lights are disabled when killed. uneq_all() // particularly to ensure sight modes are cleared diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index 9b964ef188..b11737659c 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -1,11 +1,12 @@ //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) -//This proc has been butchered into a proc that overrides borg item holding for the sake of making grippers work. -//I'd be immensely thankful if anyone can figure out a less obtuse way of making grippers work without breaking functionality. +/** + * 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() var/item = module_active + // snowflake handler for the gripper if(istype(item, /obj/item/weapon/gripper)) var/obj/item/weapon/gripper/G = item if(G.wrapped) @@ -15,230 +16,416 @@ 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 -/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 +/** + * 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, "That module is already activated.") + 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) + 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() - else if(istype(O, /obj/item/storage/bag/tray/)) - SEND_SIGNAL(O, COMSIG_TRY_STORAGE_QUICK_EMPTY) //CITADEL EDIT reee proc, Dogborg modules - if(istype(O,/obj/item/gun/energy/laser/cyborg)) + if(istype(item_module, /obj/item/gun/energy/laser/cyborg)) laser = FALSE update_icons() - else if(istype(O,/obj/item/gun/energy/disabler/cyborg) || istype(O,/obj/item/gun/energy/e_gun/advtaser/cyborg)) + 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 - else if(istype(O,/obj/item/dogborg/sleeper)) + if(istype(item_module, /obj/item/dogborg/sleeper)) sleeper_g = FALSE sleeper_r = FALSE update_icons() - var/obj/item/dogborg/sleeper/S = O + var/obj/item/dogborg/sleeper/S = item_module S.go_out() //this should stop edgecase deletions //END CITADEL EDIT + if(client) - client.screen -= O - observer_screen_update(O,FALSE) + client.screen -= item_module - if(module_active == O) + if(module_active == item_module) 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(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 + 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) - O.forceMove(module) //Return item to module so it appears in its contents, so it can be taken out again. + 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 1 + return TRUE -/mob/living/silicon/robot/proc/activate_module(obj/item/O) - . = FALSE - if(!(O in module.modules)) - return - //CITADEL EDIT Dogborg lasers - if(istype(O,/obj/item/gun/energy/laser/cyborg)) - laser = TRUE - update_icons() //REEEEEEACH FOR THE SKY - if(istype(O,/obj/item/gun/energy/disabler/cyborg) || istype(O,/obj/item/gun/energy/e_gun/advtaser/cyborg)) - disabler = TRUE - update_icons() - //END CITADEL EDIT - if(activated(O)) - to_chat(src, "That module is already activated.") - return - if(!held_items[1] && health >= -maxHealth*0.5) - held_items[1] = O - O.screen_loc = inv1.screen_loc - . = TRUE - else if(!held_items[2] && health >= 0) - held_items[2] = O - O.screen_loc = inv2.screen_loc - . = TRUE - else if(!held_items[3] && health >= maxHealth*0.5) - 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, 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() +/** + * 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 -/mob/living/silicon/robot/proc/observer_screen_update(obj/item/I,add = TRUE) - if(observers && observers.len) + 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.\"") + + if(builtInCamera) + builtInCamera.status = FALSE + to_chat(src, "CRITICAL ERROR: Built in security camera 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 + +/** + * 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, "You hear your built in security camera focus adjust as it comes back online!") + 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?.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, if there is one. + */ /mob/living/silicon/robot/proc/uneq_active() - uneq_module(module_active) + if(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(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 - 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] + return TRUE -//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 + return TRUE -//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() + +/mob/living/silicon/robot/can_hold_items(obj/item/I) + return (I && (I in module.modules)) //Only if it's part of our module. + diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 0feb8b98b7..9075af2dbd 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -8,22 +8,21 @@ /mob/living/silicon/robot/proc/handle_robot_cell() if(stat != DEAD) if(low_power_mode) - if(cell && cell.charge) - low_power_mode = 0 - update_headlamp() + if(cell?.charge) + low_power_mode = FALSE else if(stat == CONSCIOUS) use_power() /mob/living/silicon/robot/proc/use_power() - if(cell && cell.charge) + if(cell?.charge) if(cell.charge <= 100) uneq_all() - var/amt = clamp((lamp_intensity - 2) * 2,1,cell.charge) //Always try to use at least one charge per tick, but allow it to completely drain the cell. + var/amt = clamp((lamp_enabled * lamp_intensity),1,cell.charge) //Lamp will use a max of 5 charge, depending on brightness of lamp. If lamp is off, borg systems consume 1 point of charge, or the rest of the cell if it's lower than that. cell.use(amt) //Usage table: 1/tick if off/lowest setting, 4 = 4/tick, 6 = 8/tick, 8 = 12/tick, 10 = 16/tick else uneq_all() - low_power_mode = 1 - update_headlamp() + low_power_mode = TRUE + toggle_headlamp(TRUE) diag_hud_set_borgcell() /mob/living/silicon/robot/proc/handle_robot_hud_updates() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 7db417b8fa..3079f65471 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -15,7 +15,7 @@ wires = new /datum/wires/robot(src) AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) - + // AddElement(/datum/element/ridable, /datum/component/riding/creature/cyborg) RegisterSignal(src, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, .proc/charge) robot_modules_background = new() @@ -23,10 +23,16 @@ robot_modules_background.layer = HUD_LAYER //Objects that appear on screen are on layer ABOVE_HUD_LAYER, UI should be just below it. robot_modules_background.plane = HUD_PLANE - ident = rand(1, 999) + inv1 = new /obj/screen/robot/module1() + inv2 = new /obj/screen/robot/module2() + inv3 = new /obj/screen/robot/module3() - if(!cell) - cell = new /obj/item/stock_parts/cell/high(src) + previous_health = health + + if(ispath(cell)) + cell = new cell(src) + + create_modularInterface() if(lawupdate) make_laws() @@ -63,18 +69,23 @@ mmi.brainmob.real_name = src.real_name mmi.brainmob.container = mmi - updatename() + INVOKE_ASYNC(src, .proc/updatename) - equippable_hats = typecacheof(equippable_hats) - - playsound(loc, 'sound/voice/liveagain.ogg', 75, 1) + playsound(loc, 'sound/voice/liveagain.ogg', 75, TRUE) aicamera = new/obj/item/camera/siliconcam/robot_camera(src) toner = tonermax diag_hud_set_borgcell() + logevent("System brought online.") add_verb(src, /mob/living/proc/lay_down) //CITADEL EDIT gimmie rest verb kthx add_verb(src, /mob/living/silicon/robot/proc/rest_style) +/mob/living/silicon/robot/proc/create_modularInterface() + if(!modularInterface) + modularInterface = new /obj/item/modular_computer/tablet/integrated(src) + modularInterface.layer = ABOVE_HUD_PLANE + modularInterface.plane = ABOVE_HUD_PLANE + //If there's an MMI in the robot, have it ejected when the mob goes away. --NEO /mob/living/silicon/robot/Destroy() var/atom/T = drop_location()//To hopefully prevent run time errors. @@ -93,28 +104,31 @@ ghostize() stack_trace("Borg MMI lacked a brainmob") mmi = null - //CITADEL EDIT: Cyborgs drop encryption keys on destroy - if(istype(radio) && istype(radio.keyslot)) - radio.keyslot.forceMove(T) - radio.keyslot = null - //END CITADEL EDIT + if(modularInterface) + QDEL_NULL(modularInterface) if(connected_ai) set_connected_ai(null) - if(shell) + if(shell) //??? why would you give an ai radio keys? GLOB.available_ai_shells -= src else if(T && istype(radio) && istype(radio.keyslot)) radio.keyslot.forceMove(T) radio.keyslot = null - qdel(wires) - qdel(module) - qdel(eye_lights) - wires = null - module = null - eye_lights = null + QDEL_NULL(wires) + QDEL_NULL(module) + QDEL_NULL(eye_lights) + QDEL_NULL(inv1) + QDEL_NULL(inv2) + QDEL_NULL(inv3) cell = null return ..() +// /mob/living/silicon/robot/Topic(href, href_list) +// . = ..() +// //Show alerts window if user clicked on "Show alerts" in chat +// if (href_list["showalerts"]) +// robot_alerts() + /mob/living/silicon/robot/proc/pick_module() if(module.type != /obj/item/robot_module) return @@ -136,7 +150,7 @@ if(BORG_SEC_AVAILABLE) modulelist["Security"] = /obj/item/robot_module/security - var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in modulelist + var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in sortList(modulelist) if(!input_module || module.type != /obj/item/robot_module) return @@ -151,9 +165,11 @@ var/changed_name = "" if(custom_name) changed_name = custom_name - if(changed_name == "" && C && C.prefs.custom_names["cyborg"] != DEFAULT_CYBORG_NAME) - if(apply_pref_name("cyborg", C)) - return //built in camera handled in proc + // if(SSticker.anonymousnames) //only robotic renames will allow for anything other than the anonymous one + // changed_name = anonymous_ai_name(is_ai = FALSE) + if(!changed_name && C && C.prefs.custom_names["cyborg"] != DEFAULT_CYBORG_NAME) + apply_pref_name("cyborg", C) + return //built in camera handled in proc if(!changed_name) changed_name = get_standard_name() @@ -262,7 +278,7 @@ C = O L[A.name] = list(A, (C) ? C : O, list(alarmsource)) queueAlarm(text("--- [class] alarm detected in [A.name]!"), class) - return 1 + return TRUE /mob/living/silicon/robot/cancelAlarm(class, area/A, obj/origin) var/list/L = alarms[class] @@ -281,6 +297,8 @@ return !cleared /mob/living/silicon/robot/can_interact_with(atom/A) + if (A == modularInterface) + return TRUE //bypass for borg tablets if (low_power_mode) return FALSE var/turf/T0 = get_turf(src) @@ -473,19 +491,6 @@ toner = tonermax qdel(W) to_chat(user, "You fill the toner level of [src] to its max capacity.") - - else if(istype(W, /obj/item/flashlight)) - if(!opened) - to_chat(user, "You need to open the panel to repair the headlamp!") - else if(lamp_cooldown <= world.time) - to_chat(user, "The headlamp is already functional!") - else - if(!user.temporarilyRemoveItemFromInventory(W)) - to_chat(user, "[W] seems to be stuck to your hand. You'll have to find a different light.") - return - lamp_cooldown = 0 - qdel(W) - to_chat(user, "You replace the headlamp bulbs.") else return ..() @@ -518,47 +523,46 @@ /mob/living/silicon/robot/proc/allowed(mob/M) //check if it doesn't require any access at all if(check_access(null)) - return 1 + return TRUE if(ishuman(M)) var/mob/living/carbon/human/H = M //if they are holding or wearing a card that has access, that works if(check_access(H.get_active_held_item()) || check_access(H.wear_id)) - return 1 + return TRUE else if(ismonkey(M)) var/mob/living/carbon/monkey/george = M //they can only hold things :( if(isitem(george.get_active_held_item())) return check_access(george.get_active_held_item()) - return 0 + return FALSE /mob/living/silicon/robot/proc/check_access(obj/item/card/id/I) if(!istype(req_access, /list)) //something's very wrong - return 1 + return TRUE var/list/L = req_access if(!L.len) //no requirements - return 1 + return TRUE if(!istype(I, /obj/item/card/id) && isitem(I)) I = I.GetID() if(!I || !I.access) //not ID or no access - return 0 + return FALSE for(var/req in req_access) if(!(req in I.access)) //doesn't have this access - return 0 - return 1 + return FALSE + return TRUE /mob/living/silicon/robot/regenerate_icons() return update_icons() /mob/living/silicon/robot/proc/self_destruct() if(emagged) - if(mmi) - qdel(mmi) - explosion(src.loc,1,2,4,flame_range = 2) + QDEL_NULL(mmi) + explosion(loc,1,2,4,flame_range = 2) else - explosion(src.loc,-1,0,2) + explosion(loc,-1,0,2) gib() /mob/living/silicon/robot/proc/UnlinkSelf() @@ -597,6 +601,8 @@ clear_alert("locked") locked_down = state update_mobility() + logevent("System lockdown [locked_down?"triggered":"released"].") + /mob/living/silicon/robot/proc/SetEmagged(new_state) emagged = new_state @@ -607,6 +613,22 @@ else clear_alert("hacked") +/** + * Handles headlamp smashing + * + * When called (such as by the shadowperson lighteater's attack), this proc will break the borg's headlamp + * and then call toggle_headlamp to disable the light. It also plays a sound effect of glass breaking, and + * tells the borg what happened to its chat. Broken lights can be repaired by using a flashlight on the borg. + */ +/mob/living/silicon/robot/proc/smash_headlamp() + if(!lamp_functional) + return + lamp_functional = FALSE + playsound(src, 'sound/effects/glass_step.ogg', 50) + toggle_headlamp(TRUE) + to_chat(src, "Your headlamp is broken! You'll need a human to help replace it.") + + /mob/living/silicon/robot/verb/outputlaws() set category = "Robot Commands" set name = "State Laws" @@ -624,32 +646,40 @@ return //won't work if dead set_autosay() -/mob/living/silicon/robot/proc/control_headlamp() - if(stat || lamp_cooldown > world.time || low_power_mode) - to_chat(src, "This function is currently offline.") +/** + * Handles headlamp toggling, disabling, and color setting. + * + * The initial if statment is a bit long, but the gist of it is that should the lamp be on AND the update_color + * arg be true, we should simply change the color of the lamp but not disable it. Otherwise, should the turn_off + * arg be true, the lamp already be enabled, any of the normal reasons the lamp would turn off happen, or the + * update_color arg be passed with the lamp not on, we should set the lamp off. The update_color arg is only + * ever true when this proc is called from the borg tablet, when the color selection feature is used. + * + * Arguments: + * * arg1 - turn_off, if enabled will force the lamp into an off state (rather than toggling it if possible) + * * arg2 - update_color, if enabled, will adjust the behavior of the proc to change the color of the light if it is already on. + */ +/mob/living/silicon/robot/proc/toggle_headlamp(turn_off = FALSE, update_color = FALSE) + //if both lamp is enabled AND the update_color flag is on, keep the lamp on. Otherwise, if anything listed is true, disable the lamp. + if(!(update_color && lamp_enabled) && (turn_off || lamp_enabled || update_color || !lamp_functional || stat || low_power_mode)) + set_light((lamp_functional && stat != DEAD && lamp_doom) ? lamp_intensity : 0, l_color = COLOR_RED) + // set_light_on(lamp_functional && stat != DEAD && lamp_doom) //If the lamp isn't broken and borg isn't dead, doomsday borgs cannot disable their light fully. + // set_light_color(COLOR_RED) //This should only matter for doomsday borgs, as any other time the lamp will be off and the color not seen + // set_light_range(1) //Again, like above, this only takes effect when the light is forced on by doomsday mode. + lamp_enabled = FALSE + lampButton.update_icon() + update_icons() return - -//Some sort of magical "modulo" thing which somehow increments lamp power by 2, until it hits the max and resets to 0. - lamp_intensity = (lamp_intensity+2) % (lamp_max+2) - to_chat(src, "[lamp_intensity ? "Headlamp power set to Level [lamp_intensity/2]" : "Headlamp disabled."]") - update_headlamp() - -/mob/living/silicon/robot/proc/update_headlamp(var/turn_off = 0, var/cooldown = 100) - set_light(0) - - if(lamp_intensity && (turn_off || stat || low_power_mode)) - to_chat(src, "Your headlamp has been deactivated.") - lamp_intensity = 0 - lamp_cooldown = world.time + cooldown - else - set_light(lamp_intensity) - - if(lamp_button) - lamp_button.icon_state = "lamp[lamp_intensity]" - + set_light(lamp_intensity, l_color = (lamp_doom? COLOR_RED : lamp_color)) + // set_light_range(lamp_intensity) + // set_light_color(lamp_doom? COLOR_RED : lamp_color) //Red for doomsday killborgs, borg's choice otherwise + // set_light_on(TRUE) + lamp_enabled = TRUE + lampButton.update_icon() update_icons() /mob/living/silicon/robot/proc/deconstruct() + // SEND_SIGNAL(src, COMSIG_BORG_SAFE_DECONSTRUCT) var/turf/T = get_turf(src) if (robot_suit) robot_suit.forceMove(T) @@ -659,7 +689,7 @@ robot_suit.r_leg = null new /obj/item/stack/cable_coil(T, robot_suit.chest.wired) robot_suit.chest.forceMove(T) - robot_suit.chest.wired = 0 + robot_suit.chest.wired = FALSE robot_suit.chest = null robot_suit.l_arm.forceMove(T) robot_suit.l_arm = null @@ -692,8 +722,12 @@ cell = null qdel(src) +///This is the subtype that gets created by robot suits. It's needed so that those kind of borgs don't have a useless cell in them +/mob/living/silicon/robot/nocell + cell = null + /mob/living/silicon/robot/modules - var/set_module = null + var/set_module = /obj/item/robot_module /mob/living/silicon/robot/modules/Initialize() . = ..() @@ -733,14 +767,20 @@ Your cyborg LMG will slowly produce ammunition from your power supply, and your operative pinpointer will find and locate fellow nuclear operatives. \ Help the operatives secure the disk at all costs!" set_module = /obj/item/robot_module/syndicate + cell = /obj/item/stock_parts/cell/hyper + // radio = /obj/item/radio/borg/syndicate /mob/living/silicon/robot/modules/syndicate/Initialize() . = ..() - cell = new /obj/item/stock_parts/cell/hyper(src, 25000) radio = new /obj/item/radio/borg/syndicate(src) laws = new /datum/ai_laws/syndicate_override() addtimer(CALLBACK(src, .proc/show_playstyle), 5) +/mob/living/silicon/robot/modules/syndicate/create_modularInterface() + if(!modularInterface) + modularInterface = new /obj/item/modular_computer/tablet/integrated/syndicate(src) + return ..() + /mob/living/silicon/robot/modules/syndicate/proc/show_playstyle() if(playstyle_string) to_chat(src, playstyle_string) @@ -795,21 +835,32 @@ /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, 1, 1) - 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, 1, 1) - 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, 1, 1) + // if(!module.breakable_modules) + // return + + /// 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) @@ -832,7 +883,7 @@ if(sight_mode & BORGMESON) sight |= SEE_TURFS - lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE see_in_dark = 1 if(sight_mode & BORGMATERIAL) @@ -847,6 +898,7 @@ if(sight_mode & BORGTHERM) sight |= SEE_MOBS + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE see_invisible = min(see_invisible, SEE_INVISIBLE_LIVING) see_in_dark = 8 @@ -860,34 +912,27 @@ if(stat != DEAD) if(health <= -maxHealth) //die only once death() + toggle_headlamp(1) return - if(IsUnconscious() || IsStun() || IsParalyzed() || getOxyLoss() > maxHealth*0.5) - if(stat == CONSCIOUS) - stat = UNCONSCIOUS - if(!eye_blind) - blind_eyes(1) - update_mobility() - update_headlamp() + if(IsUnconscious() || IsStun() || IsKnockdown() || IsParalyzed() || getOxyLoss() > maxHealth * 0.5) + stat = UNCONSCIOUS else - if(stat == UNCONSCIOUS) - stat = CONSCIOUS - adjust_blindness(-1) - update_mobility() - update_headlamp() + stat = CONSCIOUS + update_mobility() diag_hud_set_status() diag_hud_set_health() diag_hud_set_aishell() update_health_hud() -/mob/living/silicon/robot/revive(full_heal = 0, admin_revive = 0) +/mob/living/silicon/robot/revive(full_heal = FALSE, admin_revive = FALSE) if(..()) //successfully ressuscitated from death if(!QDELETED(builtInCamera) && !wires.is_cut(WIRE_CAMERA)) builtInCamera.toggle_cam(src,0) - update_headlamp() if(admin_revive) locked = TRUE notify_ai(NEW_BORG) - . = 1 + . = TRUE + toggle_headlamp(FALSE, TRUE) //This will reenable borg headlamps if doomsday is currently going on still. /mob/living/silicon/robot/fully_replace_character_name(oldname, newname) ..() @@ -899,6 +944,7 @@ /mob/living/silicon/robot/proc/ResetModule() + // SEND_SIGNAL(src, COMSIG_BORG_SAFE_DECONSTRUCT) uneq_all() shown_robot_modules = FALSE if(hud_used) @@ -908,6 +954,7 @@ resize = 0.5 hasExpanded = FALSE update_transform() + logevent("Chassis configuration has been reset.") module.transform_to(/obj/item/robot_module) // Remove upgrades. @@ -933,7 +980,8 @@ designation = module.name if(hands) hands.icon_state = module.moduleselect_icon - hands.icon = (module.moduleselect_alternate_icon ? module.moduleselect_alternate_icon : initial(hands.icon)) //CITADEL CHANGE - allows module select icons to use a different icon file + //CITADEL CHANGE - allows module select icons to use a different icon file + hands.icon = (module.moduleselect_alternate_icon ? module.moduleselect_alternate_icon : initial(hands.icon)) if(module.can_be_pushed) status_flags |= CANPUSH else @@ -947,7 +995,7 @@ hat_offset = module.hat_offset magpulse = module.magpulsing - updatename() + INVOKE_ASYNC(src, .proc/updatename) /mob/living/silicon/robot/proc/place_on_head(obj/item/new_hat) @@ -957,12 +1005,68 @@ new_hat.forceMove(src) update_icons() -/mob/living/silicon/robot/proc/make_shell(var/obj/item/borg/upgrade/ai/board) +/** + *Checking Exited() to detect if a hat gets up and walks off. + *Drones and pAIs might do this, after all. +*/ +/mob/living/silicon/robot/Exited(atom/A) + if(hat && hat == A) + hat = null + if(!QDELETED(src)) //Don't update icons if we are deleted. + update_icons() + return ..() + +///Use this to add upgrades to robots. It'll register signals for when the upgrade is moved or deleted, if not single use. +/mob/living/silicon/robot/proc/add_to_upgrades(obj/item/borg/upgrade/new_upgrade, mob/user) + if(new_upgrade in upgrades) + return FALSE + if(!user.temporarilyRemoveItemFromInventory(new_upgrade)) //calling the upgrade's dropped() proc /before/ we add action buttons + return FALSE + if(!new_upgrade.action(src, user)) + to_chat(user, "Upgrade error.") + new_upgrade.forceMove(loc) //gets lost otherwise + return FALSE + to_chat(user, "You apply the upgrade to [src].") + to_chat(src, "----------------\nNew hardware detected...Identified as \"[new_upgrade]\"...Setup complete.\n----------------") + if(new_upgrade.one_use) + logevent("Firmware [new_upgrade] run successfully.") + qdel(new_upgrade) + return FALSE + upgrades += new_upgrade + new_upgrade.forceMove(src) + RegisterSignal(new_upgrade, COMSIG_MOVABLE_MOVED, .proc/remove_from_upgrades) + RegisterSignal(new_upgrade, COMSIG_PARENT_QDELETING, .proc/on_upgrade_deleted) + logevent("Hardware [new_upgrade] installed successfully.") + +///Called when an upgrade is moved outside the robot. So don't call this directly, use forceMove etc. +/mob/living/silicon/robot/proc/remove_from_upgrades(obj/item/borg/upgrade/old_upgrade) + SIGNAL_HANDLER + if(loc == src) + return + old_upgrade.deactivate(src) + upgrades -= old_upgrade + UnregisterSignal(old_upgrade, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING)) + +///Called when an applied upgrade is deleted. +/mob/living/silicon/robot/proc/on_upgrade_deleted(obj/item/borg/upgrade/old_upgrade) + SIGNAL_HANDLER + if(!QDELETED(src)) + old_upgrade.deactivate(src) + upgrades -= old_upgrade + UnregisterSignal(old_upgrade, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING)) + +/** + * make_shell: Makes an AI shell out of a cyborg unit + * + * Arguments: + * * board - B.O.R.I.S. module board used for transforming the cyborg into AI shell + */ +/mob/living/silicon/robot/proc/make_shell(obj/item/borg/upgrade/ai/board) if(!board) upgrades |= new /obj/item/borg/upgrade/ai(src) shell = TRUE braintype = "AI Shell" - name = "[designation] AI Shell [rand(100,999)]" + name = "Empty AI Shell-[ident]" real_name = name GLOB.available_ai_shells |= src if(!QDELETED(builtInCamera)) @@ -970,6 +1074,9 @@ diag_hud_set_aishell() notify_ai(AI_SHELL) +/** + * revert_shell: Reverts AI shell back into a normal cyborg unit + */ /mob/living/silicon/robot/proc/revert_shell() if(!shell) return @@ -979,14 +1086,20 @@ qdel(boris) shell = FALSE GLOB.available_ai_shells -= src - name = "Unformatted Cyborg [rand(100,999)]" + name = "Unformatted Cyborg-[ident]" real_name = name if(!QDELETED(builtInCamera)) builtInCamera.c_tag = real_name diag_hud_set_aishell() -/mob/living/silicon/robot/proc/deploy_init(var/mob/living/silicon/ai/AI) - real_name = "[AI.real_name] shell [rand(100, 999)] - [designation]" //Randomizing the name so it shows up separately in the shells list +/** + * deploy_init: Deploys AI unit into AI shell + * + * Arguments: + * * AI - AI unit that initiated the deployment into the AI shell + */ +/mob/living/silicon/robot/proc/deploy_init(mob/living/silicon/ai/AI) + real_name = "[AI.real_name] [designation] Shell-[ident]" name = real_name if(!QDELETED(builtInCamera)) builtInCamera.c_tag = real_name //update the camera name too @@ -1067,10 +1180,10 @@ mainframe.diag_hud_set_deployed() if(mainframe.laws) mainframe.laws.show_laws(mainframe) //Always remind the AI when switching + if(mainframe.eyeobj) + mainframe.eyeobj.setLoc(loc) mainframe = null - - /mob/living/silicon/robot/attack_ai(mob/user) if(shell && (!connected_ai || connected_ai == user)) var/mob/living/silicon/ai/AI = user @@ -1078,6 +1191,7 @@ /mob/living/silicon/robot/shell shell = TRUE + cell = null /mob/living/silicon/robot/MouseDrop_T(mob/living/M, mob/living/user) . = ..() @@ -1088,20 +1202,19 @@ if(!is_type_in_typecache(M, can_ride_typecache)) M.visible_message("[M] really can't seem to mount [src]...") return + var/datum/component/riding/riding_datum = LoadComponent(/datum/component/riding/cyborg) if(buckled_mobs) if(buckled_mobs.len >= max_buckled_mobs) return if(M in buckled_mobs) return - if(stat) + + if(stat || incapacitated()) return - if(incapacitated()) + if(module && !module.allow_riding) + M.visible_message("Unfortunately, [M] just can't seem to hold onto [src]!") return - if(module) - if(!module.allow_riding) - M.visible_message("Unfortunately, [M] just can't seem to hold onto [src]!") - return if(iscarbon(M) && !M.incapacitated() && !riding_datum.equip_buckle_inhands(M, 1)) if(M.get_num_arms() <= 0) M.visible_message("[M] can't climb onto [src] because [M.p_they()] don't have any usable arms!") @@ -1118,17 +1231,25 @@ riding_datum.restore_position(user) . = ..(user) +/mob/living/silicon/robot/resist() + . = ..() + if(!has_buckled_mobs()) + return + for(var/i in buckled_mobs) + var/mob/unbuckle_me_now = i + unbuckle_mob(unbuckle_me_now, FALSE) + /mob/living/silicon/robot/proc/TryConnectToAI() set_connected_ai(select_active_ai_with_fewest_borgs(z)) if(connected_ai) lawsync() - lawupdate = 1 + lawupdate = TRUE return TRUE picturesync() return FALSE /mob/living/silicon/robot/proc/picturesync() - if(connected_ai && connected_ai.aicamera && aicamera) + if(connected_ai?.aicamera && aicamera) for(var/i in aicamera.stored) connected_ai.aicamera.stored[i] = TRUE for(var/i in connected_ai.aicamera.stored) @@ -1136,12 +1257,11 @@ /mob/living/silicon/robot/proc/charge(datum/source, amount, repairs) if(module) - var/coeff = amount * 0.005 - module.respawn_consumable(src, coeff) - if(repairs) - heal_bodypart_damage(repairs, repairs - 1) + module.respawn_consumable(src, amount * 0.005) if(cell) cell.charge = min(cell.charge + amount, cell.maxcharge) + if(repairs) + heal_bodypart_damage(repairs, repairs - 1) /mob/living/silicon/robot/proc/rest_style() set name = "Switch Rest Style" @@ -1176,5 +1296,31 @@ if(.) var/mob/living/silicon/ai/old_ai = . old_ai.connected_robots -= src + lamp_doom = FALSE if(connected_ai) connected_ai.connected_robots |= src + lamp_doom = connected_ai.doomsday_device ? TRUE : FALSE + toggle_headlamp(FALSE, TRUE) + +/** + * Records an IC event log entry in the cyborg's internal tablet. + * + * Creates an entry in the borglog list of the cyborg's internal tablet, listing the current + * in-game time followed by the message given. These logs can be seen by the cyborg in their + * BorgUI tablet app. By design, logging fails if the cyborg is dead. + * + * Arguments: + * arg1: a string containing the message to log. + */ +/mob/living/silicon/robot/proc/logevent(string = "") + if(!string) + return + if(stat == DEAD) //Dead borgs log no longer + return + if(!modularInterface) + stack_trace("Cyborg [src] ( [type] ) was somehow missing their integrated tablet. Please make a bug report.") + create_modularInterface() + modularInterface.borglog += "[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)] - [string]" + var/datum/computer_file/program/robotact/program = modularInterface.get_robotact() + if(program) + program.force_full_update() diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 0ed380040b..36f291bf36 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -1,5 +1,11 @@ +GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't really work on borgos + /obj/item/clothing/head/helmet/space, + /obj/item/clothing/head/welding, + /obj/item/clothing/head/chameleon/broken \ + ))) + /mob/living/silicon/robot/attackby(obj/item/I, mob/living/user) - if(hat_offset != INFINITY && user.a_intent == INTENT_HELP && is_type_in_typecache(I, equippable_hats)) + if(hat_offset != INFINITY && user.a_intent == INTENT_HELP && is_type_in_typecache(I, GLOB.blacklisted_borg_hats)) if(!(I.slot_flags & ITEM_SLOT_HEAD)) to_chat(user, "You can't quite fit [I] onto [src]'s head.") return diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm index 4f7ae41969..f44552f1ab 100644 --- a/code/modules/mob/living/silicon/robot/robot_defines.dm +++ b/code/modules/mob/living/silicon/robot/robot_defines.dm @@ -1,15 +1,16 @@ /mob/living/silicon/robot + maxHealth = 100 + health = 100 designation = "Default" //used for displaying the prefix & getting the current module of cyborg has_limbs = TRUE hud_type = /datum/hud/robot + // radio = /obj/item/radio/borg + blocks_emissive = EMISSIVE_BLOCK_UNIQUE - - maxHealth = 100 - health = 100 - - combat_flags = COMBAT_FLAGS_DEFAULT + // light_system = MOVABLE_LIGHT_DIRECTIONAL + var/light_on = FALSE var/custom_name = "" var/braintype = "Cyborg" @@ -21,6 +22,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 @@ -38,16 +41,20 @@ 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 - var/obj/item/stock_parts/cell/cell = null + var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high ///If this is a path, this gets created as an object in Initialize. - var/opened = 0 + var/opened = FALSE var/emagged = FALSE var/emag_cooldown = 0 - var/wiresexposed = 0 + var/wiresexposed = FALSE + /// Random serial number generated for each cyborg upon its initialization var/ident = 0 var/locked = TRUE var/list/req_access = list(ACCESS_ROBOTICS) @@ -64,57 +71,52 @@ var/datum/effect_system/spark_spread/spark_system // So they can initialize sparks whenever/N var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default - var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them. - var/locked_down //Boolean of whether the borg is locked down or not + var/scrambledcodes = FALSE // Used to determine if a borg shows up on the robotics console. Setting to TRUE hides them. + var/locked_down = FALSE //Boolean of whether the borg is locked down or not var/toner = 0 var/tonermax = 40 - var/lamp_max = 10 //Maximum brightness of a borg lamp. Set as a var for easy adjusting. - var/lamp_intensity = 0 //Luminosity of the headlamp. 0 is off. Higher settings than the minimum require power. - light_color = "#FFCC66" - light_power = 0.8 - var/lamp_cooldown = 0 //Flag for if the lamp is on cooldown after being forcibly disabled. + ///If the lamp isn't broken. + var/lamp_functional = TRUE + ///If the lamp is turned on + var/lamp_enabled = FALSE + ///Set lamp color + var/lamp_color = "#FFCC66" //COLOR_WHITE + ///Set to true if a doomsday event is locking our lamp to on and RED + var/lamp_doom = FALSE + ///Lamp brightness. Starts at 3, but can be 1 - 5. + var/lamp_intensity = 3 + ///Lamp button reference + var/obj/screen/robot/lamp/lampButton var/sight_mode = 0 hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD) + ///The reference to the built-in tablet that borgs carry. + var/obj/item/modular_computer/tablet/integrated/modularInterface + var/obj/screen/robot/modPC/interfaceButton + var/list/upgrades = list() var/hasExpanded = FALSE var/obj/item/hat var/hat_offset = -3 - var/list/equippable_hats = list(/obj/item/clothing/head/caphat, - /obj/item/clothing/head/hardhat, - /obj/item/clothing/head/centhat, - /obj/item/clothing/head/HoS, - /obj/item/clothing/head/beret, - /obj/item/clothing/head/kitty, - /obj/item/clothing/head/hopcap, - /obj/item/clothing/head/wizard, - /obj/item/clothing/head/nursehat, - /obj/item/clothing/head/sombrero, - /obj/item/clothing/head/helmet/chaplain/witchunter_hat, - /obj/item/clothing/head/soft/, //All baseball caps - /obj/item/clothing/head/that, //top hat - /obj/item/clothing/head/collectable/tophat, //Not sure where this one is found, but it looks the same so might as well include - /obj/item/clothing/mask/bandana/, //All bandanas (which only work in hat mode) - /obj/item/clothing/head/fedora, - /obj/item/clothing/head/beanie/, //All beanies - /obj/item/clothing/ears/headphones, - /obj/item/clothing/head/helmet/skull, - /obj/item/clothing/head/crown/fancy) can_buckle = TRUE buckle_lying = FALSE + /// What types of mobs are allowed to ride/buckle to this mob var/static/list/can_ride_typecache = typecacheof(/mob/living/carbon/human) + // cit specific vars // var/sitting = 0 var/bellyup = 0 var/dogborg = FALSE var/cansprint = 1 + combat_flags = COMBAT_FLAGS_DEFAULT + var/orebox = null //doggie borg stuff. diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 4c83841809..0c3ba87f5f 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -269,9 +269,10 @@ if(!prev_locked_down) R.SetLockdown(0) R.setDir(SOUTH) - R.anchored = FALSE + R.set_anchored(FALSE) R.mob_transforming = FALSE - R.update_headlamp() + R.updatehealth() + R.update_icons() R.notify_ai(NEW_MODULE) if(R.hud_used) R.hud_used.update_robot_modules_display() diff --git a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm index 8034e3c5e5..5439bbf665 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm @@ -6,7 +6,7 @@ //Drone hands -/mob/living/simple_animal/drone/doUnEquip(obj/item/I, force) +/mob/living/simple_animal/drone/doUnEquip(obj/item/I, force, silent = FALSE) if(..()) update_inv_hands() if(I == head) diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm index a1850fabca..a079507a63 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm @@ -41,7 +41,7 @@ ..() //lose items, then return //SLOT HANDLING BULLSHIT FOR INTERNAL STORAGE -/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/I, force) +/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/I, force, silent = FALSE) if(..()) update_inv_hands() if(I == internal_storage) diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 06649ac7d6..f6169be902 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -252,7 +252,7 @@ Feedon(Food) return ..() -/mob/living/simple_animal/slime/doUnEquip(obj/item/W) +/mob/living/simple_animal/slime/doUnEquip(obj/item/W, silent = FALSE) return /mob/living/simple_animal/slime/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index 90081ec87e..32facb69f5 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -391,7 +391,7 @@ /obj/item/modular_computer/proc/toggle_flashlight() if(!has_light) return FALSE - set_light_on(!light_on) + light_on = !light_on if(light_on) set_light(comp_light_luminosity, 1, comp_light_color) else @@ -410,7 +410,7 @@ if(!has_light || !color) return FALSE comp_light_color = color - set_light_color(color) + // set_light_color(color) update_light() return TRUE diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm index a96dffa9a0..72e1283553 100644 --- a/code/modules/modular_computers/computers/item/tablet.dm +++ b/code/modules/modular_computers/computers/item/tablet.dm @@ -112,7 +112,7 @@ /obj/item/modular_computer/tablet/integrated/ui_data(mob/user) . = ..() .["has_light"] = TRUE - .["light_on"] = borgo?.lamp_enabled + .["light_on"] = borgo?.lamp_intensity .["comp_light_color"] = borgo?.lamp_color //Makes the flashlight button affect the borg rather than the tablet diff --git a/code/modules/modular_computers/computers/item/tablet_presets.dm b/code/modules/modular_computers/computers/item/tablet_presets.dm index a812c62bc5..90dd149825 100644 --- a/code/modules/modular_computers/computers/item/tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/tablet_presets.dm @@ -29,7 +29,7 @@ install_component(new /obj/item/computer_hardware/card_slot) install_component(new /obj/item/computer_hardware/network_card) install_component(new /obj/item/computer_hardware/printer/mini) - hard_drive.store_file(new /datum/computer_file/program/shipping) + // hard_drive.store_file(new /datum/computer_file/program/shipping) /obj/item/modular_computer/tablet/preset/advanced/atmos/Initialize() //This will be defunct and will be replaced when NtOS PDAs are done . = ..() diff --git a/code/modules/modular_computers/file_system/programs/budgetordering.dm b/code/modules/modular_computers/file_system/programs/budgetordering.dm index 0c7dc9c394..65ff97dd1b 100644 --- a/code/modules/modular_computers/file_system/programs/budgetordering.dm +++ b/code/modules/modular_computers/file_system/programs/budgetordering.dm @@ -35,7 +35,7 @@ return FALSE if(!paccess_to_check) // No required_access, allow it. return TRUE - if(isAdminGhostAI(user)) + if(IsAdminGhost(user)) return TRUE //Aquire access from the inserted ID card. @@ -79,7 +79,8 @@ data["supplies"] = list() for(var/pack in SSshuttle.supply_packs) var/datum/supply_pack/P = SSshuttle.supply_packs[pack] - if(!is_visible_pack(usr, P.access_view , null, P.contraband) || P.hidden) + // todo: replace to P.access_view + if(!is_visible_pack(usr, P.access , null, P.contraband) || P.hidden) continue if(!data["supplies"][P.group]) data["supplies"][P.group] = list( diff --git a/code/modules/modular_computers/file_system/programs/robotact.dm b/code/modules/modular_computers/file_system/programs/robotact.dm index 0bd166624e..b25332d027 100644 --- a/code/modules/modular_computers/file_system/programs/robotact.dm +++ b/code/modules/modular_computers/file_system/programs/robotact.dm @@ -61,7 +61,7 @@ //DEBUG -- Cover, TRUE for locked data["cover"] = "[borgo.locked? "LOCKED":"UNLOCKED"]" //Ability to move. FAULT if lockdown wire is cut, DISABLED if borg locked, ENABLED otherwise - data["locomotion"] = "[borgo.wires.is_cut(WIRE_LOCKDOWN)?"FAULT":"[borgo.lockcharge?"DISABLED":"ENABLED"]"]" + data["locomotion"] = "[borgo.wires.is_cut(WIRE_LOCKDOWN)?"FAULT":"[borgo.locked_down?"DISABLED":"ENABLED"]"]" //Module wire. FAULT if cut, NOMINAL otherwise data["wireModule"] = "[borgo.wires.is_cut(WIRE_RESET_MODULE)?"FAULT":"NOMINAL"]" //DEBUG -- Camera(net) wire. FAULT if cut (or no cameranet camera), DISABLED if pulse-disabled, NOMINAL otherwise diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm index 92275b1e8b..78e72640ed 100644 --- a/code/modules/modular_computers/file_system/programs/secureye.dm +++ b/code/modules/modular_computers/file_system/programs/secureye.dm @@ -21,10 +21,10 @@ // Stuff needed to render the map var/map_name - var/atom/movable/screen/map_view/cam_screen + var/obj/screen/map_view/cam_screen /// All the plane masters that need to be applied. var/list/cam_plane_masters - var/atom/movable/screen/background/cam_background + var/obj/screen/background/cam_background /datum/computer_file/program/secureye/New() . = ..() @@ -42,8 +42,8 @@ cam_screen.del_on_map_removal = FALSE cam_screen.screen_loc = "[map_name]:1,1" cam_plane_masters = list() - for(var/plane in subtypesof(/atom/movable/screen/plane_master)) - var/atom/movable/screen/instance = new plane() + for(var/plane in subtypesof(/obj/screen/plane_master)) + var/obj/screen/instance = new plane() instance.assigned_map = map_name instance.del_on_map_removal = FALSE instance.screen_loc = "[map_name]:CENTER" diff --git a/code/modules/modular_computers/hardware/_hardware.dm b/code/modules/modular_computers/hardware/_hardware.dm index 850ba76f06..0ccb9f6b96 100644 --- a/code/modules/modular_computers/hardware/_hardware.dm +++ b/code/modules/modular_computers/hardware/_hardware.dm @@ -24,8 +24,8 @@ /obj/item/computer_hardware/New(obj/L) ..() - pixel_x = base_pixel_x + rand(-8, 8) - pixel_y = base_pixel_y + rand(-8, 8) + pixel_x = initial(pixel_x) + rand(-8, 8) + pixel_y = initial(pixel_y) + rand(-8, 8) /obj/item/computer_hardware/Destroy() if(holder) diff --git a/code/modules/modular_computers/hardware/network_card.dm b/code/modules/modular_computers/hardware/network_card.dm index 5a65184a27..625ead6ed7 100644 --- a/code/modules/modular_computers/hardware/network_card.dm +++ b/code/modules/modular_computers/hardware/network_card.dm @@ -90,7 +90,7 @@ if(!modularInterface.borgo) return FALSE //No borg found - if(modularInterface.borgo.lockcharge) + if(modularInterface.borgo.locked_down) return FALSE //lockdown restricts borg networking if(!modularInterface.borgo.cell || modularInterface.borgo.cell.charge == 0) diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm index 2cc4da6f9d..0811983088 100644 --- a/code/modules/modular_computers/laptop_vendor.dm +++ b/code/modules/modular_computers/laptop_vendor.dm @@ -225,7 +225,7 @@ return FALSE /obj/machinery/lapvend/ui_interact(mob/user, datum/tgui/ui) - if(machine_stat & (BROKEN | NOPOWER | MAINT)) + if(stat & (BROKEN | NOPOWER | MAINT)) if(ui) ui.close() return FALSE diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index b865af8cf4..7a98287809 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -98,8 +98,8 @@ /obj/item/paper/Initialize() . = ..() - pixel_x = base_pixel_x + rand(-9, 9) - pixel_y = base_pixel_y + rand(-8, 8) + pixel_x = initial(pixel_x) + rand(-9, 9) + pixel_y = initial(pixel_y) + rand(-8, 8) update_icon() /obj/item/paper/update_icon_state() diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index cf526f083d..b3ef99f98a 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -245,12 +245,10 @@ to_chat(user, "You need to secure the assembly before you can add glass.") return var/obj/item/stack/sheet/S = W - var/obj/item/stack/sheet/G = S.change_stack(null, 2) - if(G) - glass_type = G - G.moveToNullspace() - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - user.visible_message("[user] places the glass on the solar assembly.", "You place the glass on the solar assembly.") + if(S.use(2)) + glass_type = W.type + playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) + user.visible_message("[user] places the glass on the solar assembly.", "You place the glass on the solar assembly.") if(tracker) new /obj/machinery/power/tracker(get_turf(src), src) else @@ -258,7 +256,7 @@ else to_chat(user, "You need two sheets of glass to put them into a solar panel!") return - return 1 + return TRUE if(!tracker) if(istype(W, /obj/item/electronics/tracker)) diff --git a/code/modules/research/designs/computer_part_designs.dm b/code/modules/research/designs/computer_part_designs.dm index db37b13e87..d102a7516b 100644 --- a/code/modules/research/designs/computer_part_designs.dm +++ b/code/modules/research/designs/computer_part_designs.dm @@ -148,7 +148,7 @@ id = "APClink" build_type = PROTOLATHE materials = list(/datum/material/iron = 2000) - build_path = /obj/item/computer_hardware/recharger/APC + build_path = /obj/item/computer_hardware/recharger/apc_recharger category = list("Computer Parts") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING