[MIRROR] browse to browser part 1 (#11017)

Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-06-06 07:18:23 -07:00
committed by GitHub
parent d7cd22d2d0
commit 0fc7bb29d1
36 changed files with 428 additions and 423 deletions

View File

@@ -112,7 +112,9 @@ var/global/vs_control/vsc = new
if("[ch]_NAME" in vars) vw_name = vars["[ch]_NAME"] if("[ch]_NAME" in vars) vw_name = vars["[ch]_NAME"]
dat += span_bold("[vw_name] = [vw]") + " <A href='byond://?src=\ref[src];[HrefToken()];changevar=[ch]'>\[Change\]</A><br>" dat += span_bold("[vw_name] = [vw]") + " <A href='byond://?src=\ref[src];[HrefToken()];changevar=[ch]'>\[Change\]</A><br>"
dat += "<i>[vw_desc]</i><br><br>" dat += "<i>[vw_desc]</i><br><br>"
user << browse("<html>[dat]</html>","window=settings") var/datum/browser/popup = new(user, "settings", "Settings")
popup.set_content(dat)
popup.open()
/vs_control/Topic(href,href_list) /vs_control/Topic(href,href_list)
if("changevar" in href_list) if("changevar" in href_list)

2
code/__defines/client.dm Normal file
View File

@@ -0,0 +1,2 @@
/// Checks if the given target is either a client or a mock client, for now removed: || istype(target, /datum/client_interface)
#define IS_CLIENT_OR_MOCK(target) (istype(target, /client))

View File

@@ -16,6 +16,17 @@ GLOBAL_LIST_INIT(bitfields, generate_bitfields())
bitfields[bitfield.variable] = bitfield.flags bitfields[bitfield.variable] = bitfield.flags
return bitfields return bitfields
/// Returns an associative list of bitflag name -> number for all valid bitflags in the passed in field
/proc/get_valid_bitflags(var_name)
return GLOB.bitfields[var_name] || list()
/proc/get_random_bitflag(var_name)
var/list/flags = get_valid_bitflags(var_name)
if(!length(flags))
return
var/name = pick(flags)
return flags[name]
DEFINE_BITFIELD(admin_flags, list( DEFINE_BITFIELD(admin_flags, list(
"ADMIN" = R_ADMIN, "ADMIN" = R_ADMIN,
"REJUVINATE" = R_REJUVINATE, "REJUVINATE" = R_REJUVINATE,

View File

@@ -1,40 +1,48 @@
/datum/browser /datum/browser
var/mob/user var/mob/user
var/title var/title = ""
var/window_id // window_id is used as the window name for browse and onclose /// window_id is used as the window name for browse and onclose
var/window_id
var/width = 0 var/width = 0
var/height = 0 var/height = 0
var/datum/weakref/ref = null var/datum/weakref/source_ref = null
var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id /// window option is set using window_id
var/stylesheets[0] var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;"
var/scripts[0] var/list/stylesheets = list()
var/list/scripts = list()
var/head_elements var/head_elements
var/body_elements var/body_elements
var/head_content = "" var/head_content = ""
var/content = "" var/content = ""
/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null) /datum/browser/New(mob/user, window_id, title = "", width = 0, height = 0, atom/source = null)
user = nuser if(IS_CLIENT_OR_MOCK(user))
var/client/client_user = user
user = client_user.mob
src.user = user
RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(user_deleted)) RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(user_deleted))
window_id = nwindow_id src.window_id = window_id
if (ntitle) if (title)
title = format_text(ntitle) src.title = format_text(title)
if (nwidth) if (width)
width = nwidth src.width = width
if (nheight) if (height)
height = nheight src.height = height
if (nref) if (source)
ref = WEAKREF(nref) src.source_ref = WEAKREF(source)
/datum/browser/proc/user_deleted(datum/source) /datum/browser/proc/user_deleted(datum/source)
SIGNAL_HANDLER SIGNAL_HANDLER
user = null user = null
/datum/browser/proc/add_head_content(nhead_content) /datum/browser/proc/add_head_content(head_content)
head_content = nhead_content src.head_content += head_content
/datum/browser/proc/set_window_options(nwindow_options) /datum/browser/proc/set_head_content(head_content)
window_options = nwindow_options src.head_content = head_content
/datum/browser/proc/set_window_options(window_options)
src.window_options = window_options
/datum/browser/proc/add_stylesheet(name, file) /datum/browser/proc/add_stylesheet(name, file)
if (istype(name, /datum/asset/spritesheet)) if (istype(name, /datum/asset/spritesheet))
@@ -55,24 +63,24 @@
scripts["[ckey(name)].js"] = file scripts["[ckey(name)].js"] = file
SSassets.transport.register_asset("[ckey(name)].js", file) SSassets.transport.register_asset("[ckey(name)].js", file)
/datum/browser/proc/set_content(ncontent) /datum/browser/proc/set_content(content)
content = ncontent src.content = content
/datum/browser/proc/add_content(ncontent) /datum/browser/proc/add_content(content)
content += ncontent src.content += content
/datum/browser/proc/get_header() /datum/browser/proc/get_header()
var/datum/asset/simple/namespaced/common/common_asset = get_asset_datum(/datum/asset/simple/namespaced/common) var/datum/asset/simple/namespaced/common/common_asset = get_asset_datum(/datum/asset/simple/namespaced/common)
var/file var/list/new_head_content = list()
// If a client exists, but they have disabled fancy windowing, disable it! // If a client exists, but they have disabled fancy windowing, disable it!
if(user?.client?.prefs?.read_preference(/datum/preference/toggle/browser_style)) if(user?.client?.prefs?.read_preference(/datum/preference/toggle/browser_style))
head_content += "<link rel='stylesheet' type='text/css' href='[common_asset.get_url_mappings()["common.css"]]'>" new_head_content += "<link rel='stylesheet' type='text/css' href='[common_asset.get_url_mappings()["common.css"]]'>"
for (file in stylesheets) for (var/file in stylesheets)
head_content += "<link rel='stylesheet' type='text/css' href='[SSassets.transport.get_asset_url(file)]'>" new_head_content += "<link rel='stylesheet' type='text/css' href='[SSassets.transport.get_asset_url(file)]'>"
if(user.client?.window_scaling && user.client?.window_scaling != 1 && !user.client?.prefs.read_preference(/datum/preference/toggle/ui_scale) && width && height) if(user.client?.window_scaling && user.client?.window_scaling != 1 && !user.client?.prefs.read_preference(/datum/preference/toggle/ui_scale) && width && height)
head_content += {" new_head_content += {"
<style> <style>
body { body {
zoom: [100 / user.client?.window_scaling]%; zoom: [100 / user.client?.window_scaling]%;
@@ -80,9 +88,10 @@
</style> </style>
"} "}
for (file in scripts) for (var/file in scripts)
head_content += "<script type='text/javascript' src='[SSassets.transport.get_asset_url(file)]'></script>" new_head_content += "<script type='text/javascript' src='[SSassets.transport.get_asset_url(file)]'></script>"
head_content += new_head_content.Join()
return {"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> return {"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html> <html>
<head> <head>
@@ -95,6 +104,7 @@
[title ? "<div class='uiTitleWrapper'><div class='uiTitle'><tt>[title]</tt></div></div>" : ""] [title ? "<div class='uiTitleWrapper'><div class='uiTitle'><tt>[title]</tt></div></div>" : ""]
<div class='uiContent'> <div class='uiContent'>
"} "}
//" This is here because else the rest of the file looks like a string in notepad++. //" This is here because else the rest of the file looks like a string in notepad++.
/datum/browser/proc/get_footer() /datum/browser/proc/get_footer()
return {" return {"
@@ -110,11 +120,12 @@
[get_footer()] [get_footer()]
"} "}
/datum/browser/proc/open(use_onclose = TRUE) /datum/browser/proc/open(use_on_close = TRUE)
if(isnull(window_id)) //null check because this can potentially nuke goonchat if(isnull(window_id)) //null check because this can potentially nuke goonchat
WARNING("Browser [title] tried to open with a null ID") WARNING("Browser [title] tried to open with a null ID")
to_chat(user, span_userdanger("The [title] browser you tried to open failed a sanity check! Please report this on GitHub!")) to_chat(user, span_userdanger("The [title] browser you tried to open failed a sanity check! Please report this on GitHub!"))
return return
var/window_size = "" var/window_size = ""
if(width && height) if(width && height)
if(user.client?.prefs?.read_preference(/datum/preference/toggle/ui_scale)) if(user.client?.prefs?.read_preference(/datum/preference/toggle/ui_scale))
@@ -122,27 +133,28 @@
window_size = "size=[width * scaling]x[height * scaling];" window_size = "size=[width * scaling]x[height * scaling];"
else else
window_size = "size=[width]x[height];" window_size = "size=[width]x[height];"
var/datum/asset/simple/namespaced/common/common_asset = get_asset_datum(/datum/asset/simple/namespaced/common) var/datum/asset/simple/namespaced/common/common_asset = get_asset_datum(/datum/asset/simple/namespaced/common)
common_asset.send(user) common_asset.send(user)
if (stylesheets.len) if (length(stylesheets))
SSassets.transport.send_assets(user, stylesheets) SSassets.transport.send_assets(user, stylesheets)
if (scripts.len) if (length(scripts))
SSassets.transport.send_assets(user, scripts) SSassets.transport.send_assets(user, scripts)
user << browse(get_content(), "window=[window_id];[window_size][window_options]") DIRECT_OUTPUT(user, browse(get_content(), "window=[window_id];[window_size][window_options]"))
if (use_onclose) if (use_on_close)
setup_onclose() setup_onclose()
/datum/browser/proc/setup_onclose() /datum/browser/proc/setup_onclose()
set waitfor = 0 //winexists sleeps, so we don't need to. set waitfor = 0 //winexists sleeps, so we don't need to.
for (var/i in 1 to 10) for (var/i in 1 to 10)
if (user?.client && winexists(user, window_id)) if (!user?.client || !winexists(user, window_id))
continue
var/atom/send_ref var/atom/send_ref
if(ref) if(source_ref)
send_ref = ref.resolve() send_ref = source_ref.resolve()
if(!send_ref) if(!send_ref)
ref = null source_ref = null
onclose(user, window_id, send_ref) onclose(user, window_id, send_ref)
break
/datum/browser/proc/close() /datum/browser/proc/close()
if(!isnull(window_id))//null check because this can potentially nuke goonchat if(!isnull(window_id))//null check because this can potentially nuke goonchat
@@ -150,106 +162,106 @@
else else
WARNING("Browser [title] tried to close with a null ID") WARNING("Browser [title] tried to close with a null ID")
/datum/browser/modal/alert/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1,Timeout=6000) /datum/browser/modal/alert/New(user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = 600 SECONDS)
if (!User) if (!user)
return return
var/output = {"<center><b>[Message]</b></center><br /> var/list/display_list = list()
display_list += {"<center><b>[message]</b></center><br />
<div style="text-align:center"> <div style="text-align:center">
<a style="font-size:large;float:[( Button2 ? "left" : "right" )]" href='byond://?src=[REF(src)];button=1'>[Button1]</a>"} <a style="font-size:large;float:[( button_2 ? "left" : "right" )]" href='byond://?src=[REF(src)];button=1'>[button_1]</a>"}
if (Button2) if (button_2)
output += {"<a style="font-size:large;[( Button3 ? "" : "float:right" )]" href='byond://?src=[REF(src)];button=2'>[Button2]</a>"} display_list += {"<a style="font-size:large;[( button_3 ? "" : "float:right" )]" href='byond://?src=[REF(src)];button=2'>[button_2]</a>"}
if (Button3) if (button_3)
output += {"<a style="font-size:large;float:right" href='byond://?src=[REF(src)];button=3'>[Button3]</a>"} display_list += {"<a style="font-size:large;float:right" href='byond://?src=[REF(src)];button=3'>[button_3]</a>"}
output += {"</div>"} display_list += {"</div>"}
..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, 350, 150, src, StealFocus, Timeout) ..(user, ckey("[user]-[message]-[title]-[world.time]-[rand(1,10000)]"), title, 350, 150, src, steal_focus, timeout)
set_content(output) set_content(display_list.Join())
/datum/browser/modal/alert/Topic(href,href_list) /datum/browser/modal/alert/Topic(href,href_list)
if (href_list["close"] || !user || !user.client) if (href_list["close"] || !user || !user.client)
opentime = 0 open_time = 0
return return
if (href_list["button"]) if (href_list["button"])
var/button = text2num(href_list["button"]) var/button = text2num(href_list["button"])
if (button <= 3 && button >= 1) if (button <= 3 && button >= 1)
selectedbutton = button selected_button = button
opentime = 0 open_time = 0
close() close()
/** /**
* **DEPRECATED: USE tgui_alert(...) INSTEAD** * **DEPRECATED: USE tgui_alert(...) INSTEAD**
* *
* Designed as a drop in replacement for alert(); functions the same. (outside of needing User specified) * Designed as a drop in replacement for alert(); functions the same. (outside of needing user specified)
* Arguments: * Arguments:
* * User - The user to show the alert to. * * user - The user to show the alert to.
* * Message - The textual body of the alert. * * message - The textual body of the alert.
* * Title - The title of the alert's window. * * title - The title of the alert's window.
* * Button1 - The first button option. * * button_1 - The first button option.
* * Button2 - The second button option. * * button_2 - The second button option.
* * Button3 - The third button option. * * button_3 - The third button option.
* * StealFocus - Boolean operator controlling if the alert will steal the user's window focus. * * steal_focus - Boolean operator controlling if the alert will steal the user's window focus.
* * Timeout - The timeout of the window, after which no responses will be valid. * * timeout - The timeout of the window, after which no responses will be valid.
*/ */
/proc/tgalert(mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = TRUE, Timeout = 6000) /proc/tg_alert(mob/user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = 600 SECONDS)
if (!User) if (!user)
User = usr user = usr
if (!istype(User)) if (!ismob(user))
if (istype(User, /client)) if (!istype(user, /client))
var/client/client = User
User = client.mob
else
return return
var/client/user_client = user
user = user_client.mob
// Get user's response using a modal // Get user's response using a modal
var/datum/browser/modal/alert/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout) var/datum/browser/modal/alert/window = new(user, message, title, button_1, button_2, button_3, steal_focus, timeout)
A.open() window.open()
A.wait() window.wait()
switch(A.selectedbutton) switch(window.selected_button)
if (1) if (1)
return Button1 return button_1
if (2) if (2)
return Button2 return button_2
if (3) if (3)
return Button3 return button_3
/datum/browser/modal /datum/browser/modal
var/opentime = 0 var/open_time = 0
var/timeout var/timeout
var/selectedbutton = 0 var/selected_button = 0
var/stealfocus var/steal_focus
/datum/browser/modal/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null, StealFocus = 1, Timeout = 6000) /datum/browser/modal/New(user, window_id, title = 0, width = 0, height = 0, atom/source = null, steal_focus = TRUE, timeout = 600 SECONDS)
..() ..()
stealfocus = StealFocus src.steal_focus = steal_focus
if (!StealFocus) if (!src.steal_focus)
window_options += "focus=false;" window_options += "focus=false;"
timeout = Timeout src.timeout = timeout
/datum/browser/modal/close() /datum/browser/modal/close()
. = ..() . = ..()
opentime = 0 open_time = 0
/datum/browser/modal/open(use_onclose) /datum/browser/modal/open(use_on_close)
set waitfor = FALSE set waitfor = FALSE
opentime = world.time open_time = world.time
use_on_close = TRUE
if (stealfocus) if (steal_focus)
. = ..(use_onclose = 1) . = ..()
else else
var/focusedwindow = winget(user, null, "focus") var/focused_window = winget(user, null, "focus")
. = ..(use_onclose = 1) . = ..()
//waits for the window to show up client side before attempting to un-focus it //waits for the window to show up client side before attempting to un-focus it
//winexists sleeps until it gets a reply from the client, so we don't need to bother sleeping //winexists sleeps until it gets a reply from the client, so we don't need to bother sleeping
for (var/i in 1 to 10) for (var/i in 1 to 10)
if (user && winexists(user, window_id)) if (user && winexists(user, window_id))
if (focusedwindow) if (focused_window)
winset(user, focusedwindow, "focus=true") winset(user, focused_window, "focus=true")
else else
winset(user, "mapwindow", "focus=true") winset(user, "mapwindow", "focus=true")
break break
@@ -257,126 +269,237 @@
addtimer(CALLBACK(src, PROC_REF(close)), timeout) addtimer(CALLBACK(src, PROC_REF(close)), timeout)
/datum/browser/modal/proc/wait() /datum/browser/modal/proc/wait()
while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout > world.time)) while (open_time && selected_button <= 0 && (!timeout || open_time + timeout > world.time))
stoplag(1) stoplag(1)
/datum/browser/modal/listpicker /datum/browser/modal/list_picker
var/valueslist = list() var/values_list = list()
/datum/browser/modal/listpicker/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1, Timeout = FALSE,list/values,inputtype="checkbox", width, height, slidecolor) /datum/browser/modal/list_picker/New(user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = FALSE, list/values, input_type = "checkbox", width, height, slide_color)
if (!User) if (!user)
return return
var/output = {"<form><input type="hidden" name="src" value="[REF(src)]"><ul class="sparse">"} var/list/display_list = list()
if (inputtype == "checkbox" || inputtype == "radio") display_list += {"<form><input type="hidden" name="src" value="[REF(src)]"><ul class="sparse">"}
for (var/i in values) if (input_type == "checkbox" || input_type == "radio")
var/div_slider = slidecolor for (var/option in values)
if(!i["allowed_edit"]) var/div_slider = slide_color
if(!option["allowed_edit"])
div_slider = "locked" div_slider = "locked"
output += {"<li> display_list += {"<li>
<label class="switch"> <label class="switch">
<input type="[inputtype]" value="1" name="[i["name"]]"[i["checked"] ? " checked" : ""][i["allowed_edit"] ? "" : " onclick='return false' onkeydown='return false'"]> <input type="[input_type]" value="1" name="[option["name"]]"[option["checked"] ? " checked" : ""][option["allowed_edit"] ? "" : " onclick='return false' onkeydown='return false'"]>
<div class="slider [div_slider ? "[div_slider]" : ""]"></div> <div class="slider [div_slider ? "[div_slider]" : ""]"></div>
<span>[i["name"]]</span> <span>[option["name"]]</span>
</label> </label>
</li>"} </li>"}
else else
for (var/i in values) for (var/option in values)
output += {"<li><input id="name="[i["name"]]"" style="width: 50px" type="[type]" name="[i["name"]]" value="[i["value"]]"> display_list += {"<li><input id="name="[option["name"]]"" style="width: 50px" type="[type]" name="[option["name"]]" value="[option["value"]]">
<label for="[i["name"]]">[i["name"]]</label></li>"} <label for="[option["name"]]">[option["name"]]</label></li>"}
output += {"</ul><div style="text-align:center"> display_list += {"</ul><div style="text-align:center">
<button type="submit" name="button" value="1" style="font-size:large;float:[( Button2 ? "left" : "right" )]">[Button1]</button>"} <button type="submit" name="button" value="1" style="font-size:large;float:[( button_2 ? "left" : "right" )]">[button_1]</button>"}
if (Button2) if (button_2)
output += {"<button type="submit" name="button" value="2" style="font-size:large;[( Button3 ? "" : "float:right" )]">[Button2]</button>"} display_list += {"<button type="submit" name="button" value="2" style="font-size:large;[( button_3 ? "" : "float:right" )]">[button_2]</button>"}
if (Button3) if (button_3)
output += {"<button type="submit" name="button" value="3" style="font-size:large;float:right">[Button3]</button>"} display_list += {"<button type="submit" name="button" value="3" style="font-size:large;float:right">[button_3]</button>"}
output += {"</form></div>"} display_list += {"</form></div>"}
..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, width, height, src, StealFocus, Timeout) ..(user, ckey("[user]-[message]-[title]-[world.time]-[rand(1,10000)]"), title, width, height, src, steal_focus, timeout)
set_content(output) set_content(display_list.Join())
/datum/browser/modal/listpicker/Topic(href,href_list) /datum/browser/modal/list_picker/Topic(href, list/href_list)
if (href_list["close"] || !user || !user.client) if (href_list["close"] || !user || !user.client)
opentime = 0 open_time = 0
return return
if (href_list["button"]) if (href_list["button"])
var/button = text2num(href_list["button"]) var/button = text2num(href_list["button"])
if (button <= 3 && button >= 1) if (button <= 3 && button >= 1)
selectedbutton = button selected_button = button
for (var/item in href_list) values_list = href_list.Copy()
switch(item) values_list -= list("close", "button", "src")
if ("close", "button", "src") open_time = 0
continue
else
valueslist[item] = href_list[item]
opentime = 0
close() close()
/proc/presentpicker(mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor) /proc/present_picker(mob/user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = 600 SECONDS, list/values, input_type = "checkbox", width, height, slide_color)
if (!istype(User)) if (!ismob(user))
if (istype(User, /client/)) if (!istype(user, /client))
var/client/C = User
User = C.mob
else
return return
var/datum/browser/modal/listpicker/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus,Timeout, values, inputtype, width, height, slidecolor) var/client/user_client = user
A.open() user = user_client.mob
A.wait() var/datum/browser/modal/list_picker/window = new(user, message, title, button_1, button_2, button_3, steal_focus, timeout, values, input_type, width, height, slide_color)
if (A.selectedbutton) window.open()
return list("button" = A.selectedbutton, "values" = A.valueslist) window.wait()
if (window.selected_button)
return list("button" = window.selected_button, "values" = window.values_list)
/proc/input_bitfield(var/mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_list = null) /proc/input_bitfield(mob/user, title, bitfield, current_value, width = 350, height = 350, slide_color, allowed_edit_field = ALL)
if (!User || !(bitfield in GLOB.bitfields)) var/list/bitflags = get_valid_bitflags(bitfield)
if (!user || !length(bitflags))
return
var/list/picker_list = list()
for (var/bit_name in bitflags)
var/bit_value = bitflags[bit_name]
// Gotta make it TRUE/FALSE sorry brother
var/can_edit = !!(allowed_edit_field & bit_value)
var/enabled = !!(current_value & bit_value)
picker_list += list(list("checked" = enabled, "value" = bit_value, "name" = bit_name, "allowed_edit" = can_edit))
var/list/result = present_picker(user, "", title, button_1 = "Save", button_2 = "Cancel", timeout = FALSE, values = picker_list, width = width, height = height, slide_color = slide_color)
if (!islist(result))
return return
var/list/pickerlist = list()
for (var/i in GLOB.bitfields[bitfield])
var/can_edit = 1
if(!isnull(allowed_edit_list) && !(allowed_edit_list & GLOB.bitfields[bitfield][i]))
can_edit = 0
if (current_value & GLOB.bitfields[bitfield][i])
pickerlist += list(list("checked" = 1, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit))
else
pickerlist += list(list("checked" = 0, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit))
var/list/result = presentpicker(User, "", title, Button1="Save", Button2 = "Cancel", Timeout=FALSE, values = pickerlist, width = nwidth, height = nheight, slidecolor = nslidecolor)
if (islist(result))
if (result["button"] == 2) // If the user pressed the cancel button if (result["button"] == 2) // If the user pressed the cancel button
return return
. = 0
for (var/flag in result["values"]) var/result_bitfield = NONE
. |= GLOB.bitfields[bitfield][flag] for (var/flag_name in result["values"])
else result_bitfield |= bitflags[flag_name]
return result_bitfield
/datum/browser/modal/pref_like_picker
var/settings = list()
var/icon/preview_icon = null
var/datum/callback/preview_update
/datum/browser/modal/pref_like_picker/New(mob/user, message, title, steal_focus = TRUE, timeout = 600 SECONDS, list/settings, width, height)
if (!user)
return return
// src.settings = settings
/proc/onclose(mob/user, windowid, atom/ref=null)
..(user, ckey("[user]-[message]-[title]-[world.time]-[rand(1,10000)]"), title, width, height, src, steal_focus, timeout)
set_content(show_choices(user))
/datum/browser/modal/pref_like_picker/proc/show_choices(mob/user)
if (settings["preview_callback"])
var/datum/callback/callback = settings["preview_callback"]
preview_icon = callback.Invoke(settings)
if (preview_icon)
user << browse_rsc(preview_icon, "previewicon.png")
var/list/display_list = list()
for (var/name in settings["mainsettings"])
var/setting = settings["mainsettings"][name]
if (setting["type"] == "datum")
if (setting["subtypesonly"])
display_list += "<b>[setting["desc"]]:</b> <a href='byond://?src=[REF(src)];setting=[name];task=input;subtypesonly=1;type=datum;path=[setting["path"]]'>[setting["value"]]</a><BR>"
else
display_list += "<b>[setting["desc"]]:</b> <a href='byond://?src=[REF(src)];setting=[name];task=input;type=datum;path=[setting["path"]]'>[setting["value"]]</a><BR>"
else
display_list += "<b>[setting["desc"]]:</b> <a href='byond://?src=[REF(src)];setting=[name];task=input;type=[setting["type"]]'>[setting["value"]]</a><BR>"
if (preview_icon)
display_list += "<td valign='center'>"
display_list += "<div class='statusDisplay'><center><img src=previewicon.png width=[preview_icon.Width()] height=[preview_icon.Height()]></center></div>"
display_list += "</td>"
display_list += "</tr></table>"
display_list += "<hr><center><a href='byond://?src=[REF(src)];button=1'>Ok</a> "
display_list += "</center>"
return display_list.Join()
/datum/browser/modal/pref_like_picker/Topic(href,href_list)
if (href_list["close"] || !user || !user.client)
open_time = 0
return
if (href_list["task"] == "input")
var/setting_key = href_list["setting"]
var/list/setting = settings["mainsettings"][setting_key]
switch (href_list["type"])
if ("datum")
var/parent_path = text2path(href_list["path"])
var/list/paths
if (href_list["subtypesonly"])
paths = subtypesof(parent_path)
else
paths = typesof(parent_path)
var/new_value = pick_closest_path(null, make_types_fancy(paths))
if (!isnull(new_value))
setting["value"] = new_value
if ("string")
setting["value"] = stripped_input(user, "Enter new value for [setting["desc"]]", "Enter new value for [setting["desc"]]", setting["value"])
if ("number")
setting["value"] = input(user, "Enter new value for [setting["desc"]]", "Enter new value for [setting["desc"]]") as num
if ("color")
setting["value"] = input(user, "Enter new value for [setting["desc"]]", "Enter new value for [setting["desc"]]", setting["value"]) as color
if ("boolean")
setting["value"] = (setting["value"] == "Yes") ? "No" : "Yes"
if ("ckey")
setting["value"] = input(user, "[setting["desc"]]?") in (list("none") + GLOB.directory)
if (setting["callback"])
var/datum/callback/callback = setting["callback"]
settings = callback.Invoke(settings)
if (href_list["button"])
var/button = text2num(href_list["button"])
if (button <= 3 && button >= 1)
selected_button = button
if (selected_button != 1)
set_content(show_choices(user))
open()
return
open_time = 0
close()
/proc/present_pref_like_picker(mob/user, message, title, steal_focus = TRUE, timeout = 600 SECONDS, list/settings, width, height)
if (!ismob(user))
if (!istype(user, /client))
return
var/client/user_client = user
user = user_client.mob
var/datum/browser/modal/pref_like_picker/window = new(user, message, title, steal_focus, timeout, settings, width, height)
window.open()
window.wait()
if (window.selected_button)
return list("button" = window.selected_button, "settings" = window.settings)
/// Registers the on-close verb for a browse window (client/verb/windowclose)
/// this will be called when the close-button of a window is pressed.
///
/// This is usually only needed for devices that regularly update the browse window,
/// e.g. canisters, timers, etc.
///
/// windowid should be the specified window name
/// e.g. code is : user << browse(text, "window=fred")
/// then use : onclose(user, "fred")
///
/// Optionally, specify the "source" parameter as the controlled atom (usually src)
// to pass a "close=1" parameter to the atom's Topic() proc for special handling.
/// Otherwise, the user mob's machine var will be reset directly.
///
/proc/onclose(mob/user, windowid, atom/source = null)
if(!user.client) if(!user.client)
return return
var/param = "null" var/param = "null"
if(ref) if(source)
param = "[REF(ref)]" param = "[REF(source)]"
winset(user, windowid, "on-close=\".windowclose [param]\"") winset(user, windowid, "on-close=\".windowclose [param]\"")
/// the on-close client verb
/// called when a browser popup window is closed after registering with proc/onclose()
// the on-close client verb /// if a valid atom reference is supplied, call the atom's Topic() with "close=1"
// called when a browser popup window is closed after registering with proc/onclose() /// otherwise, just reset the client mob's machine var.
// if a valid atom reference is supplied, call the atom's Topic() with "close=1"
// otherwise, just reset the client mob's machine var.
//
/client/verb/windowclose(atomref as text) /client/verb/windowclose(atomref as text)
set hidden = TRUE // hide this verb from the user's panel set hidden = TRUE // hide this verb from the user's panel
set name = ".windowclose" // no autocomplete on cmd line set name = ".windowclose" // no autocomplete on cmd line
if(atomref != "null") // if passed a real atomref if(atomref == "null")
var/hsrc = locate(atomref) // find the reffed atom return
// if passed a real atomref
var/atom/hsrc = locate(atomref) // find the reffed atom
var/href = "close=1" var/href = "close=1"
if(hsrc) if(!hsrc)
return
usr = src.mob usr = src.mob
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
return // Topic() proc via client.Topic()
/datum/browser/modal/color_matrix_picker /datum/browser/modal/color_matrix_picker
var/color_matrix var/color_matrix
@@ -426,12 +549,12 @@
/datum/browser/modal/color_matrix_picker/Topic(href, list/href_list) /datum/browser/modal/color_matrix_picker/Topic(href, list/href_list)
if(href_list["close"] || !user) if(href_list["close"] || !user)
opentime = 0 open_time = 0
return return
if(href_list["button"]) if(href_list["button"])
var/button = text2num(href_list["button"]) var/button = text2num(href_list["button"])
if(ISINRANGE(button, 1, 3)) if(ISINRANGE(button, 1, 3))
selectedbutton = button selected_button = button
var/list/cm = rgb_construct_color_matrix( var/list/cm = rgb_construct_color_matrix(
text2num(href_list["rr"]), text2num(href_list["rr"]),
text2num(href_list["rg"]), text2num(href_list["rg"]),
@@ -448,7 +571,7 @@
) )
if(cm) if(cm)
color_matrix = cm color_matrix = cm
opentime = 0 open_time = 0
close() close()
/proc/color_matrix_picker(mob/user, message, title, button1 = "Ok", button2, button3, stealfocus, timeout = 10 MINUTES, list/values) /proc/color_matrix_picker(mob/user, message, title, button1 = "Ok", button2, button3, stealfocus, timeout = 10 MINUTES, list/values)
@@ -461,4 +584,4 @@
var/datum/browser/modal/color_matrix_picker/B = new(user, message, title, button1, button2, button3, stealfocus, timeout, values) var/datum/browser/modal/color_matrix_picker/B = new(user, message, title, button1, button2, button3, stealfocus, timeout, values)
B.open() B.open()
B.wait() B.wait()
return list("button" = B.selectedbutton, "matrix" = B.color_matrix) return list("button" = B.selected_button, "matrix" = B.color_matrix)

