diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm
index afea0d10c93..75e42833694 100644
--- a/code/__DEFINES/hud.dm
+++ b/code/__DEFINES/hud.dm
@@ -22,6 +22,155 @@
/// Largest viewport possible, required for checking if someone can see an object
#define LARGEST_VIEWPORT_SIZE WIDESCREEN_VIEWPORT_SIZE
+// Hud group keys
+/// Static elements that are always present in standard hud
+#define HUD_GROUP_STATIC 1
+/// Inventory elements toggled by the inventory switch
+#define HUD_GROUP_TOGGLEABLE_INVENTORY 2
+/// Info display HUD elements
+#define HUD_GROUP_INFO 3
+/// Permanently on-screen elements, regardless of your HUD status
+#define HUD_GROUP_SCREEN_OVERLAYS 4
+/// Hotkey buttons
+#define HUD_GROUP_HOTKEYS 5
+/// Open storages and items in them
+#define HUD_GROUP_STORAGE 6
+/// Total amount of screen groups in use
+#define SCREEN_GROUP_AMT 6
+
+// Hud keys for accessing hud objects
+#define HUD_MOB_TOGGLE_PALETTE "mob_toggle_palette"
+#define HUD_MOB_PALETTE_UP "mob_palette_up"
+#define HUD_MOB_PALETTE_DOWN "mob_palette_down"
+#define HUD_MOB_SCREENTIP "mob_screentips"
+#define HUD_MOB_HEALTH "mob_health"
+#define HUD_MOB_LANGUAGE_MENU "mob_language"
+#define HUD_MOB_NAVIGATE_MENU "mob_navigate"
+#define HUD_MOB_INTENTS "mob_intents"
+#define HUD_MOB_MOVE_INTENT "mob_move_intent"
+#define HUD_MOB_ZONE_SELECTOR "mob_zonesel"
+#define HUD_MOB_PULL "mob_pull"
+#define HUD_MOB_DROP "mob_drop"
+#define HUD_MOB_THROW "mob_throw"
+#define HUD_MOB_HUNGER "mob_hunger"
+#define HUD_MOB_STAMINA "mob_stamina"
+#define HUD_MOB_SPACESUIT "mob_spacesuit"
+#define HUD_MOB_COMBO "mob_combo"
+#define HUD_MOB_RESIST "mob_resist"
+#define HUD_MOB_REST "mob_rest"
+#define HUD_MOB_SLEEP "mob_sleep"
+#define HUD_MOB_AREA_CREATOR "mob_area_creator"
+#define HUD_MOB_SWAPHAND_1 "mob_swaphand1"
+#define HUD_MOB_SWAPHAND_2 "mob_swaphand2"
+#define HUD_MOB_CRAFTING_MENU "mob_crafting"
+#define HUD_MOB_FLOOR_CHANGER "mob_floor_changer"
+#define HUD_MOB_BLOOD_LEVEL "mob_blood_level"
+#define HUD_MOB_FOV_BLOCKER "mob_fov_blocker"
+#define HUD_MOB_STYLE_METER "mob_style_meter"
+#define HUD_MOB_MOOD "mob_mood"
+#define HUD_MOB_HEALTHDOLL "mob_healthdoll"
+#define HUD_MOB_MEMORIES "mob_memories"
+
+#define HUD_OOZE_NUTRITION_DISPLAY "ooze_nutrition_display"
+
+#define HUD_HUMAN_TOGGLE_INVENTORY "human_toggle_inventory"
+
+#define HUD_NEW_PLAYER_START_NOW "new_player_start_now"
+#define HUD_NEW_PLAYER_SIGN_UP "newp_layer_sign_up"
+#define HUD_KEY_NEW_PLAYER(slot) "newplayer_hud:[slot]"
+
+#define HUD_SILICON_TAKE_IMAGE "silicon_camera"
+#define HUD_SILICON_TABLET "silicon_tablet"
+#define HUD_SILICON_ALERTS "silicon_alerts"
+
+#define HUD_CYBORG_LAMP "cyborg_lamp"
+#define HUD_CYBORG_HANDS "cyborg_module"
+#define HUD_CYBORG_RADIO "cyborg_radio"
+#define HUD_CYBORG_DEATH "cyborg_death"
+#define HUD_KEY_CYBORG_MODULE(slot) "cyborg_module:[slot]"
+
+#define HUD_AI_FLOOR_INDICATOR "ai_floor_indicator"
+#define HUD_AI_GO_UP "ai_go_up"
+#define HUD_AI_GO_DOWN "ai_go_down"
+#define HUD_AI_AICORE "ai_core"
+#define HUD_AI_CAMERA_LIST "ai_camera_list"
+#define HUD_AI_CAMERA_TRACK "ai_camera_track"
+#define HUD_AI_CAMERA_LIGHT "ai_camera_light"
+#define HUD_AI_CREW_MONITOR "ai_crew_monitor"
+#define HUD_AI_CREW_MANIFEST "ai_crew_manifest"
+#define HUD_AI_ANNOUNCEMENT "ai_announce"
+#define HUD_AI_CALL_SHUTTLE "ai_shuttle"
+#define HUD_AI_STATE_LAWS "ai_state_laws"
+#define HUD_AI_TAKE_IMAGE "ai_take_image"
+#define HUD_AI_IMAGE_VIEW "ai_view_image"
+#define HUD_AI_SENSORS "ai_sensors"
+#define HUD_AI_MULTICAM "ai_view_multicam"
+#define HUD_AI_ADD_MULTICAM "ai_add_multicam"
+
+#define HUD_PAI_SOFTWARE "paisoftware"
+#define HUD_PAI_SHELL "paishell"
+#define HUD_PAI_CHASSIS "paichassis"
+#define HUD_PAI_NEWSCASTER "painewscaster"
+#define HUD_PAI_HOST_MONITOR "paimonitor"
+#define HUD_PAI_GPS "paigps"
+
+#define HUD_GHOST_SPAWNERS "ghost_spawners"
+#define HUD_GHOST_ORBIT "ghost_orbit"
+#define HUD_GHOST_REENTER_CORPSE "ghost_corpse"
+#define HUD_GHOST_TELEPORT "ghost_teleport"
+#define HUD_GHOST_PAI "ghost_pai"
+#define HUD_GHOST_MINIGAMES "ghost_minigames"
+#define HUD_GHOST_DNR "ghost_dnr"
+#define HUD_GHOST_SETTINGS "ghost_settings"
+#define HUD_KEY_GHOST_HUDBOX(slot) "ghost_hudbox:[slot]"
+
+#define HUD_ALIEN_QUEEN_FINDER "alien_queen_finder"
+#define HUD_ALIEN_PLASMA_DISPLAY "alien_plasma_display"
+#define HUD_ALIEN_HUNTER_LEAP "alien_hunter_leap"
+
+#define HUD_BLOB_POWER_DISPLAY "blob_power_display"
+#define HUD_BLOB_JUMP_TO_CORE "blob_jump_to_core"
+#define HUD_BLOB_JUMP_TO_NODE "blob_jump_to_node"
+#define HUD_BLOB_BLOBBERNAUT "blob_blobbernaut"
+#define HUD_BLOB_RESOURCES "blob_resources"
+#define HUD_BLOB_NODE "blob_node"
+#define HUD_BLOB_FACTORY "blob_factory"
+#define HUD_BLOB_READAPT "blob_readapt"
+#define HUD_BLOB_RELOCATE "blob_relocate"
+
+#define HUD_BLOBBERNAUT_OVERMIND "blobbernaut_overmind"
+
+#define HUD_GUARDIAN_MANIFEST "guardian_manifest"
+#define HUD_GUARDIAN_RECALL "guardian_recall"
+#define HUD_GUARDIAN_LIGHT "guardian_light"
+#define HUD_GUARDIAN_COMMUNICATE "guardian_communicate"
+#define HUD_GUARDIAN_TOGGLE "guardian_toggle"
+
+#define HUD_VOIDWALKER_SPACE_CAMO "voidwalker_space_camo"
+#define HUD_VOIDWALKER_VOID_JUMP "voidwalker_void_jump"
+
+#define HUD_CHANGELING_CHEMS "changeling_chems"
+#define HUD_CHANGELING_STING "changeling_sting"
+
+#define HUD_CULTIST_ARROW "cultist_arrow"
+
+#define HUD_HERETIC_ARROW "heretic_arrow"
+#define HUD_HERETIC_MOON_HEALTH "heretic_moon_health"
+
+#define HUD_WIZARD_COMPACT_PERKS "wizard_compact_perks"
+#define HUD_WIZARD_PERK(slot) "wizard_perk:[slot]"
+
+/// Converts item slots to hud keys
+#define HUD_KEY_ITEM_SLOT(slot) "item_slot:[slot]"
+/// Converts item slots to hud keys as a compiler constant
+#define HUD_KEY_ITEM_SLOT_CONST(slot) "item_slot:" + #slot
+/// Hand2hudkey
+#define HUD_KEY_HAND_SLOT(slot) "hand_slot:[slot]"
+
+#define HUD_MULTITOOL_ARROW "multitool_arrow"
+
+#define HUD_XENOBIO_CONSOLE "xenobio_console"
+
/*
These defines specificy screen locations. For more information, see the byond documentation on the screen_loc var.
@@ -63,7 +212,7 @@
#define ui_combo "CENTER+4:24,SOUTH+1:7" //combo meter for martial arts
//Lower right, persistent menu
-#define ui_rest "EAST-1:28,SOUTH+1:7"
+#define ui_below_throw "EAST-1:28,SOUTH+1:7"
#define ui_drop_throw "EAST-1:28,SOUTH+1:24"
#define ui_above_throw "EAST-1:28,SOUTH+1:41"
#define ui_above_movement "EAST-2:26,SOUTH+1:7"
@@ -71,7 +220,6 @@
#define ui_above_intent "EAST-3:24, SOUTH+1:7"
#define ui_movi "EAST-2:26,SOUTH:5"
#define ui_acti "EAST-3:24,SOUTH:5"
-#define ui_combat_toggle "EAST-3:24,SOUTH:5"
#define ui_floor_change "BOTTOM+1:8,RIGHT-1:28"
#define ui_zonesel "EAST-1:28,SOUTH:5"
#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12)
@@ -123,7 +271,7 @@
#define ui_human_navigate "EAST-3:7,SOUTH+1:7"
#define ui_human_language "EAST-3:7,SOUTH+1:24"
#define ui_human_area "EAST-3:24,SOUTH+1:24"
-#define ui_human_memories_area "EAST-4:22,SOUTH+1:7"
+#define ui_human_memories_menu "EAST-4:22,SOUTH+1:7"
//Drones
#define ui_drone_drop "CENTER+1:18,SOUTH:5"
@@ -158,6 +306,7 @@
#define ui_alien_navigate_menu "EAST-4:6,SOUTH:5"
#define ui_alien_memories_menu "EAST-4:22,SOUTH:1:20"
#define ui_alien_floor_change "EAST-3:24,SOUTH:20"
+#define ui_alienplasmadisplay_human "EAST,CENTER-5:8"
//AI
#define ui_ai_core "BOTTOM:6,RIGHT-4"
@@ -206,12 +355,12 @@
#define ui_ghost_spawners_menu "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_dnr "SOUTH:6,CENTER:24"
+#define ui_ghost_dnr "SOUTH:6,CENTER:24"
#define ui_ghost_teleport "SOUTH:6,CENTER+1:24"
-#define ui_ghost_settings "SOUTH: 6, CENTER+2:24"
-#define ui_ghost_minigames "SOUTH: 6, CENTER+3:24"
-#define ui_ghost_language_menu "SOUTH: 6, CENTER+4:22"
-#define ui_ghost_floor_changer "SOUTH: 6, CENTER+4:7"
+#define ui_ghost_settings "SOUTH:6,CENTER+2:24"
+#define ui_ghost_minigames "SOUTH:6,CENTER+3:24"
+#define ui_ghost_language_menu "SOUTH:6,CENTER+4:22"
+#define ui_ghost_floor_changer "SOUTH:6,CENTER+4:7"
//Voidwalker
#define ui_voidwalker_left_of_hands "CENTER+-2:16,SOUTH+0:5"
diff --git a/code/__DEFINES/sight.dm b/code/__DEFINES/sight.dm
index 0a14db75ef9..ab88e6e2c30 100644
--- a/code/__DEFINES/sight.dm
+++ b/code/__DEFINES/sight.dm
@@ -76,4 +76,5 @@
#define INVISIBILITY_SOURCE_INVISIMIN "invisimin"
#define INVISIBILITY_SOURCE_STEALTHMODE "stealthmode"
+#define INVISIBILITY_SOURCE_SLEEP_HUD_BUTTON "sleep_hud_button"
diff --git a/code/_onclick/hud/action_group.dm b/code/_onclick/hud/action_group.dm
new file mode 100644
index 00000000000..a8766516b23
--- /dev/null
+++ b/code/_onclick/hud/action_group.dm
@@ -0,0 +1,209 @@
+/datum/action_group
+ /// The hud we're owned by
+ var/datum/hud/owner
+ /// The actions we're managing
+ var/list/atom/movable/screen/movable/action_button/actions
+ /// The initial vertical offset of our action buttons
+ var/north_offset = 0
+ /// The pixel vertical offset of our action buttons
+ var/pixel_north_offset = 0
+ /// Max amount of buttons we can have per row
+ /// Indexes at 1
+ var/column_max = 0
+ /// How far "ahead" of the first row we start. Lets us "scroll" our rows
+ /// Indexes at 1
+ var/row_offset = 0
+ /// How many rows of actions we can have at max before we just stop hiding
+ /// Indexes at 1
+ var/max_rows = INFINITY
+ /// The screen location we go by
+ var/location
+ /// Our landing screen object
+ var/atom/movable/screen/action_landing/landing
+
+/datum/action_group/New(datum/hud/owner)
+ ..()
+ actions = list()
+ src.owner = owner
+
+/datum/action_group/Destroy()
+ owner = null
+ QDEL_NULL(landing)
+ QDEL_LIST(actions)
+ return ..()
+
+/datum/action_group/proc/insert_action(atom/movable/screen/action, index)
+ if(action in actions)
+ if(actions[index] == action)
+ return
+ actions -= action // Don't dupe, come on
+ if(!index)
+ index = length(actions) + 1
+ index = min(length(actions) + 1, index)
+ actions.Insert(index, action)
+ refresh_actions()
+
+/datum/action_group/proc/remove_action(atom/movable/screen/action)
+ actions -= action
+ refresh_actions()
+
+/datum/action_group/proc/refresh_actions()
+
+ // We don't use size() here because landings are not canon
+ var/total_rows = ROUND_UP(length(actions) / column_max)
+ total_rows -= max_rows // Lets get the amount of rows we're off from our max
+ row_offset = clamp(row_offset, 0, total_rows) // You're not allowed to offset so far that we have a row of blank space
+
+ var/button_number = 0
+ for(var/atom/movable/screen/button as anything in actions)
+ var/postion = ButtonNumberToScreenCoords(button_number )
+ button.screen_loc = postion
+ button_number++
+
+ if(landing)
+ var/postion = ButtonNumberToScreenCoords(button_number, landing = TRUE) // Need a good way to count buttons off screen, but allow this to display in the right place if it's being placed with no concern for dropdown
+ landing.screen_loc = postion
+ button_number++
+
+/// Accepts a number represeting our position in the group, indexes at 0 to make the math nicer
+/datum/action_group/proc/ButtonNumberToScreenCoords(number, landing = FALSE)
+ var/row = round(number / column_max)
+ row -= row_offset // If you're less then 0, you don't get to render, this lets us "scroll" rows ya feel?
+ if(row < 0)
+ return null
+
+ // Could use >= here, but I think it's worth noting that the two start at different places, since row is based on number here
+ if(row > max_rows - 1)
+ if(!landing) // If you're not a landing, go away please. thx
+ return null
+ // We always want to render landings, even if their action button can't be displayed.
+ // So we set a row equal to the max amount of rows + 1. Willing to overrun that max slightly to properly display the landing spot
+ row = max_rows // Remembering that max_rows indexes at 1, and row indexes at 0
+
+ // We're going to need to set our column to match the first item in the last row, so let's set number properly now
+ number = row * column_max
+
+ var/visual_row = row + north_offset
+ var/coord_row = visual_row ? "-[visual_row]" : "+0"
+
+ var/visual_column = number % column_max
+ var/coord_col = "+[visual_column]"
+ var/coord_col_offset = 4 + 2 * (visual_column + 1)
+ return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:-[pixel_north_offset]"
+
+/datum/action_group/proc/check_against_view()
+ var/owner_view = owner?.mymob?.canon_client?.view
+ if(!owner_view)
+ return
+ // Unlikey as it is, we may have been changed. Want to start from our target position and fail down
+ column_max = initial(column_max)
+ // Convert our viewer's view var into a workable offset
+ var/list/view_size = view_to_pixels(owner_view)
+
+ // We're primarially concerned about width here, if someone makes us 1x2000 I wish them a swift and watery death
+ var/furthest_screen_loc = ButtonNumberToScreenCoords(column_max - 1)
+ var/list/offsets = screen_loc_to_offset(furthest_screen_loc, owner_view)
+ if(offsets[1] > ICON_SIZE_X && offsets[1] < view_size[1] && offsets[2] > ICON_SIZE_Y && offsets[2] < view_size[2]) // We're all good
+ return
+
+ for(column_max in column_max - 1 to 1 step -1) // Yes I could do this by unwrapping ButtonNumberToScreenCoords, but I don't feel like it
+ var/tested_screen_loc = ButtonNumberToScreenCoords(column_max)
+ offsets = screen_loc_to_offset(tested_screen_loc, owner_view)
+ // We've found a valid max length, pack it in
+ if(offsets[1] > ICON_SIZE_X && offsets[1] < view_size[1] && offsets[2] > ICON_SIZE_Y && offsets[2] < view_size[2])
+ break
+ // Use our newly resized column max
+ refresh_actions()
+
+/// Returns the amount of objects we're storing at the moment
+/datum/action_group/proc/size()
+ var/amount = length(actions)
+ if(landing)
+ amount += 1
+ return amount
+
+/datum/action_group/proc/index_of(atom/movable/screen/get_location)
+ return actions.Find(get_location)
+
+/// Generates a landing object that can be dropped on to join this group
+/datum/action_group/proc/generate_landing()
+ if(landing)
+ return
+ landing = new()
+ landing.set_owner(src)
+ refresh_actions()
+
+/// Clears any landing objects we may currently have
+/datum/action_group/proc/clear_landing()
+ QDEL_NULL(landing)
+
+/datum/action_group/proc/update_landing()
+ if(!landing)
+ return
+ landing.refresh_owner()
+
+/datum/action_group/proc/scroll(amount)
+ row_offset += amount
+ refresh_actions()
+
+/datum/action_group/palette
+ north_offset = 2
+ column_max = 3
+ max_rows = 3
+ location = SCRN_OBJ_IN_PALETTE
+
+/datum/action_group/palette/insert_action(atom/movable/screen/action, index)
+ . = ..()
+ var/atom/movable/screen/button_palette/palette = owner.screen_objects[HUD_MOB_TOGGLE_PALETTE]
+ palette.play_item_added()
+
+/datum/action_group/palette/remove_action(atom/movable/screen/action)
+ . = ..()
+ var/atom/movable/screen/button_palette/palette = owner.screen_objects[HUD_MOB_TOGGLE_PALETTE]
+ palette.play_item_removed()
+ if(!length(actions))
+ palette.set_expanded(FALSE)
+
+/datum/action_group/palette/refresh_actions()
+ var/atom/movable/screen/button_palette/palette = owner.screen_objects[HUD_MOB_TOGGLE_PALETTE]
+ var/atom/movable/screen/palette_scroll/scroll_down = owner.screen_objects[HUD_MOB_PALETTE_DOWN]
+ var/atom/movable/screen/palette_scroll/scroll_up = owner.screen_objects[HUD_MOB_PALETTE_UP]
+
+ var/actions_above = round((owner.listed_actions.size() - 1) / owner.listed_actions.column_max)
+ north_offset = initial(north_offset) + actions_above
+
+ palette.screen_loc = ui_action_palette_offset(actions_above)
+ var/action_count = length(owner?.mymob?.actions)
+ var/our_row_count = round((length(actions) - 1) / column_max)
+ if(!action_count)
+ palette.screen_loc = null
+
+ if(palette.expanded && action_count && our_row_count >= max_rows)
+ scroll_down.screen_loc = ui_palette_scroll_offset(actions_above)
+ scroll_up.screen_loc = ui_palette_scroll_offset(actions_above)
+ else
+ scroll_down.screen_loc = null
+ scroll_up.screen_loc = null
+
+ return ..()
+
+/datum/action_group/palette/ButtonNumberToScreenCoords(number, landing)
+ var/atom/movable/screen/button_palette/palette = owner.screen_objects[HUD_MOB_TOGGLE_PALETTE]
+ if(palette.expanded)
+ return ..()
+
+ if(!landing)
+ return null
+
+ // We only render the landing in this case, so we force it to be the second item displayed (Second rather then first since it looks nicer)
+ // Remember the number var indexes at 0
+ return ..(1 + (row_offset * column_max), landing)
+
+/datum/action_group/listed
+ pixel_north_offset = 6
+ column_max = 10
+ location = SCRN_OBJ_IN_LIST
+
+/datum/action_group/listed/refresh_actions()
+ . = ..()
+ owner?.palette_actions.refresh_actions() // We effect them, so we gotta refresh em
diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm
index 728439e5fad..84e303a8894 100644
--- a/code/_onclick/hud/ai.dm
+++ b/code/_onclick/hud/ai.dm
@@ -1,345 +1,26 @@
-/atom/movable/screen/ai
- icon = 'icons/hud/screen_ai.dmi'
- mouse_over_pointer = MOUSE_HAND_POINTER
-
-/atom/movable/screen/ai/Click()
- if(isobserver(usr) || usr.incapacitated)
- return TRUE
-
-/atom/movable/screen/ai/aicore
- name = "AI core"
- icon_state = "ai_core"
-
-/atom/movable/screen/ai/aicore/Click()
- if(isobserver(usr))
- return
- var/mob/living/silicon/ai/AI = usr
- AI.view_core()
-
-/atom/movable/screen/ai/camera_list
- name = "Show Camera List"
- icon_state = "camera"
-
-/atom/movable/screen/ai/camera_list/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.show_camera_list()
-
-/atom/movable/screen/ai/camera_track
- name = "Track With Camera"
- icon_state = "track"
-
-/atom/movable/screen/ai/camera_track/Click()
- . = ..()
- if(.)
- return
- var/mob/living/silicon/ai/AI = usr
- AI.ai_camera_track()
-
-/atom/movable/screen/ai/camera_light
- name = "Toggle Camera Light"
- icon_state = "camera_light"
-
-/atom/movable/screen/ai/camera_light/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.toggle_camera_light()
-
-/atom/movable/screen/ai/modpc
- name = "Messenger"
- icon_state = "pda_send"
- var/mob/living/silicon/ai/robot
-
-/atom/movable/screen/ai/modpc/Click()
- . = ..()
- if(.)
- return
- robot.modularInterface?.interact(robot)
-
-/atom/movable/screen/ai/crew_monitor
- name = "Crew Monitoring Console"
- icon_state = "crew_monitor"
-
-/atom/movable/screen/ai/crew_monitor/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- GLOB.crewmonitor.show(AI,AI)
-
-/atom/movable/screen/ai/crew_manifest
- name = "Crew Manifest"
- icon_state = "manifest"
-
-/atom/movable/screen/ai/crew_manifest/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.ai_roster()
-
-/atom/movable/screen/ai/alerts
- name = "Show Alerts"
- icon_state = "alerts"
-
-/atom/movable/screen/ai/alerts/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.alert_control.ui_interact(AI)
-
-/atom/movable/screen/ai/announcement
- name = "Make Vox Announcement"
- icon_state = "announcement"
-
-/atom/movable/screen/ai/announcement/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.announcement()
-
-/atom/movable/screen/ai/call_shuttle
- name = "Call Emergency Shuttle"
- icon_state = "call_shuttle"
-
-/atom/movable/screen/ai/call_shuttle/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.ai_call_shuttle()
-
-/atom/movable/screen/ai/state_laws
- name = "State Laws"
- icon_state = "state_laws"
-
-/atom/movable/screen/ai/state_laws/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.checklaws()
-
-/atom/movable/screen/ai/image_take
- name = "Take Image"
- icon_state = "take_picture"
-
-/atom/movable/screen/ai/image_take/Click()
- if(..())
- return
- if(isAI(usr))
- var/mob/living/silicon/ai/AI = usr
- AI.aicamera.toggle_camera_mode(usr)
- else if(iscyborg(usr))
- var/mob/living/silicon/robot/R = usr
- R.aicamera.toggle_camera_mode(usr)
-
-/atom/movable/screen/ai/image_view
- name = "View Images"
- icon_state = "view_images"
-
-/atom/movable/screen/ai/image_view/Click()
- if(..())
- return
- if(isAI(usr))
- var/mob/living/silicon/ai/AI = usr
- AI.aicamera.viewpictures(usr)
-
-/atom/movable/screen/ai/sensors
- name = "Sensor Augmentation"
- icon_state = "ai_sensor"
-
-/atom/movable/screen/ai/sensors/Click()
- if(..())
- return
- var/mob/living/silicon/S = usr
- S.toggle_sensors()
-
-/atom/movable/screen/ai/multicam
- name = "Multicamera Mode"
- icon_state = "multicam"
-
-/atom/movable/screen/ai/multicam/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.toggle_multicam()
-
-/atom/movable/screen/ai/add_multicam
- name = "New Camera"
- icon_state = "new_cam"
-
-/atom/movable/screen/ai/add_multicam/Click()
- if(..())
- return
- var/mob/living/silicon/ai/AI = usr
- AI.drop_new_multicam()
-
-/atom/movable/screen/ai/floor_indicator
- icon_state = "zindicator"
- screen_loc = ui_ai_floor_indicator
-
-/atom/movable/screen/ai/floor_indicator/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- if(istype(hud_owner))
- RegisterSignal(hud_owner, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(update_z))
- update_z()
-
-/atom/movable/screen/ai/floor_indicator/proc/update_z(datum/hud/source)
- SIGNAL_HANDLER
- var/mob/living/silicon/ai/ai = get_mob() //if you use this for anyone else i will find you
- if(isnull(ai))
- return
- var/turf/locturf = isturf(ai.loc) ? get_turf(ai.eyeobj) : get_turf(ai) //must be a var cuz error
- var/ai_z = locturf.z
- var/text = "Level
[ai_z]"
- if(SSmapping.level_trait(ai_z, ZTRAIT_STATION))
- text = "Floor
[ai_z - 1]"
- else if (SSmapping.level_trait(ai_z, ZTRAIT_NOPHASE))
- text = "ERROR"
- maptext = MAPTEXT_TINY_UNICODE("
[text]
")
-
-/atom/movable/screen/ai/go_up
- name = "go up"
- icon_state = "up"
- screen_loc = ui_ai_godownup
-
-/atom/movable/screen/ai/go_up/Initialize(mapload)
- . = ..()
- register_context()
-
-/atom/movable/screen/ai/go_up/add_context(atom/source, list/context, obj/item/held_item, mob/user)
- . = ..()
- context[SCREENTIP_CONTEXT_LMB] = "Go up a floor"
- return CONTEXTUAL_SCREENTIP_SET
-
-/atom/movable/screen/ai/go_up/Click(location,control,params)
- var/mob/ai = get_mob() //the core
- flick("uppressed",src)
- if(!isturf(ai.loc) || usr != ai) //aicard and stuff
- return
- ai.up()
-
-/atom/movable/screen/ai/go_up/down
- name = "go down"
- icon_state = "down"
-
-/atom/movable/screen/ai/go_up/down/add_context(atom/source, list/context, obj/item/held_item, mob/user)
- . = ..()
- context[SCREENTIP_CONTEXT_LMB] = "Go down a floor"
- return CONTEXTUAL_SCREENTIP_SET
-
-/atom/movable/screen/ai/go_up/down/Click(location,control,params)
- var/mob/ai = get_mob() //the core
- flick("downpressed",src)
- if(!isturf(ai.loc) || usr != ai) //aicard and stuff
- return
- ai.down()
-
/datum/hud/ai
ui_style = 'icons/hud/screen_ai.dmi'
-/datum/hud/ai/New(mob/owner)
- ..()
- var/atom/movable/screen/using
- var/mob/living/silicon/ai/myai = mymob
-
-// Language menu
- using = new /atom/movable/screen/language_menu(null, src)
- using.icon = ui_style
- using.screen_loc = ui_ai_language_menu
- static_inventory += using
-
-// Memories
- using = new /atom/movable/screen/memories(null, src)
- using.icon = ui_style
- using.screen_loc = ui_ai_memories_menu
- static_inventory += using
-
-// Z-level floor change
- using = new /atom/movable/screen/ai/floor_indicator(null, src) //These come with their own predefined screen locs
- static_inventory += using
- using = new /atom/movable/screen/ai/go_up(null, src)
- static_inventory += using
- using = new /atom/movable/screen/ai/go_up/down(null, src)
- static_inventory += using
-
-//AI core
- using = new /atom/movable/screen/ai/aicore(null, src)
- using.screen_loc = ui_ai_core
- static_inventory += using
-
-//Camera list
- using = new /atom/movable/screen/ai/camera_list(null, src)
- using.screen_loc = ui_ai_camera_list
- static_inventory += using
-
-//Track
- using = new /atom/movable/screen/ai/camera_track(null, src)
- using.screen_loc = ui_ai_track_with_camera
- static_inventory += using
-
-//Camera light
- using = new /atom/movable/screen/ai/camera_light(null, src)
- using.screen_loc = ui_ai_camera_light
- static_inventory += using
-
-//Crew Monitoring
- using = new /atom/movable/screen/ai/crew_monitor(null, src)
- using.screen_loc = ui_ai_crew_monitor
- static_inventory += using
-
-//Crew Manifest
- using = new /atom/movable/screen/ai/crew_manifest(null, src)
- using.screen_loc = ui_ai_crew_manifest
- static_inventory += using
-
-//Alerts
- using = new /atom/movable/screen/ai/alerts(null, src)
- using.screen_loc = ui_ai_alerts
- static_inventory += using
-
-//Announcement
- using = new /atom/movable/screen/ai/announcement(null, src)
- using.screen_loc = ui_ai_announcement
- static_inventory += using
-
-//Shuttle
- using = new /atom/movable/screen/ai/call_shuttle(null, src)
- using.screen_loc = ui_ai_shuttle
- static_inventory += using
-
-//Laws
- using = new /atom/movable/screen/ai/state_laws(null, src)
- using.screen_loc = ui_ai_state_laws
- static_inventory += using
-
-// Modular Interface
- using = new /atom/movable/screen/ai/modpc(null, src)
- using.screen_loc = ui_ai_mod_int
- static_inventory += using
- var/atom/movable/screen/ai/modpc/tabletbutton = using
- tabletbutton.robot = myai
-
-//Take image
- using = new /atom/movable/screen/ai/image_take(null, src)
- using.screen_loc = ui_ai_take_picture
- static_inventory += using
-
-//View images
- using = new /atom/movable/screen/ai/image_view(null, src)
- using.screen_loc = ui_ai_view_images
- static_inventory += using
-
-//Medical/Security sensors
- using = new /atom/movable/screen/ai/sensors(null, src)
- using.screen_loc = ui_ai_sensor
- static_inventory += using
-
-//Multicamera mode
- using = new /atom/movable/screen/ai/multicam(null, src)
- using.screen_loc = ui_ai_multicam
- static_inventory += using
-
-//Add multicamera camera
- using = new /atom/movable/screen/ai/add_multicam(null, src)
- using.screen_loc = ui_ai_add_multicam
- static_inventory += using
+/datum/hud/ai/initialize_screen_objects()
+ . = ..()
+ add_screen_object(/atom/movable/screen/language_menu, HUD_MOB_LANGUAGE_MENU, HUD_GROUP_STATIC, ui_style, ui_ai_language_menu)
+ add_screen_object(/atom/movable/screen/memories, HUD_MOB_MEMORIES, HUD_GROUP_STATIC, ui_style, ui_ai_memories_menu)
+ add_screen_object(/atom/movable/screen/ai/floor_indicator, HUD_AI_FLOOR_INDICATOR)
+ add_screen_object(/atom/movable/screen/ai/go_up, HUD_AI_GO_UP)
+ add_screen_object(/atom/movable/screen/ai/go_up/down, HUD_AI_GO_DOWN)
+ add_screen_object(/atom/movable/screen/ai/aicore, HUD_AI_AICORE)
+ add_screen_object(/atom/movable/screen/ai/camera_list, HUD_AI_CAMERA_LIST)
+ add_screen_object(/atom/movable/screen/ai/camera_track, HUD_AI_CAMERA_TRACK)
+ add_screen_object(/atom/movable/screen/ai/camera_light, HUD_AI_CAMERA_LIGHT)
+ add_screen_object(/atom/movable/screen/ai/crew_monitor, HUD_AI_CREW_MONITOR)
+ add_screen_object(/atom/movable/screen/ai/crew_manifest, HUD_AI_CREW_MANIFEST)
+ add_screen_object(/atom/movable/screen/ai/alerts, HUD_SILICON_ALERTS)
+ add_screen_object(/atom/movable/screen/ai/announcement, HUD_AI_ANNOUNCEMENT)
+ add_screen_object(/atom/movable/screen/ai/call_shuttle, HUD_AI_CALL_SHUTTLE)
+ add_screen_object(/atom/movable/screen/ai/state_laws, HUD_AI_STATE_LAWS)
+ add_screen_object(/atom/movable/screen/ai/image_take, HUD_AI_TAKE_IMAGE)
+ add_screen_object(/atom/movable/screen/ai/image_view, HUD_AI_IMAGE_VIEW)
+ add_screen_object(/atom/movable/screen/ai/sensors, HUD_AI_SENSORS)
+ add_screen_object(/atom/movable/screen/ai/multicam, HUD_AI_MULTICAM)
+ add_screen_object(/atom/movable/screen/ai/add_multicam, HUD_AI_ADD_MULTICAM)
+ add_screen_object(/atom/movable/screen/ai/modpc, HUD_SILICON_TABLET)
diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm
index 822fe712850..4ea86de55e7 100644
--- a/code/_onclick/hud/alien.dm
+++ b/code/_onclick/hud/alien.dm
@@ -1,136 +1,36 @@
-/atom/movable/screen/alien
- icon = 'icons/hud/screen_alien.dmi'
-
-/atom/movable/screen/alien/leap
- name = "toggle leap"
- icon_state = "leap_off"
-
-/atom/movable/screen/alien/leap/Click()
- if(isalienhunter(usr))
- var/mob/living/carbon/alien/adult/hunter/AH = usr
- AH.toggle_leap()
-
-/atom/movable/screen/alien/plasma_display
- name = "plasma stored"
- icon_state = "power_display"
- screen_loc = ui_alienplasmadisplay
-
-/atom/movable/screen/alien/alien_queen_finder
- name = "queen sense"
- desc = "Allows you to sense the general direction of your Queen."
- icon_state = "queen_finder"
- screen_loc = ui_alien_queen_finder
-
/datum/hud/alien
ui_style = 'icons/hud/screen_alien.dmi'
-/datum/hud/alien/New(mob/living/carbon/alien/adult/owner)
- ..()
-
- var/atom/movable/screen/using
-
-//equippable shit
-
-//hands
+/datum/hud/alien/initialize_screen_objects()
+ . = ..()
build_hand_slots()
-//begin buttons
-
- using = new /atom/movable/screen/swap_hand(null, src)
- using.icon = ui_style
+ var/atom/movable/screen/using
+ using = add_screen_object(/atom/movable/screen/swap_hand, HUD_MOB_SWAPHAND_1, HUD_GROUP_STATIC, ui_style, ui_swaphand_position(mymob, 1))
using.icon_state = "swap_1"
- using.screen_loc = ui_swaphand_position(owner, 1)
- static_inventory += using
-
- using = new /atom/movable/screen/swap_hand(null, src)
- using.icon = ui_style
+ using = add_screen_object(/atom/movable/screen/swap_hand, HUD_MOB_SWAPHAND_2, HUD_GROUP_STATIC, ui_style, ui_swaphand_position(mymob, 2))
using.icon_state = "swap_2"
- using.screen_loc = ui_swaphand_position(owner, 2)
- static_inventory += using
- action_intent = new /atom/movable/screen/combattoggle/flashy(null, src)
- action_intent.icon = ui_style
- action_intent.screen_loc = ui_combat_toggle
- static_inventory += action_intent
+ add_screen_object(/atom/movable/screen/combattoggle/flashy, HUD_MOB_INTENTS, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/floor_changer, HUD_MOB_FLOOR_CHANGER, HUD_GROUP_STATIC, ui_style, ui_alien_floor_change)
+ add_screen_object(/atom/movable/screen/language_menu, HUD_MOB_LANGUAGE_MENU, HUD_GROUP_STATIC, ui_style, ui_alien_language_menu)
+ add_screen_object(/atom/movable/screen/navigate, HUD_MOB_NAVIGATE_MENU, HUD_GROUP_STATIC, ui_style, ui_alien_navigate_menu)
+ add_screen_object(/atom/movable/screen/zone_sel/alien, HUD_MOB_ZONE_SELECTOR)
+ add_screen_object(/atom/movable/screen/drop, HUD_MOB_DROP, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style, ui_above_movement)
+ add_screen_object(/atom/movable/screen/resist, HUD_MOB_RESIST, HUD_GROUP_HOTKEYS, ui_style)
+ add_screen_object(/atom/movable/screen/throw_catch, HUD_MOB_THROW, HUD_GROUP_HOTKEYS, ui_style)
+ add_screen_object(/atom/movable/screen/rest, HUD_MOB_REST, HUD_GROUP_HOTKEYS, ui_style)
+ add_screen_object(/atom/movable/screen/sleep, HUD_MOB_SLEEP, HUD_GROUP_HOTKEYS, ui_style)
+ add_screen_object(/atom/movable/screen/healths/alien, HUD_MOB_HEALTH, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/alien/plasma_display, HUD_ALIEN_PLASMA_DISPLAY, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/memories, HUD_MOB_MEMORIES, HUD_GROUP_STATIC, ui_style, ui_alien_memories_menu)
if(isalienhunter(mymob))
- var/mob/living/carbon/alien/adult/hunter/H = mymob
- H.leap_icon = new /atom/movable/screen/alien/leap()
- H.leap_icon.screen_loc = ui_alien_storage_r
- static_inventory += H.leap_icon
-
- floor_change = new /atom/movable/screen/floor_changer(null, src)
- floor_change.icon = ui_style
- floor_change.screen_loc = ui_alien_floor_change
- static_inventory += floor_change
-
- using = new/atom/movable/screen/language_menu(null, src)
- using.icon = ui_style
- using.screen_loc = ui_alien_language_menu
- static_inventory += using
-
- using = new /atom/movable/screen/navigate(null, src)
- using.icon = ui_style
- using.screen_loc = ui_alien_navigate_menu
- static_inventory += using
-
- using = new /atom/movable/screen/memories(null, src)
- using.icon = ui_style
- using.screen_loc = ui_alien_memories_menu
- static_inventory += using
-
- using = new /atom/movable/screen/drop(null, src)
- using.icon = ui_style
- using.screen_loc = ui_drop_throw
- static_inventory += using
-
- resist_icon = new /atom/movable/screen/resist(null, src)
- resist_icon.icon = ui_style
- resist_icon.screen_loc = ui_above_movement
- resist_icon.update_appearance()
- hotkeybuttons += resist_icon
-
- throw_icon = new /atom/movable/screen/throw_catch(null, src)
- throw_icon.icon = ui_style
- throw_icon.screen_loc = ui_drop_throw
- hotkeybuttons += throw_icon
-
- pull_icon = new /atom/movable/screen/pull(null, src)
- pull_icon.icon = ui_style
- pull_icon.update_appearance()
- pull_icon.screen_loc = ui_above_movement
- static_inventory += pull_icon
-
- rest_icon = new /atom/movable/screen/rest(null, src)
- rest_icon.icon = ui_style
- rest_icon.screen_loc = ui_rest
- rest_icon.update_appearance()
- static_inventory += rest_icon
-
- sleep_icon = new /atom/movable/screen/sleep(null, src)
- sleep_icon.icon = ui_style
- sleep_icon.screen_loc = ui_above_throw
-
-//begin indicators
-
- healths = new /atom/movable/screen/healths/alien(null, src)
- infodisplay += healths
-
- alien_plasma_display = new /atom/movable/screen/alien/plasma_display(null, src)
- infodisplay += alien_plasma_display
+ add_screen_object(/atom/movable/screen/alien/leap, HUD_ALIEN_HUNTER_LEAP, HUD_GROUP_STATIC, ui_style)
if(!isalienqueen(mymob))
- alien_queen_finder = new /atom/movable/screen/alien/alien_queen_finder(null, src)
- infodisplay += alien_queen_finder
-
- zone_select = new /atom/movable/screen/zone_sel/alien(null, src)
- zone_select.update_appearance()
- static_inventory += zone_select
-
- for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
- if(inv.slot_id)
- inv_slots[TOBITSHIFT(inv.slot_id) + 1] = inv
- inv.update_appearance()
+ add_screen_object(/atom/movable/screen/alien/plasma_display, HUD_ALIEN_QUEEN_FINDER, HUD_GROUP_INFO)
/datum/hud/alien/persistent_inventory_update()
if(!mymob)
diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm
index 3331ac8c790..25ae3ba34bb 100644
--- a/code/_onclick/hud/alien_larva.dm
+++ b/code/_onclick/hud/alien_larva.dm
@@ -1,54 +1,16 @@
/datum/hud/larva
ui_style = 'icons/hud/screen_alien.dmi'
-/datum/hud/larva/New(mob/owner)
- ..()
- var/atom/movable/screen/using
-
- action_intent = new /atom/movable/screen/combattoggle/flashy(null, src)
- action_intent.icon = ui_style
- action_intent.screen_loc = ui_combat_toggle
- static_inventory += action_intent
-
- floor_change = new /atom/movable/screen/floor_changer(null, src)
- floor_change.icon = ui_style
- floor_change.screen_loc = ui_alien_floor_change
- static_inventory += floor_change
-
- healths = new /atom/movable/screen/healths/alien(null, src)
- infodisplay += healths
-
- alien_queen_finder = new /atom/movable/screen/alien/alien_queen_finder(null, src)
- infodisplay += alien_queen_finder
-
- pull_icon = new /atom/movable/screen/pull(null, src)
- pull_icon.icon = 'icons/hud/screen_alien.dmi'
- pull_icon.update_appearance()
- pull_icon.screen_loc = ui_above_movement
- hotkeybuttons += pull_icon
-
- rest_icon = new /atom/movable/screen/rest(null, src)
- rest_icon.icon = ui_style
- rest_icon.screen_loc = ui_rest
- rest_icon.update_appearance()
- static_inventory += rest_icon
-
- sleep_icon = new /atom/movable/screen/sleep(null, src)
- sleep_icon.icon = ui_style
- sleep_icon.screen_loc = ui_drop_throw
-
- using = new/atom/movable/screen/language_menu(null, src)
- using.screen_loc = ui_alien_language_menu
- static_inventory += using
-
- using = new /atom/movable/screen/navigate(null, src)
- using.screen_loc = ui_alien_navigate_menu
- static_inventory += using
-
- using = new /atom/movable/screen/memories(null, src)
- using.screen_loc = ui_alien_memories_menu
- static_inventory += using
-
- zone_select = new /atom/movable/screen/zone_sel/alien(null, src)
- zone_select.update_appearance()
- static_inventory += zone_select
+/datum/hud/larva/initialize_screen_objects()
+ . = ..()
+ add_screen_object(/atom/movable/screen/combattoggle/flashy, HUD_MOB_INTENTS, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/floor_changer, HUD_MOB_FLOOR_CHANGER, HUD_GROUP_STATIC, ui_style, ui_alien_floor_change)
+ add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/rest, HUD_MOB_REST, HUD_GROUP_HOTKEYS, ui_style)
+ add_screen_object(/atom/movable/screen/sleep, HUD_MOB_SLEEP, HUD_GROUP_HOTKEYS, ui_style, ui_drop_throw)
+ add_screen_object(/atom/movable/screen/language_menu, HUD_MOB_LANGUAGE_MENU, ui_loc = ui_alien_language_menu)
+ add_screen_object(/atom/movable/screen/navigate, HUD_MOB_NAVIGATE_MENU, ui_loc = ui_alien_navigate_menu)
+ add_screen_object(/atom/movable/screen/zone_sel/alien, HUD_MOB_ZONE_SELECTOR)
+ add_screen_object(/atom/movable/screen/healths/alien, HUD_MOB_HEALTH, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/alien/alien_queen_finder, HUD_ALIEN_QUEEN_FINDER, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/memories, HUD_MOB_MEMORIES, HUD_GROUP_STATIC, ui_style, ui_alien_memories_menu)
diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm
index 6b5213c027b..cf92ff67b47 100644
--- a/code/_onclick/hud/blob_overmind.dm
+++ b/code/_onclick/hud/blob_overmind.dm
@@ -1,198 +1,12 @@
-
-/atom/movable/screen/blob
- icon = 'icons/hud/blob.dmi'
- mouse_over_pointer = MOUSE_HAND_POINTER
-
-/atom/movable/screen/blob/MouseEntered(location,control,params)
+/datum/hud/blob_overmind/initialize_screen_objects()
. = ..()
- openToolTip(usr,src,params,title = name,content = desc, theme = "blob")
-
-/atom/movable/screen/blob/MouseExited()
- closeToolTip(usr)
-
-/atom/movable/screen/blob/jump_to_node
- icon_state = "ui_tonode"
- name = "Jump to Node"
- desc = "Moves your camera to a selected blob node."
-
-/atom/movable/screen/blob/jump_to_node/Click()
- if(!isovermind(usr))
- return FALSE
- var/mob/eye/blob/blob = usr
- blob.jump_to_node()
-
-/atom/movable/screen/blob/jump_to_core
- icon_state = "ui_tocore"
- name = "Jump to Core"
- desc = "Moves your camera to your blob core."
-
-/atom/movable/screen/blob/jump_to_core/MouseEntered(location,control,params)
- if(hud?.mymob && isovermind(hud.mymob))
- var/mob/eye/blob/B = hud.mymob
- if(!B.placed)
- name = "Place Blob Core"
- desc = "Attempt to place your blob core at this location."
- else
- name = initial(name)
- desc = initial(desc)
- return ..()
-
-/atom/movable/screen/blob/jump_to_core/Click()
- if(!isovermind(usr))
- return FALSE
- var/mob/eye/blob/blob = usr
- if(!blob.placed)
- blob.place_blob_core(BLOB_NORMAL_PLACEMENT)
- blob.transport_core()
-
-/atom/movable/screen/blob/blobbernaut
- icon_state = "ui_blobbernaut"
- // Name and description get given their proper values on Initialize()
- name = "Produce Blobbernaut (ERROR)"
- desc = "Produces a strong, smart blobbernaut from a factory blob for (ERROR) resources.
The factory blob used will become fragile and unable to produce spores."
-
-/atom/movable/screen/blob/blobbernaut/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- name = "Produce Blobbernaut ([BLOBMOB_BLOBBERNAUT_RESOURCE_COST])"
- desc = "Produces a strong, smart blobbernaut from a factory blob for [BLOBMOB_BLOBBERNAUT_RESOURCE_COST] resources.
The factory blob used will become fragile and unable to produce spores."
-
-/atom/movable/screen/blob/blobbernaut/Click()
- if(!isovermind(usr))
- return FALSE
- var/mob/eye/blob/blob = usr
- blob.create_blobbernaut()
-
-/atom/movable/screen/blob/resource_blob
- icon_state = "ui_resource"
- // Name and description get given their proper values on Initialize()
- name = "Produce Resource Blob (ERROR)"
- desc = "Produces a resource blob for ERROR resources.
Resource blobs will give you resources every few seconds."
-
-/atom/movable/screen/blob/resource_blob/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- name = "Produce Resource Blob ([BLOB_STRUCTURE_RESOURCE_COST])"
- desc = "Produces a resource blob for [BLOB_STRUCTURE_RESOURCE_COST] resources.
Resource blobs will give you resources every few seconds."
-
-/atom/movable/screen/blob/resource_blob/Click()
- if(!isovermind(usr))
- return FALSE
- var/mob/eye/blob/blob = usr
- blob.create_special(BLOB_STRUCTURE_RESOURCE_COST, /obj/structure/blob/special/resource, BLOB_RESOURCE_MIN_DISTANCE, TRUE)
-
-/atom/movable/screen/blob/node_blob
- icon_state = "ui_node"
- // Name and description get given their proper values on Initialize()
- name = "Produce Node Blob (ERROR)"
- desc = "Produces a node blob for ERROR resources.
Node blobs will expand and activate nearby resource and factory blobs."
-
-/atom/movable/screen/blob/node_blob/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- name = "Produce Node Blob ([BLOB_STRUCTURE_NODE_COST])"
- desc = "Produces a node blob for [BLOB_STRUCTURE_NODE_COST] resources.
Node blobs will expand and activate nearby resource and factory blobs."
-
-/atom/movable/screen/blob/node_blob/Click()
- if(!isovermind(usr))
- return FALSE
- var/mob/eye/blob/blob = usr
- blob.create_special(BLOB_STRUCTURE_NODE_COST, /obj/structure/blob/special/node, BLOB_NODE_MIN_DISTANCE, FALSE)
-
-/atom/movable/screen/blob/factory_blob
- icon_state = "ui_factory"
- // Name and description get given their proper values on Initialize()
- name = "Produce Factory Blob (ERROR)"
- desc = "Produces a factory blob for ERROR resources.
Factory blobs will produce spores every few seconds."
-
-/atom/movable/screen/blob/factory_blob/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- name = "Produce Factory Blob ([BLOB_STRUCTURE_FACTORY_COST])"
- desc = "Produces a factory blob for [BLOB_STRUCTURE_FACTORY_COST] resources.
Factory blobs will produce spores every few seconds."
-
-/atom/movable/screen/blob/factory_blob/Click()
- if(!isovermind(usr))
- return FALSE
- var/mob/eye/blob/blob = usr
- blob.create_special(BLOB_STRUCTURE_FACTORY_COST, /obj/structure/blob/special/factory, BLOB_FACTORY_MIN_DISTANCE, TRUE)
-
-/atom/movable/screen/blob/readapt_strain
- icon_state = "ui_chemswap"
- // Description gets given its proper values on Initialize()
- name = "Readapt Strain"
- desc = "Allows you to choose a new strain from ERROR random choices for ERROR resources."
-
-/atom/movable/screen/blob/readapt_strain/MouseEntered(location,control,params)
- if(hud?.mymob && isovermind(hud.mymob))
- var/mob/eye/blob/B = hud.mymob
- if(B.free_strain_rerolls)
- name = "[initial(name)] (FREE)"
- desc = "Randomly rerolls your strain for free."
- else
- name = "[initial(name)] ([BLOB_POWER_REROLL_COST])"
- desc = "Allows you to choose a new strain from [BLOB_POWER_REROLL_CHOICES] random choices for [BLOB_POWER_REROLL_COST] resources."
- return ..()
-
-/atom/movable/screen/blob/readapt_strain/Click()
- if(isovermind(usr))
- var/mob/eye/blob/B = usr
- B.strain_reroll()
-
-/atom/movable/screen/blob/relocate_core
- icon_state = "ui_swap"
- // Name and description get given their proper values on Initialize()
- name = "Relocate Core (ERROR)"
- desc = "Swaps a node and your core for ERROR resources."
-
-/atom/movable/screen/blob/relocate_core/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- name = "Relocate Core ([BLOB_POWER_RELOCATE_COST])"
- desc = "Swaps a node and your core for [BLOB_POWER_RELOCATE_COST] resources."
-
-/atom/movable/screen/blob/relocate_core/Click()
- if(isovermind(usr))
- var/mob/eye/blob/B = usr
- B.relocate_core()
-
-/atom/movable/screen/blob_power_display
- name = "blob power"
- icon_state = "block"
- screen_loc = ui_health
- mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- plane = ABOVE_HUD_PLANE
-
-/datum/hud/blob_overmind/New(mob/owner)
- ..()
- var/atom/movable/screen/using
-
- healths = new /atom/movable/screen/healths/blob(null, src)
- infodisplay += healths
-
- using = new /atom/movable/screen/blob/jump_to_node(null, src)
- using.screen_loc = ui_inventory
- static_inventory += using
-
- using = new /atom/movable/screen/blob/jump_to_core(null, src)
- using.screen_loc = ui_zonesel
- static_inventory += using
-
- using = new /atom/movable/screen/blob/blobbernaut(null, src)
- using.screen_loc = ui_belt
- static_inventory += using
-
- using = new /atom/movable/screen/blob/resource_blob(null, src)
- using.screen_loc = ui_back
- static_inventory += using
-
- using = new /atom/movable/screen/blob/node_blob(null, src)
- using.screen_loc = ui_hand_position(RIGHT_HANDS)
- static_inventory += using
-
- using = new /atom/movable/screen/blob/factory_blob(null, src)
- using.screen_loc = ui_hand_position(LEFT_HANDS)
- static_inventory += using
-
- using = new /atom/movable/screen/blob/readapt_strain(null, src)
- using.screen_loc = ui_storage1
- static_inventory += using
-
- using = new /atom/movable/screen/blob/relocate_core(null, src)
- using.screen_loc = ui_storage2
- static_inventory += using
+ add_screen_object(/atom/movable/screen/healths/blob, HUD_MOB_HEALTH, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/blob/blob_power, HUD_BLOB_POWER_DISPLAY, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/blob/jump_to_node, HUD_BLOB_JUMP_TO_NODE)
+ add_screen_object(/atom/movable/screen/blob/jump_to_core, HUD_BLOB_JUMP_TO_CORE)
+ add_screen_object(/atom/movable/screen/blob/blobbernaut, HUD_BLOB_BLOBBERNAUT)
+ add_screen_object(/atom/movable/screen/blob/resource_blob, HUD_BLOB_RESOURCES)
+ add_screen_object(/atom/movable/screen/blob/node_blob, HUD_BLOB_NODE, ui_loc = ui_hand_position(RIGHT_HANDS))
+ add_screen_object(/atom/movable/screen/blob/factory_blob, HUD_BLOB_FACTORY, ui_loc = ui_hand_position(LEFT_HANDS))
+ add_screen_object(/atom/movable/screen/blob/readapt_strain, HUD_BLOB_READAPT)
+ add_screen_object(/atom/movable/screen/blob/relocate_core, HUD_BLOB_RELOCATE)
diff --git a/code/_onclick/hud/drones.dm b/code/_onclick/hud/drones.dm
index ad3604a19e7..e7694d5d660 100644
--- a/code/_onclick/hud/drones.dm
+++ b/code/_onclick/hud/drones.dm
@@ -1,30 +1,5 @@
-/datum/hud/dextrous/drone/New(mob/owner)
- ..()
- var/atom/movable/screen/inventory/inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "internal storage"
- inv_box.icon = ui_style
- inv_box.icon_state = "suit_storage"
-// inv_box.icon_full = "template"
- inv_box.screen_loc = ui_drone_storage
- inv_box.slot_id = ITEM_SLOT_DEX_STORAGE
- static_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "head/mask"
- inv_box.icon = ui_style
- inv_box.icon_state = "mask"
-// inv_box.icon_full = "template"
- inv_box.screen_loc = ui_drone_head
- inv_box.slot_id = ITEM_SLOT_HEAD
- static_inventory += inv_box
-
- for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
- if(inv.slot_id)
- inv_slots[TOBITSHIFT(inv.slot_id) + 1] = inv
- inv.update_appearance()
-
+/datum/hud/dextrous/drone
+ inventory_slots = /datum/inventory_slot/drone
/datum/hud/dextrous/drone/persistent_inventory_update()
if(!mymob)
@@ -41,5 +16,19 @@
else
drone.internal_storage?.screen_loc = null
drone.head?.screen_loc = null
-
..()
+
+/datum/inventory_slot/drone
+ abstract_type = /datum/inventory_slot/drone
+
+/datum/inventory_slot/drone/storage
+ name = "internal storage"
+ icon_state = "suit_storage"
+ slot_id = ITEM_SLOT_DEX_STORAGE
+ screen_loc = ui_drone_storage
+
+/datum/inventory_slot/drone/head
+ name = "head/mask"
+ icon_state = "mask"
+ slot_id = ITEM_SLOT_HEAD
+ screen_loc = ui_drone_head
diff --git a/code/_onclick/hud/generic_dextrous.dm b/code/_onclick/hud/generic_dextrous.dm
index b7f7f7af739..0799edc98ba 100644
--- a/code/_onclick/hud/generic_dextrous.dm
+++ b/code/_onclick/hud/generic_dextrous.dm
@@ -1,70 +1,36 @@
//Used for normal mobs that have hands.
-/datum/hud/dextrous/New(mob/living/owner)
- ..()
+/datum/hud/dextrous/initialize_screen_objects()
+ . = ..()
var/atom/movable/screen/using
-
- pull_icon = new /atom/movable/screen/pull(null, src)
- pull_icon.icon = ui_style
- pull_icon.update_appearance()
- pull_icon.screen_loc = ui_drone_pull
- static_inventory += pull_icon
-
- build_hand_slots()
-
- using = new /atom/movable/screen/drop(null, src)
- using.icon = ui_style
- using.screen_loc = ui_swaphand_position(owner, 1)
- static_inventory += using
-
- using = new /atom/movable/screen/swap_hand(null, src)
- using.icon = ui_style
+ add_screen_object(/atom/movable/screen/drop, HUD_MOB_DROP, HUD_GROUP_STATIC, ui_style, ui_swaphand_position(mymob, 1))
+ using = add_screen_object(/atom/movable/screen/swap_hand, HUD_MOB_SWAPHAND_2, HUD_GROUP_STATIC, ui_style, ui_swaphand_position(mymob, 2))
using.icon_state = "act_swap"
- using.screen_loc = ui_swaphand_position(owner, 2)
- static_inventory += using
-
- action_intent = new /atom/movable/screen/combattoggle/flashy(null, src)
- action_intent.icon = ui_style
- action_intent.screen_loc = ui_movi
- static_inventory += action_intent
-
- floor_change = new /atom/movable/screen/floor_changer(null, src)
- floor_change.icon = 'icons/hud/screen_midnight.dmi'
- static_inventory += floor_change
-
- if(HAS_TRAIT(owner, TRAIT_CAN_THROW_ITEMS))
- throw_icon = new /atom/movable/screen/throw_catch(null, src)
- throw_icon.icon = ui_style
- throw_icon.screen_loc = ui_drop_throw
- static_inventory += throw_icon
-
- zone_select = new /atom/movable/screen/zone_sel(null, src)
- zone_select.icon = ui_style
- zone_select.update_appearance()
- static_inventory += zone_select
-
- using = new /atom/movable/screen/area_creator(null, src)
- using.icon = ui_style
- static_inventory += using
-
- healthdoll = new /atom/movable/screen/healthdoll/living(null, src)
- infodisplay += healthdoll
mymob.canon_client?.clear_screen()
- for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
- if(inv.slot_id)
- inv_slots[TOBITSHIFT(inv.slot_id) + 1] = inv
- inv.update_appearance()
+ build_hand_slots()
+
+ add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style, ui_below_throw)
+ add_screen_object(/atom/movable/screen/combattoggle/flashy, HUD_MOB_INTENTS, HUD_GROUP_STATIC, ui_style, ui_movi)
+ add_screen_object(/atom/movable/screen/floor_changer, HUD_MOB_FLOOR_CHANGER, HUD_GROUP_STATIC, ui_style, ui_above_movement)
+ add_screen_object(/atom/movable/screen/zone_sel, HUD_MOB_ZONE_SELECTOR, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/area_creator, HUD_MOB_AREA_CREATOR, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/memories, HUD_MOB_MEMORIES, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/healthdoll/living, HUD_MOB_HEALTHDOLL, HUD_GROUP_INFO)
+
+ if(HAS_TRAIT(mymob, TRAIT_CAN_THROW_ITEMS))
+ add_screen_object(/atom/movable/screen/throw_catch, HUD_MOB_THROW, HUD_GROUP_HOTKEYS, ui_style, ui_drop_throw)
/datum/hud/dextrous/persistent_inventory_update()
if(!mymob)
return
- var/mob/living/D = mymob
+ var/mob/living/owner = mymob
if(hud_version != HUD_STYLE_NOHUD)
- for(var/obj/item/I in D.held_items)
- I.screen_loc = ui_hand_position(D.get_held_index_of_item(I))
- D.client.screen += I
- else
- for(var/obj/item/I in D.held_items)
- I.screen_loc = null
- D.client.screen -= I
+ for(var/obj/item/held in owner.held_items)
+ held.screen_loc = ui_hand_position(owner.get_held_index_of_item(held))
+ owner.client.screen += held
+ return
+
+ for(var/obj/item/held in owner.held_items)
+ held.screen_loc = null
+ owner.client.screen -= held
diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm
index 14b332d0c3c..b8f5e611e37 100644
--- a/code/_onclick/hud/ghost.dm
+++ b/code/_onclick/hud/ghost.dm
@@ -1,198 +1,22 @@
-/atom/movable/screen/ghost
- icon = 'icons/hud/screen_ghost.dmi'
- mouse_over_pointer = MOUSE_HAND_POINTER
-
-/atom/movable/screen/ghost/MouseEntered(location, control, params)
- . = ..()
- flick(icon_state + "_anim", src)
-
-/atom/movable/screen/ghost/spawners_menu
- name = "Spawners menu"
- icon_state = "spawners"
-
-/atom/movable/screen/ghost/spawners_menu/Click()
- var/mob/dead/observer/observer = usr
- observer.open_spawners_menu()
-
-/atom/movable/screen/ghost/orbit
- name = "Orbit"
- icon_state = "orbit"
-
-/atom/movable/screen/ghost/orbit/Click()
- GLOB.orbit_menu.show(usr)
-
-/atom/movable/screen/ghost/reenter_corpse
- name = "Reenter corpse"
- icon_state = "reenter_corpse"
-
-/atom/movable/screen/ghost/reenter_corpse/Click()
- var/mob/dead/observer/G = usr
- G.reenter_corpse()
-
-/atom/movable/screen/ghost/dnr
- name = "Do Not Resuscitate"
- icon_state = "dnr"
-
-/atom/movable/screen/ghost/dnr/Click()
- var/mob/dead/observer/dnring = usr
- dnring.do_not_resuscitate()
-
-/atom/movable/screen/ghost/teleport
- name = "Teleport"
- icon_state = "teleport"
-
-/atom/movable/screen/ghost/teleport/Click()
- var/mob/dead/observer/G = usr
- G.dead_tele()
-
-/atom/movable/screen/ghost/settings
- name = "Ghost Settings"
- icon_state = "settings"
-
-/atom/movable/screen/ghost/settings/MouseEntered(location, control, params)
- . = ..()
- flick(icon_state + "_anim", src)
-
-/atom/movable/screen/ghost/settings/Click()
- GLOB.ghost_menu.ui_interact(usr)
-
-/atom/movable/screen/ghost/minigames_menu
- name ="Minigames"
- icon_state = "minigames"
-
-/atom/movable/screen/ghost/minigames_menu/Click()
- var/mob/dead/observer/observer = usr
- observer.open_minigames_menu()
-
-/atom/movable/screen/ghost/hudbox
- icon_state = "smallbox"
- abstract_type = /atom/movable/screen/ghost/hudbox
- /// Icon state used for the overlay representing this hudbox
- var/hud_icon_state
- /// The flag this hudbox toggles
- var/relevant_flag
-
-/atom/movable/screen/ghost/hudbox/update_overlays()
- . = ..()
- . += hud_icon_state
-
-/atom/movable/screen/ghost/hudbox/update_icon_state()
- . = ..()
- var/mob/dead/observer/observer = hud?.mymob
- if(!istype(observer))
- return
-
- icon_state = "smallbox[is_active(observer) ? "_active" : ""]"
-
-/atom/movable/screen/ghost/hudbox/proc/is_active(mob/dead/observer/observer)
- return (observer.ghost_hud_flags & relevant_flag)
-
-/atom/movable/screen/ghost/hudbox/Click(location, control, params)
- var/mob/dead/observer/observer = usr
- switch(relevant_flag)
- if(GHOST_DARKNESS_LEVEL)
- observer.toggle_darkness()
- if(GHOST_TRAY)
- observer.tray_view()
- else
- observer.toggle_ghost_hud_flag(relevant_flag)
-
- update_appearance(UPDATE_ICON_STATE)
-
-/atom/movable/screen/ghost/hudbox/health_scanner
- name = "Health Scanner"
- desc = "Toggles your ability to health scan mobs on click."
- hud_icon_state = "health_vision"
- relevant_flag = GHOST_HEALTH
-
-/atom/movable/screen/ghost/hudbox/chem_scanner
- name = "Chem Scanner"
- desc = "Toggles your ability to chemical scan mobs on click."
- hud_icon_state = "chem_vision"
- relevant_flag = GHOST_CHEM
-
-/atom/movable/screen/ghost/hudbox/gas_scanner
- name = "Gas Scanner"
- desc = "Toggles your ability to gas scan objects on click."
- hud_icon_state = "atmos_vision"
- relevant_flag = GHOST_GAS
-
-/atom/movable/screen/ghost/hudbox/ghost
- name = "Ghost Vision"
- desc = "Toggles whether you can see other ghosts."
- hud_icon_state = "ghost_vision"
- relevant_flag = GHOST_VISION
-
-/atom/movable/screen/ghost/hudbox/data_huds
- name = "Data HUDs"
- desc = "Toggles the display of data HUDs (health, security, diagnostics, etc)."
- hud_icon_state = "data_vision"
- relevant_flag = GHOST_DATA_HUDS
-
-/atom/movable/screen/ghost/hudbox/tray_icon
- name = "Tray View"
- desc = "Shows the t-ray view of the area around your ghost."
- hud_icon_state = "tray_vision"
- relevant_flag = GHOST_TRAY
-
-/atom/movable/screen/ghost/hudbox/darkness_level
- name = "Darkness Level"
- desc = "Cycles through different darkness levels for ghost vision."
- hud_icon_state = "darkness_vision"
- relevant_flag = GHOST_DARKNESS_LEVEL
/datum/hud/ghost
ui_style = 'icons/hud/screen_ghost.dmi'
-/datum/hud/ghost/New(mob/owner)
- ..()
- var/atom/movable/screen/using
-
- using = new /atom/movable/screen/ghost/spawners_menu(null, src)
- using.screen_loc = ui_ghost_spawners_menu
- static_inventory += using
-
- using = new /atom/movable/screen/ghost/orbit(null, src)
- using.screen_loc = ui_ghost_orbit
- static_inventory += using
-
- using = new /atom/movable/screen/ghost/reenter_corpse(null, src)
- using.screen_loc = ui_ghost_reenter_corpse
- static_inventory += using
-
- using = new /atom/movable/screen/ghost/dnr(null, src)
- using.screen_loc = ui_dnr
- static_inventory += using
-
- using = new /atom/movable/screen/ghost/teleport(null, src)
- using.screen_loc = ui_ghost_teleport
- static_inventory += using
-
- using = new /atom/movable/screen/ghost/settings(null, src)
- using.screen_loc = ui_ghost_settings
- static_inventory += using
-
- using = new /atom/movable/screen/ghost/minigames_menu(null, src)
- using.screen_loc = ui_ghost_minigames
- static_inventory += using
-
- using = new /atom/movable/screen/language_menu(null, src)
- using.icon = ui_style
- using.screen_loc = ui_ghost_language_menu
- static_inventory += using
-
- floor_change = new /atom/movable/screen/floor_changer/vertical(null, src)
- floor_change.icon = ui_style
- floor_change.screen_loc = ui_ghost_floor_changer
- static_inventory += floor_change
+/datum/hud/ghost/initialize_screen_objects()
+ . = ..()
+ add_screen_object(/atom/movable/screen/ghost/spawners_menu, HUD_GHOST_SPAWNERS)
+ add_screen_object(/atom/movable/screen/ghost/orbit, HUD_GHOST_ORBIT)
+ add_screen_object(/atom/movable/screen/ghost/reenter_corpse, HUD_GHOST_REENTER_CORPSE)
+ add_screen_object(/atom/movable/screen/ghost/dnr, HUD_GHOST_DNR)
+ add_screen_object(/atom/movable/screen/ghost/teleport, HUD_GHOST_TELEPORT)
+ add_screen_object(/atom/movable/screen/ghost/settings, HUD_GHOST_SETTINGS)
+ add_screen_object(/atom/movable/screen/ghost/minigames_menu, HUD_GHOST_MINIGAMES)
+ add_screen_object(/atom/movable/screen/language_menu, HUD_MOB_LANGUAGE_MENU, HUD_GROUP_STATIC, ui_style, ui_ghost_language_menu)
+ add_screen_object(/atom/movable/screen/floor_changer/vertical, HUD_MOB_FLOOR_CHANGER, HUD_GROUP_STATIC, ui_style, ui_ghost_floor_changer)
var/list/hudboxes = valid_subtypesof(/atom/movable/screen/ghost/hudbox)
for(var/i in 1 to length(hudboxes))
- var/hudbox_type = hudboxes[i]
- var/atom/movable/screen/ghost/hudbox/hudbox = new hudbox_type(null, src)
- hudbox.screen_loc = position_hudbox(i - 1)
- static_inventory += hudbox
- hudbox.update_appearance()
+ add_screen_object(hudboxes[i], HUD_KEY_GHOST_HUDBOX(i), ui_loc = position_hudbox(i - 1))
/datum/hud/ghost/proc/position_hudbox(i)
var/row = floor(i / 3)
@@ -211,15 +35,15 @@
return
var/mob/screenmob = viewmob || mymob
if(screenmob.client.prefs.read_preference(/datum/preference/toggle/ghost_hud))
- screenmob.client.screen |= static_inventory
- for(var/atom/movable/screen/ghost/hudbox/hud in static_inventory)
+ screenmob.client.screen |= screen_groups[HUD_GROUP_STATIC]
+ for(var/atom/movable/screen/ghost/hudbox/hud in screen_groups[HUD_GROUP_STATIC])
hud.update_appearance()
else
- screenmob.client.screen -= static_inventory
+ screenmob.client.screen -= screen_groups[HUD_GROUP_STATIC]
//We should only see observed mob alerts.
/datum/hud/ghost/reorganize_alerts(mob/viewmob)
var/mob/dead/observer/O = mymob
if (istype(O) && O.observetarget)
return
- . = ..()
+ return ..()
diff --git a/code/_onclick/hud/guardian.dm b/code/_onclick/hud/guardian.dm
index 68a480d47f8..cabe261b14e 100644
--- a/code/_onclick/hud/guardian.dm
+++ b/code/_onclick/hud/guardian.dm
@@ -1,169 +1,54 @@
/datum/hud/guardian
ui_style = 'icons/hud/guardian.dmi'
+ inventory_slots = list(/datum/inventory_slot/guardian_storage)
-/datum/hud/guardian/New(mob/living/basic/guardian/owner)
- ..()
- var/atom/movable/screen/using
+/datum/hud/guardian/initialize_screen_objects()
+ . = ..()
+ add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/guardian/manifest, HUD_GUARDIAN_MANIFEST, ui_loc = ui_hand_position(RIGHT_HANDS))
+ add_screen_object(/atom/movable/screen/guardian/recall, HUD_GUARDIAN_RECALL, ui_loc = ui_hand_position(LEFT_HANDS))
+ add_screen_object(/atom/movable/screen/guardian/toggle_light, HUD_GUARDIAN_LIGHT)
+ add_screen_object(/atom/movable/screen/guardian/communicate, HUD_GUARDIAN_COMMUNICATE)
- pull_icon = new /atom/movable/screen/pull(null, src)
- pull_icon.icon = ui_style
- pull_icon.update_appearance()
- pull_icon.screen_loc = ui_living_pull
- static_inventory += pull_icon
+ add_screen_object(/atom/movable/screen/healths/guardian, HUD_MOB_HEALTH, HUD_GROUP_INFO)
- healths = new /atom/movable/screen/healths/guardian(null, src)
- infodisplay += healths
+ var/mob/living/basic/guardian/owner = mymob
+ if (istype(owner))
+ add_screen_object(owner.toggle_button_type, HUD_GUARDIAN_TOGGLE, ui_loc = ui_storage1)
- using = new /atom/movable/screen/guardian/manifest(null, src)
- using.screen_loc = ui_hand_position(RIGHT_HANDS)
- static_inventory += using
+/datum/hud/dextrous/guardian/initialize_screen_objects()
+ . = ..()
+ add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/guardian/communicate, HUD_GUARDIAN_COMMUNICATE, ui_loc = ui_sstore1)
+ add_screen_object(/atom/movable/screen/guardian/manifest, HUD_GUARDIAN_MANIFEST, ui_loc = ui_belt)
+ add_screen_object(/atom/movable/screen/guardian/recall, HUD_GUARDIAN_RECALL, ui_loc = ui_back)
+ add_screen_object(/atom/movable/screen/guardian/toggle_light, HUD_GUARDIAN_LIGHT)
- using = new /atom/movable/screen/guardian/recall(null, src)
- using.screen_loc = ui_hand_position(LEFT_HANDS)
- static_inventory += using
+ add_screen_object(/atom/movable/screen/healths/guardian, HUD_MOB_HEALTH, HUD_GROUP_INFO)
- using = new owner.toggle_button_type(null, src)
- using.screen_loc = ui_storage1
- static_inventory += using
-
- using = new /atom/movable/screen/guardian/toggle_light(null, src)
- using.screen_loc = ui_inventory
- static_inventory += using
-
- using = new /atom/movable/screen/guardian/communicate(null, src)
- using.screen_loc = ui_back
- static_inventory += using
-
-/datum/hud/dextrous/guardian/New(mob/living/basic/guardian/owner) //for a dextrous guardian
- ..()
- var/atom/movable/screen/using
- if(istype(owner, /mob/living/basic/guardian/dextrous))
- var/atom/movable/screen/inventory/inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "internal storage"
- inv_box.icon = ui_style
- inv_box.icon_state = "suit_storage"
- inv_box.screen_loc = ui_id
- inv_box.slot_id = ITEM_SLOT_DEX_STORAGE
- static_inventory += inv_box
-
- using = new /atom/movable/screen/guardian/communicate(null, src)
- using.screen_loc = ui_sstore1
- static_inventory += using
-
- else
-
- using = new /atom/movable/screen/guardian/communicate(null, src)
- using.screen_loc = ui_id
- static_inventory += using
-
- pull_icon = new /atom/movable/screen/pull(null, src)
- pull_icon.icon = ui_style
- pull_icon.update_appearance()
- pull_icon.screen_loc = ui_living_pull
- static_inventory += pull_icon
-
- healths = new /atom/movable/screen/healths/guardian(null, src)
- infodisplay += healths
-
- using = new /atom/movable/screen/guardian/manifest(null, src)
- using.screen_loc = ui_belt
- static_inventory += using
-
- using = new /atom/movable/screen/guardian/recall(null, src)
- using.screen_loc = ui_back
- static_inventory += using
-
- using = new owner.toggle_button_type(null, src)
- using.screen_loc = ui_storage2
- static_inventory += using
-
- using = new /atom/movable/screen/guardian/toggle_light(null, src)
- using.screen_loc = ui_inventory
- static_inventory += using
+ var/mob/living/basic/guardian/owner = mymob
+ if (istype(owner))
+ add_screen_object(owner.toggle_button_type, HUD_GUARDIAN_TOGGLE, ui_loc = ui_storage2)
/datum/hud/dextrous/guardian/persistent_inventory_update()
if(!mymob)
return
- if(istype(mymob, /mob/living/basic/guardian/dextrous))
- var/mob/living/basic/guardian/dextrous/dex_guardian = mymob
- if(hud_shown)
- if(dex_guardian.internal_storage)
- dex_guardian.internal_storage.screen_loc = ui_id
- dex_guardian.client.screen += dex_guardian.internal_storage
- else
- if(dex_guardian.internal_storage)
- dex_guardian.internal_storage.screen_loc = null
+ if(!istype(mymob, /mob/living/basic/guardian/dextrous))
+ return ..()
- ..()
+ var/mob/living/basic/guardian/dextrous/dex_guardian = mymob
+ if(hud_shown)
+ if(dex_guardian.internal_storage)
+ dex_guardian.internal_storage.screen_loc = ui_id
+ dex_guardian.client.screen += dex_guardian.internal_storage
+ else
+ if(dex_guardian.internal_storage)
+ dex_guardian.internal_storage.screen_loc = null
+ return ..()
-/atom/movable/screen/guardian
- icon = 'icons/hud/guardian.dmi'
- mouse_over_pointer = MOUSE_HAND_POINTER
-
-/atom/movable/screen/guardian/manifest
- icon_state = "manifest"
- name = "Manifest"
- desc = "Spring forth into battle!"
-
-/atom/movable/screen/guardian/manifest/Click()
- if(isguardian(usr))
- var/mob/living/basic/guardian/user = usr
- user.manifest()
-
-
-/atom/movable/screen/guardian/recall
- icon_state = "recall"
- name = "Recall"
- desc = "Return to your user."
-
-/atom/movable/screen/guardian/recall/Click()
- if(isguardian(usr))
- var/mob/living/basic/guardian/user = usr
- user.recall()
-
-/atom/movable/screen/guardian/toggle_mode
- icon_state = "toggle"
- name = "Toggle Mode"
- desc = "Switch between ability modes."
-
-/atom/movable/screen/guardian/toggle_mode/Click()
- if(isguardian(usr))
- var/mob/living/basic/guardian/user = usr
- user.toggle_modes()
-
-/atom/movable/screen/guardian/toggle_mode/inactive
- icon_state = "notoggle" //greyed out so it doesn't look like it'll work
-
-/atom/movable/screen/guardian/toggle_mode/assassin
- icon_state = "stealth"
- name = "Toggle Stealth"
- desc = "Enter or exit stealth."
-
-/atom/movable/screen/guardian/toggle_mode/gases
- icon_state = "gases"
- name = "Toggle Gas"
- desc = "Switch between possible gases."
-
-/atom/movable/screen/guardian/communicate
- icon_state = "communicate"
- name = "Communicate"
- desc = "Communicate telepathically with your user."
-
-/atom/movable/screen/guardian/communicate/Click()
- if(isguardian(usr))
- var/mob/living/basic/guardian/user = usr
- user.communicate()
-
-
-/atom/movable/screen/guardian/toggle_light
- icon_state = "light"
- name = "Toggle Light"
- desc = "Glow like star dust."
-
-/atom/movable/screen/guardian/toggle_light/Click()
- if(isguardian(usr))
- var/mob/living/basic/guardian/user = usr
- user.toggle_light()
+/datum/inventory_slot/guardian_storage
+ name = "internal storage"
+ icon_state = "suit_storage"
+ slot_id = ITEM_SLOT_DEX_STORAGE
+ screen_loc = ui_id
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 0f722a1bc11..88eb2d5a6f1 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -22,34 +22,15 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
/datum/hud
var/mob/mymob
+ /// Used for the HUD toggle (F12)
+ var/hud_shown = TRUE
+ /// Current displayed version of the HUD
+ var/hud_version = HUD_STYLE_STANDARD
+ /// Equipped item inventory
+ var/inventory_shown = FALSE
+ /// This is to hide the buttons that can be used via hotkeys. (hotkeybuttons list of buttons)
+ var/hotkey_ui_hidden = FALSE
- var/hud_shown = TRUE //Used for the HUD toggle (F12)
- var/hud_version = HUD_STYLE_STANDARD //Current displayed version of the HUD
- var/inventory_shown = FALSE //Equipped item inventory
- var/hotkey_ui_hidden = FALSE //This is to hide the buttons that can be used via hotkeys. (hotkeybuttons list of buttons)
-
- var/atom/movable/screen/alien_plasma_display
- var/atom/movable/screen/alien_queen_finder
-
- var/atom/movable/screen/action_intent
- var/atom/movable/screen/zone_select
- var/atom/movable/screen/pull_icon
- var/atom/movable/screen/rest_icon
- var/atom/movable/screen/sleep_icon
- var/atom/movable/screen/throw_icon
- var/atom/movable/screen/resist_icon
- var/atom/movable/screen/floor_change
-
- var/list/static_inventory = list() //the screen objects which are static
- var/list/toggleable_inventory = list() //the screen objects which can be hidden
- var/list/atom/movable/screen/hotkeybuttons = list() //the buttons that can be used via hotkeys
- var/list/infodisplay = list() //the screen objects that display mob info (health, alien plasma, etc...)
- /// Screen objects that never exit view.
- var/list/always_visible_inventory = list()
- var/list/inv_slots[SLOTS_AMT] // /atom/movable/screen/inventory objects, ordered by their slot ID.
- var/list/hand_slots // /atom/movable/screen/inventory/hand objects, assoc list of "[held_index]" = object
- /// storages (and its content) currently open by mob
- var/list/open_containers = list()
/// Assoc list of key => "plane master groups"
/// This is normally just the main window, but it'll occasionally contain things like spyglasses windows
var/list/datum/plane_master_group/master_groups = list()
@@ -62,8 +43,9 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
/// Goes from 0 to the max (z level stack size - 1)
var/current_plane_offset = 0
- ///UI for screentips that appear when you mouse over things
- var/atom/movable/screen/screentip/screentip_text
+ /// UI for screentips that appear when you mouse over things
+ /// Stored directly as it is used in very hot MouseEntered code
+ var/atom/movable/screen/screentip/screentip_text = null
/// Whether or not screentips are enabled.
/// This is updated by the preference for cheaper reads than would be
@@ -78,26 +60,27 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
/// The color to use for the screentips.
/// This is updated by the preference for cheaper reads than would be
- /// had with a proc call, especially on one of the hottest procs in the
- /// game (MouseEntered).
- var/screentip_color
-
- var/atom/movable/screen/button_palette/toggle_palette
- var/atom/movable/screen/palette_scroll/down/palette_down
- var/atom/movable/screen/palette_scroll/up/palette_up
-
- var/datum/action_group/palette/palette_actions
- var/datum/action_group/listed/listed_actions
- var/list/floating_actions
-
- var/atom/movable/screen/healths
- var/atom/movable/screen/stamina
- var/atom/movable/screen/healthdoll/healthdoll
- var/atom/movable/screen/spacesuit/spacesuit_hud
- var/atom/movable/screen/hunger/hunger
+ /// had with a proc call, especially on one of the hottest procs in the game (MouseEntered).
+ var/screentip_color = null
+ var/datum/action_group/palette/palette_actions = null
+ var/datum/action_group/listed/listed_actions = null
+ var/list/floating_actions = null
/// Subtypes can override this to force a specific UI style
- var/ui_style
+ var/ui_style = null
+ /// Assoc list of all screen objects we hold by their key
+ var/list/atom/movable/screen/screen_objects = list()
+ /// List of screen objects by their screen group
+ var/list/screen_groups[SCREEN_GROUP_AMT]
+ /// List of all inventory slot screen objects by their slot ID. Some slots are fake and will be missing from here!
+ var/list/inv_slots[SLOTS_AMT]
+ /// List of hand slot objects, kept separate from the rest of inventory as mobs can have varying amount of hands
+ var/list/atom/movable/screen/inventory/hand/hand_slots = null
+
+ /// List of typepaths of /datum/inventory_slot which will be used to automatically create inventory slot UI elements
+ /// If assigned a typepath instead of a list, it will instead use all valid subtypes of said typepath
+ /// Safe to change in initialize_screen_objects() but not later
+ var/list/inventory_slots = null
/// List of weakrefs to objects that we add to our screen that we don't expect to DO anything
/// They typically use * in their render target. They exist solely so we can reuse them,
@@ -111,12 +94,9 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
// will fall back to the default if any of these are null
ui_style = ui_style2icon(owner.client?.prefs?.read_preference(/datum/preference/choiced/ui_style))
- toggle_palette = new()
- toggle_palette.set_hud(src)
- palette_down = new()
- palette_down.set_hud(src)
- palette_up = new()
- palette_up.set_hud(src)
+ add_screen_object(/atom/movable/screen/button_palette, HUD_MOB_TOGGLE_PALETTE)
+ add_screen_object(/atom/movable/screen/palette_scroll/down, HUD_MOB_PALETTE_DOWN)
+ add_screen_object(/atom/movable/screen/palette_scroll/up, HUD_MOB_PALETTE_UP)
hand_slots = list()
@@ -127,8 +107,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
screentip_color = preferences?.read_preference(/datum/preference/color/screentip_color)
screentips_enabled = preferences?.read_preference(/datum/preference/choiced/enable_screentips)
screentip_images = preferences?.read_preference(/datum/preference/toggle/screentip_images)
- screentip_text = new(null, src)
- static_inventory += screentip_text
+ screentip_text = add_screen_object(/atom/movable/screen/screentip, HUD_MOB_SCREENTIP)
for(var/mytype in subtypesof(/atom/movable/plane_master_controller))
var/atom/movable/plane_master_controller/controller_instance = new mytype(null,src)
@@ -146,8 +125,73 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
RegisterSignal(mymob, COMSIG_MOB_LOGOUT, PROC_REF(clear_client))
RegisterSignal(mymob, COMSIG_MOB_SIGHT_CHANGE, PROC_REF(update_sightflags))
RegisterSignal(mymob, COMSIG_VIEWDATA_UPDATE, PROC_REF(on_viewdata_update))
+
+ initialize_screen_objects()
+ create_inventory_slots()
+ update_locked_slots()
+
update_sightflags(mymob, mymob.sight, NONE)
+/datum/hud/Destroy()
+ if(mymob.hud_used == src)
+ mymob.hud_used = null
+
+ QDEL_NULL(palette_actions)
+ QDEL_NULL(listed_actions)
+ QDEL_LIST(floating_actions)
+ screentip_text = null
+ screen_groups = null
+ inv_slots.Cut()
+ hand_slots.Cut()
+ QDEL_LIST_ASSOC_VAL(screen_objects)
+ QDEL_LIST_ASSOC_VAL(master_groups)
+ QDEL_LIST_ASSOC_VAL(plane_master_controllers)
+ mymob = null
+
+ return ..()
+
+/// Creates and registers a managed screen object
+/datum/hud/proc/add_screen_object(atom/movable/screen/new_object, hud_key, group_key = HUD_GROUP_STATIC, ui_icon, ui_loc, update_screen = FALSE)
+ if (ispath(new_object))
+ new_object = new new_object(null, src)
+
+ if (isnull(hud_key))
+ hud_key = REF(new_object)
+
+ if (!isnull(ui_icon))
+ new_object.icon = ui_icon
+
+ if (!isnull(ui_loc))
+ new_object.screen_loc = ui_loc
+
+ new_object.hud_key = hud_key
+ if (screen_objects[hud_key])
+ CRASH("Attempted to add a new [new_object] screen object to the [src] hud while an object with the same key [hud_key] is already present!")
+
+ screen_objects[hud_key] = new_object
+
+ if (group_key)
+ LAZYADD(screen_groups[group_key], new_object)
+ new_object.hud_group_key = group_key
+
+ if (update_screen)
+ show_hud(hud_version)
+ return new_object
+
+/// Removes a screen object and refreshes the hud. Can just be passed a key.
+/datum/hud/proc/remove_screen_object(atom/movable/screen/to_remove, update = TRUE)
+ if (!istype(to_remove))
+ to_remove = screen_objects[to_remove]
+ if (!to_remove)
+ return
+ qdel(to_remove)
+ if (update && !QDELETED(src))
+ show_hud(hud_version)
+
+/// Proc for children to spawn their screen object in
+/datum/hud/proc/initialize_screen_objects()
+ return
+
/datum/hud/proc/client_refresh(datum/source)
SIGNAL_HANDLER
var/client/client = mymob.canon_client
@@ -212,53 +256,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
var/datum/plane_master_group/group = master_groups[group_key]
group.build_planes_offset(src, new_offset)
-/datum/hud/Destroy()
- if(mymob.hud_used == src)
- mymob.hud_used = null
-
- QDEL_NULL(toggle_palette)
- QDEL_NULL(palette_down)
- QDEL_NULL(palette_up)
- QDEL_NULL(palette_actions)
- QDEL_NULL(listed_actions)
- QDEL_LIST(floating_actions)
-
- QDEL_LIST(static_inventory)
-
- // all already deleted by static inventory clear
- inv_slots.Cut()
- action_intent = null
- zone_select = null
- pull_icon = null
- rest_icon = null
- sleep_icon = null
- floor_change = null
- hand_slots.Cut()
-
- QDEL_LIST(toggleable_inventory)
- QDEL_LIST(hotkeybuttons)
- throw_icon = null
- resist_icon = null
- QDEL_LIST(infodisplay)
- open_containers = null
-
- healths = null
- stamina = null
- healthdoll = null
- spacesuit_hud = null
- hunger = null
- alien_plasma_display = null
- alien_queen_finder = null
-
- QDEL_LIST_ASSOC_VAL(master_groups)
- QDEL_LIST_ASSOC_VAL(plane_master_controllers)
- QDEL_LIST(always_visible_inventory)
- mymob = null
-
- QDEL_NULL(screentip_text)
-
- return ..()
-
/datum/hud/proc/on_plane_increase(datum/source, old_max_offset, new_max_offset)
SIGNAL_HANDLER
for(var/i in old_max_offset + 1 to new_max_offset)
@@ -314,75 +311,73 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
* * viewmob - what mob to show the hud to. Can be this hud's mob, can be another mob, can be null (will use this hud's mob if so)
*/
/datum/hud/proc/show_hud(version = 0, mob/viewmob)
- if(!ismob(mymob))
+ if (!ismob(mymob))
return FALSE
+
var/mob/screenmob = viewmob || mymob
- if(!screenmob.client)
+ if (!screenmob.client)
return FALSE
// This code is the absolute fucking worst, I want it to go die in a fire
// Seriously, why
+ // I'm sorry
screenmob.client.clear_screen()
screenmob.client.apply_clickcatcher()
var/display_hud_version = version
- if(!display_hud_version) //If 0 or blank, display the next hud version
+ if (!display_hud_version) // If 0 or blank, display the next hud version
display_hud_version = hud_version + 1
- if(display_hud_version > HUD_VERSIONS) //If the requested version number is greater than the available versions, reset back to the first version
- display_hud_version = 1
- switch(display_hud_version)
- if(HUD_STYLE_STANDARD) //Default HUD
- hud_shown = TRUE //Governs behavior of other procs
- if(static_inventory.len)
- screenmob.client.screen += static_inventory
- if(toggleable_inventory.len && screenmob.hud_used && screenmob.hud_used.inventory_shown)
- screenmob.client.screen += toggleable_inventory
- if(hotkeybuttons.len && !hotkey_ui_hidden)
- screenmob.client.screen += hotkeybuttons
- if(infodisplay.len)
- screenmob.client.screen += infodisplay
- if(always_visible_inventory.len)
- screenmob.client.screen += always_visible_inventory
- if(open_containers.len && screenmob == mymob) // Don't show open inventories to ghosts
- list_clear_nulls(open_containers)
- screenmob.client.screen += open_containers
- screenmob.client.screen += toggle_palette
+ // If the requested version number is greater than the available versions, reset back to the first version
+ if (display_hud_version > HUD_VERSIONS)
+ display_hud_version = HUD_STYLE_STANDARD
- if(HUD_STYLE_REDUCED) //Reduced HUD
- hud_shown = FALSE //Governs behavior of other procs
- if(static_inventory.len)
- screenmob.client.screen -= static_inventory
- if(toggleable_inventory.len)
- screenmob.client.screen -= toggleable_inventory
- if(hotkeybuttons.len)
- screenmob.client.screen -= hotkeybuttons
- if(infodisplay.len)
- screenmob.client.screen += infodisplay
- if(always_visible_inventory.len)
- screenmob.client.screen += always_visible_inventory
+ var/list/group_static = screen_groups[HUD_GROUP_STATIC]
+ var/list/group_toggleable = screen_groups[HUD_GROUP_TOGGLEABLE_INVENTORY]
+ var/list/group_hotkeys = screen_groups[HUD_GROUP_HOTKEYS]
+ var/list/group_info = screen_groups[HUD_GROUP_INFO]
+ var/list/group_screen = screen_groups[HUD_GROUP_SCREEN_OVERLAYS]
+ var/list/group_storage = screen_groups[HUD_GROUP_STORAGE]
+
+ // Screen overlays get added regardless of the HUD state
+ if (length(group_screen))
+ screenmob.client.screen += group_screen
+
+ var/atom/movable/screen/button_palette/palette = screen_objects[HUD_MOB_TOGGLE_PALETTE]
+ var/atom/movable/screen/action_intent = screen_objects[HUD_MOB_INTENTS]
+
+ switch (display_hud_version)
+ if (HUD_STYLE_STANDARD)
+ hud_shown = TRUE
+
+ if (length(group_static))
+ screenmob.client.screen += group_static
+ if (length(group_toggleable) && screenmob.hud_used && screenmob.hud_used.inventory_shown)
+ screenmob.client.screen += group_toggleable
+ if (length(group_hotkeys) && !hotkey_ui_hidden)
+ screenmob.client.screen += group_hotkeys
+ if (length(group_info))
+ screenmob.client.screen += group_info
+ if (length(group_storage))
+ screenmob.client.screen += group_storage
+
+ screenmob.client.screen += palette
+
+ if (HUD_STYLE_REDUCED)
+ hud_shown = FALSE
+
+ if (length(group_info))
+ screenmob.client.screen += group_info
+
+ // Hands are apart of the static group but still should be presetn in the reduced mode
+ for (var/atom/movable/screen/hand in hand_slots)
+ screenmob.client.screen += hand
- //These ones are a part of 'static_inventory', 'toggleable_inventory' or 'hotkeybuttons' but we want them to stay
- for(var/h in hand_slots)
- var/atom/movable/screen/hand = hand_slots[h]
- if(hand)
- screenmob.client.screen += hand
if(action_intent)
- screenmob.client.screen += action_intent //we want the intent switcher visible
- action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is.
+ screenmob.client.screen += action_intent
- if(HUD_STYLE_NOHUD) //No HUD
- hud_shown = FALSE //Governs behavior of other procs
- if(static_inventory.len)
- screenmob.client.screen -= static_inventory
- if(toggleable_inventory.len)
- screenmob.client.screen -= toggleable_inventory
- if(hotkeybuttons.len)
- screenmob.client.screen -= hotkeybuttons
- if(infodisplay.len)
- screenmob.client.screen -= infodisplay
- if(always_visible_inventory.len)
- screenmob.client.screen += always_visible_inventory
+ if (HUD_STYLE_NOHUD)
+ hud_shown = FALSE
hud_version = display_hud_version
persistent_inventory_update(screenmob)
@@ -442,12 +437,13 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
if (initial(ui_style) || ui_style == new_ui_style)
return
- for(var/atom/item in static_inventory + toggleable_inventory + hotkeybuttons + infodisplay + always_visible_inventory + inv_slots)
- if (item.icon == ui_style)
+ for(var/hud_key in screen_objects)
+ var/atom/item = screen_objects[hud_key]
+ if (item?.icon == ui_style)
item.icon = new_ui_style
ui_style = new_ui_style
- build_hand_slots()
+ build_hand_slots(update_hud = TRUE)
/datum/hud/proc/register_reuse(atom/movable/screen/reuse)
asset_refs_for_reuse += WEAKREF(reuse)
@@ -476,62 +472,80 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
else
to_chat(usr, span_warning("This mob type does not use a HUD."))
+/// Rebuilds our mob's hand slot screen elements
+/datum/hud/proc/build_hand_slots(update_hud = FALSE)
+ QDEL_LIST(hand_slots)
+ hand_slots = new /list(length(mymob.held_items))
-//(re)builds the hand ui slots, throwing away old ones
-//not really worth jugglying existing ones so we just scrap+rebuild
-//9/10 this is only called once per mob and only for 2 hands
-/datum/hud/proc/build_hand_slots()
- for(var/h in hand_slots)
- var/atom/movable/screen/inventory/hand/H = hand_slots[h]
- if(H)
- static_inventory -= H
- hand_slots = list()
- var/atom/movable/screen/inventory/hand/hand_box
- for(var/i in 1 to mymob.held_items.len)
- hand_box = new /atom/movable/screen/inventory/hand(null, src)
+ for(var/i in 1 to length(mymob.held_items))
+ var/atom/movable/screen/inventory/hand/hand_box = add_screen_object(/atom/movable/screen/inventory/hand, HUD_KEY_HAND_SLOT(i), HUD_GROUP_STATIC, ui_style, ui_hand_position(i))
hand_box.name = mymob.get_held_index_name(i)
- hand_box.icon = ui_style
hand_box.icon_state = "hand_[mymob.held_index_to_dir(i)]"
- hand_box.screen_loc = ui_hand_position(i)
hand_box.held_index = i
- hand_slots["[i]"] = hand_box
- static_inventory += hand_box
hand_box.update_appearance()
+ hand_slots[i] = hand_box
var/num_of_swaps = 0
- for(var/atom/movable/screen/swap_hand/swap_hands in static_inventory)
+ for(var/atom/movable/screen/swap_hand/swap_hands in screen_groups[HUD_GROUP_STATIC])
num_of_swaps += 1
var/hand_num = 1
- for(var/atom/movable/screen/swap_hand/swap_hands in static_inventory)
+ for(var/atom/movable/screen/swap_hand/swap_hands in screen_groups[HUD_GROUP_STATIC])
var/hand_ind = RIGHT_HANDS
if (num_of_swaps > 1)
hand_ind = IS_RIGHT_INDEX(hand_num) ? LEFT_HANDS : RIGHT_HANDS
swap_hands.screen_loc = ui_swaphand_position(mymob, hand_ind)
hand_num += 1
+
hand_num = 1
- for(var/atom/movable/screen/drop/swap_hands in static_inventory)
+
+ for(var/atom/movable/screen/drop/swap_hands in screen_groups[HUD_GROUP_STATIC])
var/hand_ind = LEFT_HANDS
if (num_of_swaps > 1)
hand_ind = IS_LEFT_INDEX(hand_num) ? LEFT_HANDS : RIGHT_HANDS
swap_hands.screen_loc = ui_swaphand_position(mymob, hand_ind)
hand_num += 1
- if(ismob(mymob) && mymob.hud_used == src)
+ if(update_hud && mymob?.hud_used == src)
show_hud(hud_version)
/// Handles dimming inventory slots that a mob can't equip items to in their current state
/datum/hud/proc/update_locked_slots()
return
+/// Creates inventory slot screen elements based on our assigned inventory_slots
+/datum/hud/proc/create_inventory_slots()
+ var/list/created_paths = inventory_slots
+ if (ispath(inventory_slots))
+ created_paths = valid_subtypesof(inventory_slots)
+
+ for (var/datum/inventory_slot/slot_type as anything in created_paths)
+ var/datum/inventory_slot/inv_slot = GLOB.inventory_slot_datums[slot_type]
+ if (!inv_slot)
+ stack_trace("[src] attempted to use an invalid inventory slot: [slot_type]")
+ continue
+ inv_slot.create_element(src)
+
+ update_inventory_slots()
+
+/// Updates all of our inventory slots
+/// Avoid calling directly in favor of specific update procs
+/datum/hud/proc/update_inventory_slots()
+ for(var/atom/movable/screen/inventory/inv in screen_groups[HUD_GROUP_STATIC] + screen_groups[HUD_GROUP_TOGGLEABLE_INVENTORY])
+ if(inv.slot_id)
+ inv_slots[TOBITSHIFT(inv.slot_id) + 1] = inv
+ inv.update_appearance()
+
/datum/hud/proc/position_action(atom/movable/screen/movable/action_button/button, position)
// This is kinda a hack, I'm sorry.
// Basically, FLOATING is never a valid position to pass into this proc. It exists as a generic marker for manually positioned buttons
// Not as a position to target
if(position == SCRN_OBJ_FLOATING)
return
+
if(button.location != SCRN_OBJ_DEFAULT)
hide_action(button)
+
switch(position)
if(SCRN_OBJ_DEFAULT) // Reset to the default
button.dump_save() // Nuke any existing saves
@@ -548,6 +562,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
floating_actions += button
button.screen_loc = position
position = SCRN_OBJ_FLOATING
+ var/atom/movable/screen/button_palette/toggle_palette = screen_objects[HUD_MOB_TOGGLE_PALETTE]
toggle_palette.update_state()
button.location = position
@@ -555,18 +570,24 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
/datum/hud/proc/position_action_relative(atom/movable/screen/movable/action_button/button, atom/movable/screen/movable/action_button/relative_to)
if(button.location != SCRN_OBJ_DEFAULT)
hide_action(button)
+
switch(relative_to.location)
if(SCRN_OBJ_IN_LIST)
listed_actions.insert_action(button, listed_actions.index_of(relative_to))
+
if(SCRN_OBJ_IN_PALETTE)
palette_actions.insert_action(button, palette_actions.index_of(relative_to))
+
if(SCRN_OBJ_FLOATING) // If we don't have it as a define, this is a screen_loc, and we should be floating
floating_actions += button
var/client/our_client = mymob.canon_client
if(!our_client)
position_action(button, button.linked_action.default_button_position)
return
- button.screen_loc = get_valid_screen_location(relative_to.screen_loc, ICON_SIZE_ALL, our_client.view_size.getView()) // Asks for a location adjacent to our button that won't overflow the map
+
+ // Asks for a location adjacent to our button that won't overflow the map
+ button.screen_loc = get_valid_screen_location(relative_to.screen_loc, ICON_SIZE_ALL, our_client.view_size.getView())
+ var/atom/movable/screen/button_palette/toggle_palette = screen_objects[HUD_MOB_TOGGLE_PALETTE]
toggle_palette.update_state()
button.location = relative_to.location
@@ -576,32 +597,44 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
switch(button.location)
if(SCRN_OBJ_DEFAULT) // Invalid
CRASH("We just tried to hide an action buttion that somehow has the default position as its location, you done fucked up")
+
if(SCRN_OBJ_FLOATING)
floating_actions -= button
+ var/atom/movable/screen/button_palette/toggle_palette = screen_objects[HUD_MOB_TOGGLE_PALETTE]
toggle_palette.update_state()
+
if(SCRN_OBJ_IN_LIST)
listed_actions.remove_action(button)
+
if(SCRN_OBJ_IN_PALETTE)
palette_actions.remove_action(button)
+
button.screen_loc = null
/// Generates visual landings for all groups that the button is not a memeber of
/datum/hud/proc/generate_landings(atom/movable/screen/movable/action_button/button)
listed_actions.generate_landing()
palette_actions.generate_landing()
+ var/atom/movable/screen/button_palette/toggle_palette = screen_objects[HUD_MOB_TOGGLE_PALETTE]
toggle_palette.activate_landing()
/// Clears all currently visible landings
/datum/hud/proc/hide_landings()
listed_actions.clear_landing()
palette_actions.clear_landing()
+ var/atom/movable/screen/button_palette/toggle_palette = screen_objects[HUD_MOB_TOGGLE_PALETTE]
toggle_palette.disable_landing()
// Updates any existing "owned" visuals, ensures they continue to be visible
/datum/hud/proc/update_our_owner()
+ var/atom/movable/screen/button_palette/toggle_palette = screen_objects[HUD_MOB_TOGGLE_PALETTE]
+ var/atom/movable/screen/palette_scroll/palette_down = screen_objects[HUD_MOB_PALETTE_DOWN]
+ var/atom/movable/screen/palette_scroll/palette_up = screen_objects[HUD_MOB_PALETTE_UP]
+
toggle_palette.refresh_owner()
palette_down.refresh_owner()
palette_up.refresh_owner()
+
listed_actions.update_landing()
palette_actions.update_landing()
@@ -628,214 +661,3 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
action.ShowTo(mymob)
else
position_action(button, button.location)
-
-/datum/action_group
- /// The hud we're owned by
- var/datum/hud/owner
- /// The actions we're managing
- var/list/atom/movable/screen/movable/action_button/actions
- /// The initial vertical offset of our action buttons
- var/north_offset = 0
- /// The pixel vertical offset of our action buttons
- var/pixel_north_offset = 0
- /// Max amount of buttons we can have per row
- /// Indexes at 1
- var/column_max = 0
- /// How far "ahead" of the first row we start. Lets us "scroll" our rows
- /// Indexes at 1
- var/row_offset = 0
- /// How many rows of actions we can have at max before we just stop hiding
- /// Indexes at 1
- var/max_rows = INFINITY
- /// The screen location we go by
- var/location
- /// Our landing screen object
- var/atom/movable/screen/action_landing/landing
-
-/datum/action_group/New(datum/hud/owner)
- ..()
- actions = list()
- src.owner = owner
-
-/datum/action_group/Destroy()
- owner = null
- QDEL_NULL(landing)
- QDEL_LIST(actions)
- return ..()
-
-/datum/action_group/proc/insert_action(atom/movable/screen/action, index)
- if(action in actions)
- if(actions[index] == action)
- return
- actions -= action // Don't dupe, come on
- if(!index)
- index = length(actions) + 1
- index = min(length(actions) + 1, index)
- actions.Insert(index, action)
- refresh_actions()
-
-/datum/action_group/proc/remove_action(atom/movable/screen/action)
- actions -= action
- refresh_actions()
-
-/datum/action_group/proc/refresh_actions()
-
- // We don't use size() here because landings are not canon
- var/total_rows = ROUND_UP(length(actions) / column_max)
- total_rows -= max_rows // Lets get the amount of rows we're off from our max
- row_offset = clamp(row_offset, 0, total_rows) // You're not allowed to offset so far that we have a row of blank space
-
- var/button_number = 0
- for(var/atom/movable/screen/button as anything in actions)
- var/postion = ButtonNumberToScreenCoords(button_number )
- button.screen_loc = postion
- button_number++
-
- if(landing)
- var/postion = ButtonNumberToScreenCoords(button_number, landing = TRUE) // Need a good way to count buttons off screen, but allow this to display in the right place if it's being placed with no concern for dropdown
- landing.screen_loc = postion
- button_number++
-
-/// Accepts a number represeting our position in the group, indexes at 0 to make the math nicer
-/datum/action_group/proc/ButtonNumberToScreenCoords(number, landing = FALSE)
- var/row = round(number / column_max)
- row -= row_offset // If you're less then 0, you don't get to render, this lets us "scroll" rows ya feel?
- if(row < 0)
- return null
-
- // Could use >= here, but I think it's worth noting that the two start at different places, since row is based on number here
- if(row > max_rows - 1)
- if(!landing) // If you're not a landing, go away please. thx
- return null
- // We always want to render landings, even if their action button can't be displayed.
- // So we set a row equal to the max amount of rows + 1. Willing to overrun that max slightly to properly display the landing spot
- row = max_rows // Remembering that max_rows indexes at 1, and row indexes at 0
-
- // We're going to need to set our column to match the first item in the last row, so let's set number properly now
- number = row * column_max
-
- var/visual_row = row + north_offset
- var/coord_row = visual_row ? "-[visual_row]" : "+0"
-
- var/visual_column = number % column_max
- var/coord_col = "+[visual_column]"
- var/coord_col_offset = 4 + 2 * (visual_column + 1)
- return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:-[pixel_north_offset]"
-
-/datum/action_group/proc/check_against_view()
- var/owner_view = owner?.mymob?.canon_client?.view
- if(!owner_view)
- return
- // Unlikey as it is, we may have been changed. Want to start from our target position and fail down
- column_max = initial(column_max)
- // Convert our viewer's view var into a workable offset
- var/list/view_size = view_to_pixels(owner_view)
-
- // We're primarially concerned about width here, if someone makes us 1x2000 I wish them a swift and watery death
- var/furthest_screen_loc = ButtonNumberToScreenCoords(column_max - 1)
- var/list/offsets = screen_loc_to_offset(furthest_screen_loc, owner_view)
- if(offsets[1] > ICON_SIZE_X && offsets[1] < view_size[1] && offsets[2] > ICON_SIZE_Y && offsets[2] < view_size[2]) // We're all good
- return
-
- for(column_max in column_max - 1 to 1 step -1) // Yes I could do this by unwrapping ButtonNumberToScreenCoords, but I don't feel like it
- var/tested_screen_loc = ButtonNumberToScreenCoords(column_max)
- offsets = screen_loc_to_offset(tested_screen_loc, owner_view)
- // We've found a valid max length, pack it in
- if(offsets[1] > ICON_SIZE_X && offsets[1] < view_size[1] && offsets[2] > ICON_SIZE_Y && offsets[2] < view_size[2])
- break
- // Use our newly resized column max
- refresh_actions()
-
-/// Returns the amount of objects we're storing at the moment
-/datum/action_group/proc/size()
- var/amount = length(actions)
- if(landing)
- amount += 1
- return amount
-
-/datum/action_group/proc/index_of(atom/movable/screen/get_location)
- return actions.Find(get_location)
-
-/// Generates a landing object that can be dropped on to join this group
-/datum/action_group/proc/generate_landing()
- if(landing)
- return
- landing = new()
- landing.set_owner(src)
- refresh_actions()
-
-/// Clears any landing objects we may currently have
-/datum/action_group/proc/clear_landing()
- QDEL_NULL(landing)
-
-/datum/action_group/proc/update_landing()
- if(!landing)
- return
- landing.refresh_owner()
-
-/datum/action_group/proc/scroll(amount)
- row_offset += amount
- refresh_actions()
-
-/datum/action_group/palette
- north_offset = 2
- column_max = 3
- max_rows = 3
- location = SCRN_OBJ_IN_PALETTE
-
-/datum/action_group/palette/insert_action(atom/movable/screen/action, index)
- . = ..()
- var/atom/movable/screen/button_palette/palette = owner.toggle_palette
- palette.play_item_added()
-
-/datum/action_group/palette/remove_action(atom/movable/screen/action)
- . = ..()
- var/atom/movable/screen/button_palette/palette = owner.toggle_palette
- palette.play_item_removed()
- if(!length(actions))
- palette.set_expanded(FALSE)
-
-/datum/action_group/palette/refresh_actions()
- var/atom/movable/screen/button_palette/palette = owner.toggle_palette
- var/atom/movable/screen/palette_scroll/scroll_down = owner.palette_down
- var/atom/movable/screen/palette_scroll/scroll_up = owner.palette_up
-
- var/actions_above = round((owner.listed_actions.size() - 1) / owner.listed_actions.column_max)
- north_offset = initial(north_offset) + actions_above
-
- palette.screen_loc = ui_action_palette_offset(actions_above)
- var/action_count = length(owner?.mymob?.actions)
- var/our_row_count = round((length(actions) - 1) / column_max)
- if(!action_count)
- palette.screen_loc = null
-
- if(palette.expanded && action_count && our_row_count >= max_rows)
- scroll_down.screen_loc = ui_palette_scroll_offset(actions_above)
- scroll_up.screen_loc = ui_palette_scroll_offset(actions_above)
- else
- scroll_down.screen_loc = null
- scroll_up.screen_loc = null
-
- return ..()
-
-/datum/action_group/palette/ButtonNumberToScreenCoords(number, landing)
- var/atom/movable/screen/button_palette/palette = owner.toggle_palette
- if(palette.expanded)
- return ..()
-
- if(!landing)
- return null
-
- // We only render the landing in this case, so we force it to be the second item displayed (Second rather then first since it looks nicer)
- // Remember the number var indexes at 0
- return ..(1 + (row_offset * column_max), landing)
-
-
-/datum/action_group/listed
- pixel_north_offset = 6
- column_max = 10
- location = SCRN_OBJ_IN_LIST
-
-/datum/action_group/listed/refresh_actions()
- . = ..()
- owner?.palette_actions.refresh_actions() // We effect them, so we gotta refresh em
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 4e6ef6f0e2b..d8d55dccf16 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -1,328 +1,38 @@
-/atom/movable/screen/human
- icon = 'icons/hud/screen_midnight.dmi'
+/datum/hud/human
+ inventory_slots = /datum/inventory_slot/human
-/atom/movable/screen/human/toggle
- name = "toggle"
- icon_state = "toggle"
- base_icon_state = "toggle"
- mouse_over_pointer = MOUSE_HAND_POINTER
-
-/atom/movable/screen/human/toggle/Click()
-
- var/mob/targetmob = usr
-
- if(isobserver(usr))
- if(ishuman(usr.client.eye) && (usr.client.eye != usr))
- var/mob/M = usr.client.eye
- targetmob = M
-
- if(usr.hud_used.inventory_shown && targetmob.hud_used)
- usr.hud_used.inventory_shown = FALSE
- usr.client.screen -= targetmob.hud_used.toggleable_inventory
- else
- usr.hud_used.inventory_shown = TRUE
- usr.client.screen += targetmob.hud_used.toggleable_inventory
-
- targetmob.hud_used.hidden_inventory_update(usr)
- update_appearance()
-
-/atom/movable/screen/human/toggle/update_icon_state()
- icon_state = "[base_icon_state][hud?.inventory_shown ? "_active" : ""]"
- return ..()
-
-/atom/movable/screen/ling
- icon = 'icons/hud/screen_changeling.dmi'
-
-/atom/movable/screen/ling/chems
- name = "chemical storage"
- icon_state = "power_display"
- screen_loc = ui_lingchemdisplay
- ///Boolean on whether a mouse is being hovered over us right now.
- var/hovering = FALSE
-
-/atom/movable/screen/ling/chems/Click(location, control, params)
+/datum/hud/human/initialize_screen_objects()
. = ..()
- to_chat(usr, span_notice("Shows you how many chemicals you have. While hovering over this, it will show the max amount of chemicals you can hold."))
-
-/atom/movable/screen/ling/chems/MouseEntered(location,control,params)
- if(usr != get_mob())
- return
- var/datum/antagonist/changeling/antagonist_datum = IS_CHANGELING(hud.mymob)
- if(!antagonist_datum)
- return
- . = ..()
- hovering = TRUE
- antagonist_datum.update_chemical_hud()
-
-/atom/movable/screen/ling/chems/MouseExited(location, control, params)
- if(usr != get_mob())
- return
- var/datum/antagonist/changeling/antagonist_datum = IS_CHANGELING(hud.mymob)
- if(!antagonist_datum)
- return
- . = ..()
- hovering = FALSE
- antagonist_datum.update_chemical_hud(antagonist_datum.chem_charges)
-
-/atom/movable/screen/ling/sting
- name = "current sting"
- screen_loc = ui_lingstingdisplay
- invisibility = INVISIBILITY_ABSTRACT
- mouse_over_pointer = MOUSE_HAND_POINTER
-
-/atom/movable/screen/ling/sting/Click()
- if(isobserver(usr))
- return
- var/mob/living/carbon/carbon_user = usr
- carbon_user.unset_sting()
-
-/datum/hud/human/New(mob/living/carbon/human/owner)
- ..()
-
var/atom/movable/screen/using
- var/atom/movable/screen/inventory/inv_box
-
- using = new /atom/movable/screen/language_menu(null, src)
- using.icon = ui_style
- using.screen_loc = ui_human_language
- static_inventory += using
-
- using = new /atom/movable/screen/navigate(null, src)
- using.icon = ui_style
- using.screen_loc = ui_human_navigate
- static_inventory += using
-
- using = new /atom/movable/screen/area_creator(null, src)
- using.icon = ui_style
- using.screen_loc = ui_human_area
- static_inventory += using
-
- using = new /atom/movable/screen/memories(null, src)
- using.icon = ui_style
- using.screen_loc = ui_human_memories_area
- static_inventory += using
-
- action_intent = new /atom/movable/screen/combattoggle/flashy(null, src)
- action_intent.icon = ui_style
- action_intent.screen_loc = ui_combat_toggle
- static_inventory += action_intent
-
- floor_change = new /atom/movable/screen/floor_changer/vertical(null, src)
- floor_change.icon = ui_style
- floor_change.screen_loc = ui_human_floor_changer
- static_inventory += floor_change
-
- using = new /atom/movable/screen/mov_intent(null, src)
- using.icon = ui_style
- using.icon_state = (owner.move_intent == MOVE_INTENT_RUN ? "running" : "walking")
- using.screen_loc = ui_movi
- static_inventory += using
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "uniform"
- inv_box.icon = ui_style
- inv_box.slot_id = ITEM_SLOT_ICLOTHING
- inv_box.icon_state = "uniform"
- inv_box.icon_full = "template"
- inv_box.screen_loc = ui_iclothing
- toggleable_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "suit"
- inv_box.icon = ui_style
- inv_box.slot_id = ITEM_SLOT_OCLOTHING
- inv_box.icon_state = "suit"
- inv_box.icon_full = "template"
- inv_box.screen_loc = ui_oclothing
- toggleable_inventory += inv_box
-
+ // Static elements
+ add_screen_object(/atom/movable/screen/language_menu, HUD_MOB_LANGUAGE_MENU, HUD_GROUP_STATIC, ui_style, ui_human_language)
+ add_screen_object(/atom/movable/screen/navigate, HUD_MOB_NAVIGATE_MENU, HUD_GROUP_STATIC, ui_style, ui_human_navigate)
+ add_screen_object(/atom/movable/screen/area_creator, HUD_MOB_AREA_CREATOR, HUD_GROUP_STATIC, ui_style, ui_human_area)
+ add_screen_object(/atom/movable/screen/combattoggle/flashy, HUD_MOB_INTENTS, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/floor_changer/vertical, HUD_MOB_FLOOR_CHANGER, HUD_GROUP_STATIC, ui_style, ui_human_floor_changer)
+ add_screen_object(/atom/movable/screen/mov_intent, HUD_MOB_MOVE_INTENT, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/drop, HUD_MOB_DROP, HUD_GROUP_STATIC, ui_style, ui_swaphand_position(mymob, 1))
+ add_screen_object(/atom/movable/screen/human/toggle, HUD_HUMAN_TOGGLE_INVENTORY, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/rest, HUD_MOB_REST, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/sleep, HUD_MOB_SLEEP, HUD_GROUP_HOTKEYS, ui_style, ui_above_throw)
+ add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style, ui_above_movement_top)
+ add_screen_object(/atom/movable/screen/zone_sel, HUD_MOB_ZONE_SELECTOR, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/memories, HUD_MOB_MEMORIES, HUD_GROUP_STATIC, ui_style, ui_human_memories_menu)
build_hand_slots()
- using = new /atom/movable/screen/drop(null, src)
- using.icon = ui_style
- using.screen_loc = ui_swaphand_position(owner, 1)
- static_inventory += using
-
- using = new /atom/movable/screen/swap_hand(null, src)
- using.icon = ui_style
+ using = add_screen_object(/atom/movable/screen/swap_hand, HUD_MOB_SWAPHAND_2, HUD_GROUP_STATIC, ui_style, ui_swaphand_position(mymob, 2))
using.icon_state = "act_swap"
- using.screen_loc = ui_swaphand_position(owner, 2)
- static_inventory += using
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "id"
- inv_box.icon = ui_style
- inv_box.icon_state = "id"
- inv_box.icon_full = "template_small"
- inv_box.screen_loc = ui_id
- inv_box.slot_id = ITEM_SLOT_ID
- static_inventory += inv_box
+ // Hotkey buttons
+ add_screen_object(/atom/movable/screen/resist, HUD_MOB_RESIST, HUD_GROUP_HOTKEYS, ui_style)
+ add_screen_object(/atom/movable/screen/throw_catch, HUD_MOB_THROW, HUD_GROUP_HOTKEYS, ui_style)
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "mask"
- inv_box.icon = ui_style
- inv_box.icon_state = "mask"
- inv_box.icon_full = "template"
- inv_box.screen_loc = ui_mask
- inv_box.slot_id = ITEM_SLOT_MASK
- toggleable_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "neck"
- inv_box.icon = ui_style
- inv_box.icon_state = "neck"
- inv_box.icon_full = "template"
- inv_box.screen_loc = ui_neck
- inv_box.slot_id = ITEM_SLOT_NECK
- toggleable_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "back"
- inv_box.icon = ui_style
- inv_box.icon_state = "back"
- inv_box.icon_full = "template_small"
- inv_box.screen_loc = ui_back
- inv_box.slot_id = ITEM_SLOT_BACK
- static_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "left pocket"
- inv_box.icon = ui_style
- inv_box.icon_state = "pocket"
- inv_box.icon_full = "template_small"
- inv_box.screen_loc = ui_storage1
- inv_box.slot_id = ITEM_SLOT_LPOCKET
- static_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "right pocket"
- inv_box.icon = ui_style
- inv_box.icon_state = "pocket"
- inv_box.icon_full = "template_small"
- inv_box.screen_loc = ui_storage2
- inv_box.slot_id = ITEM_SLOT_RPOCKET
- static_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "suit storage"
- inv_box.icon = ui_style
- inv_box.icon_state = "suit_storage"
- inv_box.icon_full = "template"
- inv_box.screen_loc = ui_sstore1
- inv_box.slot_id = ITEM_SLOT_SUITSTORE
- static_inventory += inv_box
-
- resist_icon = new /atom/movable/screen/resist(null, src)
- resist_icon.icon = ui_style
- resist_icon.screen_loc = ui_above_movement
- hotkeybuttons += resist_icon
-
- using = new /atom/movable/screen/human/toggle(null, src)
- using.icon = ui_style
- using.screen_loc = ui_inventory
- static_inventory += using
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "gloves"
- inv_box.icon = ui_style
- inv_box.icon_state = "gloves"
- inv_box.icon_full = "template"
- inv_box.screen_loc = ui_gloves
- inv_box.slot_id = ITEM_SLOT_GLOVES
- toggleable_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "eyes"
- inv_box.icon = ui_style
- inv_box.icon_state = "glasses"
- inv_box.icon_full = "template"
- inv_box.screen_loc = ui_glasses
- inv_box.slot_id = ITEM_SLOT_EYES
- toggleable_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "ears"
- inv_box.icon = ui_style
- inv_box.icon_state = "ears"
- inv_box.icon_full = "template"
- inv_box.screen_loc = ui_ears
- inv_box.slot_id = ITEM_SLOT_EARS
- toggleable_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "head"
- inv_box.icon = ui_style
- inv_box.icon_state = "head"
- inv_box.icon_full = "template"
- inv_box.screen_loc = ui_head
- inv_box.slot_id = ITEM_SLOT_HEAD
- toggleable_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "shoes"
- inv_box.icon = ui_style
- inv_box.icon_state = "shoes"
- inv_box.icon_full = "template"
- inv_box.screen_loc = ui_shoes
- inv_box.slot_id = ITEM_SLOT_FEET
- toggleable_inventory += inv_box
-
- inv_box = new /atom/movable/screen/inventory(null, src)
- inv_box.name = "belt"
- inv_box.icon = ui_style
- inv_box.icon_state = "belt"
- inv_box.icon_full = "template_small"
- inv_box.screen_loc = ui_belt
- inv_box.slot_id = ITEM_SLOT_BELT
- static_inventory += inv_box
-
- throw_icon = new /atom/movable/screen/throw_catch(null, src)
- throw_icon.icon = ui_style
- throw_icon.screen_loc = ui_drop_throw
- hotkeybuttons += throw_icon
-
- rest_icon = new /atom/movable/screen/rest(null, src)
- rest_icon.icon = ui_style
- rest_icon.screen_loc = ui_rest
- rest_icon.update_appearance()
- static_inventory += rest_icon
-
- sleep_icon = new /atom/movable/screen/sleep(null, src)
- sleep_icon.icon = ui_style
- sleep_icon.screen_loc = ui_above_throw
-
- spacesuit_hud = new /atom/movable/screen/spacesuit(null, src)
- infodisplay += spacesuit_hud
-
- healths = new /atom/movable/screen/healths(null, src)
- infodisplay += healths
-
- hunger = new /atom/movable/screen/hunger(null, src)
- infodisplay += hunger
-
- healthdoll = new /atom/movable/screen/healthdoll/human(null, src)
- infodisplay += healthdoll
-
- stamina = new /atom/movable/screen/stamina(null, src)
- infodisplay += stamina
-
- pull_icon = new /atom/movable/screen/pull(null, src)
- pull_icon.icon = ui_style
- pull_icon.screen_loc = ui_above_movement_top
- pull_icon.update_appearance()
- static_inventory += pull_icon
-
- zone_select = new /atom/movable/screen/zone_sel(null, src)
- zone_select.icon = ui_style
- zone_select.update_appearance()
- static_inventory += zone_select
-
- for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
- if(inv.slot_id)
- inv_slots[TOBITSHIFT(inv.slot_id) + 1] = inv
- inv.update_appearance()
-
- update_locked_slots()
+ // Info
+ add_screen_object(/atom/movable/screen/spacesuit, HUD_MOB_SPACESUIT, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/healthdoll/human, HUD_MOB_HEALTHDOLL, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/stamina, HUD_MOB_STAMINA, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/healths, HUD_MOB_HEALTH, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/hunger, HUD_MOB_HUNGER, HUD_GROUP_INFO)
/datum/hud/human/update_locked_slots()
if(!mymob)
@@ -355,8 +65,9 @@
if(eyes?.no_glasses)
blocked_slots |= ITEM_SLOT_EYES
- for(var/atom/movable/screen/inventory/inv in (static_inventory + toggleable_inventory))
- if(!inv.slot_id)
+ for(var/slot_key in screen_objects)
+ var/atom/movable/screen/inventory/inv = screen_objects[slot_key]
+ if(!istype(inv) || !inv.slot_id)
continue
inv.alpha = (blocked_slots & inv.slot_id) ? 128 : initial(inv.alpha)
@@ -415,8 +126,6 @@
if(H.head)
screenmob.client.screen -= H.head
-
-
/datum/hud/human/persistent_inventory_update(mob/viewer)
if(!mymob)
return
@@ -468,15 +177,131 @@
I.screen_loc = null
screenmob.client.screen -= I
-
/mob/living/carbon/human/verb/toggle_hotkey_verbs()
set category = "OOC"
set name = "Toggle hotkey buttons"
set desc = "This disables or enables the user interface buttons which can be used with hotkeys."
if(hud_used.hotkey_ui_hidden)
- client.screen += hud_used.hotkeybuttons
+ client.screen += hud_used.screen_groups[HUD_GROUP_HOTKEYS]
hud_used.hotkey_ui_hidden = FALSE
else
- client.screen -= hud_used.hotkeybuttons
+ client.screen -= hud_used.screen_groups[HUD_GROUP_HOTKEYS]
hud_used.hotkey_ui_hidden = TRUE
+
+/datum/inventory_slot/human
+ abstract_type = /datum/inventory_slot/human
+
+/datum/inventory_slot/human/uniform
+ name = "uniform"
+ slot_id = ITEM_SLOT_ICLOTHING
+ icon_state = "uniform"
+ icon_full = "template"
+ screen_loc = ui_iclothing
+ screen_group = HUD_GROUP_TOGGLEABLE_INVENTORY
+
+/datum/inventory_slot/human/suit
+ name = "suit"
+ slot_id = ITEM_SLOT_OCLOTHING
+ icon_state = "suit"
+ icon_full = "template"
+ screen_loc = ui_oclothing
+ screen_group = HUD_GROUP_TOGGLEABLE_INVENTORY
+
+/datum/inventory_slot/human/id
+ name = "id"
+ icon_state = "id"
+ icon_full = "template_small"
+ screen_loc = ui_id
+ slot_id = ITEM_SLOT_ID
+
+/datum/inventory_slot/human/mask
+ name = "mask"
+ icon_state = "mask"
+ icon_full = "template"
+ screen_loc = ui_mask
+ slot_id = ITEM_SLOT_MASK
+ screen_group = HUD_GROUP_TOGGLEABLE_INVENTORY
+
+/datum/inventory_slot/human/neck
+ name = "neck"
+ icon_state = "neck"
+ icon_full = "template"
+ screen_loc = ui_neck
+ slot_id = ITEM_SLOT_NECK
+ screen_group = HUD_GROUP_TOGGLEABLE_INVENTORY
+
+/datum/inventory_slot/human/back
+ name = "back"
+ icon_state = "back"
+ icon_full = "template_small"
+ screen_loc = ui_back
+ slot_id = ITEM_SLOT_BACK
+
+/datum/inventory_slot/human/l_pocket
+ name = "left pocket"
+ icon_state = "pocket"
+ icon_full = "template_small"
+ screen_loc = ui_storage1
+ slot_id = ITEM_SLOT_LPOCKET
+
+/datum/inventory_slot/human/r_pocket
+ name = "right pocket"
+ icon_state = "pocket"
+ icon_full = "template_small"
+ screen_loc = ui_storage2
+ slot_id = ITEM_SLOT_RPOCKET
+
+/datum/inventory_slot/human/suit_storage
+ name = "suit storage"
+ icon_state = "suit_storage"
+ icon_full = "template"
+ screen_loc = ui_sstore1
+ slot_id = ITEM_SLOT_SUITSTORE
+
+/datum/inventory_slot/human/gloves
+ name = "gloves"
+ icon_state = "gloves"
+ icon_full = "template"
+ screen_loc = ui_gloves
+ slot_id = ITEM_SLOT_GLOVES
+ screen_group = HUD_GROUP_TOGGLEABLE_INVENTORY
+
+/datum/inventory_slot/human/eyes
+ name = "eyes"
+ icon_state = "glasses"
+ icon_full = "template"
+ screen_loc = ui_glasses
+ slot_id = ITEM_SLOT_EYES
+ screen_group = HUD_GROUP_TOGGLEABLE_INVENTORY
+
+/datum/inventory_slot/human/ears
+ name = "ears"
+ icon_state = "ears"
+ icon_full = "template"
+ screen_loc = ui_ears
+ slot_id = ITEM_SLOT_EARS
+ screen_group = HUD_GROUP_TOGGLEABLE_INVENTORY
+
+/datum/inventory_slot/human/head
+ name = "head"
+ icon_state = "head"
+ icon_full = "template"
+ screen_loc = ui_head
+ slot_id = ITEM_SLOT_HEAD
+ screen_group = HUD_GROUP_TOGGLEABLE_INVENTORY
+
+/datum/inventory_slot/human/shoes
+ name = "shoes"
+ icon_state = "shoes"
+ icon_full = "template"
+ screen_loc = ui_shoes
+ slot_id = ITEM_SLOT_FEET
+ screen_group = HUD_GROUP_TOGGLEABLE_INVENTORY
+
+/datum/inventory_slot/human/belt
+ name = "belt"
+ icon_state = "belt"
+ icon_full = "template_small"
+ screen_loc = ui_belt
+ slot_id = ITEM_SLOT_BELT
diff --git a/code/_onclick/hud/inventory_slot.dm b/code/_onclick/hud/inventory_slot.dm
new file mode 100644
index 00000000000..af3307be551
--- /dev/null
+++ b/code/_onclick/hud/inventory_slot.dm
@@ -0,0 +1,35 @@
+GLOBAL_LIST_INIT(inventory_slot_datums, initialize_inventory_slots())
+
+/proc/initialize_inventory_slots()
+ var/list/slot_types = list()
+ for (var/slot_type in valid_subtypesof(/datum/inventory_slot))
+ slot_types[slot_type] = new slot_type()
+ return slot_types
+
+/// Inventory slot datum (singleton) which holds data about an inventory screen element
+/datum/inventory_slot
+ abstract_type = /datum/inventory_slot
+ /// Name assigned to the screen element
+ var/name = "error"
+ /// Should the slot inherit HUD's ui_style?
+ var/inherit_style = TRUE
+ /// Slot ID of the element
+ var/slot_id = NONE
+ /// Icon state of the element with nothing in it/unassigned icon_full
+ var/icon_state = "template"
+ /// Icon state of the element when it has an item in it
+ var/icon_full = "template"
+ /// Location of the element
+ var/screen_loc = null
+ /// Screen group to which the element is assigned
+ var/screen_group = HUD_GROUP_STATIC
+ /// Typepath of the screen element
+ var/screen_type = /atom/movable/screen/inventory
+
+/datum/inventory_slot/proc/create_element(datum/hud/hud)
+ var/atom/movable/screen/inventory/inv_box = hud.add_screen_object(screen_type, HUD_KEY_ITEM_SLOT(slot_id), screen_group, inherit_style ? hud.ui_style : null, screen_loc)
+ inv_box.name = name
+ inv_box.icon_state = icon_state
+ inv_box.icon_full = icon_full
+ inv_box.slot_id = slot_id
+ return inv_box
diff --git a/code/_onclick/hud/living.dm b/code/_onclick/hud/living.dm
index e9237d6dbb5..cd1575908e0 100644
--- a/code/_onclick/hud/living.dm
+++ b/code/_onclick/hud/living.dm
@@ -1,37 +1,9 @@
-/datum/hud/living/New(mob/living/owner)
- ..()
-
- pull_icon = new /atom/movable/screen/pull(null, src)
- pull_icon.icon = ui_style
- pull_icon.update_appearance()
- pull_icon.screen_loc = ui_living_pull
- static_inventory += pull_icon
-
- action_intent = new /atom/movable/screen/combattoggle/flashy(null, src)
- action_intent.icon = ui_style
- action_intent.screen_loc = ui_basic_combat_toggle
- static_inventory += action_intent
-
- floor_change = new /atom/movable/screen/floor_changer(null, src)
- floor_change.icon = ui_style
- floor_change.screen_loc = ui_floor_change
- static_inventory += floor_change
-
- var/atom/movable/screen/using
-
- using = new /atom/movable/screen/language_menu(null, src)
- using.icon = ui_style
- using.screen_loc = ui_basic_language_menu
- static_inventory += using
-
- using = new /atom/movable/screen/memories(null, src)
- using.icon = ui_style
- using.screen_loc = ui_basic_memories_menu
- static_inventory += using
-
- //mob health doll assumes whatever sprite the mob is
- healthdoll = new /atom/movable/screen/healthdoll/living(null, src)
- infodisplay += healthdoll
-
- stamina = new /atom/movable/screen/stamina(null, src)
- infodisplay += stamina
+/datum/hud/living/initialize_screen_objects()
+ . = ..()
+ add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style, ui_living_pull)
+ add_screen_object(/atom/movable/screen/combattoggle/flashy, HUD_MOB_INTENTS, HUD_GROUP_STATIC, ui_style, ui_basic_combat_toggle)
+ add_screen_object(/atom/movable/screen/healthdoll/living, HUD_MOB_HEALTHDOLL, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/stamina, HUD_MOB_STAMINA, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/floor_changer, HUD_MOB_FLOOR_CHANGER, HUD_GROUP_STATIC, ui_style, ui_floor_change)
+ add_screen_object(/atom/movable/screen/language_menu, HUD_MOB_LANGUAGE_MENU, HUD_GROUP_STATIC, ui_style, ui_basic_language_menu)
+ add_screen_object(/atom/movable/screen/memories, HUD_MOB_MEMORIES, HUD_GROUP_STATIC, ui_style, ui_basic_memories_menu)
diff --git a/code/_onclick/hud/new_player.dm b/code/_onclick/hud/new_player.dm
index 0b247aaa7da..fa991657de7 100644
--- a/code/_onclick/hud/new_player.dm
+++ b/code/_onclick/hud/new_player.dm
@@ -1,5 +1,3 @@
-#define SHUTTER_MOVEMENT_DURATION 0.4 SECONDS
-#define SHUTTER_WAIT_DURATION 0.2 SECONDS
/// Maximum number of station trait buttons we will display, please think hard before creating scenarios where there are more than this
#define MAX_STATION_TRAIT_BUTTONS_VERTICAL 3
#define TRAIT_BUTTON_Y_ORIGIN 397
@@ -18,13 +16,11 @@
if (!owner?.client || owner.client.interviewee)
return
- var/list/buttons = subtypesof(/atom/movable/screen/lobby)
- for (var/atom/movable/screen/lobby/lobbyscreen as anything in buttons)
+ for (var/atom/movable/screen/lobby/lobbyscreen as anything in subtypesof(/atom/movable/screen/lobby))
if (!initial(lobbyscreen.always_available))
continue
- lobbyscreen = new lobbyscreen(our_hud = src)
+ lobbyscreen = add_screen_object(lobbyscreen, HUD_KEY_NEW_PLAYER(lobbyscreen))
lobbyscreen.SlowInit()
- static_inventory += lobbyscreen
if (!lobbyscreen.always_shown)
lobbyscreen.RegisterSignal(src, COMSIG_HUD_LOBBY_COLLAPSED, TYPE_PROC_REF(/atom/movable/screen/lobby, collapse_button))
lobbyscreen.RegisterSignal(src, COMSIG_HUD_LOBBY_EXPANDED, TYPE_PROC_REF(/atom/movable/screen/lobby, expand_button))
@@ -32,9 +28,8 @@
if (!owner.client.is_localhost())
return
- var/atom/movable/screen/lobby/button/start_now/start_button = new(our_hud = src)
+ var/atom/movable/screen/lobby/button/start_now/start_button = add_screen_object(/atom/movable/screen/lobby/button/start_now, HUD_NEW_PLAYER_START_NOW)
start_button.SlowInit()
- static_inventory += start_button
start_button.RegisterSignal(src, COMSIG_HUD_LOBBY_COLLAPSED, TYPE_PROC_REF(/atom/movable/screen/lobby, collapse_button))
start_button.RegisterSignal(src, COMSIG_HUD_LOBBY_EXPANDED, TYPE_PROC_REF(/atom/movable/screen/lobby, expand_button))
@@ -52,9 +47,8 @@
continue
if(LAZYACCESS(shown_station_trait_buttons, trait))
continue
- var/atom/movable/screen/lobby/button/sign_up/sign_up_button = new(our_hud = src)
+ var/atom/movable/screen/lobby/button/sign_up/sign_up_button = add_screen_object(/atom/movable/screen/lobby/button/sign_up, HUD_NEW_PLAYER_SIGN_UP)
trait.setup_lobby_button(sign_up_button)
- static_inventory |= sign_up_button
LAZYSET(shown_station_trait_buttons, trait, sign_up_button)
RegisterSignal(trait, COMSIG_QDELETING, PROC_REF(remove_station_trait_button))
@@ -93,734 +87,9 @@
return
LAZYREMOVE(shown_station_trait_buttons, trait)
UnregisterSignal(trait, COMSIG_QDELETING)
- static_inventory -= button
qdel(button)
place_station_trait_buttons()
-/atom/movable/screen/lobby
- plane = SPLASHSCREEN_PLANE
- layer = LOBBY_MENU_LAYER
- screen_loc = "TOP,CENTER"
- /// Whether this HUD element can be hidden from the client's "screen" (moved off-screen) or not
- var/always_shown = FALSE
- /// If true we will create this button every time the HUD is generated
- var/always_available = TRUE
-
-///Set the HUD in New, as lobby screens are made before Atoms are Initialized.
-/atom/movable/screen/lobby/New(loc, datum/hud/our_hud, ...)
- set_new_hud(our_hud)
- return ..()
-
-///Run sleeping actions after initialize
-/atom/movable/screen/lobby/proc/SlowInit()
- return
-
-///Animates moving the button off-screen
-/atom/movable/screen/lobby/proc/collapse_button()
- SIGNAL_HANDLER
- //wait for the shutter to come down
- animate(src, transform = transform, time = SHUTTER_MOVEMENT_DURATION + SHUTTER_WAIT_DURATION)
- //then pull the buttons up with the shutter
- animate(transform = transform.Translate(x = 0, y = 146), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_IN)
-
-///Animates moving the button back into place
-/atom/movable/screen/lobby/proc/expand_button()
- SIGNAL_HANDLER
- //the buttons are off-screen, so we sync them up to come down with the shutter
- animate(src, transform = matrix(), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_OUT)
-
-/atom/movable/screen/lobby/background
- icon = 'icons/hud/lobby/background.dmi'
- icon_state = "background"
- layer = LOBBY_BACKGROUND_LAYER
- screen_loc = "TOP,CENTER:-61"
-
-/atom/movable/screen/lobby/button
- mouse_over_pointer = MOUSE_HAND_POINTER
- ///Is the button currently enabled?
- VAR_PROTECTED/enabled = TRUE
- ///Is the button currently being hovered over with the mouse?
- var/highlighted = FALSE
- ///Should this button play the select sound?
- var/select_sound_play = TRUE
-
-/atom/movable/screen/lobby/button/Click(location, control, params)
- if(usr != get_mob())
- return
-
- if(!usr.client || usr.client.interviewee)
- return
-
- . = ..()
-
- if(!enabled)
- return
- flick("[base_icon_state]_pressed", src)
- if(select_sound_play)
- var/sound/ui_select_sound = sound('sound/misc/menu/ui_select1.ogg')
- ui_select_sound.frequency = get_rand_frequency_low_range()
- SEND_SOUND(hud.mymob, ui_select_sound)
- update_appearance(UPDATE_ICON)
- return TRUE
-
-/atom/movable/screen/lobby/button/MouseEntered(location,control,params)
- if(usr != get_mob())
- return
-
- if(!usr.client || usr.client.interviewee)
- return
-
- . = ..()
- highlighted = TRUE
- update_appearance(UPDATE_ICON)
-
-/atom/movable/screen/lobby/button/MouseExited()
- if(usr != get_mob())
- return
-
- if(!usr.client || usr.client.interviewee)
- return
-
- . = ..()
- highlighted = FALSE
- update_appearance(UPDATE_ICON)
-
-/atom/movable/screen/lobby/button/update_icon(updates)
- . = ..()
- if(!enabled)
- icon_state = "[base_icon_state]_disabled"
- return
- else if(highlighted)
- icon_state = "[base_icon_state]_highlighted"
- return
- icon_state = base_icon_state
-
-///Updates the button's status: TRUE to enable interaction with the button, FALSE to disable
-/atom/movable/screen/lobby/button/proc/set_button_status(status)
- if(status == enabled)
- return FALSE
- enabled = status
- update_appearance(UPDATE_ICON)
- mouse_over_pointer = enabled ? MOUSE_HAND_POINTER : MOUSE_INACTIVE_POINTER
- return TRUE
-
-///Prefs menu
-/atom/movable/screen/lobby/button/character_setup
- name = "View Character Setup"
- screen_loc = "TOP:-70,CENTER:-54"
- icon = 'icons/hud/lobby/character_setup.dmi'
- icon_state = "character_setup_disabled"
- base_icon_state = "character_setup"
- enabled = FALSE
-
-/atom/movable/screen/lobby/button/character_setup/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- // We need IconForge and the assets to be ready before allowing the menu to open
- if(SSearly_assets.initialized == INITIALIZATION_INNEW_REGULAR || SSatoms.initialized == INITIALIZATION_INNEW_REGULAR)
- flick("[base_icon_state]_enabled", src)
- set_button_status(TRUE)
- else
- set_button_status(FALSE)
- RegisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(enable_character_setup))
- RegisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(enable_character_setup))
-
-/atom/movable/screen/lobby/button/character_setup/Click(location, control, params)
- . = ..()
- if(!.)
- return
-
- var/datum/preferences/preferences = hud.mymob.canon_client.prefs
- preferences.current_window = PREFERENCE_TAB_CHARACTER_PREFERENCES
- preferences.update_static_data(usr)
- preferences.ui_interact(usr)
-
-/atom/movable/screen/lobby/button/character_setup/proc/enable_character_setup()
- SIGNAL_HANDLER
- flick("[base_icon_state]_enabled", src)
- set_button_status(TRUE)
- UnregisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE)
- UnregisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE)
-
-///Button that appears before the game has started
-/atom/movable/screen/lobby/button/ready
- name = "Toggle Readiness"
- screen_loc = "TOP:-8,CENTER:-65"
- icon = 'icons/hud/lobby/ready.dmi'
- icon_state = "not_ready"
- base_icon_state = "not_ready"
-
-/atom/movable/screen/lobby/button/ready/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- switch(SSticker.current_state)
- if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
- RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(hide_ready_button))
- if(GAME_STATE_SETTING_UP)
- set_button_status(FALSE)
- RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(show_ready_button))
- else
- set_button_status(FALSE)
-
-/atom/movable/screen/lobby/button/ready/proc/hide_ready_button()
- SIGNAL_HANDLER
- set_button_status(FALSE)
- UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
- RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(show_ready_button))
-
-/atom/movable/screen/lobby/button/ready/proc/show_ready_button()
- SIGNAL_HANDLER
- set_button_status(TRUE)
- UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
- RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(hide_ready_button))
-
-/atom/movable/screen/lobby/button/ready/Click(location, control, params)
- . = ..()
- if(!.)
- return
- var/mob/dead/new_player/new_player = hud.mymob
-
- // switch based on the user, if they aren't ready then we change them to ready, and vice versa
- if(new_player.ready == PLAYER_NOT_READY)
- new_player.auto_deadmin_on_ready_or_latejoin()
- new_player.ready = PLAYER_READY_TO_PLAY
- base_icon_state = "ready"
- else
- new_player.ready = PLAYER_NOT_READY
- base_icon_state = "not_ready"
-
- update_appearance(UPDATE_ICON)
- SEND_SIGNAL(hud, COMSIG_HUD_PLAYER_READY_TOGGLE)
-
-///Shown when the game has started
-/atom/movable/screen/lobby/button/join
- name = "Join Game"
- screen_loc = "TOP:-13,CENTER:-58"
- icon = 'icons/hud/lobby/join.dmi'
- icon_state = "" //Default to not visible
- base_icon_state = "join_game"
- enabled = null // set in init
-
-/atom/movable/screen/lobby/button/join/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- switch(SSticker.current_state)
- if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
- set_button_status(FALSE)
- RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(show_join_button))
- if(GAME_STATE_SETTING_UP)
- set_button_status(TRUE)
- RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(hide_join_button))
- else
- set_button_status(TRUE)
-
-/atom/movable/screen/lobby/button/join/Click(location, control, params)
- . = ..()
- if(!.)
- return
-
- if(!SSticker?.IsRoundInProgress())
- to_chat(hud.mymob, span_boldwarning("The round is either not ready, or has already finished..."))
- return
-
- //Determines Relevent Population Cap
- var/relevant_cap
- var/hard_popcap = CONFIG_GET(number/hard_popcap)
- var/extreme_popcap = CONFIG_GET(number/extreme_popcap)
- if(hard_popcap && extreme_popcap)
- relevant_cap = min(hard_popcap, extreme_popcap)
- else
- relevant_cap = max(hard_popcap, extreme_popcap)
-
- var/mob/dead/new_player/new_player = hud.mymob
-
- if(SSticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(new_player.key) in GLOB.admin_datums)))
- to_chat(new_player, span_danger("[CONFIG_GET(string/hard_popcap_message)]"))
-
- var/queue_position = SSticker.queued_players.Find(new_player)
- if(queue_position == 1)
- to_chat(new_player, span_notice("You are next in line to join the game. You will be notified when a slot opens up."))
- else if(queue_position)
- to_chat(new_player, span_notice("There are [queue_position-1] players in front of you in the queue to join the game."))
- else
- SSticker.queued_players += new_player
- to_chat(new_player, span_notice("You have been added to the queue to join the game. Your position in queue is [SSticker.queued_players.len]."))
- return
-
- new_player.auto_deadmin_on_ready_or_latejoin()
-
- if(!LAZYACCESS(params2list(params), CTRL_CLICK))
- GLOB.latejoin_menu.ui_interact(new_player)
- else
- to_chat(new_player, span_warning("Opening emergency fallback late join menu! If THIS doesn't show, ahelp immediately!"))
- GLOB.latejoin_menu.fallback_ui(new_player)
-
-
-/atom/movable/screen/lobby/button/join/proc/show_join_button()
- SIGNAL_HANDLER
- set_button_status(TRUE)
- UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
- RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(hide_join_button))
-
-/atom/movable/screen/lobby/button/join/proc/hide_join_button()
- SIGNAL_HANDLER
- set_button_status(FALSE)
- UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
- RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(show_join_button))
-
-/atom/movable/screen/lobby/button/observe
- name = "Observe"
- screen_loc = "TOP:-40,CENTER:-54"
- icon = 'icons/hud/lobby/observe.dmi'
- icon_state = "observe_disabled"
- base_icon_state = "observe"
- enabled = null // set in init
-
-/atom/movable/screen/lobby/button/observe/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- if(SSticker.current_state > GAME_STATE_STARTUP)
- set_button_status(TRUE)
- else
- set_button_status(FALSE)
- RegisterSignal(SSticker, COMSIG_TICKER_ENTER_PREGAME, PROC_REF(enable_observing))
-
-/atom/movable/screen/lobby/button/observe/Click(location, control, params)
- . = ..()
- if(!.)
- return
- var/mob/dead/new_player/new_player = hud.mymob
- new_player.make_me_an_observer()
-
-/atom/movable/screen/lobby/button/observe/proc/enable_observing()
- SIGNAL_HANDLER
- flick("[base_icon_state]_enabled", src)
- set_button_status(TRUE)
- UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_PREGAME)
-
-//Subtype the bottom buttons away so the collapse/expand shutter goes behind them
-/atom/movable/screen/lobby/button/bottom
- layer = LOBBY_BOTTOM_BUTTON_LAYER
- icon = 'icons/hud/lobby/bottom_buttons.dmi'
-
-/atom/movable/screen/lobby/button/bottom/settings
- name = "View Game Preferences"
- icon_state = "settings_disabled"
- base_icon_state = "settings"
- screen_loc = "TOP:-122,CENTER:+29"
- enabled = FALSE
-
-/atom/movable/screen/lobby/button/bottom/settings/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- // We need IconForge and the assets to be ready before allowing the menu to open
- if(SSearly_assets.initialized == INITIALIZATION_INNEW_REGULAR || SSatoms.initialized == INITIALIZATION_INNEW_REGULAR)
- set_button_status(TRUE)
- else
- set_button_status(FALSE)
- RegisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(enable_settings))
- RegisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(enable_settings))
-
-/atom/movable/screen/lobby/button/bottom/settings/Click(location, control, params)
- . = ..()
- if(!.)
- return
-
- var/datum/preferences/preferences = hud.mymob.canon_client.prefs
- preferences.current_window = PREFERENCE_TAB_GAME_PREFERENCES
- preferences.update_static_data(usr)
- preferences.ui_interact(usr)
-
-/atom/movable/screen/lobby/button/bottom/settings/proc/enable_settings()
- SIGNAL_HANDLER
- set_button_status(TRUE)
- UnregisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE)
- UnregisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE)
-
-/atom/movable/screen/lobby/button/bottom/changelog_button
- name = "View Changelog"
- icon_state = "changelog"
- base_icon_state = "changelog"
- screen_loc ="TOP:-122,CENTER:+57"
-
-/atom/movable/screen/lobby/button/bottom/changelog_button/Click(location, control, params)
- . = ..()
- usr.client?.changelog()
-
-/atom/movable/screen/lobby/button/bottom/crew_manifest
- name = "View Crew Manifest"
- icon_state = "crew_manifest"
- base_icon_state = "crew_manifest"
- screen_loc = "TOP:-122,CENTER:+2"
-
-/atom/movable/screen/lobby/button/bottom/crew_manifest/Click(location, control, params)
- . = ..()
- if(!.)
- return
- var/mob/dead/new_player/new_player = hud.mymob
- new_player.ViewManifest()
-
-/atom/movable/screen/lobby/button/bottom/poll
- name = "View Available Polls"
- icon_state = "poll"
- base_icon_state = "poll"
- screen_loc = "TOP:-122,CENTER:-26"
- ///Whether the button should have a New Poll notification overlay
- var/new_poll = FALSE
-
-/atom/movable/screen/lobby/button/bottom/poll/SlowInit(mapload)
- . = ..()
- if(!usr)
- return
- var/mob/dead/new_player/new_player = usr
- if(is_guest_key(new_player.key))
- set_button_status(FALSE)
- return
- if(!SSdbcore.Connect())
- set_button_status(FALSE)
- return
- var/isadmin = FALSE
- if(new_player.client?.holder)
- isadmin = TRUE
- var/datum/db_query/query_get_new_polls = SSdbcore.NewQuery({"
- SELECT id FROM [format_table_name("poll_question")]
- WHERE (adminonly = 0 OR :isadmin = 1)
- AND Now() BETWEEN starttime AND endtime
- AND deleted = 0
- AND id NOT IN (
- SELECT pollid FROM [format_table_name("poll_vote")]
- WHERE ckey = :ckey
- AND deleted = 0
- )
- AND id NOT IN (
- SELECT pollid FROM [format_table_name("poll_textreply")]
- WHERE ckey = :ckey
- AND deleted = 0
- )
- "}, list("isadmin" = isadmin, "ckey" = new_player.ckey))
- if(!query_get_new_polls.Execute())
- qdel(query_get_new_polls)
- set_button_status(FALSE)
- return
- if(query_get_new_polls.NextRow())
- new_poll = TRUE
- else
- new_poll = FALSE
- update_appearance(UPDATE_OVERLAYS)
- qdel(query_get_new_polls)
- if(QDELETED(new_player))
- set_button_status(FALSE)
- return
-
-/atom/movable/screen/lobby/button/bottom/poll/update_overlays()
- . = ..()
- if(new_poll)
- . += mutable_appearance('icons/hud/lobby/poll_overlay.dmi', "new_poll")
-
-/atom/movable/screen/lobby/button/bottom/poll/Click(location, control, params)
- . = ..()
- if(!.)
- return
- var/mob/dead/new_player/new_player = hud.mymob
- new_player.handle_player_polling()
-
-/// A generic "sign up" button used by station traits
-/atom/movable/screen/lobby/button/sign_up
- icon = 'icons/hud/lobby/signup_button.dmi'
- icon_state = "signup"
- base_icon_state = "signup"
- always_available = FALSE
-
-/atom/movable/screen/lobby/button/sign_up/MouseEntered(location, control, params)
- . = ..()
- if(QDELETED(src) || !desc)
- return
- openToolTip(usr, tip_src = src, params = params, title = name, content = desc,)
-
-/atom/movable/screen/lobby/button/sign_up/MouseExited()
- . = ..()
- closeToolTip(usr)
-
-/atom/movable/screen/lobby/button/collapse
- name = "Collapse Lobby Menu"
- icon = 'icons/hud/lobby/collapse_expand.dmi'
- icon_state = "collapse"
- base_icon_state = "collapse"
- layer = LOBBY_BELOW_MENU_LAYER
- screen_loc = "TOP:-82,CENTER:-54"
- always_shown = TRUE
-
- var/blip_enabled = TRUE
-
-/atom/movable/screen/lobby/button/collapse/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- switch(SSticker.current_state)
- if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
- RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(disable_blip))
- RegisterSignal(hud, COMSIG_HUD_PLAYER_READY_TOGGLE, PROC_REF(on_player_ready_toggle))
- if(GAME_STATE_SETTING_UP)
- blip_enabled = FALSE
- RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(enable_blip))
- else
- blip_enabled = FALSE
-
- add_overlay(get_blip_overlay())
- update_icon(UPDATE_OVERLAYS)
-
-/atom/movable/screen/lobby/button/collapse/update_overlays()
- . = ..()
- . += get_blip_overlay()
-
-/atom/movable/screen/lobby/button/collapse/Click(location, control, params)
- . = ..()
- if(!.)
- return
-
- if(!istype(hud, /datum/hud/new_player))
- return
- var/datum/hud/new_player/our_hud = hud
- base_icon_state = our_hud.menu_hud_status ? "expand" : "collapse"
- name = "[our_hud.menu_hud_status ? "Expand" : "Collapse"] Lobby Menu"
- set_button_status(FALSE)
-
- //get the shutter object used by our hud
- var/atom/movable/screen/lobby/shutter/menu_shutter = locate(/atom/movable/screen/lobby/shutter) in hud.static_inventory
-
- //animate the shutter
- menu_shutter.setup_shutter_animation()
- //animate bottom buttons' movement
- if(our_hud.menu_hud_status)
- collapse_menu()
- else
- expand_menu()
- our_hud.menu_hud_status = !our_hud.menu_hud_status
-
- //re-enable clicking the button when the shutter animation finishes
- //we use sleep here so it can work during game setup, as addtimer would not work until the game would finish setting up
- sleep(2 * SHUTTER_MOVEMENT_DURATION + SHUTTER_WAIT_DURATION)
- set_button_status(TRUE)
-
-///Proc to update the ready blip state upon new player's ready status change
-/atom/movable/screen/lobby/button/collapse/proc/on_player_ready_toggle()
- SIGNAL_HANDLER
- update_appearance(UPDATE_ICON)
-
-///Returns a ready blip overlay depending on the player's ready state
-/atom/movable/screen/lobby/button/collapse/proc/get_blip_overlay()
- var/blip_icon_state = "ready_blip"
- if(blip_enabled && hud)
- var/mob/dead/new_player/new_player = hud.mymob
- blip_icon_state += "_[new_player.is_ready_to_play() ? "" : "not_"]ready"
- else
- blip_icon_state += "_disabled"
- var/mutable_appearance/ready_blip = mutable_appearance(icon, blip_icon_state)
- return ready_blip
-
-///Disables the ready blip; makes us listen for the setup error to re-enable the blip
-/atom/movable/screen/lobby/button/collapse/proc/disable_blip()
- SIGNAL_HANDLER
- blip_enabled = FALSE
- UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
- RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(enable_blip))
- update_appearance(UPDATE_ICON)
-
-///Enables the ready blip; makes us listen for the setup completion and game start to disable the blip
-/atom/movable/screen/lobby/button/collapse/proc/enable_blip()
- SIGNAL_HANDLER
- blip_enabled = TRUE
- UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
- RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(disable_blip))
- update_appearance(UPDATE_ICON)
-
-///Moves the button to the top of the screen, leaving only the screen part in view
-///Sends a signal on the hud for the menu hud elements to listen to
-/atom/movable/screen/lobby/button/collapse/proc/collapse_menu()
- SEND_SIGNAL(hud, COMSIG_HUD_LOBBY_COLLAPSED)
- //wait for the shutter to come down
- animate(src, transform = transform, time = SHUTTER_MOVEMENT_DURATION + SHUTTER_WAIT_DURATION)
- //then pull the button up with the shutter and leave it on the edge of the screen
- animate(transform = transform.Translate(x = 0, y = 134), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_IN)
- SEND_SOUND(hud.mymob, sound('sound/misc/menu/menu_rollup1.ogg'))
-
-///Extends the button back to its usual spot
-///Sends a signal on the hud for the menu hud elements to listen to
-/atom/movable/screen/lobby/button/collapse/proc/expand_menu()
- SEND_SIGNAL(hud, COMSIG_HUD_LOBBY_EXPANDED)
- animate(src, transform = matrix(), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_OUT)
- SEND_SOUND(hud.mymob, sound('sound/misc/menu/menu_rolldown1.ogg'))
-
-/atom/movable/screen/lobby/shutter
- icon = 'icons/hud/lobby/shutter.dmi'
- icon_state = "shutter"
- base_icon_state = "shutter"
- screen_loc = "TOP:+143,CENTER:-73" //"home" position is off-screen
- layer = LOBBY_SHUTTER_LAYER
- always_shown = TRUE
-
-///Sets up the shutter pulling down and up. It's the same animation for both collapsing and expanding the menu.
-/atom/movable/screen/lobby/shutter/proc/setup_shutter_animation()
- //bring down the shutter
- animate(src, transform = transform.Translate(x = 0, y = -143), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_OUT)
-
- //wait a little bit before bringing the shutter up
- animate(transform = transform, time = SHUTTER_WAIT_DURATION)
-
- //pull the shutter back off-screen
- animate(transform = matrix(), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_IN)
-
-/// LOCALHOST ONLY - Start Now button
-/atom/movable/screen/lobby/button/start_now
- name = "Start Now (LOCALHOST ONLY)"
- screen_loc = "TOP:-146,CENTER:-54"
- icon = 'icons/hud/lobby/start_now.dmi'
- icon_state = "start_now"
- base_icon_state = "start_now"
- always_available = FALSE
- select_sound_play = FALSE
-
-/atom/movable/screen/lobby/button/start_now/Click(location, control, params)
- . = ..()
- if(!. || !usr.client.is_localhost() || !check_rights_for(usr.client, R_SERVER))
- return
- SEND_SOUND(hud.mymob, sound('sound/effects/cartoon_sfx/cartoon_splat.ogg', volume = 50))
- SSticker.start_immediately = TRUE
- if(SSticker.current_state == GAME_STATE_STARTUP)
- to_chat(usr, span_admin("The server is still setting up, but the round will be started as soon as possible."))
-
-#define OVERLAY_X_DIFF 12
-#define OVERLAY_Y_DIFF 5
-
-///Lobby screen that appears before the game has started showing how many players there are and who is ready.
-/atom/movable/screen/lobby/new_player_info
- name = "New Player Info"
- screen_loc = "EAST-3,CENTER:140"
- icon = 'icons/hud/lobby/newplayer.dmi'
- icon_state = null //we only show up when we get update appearance called, cause we need our overlay to not look bad.
- base_icon_state = "newplayer"
- maptext_height = 75
- maptext_width = 80
- maptext_x = OVERLAY_X_DIFF
- maptext_y = OVERLAY_Y_DIFF
-
- ///Boolean on whether or not we should have our static overlay, so we 'turn' the TV off when collapsing.
- var/show_static = TRUE
- ///Static mutable appearance of a job icon we're displaying on the TV for overflow job.
- var/static/mutable_appearance/job_overlay
-
-/atom/movable/screen/lobby/new_player_info/Initialize(mapload, datum/hud/hud_owner)
- . = ..()
- START_PROCESSING(SSnewplayer_info, src)
- update_text()
-
- //only go if the station trait is selected, otherwise it'll show "Assistant" every round.
- var/datum/station_trait/overflow_job_bureaucracy/overflow_job = locate() in SSstation.station_traits
- if(overflow_job && isnull(job_overlay))
- var/icon/job_icon = get_job_hud_icon(SSjob.overflow_role)
- if(isnull(job_icon))
- stack_trace("[SSjob.overflow_role::title] was selected as the Job Overflow but has no icon!")
- else
- job_icon.Scale(ICON_SIZE_X / 2, ICON_SIZE_X / 2)
- job_overlay = mutable_appearance(job_icon, offset_spokesman = src, alpha = 120, layer = src.layer+0.02)
- var/matrix/job_matrix = matrix()
- job_matrix.Translate(6, 14) //this is completely arbitruary just what I thought looked good.
- job_overlay.transform = job_matrix
-
- update_appearance(UPDATE_ICON)
-
-/atom/movable/screen/lobby/new_player_info/Destroy()
- STOP_PROCESSING(SSnewplayer_info, src)
- return ..()
-
-/atom/movable/screen/lobby/new_player_info/MouseEntered(location, control, params)
- . = ..()
- if(QDELETED(src) || isnull(job_overlay))
- return
- openToolTip(usr, src, params, title = "[SSjob.overflow_role::title] overflow", content = "The overflow for the round has been set as [SSjob.overflow_role::title].")
-
-/atom/movable/screen/lobby/new_player_info/MouseExited()
- closeToolTip(usr)
- return ..()
-
-/atom/movable/screen/lobby/new_player_info/update_icon_state()
- . = ..()
- icon_state = base_icon_state
-
-/atom/movable/screen/lobby/new_player_info/update_overlays()
- . = ..()
- . += mutable_appearance(icon, "[base_icon_state]_overlay", layer = src.layer+0.01)
- if(!show_static)
- return .
- if(job_overlay)
- . += job_overlay
- . += mutable_appearance(icon, "static_base", alpha = 20, layer = src.layer+0.03)
- //we have this in a separate file because `generate_icon_alpha_mask` puts lighting even on non-existent pixels,
- //giving the icon a weird background color.
- var/mutable_appearance/scanline = mutable_appearance(generate_icon_alpha_mask('icons/hud/lobby/newplayer_scanline.dmi', "scanline"), alpha = 20, layer = src.layer+0.04)
- scanline.pixel_y = OVERLAY_X_DIFF
- scanline.pixel_x = OVERLAY_Y_DIFF
- . += scanline
-
-/atom/movable/screen/lobby/new_player_info/process(seconds_per_tick)
- update_text()
-
-/atom/movable/screen/lobby/new_player_info/collapse_button()
- show_static = FALSE
- update_text()
- //to be in sync with parent, we'll turn the TV off in this time instead.
- animate(src, appearance = update_appearance(UPDATE_ICON), time = SHUTTER_MOVEMENT_DURATION + SHUTTER_WAIT_DURATION)
- //we go to the right, not up
- animate(transform = transform.Translate(x = 146, y = 0), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_IN)
-
-/atom/movable/screen/lobby/new_player_info/expand_button()
- . = ..()
- show_static = TRUE
- update_appearance(UPDATE_ICON)
- update_text()
-
-/atom/movable/screen/lobby/new_player_info/proc/update_text()
- if(!hud || !show_static)
- maptext = null
- return
-
- var/round_started = SSticker.HasRoundStarted()
- if(!MC_RUNNING())
- maptext = MAPTEXT("[(round_started ? null : "Starting in [time_remaining_str()]
")]Loading...")
- return
- if(SSticker.IsPostgame())
- maptext = MAPTEXT("Game ended,
\
- restart soon")
- return
-
- var/new_maptext
- if(round_started)
- new_maptext = "[SSmapping.current_map.map_name]
\
- [LAZYLEN(GLOB.clients)] player\s online
\
- [ROUND_TIME()] in
"
- new_maptext += ""
- else
-
- if(hud.mymob.client?.holder)
- new_maptext = "Starting in [time_remaining_str()]
\
- [LAZYLEN(GLOB.clients)] player\s
\
- [SSticker.totalPlayersReady] players ready
\
- [SSticker.total_admins_ready] / [length(GLOB.admins)] admins ready"
- else
- new_maptext = "[time_remaining_str()]
\
- [LAZYLEN(GLOB.clients)] player\s"
-
- maptext = MAPTEXT(new_maptext)
-
-/atom/movable/screen/lobby/new_player_info/proc/time_remaining_str()
- var/time_remaining = SSticker.GetTimeLeft()
- if(time_remaining > 0)
- time_remaining = "[round(time_remaining/10)]s"
- else if(time_remaining == -10)
- time_remaining = "DELAYED"
- else
- time_remaining = "SOON"
-
- return time_remaining
-
-#undef OVERLAY_X_DIFF
-#undef OVERLAY_Y_DIFF
-
-#undef SHUTTER_MOVEMENT_DURATION
-#undef SHUTTER_WAIT_DURATION
#undef MAX_STATION_TRAIT_BUTTONS_VERTICAL
#undef TRAIT_BUTTON_Y_ORIGIN
#undef TRAIT_BUTTON_X_ORIGIN
diff --git a/code/_onclick/hud/ooze.dm b/code/_onclick/hud/ooze.dm
index 0962b58126a..e796df33b4a 100644
--- a/code/_onclick/hud/ooze.dm
+++ b/code/_onclick/hud/ooze.dm
@@ -1,14 +1,8 @@
///Hud type with targeting dol and a nutrition bar
-/datum/hud/ooze/New(mob/living/owner)
+/datum/hud/ooze/initialize_screen_objects()
. = ..()
-
- zone_select = new /atom/movable/screen/zone_sel(null, src)
- zone_select.icon = ui_style
- zone_select.update_appearance()
- static_inventory += zone_select
-
- alien_plasma_display = new /atom/movable/screen/ooze_nutrition_display(null, src) //Just going to use the alien plasma display because making new vars for each object is braindead.
- infodisplay += alien_plasma_display
+ add_screen_object(/atom/movable/screen/zone_sel, HUD_MOB_ZONE_SELECTOR, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/ooze_nutrition_display, HUD_OOZE_NUTRITION_DISPLAY)
/atom/movable/screen/ooze_nutrition_display
icon = 'icons/hud/screen_alien.dmi'
diff --git a/code/_onclick/hud/pai.dm b/code/_onclick/hud/pai.dm
new file mode 100644
index 00000000000..74da5962b37
--- /dev/null
+++ b/code/_onclick/hud/pai.dm
@@ -0,0 +1,33 @@
+
+/datum/hud/pai
+ ui_style = 'icons/hud/screen_pai.dmi'
+
+/datum/hud/pai/initialize_screen_objects()
+ . = ..()
+ add_screen_object(/atom/movable/screen/language_menu, HUD_MOB_LANGUAGE_MENU, ui_style, ui_pai_language_menu)
+ add_screen_object(/atom/movable/screen/navigate, HUD_MOB_NAVIGATE_MENU, ui_style, ui_pai_navigate_menu)
+ add_screen_object(/atom/movable/screen/memories, HUD_MOB_MEMORIES, HUD_GROUP_STATIC, ui_style, ui_pai_memories_menu)
+
+ add_screen_object(/atom/movable/screen/pai/software, HUD_PAI_SOFTWARE)
+ add_screen_object(/atom/movable/screen/pai/shell, HUD_PAI_SHELL)
+ add_screen_object(/atom/movable/screen/pai/chassis, HUD_PAI_CHASSIS)
+ add_screen_object(/atom/movable/screen/pai/rest, HUD_MOB_REST)
+ add_screen_object(/atom/movable/screen/pai/light, HUD_CYBORG_LAMP)
+ add_screen_object(/atom/movable/screen/pai/newscaster, HUD_PAI_NEWSCASTER)
+ add_screen_object(/atom/movable/screen/pai/host_monitor, HUD_PAI_HOST_MONITOR)
+ add_screen_object(/atom/movable/screen/pai/crew_manifest, HUD_AI_CREW_MANIFEST)
+ add_screen_object(/atom/movable/screen/pai/state_laws, HUD_AI_STATE_LAWS)
+ add_screen_object(/atom/movable/screen/pai/internal_gps, HUD_PAI_GPS)
+ add_screen_object(/atom/movable/screen/pai/image_take, HUD_AI_TAKE_IMAGE)
+ add_screen_object(/atom/movable/screen/pai/image_view, HUD_AI_IMAGE_VIEW)
+ add_screen_object(/atom/movable/screen/pai/radio, HUD_CYBORG_RADIO)
+ add_screen_object(/atom/movable/screen/pai/modpc, HUD_SILICON_TABLET)
+
+ update_software_buttons()
+
+/datum/hud/pai/proc/update_software_buttons()
+ var/mob/living/silicon/pai/owner = mymob
+ for(var/button_key in screen_objects)
+ var/atom/movable/screen/pai/button = screen_objects[button_key]
+ if(istype(button) && button.required_software)
+ button.color = owner.installed_software.Find(button.required_software) ? null : COLOR_GRAY
diff --git a/code/_onclick/hud/parallax/parallax.dm b/code/_onclick/hud/parallax/parallax.dm
index 8a2227db588..c29e45dfde7 100644
--- a/code/_onclick/hud/parallax/parallax.dm
+++ b/code/_onclick/hud/parallax/parallax.dm
@@ -201,7 +201,6 @@
hud_used.set_parallax_movedir(areaobj.parallax_movedir, TRUE)
// Root object for parallax, all parallax layers are drawn onto this and it manages them
-INITIALIZE_IMMEDIATE(/atom/movable/screen/parallax_home)
/atom/movable/screen/parallax_home
icon = null
blend_mode = BLEND_ADD
@@ -293,7 +292,6 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/parallax_home)
QDEL_LIST(parallax_layers_cached)
// We need parallax to always pass its args down into initialize, so we immediate init it
-INITIALIZE_IMMEDIATE(/atom/movable/screen/parallax_layer)
/atom/movable/screen/parallax_layer
icon = 'icons/effects/parallax.dmi'
var/speed = 1
diff --git a/code/_onclick/hud/perks.dm b/code/_onclick/hud/perks.dm
deleted file mode 100644
index 22b08906b66..00000000000
--- a/code/_onclick/hud/perks.dm
+++ /dev/null
@@ -1,35 +0,0 @@
-/atom/movable/screen/perk
- icon = 'icons/hud/perks.dmi'
- name = "blank"
- icon_state = "blank"
-
-/atom/movable/screen/perk/more
- name = "more"
- icon_state = "more"
- // When compact we don't show our perk huds in ui.
- var/compact = FALSE
- // List of all perks that we see on hud.
- var/list/perks_on_hud = list()
- // List to remember all perks we hide when compact it.
- var/list/perks_compacted = list()
-
-/atom/movable/screen/perk/more/Click(location, control, params)
- . = ..()
- if(!isliving(usr))
- return
- var/mob/living/usr_is_living = usr
- var/datum/antagonist/wizard/wizard_datum = usr_is_living.mind.has_antag_datum(/datum/antagonist/wizard)
- if(!wizard_datum)
- return
- compact = !compact
- var/datum/hud/user_hud = usr_is_living.hud_used
- if(compact)
- for(var/atom/movable/screen/perk/perk_on_hud as anything in perks_on_hud)
- perks_compacted += perk_on_hud
- user_hud.infodisplay -= perk_on_hud
- user_hud.show_hud(user_hud.hud_version)
- else
- for(var/atom/movable/screen/perk/perk_compacted as anything in perks_compacted)
- user_hud.infodisplay += perk_compacted
- perks_compacted -= perk_compacted
- user_hud.show_hud(user_hud.hud_version)
diff --git a/code/_onclick/hud/rendering/plane_masters/_plane_master.dm b/code/_onclick/hud/rendering/plane_masters/_plane_master.dm
index 02d1f0ca3b4..c1efa44f8a3 100644
--- a/code/_onclick/hud/rendering/plane_masters/_plane_master.dm
+++ b/code/_onclick/hud/rendering/plane_masters/_plane_master.dm
@@ -1,6 +1,3 @@
-// I hate this place
-INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
-
/atom/movable/screen/plane_master
screen_loc = "CENTER"
icon_state = "blank"
diff --git a/code/_onclick/hud/revenanthud.dm b/code/_onclick/hud/revenanthud.dm
index c47ea4c2418..49d89fb159e 100644
--- a/code/_onclick/hud/revenanthud.dm
+++ b/code/_onclick/hud/revenanthud.dm
@@ -1,14 +1,7 @@
/datum/hud/revenant
ui_style = 'icons/hud/screen_gen.dmi'
-/datum/hud/revenant/New(mob/owner)
- ..()
-
- pull_icon = new /atom/movable/screen/pull(null, src)
- pull_icon.icon = ui_style
- pull_icon.update_appearance()
- pull_icon.screen_loc = ui_living_pull
- static_inventory += pull_icon
-
- healths = new /atom/movable/screen/healths/revenant(null, src)
- infodisplay += healths
+/datum/hud/revenant/initialize_screen_objects()
+ . = ..()
+ add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style, ui_living_pull)
+ add_screen_object(/atom/movable/screen/healths/revenant, HUD_MOB_HEALTH, HUD_GROUP_INFO)
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index 498d58dccb2..53b146b5b03 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -1,184 +1,38 @@
-/atom/movable/screen/robot
- icon = 'icons/hud/screen_cyborg.dmi'
- mouse_over_pointer = MOUSE_HAND_POINTER
-
-/atom/movable/screen/robot/module
- name = "cyborg module"
- icon_state = "nomod"
-
-/atom/movable/screen/robot/Click(location, control, params)
- if(isobserver(usr))
- return TRUE
-
-/atom/movable/screen/robot/module/Click(location, control, params)
- . = ..()
- var/mob/living/silicon/robot/robot_owner = hud.mymob
- if(robot_owner.model.type == /obj/item/robot_model)
- if(.)
- return
- robot_owner.pick_model()
- return
- var/list/modifiers = params2list(params)
- if(robot_owner.module_active && !LAZYACCESS(modifiers, RIGHT_CLICK) && !.)
- robot_owner.uneq_active()
- return
-
- //observers can look at borg's inventories, so we ignore parent return value here, unlike everywhere else.
- if(usr.active_storage == robot_owner.model.atom_storage)
- robot_owner.model.atom_storage.hide_contents(usr)
- else
- robot_owner.model.atom_storage.open_storage(usr)
- return TRUE
-
-/atom/movable/screen/robot/module1
- name = "module1"
- icon_state = "inv1"
-
-/atom/movable/screen/robot/module1/Click()
- if(..())
- return
- var/mob/living/silicon/robot/R = usr
- R.toggle_module(1)
-
-/atom/movable/screen/robot/module2
- name = "module2"
- icon_state = "inv2"
-
-/atom/movable/screen/robot/module2/Click()
- if(..())
- return
- var/mob/living/silicon/robot/R = usr
- R.toggle_module(2)
-
-/atom/movable/screen/robot/module3
- name = "module3"
- icon_state = "inv3"
-
-/atom/movable/screen/robot/module3/Click()
- if(..())
- return
- var/mob/living/silicon/robot/R = usr
- R.toggle_module(3)
-
-/atom/movable/screen/robot/radio
- name = "radio"
- icon_state = "radio"
-
-/atom/movable/screen/robot/radio/Click()
- if(..())
- return
- var/mob/living/silicon/robot/R = usr
- R.radio.interact(R)
-
/datum/hud/robot
ui_style = 'icons/hud/screen_cyborg.dmi'
-/datum/hud/robot/New(mob/owner)
- ..()
+/datum/hud/robot/initialize_screen_objects()
+ . = ..()
// i, Robit
var/mob/living/silicon/robot/robit = mymob
- var/atom/movable/screen/using
+ add_screen_object(/atom/movable/screen/language_menu, HUD_MOB_LANGUAGE_MENU, HUD_GROUP_STATIC, ui_style, ui_borg_language_menu)
+ add_screen_object(/atom/movable/screen/navigate, HUD_MOB_NAVIGATE_MENU, HUD_GROUP_STATIC, ui_style, ui_borg_navigate_menu)
+ add_screen_object(/atom/movable/screen/memories, HUD_MOB_MEMORIES, HUD_GROUP_STATIC, ui_style, ui_borg_memories_menu)
+ add_screen_object(/atom/movable/screen/robot/radio, HUD_CYBORG_RADIO)
-// Language
- using = new/atom/movable/screen/language_menu(null, src)
- using.icon = ui_style
- using.screen_loc = ui_borg_language_menu
- static_inventory += using
+ for (var/i in BORG_CHOOSE_MODULE_ONE to BORG_CHOOSE_MODULE_THREE)
+ var/atom/movable/screen/robot/module_slot/module = add_screen_object(/atom/movable/screen/robot/module_slot, HUD_KEY_CYBORG_MODULE(i))
+ module.set_slot(i)
-// Navigation
- using = new /atom/movable/screen/navigate(null, src)
- using.icon = ui_style
- using.screen_loc = ui_borg_navigate_menu
- static_inventory += using
+ add_screen_object(/atom/movable/screen/robot/lamp, HUD_CYBORG_LAMP)
+ add_screen_object(/atom/movable/screen/ai/image_take, HUD_SILICON_TAKE_IMAGE, ui_loc = ui_borg_camera)
-// Memories
- using = new /atom/movable/screen/memories(null, src)
- using.icon = ui_style
- using.screen_loc = ui_borg_memories_menu
- static_inventory += using
-
-//Radio
- using = new /atom/movable/screen/robot/radio(null, src)
- using.screen_loc = ui_borg_radio
- static_inventory += using
-
-//Module select
- if(!robit.inv1)
- robit.inv1 = new /atom/movable/screen/robot/module1(null, src)
- robit.inv1.screen_loc = ui_inv1
- static_inventory += robit.inv1
-
- if(!robit.inv2)
- robit.inv2 = new /atom/movable/screen/robot/module2(null, src)
- robit.inv2.screen_loc = ui_inv2
- static_inventory += robit.inv2
-
- if(!robit.inv3)
- robit.inv3 = new /atom/movable/screen/robot/module3(null, src)
- robit.inv3.screen_loc = ui_inv3
- static_inventory += robit.inv3
-
-//End of module select
- using = new /atom/movable/screen/robot/lamp(null, src)
- using.screen_loc = ui_borg_lamp
- static_inventory += using
- robit.lampButton = using
- var/atom/movable/screen/robot/lamp/lampscreen = using
- lampscreen.robot = robit
-
-//Photography stuff
- using = new /atom/movable/screen/ai/image_take(null, src)
- using.screen_loc = ui_borg_camera
- static_inventory += using
-
-//Borg Integrated Tablet
- using = new /atom/movable/screen/robot/modpc(null, src)
- using.screen_loc = ui_borg_tablet
- static_inventory += using
- robit.interfaceButton = using
+ var/atom/movable/screen/robot/modpc/tablet = add_screen_object(/atom/movable/screen/robot/modpc, HUD_SILICON_TABLET, HUD_GROUP_STATIC)
if(robit.modularInterface)
// Just trust me
robit.modularInterface.vis_flags |= VIS_INHERIT_PLANE
- using.vis_contents += robit.modularInterface
- var/atom/movable/screen/robot/modpc/tabletbutton = using
- tabletbutton.robot = robit
+ tablet.vis_contents += robit.modularInterface
-//Alerts
- using = new /atom/movable/screen/robot/alerts(null, src)
- using.screen_loc = ui_borg_alerts
- static_inventory += using
+ add_screen_object(/atom/movable/screen/robot/alerts, HUD_SILICON_ALERTS)
+ add_screen_object(/atom/movable/screen/combattoggle/robot, HUD_MOB_INTENTS)
+ add_screen_object(/atom/movable/screen/floor_changer, HUD_MOB_FLOOR_CHANGER, HUD_GROUP_STATIC, ui_style, ui_borg_floor_changer)
+ add_screen_object(/atom/movable/screen/zone_sel/robot, HUD_MOB_ZONE_SELECTOR)
+ var/atom/movable/screen/robot/module/module = add_screen_object(/atom/movable/screen/robot/module, HUD_CYBORG_HANDS, ui_loc = ui_borg_module)
+ module.icon_state = robit.model ? robit.model.model_select_icon : "nomod"
- //Combat Mode
- action_intent = new /atom/movable/screen/combattoggle/robot(null, src)
- action_intent.icon = ui_style
- action_intent.screen_loc = ui_borg_intents
- static_inventory += action_intent
+ add_screen_object(/atom/movable/screen/healths/robot, HUD_MOB_HEALTH, HUD_GROUP_INFO)
- floor_change = new /atom/movable/screen/floor_changer(null, src)
- floor_change.icon = ui_style
- floor_change.screen_loc = ui_borg_floor_changer
- static_inventory += floor_change
-
-//Health
- healths = new /atom/movable/screen/healths/robot(null, src)
- infodisplay += healths
-
-//Installed Module
- robit.hands = new /atom/movable/screen/robot/module(null, src)
- robit.hands.icon_state = robit.model ? robit.model.model_select_icon : "nomod"
- robit.hands.screen_loc = ui_borg_module
- static_inventory += robit.hands
-
- pull_icon = new /atom/movable/screen/pull(null, src)
- pull_icon.icon = 'icons/hud/screen_cyborg.dmi'
- pull_icon.screen_loc = ui_borg_pull
- pull_icon.update_appearance()
- hotkeybuttons += pull_icon
-
-
- zone_select = new /atom/movable/screen/zone_sel/robot(null, src)
- zone_select.update_appearance()
- static_inventory += zone_select
+ add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_HOTKEYS, ui_style, ui_borg_pull)
/datum/hud/robot/persistent_inventory_update(mob/viewer)
if(!mymob)
@@ -186,74 +40,18 @@
var/mob/living/silicon/robot/R = mymob
var/mob/screenmob = viewer || R
-
- if(screenmob.hud_used)
- if(screenmob.hud_used.hud_shown)
- for(var/i in 1 to R.held_items.len)
- var/obj/item/I = R.held_items[i]
- if(I)
- switch(i)
- if(BORG_CHOOSE_MODULE_ONE)
- I.screen_loc = ui_inv1
- if(BORG_CHOOSE_MODULE_TWO)
- I.screen_loc = ui_inv2
- if(BORG_CHOOSE_MODULE_THREE)
- I.screen_loc = ui_inv3
- else
- return
- screenmob.client.screen += I
- else
- for(var/obj/item/I in R.held_items)
- screenmob.client.screen -= I
-
-/atom/movable/screen/robot/lamp
- name = "headlamp"
- icon_state = "lamp_off"
- base_icon_state = "lamp"
- var/mob/living/silicon/robot/robot
-
-/atom/movable/screen/robot/lamp/Click()
- . = ..()
- if(.)
+ if(!screenmob.hud_used)
return
- robot?.toggle_headlamp()
- update_appearance()
-/atom/movable/screen/robot/lamp/update_icon_state()
- icon_state = "[base_icon_state]_[robot?.lamp_enabled ? "on" : "off"]"
- return ..()
-
-/atom/movable/screen/robot/lamp/Destroy()
- if(robot)
- robot.lampButton = null
- robot = null
- return ..()
-
-/atom/movable/screen/robot/modpc
- name = "Modular Interface"
- icon_state = "template"
- var/mob/living/silicon/robot/robot
-
-/atom/movable/screen/robot/modpc/Click()
- . = ..()
- if(.)
+ if(!screenmob.hud_used.hud_shown)
+ for(var/obj/item/I in R.held_items)
+ screenmob.client.screen -= I
return
- robot.modularInterface?.interact(robot)
-/atom/movable/screen/robot/modpc/Destroy()
- if(robot)
- robot.interfaceButton = null
- robot = null
- return ..()
-
-/atom/movable/screen/robot/alerts
- name = "Alert Panel"
- icon = 'icons/hud/screen_ai.dmi'
- icon_state = "alerts"
-
-/atom/movable/screen/robot/alerts/Click()
- . = ..()
- if(.)
- return
- var/mob/living/silicon/robot/borgo = usr
- borgo.alert_control.ui_interact(borgo)
+ for(var/i in 1 to length(R.held_items))
+ var/obj/item/I = R.held_items[i]
+ if(!I)
+ continue
+ var/atom/movable/screen/robot/module_slot/slot = screen_objects[HUD_KEY_CYBORG_MODULE(i)]
+ I.screen_loc = slot.screen_loc
+ screenmob.client.screen += I
diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/screen_objects/action_button.dm
similarity index 97%
rename from code/_onclick/hud/action_button.dm
rename to code/_onclick/hud/screen_objects/action_button.dm
index 88508c11e47..0782aabd5c0 100644
--- a/code/_onclick/hud/action_button.dm
+++ b/code/_onclick/hud/screen_objects/action_button.dm
@@ -31,10 +31,13 @@
viewer?.client?.screen -= src
linked_action.viewers -= our_hud
viewer.update_action_buttons()
+ our_hud.screen_objects -= hud_key
+ our_hud.screen_groups?[hud_group_key] -= src
our_hud = null
linked_action = null
return ..()
+
/atom/movable/screen/movable/action_button/proc/can_use(mob/user)
if(isobserver(user))
var/mob/dead/observer/dead_mob = user
@@ -278,15 +281,17 @@
var/color_timer_id
/atom/movable/screen/button_palette/Destroy()
- if(our_hud)
+ if (our_hud)
our_hud.mymob?.canon_client?.screen -= src
- our_hud.toggle_palette = null
+ our_hud.screen_objects -= hud_key
+ our_hud.screen_groups?[hud_group_key] -= src
our_hud = null
return ..()
/atom/movable/screen/button_palette/Initialize(mapload, datum/hud/hud_owner)
. = ..()
update_appearance()
+ set_hud(hud_owner)
/atom/movable/screen/button_palette/proc/set_hud(datum/hud/our_hud)
src.our_hud = our_hud
@@ -419,6 +424,18 @@ GLOBAL_LIST_INIT(palette_removed_matrix, list(1.4,0,0,0, 0.7,0.4,0,0, 0.4,0,0.6,
var/scroll_direction = 0
var/datum/hud/our_hud
+/atom/movable/screen/palette_scroll/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ set_hud(hud_owner)
+
+/atom/movable/screen/palette_scroll/Destroy()
+ if (our_hud)
+ our_hud.mymob?.canon_client?.screen -= src
+ our_hud.screen_objects -= hud_key
+ our_hud.screen_groups?[hud_group_key] -= src
+ our_hud = null
+ return ..()
+
/atom/movable/screen/palette_scroll/proc/can_use(mob/user)
if (isobserver(user))
var/mob/dead/observer/O = user
@@ -458,26 +475,12 @@ GLOBAL_LIST_INIT(palette_removed_matrix, list(1.4,0,0,0, 0.7,0.4,0,0, 0.4,0,0.6,
icon_state = "scroll_down"
scroll_direction = 1
-/atom/movable/screen/palette_scroll/down/Destroy()
- if(our_hud)
- our_hud.mymob?.canon_client?.screen -= src
- our_hud.palette_down = null
- our_hud = null
- return ..()
-
/atom/movable/screen/palette_scroll/up
name = "Scroll Up"
desc = "Click on this to scroll the actions above up"
icon_state = "scroll_up"
scroll_direction = -1
-/atom/movable/screen/palette_scroll/up/Destroy()
- if(our_hud)
- our_hud.mymob?.canon_client?.screen -= src
- our_hud.palette_up = null
- our_hud = null
- return ..()
-
/// Exists so you have a place to put your buttons when you move them around
/atom/movable/screen/action_landing
name = "Button Space"
diff --git a/code/_onclick/hud/screen_objects/ai.dm b/code/_onclick/hud/screen_objects/ai.dm
new file mode 100644
index 00000000000..ffa18a01e68
--- /dev/null
+++ b/code/_onclick/hud/screen_objects/ai.dm
@@ -0,0 +1,250 @@
+/atom/movable/screen/ai
+ icon = 'icons/hud/screen_ai.dmi'
+ mouse_over_pointer = MOUSE_HAND_POINTER
+
+/atom/movable/screen/ai/Click()
+ if(isobserver(usr) || usr.incapacitated)
+ return TRUE
+
+/atom/movable/screen/ai/aicore
+ name = "AI core"
+ icon_state = "ai_core"
+ screen_loc = ui_ai_core
+
+/atom/movable/screen/ai/aicore/Click()
+ if(!isAI(usr))
+ return
+
+ var/mob/living/silicon/ai/AI = usr
+ AI.view_core()
+
+/atom/movable/screen/ai/camera_list
+ name = "Show Camera List"
+ icon_state = "camera"
+ screen_loc = ui_ai_camera_list
+
+/atom/movable/screen/ai/camera_list/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.show_camera_list()
+
+/atom/movable/screen/ai/camera_track
+ name = "Track With Camera"
+ icon_state = "track"
+ screen_loc = ui_ai_track_with_camera
+
+/atom/movable/screen/ai/camera_track/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.ai_camera_track()
+
+/atom/movable/screen/ai/camera_light
+ name = "Toggle Camera Light"
+ icon_state = "camera_light"
+ screen_loc = ui_ai_camera_light
+
+/atom/movable/screen/ai/camera_light/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.toggle_camera_light()
+
+/atom/movable/screen/ai/modpc
+ name = "Messenger"
+ icon_state = "pda_send"
+ screen_loc = ui_ai_mod_int
+
+/atom/movable/screen/ai/modpc/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.modularInterface?.interact(AI)
+
+/atom/movable/screen/ai/crew_monitor
+ name = "Crew Monitoring Console"
+ icon_state = "crew_monitor"
+ screen_loc = ui_ai_crew_monitor
+
+/atom/movable/screen/ai/crew_monitor/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ GLOB.crewmonitor.show(AI,AI)
+
+/atom/movable/screen/ai/crew_manifest
+ name = "Crew Manifest"
+ icon_state = "manifest"
+ screen_loc = ui_ai_crew_manifest
+
+/atom/movable/screen/ai/crew_manifest/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.ai_roster()
+
+/atom/movable/screen/ai/alerts
+ name = "Show Alerts"
+ icon_state = "alerts"
+ screen_loc = ui_ai_alerts
+
+/atom/movable/screen/ai/alerts/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.alert_control.ui_interact(AI)
+
+/atom/movable/screen/ai/announcement
+ name = "Make Vox Announcement"
+ icon_state = "announcement"
+ screen_loc = ui_ai_announcement
+
+/atom/movable/screen/ai/announcement/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.announcement()
+
+/atom/movable/screen/ai/call_shuttle
+ name = "Call Emergency Shuttle"
+ icon_state = "call_shuttle"
+ screen_loc = ui_ai_shuttle
+
+/atom/movable/screen/ai/call_shuttle/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.ai_call_shuttle()
+
+/atom/movable/screen/ai/state_laws
+ name = "State Laws"
+ icon_state = "state_laws"
+ screen_loc = ui_ai_state_laws
+
+/atom/movable/screen/ai/state_laws/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.checklaws()
+
+/atom/movable/screen/ai/image_take
+ name = "Take Image"
+ icon_state = "take_picture"
+ screen_loc = ui_ai_take_picture
+
+/atom/movable/screen/ai/image_take/Click()
+ if(..())
+ return
+ if(isAI(usr))
+ var/mob/living/silicon/ai/AI = usr
+ AI.aicamera.toggle_camera_mode(usr)
+ else if(iscyborg(usr))
+ var/mob/living/silicon/robot/R = usr
+ R.aicamera.toggle_camera_mode(usr)
+
+/atom/movable/screen/ai/image_view
+ name = "View Images"
+ icon_state = "view_images"
+ screen_loc = ui_ai_view_images
+
+/atom/movable/screen/ai/image_view/Click()
+ if(..())
+ return
+ if(isAI(usr))
+ var/mob/living/silicon/ai/AI = usr
+ AI.aicamera.viewpictures(usr)
+
+/atom/movable/screen/ai/sensors
+ name = "Sensor Augmentation"
+ icon_state = "ai_sensor"
+ screen_loc = ui_ai_sensor
+
+/atom/movable/screen/ai/sensors/Click()
+ if(..())
+ return
+ var/mob/living/silicon/S = usr
+ S.toggle_sensors()
+
+/atom/movable/screen/ai/multicam
+ name = "Multicamera Mode"
+ icon_state = "multicam"
+ screen_loc = ui_ai_multicam
+
+/atom/movable/screen/ai/multicam/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.toggle_multicam()
+
+/atom/movable/screen/ai/add_multicam
+ name = "New Camera"
+ icon_state = "new_cam"
+ screen_loc = ui_ai_add_multicam
+
+/atom/movable/screen/ai/add_multicam/Click()
+ if(..())
+ return
+ var/mob/living/silicon/ai/AI = usr
+ AI.drop_new_multicam()
+
+/atom/movable/screen/ai/floor_indicator
+ icon_state = "zindicator"
+ screen_loc = ui_ai_floor_indicator
+
+/atom/movable/screen/ai/floor_indicator/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ if(istype(hud_owner))
+ RegisterSignal(hud_owner, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(update_z))
+ update_z()
+
+/atom/movable/screen/ai/floor_indicator/proc/update_z(datum/hud/source)
+ SIGNAL_HANDLER
+ var/mob/living/silicon/ai/ai = get_mob() //if you use this for anyone else i will find you
+ if(isnull(ai))
+ return
+ var/turf/locturf = isturf(ai.loc) ? get_turf(ai.eyeobj) : get_turf(ai) //must be a var cuz error
+ var/ai_z = locturf.z
+ var/text = "Level
[ai_z]"
+ if(SSmapping.level_trait(ai_z, ZTRAIT_STATION))
+ text = "Floor
[ai_z - 1]"
+ else if (SSmapping.level_trait(ai_z, ZTRAIT_NOPHASE))
+ text = "ERROR"
+ maptext = MAPTEXT_TINY_UNICODE("[text]
")
+
+/atom/movable/screen/ai/go_up
+ name = "go up"
+ icon_state = "up"
+ screen_loc = ui_ai_godownup
+
+/atom/movable/screen/ai/go_up/Initialize(mapload)
+ . = ..()
+ register_context()
+
+/atom/movable/screen/ai/go_up/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = ..()
+ context[SCREENTIP_CONTEXT_LMB] = "Go up a floor"
+ return CONTEXTUAL_SCREENTIP_SET
+
+/atom/movable/screen/ai/go_up/Click(location,control,params)
+ var/mob/ai = get_mob() //the core
+ flick("uppressed",src)
+ if(!isturf(ai.loc) || usr != ai) //aicard and stuff
+ return
+ ai.up()
+
+/atom/movable/screen/ai/go_up/down
+ name = "go down"
+ icon_state = "down"
+
+/atom/movable/screen/ai/go_up/down/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = ..()
+ context[SCREENTIP_CONTEXT_LMB] = "Go down a floor"
+ return CONTEXTUAL_SCREENTIP_SET
+
+/atom/movable/screen/ai/go_up/down/Click(location,control,params)
+ var/mob/ai = get_mob() //the core
+ flick("downpressed",src)
+ if(!isturf(ai.loc) || usr != ai) //aicard and stuff
+ return
+ ai.down()
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/screen_objects/alert.dm
similarity index 100%
rename from code/_onclick/hud/alert.dm
rename to code/_onclick/hud/screen_objects/alert.dm
diff --git a/code/_onclick/hud/screen_objects/alien.dm b/code/_onclick/hud/screen_objects/alien.dm
new file mode 100644
index 00000000000..d99cdc55b35
--- /dev/null
+++ b/code/_onclick/hud/screen_objects/alien.dm
@@ -0,0 +1,24 @@
+/atom/movable/screen/alien
+ icon = 'icons/hud/screen_alien.dmi'
+
+/atom/movable/screen/alien/leap
+ name = "toggle leap"
+ icon_state = "leap_off"
+ screen_loc = ui_alien_storage_r
+
+/atom/movable/screen/alien/leap/Click()
+ if(!isalienhunter(usr))
+ return
+ var/mob/living/carbon/alien/adult/hunter/AH = usr
+ AH.toggle_leap()
+
+/atom/movable/screen/alien/plasma_display
+ name = "plasma stored"
+ icon_state = "power_display"
+ screen_loc = ui_alienplasmadisplay
+
+/atom/movable/screen/alien/alien_queen_finder
+ name = "queen sense"
+ desc = "Allows you to sense the general direction of your Queen."
+ icon_state = "queen_finder"
+ screen_loc = ui_alien_queen_finder
diff --git a/code/_onclick/hud/screen_objects/blob.dm b/code/_onclick/hud/screen_objects/blob.dm
new file mode 100644
index 00000000000..3f78d94854f
--- /dev/null
+++ b/code/_onclick/hud/screen_objects/blob.dm
@@ -0,0 +1,164 @@
+/atom/movable/screen/blob
+ icon = 'icons/hud/blob.dmi'
+ mouse_over_pointer = MOUSE_HAND_POINTER
+
+/atom/movable/screen/blob/MouseEntered(location,control,params)
+ . = ..()
+ openToolTip(usr,src,params,title = name,content = desc, theme = "blob")
+
+/atom/movable/screen/blob/MouseExited()
+ closeToolTip(usr)
+
+/atom/movable/screen/blob/jump_to_node
+ name = "Jump to Node"
+ desc = "Moves your camera to a selected blob node."
+ icon_state = "ui_tonode"
+ screen_loc = ui_inventory
+
+/atom/movable/screen/blob/jump_to_node/Click()
+ if(!isovermind(usr))
+ return FALSE
+ var/mob/eye/blob/blob = usr
+ blob.jump_to_node()
+
+/atom/movable/screen/blob/jump_to_core
+ name = "Jump to Core"
+ desc = "Moves your camera to your blob core."
+ icon_state = "ui_tocore"
+ screen_loc = ui_zonesel
+
+/atom/movable/screen/blob/jump_to_core/MouseEntered(location,control,params)
+ if(hud?.mymob && isovermind(hud.mymob))
+ var/mob/eye/blob/B = hud.mymob
+ if(!B.placed)
+ name = "Place Blob Core"
+ desc = "Attempt to place your blob core at this location."
+ else
+ name = initial(name)
+ desc = initial(desc)
+ return ..()
+
+/atom/movable/screen/blob/jump_to_core/Click()
+ if(!isovermind(usr))
+ return FALSE
+ var/mob/eye/blob/blob = usr
+ if(!blob.placed)
+ blob.place_blob_core(BLOB_NORMAL_PLACEMENT)
+ blob.transport_core()
+
+/atom/movable/screen/blob/blobbernaut
+ // Name and description get given their proper values on Initialize()
+ name = "Produce Blobbernaut (ERROR)"
+ desc = "Produces a strong, smart blobbernaut from a factory blob for (ERROR) resources.
The factory blob used will become fragile and unable to produce spores."
+ icon_state = "ui_blobbernaut"
+ screen_loc = ui_belt
+
+/atom/movable/screen/blob/blobbernaut/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ name = "Produce Blobbernaut ([BLOBMOB_BLOBBERNAUT_RESOURCE_COST])"
+ desc = "Produces a strong, smart blobbernaut from a factory blob for [BLOBMOB_BLOBBERNAUT_RESOURCE_COST] resources.
The factory blob used will become fragile and unable to produce spores."
+
+/atom/movable/screen/blob/blobbernaut/Click()
+ if(!isovermind(usr))
+ return FALSE
+ var/mob/eye/blob/blob = usr
+ blob.create_blobbernaut()
+
+/atom/movable/screen/blob/resource_blob
+ // Name and description get given their proper values on Initialize()
+ name = "Produce Resource Blob (ERROR)"
+ desc = "Produces a resource blob for ERROR resources.
Resource blobs will give you resources every few seconds."
+ icon_state = "ui_resource"
+ screen_loc = ui_back
+
+/atom/movable/screen/blob/resource_blob/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ name = "Produce Resource Blob ([BLOB_STRUCTURE_RESOURCE_COST])"
+ desc = "Produces a resource blob for [BLOB_STRUCTURE_RESOURCE_COST] resources.
Resource blobs will give you resources every few seconds."
+
+/atom/movable/screen/blob/resource_blob/Click()
+ if(!isovermind(usr))
+ return FALSE
+ var/mob/eye/blob/blob = usr
+ blob.create_special(BLOB_STRUCTURE_RESOURCE_COST, /obj/structure/blob/special/resource, BLOB_RESOURCE_MIN_DISTANCE, TRUE)
+
+/atom/movable/screen/blob/node_blob
+ // Name and description get given their proper values on Initialize()
+ name = "Produce Node Blob (ERROR)"
+ desc = "Produces a node blob for ERROR resources.
Node blobs will expand and activate nearby resource and factory blobs."
+ icon_state = "ui_node"
+
+/atom/movable/screen/blob/node_blob/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ name = "Produce Node Blob ([BLOB_STRUCTURE_NODE_COST])"
+ desc = "Produces a node blob for [BLOB_STRUCTURE_NODE_COST] resources.
Node blobs will expand and activate nearby resource and factory blobs."
+
+/atom/movable/screen/blob/node_blob/Click()
+ if(!isovermind(usr))
+ return FALSE
+ var/mob/eye/blob/blob = usr
+ blob.create_special(BLOB_STRUCTURE_NODE_COST, /obj/structure/blob/special/node, BLOB_NODE_MIN_DISTANCE, FALSE)
+
+/atom/movable/screen/blob/factory_blob
+ // Name and description get given their proper values on Initialize()
+ name = "Produce Factory Blob (ERROR)"
+ desc = "Produces a factory blob for ERROR resources.
Factory blobs will produce spores every few seconds."
+ icon_state = "ui_factory"
+
+/atom/movable/screen/blob/factory_blob/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ name = "Produce Factory Blob ([BLOB_STRUCTURE_FACTORY_COST])"
+ desc = "Produces a factory blob for [BLOB_STRUCTURE_FACTORY_COST] resources.
Factory blobs will produce spores every few seconds."
+
+/atom/movable/screen/blob/factory_blob/Click()
+ if(!isovermind(usr))
+ return FALSE
+ var/mob/eye/blob/blob = usr
+ blob.create_special(BLOB_STRUCTURE_FACTORY_COST, /obj/structure/blob/special/factory, BLOB_FACTORY_MIN_DISTANCE, TRUE)
+
+/atom/movable/screen/blob/readapt_strain
+ // Description gets given its proper values on Initialize()
+ name = "Readapt Strain"
+ desc = "Allows you to choose a new strain from ERROR random choices for ERROR resources."
+ icon_state = "ui_chemswap"
+ screen_loc = ui_storage1
+
+/atom/movable/screen/blob/readapt_strain/MouseEntered(location,control,params)
+ if(hud?.mymob && isovermind(hud.mymob))
+ var/mob/eye/blob/B = hud.mymob
+ if(B.free_strain_rerolls)
+ name = "[initial(name)] (FREE)"
+ desc = "Randomly rerolls your strain for free."
+ else
+ name = "[initial(name)] ([BLOB_POWER_REROLL_COST])"
+ desc = "Allows you to choose a new strain from [BLOB_POWER_REROLL_CHOICES] random choices for [BLOB_POWER_REROLL_COST] resources."
+ return ..()
+
+/atom/movable/screen/blob/readapt_strain/Click()
+ if(isovermind(usr))
+ var/mob/eye/blob/B = usr
+ B.strain_reroll()
+
+/atom/movable/screen/blob/relocate_core
+ // Name and description get given their proper values on Initialize()
+ name = "Relocate Core (ERROR)"
+ desc = "Swaps a node and your core for ERROR resources."
+ icon_state = "ui_swap"
+ screen_loc = ui_storage2
+
+/atom/movable/screen/blob/relocate_core/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ name = "Relocate Core ([BLOB_POWER_RELOCATE_COST])"
+ desc = "Swaps a node and your core for [BLOB_POWER_RELOCATE_COST] resources."
+
+/atom/movable/screen/blob/relocate_core/Click()
+ if(isovermind(usr))
+ var/mob/eye/blob/B = usr
+ B.relocate_core()
+
+/atom/movable/screen/blob/blob_power
+ name = "blob power"
+ icon_state = "block"
+ screen_loc = ui_health
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ plane = ABOVE_HUD_PLANE
diff --git a/code/_onclick/hud/credits.dm b/code/_onclick/hud/screen_objects/credits.dm
similarity index 100%
rename from code/_onclick/hud/credits.dm
rename to code/_onclick/hud/screen_objects/credits.dm
diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/screen_objects/fullscreen.dm
similarity index 100%
rename from code/_onclick/hud/fullscreen.dm
rename to code/_onclick/hud/screen_objects/fullscreen.dm
diff --git a/code/_onclick/hud/screen_objects/ghost.dm b/code/_onclick/hud/screen_objects/ghost.dm
new file mode 100644
index 00000000000..532817e558a
--- /dev/null
+++ b/code/_onclick/hud/screen_objects/ghost.dm
@@ -0,0 +1,149 @@
+/atom/movable/screen/ghost
+ icon = 'icons/hud/screen_ghost.dmi'
+ mouse_over_pointer = MOUSE_HAND_POINTER
+
+/atom/movable/screen/ghost/MouseEntered(location, control, params)
+ . = ..()
+ flick(icon_state + "_anim", src)
+
+/atom/movable/screen/ghost/spawners_menu
+ name = "Spawners menu"
+ icon_state = "spawners"
+ screen_loc = ui_ghost_spawners_menu
+
+/atom/movable/screen/ghost/spawners_menu/Click()
+ var/mob/dead/observer/observer = usr
+ observer.open_spawners_menu()
+
+/atom/movable/screen/ghost/orbit
+ name = "Orbit"
+ icon_state = "orbit"
+ screen_loc = ui_ghost_orbit
+
+/atom/movable/screen/ghost/orbit/Click()
+ GLOB.orbit_menu.show(usr)
+
+/atom/movable/screen/ghost/reenter_corpse
+ name = "Reenter corpse"
+ icon_state = "reenter_corpse"
+ screen_loc = ui_ghost_reenter_corpse
+
+/atom/movable/screen/ghost/reenter_corpse/Click()
+ var/mob/dead/observer/G = usr
+ G.reenter_corpse()
+
+/atom/movable/screen/ghost/dnr
+ name = "Do Not Resuscitate"
+ icon_state = "dnr"
+ screen_loc = ui_ghost_dnr
+
+/atom/movable/screen/ghost/dnr/Click()
+ var/mob/dead/observer/dnring = usr
+ dnring.do_not_resuscitate()
+
+/atom/movable/screen/ghost/teleport
+ name = "Teleport"
+ icon_state = "teleport"
+ screen_loc = ui_ghost_teleport
+
+/atom/movable/screen/ghost/teleport/Click()
+ var/mob/dead/observer/G = usr
+ G.dead_tele()
+
+/atom/movable/screen/ghost/settings
+ name = "Ghost Settings"
+ icon_state = "settings"
+ screen_loc = ui_ghost_settings
+
+/atom/movable/screen/ghost/settings/MouseEntered(location, control, params)
+ . = ..()
+ flick(icon_state + "_anim", src)
+
+/atom/movable/screen/ghost/settings/Click()
+ GLOB.ghost_menu.ui_interact(usr)
+
+/atom/movable/screen/ghost/minigames_menu
+ name ="Minigames"
+ icon_state = "minigames"
+ screen_loc = ui_ghost_minigames
+
+/atom/movable/screen/ghost/minigames_menu/Click()
+ var/mob/dead/observer/observer = usr
+ observer.open_minigames_menu()
+
+/atom/movable/screen/ghost/hudbox
+ icon_state = "smallbox"
+ abstract_type = /atom/movable/screen/ghost/hudbox
+ /// Icon state used for the overlay representing this hudbox
+ var/hud_icon_state
+ /// The flag this hudbox toggles
+ var/relevant_flag
+
+/atom/movable/screen/ghost/hudbox/update_overlays()
+ . = ..()
+ . += hud_icon_state
+
+/atom/movable/screen/ghost/hudbox/update_icon_state()
+ . = ..()
+ var/mob/dead/observer/observer = hud?.mymob
+ if(!istype(observer))
+ return
+
+ icon_state = "smallbox[is_active(observer) ? "_active" : ""]"
+
+/atom/movable/screen/ghost/hudbox/proc/is_active(mob/dead/observer/observer)
+ return (observer.ghost_hud_flags & relevant_flag)
+
+/atom/movable/screen/ghost/hudbox/Click(location, control, params)
+ var/mob/dead/observer/observer = usr
+ switch(relevant_flag)
+ if(GHOST_DARKNESS_LEVEL)
+ observer.toggle_darkness()
+ if(GHOST_TRAY)
+ observer.tray_view()
+ else
+ observer.toggle_ghost_hud_flag(relevant_flag)
+
+ update_appearance(UPDATE_ICON)
+
+/atom/movable/screen/ghost/hudbox/health_scanner
+ name = "Health Scanner"
+ desc = "Toggles your ability to health scan mobs on click."
+ hud_icon_state = "health_vision"
+ relevant_flag = GHOST_HEALTH
+
+/atom/movable/screen/ghost/hudbox/chem_scanner
+ name = "Chem Scanner"
+ desc = "Toggles your ability to chemical scan mobs on click."
+ hud_icon_state = "chem_vision"
+ relevant_flag = GHOST_CHEM
+
+/atom/movable/screen/ghost/hudbox/gas_scanner
+ name = "Gas Scanner"
+ desc = "Toggles your ability to gas scan objects on click."
+ hud_icon_state = "atmos_vision"
+ relevant_flag = GHOST_GAS
+
+/atom/movable/screen/ghost/hudbox/ghost
+ name = "Ghost Vision"
+ desc = "Toggles whether you can see other ghosts."
+ hud_icon_state = "ghost_vision"
+ relevant_flag = GHOST_VISION
+
+/atom/movable/screen/ghost/hudbox/data_huds
+ name = "Data HUDs"
+ desc = "Toggles the display of data HUDs (health, security, diagnostics, etc)."
+ hud_icon_state = "data_vision"
+ relevant_flag = GHOST_DATA_HUDS
+
+/atom/movable/screen/ghost/hudbox/tray_icon
+ name = "Tray View"
+ desc = "Shows the t-ray view of the area around your ghost."
+ hud_icon_state = "tray_vision"
+ relevant_flag = GHOST_TRAY
+
+/atom/movable/screen/ghost/hudbox/darkness_level
+ name = "Darkness Level"
+ desc = "Cycles through different darkness levels for ghost vision."
+ hud_icon_state = "darkness_vision"
+ relevant_flag = GHOST_DARKNESS_LEVEL
diff --git a/code/_onclick/hud/screen_objects/guardian.dm b/code/_onclick/hud/screen_objects/guardian.dm
new file mode 100644
index 00000000000..41282bc45ed
--- /dev/null
+++ b/code/_onclick/hud/screen_objects/guardian.dm
@@ -0,0 +1,68 @@
+/atom/movable/screen/guardian
+ icon = 'icons/hud/guardian.dmi'
+ mouse_over_pointer = MOUSE_HAND_POINTER
+
+/atom/movable/screen/guardian/manifest
+ name = "Manifest"
+ desc = "Spring forth into battle!"
+ icon_state = "manifest"
+
+/atom/movable/screen/guardian/manifest/Click()
+ if(isguardian(usr))
+ var/mob/living/basic/guardian/user = usr
+ user.manifest()
+
+/atom/movable/screen/guardian/recall
+ name = "Recall"
+ desc = "Return to your user."
+ icon_state = "recall"
+
+/atom/movable/screen/guardian/recall/Click()
+ if(isguardian(usr))
+ var/mob/living/basic/guardian/user = usr
+ user.recall()
+
+/atom/movable/screen/guardian/toggle_mode
+ name = "Toggle Mode"
+ desc = "Switch between ability modes."
+ icon_state = "toggle"
+
+/atom/movable/screen/guardian/toggle_mode/Click()
+ if(isguardian(usr))
+ var/mob/living/basic/guardian/user = usr
+ user.toggle_modes()
+
+/atom/movable/screen/guardian/toggle_mode/inactive
+ icon_state = "notoggle" //greyed out so it doesn't look like it'll work
+
+/atom/movable/screen/guardian/toggle_mode/assassin
+ name = "Toggle Stealth"
+ desc = "Enter or exit stealth."
+ icon_state = "stealth"
+
+/atom/movable/screen/guardian/toggle_mode/gases
+ name = "Toggle Gas"
+ desc = "Switch between possible gases."
+ icon_state = "gases"
+
+/atom/movable/screen/guardian/communicate
+ name = "Communicate"
+ desc = "Communicate telepathically with your user."
+ icon_state = "communicate"
+ screen_loc = ui_back
+
+/atom/movable/screen/guardian/communicate/Click()
+ if(isguardian(usr))
+ var/mob/living/basic/guardian/user = usr
+ user.communicate()
+
+/atom/movable/screen/guardian/toggle_light
+ name = "Toggle Light"
+ desc = "Glow like star dust."
+ icon_state = "light"
+ screen_loc = ui_inventory
+
+/atom/movable/screen/guardian/toggle_light/Click()
+ if(isguardian(usr))
+ var/mob/living/basic/guardian/user = usr
+ user.toggle_light()
diff --git a/code/_onclick/hud/screen_objects/human.dm b/code/_onclick/hud/screen_objects/human.dm
new file mode 100644
index 00000000000..b69ceb2143e
--- /dev/null
+++ b/code/_onclick/hud/screen_objects/human.dm
@@ -0,0 +1,77 @@
+/atom/movable/screen/human
+ icon = 'icons/hud/screen_midnight.dmi'
+
+/atom/movable/screen/human/toggle
+ name = "toggle"
+ icon_state = "toggle"
+ base_icon_state = "toggle"
+ mouse_over_pointer = MOUSE_HAND_POINTER
+ screen_loc = ui_inventory
+
+/atom/movable/screen/human/toggle/Click()
+ var/mob/targetmob = usr
+
+ if(isobserver(usr))
+ if(ishuman(usr.client.eye) && (usr.client.eye != usr))
+ var/mob/M = usr.client.eye
+ targetmob = M
+
+ if(usr.hud_used.inventory_shown && targetmob.hud_used)
+ usr.hud_used.inventory_shown = FALSE
+ usr.client.screen -= targetmob.hud_used.screen_groups[HUD_GROUP_TOGGLEABLE_INVENTORY]
+ else
+ usr.hud_used.inventory_shown = TRUE
+ usr.client.screen += targetmob.hud_used.screen_groups[HUD_GROUP_TOGGLEABLE_INVENTORY]
+
+ targetmob.hud_used.hidden_inventory_update(usr)
+ update_appearance()
+
+/atom/movable/screen/human/toggle/update_icon_state()
+ icon_state = "[base_icon_state][hud?.inventory_shown ? "_active" : ""]"
+ return ..()
+
+/atom/movable/screen/ling
+ icon = 'icons/hud/screen_changeling.dmi'
+
+/atom/movable/screen/ling/chems
+ name = "chemical storage"
+ icon_state = "power_display"
+ screen_loc = ui_lingchemdisplay
+ ///Boolean on whether a mouse is being hovered over us right now.
+ var/hovering = FALSE
+
+/atom/movable/screen/ling/chems/Click(location, control, params)
+ . = ..()
+ to_chat(usr, span_notice("Shows you how many chemicals you have. While hovering over this, it will show the max amount of chemicals you can hold."))
+
+/atom/movable/screen/ling/chems/MouseEntered(location,control,params)
+ if(usr != get_mob())
+ return
+ var/datum/antagonist/changeling/antagonist_datum = IS_CHANGELING(hud.mymob)
+ if(!antagonist_datum)
+ return
+ . = ..()
+ hovering = TRUE
+ antagonist_datum.update_chemical_hud()
+
+/atom/movable/screen/ling/chems/MouseExited(location, control, params)
+ if(usr != get_mob())
+ return
+ var/datum/antagonist/changeling/antagonist_datum = IS_CHANGELING(hud.mymob)
+ if(!antagonist_datum)
+ return
+ . = ..()
+ hovering = FALSE
+ antagonist_datum.update_chemical_hud(antagonist_datum.chem_charges)
+
+/atom/movable/screen/ling/sting
+ name = "current sting"
+ screen_loc = ui_lingstingdisplay
+ invisibility = INVISIBILITY_ABSTRACT
+ mouse_over_pointer = MOUSE_HAND_POINTER
+
+/atom/movable/screen/ling/sting/Click()
+ if(isobserver(usr))
+ return
+ var/mob/living/carbon/carbon_user = usr
+ carbon_user.unset_sting()
diff --git a/code/_onclick/hud/map_popups.dm b/code/_onclick/hud/screen_objects/map_popups.dm
similarity index 100%
rename from code/_onclick/hud/map_popups.dm
rename to code/_onclick/hud/screen_objects/map_popups.dm
diff --git a/code/_onclick/hud/map_view.dm b/code/_onclick/hud/screen_objects/map_view.dm
similarity index 100%
rename from code/_onclick/hud/map_view.dm
rename to code/_onclick/hud/screen_objects/map_view.dm
diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/screen_objects/movable_screen_objects.dm
similarity index 100%
rename from code/_onclick/hud/movable_screen_objects.dm
rename to code/_onclick/hud/screen_objects/movable_screen_objects.dm
diff --git a/code/_onclick/hud/screen_objects/new_player.dm b/code/_onclick/hud/screen_objects/new_player.dm
new file mode 100644
index 00000000000..5a17abfc5d9
--- /dev/null
+++ b/code/_onclick/hud/screen_objects/new_player.dm
@@ -0,0 +1,724 @@
+#define SHUTTER_MOVEMENT_DURATION 0.4 SECONDS
+#define SHUTTER_WAIT_DURATION 0.2 SECONDS
+
+/atom/movable/screen/lobby
+ plane = SPLASHSCREEN_PLANE
+ layer = LOBBY_MENU_LAYER
+ screen_loc = "TOP,CENTER"
+ /// Whether this HUD element can be hidden from the client's "screen" (moved off-screen) or not
+ var/always_shown = FALSE
+ /// If true we will create this button every time the HUD is generated
+ var/always_available = TRUE
+
+///Set the HUD in New, as lobby screens are made before Atoms are Initialized.
+/atom/movable/screen/lobby/New(loc, datum/hud/our_hud, ...)
+ set_new_hud(our_hud)
+ return ..()
+
+///Run sleeping actions after initialize
+/atom/movable/screen/lobby/proc/SlowInit()
+ return
+
+///Animates moving the button off-screen
+/atom/movable/screen/lobby/proc/collapse_button()
+ SIGNAL_HANDLER
+ //wait for the shutter to come down
+ animate(src, transform = transform, time = SHUTTER_MOVEMENT_DURATION + SHUTTER_WAIT_DURATION)
+ //then pull the buttons up with the shutter
+ animate(transform = transform.Translate(x = 0, y = 146), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_IN)
+
+///Animates moving the button back into place
+/atom/movable/screen/lobby/proc/expand_button()
+ SIGNAL_HANDLER
+ //the buttons are off-screen, so we sync them up to come down with the shutter
+ animate(src, transform = matrix(), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_OUT)
+
+/atom/movable/screen/lobby/background
+ icon = 'icons/hud/lobby/background.dmi'
+ icon_state = "background"
+ layer = LOBBY_BACKGROUND_LAYER
+ screen_loc = "TOP,CENTER:-61"
+
+/atom/movable/screen/lobby/button
+ mouse_over_pointer = MOUSE_HAND_POINTER
+ ///Is the button currently enabled?
+ VAR_PROTECTED/enabled = TRUE
+ ///Is the button currently being hovered over with the mouse?
+ var/highlighted = FALSE
+ ///Should this button play the select sound?
+ var/select_sound_play = TRUE
+
+/atom/movable/screen/lobby/button/Click(location, control, params)
+ if(usr != get_mob())
+ return
+
+ if(!usr.client || usr.client.interviewee)
+ return
+
+ . = ..()
+
+ if(!enabled)
+ return
+ flick("[base_icon_state]_pressed", src)
+ if(select_sound_play)
+ var/sound/ui_select_sound = sound('sound/misc/menu/ui_select1.ogg')
+ ui_select_sound.frequency = get_rand_frequency_low_range()
+ SEND_SOUND(hud.mymob, ui_select_sound)
+ update_appearance(UPDATE_ICON)
+ return TRUE
+
+/atom/movable/screen/lobby/button/MouseEntered(location,control,params)
+ if(usr != get_mob())
+ return
+
+ if(!usr.client || usr.client.interviewee)
+ return
+
+ . = ..()
+ highlighted = TRUE
+ update_appearance(UPDATE_ICON)
+
+/atom/movable/screen/lobby/button/MouseExited()
+ if(usr != get_mob())
+ return
+
+ if(!usr.client || usr.client.interviewee)
+ return
+
+ . = ..()
+ highlighted = FALSE
+ update_appearance(UPDATE_ICON)
+
+/atom/movable/screen/lobby/button/update_icon(updates)
+ . = ..()
+ if(!enabled)
+ icon_state = "[base_icon_state]_disabled"
+ return
+ if(highlighted)
+ icon_state = "[base_icon_state]_highlighted"
+ return
+ icon_state = base_icon_state
+
+///Updates the button's status: TRUE to enable interaction with the button, FALSE to disable
+/atom/movable/screen/lobby/button/proc/set_button_status(status)
+ if(status == enabled)
+ return FALSE
+ enabled = status
+ update_appearance(UPDATE_ICON)
+ mouse_over_pointer = enabled ? MOUSE_HAND_POINTER : MOUSE_INACTIVE_POINTER
+ return TRUE
+
+///Prefs menu
+/atom/movable/screen/lobby/button/character_setup
+ name = "View Character Setup"
+ screen_loc = "TOP:-70,CENTER:-54"
+ icon = 'icons/hud/lobby/character_setup.dmi'
+ icon_state = "character_setup_disabled"
+ base_icon_state = "character_setup"
+ enabled = FALSE
+
+/atom/movable/screen/lobby/button/character_setup/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ // We need IconForge and the assets to be ready before allowing the menu to open
+ if(SSearly_assets.initialized == INITIALIZATION_INNEW_REGULAR || SSatoms.initialized == INITIALIZATION_INNEW_REGULAR)
+ flick("[base_icon_state]_enabled", src)
+ set_button_status(TRUE)
+ else
+ set_button_status(FALSE)
+ RegisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(enable_character_setup))
+ RegisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(enable_character_setup))
+
+/atom/movable/screen/lobby/button/character_setup/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+
+ var/datum/preferences/preferences = hud.mymob.canon_client.prefs
+ preferences.current_window = PREFERENCE_TAB_CHARACTER_PREFERENCES
+ preferences.update_static_data(usr)
+ preferences.ui_interact(usr)
+
+/atom/movable/screen/lobby/button/character_setup/proc/enable_character_setup()
+ SIGNAL_HANDLER
+ flick("[base_icon_state]_enabled", src)
+ set_button_status(TRUE)
+ UnregisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE)
+ UnregisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE)
+
+///Button that appears before the game has started
+/atom/movable/screen/lobby/button/ready
+ name = "Toggle Readiness"
+ screen_loc = "TOP:-8,CENTER:-65"
+ icon = 'icons/hud/lobby/ready.dmi'
+ icon_state = "not_ready"
+ base_icon_state = "not_ready"
+
+/atom/movable/screen/lobby/button/ready/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ switch(SSticker.current_state)
+ if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(hide_ready_button))
+ if(GAME_STATE_SETTING_UP)
+ set_button_status(FALSE)
+ RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(show_ready_button))
+ else
+ set_button_status(FALSE)
+
+/atom/movable/screen/lobby/button/ready/proc/hide_ready_button()
+ SIGNAL_HANDLER
+ set_button_status(FALSE)
+ UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(show_ready_button))
+
+/atom/movable/screen/lobby/button/ready/proc/show_ready_button()
+ SIGNAL_HANDLER
+ set_button_status(TRUE)
+ UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(hide_ready_button))
+
+/atom/movable/screen/lobby/button/ready/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+ var/mob/dead/new_player/new_player = hud.mymob
+
+ // switch based on the user, if they aren't ready then we change them to ready, and vice versa
+ if(new_player.ready == PLAYER_NOT_READY)
+ new_player.auto_deadmin_on_ready_or_latejoin()
+ new_player.ready = PLAYER_READY_TO_PLAY
+ base_icon_state = "ready"
+ else
+ new_player.ready = PLAYER_NOT_READY
+ base_icon_state = "not_ready"
+
+ update_appearance(UPDATE_ICON)
+ SEND_SIGNAL(hud, COMSIG_HUD_PLAYER_READY_TOGGLE)
+
+///Shown when the game has started
+/atom/movable/screen/lobby/button/join
+ name = "Join Game"
+ screen_loc = "TOP:-13,CENTER:-58"
+ icon = 'icons/hud/lobby/join.dmi'
+ icon_state = "" //Default to not visible
+ base_icon_state = "join_game"
+ enabled = null // set in init
+
+/atom/movable/screen/lobby/button/join/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ switch(SSticker.current_state)
+ if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
+ set_button_status(FALSE)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(show_join_button))
+ if(GAME_STATE_SETTING_UP)
+ set_button_status(TRUE)
+ RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(hide_join_button))
+ else
+ set_button_status(TRUE)
+
+/atom/movable/screen/lobby/button/join/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+
+ if(!SSticker?.IsRoundInProgress())
+ to_chat(hud.mymob, span_boldwarning("The round is either not ready, or has already finished..."))
+ return
+
+ //Determines Relevent Population Cap
+ var/relevant_cap
+ var/hard_popcap = CONFIG_GET(number/hard_popcap)
+ var/extreme_popcap = CONFIG_GET(number/extreme_popcap)
+ if(hard_popcap && extreme_popcap)
+ relevant_cap = min(hard_popcap, extreme_popcap)
+ else
+ relevant_cap = max(hard_popcap, extreme_popcap)
+
+ var/mob/dead/new_player/new_player = hud.mymob
+
+ if(SSticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(new_player.key) in GLOB.admin_datums)))
+ to_chat(new_player, span_danger("[CONFIG_GET(string/hard_popcap_message)]"))
+
+ var/queue_position = SSticker.queued_players.Find(new_player)
+ if(queue_position == 1)
+ to_chat(new_player, span_notice("You are next in line to join the game. You will be notified when a slot opens up."))
+ else if(queue_position)
+ to_chat(new_player, span_notice("There are [queue_position-1] players in front of you in the queue to join the game."))
+ else
+ SSticker.queued_players += new_player
+ to_chat(new_player, span_notice("You have been added to the queue to join the game. Your position in queue is [SSticker.queued_players.len]."))
+ return
+
+ new_player.auto_deadmin_on_ready_or_latejoin()
+
+ if(!LAZYACCESS(params2list(params), CTRL_CLICK))
+ GLOB.latejoin_menu.ui_interact(new_player)
+ else
+ to_chat(new_player, span_warning("Opening emergency fallback late join menu! If THIS doesn't show, ahelp immediately!"))
+ GLOB.latejoin_menu.fallback_ui(new_player)
+
+
+/atom/movable/screen/lobby/button/join/proc/show_join_button()
+ SIGNAL_HANDLER
+ set_button_status(TRUE)
+ UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(hide_join_button))
+
+/atom/movable/screen/lobby/button/join/proc/hide_join_button()
+ SIGNAL_HANDLER
+ set_button_status(FALSE)
+ UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(show_join_button))
+
+/atom/movable/screen/lobby/button/observe
+ name = "Observe"
+ screen_loc = "TOP:-40,CENTER:-54"
+ icon = 'icons/hud/lobby/observe.dmi'
+ icon_state = "observe_disabled"
+ base_icon_state = "observe"
+ enabled = null // set in init
+
+/atom/movable/screen/lobby/button/observe/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ if(SSticker.current_state > GAME_STATE_STARTUP)
+ set_button_status(TRUE)
+ else
+ set_button_status(FALSE)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_PREGAME, PROC_REF(enable_observing))
+
+/atom/movable/screen/lobby/button/observe/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+ var/mob/dead/new_player/new_player = hud.mymob
+ new_player.make_me_an_observer()
+
+/atom/movable/screen/lobby/button/observe/proc/enable_observing()
+ SIGNAL_HANDLER
+ flick("[base_icon_state]_enabled", src)
+ set_button_status(TRUE)
+ UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_PREGAME)
+
+//Subtype the bottom buttons away so the collapse/expand shutter goes behind them
+/atom/movable/screen/lobby/button/bottom
+ layer = LOBBY_BOTTOM_BUTTON_LAYER
+ icon = 'icons/hud/lobby/bottom_buttons.dmi'
+
+/atom/movable/screen/lobby/button/bottom/settings
+ name = "View Game Preferences"
+ icon_state = "settings_disabled"
+ base_icon_state = "settings"
+ screen_loc = "TOP:-122,CENTER:+29"
+ enabled = FALSE
+
+/atom/movable/screen/lobby/button/bottom/settings/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ // We need IconForge and the assets to be ready before allowing the menu to open
+ if(SSearly_assets.initialized == INITIALIZATION_INNEW_REGULAR || SSatoms.initialized == INITIALIZATION_INNEW_REGULAR)
+ set_button_status(TRUE)
+ else
+ set_button_status(FALSE)
+ RegisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(enable_settings))
+ RegisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(enable_settings))
+
+/atom/movable/screen/lobby/button/bottom/settings/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+
+ var/datum/preferences/preferences = hud.mymob.canon_client.prefs
+ preferences.current_window = PREFERENCE_TAB_GAME_PREFERENCES
+ preferences.update_static_data(usr)
+ preferences.ui_interact(usr)
+
+/atom/movable/screen/lobby/button/bottom/settings/proc/enable_settings()
+ SIGNAL_HANDLER
+ set_button_status(TRUE)
+ UnregisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE)
+ UnregisterSignal(SSatoms, COMSIG_SUBSYSTEM_POST_INITIALIZE)
+
+/atom/movable/screen/lobby/button/bottom/changelog_button
+ name = "View Changelog"
+ icon_state = "changelog"
+ base_icon_state = "changelog"
+ screen_loc ="TOP:-122,CENTER:+57"
+
+/atom/movable/screen/lobby/button/bottom/changelog_button/Click(location, control, params)
+ . = ..()
+ usr.client?.changelog()
+
+/atom/movable/screen/lobby/button/bottom/crew_manifest
+ name = "View Crew Manifest"
+ icon_state = "crew_manifest"
+ base_icon_state = "crew_manifest"
+ screen_loc = "TOP:-122,CENTER:+2"
+
+/atom/movable/screen/lobby/button/bottom/crew_manifest/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+ var/mob/dead/new_player/new_player = hud.mymob
+ new_player.ViewManifest()
+
+/atom/movable/screen/lobby/button/bottom/poll
+ name = "View Available Polls"
+ icon_state = "poll"
+ base_icon_state = "poll"
+ screen_loc = "TOP:-122,CENTER:-26"
+ ///Whether the button should have a New Poll notification overlay
+ var/new_poll = FALSE
+
+/atom/movable/screen/lobby/button/bottom/poll/SlowInit(mapload)
+ . = ..()
+ if(!usr)
+ return
+ var/mob/dead/new_player/new_player = usr
+ if(is_guest_key(new_player.key))
+ set_button_status(FALSE)
+ return
+ if(!SSdbcore.Connect())
+ set_button_status(FALSE)
+ return
+ var/isadmin = FALSE
+ if(new_player.client?.holder)
+ isadmin = TRUE
+ var/datum/db_query/query_get_new_polls = SSdbcore.NewQuery({"
+ SELECT id FROM [format_table_name("poll_question")]
+ WHERE (adminonly = 0 OR :isadmin = 1)
+ AND Now() BETWEEN starttime AND endtime
+ AND deleted = 0
+ AND id NOT IN (
+ SELECT pollid FROM [format_table_name("poll_vote")]
+ WHERE ckey = :ckey
+ AND deleted = 0
+ )
+ AND id NOT IN (
+ SELECT pollid FROM [format_table_name("poll_textreply")]
+ WHERE ckey = :ckey
+ AND deleted = 0
+ )
+ "}, list("isadmin" = isadmin, "ckey" = new_player.ckey))
+ if(!query_get_new_polls.Execute())
+ qdel(query_get_new_polls)
+ set_button_status(FALSE)
+ return
+ if(query_get_new_polls.NextRow())
+ new_poll = TRUE
+ else
+ new_poll = FALSE
+ update_appearance(UPDATE_OVERLAYS)
+ qdel(query_get_new_polls)
+ if(QDELETED(new_player))
+ set_button_status(FALSE)
+ return
+
+/atom/movable/screen/lobby/button/bottom/poll/update_overlays()
+ . = ..()
+ if(new_poll)
+ . += mutable_appearance('icons/hud/lobby/poll_overlay.dmi', "new_poll")
+
+/atom/movable/screen/lobby/button/bottom/poll/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+ var/mob/dead/new_player/new_player = hud.mymob
+ new_player.handle_player_polling()
+
+/// A generic "sign up" button used by station traits
+/atom/movable/screen/lobby/button/sign_up
+ icon = 'icons/hud/lobby/signup_button.dmi'
+ icon_state = "signup"
+ base_icon_state = "signup"
+ always_available = FALSE
+
+/atom/movable/screen/lobby/button/sign_up/MouseEntered(location, control, params)
+ . = ..()
+ if(QDELETED(src) || !desc)
+ return
+ openToolTip(usr, tip_src = src, params = params, title = name, content = desc,)
+
+/atom/movable/screen/lobby/button/sign_up/MouseExited()
+ . = ..()
+ closeToolTip(usr)
+
+/atom/movable/screen/lobby/button/collapse
+ name = "Collapse Lobby Menu"
+ icon = 'icons/hud/lobby/collapse_expand.dmi'
+ icon_state = "collapse"
+ base_icon_state = "collapse"
+ layer = LOBBY_BELOW_MENU_LAYER
+ screen_loc = "TOP:-82,CENTER:-54"
+ always_shown = TRUE
+
+ var/blip_enabled = TRUE
+
+/atom/movable/screen/lobby/button/collapse/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ switch(SSticker.current_state)
+ if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(disable_blip))
+ RegisterSignal(hud, COMSIG_HUD_PLAYER_READY_TOGGLE, PROC_REF(on_player_ready_toggle))
+ if(GAME_STATE_SETTING_UP)
+ blip_enabled = FALSE
+ RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(enable_blip))
+ else
+ blip_enabled = FALSE
+
+ add_overlay(get_blip_overlay())
+ update_icon(UPDATE_OVERLAYS)
+
+/atom/movable/screen/lobby/button/collapse/update_overlays()
+ . = ..()
+ . += get_blip_overlay()
+
+/atom/movable/screen/lobby/button/collapse/Click(location, control, params)
+ . = ..()
+ if(!.)
+ return
+
+ if(!istype(hud, /datum/hud/new_player))
+ return
+ var/datum/hud/new_player/our_hud = hud
+ base_icon_state = our_hud.menu_hud_status ? "expand" : "collapse"
+ name = "[our_hud.menu_hud_status ? "Expand" : "Collapse"] Lobby Menu"
+ set_button_status(FALSE)
+
+ //get the shutter object used by our hud
+ var/atom/movable/screen/lobby/shutter/menu_shutter = locate(/atom/movable/screen/lobby/shutter) in hud.screen_groups[HUD_GROUP_STATIC]
+
+ //animate the shutter
+ menu_shutter.setup_shutter_animation()
+ //animate bottom buttons' movement
+ if(our_hud.menu_hud_status)
+ collapse_menu()
+ else
+ expand_menu()
+ our_hud.menu_hud_status = !our_hud.menu_hud_status
+
+ //re-enable clicking the button when the shutter animation finishes
+ //we use sleep here so it can work during game setup, as addtimer would not work until the game would finish setting up
+ sleep(2 * SHUTTER_MOVEMENT_DURATION + SHUTTER_WAIT_DURATION)
+ set_button_status(TRUE)
+
+///Proc to update the ready blip state upon new player's ready status change
+/atom/movable/screen/lobby/button/collapse/proc/on_player_ready_toggle()
+ SIGNAL_HANDLER
+ update_appearance(UPDATE_ICON)
+
+///Returns a ready blip overlay depending on the player's ready state
+/atom/movable/screen/lobby/button/collapse/proc/get_blip_overlay()
+ var/blip_icon_state = "ready_blip"
+ if(blip_enabled && hud)
+ var/mob/dead/new_player/new_player = hud.mymob
+ blip_icon_state += "_[new_player.is_ready_to_play() ? "" : "not_"]ready"
+ else
+ blip_icon_state += "_disabled"
+ var/mutable_appearance/ready_blip = mutable_appearance(icon, blip_icon_state)
+ return ready_blip
+
+///Disables the ready blip; makes us listen for the setup error to re-enable the blip
+/atom/movable/screen/lobby/button/collapse/proc/disable_blip()
+ SIGNAL_HANDLER
+ blip_enabled = FALSE
+ UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, PROC_REF(enable_blip))
+ update_appearance(UPDATE_ICON)
+
+///Enables the ready blip; makes us listen for the setup completion and game start to disable the blip
+/atom/movable/screen/lobby/button/collapse/proc/enable_blip()
+ SIGNAL_HANDLER
+ blip_enabled = TRUE
+ UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
+ RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, PROC_REF(disable_blip))
+ update_appearance(UPDATE_ICON)
+
+///Moves the button to the top of the screen, leaving only the screen part in view
+///Sends a signal on the hud for the menu hud elements to listen to
+/atom/movable/screen/lobby/button/collapse/proc/collapse_menu()
+ SEND_SIGNAL(hud, COMSIG_HUD_LOBBY_COLLAPSED)
+ //wait for the shutter to come down
+ animate(src, transform = transform, time = SHUTTER_MOVEMENT_DURATION + SHUTTER_WAIT_DURATION)
+ //then pull the button up with the shutter and leave it on the edge of the screen
+ animate(transform = transform.Translate(x = 0, y = 134), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_IN)
+ SEND_SOUND(hud.mymob, sound('sound/misc/menu/menu_rollup1.ogg'))
+
+///Extends the button back to its usual spot
+///Sends a signal on the hud for the menu hud elements to listen to
+/atom/movable/screen/lobby/button/collapse/proc/expand_menu()
+ SEND_SIGNAL(hud, COMSIG_HUD_LOBBY_EXPANDED)
+ animate(src, transform = matrix(), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_OUT)
+ SEND_SOUND(hud.mymob, sound('sound/misc/menu/menu_rolldown1.ogg'))
+
+/atom/movable/screen/lobby/shutter
+ icon = 'icons/hud/lobby/shutter.dmi'
+ icon_state = "shutter"
+ base_icon_state = "shutter"
+ screen_loc = "TOP:+143,CENTER:-73" //"home" position is off-screen
+ layer = LOBBY_SHUTTER_LAYER
+ always_shown = TRUE
+
+///Sets up the shutter pulling down and up. It's the same animation for both collapsing and expanding the menu.
+/atom/movable/screen/lobby/shutter/proc/setup_shutter_animation()
+ //bring down the shutter
+ animate(src, transform = transform.Translate(x = 0, y = -143), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_OUT)
+
+ //wait a little bit before bringing the shutter up
+ animate(transform = transform, time = SHUTTER_WAIT_DURATION)
+
+ //pull the shutter back off-screen
+ animate(transform = matrix(), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_IN)
+
+/// LOCALHOST ONLY - Start Now button
+/atom/movable/screen/lobby/button/start_now
+ name = "Start Now (LOCALHOST ONLY)"
+ screen_loc = "TOP:-146,CENTER:-54"
+ icon = 'icons/hud/lobby/start_now.dmi'
+ icon_state = "start_now"
+ base_icon_state = "start_now"
+ always_available = FALSE
+ select_sound_play = FALSE
+
+/atom/movable/screen/lobby/button/start_now/Click(location, control, params)
+ . = ..()
+ if(!. || !usr.client.is_localhost() || !check_rights_for(usr.client, R_SERVER))
+ return
+ SEND_SOUND(hud.mymob, sound('sound/effects/cartoon_sfx/cartoon_splat.ogg', volume = 50))
+ SSticker.start_immediately = TRUE
+ if(SSticker.current_state == GAME_STATE_STARTUP)
+ to_chat(usr, span_admin("The server is still setting up, but the round will be started as soon as possible."))
+
+#define OVERLAY_X_DIFF 12
+#define OVERLAY_Y_DIFF 5
+
+///Lobby screen that appears before the game has started showing how many players there are and who is ready.
+/atom/movable/screen/lobby/new_player_info
+ name = "New Player Info"
+ screen_loc = "EAST-3,CENTER:140"
+ icon = 'icons/hud/lobby/newplayer.dmi'
+ icon_state = null //we only show up when we get update appearance called, cause we need our overlay to not look bad.
+ base_icon_state = "newplayer"
+ maptext_height = 75
+ maptext_width = 80
+ maptext_x = OVERLAY_X_DIFF
+ maptext_y = OVERLAY_Y_DIFF
+
+ ///Boolean on whether or not we should have our static overlay, so we 'turn' the TV off when collapsing.
+ var/show_static = TRUE
+ ///Static mutable appearance of a job icon we're displaying on the TV for overflow job.
+ var/static/mutable_appearance/job_overlay
+
+/atom/movable/screen/lobby/new_player_info/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ START_PROCESSING(SSnewplayer_info, src)
+ update_text()
+
+ //only go if the station trait is selected, otherwise it'll show "Assistant" every round.
+ var/datum/station_trait/overflow_job_bureaucracy/overflow_job = locate() in SSstation.station_traits
+ if(overflow_job && isnull(job_overlay))
+ var/icon/job_icon = get_job_hud_icon(SSjob.overflow_role)
+ if(isnull(job_icon))
+ stack_trace("[SSjob.overflow_role::title] was selected as the Job Overflow but has no icon!")
+ else
+ job_icon.Scale(ICON_SIZE_X / 2, ICON_SIZE_X / 2)
+ job_overlay = mutable_appearance(job_icon, offset_spokesman = src, alpha = 120, layer = src.layer+0.02)
+ var/matrix/job_matrix = matrix()
+ job_matrix.Translate(6, 14) //this is completely arbitruary just what I thought looked good.
+ job_overlay.transform = job_matrix
+
+ update_appearance(UPDATE_ICON)
+
+/atom/movable/screen/lobby/new_player_info/Destroy()
+ STOP_PROCESSING(SSnewplayer_info, src)
+ return ..()
+
+/atom/movable/screen/lobby/new_player_info/MouseEntered(location, control, params)
+ . = ..()
+ if(QDELETED(src) || isnull(job_overlay))
+ return
+ openToolTip(usr, src, params, title = "[SSjob.overflow_role::title] overflow", content = "The overflow for the round has been set as [SSjob.overflow_role::title].")
+
+/atom/movable/screen/lobby/new_player_info/MouseExited()
+ closeToolTip(usr)
+ return ..()
+
+/atom/movable/screen/lobby/new_player_info/update_icon_state()
+ . = ..()
+ icon_state = base_icon_state
+
+/atom/movable/screen/lobby/new_player_info/update_overlays()
+ . = ..()
+ . += mutable_appearance(icon, "[base_icon_state]_overlay", layer = src.layer+0.01)
+ if(!show_static)
+ return .
+ if(job_overlay)
+ . += job_overlay
+ . += mutable_appearance(icon, "static_base", alpha = 20, layer = src.layer+0.03)
+ //we have this in a separate file because `generate_icon_alpha_mask` puts lighting even on non-existent pixels,
+ //giving the icon a weird background color.
+ var/mutable_appearance/scanline = mutable_appearance(generate_icon_alpha_mask('icons/hud/lobby/newplayer_scanline.dmi', "scanline"), alpha = 20, layer = src.layer+0.04)
+ scanline.pixel_y = OVERLAY_X_DIFF
+ scanline.pixel_x = OVERLAY_Y_DIFF
+ . += scanline
+
+/atom/movable/screen/lobby/new_player_info/process(seconds_per_tick)
+ update_text()
+
+/atom/movable/screen/lobby/new_player_info/collapse_button()
+ show_static = FALSE
+ update_text()
+ //to be in sync with parent, we'll turn the TV off in this time instead.
+ animate(src, appearance = update_appearance(UPDATE_ICON), time = SHUTTER_MOVEMENT_DURATION + SHUTTER_WAIT_DURATION)
+ //we go to the right, not up
+ animate(transform = transform.Translate(x = 146, y = 0), time = SHUTTER_MOVEMENT_DURATION, easing = CUBIC_EASING|EASE_IN)
+
+/atom/movable/screen/lobby/new_player_info/expand_button()
+ . = ..()
+ show_static = TRUE
+ update_appearance(UPDATE_ICON)
+ update_text()
+
+/atom/movable/screen/lobby/new_player_info/proc/update_text()
+ if(!hud || !show_static)
+ maptext = null
+ return
+
+ var/round_started = SSticker.HasRoundStarted()
+ if(!MC_RUNNING())
+ maptext = MAPTEXT("[(round_started ? null : "Starting in [time_remaining_str()]
")]Loading...")
+ return
+
+ if(SSticker.IsPostgame())
+ maptext = MAPTEXT("Game ended,
\
+ restart soon")
+ return
+
+ var/new_maptext
+ if(round_started)
+ new_maptext = "[SSmapping.current_map.map_name]
\
+ [LAZYLEN(GLOB.clients)] player\s online
\
+ [ROUND_TIME()] in
"
+ new_maptext += ""
+ else
+ if(hud.mymob.client?.holder)
+ new_maptext = "Starting in [time_remaining_str()]
\
+ [LAZYLEN(GLOB.clients)] player\s
\
+ [SSticker.totalPlayersReady] players ready
\
+ [SSticker.total_admins_ready] / [length(GLOB.admins)] admins ready"
+ else
+ new_maptext = "[time_remaining_str()]
\
+ [LAZYLEN(GLOB.clients)] player\s"
+
+ maptext = MAPTEXT(new_maptext)
+
+/atom/movable/screen/lobby/new_player_info/proc/time_remaining_str()
+ var/time_remaining = SSticker.GetTimeLeft()
+ if(time_remaining > 0)
+ return "[round(time_remaining/10)]s"
+ if(time_remaining == -10)
+ return "DELAYED"
+ return "SOON"
+
+#undef OVERLAY_X_DIFF
+#undef OVERLAY_Y_DIFF
+
+#undef SHUTTER_MOVEMENT_DURATION
+#undef SHUTTER_WAIT_DURATION
diff --git a/code/modules/pai/hud.dm b/code/_onclick/hud/screen_objects/pai.dm
similarity index 57%
rename from code/modules/pai/hud.dm
rename to code/_onclick/hud/screen_objects/pai.dm
index fb1fd483116..0965787ef42 100644
--- a/code/modules/pai/hud.dm
+++ b/code/_onclick/hud/screen_objects/pai.dm
@@ -17,6 +17,7 @@
/atom/movable/screen/pai/software
name = "Software Interface"
icon_state = "pai"
+ screen_loc = ui_pai_software
/atom/movable/screen/pai/software/Click()
if(!..())
@@ -27,6 +28,7 @@
/atom/movable/screen/pai/shell
name = "Toggle Holoform"
icon_state = "pai_holoform"
+ screen_loc = ui_pai_shell
/atom/movable/screen/pai/shell/Click()
if(!..())
@@ -40,6 +42,7 @@
/atom/movable/screen/pai/chassis
name = "Holochassis Appearance Composite"
icon_state = "pai_chassis"
+ screen_loc = ui_pai_chassis
/atom/movable/screen/pai/chassis/Click()
if(!..())
@@ -50,6 +53,7 @@
/atom/movable/screen/pai/rest
name = "Rest"
icon_state = "pai_rest"
+ screen_loc = ui_pai_rest
/atom/movable/screen/pai/rest/Click()
if(!..())
@@ -60,6 +64,7 @@
/atom/movable/screen/pai/light
name = "Toggle Integrated Lights"
icon_state = "light"
+ screen_loc = ui_pai_light
/atom/movable/screen/pai/light/Click()
if(!..())
@@ -70,6 +75,7 @@
/atom/movable/screen/pai/newscaster
name = "pAI Newscaster"
icon_state = "newscaster"
+ screen_loc = ui_pai_newscaster
required_software = "Newscaster"
/atom/movable/screen/pai/newscaster/Click()
@@ -81,6 +87,7 @@
/atom/movable/screen/pai/host_monitor
name = "Host Health Scan"
icon_state = "host_monitor"
+ screen_loc = ui_pai_host_monitor
required_software = "Host Scan"
/atom/movable/screen/pai/host_monitor/Click(location, control, params)
@@ -99,6 +106,7 @@
/atom/movable/screen/pai/crew_manifest
name = "Crew Manifest"
icon_state = "manifest"
+ screen_loc = ui_pai_crew_manifest
required_software = "Crew Manifest"
/atom/movable/screen/pai/crew_manifest/Click()
@@ -110,6 +118,7 @@
/atom/movable/screen/pai/state_laws
name = "State Laws"
icon_state = "state_laws"
+ screen_loc = ui_pai_state_laws
/atom/movable/screen/pai/state_laws/Click()
if(!..())
@@ -120,18 +129,21 @@
/atom/movable/screen/pai/modpc
name = "Messenger"
icon_state = "pda_send"
+ screen_loc = ui_pai_mod_int
required_software = "Digital Messenger"
- var/mob/living/silicon/pai/pAI
/atom/movable/screen/pai/modpc/Click()
. = ..()
if(!.) // this works for some reason.
return
- pAI.modularInterface?.interact(pAI)
+ var/mob/living/silicon/pai/pAI = usr
+ if (istype(pAI))
+ pAI.modularInterface?.interact(pAI)
/atom/movable/screen/pai/internal_gps
name = "Internal GPS"
icon_state = "internal_gps"
+ screen_loc = ui_pai_internal_gps
required_software = "Internal GPS"
/atom/movable/screen/pai/internal_gps/Click()
@@ -146,6 +158,7 @@
/atom/movable/screen/pai/image_take
name = "Take Image"
icon_state = "take_picture"
+ screen_loc = ui_pai_take_picture
required_software = "Photography Module"
/atom/movable/screen/pai/image_take/Click()
@@ -158,6 +171,7 @@
/atom/movable/screen/pai/image_view
name = "View Images"
icon_state = "view_images"
+ screen_loc = ui_pai_view_images
required_software = "Photography Module"
/atom/movable/screen/pai/image_view/Click()
@@ -170,6 +184,7 @@
name = "radio"
icon = 'icons/hud/screen_cyborg.dmi'
icon_state = "radio"
+ screen_loc = ui_pai_radio
/atom/movable/screen/pai/radio/Click()
if(!..())
@@ -177,109 +192,4 @@
var/mob/living/silicon/pai/pAI = usr
pAI.radio.interact(usr)
-/datum/hud/pai
- ui_style = 'icons/hud/screen_pai.dmi'
-
-/datum/hud/pai/New(mob/living/silicon/pai/owner)
- ..()
- var/atom/movable/screen/using
-
-// Software menu
- using = new /atom/movable/screen/pai/software(null, src)
- using.screen_loc = ui_pai_software
- static_inventory += using
-
-// Holoform
- using = new /atom/movable/screen/pai/shell(null, src)
- using.screen_loc = ui_pai_shell
- static_inventory += using
-
-// Chassis Select Menu
- using = new /atom/movable/screen/pai/chassis(null, src)
- using.screen_loc = ui_pai_chassis
- static_inventory += using
-
-// Rest
- using = new /atom/movable/screen/pai/rest(null, src)
- using.screen_loc = ui_pai_rest
- static_inventory += using
-
-// Integrated Light
- using = new /atom/movable/screen/pai/light(null, src)
- using.screen_loc = ui_pai_light
- static_inventory += using
-
-// Newscaster
- using = new /atom/movable/screen/pai/newscaster(null, src)
- using.screen_loc = ui_pai_newscaster
- static_inventory += using
-
-// Language menu
- using = new /atom/movable/screen/language_menu(null, src)
- using.icon = ui_style
- using.screen_loc = ui_pai_language_menu
- static_inventory += using
-
-// Memories
- using = new /atom/movable/screen/memories(null, src)
- using.icon = ui_style
- using.screen_loc = ui_pai_memories_menu
- static_inventory += using
-
-// Navigation
- using = new /atom/movable/screen/navigate(null, src)
- using.icon = ui_style
- using.screen_loc = ui_pai_navigate_menu
- static_inventory += using
-
-// Host Monitor
- using = new /atom/movable/screen/pai/host_monitor(null, src)
- using.screen_loc = ui_pai_host_monitor
- static_inventory += using
-
-// Crew Manifest
- using = new /atom/movable/screen/pai/crew_manifest(null, src)
- using.screen_loc = ui_pai_crew_manifest
- static_inventory += using
-
-// Laws
- using = new /atom/movable/screen/pai/state_laws(null, src)
- using.screen_loc = ui_pai_state_laws
- static_inventory += using
-
-// Modular Interface
- using = new /atom/movable/screen/pai/modpc(null, src)
- using.screen_loc = ui_pai_mod_int
- static_inventory += using
- var/atom/movable/screen/pai/modpc/tablet_button = using
- tablet_button.pAI = mymob
-
-// Internal GPS
- using = new /atom/movable/screen/pai/internal_gps(null, src)
- using.screen_loc = ui_pai_internal_gps
- static_inventory += using
-
-// Take image
- using = new /atom/movable/screen/pai/image_take(null, src)
- using.screen_loc = ui_pai_take_picture
- static_inventory += using
-
-// View images
- using = new /atom/movable/screen/pai/image_view(null, src)
- using.screen_loc = ui_pai_view_images
- static_inventory += using
-
-// Radio
- using = new /atom/movable/screen/pai/radio(null, src)
- using.screen_loc = ui_pai_radio
- static_inventory += using
-
- update_software_buttons()
-
-/datum/hud/pai/proc/update_software_buttons()
- var/mob/living/silicon/pai/owner = mymob
- for(var/atom/movable/screen/pai/button in static_inventory)
- if(button.required_software)
- button.color = owner.installed_software.Find(button.required_software) ? null : COLOR_GRAY
-
#undef PAI_MISSING_SOFTWARE_MESSAGE
diff --git a/code/_onclick/hud/screen_objects/perks.dm b/code/_onclick/hud/screen_objects/perks.dm
new file mode 100644
index 00000000000..5d6be963b02
--- /dev/null
+++ b/code/_onclick/hud/screen_objects/perks.dm
@@ -0,0 +1,29 @@
+/atom/movable/screen/perk
+ icon = 'icons/hud/perks.dmi'
+ name = "blank"
+ icon_state = "blank"
+
+/atom/movable/screen/perk/more
+ name = "more"
+ icon_state = "more"
+ // When compact we don't show our perk huds in ui.
+ var/compact = FALSE
+
+/atom/movable/screen/perk/more/Click(location, control, params)
+ . = ..()
+ if(!isliving(usr))
+ return
+ var/mob/living/usr_is_living = usr
+ var/datum/antagonist/wizard/wizard_datum = usr_is_living.mind.has_antag_datum(/datum/antagonist/wizard)
+ if(!wizard_datum)
+ return
+ compact = !compact
+ var/datum/hud/user_hud = usr_is_living.hud_used
+ for (var/perk_id in 1 to length(wizard_datum.perks))
+ var/atom/movable/screen/perk/perk = user_hud.screen_objects[HUD_WIZARD_PERK(perk_id)]
+ if (!perk) // ??
+ continue
+ if (compact)
+ perk.SetInvisibility(INVISIBILITY_ABSTRACT, type)
+ else
+ perk.RemoveInvisibility(type)
diff --git a/code/_onclick/hud/picture_in_picture.dm b/code/_onclick/hud/screen_objects/picture_in_picture.dm
similarity index 100%
rename from code/_onclick/hud/picture_in_picture.dm
rename to code/_onclick/hud/screen_objects/picture_in_picture.dm
diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/screen_objects/radial.dm
similarity index 100%
rename from code/_onclick/hud/radial.dm
rename to code/_onclick/hud/screen_objects/radial.dm
diff --git a/code/_onclick/hud/radial_persistent.dm b/code/_onclick/hud/screen_objects/radial_persistent.dm
similarity index 100%
rename from code/_onclick/hud/radial_persistent.dm
rename to code/_onclick/hud/screen_objects/radial_persistent.dm
diff --git a/code/_onclick/hud/screen_objects/robot.dm b/code/_onclick/hud/screen_objects/robot.dm
new file mode 100644
index 00000000000..9dd39e8d4d6
--- /dev/null
+++ b/code/_onclick/hud/screen_objects/robot.dm
@@ -0,0 +1,113 @@
+/atom/movable/screen/robot
+ icon = 'icons/hud/screen_cyborg.dmi'
+ mouse_over_pointer = MOUSE_HAND_POINTER
+
+/atom/movable/screen/robot/module
+ name = "cyborg module"
+ icon_state = "nomod"
+
+/atom/movable/screen/robot/Click(location, control, params)
+ if(isobserver(usr))
+ return TRUE
+
+/atom/movable/screen/robot/module/Click(location, control, params)
+ . = ..()
+ var/mob/living/silicon/robot/robot_owner = hud.mymob
+ if(robot_owner.model.type == /obj/item/robot_model)
+ if(.)
+ return
+ robot_owner.pick_model()
+ return
+
+ var/list/modifiers = params2list(params)
+ if(robot_owner.module_active && !LAZYACCESS(modifiers, RIGHT_CLICK) && !.)
+ robot_owner.uneq_active()
+ return
+
+ // Observers can look at borg's inventories, so we ignore parent return value here, unlike everywhere else.
+ if(usr.active_storage == robot_owner.model.atom_storage)
+ robot_owner.model.atom_storage.hide_contents(usr)
+ else
+ robot_owner.model.atom_storage.open_storage(usr)
+ return TRUE
+
+/atom/movable/screen/robot/module_slot
+ name = "module"
+ icon_state = "inv1"
+ base_icon_state = "inv1"
+ /// Slot number of the module
+ var/slot_num = 1
+
+/atom/movable/screen/robot/module_slot/proc/set_slot(slot_num)
+ src.slot_num = slot_num
+ name = "module[slot_num]"
+ base_icon_state = "inv[slot_num]"
+ icon_state = base_icon_state
+
+ switch(slot_num)
+ if(BORG_CHOOSE_MODULE_ONE)
+ screen_loc = ui_inv1
+ if(BORG_CHOOSE_MODULE_TWO)
+ screen_loc = ui_inv2
+ if(BORG_CHOOSE_MODULE_THREE)
+ screen_loc = ui_inv3
+
+/atom/movable/screen/robot/module_slot/Click()
+ if(..())
+ return
+ var/mob/living/silicon/robot/R = usr
+ R.toggle_module(slot_num)
+
+/atom/movable/screen/robot/radio
+ name = "radio"
+ icon_state = "radio"
+ screen_loc = ui_borg_radio
+
+/atom/movable/screen/robot/radio/Click()
+ if(..())
+ return
+ var/mob/living/silicon/robot/R = usr
+ R.radio.interact(R)
+
+/atom/movable/screen/robot/lamp
+ name = "headlamp"
+ icon_state = "lamp_off"
+ base_icon_state = "lamp"
+ screen_loc = ui_borg_lamp
+
+/atom/movable/screen/robot/lamp/Click()
+ . = ..()
+ if(.)
+ return
+ var/mob/living/silicon/robot/user = usr
+ user.toggle_headlamp()
+ update_appearance()
+
+/atom/movable/screen/robot/lamp/update_icon_state()
+ icon_state = "[base_icon_state]_[astype(hud?.mymob, /mob/living/silicon/robot)?.lamp_enabled ? "on" : "off"]"
+ return ..()
+
+/atom/movable/screen/robot/modpc
+ name = "Modular Interface"
+ icon_state = "template"
+ screen_loc = ui_borg_tablet
+
+/atom/movable/screen/robot/modpc/Click()
+ . = ..()
+ if(.)
+ return
+ var/mob/living/silicon/robot/user = usr
+ user.modularInterface?.interact(user)
+
+/atom/movable/screen/robot/alerts
+ name = "Alert Panel"
+ icon = 'icons/hud/screen_ai.dmi'
+ icon_state = "alerts"
+ screen_loc = ui_borg_alerts
+
+/atom/movable/screen/robot/alerts/Click()
+ . = ..()
+ if(.)
+ return
+ var/mob/living/silicon/robot/borgo = usr
+ borgo.alert_control.ui_interact(borgo)
diff --git a/code/_onclick/hud/screen_object_holder.dm b/code/_onclick/hud/screen_objects/screen_object_holder.dm
similarity index 100%
rename from code/_onclick/hud/screen_object_holder.dm
rename to code/_onclick/hud/screen_objects/screen_object_holder.dm
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects/screen_objects.dm
similarity index 96%
rename from code/_onclick/hud/screen_objects.dm
rename to code/_onclick/hud/screen_objects/screen_objects.dm
index 2514376f911..fc4c8be9e4f 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects/screen_objects.dm
@@ -1,3 +1,4 @@
+INITIALIZE_IMMEDIATE(/atom/movable/screen) // I hate this place
/*
Screen objects
Todo: improve/re-implement
@@ -34,6 +35,10 @@
*/
var/del_on_map_removal = TRUE
+ /// A key for cleaning up references in hud datums
+ var/hud_group_key
+ var/hud_key
+
/// If FALSE, this will not be cleared when calling /client/clear_screen()
var/clear_with_screen = TRUE
/// If TRUE, clicking the screen element will fall through and perform a default "Click" call
@@ -50,6 +55,10 @@
set_new_hud(hud_owner)
/atom/movable/screen/Destroy()
+ if(hud)
+ if (hud_group_key && hud.screen_groups?[hud_group_key])
+ hud.screen_groups?[hud_group_key] -= src
+ hud.screen_objects -= hud_key
master_ref = null
hud = null
return ..()
@@ -57,6 +66,7 @@
/atom/movable/screen/Click(location, control, params)
if(flags_1 & INITIALIZED_1)
SEND_SIGNAL(src, COMSIG_SCREEN_ELEMENT_CLICK, location, control, params, usr)
+
if(default_click)
return ..()
@@ -101,7 +111,6 @@
maptext_width = 480
/atom/movable/screen/swap_hand
- plane = HUD_PLANE
name = "swap hand"
mouse_over_pointer = MOUSE_HAND_POINTER
@@ -187,7 +196,6 @@
var/icon_full
/// The overlay when hovering over with an item in your hand
var/image/object_overlay
- plane = HUD_PLANE
/atom/movable/screen/inventory/Click(location, control, params)
// At this point in client Click() code we have passed the 1/10 sec check and little else
@@ -304,6 +312,7 @@
icon = 'icons/hud/screen_midnight.dmi'
icon_state = "storage_close"
mouse_over_pointer = MOUSE_HAND_POINTER
+ hud_group_key = HUD_GROUP_STORAGE
/atom/movable/screen/close/Initialize(mapload, datum/hud/hud_owner, new_master)
. = ..()
@@ -320,7 +329,6 @@
name = "drop"
icon = 'icons/hud/screen_midnight.dmi'
icon_state = "act_drop"
- plane = HUD_PLANE
mouse_over_pointer = MOUSE_HAND_POINTER
/atom/movable/screen/drop/Click()
@@ -331,7 +339,7 @@
name = "toggle combat mode"
icon = 'icons/hud/screen_midnight.dmi'
icon_state = "combat_off"
- screen_loc = ui_combat_toggle
+ screen_loc = ui_acti
mouse_over_pointer = MOUSE_HAND_POINTER
/atom/movable/screen/combattoggle/Initialize(mapload, datum/hud/hud_owner)
@@ -470,6 +478,11 @@
icon = 'icons/hud/screen_midnight.dmi'
icon_state = "running"
mouse_over_pointer = MOUSE_HAND_POINTER
+ screen_loc = ui_movi
+
+/atom/movable/screen/mov_intent/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ update_appearance(UPDATE_ICON_STATE)
/atom/movable/screen/mov_intent/Click()
toggle(usr)
@@ -496,6 +509,11 @@
icon_state = "pull"
base_icon_state = "pull"
mouse_over_pointer = MOUSE_HAND_POINTER
+ screen_loc = ui_living_pull
+
+/atom/movable/screen/pull/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ update_appearance(UPDATE_ICON_STATE)
/atom/movable/screen/pull/Click()
if(isobserver(usr))
@@ -511,8 +529,8 @@
icon = 'icons/hud/screen_midnight.dmi'
icon_state = "act_resist"
base_icon_state = "act_resist"
- plane = HUD_PLANE
mouse_over_pointer = MOUSE_HAND_POINTER
+ screen_loc = ui_above_movement
/atom/movable/screen/resist/Click()
flick("[base_icon_state]_on", src)
@@ -525,8 +543,12 @@
icon = 'icons/hud/screen_midnight.dmi'
icon_state = "act_rest"
base_icon_state = "act_rest"
- plane = HUD_PLANE
mouse_over_pointer = MOUSE_HAND_POINTER
+ screen_loc = ui_below_throw
+
+/atom/movable/screen/rest/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ update_appearance(UPDATE_ICON_STATE)
/atom/movable/screen/rest/Click()
if(isliving(usr))
@@ -545,32 +567,38 @@
icon = 'icons/hud/screen_midnight.dmi'
icon_state = "act_sleep"
base_icon_state = "act_sleep"
- plane = HUD_PLANE
mouse_over_pointer = MOUSE_HAND_POINTER
+ screen_loc = ui_above_throw
+
+/atom/movable/screen/sleep/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ // Invisible by default
+ SetInvisibility(INVISIBILITY_ABSTRACT, "sleep")
/atom/movable/screen/sleep/Click()
if(!isliving(usr) || HAS_TRAIT(usr, TRAIT_KNOCKEDOUT))
return
- if(usr.client?.prefs.read_preference(/datum/preference/toggle/remove_double_click))
- var/tgui_answer = tgui_alert(usr, "You sure you want to sleep for a while?", "Sleeping", list("Yes", "No"))
- if(tgui_answer == "Yes" && !HAS_TRAIT(usr, TRAIT_KNOCKEDOUT))
- var/mob/living/L = usr
- L.SetSleeping(400)
- else
+ if(!usr.client?.prefs.read_preference(/datum/preference/toggle/remove_double_click))
flick("[base_icon_state]_flick", src)
+ return
+
+ var/tgui_answer = tgui_alert(usr, "You sure you want to sleep for a while?", "Sleeping", list("Yes", "No"))
+ if(tgui_answer == "Yes" && !HAS_TRAIT(usr, TRAIT_KNOCKEDOUT))
+ var/mob/living/L = usr
+ L.Sleeping(400)
/atom/movable/screen/sleep/DblClick(location, control, params)
if(!isliving(usr) || usr.client?.prefs.read_preference(/datum/preference/toggle/remove_double_click))
return
if(isliving(usr))
var/mob/living/L = usr
- L.SetSleeping(400)
+ L.Sleeping(400)
/atom/movable/screen/storage
name = "storage"
icon = 'icons/hud/screen_midnight.dmi'
icon_state = "storage_cell"
- plane = HUD_PLANE
+ hud_group_key = HUD_GROUP_STORAGE
/atom/movable/screen/storage/Initialize(mapload, datum/hud/hud_owner, new_master)
. = ..()
@@ -638,6 +666,7 @@
icon = 'icons/hud/screen_midnight.dmi'
icon_state = "act_throw"
mouse_over_pointer = MOUSE_HAND_POINTER
+ screen_loc = ui_drop_throw
/atom/movable/screen/throw_catch/Click()
if(isliving(usr))
@@ -653,6 +682,10 @@
var/static/list/hover_overlays_cache = list()
var/hovering
+/atom/movable/screen/zone_sel/Initialize(mapload, datum/hud/hud_owner)
+ . = ..()
+ update_appearance()
+
/atom/movable/screen/zone_sel/Click(location, control,params)
if(isobserver(usr))
return
@@ -941,7 +974,6 @@
plane = SPLASHSCREEN_PLANE
var/client/holder
-INITIALIZE_IMMEDIATE(/atom/movable/screen/splash)
/atom/movable/screen/splash/Initialize(mapload, datum/hud/hud_owner, client/C, visible, use_previous_title)
. = ..()
diff --git a/code/_onclick/hud/screentip.dm b/code/_onclick/hud/screen_objects/screentip.dm
similarity index 100%
rename from code/_onclick/hud/screentip.dm
rename to code/_onclick/hud/screen_objects/screentip.dm
diff --git a/code/_onclick/hud/voidwalkerhud.dm b/code/_onclick/hud/screen_objects/voidwalker.dm
similarity index 73%
rename from code/_onclick/hud/voidwalkerhud.dm
rename to code/_onclick/hud/screen_objects/voidwalker.dm
index 7ba892f7d7a..6d718ac58d7 100644
--- a/code/_onclick/hud/voidwalkerhud.dm
+++ b/code/_onclick/hud/screen_objects/voidwalker.dm
@@ -1,30 +1,3 @@
-/datum/hud/dextrous/voidwalker
- ui_style = 'icons/hud/screen_voidwalker.dmi'
-
-/datum/hud/dextrous/voidwalker/New(mob/living/owner)
- . = ..()
-
- floor_change.icon = ui_style
- floor_change.screen_loc = ui_rest
- static_inventory += floor_change
-
- resist_icon = new /atom/movable/screen/resist(null, src)
- resist_icon.icon = ui_style
- resist_icon.screen_loc = ui_voidwalker_left_of_hands
- resist_icon.update_appearance()
-
- action_intent = new /atom/movable/screen/combattoggle/flashy/voidwalker(null, src)
- action_intent.icon = ui_style
- static_inventory += action_intent
-
- var/atom/movable/screen/space_camo_toggle = new /atom/movable/screen/space_camo(null, src)
- space_camo_toggle.screen_loc = ui_above_movement
- static_inventory += space_camo_toggle
-
- var/atom/movable/screen/vomit_jump/vomit = new /atom/movable/screen/vomit_jump(null, src)
- vomit.screen_loc = ui_mood
- static_inventory += vomit
-
/// This exists because for some reason only the combat indicator screen_loc is constantly set to initial
/atom/movable/screen/combattoggle/flashy/voidwalker
screen_loc = ui_movi
@@ -33,6 +6,7 @@
name = "space camouflage toggle"
icon = 'icons/hud/screen_voidwalker.dmi'
icon_state = "camo_toggle"
+ screen_loc = ui_above_movement
/// Wheter or not we're toggled on or off
var/invisibility_toggle = TRUE
@@ -57,6 +31,7 @@
name = "vomit tracker"
icon = 'icons/hud/screen_voidwalker.dmi'
icon_state = "template"
+ screen_loc = ui_mood
/// So we can sort of loop through it
var/index = 1
diff --git a/code/_onclick/hud/soulscythe.dm b/code/_onclick/hud/soulscythe.dm
index 8c7a3359c8a..e290d960e56 100644
--- a/code/_onclick/hud/soulscythe.dm
+++ b/code/_onclick/hud/soulscythe.dm
@@ -1,4 +1,3 @@
-/datum/hud/soulscythe/New(mob/living/basic/soulscythe/owner)
+/datum/hud/soulscythe/initialize_screen_objects()
. = ..()
- var/atom/movable/screen/using = new /atom/movable/screen/blood_level(null, src)
- static_inventory += using
+ add_screen_object(/atom/movable/screen/blood_level, HUD_MOB_BLOOD_LEVEL, HUD_GROUP_INFO)
diff --git a/code/_onclick/hud/voidwalker.dm b/code/_onclick/hud/voidwalker.dm
new file mode 100644
index 00000000000..7fe95fc3f28
--- /dev/null
+++ b/code/_onclick/hud/voidwalker.dm
@@ -0,0 +1,14 @@
+/datum/hud/dextrous/voidwalker
+ ui_style = 'icons/hud/screen_voidwalker.dmi'
+
+/datum/hud/dextrous/voidwalker/initialize_screen_objects()
+ . = ..()
+ var/atom/movable/screen/floor_change = screen_objects[HUD_MOB_FLOOR_CHANGER]
+ floor_change.icon = ui_style
+ floor_change.screen_loc = ui_below_throw
+
+ add_screen_object(/atom/movable/screen/resist, HUD_MOB_RESIST, HUD_GROUP_HOTKEYS, ui_style, ui_voidwalker_left_of_hands)
+ add_screen_object(/atom/movable/screen/combattoggle/flashy/voidwalker, HUD_MOB_INTENTS, HUD_GROUP_STATIC, ui_style)
+ add_screen_object(/atom/movable/screen/space_camo, HUD_VOIDWALKER_SPACE_CAMO)
+ add_screen_object(/atom/movable/screen/vomit_jump, HUD_VOIDWALKER_VOID_JUMP)
+
diff --git a/code/datums/actions/action.dm b/code/datums/actions/action.dm
index 64f2f2a6c2b..b5993e1894a 100644
--- a/code/datums/actions/action.dm
+++ b/code/datums/actions/action.dm
@@ -373,7 +373,7 @@
/// Creates an action button movable for the passed mob, and returns it.
/datum/action/proc/create_button()
- var/atom/movable/screen/movable/action_button/button = new()
+ var/atom/movable/screen/movable/action_button/button = owner.hud_used.add_screen_object(/atom/movable/screen/movable/action_button)
button.linked_action = src
button.allow_observer_click = allow_observer_click
build_button_icon(button, ALL, TRUE)
diff --git a/code/datums/components/crafting/crafting.dm b/code/datums/components/crafting/crafting.dm
index d8b6103e338..a042bfe7a02 100644
--- a/code/datums/components/crafting/crafting.dm
+++ b/code/datums/components/crafting/crafting.dm
@@ -15,20 +15,29 @@
/datum/component/personal_crafting/Initialize(screen_loc_override)
src.screen_loc_override = screen_loc_override
- if(ismob(parent))
- RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN, PROC_REF(create_mob_button))
-/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/user_client)
+/datum/component/personal_crafting/RegisterWithParent()
+ if(!ismob(parent))
+ return
+
+ var/mob/user = parent
+ RegisterSignal(parent, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
+ if(user.hud_used)
+ on_hud_created()
+
+/datum/component/personal_crafting/UnregisterFromParent()
+ if(!ismob(parent))
+ return
+ var/mob/user = parent
+ UnregisterSignal(parent, COMSIG_MOB_HUD_CREATED)
+ user.hud_used?.remove_screen_object(HUD_MOB_CRAFTING_MENU)
+
+/datum/component/personal_crafting/proc/on_hud_created(datum/source)
SIGNAL_HANDLER
- var/datum/hud/hud = user.hud_used
- var/atom/movable/screen/craft/craft_ui = new()
- craft_ui.icon = hud.ui_style
- if (screen_loc_override)
- craft_ui.screen_loc = screen_loc_override
- hud.static_inventory += craft_ui
- user_client.screen += craft_ui
- RegisterSignal(craft_ui, COMSIG_SCREEN_ELEMENT_CLICK, PROC_REF(component_ui_interact))
+ var/mob/user = parent
+ var/atom/movable/screen/screen_obj = user.hud_used.add_screen_object(/atom/movable/screen/craft, HUD_MOB_CRAFTING_MENU, HUD_GROUP_STATIC, user.hud_used.ui_style, screen_loc_override, update_screen = TRUE)
+ RegisterSignal(screen_obj, COMSIG_SCREEN_ELEMENT_CLICK, PROC_REF(component_ui_interact))
#define COOKING TRUE
#define CRAFTING FALSE
diff --git a/code/datums/components/food/edible.dm b/code/datums/components/food/edible.dm
index b58ef88a3dc..465b6ae2066 100644
--- a/code/datums/components/food/edible.dm
+++ b/code/datums/components/food/edible.dm
@@ -504,7 +504,9 @@ Behavior that's still missing from this component that original food items had t
var/fraction = 0.3
fraction = min(bite_consumption / owner.reagents.total_volume, 1)
owner.reagents.trans_to(eater, bite_consumption, transferred_by = feeder, methods = INGEST)
- eater.hud_used?.hunger?.update_hunger_bar()
+ var/atom/movable/screen/hunger/hunger_bar = eater.hud_used?.screen_objects[HUD_MOB_HUNGER]
+ if (istype(hunger_bar))
+ hunger_bar.update_hunger_bar()
bitecount++
checkLiked(fraction, eater)
diff --git a/code/datums/components/fov_handler.dm b/code/datums/components/fov_handler.dm
index df56df1ff6e..cd3061291a2 100644
--- a/code/datums/components/fov_handler.dm
+++ b/code/datums/components/fov_handler.dm
@@ -90,8 +90,6 @@
/datum/component/fov_handler/proc/remove_mask()
var/mob/parent_mob = parent
var/client/parent_client = parent_mob.client
- // Prevents stupid ass hard deletes
- parent_mob.hud_used.always_visible_inventory -= blocker_mask
if(!parent_client) //Love client volatility!!
return
applied_mask = FALSE
@@ -104,7 +102,8 @@
return
applied_mask = TRUE
parent_client.screen += blocker_mask
- parent_mob.hud_used.always_visible_inventory += blocker_mask
+ parent_mob.hud_used.screen_objects += blocker_mask
+ parent_mob.hud_used.screen_groups[HUD_GROUP_SCREEN_OVERLAYS] += blocker_mask
/// When a direction of the user changes, so do the masks
/datum/component/fov_handler/proc/on_dir_change(mob/source, old_dir, new_dir)
diff --git a/code/datums/components/life_link.dm b/code/datums/components/life_link.dm
index a79758122c5..d1371467682 100644
--- a/code/datums/components/life_link.dm
+++ b/code/datums/components/life_link.dm
@@ -118,8 +118,9 @@
mob_parent.overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
else
mob_parent.clear_fullscreen("brute")
- if(mob_parent.hud_used?.healths)
- mob_parent.hud_used.healths.maptext = MAPTEXT("[round(healthpercent, 0.5)]%
")
+
+ if(mob_parent.hud_used?.screen_objects[HUD_MOB_HEALTH])
+ mob_parent.hud_used.screen_objects[HUD_MOB_HEALTH].maptext = MAPTEXT("[round(healthpercent, 0.5)]%
")
/// Update our health on the medical hud
/datum/component/life_link/proc/update_med_hud_health(mob/living/mob_parent)
diff --git a/code/datums/components/style/style.dm b/code/datums/components/style/style.dm
index 6e1147a7ba3..04ea7b3654c 100644
--- a/code/datums/components/style/style.dm
+++ b/code/datums/components/style/style.dm
@@ -74,23 +74,7 @@
if(!ismob(parent))
return COMPONENT_INCOMPATIBLE
- var/mob/mob_parent = parent
-
- meter = new()
- meter_image = new()
- meter.vis_contents += meter_image
- meter_image.add_filter("meter_mask", 1, list(type = "alpha", icon = icon('icons/hud/style_meter.dmi', "style_meter"), flags = MASK_INVERSE))
- meter.update_appearance()
- meter_image.update_appearance()
-
- update_screen()
-
- if(mob_parent.hud_used)
- mob_parent.hud_used.static_inventory += meter
- mob_parent.hud_used.show_hud(mob_parent.hud_used.hud_version)
-
START_PROCESSING(SSdcs, src)
-
if(multitooled)
src.multitooled = multitooled
@@ -107,7 +91,11 @@
RegisterSignal(parent, COMSIG_LIVING_DEFUSED_GIBTONITE, PROC_REF(on_gibtonite_defuse))
RegisterSignal(parent, COMSIG_LIVING_CRUSHER_DETONATE, PROC_REF(on_crusher_detonate))
RegisterSignal(parent, COMSIG_LIVING_DISCOVERED_GEYSER, PROC_REF(on_geyser_discover))
+ RegisterSignal(parent, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
ADD_TRAIT(parent, TRAIT_MINING_PARRYING, STYLE_TRAIT)
+ var/mob/mob_parent = parent
+ if (mob_parent.hud_used)
+ on_hud_created()
/datum/component/style/UnregisterFromParent()
UnregisterSignal(parent, COMSIG_USER_PRE_ITEM_ATTACK)
@@ -121,16 +109,31 @@
UnregisterSignal(parent, COMSIG_LIVING_DEFUSED_GIBTONITE)
UnregisterSignal(parent, COMSIG_LIVING_CRUSHER_DETONATE)
UnregisterSignal(parent, COMSIG_LIVING_DISCOVERED_GEYSER)
+ UnregisterSignal(parent, COMSIG_MOB_HUD_CREATED)
REMOVE_TRAIT(parent, TRAIT_MINING_PARRYING, STYLE_TRAIT)
/datum/component/style/Destroy(force)
STOP_PROCESSING(SSdcs, src)
+ QDEL_NULL(meter)
+ QDEL_NULL(meter_image)
var/mob/mob_parent = parent
if(mob_parent.hud_used)
- mob_parent.hud_used.static_inventory -= meter
mob_parent.hud_used.show_hud(mob_parent.hud_used.hud_version)
return ..()
+
+/datum/component/style/proc/on_hud_created(datum/source)
+ SIGNAL_HANDLER
+
+ var/mob/owner = parent
+ meter = owner.hud_used.add_screen_object(/atom/movable/screen/style_meter_background, HUD_MOB_STYLE_METER, update_screen = TRUE)
+ meter_image = new()
+ meter.vis_contents += meter_image
+ meter_image.add_filter("meter_mask", 1, list(type = "alpha", icon = icon('icons/hud/style_meter.dmi', "style_meter"), flags = MASK_INVERSE))
+ meter.update_appearance()
+ meter_image.update_appearance()
+ update_screen()
+
/datum/component/style/process(seconds_per_tick)
point_multiplier = round(max(point_multiplier - 0.2 * seconds_per_tick, 1), 0.1)
change_points(-5 * seconds_per_tick * ROUND_UP((style_points + 1) / 200), use_multiplier = FALSE)
@@ -195,6 +198,9 @@
mob_parent.balloon_alert(mob_parent, "hotswapping disabled")
rank = rank_changed
+
+ if(!meter)
+ return
meter.maptext = "[format_rank_string(rank)][generate_multiplier()][generate_actions()]"
meter.maptext_y = initial(meter.maptext_y) - 12 * length(actions)
update_meter(point_to_rank(), go_back)
diff --git a/code/datums/elements/attack_zone_randomiser.dm b/code/datums/elements/attack_zone_randomiser.dm
index 1e364265bab..efd7648bc7c 100644
--- a/code/datums/elements/attack_zone_randomiser.dm
+++ b/code/datums/elements/attack_zone_randomiser.dm
@@ -21,14 +21,14 @@
SIGNAL_HANDLER
if (!iscarbon(target))
return
- if (!isnull(source.mind) && !isnull(source.hud_used?.zone_select))
+ if (!isnull(source.mind) && !isnull(source.hud_used?.screen_objects[HUD_MOB_ZONE_SELECTOR]))
return
var/mob/living/living_target = target
var/list/blacklist_zones = GLOB.all_body_zones - valid_attack_zones
var/new_zone = living_target.get_random_valid_zone(blacklisted_parts = blacklist_zones, bypass_warning = TRUE)
if (isnull(new_zone))
new_zone = BODY_ZONE_CHEST
- var/atom/movable/screen/zone_sel/zone_selector = source.hud_used?.zone_select
+ var/atom/movable/screen/zone_sel/zone_selector = source.hud_used?.screen_objects[HUD_MOB_ZONE_SELECTOR]
if (isnull(zone_selector))
source.zone_selected = new_zone
else
diff --git a/code/datums/keybinding/living.dm b/code/datums/keybinding/living.dm
index 42eb96bf5da..d9d12020ef2 100644
--- a/code/datums/keybinding/living.dm
+++ b/code/datums/keybinding/living.dm
@@ -18,8 +18,8 @@
return
var/mob/living/owner = user.mob
owner.resist()
- if (owner.hud_used?.resist_icon)
- owner.hud_used.resist_icon.icon_state = "[owner.hud_used.resist_icon.base_icon_state]_on"
+ if (owner.hud_used?.screen_objects[HUD_MOB_RESIST])
+ owner.hud_used.screen_objects[HUD_MOB_RESIST].icon_state = "[owner.hud_used.screen_objects[HUD_MOB_RESIST].base_icon_state]_on"
return TRUE
/datum/keybinding/living/resist/up(client/user, turf/target)
@@ -27,8 +27,8 @@
if(.)
return
var/mob/living/owner = user.mob
- if (owner.hud_used?.resist_icon)
- owner.hud_used.resist_icon.icon_state = owner.hud_used.resist_icon.base_icon_state
+ if (owner.hud_used?.screen_objects[HUD_MOB_RESIST])
+ owner.hud_used.screen_objects[HUD_MOB_RESIST].icon_state = owner.hud_used.screen_objects[HUD_MOB_RESIST].base_icon_state
/datum/keybinding/living/look_up
hotkey_keys = list("L")
diff --git a/code/datums/martial/_martial.dm b/code/datums/martial/_martial.dm
index 4a0c9c84b30..1281d028b22 100644
--- a/code/datums/martial/_martial.dm
+++ b/code/datums/martial/_martial.dm
@@ -24,8 +24,6 @@
var/smashes_tables = FALSE
/// If TRUE, a combo meter will be displayed on the HUD for the current streak
var/display_combos = FALSE
- ///The Combo HUD given to display comboes, if we're set to display them.
- var/atom/movable/screen/combo/combo_display
/// The length of time until streaks are auto-reset.
var/combo_timer = 6 SECONDS
/// Timer ID for the combo reset timer.
@@ -276,8 +274,11 @@
streak += element
if(length(streak) > max_streak_length)
streak = copytext(streak, 1 + length(streak[1]))
- if(display_combos)
- timerid = addtimer(CALLBACK(src, PROC_REF(reset_streak), null, FALSE), combo_timer, TIMER_UNIQUE | TIMER_STOPPABLE)
+ if(!display_combos)
+ return
+ timerid = addtimer(CALLBACK(src, PROC_REF(reset_streak), null, FALSE), combo_timer, TIMER_UNIQUE | TIMER_STOPPABLE)
+ var/atom/movable/screen/combo/combo_display = holder.hud_used?.screen_objects[HUD_MOB_COMBO]
+ if(istype(combo_display))
combo_display.update_icon_state(streak, combo_timer - 2 SECONDS)
/**
@@ -292,7 +293,8 @@
deltimer(timerid)
current_target = WEAKREF(new_target)
streak = ""
- if(display_combos && update_icon)
+ var/atom/movable/screen/combo/combo_display = holder.hud_used?.screen_objects[HUD_MOB_COMBO]
+ if(istype(combo_display) && display_combos && update_icon)
combo_display.update_icon_state(streak)
/datum/martial_art/proc/smash_table(mob/living/source, mob/living/pushed_mob, obj/structure/table/table)
@@ -383,10 +385,9 @@
RegisterSignal(new_holder, COMSIG_LIVING_GRAB, PROC_REF(attempt_grab))
RegisterSignals(new_holder, list(COMSIG_LIVING_TABLE_SLAMMING, COMSIG_LIVING_TABLE_LIMB_SLAMMING), PROC_REF(smash_table))
if(display_combos)
+ RegisterSignal(new_holder, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
if(new_holder.hud_used)
on_hud_created(new_holder)
- else
- RegisterSignal(new_holder, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
/**
* Called when this martial art is removed from a mob.
@@ -397,19 +398,12 @@
if(help_verb)
remove_verb(remove_from, help_verb)
UnregisterSignal(remove_from, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_LIVING_GRAB, COMSIG_LIVING_TABLE_SLAMMING, COMSIG_LIVING_TABLE_LIMB_SLAMMING))
- if(!isnull(combo_display))
- var/datum/hud/hud_used = remove_from.hud_used
- hud_used.infodisplay -= combo_display
- hud_used.show_hud(hud_used.hud_version)
- QDEL_NULL(combo_display)
+ remove_from.hud_used?.remove_screen_object(HUD_MOB_COMBO)
///Gives the owner of the martial art the combo HUD.
/datum/martial_art/proc/on_hud_created(mob/source)
SIGNAL_HANDLER
- var/datum/hud/hud_used = source.hud_used
- combo_display = new(null, hud_used)
- hud_used.infodisplay += combo_display
- hud_used.show_hud(hud_used.hud_version)
+ source.hud_used.add_screen_object(/atom/movable/screen/combo, HUD_MOB_COMBO, HUD_GROUP_INFO, update_screen = TRUE)
/mob/living/proc/verb_switch_style()
set name = "Swap Style"
diff --git a/code/datums/mood.dm b/code/datums/mood.dm
index 6ee75391517..afc7824380f 100644
--- a/code/datums/mood.dm
+++ b/code/datums/mood.dm
@@ -36,8 +36,6 @@
var/sanity_level = SANITY_LEVEL_NEUTRAL
/// Is the owner being punished for low mood? if so, how much?
var/insanity_effect = 0
- /// The screen object for the current mood level
- var/atom/movable/screen/mood/mood_screen_object
/// List of mood events currently active on this datum
var/list/mood_events = list()
@@ -308,7 +306,11 @@
/// Updates the mob's mood icon
/datum/mood/proc/update_mood_icon()
- if (!(mob_parent.client || mob_parent.hud_used) || isnull(mood_screen_object))
+ if (!mob_parent.client || !mob_parent.hud_used)
+ return
+
+ var/atom/movable/screen/mood/mood_screen_object = mob_parent.hud_used.screen_objects[HUD_MOB_MOOD]
+ if (!istype(mood_screen_object))
return
mood_screen_object.cut_overlays()
@@ -356,9 +358,8 @@
SIGNAL_HANDLER
var/datum/hud/hud = mob_parent.hud_used
- mood_screen_object = new
+ var/atom/movable/screen/mood/mood_screen_object = hud.add_screen_object(/atom/movable/screen/mood, HUD_MOB_MOOD, HUD_GROUP_INFO, update_screen = TRUE)
mood_screen_object.color = "#4b96c4"
- hud.infodisplay += mood_screen_object
RegisterSignal(hud, COMSIG_QDELETING, PROC_REF(unmodify_hud))
RegisterSignal(mood_screen_object, COMSIG_SCREEN_ELEMENT_CLICK, PROC_REF(hud_click))
@@ -366,12 +367,17 @@
/datum/mood/proc/unmodify_hud(datum/source)
SIGNAL_HANDLER
+ var/datum/hud/hud = mob_parent.hud_used
+ if (!hud)
+ return
+
+ var/atom/movable/screen/mood/mood_screen_object = hud.screen_objects[HUD_MOB_MOOD]
if(!mood_screen_object)
return
- var/datum/hud/hud = mob_parent.hud_used
- if(hud?.infodisplay)
- hud.infodisplay -= mood_screen_object
+
QDEL_NULL(mood_screen_object)
+ if (!QDELETED(hud))
+ hud.show_hud(hud.hud_version)
UnregisterSignal(hud, COMSIG_QDELETING)
/// Handles clicking on the mood HUD object
diff --git a/code/datums/status_effects/debuffs/screwy_hud.dm b/code/datums/status_effects/debuffs/screwy_hud.dm
index 10c20112160..4779db579c6 100644
--- a/code/datums/status_effects/debuffs/screwy_hud.dm
+++ b/code/datums/status_effects/debuffs/screwy_hud.dm
@@ -40,7 +40,7 @@
if(other_screwy_hud.priority > priority)
return
- source.hud_used.healths.icon_state = override_icon
+ source.hud_used?.screen_objects[HUD_MOB_HEALTH]?.icon_state = override_icon
return COMPONENT_OVERRIDE_HEALTH_HUD
/datum/status_effect/grouped/screwy_hud/fake_dead
diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm
index baab88cf239..472f9c6baa6 100644
--- a/code/datums/storage/storage.dm
+++ b/code/datums/storage/storage.dm
@@ -718,9 +718,12 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
SIGNAL_HANDLER
for(var/mob/user as anything in is_using)
- user.hud_used?.open_containers -= gone
+ if (user.hud_used?.screen_groups[HUD_GROUP_STORAGE])
+ user.hud_used.screen_groups[HUD_GROUP_STORAGE] -= gone
+
if(!user.client)
continue
+
var/client/cuser = user.client
cuser.screen -= gone
@@ -1086,9 +1089,10 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
LAZYOR(is_using, to_show)
- to_show.hud_used.open_containers |= storage_interfaces[to_show].list_ui_elements()
+ // Don't add to screen_objects as that one gets its contents actually deleted
+ LAZYOR(to_show.hud_used.screen_groups[HUD_GROUP_STORAGE], storage_interfaces[to_show].list_ui_elements())
to_show.client.screen |= storage_interfaces[to_show].list_ui_elements()
- to_show.hud_used.open_containers |= real_location.contents
+ LAZYOR(to_show.hud_used.screen_groups[HUD_GROUP_STORAGE], real_location.contents)
to_show.client.screen |= real_location.contents
return TRUE
@@ -1116,9 +1120,9 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
if(to_hide.client)
to_hide.client.screen -= storage_interfaces[to_hide].list_ui_elements()
to_hide.client.screen -= real_location.contents
- if(to_hide.hud_used)
- to_hide.hud_used.open_containers -= storage_interfaces[to_hide].list_ui_elements()
- to_hide.hud_used.open_containers -= real_location.contents
+ if(to_hide.hud_used.screen_groups[HUD_GROUP_STORAGE])
+ to_hide.hud_used.screen_groups[HUD_GROUP_STORAGE] -= storage_interfaces[to_hide].list_ui_elements()
+ to_hide.hud_used.screen_groups[HUD_GROUP_STORAGE] -= real_location.contents
QDEL_NULL(storage_interfaces[to_hide])
storage_interfaces -= to_hide
diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm
index f6ba5f3acb9..695af1eaef9 100644
--- a/code/datums/wounds/bones.dm
+++ b/code/datums/wounds/bones.dm
@@ -286,7 +286,7 @@
/datum/wound/blunt/bone/moderate/try_handling(mob/living/user)
if(user.usable_hands <= 0 || user.pulling != victim)
return FALSE
- if(!isnull(user.hud_used?.zone_select) && user.zone_selected != limb.body_zone)
+ if(!isnull(user.hud_used?.screen_objects[HUD_MOB_ZONE_SELECTOR]) && user.zone_selected != limb.body_zone)
return FALSE
if(user.grab_state == GRAB_PASSIVE)
diff --git a/code/datums/wounds/cranial_fissure.dm b/code/datums/wounds/cranial_fissure.dm
index e26e3a97d9d..9a2fd0eb439 100644
--- a/code/datums/wounds/cranial_fissure.dm
+++ b/code/datums/wounds/cranial_fissure.dm
@@ -87,7 +87,7 @@
if (user.usable_hands <= 0 || user.combat_mode)
return FALSE
- if(!isnull(user.hud_used?.zone_select) && (user.zone_selected != BODY_ZONE_HEAD && user.zone_selected != BODY_ZONE_PRECISE_EYES))
+ if(!isnull(user.hud_used?.screen_objects[HUD_MOB_ZONE_SELECTOR]) && (user.zone_selected != BODY_ZONE_HEAD && user.zone_selected != BODY_ZONE_PRECISE_EYES))
return FALSE
if (victim.body_position != LYING_DOWN)
diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm
index 68f6d685ae8..5ed2e8695b7 100644
--- a/code/datums/wounds/slash.dm
+++ b/code/datums/wounds/slash.dm
@@ -181,7 +181,7 @@
/datum/wound/slash/flesh/try_handling(mob/living/user)
if(user.pulling != victim || !HAS_TRAIT(user, TRAIT_WOUND_LICKER) || !victim.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE))
return FALSE
- if(!isnull(user.hud_used?.zone_select) && user.zone_selected != limb.body_zone)
+ if(!isnull(user.hud_used?.screen_objects[HUD_MOB_ZONE_SELECTOR]) && user.zone_selected != limb.body_zone)
return FALSE
if(DOING_INTERACTION_WITH_TARGET(user, victim))
diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm
index 416f4c16fac..79d9b9279e0 100644
--- a/code/game/machinery/computer/operating_computer.dm
+++ b/code/game/machinery/computer/operating_computer.dm
@@ -148,7 +148,7 @@
if(!zone_found)
return
- var/atom/movable/screen/zone_sel/selector = user.hud_used?.zone_select
+ var/atom/movable/screen/zone_sel/selector = user.hud_used?.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector?.set_selected_zone(zone_found, user, FALSE)
LAZYREMOVE(zone_on_open, WEAKREF(user))
if(!LAZYLEN(zone_on_open))
@@ -257,7 +257,7 @@
if("change_zone")
if(params["new_zone"] in (GLOB.all_body_zones + GLOB.all_precise_body_zones))
target_zone = params["new_zone"]
- var/atom/movable/screen/zone_sel/selector = ui.user.hud_used?.zone_select
+ var/atom/movable/screen/zone_sel/selector = ui.user.hud_used?.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector?.set_selected_zone(params["new_zone"], ui.user, FALSE)
update_static_data_for_all_viewers()
return TRUE
diff --git a/code/game/machinery/computer/records/records.dm b/code/game/machinery/computer/records/records.dm
index 2f6e429c772..a860e66d4f7 100644
--- a/code/game/machinery/computer/records/records.dm
+++ b/code/game/machinery/computer/records/records.dm
@@ -111,7 +111,7 @@
if(user.client?.screen_maps[assigned_view])
return
- var/atom/movable/screen/map_view/char_preview/new_view = new(null, src)
+ var/atom/movable/screen/map_view/char_preview/new_view = new(null, null, src)
new_view.generate_view(assigned_view)
new_view.display_to(user, window)
return new_view
diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm
index 6a3ec38c3da..c58e46e7478 100644
--- a/code/game/objects/items/devices/multitool.dm
+++ b/code/game/objects/items/devices/multitool.dm
@@ -97,19 +97,27 @@
user.balloon_alert(user, balloon_message)
var/datum/hud/user_hud = user.hud_used
- if(!user_hud || !istype(user_hud, /datum/hud) || !islist(user_hud.infodisplay))
+ if(!user_hud)
return
- var/atom/movable/screen/multitool_arrow/arrow = new(null, user_hud)
+ var/atom/movable/screen/multitool_arrow/arrow = user_hud.add_screen_object(/atom/movable/screen/multitool_arrow, HUD_MULTITOOL_ARROW, HUD_GROUP_INFO, update_screen = TRUE)
arrow.color = arrow_color
- arrow.screen_loc = around_player
arrow.transform = matrix(dir2angle(dir), MATRIX_ROTATE)
-
- user_hud.infodisplay += arrow
- user_hud.show_hud(user_hud.hud_version)
-
QDEL_IN(arrow, 1.5 SECONDS)
+/atom/movable/screen/multitool_arrow
+ icon = 'icons/effects/96x96.dmi'
+ icon_state = "multitool_arrow"
+ pixel_x = -32
+ pixel_y = -32
+ screen_loc = around_player
+
+/atom/movable/screen/multitool_arrow/Destroy()
+ var/datum/hud/our_hud = hud
+ . = ..()
+ if (!QDELETED(our_hud))
+ INVOKE_ASYNC(our_hud, TYPE_PROC_REF(/datum/hud, show_hud), our_hud.hud_version)
+
/obj/item/multitool/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("[user] puts the [src] to [user.p_their()] chest. It looks like [user.p_theyre()] trying to pulse [user.p_their()] heart off!"))
return OXYLOSS//there's a reason it wasn't recommended by doctors
diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm
index 2fc737cb365..e6f8ad51e22 100644
--- a/code/modules/antagonists/blob/overmind.dm
+++ b/code/modules/antagonists/blob/overmind.dm
@@ -61,9 +61,6 @@ GLOBAL_LIST_EMPTY(blob_nodes)
/// The list of strains the blob can reroll for.
var/list/strain_choices
- ///The HUD given to blobs with their power
- var/atom/movable/screen/blob_power_display/blob_power_hud
-
/mob/eye/blob/Initialize(mapload, starting_points = OVERMIND_STARTING_POINTS)
ADD_TRAIT(src, TRAIT_BLOB_ALLY, INNATE_TRAIT)
validate_location()
@@ -85,14 +82,6 @@ GLOBAL_LIST_EMPTY(blob_nodes)
START_PROCESSING(SSobj, src)
GLOB.blob_telepathy_mobs |= src
-/mob/eye/blob/create_mob_hud()
- . = ..()
- if(!.)
- return
- blob_power_hud = new(null, src)
- hud_used.infodisplay += blob_power_hud
- hud_used.show_hud(hud_used.hud_version)
-
/mob/eye/blob/proc/validate_location()
var/turf/T = get_turf(src)
if(is_valid_turf(T))
@@ -263,7 +252,6 @@ GLOBAL_LIST_EMPTY(blob_nodes)
/mob/eye/blob/Destroy()
QDEL_NULL(blobstrain)
- QDEL_NULL(blob_power_hud)
// Clear references immediately without iterating to avoid blocking
all_blobs = null
@@ -304,15 +292,15 @@ GLOBAL_LIST_EMPTY(blob_nodes)
return FALSE
var/current_health = round((blob_core.get_integrity() / blob_core.max_integrity) * 100)
var/new_maptext = MAPTEXT("[current_health]%
")
- hud_used.healths.maptext = new_maptext
+ hud_used.screen_objects[HUD_MOB_HEALTH].maptext = new_maptext
for(var/mob/living/basic/blob_minion/blobbernaut/blobbernaut in blob_mobs)
- if(isnull(blobbernaut.overmind_hud))
- continue
- blobbernaut.overmind_hud.maptext = new_maptext
+ var/atom/movable/screen/overmind_hud = blobbernaut.hud_used?.screen_objects[HUD_BLOBBERNAUT_OVERMIND]
+ if (overmind_hud)
+ overmind_hud.maptext = new_maptext
/mob/eye/blob/proc/add_points(points)
blob_points = clamp(blob_points + points, 0, max_blob_points)
- blob_power_hud.maptext = MAPTEXT("[round(blob_points)]
")
+ hud_used.screen_objects[HUD_BLOB_POWER_DISPLAY].maptext = MAPTEXT("[round(blob_points)]
")
/mob/eye/blob/say(
message,
diff --git a/code/modules/antagonists/blood_worm/blood_worm_host_handling.dm b/code/modules/antagonists/blood_worm/blood_worm_host_handling.dm
index 67543842cd0..2b87fd4c9f6 100644
--- a/code/modules/antagonists/blood_worm/blood_worm_host_handling.dm
+++ b/code/modules/antagonists/blood_worm/blood_worm_host_handling.dm
@@ -132,7 +132,7 @@
host.remove_blood_volume_modifier(REF(src))
sync_health(already_ejecting = TRUE)
- remove_host_hud()
+ host.hud_used?.remove_screen_object(HUD_MOB_BLOOD_LEVEL)
host.set_blood_volume(0)
@@ -245,16 +245,8 @@
UnregisterSignal(host, COMSIG_MOB_HUD_CREATED)
var/datum/hud/hud = host.hud_used
- blood_display = new(null, hud)
- hud.infodisplay += blood_display
- hud.show_hud(hud.hud_version)
-
-/mob/living/basic/blood_worm/proc/remove_host_hud()
- var/datum/hud/hud = host.hud_used
-
- if (!hud)
- QDEL_NULL(blood_display)
+ var/atom/movable/screen/blood_level/blood_display = hud.screen_objects[HUD_MOB_BLOOD_LEVEL]
+ if (blood_display)
return
- hud.infodisplay -= blood_display
- QDEL_NULL(blood_display)
+ blood_display = hud.add_screen_object(/atom/movable/screen/blood_level, HUD_MOB_BLOOD_LEVEL, HUD_GROUP_INFO, update_screen = TRUE)
diff --git a/code/modules/antagonists/blood_worm/blood_worm_mob.dm b/code/modules/antagonists/blood_worm/blood_worm_mob.dm
index a3a960abcd9..6fe2a41391f 100644
--- a/code/modules/antagonists/blood_worm/blood_worm_mob.dm
+++ b/code/modules/antagonists/blood_worm/blood_worm_mob.dm
@@ -62,9 +62,6 @@
/// This mob is always dead as it's just a mind holder.
var/mob/living/blood_worm_host/backseat
- /// The blood display on the left side of the screen, which is shown to the blood worm while in a host, if any.
- var/atom/movable/screen/blood_level/blood_display
-
// Innate and shared actions
/// Typed, please initialize with a proper action subtype. (empty = no action)
diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm
index ad138d35d56..1fdf17ef8d7 100644
--- a/code/modules/antagonists/changeling/changeling.dm
+++ b/code/modules/antagonists/changeling/changeling.dm
@@ -71,11 +71,6 @@
/// A reference to our cellular emporium action (which opens the UI for the datum).
var/datum/action/cellular_emporium/emporium_action
- /// UI displaying how many chems we have
- var/atom/movable/screen/ling/chems/lingchemdisplay
- /// UI displayng our currently active sting
- var/atom/movable/screen/ling/sting/lingstingdisplay
-
/// The name of our "hive" that our ling came from. Flavor.
var/hive_name
@@ -144,23 +139,14 @@
RegisterSignal(living_mob, COMSIG_LIVING_LIFE, PROC_REF(on_life))
RegisterSignal(living_mob, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(on_fullhealed))
RegisterSignal(living_mob, COMSIG_CARBON_GAIN_ORGAN, PROC_REF(new_brain))
+ RegisterSignal(living_mob, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
RegisterSignals(living_mob, list(COMSIG_MOB_MIDDLECLICKON, COMSIG_MOB_ALTCLICKON), PROC_REF(on_click_sting))
ADD_TRAIT(living_mob, TRAIT_FAKE_SOULLESS, CHANGELING_TRAIT)
ADD_TRAIT(living_mob, TRAIT_BRAINLESS_CARBON, CHANGELING_TRAIT)
ADD_TRAIT(living_mob, TRAIT_CHANGELING_HIVEMIND, CHANGELING_TRAIT)
- if(living_mob.hud_used)
- var/datum/hud/hud_used = living_mob.hud_used
-
- lingchemdisplay = new /atom/movable/screen/ling/chems(null, hud_used)
- hud_used.infodisplay += lingchemdisplay
-
- lingstingdisplay = new /atom/movable/screen/ling/sting(null, hud_used)
- hud_used.infodisplay += lingstingdisplay
-
- hud_used.show_hud(hud_used.hud_version)
- else
- RegisterSignal(living_mob, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
+ if (living_mob.hud_used)
+ on_hud_created()
make_brain_decoy(living_mob)
@@ -193,14 +179,8 @@
SIGNAL_HANDLER
var/datum/hud/ling_hud = owner.current.hud_used
-
- lingchemdisplay = new(null, ling_hud)
- ling_hud.infodisplay += lingchemdisplay
-
- lingstingdisplay = new(null, ling_hud)
- ling_hud.infodisplay += lingstingdisplay
-
- ling_hud.show_hud(ling_hud.hud_version)
+ ling_hud.add_screen_object(/atom/movable/screen/ling/chems, HUD_CHANGELING_CHEMS, HUD_GROUP_INFO)
+ ling_hud.add_screen_object(/atom/movable/screen/ling/sting, HUD_CHANGELING_STING, HUD_GROUP_INFO, update_screen = TRUE)
/datum/antagonist/changeling/proc/new_brain(mob/living/carbon/ling, obj/item/organ/new_brain)
SIGNAL_HANDLER
@@ -228,14 +208,12 @@
for(var/mob/eye/imaginary_friend/hivemind/hivemind_member in living_mob.imaginary_group)
qdel(hivemind_member)
- if(living_mob.hud_used)
- var/datum/hud/hud_used = living_mob.hud_used
-
- hud_used.infodisplay -= lingchemdisplay
- hud_used.infodisplay -= lingstingdisplay
- QDEL_NULL(lingchemdisplay)
- QDEL_NULL(lingstingdisplay)
+ if(!living_mob.hud_used)
+ return
+ var/datum/hud/hud_used = living_mob.hud_used
+ hud_used.remove_screen_object(HUD_CHANGELING_CHEMS, update = FALSE)
+ hud_used.remove_screen_object(HUD_CHANGELING_STING)
// The old body's brain still remains a decoy, I guess?
/datum/antagonist/changeling/on_removal()
@@ -351,12 +329,13 @@
///Updates the Changeling's chemical HUD to display the information we want it to (chem charges, or max if hovered over).
/datum/antagonist/changeling/proc/update_chemical_hud(amount)
- if(isnull(lingchemdisplay))
+ var/atom/movable/screen/ling/chems/chems = owner.current?.hud_used?.screen_objects[HUD_CHANGELING_CHEMS]
+ if(isnull(chems))
return
- if(lingchemdisplay.hovering)
- lingchemdisplay.maptext = FORMAT_CHEM_MAX_TEXT(total_chem_storage)
+ if(chems.hovering)
+ chems.maptext = FORMAT_CHEM_MAX_TEXT(total_chem_storage)
else
- lingchemdisplay.maptext = FORMAT_CHEM_CHARGES_TEXT(amount)
+ chems.maptext = FORMAT_CHEM_CHARGES_TEXT(amount)
/*
* Remove changeling powers from the current Changeling's purchased_powers list.
diff --git a/code/modules/antagonists/changeling/powers/tiny_prick.dm b/code/modules/antagonists/changeling/powers/tiny_prick.dm
index 91d7f8ba059..3368417c2c6 100644
--- a/code/modules/antagonists/changeling/powers/tiny_prick.dm
+++ b/code/modules/antagonists/changeling/powers/tiny_prick.dm
@@ -1,7 +1,8 @@
/datum/action/changeling/sting//parent path, not meant for users afaik
- name = "Tiny Prick"
+ name = "Tiny Prick" //cellularemporium uses `nameToIconState` to button icon state must match this, on top of matching the hud below.
desc = "Stabby stabby"
category = "stings"
+ button_icon_state = "sting_null" //This must be equal to the icon state for `/atom/movable/screen/ling/sting`
/datum/action/changeling/sting/Trigger(mob/clicker, trigger_flags)
var/mob/user = owner
@@ -21,16 +22,20 @@
var/datum/antagonist/changeling/changeling = IS_CHANGELING(user)
changeling.chosen_sting = src
- changeling.lingstingdisplay.icon_state = button_icon_state
- changeling.lingstingdisplay.SetInvisibility(0, id=type)
+ var/atom/movable/screen/ling/sting/sting = user.hud_used?.screen_objects[HUD_CHANGELING_STING]
+ if (sting)
+ sting.icon_state = button_icon_state
+ sting.SetInvisibility(0, id=type)
/datum/action/changeling/sting/proc/unset_sting(mob/user)
to_chat(user, span_warning("We retract our sting, we can't sting anyone for now."))
var/datum/antagonist/changeling/changeling = IS_CHANGELING(user)
changeling.chosen_sting = null
- changeling.lingstingdisplay.icon_state = null
- changeling.lingstingdisplay.RemoveInvisibility(type)
+ var/atom/movable/screen/ling/sting/sting = user.hud_used?.screen_objects[HUD_CHANGELING_STING]
+ if (sting)
+ sting.icon_state = null
+ sting.RemoveInvisibility(type)
/mob/living/carbon/proc/unset_sting()
if(mind)
@@ -71,7 +76,7 @@
For complex humanoids, the transformation is temporarily, but the duration is paused while the victim is dead or in stasis. \
For more simple humanoids, such as monkeys, the transformation is permanent. \
Does not provide a warning to others. Mutations will not be transferred."
- button_icon_state = "sting_transform"
+ button_icon_state = "transformation_sting"
chemical_cost = 33 // Low enough that you can sting only two people in quick succession
dna_cost = 2
/// A reference to our active profile, which we grab DNA from
diff --git a/code/modules/antagonists/cult/datums/cult_team.dm b/code/modules/antagonists/cult/datums/cult_team.dm
index 130683a9046..939938f621c 100644
--- a/code/modules/antagonists/cult/datums/cult_team.dm
+++ b/code/modules/antagonists/cult/datums/cult_team.dm
@@ -169,7 +169,8 @@
SEND_SOUND(cultist.current, sound(SFX_HALLUCINATION_OVER_HERE, 0, 1, 75))
cultist.current.client.images += blood_target_image
if (cultist.current.hud_used)
- new /atom/movable/screen/navigate_arrow(null, cultist.current.hud_used, get_turf(new_target), COLOR_CULT_RED)
+ var/atom/movable/screen/navigate_arrow/arrow = cultist.current.hud_used.add_screen_object(/atom/movable/screen/navigate_arrow, HUD_CULTIST_ARROW, HUD_GROUP_INFO, update_screen = TRUE)
+ arrow.start_effect(get_turf(new_target), COLOR_CULT_RED)
if(duration != INFINITY)
blood_target_reset_timer = addtimer(CALLBACK(src, PROC_REF(unset_blood_target)), duration, TIMER_STOPPABLE)
diff --git a/code/modules/antagonists/heretic/heretic_living_heart.dm b/code/modules/antagonists/heretic/heretic_living_heart.dm
index f8f18a8188e..78256b12a63 100644
--- a/code/modules/antagonists/heretic/heretic_living_heart.dm
+++ b/code/modules/antagonists/heretic/heretic_living_heart.dm
@@ -249,7 +249,8 @@
arrow_color = COLOR_RED
if(owner.hud_used)
- new /atom/movable/screen/navigate_arrow(null, owner.hud_used, their_turf, arrow_color)
+ var/atom/movable/screen/navigate_arrow/arrow = owner.hud_used.add_screen_object(/atom/movable/screen/navigate_arrow, HUD_HERETIC_ARROW, HUD_GROUP_INFO, update_screen = TRUE)
+ arrow.start_effect(their_turf, arrow_color)
if(ismob(tracked_thing))
var/mob/tracked_mob = tracked_thing
@@ -265,25 +266,21 @@
pixel_x = -32
pixel_y = -32
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ screen_loc = around_player
-/atom/movable/screen/navigate_arrow/Initialize(mapload, datum/hud/hud_owner, turf/tracked_turf, arrow_color)
- . = ..()
+/atom/movable/screen/navigate_arrow/proc/start_effect(turf/tracked_turf, arrow_color)
var/mob/owner = get_mob()
if (owner)
animate(src, transform = matrix(get_angle(owner, tracked_turf), MATRIX_ROTATE), 0.2 SECONDS)
- screen_loc = around_player
color = arrow_color
- if (hud)
- hud.infodisplay += src
- hud.show_hud(hud.hud_version)
addtimer(CALLBACK(src, PROC_REF(end_effect)), 1.6 SECONDS)
+/atom/movable/screen/navigate_arrow/Destroy()
+ var/datum/hud/our_hud = hud
+ . = ..()
+ if (!QDELETED(our_hud))
+ INVOKE_ASYNC(our_hud, TYPE_PROC_REF(/datum/hud, show_hud), our_hud.hud_version)
+
/atom/movable/screen/navigate_arrow/proc/end_effect()
icon_state = "navigate_arrow_disappear"
- addtimer(CALLBACK(src, PROC_REF(null_arrow)), 0.4 SECONDS)
-
-/atom/movable/screen/navigate_arrow/proc/null_arrow()
- if (hud)
- hud.infodisplay -= src
- hud.show_hud(hud.hud_version)
- qdel(src)
+ QDEL_IN(src, 0.4 SECONDS)
diff --git a/code/modules/antagonists/heretic/items/heretic_armor.dm b/code/modules/antagonists/heretic/items/heretic_armor.dm
index 8e496353fae..20cdbed7a9a 100644
--- a/code/modules/antagonists/heretic/items/heretic_armor.dm
+++ b/code/modules/antagonists/heretic/items/heretic_armor.dm
@@ -533,8 +533,6 @@
TRAIT_PACIFISM,
TRAIT_NOHUNGER
)
- /// Hud that gets shown to the wearer, gives a rough estimate of their current brain damage
- var/atom/movable/screen/moon_health/health_hud
/// Boolean if you are brain dead so the sound doesn't spam during the delay
var/braindead = FALSE
//---- Messages that get sent when someone wearing the moon robes is attacked
@@ -624,8 +622,7 @@
if(our_brain)
REMOVE_TRAIT(our_brain, TRAIT_BRAIN_DAMAGE_NODEATH, REF(src))
braindead = FALSE
- if(health_hud in user.hud_used.infodisplay)
- on_hud_remove(user)
+ on_hud_remove(user)
/obj/item/clothing/suit/hooded/cultrobes/eldritch/moon/proc/on_apply_modifiers(mob/living/user, damage_mods, damage, damagetype, def_zone, sharpness, attack_direction, attacking_item)
SIGNAL_HANDLER
@@ -655,35 +652,30 @@
/obj/item/clothing/suit/hooded/cultrobes/eldritch/moon/proc/on_hud_created(mob/living/carbon/human/wearer)
SIGNAL_HANDLER
var/datum/hud/original_hud = wearer.hud_used
- // Remove the old health elements
- var/list/to_remove = list(/atom/movable/screen/stamina, /atom/movable/screen/healths, /atom/movable/screen/healthdoll/human)
- for(var/removing in original_hud.infodisplay)
- if(is_type_in_list(removing, to_remove))
- original_hud.infodisplay -= removing
- QDEL_NULL(removing)
+
+ for(var/removing in list(HUD_MOB_STAMINA, HUD_MOB_HEALTH, HUD_MOB_HEALTHDOLL))
+ var/atom/movable/screen/to_remove = original_hud.screen_objects[removing]
+ if (to_remove)
+ to_remove.SetInvisibility(INVISIBILITY_ABSTRACT, type)
wearer.mob_mood.unmodify_hud()
// Add the moon health hud element
- health_hud = new(null, original_hud)
- original_hud.infodisplay += health_hud
- original_hud.show_hud(original_hud.hud_version)
+ original_hud.add_screen_object(/atom/movable/screen/moon_health, HUD_HERETIC_MOON_HEALTH, HUD_GROUP_INFO, update_screen = TRUE)
UnregisterSignal(wearer, COMSIG_MOB_HUD_CREATED)
signal_registered -= COMSIG_MOB_HUD_CREATED
/// Removes the HUD element from the wearer
/obj/item/clothing/suit/hooded/cultrobes/eldritch/moon/proc/on_hud_remove(mob/living/carbon/human/wearer)
var/datum/hud/original_hud = wearer.hud_used
- original_hud.infodisplay -= health_hud
- QDEL_NULL(health_hud)
+ QDEL_NULL(original_hud.screen_objects[HUD_HERETIC_MOON_HEALTH])
// Restore the old health elements
- var/atom/movable/screen/stamina/stamina_hud = new(null, original_hud)
- var/atom/movable/screen/healths/old_health_hud = new(null, original_hud)
- var/atom/movable/screen/healthdoll/human/health_doll_hud = new(null, original_hud)
- original_hud.infodisplay += stamina_hud
- original_hud.infodisplay += old_health_hud
- original_hud.infodisplay += health_doll_hud
+ for(var/restoring in list(HUD_MOB_STAMINA, HUD_MOB_HEALTH, HUD_MOB_HEALTHDOLL))
+ var/atom/movable/screen/to_restore = original_hud.screen_objects[restoring]
+ if (to_restore)
+ to_restore.RemoveInvisibility(type)
+
+ // Updates HUD on its own
wearer.mob_mood.modify_hud()
- original_hud.show_hud(original_hud.hud_version)
/obj/item/clothing/suit/hooded/cultrobes/eldritch/moon/can_mob_unequip(mob/user)
if(!ishuman(user))
diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm
index 087f9b6a16b..d676c284daa 100644
--- a/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm
+++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/perks.dm
@@ -7,44 +7,28 @@
requires_wizard_garb = FALSE
/// Icon that will be shown on wizard hud when purchasing a perk.
var/hud_icon
- /// Type path to perks hud.
- var/atom/movable/screen/perk/hud_to_show = /atom/movable/screen/perk
/datum/spellbook_entry/perks/buy_spell(mob/living/carbon/human/user, obj/item/spellbook/book, log_buy)
var/datum/antagonist/wizard/wizard_datum = user.mind.has_antag_datum(/datum/antagonist/wizard)
if(wizard_datum)
wizard_datum.perks += src
- create_hud_icon(user, wizard_datum)
+ RegisterSignal(user, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
+ if (user.hud_used)
+ on_hud_created()
to_chat(user, span_notice("You got a new perk: [src.name]."))
log_purchase(user.key)
return TRUE
-/datum/spellbook_entry/perks/proc/create_compact_button(mob/living/carbon/human/user, datum/antagonist/wizard/wizard_datum)
- var/datum/hud/user_hud = user.hud_used
- wizard_datum.compact_button = new /atom/movable/screen/perk/more(null, user_hud)
- wizard_datum.compact_button.screen_loc = ui_perk_position(0)
- user_hud.infodisplay += wizard_datum.compact_button
- user_hud.show_hud(user_hud.hud_version)
-
-/datum/spellbook_entry/perks/proc/create_hud_icon(mob/living/carbon/human/user, datum/antagonist/wizard/wizard_datum)
- if(user.hud_used)
- var/datum/hud/user_hud = user.hud_used
- if(isnull(wizard_datum.compact_button))
- create_compact_button(user, wizard_datum)
- hud_to_show = new hud_to_show(null, user_hud)
- hud_to_show.name = name
- hud_to_show.icon_state = hud_icon
- hud_to_show.screen_loc = ui_perk_position(wizard_datum.perks.len)
- user_hud.infodisplay += hud_to_show
- user_hud.show_hud(user_hud.hud_version)
- wizard_datum.compact_button.perks_on_hud += hud_to_show
- else
- RegisterSignal(user, COMSIG_MOB_HUD_CREATED, wizard_datum, PROC_REF(on_hud_created))
-
/datum/spellbook_entry/perks/proc/on_hud_created(mob/living/carbon/human/user, datum/antagonist/wizard/wizard_datum)
SIGNAL_HANDLER
- create_hud_icon(user, wizard_datum)
+ var/datum/hud/user_hud = user.hud_used
+ if(!user_hud.screen_objects[HUD_WIZARD_COMPACT_PERKS])
+ user_hud.add_screen_object(/atom/movable/screen/perk/more, HUD_WIZARD_COMPACT_PERKS, HUD_GROUP_INFO, ui_loc = ui_perk_position(0), update_screen = TRUE)
+
+ var/atom/movable/screen/perk/perk = user_hud.add_screen_object(/atom/movable/screen/perk, HUD_WIZARD_PERK(length(wizard_datum.perks)), HUD_GROUP_INFO, ui_loc = ui_perk_position(length(wizard_datum.perks)), update_screen = TRUE)
+ perk.name = name
+ perk.icon_state = hud_icon
/datum/spellbook_entry/perks/fourhands
name = "Four Hands"
diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm
index ce38b05c426..d76d90a35c8 100644
--- a/code/modules/antagonists/wizard/wizard.dm
+++ b/code/modules/antagonists/wizard/wizard.dm
@@ -28,8 +28,6 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key)
var/datum/action/cooldown/grand_ritual/ritual
/// Perks that wizard learn
var/list/perks = list()
- /// Button that hide perks hud.
- var/atom/movable/screen/perk/more/compact_button
/datum/antagonist/wizard_minion
name = "Wizard Minion"
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index dd280d120f5..af6789d02f4 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -295,7 +295,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
return TRUE
/datum/preferences/proc/create_character_preview_view(mob/user)
- character_preview_view = new(null, src)
+ character_preview_view = new(null, null, src)
character_preview_view.generate_view("character_preview_[REF(character_preview_view)]")
character_preview_view.update_body()
@@ -348,7 +348,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
/// Whether we show current job clothes or nude/loadout only
var/show_job_clothes = TRUE
-/atom/movable/screen/map_view/char_preview/Initialize(mapload, datum/preferences/preferences)
+/atom/movable/screen/map_view/char_preview/Initialize(mapload, datum/hud/hud_owner, datum/preferences/preferences)
. = ..()
src.preferences = preferences
diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm
index d5283c7c20c..f4535059a05 100644
--- a/code/modules/clothing/spacesuits/_spacesuits.dm
+++ b/code/modules/clothing/spacesuits/_spacesuits.dm
@@ -123,7 +123,9 @@
STOP_PROCESSING(SSobj, src)
var/mob/living/carbon/human/human_user = user
if(istype(human_user) && human_user.hud_used)
- human_user.hud_used.spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_NO_ICON)
+ var/atom/movable/screen/spacesuit/spacesuit_hud = human_user.hud_used.screen_objects[HUD_MOB_SPACESUIT]
+ if (spacesuit_hud)
+ spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_NO_ICON)
// Space Suit temperature regulation and power usage
/obj/item/clothing/suit/space/process(seconds_per_tick)
@@ -159,7 +161,9 @@
QDEL_NULL(cell)
var/mob/living/carbon/human/human = src.loc
if(istype(human) && human.hud_used)
- human.hud_used.spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_NO_ICON)
+ var/atom/movable/screen/spacesuit/spacesuit_hud = human.hud_used.screen_objects[HUD_MOB_SPACESUIT]
+ if (spacesuit_hud)
+ spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_NO_ICON)
STOP_PROCESSING(SSobj, src)
return ..()
@@ -306,8 +310,12 @@
if(!show_hud || human.wear_suit != src || isnull(human.hud_used))
return
+ var/atom/movable/screen/spacesuit/spacesuit_hud = human.hud_used.screen_objects[HUD_MOB_SPACESUIT]
+ if(!spacesuit_hud)
+ return
+
if(!cell)
- human.hud_used.spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_MISSING, 0, thermal_on)
+ spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_MISSING, 0, thermal_on)
return
var/cell_percent = cell.percent()
@@ -315,17 +323,17 @@
// if there is, whethere the cell's capacity indicates high, medium or low
// charge based on it.
if(cell.charge < THERMAL_REGULATOR_COST)
- human.hud_used.spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_EMPTY, cell_percent, thermal_on)
+ spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_EMPTY, cell_percent, thermal_on)
return
switch(cell_percent)
if(0 to 20)
- human.hud_used.spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_VERY_LOW, cell_percent, thermal_on)
+ spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_VERY_LOW, cell_percent, thermal_on)
if(21 to 40)
- human.hud_used.spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_LOW, cell_percent, thermal_on)
+ spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_LOW, cell_percent, thermal_on)
if(41 to 60)
- human.hud_used.spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_MID, cell_percent, thermal_on)
+ spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_MID, cell_percent, thermal_on)
if(61 to 100)
- human.hud_used.spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_HIGH, cell_percent, thermal_on)
+ spacesuit_hud.update_spacesuit_hud_icon(SPACESUIT_CELL_HIGH, cell_percent, thermal_on)
// zap the cell if we get hit with an emp
/obj/item/clothing/suit/space/emp_act(severity)
diff --git a/code/modules/engineering/tools/multitool.dm b/code/modules/engineering/tools/multitool.dm
deleted file mode 100644
index 47f4857ffc3..00000000000
--- a/code/modules/engineering/tools/multitool.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/atom/movable/screen/multitool_arrow
- icon = 'icons/effects/96x96.dmi'
- icon_state = "multitool_arrow"
- pixel_x = -32
- pixel_y = -32
-
-/atom/movable/screen/multitool_arrow/Destroy()
- if(hud)
- hud.infodisplay -= src
- INVOKE_ASYNC(hud, TYPE_PROC_REF(/datum/hud, show_hud), hud.hud_version)
- return ..()
diff --git a/code/modules/escape_menu/escape_menu.dm b/code/modules/escape_menu/escape_menu.dm
index 842d70a8c77..0042a6f7332 100644
--- a/code/modules/escape_menu/escape_menu.dm
+++ b/code/modules/escape_menu/escape_menu.dm
@@ -151,9 +151,6 @@ GLOBAL_LIST_EMPTY(escape_menus)
plane = ESCAPE_MENU_PLANE
clear_with_screen = FALSE
-// The escape menu can be opened before SSatoms
-INITIALIZE_IMMEDIATE(/atom/movable/screen/escape_menu)
-
#undef PAGE_HOME
#undef PAGE_LEAVE_BODY
#undef PAGE_QUIT_GAME
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 80d383faba9..1a8e2a7c00f 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -644,8 +644,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
else
remove_data_huds()
update_sight()
- for(var/atom/movable/screen/ghost/hudbox/hud in hud_used?.static_inventory)
- if(hud.relevant_flag & toggled)
+ for(var/hud_key in hud_used?.screen_objects)
+ var/atom/movable/screen/ghost/hudbox/hud = hud_used.screen_objects[hud_key]
+ if(istype(hud) && (hud.relevant_flag & toggled))
hud.update_appearance(UPDATE_ICON_STATE)
// This is the ghost's follow verb with an argument
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index 4c57ced89bb..5fd9172e160 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -675,9 +675,13 @@
dropItemToGround(held_items[i])
held_items.len = amt
- if(hud_used)
- hud_used.build_hand_slots()
- hud_used.healthdoll.update_body_zones()
+ if(!hud_used)
+ return
+
+ hud_used.build_hand_slots(update_hud = TRUE)
+ var/atom/movable/screen/healthdoll/doll = hud_used.screen_objects[HUD_MOB_HEALTHDOLL]
+ if(doll)
+ doll.update_body_zones()
//GetAllContents that is reasonable and not stupid
/mob/living/proc/get_all_gear(equipment_flags = INCLUDE_ACCESSORIES|INCLUDE_PROSTHETICS, recursive = TRUE)
diff --git a/code/modules/mob/living/basic/blob_minions/blobbernaut.dm b/code/modules/mob/living/basic/blob_minions/blobbernaut.dm
index bbc9c1be16f..703fd0d4d1d 100644
--- a/code/modules/mob/living/basic/blob_minions/blobbernaut.dm
+++ b/code/modules/mob/living/basic/blob_minions/blobbernaut.dm
@@ -27,8 +27,6 @@
mob_size = MOB_SIZE_LARGE
ai_controller = /datum/ai_controller/basic_controller/blobbernaut
loot = null
- ///The HUD given to blobbernauts, updated by the Blob itself
- var/atom/movable/screen/healths/blob/overmind/overmind_hud
///The overlay for veins.
var/mutable_appearance/vein_overlay
///The overlay for our eyes
@@ -53,11 +51,6 @@
AddComponent(/datum/component/tameable, food_types = food_types, tame_chance = 25, bonus_tame_chance = 15)
update_appearance()
-
-/mob/living/basic/blob_minion/blobbernaut/Destroy()
- QDEL_NULL(overmind_hud)
- return ..()
-
/mob/living/basic/blob_minion/blobbernaut/death(gibbed)
flick("[icon_state]_death", src)
playsound(src, 'sound/mobs/non-humanoids/blobmob/blobbernaut_death.ogg', 100, TRUE)
@@ -68,9 +61,7 @@
. = ..()
if(!.)
return
- overmind_hud = new(null, hud_used)
- hud_used.infodisplay += overmind_hud
- hud_used.show_hud(hud_used.hud_version)
+ hud_used.add_screen_object(/atom/movable/screen/healths/blob/overmind, HUD_BLOBBERNAUT_OVERMIND, HUD_GROUP_INFO, update_screen = TRUE)
/mob/living/basic/blob_minion/blobbernaut/on_strain_updated(mob/eye/blob/overmind, datum/blobstrain/new_strain)
. = ..()
diff --git a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
index 436f8e27c89..ea32e7e5d6d 100644
--- a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
+++ b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
@@ -182,7 +182,7 @@
essencecolor = "#9A5ACB" //oh boy you've got a lot of essence
else if(essence <= 0)
essencecolor = "#1D2953" //oh jeez you're dying
- hud_used.healths.maptext = MAPTEXT("[essence]E
")
+ hud_used.screen_objects[HUD_MOB_HEALTH]?.maptext = MAPTEXT("[essence]E
")
/mob/living/basic/revenant/say(
message,
diff --git a/code/modules/mob/living/carbon/alien/adult/alien_powers.dm b/code/modules/mob/living/carbon/alien/adult/alien_powers.dm
index 928b5e16bdd..5633d54fb53 100644
--- a/code/modules/mob/living/carbon/alien/adult/alien_powers.dm
+++ b/code/modules/mob/living/carbon/alien/adult/alien_powers.dm
@@ -390,12 +390,7 @@ Doesn't work on other aliens/AI.*/
var/obj/item/organ/alien/plasmavessel/vessel = get_organ_by_type(/obj/item/organ/alien/plasmavessel)
if(!vessel)
return FALSE
- vessel.stored_plasma = max(vessel.stored_plasma + amount,0)
- vessel.stored_plasma = min(vessel.stored_plasma, vessel.max_plasma) //upper limit of max_plasma, lower limit of 0
+ vessel.adjust_plasma(amount)
for(var/datum/action/cooldown/alien/ability in actions)
ability.build_all_button_icons()
return TRUE
-
-/mob/living/carbon/alien/adjustPlasma(amount)
- . = ..()
- updatePlasmaDisplay()
diff --git a/code/modules/mob/living/carbon/alien/adult/caste/hunter.dm b/code/modules/mob/living/carbon/alien/adult/caste/hunter.dm
index c056f663849..995235d5fa2 100644
--- a/code/modules/mob/living/carbon/alien/adult/caste/hunter.dm
+++ b/code/modules/mob/living/carbon/alien/adult/caste/hunter.dm
@@ -18,7 +18,6 @@
ORGAN_SLOT_EXTERNAL_TAIL = /obj/item/organ/tail/xeno,
)
- var/atom/movable/screen/leap_icon = null
///How fast does our pounce move us?
var/pounce_speed = 2
@@ -26,7 +25,8 @@
/mob/living/carbon/alien/adult/hunter/proc/toggle_leap(message = 1)
leap_on_click = !leap_on_click
- leap_icon.icon_state = "leap_[leap_on_click ? "on":"off"]"
+ var/atom/movable/screen/leap_icon = hud_used?.screen_objects[HUD_ALIEN_HUNTER_LEAP]
+ leap_icon?.icon_state = "leap_[leap_on_click ? "on":"off"]"
update_icons()
if(message)
to_chat(src, span_noticealien("You will now [leap_on_click ? "leap at":"slash at"] enemies!"))
diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm
index f5705c88494..ebbacdf2c02 100644
--- a/code/modules/mob/living/carbon/alien/organs.dm
+++ b/code/modules/mob/living/carbon/alien/organs.dm
@@ -56,38 +56,55 @@
//Instantly healing to max health in a single tick would be silly. If it takes 8 seconds to fire, then something's fucked.
var/delta_time_capped = min(delta_time, 8)
//If there are alien weeds on the ground then heal if needed or give some plasma
- if(locate(/obj/structure/alien/weeds) in owner.loc)
- if(owner.health >= owner.maxHealth)
- owner.adjustPlasma(plasma_rate * delta_time)
- else
- var/heal_amt = heal_rate
- if(!isalien(owner))
- heal_amt *= 0.2
- owner.adjustPlasma(0.5 * plasma_rate * delta_time_capped)
- owner.adjust_brute_loss(-heal_amt * delta_time_capped)
- owner.adjust_fire_loss(-heal_amt * delta_time_capped)
- owner.adjust_oxy_loss(-heal_amt * delta_time_capped)
- else
+ if(!(locate(/obj/structure/alien/weeds) in owner.loc))
owner.adjustPlasma(0.1 * plasma_rate * delta_time)
+ return
+
+ if(owner.health >= owner.maxHealth)
+ owner.adjustPlasma(plasma_rate * delta_time)
+ return
+
+ var/heal_amt = heal_rate
+ if(!isalien(owner))
+ heal_amt *= 0.2
+ owner.adjustPlasma(0.5 * plasma_rate * delta_time_capped)
+ owner.adjust_brute_loss(-heal_amt * delta_time_capped)
+ owner.adjust_fire_loss(-heal_amt * delta_time_capped)
+ owner.adjust_oxy_loss(-heal_amt * delta_time_capped)
+
+/obj/item/organ/alien/plasmavessel/proc/adjust_plasma(amount)
+ stored_plasma = clamp(stored_plasma + amount, 0, max_plasma)
+ update_plasma_display()
+
+/obj/item/organ/alien/plasmavessel/proc/on_hud_created(mob/source)
+ SIGNAL_HANDLER
+
+ if (!owner.hud_used.screen_objects[HUD_ALIEN_PLASMA_DISPLAY])
+ owner.hud_used.add_screen_object(/atom/movable/screen/alien/plasma_display, HUD_ALIEN_PLASMA_DISPLAY, HUD_GROUP_INFO, ui_loc = istype(owner.hud_used, /datum/hud/alien) ? null : ui_alienplasmadisplay_human, update_screen = TRUE)
+ update_plasma_display()
/obj/item/organ/alien/plasmavessel/on_mob_insert(mob/living/carbon/organ_owner)
. = ..()
- if(isalien(organ_owner))
- var/mob/living/carbon/alien/target_alien = organ_owner
- target_alien.updatePlasmaDisplay()
RegisterSignal(organ_owner, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(get_status_tab_item))
+ RegisterSignal(organ_owner, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
+ if (organ_owner.hud_used)
+ on_hud_created()
/obj/item/organ/alien/plasmavessel/on_mob_remove(mob/living/carbon/organ_owner)
. = ..()
- if(isalien(organ_owner))
- var/mob/living/carbon/alien/organ_owner_alien = organ_owner
- organ_owner_alien.updatePlasmaDisplay()
UnregisterSignal(organ_owner, COMSIG_MOB_GET_STATUS_TAB_ITEMS)
+ UnregisterSignal(organ_owner, COMSIG_MOB_HUD_CREATED)
+ organ_owner.hud_used?.remove_screen_object(HUD_ALIEN_PLASMA_DISPLAY)
/obj/item/organ/alien/plasmavessel/proc/get_status_tab_item(mob/living/carbon/source, list/items)
SIGNAL_HANDLER
items += "Plasma Stored: [stored_plasma]/[max_plasma]"
+/obj/item/organ/alien/plasmavessel/proc/update_plasma_display()
+ owner.hud_used?.screen_objects[HUD_ALIEN_PLASMA_DISPLAY]?.maptext = MAPTEXT( \
+ "[round(owner.getPlasma())]
" \
+ )
+
#define QUEEN_DEATH_DEBUFF_DURATION 2400
/obj/item/organ/alien/hivenode
diff --git a/code/modules/mob/living/carbon/alien/screen.dm b/code/modules/mob/living/carbon/alien/screen.dm
index ca75bb2d789..1526f78a320 100644
--- a/code/modules/mob/living/carbon/alien/screen.dm
+++ b/code/modules/mob/living/carbon/alien/screen.dm
@@ -1,33 +1,30 @@
-/mob/living/carbon/alien/proc/updatePlasmaDisplay()
- if(hud_used) //clientless aliens
- hud_used.alien_plasma_display.maptext = MAPTEXT("[round(getPlasma())]
")
-
-/mob/living/carbon/alien/larva/updatePlasmaDisplay()
- return
-
/mob/living/carbon/alien/proc/findQueen()
- if(hud_used)
- hud_used.alien_queen_finder.cut_overlays()
- var/mob/queen = get_alien_type(/mob/living/carbon/alien/adult/royal/queen)
- if(!queen)
- return
- var/turf/Q = get_turf(queen)
- var/turf/A = get_turf(src)
- if(Q.z != A.z) //The queen is on a different Z level, we cannot sense that far.
- return
- var/Qdir = get_dir(src, Q)
- var/Qdist = get_dist(src, Q)
- var/finder_icon = "finder_center" //Overlay showed when adjacent to or on top of the queen!
- switch(Qdist)
- if(2 to 7)
- finder_icon = "finder_near"
- if(8 to 20)
- finder_icon = "finder_med"
- if(21 to INFINITY)
- finder_icon = "finder_far"
- var/image/finder_eye = image('icons/hud/screen_alien.dmi', finder_icon, dir = Qdir)
- hud_used.alien_queen_finder.add_overlay(finder_eye)
+ if(!hud_used)
+ return
+ var/atom/movable/screen/alien/alien_queen_finder/finder = hud_used.screen_objects[HUD_ALIEN_QUEEN_FINDER]
+ if (!finder)
+ return
+ finder.cut_overlays()
+ var/mob/queen = get_alien_type(/mob/living/carbon/alien/adult/royal/queen)
+ if(!queen)
+ return
+ var/turf/Q = get_turf(queen)
+ var/turf/A = get_turf(src)
+ if(Q.z != A.z) //The queen is on a different Z level, we cannot sense that far.
+ return
+ var/Qdir = get_dir(src, Q)
+ var/Qdist = get_dist(src, Q)
+ var/finder_icon = "finder_center" //Overlay showed when adjacent to or on top of the queen!
+ switch(Qdist)
+ if(2 to 7)
+ finder_icon = "finder_near"
+ if(8 to 20)
+ finder_icon = "finder_med"
+ if(21 to INFINITY)
+ finder_icon = "finder_far"
+ var/image/finder_eye = image('icons/hud/screen_alien.dmi', finder_icon, dir = Qdir)
+ finder.add_overlay(finder_eye)
/mob/living/carbon/alien/adult/royal/queen/findQueen()
return //Queen already knows where she is. Hopefully.
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 514e7035cba..924227483a9 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -635,11 +635,16 @@
clear_fullscreen("brute")
/mob/living/carbon/update_health_hud(shown_health_amount)
- if(!client || !hud_used?.healths)
+ if(!client || !hud_used)
+ return
+
+ var/atom/movable/screen/healths/health_hud = hud_used.screen_objects[HUD_MOB_HEALTH]
+
+ if (!health_hud)
return
if(stat == DEAD)
- hud_used.healths.icon_state = "health7"
+ health_hud.icon_state = "health7"
return
if(SEND_SIGNAL(src, COMSIG_CARBON_UPDATING_HEALTH_HUD, shown_health_amount) & COMPONENT_OVERRIDE_HEALTH_HUD)
@@ -649,25 +654,11 @@
shown_health_amount = health
if(shown_health_amount >= maxHealth)
- hud_used.healths.icon_state = "health0"
-
- else if(shown_health_amount > maxHealth * 0.8)
- hud_used.healths.icon_state = "health1"
-
- else if(shown_health_amount > maxHealth * 0.6)
- hud_used.healths.icon_state = "health2"
-
- else if(shown_health_amount > maxHealth * 0.4)
- hud_used.healths.icon_state = "health3"
-
- else if(shown_health_amount > maxHealth*0.2)
- hud_used.healths.icon_state = "health4"
-
- else if(shown_health_amount > 0)
- hud_used.healths.icon_state = "health5"
-
+ health_hud.icon_state = "health0"
+ else if(shown_health_amount > 0 && maxHealth > 0)
+ health_hud.icon_state = "health[6 - ceil(shown_health_amount / (maxHealth * 0.2))]"
else
- hud_used.healths.icon_state = "health6"
+ health_hud.icon_state = "health6"
/mob/living/carbon/set_health(new_value)
. = ..()
diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm
index b759c290efe..fb1ceda9558 100644
--- a/code/modules/mob/living/carbon/carbon_update_icons.dm
+++ b/code/modules/mob/living/carbon/carbon_update_icons.dm
@@ -417,11 +417,11 @@
//update whether handcuffs appears on our hud.
/mob/living/carbon/proc/update_hud_handcuffed()
- if(hud_used)
- for(var/hand in hud_used.hand_slots)
- var/atom/movable/screen/inventory/hand/H = hud_used.hand_slots[hand]
- if(H)
- H.update_appearance()
+ if(!hud_used)
+ return
+
+ for(var/atom/movable/screen/inventory/hand/hand in hud_used.hand_slots)
+ hand.update_appearance()
//update whether our head item appears on our hud.
/mob/living/carbon/proc/update_hud_head(obj/item/I)
diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm
index 75dbe2f24e9..72f9968d250 100644
--- a/code/modules/mob/living/carbon/human/_species.dm
+++ b/code/modules/mob/living/carbon/human/_species.dm
@@ -381,7 +381,9 @@ GLOBAL_LIST_EMPTY(features_by_species)
human_who_gained_species.butcher_results = knife_butcher_results?.Copy()
//update body zones to match what they are supposed to have
- human_who_gained_species.hud_used?.healthdoll.update_body_zones()
+ var/atom/movable/screen/healthdoll/doll = human_who_gained_species.hud_used?.screen_objects[HUD_MOB_HEALTHDOLL]
+ if (doll)
+ doll.update_body_zones()
if(old_species.type != type)
replace_body(human_who_gained_species, src)
@@ -433,7 +435,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
human_who_gained_species.living_flags &= ~STOP_OVERLAY_UPDATE_BODY_PARTS
//we don't allow it to update during species transition, so update it now
- human_who_gained_species.hud_used?.healthdoll.update_appearance()
+ human_who_gained_species.hud_used?.screen_objects[HUD_MOB_HEALTHDOLL]?.update_appearance()
/**
* Proc called when a carbon is no longer this species.
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index bfac199095d..9d78211d91f 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -690,7 +690,7 @@
. = ..()
// Handles changing limb colors and stuff
if(!(living_flags & STOP_OVERLAY_UPDATE_BODY_PARTS))
- hud_used.healthdoll?.update_appearance()
+ hud_used.screen_objects[HUD_MOB_HEALTHDOLL]?.update_appearance()
/mob/living/carbon/human/fully_heal(heal_flags = HEAL_ALL)
if(heal_flags & HEAL_NEGATIVE_MUTATIONS)
diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm
index 0539776acbe..6013c6d2b92 100644
--- a/code/modules/mob/living/carbon/human/species_types/vampire.dm
+++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm
@@ -21,8 +21,6 @@
mutanttongue = /obj/item/organ/tongue/vampire
///some starter text sent to the vampire initially, because vampires have shit to do to stay alive
var/info_text = "You are a Vampire. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability."
- /// UI displaying how much blood we have
- var/atom/movable/screen/blood_level/blood_display
/datum/species/human/vampire/check_roundstart_eligible()
if(check_holidays(HALLOWEEN))
@@ -35,17 +33,14 @@
new_vampire.skin_tone = "albino"
new_vampire.update_body(0)
RegisterSignal(new_vampire, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby))
+ RegisterSignal(new_vampire, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
if(new_vampire.hud_used)
on_hud_created(new_vampire)
- else
- RegisterSignal(new_vampire, COMSIG_MOB_HUD_CREATED, PROC_REF(on_hud_created))
/datum/species/human/vampire/on_species_loss(mob/living/carbon/human/old_vampire, datum/species/new_species, pref_load)
. = ..()
UnregisterSignal(old_vampire, COMSIG_ATOM_ATTACKBY)
- if(blood_display)
- old_vampire.hud_used.infodisplay -= blood_display
- QDEL_NULL(blood_display)
+ old_vampire.hud_used?.remove_screen_object(HUD_MOB_BLOOD_LEVEL)
/datum/species/human/vampire/spec_life(mob/living/carbon/human/vampire, seconds_per_tick)
. = ..()
@@ -72,10 +67,7 @@
///Gives the blood HUD to the vampire so they always know how much blood they have.
/datum/species/human/vampire/proc/on_hud_created(mob/source)
SIGNAL_HANDLER
- var/datum/hud/blood_hud = source.hud_used
- blood_display = new(null, blood_hud)
- blood_hud.infodisplay += blood_display
- blood_hud.show_hud(blood_hud.hud_version)
+ source.hud_used.add_screen_object(/atom/movable/screen/blood_level, HUD_MOB_BLOOD_LEVEL, HUD_GROUP_INFO, update_screen = TRUE)
/datum/species/human/vampire/proc/on_attackby(mob/living/source, obj/item/attacking_item, mob/living/attacker, list/modifiers, list/attack_modifiers)
SIGNAL_HANDLER
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 9d6ca3159d6..a0a1ae072cc 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -761,15 +761,17 @@
/mob/living/update_rest_hud_icon()
. = ..()
- if(!.)
+ if(!. || !hud_used)
return FALSE
- if(!hud_used.sleep_icon || HAS_TRAIT(src, TRAIT_SLEEPIMMUNE))
+
+ var/atom/movable/screen/sleep/sleep_icon = hud_used.screen_objects[HUD_MOB_SLEEP]
+ if(!sleep_icon || HAS_TRAIT(src, TRAIT_SLEEPIMMUNE))
return TRUE
+
if(resting || HAS_TRAIT(src, TRAIT_FLOORED))
- hud_used.static_inventory |= hud_used.sleep_icon
+ sleep_icon.RemoveInvisibility(INVISIBILITY_SOURCE_SLEEP_HUD_BUTTON)
else
- hud_used.static_inventory -= hud_used.sleep_icon
- hud_used.show_hud(hud_used.hud_version)
+ sleep_icon.SetInvisibility(INVISIBILITY_ABSTRACT, INVISIBILITY_SOURCE_SLEEP_HUD_BUTTON)
return TRUE
//Recursive function to find everything a mob is holding. Really shitty proc tbh.
@@ -833,8 +835,8 @@
/mob/living/update_health_hud()
var/severity = 0
var/healthpercent = (health/maxHealth) * 100
- if(hud_used?.healthdoll) //to really put you in the boots of a simplemob
- var/atom/movable/screen/healthdoll/living/livingdoll = hud_used.healthdoll
+ var/atom/movable/screen/healthdoll/living/livingdoll = hud_used?.screen_objects[HUD_MOB_HEALTHDOLL]
+ if(istype(livingdoll)) //to really put you in the boots of a simplemob
switch(healthpercent)
if(100 to INFINITY)
severity = 0
@@ -859,6 +861,7 @@
mob_mask = icon('icons/hud/screen_gen.dmi', health_doll_icon_state) //swap to something generic if they have no special doll
livingdoll.add_filter("mob_shape_mask", 1, alpha_mask_filter(icon = mob_mask))
livingdoll.add_filter("inset_drop_shadow", 2, drop_shadow_filter(size = -1))
+
if(severity > 0)
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
else
@@ -1430,32 +1433,27 @@
update_stamina_hud()
/mob/living/update_stamina_hud(shown_stamina_loss)
- if(!client || !hud_used?.stamina)
+ if(!client || !hud_used)
+ return
+
+ var/atom/movable/screen/stamina/stamina = hud_used.screen_objects[HUD_MOB_STAMINA]
+ if (!stamina)
+ return
+
+ if(stat == DEAD)
+ stamina.icon_state = "stamina_dead"
return
var/stam_crit_threshold = maxHealth - crit_threshold
+ if(shown_stamina_loss == null)
+ shown_stamina_loss = get_stamina_loss()
- if(stat == DEAD)
- hud_used.stamina.icon_state = "stamina_dead"
+ if(shown_stamina_loss >= stam_crit_threshold)
+ stamina.icon_state = "stamina_crit"
+ else if(shown_stamina_loss > 0 && maxHealth > 0)
+ stamina.icon_state = "stamina_[6 - ceil(shown_stamina_loss / (maxHealth * 0.2))]"
else
-
- if(shown_stamina_loss == null)
- shown_stamina_loss = get_stamina_loss()
-
- if(shown_stamina_loss >= stam_crit_threshold)
- hud_used.stamina.icon_state = "stamina_crit"
- else if(shown_stamina_loss > maxHealth*0.8)
- hud_used.stamina.icon_state = "stamina_5"
- else if(shown_stamina_loss > maxHealth*0.6)
- hud_used.stamina.icon_state = "stamina_4"
- else if(shown_stamina_loss > maxHealth*0.4)
- hud_used.stamina.icon_state = "stamina_3"
- else if(shown_stamina_loss > maxHealth*0.2)
- hud_used.stamina.icon_state = "stamina_2"
- else if(shown_stamina_loss > 0)
- hud_used.stamina.icon_state = "stamina_1"
- else
- hud_used.stamina.icon_state = "stamina_full"
+ stamina.icon_state = "stamina_full"
/mob/living/carbon/alien/update_stamina()
return
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 68bcf1fee29..701b118ebdc 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -225,8 +225,7 @@
. = combat_mode
combat_mode = new_mode
SEND_SIGNAL(src, COMSIG_COMBAT_MODE_TOGGLED)
- if(hud_used?.action_intent)
- hud_used.action_intent.update_appearance()
+ hud_used?.screen_objects[HUD_MOB_INTENTS]?.update_appearance()
if(silent || !client?.prefs.read_preference(/datum/preference/toggle/sound_combatmode))
return
if(combat_mode)
diff --git a/code/modules/mob/living/living_fov.dm b/code/modules/mob/living/living_fov.dm
index a16cf111133..8c6c0833fbf 100644
--- a/code/modules/mob/living/living_fov.dm
+++ b/code/modules/mob/living/living_fov.dm
@@ -131,3 +131,5 @@
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
plane = FIELD_OF_VISION_BLOCKER_PLANE
screen_loc = "BOTTOM,LEFT"
+ hud_key = HUD_MOB_FOV_BLOCKER
+ hud_group_key = HUD_GROUP_SCREEN_OVERLAYS
diff --git a/code/modules/mob/living/living_item_handling.dm b/code/modules/mob/living/living_item_handling.dm
index 482e0099491..24b3e2692d1 100644
--- a/code/modules/mob/living/living_item_handling.dm
+++ b/code/modules/mob/living/living_item_handling.dm
@@ -17,7 +17,7 @@
return
throw_mode = THROW_MODE_DISABLED
if(hud_used)
- hud_used.throw_icon.icon_state = "act_throw"
+ hud_used.screen_objects[HUD_MOB_THROW]?.icon_state = "act_throw"
SEND_SIGNAL(src, COMSIG_LIVING_THROW_MODE_TOGGLE, throw_mode)
@@ -26,7 +26,7 @@
return
throw_mode = mode
if(hud_used)
- hud_used.throw_icon.icon_state = "act_throw_on"
+ hud_used.screen_objects[HUD_MOB_THROW]?.icon_state = "act_throw_on"
SEND_SIGNAL(src, COMSIG_LIVING_THROW_MODE_TOGGLE, throw_mode)
/mob/proc/throw_item(atom/target)
diff --git a/code/modules/mob/living/silicon/death.dm b/code/modules/mob/living/silicon/death.dm
index 8aff9b59278..1522555af70 100644
--- a/code/modules/mob/living/silicon/death.dm
+++ b/code/modules/mob/living/silicon/death.dm
@@ -8,12 +8,10 @@
/mob/living/silicon/set_stat(new_stat)
. = ..()
- if(. != DEAD)
+ if(. != DEAD || !hud_used)
return
// Clean up hud element used for the death sequence
- for(var/atom/movable/screen/cyborg_death/deathhud in hud_used?.always_visible_inventory)
- hud_used.always_visible_inventory -= deathhud
- qdel(deathhud)
+ hud_used.remove_screen_object(HUD_CYBORG_DEATH)
/mob/living/silicon/death(gibbed)
diag_hud_set_status()
@@ -38,10 +36,8 @@
if(get_oxy_loss() > 100)
cause_of_death = "Critically low power."
- var/atom/movable/screen/cyborg_death/deathhud = new(null, hud_used, cause_of_death)
- hud_used.always_visible_inventory += deathhud
- hud_used.show_hud(hud_used.hud_version)
- deathhud.run_animation()
+ var/atom/movable/screen/cyborg_death/deathhud = hud_used.add_screen_object(/atom/movable/screen/cyborg_death, HUD_CYBORG_DEATH, HUD_GROUP_SCREEN_OVERLAYS, update_screen = TRUE)
+ deathhud.run_animation(cause_of_death)
#define WARNING_ROBOT(text) ("" + text + "")
#define DANGER_ROBOT(text) ("" + text + "")
@@ -88,13 +84,10 @@
WARNING_ROBOT("WARNI-"),
)
-/atom/movable/screen/cyborg_death/Initialize(mapload, datum/hud/hud_owner, cause_of_death = "Unidentified kernel error.")
- . = ..()
- messages.Insert(1, WARNING_ROBOT("WARNING: [cause_of_death]"))
-
-/atom/movable/screen/cyborg_death/proc/run_animation()
+/atom/movable/screen/cyborg_death/proc/run_animation(cause_of_death = "Unidentified kernel error.")
set waitfor = FALSE
+ messages.Insert(1, WARNING_ROBOT("WARNING: [cause_of_death]"))
if(prob(1))
messages[length(messages)] = SENTIENT_ROBOT(pick("I don't want to go.", "I don't feel good.", "I don't want to die."))
diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm
index d7a320c6e67..30790c176b5 100644
--- a/code/modules/mob/living/silicon/robot/inventory.dm
+++ b/code/modules/mob/living/silicon/robot/inventory.dm
@@ -77,16 +77,17 @@
. = ..()
if(isnull(client) || isnull(hud_used) || hud_used.hud_version == HUD_STYLE_NOHUD)
return
- var/turf/our_turf = get_turf(src)
- for(var/obj/item/held in held_items)
+ var/turf/our_turf = get_turf(src)
+ for (var/held_index in 1 to length(held_items))
+ var/obj/item/held = held_items[held_index]
+ if (!held)
+ continue
SET_PLANE(held, ABOVE_HUD_PLANE, our_turf)
- if(held_items[BORG_CHOOSE_MODULE_ONE] == held)
- held.screen_loc = inv1.screen_loc
- else if(held_items[BORG_CHOOSE_MODULE_TWO] == held)
- held.screen_loc = inv2.screen_loc
- else if(held_items[BORG_CHOOSE_MODULE_THREE] == held)
- held.screen_loc = inv3.screen_loc
+ var/atom/movable/screen/robot/module_slot/slot = hud_used.screen_objects[HUD_KEY_CYBORG_MODULE(held_index)]
+ if (!slot) //??
+ continue
+ held.screen_loc = slot.screen_loc
client.screen |= held
/mob/living/silicon/robot/put_in_hand_check(obj/item/item_equipping)
@@ -111,7 +112,6 @@
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)
@@ -127,7 +127,6 @@
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)
@@ -138,13 +137,15 @@
if(disabled_modules & BORG_MODULE_THREE_DISABLED)
return FALSE
- inv3.icon_state = "[initial(inv3.icon_state)] +b"
disabled_modules |= BORG_MODULE_THREE_DISABLED
playsound(src, 'sound/machines/warning-buzzer.ogg', 50, TRUE, TRUE)
audible_message(span_warning("[src] sounds an alarm! \"SYSTEM ERROR: Module [module_num] OFFLINE.\""))
to_chat(src, span_userdanger("SYSTEM ERROR: Module [module_num] OFFLINE."))
+ var/atom/movable/screen/robot/module_slot/module = hud_used?.screen_objects[HUD_KEY_CYBORG_MODULE(module_num)]
+ if(module)
+ module.icon_state = "[module.base_icon_state] +b"
return TRUE
/**
@@ -169,26 +170,27 @@
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.camera_enabled = TRUE
to_chat(src, span_notice("You hear your built in security camera focus adjust as it comes back online!"))
+
if(BORG_CHOOSE_MODULE_TWO)
if(!(disabled_modules & BORG_MODULE_TWO_DISABLED))
return FALSE
- inv2.icon_state = initial(inv2.icon_state)
disabled_modules &= ~BORG_MODULE_TWO_DISABLED
+
if(BORG_CHOOSE_MODULE_THREE)
if(!(disabled_modules & BORG_MODULE_THREE_DISABLED))
return FALSE
- inv3.icon_state = initial(inv3.icon_state)
disabled_modules &= ~BORG_MODULE_THREE_DISABLED
to_chat(src, span_notice("ERROR CLEARED: Module [module_num] back online."))
-
+ var/atom/movable/screen/robot/module_slot/module = hud_used?.screen_objects[HUD_KEY_CYBORG_MODULE(module_num)]
+ if(module)
+ module.icon_state = module.base_icon_state
return TRUE
/**
@@ -268,16 +270,9 @@
if(is_invalid_module_number(module_num) || !held_items[module_num]) //If the slot number is invalid, or there's nothing there, we have nothing to equip
return FALSE
- switch(module_num)
- if(BORG_CHOOSE_MODULE_ONE)
- if(module_active != held_items[module_num])
- inv1.icon_state = "[initial(inv1.icon_state)] +a"
- if(BORG_CHOOSE_MODULE_TWO)
- if(module_active != held_items[module_num])
- inv2.icon_state = "[initial(inv2.icon_state)] +a"
- if(BORG_CHOOSE_MODULE_THREE)
- if(module_active != held_items[module_num])
- inv3.icon_state = "[initial(inv3.icon_state)] +a"
+ var/atom/movable/screen/robot/module_slot/module = hud_used?.screen_objects[HUD_KEY_CYBORG_MODULE(module_num)]
+ if(module && module_active != held_items[module_num])
+ module.icon_state = "[module.base_icon_state] +a"
module_active = held_items[module_num]
return TRUE
@@ -287,13 +282,9 @@
* * module_num - the slot number being de-selected
*/
/mob/living/silicon/robot/proc/deselect_module(module_num)
- switch(module_num)
- if(BORG_CHOOSE_MODULE_ONE)
- inv1.icon_state = initial(inv1.icon_state)
- if(BORG_CHOOSE_MODULE_TWO)
- inv2.icon_state = initial(inv2.icon_state)
- if(BORG_CHOOSE_MODULE_THREE)
- inv3.icon_state = initial(inv3.icon_state)
+ var/atom/movable/screen/robot/module_slot/module = hud_used?.screen_objects[HUD_KEY_CYBORG_MODULE(module_num)]
+ if(module)
+ module.icon_state = module.base_icon_state
module_active = null
return TRUE
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index d428c275171..a4da3bd1c80 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -37,22 +37,27 @@
/mob/living/silicon/robot/update_health_hud()
if(!client || !hud_used)
return
- if(hud_used.healths)
- if(stat != DEAD)
- if(health >= maxHealth)
- hud_used.healths.icon_state = "health0"
- else if(health > maxHealth*0.6)
- hud_used.healths.icon_state = "health2"
- else if(health > maxHealth*0.2)
- hud_used.healths.icon_state = "health3"
- else if(health > -maxHealth*0.2)
- hud_used.healths.icon_state = "health4"
- else if(health > -maxHealth*0.6)
- hud_used.healths.icon_state = "health5"
- else
- hud_used.healths.icon_state = "health6"
- else
- hud_used.healths.icon_state = "health7"
+
+ var/atom/movable/screen/healths/healths = hud_used.screen_objects[HUD_MOB_HEALTH]
+ if(!healths)
+ return
+
+ if(stat == DEAD)
+ healths.icon_state = "health7"
+ return
+
+ if(health >= maxHealth)
+ healths.icon_state = "health0"
+ else if(health > maxHealth*0.6)
+ healths.icon_state = "health2"
+ else if(health > maxHealth*0.2)
+ healths.icon_state = "health3"
+ else if(health > -maxHealth*0.2)
+ healths.icon_state = "health4"
+ else if(health > -maxHealth*0.6)
+ healths.icon_state = "health5"
+ else
+ healths.icon_state = "health6"
/mob/living/silicon/robot/proc/update_cell_hud_icon()
if(cell)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index b132ce92987..429b66c1a34 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -20,10 +20,6 @@
RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, PROC_REF(on_light_eater))
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_GOT_DAMPENED), PROC_REF(on_dampen))
- inv1 = new /atom/movable/screen/robot/module1()
- inv2 = new /atom/movable/screen/robot/module2()
- inv3 = new /atom/movable/screen/robot/module3()
-
previous_health = health
if(ispath(cell))
@@ -131,10 +127,6 @@
QDEL_NULL(model)
QDEL_NULL(eye_lights)
QDEL_NULL(hat_overlay)
- QDEL_NULL(inv1)
- QDEL_NULL(inv2)
- QDEL_NULL(inv3)
- QDEL_NULL(hands)
QDEL_NULL(spark_system)
QDEL_NULL(alert_control)
QDEL_LIST(upgrades)
@@ -513,19 +505,21 @@
if(!COOLDOWN_FINISHED(src, disabled_time))
balloon_alert(src, "disrupted!")
return FALSE
+
if(!(update_color && lamp_enabled) && (turn_off || lamp_enabled || update_color || !lamp_functional || stat || low_power_mode))
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_appearance()
+ hud_used?.screen_objects[HUD_CYBORG_LAMP]?.update_appearance()
update_icons()
return
+
set_light_range(max(MINIMUM_USEFUL_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_appearance()
+ hud_used?.screen_objects[HUD_CYBORG_LAMP]?.update_appearance()
update_icons()
///Completely deconstructs the borg, dropping the MMI/posibrain, removing applied upgrades and stripping the exoskeleton of all limbs,
@@ -762,18 +756,15 @@
/mob/living/silicon/robot/proc/update_module_innate()
designation = model.name
- if(hands)
- hands.icon_state = model.model_select_icon
+ hud_used?.screen_objects[HUD_CYBORG_HANDS]?.icon_state = model.model_select_icon
REMOVE_TRAITS_IN(src, MODEL_TRAIT)
if(length(model.model_traits))
add_traits(model.model_traits, MODEL_TRAIT)
hat_offset = model.hat_offset
-
INVOKE_ASYNC(src, PROC_REF(updatename))
-
/mob/living/silicon/robot/proc/place_on_head(obj/item/new_hat)
if(hat)
hat.forceMove(get_turf(src))
diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm
index 2cf30e5a5d9..c4cf75317d9 100644
--- a/code/modules/mob/living/silicon/robot/robot_defines.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defines.dm
@@ -69,30 +69,15 @@
// Overlay for borg hat
var/mutable_appearance/hat_overlay
-
- // Hud
- var/atom/movable/screen/inv1 = null
- var/atom/movable/screen/inv2 = null
- var/atom/movable/screen/inv3 = null
- var/atom/movable/screen/hands = null
-
- ///Lamp button reference
- var/atom/movable/screen/robot/lamp/lampButton
-
- ///The reference to the built-in tablet that borgs carry.
- var/atom/movable/screen/robot/modpc/interfaceButton
-
var/sight_mode = 0
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD)
-
// Modules (tool slots)
var/obj/item/module_active = null
///For checking which modules are disabled or not.
var/disabled_modules
-
// Status
var/mob/living/silicon/ai/connected_ai = null
diff --git a/code/modules/mob/living/simple_animal/hostile/ooze.dm b/code/modules/mob/living/simple_animal/hostile/ooze.dm
index aec9457ecae..4bb2858bce1 100644
--- a/code/modules/mob/living/simple_animal/hostile/ooze.dm
+++ b/code/modules/mob/living/simple_animal/hostile/ooze.dm
@@ -85,7 +85,9 @@
///Does ooze_nutrition + supplied amount and clamps it within 0 and 500
/mob/living/simple_animal/hostile/ooze/proc/adjust_ooze_nutrition(amount)
ooze_nutrition = clamp(ooze_nutrition + amount, 0, 500)
- updateNutritionDisplay()
+ hud_used?.screen_objects[HUD_OOZE_NUTRITION_DISPLAY]?.maptext = MAPTEXT( \
+ "[round(ooze_nutrition)]
" \
+ )
///Tries to transfer the atoms reagents then delete it
/mob/living/simple_animal/hostile/ooze/proc/eat_atom(atom/eat_target, silent)
@@ -98,12 +100,6 @@
to_chat(src, span_warning("[eat_target] cannot be eaten!"))
return FALSE
-///Updates the display that shows the mobs nutrition
-/mob/living/simple_animal/hostile/ooze/proc/updateNutritionDisplay()
- if(hud_used) //clientless oozes
- hud_used.alien_plasma_display.maptext = MAPTEXT("[round(ooze_nutrition)]
")
-
-
///* Gelatinious Ooze code below *\\\\
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 4a8c75c0b11..dfdce3c3292 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -766,13 +766,13 @@
///Update the pulling hud icon
/mob/proc/update_pull_hud_icon()
- hud_used?.pull_icon?.update_appearance()
+ hud_used?.screen_objects[HUD_MOB_PULL]?.update_appearance()
///Update the resting hud icon
/mob/proc/update_rest_hud_icon()
if(!hud_used)
return FALSE
- hud_used.rest_icon?.update_appearance()
+ hud_used.screen_objects[HUD_MOB_REST]?.update_appearance()
return TRUE
/**
@@ -943,10 +943,10 @@
active_hand_index = held_index
if(hud_used)
var/atom/movable/screen/inventory/hand/held_location
- held_location = hud_used.hand_slots["[previous_index]"]
+ held_location = hud_used.hand_slots[previous_index]
if(!isnull(held_location))
held_location.update_appearance()
- held_location = hud_used.hand_slots["[held_index]"]
+ held_location = hud_used.hand_slots[held_index]
if(!isnull(held_location))
held_location.update_appearance()
return TRUE
@@ -1501,7 +1501,9 @@
/// Updates nutrition related effects
/mob/living/proc/update_nutrition()
mob_mood?.update_nutrition_moodlets()
- hud_used?.hunger?.update_hunger_bar()
+ var/atom/movable/screen/hunger/hunger_bar = hud_used?.screen_objects[HUD_MOB_HUNGER]
+ if (hunger_bar)
+ hunger_bar.update_hunger_bar()
SEND_SIGNAL(src, COMSIG_LIVING_UPDATE_NUTRITION)
/// Apply a proper movespeed modifier based on items we have equipped
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index d461d9458cb..f0e07051a14 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -398,7 +398,7 @@
///Validate the client's mob has a valid zone selected
/client/proc/check_has_body_select()
- return mob && mob.hud_used && mob.hud_used.zone_select && istype(mob.hud_used.zone_select, /atom/movable/screen/zone_sel)
+ return istype(mob?.hud_used?.screen_objects[HUD_MOB_ZONE_SELECTOR], /atom/movable/screen/zone_sel)
/**
* Hidden verbs to set desired body target zone
@@ -423,7 +423,7 @@
else
next_in_line = BODY_ZONE_HEAD
- var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
+ var/atom/movable/screen/zone_sel/selector = mob.hud_used.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector.set_selected_zone(next_in_line, mob)
///Hidden verb to target the head, unbound by default.
@@ -434,7 +434,7 @@
if(!check_has_body_select())
return
- var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
+ var/atom/movable/screen/zone_sel/selector = mob.hud_used.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector.set_selected_zone(BODY_ZONE_HEAD, mob)
///Hidden verb to target the eyes, bound to 7
@@ -445,7 +445,7 @@
if(!check_has_body_select())
return
- var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
+ var/atom/movable/screen/zone_sel/selector = mob.hud_used.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector.set_selected_zone(BODY_ZONE_PRECISE_EYES, mob)
///Hidden verb to target the mouth, bound to 9
@@ -456,7 +456,7 @@
if(!check_has_body_select())
return
- var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
+ var/atom/movable/screen/zone_sel/selector = mob.hud_used.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector.set_selected_zone(BODY_ZONE_PRECISE_MOUTH, mob)
///Hidden verb to target the right arm, bound to 4
@@ -467,7 +467,7 @@
if(!check_has_body_select())
return
- var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
+ var/atom/movable/screen/zone_sel/selector = mob.hud_used.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector.set_selected_zone(BODY_ZONE_R_ARM, mob)
///Hidden verb to target the chest, bound to 5
@@ -478,7 +478,7 @@
if(!check_has_body_select())
return
- var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
+ var/atom/movable/screen/zone_sel/selector = mob.hud_used.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector.set_selected_zone(BODY_ZONE_CHEST, mob)
///Hidden verb to target the left arm, bound to 6
@@ -489,7 +489,7 @@
if(!check_has_body_select())
return
- var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
+ var/atom/movable/screen/zone_sel/selector = mob.hud_used.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector.set_selected_zone(BODY_ZONE_L_ARM, mob)
///Hidden verb to target the right leg, bound to 1
@@ -500,7 +500,7 @@
if(!check_has_body_select())
return
- var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
+ var/atom/movable/screen/zone_sel/selector = mob.hud_used.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector.set_selected_zone(BODY_ZONE_R_LEG, mob)
///Hidden verb to target the groin, bound to 2
@@ -511,7 +511,7 @@
if(!check_has_body_select())
return
- var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
+ var/atom/movable/screen/zone_sel/selector = mob.hud_used.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector.set_selected_zone(BODY_ZONE_PRECISE_GROIN, mob)
///Hidden verb to target the left leg, bound to 3
@@ -522,7 +522,7 @@
if(!check_has_body_select())
return
- var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
+ var/atom/movable/screen/zone_sel/selector = mob.hud_used.screen_objects[HUD_MOB_ZONE_SELECTOR]
selector.set_selected_zone(BODY_ZONE_L_LEG, mob)
///Verb to toggle the walk or run status
@@ -544,11 +544,9 @@
move_intent = MOVE_INTENT_WALK
else
move_intent = MOVE_INTENT_RUN
- if(hud_used?.static_inventory)
- for(var/atom/movable/screen/mov_intent/selector in hud_used.static_inventory)
- selector.update_appearance()
- update_move_intent_slowdown()
+ hud_used?.screen_objects[HUD_MOB_MOVE_INTENT]?.update_appearance()
+ update_move_intent_slowdown()
SEND_SIGNAL(src, COMSIG_MOVE_INTENT_TOGGLED)
///Moves a mob upwards in z level
diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm
index e9e1f1a05fe..7f6fff2e89e 100644
--- a/code/modules/mod/mod_control.dm
+++ b/code/modules/mod/mod_control.dm
@@ -524,7 +524,9 @@
module.on_unequip()
UnregisterSignal(wearer, list(COMSIG_ATOM_EXITED, COMSIG_SPECIES_GAIN, COMSIG_MOB_CLICKON))
SEND_SIGNAL(src, COMSIG_MOD_WEARER_UNSET, wearer)
- wearer.hud_used?.spacesuit_hud.update_spacesuit_hud_icon()
+ var/atom/movable/screen/spacesuit/spacesuit_hud = wearer.hud_used?.screen_objects[HUD_MOB_SPACESUIT]
+ if (spacesuit_hud)
+ spacesuit_hud.update_spacesuit_hud_icon()
wearer = null
/obj/item/mod/control/proc/get_sealed_slots(list/parts)
@@ -725,7 +727,9 @@
else
state_to_use = core.get_charge_icon_state()
- wearer.hud_used.spacesuit_hud.update_spacesuit_hud_icon(state_to_use || SPACESUIT_NO_ICON)
+ var/atom/movable/screen/spacesuit/spacesuit_hud = wearer.hud_used?.screen_objects[HUD_MOB_SPACESUIT]
+ if (spacesuit_hud)
+ spacesuit_hud.update_spacesuit_hud_icon(state_to_use || SPACESUIT_NO_ICON)
/obj/item/mod/control/proc/update_speed()
var/total_slowdown = 0
diff --git a/code/modules/reagents/reagent_containers/cups/_cup.dm b/code/modules/reagents/reagent_containers/cups/_cup.dm
index 953fb3d248a..e19880d6a66 100644
--- a/code/modules/reagents/reagent_containers/cups/_cup.dm
+++ b/code/modules/reagents/reagent_containers/cups/_cup.dm
@@ -138,7 +138,9 @@
SEND_SIGNAL(src, COMSIG_GLASS_DRANK, target_mob, user)
var/fraction = min(gulp_size / reagents.total_volume, 1)
reagents.trans_to(target_mob, gulp_size, transferred_by = user, methods = reagent_consumption_method)
- user.hud_used?.hunger?.update_hunger_bar()
+ var/atom/movable/screen/hunger/hunger_bar = user.hud_used?.screen_objects[HUD_MOB_HUNGER]
+ if (istype(hunger_bar))
+ hunger_bar.update_hunger_bar()
checkLiked(fraction, target_mob)
playsound(target_mob, consumption_sound, rand(10, 50), TRUE)
var/list/datum/disease/diseases_to_add
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index 65fcb3ffc38..b26e759c218 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -46,8 +46,6 @@
var/max_slimes = 5
/// The amount of monkey cubes inside this machine.
var/stored_monkeys = 0
- /// The HUD for this console.
- var/atom/movable/screen/xenobio_console/xeno_hud
/obj/machinery/computer/camera_advanced/xenobio/Initialize(mapload)
. = ..()
@@ -60,8 +58,6 @@
actions += new /datum/action/innate/hotkey_help(src)
stored_slimes = list()
- xeno_hud = new(null, src)
- xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
register_context()
/obj/machinery/computer/camera_advanced/xenobio/post_machine_initialize()
@@ -77,7 +73,6 @@
var/mob/living/basic/slime/stored_slime = thing
stored_slime.forceMove(drop_location())
stored_slimes.Cut()
- QDEL_NULL(xeno_hud)
return ..()
/obj/machinery/computer/camera_advanced/xenobio/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
@@ -115,8 +110,8 @@
RegisterSignal(user, COMSIG_CLICK_SHIFT, PROC_REF(user_shift_click))
if(!user.hud_used)
return
- user.hud_used.static_inventory += xeno_hud
- user.hud_used.show_hud(user.hud_used.hud_version)
+ var/atom/movable/screen/xenobio_console/xeno_hud = user.hud_used.add_screen_object(/atom/movable/screen/xenobio_console, HUD_XENOBIO_CONSOLE, update_screen = TRUE)
+ xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
/obj/machinery/computer/camera_advanced/xenobio/remove_eye_control(mob/living/user)
UnregisterSignal(user, list(
@@ -124,10 +119,7 @@
COMSIG_MOB_ALTCLICKON,
COMSIG_CLICK_SHIFT,
))
- if(user.hud_used)
- if(xeno_hud)
- user.hud_used.static_inventory -= xeno_hud
- user.hud_used.show_hud(user.hud_used.hud_version)
+ user.hud_used?.remove_screen_object(HUD_XENOBIO_CONSOLE)
return ..()
/obj/machinery/computer/camera_advanced/xenobio/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
@@ -156,14 +148,18 @@
balloon_alert(user, "inserted")
current_potion = used_potion
- xeno_hud.update_potion(current_potion)
+ var/atom/movable/screen/xenobio_console/xeno_hud = user.hud_used?.screen_objects[HUD_XENOBIO_CONSOLE]
+ if(xeno_hud)
+ xeno_hud.update_potion(current_potion)
return ITEM_INTERACT_SUCCESS
/// Handles inserting a monkey cube into the console.
/obj/machinery/computer/camera_advanced/xenobio/proc/monkeycube_act(mob/living/user, obj/item/food/monkeycube/used_cube)
stored_monkeys += 1
balloon_alert(user, "[stored_monkeys] cube\s stored")
- xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
+ var/atom/movable/screen/xenobio_console/xeno_hud = user.hud_used?.screen_objects[HUD_XENOBIO_CONSOLE]
+ if(xeno_hud)
+ xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
qdel(used_cube)
return ITEM_INTERACT_SUCCESS
@@ -180,7 +176,9 @@
return ITEM_INTERACT_BLOCKING
balloon_alert(user, "[stored_monkeys] cube\s stored")
- xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
+ var/atom/movable/screen/xenobio_console/xeno_hud = user.hud_used?.screen_objects[HUD_XENOBIO_CONSOLE]
+ if(xeno_hud)
+ xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
return ITEM_INTERACT_SUCCESS
/obj/machinery/computer/camera_advanced/xenobio/multitool_act(mob/living/user, obj/item/multitool/tool)
@@ -212,19 +210,24 @@
return TRUE
///Places every slime in storage on target turf
-/obj/machinery/computer/camera_advanced/xenobio/proc/slime_place(turf/open/target_turf)
+/obj/machinery/computer/camera_advanced/xenobio/proc/slime_place(turf/open/target_turf, mob/living/user)
spit_out(stored_slimes, target_turf)
if(stored_slimes.len <= 0)
return
+
if(stored_slimes.len == 1)
target_turf.visible_message(span_notice("The slime is spat out!"))
else
target_turf.visible_message(span_notice("[stored_slimes.len] slimes are spat out!"))
+
for(var/mob/living/basic/slime/stored_slime in stored_slimes)
stored_slime.forceMove(target_turf)
REMOVE_TRAIT(stored_slime, TRAIT_STASIS, XENOBIO_CONSOLE_TRAIT)
stored_slime.handle_slime_stasis()
- xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
+
+ var/atom/movable/screen/xenobio_console/xeno_hud = user.hud_used?.screen_objects[HUD_XENOBIO_CONSOLE]
+ if(xeno_hud)
+ xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
///Places every slime not controlled by a player into the internal storage, respecting its limits
///Returns TRUE to signal it hitting the limit, in case its being called from a loop and we want it to stop
@@ -233,13 +236,16 @@
// It's possible for this proc to be called on a slime that's already being picked up,
// so we need to check whether we already have to avoid duplicate entries.
return FALSE
+
if(stored_slimes.len >= max_slimes)
to_chat(user, span_warning("Slime storage is full."))
target_slime.balloon_alert(user, "storage full")
return TRUE
+
if(target_slime.ckey)
to_chat(user, span_warning("The slime wiggled free!"))
return FALSE
+
if(target_slime.buckled)
target_slime.stop_feeding(silent = TRUE)
target_slime.visible_message(span_notice("The slime gets sucked up!"))
@@ -247,8 +253,10 @@
target_slime.forceMove(src)
stored_slimes += target_slime
ADD_TRAIT(target_slime, TRAIT_STASIS, XENOBIO_CONSOLE_TRAIT)
- xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
+ var/atom/movable/screen/xenobio_console/xeno_hud = user.hud_used?.screen_objects[HUD_XENOBIO_CONSOLE]
+ if(xeno_hud)
+ xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
return FALSE
///Places one monkey, if possible
@@ -261,13 +269,16 @@
var/mob/living/carbon/human/species/monkey/food = new /mob/living/carbon/human/species/monkey(target_turf, TRUE, user)
if (QDELETED(food))
return
+
food.apply_status_effect(/datum/status_effect/slime_food, user)
ADD_TRAIT(food, TRAIT_SPAWNED_MOB, INNATE_TRAIT)
-
stored_monkeys--
stored_monkeys = round(stored_monkeys, 0.1) //Prevents rounding errors
spit_out(food, target_turf)
- xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
+
+ var/atom/movable/screen/xenobio_console/xeno_hud = user.hud_used?.screen_objects[HUD_XENOBIO_CONSOLE]
+ if(xeno_hud)
+ xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
/// Check whether we can recycle monkeys at all. Optionally, displays a balloon alert over a target atom for feedback.
/obj/machinery/computer/camera_advanced/xenobio/proc/can_recycle_monkeys(mob/living/user, atom/target_atom)
@@ -302,7 +313,7 @@
for(var/mob/living/carbon/human/target_human in target_turf)
if(!can_recycle_target_monkey(target_human))
continue
- recycle_monkey(target_human)
+ recycle_monkey(target_human, user)
monkey_found = TRUE
return monkey_found
@@ -314,11 +325,11 @@
if(!can_recycle_monkeys(user, target_human))
return FALSE
- recycle_monkey(target_human)
+ recycle_monkey(target_human, user)
return TRUE
/// Recycles a given monkey.
-/obj/machinery/computer/camera_advanced/xenobio/proc/recycle_monkey(mob/living/carbon/human/target_monkey)
+/obj/machinery/computer/camera_advanced/xenobio/proc/recycle_monkey(mob/living/carbon/human/target_monkey, mob/living/user)
var/obj/machinery/monkey_recycler/connected_recycler = connected_recycler_ref?.resolve()
if(isnull(connected_recycler))
return
@@ -328,7 +339,9 @@
connected_recycler.use_energy(500 JOULES)
stored_monkeys += connected_recycler.cube_production
stored_monkeys = round(stored_monkeys, 0.1) //Prevents rounding errors
- xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
+ var/atom/movable/screen/xenobio_console/xeno_hud = user.hud_used?.screen_objects[HUD_XENOBIO_CONSOLE]
+ if(xeno_hud)
+ xeno_hud.on_update_hud(LAZYLEN(stored_slimes), stored_monkeys, max_slimes)
qdel(target_monkey)
/datum/action/innate/slime_place
@@ -346,7 +359,7 @@
if(!xeno_console.validate_turf(owner, eye_turf))
return
- xeno_console.slime_place(eye_turf)
+ xeno_console.slime_place(eye_turf, owner)
/datum/action/innate/slime_pick_up
name = "Pick up Slime"
@@ -443,7 +456,9 @@
for(var/mob/living/basic/slime/potioned_slime in eye_turf)
xeno_console.spit_atom(xeno_console.current_potion, eye_turf)
xeno_console.current_potion.interact_with_slime(potioned_slime, living_owner)
- xeno_console.xeno_hud.update_potion(xeno_console.current_potion)
+ var/atom/movable/screen/xenobio_console/xeno_hud = owner.hud_used?.screen_objects[HUD_XENOBIO_CONSOLE]
+ if(xeno_hud)
+ xeno_hud.update_potion(xeno_console.current_potion)
break
/datum/action/innate/hotkey_help
@@ -485,7 +500,9 @@
spit_atom(current_potion, slime_turf)
INVOKE_ASYNC(current_potion, TYPE_PROC_REF(/obj/item/slimepotion/slime, attack), target_slime, user)
- xeno_hud.update_potion(current_potion)
+ var/atom/movable/screen/xenobio_console/xeno_hud = user.hud_used?.screen_objects[HUD_XENOBIO_CONSOLE]
+ if(xeno_hud)
+ xeno_hud.update_potion(current_potion)
/// Handles console user shift-clicking, forwards to other procs based on target type.
/obj/machinery/computer/camera_advanced/xenobio/proc/user_shift_click(mob/living/user, atom/target)
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 72108859d3e..d0a3d18cfa2 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -204,7 +204,7 @@
arm_owner.set_handcuffed(null)
arm_owner.dropItemToGround(lost_cuffs, force = TRUE)
if(arm_owner.hud_used)
- var/atom/movable/screen/inventory/hand/associated_hand = arm_owner.hud_used.hand_slots["[held_index]"]
+ var/atom/movable/screen/inventory/hand/associated_hand = arm_owner.hud_used.hand_slots[held_index]
associated_hand?.update_appearance()
if(arm_owner.num_hands == 0)
arm_owner.dropItemToGround(arm_owner.gloves, force = TRUE)
diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm
index 7c112950265..9b0f56c6a58 100644
--- a/code/modules/surgery/bodyparts/parts.dm
+++ b/code/modules/surgery/bodyparts/parts.dm
@@ -211,7 +211,7 @@
if(!old_owner.hud_used)
return
- var/atom/movable/screen/inventory/hand/hand = old_owner.hud_used.hand_slots["[held_index]"]
+ var/atom/movable/screen/inventory/hand/hand = old_owner.hud_used.hand_slots[held_index]
hand?.update_appearance()
/// We need to add hand hud items and appearance, so do that here
@@ -230,7 +230,7 @@
if(!new_owner.hud_used)
return
- var/atom/movable/screen/inventory/hand/hand = new_owner.hud_used.hand_slots["[held_index]"]
+ var/atom/movable/screen/inventory/hand/hand = new_owner.hud_used.hand_slots[held_index]
hand?.update_appearance()
/obj/item/bodypart/arm/set_disabled(new_disabled)
@@ -249,7 +249,7 @@
owner.set_usable_hands(owner.usable_hands + 1)
if(owner.hud_used)
- var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots["[held_index]"]
+ var/atom/movable/screen/inventory/hand/hand_screen_object = owner.hud_used.hand_slots[held_index]
hand_screen_object?.update_appearance()
/datum/status_effect/arm_speed_penalty
diff --git a/code/modules/surgery/organs/internal/stomach/_stomach.dm b/code/modules/surgery/organs/internal/stomach/_stomach.dm
index f8cb50193d5..7429f072f53 100644
--- a/code/modules/surgery/organs/internal/stomach/_stomach.dm
+++ b/code/modules/surgery/organs/internal/stomach/_stomach.dm
@@ -388,7 +388,9 @@
/obj/item/organ/stomach/on_mob_insert(mob/living/carbon/receiver, special, movement_flags)
. = ..()
- receiver.hud_used?.hunger?.update_hunger_bar()
+ var/atom/movable/screen/hunger/hunger_bar = receiver.hud_used?.screen_objects[HUD_MOB_HUNGER]
+ if(hunger_bar)
+ hunger_bar.update_hunger_bar()
RegisterSignal(receiver, COMSIG_CARBON_VOMITED, PROC_REF(on_vomit))
RegisterSignal(receiver, COMSIG_HUMAN_GOT_PUNCHED, PROC_REF(on_punched))
@@ -397,7 +399,9 @@
var/mob/living/carbon/human/human_owner = stomach_owner
human_owner.clear_alert(ALERT_DISGUST)
human_owner.clear_mood_event("disgust")
- stomach_owner.hud_used?.hunger?.update_hunger_bar()
+ var/atom/movable/screen/hunger/hunger_bar = stomach_owner.hud_used?.screen_objects[HUD_MOB_HUNGER]
+ if(hunger_bar)
+ hunger_bar.update_hunger_bar()
UnregisterSignal(stomach_owner, list(COMSIG_CARBON_VOMITED, COMSIG_HUMAN_GOT_PUNCHED))
return ..()
diff --git a/code/modules/unit_tests/unequip_defib.dm b/code/modules/unit_tests/unequip_defib.dm
index e2db399f2de..910cf599af2 100644
--- a/code/modules/unit_tests/unequip_defib.dm
+++ b/code/modules/unit_tests/unequip_defib.dm
@@ -12,7 +12,7 @@
usr = dummy // mouse drop still uses usr
- defib.MouseDrop(dummy.hud_used.hand_slots["1"])
+ defib.MouseDrop(dummy.hud_used.hand_slots[1])
if(!dummy.is_holding(defib))
TEST_FAIL("The dummy failed to remove the defib from their back via mouse drop.")
diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm
index 74f14ecea49..289bfc097bc 100644
--- a/code/modules/unit_tests/unit_test.dm
+++ b/code/modules/unit_tests/unit_test.dm
@@ -351,13 +351,12 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests())
returnable_list += typesof(/obj/structure/transport/linear)
// Runtimes if the associated machinery does not exist, but not the base type
returnable_list += subtypesof(/obj/machinery/airlock_controller)
- // Always ought to have an associated escape menu. Any references it could possibly hold would need one regardless.
- returnable_list += subtypesof(/atom/movable/screen/escape_menu)
// Can't spawn openspace above nothing, it'll get pissy at me
returnable_list += typesof(/turf/open/space/openspace)
returnable_list += typesof(/turf/open/openspace)
returnable_list += typesof(/obj/item/robot_model) // These should never be spawned outside of a robot.
-
+ //A lot of these depend on a hud datum to function and should not be created in a vacuum
+ returnable_list += typesof(/atom/movable/screen)
return returnable_list
/proc/RunUnitTests()
diff --git a/icons/hud/screen_changeling.dmi b/icons/hud/screen_changeling.dmi
index c3bab062ac4..30c3df29948 100644
Binary files a/icons/hud/screen_changeling.dmi and b/icons/hud/screen_changeling.dmi differ
diff --git a/icons/mob/actions/actions_changeling.dmi b/icons/mob/actions/actions_changeling.dmi
index a721505a8c0..aae88cd0b5c 100644
Binary files a/icons/mob/actions/actions_changeling.dmi and b/icons/mob/actions/actions_changeling.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 233b01bea38..ca737cae21b 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -619,37 +619,26 @@
#include "code\_onclick\other_mobs.dm"
#include "code\_onclick\overmind.dm"
#include "code\_onclick\telekinesis.dm"
-#include "code\_onclick\hud\action_button.dm"
+#include "code\_onclick\hud\action_group.dm"
#include "code\_onclick\hud\ai.dm"
-#include "code\_onclick\hud\alert.dm"
#include "code\_onclick\hud\alien.dm"
#include "code\_onclick\hud\alien_larva.dm"
#include "code\_onclick\hud\blob_overmind.dm"
-#include "code\_onclick\hud\credits.dm"
#include "code\_onclick\hud\drones.dm"
-#include "code\_onclick\hud\fullscreen.dm"
#include "code\_onclick\hud\generic_dextrous.dm"
#include "code\_onclick\hud\ghost.dm"
#include "code\_onclick\hud\guardian.dm"
#include "code\_onclick\hud\hud.dm"
#include "code\_onclick\hud\human.dm"
+#include "code\_onclick\hud\inventory_slot.dm"
#include "code\_onclick\hud\living.dm"
-#include "code\_onclick\hud\map_popups.dm"
-#include "code\_onclick\hud\map_view.dm"
-#include "code\_onclick\hud\movable_screen_objects.dm"
#include "code\_onclick\hud\new_player.dm"
#include "code\_onclick\hud\ooze.dm"
-#include "code\_onclick\hud\perks.dm"
-#include "code\_onclick\hud\picture_in_picture.dm"
-#include "code\_onclick\hud\radial.dm"
-#include "code\_onclick\hud\radial_persistent.dm"
+#include "code\_onclick\hud\pai.dm"
#include "code\_onclick\hud\revenanthud.dm"
#include "code\_onclick\hud\robot.dm"
-#include "code\_onclick\hud\screen_object_holder.dm"
-#include "code\_onclick\hud\screen_objects.dm"
-#include "code\_onclick\hud\screentip.dm"
#include "code\_onclick\hud\soulscythe.dm"
-#include "code\_onclick\hud\voidwalkerhud.dm"
+#include "code\_onclick\hud\voidwalker.dm"
#include "code\_onclick\hud\parallax\parallax.dm"
#include "code\_onclick\hud\parallax\random_layer.dm"
#include "code\_onclick\hud\rendering\plane_master_controller.dm"
@@ -657,6 +646,30 @@
#include "code\_onclick\hud\rendering\render_plate.dm"
#include "code\_onclick\hud\rendering\plane_masters\_plane_master.dm"
#include "code\_onclick\hud\rendering\plane_masters\plane_master_subtypes.dm"
+#include "code\_onclick\hud\screen_objects\action_button.dm"
+#include "code\_onclick\hud\screen_objects\ai.dm"
+#include "code\_onclick\hud\screen_objects\alert.dm"
+#include "code\_onclick\hud\screen_objects\alien.dm"
+#include "code\_onclick\hud\screen_objects\blob.dm"
+#include "code\_onclick\hud\screen_objects\credits.dm"
+#include "code\_onclick\hud\screen_objects\fullscreen.dm"
+#include "code\_onclick\hud\screen_objects\ghost.dm"
+#include "code\_onclick\hud\screen_objects\guardian.dm"
+#include "code\_onclick\hud\screen_objects\human.dm"
+#include "code\_onclick\hud\screen_objects\map_popups.dm"
+#include "code\_onclick\hud\screen_objects\map_view.dm"
+#include "code\_onclick\hud\screen_objects\movable_screen_objects.dm"
+#include "code\_onclick\hud\screen_objects\new_player.dm"
+#include "code\_onclick\hud\screen_objects\pai.dm"
+#include "code\_onclick\hud\screen_objects\perks.dm"
+#include "code\_onclick\hud\screen_objects\picture_in_picture.dm"
+#include "code\_onclick\hud\screen_objects\radial.dm"
+#include "code\_onclick\hud\screen_objects\radial_persistent.dm"
+#include "code\_onclick\hud\screen_objects\robot.dm"
+#include "code\_onclick\hud\screen_objects\screen_object_holder.dm"
+#include "code\_onclick\hud\screen_objects\screen_objects.dm"
+#include "code\_onclick\hud\screen_objects\screentip.dm"
+#include "code\_onclick\hud\screen_objects\voidwalker.dm"
#include "code\controllers\admin.dm"
#include "code\controllers\controller.dm"
#include "code\controllers\failsafe.dm"
@@ -4320,7 +4333,6 @@
#include "code\modules\economy\poker_chips.dm"
#include "code\modules\emoji\emoji_parse.dm"
#include "code\modules\emote_panel\emote_panel.dm"
-#include "code\modules\engineering\tools\multitool.dm"
#include "code\modules\error_handler\error_handler.dm"
#include "code\modules\error_handler\error_viewer.dm"
#include "code\modules\escape_menu\details.dm"
@@ -5815,7 +5827,6 @@
#include "code\modules\pai\debug.dm"
#include "code\modules\pai\defense.dm"
#include "code\modules\pai\door_jack.dm"
-#include "code\modules\pai\hud.dm"
#include "code\modules\pai\login.dm"
#include "code\modules\pai\pai.dm"
#include "code\modules\pai\personality.dm"