diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm index 73a307246a..14d54bb1b0 100644 --- a/code/__defines/_planes+layers.dm +++ b/code/__defines/_planes+layers.dm @@ -198,7 +198,6 @@ What is the naming convention for planes or layers? #define LAYER_HUD_ABOVE 4 //Things that reside above items (highlights) #define PLANE_PLAYER_HUD_ITEMS 96 //Separate layer with which to apply colorblindness #define PLANE_PLAYER_HUD_ABOVE 97 //Things above the player hud -#define PLANE_PLAYER_SPLASH 98 //Splash screen //CHOMPEdit #define RADIAL_BACKGROUND_LAYER 0 ///1000 is an unimportant number, it's just to normalize copied layers diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm index 3852940e67..28a4e27f93 100644 --- a/code/__defines/subsystems.dm +++ b/code/__defines/subsystems.dm @@ -119,7 +119,6 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G // Subsystem init_order, from highest priority to lowest priority // Subsystems shutdown in the reverse of the order they initialize in // The numbers just define the ordering, they are meaningless otherwise. -#define INIT_ORDER_TITLE 99 //CHOMPEdit #define INIT_ORDER_SERVER_MAINT 93 #define INIT_ORDER_ADMIN_VERBS 84 // needs to be pretty high, admins can't do much without it #define INIT_ORDER_WEBHOOKS 50 diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index cc0398c3cb..b884dd4e7c 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -706,51 +706,6 @@ /obj/screen/setup_preview/bg/Click(params) pref?.bgstate = next_in_list(pref.bgstate, pref.bgstate_options) pref?.update_preview_icon() - -/obj/screen/splash - screen_loc = "1,1" - layer = LAYER_HUD_ABOVE - plane = PLANE_PLAYER_HUD_ABOVE - var/client/holder - -INITIALIZE_IMMEDIATE(/obj/screen/splash) -/obj/screen/splash/Initialize(mapload, visible) - . = ..() - - if(!isclient(loc)) - return INITIALIZE_HINT_QDEL - - holder = loc - - if(!visible) - alpha = 0 - - if(!lobby_image) - return INITIALIZE_HINT_QDEL - - icon = lobby_image.icon - icon_state = lobby_image.icon_state - - holder.screen += src - -/obj/screen/splash/proc/Fade(out, qdel_after = TRUE) - if(QDELETED(src)) - return - if(out) - animate(src, alpha = 0, time = 30) - else - alpha = 0 - animate(src, alpha = 255, time = 30) - if(qdel_after) - QDEL_IN(src, 30) - -/obj/screen/splash/Destroy() - if(holder) - holder.screen -= src - holder = null - return ..() - - /** * This object holds all the on-screen elements of the mapping unit. * It has a decorative frame and onscreen buttons. The map itself is drawn diff --git a/code/controllers/subsystems/tgui.dm b/code/controllers/subsystems/tgui.dm index a03e3452c3..1563be683d 100644 --- a/code/controllers/subsystems/tgui.dm +++ b/code/controllers/subsystems/tgui.dm @@ -279,7 +279,7 @@ SUBSYSTEM_DEF(tgui) if(length(user?.tgui_open_uis) == 0) return count for(var/datum/tgui/ui in user.tgui_open_uis) - if(isnull(src_object) || ui.src_object == src_object) + if((isnull(src_object) || ui.src_object == src_object) && ui.closeable) ui.close(logout = logout) count++ return count diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index b00fbac78f..907eb83f32 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -421,8 +421,6 @@ var/global/datum/controller/subsystem/ticker/ticker if(new_char) qdel(player) if(new_char.client) - var/obj/screen/splash/S = new(new_char.client, TRUE) - S.Fade(TRUE) new_char.client.init_verbs() // If they're a carbon, they can get manifested diff --git a/code/controllers/subsystems/title_ch.dm b/code/controllers/subsystems/title_ch.dm deleted file mode 100644 index e70ae8662b..0000000000 --- a/code/controllers/subsystems/title_ch.dm +++ /dev/null @@ -1,96 +0,0 @@ -SUBSYSTEM_DEF(title) - name = "Title Screen" - flags = SS_NO_FIRE - init_order = INIT_ORDER_TITLE -// init_stage = INITSTAGE_EARLY - - var/file_path - var/icon/icon - var/icon_state - var/icon/previous_icon - var/turf/closed/indestructible/splashscreen/splash_turf - -/datum/controller/subsystem/title/Initialize() - if(file_path && icon) - return SS_INIT_SUCCESS - /* - if(fexists("data/previous_title.dat")) - var/previous_path = file2text("data/previous_title.dat") - if(istext(previous_path)) - previous_icon = new(previous_icon) - fdel("data/previous_title.dat") - - var/list/provisional_title_screens = flist("[global.config.directory]/title_screens/images/") - var/list/title_screens = list() - var/use_rare_screens = prob(1) - - for(var/S in provisional_title_screens) - var/list/L = splittext(S,"+") - if((L.len == 1 && (L[1] != "exclude" && L[1] != "blank.png")) || (L.len > 1 && ((use_rare_screens && LOWER_TEXT(L[1]) == "rare") || (LOWER_TEXT(L[1]) == LOWER_TEXT(SSmapping.config.map_name))))) - title_screens += S - - if(length(title_screens)) - file_path = "[global.config.directory]/title_screens/images/[pick(title_screens)]" - - if(!file_path) - file_path = "icons/runtime/default_title.dmi" - - ASSERT(fexists(file_path)) - - icon = new(fcopy_rsc(file_path)) - */ - icon = new(using_map.lobby_icon) - var/known_icon_states = cached_icon_states(icon) - for(var/lobby_screen in using_map.lobby_screens) - if(!(lobby_screen in known_icon_states)) - error("Lobby screen '[lobby_screen]' did not exist in the icon set [icon].") - using_map.lobby_screens -= lobby_screen - - if(using_map.lobby_screens.len) - icon_state = pick(using_map.lobby_screens) - else - icon_state = known_icon_states[1] - - if(splash_turf) - splash_turf.icon = icon - splash_turf.icon_state = icon_state - splash_turf.handle_generic_titlescreen_sizes() - - return SS_INIT_SUCCESS - -/datum/controller/subsystem/title/vv_edit_var(var_name, var_value) - . = ..() - if(.) - switch(var_name) - if(NAMEOF(src, icon)) - if(splash_turf) - splash_turf.icon = icon - -/datum/controller/subsystem/title/Shutdown() - /*if(file_path) - var/F = file("data/previous_title.dat") - WRITE_FILE(F, file_path)*/ - - /*for(var/thing in GLOB.clients) - if(!thing) - continue - var/atom/movable/screen/splash/S = new(thing, FALSE) - S.Fade(FALSE,FALSE)*/ - -/datum/controller/subsystem/title/Recover() - icon = SStitle.icon - splash_turf = SStitle.splash_turf - file_path = SStitle.file_path - previous_icon = SStitle.previous_icon - -// Must be immediate because players will -// join before SSatom initializes everything. -INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player) - -/obj/effect/landmark/start/new_player - name = "New Player" - -/obj/effect/landmark/start/new_player/Initialize(mapload) - ..() - GLOB.newplayer_start += loc - return INITIALIZE_HINT_QDEL diff --git a/code/datums/managed_browsers/feedback_form.dm b/code/datums/managed_browsers/feedback_form.dm index 3717e3e16a..f04d162b0a 100644 --- a/code/datums/managed_browsers/feedback_form.dm +++ b/code/datums/managed_browsers/feedback_form.dm @@ -141,7 +141,4 @@ GENERAL_PROTECT_DATUM(/datum/managed_browser/feedback_form) return my_client.mob << browse(null, "window=[browser_id]") // Closes the window. - if(isnewplayer(my_client.mob)) - var/mob/new_player/NP = my_client.mob - NP.new_player_panel_proc() // So the feedback button goes away, if the user gets put on cooldown. qdel(src) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 104c8bedcd..d02118c24c 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -357,7 +357,6 @@ var/global/datum/controller/occupations/job_master for(var/mob/new_player/player in unassigned) if(player.client.prefs.alternate_option == RETURN_TO_LOBBY) player.ready = 0 - player.new_player_panel_proc() unassigned -= player return 1 diff --git a/code/game/turfs/closed/_closed_ch.dm b/code/game/turfs/closed/_closed_ch.dm deleted file mode 100644 index 8d4df6acbd..0000000000 --- a/code/game/turfs/closed/_closed_ch.dm +++ /dev/null @@ -1,14 +0,0 @@ -/turf/closed - //layer = CLOSED_TURF_LAYER - //plane = WALL_PLANE - //turf_flags = IS_SOLID - opacity = TRUE - density = TRUE - blocks_air = TRUE - //init_air = FALSE - //rad_insulation = RAD_MEDIUM_INSULATION - //pass_flags_self = PASSCLOSEDTURF -/* -/turf/closed/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir) - return FALSE -*/ diff --git a/code/game/turfs/closed/indestructible_ch.dm b/code/game/turfs/closed/indestructible_ch.dm deleted file mode 100644 index 1f871f3b3b..0000000000 --- a/code/game/turfs/closed/indestructible_ch.dm +++ /dev/null @@ -1,76 +0,0 @@ -/turf/closed/indestructible - name = "wall" - desc = "Effectively impervious to conventional methods of destruction." - icon = 'icons/turf/walls.dmi' - //explosive_resistance = 50 -/* -/turf/closed/indestructible/rust_heretic_act() - return - -/turf/closed/indestructible/TerraformTurf(path, new_baseturf, flags, defer_change = FALSE, ignore_air = FALSE) - return - -/turf/closed/indestructible/acid_act(acidpwr, acid_volume, acid_id) - return FALSE -*/ -/turf/closed/indestructible/melt() - return - -/turf/closed/indestructible/singularity_act() - return - -/turf/closed/indestructible/ex_act() - return -/* -/turf/closed/indestructible/attackby(obj/item/attacking_item, mob/user, params) - if(istype(attacking_item, /obj/item/poster) && Adjacent(user)) - return place_poster(attacking_item, user) - - return ..() -*/ -//Splashscreen - -/turf/closed/indestructible/splashscreen - name = "Space Station 13" - desc = null - icon = 'icons/misc/loading.dmi' - icon_state = "loading(old)" - pixel_x = 0 - plane = PLANE_PLAYER_SPLASH - -INITIALIZE_IMMEDIATE(/turf/closed/indestructible/splashscreen) - -/turf/closed/indestructible/splashscreen/Initialize(mapload) - . = ..() - SStitle.splash_turf = src - if(SStitle.icon) - icon = SStitle.icon - icon_state = SStitle.icon_state - handle_generic_titlescreen_sizes() - -///helper proc that will center the screen if the icon is changed to a generic width, to make admins have to fudge around with pixel_x less. returns null -/turf/closed/indestructible/splashscreen/proc/handle_generic_titlescreen_sizes() - var/icon/size_check = icon(SStitle.icon, icon_state) - var/width = size_check.Width() - if(width == 480 || width == 500) // 480x480 is nonwidescreen - pixel_x = 0 - else if(width == 608) // 608x480 is widescreen - pixel_x = -64 - -/turf/closed/indestructible/splashscreen/vv_edit_var(var_name, var_value) - . = ..() - if(.) - switch(var_name) - if(NAMEOF(src, icon)) - SStitle.icon = icon - handle_generic_titlescreen_sizes() - -/turf/closed/indestructible/splashscreen/examine() - //desc = pick(strings(SPLASH_FILE, "splashes")) - return ..() - -/turf/closed/indestructible/start_area - name = null - desc = null - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - icon_state = "0" diff --git a/code/modules/asset_cache/assets/lobby.dm b/code/modules/asset_cache/assets/lobby.dm new file mode 100644 index 0000000000..46d61ef305 --- /dev/null +++ b/code/modules/asset_cache/assets/lobby.dm @@ -0,0 +1,10 @@ +/datum/asset/simple/lobby_files + keep_local_name = TRUE + assets = list( + "lobby_loading.gif" = 'html/lobby/loading.gif', + "load.ogg" = 'sound/lobby/lobby_load.ogg', + ) + +/datum/asset/simple/lobby_files/register() + assets["lobby_bg.gif"] = icon(using_map.lobby_icon, pick(using_map.lobby_screens)) + . = ..() diff --git a/code/modules/clothing/gloves/miscellaneous_vr.dm b/code/modules/clothing/gloves/miscellaneous_vr.dm index 04359c3ccb..8f286ed21c 100644 --- a/code/modules/clothing/gloves/miscellaneous_vr.dm +++ b/code/modules/clothing/gloves/miscellaneous_vr.dm @@ -17,6 +17,7 @@ item_state = "wedring_s" /obj/item/clothing/gloves/color + name = "gloves" desc = "A pair of gloves, they don't look special in any way." item_state_slots = list(slot_r_hand_str = "white", slot_l_hand_str = "white") icon_state = "latex" diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index d6a5ffcbdd..9d539edaa9 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -31,6 +31,7 @@ log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).") /mob/Login() + persistent_ckey = client.ckey player_list |= src update_Login_details() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index bc7dca8590..9507e5ad89 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -246,3 +246,6 @@ var/custom_footstep = FOOTSTEP_MOB_SHOE VAR_PRIVATE/is_motion_tracking = FALSE // Prevent multiple unsubs and resubs, also used to check if the vis layer is enabled, use has_motiontracking() to get externally. VAR_PRIVATE/wants_to_see_motion_echos = TRUE + + /// a ckey that persists client logout / ghosting, replaced when a client inhabits the mob + var/persistent_ckey diff --git a/code/modules/mob/new_player/lobby_browser.dm b/code/modules/mob/new_player/lobby_browser.dm new file mode 100644 index 0000000000..a7349886b0 --- /dev/null +++ b/code/modules/mob/new_player/lobby_browser.dm @@ -0,0 +1,162 @@ +/mob/new_player/proc/initialize_lobby_screen() + if(!client) + return + + var/datum/tgui/ui = SStgui.get_open_ui(src, src) + if(ui) + ui.close() + + winset(src, "lobby_browser", "is-disabled=false;is-visible=true") + // winset(src, "mapwindow.status_bar", "is-visible=false") + lobby_window = new(client, "lobby_browser") + lobby_window.initialize( + assets = list( + get_asset_datum(/datum/asset/simple/tgui) + ) + ) + + tgui_interact(src) + +/mob/new_player/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui, custom_state) + . = ..() + + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "LobbyMenu", window = lobby_window) + ui.closeable = FALSE + ui.open(preinitialized = TRUE) + +/mob/new_player/tgui_state(mob/user) + return GLOB.tgui_always_state + +/mob/new_player/ui_assets(mob/user) + . = ..() + . += get_asset_datum(/datum/asset/simple/lobby_files) + +/mob/new_player/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + var/displayed_name = world.name + if(config && CONFIG_GET(string/servername)) + displayed_name = CONFIG_GET(string/servername) + + data["server_name"] = displayed_name + data["map"] = using_map.full_name + data["station_time"] = stationtime2text() + data["display_loading"] = SSticker.current_state == GAME_STATE_INIT + data["round_start"] = !SSticker.mode || SSticker.current_state <= GAME_STATE_PREGAME + data["round_time"] = roundduration2text() + data["ready"] = ready + data["new_news"] = client?.check_for_new_server_news() + data["can_submit_feedback"] = SSsqlite.can_submit_feedback(client) + data["show_station_news"] = GLOB.news_data.station_newspaper + data["new_station_news"] = client.prefs.lastlorenews != GLOB.news_data.newsindex + data["new_changelog"] = read_preference(/datum/preference/text/lastchangelog) == GLOB.changelog_hash + + return data + +/mob/new_player/tgui_static_data(mob/user) + var/list/data = ..() + + data["bg"] = 'icons/misc/loading.dmi' + data["bg_state"] = "loading" + + return data + +/mob/new_player/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + . = ..() + if(.) + return + + switch(action) + if("character_setup") + client.prefs.ShowChoices(src) + return TRUE + if("ready") + if(!SSticker || SSticker.current_state <= GAME_STATE_PREGAME) + ready = !ready + else + ready = 0 + return TRUE + if("manifest") + ViewManifest() + return TRUE + if("late_join") + if(!ticker || ticker.current_state != GAME_STATE_PLAYING) + to_chat(usr, span_red("The round is either not ready, or has already finished...")) + return TRUE + + var/time_till_respawn = time_till_respawn() + if(time_till_respawn == -1) // Special case, never allowed to respawn + to_chat(usr, span_warning("Respawning is not allowed!")) + else if(time_till_respawn) // Nonzero time to respawn + to_chat(usr, span_warning("You can't respawn yet! You need to wait another [round(time_till_respawn/10/60, 0.1)] minutes.")) + return TRUE + LateChoices() + return TRUE + if("observe") + if(!SSticker || SSticker.current_state == GAME_STATE_INIT) + to_chat(src, span_warning("The game is still setting up, please try again later.")) + return TRUE + if(tgui_alert(src,"Are you sure you wish to observe? If you do, make sure to not use any knowledge gained from observing if you decide to join later.","Observe Round?",list("Yes","No")) == "Yes") + if(!client) + return TRUE + + //Make a new mannequin quickly, and allow the observer to take the appearance + var/mob/living/carbon/human/dummy/mannequin = get_mannequin(client.ckey) + client.prefs.dress_preview_mob(mannequin) + var/mob/observer/dead/observer = new(mannequin) + observer.moveToNullspace() //Let's not stay in our doomed mannequin + + spawning = 1 + if(client.media) + client.media.stop_music() // MAD JAMS cant last forever yo + + observer.started_as_observer = 1 + close_spawn_windows() + var/obj/O = locate("landmark*Observer-Start") + if(istype(O)) + to_chat(src, span_notice("Now teleporting.")) + observer.forceMove(O.loc) + else + to_chat(src, span_danger("Could not locate an observer spawn point. Use the Teleport verb to jump to the station map.")) + + announce_ghost_joinleave(src) + + if(client.prefs.read_preference(/datum/preference/toggle/human/name_is_always_random)) + client.prefs.real_name = random_name(client.prefs.identifying_gender) + observer.real_name = client.prefs.real_name + observer.name = observer.real_name + if(!client.holder && !CONFIG_GET(flag/antag_hud_allowed)) // For new ghosts we remove the verb from even showing up if it's not allowed. + remove_verb(observer, /mob/observer/dead/verb/toggle_antagHUD) // Poor guys, don't know what they are missing! + observer.key = key + observer.set_respawn_timer(time_till_respawn()) // Will keep their existing time if any, or return 0 and pass 0 into set_respawn_timer which will use the defaults + observer.client.init_verbs() + qdel(src) + + return TRUE + if("shownews") + handle_server_news() + return TRUE + if("give_feedback") + if(!SSsqlite.can_submit_feedback(GLOB.directory[persistent_ckey])) + return + + if(client.feedback_form) + client.feedback_form.display() // In case they closed the form early. + else + client.feedback_form = new(client) + return TRUE + if("open_station_news") + show_latest_news(GLOB.news_data.station_newspaper) + return TRUE + if("open_changelog") + write_preference_directly(/datum/preference/text/lastchangelog, GLOB.changelog_hash) + client.changes() + return TRUE + if("keyboard") + if(!SSsounds.subsystem_initialized) + return + + playsound_local(ui.user, get_sfx("keyboard"), vol = 20) + return TRUE diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm index 684c47358f..c4befc15e8 100644 --- a/code/modules/mob/new_player/login.dm +++ b/code/modules/mob/new_player/login.dm @@ -1,31 +1,3 @@ -///var/atom/movable/lobby_image = new /atom/movable{icon = 'icons/misc/title.dmi'; icon_state = lobby_image_state; screen_loc = "1,1"; name = "Polaris"} - -var/obj/effect/lobby_image = new /obj/effect/lobby_image - -/obj/effect/lobby_image - name = "CHOMPStation" // CHOMPEdit - desc = "How are you reading this?" - screen_loc = "1,1" - icon = 'icons/misc/loading.dmi' - icon_state = "loading(old)" // CHOMPEdit - -/obj/effect/lobby_image/Initialize(mapload) - icon = using_map.lobby_icon - var/known_icon_states = cached_icon_states(icon) - for(var/lobby_screen in using_map.lobby_screens) - if(!(lobby_screen in known_icon_states)) - error("Lobby screen '[lobby_screen]' did not exist in the icon set [icon].") - using_map.lobby_screens -= lobby_screen - - if(using_map.lobby_screens.len) - icon_state = pick(using_map.lobby_screens) - else - icon_state = known_icon_states[1] - . = ..() - -/mob/new_player - var/client/my_client // Need to keep track of this ourselves, since by the time Logout() is called the client has already been nulled - /mob/new_player/Login() update_Login_details() //handles setting lastKnownIP and computer_id for use by the ban systems as well as checking for multikeying if(GLOB.join_motd) @@ -41,23 +13,19 @@ var/obj/effect/lobby_image = new /obj/effect/lobby_image mind.active = 1 mind.current = src - //CHOMPEdit Begin - if(length(GLOB.newplayer_start)) - forceMove(pick(GLOB.newplayer_start)) - else - forceMove(locate(1,1,1)) - //CHOMPEdit End + if(client) + persistent_ckey = client.ckey - //loc = null CHOMPEdit Removal - //client.screen += lobby_image CHOMPEdit Removal - my_client = client + loc = null sight |= SEE_TURFS + + initialize_lobby_screen() + player_list |= src created_for = ckey if(!QDELETED(src)) - new_player_panel() addtimer(CALLBACK(src, PROC_REF(do_after_login)), 4 SECONDS, TIMER_DELETE_ME) /mob/new_player/proc/do_after_login() diff --git a/code/modules/mob/new_player/logout.dm b/code/modules/mob/new_player/logout.dm index bbffe5e9ba..29a3abddad 100644 --- a/code/modules/mob/new_player/logout.dm +++ b/code/modules/mob/new_player/logout.dm @@ -1,10 +1,11 @@ /mob/new_player/Logout() ready = 0 - // see login.dm - if(my_client) - my_client.screen -= lobby_image - my_client = null + QDEL_NULL(lobby_window) + + var/client/exiting_client = GLOB.directory[persistent_ckey] + if(exiting_client) + winset(exiting_client, "lobby_browser", "is-disabled=true;is-visible=false") ..() diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 6a2a0d3801..cbb295fb70 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -5,9 +5,8 @@ var/spawning = 0 //Referenced when you want to delete the new_player later on in the code. var/totalPlayers = 0 //Player counts for the Lobby tab var/totalPlayersReady = 0 - var/show_hidden_jobs = 0 //Show jobs that are set to "Never" in preferences var/has_respawned = FALSE //Determines if we're using RESPAWN_MESSAGE - var/datum/browser/panel + var/datum/tgui_window/lobby_window = null var/datum/tgui_module/crew_manifest/new_player/manifest_dialog = null var/datum/tgui_module/late_choices/late_choices_dialog = null universal_speak = 1 @@ -27,103 +26,12 @@ add_verb(src, /mob/proc/insidePanel) /mob/new_player/Destroy() - if(panel) - QDEL_NULL(panel) if(manifest_dialog) QDEL_NULL(manifest_dialog) if(late_choices_dialog) QDEL_NULL(late_choices_dialog) . = ..() -/mob/new_player/verb/new_player_panel() - set src = usr - new_player_panel_proc() - - -/mob/new_player/proc/new_player_panel_proc() - var/output = "
" - - output += span_bold("Map:") + " [using_map.full_name]
" - output += span_bold("Station Time:") + " [stationtime2text()]
" - - if(!ticker || ticker.current_state <= GAME_STATE_PREGAME) - output += span_bold("Server Initializing!") - else - output += span_bold("Round Duration:") + " [roundduration2text()]
" - output += "
" - - output += "