View File

@@ -114,7 +114,10 @@
if(ambitions) if(ambitions)
output += "<HR><B>Ambitions:</B> [ambitions]<br>" output += "<HR><B>Ambitions:</B> [ambitions]<br>"
recipient << browse("<html>[output]</html>","window=memory")
var/datum/browser/popup = new(recipient, "memory", "Memory")
popup.set_content(output)
popup.open()
/datum/mind/proc/edit_memory() /datum/mind/proc/edit_memory()
if(!ticker || !ticker.mode) if(!ticker || !ticker.mode)
@@ -149,7 +152,10 @@
out += "None." out += "None."
out += "<br><a href='byond://?src=\ref[src];[HrefToken()];obj_add=1'>\[add\]</a><br><br>" out += "<br><a href='byond://?src=\ref[src];[HrefToken()];obj_add=1'>\[add\]</a><br><br>"
out += span_bold("Ambitions:") + " [ambitions ? ambitions : "None"] <a href='byond://?src=\ref[src];[HrefToken()];amb_edit=\ref[src]'>\[edit\]</a></br>" out += span_bold("Ambitions:") + " [ambitions ? ambitions : "None"] <a href='byond://?src=\ref[src];[HrefToken()];amb_edit=\ref[src]'>\[edit\]</a></br>"
usr << browse("<html>[out]</html>", "window=edit_memory[src]")
var/datum/browser/popup = new(usr, "edit_memory[src]", "Edit Memory")
popup.set_content(out)
popup.open()
/datum/mind/Topic(href, href_list) /datum/mind/Topic(href, href_list)
if(!check_rights(R_ADMIN|R_FUN|R_EVENT)) return if(!check_rights(R_ADMIN|R_FUN|R_EVENT)) return

