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) => ( -
-
-
- ); -};