Merge remote-tracking branch 'upstream/master' into rnd-tgui-rebase

This commit is contained in:
nicetoolbox
2020-10-11 11:59:11 -07:00
144 changed files with 5584 additions and 4243 deletions
+46 -255
View File
@@ -6,7 +6,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
msg = "<span class=\"admin\"><span class=\"prefix\">ADMIN LOG:</span> <span class=\"message\">[msg]</span></span>"
for(var/client/C in GLOB.admins)
if(R_ADMIN & C.holder.rights)
if(C.prefs && !(C.prefs.toggles & CHAT_NO_ADMINLOGS))
if(C.prefs && !(C.prefs.toggles & PREFTOGGLE_CHAT_NO_ADMINLOGS))
to_chat(C, msg)
/proc/msg_admin_attack(var/text, var/loglevel)
@@ -20,22 +20,39 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(C.prefs.atklog <= loglevel)
to_chat(C, msg)
/proc/message_adminTicket(var/msg, var/alt = FALSE)
if(alt)
msg = "<span class=admin_channel>ADMIN TICKET: [msg]</span>"
else
msg = "<span class=adminticket><span class='prefix'>ADMIN TICKET:</span> [msg]</span>"
/**
* Sends a message to the staff able to see admin tickets
* Arguments:
* msg - The message being send
* important - If the message is important. If TRUE it will ignore the CHAT_NO_TICKETLOGS preferences,
send a sound and flash the window. Defaults to FALSE
*/
/proc/message_adminTicket(msg, important = FALSE)
for(var/client/C in GLOB.admins)
if(R_ADMIN & C.holder.rights)
if(C.prefs && !(C.prefs.toggles & CHAT_NO_TICKETLOGS))
if(important || (C.prefs && !(C.prefs.toggles & PREFTOGGLE_CHAT_NO_TICKETLOGS)))
to_chat(C, msg)
if(important)
if(C.prefs?.sound & SOUND_ADMINHELP)
SEND_SOUND(C, 'sound/effects/adminhelp.ogg')
window_flash(C)
/proc/message_mentorTicket(var/msg)
/**
* Sends a message to the staff able to see mentor tickets
* Arguments:
* msg - The message being send
* important - If the message is important. If TRUE it will ignore the CHAT_NO_TICKETLOGS preferences,
send a sound and flash the window. Defaults to FALSE
*/
/proc/message_mentorTicket(msg, important = FALSE)
for(var/client/C in GLOB.admins)
if(check_rights(R_ADMIN | R_MENTOR | R_MOD, 0, C.mob))
if(C.prefs && !(C.prefs.toggles & CHAT_NO_MENTORTICKETLOGS))
if(important || (C.prefs && !(C.prefs.toggles & PREFTOGGLE_CHAT_NO_TICKETLOGS)))
to_chat(C, msg)
if(important)
if(C.prefs?.sound & SOUND_MENTORHELP)
SEND_SOUND(C, 'sound/effects/adminhelp.ogg')
window_flash(C)
/proc/admin_ban_mobsearch(var/mob/M, var/ckey_to_find, var/mob/admin_to_notify)
if(!M || !M.ckey)
@@ -291,251 +308,6 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(key)
vpn_whitelist_panel(key)
/datum/admins/proc/access_news_network() //MARKER
set category = "Event"
set name = "Access Newscaster Network"
set desc = "Allows you to view, add and edit news feeds."
if(!check_rights(R_EVENT))
return
if(!istype(src,/datum/admins))
src = usr.client.holder
var/dat
dat = text("<HEAD><TITLE>Admin Newscaster</TITLE></HEAD><H3>Admin Newscaster Unit</H3>")
switch(admincaster_screen)
if(0)
dat += {"Welcome to the admin newscaster.<BR> Here you can add, edit and censor every newspiece on the network.
<BR>Feed channels and stories entered through here will be uneditable and handled as official news by the rest of the units.
<BR>Note that this panel allows full freedom over the news network, there are no constrictions except the few basic ones. Don't break things!</FONT>
"}
if(GLOB.news_network.wanted_issue)
dat+= "<HR><A href='?src=[UID()];ac_view_wanted=1'>Read Wanted Issue</A>"
dat+= {"<HR><BR><A href='?src=[UID()];ac_create_channel=1'>Create Feed Channel</A>
<BR><A href='?src=[UID()];ac_view=1'>View Feed Channels</A>
<BR><A href='?src=[UID()];ac_create_feed_story=1'>Submit new Feed story</A>
<BR><BR><A href='?src=[usr.UID()];mach_close=newscaster_main'>Exit</A>
"}
var/wanted_already = 0
if(GLOB.news_network.wanted_issue)
wanted_already = 1
dat+={"<HR><B>Feed Security functions:</B><BR>
<BR><A href='?src=[UID()];ac_menu_wanted=1'>[(wanted_already) ? ("Manage") : ("Publish")] \"Wanted\" Issue</A>
<BR><A href='?src=[UID()];ac_menu_censor_story=1'>Censor Feed Stories</A>
<BR><A href='?src=[UID()];ac_menu_censor_channel=1'>Mark Feed Channel with Nanotrasen D-Notice (disables and locks the channel.</A>
<BR><HR><A href='?src=[UID()];ac_set_signature=1'>The newscaster recognises you as:<BR> <FONT COLOR='green'>[src.admincaster_signature]</FONT></A>
"}
if(1)
dat+= "Station Feed Channels<HR>"
if( isemptylist(GLOB.news_network.network_channels) )
dat+="<I>No active channels found...</I>"
else
for(var/datum/feed_channel/CHANNEL in GLOB.news_network.network_channels)
if(CHANNEL.is_admin_channel)
dat+="<B><FONT style='BACKGROUND-COLOR: LightGreen'><A href='?src=[UID()];ac_show_channel=\ref[CHANNEL]'>[CHANNEL.channel_name]</A></FONT></B><BR>"
else
dat+="<B><A href='?src=[UID()];ac_show_channel=\ref[CHANNEL]'>[CHANNEL.channel_name]</A> [(CHANNEL.censored) ? ("<FONT COLOR='red'>***</FONT>") : ""]<BR></B>"
dat+={"<BR><HR><A href='?src=[UID()];ac_refresh=1'>Refresh</A>
<BR><A href='?src=[UID()];ac_setScreen=[0]'>Back</A>
"}
if(2)
dat+={"
Creating new Feed Channel...
<HR><B><A href='?src=[UID()];ac_set_channel_name=1'>Channel Name</A>:</B> [src.admincaster_feed_channel.channel_name]<BR>
<B><A href='?src=[UID()];ac_set_signature=1'>Channel Author</A>:</B> <FONT COLOR='green'>[src.admincaster_signature]</FONT><BR>
<B><A href='?src=[UID()];ac_set_channel_lock=1'>Will Accept Public Feeds</A>:</B> [(src.admincaster_feed_channel.locked) ? ("NO") : ("YES")]<BR><BR>
<BR><A href='?src=[UID()];ac_submit_new_channel=1'>Submit</A><BR><BR><A href='?src=[UID()];ac_setScreen=[0]'>Cancel</A><BR>
"}
if(3)
dat+={"
Creating new Feed Message...
<HR><B><A href='?src=[UID()];ac_set_channel_receiving=1'>Receiving Channel</A>:</B> [src.admincaster_feed_channel.channel_name]<BR>
<B>Message Author:</B> <FONT COLOR='green'>[src.admincaster_signature]</FONT><BR>
<B><A href='?src=[UID()];ac_set_new_message=1'>Message Body</A>:</B> [src.admincaster_feed_message.body] <BR>
<BR><A href='?src=[UID()];ac_submit_new_message=1'>Submit</A><BR><BR><A href='?src=[UID()];ac_setScreen=[0]'>Cancel</A><BR>
"}
if(4)
dat+={"
Feed story successfully submitted to [src.admincaster_feed_channel.channel_name].<BR><BR>
<BR><A href='?src=[UID()];ac_setScreen=[0]'>Return</A><BR>
"}
if(5)
dat+={"
Feed Channel [src.admincaster_feed_channel.channel_name] created successfully.<BR><BR>
<BR><A href='?src=[UID()];ac_setScreen=[0]'>Return</A><BR>
"}
if(6)
dat+="<B><FONT COLOR='maroon'>ERROR: Could not submit Feed story to Network.</B></FONT><HR><BR>"
if(src.admincaster_feed_channel.channel_name=="")
dat+="<FONT COLOR='maroon'>•Invalid receiving channel name.</FONT><BR>"
if(src.admincaster_feed_message.body == "" || src.admincaster_feed_message.body == "\[REDACTED\]")
dat+="<FONT COLOR='maroon'>•Invalid message body.</FONT><BR>"
dat+="<BR><A href='?src=[UID()];ac_setScreen=[3]'>Return</A><BR>"
if(7)
dat+="<B><FONT COLOR='maroon'>ERROR: Could not submit Feed Channel to Network.</B></FONT><HR><BR>"
if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]")
dat+="<FONT COLOR='maroon'>•Invalid channel name.</FONT><BR>"
var/check = 0
for(var/datum/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.channel_name == src.admincaster_feed_channel.channel_name)
check = 1
break
if(check)
dat+="<FONT COLOR='maroon'>•Channel name already in use.</FONT><BR>"
dat+="<BR><A href='?src=[UID()];ac_setScreen=[2]'>Return</A><BR>"
if(9)
dat+="<B>[src.admincaster_feed_channel.channel_name]: </B><FONT SIZE=1>\[created by: <FONT COLOR='maroon'>[src.admincaster_feed_channel.author]</FONT>\]</FONT><HR>"
if(src.admincaster_feed_channel.censored)
dat+={"
<FONT COLOR='red'><B>ATTENTION: </B></FONT>This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.<BR>
No further feed story additions are allowed while the D-Notice is in effect.</FONT><BR><BR>
"}
else
if( isemptylist(src.admincaster_feed_channel.messages) )
dat+="<I>No feed messages found in channel...</I><BR>"
else
var/i = 0
for(var/datum/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
i++
dat+="-[MESSAGE.body] <BR>"
if(MESSAGE.img)
usr << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
dat+="<img src='tmp_photo[i].png' width = '180'><BR><BR>"
dat+="<FONT SIZE=1>\[Story by <FONT COLOR='maroon'>[MESSAGE.author]</FONT>\]</FONT><BR>"
dat+={"
<BR><HR><A href='?src=[UID()];ac_refresh=1'>Refresh</A>
<BR><A href='?src=[UID()];ac_setScreen=[1]'>Back</A>
"}
if(10)
dat+={"
<B>Nanotrasen Feed Censorship Tool</B><BR>
<FONT SIZE=1>NOTE: Due to the nature of news Feeds, total deletion of a Feed Story is not possible.<BR>
Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it.</FONT>
<HR>Select Feed channel to get Stories from:<BR>
"}
if(isemptylist(GLOB.news_network.network_channels))
dat+="<I>No feed channels found active...</I><BR>"
else
for(var/datum/feed_channel/CHANNEL in GLOB.news_network.network_channels)
dat+="<A href='?src=[UID()];ac_pick_censor_channel=\ref[CHANNEL]'>[CHANNEL.channel_name]</A> [(CHANNEL.censored) ? ("<FONT COLOR='red'>***</FONT>") : ""]<BR>"
dat+="<BR><A href='?src=[UID()];ac_setScreen=[0]'>Cancel</A>"
if(11)
dat+={"
<B>Nanotrasen D-Notice Handler</B><HR>
<FONT SIZE=1>A D-Notice is to be bestowed upon the channel if the handling Authority deems it as harmful for the station's
morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed
stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.</FONT><HR>
"}
if(isemptylist(GLOB.news_network.network_channels))
dat+="<I>No feed channels found active...</I><BR>"
else
for(var/datum/feed_channel/CHANNEL in GLOB.news_network.network_channels)
dat+="<A href='?src=[UID()];ac_pick_d_notice=\ref[CHANNEL]'>[CHANNEL.channel_name]</A> [(CHANNEL.censored) ? ("<FONT COLOR='red'>***</FONT>") : ""]<BR>"
dat+="<BR><A href='?src=[UID()];ac_setScreen=[0]'>Back</A>"
if(12)
dat+={"
<B>[src.admincaster_feed_channel.channel_name]: </B><FONT SIZE=1>\[ created by: <FONT COLOR='maroon'>[src.admincaster_feed_channel.author]</FONT> \]</FONT><BR>
<FONT SIZE=2><A href='?src=[UID()];ac_censor_channel_author=\ref[src.admincaster_feed_channel]'>[(src.admincaster_feed_channel.author=="\[REDACTED\]") ? ("Undo Author censorship") : ("Censor channel Author")]</A></FONT><HR>
"}
if( isemptylist(src.admincaster_feed_channel.messages) )
dat+="<I>No feed messages found in channel...</I><BR>"
else
for(var/datum/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
dat+={"
-[MESSAGE.body] <BR><FONT SIZE=1>\[Story by <FONT COLOR='maroon'>[MESSAGE.author]</FONT>\]</FONT><BR>
<FONT SIZE=2><A href='?src=[UID()];ac_censor_channel_story_body=\ref[MESSAGE]'>[(MESSAGE.body == "\[REDACTED\]") ? ("Undo story censorship") : ("Censor story")]</A> - <A href='?src=[UID()];ac_censor_channel_story_author=\ref[MESSAGE]'>[(MESSAGE.author == "\[REDACTED\]") ? ("Undo Author Censorship") : ("Censor message Author")]</A></FONT><BR>
"}
dat+="<BR><A href='?src=[UID()];ac_setScreen=[10]'>Back</A>"
if(13)
dat+={"
<B>[src.admincaster_feed_channel.channel_name]: </B><FONT SIZE=1>\[ created by: <FONT COLOR='maroon'>[src.admincaster_feed_channel.author]</FONT> \]</FONT><BR>
Channel messages listed below. If you deem them dangerous to the station, you can <A href='?src=[UID()];ac_toggle_d_notice=\ref[src.admincaster_feed_channel]'>Bestow a D-Notice upon the channel</A>.<HR>
"}
if(src.admincaster_feed_channel.censored)
dat+={"
<FONT COLOR='red'><B>ATTENTION: </B></FONT>This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.<BR>
No further feed story additions are allowed while the D-Notice is in effect.</FONT><BR><BR>
"}
else
if( isemptylist(src.admincaster_feed_channel.messages) )
dat+="<I>No feed messages found in channel...</I><BR>"
else
for(var/datum/feed_message/MESSAGE in src.admincaster_feed_channel.messages)
dat+="-[MESSAGE.body] <BR><FONT SIZE=1>\[Story by <FONT COLOR='maroon'>[MESSAGE.author]</FONT>\]</FONT><BR>"
dat+="<BR><A href='?src=[UID()];ac_setScreen=[11]'>Back</A>"
if(14)
dat+="<B>Wanted Issue Handler:</B>"
var/wanted_already = 0
var/end_param = 1
if(GLOB.news_network.wanted_issue)
wanted_already = 1
end_param = 2
if(wanted_already)
dat+="<FONT SIZE=2><BR><I>A wanted issue is already in Feed Circulation. You can edit or cancel it below.</FONT></I>"
dat+={"
<HR>
<A href='?src=[UID()];ac_set_wanted_name=1'>Criminal Name</A>: [src.admincaster_feed_message.author] <BR>
<A href='?src=[UID()];ac_set_wanted_desc=1'>Description</A>: [src.admincaster_feed_message.body] <BR>
"}
if(wanted_already)
dat+="<B>Wanted Issue created by:</B><FONT COLOR='green'> [GLOB.news_network.wanted_issue.backup_author]</FONT><BR>"
else
dat+="<B>Wanted Issue will be created under prosecutor:</B><FONT COLOR='green'> [src.admincaster_signature]</FONT><BR>"
dat+="<BR><A href='?src=[UID()];ac_submit_wanted=[end_param]'>[(wanted_already) ? ("Edit Issue") : ("Submit")]</A>"
if(wanted_already)
dat+="<BR><A href='?src=[UID()];ac_cancel_wanted=1'>Take down Issue</A>"
dat+="<BR><A href='?src=[UID()];ac_setScreen=[0]'>Cancel</A>"
if(15)
dat+={"
<FONT COLOR='green'>Wanted issue for [src.admincaster_feed_message.author] is now in Network Circulation.</FONT><BR><BR>
<BR><A href='?src=[UID()];ac_setScreen=[0]'>Return</A><BR>
"}
if(16)
dat+="<B><FONT COLOR='maroon'>ERROR: Wanted Issue rejected by Network.</B></FONT><HR><BR>"
if(src.admincaster_feed_message.author =="" || src.admincaster_feed_message.author == "\[REDACTED\]")
dat+="<FONT COLOR='maroon'>•Invalid name for person wanted.</FONT><BR>"
if(src.admincaster_feed_message.body == "" || src.admincaster_feed_message.body == "\[REDACTED\]")
dat+="<FONT COLOR='maroon'>•Invalid description.</FONT><BR>"
dat+="<BR><A href='?src=[UID()];ac_setScreen=[0]'>Return</A><BR>"
if(17)
dat+={"
<B>Wanted Issue successfully deleted from Circulation</B><BR>
<BR><A href='?src=[UID()];ac_setScreen=[0]'>Return</A><BR>
"}
if(18)
dat+={"
<B><FONT COLOR ='maroon'>-- STATIONWIDE WANTED ISSUE --</B></FONT><BR><FONT SIZE=2>\[Submitted by: <FONT COLOR='green'>[GLOB.news_network.wanted_issue.backup_author]</FONT>\]</FONT><HR>
<B>Criminal</B>: [GLOB.news_network.wanted_issue.author]<BR>
<B>Description</B>: [GLOB.news_network.wanted_issue.body]<BR>
<B>Photo:</B>:
"}
if(GLOB.news_network.wanted_issue.img)
usr << browse_rsc(GLOB.news_network.wanted_issue.img, "tmp_photow.png")
dat+="<BR><img src='tmp_photow.png' width = '180'>"
else
dat+="None"
dat+="<BR><A href='?src=[UID()];ac_setScreen=[0]'>Back</A><BR>"
if(19)
dat+={"
<FONT COLOR='green'>Wanted issue for [src.admincaster_feed_message.author] successfully edited.</FONT><BR><BR>
<BR><A href='?src=[UID()];ac_setScreen=[0]'>Return</A><BR>
"}
else
dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com"
// to_chat(world, "Channelname: [src.admincaster_feed_channel.channel_name] [src.admincaster_feed_channel.author]")
// to_chat(world, "Msg: [src.admincaster_feed_message.author] [src.admincaster_feed_message.body]")
usr << browse(dat, "window=admincaster_main;size=400x600")
onclose(usr, "admincaster_main")
/datum/admins/proc/Jobbans()
if(!check_rights(R_BAN))
return
@@ -594,6 +366,25 @@ GLOBAL_VAR_INIT(nologevent, 0)
feedback_add_details("admin_verb","R") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
world.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "end_error", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", delay)
/datum/admins/proc/end_round()
set category = "Server"
set name = "End Round"
set desc = "Instantly ends the round and brings up the scoreboard, like shadowlings or wizards dying."
if(!check_rights(R_SERVER))
return
var/input = sanitize(copytext(input(usr, "What text should players see announcing the round end? Input nothing to cancel.", "Specify Announcement Text", "Shift Has Ended!"), 1, MAX_MESSAGE_LEN))
if(!input)
return
if(SSticker.force_ending)
return
message_admins("[key_name_admin(usr)] has admin ended the round with message: '[input]'")
log_admin("[key_name(usr)] has admin ended the round with message: '[input]'")
SSticker.force_ending = TRUE
to_chat(world, "<span class='warning'><big><b>[input]</b></big></span>")
feedback_add_details("admin_verb", "END") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
feedback_set_details("round_end_result", "Admin ended")
/datum/admins/proc/announce()
set category = "Admin"
set name = "Announce"
+9 -9
View File
@@ -98,7 +98,6 @@ GLOBAL_LIST_INIT(admin_verbs_event, list(
/client/proc/toggle_ert_calling,
/client/proc/show_tip,
/client/proc/cmd_admin_change_custom_event,
/datum/admins/proc/access_news_network, /*allows access of newscasters*/
/client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/
/client/proc/cmd_admin_direct_narrate, /*send text directly to a player with no padding. Useful for narratives and fluff-text*/
/client/proc/cmd_admin_world_narrate, /*sends text to all players with no padding*/
@@ -123,6 +122,7 @@ GLOBAL_LIST_INIT(admin_verbs_server, list(
/client/proc/Set_Holiday,
/datum/admins/proc/startnow,
/datum/admins/proc/restart,
/datum/admins/proc/end_round,
/datum/admins/proc/delay,
/datum/admins/proc/toggleaban,
/datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/
@@ -888,9 +888,9 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
if(!check_rights(R_ADMIN))
return
prefs.toggles ^= CHAT_NO_ADMINLOGS
prefs.toggles ^= PREFTOGGLE_CHAT_NO_ADMINLOGS
prefs.save_preferences(src)
if(prefs.toggles & CHAT_NO_ADMINLOGS)
if(prefs.toggles & PREFTOGGLE_CHAT_NO_ADMINLOGS)
to_chat(usr, "You now won't get admin log messages.")
else
to_chat(usr, "You now will get admin log messages.")
@@ -902,9 +902,9 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
if(!check_rights(R_MENTOR|R_ADMIN))
return
prefs.toggles ^= CHAT_NO_MENTORTICKETLOGS
prefs.toggles ^= PREFTOGGLE_CHAT_NO_MENTORTICKETLOGS
prefs.save_preferences(src)
if(prefs.toggles & CHAT_NO_MENTORTICKETLOGS)
if(prefs.toggles & PREFTOGGLE_CHAT_NO_MENTORTICKETLOGS)
to_chat(usr, "You now won't get mentor ticket messages.")
else
to_chat(usr, "You now will get mentor ticket messages.")
@@ -916,9 +916,9 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
if(!check_rights(R_ADMIN))
return
prefs.toggles ^= CHAT_NO_TICKETLOGS
prefs.toggles ^= PREFTOGGLE_CHAT_NO_TICKETLOGS
prefs.save_preferences(src)
if(prefs.toggles & CHAT_NO_TICKETLOGS)
if(prefs.toggles & PREFTOGGLE_CHAT_NO_TICKETLOGS)
to_chat(usr, "You now won't get admin ticket messages.")
else
to_chat(usr, "You now will get admin ticket messages.")
@@ -941,9 +941,9 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
if(!check_rights(R_DEBUG))
return
prefs.toggles ^= CHAT_DEBUGLOGS
prefs.toggles ^= PREFTOGGLE_CHAT_DEBUGLOGS
prefs.save_preferences(src)
if(prefs.toggles & CHAT_DEBUGLOGS)
if(prefs.toggles & PREFTOGGLE_CHAT_DEBUGLOGS)
to_chat(usr, "You now will get debug log messages")
else
to_chat(usr, "You now won't get debug log messages")
+13 -225
View File
@@ -26,17 +26,16 @@
message_admins("[key_name_admin(usr)] rejected [key_name_admin(C.mob)]'s admin help")
log_admin("[key_name(usr)] rejected [key_name(C.mob)]'s admin help")
if(href_list["openadminticket"])
if(!check_rights(R_ADMIN))
return
var/ticketID = text2num(href_list["openadminticket"])
SStickets.showDetailUI(usr, ticketID)
if(href_list["openmentorticket"])
if(!check_rights(R_MENTOR|R_MOD|R_ADMIN))
return
var/ticketID = text2num(href_list["openmentorticket"])
SSmentor_tickets.showDetailUI(usr, ticketID)
if(href_list["openticket"])
var/ticketID = text2num(href_list["openticket"])
if(!href_list["is_mhelp"])
if(!check_rights(R_ADMIN))
return
SStickets.showDetailUI(usr, ticketID)
else
if(!check_rights(R_MENTOR|R_MOD|R_ADMIN))
return
SSmentor_tickets.showDetailUI(usr, ticketID)
if(href_list["stickyban"])
stickyban(href_list["stickyban"],href_list)
@@ -1669,6 +1668,9 @@
SStickets.resolveTicket(index)
else if(href_list["autorespond"])
if(href_list["is_mhelp"])
to_chat(usr, "<span class='warning'>Auto responses are not available for mentor helps.</span>")
return
var/index = text2num(href_list["autorespond"])
if(!check_rights(R_ADMIN|R_MOD))
return
@@ -3214,220 +3216,6 @@
J.spawn_positions = -1
message_admins("[key_name_admin(usr)] has removed the cap on security officers.")
else if(href_list["ac_view_wanted"]) //Admin newscaster Topic() stuff be here
src.admincaster_screen = 18 //The ac_ prefix before the hrefs stands for AdminCaster.
src.access_news_network()
else if(href_list["ac_set_channel_name"])
src.admincaster_feed_channel.channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", ""))
while(findtext(src.admincaster_feed_channel.channel_name," ") == 1)
src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,length(src.admincaster_feed_channel.channel_name)+1)
src.access_news_network()
else if(href_list["ac_set_channel_lock"])
src.admincaster_feed_channel.locked = !src.admincaster_feed_channel.locked
src.access_news_network()
else if(href_list["ac_submit_new_channel"])
var/check = 0
for(var/datum/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.channel_name == src.admincaster_feed_channel.channel_name)
check = 1
break
if(src.admincaster_feed_channel.channel_name == "" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]" || check )
src.admincaster_screen=7
else
var/choice = alert("Please confirm Feed channel creation","Network Channel Handler","Confirm","Cancel")
if(choice=="Confirm")
var/datum/feed_channel/newChannel = new /datum/feed_channel
newChannel.channel_name = src.admincaster_feed_channel.channel_name
newChannel.author = src.admincaster_signature
newChannel.locked = src.admincaster_feed_channel.locked
newChannel.is_admin_channel = 1
feedback_inc("newscaster_channels",1)
GLOB.news_network.network_channels += newChannel //Adding channel to the global network
log_admin("[key_name_admin(usr)] created command feed channel: [src.admincaster_feed_channel.channel_name]!")
src.admincaster_screen=5
src.access_news_network()
else if(href_list["ac_set_channel_receiving"])
var/list/available_channels = list()
for(var/datum/feed_channel/F in GLOB.news_network.network_channels)
available_channels += F.channel_name
src.admincaster_feed_channel.channel_name = adminscrub(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels )
src.access_news_network()
else if(href_list["ac_set_new_message"])
src.admincaster_feed_message.body = adminscrub(input(usr, "Write your Feed story", "Network Channel Handler", ""))
while(findtext(src.admincaster_feed_message.body," ") == 1)
src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.body,2,length(src.admincaster_feed_message.body)+1)
src.access_news_network()
else if(href_list["ac_submit_new_message"])
if(src.admincaster_feed_message.body =="" || src.admincaster_feed_message.body =="\[REDACTED\]" || src.admincaster_feed_channel.channel_name == "" )
src.admincaster_screen = 6
else
var/datum/feed_message/newMsg = new /datum/feed_message
newMsg.author = src.admincaster_signature
newMsg.body = src.admincaster_feed_message.body
newMsg.is_admin_message = 1
feedback_inc("newscaster_stories",1)
for(var/datum/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.channel_name == src.admincaster_feed_channel.channel_name)
FC.messages += newMsg //Adding message to the network's appropriate feed_channel
break
src.admincaster_screen=4
for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters)
NEWSCASTER.newsAlert(src.admincaster_feed_channel.channel_name)
log_admin("[key_name_admin(usr)] submitted a feed story to channel: [src.admincaster_feed_channel.channel_name]!")
src.access_news_network()
else if(href_list["ac_create_channel"])
src.admincaster_screen=2
src.access_news_network()
else if(href_list["ac_create_feed_story"])
src.admincaster_screen=3
src.access_news_network()
else if(href_list["ac_menu_censor_story"])
src.admincaster_screen=10
src.access_news_network()
else if(href_list["ac_menu_censor_channel"])
src.admincaster_screen=11
src.access_news_network()
else if(href_list["ac_menu_wanted"])
var/already_wanted = 0
if(GLOB.news_network.wanted_issue)
already_wanted = 1
if(already_wanted)
src.admincaster_feed_message.author = GLOB.news_network.wanted_issue.author
src.admincaster_feed_message.body = GLOB.news_network.wanted_issue.body
src.admincaster_screen = 14
src.access_news_network()
else if(href_list["ac_set_wanted_name"])
src.admincaster_feed_message.author = adminscrub(input(usr, "Provide the name of the Wanted person", "Network Security Handler", ""))
while(findtext(src.admincaster_feed_message.author," ") == 1)
src.admincaster_feed_message.author = copytext(admincaster_feed_message.author,2,length(admincaster_feed_message.author)+1)
src.access_news_network()
else if(href_list["ac_set_wanted_desc"])
src.admincaster_feed_message.body = adminscrub(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", ""))
while(findtext(src.admincaster_feed_message.body," ") == 1)
src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.body,2,length(src.admincaster_feed_message.body)+1)
src.access_news_network()
else if(href_list["ac_submit_wanted"])
var/input_param = text2num(href_list["ac_submit_wanted"])
if(src.admincaster_feed_message.author == "" || src.admincaster_feed_message.body == "")
src.admincaster_screen = 16
else
var/choice = alert("Please confirm Wanted Issue [(input_param==1) ? ("creation.") : ("edit.")]","Network Security Handler","Confirm","Cancel")
if(choice=="Confirm")
if(input_param==1) //If input_param == 1 we're submitting a new wanted issue. At 2 we're just editing an existing one. See the else below
var/datum/feed_message/WANTED = new /datum/feed_message
WANTED.author = src.admincaster_feed_message.author //Wanted name
WANTED.body = src.admincaster_feed_message.body //Wanted desc
WANTED.backup_author = src.admincaster_signature //Submitted by
WANTED.is_admin_message = 1
GLOB.news_network.wanted_issue = WANTED
for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters)
NEWSCASTER.newsAlert()
NEWSCASTER.update_icon()
src.admincaster_screen = 15
else
GLOB.news_network.wanted_issue.author = src.admincaster_feed_message.author
GLOB.news_network.wanted_issue.body = src.admincaster_feed_message.body
GLOB.news_network.wanted_issue.backup_author = src.admincaster_feed_message.backup_author
src.admincaster_screen = 19
log_admin("[key_name_admin(usr)] issued a Station-wide Wanted Notification for [src.admincaster_feed_message.author]!")
src.access_news_network()
else if(href_list["ac_cancel_wanted"])
var/choice = alert("Please confirm Wanted Issue removal","Network Security Handler","Confirm","Cancel")
if(choice=="Confirm")
GLOB.news_network.wanted_issue = null
for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters)
NEWSCASTER.update_icon()
src.admincaster_screen=17
src.access_news_network()
else if(href_list["ac_censor_channel_author"])
var/datum/feed_channel/FC = locate(href_list["ac_censor_channel_author"])
if(FC.author != "<b>\[REDACTED\]</b>")
FC.backup_author = FC.author
FC.author = "<b>\[REDACTED\]</b>"
else
FC.author = FC.backup_author
src.access_news_network()
else if(href_list["ac_censor_channel_story_author"])
var/datum/feed_message/MSG = locate(href_list["ac_censor_channel_story_author"])
if(MSG.author != "<b>\[REDACTED\]</b>")
MSG.backup_author = MSG.author
MSG.author = "<b>\[REDACTED\]</b>"
else
MSG.author = MSG.backup_author
src.access_news_network()
else if(href_list["ac_censor_channel_story_body"])
var/datum/feed_message/MSG = locate(href_list["ac_censor_channel_story_body"])
if(MSG.body != "<b>\[REDACTED\]</b>")
MSG.backup_body = MSG.body
MSG.body = "<b>\[REDACTED\]</b>"
else
MSG.body = MSG.backup_body
src.access_news_network()
else if(href_list["ac_pick_d_notice"])
var/datum/feed_channel/FC = locate(href_list["ac_pick_d_notice"])
src.admincaster_feed_channel = FC
src.admincaster_screen=13
src.access_news_network()
else if(href_list["ac_toggle_d_notice"])
var/datum/feed_channel/FC = locate(href_list["ac_toggle_d_notice"])
FC.censored = !FC.censored
src.access_news_network()
else if(href_list["ac_view"])
src.admincaster_screen=1
src.access_news_network()
else if(href_list["ac_setScreen"]) //Brings us to the main menu and resets all fields~
src.admincaster_screen = text2num(href_list["ac_setScreen"])
if(src.admincaster_screen == 0)
if(src.admincaster_feed_channel)
src.admincaster_feed_channel = new /datum/feed_channel
if(src.admincaster_feed_message)
src.admincaster_feed_message = new /datum/feed_message
src.access_news_network()
else if(href_list["ac_show_channel"])
var/datum/feed_channel/FC = locate(href_list["ac_show_channel"])
src.admincaster_feed_channel = FC
src.admincaster_screen = 9
src.access_news_network()
else if(href_list["ac_pick_censor_channel"])
var/datum/feed_channel/FC = locate(href_list["ac_pick_censor_channel"])
src.admincaster_feed_channel = FC
src.admincaster_screen = 12
src.access_news_network()
else if(href_list["ac_refresh"])
src.access_news_network()
else if(href_list["ac_set_signature"])
src.admincaster_signature = adminscrub(input(usr, "Provide your desired signature", "Network Identity Handler", ""))
src.access_news_network()
if(href_list["secretsmenu"])
switch(href_list["secretsmenu"])
if("tab")
+10 -108
View File
@@ -29,64 +29,12 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","mo
msg = sanitize_simple(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg) return
var/original_msg = msg
if(selected_type == "Mentorhelp")
SSmentor_tickets.newHelpRequest(src, msg)
else
SStickets.newHelpRequest(src, msg)
//explode the input msg into a list
var/list/msglist = splittext(msg, " ")
//generate keywords lookup
var/list/surnames = list()
var/list/forenames = list()
var/list/ckeys = list()
for(var/mob/M in GLOB.mob_list)
var/list/indexing = list(M.real_name, M.name)
if(M.mind) indexing += M.mind.name
for(var/string in indexing)
var/list/L = splittext(string, " ")
var/surname_found = 0
//surnames
for(var/i=L.len, i>=1, i--)
var/word = ckey(L[i])
if(word)
surnames[word] = M
surname_found = i
break
//forenames
for(var/i=1, i<surname_found, i++)
var/word = ckey(L[i])
if(word)
forenames[word] = M
//ckeys
ckeys[M.ckey] = M
var/ai_found = 0
msg = ""
var/list/mobs_found = list()
for(var/original_word in msglist)
var/word = ckey(original_word)
if(word)
if(!(word in GLOB.adminhelp_ignored_words))
if(word == "ai")
ai_found = 1
else
var/mob/found = ckeys[word]
if(!found)
found = surnames[word]
if(!found)
found = forenames[word]
if(found)
if(!(found in mobs_found))
mobs_found += found
if(!ai_found && isAI(found))
ai_found = 1
msg += "<b><span class='adminnotice'>[original_word] </span></b> "
continue
msg += "[original_word] "
if(!mob) return //this doesn't happen
//send this msg to all admins
//See how many staff are on
var/admin_number_afk = 0
var/list/mentorholders = list()
var/list/modholders = list()
@@ -103,65 +51,19 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","mo
if(check_rights(R_MENTOR, 0, X.mob))
mentorholders += X
continue
var/ticketNum // Holder for the ticket number
var/prunedmsg ="[src]: [msg]" // Message without links
var/datum/ticket/T
var/isMhelp = selected_type == "Mentorhelp"
var/span
if(isMhelp)
span = "<span class='mentorhelp'>"
if(SSmentor_tickets.checkForOpenTicket(src)) // If user already has an open ticket
T = SSmentor_tickets.checkForOpenTicket(src)
else
ticketNum = SSmentor_tickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
else //Ahelp
span = "<span class='adminhelp'>"
if(SStickets.checkForOpenTicket(src)) // If user already has an open ticket
T = SStickets.checkForOpenTicket(src) // Make T equal to the ticket they have open
else
ticketNum = SStickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
if(T)
ticketNum = T.ticketNum // ticketNum is the number of their ticket.
T.addResponse(src, msg)
var/finalised_msg = "[span][selected_type]: </span><span class='boldnotice'>[key_name(src, TRUE, selected_type)] "
finalised_msg += "([ADMIN_QUE(mob,"?")]) ([ADMIN_PP(mob,"PP")]) ([ADMIN_VV(mob,"VV")]) ([ADMIN_TP(mob,"TP")]) ([ADMIN_SM(mob,"SM")]) "
finalised_msg += "([admin_jump_link(mob)]) (<A HREF='?_src_=holder;[isMhelp ? "openmentorticket" : "openadminticket"]=[ticketNum]'>TICKET</A>) "
finalised_msg += "[ai_found ? "(<A HREF='?_src_=holder;adminchecklaws=[mob.UID()]'>CL</A>)" : ""] (<A HREF='?_src_=holder;take_question=[ticketNum][isMhelp ? ";is_mhelp=1" : ""]'>TAKE</A>) "
finalised_msg += "(<A HREF='?_src_=holder;resolve=[ticketNum][isMhelp ? ";is_mhelp=1" : ""]'>RESOLVE</A>) [isMhelp ? "" : "<A HREF='?_src_=holder;autorespond=[ticketNum]'>(AUTO)</A>"] "
finalised_msg += "<a href='?_src_=holder;convert_ticket=[ticketNum][isMhelp ? ";is_mhelp=1" : ""]'>(CONVERT)</a> :</span> [span][msg]</span>"
if(isMhelp)
//Open a new adminticket and inform the user.
SSmentor_tickets.newTicket(src, prunedmsg, finalised_msg)
for(var/client/X in mentorholders + modholders + adminholders)
if(X.prefs.sound & SOUND_MENTORHELP)
SEND_SOUND(X, 'sound/effects/adminhelp.ogg')
to_chat(X, finalised_msg)
else //Ahelp
//Open a new adminticket and inform the user.
SStickets.newTicket(src, prunedmsg, finalised_msg)
for(var/client/X in modholders + adminholders)
if(X.prefs.sound & SOUND_ADMINHELP)
SEND_SOUND(X, 'sound/effects/adminhelp.ogg')
window_flash(X)
to_chat(X, finalised_msg)
//show it to the person adminhelping too
to_chat(src, "<span class='boldnotice'>[selected_type]</b>: [original_msg]</span>")
to_chat(src, "<span class='boldnotice'>[selected_type]</b>: [msg]</span>")
var/admin_number_present = adminholders.len - admin_number_afk
log_admin("[selected_type]: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins.")
log_admin("[selected_type]: [key_name(src)]: [msg] - heard by [admin_number_present] non-AFK admins.")
if(admin_number_present <= 0)
if(!admin_number_afk)
send2adminirc("[selected_type] from [key_name(src)]: [original_msg] - !!No admins online!!")
send2adminirc("[selected_type] from [key_name(src)]: [msg] - !!No admins online!!")
else
send2adminirc("[selected_type] from [key_name(src)]: [original_msg] - !!All admins AFK ([admin_number_afk])!!")
send2adminirc("[selected_type] from [key_name(src)]: [msg] - !!All admins AFK ([admin_number_afk])!!")
else
send2adminirc("[selected_type] from [key_name(src)]: [original_msg]")
send2adminirc("[selected_type] from [key_name(src)]: [msg]")
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
+4 -4
View File
@@ -2,18 +2,18 @@
set category = "Admin"
set name = "Dsay" //Gave this shit a shorter name so you only have to time out "dsay" rather than "dead say" to use it --NeoFite
set hidden = 1
if(!check_rights(R_ADMIN|R_MOD))
return
if(!src.mob)
return
if(prefs.muted & MUTE_DEADCHAT)
to_chat(src, "<span class='warning'>You cannot send DSAY messages (muted).</span>")
return
if(!(prefs.toggles & CHAT_DEAD))
if(!(prefs.toggles & PREFTOGGLE_CHAT_DEAD))
to_chat(src, "<span class='warning'>You have deadchat muted.</span>")
return
@@ -90,6 +90,7 @@
This facility is sealed shut by order of Commander Marquez. Do not enter.<br>
Terror spiders live here. We believe they are a weapon developed by the syndicate.<br>
Any surviving personnel are to evacuate immediately via the gateway.<br>
Any arriving response team is advised to use the ID Upgrade Machine to obtain local access.<br>
"}
/obj/item/paper/terrorspiders2
@@ -134,10 +135,10 @@
name = "paper - 'Prescription for Jones, David'"
info = {"PRESCRIPTION FOR: David Jones<br>
RANK: Miner<br>
FOR: Haloperidol<br>
REASON FOR TREATMENT: Hallucinations, Paranoia<br>
CAUSE: Hallucinations caused by encounter with toxic spit of spider in the caves. Paranoia caused by disappearing staff and suspicions of syndicate infiltration.<br>
TREATMENT PLAN: Take as needed. See Dr. Phloxi in one week if symptoms persist. <br>
FOR: Charcoal<br>
REASON FOR TREATMENT: Toxins in bloodstream<br>
CAUSE: Bitten by a black terror spider.<br>
TREATMENT PLAN: Take hourly. See Dr. Phloxi if symptoms persist more than three hours.<br>
"}
/obj/item/paper/terrorspiders5
@@ -149,7 +150,7 @@
<p>Green<br>Will lay eggs on dead bodies, breeding more spiders.</p>
<p>Black<br>Even a single bite is enough to kill a humanoid, given time.</p>
<p>White<br>Injects a parasitic agent. Deemed to pose too great an infection risk to study.</p>
<p>Purple<br>Only seen guarding the nest of the Queen to the south. Appear to be territorial, and very dangerous.</p>
<p>Purple<br>Seen guarding key areas and important spiders. Appear to be territorial, and very dangerous.</p>
<p>Prince<br>Held in containment 2. Appears to be a sort of super-warrior. Fast, strong, and thickly armored.</p>
<p>Mother<br>Carries hordes of spiderlings on its back. Held in containment 1. </p>
<p>Queen<br>Unable to contain. Present south of Cargo before contact was lost. Presumed ruler of the local hive.</p>
+2 -2
View File
@@ -398,14 +398,14 @@
check_ip_intel()
send_resources()
if(prefs.toggles & UI_DARKMODE) // activates dark mode if its flagged. -AA07
if(prefs.toggles & PREFTOGGLE_UI_DARKMODE) // activates dark mode if its flagged. -AA07
activate_darkmode()
else
// activate_darkmode() calls the CL update button proc, so we dont want it double called
SSchangelog.UpdatePlayerChangelogButton(src)
if(prefs.toggles & DISABLE_KARMA) // activates if karma is disabled
if(prefs.toggles & PREFTOGGLE_DISABLE_KARMA) // activates if karma is disabled
if(establish_db_connection())
to_chat(src,"<span class='notice'>You have disabled karma gains.") // reminds those who have it disabled
else
+32 -41
View File
@@ -83,20 +83,14 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
var/ooccolor = "#b82e00"
var/list/be_special = list() //Special role selection
var/UI_style = "Midnight"
var/nanoui_fancy = TRUE
var/toggles = TOGGLES_DEFAULT
var/toggles2 = TOGGLES_2_DEFAULT // Created because 1 column has a bitflag limit of 24 (BYOND limitation not MySQL)
var/sound = SOUND_DEFAULT
var/show_ghostitem_attack = TRUE
var/UI_style_color = "#ffffff"
var/UI_style_alpha = 255
var/windowflashing = TRUE
var/clientfps = 0
var/atklog = ATKLOG_ALL
var/fuid // forum userid
var/afk_watch = FALSE // If the player wants to be kept track of by the AFK system
//ghostly preferences
var/ghost_anonsay = 0
//character preferences
var/real_name //our character's name
@@ -190,9 +184,6 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
var/slot_name = ""
var/saved = FALSE // Indicates whether the character comes from the database or not
// Whether or not to use randomized character slots
var/randomslot = 0
// jukebox volume
var/volume = 100
@@ -447,24 +438,24 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
dat += "<h2>General Settings</h2>"
if(user.client.holder)
dat += "<b>Adminhelp sound:</b> <a href='?_src_=prefs;preference=hear_adminhelps'><b>[(sound & SOUND_ADMINHELP)?"On":"Off"]</b></a><br>"
dat += "<b>AFK Cryoing:</b> <a href='?_src_=prefs;preference=afk_watch'>[(afk_watch) ? "Yes" : "No"]</a><br>"
dat += "<b>Ambient Occlusion:</b> <a href='?_src_=prefs;preference=ambientocclusion'><b>[toggles & AMBIENT_OCCLUSION ? "Enabled" : "Disabled"]</b></a><br>"
dat += "<b>Attack Animations:</b> <a href='?_src_=prefs;preference=ghost_att_anim'>[(show_ghostitem_attack) ? "Yes" : "No"]</a><br>"
dat += "<b>AFK Cryoing:</b> <a href='?_src_=prefs;preference=afk_watch'>[(toggles2 & PREFTOGGLE_2_AFKWATCH) ? "Yes" : "No"]</a><br>"
dat += "<b>Ambient Occlusion:</b> <a href='?_src_=prefs;preference=ambientocclusion'><b>[toggles & PREFTOGGLE_AMBIENT_OCCLUSION ? "Enabled" : "Disabled"]</b></a><br>"
dat += "<b>Attack Animations:</b> <a href='?_src_=prefs;preference=ghost_att_anim'>[(toggles2 & PREFTOGGLE_2_ITEMATTACK) ? "Yes" : "No"]</a><br>"
if(unlock_content)
dat += "<b>BYOND Membership Publicity:</b> <a href='?_src_=prefs;preference=publicity'><b>[(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]</b></a><br>"
dat += "<b>BYOND Membership Publicity:</b> <a href='?_src_=prefs;preference=publicity'><b>[(toggles & PREFTOGGLE_MEMBER_PUBLIC) ? "Public" : "Hidden"]</b></a><br>"
dat += "<b>Custom UI settings:</b><br>"
dat += " - <b>Alpha (transparency):</b> <a href='?_src_=prefs;preference=UIalpha'><b>[UI_style_alpha]</b></a><br>"
dat += " - <b>Color:</b> <a href='?_src_=prefs;preference=UIcolor'><b>[UI_style_color]</b></a> <span style='border: 1px solid #161616; background-color: [UI_style_color];'>&nbsp;&nbsp;&nbsp;</span><br>"
dat += " - <b>UI Style:</b> <a href='?_src_=prefs;preference=ui'><b>[UI_style]</b></a><br>"
dat += "<b>Deadchat Anonymity:</b> <a href='?_src_=prefs;preference=ghost_anonsay'><b>[ghost_anonsay ? "Anonymous" : "Not Anonymous"]</b></a><br>"
dat += "<b>Deadchat Anonymity:</b> <a href='?_src_=prefs;preference=ghost_anonsay'><b>[toggles2 & PREFTOGGLE_2_ANONDCHAT ? "Anonymous" : "Not Anonymous"]</b></a><br>"
if(user.client.donator_level > 0)
dat += "<b>Donator Publicity:</b> <a href='?_src_=prefs;preference=donor_public'><b>[(toggles & DONATOR_PUBLIC) ? "Public" : "Hidden"]</b></a><br>"
dat += "<b>Fancy NanoUI:</b> <a href='?_src_=prefs;preference=nanoui'>[(nanoui_fancy) ? "Yes" : "No"]</a><br>"
dat += "<b>Donator Publicity:</b> <a href='?_src_=prefs;preference=donor_public'><b>[(toggles & PREFTOGGLE_DONATOR_PUBLIC) ? "Public" : "Hidden"]</b></a><br>"
dat += "<b>Fancy NanoUI:</b> <a href='?_src_=prefs;preference=nanoui'>[(toggles2 & PREFTOGGLE_2_FANCYUI) ? "Yes" : "No"]</a><br>"
dat += "<b>FPS:</b> <a href='?_src_=prefs;preference=clientfps;task=input'>[clientfps]</a><br>"
dat += "<b>Ghost Ears:</b> <a href='?_src_=prefs;preference=ghost_ears'><b>[(toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]</b></a><br>"
dat += "<b>Ghost Radio:</b> <a href='?_src_=prefs;preference=ghost_radio'><b>[(toggles & CHAT_GHOSTRADIO) ? "All Chatter" : "Nearest Speakers"]</b></a><br>"
dat += "<b>Ghost Sight:</b> <a href='?_src_=prefs;preference=ghost_sight'><b>[(toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]</b></a><br>"
dat += "<b>Ghost PDA:</b> <a href='?_src_=prefs;preference=ghost_pda'><b>[(toggles & CHAT_GHOSTPDA) ? "All PDA Messages" : "No PDA Messages"]</b></a><br>"
dat += "<b>Ghost Ears:</b> <a href='?_src_=prefs;preference=ghost_ears'><b>[(toggles & PREFTOGGLE_CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]</b></a><br>"
dat += "<b>Ghost Radio:</b> <a href='?_src_=prefs;preference=ghost_radio'><b>[(toggles & PREFTOGGLE_CHAT_GHOSTRADIO) ? "All Chatter" : "Nearest Speakers"]</b></a><br>"
dat += "<b>Ghost Sight:</b> <a href='?_src_=prefs;preference=ghost_sight'><b>[(toggles & PREFTOGGLE_CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]</b></a><br>"
dat += "<b>Ghost PDA:</b> <a href='?_src_=prefs;preference=ghost_pda'><b>[(toggles & PREFTOGGLE_CHAT_GHOSTPDA) ? "All PDA Messages" : "No PDA Messages"]</b></a><br>"
if(check_rights(R_ADMIN,0))
dat += "<b>OOC Color:</b> <span style='border: 1px solid #161616; background-color: [ooccolor ? ooccolor : GLOB.normal_ooc_colour];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=ooccolor;task=input'><b>Change</b></a><br>"
if(config.allow_Metadata)
@@ -484,8 +475,8 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
dat += "</a><br>"
dat += "<b>Play Admin MIDIs:</b> <a href='?_src_=prefs;preference=hear_midis'><b>[(sound & SOUND_MIDI) ? "Yes" : "No"]</b></a><br>"
dat += "<b>Play Lobby Music:</b> <a href='?_src_=prefs;preference=lobby_music'><b>[(sound & SOUND_LOBBY) ? "Yes" : "No"]</b></a><br>"
dat += "<b>Randomized Character Slot:</b> <a href='?_src_=prefs;preference=randomslot'><b>[randomslot ? "Yes" : "No"]</b></a><br>"
dat += "<b>Window Flashing:</b> <a href='?_src_=prefs;preference=winflash'>[(windowflashing) ? "Yes" : "No"]</a><br>"
dat += "<b>Randomized Character Slot:</b> <a href='?_src_=prefs;preference=randomslot'><b>[toggles2 & PREFTOGGLE_2_RANDOMSLOT ? "Yes" : "No"]</b></a><br>"
dat += "<b>Window Flashing:</b> <a href='?_src_=prefs;preference=winflash'>[(toggles2 & PREFTOGGLE_2_WINDOWFLASHING) ? "Yes" : "No"]</a><br>"
// RIGHT SIDE OF THE PAGE
dat += "</td><td width='300px' height='300px' valign='top'>"
dat += "<h2>Special Role Settings</h2>"
@@ -1952,11 +1943,11 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
switch(href_list["preference"])
if("publicity")
if(unlock_content)
toggles ^= MEMBER_PUBLIC
toggles ^= PREFTOGGLE_MEMBER_PUBLIC
if("donor_public")
if(user.client.donator_level > 0)
toggles ^= DONATOR_PUBLIC
toggles ^= PREFTOGGLE_DONATOR_PUBLIC
if("gender")
if(!S.has_gender)
@@ -1997,21 +1988,21 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
H.remake_hud()
if("nanoui")
nanoui_fancy = !nanoui_fancy
toggles2 ^= PREFTOGGLE_2_FANCYUI
if("ghost_att_anim")
show_ghostitem_attack = !show_ghostitem_attack
toggles2 ^= PREFTOGGLE_2_ITEMATTACK
if("winflash")
windowflashing = !windowflashing
toggles2 ^= PREFTOGGLE_2_WINDOWFLASHING
if("afk_watch")
if(!afk_watch)
if(!(toggles2 & PREFTOGGLE_2_AFKWATCH))
to_chat(user, "<span class='info'>You will now get put into cryo dorms after [config.auto_cryo_afk] minutes. \
Then after [config.auto_despawn_afk] minutes you will be fully despawned. You will receive a visual and auditory warning before you will be put into cryodorms.</span>")
else
to_chat(user, "<span class='info'>Automatic cryoing turned off.</span>")
afk_watch = !afk_watch
toggles2 ^= PREFTOGGLE_2_AFKWATCH
if("UIcolor")
var/UI_style_color_new = input(user, "Choose your UI color, dark colors are not recommended!", UI_style_color) as color|null
@@ -2040,7 +2031,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
be_random_name = !be_random_name
if("randomslot")
randomslot = !randomslot
toggles2 ^= PREFTOGGLE_2_RANDOMSLOT
if(isnewplayer(usr))
var/mob/new_player/N = usr
N.new_player_panel_proc()
@@ -2056,22 +2047,22 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
user.stop_sound_channel(CHANNEL_LOBBYMUSIC)
if("ghost_ears")
toggles ^= CHAT_GHOSTEARS
toggles ^= PREFTOGGLE_CHAT_GHOSTEARS
if("ghost_sight")
toggles ^= CHAT_GHOSTSIGHT
toggles ^= PREFTOGGLE_CHAT_GHOSTSIGHT
if("ghost_radio")
toggles ^= CHAT_GHOSTRADIO
toggles ^= PREFTOGGLE_CHAT_GHOSTRADIO
if("ghost_radio")
toggles ^= CHAT_GHOSTRADIO
toggles ^= PREFTOGGLE_CHAT_GHOSTRADIO
if("ghost_pda")
toggles ^= CHAT_GHOSTPDA
toggles ^= PREFTOGGLE_CHAT_GHOSTPDA
if("ghost_anonsay")
ghost_anonsay = !ghost_anonsay
toggles2 ^= PREFTOGGLE_2_ANONDCHAT
if("save")
save_preferences(user)
@@ -2110,12 +2101,12 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
if("ambientocclusion")
toggles ^= AMBIENT_OCCLUSION
toggles ^= PREFTOGGLE_AMBIENT_OCCLUSION
if(parent && parent.screen && parent.screen.len)
var/obj/screen/plane_master/game_world/PM = locate(/obj/screen/plane_master/game_world) in parent.screen
PM.filters -= FILTER_AMBIENT_OCCLUSION
if(toggles & AMBIENT_OCCLUSION)
PM.filters += FILTER_AMBIENT_OCCLUSION
PM.remove_filter(AMBIENT_OCCLUSION_FILTER_KEY)
if(toggles & PREFTOGGLE_AMBIENT_OCCLUSION)
PM.add_filter(AMBIENT_OCCLUSION_FILTER_KEY, FILTER_AMBIENT_OCCLUSION)
if("parallax")
var/parallax_styles = list(
@@ -8,19 +8,14 @@
be_role,
default_slot,
toggles,
toggles_2,
sound,
randomslot,
volume,
nanoui_fancy,
show_ghostitem_attack,
lastchangelog,
windowflashing,
ghost_anonsay,
exp,
clientfps,
atklog,
fuid,
afk_watch,
parallax
FROM [format_table_name("player")]
WHERE ckey='[C.ckey]'"}
@@ -42,41 +37,31 @@
be_special = params2list(query.item[5])
default_slot = text2num(query.item[6])
toggles = text2num(query.item[7])
sound = text2num(query.item[8])
randomslot = text2num(query.item[9])
toggles2 = text2num(query.item[8])
sound = text2num(query.item[9])
volume = text2num(query.item[10])
nanoui_fancy = text2num(query.item[11])
show_ghostitem_attack = text2num(query.item[12])
lastchangelog = query.item[13]
windowflashing = text2num(query.item[14])
ghost_anonsay = text2num(query.item[15])
exp = query.item[16]
clientfps = text2num(query.item[17])
atklog = text2num(query.item[18])
fuid = text2num(query.item[19])
afk_watch = text2num(query.item[20])
parallax = text2num(query.item[21])
lastchangelog = query.item[11]
exp = query.item[12]
clientfps = text2num(query.item[13])
atklog = text2num(query.item[14])
fuid = text2num(query.item[15])
parallax = text2num(query.item[16])
//Sanitize
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
UI_style = sanitize_inlist(UI_style, list("White", "Midnight"), initial(UI_style))
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
toggles = sanitize_integer(toggles, 0, TOGGLES_TOTAL, initial(toggles))
toggles2 = sanitize_integer(toggles2, 0, TOGGLES_2_TOTAL, initial(toggles2))
sound = sanitize_integer(sound, 0, 65535, initial(sound))
UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color))
UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha))
randomslot = sanitize_integer(randomslot, 0, 1, initial(randomslot))
volume = sanitize_integer(volume, 0, 100, initial(volume))
nanoui_fancy = sanitize_integer(nanoui_fancy, 0, 1, initial(nanoui_fancy))
show_ghostitem_attack = sanitize_integer(show_ghostitem_attack, 0, 1, initial(show_ghostitem_attack))
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
windowflashing = sanitize_integer(windowflashing, 0, 1, initial(windowflashing))
ghost_anonsay = sanitize_integer(ghost_anonsay, 0, 1, initial(ghost_anonsay))
exp = sanitize_text(exp, initial(exp))
clientfps = sanitize_integer(clientfps, 0, 1000, initial(clientfps))
atklog = sanitize_integer(atklog, 0, 100, initial(atklog))
fuid = sanitize_integer(fuid, 0, 10000000, initial(fuid))
afk_watch = sanitize_integer(afk_watch, 0, 1, initial(afk_watch))
parallax = sanitize_integer(parallax, 0, 16, initial(parallax))
return 1
@@ -97,18 +82,13 @@
be_role='[sanitizeSQL(list2params(be_special))]',
default_slot='[default_slot]',
toggles='[num2text(toggles, CEILING(log(10, (TOGGLES_TOTAL)), 1))]',
toggles_2='[num2text(toggles2, CEILING(log(10, (TOGGLES_2_TOTAL)), 1))]',
atklog='[atklog]',
sound='[sound]',
randomslot='[randomslot]',
volume='[volume]',
nanoui_fancy='[nanoui_fancy]',
show_ghostitem_attack='[show_ghostitem_attack]',
lastchangelog='[lastchangelog]',
windowflashing='[windowflashing]',
ghost_anonsay='[ghost_anonsay]',
clientfps='[clientfps]',
atklog='[atklog]',
afk_watch='[afk_watch]',
parallax='[parallax]'
WHERE ckey='[C.ckey]'"}
)
@@ -3,8 +3,8 @@
set name = "Show/Hide GhostEars"
set category = "Preferences"
set desc = ".Toggle Between seeing all mob speech, and only speech of nearby mobs"
prefs.toggles ^= CHAT_GHOSTEARS
to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].")
prefs.toggles ^= PREFTOGGLE_CHAT_GHOSTEARS
to_chat(src, "As a ghost, you will now [(prefs.toggles & PREFTOGGLE_CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].")
prefs.save_preferences(src)
feedback_add_details("admin_verb","TGE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -12,8 +12,8 @@
set name = "Show/Hide GhostSight"
set category = "Preferences"
set desc = ".Toggle Between seeing all mob emotes, and only emotes of nearby mobs"
prefs.toggles ^= CHAT_GHOSTSIGHT
to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].")
prefs.toggles ^= PREFTOGGLE_CHAT_GHOSTSIGHT
to_chat(src, "As a ghost, you will now [(prefs.toggles & PREFTOGGLE_CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].")
prefs.save_preferences(src)
feedback_add_details("admin_verb","TGS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -21,8 +21,8 @@
set name = "Enable/Disable GhostRadio"
set category = "Preferences"
set desc = ".Toggle between hearing all radio chatter, or only from nearby speakers"
prefs.toggles ^= CHAT_GHOSTRADIO
to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"].")
prefs.toggles ^= PREFTOGGLE_CHAT_GHOSTRADIO
to_chat(src, "As a ghost, you will now [(prefs.toggles & PREFTOGGLE_CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"].")
prefs.save_preferences(src)
feedback_add_details("admin_verb","TGR")
@@ -32,9 +32,9 @@
set desc = "Toggle seeing radiochatter from radios and speakers"
if(!check_rights(R_ADMIN))
return
prefs.toggles ^= CHAT_RADIO
prefs.toggles ^= PREFTOGGLE_CHAT_RADIO
prefs.save_preferences(src)
to_chat(usr, "You will [(prefs.toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from radios or speakers")
to_chat(usr, "You will [(prefs.toggles & PREFTOGGLE_CHAT_RADIO) ? "now" : "no longer"] see radio chatter from radios or speakers")
feedback_add_details("admin_verb","THR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_ai_voice_annoucements()
@@ -72,13 +72,13 @@
set name = "Show/Hide Deadchat"
set category = "Preferences"
set desc ="Toggles seeing deadchat"
prefs.toggles ^= CHAT_DEAD
prefs.toggles ^= PREFTOGGLE_CHAT_DEAD
prefs.save_preferences(src)
if(src.holder)
to_chat(src, "You will [(prefs.toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
else
to_chat(src, "As a ghost, you will [(prefs.toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
to_chat(src, "As a ghost, you will [(prefs.toggles & PREFTOGGLE_CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
feedback_add_details("admin_verb","TDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -86,27 +86,27 @@
set name = "Show/Hide Prayers"
set category = "Preferences"
set desc = "Toggles seeing prayers"
prefs.toggles ^= CHAT_PRAYER
prefs.toggles ^= PREFTOGGLE_CHAT_PRAYER
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
feedback_add_details("admin_verb","TP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/togglescoreboard()
set name = "Hide/Display End Round Scoreboard"
set category = "Preferences"
set desc = "Toggles displaying end of round scoreboard"
prefs.toggles ^= DISABLE_SCOREBOARD
prefs.toggles ^= PREFTOGGLE_DISABLE_SCOREBOARD
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & DISABLE_SCOREBOARD) ? "no longer" : "now"] see the end of round scoreboard.")
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_DISABLE_SCOREBOARD) ? "no longer" : "now"] see the end of round scoreboard.")
feedback_add_details("admin_verb","TScoreboard") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/togglekarmareminder()
set name = "Hide/Display End Round Karma Reminder"
set category = "Preferences"
set desc = "Toggles displaying end of round karma reminder"
prefs.toggles ^= DISABLE_KARMA_REMINDER
prefs.toggles ^= PREFTOGGLE_DISABLE_KARMA_REMINDER
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & DISABLE_KARMA_REMINDER) ? "no longer" : "now"] see the end of round karma reminder.")
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_DISABLE_KARMA_REMINDER) ? "no longer" : "now"] see the end of round karma reminder.")
feedback_add_details("admin_verb","TKarmabugger") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggletitlemusic()
@@ -143,9 +143,9 @@
set name = "Show/Hide OOC"
set category = "Preferences"
set desc = "Toggles seeing OutOfCharacter chat"
prefs.toggles ^= CHAT_OOC
prefs.toggles ^= PREFTOGGLE_CHAT_OOC
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.")
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.")
feedback_add_details("admin_verb","TOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -153,9 +153,9 @@
set name = "Show/Hide LOOC"
set category = "Preferences"
set desc = "Toggles seeing Local OutOfCharacter chat"
prefs.toggles ^= CHAT_LOOC
prefs.toggles ^= PREFTOGGLE_CHAT_LOOC
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel.")
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel.")
feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -236,9 +236,9 @@
set name = "Toggle Darkmode"
set category = "Preferences"
set desc = "Toggles UI style between dark and light"
prefs.toggles ^= UI_DARKMODE
prefs.toggles ^= PREFTOGGLE_UI_DARKMODE
prefs.save_preferences(src)
if(prefs.toggles & UI_DARKMODE)
if(prefs.toggles & PREFTOGGLE_UI_DARKMODE)
activate_darkmode()
else
deactivate_darkmode()
@@ -248,9 +248,9 @@
set name = "Toggle Karma Gains"
set category = "Special Verbs"
set desc = "This button will allow you to stop other people giving you karma."
prefs.toggles ^= DISABLE_KARMA
prefs.toggles ^= PREFTOGGLE_DISABLE_KARMA
prefs.save_preferences(src)
if(prefs.toggles & DISABLE_KARMA)
if(prefs.toggles & PREFTOGGLE_DISABLE_KARMA)
to_chat(usr, "<span class='notice'>You have disabled karma gains.")
else
to_chat(usr, "<span class='notice'>You have enabled karma gains.")
@@ -259,9 +259,9 @@
set name = "Toggle Text Popup Limiter"
set category = "Preferences"
set desc = "Will let you limit the text input popups to one at a time."
prefs.toggles ^= TYPING_ONCE
prefs.toggles ^= PREFTOGGLE_TYPING_ONCE
prefs.save_preferences(src)
if(prefs.toggles & TYPING_ONCE)
if(prefs.toggles & PREFTOGGLE_TYPING_ONCE)
to_chat(usr, "<span class='notice'>You have enabled text popup limiting.")
else
to_chat(usr, "<span class='notice'>You have disabled text popup limiting.")
@@ -271,9 +271,9 @@
set name = "Toggle Numpad targetting"
set category = "Preferences"
set desc = "This button will allow you to enable or disable Numpad Targetting"
prefs.toggles ^= NUMPAD_TARGET
prefs.toggles ^= PREFTOGGLE_NUMPAD_TARGET
prefs.save_preferences(src)
if (prefs.toggles & NUMPAD_TARGET)
if (prefs.toggles & PREFTOGGLE_NUMPAD_TARGET)
to_chat(usr, "<span class='notice'>You have enabled Numpad Targetting.")
else
to_chat(usr, "<span class='notice'>You have disabled Numpad Targetting.")
@@ -283,9 +283,9 @@
set name = "Toggle QWERTY/AZERTY"
set category = "Preferences"
set desc = "This button will switch you between QWERTY and AZERTY control sets"
prefs.toggles ^= AZERTY
prefs.toggles ^= PREFTOGGLE_AZERTY
prefs.save_preferences(src)
if (prefs.toggles & AZERTY)
if (prefs.toggles & PREFTOGGLE_AZERTY)
to_chat(usr, "<span class='notice'>You are now in AZERTY mode.")
else
to_chat(usr, "<span class='notice'>You are now in QWERTY mode.")
@@ -294,8 +294,8 @@
set name = "Show/Hide GhostPDA"
set category = "Preferences"
set desc = ".Toggle seeing PDA messages as an observer."
prefs.toggles ^= CHAT_GHOSTPDA
to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTPDA) ? "see all PDA messages" : "no longer see PDA messages"].")
prefs.toggles ^= PREFTOGGLE_CHAT_GHOSTPDA
to_chat(src, "As a ghost, you will now [(prefs.toggles & PREFTOGGLE_CHAT_GHOSTPDA) ? "see all PDA messages" : "no longer see PDA messages"].")
prefs.save_preferences(src)
feedback_add_details("admin_verb","TGP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+3 -2
View File
@@ -12,7 +12,6 @@
armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/suit.dmi',
"Grey" = 'icons/mob/species/grey/suit.dmi'
)
w_class = WEIGHT_CLASS_NORMAL
@@ -41,6 +40,9 @@
/obj/item/clothing/suit/armor/vest/security
name = "security armor"
desc = "An armored vest that protects against some damage. This one has a clip for a holobadge."
sprite_sheets = list(
"Grey" = 'icons/mob/species/grey/suit.dmi'
)
icon_state = "armor"
item_state = "armor"
var/obj/item/clothing/accessory/holobadge/attached_badge
@@ -51,7 +53,6 @@
add_fingerprint(user)
W.forceMove(src)
attached_badge = W
var/datum/action/A = new /datum/action/item_action/remove_badge(src)
A.Grant(user)
icon_state = "armorsec"
+12 -9
View File
@@ -71,23 +71,26 @@ GLOBAL_VAR_INIT(setup_economy, 0)
var/datum/feed_channel/newChannel = new /datum/feed_channel
newChannel.channel_name = "Public Station Announcements"
newChannel.author = "Automated Announcement Listing"
newChannel.locked = 1
newChannel.is_admin_channel = 1
GLOB.news_network.network_channels += newChannel
newChannel.icon = "bullhorn"
newChannel.frozen = TRUE
newChannel.admin_locked = TRUE
GLOB.news_network.channels += newChannel
newChannel = new /datum/feed_channel
newChannel.channel_name = "Nyx Daily"
newChannel.author = "CentComm Minister of Information"
newChannel.locked = 1
newChannel.is_admin_channel = 1
GLOB.news_network.network_channels += newChannel
newChannel.icon = "meteor"
newChannel.frozen = TRUE
newChannel.admin_locked = TRUE
GLOB.news_network.channels += newChannel
newChannel = new /datum/feed_channel
newChannel.channel_name = "The Gibson Gazette"
newChannel.author = "Editor Mike Hammers"
newChannel.locked = 1
newChannel.is_admin_channel = 1
GLOB.news_network.network_channels += newChannel
newChannel.icon = "star"
newChannel.frozen = TRUE
newChannel.admin_locked = TRUE
GLOB.news_network.channels += newChannel
for(var/loc_type in subtypesof(/datum/trade_destination))
var/datum/trade_destination/D = new loc_type
+5 -7
View File
@@ -58,7 +58,7 @@
//copy-pasted from the admin verbs to submit new newscaster messages
var/datum/feed_message/newMsg = new /datum/feed_message
newMsg.author = "Nyx Daily"
newMsg.is_admin_message = 1
newMsg.admin_locked = TRUE
//see if our location has custom event info for this event
newMsg.body = affected_dest.get_custom_eventstring()
@@ -94,12 +94,10 @@
if(FESTIVAL)
newMsg.body = "A [pick("festival","week long celebration","day of revelry","planet-wide holiday")] has been declared on [affected_dest.name] by [pick("Governor","Commissioner","General","Commandant","Administrator")] [random_name(pick(MALE,FEMALE))] to celebrate [pick("the birth of their [pick("son","daughter")]","coming of age of their [pick("son","daughter")]","the pacification of rogue military cell","the apprehension of a violent criminal who had been terrorising the planet")]. Massive stocks of food and meat have been bought driving up prices across the planet."
for(var/datum/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.channel_name == "Nyx Daily")
FC.messages += newMsg
break
for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters)
NEWSCASTER.newsAlert("Nyx Daily")
GLOB.news_network.get_channel_by_name("Nyx Daily")?.add_message(newMsg)
for(var/nc in GLOB.allNewscasters)
var/obj/machinery/newscaster/NC = nc
NC.alert_news("Nyx Daily")
/datum/event/economic_event/end()
for(var/good_type in dearer_goods)
+9 -13
View File
@@ -14,7 +14,7 @@
//copy-pasted from the admin verbs to submit new newscaster messages
var/datum/feed_message/newMsg = new /datum/feed_message
newMsg.author = "Nyx Daily"
newMsg.is_admin_message = 1
newMsg.admin_locked = TRUE
//see if our location has custom event info for this event
newMsg.body = affected_dest.get_custom_eventstring()
@@ -126,12 +126,10 @@
Nyx Daily is offering discount tickets for two to see [random_name(pick(MALE,FEMALE))] live in return for eyewitness reports and up to the minute coverage."
for(var/datum/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.channel_name == "Nyx Daily")
FC.messages += newMsg
break
for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters)
NEWSCASTER.newsAlert("Nyx Daily")
GLOB.news_network.get_channel_by_name("Nyx Daily")?.add_message(newMsg)
for(var/nc in GLOB.allNewscasters)
var/obj/machinery/newscaster/NC = nc
NC.alert_news("Nyx Daily")
/datum/event/trivial_news
endWhen = 10
@@ -145,9 +143,7 @@
newMsg.body = pick(file2list("config/news/trivial.txt"))
newMsg.body = replacetext(newMsg.body,"{{AFFECTED}}",affected_dest.name)
for(var/datum/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.channel_name == "The Gibson Gazette")
FC.messages += newMsg
break
for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters)
NEWSCASTER.newsAlert("The Gibson Gazette")
GLOB.news_network.get_channel_by_name("The Gibson Gazette")?.add_message(newMsg)
for(var/nc in GLOB.allNewscasters)
var/obj/machinery/newscaster/NC = nc
NC.alert_news("The Gibson Gazette")
+6 -9
View File
@@ -3,7 +3,7 @@
var/highpop_trigger = 80
var/spawncount = 2
var/list/playercount
var/successSpawn = 0 //So we don't make a command report if nothing gets spawned.
var/successSpawn = FALSE //So we don't make a command report if nothing gets spawned.
/datum/event/alien_infestation/setup()
announceWhen = rand(announceWhen, announceWhen + 50)
@@ -11,21 +11,18 @@
/datum/event/alien_infestation/announce()
if(successSpawn)
GLOB.event_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg')
else
log_and_message_admins("Warning: Could not spawn any mobs for event Alien Infestation")
/datum/event/alien_infestation/start()
var/list/vents = list()
var/list/vents = get_valid_vent_spawns(exclude_mobs_nearby = TRUE, exclude_visible_by_mobs = TRUE)
playercount = length(GLOB.clients)//grab playercount when event starts not when game starts
if(playercount >= highpop_trigger) //spawn with 4 if highpop
spawncount = 4
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in SSair.atmos_machinery)
if(is_station_level(temp_vent.loc.z) && !temp_vent.welded)
if(temp_vent.parent.other_atmosmch.len > 50) //Stops Aliens getting stuck in small networks. See: Security, Virology
vents += temp_vent
spawn()
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as an alien?", ROLE_ALIEN, TRUE, source = /mob/living/carbon/alien/larva)
while(spawncount > 0 && vents.len && candidates.len)
while(spawncount && length(vents) && length(candidates))
var/obj/vent = pick_n_take(vents)
var/mob/C = pick_n_take(candidates)
if(C)
@@ -37,4 +34,4 @@
SSticker.mode.xenos += new_xeno.mind
spawncount--
successSpawn = 1
successSpawn = TRUE
+52
View File
@@ -0,0 +1,52 @@
/datum/event/anomaly/anomaly_atmos
startWhen = 30
announceWhen = 3
endWhen = 100
/datum/event/anomaly/anomaly_atmos/announce()
GLOB.event_announcement.Announce("Transformative gas anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert")
/datum/event/anomaly/anomaly_atmos/start()
var/turf/T = pick(get_area_turfs(impact_area))
if(T)
newAnomaly = new /obj/effect/anomaly/atmos(T.loc)
/datum/event/anomaly/anomaly_atmos/tick()
if(!newAnomaly)
kill()
return
if(ISMULTIPLE(activeFor, 5))
newAnomaly.anomalyEffect()
/datum/event/anomaly/anomaly_atmos/end()
if(!newAnomaly || !newAnomaly.loc) //no anomaly or it is in nullspace
return
var/obj/effect/anomaly/atmos/A = newAnomaly
var/gas_type = A.gas_type
var/area/t_area = get_area(A)
for(var/turf/T in t_area)
if(istype(T, /turf/simulated)) //should not occur on unsimulated turfs without admemery
var/turf/simulated/S = T
fill_with_gas(gas_type, S)
explosion(get_turf(newAnomaly), -1, 0, 2) // a small boom so people know something happened.
..()
/**
* Replaces all oxygen and nitrogen on the simulated turf S with the gas type specified in gas, taking N2, N20, CO2 and agent B
*/
/datum/event/anomaly/anomaly_atmos/proc/fill_with_gas(gas, turf/simulated/S)
if(!S.air)//no air to transform
return
var/amount_to_add = S.air.oxygen + S.air.nitrogen
S.air.oxygen = 0
S.air.nitrogen = 0
switch(gas)
if(GAS_N2)
S.air.nitrogen += amount_to_add
if(GAS_N2O)
S.air.sleeping_agent += amount_to_add
if(GAS_CO2)
S.air.carbon_dioxide += amount_to_add
S.update_visuals()
S.air_update_turf()
+9 -7
View File
@@ -1,9 +1,13 @@
/datum/event/blob
announceWhen = 180
endWhen = 240
var/successSpawn = FALSE //So we don't make a command report if nothing gets spawned.
/datum/event/blob/announce()
GLOB.event_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
if(successSpawn)
GLOB.event_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
else
log_and_message_admins("Warning: Could not spawn any mobs for event Blob")
/datum/event/blob/start()
processing = FALSE //so it won't fire again in next tick
@@ -16,12 +20,9 @@
if(!length(candidates))
return kill()
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in GLOB.all_vent_pumps)
if(is_station_level(temp_vent.loc.z) && !temp_vent.welded)
if(length(temp_vent.parent.other_atmosmch) > 50)
vents += temp_vent
var/list/vents = get_valid_vent_spawns(exclude_mobs_nearby = TRUE, exclude_visible_by_mobs = TRUE)
if(!length(vents))
return
var/obj/vent = pick(vents)
var/mob/living/simple_animal/mouse/blobinfected/B = new(vent.loc)
var/mob/M = pick(candidates)
@@ -30,4 +31,5 @@
to_chat(B, "<span class='userdanger'>You are now a mouse, infected with blob spores. Find somewhere isolated... before you burst and become the blob! Use ventcrawl (alt-click on vents) to move around.</span>")
notify_ghosts("Infected Mouse has appeared in [get_area(B)].", source = B)
successSpawn = TRUE
processing = TRUE // Let it naturally end, if it runs successfully
+5 -4
View File
@@ -170,19 +170,20 @@ GLOBAL_LIST_EMPTY(event_last_fired)
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Brand Intelligence", /datum/event/brand_intelligence, 50, list(ASSIGNMENT_ENGINEER = 25), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Dust", /datum/event/dust, 50, list(ASSIGNMENT_ENGINEER = 50)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Dimensional Tear", /datum/event/tear, 0, list(ASSIGNMENT_SECURITY = 35)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Honknomoly", /datum/event/tear/honk, 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Honknomoly", /datum/event/tear/honk, 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vent Clog", /datum/event/vent_clog, 250),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Wormholes", /datum/event/wormholes, 150),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Pyro Anomaly", /datum/event/anomaly/anomaly_pyro, 75, list(ASSIGNMENT_ENGINEER = 60)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Pyro Anomaly", /datum/event/anomaly/anomaly_pyro, 75, list(ASSIGNMENT_ENGINEER = 60)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Atmos Anomaly", /datum/event/anomaly/anomaly_atmos, 75, list(ASSIGNMENT_ENGINEER = 60)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vortex Anomaly", /datum/event/anomaly/anomaly_vortex, 75, list(ASSIGNMENT_ENGINEER = 25)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Bluespace Anomaly", /datum/event/anomaly/anomaly_bluespace, 75, list(ASSIGNMENT_ENGINEER = 25)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Flux Anomaly", /datum/event/anomaly/anomaly_flux, 75, list(ASSIGNMENT_ENGINEER = 50)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gravitational Anomaly", /datum/event/anomaly/anomaly_grav, 200),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Revenant", /datum/event/revenant, 150),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Swarmer Spawn", /datum/event/spawn_swarmer, 150, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/spawn_morph, 40, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/spawn_morph, 40, list(ASSIGNMENT_SECURITY = 10), is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Disease Outbreak", /datum/event/disease_outbreak, 0, list(ASSIGNMENT_MEDICAL = 150), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Headcrabs", /datum/event/headcrabs, 0, list(ASSIGNMENT_SECURITY = 20))
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Headcrabs", /datum/event/headcrabs, 0, list(ASSIGNMENT_SECURITY = 20))
)
/datum/event_container/major
+5 -8
View File
@@ -15,16 +15,13 @@
/datum/event/money_lotto/announce()
var/datum/feed_message/newMsg = new /datum/feed_message
newMsg.author = "Nanotrasen Editor"
newMsg.is_admin_message = 1
newMsg.admin_locked = TRUE
newMsg.body = "Nyx Daily wishes to congratulate <b>[winner_name]</b> for recieving the Nyx Stellar Slam Lottery, and receiving the out of this world sum of [winner_sum] credits!"
if(!deposit_success)
newMsg.body += "<br>Unfortunately, we were unable to verify the account details provided, so we were unable to transfer the money. Send a cheque containing the sum of $500 to ND 'Stellar Slam' office on the Nyx gateway containing updated details, and your winnings'll be re-sent within the month."
for(var/datum/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.channel_name == "Nyx Daily")
FC.messages += newMsg
break
for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters)
NEWSCASTER.newsAlert("Nyx Daily")
GLOB.news_network.get_channel_by_name("Nyx Daily")?.add_message(newMsg)
for(var/nc in GLOB.allNewscasters)
var/obj/machinery/newscaster/NC = nc
NC.alert_news("Nyx Daily")
+9 -11
View File
@@ -3,6 +3,7 @@ GLOBAL_VAR_INIT(sent_spiders_to_station, 0)
/datum/event/spider_infestation
announceWhen = 400
var/spawncount = 1
var/successSpawn = FALSE //So we don't make a command report if nothing gets spawned.
/datum/event/spider_infestation/setup()
announceWhen = rand(announceWhen, announceWhen + 50)
@@ -10,20 +11,17 @@ GLOBAL_VAR_INIT(sent_spiders_to_station, 0)
GLOB.sent_spiders_to_station = 1
/datum/event/spider_infestation/announce()
GLOB.event_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg')
if(successSpawn)
GLOB.event_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg')
else
log_and_message_admins("Warning: Could not spawn any mobs for event Spider Infestation")
/datum/event/spider_infestation/start()
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in SSair.atmos_machinery)
if(is_station_level(temp_vent.loc.z) && !temp_vent.welded)
if(temp_vent.parent.other_atmosmch.len > 50)
vents += temp_vent
while((spawncount >= 1) && vents.len)
var/obj/vent = pick(vents)
var/list/vents = get_valid_vent_spawns(exclude_mobs_nearby = TRUE, exclude_visible_by_mobs = TRUE)
while(spawncount && length(vents))
var/obj/vent = pick_n_take(vents)
var/obj/structure/spider/spiderling/S = new(vent.loc)
if(prob(66))
S.grow_as = /mob/living/simple_animal/hostile/poison/giant_spider/nurse
vents -= vent
spawncount--
successSpawn = TRUE
+11 -32
View File
@@ -3,25 +3,20 @@
/datum/event/spider_terror
announceWhen = 240
var/spawncount = 1
var/successSpawn = FALSE //So we don't make a command report if nothing gets spawned.
/datum/event/spider_terror/setup()
announceWhen = rand(announceWhen, announceWhen + 30)
spawncount = 1
/datum/event/spider_terror/announce()
GLOB.command_announcement.Announce("Confirmed outbreak of level 3 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/effects/siren-spooky.ogg')
if(successSpawn)
GLOB.command_announcement.Announce("Confirmed outbreak of level 3 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/effects/siren-spooky.ogg')
else
log_and_message_admins("Warning: Could not spawn any mobs for event Terror Spiders")
/datum/event/spider_terror/start()
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in GLOB.all_vent_pumps)
if(is_station_level(temp_vent.loc.z) && !temp_vent.welded)
if(!temp_vent.parent)
// Issue happening more often with vents. Log and continue. Delete once solved
log_debug("spider_terror/start(), vent has no parent: [temp_vent], qdeled: [QDELETED(temp_vent)], loc: [temp_vent.loc]")
continue
if(temp_vent.parent.other_atmosmch.len > 50)
vents += temp_vent
var/list/vents = get_valid_vent_spawns(exclude_mobs_nearby = TRUE, exclude_visible_by_mobs = TRUE)
var/spider_type
var/infestation_type
if((length(GLOB.clients)) < TS_HIGHPOP_TRIGGER)
@@ -49,27 +44,11 @@
// Strongest, only used during highpop.
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/queen
spawncount = 1
while(spawncount >= 1 && vents.len)
var/obj/machinery/atmospherics/unary/vent_pump/vent = pick(vents)
if(vent.welded)
vents -= vent
continue
// If the vent we picked has any living mob nearby, just remove it from the list, loop again, and pick something else.
var/turf/T = get_turf(vent)
var/hostiles_present = FALSE
for(var/mob/living/L in viewers(T))
if(L.stat != DEAD)
hostiles_present = TRUE
break
vents -= vent
if(!hostiles_present)
new spider_type(vent.loc)
spawncount--
while(spawncount && length(vents))
var/obj/vent = pick_n_take(vents)
new spider_type(vent.loc)
spawncount--
successSpawn = TRUE
#undef TS_HIGHPOP_TRIGGER
@@ -226,7 +226,7 @@
desc = "Made in Space Switzerland."
icon_state = "hot_coco"
item_state = "coffee"
list_reagents = list("chocolate" = 30)
list_reagents = list("hot_coco" = 15, "chocolate" = 6, "water" = 9)
resistance_flags = FREEZE_PROOF
/obj/item/reagent_containers/food/drinks/weightloss
@@ -370,6 +370,7 @@
var/extra_reagent = null
filling_color = "#D2691E"
var/randomized_sprinkles = 1
var/donut_sprite_type = "regular"
tastes = list("donut" = 1)
/obj/item/reagent_containers/food/snacks/donut/New()
@@ -378,6 +379,7 @@
icon_state = "donut2"
name = "frosted donut"
reagents.add_reagent("sprinkles", 2)
donut_sprite_type = "frosted"
filling_color = "#FF69B4"
/obj/item/reagent_containers/food/snacks/donut/sprinkles
@@ -385,6 +387,7 @@
icon_state = "donut2"
list_reagents = list("nutriment" = 3, "sugar" = 2, "sprinkles" = 2)
filling_color = "#FF69B4"
donut_sprite_type = "frosted"
randomized_sprinkles = 0
/obj/item/reagent_containers/food/snacks/donut/chaos
@@ -408,6 +411,7 @@
desc = "You jelly?"
icon_state = "jdonut1"
extra_reagent = "berryjuice"
donut_sprite_type = "jelly"
tastes = list("jelly" = 1, "donut" = 3)
/obj/item/reagent_containers/food/snacks/donut/jelly/New()
@@ -417,6 +421,7 @@
if(prob(30))
icon_state = "jdonut2"
name = "frosted jelly Donut"
donut_sprite_type = "frostedjelly"
reagents.add_reagent("sprinkles", 2)
filling_color = "#FF69B4"
@@ -65,6 +65,7 @@
name = "sweet & sour chicken balls"
desc = "Is this chicken cooked? The odds are better than wok paper scissors."
icon_state = "chickenball"
item_state = "chinese3"
junkiness = 25
list_reagents = list("nutriment" = 2, "msg" = 4, "sugar" = 2)
tastes = list("chicken" = 1, "sweetness" = 1)
@@ -89,6 +90,7 @@
name = "fried rice"
desc = "A timeless classic."
icon_state = "chinese4"
item_state = "chinese2"
junkiness = 20
list_reagents = list("nutriment" = 1, "rice" = 3, "msg" = 4, "sugar" = 2)
tastes = list("rice" = 1)
+1 -1
View File
@@ -323,7 +323,7 @@
else
I = image(icon = myseed.growing_icon, icon_state = myseed.icon_harvest)
else
var/t_growthstate = min(round((age / myseed.maturation) * myseed.growthstages), myseed.growthstages)
var/t_growthstate = clamp(round((age / myseed.maturation) * myseed.growthstages), 1, myseed.growthstages)
I = image(icon = myseed.growing_icon, icon_state = "[myseed.icon_grow][t_growthstate]")
I.layer = OBJ_LAYER + 0.01
overlays += I
+1 -1
View File
@@ -85,7 +85,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
log_game("Illegal karma spending attempt detected from [key] to [M.key]. Using the same IP!")
to_chat(src, "<span class='warning'>You can't spend karma on someone connected from the same IP.</span>")
return FALSE
if(M.get_preference(DISABLE_KARMA))
if(M.get_preference(PREFTOGGLE_DISABLE_KARMA))
to_chat(src, "<span class='warning'>That player has turned off incoming karma.")
return FALSE
return TRUE
+1 -1
View File
@@ -5,7 +5,7 @@
if(!user.keys_held["Ctrl"])
var/movement_dir = NONE
var/list/movement = SSinput.movement_keys
if(user.prefs.toggles & AZERTY)
if(user.prefs.toggles & PREFTOGGLE_AZERTY)
movement = SSinput.alt_movement_keys
for(var/_key in user.keys_held)
movement_dir = movement_dir | movement[_key]
+2 -2
View File
@@ -44,7 +44,7 @@
current_key_address = ((current_key_address + 1) % HELD_KEY_BUFFER_LENGTH)
var/movement = SSinput.movement_keys[_key]
if (prefs.toggles & AZERTY) movement = SSinput.alt_movement_keys[_key]
if (prefs.toggles & PREFTOGGLE_AZERTY) movement = SSinput.alt_movement_keys[_key]
if(!(next_move_dir_sub & movement) && !keys_held["Ctrl"])
next_move_dir_add |= movement
@@ -85,7 +85,7 @@
keys_held[i] = null
break
var/movement = SSinput.movement_keys[_key]
if (prefs.toggles & AZERTY) movement = SSinput.alt_movement_keys[_key]
if (prefs.toggles & PREFTOGGLE_AZERTY) movement = SSinput.alt_movement_keys[_key]
if(!(next_move_dir_add & movement))
next_move_dir_sub |= movement
+3 -3
View File
@@ -3,7 +3,7 @@
// Or we can have NPC's send actual keypresses and detect that by seeing no client
/mob/key_down(_key, client/user)
if(user.prefs.toggles & AZERTY)
if(user.prefs.toggles & PREFTOGGLE_AZERTY)
switch(_key)
if("Delete")
if(!pulling)
@@ -70,7 +70,7 @@
toggle_move_intent()
return
//Bodypart selections
if(client.prefs.toggles & NUMPAD_TARGET)
if(client.prefs.toggles & PREFTOGGLE_NUMPAD_TARGET)
switch(_key)
if("Numpad8")
user.body_toggle_head()
@@ -107,7 +107,7 @@
if("Numpad4")
a_intent_change("harm")
return
if(client.keys_held["Ctrl"] && client.prefs.toggles & AZERTY)
if(client.keys_held["Ctrl"] && client.prefs.toggles & PREFTOGGLE_AZERTY)
switch(SSinput.alt_movement_keys[_key])
if(NORTH)
northface()
+2 -2
View File
@@ -10,9 +10,9 @@
cycle_modules()
return
if("Q")
if(!(client.prefs.toggles & AZERTY))
if(!(client.prefs.toggles & PREFTOGGLE_AZERTY))
on_drop_hotkey_press() // User is in QWERTY hotkey mode.
if("A")
if(client.prefs.toggles & AZERTY)
if(client.prefs.toggles & PREFTOGGLE_AZERTY)
on_drop_hotkey_press()
return ..()
@@ -11,6 +11,7 @@
throw_range = 5
origin_tech = "bluespace=2"
slot_flags = SLOT_BELT
var/emagged = FALSE
/obj/item/wormhole_jaunter/attack_self(mob/user)
user.visible_message("<span class='notice'>[user.name] activates the [name]!</span>")
@@ -43,6 +44,7 @@
return
var/chosen_beacon = pick(L)
var/obj/effect/portal/jaunt_tunnel/J = new(get_turf(src), get_turf(chosen_beacon), src, 100)
J.emagged = emagged
if(adjacent)
try_move_adjacent(J)
else
@@ -57,12 +59,26 @@
else
to_chat(user, "[src] is not attached to your belt, preventing it from saving you from the chasm. RIP.</span>")
/obj/item/wormhole_jaunter/emag_act(mob/user)
if(!emagged)
emagged = TRUE
to_chat(user, "<span class='notice'>You emag [src].</span>")
var/turf/T = get_turf(src)
do_sparks(5, 0, T)
playsound(T, "sparks", 50, 1)
/obj/effect/portal/jaunt_tunnel
name = "jaunt tunnel"
icon = 'icons/effects/effects.dmi'
icon_state = "bhole3"
desc = "A stable hole in the universe made by a wormhole jaunter. Turbulent doesn't even begin to describe how rough passage through one of these is, but at least it will always get you somewhere near a beacon."
failchance = 0
var/emagged = FALSE
/obj/effect/portal/jaunt_tunnel/can_teleport(atom/movable/M)
if(!emagged && ismegafauna(M))
return FALSE
return ..()
/obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M)
. = ..()
@@ -120,13 +120,18 @@
return
var/mob/living/carbon/human/H = user
var/random = rand(1,2)
var/random = rand(1,3)
switch(random)
if(1)
to_chat(user, "<span class='danger'>Your flesh begins to melt! Miraculously, you seem fine otherwise.</span>")
H.set_species(/datum/species/skeleton)
if(2)
to_chat(user, "<span class='danger'>Power courses through you! You can now shift your form at will.")
if(user.mind)
var/obj/effect/proc_holder/spell/targeted/shapeshift/dragon/D = new
user.mind.AddSpell(D)
if(3)
to_chat(user, "<span class='danger'>You feel like you could walk straight through lava now.</span>")
H.weather_immunities |= "lava"
@@ -393,7 +393,8 @@
activation_method = "touch"
cooldown_add = 50
activation_sound = 'sound/magic/timeparadox2.ogg'
var/list/banned_items_typecache = list(/obj/item/storage, /obj/item/implant, /obj/item/implanter, /obj/item/disk/nuclear, /obj/item/projectile, /obj/item/spellbook)
var/list/banned_items_typecache = list(/obj/item/storage, /obj/item/implant, /obj/item/implanter, /obj/item/disk/nuclear,
/obj/item/projectile, /obj/item/spellbook, /obj/item/clothing/mask/facehugger)
/obj/machinery/anomalous_crystal/refresher/New()
..()
+2 -23
View File
@@ -254,7 +254,7 @@
new /obj/item/extinguisher/mini(drop_location)
new /obj/item/twohanded/kinetic_crusher(drop_location)
if("Mining Conscription Kit")
new /obj/item/storage/backpack/duffel/mining_conscript/full(drop_location)
new /obj/item/storage/backpack/duffel/mining_conscript(drop_location)
qdel(voucher)
@@ -343,27 +343,6 @@
. = ..()
. += "There's [points] points on the card."
/**********************Conscription Kit**********************/
/obj/item/card/id/mining_access_card
name = "mining access card"
desc = "A small card, that when used on any ID, will add mining access."
icon_state = "data"
/obj/item/card/id/mining_access_card/afterattack(atom/movable/AM, mob/user, proximity)
. = ..()
if(istype(AM, /obj/item/card/id) && proximity)
var/obj/item/card/id/I = AM
I.access |= list(ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_CARGO)
to_chat(user, "You upgrade [I] with mining access.")
qdel(src)
/obj/item/storage/backpack/duffel/mining_conscript/full
name = "mining conscription kit"
desc = "A kit containing everything a crewmember needs to support a shaft miner in the field."
/obj/item/storage/backpack/duffel/mining_conscript/full/New()
..()
new /obj/item/card/id/mining_access_card(src)
#undef EQUIPMENT
+3 -3
View File
@@ -576,7 +576,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/dat
dat += "<h4>Crew Manifest</h4>"
dat += GLOB.data_core.get_manifest()
dat += GLOB.data_core.get_manifest(OOC = TRUE)
src << browse(dat, "window=manifest;size=370x420;can_close=1")
@@ -647,8 +647,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set name = "Toggle Anonymous Dead-chat"
set category = "Ghost"
set desc = "Toggles showing your key in dead chat."
client.prefs.ghost_anonsay = !client.prefs.ghost_anonsay
to_chat(src, "As a ghost, your key will [(client.prefs.ghost_anonsay) ? "no longer" : "now"] be shown when you speak in dead chat.</span>")
client.prefs.toggles2 ^= PREFTOGGLE_2_ANONDCHAT
to_chat(src, "As a ghost, your key will [(client.prefs.toggles2 & PREFTOGGLE_2_ANONDCHAT) ? "no longer" : "now"] be shown when you speak in dead chat.</span>")
client.prefs.save_preferences(src)
/mob/dead/observer/verb/toggle_ghostsee()
+4 -4
View File
@@ -72,7 +72,7 @@
if(findtext(message, " snores.")) //Because we have so many sleeping people.
break
if(isobserver(M) && M.get_preference(CHAT_GHOSTSIGHT) && !(M in viewers(src, null)) && client) // The client check makes sure people with ghost sight don't get spammed by simple mobs emoting.
if(isobserver(M) && M.get_preference(PREFTOGGLE_CHAT_GHOSTSIGHT) && !(M in viewers(src, null)) && client) // The client check makes sure people with ghost sight don't get spammed by simple mobs emoting.
M.show_message(message)
// Type 1 (Visual) emotes are sent to anyone in view of the item
@@ -111,7 +111,7 @@
to_chat(src, "<span class='warning'>You cannot send deadchat emotes (muted).</span>")
return
if(!(client.prefs.toggles & CHAT_DEAD))
if(!(client.prefs.toggles & PREFTOGGLE_CHAT_DEAD))
to_chat(src, "<span class='warning'>You have deadchat muted.</span>")
return
@@ -138,8 +138,8 @@
if(isnewplayer(M))
continue
if(check_rights(R_ADMIN|R_MOD, 0, M) && M.get_preference(CHAT_DEAD)) // Show the emote to admins/mods
if(check_rights(R_ADMIN|R_MOD, 0, M) && M.get_preference(PREFTOGGLE_CHAT_DEAD)) // Show the emote to admins/mods
to_chat(M, message)
else if(M.stat == DEAD && M.get_preference(CHAT_DEAD)) // Show the emote to regular ghosts with deadchat toggled on
else if(M.stat == DEAD && M.get_preference(PREFTOGGLE_CHAT_DEAD)) // Show the emote to regular ghosts with deadchat toggled on
M.show_message(message, 2)
+2 -2
View File
@@ -51,7 +51,7 @@
if(!client)
return 0
if(isobserver(src) && client.prefs.toggles & CHAT_GHOSTEARS)
if(isobserver(src) && client.prefs.toggles & PREFTOGGLE_CHAT_GHOSTEARS)
if(speaker && !speaker.client && !(speaker in view(src)))
//Does the speaker have a client? It's either random stuff that observers won't care about (Experiment 97B says, 'EHEHEHEHEHEHEHE')
//Or someone snoring. So we make it where they won't hear it.
@@ -90,7 +90,7 @@
if(speaker_name != speaker.real_name && speaker.real_name)
speaker_name = "[speaker.real_name] ([speaker_name])"
track = "([ghost_follow_link(speaker, ghost=src)]) "
if(client.prefs.toggles & CHAT_GHOSTEARS && (speaker in view(src)))
if(client.prefs.toggles & PREFTOGGLE_CHAT_GHOSTEARS && (speaker in view(src)))
message = "<b>[message]</b>"
if(!can_hear())
@@ -23,6 +23,9 @@
// Needed to fix a rather insane bug when a posibrain/robotic brain commits suicide
var/dead_icon = "mmi_dead"
/// Time at which the ghost belonging to the mind in the mmi can be pinged again to be borged
var/next_possible_ghost_ping
/obj/item/mmi/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
if(istype(O, /obj/item/organ/internal/brain/crystal))
to_chat(user, "<span class='warning'> This brain is too malformed to be able to use with the [src].</span>")
@@ -986,7 +986,7 @@
if(isnewplayer(M))
continue
if(isobserver(M) && M.get_preference(CHAT_GHOSTSIGHT) && !(M in viewers(src, null)) && client) // The client check makes sure people with ghost sight don't get spammed by simple mobs emoting.
if(isobserver(M) && M.get_preference(PREFTOGGLE_CHAT_GHOSTSIGHT) && !(M in viewers(src, null)) && client) // The client check makes sure people with ghost sight don't get spammed by simple mobs emoting.
M.show_message(message)
switch(m_type)
@@ -218,37 +218,38 @@
////////////////
// MOVE SPEED //
////////////////
#define ADD_SLOWDOWN(__value) if(!ignoreslow || __value < 0) . += __value
/datum/species/proc/movement_delay(mob/living/carbon/human/H)
. = 0 //We start at 0.
var/flight = 0 //Check for flight and flying items
var/ignoreslow = 0
var/gravity = 0
if(H.flying)
flight = 1
if((H.status_flags & IGNORESLOWDOWN) || (RUN in H.mutations))
ignoreslow = 1
if(H.status_flags & IGNORE_SPEED_CHANGES)
return .
if(has_gravity(H))
gravity = 1
if(H.status_flags & GOTTAGOFAST)
. -= 1
if(!ignoreslow && gravity)
if(speed_mod)
. = speed_mod
var/ignoreslow = FALSE
if((H.status_flags & IGNORESLOWDOWN) || (RUN in H.mutations))
ignoreslow = TRUE
var/flight = H.flying //Check for flight and flying items
ADD_SLOWDOWN(speed_mod)
if(H.wear_suit)
. += H.wear_suit.slowdown
if(!H.buckled)
if(H.shoes)
. += H.shoes.slowdown
ADD_SLOWDOWN(H.wear_suit.slowdown)
if(!H.buckled && H.shoes)
ADD_SLOWDOWN(H.shoes.slowdown)
if(H.back)
. += H.back.slowdown
ADD_SLOWDOWN(H.back.slowdown)
if(H.l_hand && (H.l_hand.flags & HANDSLOW))
. += H.l_hand.slowdown
ADD_SLOWDOWN(H.l_hand.slowdown)
if(H.r_hand && (H.r_hand.flags & HANDSLOW))
. += H.r_hand.slowdown
ADD_SLOWDOWN(H.r_hand.slowdown)
if(ignoreslow)
return . // Only malusses after here
var/health_deficiency = max(H.maxHealth - H.health, H.staminaloss)
var/hungry = (500 - H.nutrition)/5 // So overeat would be 100 and default level would be 80
@@ -270,10 +271,10 @@
if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT)
. += (BODYTEMP_COLD_DAMAGE_LIMIT - H.bodytemperature) / COLD_SLOWDOWN_FACTOR
if(H.status_flags & GOTTAGOFAST)
. -= 1
return .
#undef ADD_SLOWDOWN
/datum/species/proc/on_species_gain(mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment.
for(var/slot_id in no_equip)
var/obj/item/thing = H.get_item_by_slot(slot_id)
+3 -3
View File
@@ -251,7 +251,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key)
continue
if(isobserver(M))
if(M.get_preference(CHAT_GHOSTEARS) && client) // The client check is so that ghosts don't have to listen to mice.
if(M.get_preference(PREFTOGGLE_CHAT_GHOSTEARS) && client) // The client check is so that ghosts don't have to listen to mice.
listening |= M
continue
@@ -311,7 +311,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key)
if(isnewplayer(M))
continue
if(isobserver(M) && M.get_preference(CHAT_GHOSTSIGHT) && !(M in viewers(src, null)) && client) // The client check makes sure people with ghost sight don't get spammed by simple mobs emoting.
if(isobserver(M) && M.get_preference(PREFTOGGLE_CHAT_GHOSTSIGHT) && !(M in viewers(src, null)) && client) // The client check makes sure people with ghost sight don't get spammed by simple mobs emoting.
M.show_message(message)
switch(type)
@@ -418,7 +418,7 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key)
continue
if(isobserver(M))
if(M.get_preference(CHAT_GHOSTEARS)) // The client check is so that ghosts don't have to listen to mice.
if(M.get_preference(PREFTOGGLE_CHAT_GHOSTEARS)) // The client check is so that ghosts don't have to listen to mice.
listening |= M
continue
@@ -47,6 +47,13 @@
if(C.can_inject(null, FALSE, inject_target, FALSE))
C.reagents.add_reagent("spidertoxin", venom_per_bite)
/mob/living/simple_animal/hostile/poison/giant_spider/get_spacemove_backup()
. = ..()
// If we don't find any normal thing to use, attempt to use any nearby spider structure instead.
if(!.)
for(var/obj/structure/spider/S in range(1, get_turf(src)))
return S
//nursemaids - these create webs and eggs
/mob/living/simple_animal/hostile/poison/giant_spider/nurse
desc = "Furry and black, it makes you shudder to look at it. This one has brilliant green eyes."
@@ -391,6 +391,13 @@ GLOBAL_LIST_EMPTY(ts_spiderling_list)
return TRUE
/mob/living/simple_animal/hostile/poison/terror_spider/get_spacemove_backup()
. = ..()
// If we don't find any normal thing to use, attempt to use any nearby spider structure instead.
if(!.)
for(var/obj/structure/spider/S in range(1, get_turf(src)))
return S
/mob/living/simple_animal/hostile/poison/terror_spider/Stat()
..()
// Determines what shows in the "Status" tab for player-controlled spiders. Used to help players understand spider health regeneration mechanics.
+18 -2
View File
@@ -10,10 +10,10 @@
/mob/living/update_blurry_effects()
if(eyes_blurred())
overlay_fullscreen("blurry", /obj/screen/fullscreen/blurry)
add_eyeblur()
return 1
else
clear_fullscreen("blurry")
remove_eyeblur()
return 0
/mob/living/update_druggy_effects()
@@ -133,3 +133,19 @@
updatehealth("var edit")
if("resize")
update_transform()
/mob/proc/add_eyeblur()
if(client?.screen)
var/obj/screen/plane_master/game_world/GW = locate(/obj/screen/plane_master/game_world) in client.screen
var/obj/screen/plane_master/floor/F = locate(/obj/screen/plane_master/floor) in client.screen
GW.add_filter(EYE_BLUR_FILTER_KEY, FILTER_EYE_BLUR)
F.add_filter(EYE_BLUR_FILTER_KEY, FILTER_EYE_BLUR)
animate(GW.filters[GW.filters.len], size = 3, time = 5)
animate(F.filters[F.filters.len], size = 3, time = 5)
/mob/proc/remove_eyeblur()
if(client?.screen)
var/obj/screen/plane_master/game_world/GW = locate(/obj/screen/plane_master/game_world) in client.screen
var/obj/screen/plane_master/floor/F = locate(/obj/screen/plane_master/floor) in client.screen
GW.remove_filter(EYE_BLUR_FILTER_KEY)
F.remove_filter(EYE_BLUR_FILTER_KEY)
+6 -13
View File
@@ -1133,21 +1133,14 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
return
//find a viable mouse candidate
var/mob/living/simple_animal/mouse/host
var/obj/machinery/atmospherics/unary/vent_pump/vent_found
var/list/found_vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/v in SSair.atmos_machinery)
if(!v.welded && v.z == src.z)
found_vents.Add(v)
if(found_vents.len)
vent_found = pick(found_vents)
host = new /mob/living/simple_animal/mouse(vent_found.loc)
else
to_chat(src, "<span class='warning'>Unable to find any unwelded vents to spawn mice at.</span>")
if(host)
var/list/found_vents = get_valid_vent_spawns(min_network_size = 0, station_levels_only = FALSE, z_level = z)
if(length(found_vents))
var/obj/vent_found = pick(found_vents)
var/mob/living/simple_animal/mouse/host = new(vent_found.loc)
host.ckey = src.ckey
to_chat(host, "<span class='info'>You are now a mouse. Try to avoid interaction with players, and do not give hints away that you are more than a simple rodent.</span>")
else
to_chat(src, "<span class='warning'>Unable to find any unwelded vents to spawn mice at.</span>")
/mob/proc/assess_threat() //For sec bot threat assessment
return 5
+3 -3
View File
@@ -459,7 +459,7 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM
name = realname
for(var/mob/M in GLOB.player_list)
if(M.client && ((!isnewplayer(M) && M.stat == DEAD) || check_rights(R_ADMIN|R_MOD,0,M)) && M.get_preference(CHAT_DEAD))
if(M.client && ((!isnewplayer(M) && M.stat == DEAD) || check_rights(R_ADMIN|R_MOD,0,M)) && M.get_preference(PREFTOGGLE_CHAT_DEAD))
var/follow
var/lname
if(subject)
@@ -471,9 +471,9 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM
if(istype(subject, /mob/dead/observer))
DM = subject
if(check_rights(R_ADMIN|R_MOD,0,M)) // What admins see
lname = "[keyname][(DM && DM.client && DM.client.prefs.ghost_anonsay) ? "*" : (DM ? "" : "^")] ([name])"
lname = "[keyname][(DM && DM.client && DM.client.prefs.toggles2 & PREFTOGGLE_2_ANONDCHAT) ? "*" : (DM ? "" : "^")] ([name])"
else
if(DM && DM.client && DM.client.prefs.ghost_anonsay) // If the person is actually observer they have the option to be anonymous
if(DM && DM.client && DM.client.prefs.toggles2 & PREFTOGGLE_2_ANONDCHAT) // If the person is actually observer they have the option to be anonymous
lname = "Ghost of [name]"
else if(DM) // Non-anons
lname = "[keyname] ([name])"
+2 -2
View File
@@ -60,7 +60,7 @@
/mob/new_player/proc/new_player_panel_proc()
var/real_name = client.prefs.real_name
if(client.prefs.randomslot)
if(client.prefs.toggles2 & PREFTOGGLE_2_RANDOMSLOT)
real_name = "Random Character Slot"
var/output = "<center><p><a href='byond://?src=[UID()];show_preferences=1'>Setup Character</A><br /><i>[real_name]</i></p>"
@@ -250,7 +250,7 @@
to_chat(usr, "<span class='notice'>There is an administrative lock on entering the game!</span>")
return
if(client.prefs.randomslot)
if(client.prefs.toggles2 & PREFTOGGLE_2_RANDOMSLOT)
client.prefs.load_random_character_slot(client)
if(client.prefs.species in GLOB.whitelisted_species)
+1 -1
View File
@@ -55,7 +55,7 @@
to_chat(src, "<span class='warning'>You cannot talk in deadchat (muted).</span>")
return
if(!(client.prefs.toggles & CHAT_DEAD))
if(!(client.prefs.toggles & PREFTOGGLE_CHAT_DEAD))
to_chat(src, "<span class='danger'>You have deadchat muted.</span>")
return
+5 -5
View File
@@ -21,7 +21,7 @@ GLOBAL_LIST_EMPTY(typing_indicator)
return
if(client)
if((client.prefs.toggles & SHOW_TYPING) || stat != CONSCIOUS || is_muzzled())
if((client.prefs.toggles & PREFTOGGLE_SHOW_TYPING) || stat != CONSCIOUS || is_muzzled())
overlays -= GLOB.typing_indicator[bubble_icon]
else
if(state)
@@ -61,7 +61,7 @@ GLOBAL_LIST_EMPTY(typing_indicator)
/mob/proc/handle_typing_indicator()
if(client)
if(!(client.prefs.toggles & SHOW_TYPING) && !hud_typing)
if(!(client.prefs.toggles & PREFTOGGLE_SHOW_TYPING) && !hud_typing)
var/temp = winget(client, "input", "text")
if(temp != last_typed)
@@ -83,12 +83,12 @@ GLOBAL_LIST_EMPTY(typing_indicator)
set name = "Show/Hide Typing Indicator"
set category = "Preferences"
set desc = "Toggles showing an indicator when you are typing emote or say message."
prefs.toggles ^= SHOW_TYPING
prefs.toggles ^= PREFTOGGLE_SHOW_TYPING
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & SHOW_TYPING) ? "no longer" : "now"] display a typing indicator.")
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_SHOW_TYPING) ? "no longer" : "now"] display a typing indicator.")
// Clear out any existing typing indicator.
if(prefs.toggles & SHOW_TYPING)
if(prefs.toggles & PREFTOGGLE_SHOW_TYPING)
if(istype(mob)) mob.set_typing_indicator(0)
feedback_add_details("admin_verb","TID") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+2 -2
View File
@@ -186,7 +186,7 @@ nanoui is used to open and update nano browser uis
"mapZLevel" = map_z_level,
"user" = list(
"name" = user.name,
"fancy" = user.client.prefs.nanoui_fancy
"fancy" = user.client.prefs.toggles2 & PREFTOGGLE_2_FANCYUI
),
"window" = list(
"width" = width,
@@ -418,7 +418,7 @@ nanoui is used to open and update nano browser uis
// Preset the can_rezie and titlebar values on uis if the user has fancy uis set
// Prevents the ui from flickering when opened
if(user.client.prefs.nanoui_fancy)
if(user.client.prefs.toggles2 & PREFTOGGLE_2_FANCYUI)
set_window_options("focus=0;can_close=1;can_minimize=1;can_maximize=0;can_resize=0;titlebar=0;")
user << browse(get_html(), "window=[window_id];[window_size][window_options]")
+186
View File
@@ -0,0 +1,186 @@
/**
* # Feed Network
*
* Singleton that contains all informations related to newscasters (channels, stories).
*/
/datum/feed_network
/// Contains all of the feed channels created during the round.
var/list/datum/feed_channel/channels = list()
/// Contains all of the feed stories created during the round.
var/list/datum/feed_message/stories = list()
/// The current wanted issue.
var/datum/feed_message/wanted_issue
/**
* Returns the [/datum/feed_channel] with the given name, or null if not found.
*
* Arguments:
* * name - The name
*/
/datum/feed_network/proc/get_channel_by_name(name)
RETURN_TYPE(/datum/feed_channel)
for(var/fc in channels)
var/datum/feed_channel/FC = fc
if(FC.channel_name == name)
return FC
/**
* Returns the [/datum/feed_channel] with the given author, or null if not found.
*
* Arguments:
* * author - The author
*/
/datum/feed_network/proc/get_channel_by_author(author)
RETURN_TYPE(/datum/feed_channel)
for(var/fc in channels)
var/datum/feed_channel/FC = fc
if(FC.author == author)
return FC
/**
* Returns the [/datum/feed_channel] at the given index, or null if not found.
*
* Arguments:
* * idx - The index
*/
/datum/feed_network/proc/get_channel_by_idx(idx)
RETURN_TYPE(/datum/feed_channel)
if(!ISINDEXSAFE(channels, idx))
return
return channels[idx]
/**
* # Feed Message
*
* Describes a single feed story. Always owned by a [/datum/feed_channel].
*/
/datum/feed_message
/// The author of the story.
var/author = ""
/// The title of the story.
var/title = ""
/// The textual contents of the story.
var/body = ""
/// The story's icon.
var/icon/img = null
/// Flags that dictate the story should be censored.
var/censor_flags = 0
/// Whether the story is admin-locked.
var/admin_locked = FALSE
/// The number of views the story has.
var/view_count = 0
/// The world.time at which the story was published.
var/publish_time = 0
/datum/feed_message/New()
publish_time = world.time
/**
* Clears the story's information.
*
* Does not delete it from the owning channel.
*/
/datum/feed_message/proc/clear()
author = ""
title = ""
body = ""
img = null
censor_flags = 0
admin_locked = 0
view_count = 0
publish_time = 0
/**
* # Feed Channel
*
* Describes a single feed channel. Owns a list of [/datum/feed_message].
*/
/datum/feed_channel
/// The name of the channel.
var/channel_name = ""
/// The author of the channel.
var/author = ""
/// The description of the channel.
var/description = ""
/// The channel's icon.
var/icon = "newspaper"
/// The fallback author name to display if the channel is censored.
var/backup_author = ""
/// Lazy list. Contains all [/datum/feed_message] pertaining to the channel.
var/list/datum/feed_message/messages
/// Whether the channel is public or not.
var/is_public = FALSE
/// Whether the channel is frozen or not.
var/frozen = FALSE
/// Whether the channel is censored or not.
var/censored = FALSE
/// Whether the channel is admin-locked.
var/admin_locked = FALSE
/datum/feed_channel/Destroy()
for(var/m in messages)
GLOB.news_network.stories -= m
/**
* Returns whether the given user can publish new stories to this channel.
*
* Arguments:
* * user - The user
* * scanned_user - The user's identifying information on the newscaster
*/
/datum/feed_channel/proc/can_publish(mob/user, scanned_user = "Unknown")
return (!frozen && (is_public || (author == scanned_user))) || user?.can_admin_interact()
/**
* Returns whether the given user can edit or delete this channel.
*
* Arguments:
* * user - The user
* * scanned_user - The user's identifying information on the newscaster
*/
/datum/feed_channel/proc/can_modify(mob/user, scanned_user = "Unknown")
return (!frozen && author == scanned_user) || user?.can_admin_interact()
/**
* Clears the channel's information.
*
* Discards all owned stories.
*/
/datum/feed_channel/proc/clear()
channel_name = ""
author = ""
backup_author = ""
messages = list()
is_public = FALSE
frozen = FALSE
censored = FALSE
admin_locked = FALSE
/**
* Adds a new [story][/datum/feed_message] to the channel and network singleton.
*
* Arguments:
* * M - The story to add.
*/
/datum/feed_channel/proc/add_message(datum/feed_message/M)
ASSERT(istype(M))
if(!length(M.title))
M.title = "[channel_name] Story #[length(messages) + 1]"
LAZYADD(messages, M)
GLOB.news_network.stories += M
// Update all newscaster TGUIs
for(var/nc in GLOB.allNewscasters)
SStgui.update_uis(nc)
/**
* Returns the text to be said by newscasters when announcing new news from a channel.
*
* Arguments:
* * title - Optional. The headline to announce along with the channel's name. Typically the newest story's title.
*/
/datum/feed_channel/proc/get_announce_text(title)
if(length(title))
return "Breaking news from [channel_name]: [title]"
return "Breaking news from [channel_name]"
+19
View File
@@ -0,0 +1,19 @@
// Globals
/// The feed network singleton. Contains all channels (which contain all stories).
GLOBAL_DATUM_INIT(news_network, /datum/feed_network, new)
/// Global list that contains all existing newscasters in the world.
GLOBAL_LIST_EMPTY(allNewscasters)
// Screen indexes
/// Headlines screen index.
#define NEWSCASTER_HEADLINES 0
/// Available Jobs screen index.
#define NEWSCASTER_JOBS 1
/// View Channel screen index.
#define NEWSCASTER_CHANNEL 2
// Censor flags
/// Censor author name.
#define CENSOR_AUTHOR (1 << 0)
/// Censor story title, body and image.
#define CENSOR_STORY (1 << 1)
+718
View File
@@ -0,0 +1,718 @@
#define CHANNEL_NAME_MAX_LENGTH 50
#define CHANNEL_DESC_MAX_LENGTH 128
#define STORY_NAME_MAX_LENGTH 128
#define STORY_BODY_MAX_LENGTH 1024
#define WANTED_NOTICE_NAME_MAX_LENGTH 128
#define WANTED_NOTICE_DESC_MAX_LENGTH 512
#define STORIES_PER_LOAD 9999 // TODO during QP...
/**
* # Newscaster
*
* For all of the crew's news need. Includes reading, submitting and printing stories.
*
* Includes a security variant which can be used to issue wanted notices, censor channels and stories.
* Allows full access when aghosting.
*/
/obj/machinery/newscaster
name = "newscaster"
desc = "A standard Nanotrasen-licensed newsfeed handler for use in commercial space stations. All the news you absolutely have no use for, in one place!"
icon = 'icons/obj/terminals.dmi'
icon_state = "newscaster_normal"
max_integrity = 200
integrity_failure = 50
light_range = 0
anchored = TRUE
/// The current screen index in the UI.
var/screen = NEWSCASTER_HEADLINES
/// The amount of newspapers the newscaster can print.
var/paper_remaining = 15
/// Whether the newscaster can be used to make wanted issues or not.
var/is_security = FALSE
/// Whether the newscaster has new stories or not.
var/alert = FALSE
/// The newcaster's index among all newscasters (GLOB.allNewscasters).
var/unit_number = 0
/// The name of the mob currently using the newscaster.
var/scanned_user = "Unknown"
/// The currently attached photo.
var/obj/item/photo/photo = null
/// The currently viewed channel.
var/datum/feed_channel/viewing_channel = null
/// Whether the unit is silent or not.
var/is_silent = FALSE
/// The current temporary notice.
var/temp_notice
/// Whether the newscaster is currently printing a newspaper or not.
var/is_printing = FALSE
/// Static list of jobs that shouldn't be advertised if a position is available.
var/static/list/jobblacklist
/// Static, lazy list containing a user's last view time per channel.
var/static/last_views
/obj/machinery/newscaster/security_unit
name = "security newscaster"
is_security = TRUE
/obj/machinery/newscaster/New()
GLOB.allNewscasters += src
unit_number = length(GLOB.allNewscasters)
update_icon() //for any custom ones on the map...
if(!last_views)
last_views = list()
armor = list(melee = 50, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30)
..()
/obj/machinery/newscaster/Initialize(mapload)
. = ..()
if(!jobblacklist)
jobblacklist = list(
/datum/job/ai,
/datum/job/cyborg,
/datum/job/captain,
/datum/job/judge,
/datum/job/blueshield,
/datum/job/nanotrasenrep,
/datum/job/pilot,
/datum/job/brigdoc,
/datum/job/mechanic,
/datum/job/barber,
/datum/job/chaplain,
/datum/job/ntnavyofficer,
/datum/job/ntspecops,
/datum/job/civilian,
/datum/job/syndicateofficer
)
/obj/machinery/newscaster/Destroy()
GLOB.allNewscasters -= src
viewing_channel = null
QDEL_NULL(photo)
return ..()
/obj/machinery/newscaster/update_icon()
cut_overlays()
if(inoperable())
icon_state = "newscaster_off"
else
if(!GLOB.news_network.wanted_issue) //wanted icon state, there can be no overlays on it as it's a priority message
icon_state = "newscaster_normal"
if(alert) //new message alert overlay
add_overlay("newscaster_alert")
var/hp_percent = obj_integrity * 100 / max_integrity
switch(hp_percent)
if(75 to INFINITY)
return
if(50 to 75)
add_overlay("crack1")
if(25 to 50)
add_overlay("crack2")
else
add_overlay("crack3")
/obj/machinery/newscaster/power_change()
..()
update_icon()
/obj/machinery/newscaster/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = TRUE, attack_dir)
. = ..()
update_icon()
/obj/machinery/newscaster/wrench_act(mob/user, obj/item/I)
. = TRUE
if(!I.tool_use_check(user, 0))
return
to_chat(user, "<span class='notice'>Now [anchored ? "un" : ""]securing [name]</span>")
if(!I.use_tool(src, user, 60, volume = I.tool_volume))
return
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
if(stat & BROKEN)
to_chat(user, "<span class='warning'>The broken remains of [src] fall on the ground.</span>")
new /obj/item/stack/sheet/metal(loc, 5)
new /obj/item/shard(loc)
new /obj/item/shard(loc)
else
to_chat(user, "<span class='notice'>You [anchored ? "un" : ""]secure [name].</span>")
new /obj/item/mounted/frame/newscaster_frame(loc)
qdel(src)
/obj/machinery/newscaster/welder_act(mob/user, obj/item/I)
. = TRUE
if(!I.tool_use_check(user, 0))
return
default_welder_repair(user, I)
/obj/machinery/newscaster/play_attack_sound(damage, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BRUTE)
if(stat & BROKEN)
playsound(loc, 'sound/effects/hit_on_shattered_glass.ogg', 100, TRUE)
else
playsound(loc, 'sound/effects/glasshit.ogg', 90, TRUE)
if(BURN)
playsound(loc, 'sound/items/welder.ogg', 100, TRUE)
/obj/machinery/newscaster/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
new /obj/item/stack/sheet/metal(loc, 2)
new /obj/item/shard(loc)
new /obj/item/shard(loc)
qdel(src)
/obj/machinery/newscaster/obj_break()
if(!(stat & BROKEN) && !(flags & NODECONSTRUCT))
stat |= BROKEN
playsound(loc, 'sound/effects/glassbr3.ogg', 100, TRUE)
update_icon()
/obj/machinery/newscaster/attack_ghost(mob/user)
tgui_interact(user)
/obj/machinery/newscaster/attack_hand(mob/user)
if(..())
return
tgui_interact(user)
/obj/machinery/newscaster/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
if(can_scan(user))
scanned_user = get_scanned_user(user)["name"]
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "Newscaster", name, 800, 600)
ui.open()
ui.set_autoupdate(FALSE)
/obj/machinery/newscaster/tgui_data(mob/user)
var/list/data = list()
data["unit_number"] = unit_number
data["is_security"] = is_security
data["is_admin"] = user.can_admin_interact()
data["is_silent"] = is_silent
data["is_printing"] = is_printing
data["screen"] = screen
data["modal"] = tgui_modal_data(src)
if(data["modal"] && !isnull(data["modal"]["args"]["is_admin"]))
data["modal"]["args"]["is_admin"] = user.can_admin_interact()
data["temp"] = temp_notice
// Wanted notice
if(GLOB.news_network.wanted_issue)
data["wanted"] = get_message_data(GLOB.news_network.wanted_issue, user)[1]
data["world_time"] = world.time
var/user_name = get_scanned_user(user)["name"]
switch(screen)
if(NEWSCASTER_HEADLINES, NEWSCASTER_CHANNEL)
// Get the list of stories to pick from - either all or from a specific channel depending on the screen
var/list/message_list = GLOB.news_network.stories
if(screen == NEWSCASTER_CHANNEL)
if(!viewing_channel) // Uh oh, channel doesn't exist! Redirect to Headlines
screen = NEWSCASTER_HEADLINES
return tgui_data(user)
message_list = viewing_channel.messages
data["channel_idx"] = GLOB.news_network.channels.Find(viewing_channel)
data["channel_can_manage"] = viewing_channel.can_modify(usr, user_name)
// Append the data
var/list/stories = list()
data["stories"] = stories
for(var/i in 1 to min(STORIES_PER_LOAD, length(message_list)))
stories += get_message_data(message_list[i], user)
// View and unread data
var/now = world.time
data["world_time"] = now
if(user_name)
// Increase views
for(var/m in stories)
if(now >= m["publish_time"])
var/datum/feed_message/FM = locateUID(m["uid"])
if(FM && !(FM.censor_flags & CENSOR_STORY))
FM.view_count++
m["view_count"] = FM.view_count
// Update the last viewed times for the user
LAZYINITLIST(last_views[user_name])
for(var/c in GLOB.news_network.channels)
var/datum/feed_channel/C = c
if(screen == NEWSCASTER_CHANNEL && C != viewing_channel)
continue
last_views[user_name][C.UID()] = now
if(NEWSCASTER_JOBS)
var/list/jobs = list()
data["jobs"] = jobs
for(var/cat in list("security", "engineering", "medical", "science", "service", "supply"))
jobs[cat] = list()
for(var/datum/job/job in SSjobs.occupations)
if(job.type in jobblacklist)
continue
if(job.is_position_available())
var/list/opening_data = list("title" = job.title)
// Is the job a command job?
if(job.title in GLOB.command_positions)
opening_data["is_command"] = TRUE
// Add the job opening to the corresponding categories
// Ugly!
opening_data = list(opening_data)
if(job.is_security)
jobs["security"] += opening_data
if(job.is_engineering)
jobs["engineering"] += opening_data
if(job.is_medical)
jobs["medical"] += opening_data
if(job.is_science)
jobs["science"] += opening_data
if(job.is_service)
jobs["service"] += opening_data
if(job.is_supply)
jobs["supply"] += opening_data
// Append temp photo
if(photo && data["modal"] && (data["modal"]["id"] in list("create_story", "wanted_notice")))
data["photo"] = list(
name = photo.name,
uid = photo.UID(),
)
user << browse_rsc(photo.img, "inserted_photo_[photo.UID()].png")
else
data["photo"] = null
// Append channels
var/list/channels = list()
data["channels"] = channels
for(var/c in GLOB.news_network.channels)
var/datum/feed_channel/C = c
var/list/channel = list(
uid = C.UID(),
name = C.channel_name,
author = C.author,
description = C.description,
icon = C.icon,
public = C.is_public,
frozen = C.frozen,
censored = C.censored,
admin = C.admin_locked,
unread = 0,
)
// Add the number of unseen stories if authed
if(user_name)
var/last_view_time = (last_views[user_name] && last_views[user_name][C.UID()]) || 0
for(var/m in C.messages)
var/datum/feed_message/M = m
if(last_view_time < M.publish_time)
channel["unread"]++
channels += list(channel)
return data
/**
* Returns a [/datum/feed_message] in a format that can be used as TGUI data.
*
* Arguments:
* * FM - The story to send
* * M - Optional. The user to send the story's photo to if it exists
*/
/obj/machinery/newscaster/proc/get_message_data(datum/feed_message/FM, mob/M)
if(!(FM.censor_flags & CENSOR_STORY) && M && FM.img)
M << browse_rsc(FM.img, "story_photo_[FM.UID()].png")
return list(list(
uid = FM.UID(),
author = (FM.censor_flags & CENSOR_AUTHOR) ? "" : FM.author,
title = (FM.censor_flags & CENSOR_STORY) ? "" : FM.title,
body = (FM.censor_flags & CENSOR_STORY) ? "" : FM.body,
admin_locked = FM.admin_locked,
censor_flags = FM.censor_flags,
view_count = FM.view_count,
publish_time = FM.publish_time,
publish_time_proper = station_time_timestamp(time = FM.publish_time),
has_photo = !isnull(FM.img),
))
/obj/machinery/newscaster/tgui_act(action, list/params)
if(..())
return
. = TRUE
if(tgui_act_modal(action, params))
return
switch(action)
if("cleartemp")
temp_notice = null
if("jobs")
screen = NEWSCASTER_JOBS
if("headlines")
if(screen == NEWSCASTER_HEADLINES)
return FALSE
screen = NEWSCASTER_HEADLINES
if("channel")
var/datum/feed_channel/FC = locateUID(params["uid"])
if(!istype(FC))
return
if(screen == NEWSCASTER_CHANNEL && viewing_channel == FC)
return FALSE
screen = NEWSCASTER_CHANNEL
viewing_channel = FC
if("attach_photo")
var/list/open_modal = tgui_modal_data(src)
if(photo || !open_modal || !(open_modal["id"] in list("create_story", "wanted_notice")))
return
if(ishuman(usr))
var/obj/item/photo/P = usr.get_active_hand()
if(istype(P) && usr.unEquip(P))
photo = P
P.forceMove(src)
usr.visible_message("<span class='notice'>[usr] inserts [P] into [src]'s photo slot.</span>",\
"<span class='notice'>You insert [P] into [src]'s photo slot.</span>")
playsound(loc, 'sound/machines/terminal_insert_disc.ogg', 30, TRUE)
else if(issilicon(usr))
var/mob/living/silicon/M = usr
var/datum/picture/selection = M.aiCamera?.selectpicture()
if(!selection)
return
var/obj/item/photo/P = new
P.construct(selection)
P.forceMove(src)
photo = P
visible_message("<span class='notice'>[src]'s photo slot quietly whirs as it prints [P] inside it.</span>")
playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 15, TRUE)
if("eject_photo")
eject_photo(usr)
return FALSE // Updating handled in that proc
if("censor_channel")
if(is_security && !get_scanned_user(usr)["security"])
set_temp("You do not have permission to perform this action. Please ensure your ID has appropiate access.", "danger")
return
var/datum/feed_channel/FC = locateUID(params["uid"])
if(!istype(FC))
return
if(FC.admin_locked && !usr.can_admin_interact())
set_temp("This channel has been locked by CentComm and thus cannot be (un)censored.", "danger")
return
FC.censored = !FC.censored
if("censor_author", "censor_story")
if(is_security && !get_scanned_user(usr)["security"])
set_temp("You do not have permission to perform this action. Please ensure your ID has appropiate access.", "danger")
return
var/datum/feed_message/FM = locateUID(params["uid"])
if(!istype(FM))
return
if(FM.admin_locked && !usr.can_admin_interact())
set_temp("This story has been locked by CentComm and thus cannot be censored in any way.", "danger")
return
if(action == "censor_author")
FM.censor_flags = (FM.censor_flags & CENSOR_AUTHOR) ? (FM.censor_flags & ~CENSOR_AUTHOR) : (FM.censor_flags|CENSOR_AUTHOR)
else if(action == "censor_story")
FM.censor_flags = (FM.censor_flags & CENSOR_STORY) ? (FM.censor_flags & ~CENSOR_STORY) : (FM.censor_flags|CENSOR_STORY)
else
return FALSE
if("clear_wanted_notice")
if(is_security && !get_scanned_user(usr)["security"])
set_temp("You do not have permission to perform this action. Please ensure your ID has appropiate access.", "danger")
return
var/datum/feed_message/WN = GLOB.news_network.wanted_issue
if(!WN)
return
if(WN.admin_locked && !usr.can_admin_interact())
set_temp("This wanted notice has been locked by CentComm and thus cannot be altered.", "danger")
return
GLOB.news_network.wanted_issue = null
set_temp("Wanted notice cleared.", update_now = TRUE)
return FALSE
if("toggle_mute")
is_silent = !is_silent
if("print_newspaper")
if(is_printing)
return
if(paper_remaining <= 0)
set_temp("There is no more paper available.", "danger")
return
print_newspaper()
else
return FALSE
add_fingerprint(usr)
/**
* Called in tgui_act() to process modal actions
*
* Arguments:
* * action - The action passed by tgui
* * params - The params passed by tgui
*/
/obj/machinery/newscaster/proc/tgui_act_modal(action, list/params)
. = TRUE
var/id = params["id"]
var/list/arguments = istext(params["arguments"]) ? json_decode(params["arguments"]) : params["arguments"]
switch(tgui_modal_act(src, action, params))
if(TGUI_MODAL_OPEN)
switch(id)
if("create_channel", "manage_channel")
// If trying to manage the channel, make sure the user is allowed to!
if(id == "manage_channel")
var/datum/feed_channel/FC = locateUID(arguments["uid"])
if(!istype(FC) || !FC.can_modify(usr, get_scanned_user(usr)["name"]))
return
tgui_modal_message(src, id, "", arguments = list(
uid = arguments["uid"], // Only when managing a channel
scanned_user = scanned_user,
is_admin = usr.can_admin_interact(),
))
if("create_story", "wanted_notice") // Other modals
if(id == "wanted_notice" && !(is_security || usr.can_admin_interact()))
return
tgui_modal_message(src, id, "", arguments = list(
scanned_user = scanned_user,
is_admin = usr.can_admin_interact(),
))
else
return FALSE
if(TGUI_MODAL_ANSWER)
switch(id)
if("create_channel", "manage_channel")
var/author = trim(arguments["author"])
var/name = trim(arguments["name"])
if(!length(author) || !length(name))
return
var/description = trim(arguments["description"])
var/icon = arguments["icon"]
var/public = text2num(arguments["public"])
var/admin_locked = text2num(arguments["admin_locked"])
//
var/datum/feed_channel/FC = null
if(id == "create_channel") // Channel creation
if(GLOB.news_network.get_channel_by_name(name))
set_temp("A channel with this name already exists.", "danger")
return
if(GLOB.news_network.get_channel_by_author(author))
set_temp("A channel with this author name already exists.", "danger")
return
FC = new
GLOB.news_network.channels += FC
feedback_inc("newscaster_channels", 1)
// Redirect
screen = NEWSCASTER_CHANNEL
viewing_channel = FC
else if (id == "manage_channel") // Channel management
FC = locateUID(arguments["uid"])
if(!FC || !FC.can_modify(usr, get_scanned_user(usr)["name"]))
return
// Add/update the information
FC.channel_name = copytext(name, 1, CHANNEL_NAME_MAX_LENGTH)
FC.description = copytext(description, 1, CHANNEL_DESC_MAX_LENGTH)
FC.icon = usr.can_admin_interact() ? icon : "newspaper"
FC.author = usr.can_admin_interact() ? author : scanned_user
FC.is_public = public
FC.admin_locked = usr.can_admin_interact() && admin_locked
set_temp("Channel [FC.channel_name] created.", "good")
if("create_story")
var/author = trim(arguments["author"])
var/channel = trim(arguments["channel"])
var/title = trim(arguments["title"])
var/body = trim(arguments["body"])
var/admin_locked = text2num(arguments["admin_locked"])
if(!length(author) || !length(title) || !length(body))
return
// Find the named channel the user is trying to publish a story to
var/user_name = get_scanned_user(usr)["name"]
var/datum/feed_channel/FC = GLOB.news_network.get_channel_by_name(channel)
if(!FC || !FC.can_publish(usr, user_name))
return
var/datum/feed_message/FM = new
FM.author = usr.can_admin_interact() ? author : scanned_user
FM.title = copytext(title, 1, STORY_NAME_MAX_LENGTH)
FM.body = copytext(body, 1, STORY_BODY_MAX_LENGTH)
FM.img = photo?.img
FM.admin_locked = usr.can_admin_interact() && admin_locked
// Register it
FC.add_message(FM)
feedback_inc("newscaster_stories", 1)
var/announcement = FC.get_announce_text(title)
// Announce it
for(var/nc in GLOB.allNewscasters)
var/obj/machinery/newscaster/NC = nc
NC.alert_news(announcement)
// Redirect and eject photo
LAZYINITLIST(last_views[user_name])
last_views[user_name][FC.UID()] = world.time
screen = NEWSCASTER_CHANNEL
viewing_channel = FC
eject_photo(usr)
set_temp("Story published to channel [FC.channel_name].", "good")
if("wanted_notice")
if(id == "wanted_notice" && !(is_security || usr.can_admin_interact()))
return
var/author = trim(arguments["author"])
var/name = trim(arguments["name"])
var/description = trim(arguments["description"])
var/admin_locked = text2num(arguments["admin_locked"])
if(!length(author) || !length(name) || !length(description))
return
var/datum/feed_message/WN = GLOB.news_network.wanted_issue
if(WN)
if(WN.admin_locked && !usr.can_admin_interact())
set_temp("This wanted notice has been locked by CentComm and thus cannot be altered.", "danger")
return
else
WN = new
GLOB.news_network.wanted_issue = WN
WN.author = usr.can_admin_interact() ? author : scanned_user
WN.title = "WANTED: [copytext(name, 1, WANTED_NOTICE_NAME_MAX_LENGTH)]"
WN.body = copytext(description, 1, WANTED_NOTICE_DESC_MAX_LENGTH)
WN.img = photo?.img
WN.admin_locked = usr.can_admin_interact() && admin_locked
WN.publish_time = world.time
// Announce it and eject photo
for(var/nc in GLOB.allNewscasters)
var/obj/machinery/newscaster/NC = nc
NC.alert_news(wanted_notice = TRUE)
eject_photo(usr)
set_temp("Wanted notice distributed.", "good")
else
return FALSE
else
return FALSE
/**
* Ejects the photo currently held by the machine if there is one.
*
* Arguments:
* * user - The user to try to give the photo to.
*/
/obj/machinery/newscaster/proc/eject_photo(mob/user)
if(!photo)
return
var/obj/item/photo/P = photo
photo = null
P.forceMove(loc)
if(ishuman(user) && user.put_in_active_hand(P))
visible_message("<span class='notice'>[src] ejects [P] from its photo slot into [user]'s hand.")
else
visible_message("<span class='notice'>[src] ejects [P] from its photo slot.")
playsound(loc, 'sound/machines/terminal_insert_disc.ogg', 30, TRUE)
SStgui.update_uis(src)
/**
* Sets a temporary message to display to the user
*
* Arguments:
* * text - Text to display, null/empty to clear the message from the UI
* * style - The style of the message: (color name), info, success, warning, danger
*/
/obj/machinery/newscaster/proc/set_temp(text = "", style = "info", update_now = FALSE)
temp_notice = list(text = text, style = style)
if(update_now)
SStgui.update_uis(src)
/**
* Tries to obtain a mob's name and security access based on their ID.
*
* Arguments:
* * user - The user
*/
/obj/machinery/newscaster/proc/get_scanned_user(mob/user)
. = list(name = "Unknown", security = user.can_admin_interact())
if(ishuman(user))
var/mob/living/carbon/human/M = user
// No ID, no luck
if(!M.wear_id)
return
// Try to get the ID
var/obj/item/card/id/ID
if(istype(M.wear_id, /obj/item/pda))
var/obj/item/pda/P = M.wear_id
ID = P.id
else if(istype(M.wear_id, /obj/item/card/id))
ID = M.wear_id
if(istype(ID))
return list(name = "[ID.registered_name] ([ID.assignment])", security = has_access(list(), list(ACCESS_SECURITY), ID.access))
else if(issilicon(user))
var/mob/living/silicon/ai_user = user
return list(name = "[ai_user.name] ([ai_user.job])", security = TRUE)
/**
* Returns whether the machine's [/obj/machinery/newscaster/var/scanned_user] should update on interact.
*
* Arguments:
* * user - The user to check
*/
/obj/machinery/newscaster/proc/can_scan(mob/user)
if(ishuman(user) || issilicon(user))
return TRUE
return FALSE
/**
* Tries to print a newspaper with all of the content so far.
*/
/obj/machinery/newscaster/proc/print_newspaper()
if(paper_remaining <= 0 || is_printing)
return
paper_remaining--
feedback_inc("newscaster_newspapers_printed", 1)
// Print it
is_printing = TRUE
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, TRUE)
visible_message("<span class='notice'>[src] whirs as it prints a newspaper.</span>")
addtimer(CALLBACK(src, .proc/print_newspaper_finish), 5 SECONDS)
/**
* Called when the timer following a call to [/obj/machinery/newscaster/proc/print_newspaper] finishes.
*/
/obj/machinery/newscaster/proc/print_newspaper_finish()
is_printing = FALSE
SStgui.update_uis(src)
// Create the newspaper
var/obj/item/newspaper/NP = new
NP.forceMove(loc)
// Populate the newspaper
NP.important_message = GLOB.news_network.wanted_issue
for(var/fc in GLOB.news_network.channels)
var/datum/feed_channel/FC = fc
NP.news_content += FC
/**
* Makes the newscaster say a message and change its icon state for a while.
*
* Arguments:
* * announcement - The message to say
* * wanted_notice - Whether the alert is a wanted notice notification (overrides announcement)
*/
/obj/machinery/newscaster/proc/alert_news(announcement, wanted_notice = FALSE)
if(wanted_notice)
atom_say("Attention! Wanted issue distributed!")
playsound(loc, 'sound/machines/warning-buzzer.ogg', 75, TRUE)
else if(length(announcement))
atom_say("[announcement]!")
if(!is_silent)
playsound(loc, 'sound/machines/twobeep.ogg', 75, TRUE)
else
return
alert = TRUE
addtimer(CALLBACK(src, .proc/alert_timer_finish), 30 SECONDS)
update_icon()
/**
* Called when the timer following a call to [/obj/machinery/newscaster/proc/alert_news] finishes.
*/
/obj/machinery/newscaster/proc/alert_timer_finish()
alert = FALSE
update_icon()
/**
* Ejects the currently loaded photo if there is one.
*/
/obj/machinery/newscaster/verb/eject_photo_verb()
set name = "Eject Photo"
set category = "Object"
set src in oview(1)
if(usr.incapacitated())
return
eject_photo(usr)
#undef CHANNEL_NAME_MAX_LENGTH
#undef CHANNEL_DESC_MAX_LENGTH
#undef STORY_NAME_MAX_LENGTH
#undef STORY_BODY_MAX_LENGTH
#undef WANTED_NOTICE_NAME_MAX_LENGTH
#undef WANTED_NOTICE_DESC_MAX_LENGTH
#undef STORIES_PER_LOAD
+166
View File
@@ -0,0 +1,166 @@
#define SCREEN_COVER 0
#define SCREEN_PAGE_INNER 1
#define SCREEN_PAGE_LAST 2
/**
* # Newspaper
*
* A newspaper displaying the stories of all channels contained within.
*/
/obj/item/newspaper
name = "newspaper"
desc = "An issue of The Griffon, the newspaper circulating aboard Nanotrasen Space Stations."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "newspaper"
w_class = WEIGHT_CLASS_SMALL
attack_verb = list("bapped")
/// The current screen to display.
var/screen = 0
/// The number of pages.
var/pages = 0
/// The currently selected page.
var/curr_page = 0
/// The channels to display as content.
var/list/datum/feed_channel/news_content
/// The security notice to display optionally.
var/datum/feed_message/important_message = null
/// The contents of a scribble made through pen, if any.
var/scribble = ""
/// The page of said scribble.
var/scribble_page = null
/obj/item/newspaper/Initialize(mapload)
. = ..()
if(!news_content)
news_content = list()
/obj/item/newspaper/attack_self(mob/user)
if(ishuman(user))
var/mob/living/carbon/human/human_user = user
var/dat
pages = 0
switch(screen)
if(SCREEN_COVER) //Cover
dat += "<div align='center'><b><font size=6>The Griffon</font></b></div>"
dat += "<div align='center'><font size=2>Nanotrasen-standard newspaper, for use on Nanotrasen Space Facilities</font></div><hr>"
if(!length(news_content))
if(important_message)
dat += "Contents:<br><ul><b><font color='red'>**</font>Important Security Announcement<font color='red'>**</font></b> <font size=2>\[page [pages+2]\]</font><br></ul>"
else
dat += "<i>Other than the title, the rest of the newspaper is unprinted...</i>"
else
dat += "Contents:<br><ul>"
for(var/datum/feed_channel/NP in news_content)
pages++
if(important_message)
dat += "<b><font color='red'>**</font>Important Security Announcement<font color='red'>**</font></b> <font size=2>\[page [pages+2]\]</font><br>"
var/temp_page=0
for(var/datum/feed_channel/NP in news_content)
temp_page++
dat += "<b>[NP.channel_name]</b> <font size=2>\[page [temp_page+1]\]</font><br>"
dat += "</ul>"
if(scribble_page==curr_page)
dat += "<br><i>There is a small scribble near the end of this page... It reads: \"[scribble]\"</i>"
dat+= "<hr><div style='float:right;'><a href='?src=[UID()];next_page=1'>Next Page</a></div> <div style='float:left;'><a href='?src=[human_user.UID()];mach_close=newspaper_main'>Done reading</a></div>"
if(SCREEN_PAGE_INNER) // X channel pages inbetween.
for(var/datum/feed_channel/NP in news_content)
pages++ //Let's get it right again.
var/datum/feed_channel/C = news_content[curr_page]
dat += "<font size=4><b>[C.channel_name]</b></font><font size=1> \[created by: <font color='maroon'>[C.author]</font>\]</font><br><br>"
if(C.censored)
dat += "This channel was deemed dangerous to the general welfare of the station and therefore marked with a <b><font color='red'>D-Notice</b></font>. Its contents were not transferred to the newspaper at the time of printing."
else
if(!length(C.messages))
dat += "No Feed stories stem from this channel..."
else
dat += "<ul>"
var/i = 0
for(var/datum/feed_message/MESSAGE in C.messages)
var/title = (MESSAGE.censor_flags & CENSOR_STORY) ? "\[REDACTED\]" : MESSAGE.title
var/body = (MESSAGE.censor_flags & CENSOR_STORY) ? "\[REDACTED\]" : MESSAGE.body
i++
dat += "<b>[title]</b> <br>"
dat += "[body] <br>"
if(MESSAGE.img)
user << browse_rsc(MESSAGE.img, "tmp_photo[i].png")
dat += "<img src='tmp_photo[i].png' width = '180'><br>"
dat += "<font size=1>\[Story by <font color='maroon'>[MESSAGE.author]</font>\]</font><br><br>"
dat += "</ul>"
if(scribble_page==curr_page)
dat += "<br><i>There is a small scribble near the end of this page... It reads: \"[scribble]\"</i>"
dat+= "<br><hr><div style='float:left;'><a href='?src=[UID()];prev_page=1'>Previous Page</a></div> <div style='float:right;'><a href='?src=[UID()];next_page=1'>Next Page</a></div>"
if(SCREEN_PAGE_LAST) //Last page
for(var/datum/feed_channel/NP in news_content)
pages++
if(important_message!=null)
dat += "<div style='float:center;'><font size=4><b>Wanted Issue:</b></font size></div><br><br>"
dat += "<b>Criminal name</b>: <font color='maroon'>[important_message.author]</font><br>"
dat += "<b>Description</b>: [important_message.body]<br>"
dat += "<b>Photo:</b>: "
if(important_message.img)
user << browse_rsc(important_message.img, "tmp_photow.png")
dat += "<br><img src='tmp_photow.png' width = '180'>"
else
dat += "None"
else
dat += "<i>Apart from some uninteresting Classified ads, there's nothing on this page...</i>"
if(scribble_page==curr_page)
dat += "<br><i>There is a small scribble near the end of this page... It reads: \"[scribble]\"</i>"
dat+= "<hr><div style='float:left;'><a href='?src=[UID()];prev_page=1'>Previous Page</a></div>"
else
dat += "i'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com"
dat += "<br><hr><div align='center'>[curr_page+1]</div>"
human_user << browse(dat, "window=newspaper_main;size=300x400")
onclose(human_user, "newspaper_main")
else
to_chat(user, "<span class='warning'>The paper is full of unintelligible symbols!</span>")
/obj/item/newspaper/Topic(href, href_list)
if(..())
return
var/mob/living/M = usr
if(!Adjacent(M))
return
M.set_machine(src)
if(href_list["next_page"])
if(curr_page == pages + 1)
return //Don't need that at all, but anyway.
else if(curr_page == pages) //We're at the middle, get to the end
screen = SCREEN_PAGE_LAST
else if(curr_page == 0) //We're at the start, get to the middle
screen = SCREEN_PAGE_INNER
curr_page++
playsound(loc, "pageturn", 50, TRUE)
else if(href_list["prev_page"])
if(curr_page == 0)
return
else if(curr_page == 1)
screen = SCREEN_COVER
else if(curr_page == pages + 1) //we're at the end, let's go back to the middle.
screen = SCREEN_PAGE_INNER
curr_page--
playsound(loc, "pageturn", 50, TRUE)
if(loc == M)
attack_self(M)
/obj/item/newspaper/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/pen))
if(scribble_page == curr_page)
to_chat(user, "<span class='notice'>There's already a scribble in this page... You wouldn't want to make things too cluttered, would you?</span>")
else
var/s = strip_html(input(user, "Write something", "Newspaper", ""))
s = sanitize(copytext(s, 1, MAX_MESSAGE_LEN))
if(!s || !Adjacent(user))
return
scribble_page = curr_page
scribble = s
user.visible_message("<span class='notice'>[user] scribbles something on [src].</span>",\
"<span class='notice'>You scribble on page number [curr_page] of [src].</span>")
attack_self(user)
return
return ..()
#undef SCREEN_COVER
#undef SCREEN_PAGE_INNER
#undef SCREEN_PAGE_LAST
+1 -1
View File
@@ -177,7 +177,7 @@
// Show it to ghosts
for(var/mob/M in GLOB.dead_mob_list)
if(isobserver(M) && M.client && (M.client.prefs.toggles & CHAT_GHOSTPDA))
if(isobserver(M) && M.client && (M.client.prefs.toggles & PREFTOGGLE_CHAT_GHOSTPDA))
var/ghost_message = "<span class='name'>[pda.owner]</span> ([ghost_follow_link(pda, ghost=M)]) <span class='game say'>PDA Message</span> --> <span class='name'>[P.owner]</span> ([ghost_follow_link(P, ghost=M)]): <span class='message'>[t]</span>"
to_chat(M, "[ghost_message]")
@@ -144,7 +144,7 @@ field_generator power level display
..()
/obj/machinery/field/generator/bullet_act(obj/item/projectile/Proj)
if(Proj.flag != "bullet")
if(Proj.flag != "bullet" && !Proj.nodamage)
power = min(power + Proj.damage, field_generator_max_power)
check_power_level()
return 0
@@ -313,6 +313,8 @@
return attack_hand(user)
/obj/machinery/power/supermatter_shard/attack_hand(mob/user as mob)
if(isAI(user))
return
user.visible_message("<span class=\"warning\">\The [user] reaches out and touches \the [src], inducing a resonance... [user.p_their(TRUE)] body starts to glow and bursts into flames before flashing into ash.</span>",\
"<span class=\"danger\">You reach out and touch \the [src]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"</span>",\
"<span class=\"warning\">You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.</span>")
@@ -187,7 +187,8 @@
/obj/item/ammo_casing/energy/wormhole
projectile_type = /obj/item/projectile/beam/wormhole
muzzle_flash_color = "#33CCFF"
e_cost = 0
delay = 10
e_cost = 100
fire_sound = 'sound/weapons/pulse3.ogg'
var/obj/item/gun/energy/wormhole_projector/gun = null
select_name = "blue"
@@ -200,6 +200,8 @@
item_state = null
icon_state = "wormhole_projector1"
origin_tech = "combat=4;bluespace=6;plasmatech=4;engineering=4"
charge_delay = 5
selfcharge = TRUE
var/obj/effect/portal/blue
var/obj/effect/portal/orange
@@ -85,6 +85,7 @@
icon_state = "omnilaser"
hitsound = 'sound/weapons/tap.ogg'
nodamage = 1
damage = 0
damage_type = STAMINA
flag = "laser"
var/suit_types = list(/obj/item/clothing/suit/redtag, /obj/item/clothing/suit/bluetag)
@@ -85,6 +85,7 @@
damage = 12.5
tile_dropoff = 0.75
tile_dropoff_s = 1.25
armour_penetration = -30
/obj/item/projectile/bullet/pellet/rubber
name = "rubber pellet"
@@ -628,7 +628,7 @@
reagent_state = LIQUID
color = "#B4B400"
metabolization_rate = 0.2
nutriment_factor = 2
nutriment_factor = 2.5 * REAGENTS_METABOLISM
taste_description = "broth"
/datum/reagent/consumable/cheese
@@ -121,7 +121,14 @@
/datum/reagent/medicine/cryoxadone/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
if(M.bodytemperature < TCRYO)
var/external_temp
if(istype(M.loc, /obj/machinery/atmospherics/unary/cryo_cell))
var/obj/machinery/atmospherics/unary/cryo_cell/C = M.loc
external_temp = C.temperature_archived
else
var/turf/T = get_turf(M)
external_temp = T.temperature
if(external_temp < TCRYO)
update_flags |= M.adjustCloneLoss(-4, FALSE)
update_flags |= M.adjustOxyLoss(-10, FALSE)
update_flags |= M.adjustToxLoss(-3, FALSE)
@@ -50,15 +50,20 @@
user.changeNext_move(CLICK_CD_RANGE*2)
user.newtonian_move(get_dir(A, user))
if(reagents.reagent_list.len == 1 && reagents.has_reagent("cleaner")) // Only show space cleaner logs if it's burning people from being too hot or cold
if(reagents.chem_temp < 300 && reagents.chem_temp > 280) // 280 is the cold threshold for slimes, 300 the hot threshold for drask
var/attack_log_type = ATKLOG_ALMOSTALL
if(reagents.chem_temp > 300 || reagents.chem_temp < 280) //harmful temperature
attack_log_type = ATKLOG_MOST
if(reagents.reagent_list.len == 1 && reagents.has_reagent("cleaner")) // Only create space cleaner logs if it's burning people from being too hot or cold
if(attack_log_type == ATKLOG_ALMOSTALL)
return
var/attack_log_type = ATKLOG_MOST
//commonly used for griefing or just very annoying and dangerous
if(reagents.has_reagent("sacid") || reagents.has_reagent("facid") || reagents.has_reagent("lube"))
attack_log_type = ATKLOG_FEW
add_attack_logs(user, A, "Used a potentially harmful spray bottle. Contents: [contents_log] - Temperature: [reagents.chem_temp]K", attack_log_type)
add_attack_logs(user, A, "Used a spray bottle. Contents: [contents_log] - Temperature: [reagents.chem_temp]K", attack_log_type)
return
+1 -1
View File
@@ -267,7 +267,7 @@
timer = world.time
GLOB.priority_announcement.Announce("The Emergency Shuttle has left the station. Estimate [timeLeft(600)] minutes until the shuttle docks at Central Command.")
for(var/mob/M in GLOB.player_list)
if(!isnewplayer(M) && !M.client.karma_spent && !(M.client.ckey in GLOB.karma_spenders) && !M.get_preference(DISABLE_KARMA_REMINDER))
if(!isnewplayer(M) && !M.client.karma_spent && !(M.client.ckey in GLOB.karma_spenders) && !M.get_preference(PREFTOGGLE_DISABLE_KARMA_REMINDER))
to_chat(M, "<i>You have not yet spent your karma for the round; was there a player worthy of receiving your reward? Look under Special Verbs tab, Award Karma.</i>")
if(SHUTTLE_ESCAPE)
+1 -1
View File
@@ -930,7 +930,7 @@
desc = "Used to control the Golem Ship."
circuit = /obj/item/circuitboard/shuttle/golem_ship
shuttleId = "freegolem"
possible_destinations = "freegolem_lavaland;freegolem_z5;freegolem_z6"
possible_destinations = "freegolem_lavaland;freegolem_space;freegolem_ussp"
/obj/machinery/computer/shuttle/golem_ship/attack_hand(mob/user)
if(!isgolem(user) && !isobserver(user))
@@ -20,6 +20,10 @@
/datum/tgui_module/power_monitor/tgui_data(mob/user)
var/list/data = list()
// Sanity check
if(QDELETED(powermonitor))
powermonitor = null
data["powermonitor"] = powermonitor
if(select_monitor)
data["select_monitor"] = TRUE
+3 -4
View File
@@ -106,7 +106,7 @@
window_options += "size=[width]x[height];"
// Remove titlebar and resize handles for a fancy window
if(user.client.prefs.nanoui_fancy)
if(user.client.prefs.toggles2 & PREFTOGGLE_2_FANCYUI)
window_options += "titlebar=0;can_resize=0;"
else
window_options += "titlebar=1;can_resize=1;"
@@ -196,7 +196,7 @@
"title" = title,
"status" = status,
"interface" = interface,
"fancy" = user.client.prefs.nanoui_fancy,
"fancy" = user.client.prefs.toggles2 & PREFTOGGLE_2_FANCYUI,
"observer" = isobserver(user),
"window" = window_id,
"map" = (GLOB.using_map && GLOB.using_map.name) ? GLOB.using_map.name : "Unknown",
@@ -252,8 +252,7 @@
src_object.tgui_shared_states[key] = value
SStgui.update_uis(src_object)
if("tgui:setFancy")
var/value = text2num(params["value"])
user.client.prefs.nanoui_fancy = value
user.client.prefs.toggles2 ^= PREFTOGGLE_2_FANCYUI
if("tgui:log")
// Force window to show frills on fatal errors
if(params["fatal"])