View File

@@ -72,8 +72,10 @@
dat += "<A href='byond://?src=\ref[src];rune=armor'>Sa tatha najin</A> - Allows you to summon armoured robes and an unholy blade<BR>" dat += "<A href='byond://?src=\ref[src];rune=armor'>Sa tatha najin</A> - Allows you to summon armoured robes and an unholy blade<BR>"
dat += "<A href='byond://?src=\ref[src];rune=soulstone'>Kal om neth</A> - Summons a soul stone<BR>" dat += "<A href='byond://?src=\ref[src];rune=soulstone'>Kal om neth</A> - Summons a soul stone<BR>"
dat += "<A href='byond://?src=\ref[src];rune=construct'>Da A'ig Osk</A> - Summons a construct shell for use with captured souls. It is too large to carry on your person.<BR>" dat += "<A href='byond://?src=\ref[src];rune=construct'>Da A'ig Osk</A> - Summons a construct shell for use with captured souls. It is too large to carry on your person.<BR>"
usr << browse("<html>[dat]</html>", "window=id_com;size=350x200")
return var/datum/browser/popup = new(usr, "id_com", "Talisman", 350, 200)
popup.set_content(dat)
popup.open()
/obj/item/paper/talisman/Topic(href, href_list) /obj/item/paper/talisman/Topic(href, href_list)

