This commit is contained in:
Arkatos1
2019-08-12 16:38:33 +02:00
517 changed files with 25918 additions and 8376 deletions
+1 -1
View File
@@ -108,7 +108,7 @@ world/IsBanned(key, address, computer_id, check_ipintel = TRUE)
var/appealmessage = ""
if(config.banappeals)
appealmessage = " You may appeal it at <a href='[config.banappeals]'>[config.banappeals]</a>."
expires = " This is a permanent ban.[appealmessage]"
expires = " This ban does not expire automatically and must be appealed.[appealmessage]"
var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime].[expires]"
+21 -6
View File
@@ -77,9 +77,11 @@ var/list/admin_verbs_admin = list(
/client/proc/toggle_mentor_chat,
/client/proc/toggle_advanced_interaction, /*toggle admin ability to interact with not only machines, but also atoms such as buttons and doors*/
/client/proc/list_ssds,
/client/proc/list_afks,
/client/proc/cmd_admin_headset_message,
/client/proc/spawn_floor_cluwne,
/client/proc/show_discord_duplicates,
/client/proc/show_discord_duplicates, // This needs removing at some point, ingame discord linking got removed in #11359
/client/proc/toggle_panic_bunker
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
@@ -475,7 +477,7 @@ var/list/admin_verbs_ticket = list(
if(holder.fakekey)
holder.fakekey = null
else
var/new_key = ckeyEx(input("Enter your desired display name.", "Fake Key", key) as text|null)
var/new_key = ckeyEx(clean_input("Enter your desired display name.", "Fake Key", key))
if(!new_key) return
if(length(new_key) >= 26)
new_key = copytext(new_key, 1, 26)
@@ -497,7 +499,7 @@ var/list/admin_verbs_ticket = list(
holder.fakekey = null
holder.big_brother = 0
else
var/new_key = ckeyEx(input("Enter your desired display name. Unlike normal stealth mode, this will not appear in Who at all, except for other heads.", "Fake Key", key) as text|null)
var/new_key = ckeyEx(clean_input("Enter your desired display name. Unlike normal stealth mode, this will not appear in Who at all, except for other heads.", "Fake Key", key))
if(!new_key)
return
if(length(new_key) >= 26)
@@ -638,7 +640,7 @@ var/list/admin_verbs_ticket = list(
return
if(O)
var/message = input("What do you want the message to be?", "Make Sound") as text|null
var/message = clean_input("What do you want the message to be?", "Make Sound")
if(!message)
return
for(var/mob/V in hearers(O))
@@ -889,7 +891,7 @@ var/list/admin_verbs_ticket = list(
to_chat(usr, "Your attack logs preference is now: show ALMOST ALL attack logs (notable exceptions: NPCs attacking other NPCs, vampire bites, equipping/stripping, people pushing each other over)")
else if(prefs.atklog == ATKLOG_ALMOSTALL)
prefs.atklog = ATKLOG_MOST
to_chat(usr, "Your attack logs preference is now: show MOST attack logs (like ALMOST ALL, except that it also hides attacks by players on NPCs)")
to_chat(usr, "Your attack logs preference is now: show MOST attack logs (like ALMOST ALL, except that it also hides player v. NPC combat, and certain areas like lavaland syndie base and thunderdome)")
else if(prefs.atklog == ATKLOG_MOST)
prefs.atklog = ATKLOG_FEW
to_chat(usr, "Your attack logs preference is now: show FEW attack logs (only the most important stuff: attacks on SSDs, use of explosives, messing with the engine, gibbing, AI wiping, forcefeeding, acid sprays, and organ extraction)")
@@ -1026,4 +1028,17 @@ var/list/admin_verbs_ticket = list(
if(!check_rights(R_ADMIN))
return
holder.discord_duplicates()
holder.discord_duplicates()
/client/proc/toggle_panic_bunker()
set name = "Toggle Panic Bunker"
set category = "Admin"
set desc = "Disables new players connecting."
if(!check_rights(R_ADMIN))
return
GLOB.panic_bunker_enabled = !GLOB.panic_bunker_enabled
log_admin("[key_name(usr)] has [GLOB.panic_bunker_enabled ? "activated" : "deactivated"] the panic bunker.")
message_admins("[key_name_admin(usr)] has [GLOB.panic_bunker_enabled ? "activated" : "deactivated"] the panic bunker.")
+1 -1
View File
@@ -5,7 +5,7 @@
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
if(!target_ckey)
var/new_ckey = ckey(input(usr,"Who would you like to add a note for?","Enter a ckey",null) as text|null)
var/new_ckey = ckey(clean_input("Who would you like to add a note for?","Enter a ckey",null))
if(!new_ckey)
return
new_ckey = ckey(new_ckey)
+3 -3
View File
@@ -16,7 +16,7 @@
if(data["ckey"])
ckey = ckey(data["ckey"])
else
ckey = input(usr,"Ckey","Ckey","") as text|null
ckey = clean_input("Ckey","Ckey","")
if(!ckey)
return
ckey = ckey(ckey)
@@ -26,7 +26,7 @@
if(data["reason"])
ban["message"] = data["reason"]
else
var/reason = input(usr,"Reason","Reason","Ban Evasion") as text|null
var/reason = clean_input("Reason","Reason","Ban Evasion")
if(!reason)
return
ban["message"] = "[reason]"
@@ -112,7 +112,7 @@
to_chat(usr, "<span class='adminnotice'>Error: No sticky ban for [ckey] found!")
return
var/oldreason = ban["message"]
var/reason = input(usr,"Reason","Reason","[ban["message"]]") as text|null
var/reason = clean_input("Reason","Reason","[ban["message"]]")
if(!reason || reason == oldreason)
return
//we have to do this again incase something changed while we waited for input
+16 -11
View File
@@ -189,7 +189,7 @@
var/task = href_list["editrights"]
if(task == "add")
var/new_ckey = ckey(input(usr,"New admin's ckey","Admin ckey", null) as text|null)
var/new_ckey = ckey(clean_input("New admin's ckey","Admin ckey", null))
if(!new_ckey) return
if(new_ckey in admin_datums)
to_chat(usr, "<font color='red'>Error: Topic 'editrights': [new_ckey] is already an admin</font>")
@@ -1015,14 +1015,14 @@
return
AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0, M.lastKnownIP)
to_chat(M, "<span class='warning'><BIG><B>You have been banned by [usr.client.ckey].\nReason: [reason].</B></BIG></span>")
to_chat(M, "<span class='warning'>This is a permanent ban.</span>")
to_chat(M, "<span class='warning'>This ban does not expire automatically and must be appealed.</span>")
if(config.banappeals)
to_chat(M, "<span class='warning'>To try to resolve this matter head to [config.banappeals]</span>")
else
to_chat(M, "<span class='warning'>No ban appeals URL has been set.</span>")
ban_unban_log_save("[usr.client.ckey] has permabanned [M.ckey]. - Reason: [reason] - This is a permanent ban.")
log_admin("[key_name(usr)] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.")
message_admins("<span class='notice'>[key_name_admin(usr)] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.</span>")
ban_unban_log_save("[usr.client.ckey] has permabanned [M.ckey]. - Reason: [reason] - This ban does not expire automatically and must be appealed.")
log_admin("[key_name(usr)] has banned [M.ckey].\nReason: [reason]\nThis ban does not expire automatically and must be appealed.")
message_admins("<span class='notice'>[key_name_admin(usr)] has banned [M.ckey].\nReason: [reason]\nThis ban does not expire automatically and must be appealed.</span>")
feedback_inc("ban_perma",1)
DB_ban_record(BANTYPE_PERMA, M, -1, reason)
@@ -1700,7 +1700,7 @@
var/eviltype = input(src.owner, "Which type of evil fax do you wish to send [H]?","Its good to be baaaad...", "") as null|anything in etypes
if(!(eviltype in etypes))
return
var/customname = input(src.owner, "Pick a title for the evil fax.", "Fax Title") as text|null
var/customname = clean_input("Pick a title for the evil fax.", "Fax Title", , owner)
if(!customname)
customname = "paper"
var/obj/item/paper/evilfax/P = new /obj/item/paper/evilfax(null)
@@ -2001,7 +2001,7 @@
if(!istype(H))
to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human")
return
if(!isLivingSSD(H))
if(!href_list["cryoafk"] && !isLivingSSD(H))
to_chat(usr, "This can only be used on living, SSD players.")
return
if(istype(H.loc, /obj/machinery/cryopod))
@@ -2012,6 +2012,11 @@
else if(cryo_ssd(H))
log_admin("[key_name(usr)] sent [H.job] [H] to cryo.")
message_admins("[key_name_admin(usr)] sent [H.job] [H] to cryo.")
if(href_list["cryoafk"]) // Warn them if they are send to storage and are AFK
to_chat(H, "<span class='danger'>The admins have moved you to cryo storage for being AFK. Please eject yourself (right click, eject) out of the cryostorage if you want to avoid being despawned.</span>")
SEND_SOUND(H, 'sound/effects/adminhelp.ogg')
if(H.client)
window_flash(H.client)
else if(href_list["FaxReplyTemplate"])
if(!check_rights(R_ADMIN))
return
@@ -2183,7 +2188,7 @@
return
input = P.parsepencode(input) // Encode everything from pencode to html
var/customname = input(src.owner, "Pick a title for the fax.", "Fax Title") as text|null
var/customname = clean_input("Pick a title for the fax.", "Fax Title", , owner)
if(!customname)
customname = "paper"
@@ -2216,14 +2221,14 @@
if("clown")
stampvalue = "clown"
else if(stamptype == "text")
stampvalue = input(src.owner, "What should the stamp say?", "Stamp Text") as text|null
stampvalue = clean_input("What should the stamp say?", "Stamp Text", , owner)
else if(stamptype == "none")
stamptype = ""
else
qdel(P)
return
sendername = input(src.owner, "What organization does the fax come from? This determines the prefix of the paper (i.e. Central Command- Title). This is optional.", "Organization") as text|null
sendername = clean_input("What organization does the fax come from? This determines the prefix of the paper (i.e. Central Command- Title). This is optional.", "Organization", , owner)
if(sender)
notify = alert(src.owner, "Would you like to inform the original sender that a fax has arrived?","Notify Sender","Yes","No")
@@ -3283,7 +3288,7 @@
return
var/datum/station_goal/G = new picked()
if(picked == /datum/station_goal)
var/newname = input("Enter goal name:") as text|null
var/newname = clean_input("Enter goal name:")
if(!newname)
return
G.name = newname
+3 -2
View File
@@ -18,7 +18,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
var/list/type = list("Mentorhelp","Adminhelp")
var/selected_type = input("Pick a category.", "Admin Help", null, null) as null|anything in type
if(selected_type)
msg = input("Please enter your message.", "Admin Help", null, null) as text|null
msg = clean_input("Please enter your message.", "Admin Help", null)
//clean the input msg
if(!msg)
@@ -27,7 +27,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
if(handle_spam_prevention(msg, MUTE_ADMINHELP, OOC_COOLDOWN))
return
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
msg = sanitize_simple(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg) return
var/original_msg = msg
@@ -185,3 +185,4 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
else
send2irc(source, "[msg] - All admins AFK ([admin_number_afk]/[admin_number_total]) or skipped ([admin_number_ignored]/[admin_number_total])")
return admin_number_present
+15 -13
View File
@@ -3,7 +3,7 @@
set category = null
set name = "Admin PM Mob"
if(!holder)
to_chat(src, "<font color='red'>Error: Admin-PM-Context: Only administrators may use this command.</font>")
to_chat(src, "<span class='danger'>Error: Admin-PM-Context: Only administrators may use this command.</span>")
return
if( !ismob(M) || !M.client ) return
cmd_admin_pm(M.client,null)
@@ -14,7 +14,7 @@
set category = "Admin"
set name = "Admin PM Name"
if(!holder)
to_chat(src, "<font color='red'>Error: Admin-PM-Panel: Only administrators may use this command.</font>")
to_chat(src, "<span class='danger'>Error: Admin-PM-Panel: Only administrators may use this command.</span>")
return
var/list/client/targets[0]
for(var/client/T)
@@ -37,7 +37,7 @@
set category = "Admin"
set name = "Admin PM Key"
if(!holder)
to_chat(src, "<font color='red'>Error: Admin-PM-Panel: Only administrators may use this command.</font>")
to_chat(src, "<span class='danger'>Error: Admin-PM-Panel: Only administrators may use this command.</span>")
return
var/list/client/targets[0]
for(var/client/T)
@@ -60,7 +60,7 @@
//Fetching a message if needed. src is the sender and C is the target client
/client/proc/cmd_admin_pm(whom, msg, type = "PM")
if(prefs.muted & MUTE_ADMINHELP)
to_chat(src, "<font color='red'>Error: Private-Message: You are unable to use PM-s (muted).</font>")
to_chat(src, "<span class='danger'>Error: Private-Message: You are unable to use PM-s (muted).</span>")
return
var/client/C
@@ -89,7 +89,7 @@
//get message text, limit it's length.and clean/escape html
if(!msg)
set_typing(C, TRUE)
msg = input(src,"Message:", "Private message to [holder ? key_name(C, FALSE) : key_name_hidden(C, FALSE)]") as text|null
msg = clean_input("Message:", "Private message to [holder ? key_name(C, FALSE) : key_name_hidden(C, FALSE)]", , src)
set_typing(C, FALSE)
if(!msg)
@@ -106,9 +106,11 @@
//clean the message if it's not sent by a high-rank admin
if(!check_rights(R_SERVER|R_DEBUG,0))
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
msg = sanitize_simple(copytext(msg,1,MAX_MESSAGE_LEN))
if(!msg)
return
else
msg = pencode_to_html(msg)
var/recieve_span = "playerreply"
var/send_pm_type = " "
@@ -127,7 +129,7 @@
recieve_pm_type = holder.rank
else if(!C.holder)
to_chat(src, "<font color='red'>Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.</font>")
to_chat(src, "<span class='danger'>Error: Admin-PM: Non-admin to non-admin PM communication is forbidden.</span>")
return
var/recieve_message = ""
@@ -147,7 +149,7 @@
spawn(0) //so we don't hold the caller proc up
var/sender = src
var/sendername = key
var/reply = input(C, msg,"[recieve_pm_type] [type] from-[sendername]", "") as text|null //show message and await a reply
var/reply = clean_input(msg,"[recieve_pm_type] [type] from-[sendername]", "", C) //show message and await a reply
if(C && reply)
if(sender)
C.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them
@@ -159,7 +161,7 @@
var/emoji_msg = "<span class='emoji_enabled'>[msg]</span>"
recieve_message = "<span class='[recieve_span]'>[type] from-<b>[recieve_pm_type][C.holder ? key_name(src, TRUE, type) : key_name_hidden(src, TRUE, type)]</b>: [emoji_msg]</span>"
to_chat(C, recieve_message)
to_chat(src, "<font color='blue'>[send_pm_type][type] to-<b>[holder ? key_name(C, TRUE, type) : key_name_hidden(C, TRUE, type)]</b>: [emoji_msg]</font>")
to_chat(src, "<span class='pmsend'>[send_pm_type][type] to-<b>[holder ? key_name(C, TRUE, type) : key_name_hidden(C, TRUE, type)]</b>: [emoji_msg]</span>")
/*if(holder && !C.holder)
C.last_pm_recieved = world.time
@@ -213,10 +215,10 @@
/client/proc/cmd_admin_irc_pm()
if(prefs.muted & MUTE_ADMINHELP)
to_chat(src, "<font color='red'>Error: Private-Message: You are unable to use PM-s (muted).</font>")
to_chat(src, "<span class='danger'>Error: Private-Message: You are unable to use PM-s (muted).</span>")
return
var/msg = input(src,"Message:", "Private message to admins on IRC / 400 character limit") as text|null
var/msg = clean_input("Message:", "Private message to admins on IRC / 400 character limit", , src) as text|null
if(!msg)
return
@@ -230,14 +232,14 @@
send2adminirc("PlayerPM from [key_name(src)]: [html_decode(msg)]")
to_chat(src, "<font color='blue'>IRC PM to-<b>IRC-Admins</b>: [msg]</font>")
to_chat(src, "<span class='pmsend'>IRC PM to-<b>IRC-Admins</b>: [msg]</span>")
log_admin("PM: [key_name(src)]->IRC: [msg]")
for(var/client/X in GLOB.admins)
if(X == src)
continue
if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, X.mob))
to_chat(X, "<B><font color='blue'>PM: [key_name(src, TRUE, 0)]-&gt;IRC-Admins:</B> <span class='notice'>[msg]</span></font>")
to_chat(X, "<B><span class='pmsend'>PM: [key_name(src, TRUE, 0)]-&gt;IRC-Admins:</B> <span class='notice'>[msg]</span></span>")
/client/verb/open_pms_ui()
set name = "My PMs"
+4
View File
@@ -17,6 +17,10 @@
feedback_add_details("admin_verb","M") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/get_admin_say()
var/msg = input(src, null, "asay \"text\"") as text|null
cmd_admin_say(msg)
/client/proc/cmd_mentor_say(msg as text)
set category = "Admin"
set name = "Msay"
+4
View File
@@ -43,3 +43,7 @@
say_dead_direct("<span class='name'>[prefix]</span> says, <span class='message'>\"[msg]\"</span>")
feedback_add_details("admin_verb","D") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/get_dead_say()
var/msg = input(src, null, "dsay \"text\"") as text
dsay(msg)
+4 -4
View File
@@ -68,7 +68,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
target = null
targetselected = 0
var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
var/procname = clean_input("Proc path, eg: /proc/fake_blood","Path:", null)
if(!procname) return
if(targetselected && !hascall(target,procname))
@@ -102,7 +102,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_PROCCALL))
return
var/procname = input("Proc name, eg: fake_blood","Proc:", null) as text|null
var/procname = clean_input("Proc name, eg: fake_blood","Proc:", null)
if(!procname)
return
@@ -149,7 +149,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return null
if("text")
lst += input("Enter new text:","Text",null) as text
lst += clean_input("Enter new text:","Text",null)
if("num")
lst += input("Enter new number:","Num",0) as num
@@ -271,7 +271,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return 0
var/obj/item/paicard/card = new(T)
var/mob/living/silicon/pai/pai = new(card)
var/raw_name = input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text
var/raw_name = clean_input("Enter your pAI name:", "pAI Name", "Personal AI", choice)
var/new_name = reject_bad_name(raw_name, 1)
if(new_name)
pai.name = new_name
+2 -2
View File
@@ -145,7 +145,7 @@
if(!check_rights(R_DEBUG))
return
var/filter = input("Contains what?","Filter") as text|null
var/filter = clean_input("Contains what?","Filter")
if(!filter)
return
@@ -166,7 +166,7 @@
if(!check_rights(R_DEBUG))
return
var/refstring = input("Which reference?","Ref") as text|null
var/refstring = clean_input("Which reference?","Ref")
if(!refstring)
return
+2 -2
View File
@@ -28,7 +28,7 @@ var/global/list/frozen_mob_list = list()
/mob/living/proc/admin_Freeze(var/client/admin, skip_overlays = FALSE)
if(istype(admin))
to_chat(src, "<b><font color= red>You have been frozen by [key_name(admin)]</b></font>")
to_chat(src, "<b><font color= red>You have been frozen by [admin]</b></font>")
message_admins("<span class='notice'>[key_name_admin(admin)]</span> froze [key_name_admin(src)]")
log_admin("[key_name(admin)] froze [key_name(src)]")
@@ -45,7 +45,7 @@ var/global/list/frozen_mob_list = list()
/mob/living/proc/admin_unFreeze(var/client/admin, skip_overlays = FALSE)
if(istype(admin))
to_chat(src, "<b><font color= red>You have been unfrozen by [key_name(admin)]</b></font>")
to_chat(src, "<b><font color= red>You have been unfrozen by [admin]</b></font>")
message_admins("<span class='notice'>[key_name_admin(admin)] unfroze [key_name_admin(src)]</span>")
log_admin("[key_name(admin)] unfroze [key_name(src)]")
+3 -3
View File
@@ -132,13 +132,13 @@ var/intercom_range_display_status = 0
if(!check_rights(R_DEBUG))
return
var/level = input("Which z-level?","Level?") as text
var/level = clean_input("Which z-level?","Level?")
if(!level) return
var/num_level = text2num(level)
if(!num_level) return
if(!isnum(num_level)) return
var/type_text = input("Which type path?","Path?") as text
var/type_text = clean_input("Which type path?","Path?")
if(!type_text) return
var/type_path = text2path(type_text)
if(!type_path) return
@@ -170,7 +170,7 @@ var/intercom_range_display_status = 0
if(!check_rights(R_DEBUG))
return
var/type_text = input("Which type path?","") as text
var/type_text = clean_input("Which type path?","")
if(!type_text) return
var/type_path = text2path(type_text)
if(!type_path) return
+61 -7
View File
@@ -54,7 +54,7 @@
if(!check_rights(R_SERVER|R_EVENT))
return
var/msg = input("Message:", text("Subtle PM to [M.key]")) as text
var/msg = clean_input("Message:", text("Subtle PM to [M.key]"))
if(!msg)
return
@@ -109,10 +109,11 @@
if(!check_rights(R_SERVER|R_EVENT))
return
var/msg = input("Message:", text("Enter the text you wish to appear to everyone:")) as text
var/msg = clean_input("Message:", text("Enter the text you wish to appear to everyone:"))
if(!msg)
return
msg = pencode_to_html(msg)
to_chat(world, "[msg]")
log_admin("GlobalNarrate: [key_name(usr)] : [msg]")
message_admins("<span class='boldnotice'>GlobalNarrate: [key_name_admin(usr)]: [msg]<BR></span>", 1)
@@ -131,10 +132,11 @@
if(!M)
return
var/msg = input("Message:", text("Enter the text you wish to appear to your target:")) as text
var/msg = clean_input("Message:", text("Enter the text you wish to appear to your target:"))
if( !msg )
return
msg = pencode_to_html(msg)
to_chat(M, msg)
log_admin("DirectNarrate: [key_name(usr)] to ([key_name(M)]): [msg]")
@@ -169,7 +171,7 @@
return
message_admins("[key_name_admin(src)] has started answering [key_name_admin(H)]'s [sender] request.")
var/input = input("Please enter a message to reply to [key_name(H)] via their headset.", "Outgoing message from [sender]", "") as text|null
var/input = clean_input("Please enter a message to reply to [key_name(H)] via their headset.", "Outgoing message from [sender]", "")
if(!input)
message_admins("[key_name_admin(src)] decided not to answer [key_name_admin(H)]'s [sender] request.")
return
@@ -550,7 +552,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_EVENT))
return
var/input = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null
var/input = clean_input("Please enter anything you want the AI to do. Anything. Serious.", "What?", "")
if(!input)
return
@@ -603,14 +605,15 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/type = input(usr, "Pick a type of report to send", "Report Type", "") as anything in MsgType
if(type == "Custom")
type = input(usr, "What would you like the report type to be?", "Report Type", "Encrypted Transmission") as text|null
type = clean_input("What would you like the report type to be?", "Report Type", "Encrypted Transmission")
var/customname = input(usr, "Pick a title for the report.", "Title", MsgType[type]) as text|null
var/customname = clean_input("Pick a title for the report.", "Title", MsgType[type])
if(!customname)
return
var/input = input(usr, "Please enter anything you want. Anything. Serious.", "What's the message?") as message|null
if(!input)
return
input = html_encode(input)
switch(alert("Should this be announced to the general population?",,"Yes","No", "Cancel"))
if("Yes")
@@ -1001,6 +1004,57 @@ Traitors and the like can also be revived with the previous role mostly intact.
msg += "</TABLE></BODY></HTML>"
src << browse(msg, "window=Player_ssd_check")
/client/proc/list_afks()
set category = "Admin"
set name = "List AFKs"
set desc = "Lists AFK players"
if(!check_rights(R_ADMIN))
return
var/msg = "<html><head><title>AFK Report</title></head><body>"
msg += "AFK Players:<BR><TABLE border='1'>"
msg += "<TR><TD><B>Key</B></TD><TD><B>Real Name</B></TD><TD><B>Job</B></TD><TD><B>Mins AFK</B></TD><TD><B>Special Role</B></TD><TD><B>Area</B></TD><TD><B>PPN</B></TD><TD><B>Cryo</B></TD></TR>"
var/mins_afk
var/job_string
var/key_string
var/role_string
for(var/mob/living/carbon/human/H in GLOB.living_mob_list)
if(H.client == null || H.stat == DEAD) // No clientless or dead
continue
mins_afk = round(H.client.inactivity / 600)
if(mins_afk < config.list_afk_minimum)
continue
if(H.job)
job_string = H.job
else
job_string = "-"
key_string = H.key
if(job_string in command_positions)
job_string = "<U>" + job_string + "</U>"
role_string = "-"
var/obj_count = 0
var/obj_string = ""
if(H.mind)
if(H.mind.special_role)
role_string = "<U>[H.mind.special_role]</U>"
if(!H.key && H.mind.key)
key_string = H.mind.key
for(var/datum/objective/O in all_objectives)
if(O.target == H.mind)
obj_count++
if(obj_count > 0)
obj_string = "<BR><U>Obj Target</U>"
msg += "<TR><TD>[key_string]</TD><TD>[H.real_name]</TD><TD>[job_string]</TD><TD>[mins_afk]</TD><TD>[role_string][obj_string]</TD>"
msg += "<TD>[get_area(H)]</TD><TD>[ADMIN_PP(H,"PP")]</TD>"
if(istype(H.loc, /obj/machinery/cryopod))
msg += "<TD><A href='?_src_=holder;cryossd=[H.UID()];cryoafk=1'>De-Spawn</A></TD>"
else
msg += "<TD><A href='?_src_=holder;cryossd=[H.UID()];cryoafk=1'>Cryo</A></TD>"
msg += "</TR>"
msg += "</TABLE></BODY></HTML>"
src << browse(msg, "window=Player_afk_check")
/client/proc/toggle_ert_calling()
set category = "Event"
set name = "Toggle ERT"
+1 -1
View File
@@ -2,7 +2,7 @@
if(!check_rights(R_ADMIN))
return
if(!target_ckey)
var/new_ckey = ckey(input(usr,"Who would you like to add to the watchlist?","Enter a ckey",null) as text)
var/new_ckey = ckey(clean_input("Who would you like to add to the watchlist?","Enter a ckey",null))
if(!new_ckey)
return
new_ckey = sanitizeSQL(new_ckey)
+2 -2
View File
@@ -77,9 +77,9 @@
if(bombassembly)
bombassembly.HasProximity(AM)
/obj/item/onetankbomb/Crossed(atom/movable/AM) //for mousetraps
/obj/item/onetankbomb/Crossed(atom/movable/AM, oldloc) //for mousetraps
if(bombassembly)
bombassembly.Crossed(AM)
bombassembly.Crossed(AM, oldloc)
/obj/item/onetankbomb/on_found(mob/finder) //for mousetraps
if(bombassembly)
+4 -4
View File
@@ -85,11 +85,11 @@
a_right.HasProximity(AM)
/obj/item/assembly_holder/Crossed(atom/movable/AM)
/obj/item/assembly_holder/Crossed(atom/movable/AM, oldloc)
if(a_left)
a_left.Crossed(AM)
a_left.Crossed(AM, oldloc)
if(a_right)
a_right.Crossed(AM)
a_right.Crossed(AM, oldloc)
/obj/item/assembly_holder/on_found(mob/finder)
if(a_left)
@@ -116,7 +116,7 @@
a_right.holder_movement()
/obj/item/assembly_holder/Move()
..()
. = ..()
process_movement()
return
+2 -2
View File
@@ -106,7 +106,7 @@
/obj/item/assembly/infra/Move()
var/t = dir
..()
. = ..()
dir = t
qdel(first)
@@ -269,7 +269,7 @@
/obj/effect/beam/i_beam/Bumped()
hit()
/obj/effect/beam/i_beam/Crossed(atom/movable/AM)
/obj/effect/beam/i_beam/Crossed(atom/movable/AM, oldloc)
if(!isobj(AM) && !isliving(AM))
return
if(istype(AM, /obj/effect))
+1 -1
View File
@@ -93,7 +93,7 @@
return
..()
/obj/item/assembly/mousetrap/Crossed(atom/movable/AM)
/obj/item/assembly/mousetrap/Crossed(atom/movable/AM, oldloc)
if(armed)
if(ishuman(AM))
var/mob/living/carbon/H = AM
+2
View File
@@ -432,6 +432,8 @@
l_pocket = /obj/item/reagent_containers/food/pill/patch/styptic
r_pocket = /obj/item/flashlight/seclite
/obj/effect/mob_spawn/human/miner/explorer
outfit = /datum/outfit/job/mining/equipped
/obj/effect/mob_spawn/human/bartender
name = "Space Bartender"
@@ -36,9 +36,226 @@
if(prob(1))
mezzer()
/obj/item/clothing/glasses/meson/truesight
name = "The Lens of Truesight"
desc = "I can see forever!"
icon_state = "monocle"
item_state = "headset"
item_state = "headset"
// Die of Fate
/obj/item/dice/d20/fate
name = "\improper Die of Fate"
desc = "A die with twenty sides. You can feel unearthly energies radiating from it. Using this might be VERY risky."
icon_state = "d20"
var/reusable = TRUE
var/used = FALSE
/obj/item/dice/d20/fate/stealth
name = "d20"
desc = "A die with twenty sides. The preferred die to throw at the GM."
/obj/item/dice/d20/fate/one_use
reusable = FALSE
/obj/item/dice/d20/fate/one_use/stealth
name = "d20"
desc = "A die with twenty sides. The preferred die to throw at the GM."
/obj/item/dice/d20/fate/cursed
name = "cursed Die of Fate"
desc = "A die with twenty sides. You feel that rolling this is a REALLY bad idea."
color = "#00BB00"
rigged = DICE_TOTALLY_RIGGED
rigged_value = 1
/obj/item/dice/d20/fate/diceroll(mob/user)
. = ..()
if(!used)
if(!ishuman(user) || !user.mind || (user.mind in SSticker.mode.wizards))
to_chat(user, "<span class='warning'>You feel the magic of the dice is restricted to ordinary humans!</span>")
return
if(!reusable)
used = TRUE
var/turf/T = get_turf(src)
T.visible_message("<span class='userdanger'>[src] flares briefly.</span>")
addtimer(CALLBACK(src, .proc/effect, user, .), 1 SECONDS)
/obj/item/dice/d20/fate/equipped(mob/user, slot)
if(!ishuman(user) || !user.mind || (user.mind in SSticker.mode.wizards))
to_chat(user, "<span class='warning'>You feel the magic of the dice is restricted to ordinary humans! You should leave it alone.</span>")
user.unEquip(src)
/obj/item/dice/d20/fate/proc/create_smoke(amount)
var/datum/effect_system/smoke_spread/smoke = new
smoke.set_up(amount, 0, drop_location())
smoke.start()
/obj/item/dice/d20/fate/proc/effect(var/mob/living/carbon/human/user, roll)
var/turf/T = get_turf(src)
switch(roll)
if(1)
//Dust
T.visible_message("<span class='userdanger'>[user] turns to dust!</span>")
user.dust()
if(2)
//Death
T.visible_message("<span class='userdanger'>[user] suddenly dies!</span>")
user.death()
if(3)
//Swarm of creatures
T.visible_message("<span class='userdanger'>A swarm of creatures surround [user]!</span>")
for(var/direction in alldirs)
new /mob/living/simple_animal/hostile/netherworld(get_step(get_turf(user),direction))
if(4)
//Destroy Equipment
T.visible_message("<span class='userdanger'>Everything [user] is holding and wearing disappears!</span>")
for(var/obj/item/I in user)
if(istype(I, /obj/item/implant) || istype(I, /obj/item/organ))
continue
qdel(I)
if(5)
//Monkeying
T.visible_message("<span class='userdanger'>[user] transforms into a monkey!</span>")
user.monkeyize()
if(6)
//Cut speed
T.visible_message("<span class='userdanger'>[user] starts moving slower!</span>")
var/datum/species/S = user.dna.species
S.slowdown += 1
if(7)
//Throw
T.visible_message("<span class='userdanger'>Unseen forces throw [user]!</span>")
user.Stun(6)
user.adjustBruteLoss(50)
var/throw_dir = cardinal
var/atom/throw_target = get_edge_target_turf(user, throw_dir)
user.throw_at(throw_target, 200, 4)
if(8)
//Fueltank Explosion
T.visible_message("<span class='userdanger'>An explosion bursts into existence around [user]!</span>")
explosion(get_turf(user),-1,0,2, flame_range = 2)
if(9)
//Cold
var/datum/disease/D = new /datum/disease/cold()
T.visible_message("<span class='userdanger'>[user] looks a little under the weather!</span>")
user.ForceContractDisease(D)
if(10)
//Nothing
T.visible_message("<span class='userdanger'>Nothing seems to happen.</span>")
if(11)
//Cookie
T.visible_message("<span class='userdanger'>A cookie appears out of thin air!</span>")
var/obj/item/reagent_containers/food/snacks/cookie/C = new(drop_location())
create_smoke(2)
C.name = "Cookie of Fate"
if(12)
//Healing
T.visible_message("<span class='userdanger'>[user] looks very healthy!</span>")
user.revive()
if(13)
//Mad Dosh
T.visible_message("<span class='userdanger'>Mad dosh shoots out of [src]!</span>")
var/turf/Start = get_turf(src)
for(var/direction in alldirs)
var/turf/dirturf = get_step(Start,direction)
if(rand(0,1))
new /obj/item/stack/spacecash/c1000(dirturf)
else
var/obj/item/storage/bag/money/M = new(dirturf)
for(var/i in 1 to rand(5,50))
new /obj/item/coin/gold(M)
if(14)
//Free Gun
T.visible_message("<span class='userdanger'>An impressive gun appears!</span>")
create_smoke(2)
new /obj/item/gun/projectile/revolver/mateba(drop_location())
if(15)
//Random One-use spellbook
T.visible_message("<span class='userdanger'>A magical looking book drops to the floor!</span>")
create_smoke(2)
new /obj/item/spellbook/oneuse/random(drop_location())
if(16)
//Servant & Servant Summon
T.visible_message("<span class='userdanger'>A Dice Servant appears in a cloud of smoke!</span>")
var/mob/living/carbon/human/H = new(drop_location())
create_smoke(2)
H.equipOutfit(/datum/outfit/butler)
var/datum/mind/servant_mind = new /datum/mind()
var/datum/objective/O = new
O.owner = servant_mind
O.target = user.mind
O.explanation_text = "Serve [user.real_name]."
servant_mind.objectives += O
servant_mind.transfer_to(H)
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the servant of [user.real_name]?", ROLE_WIZARD, poll_time = 50)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Dice Servant")
H.key = C.key
to_chat(H, "<span class='notice'>You are a servant of [user.real_name]. You must do everything in your power to follow their orders.</span>")
var/obj/effect/proc_holder/spell/targeted/summonmob/S = new
S.target_mob = H
user.mind.AddSpell(S)
if(17)
//Tator Kit
T.visible_message("<span class='userdanger'>A suspicious box appears!</span>")
new /obj/item/storage/box/syndicate(drop_location())
create_smoke(2)
if(18)
//Captain ID
T.visible_message("<span class='userdanger'>A golden identification card appears!</span>")
new /obj/item/card/id/captains_spare(drop_location())
create_smoke(2)
if(19)
//Instrinct Resistance
T.visible_message("<span class='userdanger'>[user] looks very robust!</span>")
var/datum/species/S = user.dna.species
S.brute_mod *= 0.5
S.burn_mod *= 0.5
if(20)
//Free wizard!
T.visible_message("<span class='userdanger'>Magic flows out of [src] and into [user]!</span>")
user.mind.make_Wizard()
// Butler outfit
/datum/outfit/butler
name = "Butler"
uniform = /obj/item/clothing/under/suit_jacket/really_black
shoes = /obj/item/clothing/shoes/laceup
head = /obj/item/clothing/head/bowlerhat
glasses = /obj/item/clothing/glasses/monocle
gloves = /obj/item/clothing/gloves/color/white
/obj/effect/proc_holder/spell/targeted/summonmob
name = "Summon Servant"
desc = "This spell can be used to call your servant, whenever you need it."
charge_max = 100
clothes_req = 0
invocation = "JE VES"
invocation_type = "whisper"
range = -1
level_max = 0 //cannot be improved
cooldown_min = 100
include_user = 1
var/mob/living/target_mob
action_icon_state = "summons"
/obj/effect/proc_holder/spell/targeted/summonmob/cast(list/targets, mob/user = usr)
if(!target_mob)
return
var/turf/Start = get_turf(user)
for(var/direction in alldirs)
var/turf/T = get_step(Start,direction)
if(!T.density)
target_mob.Move(T)
@@ -19,22 +19,22 @@
* Areas
*/
//Gateroom gets its own APC specifically for the gate
/area/awaymission/gateroom
/area/awaymission/gateroom
//Library, medbay, storage room
/area/awaymission/southblock
/area/awaymission/southblock
//Arrivals, security, hydroponics, shuttles (since they dont move, they dont need specific areas)
/area/awaymission/arrivalblock
/area/awaymission/arrivalblock
//Crew quarters, cafeteria, chapel
/area/awaymission/midblock
/area/awaymission/midblock
//engineering, bridge (not really north but it doesnt really need its own APC)
/area/awaymission/northblock
/area/awaymission/northblock
//That massive research room
/area/awaymission/research
/area/awaymission/research
//Syndicate shuttle
/area/awaymission/syndishuttle
@@ -140,7 +140,7 @@
/obj/effect/meatgrinder/New()
icon_state = "blobpod"
/obj/effect/meatgrinder/Crossed(AM as mob|obj)
/obj/effect/meatgrinder/Crossed(AM as mob|obj, oldloc)
Bumped(AM)
/obj/effect/meatgrinder/Bumped(mob/M as mob|obj)
-40
View File
@@ -1,40 +0,0 @@
/obj/effect/step_trigger/message
var/message //the message to give to the mob
var/once = 1
/obj/effect/step_trigger/message/Trigger(mob/M as mob)
if(M.client)
to_chat(M, "<span class='info'>[message]</span>")
if(once)
qdel(src)
/obj/effect/step_trigger/teleport_fancy
var/locationx
var/locationy
var/uses = 1 //0 for infinite uses
var/entersparks = 0
var/exitsparks = 0
var/entersmoke = 0
var/exitsmoke = 0
/obj/effect/step_trigger/teleport_fancy/Trigger(mob/M as mob)
var/dest = locate(locationx, locationy, z)
M.Move(dest)
if(entersparks)
do_sparks(4, 1, src)
if(exitsparks)
do_sparks(4, 1, dest)
if(entersmoke)
var/datum/effect_system/smoke_spread/s = new
s.set_up(4, 1, src, 0)
s.start()
if(exitsmoke)
var/datum/effect_system/smoke_spread/s = new
s.set_up(4, 1, dest, 0)
s.start()
uses--
if(uses == 0)
qdel(src)
+1 -1
View File
@@ -65,7 +65,7 @@
STOP_PROCESSING(SSobj, src)
return ..()
/obj/effect/portal_sensor/Crossed(A)
/obj/effect/portal_sensor/Crossed(A, oldloc)
trigger()
/obj/effect/portal_sensor/Uncrossed(A)
+8 -4
View File
@@ -1,4 +1,8 @@
/client
//////////////////////
//BLACK MAGIC THINGS//
//////////////////////
parent_type = /datum
////////////////
//ADMIN THINGS//
////////////////
@@ -24,7 +28,7 @@
var/adminhelped = 0
var/gc_destroyed //Time when this object was destroyed.
// var/gc_destroyed //Time when this object was destroyed. [Inherits from datum]
#ifdef TESTING
var/running_find_references
@@ -56,7 +60,7 @@
var/list/related_accounts_ip = list() //So admins know why it isn't working - Used to determine what other accounts previously logged in from this ip
var/list/related_accounts_cid = list() //So admins know why it isn't working - Used to determine what other accounts previously logged in from this computer id
preload_rsc = 1 // This is 0 so we can set it to an URL once the player logs in and have them download the resources from a different server.
preload_rsc = 0 // This is 0 so we can set it to an URL once the player logs in and have them download the resources from a different server.
var/global/obj/screen/click_catcher/void
@@ -89,5 +93,5 @@
// If set to true, this client can interact with atoms such as buttons and doors on top of regular machinery interaction
var/advanced_admin_interaction = FALSE
// Has the client been varedited by an admin?
var/var_edited = FALSE
// Has the client been varedited by an admin? [Inherits from datum now]
// var/var_edited = FALSE
+32 -19
View File
@@ -297,27 +297,21 @@
return null
if(byond_build < config.minimum_client_build)
alert(src, "You are using a byond build which is not supported by this server. Please use a build version of atleast [config.minimum_client_build].", "Incorrect build", "OK")
del(src)
qdel(src)
return
if(byond_version < SUGGESTED_CLIENT_VERSION) // Update is suggested, but not required.
to_chat(src,"<span class='userdanger'>Your BYOND client (v: [byond_version]) is out of date. This can cause glitches. We highly suggest you download the latest client from http://www.byond.com/ before playing. </span>")
if(IsGuestKey(key))
alert(src,"This server doesn't allow guest accounts to play. Please go to http://www.byond.com/ and register for a key.","Guest","OK")
del(src)
qdel(src)
return
// Change the way they should download resources.
if(config.resource_urls)
preload_rsc = pick(config.resource_urls)
else preload_rsc = 1 // If config.resource_urls is not set, preload like normal.
to_chat(src, "<span class='warning'>If the title screen is black, resources are still downloading. Please be patient until the title screen appears.</span>")
GLOB.clients += src
GLOB.directory[ckey] = src
//Admin Authorisation
// Automatically makes localhost connection an admin
if(!config.disable_localhost_admin)
@@ -365,11 +359,14 @@
. = ..() //calls mob.Login()
if(ckey in clientmessages)
for(var/message in clientmessages[ckey])
to_chat(src, message)
clientmessages.Remove(ckey)
if(SSinput.initialized)
set_macros()
donator_check()
check_ip_intel()
@@ -404,14 +401,23 @@
if(!winexists(src, "asset_cache_browser")) // The client is using a custom skin, tell them.
to_chat(src, "<span class='warning'>Unable to access asset cache browser, if you are using a custom skin file, please allow DS to download the updated version, if you are not, then make a bug report. This is not a critical issue but can cause issues with resource downloading, as it is impossible to know when extra resources arrived to you.</span>")
//This is down here because of the browse() calls in tooltip/New()
if(!tooltips)
tooltips = new /datum/tooltip(src)
Master.UpdateTickRate()
// Check total playercount
var/playercount = 0
for(var/mob/M in GLOB.player_list)
if(M.client)
playercount += 1
if(playercount >= 150 && GLOB.panic_bunker_enabled == 0)
GLOB.panic_bunker_enabled = 1
message_admins("Panic bunker has been automatically enabled due to playercount surpassing 150")
/client/proc/is_connecting_from_localhost()
var/localhost_addresses = list("127.0.0.1", "::1") // Adresses
if(!isnull(address) && address in localhost_addresses)
@@ -537,6 +543,14 @@
message_admins("SQL ERROR during log_client_to_db (update). Error : \[[err]\]\n")
else
//New player!! Need to insert all the stuff
// Check new peeps for panic bunker
if(GLOB.panic_bunker_enabled)
message_admins("<span class='adminnotice'>Failed Login: [key] - New account attempting to connect during panic bunker</span>")
src << "Sorry but the server is currently not accepting connections from never before seen players. Please try again later."
del(src)
return // Dont insert or they can just go in again
var/DBQuery/query_insert = dbcon.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')")
if(!query_insert.Execute())
var/err = query_insert.ErrorMsg()
@@ -664,7 +678,7 @@
sleep(10) // Since browse is non-instant, and kinda async
to_chat(src, "<pre class=\"system system\">you're a huge nerd. wakka wakka doodle doop nobody's ever gonna see this, the chat system shouldn't be online by this point</pre>")
del(src)
qdel(src)
return TRUE
else
if (!topic || !topic["token"] || !tokens[ckey] || topic["token"] != tokens[ckey])
@@ -675,7 +689,7 @@
tokens[ckey] = cid_check_reconnect()
sleep(10) //browse is queued, we don't want them to disconnect before getting the browse() command.
del(src)
qdel(src)
return TRUE
// We DO have their cached CID handy - compare it, now
if(oldcid != computer_id)
@@ -693,7 +707,7 @@
log_adminwarn("Failed Login: [key] [computer_id] [address] - CID randomizer confirmed (oldcid: [oldcid])")
del(src)
qdel(src)
return TRUE
else
// don't shoot, I'm innocent
@@ -754,6 +768,11 @@
//Send resources to the client.
/client/proc/send_resources()
// Change the way they should download resources.
if(config.resource_urls)
preload_rsc = pick(config.resource_urls)
else
preload_rsc = 1 // If config.resource_urls is not set, preload like normal.
// Most assets are now handled through global_cache.dm
getFiles(
'html/search.js', // Used in various non-NanoUI HTML windows for search functionality
@@ -795,18 +814,15 @@
/* Mainwindow */
winset(src, "mainwindow.saybutton", "background-color=#40628a;text-color=#FFFFFF")
winset(src, "mainwindow.mebutton", "background-color=#40628a;text-color=#FFFFFF")
winset(src, "mainwindow.hotkey_toggle", "background-color=#40628a;text-color=#FFFFFF")
///// UI ELEMENTS /////
/* Mainwindow */
winset(src, "mainwindow", "background-color=#272727")
winset(src, "mainwindow.mainvsplit", "background-color=#272727")
winset(src, "mainwindow.tooltip", "background-color=#272727")
/* Outputwindow */
winset(src, "outputwindow.outputwindow", "background-color=#272727")
winset(src, "outputwindow.browseroutput", "background-color=#272727")
/* Rpane */
winset(src, "rpane", "background-color=#272727")
winset(src, "rpane.rpane", "background-color=#272727")
winset(src, "rpane.rpanewindow", "background-color=#272727")
/* Browserwindow */
winset(src, "browserwindow", "background-color=#272727")
@@ -830,18 +846,15 @@
/* Mainwindow */
winset(src, "mainwindow.saybutton", "background-color=none;text-color=#000000")
winset(src, "mainwindow.mebutton", "background-color=none;text-color=#000000")
winset(src, "mainwindow.hotkey_toggle", "background-color=none;text-color=#000000")
///// UI ELEMENTS /////
/* Mainwindow */
winset(src, "mainwindow", "background-color=none")
winset(src, "mainwindow.mainvsplit", "background-color=none")
winset(src, "mainwindow.tooltip", "background-color=none")
/* Outputwindow */
winset(src, "outputwindow.outputwindow", "background-color=none")
winset(src, "outputwindow.browseroutput", "background-color=none")
/* Rpane */
winset(src, "rpane", "background-color=none")
winset(src, "rpane.rpane", "background-color=none")
winset(src, "rpane.rpanewindow", "background-color=none")
/* Browserwindow */
winset(src, "browserwindow", "background-color=none")
@@ -166,7 +166,7 @@
/datum/gear/accessory/armband_sec
display_name = " armband, security"
path = /obj/item/clothing/accessory/armband/sec
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Brig Physician")
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Brig Physician", "Security Pod Pilot")
/datum/gear/accessory/armband_cargo
display_name = "cargo armband"
@@ -93,6 +93,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
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
@@ -439,6 +440,7 @@ var/global/list/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>"
if(unlock_content)
@@ -1261,7 +1263,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
if("input")
switch(href_list["preference"])
if("name")
var/raw_name = input(user, "Choose your character's name:", "Character Preference") as text|null
var/raw_name = clean_input("Choose your character's name:", "Character Preference", , user)
if(!isnull(raw_name)) // Check to ensure that the user entered text (rather than cancel.)
var/new_name = reject_bad_name(raw_name, 1)
if(new_name)
@@ -1977,6 +1979,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
if("winflash")
windowflashing = !windowflashing
if("afk_watch")
afk_watch = !afk_watch
if("UIcolor")
var/UI_style_color_new = input(user, "Choose your UI color, dark colors are not recommended!", UI_style_color) as color|null
if(!UI_style_color_new) return
@@ -19,7 +19,8 @@
exp,
clientfps,
atklog,
fuid
fuid,
afk_watch
FROM [format_table_name("player")]
WHERE ckey='[C.ckey]'"}
)
@@ -52,6 +53,7 @@
clientfps = text2num(query.item[17])
atklog = text2num(query.item[18])
fuid = text2num(query.item[19])
afk_watch = text2num(query.item[20])
//Sanitize
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
@@ -72,6 +74,7 @@
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))
return 1
/datum/preferences/proc/save_preferences(client/C)
@@ -90,7 +93,7 @@
UI_style_alpha='[UI_style_alpha]',
be_role='[sanitizeSQL(list2params(be_special))]',
default_slot='[default_slot]',
toggles='[num2text(toggles, 7)]',
toggles='[num2text(toggles, Ceiling(log(10, (TOGGLES_TOTAL))))]',
atklog='[atklog]',
sound='[sound]',
randomslot='[randomslot]',
@@ -101,7 +104,8 @@
windowflashing='[windowflashing]',
ghost_anonsay='[ghost_anonsay]',
clientfps='[clientfps]',
atklog='[atklog]'
atklog='[atklog]',
afk_watch='[afk_watch]'
WHERE ckey='[C.ckey]'"}
)
@@ -241,7 +241,31 @@
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.")
return
/client/verb/numpad_target()
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.save_preferences(src)
if (prefs.toggles & 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.")
return
/client/verb/azerty_toggle()
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.save_preferences(src)
if (prefs.toggles & 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.")
return
/client/verb/toggle_ghost_pda()
set name = "Show/Hide GhostPDA"
set category = "Preferences"
@@ -249,4 +273,4 @@
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.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!
feedback_add_details("admin_verb","TGP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+12 -1
View File
@@ -110,12 +110,23 @@
/obj/item/clothing/mask/muzzle/safety
name = "safety muzzle"
desc = "A muzzle designed to prevent biting."
resist_time = 600
icon_state = "muzzle_secure"
item_state = "muzzle_secure"
resist_time = 0
mute = MUZZLE_MUTE_NONE
security_lock = TRUE
locked = FALSE
materials = list(MAT_METAL=500, MAT_GLASS=50)
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
"Grey" = 'icons/mob/species/grey/mask.dmi',
"Drask" = 'icons/mob/species/drask/mask.dmi'
)
/obj/item/clothing/mask/muzzle/safety/shock
name = "shock muzzle"
desc = "A muzzle designed to prevent biting. This one is fitted with a behavior correction system."
+24
View File
@@ -71,6 +71,30 @@ obj/item/clothing/shoes/magboots/syndie/advance //For the Syndicate Strike Team
silence_steps = 1
shoe_sound = "clownstep"
origin_tech = "magnets=4;syndicate=2"
var/enabled_waddle = TRUE
var/datum/component/waddle
/obj/item/clothing/shoes/magboots/clown/equipped(mob/user, slot)
. = ..()
if(slot == slot_shoes && enabled_waddle)
waddle = user.AddComponent(/datum/component/waddling)
/obj/item/clothing/shoes/magboots/clown/dropped(mob/user)
. = ..()
QDEL_NULL(waddle)
/obj/item/clothing/shoes/magboots/clown/CtrlClick(mob/living/user)
if(!isliving(user))
return
if(user.get_active_hand() != src)
to_chat(user, "You must hold [src] in your hand to do this.")
return
if(!enabled_waddle)
to_chat(user, "<span class='notice'>You switch off the waddle dampeners!</span>")
enabled_waddle = TRUE
else
to_chat(user, "<span class='notice'>You switch on the waddle dampeners!</span>")
enabled_waddle = FALSE
/obj/item/clothing/shoes/magboots/wizard //bundled with the wiz hardsuit
name = "boots of gripping"
+25 -1
View File
@@ -55,7 +55,7 @@
t_loc.MakeDry(TURF_WET_WATER)
/obj/item/clothing/shoes/clown_shoes
desc = "The prankster's standard-issue clowning shoes. Damn they're huge!"
desc = "The prankster's standard-issue clowning shoes. Damn they're huge! Ctrl-click to toggle the waddle dampeners!"
name = "clown shoes"
icon_state = "clown"
item_state = "clown_shoes"
@@ -63,6 +63,30 @@
item_color = "clown"
var/footstep = 1 //used for squeeks whilst walking
shoe_sound = "clownstep"
var/enabled_waddle = TRUE
var/datum/component/waddle
/obj/item/clothing/shoes/clown_shoes/equipped(mob/user, slot)
. = ..()
if(slot == slot_shoes && enabled_waddle)
waddle = user.AddComponent(/datum/component/waddling)
/obj/item/clothing/shoes/clown_shoes/dropped(mob/user)
. = ..()
QDEL_NULL(waddle)
/obj/item/clothing/shoes/clown_shoes/CtrlClick(mob/living/user)
if(!isliving(user))
return
if(user.get_active_hand() != src)
to_chat(user, "You must hold [src] in your hand to do this.")
return
if(!enabled_waddle)
to_chat(user, "<span class='notice'>You switch off the waddle dampeners!</span>")
enabled_waddle = TRUE
else
to_chat(user, "<span class='notice'>You switch on the waddle dampeners!</span>")
enabled_waddle = FALSE
/obj/item/clothing/shoes/clown_shoes/magical
name = "magical clown shoes"
@@ -182,34 +182,7 @@
materials = list(MAT_METAL=1000)
burn_state = FIRE_PROOF
/obj/item/clothing/accessory/medal/conduct
name = "distinguished conduct medal"
desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is the most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew."
/obj/item/clothing/accessory/medal/bronze_heart
name = "bronze heart medal"
desc = "A bronze heart-shaped medal awarded for sacrifice. It is often awarded posthumously or for severe injury in the line of duty."
icon_state = "bronze_heart"
/obj/item/clothing/accessory/medal/nobel_science
name = "nobel sciences award"
desc = "A bronze medal which represents significant contributions to the field of science or engineering."
/obj/item/clothing/accessory/medal/silver
name = "silver medal"
desc = "A silver medal."
icon_state = "silver"
item_color = "silver"
materials = list(MAT_SILVER=1000)
/obj/item/clothing/accessory/medal/silver/valor
name = "medal of valor"
desc = "A silver medal awarded for acts of exceptional valor."
/obj/item/clothing/accessory/medal/silver/security
name = "robust security award"
desc = "An award for distinguished combat and sacrifice in defence of Nanotrasen's commercial interests. Often awarded to security staff."
// GOLD (awarded by centcom)
/obj/item/clothing/accessory/medal/gold
name = "gold medal"
desc = "A prestigious golden medal."
@@ -223,7 +196,61 @@
/obj/item/clothing/accessory/medal/gold/heroism
name = "medal of exceptional heroism"
desc = "An extremely rare golden medal awarded only by CentComm. To recieve such a medal is the highest honor and as such, very few exist. This medal is almost never awarded to anybody but commanders."
desc = "An extremely rare golden medal awarded only by CentComm. To recieve such a medal is the highest honor and as such, very few exist."
// SILVER (awarded by Captain)
/obj/item/clothing/accessory/medal/silver
name = "silver medal"
desc = "A silver medal."
icon_state = "silver"
item_color = "silver"
materials = list(MAT_SILVER=1000)
/obj/item/clothing/accessory/medal/silver/valor
name = "medal of valor"
desc = "An award issued by Captains to crew members whose exceptional performance and service to the station has been commended by the station's top leadership."
/obj/item/clothing/accessory/medal/silver/leadership
name = "medal of command"
desc = "An award issued by Captains to heads of department who do an excellent job managing their department. Made of pure silver."
// BRONZE (awarded by heads of department, except for the bronze heart)
/obj/item/clothing/accessory/medal/security
name = "robust security medal"
desc = "An award issued by the HoS to security staff who excel at upholding the law."
/obj/item/clothing/accessory/medal/science
name = "smart science medal"
desc = "An award issued by the RD to science staff who advance the frontiers of knowledge."
/obj/item/clothing/accessory/medal/engineering
name = "excellent engineering medal"
desc = "An award issued by the CE to engineering staff whose dedication keep the station running at its best."
/obj/item/clothing/accessory/medal/service
name = "superior service medal"
desc = "An award issued by the HoP to service staff who go above and beyond."
/obj/item/clothing/accessory/medal/medical
name = "magnificient medical medal"
desc = "An award issued by the CMO to medical staff who excel at saving lives."
/obj/item/clothing/accessory/medal/legal
name = "meritous legal medal"
desc = "An award issued by the Magistrate to legal staff who uphold the rule of law."
/obj/item/clothing/accessory/medal/heart
name = "bronze heart medal"
desc = "A rarely-awarded medal for those who sacrifice themselves in the line of duty to save their fellow crew."
icon_state = "bronze_heart"
/*
Holobadges are worn on the belt or neck, and can be used to show that the holder is an authorized
+8
View File
@@ -463,6 +463,14 @@
/obj/item/stack/sheet/animalhide/ashdrake = 5)
category = CAT_PRIMAL
/datum/crafting_recipe/tribal_splint
name = "Tribal Splint"
time = 20
reqs = list(/obj/item/stack/sheet/bone = 2,
/obj/item/stack/sheet/sinew = 1)
result = /obj/item/stack/medical/splint/tribal
category = CAT_PRIMAL
/datum/crafting_recipe/guillotine
name = "Guillotine"
result = /obj/structure/guillotine
+1 -1
View File
@@ -116,7 +116,7 @@
else
to_chat(usr, "[bicon(src)]<span class='warning'>Unable to connect to accounts database.</span>")
if("trans_purpose")
var/purpose = input("Enter reason for EFTPOS transaction", "Transaction purpose", transaction_purpose) as text|null
var/purpose = clean_input("Enter reason for EFTPOS transaction", "Transaction purpose", transaction_purpose)
if(purpose)
transaction_purpose = purpose
if("trans_value")
+6
View File
@@ -7,21 +7,27 @@
/datum/event/blob/start()
processing = FALSE //so it won't fire again in next tick
var/turf/T = pick(blobstart)
if(!T)
return kill()
var/list/candidates = pollCandidates("Do you want to play as a blob infested mouse?", ROLE_BLOB, 1)
if(!candidates.len)
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(temp_vent.parent.other_atmosmch.len > 50)
vents += temp_vent
var/obj/vent = pick(vents)
var/mob/living/simple_animal/mouse/blobinfected/B = new(vent.loc)
var/mob/M = pick(candidates)
B.key = M.key
SSticker.mode.update_blob_icons_added(B.mind)
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)
processing = TRUE // Let it naturally end, if it runs successfully
+9 -5
View File
@@ -1,7 +1,7 @@
/datum/event/disease_outbreak
announceWhen = 15
var/virus_type
var/datum/disease/advance/virus_type
/datum/event/disease_outbreak/setup()
announceWhen = rand(15, 30)
@@ -10,9 +10,13 @@
event_announcement.Announce("Confirmed outbreak of level 7 major viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
/datum/event/disease_outbreak/start()
if(!virus_type)
if(prob(25))
virus_type = pick(/datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis, /datum/disease/beesease, /datum/disease/anxiety, /datum/disease/fake_gbs, /datum/disease/fluspanish, /datum/disease/pierrot_throat, /datum/disease/lycan)
else
virus_type = new /datum/disease/advance
virus_type.name = capitalize(pick(GLOB.adjectives)) + " " + capitalize(pick(GLOB.nouns,GLOB.verbs)) // random silly name
virus_type.GenerateSymptoms(1,9,6)
virus_type.AssignProperties(list("resistance" = rand(0,11), "stealth" = rand(0,2), "stage_rate" = rand(0,5), "transmittable" = rand(0,5), "severity" = rand(0,10)))
for(var/mob/living/carbon/human/H in shuffle(GLOB.living_mob_list))
if(issmall(H)) //don't infect monkies; that's a waste
continue
@@ -32,8 +36,8 @@
if(H.stat == DEAD || foundAlready)
continue
var/datum/disease/D
D = new virus_type()
var/datum/disease/advance/D
D = virus_type
D.carrier = TRUE
H.AddDisease(D)
break
+3
View File
@@ -1,6 +1,8 @@
/datum/event/sentience
/datum/event/sentience/start()
processing = FALSE //so it won't fire again in next tick
var/ghostmsg = "Do you want to awaken as a sentient being?"
var/list/candidates = pollCandidates(ghostmsg, ROLE_SENTIENT, 1)
var/list/potential = list()
@@ -41,6 +43,7 @@
SA.del_on_death = FALSE
greet_sentient(SA)
print_command_report(sentience_report, "[command_name()] Update")
processing = TRUE // Let it naturally end, if it runs successfully
/datum/event/sentience/proc/greet_sentient(var/mob/living/carbon/human/M)
to_chat(M, "<span class='userdanger'>Hello world!</span>")
+1 -1
View File
@@ -514,7 +514,7 @@
/obj/structure/spacevine/obj_destruction()
wither()
/obj/structure/spacevine/Crossed(mob/crosser)
/obj/structure/spacevine/Crossed(mob/crosser, oldloc)
if(isliving(crosser))
for(var/datum/spacevine_mutation/SM in mutations)
SM.on_cross(src, crosser)
+1 -1
View File
@@ -589,7 +589,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
health -= P.force
return
/obj/effect/fake_attacker/Crossed(mob/M, somenumber)
/obj/effect/fake_attacker/Crossed(mob/M, oldloc)
if(M == my_target)
step_away(src,my_target,2)
if(prob(30))
@@ -256,6 +256,7 @@
desc = "Full of vitamins and deliciousness!"
icon_state = "orangejuice"
item_state = "carton"
throwforce = 0
isGlass = 0
list_reagents = list("orangejuice" = 100)
@@ -264,6 +265,7 @@
desc = "It's cream. Made from milk. What else did you think you'd find in there?"
icon_state = "cream"
item_state = "carton"
throwforce = 0
isGlass = 0
list_reagents = list("cream" = 100)
@@ -272,6 +274,7 @@
desc = "Well, at least it LOOKS like tomato juice. You can't tell with all that redness."
icon_state = "tomatojuice"
item_state = "carton"
throwforce = 0
isGlass = 0
list_reagents = list("tomatojuice" = 100)
@@ -280,6 +283,7 @@
desc = "Sweet-sour goodness."
icon_state = "limejuice"
item_state = "carton"
throwforce = 0
isGlass = 0
list_reagents = list("limejuice" = 100)
@@ -288,6 +292,7 @@
desc = "Soothing milk."
icon_state = "milk"
item_state = "carton"
throwforce = 0
isGlass = 0
list_reagents = list("milk" = 100)
@@ -68,3 +68,10 @@
icon_state = "macncheese"
filling_color = "#ffe45d"
list_reagents = list("nutriment" = 5, "vitamin" = 2, "cheese" = 4)
/obj/item/reagent_containers/food/snacks/lasagna
name = "Lasagna"
icon_state = "lasagna"
desc = "Tajarans loves to eat this, for some reason."
filling_color = "#E18712"
list_reagents = list("nutriment" = 10, "msg" = 3, "vitamin" = 4, "tomatojuice" = 10)
@@ -224,7 +224,7 @@
if(istype(I, /obj/item/pen/))
if(open)
return
var/t = input("Enter what you want to add to the tag:", "Write", null, null) as text
var/t = clean_input("Enter what you want to add to the tag:", "Write", null)
var/obj/item/pizzabox/boxtotagto = src
if(boxes.len > 0)
boxtotagto = boxes[boxes.len]
@@ -467,3 +467,16 @@
/obj/item/reagent_containers/food/snacks/stuffing
)
result = /obj/item/reagent_containers/food/snacks/sliceable/turkey
/datum/recipe/oven/lasagna
items = list(
/obj/item/reagent_containers/food/snacks/meat,
/obj/item/reagent_containers/food/snacks/meat,
/obj/item/reagent_containers/food/snacks/cheesewedge,
/obj/item/reagent_containers/food/snacks/cheesewedge,
/obj/item/reagent_containers/food/snacks/cheesewedge,
/obj/item/reagent_containers/food/snacks/grown/tomato,
/obj/item/reagent_containers/food/snacks/grown/tomato,
/obj/item/reagent_containers/food/snacks/dough
)
result = /obj/item/reagent_containers/food/snacks/lasagna
+1 -1
View File
@@ -151,7 +151,7 @@
T.on_consume(src, usr)
..()
/obj/item/reagent_containers/food/snacks/grown/Crossed(atom/movable/AM)
/obj/item/reagent_containers/food/snacks/grown/Crossed(atom/movable/AM, oldloc)
if(seed)
for(var/datum/plant_gene/trait/T in seed.genes)
T.on_cross(src, AM)
+1 -1
View File
@@ -160,7 +160,7 @@
..()
StartBurning()
/obj/structure/bonfire/Crossed(atom/movable/AM)
/obj/structure/bonfire/Crossed(atom/movable/AM, oldloc)
if(burning)
Burn()
+1 -1
View File
@@ -51,7 +51,7 @@
return 0
/obj/item/grown/Crossed(atom/movable/AM)
/obj/item/grown/Crossed(atom/movable/AM, oldloc)
if(seed)
for(var/datum/plant_gene/trait/T in seed.genes)
T.on_cross(src, AM)
@@ -0,0 +1,21 @@
/datum/admins/key_down(_key, client/user)
switch(_key)
if("F5")
user.get_admin_say()
return
if("F6")
user.admin_ghost()
return
if("F7")
player_panel_new()
return
if("F8")
user.cmd_admin_pm_panel()
return
if("F9")
user.invisimin()
return
if("F10")
user.get_dead_say()
return
..()
+21
View File
@@ -0,0 +1,21 @@
// You might be wondering why this isn't client level. If focus is null, we don't want you to move.
// Only way to do that is to tie the behavior into the focus's keyLoop().
/atom/movable/keyLoop(client/user)
if(!user.keys_held["Ctrl"])
var/movement_dir = NONE
var/list/movement = SSinput.movement_keys
if(user.prefs.toggles & AZERTY)
movement = SSinput.alt_movement_keys
for(var/_key in user.keys_held)
movement_dir = movement_dir | movement[_key]
if(user.next_move_dir_add)
movement_dir |= user.next_move_dir_add
if(user.next_move_dir_sub)
movement_dir &= ~user.next_move_dir_sub
// Sanity checks in case you hold left and right and up to make sure you only go up
if((movement_dir & NORTH) && (movement_dir & SOUTH))
movement_dir &= ~(NORTH|SOUTH)
if((movement_dir & EAST) && (movement_dir & WEST))
movement_dir &= ~(EAST|WEST)
user.Move(get_step(src, movement_dir), movement_dir)
@@ -0,0 +1,20 @@
/mob/living/carbon/key_down(_key, client/user)
user.keys_held[_key] = world.time
if(!user.keys_held["Shift"])
switch(_key)
if("R", "Southwest") // Southwest is End
toggle_throw_mode()
return
if("1")
a_intent_change("help")
return
if("2")
a_intent_change("disarm")
return
if("3")
a_intent_change("grab")
return
if("4")
a_intent_change("harm")
return
return ..()
@@ -0,0 +1,59 @@
// Clients aren't datums so we have to define these procs indpendently.
// These verbs are called for all key press and release events
/client/verb/keyDown(_key as text)
set instant = TRUE
set hidden = TRUE
keys_held[_key] = world.time
var/movement = SSinput.movement_keys[_key]
if (prefs.toggles & AZERTY) movement = SSinput.alt_movement_keys[_key]
if(!(next_move_dir_sub & movement) && !keys_held["Ctrl"])
next_move_dir_add |= movement
// Client-level keybindings are ones anyone should be able to do at any time
// Things like taking screenshots, hitting tab, and adminhelps.
switch(_key)
if("F1")
if(keys_held["Ctrl"] && keys_held["Shift"]) // Is this command ever used?
winset(src, null, "command=.options")
else
adminhelp()
return
if("F2") // Screenshot. Hold shift to choose a name and location to save in
ooc()
return
if("F3")
mob.say_wrapper()
return
if("F4")
mob.me_wrapper()
return
if("F12") // Toggles minimal HUD
mob.button_pressed_F12()
return
if(holder)
holder.key_down(_key, src)
if(mob.focus)
mob.focus.key_down(_key, src)
/client/verb/keyUp(_key as text)
set instant = TRUE
set hidden = TRUE
keys_held -= _key
var/movement = SSinput.movement_keys[_key]
if (prefs.toggles & AZERTY) movement = SSinput.alt_movement_keys[_key]
if(!(next_move_dir_add & movement))
next_move_dir_sub |= movement
if(holder)
holder.key_up(_key, src)
if(mob.focus)
mob.focus.key_up(_key, src)
// Called every game tick
/client/keyLoop()
if(holder)
holder.keyLoop(src)
if(mob.focus)
mob.focus.keyLoop(src)
@@ -0,0 +1,80 @@
/mob/living/carbon/human/key_down(_key, client/user)
if(_key == "H")
var/obj/item/clothing/accessory/holster/H = null
if(istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/S = w_uniform
if(S.accessories.len)
H = locate() in S.accessories
if (!H)
return
if(!H.holstered)
if(!istype(get_active_hand(), /obj/item/gun))
to_chat(usr, "<span class='warning'>You need your gun equiped to holster it.</span>")
return
var/obj/item/gun/W = get_active_hand()
H.holster(W, usr)
else
H.unholster(usr)
if(client.keys_held["Shift"])
switch(_key)
if("E") // Put held thing in belt or take out most recent thing from belt
quick_equip() // Implementing the storage component is going to take way too long
// var/obj/item/thing = get_active_hand()
// var/obj/item/equipped_belt = get_item_by_slot(slot_belt)
// if(!equipped_belt) // We also let you equip a belt like this
// if(!thing)
// to_chat(user, "<span class='notice'>You have no belt to take something out of.</span>")
// return
// if(equip_to_slot_if_possible(thing, slot_belt))
// update_inv_r_hand()
// update_inv_l_hand()
// return
// if(!SEND_SIGNAL(equipped_belt, COMSIG_CONTAINS_STORAGE)) // not a storage item
// if(!thing)
// equipped_belt.attack_hand(src)
// else
// to_chat(user, "<span class='notice'>You can't fit anything in.</span>")
// return
// if(thing) // put thing in belt
// if(!SEND_SIGNAL(equipped_belt, COMSIG_TRY_STORAGE_INSERT, thing, user.mob))
// to_chat(user, "<span class='notice'>You can't fit anything in.</span>")
// return
// if(!equipped_belt.contents.len) // nothing to take out
// to_chat(user, "<span class='notice'>There's nothing in your belt to take out.</span>")
// return
// var/obj/item/stored = equipped_belt.contents[equipped_belt.contents.len]
// if(!stored || stored.on_found(src))
// return
// stored.attack_hand(src) // take out thing from belt
// return
/* if("B") // Put held thing in backpack or take out most recent thing from backpack
var/obj/item/thing = get_active_hand()
var/obj/item/equipped_back = get_item_by_slot(slot_back)
if(!equipped_back) // We also let you equip a backpack like this
if(!thing)
to_chat(user, "<span class='notice'>You have no backpack to take something out of.</span>")
return
if(equip_to_slot_if_possible(thing, slot_back))
update_inv_r_hand()
update_inv_l_hand()
return
if(!SEND_SIGNAL(equipped_back, COMSIG_CONTAINS_STORAGE)) // not a storage item
if(!thing)
equipped_back.attack_hand(src)
else
to_chat(user, "<span class='notice'>You can't fit anything in.</span>")
return
if(thing) // put thing in backpack
if(!SEND_SIGNAL(equipped_back, COMSIG_TRY_STORAGE_INSERT, thing, user.mob))
to_chat(user, "<span class='notice'>You can't fit anything in.</span>")
return
if(!equipped_back.contents.len) // nothing to take out
to_chat(user, "<span class='notice'>There's nothing in your backpack to take out.</span>")
return
var/obj/item/stored = equipped_back.contents[equipped_back.contents.len]
if(!stored || stored.on_found(src))
return
stored.attack_hand(src) // take out thing from backpack
return */
return ..()
@@ -0,0 +1,7 @@
/mob/living/key_down(_key, client/user)
switch(_key)
if("B")
resist()
return
return ..()
+145
View File
@@ -0,0 +1,145 @@
// Technically the client argument is unncessary here since that SHOULD be src.client but let's not assume things
// All it takes is one badmin setting their focus to someone else's client to mess things up
// 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)
switch(_key)
if("Delete")
if(!pulling)
to_chat(src, "<span class='notice'>You are not pulling anything.</span>")
else
stop_pulling()
return
if("Insert", "G")
a_intent_change(INTENT_HOTKEY_RIGHT)
return
if("F")
a_intent_change(INTENT_HOTKEY_LEFT)
return
if("X", "Northeast") // Northeast is Page-up
swap_hand()
return
if("Y", "W", "Southeast") // Southeast is Page-down
mode() // attack_self(). No idea who came up with "mode()"
return
if("A", "Northwest") // Northwest is Home
var/obj/item/I = get_active_hand()
if(!I)
to_chat(src, "<span class='warning'>You have nothing to drop in your hand!</span>")
else
drop_item(I)
return
if("E")
quick_equip()
return
if("Alt")
toggle_move_intent()
return
else
switch(_key)
if("Delete")
if(!pulling)
to_chat(src, "<span class='notice'>You are not pulling anything.</span>")
else
stop_pulling()
return
if("Insert", "G")
a_intent_change(INTENT_HOTKEY_RIGHT)
return
if("F")
a_intent_change(INTENT_HOTKEY_LEFT)
return
if("X", "Northeast") // Northeast is Page-up
swap_hand()
return
if("Y", "Z", "Southeast") // Southeast is Page-down
mode() // attack_self(). No idea who came up with "mode()"
return
if("Q", "Northwest") // Northwest is Home
var/obj/item/I = get_active_hand()
if(!I)
to_chat(src, "<span class='warning'>You have nothing to drop in your hand!</span>")
else
drop_item(I)
return
if("E")
quick_equip()
return
if("Alt")
toggle_move_intent()
return
//Bodypart selections
if(client.prefs.toggles & NUMPAD_TARGET)
switch(_key)
if("Numpad8")
user.body_toggle_head()
return
if("Numpad4")
user.body_r_arm()
return
if("Numpad5")
user.body_chest()
return
if("Numpad6")
user.body_l_arm()
return
if("Numpad1")
user.body_r_leg()
return
if("Numpad2")
user.body_groin()
return
if("Numpad3")
user.body_l_leg()
return
else
switch(_key)
if("Numpad1")
a_intent_change("help")
return
if("Numpad2")
a_intent_change("disarm")
return
if("Numpad3")
a_intent_change("grab")
return
if("Numpad4")
a_intent_change("harm")
return
if(client.keys_held["Ctrl"] && client.prefs.toggles & AZERTY)
switch(SSinput.alt_movement_keys[_key])
if(NORTH)
northface()
return
if(SOUTH)
southface()
return
if(WEST)
westface()
return
if(EAST)
eastface()
return
else if(client.keys_held["Ctrl"])
switch(SSinput.movement_keys[_key])
if(NORTH)
northface()
return
if(SOUTH)
southface()
return
if(WEST)
westface()
return
if(EAST)
eastface()
return
return ..()
/mob/key_up(_key, client/user)
switch(_key)
if("Alt")
toggle_move_intent()
return
return ..()
@@ -0,0 +1,20 @@
/mob/living/silicon/robot/key_down(_key, client/user)
switch(_key)
if("1", "2", "3")
toggle_module(text2num(_key))
return
if("4")
a_intent_change(INTENT_HOTKEY_LEFT)
return
if("X")
cycle_modules()
return
if("Q")
if(!(client.prefs.toggles & AZERTY))
uneq_active()
return
if("A")
if(client.prefs.toggles & AZERTY)
uneq_active()
return
return ..()
+8
View File
@@ -0,0 +1,8 @@
/mob
var/datum/focus //What receives our keyboard inputs. src by default
/mob/proc/set_focus(datum/new_focus)
if(focus == new_focus)
return
focus = new_focus
reset_perspective(focus) //Maybe this should be done manually? You figure it out, reader
+42
View File
@@ -0,0 +1,42 @@
# In-code keypress handling system
This whole system is heavily based off of forum_account's keyboard library.
Thanks to forum_account for saving the day, the library can be found
[here](https://secure.byond.com/developer/Forum_account/Keyboard)!
.dmf macros have some very serious shortcomings. For example, they do not allow reusing parts
of one macro in another, so giving cyborgs their own shortcuts to swap active module couldn't
inherit the movement that all mobs should have anyways. The webclient only supports one macro,
so having more than one was problematic. Additionally each keybind has to call an actual
verb, which meant a lot of hidden verbs that just call one other proc. Also our existing
macro was really bad and tied unrelated behavior into `Northeast()`, `Southeast()`, `Northwest()`,
and `Southwest()`.
The basic premise of this system is to not screw with .dmf macro setup at all and handle
pressing those keys in the code instead. We have every key call `client.keyDown()`
or `client.keyUp()` with the pressed key as an argument. Certain keys get processed
directly by the client because they should be doable at any time, then we call
`keyDown()` or `keyUp()` on the client's holder and the client's mob's focus.
By default `mob.focus` is the mob itself, but you can set it to any datum to give control of a
client's keypresses to another object. This would be a good way to handle a menu or driving
a mech. You can also set it to null to disregard input from a certain user.
Movement is handled by having each client call `client.keyLoop()` every game tick.
As above, this calls holder and `focus.keyLoop()`. `atom/movable/keyLoop()` handles movement
Try to keep the calculations in this proc light. It runs every tick for every client after all!
You can also tell which keys are being held down now. Each client a list of keys pressed called
`keys_held`. Each entry is a key as a text string associated with the world.time when it was
pressed.
No client-set keybindings at this time, but it shouldn't be too hard if someone wants.
Notes about certain keys:
* `Tab` has client-sided behavior but acts normally
* `T`, `O`, and `M` move focus to the input when pressed. This fires the keyUp macro right away.
* `\` needs to be escaped in the dmf so any usage is `\\`
You cannot `TICK_CHECK` or check `world.tick_usage` inside of procs called by key down and up
events. They happen outside of a byond tick and have no meaning there. Key looping
works correctly since it's part of a subsystem, not direct input.
+46
View File
@@ -0,0 +1,46 @@
/client
var/list/keys_held = list() // A list of any keys held currently
// These next two vars are to apply movement for keypresses and releases made while move delayed.
// Because discarding that input makes the game less responsive.
var/next_move_dir_add // On next move, add this dir to the move that would otherwise be done
var/next_move_dir_sub // On next move, subtract this dir from the move that would otherwise be done
// Set a client's focus to an object and override these procs on that object to let it handle keypresses
/datum/proc/key_down(key, client/user) // Called when a key is pressed down initially
return
/datum/proc/key_up(key, client/user) // Called when a key is released
return
/datum/proc/keyLoop(client/user) // Called once every frame
set waitfor = FALSE
return
// removes all the existing macros
/client/proc/erase_all_macros()
var/list/macro_sets = params2list(winget(src, null, "macros"))
var/erase_output = ""
for(var/i in 1 to macro_sets.len)
var/setname = macro_sets[i]
var/list/macro_set = params2list(winget(src, "[setname].*", "command")) // The third arg doesnt matter here as we're just removing them all
for(var/k in 1 to macro_set.len)
var/list/split_name = splittext(macro_set[k], ".")
var/macro_name = "[split_name[1]].[split_name[2]]" // [3] is "command"
erase_output = "[erase_output];[macro_name].parent=null"
winset(src, null, erase_output)
/client/proc/set_macros()
set waitfor = FALSE
erase_all_macros()
var/list/macro_sets = SSinput.macro_sets
for(var/i in 1 to macro_sets.len)
var/setname = macro_sets[i]
if(setname != "default")
winclone(src, "default", setname)
var/list/macro_set = macro_sets[setname]
for(var/k in 1 to macro_set.len)
var/key = macro_set[k]
var/command = macro_set[key]
winset(src, "[setname]-\ref[key]", "parent=[setname];name=[key];command=[command]")
winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED] mainwindow.macro=old_default")
+1 -1
View File
@@ -151,7 +151,7 @@
/obj/structure/closet/crate/secure/loot/attack_hand(mob/user)
if(locked)
to_chat(user, "<span class='notice'>The crate is locked with a Deca-code lock.</span>")
var/input = input(usr, "Enter [codelen] digits.", "Deca-Code Lock", "") as text
var/input = clean_input("Enter [codelen] digits.", "Deca-Code Lock", "")
if(in_range(src, user))
if(input == code)
to_chat(user, "<span class='notice'>The crate unlocks!</span>")
@@ -238,6 +238,9 @@
/obj/machinery/smartfridge/survival_pod/accept_check(obj/item/O)
return isitem(O)
/obj/machinery/smartfridge/survival_pod/default_unfasten_wrench()
return FALSE
/obj/machinery/smartfridge/survival_pod/empty
name = "dusty survival pod storage"
desc = "A heated storage unit. This one's seen better days."
+2
View File
@@ -474,7 +474,9 @@
new /datum/data/mining_equipment("Royal Cape of the Liberator", /obj/item/bedsheet/rd/royal_cape, 500),
new /datum/data/mining_equipment("Grey Slime Extract", /obj/item/slime_extract/grey, 1000),
new /datum/data/mining_equipment("KA Trigger Modification Kit", /obj/item/borg/upgrade/modkit/trigger_guard, 1000),
new /datum/data/mining_equipment("Shuttle Console Board", /obj/item/circuitboard/shuttle/golem_ship, 2000),
new /datum/data/mining_equipment("The Liberator's Legacy", /obj/item/storage/box/rndboards, 2000)
)
/datum/data/mining_equipment
+43 -43
View File
@@ -1,44 +1,44 @@
/****************Explorer's Suit and Mask****************/
/obj/item/clothing/suit/hooded/explorer
name = "explorer suit"
desc = "An armoured suit for exploring harsh environments."
icon_state = "explorer"
item_state = "explorer"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
hoodtype = /obj/item/clothing/head/hooded/explorer
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50)
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
resistance_flags = FIRE_PROOF
hide_tail_by_species = list("Vox" , "Vulpkanin" , "Unathi" , "Tajaran")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/suit.dmi',
"Drask" = 'icons/mob/species/drask/suit.dmi',
"Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
"Unathi" = 'icons/mob/species/unathi/suit.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/suit.dmi'
)
/obj/item/clothing/head/hooded/explorer
name = "explorer hood"
desc = "An armoured hood for exploring harsh environments."
icon_state = "explorer"
item_state = "explorer"
body_parts_covered = HEAD
flags = BLOCKHAIR | NODROP
flags_cover = HEADCOVERSEYES
min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50)
resistance_flags = FIRE_PROOF
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/head.dmi',
"Drask" = 'icons/mob/species/drask/head.dmi',
"Grey" = 'icons/mob/species/grey/head.dmi',
"Skrell" = 'icons/mob/species/skrell/head.dmi'
/****************Explorer's Suit and Mask****************/
/obj/item/clothing/suit/hooded/explorer
name = "explorer suit"
desc = "An armoured suit for exploring harsh environments."
icon_state = "explorer"
item_state = "explorer"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
hoodtype = /obj/item/clothing/head/hooded/explorer
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50)
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
resistance_flags = FIRE_PROOF
hide_tail_by_species = list("Vox" , "Vulpkanin" , "Unathi" , "Tajaran")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/suit.dmi',
"Drask" = 'icons/mob/species/drask/suit.dmi',
"Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
"Unathi" = 'icons/mob/species/unathi/suit.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/suit.dmi'
)
/obj/item/clothing/head/hooded/explorer
name = "explorer hood"
desc = "An armoured hood for exploring harsh environments."
icon_state = "explorer"
item_state = "explorer"
body_parts_covered = HEAD
flags = BLOCKHAIR | NODROP
flags_cover = HEADCOVERSEYES
min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50)
resistance_flags = FIRE_PROOF
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/head.dmi',
"Drask" = 'icons/mob/species/drask/head.dmi',
"Grey" = 'icons/mob/species/grey/head.dmi',
"Skrell" = 'icons/mob/species/skrell/head.dmi'
)
+133 -129
View File
@@ -1,3 +1,5 @@
GLOBAL_LIST(labor_sheet_values)
/**********************Prisoners' Console**************************/
/obj/machinery/mineral/labor_claim_console
@@ -5,153 +7,153 @@
desc = "A stacking console with an electromagnetic writer, used to track ore mined by prisoners."
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "console"
density = 0
anchored = 1
var/obj/machinery/mineral/stacking_machine/laborstacker/machine = null
density = FALSE
var/obj/machinery/mineral/stacking_machine/laborstacker/stacking_machine = null
var/machinedir = SOUTH
var/obj/item/card/id/prisoner/inserted_id
var/obj/machinery/door/airlock/release_door
var/door_tag = "prisonshuttle"
var/use_release_door = 0
var/obj/item/radio/intercom/announcer
/obj/machinery/mineral/labor_claim_console/New()
..()
/obj/machinery/mineral/labor_claim_console/Initialize()
. = ..()
announcer = new /obj/item/radio/intercom(null)
announcer.config(list("Security" = 0))
locate_stacking_machine()
spawn(7)
src.machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
var/t
for(var/obj/machinery/door/airlock/d in range(5,src))
t = d.id_tag
if(t == src.door_tag)
src.release_door = d
if(machine && (release_door || !use_release_door))
machine.CONSOLE = src
if(!GLOB.labor_sheet_values)
var/sheet_list = list()
for(var/sheet_type in subtypesof(/obj/item/stack/sheet))
var/obj/item/stack/sheet/sheet = sheet_type
if(!initial(sheet.point_value) || (initial(sheet.merge_type) && initial(sheet.merge_type) != sheet_type)) //ignore no-value sheets and x/fifty subtypes
continue
sheet_list += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value)))
GLOB.labor_sheet_values = sheet_list
/obj/machinery/mineral/labor_claim_console/Destroy()
. = ..()
QDEL_NULL(announcer)
/proc/cmp_sheet_list(list/a, list/b)
return a["value"] - b["value"]
/obj/machinery/mineral/labor_claim_console/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/card/id/prisoner))
if(!inserted_id)
if(!user.unEquip(I))
return
I.forceMove(src)
inserted_id = I
to_chat(user, "<span class='notice'>You insert [I].</span>")
SSnanoui.update_uis(src)
return
else
qdel(src)
to_chat(user, "<span class='notice'>There's an ID inserted already.</span>")
return ..()
/obj/machinery/mineral/labor_claim_console/attack_hand(mob/user)
ui_interact(user)
/obj/machinery/mineral/labor_claim_console/attack_ghost(mob/user)
attack_hand(user)
/obj/machinery/mineral/labor_claim_console/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "labor_claim_console.tmpl", name, 450, 625, state)
ui.open()
/obj/machinery/mineral/labor_claim_console/ui_data(mob/user)
var/list/data = list()
var/can_go_home = FALSE
data["emagged"] = (emagged) ? TRUE : FALSE
if(inserted_id)
data["id"] = inserted_id
data["id_name"] = inserted_id.registered_name
data["points"] = inserted_id.points
data["goal"] = inserted_id.goal
if(check_auth())
can_go_home = TRUE
if(stacking_machine)
data["unclaimed_points"] = stacking_machine.points
data["ores"] = GLOB.labor_sheet_values
data["can_go_home"] = can_go_home
return data
/obj/machinery/mineral/labor_claim_console/Topic(href, href_list)
if(..())
return TRUE
if(href_list["handle_id"])
if(inserted_id)
if(!usr.put_in_hands(inserted_id))
inserted_id.forceMove(get_turf(src))
inserted_id = null
else
var/obj/item/I = usr.get_active_hand()
if(istype(I, /obj/item/card/id/prisoner))
if(!usr.unEquip(I))
return
I.forceMove(src)
inserted_id = I
if(href_list["claim_points"])
inserted_id.points += stacking_machine.points
stacking_machine.points = 0
to_chat(usr, "Points transferred.")
if(href_list["move_shuttle"])
if(!alone_in_area(get_area(src), usr))
to_chat(usr, "<span class='warning'>Prisoners are only allowed to be released while alone.</span>")
else
switch(SSshuttle.moveShuttle("laborcamp", "laborcamp_home", TRUE))
if(1)
to_chat(usr, "<span class='notice'>Shuttle not found.</span>")
if(2)
to_chat(usr, "<span class='notice'>Shuttle already at station.</span>")
if(3)
to_chat(usr, "<span class='notice'>No permission to dock could be granted.</span>")
else
if(!(emagged))
var/message = "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval."
announcer.autosay(message, "Labor Camp Controller", "Security")
to_chat(usr, "<span class='notice'>Shuttle received message and will be sent shortly.</span>")
return TRUE
/obj/machinery/mineral/labor_claim_console/proc/check_auth()
if(emagged) return 1 //Shuttle is emagged, let any ol' person through
if(emagged)
return TRUE //Shuttle is emagged, let any ol' person through
return (istype(inserted_id) && inserted_id.points >= inserted_id.goal) //Otherwise, only let them out if the prisoner's reached his quota.
/obj/machinery/mineral/labor_claim_console/proc/locate_stacking_machine()
stacking_machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
if(stacking_machine)
stacking_machine.CONSOLE = src
else
qdel(src)
/obj/machinery/mineral/labor_claim_console/attack_hand(user as mob)
var/dat
dat += text("<b>Point Claim Console</b><br><br>")
if(emagged) //Shit's broken
dat += text("<b>QU&#t0A In%aL*D</b><br>")
else if(istype(inserted_id)) //There's an ID in there.
dat += text("ID: [inserted_id.registered_name] <A href='?src=[UID()];choice=eject'>Eject ID.</A><br>")
dat += text("Points Collected:[inserted_id.points]<br>")
dat += text("Point Quota: [inserted_id.goal] - Reach your quota to earn your release<br>")
dat += text("Unclaimed Collection Points: [machine.points]. <A href='?src=[UID()];choice=claim'>Claim points.</A><br>")
else //No ID in sight. Complain about it.
dat += text("No ID inserted. <A href='?src=[UID()];choice=insert'>Insert ID.</A><br>")
if(check_auth())
dat += text("<A href='?src=[UID()];choice=station'>Proceed to station.</A><br>")
if(use_release_door)
dat += text("<A href='?src=[UID()];choice=release'>Open release door.</A><br>")
if(machine)
dat += text("<HR><b>Mineral Value List:</b><BR>[machine.get_ore_values()]")
user << browse("[dat]", "window=console_stacking_machine")
/obj/machinery/mineral/labor_claim_console/attackby(obj/item/I as obj, mob/user as mob, params)
if(istype(I, /obj/item/card/id))
return attack_hand(user)
..()
/obj/machinery/mineral/labor_claim_console/emag_act(user as mob)
emag(user)
/obj/machinery/mineral/labor_claim_console/proc/emag(mob/user as mob)
if(!emagged)
emagged = 1
/obj/machinery/mineral/labor_claim_console/emag_act(mob/user)
if(!(emagged))
emagged = TRUE
to_chat(user, "<span class='warning'>PZZTTPFFFT</span>")
/obj/machinery/mineral/labor_claim_console/Topic(href, href_list)
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["choice"])
if(istype(inserted_id)) //Sanity check against href spoofs
if(href_list["choice"] == "eject")
inserted_id.loc = loc
inserted_id.verb_pickup()
inserted_id = null
if(href_list["choice"] == "claim")
inserted_id.points += machine.points
machine.points = 0
to_chat(src, "Points transferred.")
else if(href_list["choice"] == "insert")
var/obj/item/card/id/prisoner/I = usr.get_active_hand()
if(istype(I))
usr.drop_item()
I.loc = src
inserted_id = I
else
to_chat(usr, "<span class='warning'>Invalid ID.</span>")
if(check_auth()) //Sanity check against hef spoofs
if(href_list["choice"] == "station")
if(!alone_in_area(get_area(src), usr))
to_chat(usr, "<span class='warning'>Prisoners are only allowed to be released while alone.</span>")
else
switch(SSshuttle.moveShuttle("laborcamp","laborcamp_home"))
if(1)
to_chat(usr, "<span class='notice'>Shuttle not found</span>")
if(2)
to_chat(usr, "<span class='notice'>Shuttle already at station</span>")
if(3)
to_chat(usr, "<span class='notice'>No permission to dock could be granted.</span>")
else
var/message = "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval."
announcer.autosay(message, "Labor Camp Controller", "Security")
to_chat(usr, "<span class='notice'>Shuttle received message and will be sent shortly.</span>")
if(href_list["choice"] == "release")
if(alone_in_area(get_area(loc), usr))
var/obj/docking_port/stationary/S = SSshuttle.getDock("laborcamp_home")
if(S && S.get_docked())
if(release_door && release_door.density)
release_door.open()
else
to_chat(usr, "<span class='warning'>Prisoners can only be released while docked with the station.</span>")
else
to_chat(usr, "<span class='warning'>Prisoners are only allowed to be released while alone.</span>")
src.updateUsrDialog()
return
/**********************Prisoner Collection Unit**************************/
/obj/machinery/mineral/stacking_machine/laborstacker
var/points = 0 //The unclaimed value of ore stacked. Value for each ore loosely relative to its rarity.
var/list/ore_values = list(("glass" = 1), ("metal" = 2), ("solid plasma" = 20), ("plasteel" = 23), ("reinforced glass" = 4), ("gold" = 20), ("silver" = 20), ("uranium" = 20), ("diamond" = 25), ("bananium" = 50), ("tranquillite" = 50))
/obj/machinery/mineral/stacking_machine/laborstacker/proc/get_ore_values()
var/dat = "<table border='0' width='200'>"
for(var/ore in ore_values)
var/value = ore_values[ore]
dat += "<tr><td>[capitalize(ore)]</td><td>[value]</td></tr>"
dat += "</table>"
return dat
var/points = 0 //The unclaimed value of ore stacked.
/obj/machinery/mineral/stacking_machine/laborstacker/process_sheet(obj/item/stack/sheet/inp)
if(istype(inp))
var/n = inp.name
var/a = inp.amount
if(n in ore_values)
points += ore_values[n] * a
points += inp.point_value * inp.amount
..()
/obj/machinery/mineral/stacking_machine/laborstacker/attackby(obj/item/I, mob/living/user)
if(istype(I, /obj/item/stack/sheet) && user.canUnEquip(I))
var/obj/item/stack/sheet/inp = I
points += inp.point_value * inp.amount
return ..()
/**********************Point Lookup Console**************************/
/obj/machinery/mineral/labor_points_checker
@@ -159,13 +161,15 @@
desc = "A console used by prisoners to check the progress on their quotas. Simply swipe a prisoner ID."
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "console"
density = 0
anchored = 1
density = FALSE
/obj/machinery/mineral/labor_points_checker/attack_hand(mob/user)
user.examine(src)
. = ..()
if(.)
return
user.examinate(src)
/obj/machinery/mineral/labor_points_checker/attackby(obj/item/I as obj, mob/user as mob, params)
/obj/machinery/mineral/labor_points_checker/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/card/id))
if(istype(I, /obj/item/card/id/prisoner))
var/obj/item/card/id/prisoner/prisoner_id = I
@@ -175,5 +179,5 @@
to_chat(user, "<span class='notice'>Collect points by bringing smelted minerals to the Labor Shuttle stacking machine. Reach your quota to earn your release.</span>")
else
to_chat(user, "<span class='warning'>Error: Invalid ID</span>")
return
..()
else
return ..()
+12 -1
View File
@@ -27,6 +27,17 @@
if(prob(15))
harvest(null, TRUE)
/obj/structure/flora/ash/ex_act(severity, target)
switch(severity)
if(1)
qdel(src)
if(2)
if(prob(80))
qdel(src)
if(3)
if(prob(50))
qdel(src)
/obj/structure/flora/ash/proc/harvest(user, no_drop)
if(harvested)
return 0
@@ -137,7 +148,7 @@
regrowth_time_low = 4800
regrowth_time_high = 7200
/obj/structure/flora/ash/cacti/Crossed(mob/AM)
/obj/structure/flora/ash/cacti/Crossed(mob/AM, oldloc)
if(ishuman(AM) && has_gravity(loc) && prob(70))
var/mob/living/carbon/human/H = AM
if(!H.shoes && !H.lying) //ouch, my feet.
@@ -12,8 +12,12 @@
/obj/structure/closet/crate/necropolis/tendril
desc = "It's watching you suspiciously."
/obj/structure/closet/crate/necropolis/tendril/New()
/obj/structure/closet/crate/necropolis/tendril/New(add_loot = TRUE)
..()
if(!add_loot)
return
var/loot = rand(1,24)
switch(loot)
if(1)
@@ -35,7 +39,7 @@
if(8)
new /obj/item/organ/internal/brain/xeno(src)
if(9)
new /obj/item/organ/internal/heart/cursed(src)
new /obj/item/organ/internal/heart/cursed/wizard(src)
if(10)
new /obj/item/ship_in_a_bottle(src)
if(11)
@@ -68,4 +72,19 @@
new /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor(src)
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor(src)
if(24)
new /obj/item/spellbook/oneuse/summonitem(src)
new /obj/item/spellbook/oneuse/summonitem(src)
/obj/structure/closet/crate/necropolis/puzzle
name = "puzzling chest"
/obj/structure/closet/crate/necropolis/puzzle/New()
..(FALSE)
var/loot = rand(1,3)
switch(loot)
if(1)
new /obj/item/soulstone/anybody(src)
if(2)
new /obj/item/wisp_lantern(src)
if(3)
new /obj/item/prisoncube(src)
+7 -1
View File
@@ -31,7 +31,7 @@
else if(W.isOn())
to_chat(user, "<span class='info'>Not enough fuel to smelt [src].</span>")
/obj/item/stack/ore/Crossed(atom/movable/AM)
/obj/item/stack/ore/Crossed(atom/movable/AM, oldloc)
var/obj/item/storage/bag/ore/OB
var/turf/simulated/floor/F = get_turf(src)
if(loc != F)
@@ -50,6 +50,12 @@
break
if(OB && istype(F, /turf/simulated/floor/plating/asteroid))
F.attackby(OB, AM)
// Then, if the user is dragging an ore box, empty the satchel
// into the box.
var/mob/living/L = AM
if(istype(L.pulling, /obj/structure/ore_box))
var/obj/structure/ore_box/box = L.pulling
box.attackby(OB, AM)
return ..()
/obj/item/stack/ore/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
+4 -5
View File
@@ -263,7 +263,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
..()
statpanel("Status")
if(client.statpanel == "Status")
show_stat_station_time()
show_stat_emergency_shuttle_eta()
stat(null, "Respawnability: [(src in GLOB.respawnable_list) ? "Yes" : "No"]")
@@ -406,7 +405,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
A.on_close(CALLBACK(src, .proc/teleport))
/mob/dead/observer/proc/teleport(area/thearea)
if(!thearea)
if(!thearea || !isobserver(usr))
return
var/list/L = list()
@@ -417,7 +416,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(usr, "<span class='warning'>No area available.</span>")
return
usr.forceMove(pick(L))
forceMove(pick(L))
following = null
/mob/dead/observer/verb/follow()
@@ -431,7 +430,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
// This is the ghost's follow verb with an argument
/mob/dead/observer/proc/ManualFollow(var/atom/movable/target)
if(!target)
if(!target || !isobserver(usr))
return
if(!get_turf(target))
@@ -505,7 +504,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
A.on_close(CALLBACK(src, .proc/jump_to_mob))
/mob/dead/observer/proc/jump_to_mob(mob/M)
if(!M)
if(!M || !isobserver(usr))
return
var/mob/A = src //Source mob
var/turf/T = get_turf(M) //Turf of the destination mob
+10 -9
View File
@@ -58,19 +58,20 @@
if(message)
log_emote(message, src)
//Hearing gasp and such every five seconds is not good emotes were not global for a reason.
// Maybe some people are okay with that.
// Hearing gasp and such every five seconds is not good emotes were not global for a reason.
// Maybe some people are okay with that.
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue //skip monkeys and leavers
if(istype(M, /mob/new_player))
continue
if(findtext(message," snores.")) //Because we have so many sleeping people.
break
if(M.stat == DEAD && M.get_preference(CHAT_GHOSTSIGHT) && !(M in viewers(src,null)))
M.show_message(message)
if(isnewplayer(M))
continue
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.
M.show_message(message)
// Type 1 (Visual) emotes are sent to anyone in view of the item
if(m_type & EMOTE_VISUAL)
+2 -4
View File
@@ -63,10 +63,10 @@
var/datum/gas_mixture/environment = T.return_air()
var/pressure = environment ? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE && get_dist(speaker, src) > 1)
return 0
return FALSE
if(pressure < ONE_ATMOSPHERE * 0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
italics = 1
italics = TRUE
sound_vol *= 0.5
if(sleeping || stat == UNCONSCIOUS)
@@ -87,8 +87,6 @@
var/track = null
if(isobserver(src))
if(italics && client.prefs.toggles & CHAT_GHOSTRADIO)
return
if(speaker_name != speaker.real_name && speaker.real_name)
speaker_name = "[speaker.real_name] ([speaker_name])"
track = "([ghost_follow_link(speaker, ghost=src)]) "
+9
View File
@@ -6,6 +6,14 @@
if(hand) return l_hand
else return r_hand
/mob/verb/quick_equip()
set name = "quick-equip"
set hidden = 1
var/obj/item/I = get_active_hand()
if(I)
I.equip_to_best_slot(src)
/mob/proc/is_in_active_hand(obj/item/I)
var/obj/item/item_to_test = get_active_hand()
@@ -254,3 +262,4 @@
if(slot_r_hand)
return r_hand
return null
+13 -8
View File
@@ -455,6 +455,7 @@
colour = "alien"
key = "y"
flags = RESTRICTED | HIVEMIND
follow = TRUE
/datum/language/wryn/check_special_condition(mob/other)
var/mob/living/carbon/M = other
@@ -485,7 +486,7 @@
colour = "alien"
key = "a"
flags = RESTRICTED | HIVEMIND
follow = 1
follow = TRUE
/datum/language/terrorspider
name = "Spider Hivemind"
@@ -496,7 +497,7 @@
colour = "terrorspider"
key = "ts"
flags = RESTRICTED | HIVEMIND
follow = 1
follow = TRUE
/datum/language/ling
name = "Changeling"
@@ -505,10 +506,11 @@
colour = "changeling"
key = "g"
flags = RESTRICTED | HIVEMIND
follow = TRUE
/datum/language/ling/broadcast(mob/living/speaker, message, speaker_mask)
if(speaker.mind && speaker.mind.changeling)
..(speaker,message,speaker.mind.changeling.changelingID)
..(speaker, message, speaker.mind.changeling.changelingID)
else if(speaker.mind && speaker.mind.linglink)
..()
else
@@ -521,6 +523,7 @@
colour = "shadowling"
key = "8"
flags = RESTRICTED | HIVEMIND
follow = TRUE
/datum/language/shadowling/broadcast(mob/living/speaker, message, speaker_mask)
if(speaker.mind && speaker.mind.special_role == SPECIAL_ROLE_SHADOWLING)
@@ -539,6 +542,7 @@
colour = "abductor"
key = "zw" //doesn't matter, this is their default and only language
flags = RESTRICTED | HIVEMIND
follow = TRUE
/datum/language/abductor/broadcast(mob/living/speaker, message, speaker_mask)
..(speaker,message,speaker.real_name)
@@ -567,6 +571,7 @@
colour = "alien"
key = "bo"
flags = RESTRICTED | HIVEMIND
follow = TRUE
/datum/language/corticalborer/broadcast(mob/living/speaker, message, speaker_mask)
var/mob/living/simple_animal/borer/B
@@ -590,7 +595,7 @@
exclaim_verb = "declares"
key = "b"
flags = RESTRICTED | HIVEMIND
follow = 1
follow = TRUE
var/drone_only
/datum/language/binary/broadcast(mob/living/speaker, message, speaker_mask)
@@ -636,8 +641,8 @@
colour = "say_quote"
key = "d"
flags = RESTRICTED | HIVEMIND
drone_only = 1
follow = 1
drone_only = TRUE
follow = TRUE
/datum/language/drone
name = "Drone"
@@ -647,7 +652,7 @@
exclaim_verb = "declares"
key = "]"
flags = RESTRICTED
follow = 1
follow = TRUE
syllables = list ("beep", "boop")
/datum/language/swarmer
@@ -659,7 +664,7 @@
colour = "say_quote"
key = "z"//Zwarmer...Or Zerg!
flags = RESTRICTED | HIVEMIND
follow = 1
follow = TRUE
// Language handling.
/mob/proc/add_language(language)
@@ -73,7 +73,11 @@
stat = CONSCIOUS
return
health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss()
update_stat("updatehealth([reason])")
med_hud_set_health()
med_hud_set_status()
handle_hud_icons_health()
/mob/living/carbon/alien/handle_environment(var/datum/gas_mixture/environment)
@@ -17,7 +17,7 @@
. = -1 //hunters are sanic
. += ..() //but they still need to slow down on stun
/mob/living/carbon/alien/humanoid/hunter/handle_regular_hud_updates()
/mob/living/carbon/alien/humanoid/hunter/handle_hud_icons_health()
..() //-Yvarov
if(healths)
@@ -42,7 +42,7 @@
alien_organs += new /obj/item/organ/internal/xenos/neurotoxin
..()
/mob/living/carbon/alien/humanoid/sentinel/handle_regular_hud_updates()
/mob/living/carbon/alien/humanoid/sentinel/handle_hud_icons_health()
..() //-Yvarov
if(healths)
@@ -48,29 +48,26 @@
alien_organs += new /obj/item/organ/internal/xenos/neurotoxin
..()
/mob/living/carbon/alien/humanoid/empress
/mob/living/carbon/alien/humanoid/empress/handle_hud_icons_health()
..() //-Yvarov
handle_regular_hud_updates()
..() //-Yvarov
if(src.healths)
if(src.stat != 2)
switch(health)
if(250 to INFINITY)
src.healths.icon_state = "health0"
if(175 to 250)
src.healths.icon_state = "health1"
if(100 to 175)
src.healths.icon_state = "health2"
if(50 to 100)
src.healths.icon_state = "health3"
if(0 to 50)
src.healths.icon_state = "health4"
else
src.healths.icon_state = "health5"
else
src.healths.icon_state = "health6"
if(healths)
if(stat != 2)
switch(health)
if(250 to INFINITY)
healths.icon_state = "health0"
if(175 to 250)
healths.icon_state = "health1"
if(100 to 175)
healths.icon_state = "health2"
if(50 to 100)
healths.icon_state = "health3"
if(0 to 50)
healths.icon_state = "health4"
else
healths.icon_state = "health5"
else
healths.icon_state = "health6"
/mob/living/carbon/alien/humanoid/empress/verb/lay_egg()
set name = "Lay Egg (250)"
@@ -32,7 +32,7 @@
. = ..()
. += 3
/mob/living/carbon/alien/humanoid/queen/handle_regular_hud_updates()
/mob/living/carbon/alien/humanoid/queen/handle_hud_icons_health()
..() //-Yvarov
if(healths)
@@ -72,7 +72,7 @@ var/const/MAX_ACTIVE_TIME = 400
/obj/item/clothing/mask/facehugger/equipped(mob/M)
Attach(M)
/obj/item/clothing/mask/facehugger/Crossed(atom/target)
/obj/item/clothing/mask/facehugger/Crossed(atom/target, oldloc)
HasProximity(target)
return
@@ -95,7 +95,6 @@ I'm using this for Stat to give it a more nifty interface to work with
..()
if(has_synthetic_assistance())
statpanel("Status")
show_stat_station_time()
show_stat_emergency_shuttle_eta()
if(client.statpanel == "Status")
+1
View File
@@ -975,6 +975,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
to_chat(src, "<span class='notice'>You [slipVerb]ped on [description]!</span>")
playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
// Something something don't run with scissors
moving_diagonally = 0 //If this was part of diagonal move slipping will stop it.
Stun(stun)
Weaken(weaken)
return 1
@@ -671,9 +671,9 @@
if(!restrained())
var/t1 = round(text2num(param))
if(isnum(t1))
if(t1 <= 5 && (!r_hand || !l_hand))
if(t1 <= 5 && t1 >= 1 && (!r_hand || !l_hand))
message = "<B>[src]</B> raises [t1] finger\s."
else if(t1 <= 10 && (!r_hand && !l_hand))
else if(t1 <= 10 && t1 >= 1 && (!r_hand && !l_hand))
message = "<B>[src]</B> raises [t1] finger\s."
m_type = 1
@@ -946,9 +946,13 @@
// Maybe some people are okay with that.
for(var/mob/M in GLOB.dead_mob_list)
if(!M.client || istype(M, /mob/new_player))
continue //skip monkeys, leavers and new players
if(M.stat == DEAD && M.get_preference(CHAT_GHOSTSIGHT) && !(M in viewers(src,null)))
if(!M.client)
continue
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.
M.show_message(message)
switch(m_type)
@@ -338,18 +338,9 @@
msg += "[p_they(TRUE)] [p_are()] mostly dessicated now, with only bones remaining of what used to be a person.\n"
if(hasHUD(user,"security"))
var/perpname = "wot"
var/perpname = get_visible_name(TRUE)
var/criminal = "None"
if(wear_id)
var/obj/item/card/id/I = wear_id.GetID()
if(I)
perpname = I.registered_name
else
perpname = name
else
perpname = name
if(perpname)
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
@@ -361,18 +352,9 @@
msg += "<span class = 'deptradio'>Security records:</span> <a href='?src=[UID()];secrecord=`'>\[View\]</a> <a href='?src=[UID()];secrecordadd=`'>\[Add comment\]</a>\n"
if(hasHUD(user,"medical"))
var/perpname = "wot"
var/perpname = get_visible_name(TRUE)
var/medical = "None"
if(wear_id)
if(istype(wear_id,/obj/item/card/id))
perpname = wear_id:registered_name
else if(istype(wear_id,/obj/item/pda))
var/obj/item/pda/tempPda = wear_id
perpname = tempPda.owner
else
perpname = src.name
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.general)
+18 -81
View File
@@ -162,8 +162,6 @@
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
show_stat_station_time()
show_stat_emergency_shuttle_eta()
if(client.statpanel == "Status")
@@ -455,7 +453,7 @@
popup.open()
/mob/living/carbon/human/Crossed(atom/movable/AM)
/mob/living/carbon/human/Crossed(atom/movable/AM, oldloc)
var/mob/living/simple_animal/bot/mulebot/MB = AM
if(istype(MB))
MB.RunOver(src)
@@ -713,17 +711,9 @@
if(usr.incapacitated())
return
var/found_record = 0
var/perpname = "wot"
if(wear_id)
var/obj/item/card/id/I = wear_id.GetID()
if(I)
perpname = I.registered_name
else
perpname = name
else
perpname = name
var/perpname = get_visible_name(TRUE)
if(perpname)
if(perpname != "Unknown")
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.security)
@@ -760,17 +750,9 @@
if(hasHUD(usr,"security"))
if(usr.incapacitated())
return
var/perpname = "wot"
var/perpname = get_visible_name(TRUE)
var/read = 0
if(wear_id)
if(istype(wear_id,/obj/item/card/id))
perpname = wear_id:registered_name
else if(istype(wear_id,/obj/item/pda))
var/obj/item/pda/tempPda = wear_id
perpname = tempPda.owner
else
perpname = src.name
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.security)
@@ -792,24 +774,16 @@
if(hasHUD(usr,"security"))
if(usr.incapacitated())
return
var/perpname = "wot"
var/perpname = get_visible_name(TRUE)
var/read = 0
if(wear_id)
if(istype(wear_id,/obj/item/card/id))
perpname = wear_id:registered_name
else if(istype(wear_id,/obj/item/pda))
var/obj/item/pda/tempPda = wear_id
perpname = tempPda.owner
else
perpname = src.name
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.security)
if(R.fields["id"] == E.fields["id"])
if(hasHUD(usr,"security"))
read = 1
if(length(R.fields["comments"]))
if(LAZYLEN(R.fields["comments"]))
for(var/c in R.fields["comments"])
to_chat(usr, c)
else
@@ -823,15 +797,8 @@
if(hasHUD(usr,"security"))
if(usr.incapacitated())
return
var/perpname = "wot"
if(wear_id)
if(istype(wear_id,/obj/item/card/id))
perpname = wear_id:registered_name
else if(istype(wear_id,/obj/item/pda))
var/obj/item/pda/tempPda = wear_id
perpname = tempPda.owner
else
perpname = src.name
var/perpname = get_visible_name(TRUE)
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.security)
@@ -854,17 +821,8 @@
if(hasHUD(usr,"medical"))
if(usr.incapacitated())
return
var/perpname = "wot"
var/modified = 0
if(wear_id)
if(istype(wear_id,/obj/item/card/id))
perpname = wear_id:registered_name
else if(istype(wear_id,/obj/item/pda))
var/obj/item/pda/tempPda = wear_id
perpname = tempPda.owner
else
perpname = src.name
var/perpname = get_visible_name(TRUE)
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
@@ -889,17 +847,9 @@
if(hasHUD(usr,"medical"))
if(usr.incapacitated())
return
var/perpname = "wot"
var/read = 0
if(wear_id)
if(istype(wear_id,/obj/item/card/id))
perpname = wear_id:registered_name
else if(istype(wear_id,/obj/item/pda))
var/obj/item/pda/tempPda = wear_id
perpname = tempPda.owner
else
perpname = src.name
var/perpname = get_visible_name(TRUE)
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.medical)
@@ -922,24 +872,16 @@
if(hasHUD(usr,"medical"))
if(usr.incapacitated())
return
var/perpname = "wot"
var/perpname = get_visible_name(TRUE)
var/read = 0
if(wear_id)
if(istype(wear_id,/obj/item/card/id))
perpname = wear_id:registered_name
else if(istype(wear_id,/obj/item/pda))
var/obj/item/pda/tempPda = wear_id
perpname = tempPda.owner
else
perpname = src.name
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.medical)
if(R.fields["id"] == E.fields["id"])
if(hasHUD(usr,"medical"))
read = 1
if(length(R.fields["comments"]))
if(LAZYLEN(R.fields["comments"]))
for(var/c in R.fields["comments"])
to_chat(usr, c)
else
@@ -953,15 +895,7 @@
if(hasHUD(usr,"medical"))
if(usr.incapacitated())
return
var/perpname = "wot"
if(wear_id)
if(istype(wear_id,/obj/item/card/id))
perpname = wear_id:registered_name
else if(istype(wear_id,/obj/item/pda))
var/obj/item/pda/tempPda = wear_id
perpname = tempPda.owner
else
perpname = src.name
var/perpname = get_visible_name(TRUE)
for(var/datum/data/record/E in data_core.general)
if(E.fields["name"] == perpname)
for(var/datum/data/record/R in data_core.medical)
@@ -976,6 +910,9 @@
if(isrobot(usr))
var/mob/living/silicon/robot/U = usr
R.fields["comments"] += "Made by [U.name] ([U.modtype] [U.braintype]) on [current_date_string] [station_time_timestamp()]<BR>[t1]"
if(isAI(usr))
var/mob/living/silicon/ai/U = usr
R.fields["comments"] += "Made by [U.name] (artificial intelligence) on [current_date_string] [station_time_timestamp()]<BR>[t1]"
if(href_list["lookitem"])
var/obj/item/I = locate(href_list["lookitem"])
@@ -1608,7 +1545,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
//Check for arrest warrant
if(judgebot.check_records)
var/perpname = get_face_name(get_id_name())
var/perpname = get_visible_name(TRUE)
var/datum/data/record/R = find_record("name", perpname, data_core.security)
if(R && R.fields["criminal"])
switch(R.fields["criminal"])
@@ -1,11 +1,3 @@
/mob/living/carbon/human/verb/quick_equip()
set name = "quick-equip"
set hidden = 1
var/obj/item/I = get_active_hand()
if(I)
I.equip_to_best_slot(src)
/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/W, list/slots, del_on_fail = 1)
for(var/slot in slots)
if(equip_to_slot_if_possible(W, slots[slot], del_on_fail = 0))
@@ -341,9 +341,6 @@
if(SKELETON in target.mutations)
to_chat(user, "<span class='warning'>There is no blood in a skeleton!</span>")
return
if(issmall(target) && !target.ckey) //Monkeyized humans are okay, humanized monkeys are okay, NPC monkeys are not.
to_chat(user, "<span class='warning'>Blood from a monkey is useless!</span>")
return
//we're good to suck the blood, blaah
user.mind.vampire.handle_bloodsucking(target)
add_attack_logs(user, target, "vampirebit")
@@ -603,20 +600,37 @@
H.healthdoll.cached_healthdoll_overlays = new_overlays
/datum/species/proc/handle_hud_icons_nutrition(mob/living/carbon/human/H)
switch(H.nutrition)
if(NUTRITION_LEVEL_FULL to INFINITY)
H.throw_alert("nutrition", /obj/screen/alert/fat)
if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
H.throw_alert("nutrition", /obj/screen/alert/full)
if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
H.throw_alert("nutrition", /obj/screen/alert/well_fed)
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
H.throw_alert("nutrition", /obj/screen/alert/fed)
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
H.throw_alert("nutrition", /obj/screen/alert/hungry)
else
H.throw_alert("nutrition", /obj/screen/alert/starving)
return 1
if(H.mind && H.mind.vampire && (H.mind in SSticker.mode.vampires)) //Vampires
switch(H.nutrition)
if(NUTRITION_LEVEL_FULL to INFINITY)
H.throw_alert("nutrition", /obj/screen/alert/fat/vampire)
if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
H.throw_alert("nutrition", /obj/screen/alert/full/vampire)
if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
H.throw_alert("nutrition", /obj/screen/alert/well_fed/vampire)
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
H.throw_alert("nutrition", /obj/screen/alert/fed/vampire)
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
H.throw_alert("nutrition", /obj/screen/alert/hungry/vampire)
else
H.throw_alert("nutrition", /obj/screen/alert/starving/vampire)
return 1
else ///Any other non-vampires
switch(H.nutrition)
if(NUTRITION_LEVEL_FULL to INFINITY)
H.throw_alert("nutrition", /obj/screen/alert/fat)
if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
H.throw_alert("nutrition", /obj/screen/alert/full)
if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
H.throw_alert("nutrition", /obj/screen/alert/well_fed)
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
H.throw_alert("nutrition", /obj/screen/alert/fed)
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
H.throw_alert("nutrition", /obj/screen/alert/hungry)
else
H.throw_alert("nutrition", /obj/screen/alert/starving)
return 1
/*
Returns the path corresponding to the corresponding organ
@@ -675,7 +689,7 @@ It'll return null if the organ doesn't correspond, so include null checks when u
H.see_invisible = G.invis_override
else
H.see_invisible = min(G.invis_view, H.see_invisible)
if(!isnull(G.lighting_alpha))
H.lighting_alpha = min(G.lighting_alpha, H.lighting_alpha)
+1 -2
View File
@@ -59,8 +59,7 @@
handle_status_effects() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc
if(client)
//regular_hud_updates() //THIS DOESN'T FUCKING UPDATE SHIT
handle_regular_hud_updates() //IT JUST REMOVES FUCKING HUD IMAGES
handle_regular_hud_updates()
..()
+1 -1
View File
@@ -528,7 +528,7 @@
return
var/pull_dir = get_dir(src, pulling)
if(get_dist(src, pulling) > 1 || ((pull_dir - 1) & pull_dir)) // puller and pullee more than one tile away or in diagonal position
if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir))) // puller and pullee more than one tile away or in diagonal position
if(isliving(pulling))
var/mob/living/M = pulling
if(M.lying && !M.buckled && (prob(M.getBruteLoss() * 200 / M.maxHealth)))
+34 -19
View File
@@ -216,7 +216,7 @@ proc/get_radio_key_from_channel(var/channel)
message_range = 1
if(pressure < ONE_ATMOSPHERE * 0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
italics = 1
italics = TRUE
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
var/list/hear = hear(message_range, T)
@@ -236,12 +236,20 @@ proc/get_radio_key_from_channel(var/channel)
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue //skip monkeys and leavers
continue
if(isnewplayer(M))
continue
if(M.stat == DEAD && M.client && M.get_preference(CHAT_GHOSTEARS) && client) // client is so that ghosts don't have to listen to mice
listening |= M
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.
listening |= M
continue
if(message_range < world.view && (get_dist(T, M) <= world.view))
listening |= M
continue
if(get_turf(M) in hearturfs)
listening |= M
@@ -291,10 +299,13 @@ proc/get_radio_key_from_channel(var/channel)
log_emote(message, src)
for(var/mob/M in GLOB.dead_mob_list)
if(!M.client || istype(M, /mob/new_player))
continue //skip monkeys, leavers and new players //who the hell knows why new players are in the dead mob list
if(!M.client)
continue //skip monkeys and leavers
if(M.stat == DEAD && M.get_preference(CHAT_GHOSTSIGHT) && !(M in viewers(src,null)))
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.
M.show_message(message)
switch(type)
@@ -380,7 +391,7 @@ proc/get_radio_key_from_channel(var/channel)
var/list/hearturfs = list()
//Pass whispers on to anything inside the immediate listeners.
// Pass whispers on to anything inside the immediate listeners.
// This comes before the ghosts do so that ghosts don't act as whisper relays
for(var/atom/L in listening)
if(ismob(L))
@@ -391,22 +402,26 @@ proc/get_radio_key_from_channel(var/channel)
if(isobj(L))
hearturfs += get_turf(L)
//ghosts
for(var/mob/M in GLOB.dead_mob_list) //does this include players who joined as observers as well?
// Loop through all players to see if they need to hear it.
for(var/mob/M in GLOB.player_list)
if(!M.client)
continue
if(M.stat == DEAD && M.client && M.get_preference(CHAT_GHOSTEARS))
listening |= M
// This, in tandem with "hearturfs", lets nested mobs hear whispers that are in range
// Grifted from saycode above.
for(var/mob/M in GLOB.player_list)
if(!M.client || isnewplayer(M))
continue //skip monkeys and leavers
if(isnewplayer(M))
continue
if(isobserver(M))
if(M.get_preference(CHAT_GHOSTEARS)) // The client check is so that ghosts don't have to listen to mice.
listening |= M
continue
if(message_range < world.view && (get_dist(whisper_loc, M) <= world.view))
listening |= M
continue
if(get_turf(M) in hearturfs)
listening |= M
//pass on the message to objects that can hear us.
for(var/obj/O in view(message_range, whisper_loc))
spawn(0)
+6 -6
View File
@@ -498,7 +498,7 @@ var/list/ai_verbs_default = list(
if(check_unable(AI_CHECK_WIRELESS))
return
var/input = input(usr, "Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","") as text|null
var/input = clean_input("Please enter the reason for calling the shuttle.", "Shuttle Call Reason.","")
if(!input || stat)
return
@@ -634,7 +634,7 @@ var/list/ai_verbs_default = list(
return
if(href_list["trackbot"])
var/mob/living/simple_animal/bot/target = locate(href_list["trackbot"]) in GLOB.simple_animals
var/mob/living/simple_animal/bot/target = locate(href_list["trackbot"]) in GLOB.bots_list
if(target)
ai_actual_track(target)
else
@@ -642,7 +642,7 @@ var/list/ai_verbs_default = list(
return
if(href_list["callbot"]) //Command a bot to move to a selected location.
Bot = locate(href_list["callbot"]) in GLOB.simple_animals
Bot = locate(href_list["callbot"]) in GLOB.bots_list
if(!Bot || Bot.remote_disabled || control_disabled)
return //True if there is no bot found, the bot is manually emagged, or the AI is carded with wireless off.
waypoint_mode = 1
@@ -650,7 +650,7 @@ var/list/ai_verbs_default = list(
return
if(href_list["interface"]) //Remotely connect to a bot!
Bot = locate(href_list["interface"]) in GLOB.simple_animals
Bot = locate(href_list["interface"]) in GLOB.bots_list
if(!Bot || Bot.remote_disabled || control_disabled)
return
Bot.attack_ai(src)
@@ -746,7 +746,7 @@ var/list/ai_verbs_default = list(
d += "<A HREF=?src=[UID()];botrefresh=\ref[Bot]>Query network status</A><br>"
d += "<table width='100%'><tr><td width='40%'><h3>Name</h3></td><td width='20%'><h3>Status</h3></td><td width='30%'><h3>Location</h3></td><td width='10%'><h3>Control</h3></td></tr>"
for(var/mob/living/simple_animal/bot/Bot in GLOB.simple_animals)
for(var/mob/living/simple_animal/bot/Bot in GLOB.bots_list)
if(is_ai_allowed(Bot.z) && !Bot.remote_disabled) //Only non-emagged bots on the allowed Z-level are detected!
bot_area = get_area(Bot)
d += "<tr><td width='30%'>[Bot.hacked ? "<span class='bad'>(!) </span>[Bot.name]" : Bot.name] ([Bot.model])</td>"
@@ -1074,7 +1074,7 @@ var/list/ai_verbs_default = list(
set desc = "Change the message that's transmitted when a new crew member arrives on station."
set category = "AI Commands"
var/newmsg = input("What would you like the arrival message to be? List of options: $name, $rank, $species, $gender, $age", "Change Arrival Message", arrivalmsg) as text
var/newmsg = clean_input("What would you like the arrival message to be? List of options: $name, $rank, $species, $gender, $age", "Change Arrival Message", arrivalmsg)
if(newmsg != arrivalmsg)
arrivalmsg = newmsg
to_chat(usr, "The arrival message has been successfully changed.")
+1 -1
View File
@@ -99,7 +99,7 @@ var/const/VOX_PATH = "sound/vox_fem/"
to_chat(src, "<span class='warning'>Please wait [round((announcing_vox - world.time) / 10)] seconds.</span>")
return
var/message = input(src, "WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", last_announcement) as text|null
var/message = clean_input("WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", last_announcement, src)
last_announcement = message
@@ -2,6 +2,3 @@
..()
regenerate_icons()
show_laws(0)
var/datum/hotkey_mode/cyborg/C = new(src)
C.set_winset_values()
@@ -1456,4 +1456,4 @@ var/list/robot_verbs_default = list(
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
@@ -156,7 +156,6 @@
/mob/living/silicon/Stat()
..()
if(statpanel("Status"))
show_stat_station_time()
show_stat_emergency_shuttle_eta()
show_system_integrity()
@@ -48,7 +48,7 @@
..()
light_color = LIGHT_COLOR_PURE_RED //if you see a red one. RUN!!
/mob/living/simple_animal/bot/secbot/griefsky/Crossed(atom/movable/AM)
/mob/living/simple_animal/bot/secbot/griefsky/Crossed(atom/movable/AM, oldloc)
..()
if(ismob(AM) && AM == target)
var/mob/living/carbon/C = AM
@@ -298,7 +298,7 @@
target = user
mode = BOT_HUNT
/mob/living/simple_animal/bot/honkbot/Crossed(atom/movable/AM)
/mob/living/simple_animal/bot/honkbot/Crossed(atom/movable/AM, oldloc)
if(ismob(AM) && on) //only if its online
if(prob(30)) //you're far more likely to trip on a honkbot
var/mob/living/carbon/C = AM
@@ -439,7 +439,7 @@ Auto Patrol: []"},
target = user
mode = BOT_HUNT
/mob/living/simple_animal/bot/secbot/Crossed(atom/movable/AM)
/mob/living/simple_animal/bot/secbot/Crossed(atom/movable/AM, oldloc)
if(ismob(AM) && target)
var/mob/living/carbon/C = AM
if(!istype(C) || !C || in_range(src, target))
@@ -24,7 +24,7 @@
/mob/living/simple_animal/cockroach/can_die()
return ..() && !SSticker.cinematic //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
/mob/living/simple_animal/cockroach/Crossed(var/atom/movable/AM)
/mob/living/simple_animal/cockroach/Crossed(var/atom/movable/AM, oldloc)
if(isliving(AM))
var/mob/living/A = AM
if(A.mob_size > MOB_SIZE_SMALL)
@@ -91,7 +91,7 @@
to_chat(src, "<span class='warning'>You are too small to pull anything.</span>")
return
/mob/living/simple_animal/mouse/Crossed(AM as mob|obj)
/mob/living/simple_animal/mouse/Crossed(AM as mob|obj, oldloc)
if(ishuman(AM))
if(!stat)
var/mob/M = AM
@@ -16,6 +16,10 @@
turns_per_move = 10
icon = 'icons/mob/penguins.dmi'
/mob/living/simple_animal/pet/penguin/Initialize(mapload)
. = ..()
AddComponent(/datum/component/waddling)
/mob/living/simple_animal/pet/penguin/emperor
name = "Emperor penguin"
real_name = "penguin"

Some files were not shown because too many files have changed in this diff Show More