diff --git a/code/__DEFINES/ghost.dm b/code/__DEFINES/ghost.dm
index 84b6cdc7e33..526c08e790c 100644
--- a/code/__DEFINES/ghost.dm
+++ b/code/__DEFINES/ghost.dm
@@ -21,7 +21,7 @@
/// The default ghost display selection for the main player
#define GHOST_ACCS_DEFAULT_OPTION GHOST_ACCS_FULL
-/// The other players ghosts will display as a simple white ghost
+/// The other players ghosts will display as a simple white ghost
#define GHOST_OTHERS_SIMPLE "White ghosts"
/// The other players ghosts will display as transparent mobs
#define GHOST_OTHERS_DEFAULT_SPRITE "Default sprites"
@@ -31,6 +31,8 @@
/// The default ghost display selection when viewing other players
#define GHOST_OTHERS_DEFAULT_OPTION GHOST_OTHERS_THEIR_SETTING
+/// A ghosts min view range that we won't allow them to go under by.
+#define GHOST_MIN_VIEW_RANGE 7
/// A ghosts max view range if they are a BYOND guest or regular account
#define GHOST_MAX_VIEW_RANGE_DEFAULT 10
/// A ghosts max view range if they are a BYOND paid member account (P2W feature)
@@ -56,3 +58,18 @@
#define CAMERA_SEE_GHOSTS_BASIC 1
/// Pictures taken by a camera will display ghosts and their orbits
#define CAMERA_SEE_GHOSTS_ORBIT 2 // this doesn't do anything right now as of Jan 2022
+
+
+#define GHOST_DATA_HUDS (1<<0)
+#define GHOST_VISION (1<<1)
+#define GHOST_HEALTH (1<<2)
+#define GHOST_CHEM (1<<3)
+#define GHOST_GAS (1<<4)
+
+#define ALL_GHOST_FLAGS list( \
+ GHOST_DATA_HUDS, \
+ GHOST_VISION, \
+ GHOST_HEALTH, \
+ GHOST_CHEM, \
+ GHOST_GAS, \
+)
diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm
index 9fac772cd2d..4ea51e41553 100644
--- a/code/__DEFINES/hud.dm
+++ b/code/__DEFINES/hud.dm
@@ -187,7 +187,7 @@
#define ui_ghost_orbit "SOUTH:6,CENTER-2:24"
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER-1:24"
#define ui_ghost_teleport "SOUTH:6,CENTER:24"
-#define ui_ghost_pai "SOUTH: 6, CENTER+1:24"
+#define ui_ghost_settings "SOUTH: 6, CENTER+1:24"
#define ui_ghost_minigames "SOUTH: 6, CENTER+2:24"
#define ui_ghost_language_menu "SOUTH: 6, CENTER+3:24"
#define ui_ghost_floor_changer "SOUTH: 6, CENTER+3:8"
diff --git a/code/__HELPERS/view.dm b/code/__HELPERS/view.dm
index 61aaed88350..8456061caa8 100644
--- a/code/__HELPERS/view.dm
+++ b/code/__HELPERS/view.dm
@@ -2,6 +2,9 @@
SHOULD_BE_PURE(TRUE)
if(isnum(view))
+ //resetting back to 0- this is the same as just checking !view but we want to be clear the point of the check.
+ if(view == 0)
+ return list(0, 0)
var/totalviewrange = (view < 0 ? -1 : 1) + 2 * view
return list(totalviewrange, totalviewrange)
else
diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm
index 3ee08df77cb..a958e37a3f0 100644
--- a/code/_onclick/hud/ghost.dm
+++ b/code/_onclick/hud/ghost.dm
@@ -19,8 +19,7 @@
icon_state = "orbit"
/atom/movable/screen/ghost/orbit/Click()
- var/mob/dead/observer/G = usr
- G.follow()
+ GLOB.orbit_menu.show(usr)
/atom/movable/screen/ghost/reenter_corpse
name = "Reenter corpse"
@@ -38,13 +37,16 @@
var/mob/dead/observer/G = usr
G.dead_tele()
-/atom/movable/screen/ghost/pai
- name = "pAI Candidate"
- icon_state = "pai"
+/atom/movable/screen/ghost/settings
+ name = "Ghost Settings"
+ icon_state = "settings"
-/atom/movable/screen/ghost/pai/Click()
- var/mob/dead/observer/G = usr
- G.register_pai()
+/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"
@@ -74,8 +76,8 @@
using.screen_loc = ui_ghost_teleport
static_inventory += using
- using = new /atom/movable/screen/ghost/pai(null, src)
- using.screen_loc = ui_ghost_pai
+ 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)
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 617a395ee4a..1e35113f47d 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -51,7 +51,7 @@
if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_GHOST, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
return TRUE
if(user.client)
- if(user.gas_scan && atmos_scan(user=user, target=src, silent=TRUE))
+ if((user.ghost_hud_flags & GHOST_GAS) && atmos_scan(user=user, target=src, silent=TRUE))
return TRUE
else if(isAdminGhostAI(user))
attack_ai(user)
@@ -60,9 +60,9 @@
return FALSE
/mob/living/attack_ghost(mob/dead/observer/user)
- if(user.client && user.health_scan)
+ if(user.client && (user.ghost_hud_flags & GHOST_HEALTH))
healthscan(user, src, 1, TRUE)
- if(user.client && user.chem_scan)
+ if(user.client && (user.ghost_hud_flags & GHOST_CHEM))
chemscan(user, src)
return ..()
diff --git a/code/datums/view.dm b/code/datums/view.dm
index 702550a4e18..380011fcdc7 100644
--- a/code/datums/view.dm
+++ b/code/datums/view.dm
@@ -72,8 +72,8 @@
height += shitcode[2]
apply()
-/datum/view_data/proc/setTo(toAdd)
- var/list/shitcode = getviewsize(toAdd) //Backward compatibility to account
+/datum/view_data/proc/setTo(to_set)
+ var/list/shitcode = getviewsize(to_set) //Backward compatibility to account
width = shitcode[1] //for a change in how sizes get calculated. we used to include world.view in
height = shitcode[2] //this, but it was jank, so I had to move it
apply()
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index 85b25978a52..2e89a101e2e 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -230,9 +230,6 @@
var/last_asset_job = 0
var/last_completed_asset_job = 0
- /// rate limiting for the crew manifest
- var/crew_manifest_delay
-
/// A buffer of currently held keys.
var/list/keys_held = list()
/// A buffer for combinations such of modifiers + keys (ex: CtrlD, AltE, ShiftT). Format: `"key"` -> `"combo"` (ex: `"D"` -> `"CtrlD"`)
diff --git a/code/modules/events/wizard/ghost.dm b/code/modules/events/wizard/ghost.dm
index 25f2dcfc6c3..def7f428e7c 100644
--- a/code/modules/events/wizard/ghost.dm
+++ b/code/modules/events/wizard/ghost.dm
@@ -24,7 +24,6 @@
description = "Ghosts become visible and gain the power of possession."
/datum/round_event/wizard/possession/start()
- for(var/mob/dead/observer/G in GLOB.player_list)
- add_verb(G, /mob/dead/observer/verb/boo)
- add_verb(G, /mob/dead/observer/verb/possess)
- to_chat(G, "You suddenly feel a welling of new spooky powers...")
+ for(var/mob/dead/observer/ghost_player in GLOB.player_list)
+ ghost_player.fun_verbs = TRUE
+ to_chat(ghost_player, span_hypnophrase("You suddenly feel a welling of new spooky powers..."))
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index e92357f3140..15c6ba475f7 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -297,10 +297,6 @@
/mob/dead/new_player/proc/ViewManifest()
if(!client)
return
- if(world.time < client.crew_manifest_delay)
- return
- client.crew_manifest_delay = world.time + (1 SECONDS)
-
GLOB.manifest.ui_interact(src)
/mob/dead/new_player/Move()
diff --git a/code/modules/mob/dead/observer/ghost_menu.dm b/code/modules/mob/dead/observer/ghost_menu.dm
new file mode 100644
index 00000000000..7580f844ea9
--- /dev/null
+++ b/code/modules/mob/dead/observer/ghost_menu.dm
@@ -0,0 +1,193 @@
+GLOBAL_DATUM_INIT(ghost_menu, /datum/ghost_menu, new)
+
+/datum/ghost_menu
+ ///Static assoc list of all types of lightings ghosts can use & names shown in the UI.
+ var/static/list/ghost_lightings = list(
+ "[LIGHTING_CUTOFF_VISIBLE]" = "Mob Vision",
+ "[LIGHTING_CUTOFF_MEDIUM]" = "Slight Night Vision",
+ "[LIGHTING_CUTOFF_HIGH]" = "Night Vision",
+ "[LIGHTING_CUTOFF_FULLBRIGHT]" = "Fullbright",
+ )
+
+/datum/ghost_menu/ui_state(mob/user)
+ return GLOB.observer_state
+
+/datum/ghost_menu/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if (!ui)
+ ui = new(user, src, "GhostMenu")
+ ui.open()
+
+/datum/ghost_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ if(.)
+ return
+
+ var/mob/dead/observer/dead_user = ui.user
+ switch(action)
+ if("DNR")
+ dead_user.stay_dead()
+ return TRUE
+ if("return_to_body")
+ dead_user.reenter_corpse()
+ return TRUE
+ if("restore_appearance")
+ restore_ghost_appearance(dead_user)
+ return TRUE
+ if("change_notification")
+ var/key = params["key"]
+ if(key && islist(GLOB.poll_ignore[key]))
+ GLOB.poll_ignore[key] ^= list(dead_user.ckey)
+ return TRUE
+ if("turn_all_on")
+ for(var/key in GLOB.poll_ignore)
+ GLOB.poll_ignore[key] &= ~list(dead_user.ckey)
+ return TRUE
+ if("turn_all_off")
+ for(var/key in GLOB.poll_ignore)
+ GLOB.poll_ignore[key] |= list(dead_user.ckey)
+ return TRUE
+ if("signup_pai")
+ SSpai.recruit_window(dead_user)
+ return TRUE
+ if("tray_scan")
+ tray_view(dead_user)
+ return TRUE
+ if("darkness")
+ var/darkness_type = params["darkness_level"]
+ if(isnull(darkness_type))
+ return FALSE
+ for(var/lighting_types in ghost_lightings)
+ if(darkness_type != ghost_lightings[lighting_types])
+ continue
+ toggle_darkness(dead_user, lighting_types)
+ return TRUE
+ if("toggle_visibility")
+ var/to_toggle = params["toggling"]
+ if(!(to_toggle in ALL_GHOST_FLAGS))
+ return
+ toggle_hud_type(dead_user, to_toggle)
+ return TRUE
+ if("crew_manifest")
+ GLOB.manifest.ui_interact(dead_user)
+ return TRUE
+ if("view_range")
+ var/setting_to = text2num(params["new_view_range"]) + GHOST_MIN_VIEW_RANGE
+ if(!isnum(setting_to))
+ return FALSE
+ set_view(dead_user, setting_to)
+ return TRUE
+ if("boo")
+ if(!dead_user.fun_verbs)
+ return FALSE
+ dead_user.boo()
+ return TRUE
+ if("possess")
+ if(!dead_user.fun_verbs)
+ return FALSE
+ dead_user.possess()
+ return TRUE
+
+ return FALSE
+
+/datum/ghost_menu/ui_data(mob/dead/observer/user)
+ var/list/data = list()
+
+ data["can_boo"] = COOLDOWN_FINISHED(user, bootime)
+ data["has_fun"] = user.fun_verbs
+ data["body_name"] = user.can_reenter_corpse ? user.mind.current.real_name : FALSE
+ data["current_darkness"] = ghost_lightings["[user.lighting_cutoff]"]
+ data["notification_data"] = list()
+ for(var/key in GLOB.poll_ignore_desc)
+ data["notification_data"] += list(list(
+ "key" = key,
+ "enabled" = !!(user.ckey in GLOB.poll_ignore[key]),
+ "desc" = GLOB.poll_ignore_desc[key],
+ ))
+
+ data["hud_info"] = list(
+ list(
+ "name" = "Data HUDs",
+ "enabled" = (user.ghost_hud_flags & GHOST_DATA_HUDS),
+ "flag" = GHOST_DATA_HUDS,
+ "tooltip" = "Grants you Med/Sec/Diag HUDs.",
+ ),
+ list(
+ "name" = "Ghost Vision",
+ "enabled" = (user.ghost_hud_flags & GHOST_VISION),
+ "flag" = GHOST_VISION,
+ "tooltip" = "Allows you to see ghost-only things (ex: smuggler satchels, countdowns, camera eyes).",
+ ),
+ list(
+ "name" = "Health Scanner",
+ "enabled" = (user.ghost_hud_flags & GHOST_HEALTH),
+ "flag" = GHOST_HEALTH,
+ "tooltip" = "Allows you to perform a health scan by clicking on someone.",
+ ),
+ list(
+ "name" = "Chemical Scanner",
+ "enabled" = (user.ghost_hud_flags & GHOST_CHEM),
+ "flag" = GHOST_CHEM,
+ "tooltip" = "Allows you to perform a chemical scan by clicking on someone.",
+ ),
+ list(
+ "name" = "Gas Scanner",
+ "enabled" = (user.ghost_hud_flags & GHOST_GAS),
+ "flag" = GHOST_GAS,
+ "tooltip" = "Allows you to perform a gas scan by clicking on a tile/atmos machine.",
+ ),
+ )
+
+ return data
+
+/datum/ghost_menu/ui_static_data(mob/dead/observer/user)
+ var/list/data = list()
+ data["max_extra_view"] = (user.client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT) - GHOST_MIN_VIEW_RANGE
+ data["darkness_levels"] = list()
+ for(var/level in ghost_lightings)
+ data["darkness_levels"] += ghost_lightings[level]
+ data["lag_switch_on"] = !!(SSlag_switch.measures[DISABLE_GHOST_ZOOM_TRAY] && !user.client?.holder)
+ return data
+
+/datum/ghost_menu/proc/tray_view(mob/dead/observer/user)
+ if(SSlag_switch.measures[DISABLE_GHOST_ZOOM_TRAY] && !user.client?.holder)
+ to_chat(user, span_notice("That verb is currently globally disabled."))
+ return
+ t_ray_scan(user)
+
+/datum/ghost_menu/proc/toggle_darkness(mob/dead/observer/user, darkness_type)
+ if(user.lighting_cutoff == darkness_type)
+ return
+ user.lighting_cutoff = text2num(darkness_type)
+ user.update_sight()
+
+/datum/ghost_menu/proc/toggle_hud_type(mob/dead/observer/user, hud_type)
+ user.ghost_hud_flags ^= hud_type
+ //special aftereffects for specific flags.
+ switch(hud_type)
+ if(GHOST_VISION)
+ user.update_sight()
+ if(GHOST_DATA_HUDS)
+ if(user.ghost_hud_flags & GHOST_DATA_HUDS)
+ user.show_data_huds()
+ else
+ user.remove_data_huds()
+
+/datum/ghost_menu/proc/restore_ghost_appearance(mob/dead/observer/user)
+ user.set_ghost_appearance()
+ if(!user.client?.prefs)
+ return
+ var/real_name_pref = user.client.prefs.read_preference(/datum/preference/name/real_name)
+ user.deadchat_name = real_name_pref
+ if(user.mind)
+ user.mind.ghostname = real_name_pref
+ user.name = real_name_pref
+
+/datum/ghost_menu/proc/set_view(mob/dead/observer/user, new_view)
+ if(SSlag_switch.measures[DISABLE_GHOST_ZOOM_TRAY] && !user.client?.holder)
+ to_chat(user, span_notice("That verb is currently globally disabled."))
+ return TRUE
+ var/max_view = user.client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT
+ if(max_view >= new_view && new_view < GHOST_MIN_VIEW_RANGE)
+ return TRUE
+ user.client.view_size.setTo(round(new_view, 1) - GHOST_MIN_VIEW_RANGE)
diff --git a/code/modules/mob/dead/observer/notificationprefs.dm b/code/modules/mob/dead/observer/notificationprefs.dm
deleted file mode 100644
index 5e14f1e5ce9..00000000000
--- a/code/modules/mob/dead/observer/notificationprefs.dm
+++ /dev/null
@@ -1,50 +0,0 @@
-/mob/dead/observer/verb/show_notificationprefs()
- set category = "Ghost"
- set name = "Notification preferences"
- set desc = "Notification preferences"
-
- var/datum/notificationpanel/panel = new(usr)
-
- panel.ui_interact(usr)
-
-/datum/notificationpanel
- var/client/user
-
-/datum/notificationpanel/New(user)
- if (ismob(user))
- var/mob/M = user
- if (!M.client)
- CRASH("Ghost role notification panel attempted to open to a mob without a client")
- src.user = M.client
- else
- src.user = user
-
-/datum/notificationpanel/ui_state(mob/user)
- return GLOB.observer_state
-
-/datum/notificationpanel/ui_interact(mob/user, datum/tgui/ui)
- ui = SStgui.try_update_ui(user, src, ui)
- if(!ui)
- ui = new(user, src, "NotificationPreferences")
- ui.open()
-
-/datum/notificationpanel/ui_data(mob/user)
- . = list()
- .["ignore"] = list()
- for(var/key in GLOB.poll_ignore_desc)
- .["ignore"] += list(list(
- "key" = key,
- "enabled" = (user.ckey in GLOB.poll_ignore[key]),
- "desc" = GLOB.poll_ignore_desc[key]
- ))
-
-/datum/notificationpanel/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
- . = ..()
- if(.)
- return
- switch (action)
- if ("toggle_ignore")
- var/key = params["key"]
- if (key && islist(GLOB.poll_ignore[key]))
- GLOB.poll_ignore[key] ^= list(user.ckey)
- . = TRUE
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index fcd61a3205c..0218035616b 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -22,20 +22,24 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
light_on = FALSE
shift_to_open_context_menu = FALSE
var/can_reenter_corpse
- var/bootime = 0
var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
//If you died in the game and are a ghost - this will remain as null.
//Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot.
var/atom/movable/following = null
- var/fun_verbs = 0
+
+ ///The time between being able to use boo(), if fun_verbs is TRUE.
+ COOLDOWN_DECLARE(bootime)
+ ///Boolean on whether this ghost has access to 'fun' verbs in the ghost menu.
+ var/fun_verbs = FALSE
+
var/image/ghostimage_default = null //this mobs ghost image without accessories and dirs
var/image/ghostimage_simple = null //this mob with the simple white ghost sprite
- var/ghostvision = 1 //is the ghost able to see things humans can't?
var/mob/observetarget = null //The target mob that the ghost is observing. Used as a reference in logout()
- var/data_huds_on = 0 //Are data HUDs currently enabled?
- var/health_scan = FALSE //Are health scans currently enabled?
- var/chem_scan = FALSE //Are chem scans currently enabled?
- var/gas_scan = FALSE //Are gas scans currently enabled?
+
+ ///Flags of huds the ghost currently has enabled, data huds & ghost vision by default.
+ ///Selection: GHOST_DATA_HUDS | GHOST_VISION | GHOST_HEALTH | GHOST_CHEM | GHOST_GAS
+ var/ghost_hud_flags = GHOST_DATA_HUDS | GHOST_VISION
+ ///The shape the ghost will make while orbiting mobs.
var/ghost_orbit = GHOST_ORBIT_CIRCLE
//These variables store hair data if the ghost originates from a species with head and/or facial hair.
@@ -72,12 +76,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
/mob/dead/observer/Initialize(mapload)
set_invisibility(GLOB.observer_default_invisibility)
- add_verb(src, list(
- /mob/dead/observer/proc/dead_tele,
- /mob/dead/observer/proc/open_spawners_menu,
- /mob/dead/observer/proc/tray_view,
- /mob/dead/observer/proc/open_minigames_menu))
-
if(icon_state in GLOB.ghost_forms_with_directions_list)
ghostimage_default = image(src.icon,src,src.icon_state + "_nodir")
else
@@ -133,10 +131,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
name ||= generate_random_mob_name(FALSE)
real_name = name
- if(!fun_verbs)
- remove_verb(src, /mob/dead/observer/verb/boo)
- remove_verb(src, /mob/dead/observer/verb/possess)
-
AddElement(/datum/element/movetype_handler)
add_to_dead_mob_list()
@@ -149,7 +143,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
grant_all_languages()
setup_hud_traits()
show_data_huds()
- data_huds_on = 1
SSpoints_of_interest.make_point_of_interest(src)
ADD_TRAIT(src, TRAIT_HEAR_THROUGH_DARKNESS, ref(src))
@@ -165,7 +158,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_atom_colour)), 1 SECONDS)
/mob/dead/observer/Destroy()
- if(data_huds_on)
+ if(ghost_hud_flags & GHOST_DATA_HUDS)
remove_data_huds()
// Update our old body's medhud since we're abandoning it
@@ -368,9 +361,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(new_area != ambience_tracked_area)
update_ambience_area(new_area)
-/mob/dead/observer/verb/reenter_corpse()
- set category = "Ghost"
- set name = "Re-enter Corpse"
+/mob/dead/observer/proc/reenter_corpse()
if(!client)
return
if(!mind || QDELETED(mind.current))
@@ -390,19 +381,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
mind.current.client.init_verbs()
return TRUE
-/mob/dead/observer/verb/stay_dead()
- set category = "Ghost"
- set name = "Do Not Resuscitate"
- if(!client)
- return
+/mob/dead/observer/proc/stay_dead()
if(!can_reenter_corpse)
to_chat(usr, span_warning("You're already stuck out of your body!"))
return FALSE
- var/response = tgui_alert(usr, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone.", "Are you sure you want to stay dead?", list("DNR","Save Me"))
- if(response != "DNR")
- return
-
can_reenter_corpse = FALSE
var/mob/living/current_mob = mind.current
if(istype(current_mob))
@@ -441,9 +424,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
SEND_SOUND(src, sound(sound))
/mob/dead/observer/proc/dead_tele()
- set category = "Ghost"
- set name = "Teleport"
- set desc= "Teleport to a location"
if(!isobserver(usr))
to_chat(usr, span_warning("Not when you're not dead!"))
return
@@ -469,13 +449,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
usr.abstract_move(pick(L))
-/mob/dead/observer/verb/follow()
- set category = "Ghost"
- set name = "Orbit" // "Haunt"
- set desc = "Follow and orbit a mob."
-
- GLOB.orbit_menu.show(src)
-
// This is the ghost's follow verb with an argument
/mob/dead/observer/proc/ManualFollow(atom/movable/target)
if (!istype(target) || (is_secret_level(target.z) && !client?.holder))
@@ -513,57 +486,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if (!isnull(client) && !isnull(client.eye))
reset_perspective(null)
-/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
- set category = "Ghost"
- set name = "Jump to Mob"
- set desc = "Teleport to a mob"
-
- if(!isobserver(usr)) //Make sure they're an observer!
- return
-
- var/list/possible_destinations = SSpoints_of_interest.get_mob_pois()
- var/target = null
-
- target = tgui_input_list(usr, "Please, select a player!", "Jump to Mob", possible_destinations)
- if(isnull(target))
- return
- if (!isobserver(usr))
- return
-
- var/mob/destination_mob = possible_destinations[target] //Destination mob
-
- // During the break between opening the input menu and selecting our target, has this become an invalid option?
- if(!SSpoints_of_interest.is_valid_poi(destination_mob))
- return
-
- var/mob/source_mob = src //Source mob
- var/turf/destination_turf = get_turf(destination_mob) //Turf of the destination mob
-
- if(isturf(destination_turf))
- source_mob.abstract_move(destination_turf)
- else
- to_chat(source_mob, span_danger("This mob is not located in the game world."))
-
-/mob/dead/observer/verb/change_view_range()
- set category = "Ghost"
- set name = "View Range"
- set desc = "Change your view range."
-
- if(SSlag_switch.measures[DISABLE_GHOST_ZOOM_TRAY] && !client?.holder)
- to_chat(usr, span_notice("That verb is currently globally disabled."))
- return
-
- var/max_view = client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT
- if(client.view_size.getView() == client.view_size.default)
- var/list/views = list()
- for(var/i in 7 to max_view)
- views |= i
- var/new_view = tgui_input_list(usr, "New view", "Modify view range", views)
- if(new_view)
- client.view_size.setTo(clamp(new_view, 7, max_view) - 7)
- else
- client.view_size.resetToDefault()
-
/mob/dead/observer/verb/add_view_range(input as num)
set name = "Add View Range"
set hidden = TRUE
@@ -574,49 +496,21 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/max_view = client.prefs.unlock_content ? GHOST_MAX_VIEW_RANGE_MEMBER : GHOST_MAX_VIEW_RANGE_DEFAULT
if(input)
- client.rescale_view(input, 0, ((max_view*2)+1) - 15)
+ client.rescale_view(input, 0, ((max_view * 2) + 1) - 15)
-/mob/dead/observer/verb/boo()
- set category = "Ghost"
- set name = "Boo!"
- set desc= "Scare your crew members because of boredom!"
-
- if(bootime > world.time)
+/mob/dead/observer/proc/boo()
+ if(!COOLDOWN_FINISHED(src, bootime))
return
var/obj/machinery/light/L = locate(/obj/machinery/light) in view(1, src)
if(L?.flicker())
- bootime = world.time + 600
+ COOLDOWN_START(src, bootime, 60 SECONDS)
//Maybe in the future we can add more spooky code here!
-
-/mob/dead/observer/verb/toggle_ghostsee()
- set name = "Toggle Ghost Vision"
- set desc = "Toggles your ability to see things only ghosts can see, like other ghosts"
- set category = "Ghost"
- ghostvision = !(ghostvision)
- update_sight()
- to_chat(usr, span_boldnotice("You [(ghostvision?"now":"no longer")] have ghost vision."))
-
-/mob/dead/observer/verb/toggle_darkness()
- set name = "Toggle Darkness"
- set category = "Ghost"
- switch(lighting_cutoff)
- if (LIGHTING_CUTOFF_VISIBLE)
- lighting_cutoff = LIGHTING_CUTOFF_MEDIUM
- if (LIGHTING_CUTOFF_MEDIUM)
- lighting_cutoff = LIGHTING_CUTOFF_HIGH
- if (LIGHTING_CUTOFF_HIGH)
- lighting_cutoff = LIGHTING_CUTOFF_FULLBRIGHT
- else
- lighting_cutoff = LIGHTING_CUTOFF_VISIBLE
-
- update_sight()
-
/mob/dead/observer/update_sight()
if(client)
ghost_others = client.prefs.read_preference(/datum/preference/choiced/ghost_others) //A quick update just in case this setting was changed right before calling the proc
- if (!ghostvision)
+ if(!(ghost_hud_flags & GHOST_VISION))
set_invis_see(SEE_INVISIBLE_LIVING)
else
set_invis_see(SEE_INVISIBLE_OBSERVER)
@@ -643,7 +537,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(GHOST_OTHERS_SIMPLE)
client?.images -= GLOB.ghost_images_simple
lastsetting = client?.prefs.read_preference(/datum/preference/choiced/ghost_others)
- if(!ghostvision)
+ if(!(ghost_hud_flags & GHOST_VISION))
return
if(lastsetting != GHOST_OTHERS_THEIR_SETTING)
switch(lastsetting)
@@ -652,11 +546,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(GHOST_OTHERS_SIMPLE)
client?.images |= (GLOB.ghost_images_simple-ghostimage_simple)
-/mob/dead/observer/verb/possess()
- set category = "Ghost"
- set name = "Possess!"
- set desc= "Take over the body of a mindless creature!"
-
+/mob/dead/observer/proc/possess()
var/list/possessible = list()
for(var/mob/living/L in GLOB.alive_mob_list)
if(istype(L,/mob/living/carbon/human/dummy) || !get_turf(L)) //Haha no.
@@ -690,18 +580,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
visible_message(span_deadsay("[src] points to [pointed_at]."))
-/mob/dead/observer/verb/view_manifest()
- set name = "View Crew Manifest"
- set category = "Ghost"
-
- if(!client)
- return
- if(world.time < client.crew_manifest_delay)
- return
- client.crew_manifest_delay = world.time + (1 SECONDS)
-
- GLOB.manifest.ui_interact(src)
-
//this is called when a ghost is drag clicked to something.
/mob/dead/observer/mouse_drop_dragged(atom/over, mob/user)
if (isobserver(user) && user.client.holder && (isliving(over) || iseyemob(over)))
@@ -768,70 +646,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/proc/remove_data_huds()
remove_traits(observer_hud_traits, REF(src))
-/mob/dead/observer/verb/toggle_data_huds()
- set name = "Toggle Sec/Med/Diag HUD"
- set desc = "Toggles whether you see medical/security/diagnostic HUDs"
- set category = "Ghost"
-
- if(data_huds_on) //remove old huds
- remove_data_huds()
- to_chat(src, span_notice("Data HUDs disabled."))
- data_huds_on = 0
- else
- show_data_huds()
- to_chat(src, span_notice("Data HUDs enabled."))
- data_huds_on = 1
-
-/mob/dead/observer/verb/toggle_health_scan()
- set name = "Toggle Health Scan"
- set desc = "Toggles whether you health-scan living beings on click"
- set category = "Ghost"
-
- if(health_scan) //remove old huds
- to_chat(src, span_notice("Health scan disabled."))
- health_scan = FALSE
- else
- to_chat(src, span_notice("Health scan enabled."))
- health_scan = TRUE
-
-/mob/dead/observer/verb/toggle_chem_scan()
- set name = "Toggle Chem Scan"
- set desc = "Toggles whether you scan living beings for chemicals and addictions on click"
- set category = "Ghost"
-
- if(chem_scan) //remove old huds
- to_chat(src, span_notice("Chem scan disabled."))
- chem_scan = FALSE
- else
- to_chat(src, span_notice("Chem scan enabled."))
- chem_scan = TRUE
-
-/mob/dead/observer/verb/toggle_gas_scan()
- set name = "Toggle Gas Scan"
- set desc = "Toggles whether you analyze gas contents on click"
- set category = "Ghost"
-
- if(gas_scan)
- to_chat(src, span_notice("Gas scan disabled."))
- gas_scan = FALSE
- else
- to_chat(src, span_notice("Gas scan enabled."))
- gas_scan = TRUE
-
-/mob/dead/observer/verb/restore_ghost_appearance()
- set name = "Restore Ghost Character"
- set desc = "Sets your deadchat name and ghost appearance to your \
- roundstart character."
- set category = "Ghost"
-
- set_ghost_appearance()
- if(client?.prefs)
- var/real_name = client.prefs.read_preference(/datum/preference/name/real_name)
- deadchat_name = real_name
- if(mind)
- mind.ghostname = real_name
- name = real_name
-
/mob/dead/observer/proc/set_ghost_appearance()
if(!client?.prefs)
return
@@ -868,13 +682,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(NAMEOF(src, icon_state))
ghostimage_default.icon_state = icon_state
ghostimage_simple.icon_state = icon_state
- if(NAMEOF(src, fun_verbs))
- if(fun_verbs)
- add_verb(src, /mob/dead/observer/verb/boo)
- add_verb(src, /mob/dead/observer/verb/possess)
- else
- remove_verb(src, /mob/dead/observer/verb/boo)
- remove_verb(src, /mob/dead/observer/verb/possess)
+ if(NAMEOF(src, invisibility))
+ set_invisibility(invisibility) // updates light
/mob/dead/observer/reset_perspective(atom/A)
if(client)
@@ -898,37 +707,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
hide_other_mob_action_buttons(target)
LAZYREMOVE(target.observers, src)
-/mob/dead/observer/verb/observe()
- set name = "Observe"
- set category = "Ghost"
-
- if(!isobserver(usr) || HAS_TRAIT(src, TRAIT_NO_OBSERVE)) //Make sure they're an observer!
- return
-
- reset_perspective(null)
-
- var/list/possible_destinations = SSpoints_of_interest.get_mob_pois()
- var/target = null
-
- target = tgui_input_list(usr, "Please, select a player!", "Jump to Mob", possible_destinations)
- if(isnull(target))
- return
- if (!isobserver(usr))
- return
-
- reset_perspective(null) // Reset again for sanity
-
- var/mob/chosen_target = possible_destinations[target]
-
- // During the break between opening the input menu and selecting our target, has this become an invalid option?
- if(!SSpoints_of_interest.is_valid_poi(chosen_target))
- return
-
- if (chosen_target == usr)
- return
-
- do_observe(chosen_target)
-
/mob/dead/observer/proc/do_observe(mob/mob_eye)
if(isnewplayer(mob_eye))
stack_trace("/mob/dead/new_player: \[[mob_eye]\] is being observed by [key_name(src)]. This should never happen and has been blocked.")
@@ -965,37 +743,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
else
set_sight(initial(sight))
-/mob/dead/observer/verb/register_pai_candidate()
- set category = "Ghost"
- set name = "pAI Setup"
- set desc = "Upload a fragment of your personality to the global pAI databanks"
-
- register_pai()
-
-/mob/dead/observer/proc/register_pai()
- if(isobserver(src))
- SSpai.recruit_window(src)
- else
- to_chat(usr, span_warning("Can't become a pAI candidate while not dead!"))
-
-/mob/dead/observer/verb/mafia_game_signup()
- set category = "Ghost"
- set name = "Signup for Mafia"
- set desc = "Sign up for a game of Mafia to pass the time while dead."
-
- mafia_signup()
-
-/mob/dead/observer/proc/mafia_signup()
- if(!client)
- return
- if(!isobserver(src))
- to_chat(usr, span_warning("You must be a ghost to join mafia!"))
- return
- var/datum/mafia_controller/game = GLOB.mafia_game //this needs to change if you want multiple mafia games up at once.
- if(!game)
- game = create_mafia_game()
- game.ui_interact(usr)
-
/mob/dead/observer/AltClickOn(atom/target)
client.loot_panel.open(get_turf(target))
@@ -1030,11 +777,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/Process_Spacemove(movement_dir, continuous_move = FALSE)
return TRUE
-/mob/dead/observer/vv_edit_var(var_name, var_value)
- . = ..()
- if(var_name == NAMEOF(src, invisibility))
- set_invisibility(invisibility) // updates light
-
/proc/set_observer_default_invisibility(amount, message=null)
for(var/mob/dead/observer/G in GLOB.player_list)
G.set_invisibility(amount)
@@ -1043,18 +785,12 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
GLOB.observer_default_invisibility = amount
/mob/dead/observer/proc/open_spawners_menu()
- set name = "Spawners Menu"
- set desc = "See all currently available spawners"
- set category = "Ghost"
if(!spawners_menu)
spawners_menu = new(src)
spawners_menu.ui_interact(src)
/mob/dead/observer/proc/open_minigames_menu()
- set name = "Minigames Menu"
- set desc = "See all currently available minigames"
- set category = "Ghost"
if(!client)
return
if(!isobserver(src))
@@ -1065,17 +801,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
minigames_menu.ui_interact(src)
-/mob/dead/observer/proc/tray_view()
- set category = "Ghost"
- set name = "T-ray scan"
- set desc = "Perfom a scan to view sub-floor objects"
-
- if(SSlag_switch.measures[DISABLE_GHOST_ZOOM_TRAY] && !client?.holder)
- to_chat(usr, span_notice("That verb is currently globally disabled."))
- return
-
- t_ray_scan(src)
-
/mob/dead/observer/default_lighting_cutoff()
var/datum/preferences/prefs = client?.prefs
if(!prefs || (client?.combo_hud_enabled && prefs.toggles & COMBOHUD_LIGHTING))
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 01ec2806a0f..e46f09a0873 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -385,10 +385,6 @@
/mob/living/silicon/proc/ai_roster()
if(!client)
return
- if(world.time < client.crew_manifest_delay)
- return
- client.crew_manifest_delay = world.time + (1 SECONDS)
-
GLOB.manifest.ui_interact(src)
/mob/living/silicon/proc/set_autosay() //For allowing the AI and borgs to set the radio behavior of auto announcements (state laws, arrivals).
diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm
index 5c13152551b..fb89d70789e 100644
--- a/code/modules/power/lighting/light.dm
+++ b/code/modules/power/lighting/light.dm
@@ -500,13 +500,13 @@
)
return TRUE
-
/obj/machinery/light/proc/flicker(amount = rand(10, 20))
set waitfor = FALSE
if(flickering)
return
flickering = TRUE
if(on && status == LIGHT_OK)
+ . = TRUE //did we actually flicker? Send this now because we expect immediate response, before sleeping.
for(var/i in 1 to amount)
if(status != LIGHT_OK || !has_power())
break
@@ -518,7 +518,6 @@
else
on = FALSE
update(FALSE)
- . = TRUE //did we actually flicker?
flickering = FALSE
// ai attack - make lights flicker, because why not
diff --git a/icons/hud/screen_ghost.dmi b/icons/hud/screen_ghost.dmi
index 13255a2a168..5868fcfbad4 100644
Binary files a/icons/hud/screen_ghost.dmi and b/icons/hud/screen_ghost.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 34aa3cf08b1..a5ab17d664f 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -4919,9 +4919,9 @@
#include "code\modules\mob\dead\new_player\new_player.dm"
#include "code\modules\mob\dead\new_player\poll.dm"
#include "code\modules\mob\dead\new_player\preferences_setup.dm"
+#include "code\modules\mob\dead\observer\ghost_menu.dm"
#include "code\modules\mob\dead\observer\login.dm"
#include "code\modules\mob\dead\observer\logout.dm"
-#include "code\modules\mob\dead\observer\notificationprefs.dm"
#include "code\modules\mob\dead\observer\observer.dm"
#include "code\modules\mob\dead\observer\observer_movement.dm"
#include "code\modules\mob\dead\observer\observer_say.dm"
diff --git a/tgui/packages/tgui/interfaces/GhostMenu.tsx b/tgui/packages/tgui/interfaces/GhostMenu.tsx
new file mode 100644
index 00000000000..c8b62bba683
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/GhostMenu.tsx
@@ -0,0 +1,271 @@
+import { useState } from 'react';
+import {
+ Button,
+ Dropdown,
+ ImageButton,
+ NumberInput,
+ Section,
+ Stack,
+} from 'tgui-core/components';
+import { BooleanLike } from 'tgui-core/react';
+
+import { useBackend } from '../backend';
+import { Window } from '../layouts';
+
+type Data = {
+ can_boo: BooleanLike;
+ hud_info: HudInfo[];
+ has_fun: BooleanLike;
+ lag_switch_on: BooleanLike;
+ notification_data: NotificationData[];
+ max_extra_view: number;
+ body_name: string;
+ current_darkness: string;
+ darkness_levels: string[];
+};
+
+type HudInfo = {
+ name: string;
+ enabled: BooleanLike;
+ flag: string;
+ tooltip: string;
+};
+
+type NotificationData = {
+ key: string;
+ enabled: BooleanLike;
+ desc: string;
+};
+
+export const GhostMenu = (props) => {
+ const { act, data } = useBackend();
+ const { has_fun, can_boo } = data;
+ return (
+
+
+
+ >
+ )
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const RoundSection = (props) => {
+ const { act, data } = useBackend();
+ const { body_name } = data;
+ return (
+ <>
+ {!!body_name && (
+ act('return_to_body')}
+ fontSize="11px"
+ buttons={
+ act('DNR')}
+ />
+ }
+ >
+ Re-enter {body_name}
+
+ )}
+ act('crew_manifest')}
+ fontSize="11px"
+ >
+ View Crew Manifest
+
+ act('signup_pai')}
+ fontSize="11px"
+ >
+ Sign up as pAI
+
+ >
+ );
+};
+
+const HudSection = (props) => {
+ const { act, data } = useBackend();
+ const { hud_info, lag_switch_on } = data;
+ return (
+
+ {hud_info.map((individual_hud) => (
+
+
+
+ ))}
+ {!lag_switch_on && (
+
+ )}
+
+ );
+};
+
+const GhostSettingsSection = (props) => {
+ const [viewNumber, setviewNumber] = useState(0);
+ const { act, data } = useBackend();
+ const { current_darkness, darkness_levels, max_extra_view, lag_switch_on } =
+ data;
+ return (
+
+
+
+ act('darkness', {
+ darkness_level: value,
+ })
+ }
+ />
+
+
+
+
+ {!lag_switch_on && (
+
+ Extra View Distance:
+ setviewNumber(newValue)}
+ onChange={(new_range) =>
+ act('view_range', {
+ new_view_range: new_range,
+ })
+ }
+ />
+
+ )}
+
+ );
+};
+
+const NotificationPreferences = (props) => {
+ const { act, data } = useBackend();
+ const { notification_data } = data;
+ if (!notification_data) {
+ return 'No notifications!';
+ }
+
+ const ignores = notification_data.sort((a, b) => {
+ const descA = a.desc.toLowerCase();
+ const descB = b.desc.toLowerCase();
+ if (descA < descB) {
+ return -1;
+ }
+ if (descA > descB) {
+ return 1;
+ }
+ return 0;
+ });
+
+ return (
+
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/NotificationPreferences.jsx b/tgui/packages/tgui/interfaces/NotificationPreferences.jsx
deleted file mode 100644
index 41ec2d9958a..00000000000
--- a/tgui/packages/tgui/interfaces/NotificationPreferences.jsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { Button, Section } from 'tgui-core/components';
-
-import { useBackend } from '../backend';
-import { Window } from '../layouts';
-
-export const NotificationPreferences = (props) => {
- const { act, data } = useBackend();
- const ignoresPreSort = data.ignore || [];
- const ignores = ignoresPreSort.sort((a, b) => {
- const descA = a.desc.toLowerCase();
- const descB = b.desc.toLowerCase();
- if (descA < descB) {
- return -1;
- }
- if (descA > descB) {
- return 1;
- }
- return 0;
- });
- return (
-
-
-
- {ignores.map((ignore) => (
- act('toggle_ignore', { key: ignore.key })}
- />
- ))}
-
-
-
- );
-};