View File

@@ -68,7 +68,9 @@
if(!help) if(!help)
help = "Error loading help (file /ingame_manuals/malf_ai.html is probably missing). Please report this to server administration staff." help = "Error loading help (file /ingame_manuals/malf_ai.html is probably missing). Please report this to server administration staff."
user << browse(help, "window=malf_ai_help;size=600x500") var/datum/browser/popup = new(user, "malf_ai_help", "Malf AI Help", 600, 500)
popup.set_content(help)
popup.open()
// Verb: ai_select_research() // Verb: ai_select_research()

View File

@@ -43,7 +43,10 @@ mob
hsbpanel += "- <a href=\"?\ref[src];hsb=[T]\">[hrefs[T]]</a><br>" hsbpanel += "- <a href=\"?\ref[src];hsb=[T]\">[hrefs[T]]</a><br>"
if(hsboxspawn) if(hsboxspawn)
hsbpanel += "- <a href=\"?\ref[src];hsb=hsbobj\">Spawn Object</a><br><br>" hsbpanel += "- <a href=\"?\ref[src];hsb=hsbobj\">Spawn Object</a><br><br>"
usr << browse("<html>[hsbpanel]</html>", "window=hsbpanel")
var/datum/browser/popup = new(usr, "hsbpanel", "HSB Panel")
popup.set_content(hsbpanel)
popup.open()
Topic(href, href_list) Topic(href, href_list)
if(!(src.owner == usr.ckey)) return if(!(src.owner == usr.ckey)) return
if(!usr) return //I guess this is possible if they log out or die with the panel open? It happened. if(!usr) return //I guess this is possible if they log out or die with the panel open? It happened.