Character Setup

" - - if(!ticker || ticker.current_state <= GAME_STATE_PREGAME) - if(ready) - output += "

\[ " + span_linkOn(span_bold("Ready")) + " | Not Ready \]

" //ChompEDIT - fixed height - else - output += "

\[ Ready | " + span_linkOn(span_bold("Not Ready")) + " \]

" - output += "

Join Game!

" - - else - output += "

View the Crew Manifest

" - output += "

Join Game!

" - - output += "

Observe

" - - output += "
" //ChompADD - a line divider between functional and info buttons - - //nobody uses this feature //WELL WE'RE GONNA - if(!IsGuestKey(src.key)) - establish_db_connection() - - if(SSdbcore.IsConnected()) - var/isadmin = 0 - if(src.client && src.client.holder) - isadmin = 1 - var/datum/db_query/query = SSdbcore.NewQuery("SELECT id FROM erro_poll_question WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM erro_poll_vote WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM erro_poll_textreply WHERE ckey = \"[ckey]\")") - query.Execute() - var/newpoll = 0 - while(query.NextRow()) - newpoll = 1 - break - qdel(query) - if(newpoll) - output += "

Show Player Polls
(NEW!)

" - else - output += "

Show Player Polls
No Changes

" - - if(client?.check_for_new_server_news()) - output += "

