diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm
index 4ea51e41553..b9f0aa4d89d 100644
--- a/code/__DEFINES/hud.dm
+++ b/code/__DEFINES/hud.dm
@@ -58,6 +58,7 @@
//Lower right, persistent menu
#define ui_rest "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"
#define ui_above_movement_top "EAST-2:26, SOUTH+1:24"
#define ui_above_intent "EAST-3:24, SOUTH+1:7"
@@ -140,6 +141,7 @@
#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"
#define ui_alien_language_menu "EAST-4:20,SOUTH:5"
#define ui_alien_navigate_menu "EAST-4:4,SOUTH:5"
+#define ui_alien_floor_change "EAST-3:24, SOUTH:24"
//AI
#define ui_ai_core "BOTTOM:6,RIGHT-4"
diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm
index 20e1e72f950..9609ff4977f 100644
--- a/code/_onclick/hud/alien.dm
+++ b/code/_onclick/hud/alien.dm
@@ -61,6 +61,7 @@
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)
@@ -95,10 +96,14 @@
rest_icon = new /atom/movable/screen/rest(null, src)
rest_icon.icon = ui_style
- rest_icon.screen_loc = ui_above_intent
+ 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)
diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm
index 922953b01a3..c49c97e5ec4 100644
--- a/code/_onclick/hud/alien_larva.dm
+++ b/code/_onclick/hud/alien_larva.dm
@@ -12,6 +12,7 @@
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)
@@ -28,10 +29,14 @@
rest_icon = new /atom/movable/screen/rest(null, src)
rest_icon.icon = ui_style
- rest_icon.screen_loc = ui_above_intent
+ 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
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index a28582b1b02..52ab496518e 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -35,6 +35,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
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/module_store_icon
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index d0d75b6c0c6..fda5012a4c7 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -256,6 +256,10 @@
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 = new /atom/movable/screen/spacesuit(null, src)
infodisplay += spacesuit
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 927e1e9ae70..cd3269a67cb 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -470,6 +470,32 @@
icon_state = "[base_icon_state][user.resting ? "_on" : null]"
return ..()
+/atom/movable/screen/sleep
+ name = "sleep"
+ icon = 'icons/hud/screen_midnight.dmi'
+ icon_state = "act_sleep"
+ base_icon_state = "act_sleep"
+ plane = HUD_PLANE
+ mouse_over_pointer = MOUSE_HAND_POINTER
+
+/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
+ flick("[base_icon_state]_flick", src)
+
+/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)
+
/atom/movable/screen/storage
name = "storage"
icon = 'icons/hud/screen_midnight.dmi'
diff --git a/code/modules/client/preferences/accessibility.dm b/code/modules/client/preferences/accessibility.dm
index 26f0a790985..e7486719978 100644
--- a/code/modules/client/preferences/accessibility.dm
+++ b/code/modules/client/preferences/accessibility.dm
@@ -11,3 +11,10 @@
default_value = FALSE
savefile_key = "screen_shake_darken"
savefile_identifier = PREFERENCE_PLAYER
+
+/// When toggled, removes some double-click reliant actions.
+/datum/preference/toggle/remove_double_click
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ default_value = FALSE
+ savefile_key = "remove_double_click"
+ savefile_identifier = PREFERENCE_PLAYER
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 0b82cf11052..f229c32d4df 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -760,6 +760,19 @@
else
set_density(TRUE)
+/mob/living/update_rest_hud_icon()
+ . = ..()
+ if(!.)
+ return FALSE
+ if(!hud_used.sleep_icon || HAS_TRAIT(src, TRAIT_SLEEPIMMUNE))
+ return TRUE
+ if(resting || HAS_TRAIT(src, TRAIT_FLOORED))
+ hud_used.static_inventory |= hud_used.sleep_icon
+ else
+ hud_used.static_inventory -= hud_used.sleep_icon
+ hud_used.show_hud(hud_used.hud_version)
+ return TRUE
+
//Recursive function to find everything a mob is holding. Really shitty proc tbh.
/mob/living/get_contents()
var/list/ret = list()
@@ -2637,6 +2650,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
on_lying_down()
else // From lying down to standing up.
on_standing_up()
+ update_rest_hud_icon()
/// Proc to append behavior to the condition of being floored. Called when the condition starts.
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 9d2e65a0868..2a33c67399e 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -530,7 +530,7 @@
DEFAULT_QUEUE_OR_CALL_VERB(VERB_CALLBACK(src, PROC_REF(run_examinate), examinify))
-/mob/proc/run_examinate(atom/examinify)
+/mob/proc/run_examinate(atom/examinify, force_examinate_more = FALSE)
if(isturf(examinify) && !(sight & SEE_TURFS) && !(examinify in view(client ? client.view : world.view, src)))
// shift-click catcher may issue examinate() calls for out-of-sight turfs
@@ -547,11 +547,12 @@
face_atom(examinify)
var/result_combined
+ var/removes_double_click = client?.prefs.read_preference(/datum/preference/toggle/remove_double_click)
if(client)
LAZYINITLIST(client.recent_examines)
var/ref_to_atom = REF(examinify)
var/examine_time = client.recent_examines[ref_to_atom]
- if(examine_time && (world.time - examine_time < EXAMINE_MORE_WINDOW))
+ if(force_examinate_more || (examine_time && (world.time - examine_time < EXAMINE_MORE_WINDOW) && !removes_double_click))
var/list/result = examinify.examine_more(src)
if(!length(result))
result += span_notice("You examine [examinify] closer, but find nothing of interest...")
@@ -566,11 +567,23 @@
var/list/result = examinify.examine(src)
var/atom_title = examinify.examine_title(src, thats = TRUE)
SEND_SIGNAL(src, COMSIG_MOB_EXAMINING, examinify, result)
+ if(removes_double_click)
+ result += span_notice("You can examine [examinify] closer...")
result_combined = (atom_title ? fieldset_block("[atom_title]", jointext(result, "
"), "boxed_message") : boxed_message(jointext(result, "
")))
to_chat(src, span_infoplain(result_combined))
SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, examinify)
+/mob/Topic(href, list/href_list)
+ . = ..()
+ if(.)
+ return
+ if(href_list["run_examinate"])
+ var/atom/examined_atom = locate(href_list["run_examinate"])
+ //run_examinate only early returns this check for turfs for some reason.
+ if(examined_atom in view(client ? client.view : world.view, src))
+ run_examinate(examined_atom, force_examinate_more = TRUE)
+
/mob/proc/blind_examine_check(atom/examined_thing)
return TRUE //The non-living will always succeed at this check.
@@ -721,7 +734,10 @@
///Update the resting hud icon
/mob/proc/update_rest_hud_icon()
- hud_used?.rest_icon?.update_appearance()
+ if(!hud_used)
+ return FALSE
+ hud_used.rest_icon?.update_appearance()
+ return TRUE
/**
* Verb to activate the object in your held hand
diff --git a/icons/hud/screen_alien.dmi b/icons/hud/screen_alien.dmi
index e1f513f5b8f..43a3f9e6dcb 100644
Binary files a/icons/hud/screen_alien.dmi and b/icons/hud/screen_alien.dmi differ
diff --git a/icons/hud/screen_clockwork.dmi b/icons/hud/screen_clockwork.dmi
index ea0e545d4e3..a4ff4b3950b 100644
Binary files a/icons/hud/screen_clockwork.dmi and b/icons/hud/screen_clockwork.dmi differ
diff --git a/icons/hud/screen_detective.dmi b/icons/hud/screen_detective.dmi
index 0516ce6f079..5188b3b8fd9 100644
Binary files a/icons/hud/screen_detective.dmi and b/icons/hud/screen_detective.dmi differ
diff --git a/icons/hud/screen_glass.dmi b/icons/hud/screen_glass.dmi
index f60603ef638..56e9c2a2aae 100644
Binary files a/icons/hud/screen_glass.dmi and b/icons/hud/screen_glass.dmi differ
diff --git a/icons/hud/screen_midnight.dmi b/icons/hud/screen_midnight.dmi
index 496982bfa9e..cdd986d8013 100644
Binary files a/icons/hud/screen_midnight.dmi and b/icons/hud/screen_midnight.dmi differ
diff --git a/icons/hud/screen_operative.dmi b/icons/hud/screen_operative.dmi
index 8719ef18d39..7b472e907e5 100644
Binary files a/icons/hud/screen_operative.dmi and b/icons/hud/screen_operative.dmi differ
diff --git a/icons/hud/screen_plasmafire.dmi b/icons/hud/screen_plasmafire.dmi
index 8cb1230ea50..ecdf4a70b46 100644
Binary files a/icons/hud/screen_plasmafire.dmi and b/icons/hud/screen_plasmafire.dmi differ
diff --git a/icons/hud/screen_retro.dmi b/icons/hud/screen_retro.dmi
index 21275e5320c..8273eb5e963 100644
Binary files a/icons/hud/screen_retro.dmi and b/icons/hud/screen_retro.dmi differ
diff --git a/icons/hud/screen_slimecore.dmi b/icons/hud/screen_slimecore.dmi
index 6b1d25d2689..66696941beb 100644
Binary files a/icons/hud/screen_slimecore.dmi and b/icons/hud/screen_slimecore.dmi differ
diff --git a/icons/hud/screen_trasenknox.dmi b/icons/hud/screen_trasenknox.dmi
index bb6f82caafb..93ad3c08ce8 100644
Binary files a/icons/hud/screen_trasenknox.dmi and b/icons/hud/screen_trasenknox.dmi differ
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/accessibility.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/accessibility.tsx
index a8a782b7f21..1f8262e7260 100644
--- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/accessibility.tsx
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/accessibility.tsx
@@ -18,3 +18,13 @@ export const screen_shake_darken: FeatureToggle = {
`,
component: CheckboxInput,
};
+
+export const remove_double_click: FeatureToggle = {
+ name: 'Remove double click',
+ category: 'ACCESSIBILITY',
+ description: `
+ When toggled, actions that require a double click will instead offer
+ alternatives, good if you have a not-so-functional mouse.
+ `,
+ component: CheckboxInput,
+};