View File

@@ -83,8 +83,8 @@
t += text("Dispenser [] - <A href='byond://?src=\ref[];toggleOn=1'>[]?</a><br>\n", disabled?"deactivated":"activated", src, disabled?"Enable":"Disable") t += text("Dispenser [] - <A href='byond://?src=\ref[];toggleOn=1'>[]?</a><br>\n", disabled?"deactivated":"activated", src, disabled?"Enable":"Disable")
t += text("Uses Left: [uses]. <A href='byond://?src=\ref[src];toggleUse=1'>Activate the dispenser?</A><br>\n") t += text("Uses Left: [uses]. <A href='byond://?src=\ref[src];toggleUse=1'>Activate the dispenser?</A><br>\n")
user << browse("<html>[t]</html>", "window=computer;size=575x450") user << browse("<html>[t]</html>", "window=ai_slipper;size=575x450")
onclose(user, "computer") onclose(user, "ai_slipper")
return return
/obj/machinery/ai_slipper/Topic(href, href_list) /obj/machinery/ai_slipper/Topic(href, href_list)

View File

@@ -113,7 +113,7 @@
if(..()) if(..())
return return
var/dat = "<HTML><BODY><TT><B>[title]</B>" var/dat = "<TT><B>[title]</B>"
user.set_machine(src) user.set_machine(src)
if(connected) if(connected)
var/d2 var/d2
@@ -134,11 +134,11 @@
dat += "<HR>\nPower Level: [temp]<BR>\n<A href = 'byond://?src=\ref[src];alarm=1'>Firing Sequence</A><BR>\n<A href = 'byond://?src=\ref[src];drive=1'>Test Fire Driver</A><BR>\n<A href = 'byond://?src=\ref[src];door=1'>Toggle Outer Door</A><BR>" dat += "<HR>\nPower Level: [temp]<BR>\n<A href = 'byond://?src=\ref[src];alarm=1'>Firing Sequence</A><BR>\n<A href = 'byond://?src=\ref[src];drive=1'>Test Fire Driver</A><BR>\n<A href = 'byond://?src=\ref[src];door=1'>Toggle Outer Door</A><BR>"
else else
dat += "<BR>\n<A href = 'byond://?src=\ref[src];door=1'>Toggle Outer Door</A><BR>" dat += "<BR>\n<A href = 'byond://?src=\ref[src];door=1'>Toggle Outer Door</A><BR>"
dat += "<BR><BR><A href='byond://?src=\ref[user];mach_close=computer'>Close</A></TT></BODY></HTML>" dat += "<BR><BR><A href='byond://?src=\ref[user];mach_close=computer'>Close</A></TT>"
user << browse(dat, "window=computer;size=400x500")
add_fingerprint(user) add_fingerprint(user)
onclose(user, "computer") var/datum/browser/popup = new(user, "pod_computer", "Pod Computer", 400, 500)
return popup.set_content(dat)
popup.open()
/obj/machinery/computer/pod/process() /obj/machinery/computer/pod/process()

View File

@@ -270,9 +270,9 @@ var/specops_shuttle_timeleft = 0
[specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*<BR>\n<BR>":specops_shuttle_at_station ? "\n<A href='byond://?src=\ref[src];sendtodock=1'>Shuttle standing by...</A><BR>\n<BR>":"\n<A href='byond://?src=\ref[src];sendtostation=1'>Depart to [station_name()]</A><BR>\n<BR>"] [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*<BR>\n<BR>":specops_shuttle_at_station ? "\n<A href='byond://?src=\ref[src];sendtodock=1'>Shuttle standing by...</A><BR>\n<BR>":"\n<A href='byond://?src=\ref[src];sendtostation=1'>Depart to [station_name()]</A><BR>\n<BR>"]
\n<A href='byond://?src=\ref[user];mach_close=computer'>Close</A>"} \n<A href='byond://?src=\ref[user];mach_close=computer'>Close</A>"}
user << browse("<html>[dat]</html>", "window=computer;size=575x450") var/datum/browser/popup = new(usr, "computer", "Computer", 575, 450)
onclose(user, "computer") popup.set_content(dat)
return popup.open()
/obj/machinery/computer/specops_shuttle/Topic(href, href_list) /obj/machinery/computer/specops_shuttle/Topic(href, href_list)
if(..()) if(..())

View File

@@ -137,9 +137,9 @@ Transponder Codes:<UL>"}
t += "<small><A href='byond://?src=\ref[src];add=1;'>(add new)</A></small><BR>" t += "<small><A href='byond://?src=\ref[src];add=1;'>(add new)</A></small><BR>"
t+= "<UL></TT>" t+= "<UL></TT>"
user << browse("<html>[t]</html>", "window=navbeacon") var/datum/browser/popup = new(user, "navbeacon", "Navbeacon")
onclose(user, "navbeacon") popup.set_content(t)
return popup.open()
/obj/machinery/navbeacon/Topic(href, href_list) /obj/machinery/navbeacon/Topic(href, href_list)
..() ..()

View File

@@ -111,13 +111,11 @@
else else
dat += "<a href='byond://?src=\ref[src];operation=togglerun'>NEVER</a>" dat += "<a href='byond://?src=\ref[src];operation=togglerun'>NEVER</a>"
var/datum/browser/popup = new(user, "traffic_control", "Traffic Control", 575, 400)
user << browse("<html>[dat]</html>", "window=traffic_control;size=575x400") popup.set_content(dat)
onclose(user, "server_control") popup.open()
temp = "" temp = ""
return
/obj/machinery/computer/telecomms/traffic/Topic(href, href_list) /obj/machinery/computer/telecomms/traffic/Topic(href, href_list)
if(..()) if(..())