Show Server News
(NEW!)

" - else - output += "

Show Server News
No Changes

" - - if(SSsqlite.can_submit_feedback(client)) - output += "

[href(src, list("give_feedback" = 1), "Give Feedback")]

" - - if(GLOB.news_data.station_newspaper) - if(client.prefs.lastlorenews == GLOB.news_data.newsindex) - output += "

Show [using_map.station_name] News
No Changes

" - else - output += "

Show [using_map.station_name] News
(NEW!)

" - - if(read_preference(/datum/preference/text/lastchangelog) == GLOB.changelog_hash) - output += "

Show Changelog
No Changes

" - else - output += "

Show Changelog
(NEW!)

" - - output += "
" - - if (client.prefs?.lastlorenews == GLOB.news_data.newsindex) - client.seen_news = 1 - - if(GLOB.news_data.station_newspaper && !client.seen_news && client.prefs?.read_preference(/datum/preference/toggle/show_lore_news)) - show_latest_news(GLOB.news_data.station_newspaper) - client.prefs.lastlorenews = GLOB.news_data.newsindex - SScharacter_setup.queue_preferences_save(client.prefs) - - panel = new(src, "Welcome","Welcome", 210, 500, src) - panel.set_window_options("can_close=0") - panel.set_content(output) - panel.open() - return - /mob/new_player/get_status_tab_items() . = ..() . += "" @@ -161,78 +69,6 @@ /mob/new_player/Topic(href, href_list[]) if(!client) return 0 - if(href_list["show_preferences"]) - client.prefs.ShowChoices(src) - return 1 - - if(href_list["ready"]) - if(!ticker || ticker.current_state <= GAME_STATE_PREGAME) // Make sure we don't ready up after the round has started - ready = text2num(href_list["ready"]) - else - ready = 0 - - if(href_list["refresh"]) - panel.close() - new_player_panel_proc() - - if(href_list["observe"]) - if(!SSticker || SSticker.current_state == GAME_STATE_INIT) - to_chat(src, span_warning("The game is still setting up, please try again later.")) - return 0 - if(tgui_alert(src,"Are you sure you wish to observe? If you do, make sure to not use any knowledge gained from observing if you decide to join later.","Observe Round?",list("Yes","No")) == "Yes") - if(!client) return 1 - - //Make a new mannequin quickly, and allow the observer to take the appearance - var/mob/living/carbon/human/dummy/mannequin = get_mannequin(client.ckey) - client.prefs.dress_preview_mob(mannequin) - var/mob/observer/dead/observer = new(mannequin) - observer.moveToNullspace() //Let's not stay in our doomed mannequin - - spawning = 1 - if(client.media) - client.media.stop_music() // MAD JAMS cant last forever yo - - observer.started_as_observer = 1 - close_spawn_windows() - var/obj/O = locate("landmark*Observer-Start") - if(istype(O)) - to_chat(src, span_notice("Now teleporting.")) - observer.forceMove(O.loc) - else - to_chat(src, span_danger("Could not locate an observer spawn point. Use the Teleport verb to jump to the station map.")) - - announce_ghost_joinleave(src) - - if(client.prefs.read_preference(/datum/preference/toggle/human/name_is_always_random)) - client.prefs.real_name = random_name(client.prefs.identifying_gender) - observer.real_name = client.prefs.real_name - observer.name = observer.real_name - if(!client.holder && !CONFIG_GET(flag/antag_hud_allowed)) // For new ghosts we remove the verb from even showing up if it's not allowed. - remove_verb(observer, /mob/observer/dead/verb/toggle_antagHUD) // Poor guys, don't know what they are missing! - observer.key = key - observer.set_respawn_timer(time_till_respawn()) // Will keep their existing time if any, or return 0 and pass 0 into set_respawn_timer which will use the defaults - observer.client.init_verbs() - qdel(src) - - return TRUE - - if(href_list["late_join"]) - - if(!ticker || ticker.current_state != GAME_STATE_PLAYING) - to_chat(usr, span_red("The round is either not ready, or has already finished...")) - return - - var/time_till_respawn = time_till_respawn() - if(time_till_respawn == -1) // Special case, never allowed to respawn - to_chat(usr, span_warning("Respawning is not allowed!")) - else if(time_till_respawn) // Nonzero time to respawn - to_chat(usr, span_warning("You can't respawn yet! You need to wait another [round(time_till_respawn/10/60, 0.1)] minutes.")) - return - LateChoices() - - if(href_list["manifest"]) - ViewManifest() - if(href_list["privacy_poll"]) establish_db_connection() if(!SSdbcore.IsConnected()) @@ -275,13 +111,6 @@ if(!ready && href_list["preference"]) if(client) client.prefs.process_link(src, href_list) - else if(!href_list["late_join"]) - new_player_panel() - - if(href_list["showpoll"]) - - handle_player_polling() - return if(href_list["pollid"]) @@ -333,27 +162,6 @@ if(!isnull(href_list["option_[optionid]"])) //Test if this optionid was selected vote_on_poll(pollid, optionid, 1) - if(href_list["shownews"]) - handle_server_news() - return - - if(href_list["hidden_jobs"]) - show_hidden_jobs = !show_hidden_jobs - LateChoices() - - if(href_list["give_feedback"]) - if(!SSsqlite.can_submit_feedback(my_client)) - return - - if(client.feedback_form) - client.feedback_form.display() // In case they closed the form early. - else - client.feedback_form = new(client) - - if(href_list["open_changelog"]) - write_preference_directly(/datum/preference/text/lastchangelog, GLOB.changelog_hash) - client.changes() - return /mob/new_player/proc/handle_server_news() if(!client) @@ -479,9 +287,6 @@ var/mob/living/character = create_character(T) //creates the human and transfers vars and mind character = job_master.EquipRank(character, rank, 1) //equips the human UpdateFactionList(character) - if(character && character.client) - var/obj/screen/splash/Spl = new(character.client, TRUE) - Spl.Fade(TRUE) var/datum/job/J = SSjob.get_job(rank) @@ -674,7 +479,6 @@ src << browse(null, "window=latechoices") //closes late choices window src << browse(null, "window=preferences_window") //VOREStation Edit? src << browse(null, "window=News") //closes news window - panel.close() /mob/new_player/get_species() var/datum/species/chosen_species diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm index 1fa12e3cbe..3c6ea6fffc 100644 --- a/code/modules/tgui/tgui.dm +++ b/code/modules/tgui/tgui.dm @@ -47,6 +47,8 @@ var/list/children = list() /// Any partial packets that we have received from TGUI, waiting to be sent var/partial_packets + /// If the window should be closed with other windows when requested + var/closeable = TRUE /** * public @@ -60,13 +62,13 @@ * optional parent_ui datum/tgui The parent of this UI. * optional ui_x int Deprecated: Window width. * optional ui_y int Deprecated: Window height. + * optional window datum/tgui_window: The window to display this TGUI within * * return datum/tgui The requested UI. */ -/datum/tgui/New(mob/user, datum/src_object, interface, title, datum/tgui/parent_ui, ui_x, ui_y) +/datum/tgui/New(mob/user, datum/src_object, interface, title, datum/tgui/parent_ui, ui_x, ui_y, datum/tgui_window/window) src.user = user src.src_object = src_object - src.window_key = "[REF(src_object)]-main" src.interface = interface if(title) src.title = title @@ -78,6 +80,12 @@ if(ui_x && ui_y) src.window_size = list(ui_x, ui_y) + if(window) + src.window = window + src.window_key = window.id + else + src.window_key = "[REF(src_object)]-main" + /datum/tgui/Destroy() user = null src_object = null @@ -88,22 +96,26 @@ * * Open this UI (and initialize it with data). * + * Args: + * preinitialized: bool - if TRUE, we will not attempt to force strict mode on the tgui's window datum + * * return bool - TRUE if a new pooled window is opened, FALSE in all other situations including if a new pooled window didn't open because one already exists. */ -/datum/tgui/proc/open() +/datum/tgui/proc/open(preinitialized = FALSE) if(!user?.client) return FALSE - if(window) + if(window && window.status > TGUI_WINDOW_LOADING) return FALSE process_status() if(status < STATUS_UPDATE) return FALSE - window = SStgui.request_pooled_window(user) + if(!window) + window = SStgui.request_pooled_window(user) if(!window) return FALSE opened_at = world.time window.acquire_lock(src) - if(!window.is_ready()) + if(!window.is_ready() && !preinitialized) window.initialize( strict_mode = TRUE, fancy = user.read_preference(/datum/preference/toggle/tgui_fancy), diff --git a/html/lobby/loading.gif b/html/lobby/loading.gif new file mode 100644 index 0000000000..4d2f0623d3 Binary files /dev/null and b/html/lobby/loading.gif differ diff --git a/icons/misc/splash_screen.dmi b/icons/misc/splash_screen.dmi index 93f7163dd5..62e4cc7843 100644 Binary files a/icons/misc/splash_screen.dmi and b/icons/misc/splash_screen.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index bfeeb3b11a..52e109c44e 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -1283,6 +1283,15 @@ window "mapwindow" on-show = ".winset\"mainwindow.mainvsplit.left=mapwindow\"" on-hide = ".winset\"mainwindow.mainvsplit.left=\"" style = ".center { text-align: center; } .runechatdiv {background-color: #20202070} .black_outline { -dm-text-outline: 1px black } .boldtext { font-weight: bold; } .maptext { font-family: 'Grand9K Pixel'; font-size: 6pt; -dm-text-outline: 1px black; color: white; line-height: 1.0; } .command_headset { font-weight: bold;\tfont-size: 8px; } .small { font-size: 6px; } .very_small { font-size: 5px;} .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .greentext { color: #00FF00; font-size: 7px; } .redtext { color: #FF0000; font-size: 7px; } .clown { color: #FF69Bf; font-size: 7px; font-weight: bold; } .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; } .italics { font-size: 7px; font-style: italic; }" + elem "lobby_browser" + type = BROWSER + pos = 0,0 + size = 640,480 + anchor1 = 0,0 + anchor2 = 100,100 + is-visible = false + is-disabled = true + background-color = #222222 window "outputwindow" elem "outputwindow" diff --git a/modular_chomp/maps/relic_base/relicbase-12.dmm b/modular_chomp/maps/relic_base/relicbase-12.dmm index 8195e9fdd1..9a82ebb193 100644 --- a/modular_chomp/maps/relic_base/relicbase-12.dmm +++ b/modular_chomp/maps/relic_base/relicbase-12.dmm @@ -5944,9 +5944,6 @@ icon_state = "freezerfloor" }, /area/syndicate_station) -"fWI" = ( -/turf/closed/indestructible/start_area, -/area/space) "fWK" = ( /obj/structure/closet{ name = "Evidence Closet" @@ -20350,9 +20347,6 @@ /obj/item/grenade/spawnergrenade/manhacks, /turf/simulated/shuttle/floor/darkred, /area/shuttle/skipjack) -"wPe" = ( -/turf/closed/indestructible/splashscreen, -/area/space) "wPA" = ( /obj/structure/table/reinforced, /obj/item/aicard, @@ -20448,10 +20442,6 @@ /obj/structure/table/steel_reinforced, /turf/simulated/floor/reinforced, /area/centcom/specops) -"wUm" = ( -/obj/effect/landmark/start/new_player, -/turf/closed/indestructible/start_area, -/area/space) "wVn" = ( /obj/machinery/door/airlock/silver{ name = "Toilet" @@ -21438,21 +21428,21 @@ (1,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -wPe +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -21695,21 +21685,21 @@ xUf (2,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -21952,21 +21942,21 @@ xUf (3,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -22209,21 +22199,21 @@ xUf (4,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -22466,21 +22456,21 @@ xUf (5,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -22723,21 +22713,21 @@ xUf (6,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -22980,21 +22970,21 @@ xUf (7,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -23237,21 +23227,21 @@ xUf (8,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -wUm -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -23494,21 +23484,21 @@ xUf (9,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -23751,21 +23741,21 @@ xUf (10,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -24008,21 +23998,21 @@ xUf (11,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -24265,21 +24255,21 @@ xUf (12,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -24522,21 +24512,21 @@ xUf (13,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -24779,21 +24769,21 @@ xUf (14,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -25036,21 +25026,21 @@ xUf (15,1,1) = {" vFi vFi -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI -fWI +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi diff --git a/modular_chomp/maps/soluna_nexus/soluna_nexus-7.dmm b/modular_chomp/maps/soluna_nexus/soluna_nexus-7.dmm index 58d95c2c5f..bac491af68 100644 --- a/modular_chomp/maps/soluna_nexus/soluna_nexus-7.dmm +++ b/modular_chomp/maps/soluna_nexus/soluna_nexus-7.dmm @@ -15485,9 +15485,6 @@ }, /turf/simulated/shuttle/plating, /area/centcom/evac) -"ndq" = ( -/turf/closed/indestructible/start_area, -/area/space) "nec" = ( /obj/effect/floor_decal/corner/green{ dir = 10 @@ -18137,9 +18134,6 @@ }, /turf/simulated/floor/tiled/techmaint, /area/shadekin) -"pBj" = ( -/turf/closed/indestructible/splashscreen, -/area/space) "pBu" = ( /obj/structure/table/steel, /obj/item/gun/projectile/pistol, @@ -20317,10 +20311,6 @@ /obj/random/donkpocketbox, /turf/simulated/floor/tiled/techmaint, /area/shadekin) -"rCS" = ( -/obj/effect/landmark/start/new_player, -/turf/closed/indestructible/start_area, -/area/space) "rDo" = ( /obj/effect/floor_decal/corner/blue{ dir = 5 @@ -89819,21 +89809,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -pBj +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -90077,21 +90067,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -90335,21 +90325,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -90593,21 +90583,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -90851,21 +90841,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -91109,21 +91099,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -91367,21 +91357,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -91625,21 +91615,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -rCS -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -91883,21 +91873,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -92141,21 +92131,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -92399,21 +92389,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -92657,21 +92647,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -92915,21 +92905,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -93173,21 +93163,21 @@ mUJ mUJ rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV @@ -93431,21 +93421,21 @@ rZY rZY rZY vFi -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq -ndq +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi dtV dtV diff --git a/modular_chomp/maps/soluna_nexus/soluna_nexus_defines.dm b/modular_chomp/maps/soluna_nexus/soluna_nexus_defines.dm index a15c180519..e8cf8d714f 100644 --- a/modular_chomp/maps/soluna_nexus/soluna_nexus_defines.dm +++ b/modular_chomp/maps/soluna_nexus/soluna_nexus_defines.dm @@ -39,7 +39,7 @@ but they don't actually change anything about the load order path = "soluna_nexus" lobby_icon = 'icons/misc/splash_screen.dmi' //CHOMPStation Edit - lobby_screens = list() //CHOMPStation Edit - CHOMPStation image + lobby_screens = list("southern_cross1") //CHOMPStation Edit - CHOMPStation image id_hud_icons = 'icons/mob/hud_jobs_vr.dmi' //CHOMPStation Edit - Job icons for off-duty/exploration holomap_smoosh = list(list( diff --git a/modular_chomp/maps/southern_cross/southern_cross-8.dmm b/modular_chomp/maps/southern_cross/southern_cross-8.dmm index 76ccb604ae..01156be0e5 100644 --- a/modular_chomp/maps/southern_cross/southern_cross-8.dmm +++ b/modular_chomp/maps/southern_cross/southern_cross-8.dmm @@ -5999,9 +5999,6 @@ /obj/machinery/vending/donksoft, /turf/simulated/floor/reinforced, /area/shadekin) -"faJ" = ( -/turf/closed/indestructible/splashscreen, -/area/space) "faN" = ( /obj/structure/table/standard, /obj/effect/decal/cleanable/cobweb2, @@ -14503,9 +14500,6 @@ /obj/effect/floor_decal/carpet, /turf/simulated/floor/holofloor/carpet, /area/holodeck/source_courtroom) -"mSU" = ( -/turf/closed/indestructible/start_area, -/area/space) "mTk" = ( /obj/machinery/portable_atmospherics/canister/oxygen/prechilled, /obj/machinery/atmospherics/portables_connector, @@ -15077,10 +15071,6 @@ /obj/machinery/meter, /turf/simulated/shuttle/plating, /area/shuttle/skipjack) -"nvE" = ( -/obj/effect/landmark/start/new_player, -/turf/closed/indestructible/start_area, -/area/space) "nvF" = ( /obj/machinery/embedded_controller/radio/airlock/airlock_controller{ dir = 8; @@ -25979,21 +25969,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -faJ +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -26237,21 +26227,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -26495,21 +26485,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -26753,21 +26743,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -27011,21 +27001,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -27269,21 +27259,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -27527,21 +27517,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -27785,21 +27775,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -nvE -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -28043,21 +28033,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -28301,21 +28291,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -28559,21 +28549,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -28817,21 +28807,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -29075,21 +29065,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -29333,21 +29323,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi @@ -29591,21 +29581,21 @@ vFi vFi vFi vFi -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU -mSU +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi +vFi vFi vFi vFi diff --git a/modular_chomp/maps/southern_cross/southern_cross_defines.dm b/modular_chomp/maps/southern_cross/southern_cross_defines.dm index 43d33593d3..c8794b262b 100644 --- a/modular_chomp/maps/southern_cross/southern_cross_defines.dm +++ b/modular_chomp/maps/southern_cross/southern_cross_defines.dm @@ -39,7 +39,7 @@ but they don't actually change anything about the load order path = "southern_cross" lobby_icon = 'icons/misc/splash_screen.dmi' //CHOMPStation Edit - lobby_screens = list() //CHOMPStation Edit - CHOMPStation image + lobby_screens = list("southern_cross1") //CHOMPStation Edit - CHOMPStation image id_hud_icons = 'icons/mob/hud_jobs_vr.dmi' //CHOMPStation Edit - Job icons for off-duty/exploration holomap_smoosh = list(list( diff --git a/modular_chomp/maps/virgo_minitest/virgo_minitest-1.dmm b/modular_chomp/maps/virgo_minitest/virgo_minitest-1.dmm index 073b8724ef..630879445b 100644 --- a/modular_chomp/maps/virgo_minitest/virgo_minitest-1.dmm +++ b/modular_chomp/maps/virgo_minitest/virgo_minitest-1.dmm @@ -5756,13 +5756,6 @@ }, /turf/simulated/floor, /area/engineering/workshop) -"Lu" = ( -/obj/effect/landmark{ - name = "Observer-Start" - }, -/obj/effect/landmark/start/new_player, -/turf/simulated/floor/tiled, -/area/bridge) "Lz" = ( /obj/machinery/computer/power_monitor{ dir = 4; @@ -9138,7 +9131,7 @@ ni gr gf gf -Lu +gz gf gf gN diff --git a/sound/lobby/lobby_load.ogg b/sound/lobby/lobby_load.ogg new file mode 100644 index 0000000000..71e30bf2a6 Binary files /dev/null and b/sound/lobby/lobby_load.ogg differ diff --git a/tgui/packages/tgui/interfaces/AlertModal.tsx b/tgui/packages/tgui/interfaces/AlertModal.tsx index 791bc38105..dc7f549a7c 100644 --- a/tgui/packages/tgui/interfaces/AlertModal.tsx +++ b/tgui/packages/tgui/interfaces/AlertModal.tsx @@ -1,26 +1,29 @@ -import { useState } from 'react'; +import { type KeyboardEvent, useState } from 'react'; import { useBackend } from 'tgui/backend'; import { Window } from 'tgui/layouts'; import { Autofocus, Box, Button, Section, Stack } from 'tgui-core/components'; import { isEscape, KEY } from 'tgui-core/keys'; +import { type BooleanLike } from 'tgui-core/react'; import { Loader } from './common/Loader'; -type AlertModalData = { - autofocus: boolean; +type Data = { + autofocus: BooleanLike; buttons: string[]; - large_buttons: boolean; + large_buttons: BooleanLike; message: string; - swapped_buttons: boolean; + swapped_buttons: BooleanLike; timeout: number; title: string; }; -const KEY_DECREMENT = -1; -const KEY_INCREMENT = 1; +enum DIRECTION { + Increment = 1, + Decrement = -1, +} -export const AlertModal = (props) => { - const { act, data } = useBackend(); +export function AlertModal(props) { + const { act, data } = useBackend(); const { autofocus, buttons = [], @@ -29,128 +32,168 @@ export const AlertModal = (props) => { timeout, title, } = data; + + // Stolen wholesale from fontcode + function textWidth(text: string, font: string, fontsize: number) { + // default font height is 12 in tgui + font = fontsize + 'x ' + font; + const c = document.createElement('canvas'); + const ctx = c.getContext('2d') as CanvasRenderingContext2D; + ctx.font = font; + return ctx.measureText(text).width; + } + const [selected, setSelected] = useState(0); + + const windowWidth = 345 + (buttons.length > 2 ? 55 : 0); + + // very accurate estimate of padding for each num of buttons + const paddingMagicNumber = 67 / buttons.length + 23; + + // At least one of the buttons has a long text message + const isVerbose = buttons.some( + (button) => + textWidth(button, '', large_buttons ? 14 : 12) > // 14 is the larger font size for large buttons + windowWidth / buttons.length - paddingMagicNumber, + ); + const largeSpacing = isVerbose && large_buttons ? 20 : 15; + // Dynamically sets window dimensions const windowHeight = - 115 + + 120 + + (isVerbose ? largeSpacing * buttons.length : 0) + (message.length > 30 ? Math.ceil(message.length / 4) : 0) + (message.length && large_buttons ? 5 : 0); - const windowWidth = 325 + (buttons.length > 2 ? 55 : 0); - const onKey = (direction: number) => { - if (selected === 0 && direction === KEY_DECREMENT) { - setSelected(buttons.length - 1); - } else if (selected === buttons.length - 1 && direction === KEY_INCREMENT) { - setSelected(0); - } else { - setSelected(selected + direction); - } - }; - function handleKeyDown(event: React.KeyboardEvent) { - const key = event.key; - /** - * Simulate a click when pressing space or enter, - * allow keyboard navigation, override tab behavior - */ - if (key === KEY.Space || key === KEY.Enter) { - act('choose', { choice: buttons[selected] }); - } else if (isEscape(key)) { - act('cancel'); - } else if (key === KEY.Left) { - event.preventDefault(); - onKey(KEY_DECREMENT); - } else if (key === KEY.Tab || key === KEY.Right) { - event.preventDefault(); - onKey(KEY_INCREMENT); + /** Changes button selection, etc */ + function keyDownHandler(event: KeyboardEvent) { + switch (event.key) { + case KEY.Space: + case KEY.Enter: + act('choose', { choice: buttons[selected] }); + return; + case KEY.Left: + event.preventDefault(); + onKey(DIRECTION.Decrement); + return; + case KEY.Tab: + case KEY.Right: + event.preventDefault(); + onKey(DIRECTION.Increment); + return; + + default: + if (isEscape(event.key)) { + act('cancel'); + return; + } } } + /** Manages iterating through the buttons */ + function onKey(direction: DIRECTION) { + const newIndex = (selected + direction + buttons.length) % buttons.length; + setSelected(newIndex); + } + return ( {!!timeout && } - handleKeyDown(e)}> +
- + {message} - + {!!autofocus && } - + {isVerbose ? ( + + ) : ( + + )}
); +} + +type ButtonDisplayProps = { + selected: number; }; /** * Displays a list of buttons ordered by user prefs. - * Technically this handles more than 2 buttons, but you + */ +function HorizontalButtons(props: ButtonDisplayProps) { + const { act, data } = useBackend(); + const { buttons = [], large_buttons, swapped_buttons } = data; + const { selected } = props; + + return ( + + {buttons.map((button, index) => ( + + + + ))} + + ); +} + +/** + * Technically the parent handles more than 2 buttons, but you * should just be using a list input in that case. */ -const ButtonDisplay = (props) => { - const { data } = useBackend(); +function VerticalButtons(props: ButtonDisplayProps) { + const { act, data } = useBackend(); const { buttons = [], large_buttons, swapped_buttons } = data; const { selected } = props; return ( - {buttons?.map((button, index) => - !!large_buttons && buttons.length < 3 ? ( - - - - ) : ( - - - - ), - )} + {buttons.map((button, index) => ( + + + + ))} ); -}; - -/** - * Displays a button with variable sizing. - */ -const AlertButton = (props) => { - const { act, data } = useBackend(); - const { large_buttons } = data; - const { button, selected } = props; - const buttonWidth = button.length > 7 ? button.length : 7; - - return ( - - ); -}; +} diff --git a/tgui/packages/tgui/interfaces/LobbyMenu/LobbyButtons.tsx b/tgui/packages/tgui/interfaces/LobbyMenu/LobbyButtons.tsx new file mode 100644 index 0000000000..e52ebd7a6e --- /dev/null +++ b/tgui/packages/tgui/interfaces/LobbyMenu/LobbyButtons.tsx @@ -0,0 +1,137 @@ +import { useBackend } from 'tgui/backend'; +import { Box, Section, Stack } from 'tgui-core/components'; + +import { LobbyButton, TimedDivider } from './LobbyElements'; +import type { LobbyData } from './types'; + +export const LobbyButtons = (props: { + readonly setModal: (_) => void; + readonly hidden: boolean; + readonly setHidden: (_: boolean) => void; +}) => { + const { act, data } = useBackend(); + const { setModal, hidden, setHidden } = props; + + const { + server_name, + map, + station_time, + round_start, + round_time, + ready, + new_news, + can_submit_feedback, + show_station_news, + new_station_news, + new_changelog, + } = data; + + return ( + + ); +}; diff --git a/tgui/packages/tgui/interfaces/LobbyMenu/LobbyElements.tsx b/tgui/packages/tgui/interfaces/LobbyMenu/LobbyElements.tsx new file mode 100644 index 0000000000..19467b82ad --- /dev/null +++ b/tgui/packages/tgui/interfaces/LobbyMenu/LobbyElements.tsx @@ -0,0 +1,68 @@ +import { useContext, useEffect, useRef } from 'react'; +import { useBackend } from 'tgui/backend'; +import { Box, Button, Stack } from 'tgui-core/components'; + +import { LobbyContext } from './constants'; +import type { LobbyButtonProps, LobbyContextType } from './types'; + +export const TimedDivider = () => { + const ref = useRef(null); + + const context = useContext(LobbyContext); + const { animationsDisabled, animationsFinished } = context; + + useEffect(() => { + if (!animationsFinished && !animationsDisabled) { + setTimeout(() => { + ref.current!.style.display = 'block'; + }, 1500); + } + }, [animationsFinished, animationsDisabled]); + + return ( + +
+ + ); +}; + +export const LobbyButton = (props: LobbyButtonProps) => { + const { children, index, className, ...rest } = props; + + const context = useContext(LobbyContext); + + return ( + + + {children} + + + ); +}; + +export const CustomButton = (props) => { + const { act } = useBackend(); + + return ( + // this works because of event propagation + act('keyboard')}> +