View File

@@ -76,8 +76,9 @@ var/global/datum/book_manager/book_mgr = new()
dat += "</table>" dat += "</table>"
qdel(query) qdel(query)
usr << browse("<html>[dat]</html>", "window=library") var/datum/browser/popup = new(usr, "library", "Library")
onclose(usr, "library") popup.set_content(dat)
popup.open()
//VOREStation Edit End //VOREStation Edit End
// delete a book // delete a book

View File

@@ -78,7 +78,7 @@
/obj/item/blueprints/interact() /obj/item/blueprints/interact()
var/area/A = get_area() var/area/A = get_area()
var/text = {"<HTML><head><title>[src]</title></head><BODY> var/text = {"
<h2>[station_name()] blueprints</h2> <h2>[station_name()] blueprints</h2>
<small>Property of [using_map.company_name]. For heads of staff only. Store in high-secure storage.</small><hr> <small>Property of [using_map.company_name]. For heads of staff only. Store in high-secure storage.</small><hr>
"} "}
@@ -105,10 +105,10 @@
if(curAreaType & can_rename_areas_in) if(curAreaType & can_rename_areas_in)
text += "<p>You can <a href='byond://?src=\ref[src];action=edit_area'>rename the area</a>.</p>" text += "<p>You can <a href='byond://?src=\ref[src];action=edit_area'>rename the area</a>.</p>"
text += "</BODY></HTML>" var/datum/browser/popup = new(usr, "blueprints", "Blueprints")
usr << browse(text, "window=blueprints") popup.add_head_content("<title>[src]</title>")
onclose(usr, "blueprints") popup.set_content(text)
popup.open()
/obj/item/blueprints/proc/get_area() /obj/item/blueprints/proc/get_area()
var/turf/T = get_turf(usr) var/turf/T = get_turf(usr)

View File

@@ -1,7 +1,7 @@
// I placed this here because of how relevant it is. // I placed this here because of how relevant it is.
// You place this in your uplinkable item to check if an uplink is active or not. // You place this in your uplinkable item to check if an uplink is active or not.
// If it is, it will display the uplink menu and return 1, else it'll return false. // If it is, it will display the uplink menu and return 1, else it'll return false.
// If it returns true, I recommend closing the item's normal menu with "user << browse(null, "window=name")" // If it returns true, I recommend closing the item's normal menu
/obj/item/proc/active_uplink_check(mob/user as mob) /obj/item/proc/active_uplink_check(mob/user as mob)
// Activates the uplink if it's active // Activates the uplink if it's active
if(hidden_uplink) if(hidden_uplink)
@@ -42,7 +42,7 @@
* *
* 1. All obj/item 's have a hidden_uplink var. By default it's null. Give the item one with "new(src)", it must be in it's contents. Feel free to add "uses". * 1. All obj/item 's have a hidden_uplink var. By default it's null. Give the item one with "new(src)", it must be in it's contents. Feel free to add "uses".
* *
* 2. Code in the triggers. Use check_trigger for this, I recommend closing the item's menu with "usr << browse(null, "window=windowname") if it returns true. * 2. Code in the triggers. Use check_trigger for this, I recommend closing the item's menu if it returns true.
* The var/value is the value that will be compared with the var/target. If they are equal it will activate the menu. * The var/value is the value that will be compared with the var/target. If they are equal it will activate the menu.
* *
* 3. If you want the menu to stay until the users locks his uplink, add an active_uplink_check(mob/user as mob) in your interact/attack_hand proc. * 3. If you want the menu to stay until the users locks his uplink, add an active_uplink_check(mob/user as mob) in your interact/attack_hand proc.

View File

@@ -228,8 +228,6 @@
if(gurgled && clean_types & CLEAN_WASH) if(gurgled && clean_types & CLEAN_WASH)
gurgled = FALSE gurgled = FALSE
cut_overlay(gurgled_overlays[gurgled_color]) cut_overlay(gurgled_overlays[gurgled_color])
name = initial(name)
desc = initial(desc)
if(contaminated && clean_types & CLEAN_RAD) // Phoron and stuff, washing machine needed if(contaminated && clean_types & CLEAN_RAD) // Phoron and stuff, washing machine needed
contaminated = FALSE contaminated = FALSE
cut_overlay(contamination_overlay) cut_overlay(contamination_overlay)

View File

@@ -467,7 +467,7 @@
admin_holder.rank_flags(), admin_holder.rank_flags(),
350, 350,
590, 590,
allowed_edit_list = usr.client.holder.can_edit_rights_flags(), allowed_edit_field = usr.client.holder.can_edit_rights_flags(),
) )
admin_holder.disassociate() admin_holder.disassociate()

View File

@@ -77,7 +77,9 @@ GLOBAL_VAR_INIT(global_vantag_hud, 0)
to_chat(src, "Some accounts did not have proper ages set in their clients. This function requires database to be present.") to_chat(src, "Some accounts did not have proper ages set in their clients. This function requires database to be present.")
if(msg != "") if(msg != "")
src << browse("<html>[msg]</html>", "window=Player_age_check") var/datum/browser/popup = new(src, "Player_age_check", "Player Age Check")
popup.set_content(msg)
popup.open()
else else
to_chat(src, "No matches for that age range found.") to_chat(src, "No matches for that age range found.")

View File

@@ -61,7 +61,7 @@
if(..()) if(..())
return return
user.machine = src user.machine = src
var/dat = "<head><title>Engine Computer</title></head><body>" var/dat = ""
switch(src.state) switch(src.state)
if(STATE_DEFAULT) if(STATE_DEFAULT)
if (src.authenticated) if (src.authenticated)
@@ -85,8 +85,11 @@
dat += "<BR>Contents:<br>[src.connected_E.H_fuel]kg of Hydrogen<br>[src.connected_E.antiH_fuel]kg of Anti-Hydrogen<br>" dat += "<BR>Contents:<br>[src.connected_E.H_fuel]kg of Hydrogen<br>[src.connected_E.antiH_fuel]kg of Anti-Hydrogen<br>"
dat += "<BR>\[ [(src.state != STATE_DEFAULT) ? "<A href='byond://?src=\ref[src];operation=main'>Main Menu</A> | " : ""]<A href='byond://?src=\ref[user];mach_close=communications'>Close</A> \]" dat += "<BR>\[ [(src.state != STATE_DEFAULT) ? "<A href='byond://?src=\ref[src];operation=main'>Main Menu</A> | " : ""]<A href='byond://?src=\ref[user];mach_close=communications'>Close</A> \]"
user << browse("<html>[dat]</html>", "window=communications;size=400x500")
onclose(user, "communications") var/datum/browser/popup = new(user, "communications", "Communications", 400, 500)
popup.add_head_content("<title>Engine Computer</title>")
popup.set_content(dat)
popup.open()
#undef STATE_DEFAULT #undef STATE_DEFAULT
#undef STATE_INJECTOR #undef STATE_INJECTOR

View File

@@ -31,91 +31,6 @@
monitor.tgui_interact(user) monitor.tgui_interact(user)
/*
/obj/machinery/computer/gyrotron_control/attack_hand(var/mob/user)
add_fingerprint(user)
interact(user)
/obj/machinery/computer/gyrotron_control/interact(var/mob/user)
if(stat & (BROKEN|NOPOWER))
user.unset_machine()
user << browse(null, "window=gyrotron_controller_[id_tag]")
return
if(!id_tag)
to_chat(user, span_warning("This console has not been assigned an ident tag. Please contact your system administrator or conduct a manual update with a standard multitool."))
return
var/dat = "<td>" + span_bold("Gyrotron controller #[id_tag]")
dat = "<table><tr>"
dat += "<td>" + span_bold("Mode") + "</td>"
dat += "<td>" + span_bold("Fire Delay") + "</td>"
dat += "<td>" + span_bold("Power") + "</td>"
dat += "</tr>"
for(var/obj/machinery/power/emitter/gyrotron/G in gyrotrons)
if(!G || G.id_tag != id_tag || get_dist(src, G) > scan_range)
continue
dat += "<tr>"
if(G.state != 2 || (G.stat & (NOPOWER | BROKEN))) //Error data not found.
dat += "<td>" + span_red("ERROR") + "</td>"
dat += "<td>" + span_red("ERROR") + "</td>"
dat += "<td>" + span_red("ERROR") + "</td>"
else
dat += "<td><a href='byond://?src=\ref[src];machine=\ref[G];toggle=1'>[G.active ? "Emitting" : "Standing By"]</a></td>"
dat += "<td><a href='byond://?src=\ref[src];machine=\ref[G];modifyrate=1'>[G.rate]</a></td>"
dat += "<td><a href='byond://?src=\ref[src];machine=\ref[G];modifypower=1'>[G.mega_energy]</a></td>"
dat += "</tr></table>"
var/datum/browser/popup = new(user, "gyrotron_controller_[id_tag]", "Gyrotron Remote Control Console", 500, 400, src)
popup.set_content(dat)
popup.open()
add_fingerprint(user)
user.set_machine(src)
/obj/machinery/computer/gyrotron_control/Topic(var/href, var/list/href_list)
. = ..()
if(.)
return
if(stat & (NOPOWER | BROKEN))
return
var/obj/machinery/power/emitter/gyrotron/G = locate(href_list["machine"])
if(!G || G.id_tag != id_tag || get_dist(src, G) > scan_range)
return
if(href_list["modifypower"])
var/new_val = tgui_input_number(usr, "Enter new emission power level (1 - 50)", "Modifying power level", G.mega_energy, 50, 1)
if(!new_val)
to_chat(usr, span_warning("That's not a valid number."))
return 1
G.mega_energy = CLAMP(new_val, 1, 50)
G.update_active_power_usage(G.mega_energy * 1500)
updateUsrDialog(usr)
return 1
if(href_list["modifyrate"])
var/new_val = tgui_input_number(usr, "Enter new emission delay between 1 and 10 seconds.", "Modifying emission rate", G.rate, 10, 1)
if(!new_val)
to_chat(usr, span_warning("That's not a valid number."))
return 1
G.rate = CLAMP(new_val, 1, 10)
updateUsrDialog(usr)
return 1
if(href_list["toggle"])
G.activate(usr)
updateUsrDialog(usr)
return 1
return 0
*/
/obj/machinery/computer/gyrotron_control/attackby(var/obj/item/W, var/mob/user) /obj/machinery/computer/gyrotron_control/attackby(var/obj/item/W, var/mob/user)
..() ..()
if(istype(W, /obj/item/multitool)) if(istype(W, /obj/item/multitool))

View File

@@ -162,8 +162,9 @@
dat += span_red("The dart cartridge is empty!") dat += span_red("The dart cartridge is empty!")
dat += " \[<A href='byond://?src=\ref[src];eject_cart=1'>Eject</A>\]" dat += " \[<A href='byond://?src=\ref[src];eject_cart=1'>Eject</A>\]"
user << browse("<html>[dat]</html>", "window=dartgun") var/datum/browser/popup = new(user, "dartgun", "Dartgun")
onclose(user, "dartgun", src) popup.set_content(dat)
popup.open()
/obj/item/gun/projectile/dartgun/proc/check_beaker_mixing(var/obj/item/B) /obj/item/gun/projectile/dartgun/proc/check_beaker_mixing(var/obj/item/B)
if(!mixing || !beakers) if(!mixing || !beakers)

View File

@@ -25,4 +25,6 @@ GLOBAL_LIST_EMPTY(chemical_reaction_logs)
for(var/entry in GLOB.chemical_reaction_logs) for(var/entry in GLOB.chemical_reaction_logs)
html += "[entry]<br>" html += "[entry]<br>"
usr << browse("<html>[html]</html>", "window=chemlogs") var/datum/browser/popup = new(usr, "chemlogs", "Chemlogs")
popup.set_content(html)
popup.open()

View File

@@ -301,84 +301,6 @@
return TRUE return TRUE
// src.add_fingerprint(user)
// if(stat & BROKEN)
// user.unset_machine()
// return
// var/dat = "<head><title>Waste Disposal Unit</title></head><body><TT>" + span_bold("Waste Disposal Unit") + "<HR>"
// if(!ai) // AI can't pull flush handle
// if(flush)
// dat += "Disposal handle: <A href='byond://?src=\ref[src];handle=0'>Disengage</A> " + span_bold("Engaged")
// else
// dat += "Disposal handle: " + span_bold("Disengaged") + " <A href='byond://?src=\ref[src];handle=1'>Engage</A>"
// dat += "<BR><HR><A href='byond://?src=\ref[src];eject=1'>Eject contents</A><HR>"
// if(mode <= 0)
// dat += "Pump: " + span_bold("Off") + " <A href='byond://?src=\ref[src];pump=1'>On</A><BR>"
// else if(mode == 1)
// dat += "Pump: <A href='byond://?src=\ref[src];pump=0'>Off</A> " + span_bold("On") + " (pressurizing)<BR>"
// else
// dat += "Pump: <A href='byond://?src=\ref[src];pump=0'>Off</A> " + span_bold("On") + " (idle)<BR>"
// var/per = 100* air_contents.return_pressure() / (SEND_PRESSURE)
// dat += "Pressure: [round(per, 1)]%<BR></body>"
// user.set_machine(src)
// user << browse("<html>[dat]</html>", "window=disposal;size=360x170")
// onclose(user, "disposal")
// handle machine interaction
// /obj/machinery/disposal/Topic(href, href_list)
// if(usr.loc == src)
// to_chat(usr, span_red("You cannot reach the controls from inside."))
// return
// if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1
// to_chat(usr, span_red("The disposal units power is disabled."))
// return
// if(..())
// return
// if(stat & BROKEN)
// return
// if(usr.stat || usr.restrained() || src.flushing)
// return
// if(istype(src.loc, /turf))
// usr.set_machine(src)
// if(href_list["close"])
// usr.unset_machine()
// usr << browse(null, "window=disposal")
// return
// if(href_list["pump"])
// if(text2num(href_list["pump"]))
// mode = 1
// else
// mode = 0
// update()
// if(!isAI(usr))
// if(href_list["handle"])
// flush = text2num(href_list["handle"])
// update()
// if(href_list["eject"])
// eject()
// else
// usr << browse(null, "window=disposal")
// usr.unset_machine()
// return
// return
// eject the contents of the disposal unit // eject the contents of the disposal unit
/obj/machinery/disposal/verb/force_eject() /obj/machinery/disposal/verb/force_eject()

View File

@@ -78,9 +78,10 @@
// END AUTOFIX // END AUTOFIX
if(op) if(op)
dat += "<A href='byond://?src=\ref[src];spell_choice=rememorize'>Re-memorize Spells</A><BR>" dat += "<A href='byond://?src=\ref[src];spell_choice=rememorize'>Re-memorize Spells</A><BR>"
user << browse("<html>[dat]</html>", "window=radio")
onclose(user, "radio") var/datum/browser/popup = new(user, "radio", "Spellbook")
return popup.set_content(dat)
popup.open()
/obj/item/spellbook/Topic(href, href_list) /obj/item/spellbook/Topic(href, href_list)
..() ..()

View File

@@ -124,7 +124,7 @@
GLOBAL_DATUM_INIT(stockExchange, /datum/stockMarket, new) GLOBAL_DATUM_INIT(stockExchange, /datum/stockMarket, new)
/proc/plotBarGraph(var/list/points, var/base_text, var/width=400, var/height=400) /proc/plotBarGraph(var/list/points, var/base_text, var/width=400, var/height=400)
var/output = "<html><table style='border:1px solid black; border-collapse: collapse; width: [width]px; height: [height]px'>" var/output = "<table style='border:1px solid black; border-collapse: collapse; width: [width]px; height: [height]px'>"
if (points.len && height > 20 && width > 20) if (points.len && height > 20 && width > 20)
var/min = points[1] var/min = points[1]
var/max = points[1] var/max = points[1]
@@ -165,4 +165,4 @@ GLOBAL_DATUM_INIT(stockExchange, /datum/stockMarket, new)
output += "<tr><td style='width:[width]px; height:[height]px; background: black'></td></tr>" output += "<tr><td style='width:[width]px; height:[height]px; background: black'></td></tr>"
output += "<tr><td style='font-size:10px; background:black; color:green; text-align:center'>[base_text]</td></tr>" output += "<tr><td style='font-size:10px; background:black; color:green; text-align:center'>[base_text]</td></tr>"
return "[output]</table></html>" return "[output]</table>"

View File

@@ -305,4 +305,6 @@
return 0 return 0
/datum/stock/proc/displayValues(var/mob/user) /datum/stock/proc/displayValues(var/mob/user)
user << browse(plotBarGraph(values, "[name] share value per share"), "window=stock_[name];size=450x450") var/datum/browser/popup = new(user, "stock_[name]", "Share Value", 450, 450)
popup.set_content(plotBarGraph(values, "[name] share value per share"))
popup.open()

View File

@@ -238,7 +238,9 @@
if(index == page) if(index == page)
dat = span_bold(dat) dat = span_bold(dat)
usr << browse("<html>[dat]</html>", "window=player_notes;size=400x400") var/datum/browser/popup = new(usr, "player_notes", "Admin Playernotes", 480, 480)
popup.set_content(dat)
popup.open()
/datum/admins/proc/player_has_info_legacy(var/key as text) /datum/admins/proc/player_has_info_legacy(var/key as text)
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav") var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
@@ -253,8 +255,7 @@
if (!istype(src,/datum/admins)) if (!istype(src,/datum/admins))
to_chat(usr, "Error: you are not an admin!") to_chat(usr, "Error: you are not an admin!")
return return
var/dat = "<html><head><title>Info on [key]</title></head>" var/dat = ""
dat += "<body>"
var/p_age = "unknown" var/p_age = "unknown"
for(var/client/C in GLOB.clients) for(var/client/C in GLOB.clients)
@@ -288,8 +289,10 @@
dat += "<br>" dat += "<br>"
dat += "<A href='byond://?src=\ref[src];[HrefToken()];add_player_info_legacy=[key]'>Add Comment</A><br>" dat += "<A href='byond://?src=\ref[src];[HrefToken()];add_player_info_legacy=[key]'>Add Comment</A><br>"
dat += "</body></html>" var/datum/browser/popup = new(usr, "adminplayerinfo", "Admin Playerinfo", 480, 480)
usr << browse(dat, "window=adminplayerinfo;size=480x480") popup.add_head_content("<title>Info on [key]</title>")
popup.set_content(dat)
popup.open()
/datum/admins/Topic(href, href_list) /datum/admins/Topic(href, href_list)
..() ..()

View File

@@ -17,7 +17,7 @@
nuke_chat() nuke_chat()
// Failed to fix, using tgalert as fallback // Failed to fix, using tgalert as fallback
action = tgalert(src, "Did that work?", "", "Yes", "No, switch to old ui") action = tg_alert(src, "Did that work?", "", "Yes", "No, switch to old ui")
if (action == "No, switch to old ui") if (action == "No, switch to old ui")
winset(src, "legacy_output_selector", "left=output_legacy") winset(src, "legacy_output_selector", "left=output_legacy")
log_tgui(src, "Failed to fix.", context = "verb/fix_tgui_panel") log_tgui(src, "Failed to fix.", context = "verb/fix_tgui_panel")

View File

@@ -180,6 +180,7 @@
if(dat) if(dat)
last_data = dat last_data = dat
dat += "<br><br>\[<a href='byond://?src=\ref[src];print=1'>print report</a>\]" dat += "<br><br>\[<a href='byond://?src=\ref[src];print=1'>print report</a>\]"
user << browse("<html>[dat]</html>","window=xeno_analyzer")
return var/datum/browser/popup = new(user, "xeno_analyzer", "Xeno Analyzer")
popup.set_content(dat)
popup.open()

View File

@@ -1,4 +1,4 @@
<html><h1>Malfunctioning AI guide</h1><br> <h1>Malfunctioning AI guide</h1><br>
This guide contains most important OOC information for malfunctioning AIs.<br> This guide contains most important OOC information for malfunctioning AIs.<br>
@@ -19,4 +19,4 @@ Software are abilities that have to be unlocked via research menu (Hardware tab)
<b>Interdiction</b> - Sabotage-oriented abilities. T1 ability allows you to recall emergency shuttle. Higher level abilities allow you to unlock cyborgs even without access to robotics console, and T4 ability allows you to hack other AIs to slave them under your control.<br> <b>Interdiction</b> - Sabotage-oriented abilities. T1 ability allows you to recall emergency shuttle. Higher level abilities allow you to unlock cyborgs even without access to robotics console, and T4 ability allows you to hack other AIs to slave them under your control.<br>
<b>Manipulation</b> - Physical-oriented abilities. T1 ability allows you to break few lights, and rarely even APCs. T2 ability allows you to apply upgrade of your choice to camera, or reactivate broken camera. T3 ability allows you to create weak forcefield, that holds air, but won't last for long. And T4 ability allows you to overload machines, detonating them in weak explosion.<br> <b>Manipulation</b> - Physical-oriented abilities. T1 ability allows you to break few lights, and rarely even APCs. T2 ability allows you to apply upgrade of your choice to camera, or reactivate broken camera. T3 ability allows you to create weak forcefield, that holds air, but won't last for long. And T4 ability allows you to overload machines, detonating them in weak explosion.<br>
<h2>End</h2><br> <h2>End</h2><br>
If you still have some questions, either check the wiki, ask on IRC, or adminhelp and ask your friendly administration staff.</html> If you still have some questions, either check the wiki, ask on IRC, or adminhelp and ask your friendly administration staff.

View File

@@ -73,7 +73,7 @@ export const VoreSelectedBellyInteractions = (props: {
action="set_attribute" action="set_attribute"
subAction="b_digestchance" subAction="b_digestchance"
editMode={editMode} editMode={editMode}
value={interacts.escapechance} value={interacts.digestchance}
minValue={0} minValue={0}
maxValue={100} maxValue={100}
unit="%" unit="%"

View File

@@ -18,7 +18,7 @@ export const VoreUserPreferencesAesthetic = (props: {
active_belly: string | null; active_belly: string | null;
our_bellies: bellyData[]; our_bellies: bellyData[];
belly_rub_target: string | null; belly_rub_target: string | null;
vore_sprite_color: Record<string, string>; vore_sprite_color: Record<string, string | undefined>;
vore_sprite_multiply: Record<string, BooleanLike>; vore_sprite_multiply: Record<string, BooleanLike>;
vore_icon_options: string[]; vore_icon_options: string[];
aestethicMessages: aestMessageData; aestethicMessages: aestMessageData;
@@ -46,6 +46,10 @@ export const VoreUserPreferencesAesthetic = (props: {
const capitalizedName = active_belly && capitalize(active_belly); const capitalizedName = active_belly && capitalize(active_belly);
const possibleIconOptions = vore_icon_options.filter(
(entry) => !!vore_sprite_color[entry],
);
return ( return (
<Section <Section
fill fill
@@ -64,7 +68,7 @@ export const VoreUserPreferencesAesthetic = (props: {
<Stack> <Stack>
<Stack.Item basis="49%" grow> <Stack.Item basis="49%" grow>
<LabeledList> <LabeledList>
{vore_icon_options.map((entry) => ( {possibleIconOptions.map((entry) => (
<LabeledList.Item key={entry} label={capitalize(entry)}> <LabeledList.Item key={entry} label={capitalize(entry)}>
<Stack align="center"> <Stack align="center">
<VorePanelEditColor <VorePanelEditColor
@@ -73,7 +77,7 @@ export const VoreUserPreferencesAesthetic = (props: {
editMode={editMode} editMode={editMode}
action="set_vs_color" action="set_vs_color"
subAction={entry} subAction={entry}
back_color={vore_sprite_color[entry]} back_color={vore_sprite_color[entry] || ''}
tooltip={ tooltip={
"Modify the sprite color of your '" + "Modify the sprite color of your '" +
entry + entry +

View File

@@ -373,7 +373,7 @@ export type generalPrefData = {
active_belly: string | null; active_belly: string | null;
belly_rub_target: string | null; belly_rub_target: string | null;
aestethic_messages: aestMessageData; aestethic_messages: aestMessageData;
vore_sprite_color: Record<string, string>; vore_sprite_color: Record<string, string | undefined>;
vore_sprite_multiply: Record<string, BooleanLike>; vore_sprite_multiply: Record<string, BooleanLike>;
vore_icon_options: string[]; vore_icon_options: string[];
}; };

View File

@@ -56,6 +56,7 @@
#include "code\__defines\chemistry_vr.dm" #include "code\__defines\chemistry_vr.dm"
#include "code\__defines\circuitboard.dm" #include "code\__defines\circuitboard.dm"
#include "code\__defines\cleaning.dm" #include "code\__defines\cleaning.dm"
#include "code\__defines\client.dm"
#include "code\__defines\cloning.dm" #include "code\__defines\cloning.dm"
#include "code\__defines\clothing.dm" #include "code\__defines\clothing.dm"
#include "code\__defines\color.dm" #include "code\__defines\color.dm"