mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-13 08:03:43 +01:00
Merge remote-tracking branch 'upstream/master' into refactor-spawning-from-vents
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#define MAX_ADMIN_BANS_PER_ADMIN 1
|
||||
|
||||
datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = -1, var/reason, var/job = "", var/rounds = 0, var/banckey = null, var/banip = null, var/bancid = null)
|
||||
/datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = -1, var/reason, var/job = "", var/rounds = 0, var/banckey = null, var/banip = null, var/bancid = null)
|
||||
|
||||
if(!check_rights(R_BAN)) return
|
||||
|
||||
@@ -153,7 +153,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
|
||||
else
|
||||
flag_account_for_forum_sync(ckey)
|
||||
|
||||
datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
|
||||
/datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
|
||||
|
||||
if(!check_rights(R_BAN)) return
|
||||
|
||||
@@ -233,7 +233,7 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
|
||||
else
|
||||
flag_account_for_forum_sync(ckey)
|
||||
|
||||
datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
|
||||
/datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
|
||||
|
||||
if(!check_rights(R_BAN)) return
|
||||
|
||||
@@ -297,9 +297,10 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null)
|
||||
to_chat(usr, "Cancelled")
|
||||
return
|
||||
|
||||
datum/admins/proc/DB_ban_unban_by_id(var/id)
|
||||
/datum/admins/proc/DB_ban_unban_by_id(var/id)
|
||||
|
||||
if(!check_rights(R_BAN)) return
|
||||
if(!check_rights(R_BAN))
|
||||
return
|
||||
|
||||
var/sql = "SELECT ckey FROM [format_table_name("ban")] WHERE id = [id]"
|
||||
|
||||
@@ -343,9 +344,9 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
|
||||
/client/proc/DB_ban_panel()
|
||||
set category = "Admin"
|
||||
set name = "Banning Panel"
|
||||
set desc = "Edit admin permissions"
|
||||
set desc = "DB Ban Panel"
|
||||
|
||||
if(!holder)
|
||||
if(!check_rights(R_BAN))
|
||||
return
|
||||
|
||||
holder.DB_ban_panel()
|
||||
@@ -356,7 +357,8 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
|
||||
if(!usr.client)
|
||||
return
|
||||
|
||||
if(!check_rights(R_BAN)) return
|
||||
if(!check_rights(R_BAN))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//Blocks an attempt to connect before even creating our client datum thing.
|
||||
world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE)
|
||||
/world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE)
|
||||
|
||||
if(!config.ban_legacy_system)
|
||||
if(address)
|
||||
@@ -36,17 +36,6 @@ world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE)
|
||||
// message_admins("<span class='notice'>Failed Login: [key] - Guests not allowed</span>")
|
||||
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.")
|
||||
|
||||
//check if the IP address is a known Tor node
|
||||
if(config.ToRban && ToRban_isbanned(address))
|
||||
log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned: Tor")
|
||||
message_admins("<span class='adminnotice'>Failed Login: [key] - Banned: Tor</span>")
|
||||
//ban their computer_id and ckey for posterity
|
||||
AddBan(ckey(key), computer_id, "Use of Tor", "Automated Ban", 0, 0)
|
||||
var/mistakemessage = ""
|
||||
if(config.banappeals)
|
||||
mistakemessage = "\nIf you believe this is a mistake, please request help at [config.banappeals]."
|
||||
return list("reason"="using Tor", "desc"="\nReason: The network you are using to connect has been banned.[mistakemessage]")
|
||||
|
||||
//check if the IP address is a known proxy/vpn, and the user is not whitelisted
|
||||
if(check_ipintel && config.ipintel_email && config.ipintel_whitelist && ipintel_is_banned(key, address))
|
||||
log_adminwarn("Failed Login: [key] [computer_id] [address] - Proxy/VPN")
|
||||
|
||||
@@ -103,7 +103,8 @@ GLOBAL_PROTECT(banlist_savefile) // Obvious reasons
|
||||
|
||||
GLOB.banlist_savefile.cd = "/base"
|
||||
if( GLOB.banlist_savefile.dir.Find("[ckey][computerid]") )
|
||||
to_chat(usr, "<span class='danger'>Ban already exists.</span>")
|
||||
if(usr)
|
||||
to_chat(usr, "<span class='danger'>Ban already exists.</span>")
|
||||
return 0
|
||||
else
|
||||
GLOB.banlist_savefile.dir.Add("[ckey][computerid]")
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
//By Carnwennan
|
||||
//fetches an external list and processes it into a list of ip addresses.
|
||||
//It then stores the processed list into a savefile for later use
|
||||
#define TORFILE "data/ToR_ban.bdb"
|
||||
#define TOR_UPDATE_INTERVAL 216000 //~6 hours
|
||||
|
||||
/proc/ToRban_isbanned(var/ip_address)
|
||||
var/savefile/F = new(TORFILE)
|
||||
if(F)
|
||||
if( ip_address in F.dir )
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/ToRban_autoupdate()
|
||||
var/savefile/F = new(TORFILE)
|
||||
if(F)
|
||||
var/last_update
|
||||
F["last_update"] >> last_update
|
||||
if((last_update + TOR_UPDATE_INTERVAL) < world.realtime) //we haven't updated for a while
|
||||
ToRban_update()
|
||||
return
|
||||
|
||||
/proc/ToRban_update()
|
||||
spawn(0)
|
||||
log_world("Downloading updated ToR data...")
|
||||
var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses")
|
||||
|
||||
var/list/rawlist = file2list(http["CONTENT"])
|
||||
if(rawlist.len)
|
||||
fdel(TORFILE)
|
||||
var/savefile/F = new(TORFILE)
|
||||
for( var/line in rawlist )
|
||||
if(!line) continue
|
||||
if( copytext(line,1,12) == "ExitAddress" )
|
||||
var/cleaned = copytext(line,13,length(line)-19)
|
||||
if(!cleaned) continue
|
||||
F[cleaned] << 1
|
||||
to_chat(F["last_update"], world.realtime)
|
||||
log_world("ToR data updated!")
|
||||
if(usr)
|
||||
to_chat(usr, "ToRban updated.")
|
||||
return 1
|
||||
log_world("ToR data update aborted: no data.")
|
||||
return 0
|
||||
|
||||
/client/proc/ToRban(task in list("update","toggle","show","remove","remove all","find"))
|
||||
set name = "ToRban"
|
||||
set category = "Server"
|
||||
if(!holder) return
|
||||
switch(task)
|
||||
if("update")
|
||||
ToRban_update()
|
||||
if("toggle")
|
||||
if(config)
|
||||
if(config.ToRban)
|
||||
config.ToRban = 0
|
||||
message_admins("<font color='red'>ToR banning disabled.</font>")
|
||||
else
|
||||
config.ToRban = 1
|
||||
message_admins("<font colot='green'>ToR banning enabled.</font>")
|
||||
if("show")
|
||||
var/savefile/F = new(TORFILE)
|
||||
var/dat
|
||||
if( length(F.dir) )
|
||||
for( var/i=1, i<=length(F.dir), i++ )
|
||||
dat += "<tr><td>#[i]</td><td> [F.dir[i]]</td></tr>"
|
||||
dat = "<table width='100%'>[dat]</table>"
|
||||
else
|
||||
dat = "No addresses in list."
|
||||
src << browse(dat,"window=ToRban_show")
|
||||
if("remove")
|
||||
var/savefile/F = new(TORFILE)
|
||||
var/choice = input(src,"Please select an IP address to remove from the ToR banlist:","Remove ToR ban",null) as null|anything in F.dir
|
||||
if(choice)
|
||||
F.dir.Remove(choice)
|
||||
to_chat(src, "<b>Address removed</b>")
|
||||
if("remove all")
|
||||
to_chat(src, "<b>[TORFILE] was [fdel(TORFILE)?"":"not "]removed.</b>")
|
||||
if("find")
|
||||
var/input = input(src,"Please input an IP address to search for:","Find ToR ban",null) as null|text
|
||||
if(input)
|
||||
if(ToRban_isbanned(input))
|
||||
to_chat(src, "<font color='green'><b>Address is a known ToR address</b></font>")
|
||||
else
|
||||
to_chat(src, "<font color='red'><b>Address is not a known ToR address</b></font>")
|
||||
return
|
||||
|
||||
#undef TORFILE
|
||||
#undef TOR_UPDATE_INTERVAL
|
||||
+42
-33
@@ -20,22 +20,39 @@ GLOBAL_VAR_INIT(nologevent, 0)
|
||||
if(C.prefs.atklog <= loglevel)
|
||||
to_chat(C, msg)
|
||||
|
||||
|
||||
/proc/message_adminTicket(var/msg, var/alt = FALSE)
|
||||
if(alt)
|
||||
msg = "<span class=admin_channel>ADMIN TICKET: [msg]</span>"
|
||||
else
|
||||
msg = "<span class=adminticket><span class='prefix'>ADMIN TICKET:</span> [msg]</span>"
|
||||
/**
|
||||
* Sends a message to the staff able to see admin tickets
|
||||
* Arguments:
|
||||
* msg - The message being send
|
||||
* important - If the message is important. If TRUE it will ignore the CHAT_NO_TICKETLOGS preferences,
|
||||
send a sound and flash the window. Defaults to FALSE
|
||||
*/
|
||||
/proc/message_adminTicket(msg, important = FALSE)
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(R_ADMIN & C.holder.rights)
|
||||
if(C.prefs && !(C.prefs.toggles & CHAT_NO_TICKETLOGS))
|
||||
if(important || (C.prefs && !(C.prefs.toggles & CHAT_NO_TICKETLOGS)))
|
||||
to_chat(C, msg)
|
||||
if(important)
|
||||
if(C.prefs?.sound & SOUND_ADMINHELP)
|
||||
SEND_SOUND(C, 'sound/effects/adminhelp.ogg')
|
||||
window_flash(C)
|
||||
|
||||
/proc/message_mentorTicket(var/msg)
|
||||
/**
|
||||
* Sends a message to the staff able to see mentor tickets
|
||||
* Arguments:
|
||||
* msg - The message being send
|
||||
* important - If the message is important. If TRUE it will ignore the CHAT_NO_TICKETLOGS preferences,
|
||||
send a sound and flash the window. Defaults to FALSE
|
||||
*/
|
||||
/proc/message_mentorTicket(msg, important = FALSE)
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(check_rights(R_ADMIN | R_MENTOR | R_MOD, 0, C.mob))
|
||||
if(C.prefs && !(C.prefs.toggles & CHAT_NO_MENTORTICKETLOGS))
|
||||
if(important || (C.prefs && !(C.prefs.toggles & CHAT_NO_MENTORTICKETLOGS)))
|
||||
to_chat(C, msg)
|
||||
if(important)
|
||||
if(C.prefs?.sound & SOUND_MENTORHELP)
|
||||
SEND_SOUND(C, 'sound/effects/adminhelp.ogg')
|
||||
window_flash(C)
|
||||
|
||||
/proc/admin_ban_mobsearch(var/mob/M, var/ckey_to_find, var/mob/admin_to_notify)
|
||||
if(!M || !M.ckey)
|
||||
@@ -69,7 +86,10 @@ GLOBAL_VAR_INIT(nologevent, 0)
|
||||
body += "<body>Options panel for <b>[M]</b>"
|
||||
if(M.client)
|
||||
body += " played by <b>[M.client]</b> "
|
||||
body += "\[<A href='?_src_=holder;editrights=rank;ckey=[M.ckey]'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\] "
|
||||
if(check_rights(R_PERMISSIONS, 0))
|
||||
body += "\[<A href='?_src_=holder;editrights=rank;ckey=[M.ckey]'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\] "
|
||||
else
|
||||
body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\] "
|
||||
body += "\[<A href='?_src_=holder;getplaytimewindow=[M.UID()]'>" + M.client.get_exp_type(EXP_TYPE_CREW) + " as [EXP_TYPE_CREW]</a>\]"
|
||||
|
||||
if(isnewplayer(M))
|
||||
@@ -78,10 +98,11 @@ GLOBAL_VAR_INIT(nologevent, 0)
|
||||
body += " \[<A href='?_src_=holder;revive=[M.UID()]'>Heal</A>\] "
|
||||
|
||||
body += "<br><br>\[ "
|
||||
body += "<a href='?_src_=holder;open_logging_view=[M.UID()];'>LOGS</a> - "
|
||||
body += "<a href='?_src_=vars;Vars=[M.UID()]'>VV</a> - "
|
||||
body += "[ADMIN_TP(M,"TP")] - "
|
||||
if(M.client)
|
||||
body += "<a href='?src=[usr.UID()];priv_msg=[M.client.UID()]'>PM</a> - "
|
||||
body += "<a href='?src=[usr.UID()];priv_msg=[M.client.ckey]'>PM</a> - "
|
||||
body += "[ADMIN_SM(M,"SM")] - "
|
||||
if(ishuman(M) && M.mind)
|
||||
body += "<a href='?_src_=holder;HeadsetMessage=[M.UID()]'>HM</a> -"
|
||||
@@ -109,17 +130,18 @@ GLOBAL_VAR_INIT(nologevent, 0)
|
||||
else
|
||||
body += "<A href='?_src_=holder;watchadd=[M.ckey]'>Add to Watchlist</A> "
|
||||
|
||||
if(M.client)
|
||||
body += "| <A href='?_src_=holder;sendtoprison=[M.UID()]'>Prison</A> | "
|
||||
body += "\ <A href='?_src_=holder;sendbacktolobby=[M.UID()]'>Send back to Lobby</A> | "
|
||||
body += "\ <A href='?_src_=holder;eraseflavortext=[M.UID()]'>Erase Flavor Text</A> | "
|
||||
body += "\ <A href='?_src_=holder;userandomname=[M.UID()]'>Use Random Name</A> | "
|
||||
var/muted = M.client.prefs.muted
|
||||
body += {"<br><b>Mute: </b>
|
||||
\[<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_IC]'><font color='[(muted & MUTE_IC)?"red":"blue"]'>IC</font></a> |
|
||||
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_OOC]'><font color='[(muted & MUTE_OOC)?"red":"blue"]'>OOC</font></a> |
|
||||
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_PRAY]'><font color='[(muted & MUTE_PRAY)?"red":"blue"]'>PRAY</font></a> |
|
||||
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ADMINHELP]'><font color='[(muted & MUTE_ADMINHELP)?"red":"blue"]'>ADMINHELP</font></a> |
|
||||
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_DEADCHAT]'><font color='[(muted & MUTE_DEADCHAT)?"red":"blue"]'>DEADCHAT</font></a>\]
|
||||
(<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ALL]'><font color='[(muted & MUTE_ALL)?"red":"blue"]'>toggle all</font></a>)
|
||||
\[<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_IC]'><font color='[(muted & MUTE_IC)?"red":"#6685f5"]'>IC</font></a> |
|
||||
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_OOC]'><font color='[(muted & MUTE_OOC)?"red":"#6685f5"]'>OOC</font></a> |
|
||||
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_PRAY]'><font color='[(muted & MUTE_PRAY)?"red":"#6685f5"]'>PRAY</font></a> |
|
||||
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ADMINHELP]'><font color='[(muted & MUTE_ADMINHELP)?"red":"#6685f5"]'>ADMINHELP</font></a> |
|
||||
<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_DEADCHAT]'><font color='[(muted & MUTE_DEADCHAT)?"red":"#6685f5"]'>DEADCHAT</font></a>\]
|
||||
(<A href='?_src_=holder;mute=[M.UID()];mute_type=[MUTE_ALL]'><font color='[(muted & MUTE_ALL)?"red":"#6685f5"]'>toggle all</font></a>)
|
||||
"}
|
||||
|
||||
var/jumptoeye = ""
|
||||
@@ -280,7 +302,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
|
||||
/datum/admins/proc/vpn_whitelist()
|
||||
set category = "Admin"
|
||||
set name = "VPN Ckey Whitelist"
|
||||
if(!check_rights(R_ADMIN))
|
||||
if(!check_rights(R_BAN))
|
||||
return
|
||||
var/key = stripped_input(usr, "Enter ckey to add/remove, or leave blank to cancel:", "VPN Whitelist add/remove", max_length=32)
|
||||
if(key)
|
||||
@@ -699,7 +721,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
|
||||
var/msg = ""
|
||||
if(SSticker.current_state == GAME_STATE_STARTUP)
|
||||
msg = " (The server is still setting up, but the round will be started as soon as possible.)"
|
||||
message_admins("<font color='blue'>[usr.key] has started the game.[msg]</font>")
|
||||
message_admins("<span class='darkmblue'>[usr.key] has started the game.[msg]</span>")
|
||||
feedback_add_details("admin_verb","SN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return 1
|
||||
else
|
||||
@@ -760,19 +782,6 @@ GLOBAL_VAR_INIT(nologevent, 0)
|
||||
world.update_status()
|
||||
feedback_add_details("admin_verb","TR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/datum/admins/proc/toggle_aliens()
|
||||
set category = "Event"
|
||||
set desc="Toggle alien mobs"
|
||||
set name="Toggle Aliens"
|
||||
|
||||
if(!check_rights(R_EVENT))
|
||||
return
|
||||
|
||||
GLOB.aliens_allowed = !GLOB.aliens_allowed
|
||||
log_admin("[key_name(usr)] toggled aliens to [GLOB.aliens_allowed].")
|
||||
message_admins("[key_name_admin(usr)] toggled aliens [GLOB.aliens_allowed ? "on" : "off"].")
|
||||
feedback_add_details("admin_verb","TA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/datum/admins/proc/delay()
|
||||
set category = "Server"
|
||||
set desc="Delay the game start/end"
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
/client/proc/investigate_show( subject in GLOB.investigate_log_subjects )
|
||||
set name = "Investigate"
|
||||
set category = "Admin"
|
||||
if(!holder) return
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
switch(subject)
|
||||
if("notes")
|
||||
show_note()
|
||||
|
||||
@@ -10,11 +10,8 @@ GLOBAL_LIST_INIT(admin_verbs_default, list(
|
||||
GLOBAL_LIST_INIT(admin_verbs_admin, list(
|
||||
/client/proc/check_antagonists, /*shows all antags*/
|
||||
/datum/admins/proc/show_player_panel,
|
||||
/client/proc/player_panel, /*shows an interface for all players, with links to various panels (old style)*/
|
||||
/client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/
|
||||
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
|
||||
/datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/
|
||||
/datum/admins/proc/toggleguests, /*toggles whether guests can join the current game*/
|
||||
/datum/admins/proc/announce, /*priority announce something to all clients.*/
|
||||
/client/proc/colorooc, /*allows us to set a custom colour for everything we say in ooc*/
|
||||
/client/proc/resetcolorooc, /*allows us to set a reset our ooc color*/
|
||||
@@ -23,7 +20,6 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
|
||||
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
|
||||
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
|
||||
/client/proc/cmd_admin_pm_by_key_panel, /*admin-pm list by key*/
|
||||
/client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/
|
||||
/client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
|
||||
/client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/
|
||||
/client/proc/cmd_admin_open_logging_view,
|
||||
@@ -37,6 +33,7 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
|
||||
/client/proc/jumptoturf, /*allows us to jump to a specific turf*/
|
||||
/client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/
|
||||
/client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcomm*/
|
||||
/client/proc/admin_deny_shuttle, /*toggles availability of shuttle calling*/
|
||||
/client/proc/check_ai_laws, /*shows AI and borg laws*/
|
||||
/client/proc/manage_silicon_laws, /* Allows viewing and editing silicon laws. */
|
||||
/client/proc/admin_memo, /*admin memo system. show/delete/write. +SERVER needed to delete admin memos of others*/
|
||||
@@ -54,36 +51,30 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
|
||||
/datum/admins/proc/PlayerNotes,
|
||||
/client/proc/cmd_mentor_say,
|
||||
/datum/admins/proc/show_player_notes,
|
||||
/datum/admins/proc/vpn_whitelist,
|
||||
/client/proc/free_slot, /*frees slot for chosen job*/
|
||||
/client/proc/toggleattacklogs,
|
||||
/client/proc/toggleadminlogs,
|
||||
/client/proc/toggledebuglogs,
|
||||
/client/proc/update_mob_sprite,
|
||||
/client/proc/toggledrones,
|
||||
/client/proc/man_up,
|
||||
/client/proc/global_man_up,
|
||||
/client/proc/delbook,
|
||||
/client/proc/view_flagged_books,
|
||||
/client/proc/view_asays,
|
||||
/client/proc/empty_ai_core_toggle_latejoin,
|
||||
/client/proc/aooc,
|
||||
/client/proc/freeze,
|
||||
/client/proc/alt_check,
|
||||
/client/proc/secrets,
|
||||
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
|
||||
/client/proc/change_human_appearance_self, /* Allows the human-based mob itself to change its basic appearance */
|
||||
/client/proc/debug_variables,
|
||||
/client/proc/reset_all_tcs, /*resets all telecomms scripts*/
|
||||
/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_afks,
|
||||
/client/proc/cmd_admin_headset_message,
|
||||
/client/proc/spawn_floor_cluwne
|
||||
/client/proc/list_ssds_afks
|
||||
))
|
||||
GLOBAL_LIST_INIT(admin_verbs_ban, list(
|
||||
/client/proc/unban_panel,
|
||||
/client/proc/jobbans,
|
||||
/client/proc/stickybanpanel
|
||||
/client/proc/ban_panel,
|
||||
/client/proc/stickybanpanel,
|
||||
/datum/admins/proc/vpn_whitelist
|
||||
))
|
||||
GLOBAL_LIST_INIT(admin_verbs_sounds, list(
|
||||
/client/proc/play_local_sound,
|
||||
@@ -99,7 +90,6 @@ GLOBAL_LIST_INIT(admin_verbs_event, list(
|
||||
/client/proc/drop_bomb,
|
||||
/client/proc/cinematic,
|
||||
/client/proc/one_click_antag,
|
||||
/datum/admins/proc/toggle_aliens,
|
||||
/client/proc/cmd_admin_add_freeform_ai_law,
|
||||
/client/proc/cmd_admin_add_random_ai_law,
|
||||
/client/proc/make_sound,
|
||||
@@ -109,6 +99,7 @@ GLOBAL_LIST_INIT(admin_verbs_event, list(
|
||||
/client/proc/show_tip,
|
||||
/client/proc/cmd_admin_change_custom_event,
|
||||
/datum/admins/proc/access_news_network, /*allows access of newscasters*/
|
||||
/client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/
|
||||
/client/proc/cmd_admin_direct_narrate, /*send text directly to a player with no padding. Useful for narratives and fluff-text*/
|
||||
/client/proc/cmd_admin_world_narrate, /*sends text to all players with no padding*/
|
||||
/client/proc/response_team, // Response Teams admin verb
|
||||
@@ -116,7 +107,10 @@ GLOBAL_LIST_INIT(admin_verbs_event, list(
|
||||
/client/proc/fax_panel,
|
||||
/client/proc/event_manager_panel,
|
||||
/client/proc/modify_goals,
|
||||
/client/proc/outfit_manager
|
||||
/client/proc/outfit_manager,
|
||||
/client/proc/cmd_admin_headset_message,
|
||||
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
|
||||
/client/proc/change_human_appearance_self /* Allows the human-based mob itself to change its basic appearance */
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(admin_verbs_spawn, list(
|
||||
@@ -125,25 +119,27 @@ GLOBAL_LIST_INIT(admin_verbs_spawn, list(
|
||||
/client/proc/admin_deserialize
|
||||
))
|
||||
GLOBAL_LIST_INIT(admin_verbs_server, list(
|
||||
/client/proc/ToRban,
|
||||
/client/proc/reload_admins,
|
||||
/client/proc/Set_Holiday,
|
||||
/datum/admins/proc/startnow,
|
||||
/datum/admins/proc/restart,
|
||||
/datum/admins/proc/delay,
|
||||
/datum/admins/proc/toggleaban,
|
||||
/datum/admins/proc/toggleenter, /*toggles whether people can join the current game*/
|
||||
/datum/admins/proc/toggleguests, /*toggles whether guests can join the current game*/
|
||||
/client/proc/toggle_log_hrefs,
|
||||
/client/proc/everyone_random,
|
||||
/datum/admins/proc/toggleAI,
|
||||
/client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
|
||||
/client/proc/cmd_debug_del_all,
|
||||
/client/proc/cmd_debug_del_sing,
|
||||
/datum/admins/proc/toggle_aliens,
|
||||
/client/proc/delbook,
|
||||
/client/proc/view_flagged_books,
|
||||
/client/proc/view_asays,
|
||||
/client/proc/toggle_antagHUD_use,
|
||||
/client/proc/toggle_antagHUD_restrictions,
|
||||
/client/proc/set_ooc,
|
||||
/client/proc/reset_ooc
|
||||
/client/proc/reset_ooc,
|
||||
/client/proc/toggledrones
|
||||
))
|
||||
GLOBAL_LIST_INIT(admin_verbs_debug, list(
|
||||
/client/proc/cmd_admin_list_open_jobs,
|
||||
@@ -152,9 +148,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list(
|
||||
/client/proc/debug_controller,
|
||||
/client/proc/cmd_debug_mob_lists,
|
||||
/client/proc/cmd_admin_delete,
|
||||
/client/proc/cmd_debug_del_all,
|
||||
/client/proc/cmd_debug_del_sing,
|
||||
/client/proc/reload_admins,
|
||||
/client/proc/restart_controller,
|
||||
/client/proc/enable_debug_verbs,
|
||||
/client/proc/toggledebuglogs,
|
||||
@@ -172,6 +166,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug, list(
|
||||
/client/proc/admin_serialize,
|
||||
/client/proc/jump_to_ruin,
|
||||
/client/proc/toggle_medal_disable,
|
||||
/client/proc/uid_log
|
||||
))
|
||||
GLOBAL_LIST_INIT(admin_verbs_possess, list(
|
||||
/proc/possess,
|
||||
@@ -197,7 +192,7 @@ GLOBAL_LIST_INIT(admin_verbs_mod, list(
|
||||
/client/proc/player_panel_new,
|
||||
/client/proc/dsay,
|
||||
/datum/admins/proc/show_player_panel,
|
||||
/client/proc/jobbans,
|
||||
/client/proc/ban_panel,
|
||||
/client/proc/debug_variables /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
|
||||
))
|
||||
GLOBAL_LIST_INIT(admin_verbs_mentor, list(
|
||||
@@ -337,6 +332,9 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
ghost.reenter_corpse()
|
||||
log_admin("[key_name(usr)] re-entered their body")
|
||||
feedback_add_details("admin_verb","P") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
if(ishuman(mob))
|
||||
var/mob/living/carbon/human/H = mob
|
||||
H.regenerate_icons() // workaround for #13269
|
||||
else if(isnewplayer(mob))
|
||||
to_chat(src, "<font color='red'>Error: Aghost: Can't admin-ghost whilst in the lobby. Join or observe first.</font>")
|
||||
else
|
||||
@@ -367,19 +365,8 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
to_chat(mob, "<span class='notice'>Invisimin on. You are now as invisible as a ghost.</span>")
|
||||
mob.remove_from_all_data_huds()
|
||||
|
||||
/client/proc/player_panel()
|
||||
set name = "Player Panel"
|
||||
set category = "Admin"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
holder.player_panel_old()
|
||||
feedback_add_details("admin_verb","PP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/client/proc/player_panel_new()
|
||||
set name = "Player Panel New"
|
||||
set name = "Player Panel"
|
||||
set category = "Admin"
|
||||
|
||||
if(!check_rights(R_ADMIN|R_MOD))
|
||||
@@ -401,22 +388,8 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
feedback_add_details("admin_verb","CHA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/client/proc/jobbans()
|
||||
set name = "Display Job bans"
|
||||
set category = "Admin"
|
||||
|
||||
if(!check_rights(R_ADMIN|R_MOD))
|
||||
return
|
||||
|
||||
if(config.ban_legacy_system)
|
||||
holder.Jobbans()
|
||||
else
|
||||
holder.DB_ban_panel()
|
||||
feedback_add_details("admin_verb","VJB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/client/proc/unban_panel()
|
||||
set name = "Unban Panel"
|
||||
/client/proc/ban_panel()
|
||||
set name = "Ban Panel"
|
||||
set category = "Admin"
|
||||
|
||||
if(!check_rights(R_BAN))
|
||||
@@ -451,13 +424,8 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
feedback_add_details("admin_verb","S") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/client/proc/findStealthKey(txt)
|
||||
if(txt)
|
||||
for(var/P in GLOB.stealthminID)
|
||||
if(GLOB.stealthminID[P] == txt)
|
||||
return P
|
||||
txt = GLOB.stealthminID[ckey]
|
||||
return txt
|
||||
/client/proc/getStealthKey()
|
||||
return GLOB.stealthminID[ckey]
|
||||
|
||||
/client/proc/createStealthKey()
|
||||
var/num = (rand(0,1000))
|
||||
@@ -809,7 +777,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
set desc = "Allows you to change the mob appearance"
|
||||
set category = null
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
if(!check_rights(R_EVENT))
|
||||
return
|
||||
|
||||
if(!istype(H))
|
||||
@@ -826,7 +794,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
return
|
||||
|
||||
if(holder)
|
||||
admin_log_and_message_admins("is altering the appearance of [H].")
|
||||
log_and_message_admins("is altering the appearance of [H].")
|
||||
H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0)
|
||||
feedback_add_details("admin_verb","CHAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -835,7 +803,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
set desc = "Allows the mob to change its appearance"
|
||||
set category = null
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
if(!check_rights(R_EVENT))
|
||||
return
|
||||
|
||||
if(!istype(H))
|
||||
@@ -857,10 +825,10 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
|
||||
switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel"))
|
||||
if("Yes")
|
||||
admin_log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, without whitelisting of races.")
|
||||
log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, without whitelisting of races.")
|
||||
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0)
|
||||
if("No")
|
||||
admin_log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, with whitelisting of races.")
|
||||
log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, with whitelisting of races.")
|
||||
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
|
||||
feedback_add_details("admin_verb","CMAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -980,8 +948,8 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
else
|
||||
to_chat(usr, "You now won't get debug log messages")
|
||||
|
||||
/client/proc/man_up(mob/T as mob in GLOB.mob_list)
|
||||
set category = "Admin"
|
||||
/client/proc/man_up(mob/T as mob in GLOB.player_list)
|
||||
set category = null
|
||||
set name = "Man Up"
|
||||
set desc = "Tells mob to man up and deal with it."
|
||||
|
||||
|
||||
@@ -42,20 +42,6 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
|
||||
else
|
||||
return 0
|
||||
|
||||
/*
|
||||
DEBUG
|
||||
/mob/verb/list_all_jobbans()
|
||||
set name = "list all jobbans"
|
||||
|
||||
for(var/s in jobban_keylist)
|
||||
to_chat(world, s)
|
||||
|
||||
/mob/verb/reload_jobbans()
|
||||
set name = "reload jobbans"
|
||||
|
||||
jobban_loadbanfile()
|
||||
*/
|
||||
|
||||
/proc/jobban_loadbanfile()
|
||||
if(config.ban_legacy_system)
|
||||
var/savefile/S=new("data/job_full.ban")
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/proc/machine_upgrade(obj/machinery/M in world)
|
||||
set name = "Tweak Component Ratings"
|
||||
set category = "Debug"
|
||||
set category = null
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
|
||||
if(!istype(M))
|
||||
to_chat(usr, "<span class='danger'>This can only be used on subtypes of /obj/machinery.</span>")
|
||||
return
|
||||
|
||||
|
||||
var/new_rating = input("Enter new rating:","Num") as num
|
||||
if(!isnull(new_rating) && M.component_parts)
|
||||
for(var/obj/item/stock_parts/P in M.component_parts)
|
||||
P.rating = new_rating
|
||||
M.RefreshParts()
|
||||
|
||||
|
||||
message_admins("[key_name_admin(usr)] has set the component rating of [M] to [new_rating]")
|
||||
log_admin("[key_name(usr)] has set the component rating of [M] to [new_rating]")
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
}
|
||||
|
||||
function expand(id,job,name,real_name,image,key,ip,antagonist,mobUID,clientUID,eyeUID){
|
||||
function expand(id,job,name,real_name,image,key,ip,antagonist,mobUID,client_ckey,eyeUID){
|
||||
|
||||
clearAll();
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
body += "<a href='?src=[UID()];shownoteckey="+key+"'>N</a> - "
|
||||
body += "<a href='?_src_=vars;Vars="+mobUID+"'>VV</a> - "
|
||||
body += "<a href='?src=[UID()];traitor="+mobUID+"'>TP</a> - "
|
||||
body += "<a href='?src=[usr.UID()];priv_msg="+clientUID+"'>PM</a> - "
|
||||
body += "<a href='?src=[usr.UID()];priv_msg="+client_ckey+"'>PM</a> - "
|
||||
body += "<a href='?src=[UID()];subtlemessage="+mobUID+"'>SM</a> - "
|
||||
body += "<a href='?src=[UID()];adminplayerobservefollow="+mobUID+"'>FLW</a>"
|
||||
if(eyeUID)
|
||||
@@ -297,7 +297,7 @@
|
||||
var/mob/living/silicon/ai/A = M
|
||||
if(A.client && A.eyeobj) // No point following clientless AI eyes
|
||||
M_eyeUID = "[A.eyeobj.UID()]"
|
||||
var/clientUID = M.client ? M.client.UID() : null
|
||||
var/client_ckey = M.client ? M.client.ckey : null
|
||||
//output for each mob
|
||||
dat += {"
|
||||
|
||||
@@ -305,7 +305,7 @@
|
||||
<td align='center' bgcolor='[color]'>
|
||||
<span id='notice_span[i]'></span>
|
||||
<a id='link[i]'
|
||||
onmouseover='expand("item[i]","[M_job]","[M_name]","[M_rname]","--unused--","[M_key]","[M.lastKnownIP]",[is_antagonist],"[M.UID()]","[clientUID]","[M_eyeUID]")'
|
||||
onmouseover='expand("item[i]","[M_job]","[M_name]","[M_rname]","--unused--","[M_key]","[M.lastKnownIP]",[is_antagonist],"[M.UID()]","[client_ckey]","[M_eyeUID]")'
|
||||
>
|
||||
<b id='search[i]'>[M_name] - [M_rname] - [M_key] ([M_job])</b>
|
||||
</a>
|
||||
@@ -332,65 +332,6 @@
|
||||
|
||||
usr << browse(dat, "window=players;size=600x480")
|
||||
|
||||
//The old one
|
||||
/datum/admins/proc/player_panel_old()
|
||||
if(!usr.client.holder)
|
||||
return
|
||||
var/dat = "<html><head><title>Player Menu</title></head>"
|
||||
dat += "<body><table border=1 cellspacing=5><B><tr><th>Name</th><th>Real Name</th><th>Assigned Job</th><th>Key</th><th>Options</th><th>PM</th><th>Traitor?</th></tr></B>"
|
||||
//add <th>IP:</th> to this if wanting to add back in IP checking
|
||||
//add <td>(IP: [M.lastKnownIP])</td> if you want to know their ip to the lists below
|
||||
var/list/mobs = sortmobs()
|
||||
|
||||
for(var/mob/M in mobs)
|
||||
if(!M.ckey) continue
|
||||
|
||||
dat += "<tr><td>[M.name]</td>"
|
||||
if(isAI(M))
|
||||
dat += "<td>AI</td>"
|
||||
else if(isrobot(M))
|
||||
dat += "<td>Cyborg</td>"
|
||||
else if(issmall(M))
|
||||
dat += "<td>Monkey</td>"
|
||||
else if(ishuman(M))
|
||||
dat += "<td>[M.real_name]</td>"
|
||||
else if(istype(M, /mob/living/silicon/pai))
|
||||
dat += "<td>pAI</td>"
|
||||
else if(isnewplayer(M))
|
||||
dat += "<td>New Player</td>"
|
||||
else if(isobserver(M))
|
||||
dat += "<td>Ghost</td>"
|
||||
else if(isalien(M))
|
||||
dat += "<td>Alien</td>"
|
||||
else
|
||||
dat += "<td>Unknown</td>"
|
||||
|
||||
|
||||
if(istype(M,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.mind && H.mind.assigned_role)
|
||||
dat += "<td>[H.mind.assigned_role]</td>"
|
||||
else
|
||||
dat += "<td>NA</td>"
|
||||
|
||||
|
||||
dat += {"<td>[(M.client ? "[M.client]" : "No client")]</td>
|
||||
<td align=center><A HREF='?src=[UID()];adminplayeropts=[M.UID()]'>X</A></td>
|
||||
<td align=center><A href='?src=[usr.UID()];priv_msg=[M.client ? M.client.UID() : null]'>PM</A></td>
|
||||
"}
|
||||
switch(is_special_character(M))
|
||||
if(0)
|
||||
dat += {"<td align=center><A HREF='?src=[UID()];traitor=[M.UID()]'>Traitor?</A></td>"}
|
||||
if(1)
|
||||
dat += {"<td align=center><A HREF='?src=[UID()];traitor=[M.UID()]'><font color=red>Traitor?</font></A></td>"}
|
||||
if(2)
|
||||
dat += {"<td align=center><A HREF='?src=[UID()];traitor=[M.UID()]'><font color=red><b>Traitor?</b></font></A></td>"}
|
||||
|
||||
dat += "</table></body></html>"
|
||||
|
||||
usr << browse(dat, "window=players;size=640x480")
|
||||
|
||||
|
||||
|
||||
/datum/admins/proc/check_antagonists_line(mob/M, caption = "", close = 1)
|
||||
var/logout_status
|
||||
@@ -401,7 +342,7 @@
|
||||
dname = M
|
||||
|
||||
return {"<tr><td><a href='?src=[UID()];adminplayeropts=[M.UID()]'>[dname]</a><b>[caption]</b>[logout_status][istype(A, /area/security/permabrig) ? "<b><font color=red> (PERMA) </b></font>" : ""][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>
|
||||
<td><A href='?src=[usr.UID()];priv_msg=[M.client ? M.client.UID() : null]'>PM</A> [ADMIN_FLW(M, "FLW")] </td>[close ? "</tr>" : ""]"}
|
||||
<td><A href='?src=[usr.UID()];priv_msg=[M.client?.ckey]'>PM</A> [ADMIN_FLW(M, "FLW")] </td>[close ? "</tr>" : ""]"}
|
||||
|
||||
/datum/admins/proc/check_antagonists()
|
||||
if(!check_rights(R_ADMIN))
|
||||
@@ -477,7 +418,7 @@
|
||||
var/mob/M = blob.current
|
||||
if(M)
|
||||
dat += "<tr><td>[ADMIN_PP(M,"[M.real_name]")][M.client ? "" : " <i>(ghost)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
|
||||
dat += "<td><A href='?priv_msg=[M.client ? M.client.UID() : null]'>PM</A></td>"
|
||||
dat += "<td><A href='?priv_msg=[M.client?.ckey]'>PM</A></td>"
|
||||
else
|
||||
dat += "<tr><td><i>Blob not found!</i></td></tr>"
|
||||
dat += "</table>"
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
if(checkrights && !check_rights(R_ADMIN|R_MOD))
|
||||
return
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
if(usr)
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
|
||||
if(!target_ckey)
|
||||
@@ -19,7 +20,8 @@
|
||||
log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n")
|
||||
return
|
||||
if(!query_find_ckey.NextRow())
|
||||
to_chat(usr, "<span class='redtext'>[target_ckey] has not been seen before, you can only add notes to known players.</span>")
|
||||
if(usr)
|
||||
to_chat(usr, "<span class='redtext'>[target_ckey] has not been seen before, you can only add notes to known players.</span>")
|
||||
return
|
||||
|
||||
var/exp_data = query_find_ckey.item[2]
|
||||
@@ -52,8 +54,8 @@
|
||||
log_game("SQL ERROR adding new note to table. Error : \[[err]\]\n")
|
||||
return
|
||||
if(logged)
|
||||
log_admin("[key_name(usr)] has added a note to [target_ckey]: [notetext]")
|
||||
message_admins("[key_name_admin(usr)] has added a note to [target_ckey]:<br>[notetext]")
|
||||
log_admin("[usr ? key_name(usr) : adminckey] has added a note to [target_ckey]: [notetext]")
|
||||
message_admins("[usr ? key_name_admin(usr) : adminckey] has added a note to [target_ckey]:<br>[notetext]")
|
||||
show_note(target_ckey)
|
||||
|
||||
/proc/remove_note(note_id)
|
||||
@@ -63,7 +65,8 @@
|
||||
var/notetext
|
||||
var/adminckey
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
if(usr)
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
if(!note_id)
|
||||
return
|
||||
@@ -82,15 +85,16 @@
|
||||
var/err = query_del_note.ErrorMsg()
|
||||
log_game("SQL ERROR removing note from table. Error : \[[err]\]\n")
|
||||
return
|
||||
log_admin("[key_name(usr)] has removed a note made by [adminckey] from [ckey]: [notetext]")
|
||||
message_admins("[key_name_admin(usr)] has removed a note made by [adminckey] from [ckey]:<br>[notetext]")
|
||||
log_admin("[usr ? key_name(usr) : "Bot"] has removed a note made by [adminckey] from [ckey]: [notetext]")
|
||||
message_admins("[usr ? key_name_admin(usr) : "Bot"] has removed a note made by [adminckey] from [ckey]:<br>[notetext]")
|
||||
show_note(ckey)
|
||||
|
||||
/proc/edit_note(note_id)
|
||||
if(!check_rights(R_ADMIN|R_MOD))
|
||||
return
|
||||
if(!GLOB.dbcon.IsConnected())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
if(usr)
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
if(!note_id)
|
||||
return
|
||||
@@ -117,8 +121,8 @@
|
||||
var/err = query_update_note.ErrorMsg()
|
||||
log_game("SQL ERROR editing note. Error : \[[err]\]\n")
|
||||
return
|
||||
log_admin("[key_name(usr)] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
|
||||
message_admins("[key_name_admin(usr)] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
|
||||
log_admin("[usr ? key_name(usr) : "Bot"] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
|
||||
message_admins("[usr ? key_name_admin(usr) : "Bot"] has edited [target_ckey]'s note made by [adminckey] from \"[old_note]\" to \"[new_note]\"")
|
||||
show_note(target_ckey)
|
||||
|
||||
/proc/show_note(target_ckey, index, linkless = 0)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
set name = "Open Admin Ticket Interface"
|
||||
set category = "Admin"
|
||||
|
||||
if(!holder || !check_rights(R_ADMIN))
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
SStickets.showUI(usr)
|
||||
@@ -14,7 +14,7 @@
|
||||
set name = "Resolve All Open Admin Tickets"
|
||||
set category = null
|
||||
|
||||
if(!holder || !check_rights(R_ADMIN))
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
if(alert("Are you sure you want to resolve ALL open admin tickets?","Resolve all open admin tickets?","Yes","No") != "Yes")
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
set name = "Open Mentor Ticket Interface"
|
||||
set category = "Admin"
|
||||
|
||||
if(!holder || !check_rights(R_MENTOR|R_ADMIN))
|
||||
if(!check_rights(R_MENTOR|R_ADMIN))
|
||||
return
|
||||
|
||||
SSmentor_tickets.showUI(usr)
|
||||
@@ -14,7 +14,7 @@
|
||||
set name = "Resolve All Open Mentor Tickets"
|
||||
set category = null
|
||||
|
||||
if(!holder || !check_rights(R_ADMIN))
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
if(alert("Are you sure you want to resolve ALL open mentor tickets?","Resolve all open mentor tickets?","Yes","No") != "Yes")
|
||||
|
||||
+294
-152
File diff suppressed because it is too large
Load Diff
@@ -89,403 +89,443 @@
|
||||
/datum/SDQL_parser/proc/tokenl(i)
|
||||
return lowertext(token(i))
|
||||
|
||||
/datum/SDQL_parser/proc
|
||||
|
||||
//query: select_query | delete_query | update_query
|
||||
query(i, list/node)
|
||||
query_type = tokenl(i)
|
||||
/datum/SDQL_parser/proc/query(i, list/node)
|
||||
query_type = tokenl(i)
|
||||
|
||||
switch(query_type)
|
||||
if("select")
|
||||
select_query(i, node)
|
||||
switch(query_type)
|
||||
if("select")
|
||||
select_query(i, node)
|
||||
|
||||
if("delete")
|
||||
delete_query(i, node)
|
||||
if("delete")
|
||||
delete_query(i, node)
|
||||
|
||||
if("update")
|
||||
update_query(i, node)
|
||||
if("update")
|
||||
update_query(i, node)
|
||||
|
||||
if("call")
|
||||
call_query(i, node)
|
||||
if("call")
|
||||
call_query(i, node)
|
||||
|
||||
if("explain")
|
||||
node += "explain"
|
||||
node["explain"] = list()
|
||||
query(i + 1, node["explain"])
|
||||
if("explain")
|
||||
node += "explain"
|
||||
node["explain"] = list()
|
||||
query(i + 1, node["explain"])
|
||||
|
||||
|
||||
// select_query: 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
|
||||
select_query(i, list/node)
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
/datum/SDQL_parser/proc/select_query(i, list/node)
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
|
||||
node += "select"
|
||||
node["select"] = select
|
||||
node += "select"
|
||||
node["select"] = select
|
||||
|
||||
var/list/from = list()
|
||||
if(tokenl(i) in list("from", "in"))
|
||||
i = from_list(i + 1, from)
|
||||
else
|
||||
from += "world"
|
||||
var/list/from = list()
|
||||
if(tokenl(i) in list("from", "in"))
|
||||
i = from_list(i + 1, from)
|
||||
else
|
||||
from += "world"
|
||||
|
||||
node += "from"
|
||||
node["from"] = from
|
||||
node += "from"
|
||||
node["from"] = from
|
||||
|
||||
if(tokenl(i) == "where")
|
||||
var/list/where = list()
|
||||
i = bool_expression(i + 1, where)
|
||||
if(tokenl(i) == "where")
|
||||
var/list/where = list()
|
||||
i = bool_expression(i + 1, where)
|
||||
|
||||
node += "where"
|
||||
node["where"] = where
|
||||
node += "where"
|
||||
node["where"] = where
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//delete_query: 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
|
||||
delete_query(i, list/node)
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
/datum/SDQL_parser/proc/delete_query(i, list/node)
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
|
||||
node += "delete"
|
||||
node["delete"] = select
|
||||
node += "delete"
|
||||
node["delete"] = select
|
||||
|
||||
var/list/from = list()
|
||||
if(tokenl(i) in list("from", "in"))
|
||||
i = from_list(i + 1, from)
|
||||
else
|
||||
from += "world"
|
||||
var/list/from = list()
|
||||
if(tokenl(i) in list("from", "in"))
|
||||
i = from_list(i + 1, from)
|
||||
else
|
||||
from += "world"
|
||||
|
||||
node += "from"
|
||||
node["from"] = from
|
||||
node += "from"
|
||||
node["from"] = from
|
||||
|
||||
if(tokenl(i) == "where")
|
||||
var/list/where = list()
|
||||
i = bool_expression(i + 1, where)
|
||||
if(tokenl(i) == "where")
|
||||
var/list/where = list()
|
||||
i = bool_expression(i + 1, where)
|
||||
|
||||
node += "where"
|
||||
node["where"] = where
|
||||
node += "where"
|
||||
node["where"] = where
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//update_query: 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
|
||||
update_query(i, list/node)
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
/datum/SDQL_parser/proc/update_query(i, list/node)
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
|
||||
node += "update"
|
||||
node["update"] = select
|
||||
node += "update"
|
||||
node["update"] = select
|
||||
|
||||
var/list/from = list()
|
||||
if(tokenl(i) in list("from", "in"))
|
||||
i = from_list(i + 1, from)
|
||||
else
|
||||
from += "world"
|
||||
var/list/from = list()
|
||||
if(tokenl(i) in list("from", "in"))
|
||||
i = from_list(i + 1, from)
|
||||
else
|
||||
from += "world"
|
||||
|
||||
node += "from"
|
||||
node["from"] = from
|
||||
node += "from"
|
||||
node["from"] = from
|
||||
|
||||
if(tokenl(i) != "set")
|
||||
i = parse_error("UPDATE has misplaced SET")
|
||||
if(tokenl(i) != "set")
|
||||
i = parse_error("UPDATE has misplaced SET")
|
||||
|
||||
var/list/set_assignments = list()
|
||||
i = assignments(i + 1, set_assignments)
|
||||
var/list/set_assignments = list()
|
||||
i = assignments(i + 1, set_assignments)
|
||||
|
||||
node += "set"
|
||||
node["set"] = set_assignments
|
||||
node += "set"
|
||||
node["set"] = set_assignments
|
||||
|
||||
if(tokenl(i) == "where")
|
||||
var/list/where = list()
|
||||
i = bool_expression(i + 1, where)
|
||||
if(tokenl(i) == "where")
|
||||
var/list/where = list()
|
||||
i = bool_expression(i + 1, where)
|
||||
|
||||
node += "where"
|
||||
node["where"] = where
|
||||
node += "where"
|
||||
node["where"] = where
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//call_query: 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
|
||||
call_query(i, list/node)
|
||||
var/list/func = list()
|
||||
i = variable(i + 1, func)
|
||||
/datum/SDQL_parser/proc/call_query(i, list/node)
|
||||
var/list/func = list()
|
||||
i = variable(i + 1, func)
|
||||
|
||||
node += "call"
|
||||
node["call"] = func
|
||||
|
||||
if(tokenl(i) != "on")
|
||||
return i
|
||||
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
|
||||
node += "on"
|
||||
node["on"] = select
|
||||
|
||||
var/list/from = list()
|
||||
if(tokenl(i) in list("from", "in"))
|
||||
i = from_list(i + 1, from)
|
||||
else
|
||||
from += "world"
|
||||
|
||||
node += "from"
|
||||
node["from"] = from
|
||||
|
||||
if(tokenl(i) == "where")
|
||||
var/list/where = list()
|
||||
i = bool_expression(i + 1, where)
|
||||
|
||||
node += "where"
|
||||
node["where"] = where
|
||||
node += "call"
|
||||
node["call"] = func
|
||||
|
||||
if(tokenl(i) != "on")
|
||||
return i
|
||||
|
||||
var/list/select = list()
|
||||
i = select_list(i + 1, select)
|
||||
|
||||
node += "on"
|
||||
node["on"] = select
|
||||
|
||||
var/list/from = list()
|
||||
if(tokenl(i) in list("from", "in"))
|
||||
i = from_list(i + 1, from)
|
||||
else
|
||||
from += "world"
|
||||
|
||||
node += "from"
|
||||
node["from"] = from
|
||||
|
||||
if(tokenl(i) == "where")
|
||||
var/list/where = list()
|
||||
i = bool_expression(i + 1, where)
|
||||
|
||||
node += "where"
|
||||
node["where"] = where
|
||||
|
||||
return i
|
||||
|
||||
|
||||
//select_list: select_item [',' select_list]
|
||||
select_list(i, list/node)
|
||||
i = select_item(i, node)
|
||||
/datum/SDQL_parser/proc/select_list(i, list/node)
|
||||
i = select_item(i, node)
|
||||
|
||||
if(token(i) == ",")
|
||||
i = select_list(i + 1, node)
|
||||
if(token(i) == ",")
|
||||
i = select_list(i + 1, node)
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//from_list: from_item [',' from_list]
|
||||
from_list(i, list/node)
|
||||
i = from_item(i, node)
|
||||
/datum/SDQL_parser/proc/from_list(i, list/node)
|
||||
i = from_item(i, node)
|
||||
|
||||
if(token(i) == ",")
|
||||
i = from_list(i + 1, node)
|
||||
if(token(i) == ",")
|
||||
i = from_list(i + 1, node)
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//assignments: assignment, [',' assignments]
|
||||
assignments(i, list/node)
|
||||
i = assignment(i, node)
|
||||
/datum/SDQL_parser/proc/assignments(i, list/node)
|
||||
i = assignment(i, node)
|
||||
|
||||
if(token(i) == ",")
|
||||
i = assignments(i + 1, node)
|
||||
if(token(i) == ",")
|
||||
i = assignments(i + 1, node)
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//select_item: '*' | select_function | object_type
|
||||
select_item(i, list/node)
|
||||
/datum/SDQL_parser/proc/select_item(i, list/node)
|
||||
if(token(i) == "*")
|
||||
node += "*"
|
||||
i++
|
||||
|
||||
if(token(i) == "*")
|
||||
node += "*"
|
||||
i++
|
||||
else if(tokenl(i) in select_functions)
|
||||
i = select_function(i, node)
|
||||
|
||||
else if(tokenl(i) in select_functions)
|
||||
i = select_function(i, node)
|
||||
else
|
||||
i = object_type(i, node)
|
||||
|
||||
else
|
||||
i = object_type(i, node)
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//from_item: 'world' | object_type
|
||||
from_item(i, list/node)
|
||||
/datum/SDQL_parser/proc/from_item(i, list/node)
|
||||
|
||||
if(token(i) == "world")
|
||||
node += "world"
|
||||
i++
|
||||
if(token(i) == "world")
|
||||
node += "world"
|
||||
i++
|
||||
|
||||
else
|
||||
i = object_type(i, node)
|
||||
else
|
||||
i = object_type(i, node)
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//bool_expression: expression [bool_operator bool_expression]
|
||||
bool_expression(i, list/node)
|
||||
/datum/SDQL_parser/proc/bool_expression(i, list/node)
|
||||
var/list/bool = list()
|
||||
i = expression(i, bool)
|
||||
|
||||
var/list/bool = list()
|
||||
i = expression(i, bool)
|
||||
node[++node.len] = bool
|
||||
|
||||
node[++node.len] = bool
|
||||
if(tokenl(i) in boolean_operators)
|
||||
i = bool_operator(i, node)
|
||||
i = bool_expression(i, node)
|
||||
|
||||
if(tokenl(i) in boolean_operators)
|
||||
i = bool_operator(i, node)
|
||||
i = bool_expression(i, node)
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//assignment: <variable name> '=' expression
|
||||
assignment(var/i, var/list/node, var/list/assignment_list = list())
|
||||
assignment_list += token(i)
|
||||
/datum/SDQL_parser/proc/assignment(var/i, var/list/node, var/list/assignment_list = list())
|
||||
assignment_list += token(i)
|
||||
|
||||
if(token(i + 1) == ".")
|
||||
i = assignment(i + 2, node, assignment_list)
|
||||
if(token(i + 1) == ".")
|
||||
i = assignment(i + 2, node, assignment_list)
|
||||
|
||||
else if(token(i + 1) == "=")
|
||||
var/exp_list = list()
|
||||
node[assignment_list] = exp_list
|
||||
else if(token(i + 1) == "=")
|
||||
var/exp_list = list()
|
||||
node[assignment_list] = exp_list
|
||||
|
||||
i = expression(i + 2, exp_list)
|
||||
i = expression(i + 2, exp_list)
|
||||
|
||||
else
|
||||
parse_error("Assignment expected, but no = found")
|
||||
else
|
||||
parse_error("Assignment expected, but no = found")
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//variable: <variable name> | <variable name> '.' variable
|
||||
variable(i, list/node)
|
||||
var/list/L = list(token(i))
|
||||
node[++node.len] = L
|
||||
/datum/SDQL_parser/proc/variable(i, list/node)
|
||||
var/list/L = list(token(i))
|
||||
node[++node.len] = L
|
||||
|
||||
if(token(i) == "\[")
|
||||
L += token(i + 1)
|
||||
i += 2
|
||||
if(token(i) == "\[")
|
||||
L += token(i + 1)
|
||||
i += 2
|
||||
|
||||
if(token(i) != "\]")
|
||||
parse_error("Missing \] at end of reference.")
|
||||
if(token(i) != "\]")
|
||||
parse_error("Missing \] at end of reference.")
|
||||
|
||||
if(token(i + 1) == ".")
|
||||
L += "."
|
||||
i = variable(i + 2, L)
|
||||
if(token(i + 1) == ".")
|
||||
L += "."
|
||||
i = variable(i + 2, L)
|
||||
|
||||
else if(token(i + 1) == "(") // OH BOY PROC
|
||||
var/list/arguments = list()
|
||||
i = call_function(i, null, arguments)
|
||||
L += ":"
|
||||
L[++L.len] = arguments
|
||||
else if(token(i + 1) == "(") // OH BOY PROC
|
||||
var/list/arguments = list()
|
||||
i = call_function(i, null, arguments)
|
||||
L += ":"
|
||||
L[++L.len] = arguments
|
||||
|
||||
else if(token(i + 1) == "\[") // list index
|
||||
var/list/expression = list()
|
||||
i = expression(i + 2, expression)
|
||||
if(token(i) != "]")
|
||||
parse_error("Missing ] at the end of list access.")
|
||||
else if(token(i + 1) == "\[") // list index
|
||||
var/list/expression = list()
|
||||
i = expression(i + 2, expression)
|
||||
if(token(i) != "]")
|
||||
parse_error("Missing ] at the end of list access.")
|
||||
|
||||
L += "\["
|
||||
L[++L.len] = expression
|
||||
i++
|
||||
L += "\["
|
||||
L[++L.len] = expression
|
||||
i++
|
||||
|
||||
else
|
||||
i++
|
||||
else
|
||||
i++
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//object_type: <type path> | string
|
||||
object_type(i, list/node)
|
||||
/datum/SDQL_parser/proc/object_type(i, list/node)
|
||||
|
||||
if(copytext(token(i), 1, 2) == "/")
|
||||
node += token(i)
|
||||
if(copytext(token(i), 1, 2) == "/")
|
||||
node += token(i)
|
||||
|
||||
else
|
||||
i = string(i, node)
|
||||
else
|
||||
i = string(i, node)
|
||||
|
||||
return i + 1
|
||||
return i + 1
|
||||
|
||||
|
||||
//comparitor: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
|
||||
comparitor(i, list/node)
|
||||
/datum/SDQL_parser/proc/comparitor(i, list/node)
|
||||
|
||||
if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">="))
|
||||
node += token(i)
|
||||
if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">="))
|
||||
node += token(i)
|
||||
|
||||
else
|
||||
parse_error("Unknown comparitor [token(i)]")
|
||||
else
|
||||
parse_error("Unknown comparitor [token(i)]")
|
||||
|
||||
return i + 1
|
||||
return i + 1
|
||||
|
||||
|
||||
//bool_operator: 'AND' | '&&' | 'OR' | '||'
|
||||
bool_operator(i, list/node)
|
||||
/datum/SDQL_parser/proc/bool_operator(i, list/node)
|
||||
|
||||
if(tokenl(i) in list("and", "or", "&&", "||"))
|
||||
node += token(i)
|
||||
if(tokenl(i) in list("and", "or", "&&", "||"))
|
||||
node += token(i)
|
||||
|
||||
else
|
||||
parse_error("Unknown comparitor [token(i)]")
|
||||
else
|
||||
parse_error("Unknown comparitor [token(i)]")
|
||||
|
||||
return i + 1
|
||||
return i + 1
|
||||
|
||||
|
||||
//string: ''' <some text> ''' | '"' <some text > '"'
|
||||
string(i, list/node)
|
||||
/datum/SDQL_parser/proc/string(i, list/node)
|
||||
|
||||
if(copytext(token(i), 1, 2) in list("'", "\""))
|
||||
node += token(i)
|
||||
if(copytext(token(i), 1, 2) in list("'", "\""))
|
||||
node += token(i)
|
||||
|
||||
else
|
||||
parse_error("Expected string but found '[token(i)]'")
|
||||
else
|
||||
parse_error("Expected string but found '[token(i)]'")
|
||||
|
||||
return i + 1
|
||||
return i + 1
|
||||
|
||||
//array: '{' expression, expression, ... '}'
|
||||
array(var/i, var/list/node)
|
||||
// Arrays get turned into this: list("{", list(exp_1a = exp_1b, ...), ...), "{" is to mark the next node as an array.
|
||||
if(copytext(token(i), 1, 2) != "{")
|
||||
parse_error("Expected an array but found '[token(i)]'")
|
||||
return i + 1
|
||||
|
||||
node += token(i) // Add the "{"
|
||||
var/list/expression_list = list()
|
||||
|
||||
if(token(i + 1) != "}")
|
||||
var/list/temp_expression_list = list()
|
||||
|
||||
do
|
||||
i = expression(i + 1, temp_expression_list)
|
||||
|
||||
if(token(i) == ",")
|
||||
expression_list[++expression_list.len] = temp_expression_list
|
||||
temp_expression_list = list()
|
||||
while(token(i) && token(i) != "}")
|
||||
|
||||
expression_list[++expression_list.len] = temp_expression_list
|
||||
else
|
||||
i++
|
||||
|
||||
node[++node.len] = expression_list
|
||||
/datum/SDQL_parser/proc/array(var/i, var/list/node)
|
||||
// Arrays get turned into this: list("{", list(exp_1a = exp_1b, ...), ...), "{" is to mark the next node as an array.
|
||||
if(copytext(token(i), 1, 2) != "{")
|
||||
parse_error("Expected an array but found '[token(i)]'")
|
||||
return i + 1
|
||||
|
||||
node += token(i) // Add the "{"
|
||||
var/list/expression_list = list()
|
||||
|
||||
if(token(i + 1) != "}")
|
||||
var/list/temp_expression_list = list()
|
||||
|
||||
do
|
||||
i = expression(i + 1, temp_expression_list)
|
||||
|
||||
if(token(i) == ",")
|
||||
expression_list[++expression_list.len] = temp_expression_list
|
||||
temp_expression_list = list()
|
||||
while(token(i) && token(i) != "}")
|
||||
|
||||
expression_list[++expression_list.len] = temp_expression_list
|
||||
else
|
||||
i++
|
||||
|
||||
node[++node.len] = expression_list
|
||||
return i + 1
|
||||
|
||||
//call_function: <function name> ['(' [arguments] ')']
|
||||
call_function(i, list/node, list/arguments)
|
||||
var/list/cur_argument = list()
|
||||
if(length(tokenl(i)))
|
||||
var/procname = ""
|
||||
if(tokenl(i) == "global" && token(i + 1) == ".") // Global proc.
|
||||
i += 2
|
||||
procname = "global."
|
||||
node += procname + token(i++)
|
||||
if(token(i) != "(")
|
||||
parse_error("Expected ( but found '[token(i)]'")
|
||||
else if(token(i + 1) != ")")
|
||||
do
|
||||
i = expression(i + 1, cur_argument)
|
||||
if(token(i) == ",")
|
||||
arguments += list(cur_argument)
|
||||
cur_argument = list()
|
||||
continue
|
||||
while(token(i) && token(i) != ")")
|
||||
arguments += list(cur_argument)
|
||||
else
|
||||
i++
|
||||
/datum/SDQL_parser/proc/call_function(i, list/node, list/arguments)
|
||||
var/list/cur_argument = list()
|
||||
if(length(tokenl(i)))
|
||||
var/procname = ""
|
||||
if(tokenl(i) == "global" && token(i + 1) == ".") // Global proc.
|
||||
i += 2
|
||||
procname = "global."
|
||||
node += procname + token(i++)
|
||||
if(token(i) != "(")
|
||||
parse_error("Expected ( but found '[token(i)]'")
|
||||
else if(token(i + 1) != ")")
|
||||
do
|
||||
i = expression(i + 1, cur_argument)
|
||||
if(token(i) == ",")
|
||||
arguments += list(cur_argument)
|
||||
cur_argument = list()
|
||||
continue
|
||||
while(token(i) && token(i) != ")")
|
||||
arguments += list(cur_argument)
|
||||
else
|
||||
parse_error("Expected a function but found nothing")
|
||||
return i + 1
|
||||
i++
|
||||
else
|
||||
parse_error("Expected a function but found nothing")
|
||||
return i + 1
|
||||
|
||||
|
||||
//select_function: count_function
|
||||
select_function(i, list/node)
|
||||
/datum/SDQL_parser/proc/select_function(i, list/node)
|
||||
|
||||
parse_error("Sorry, function calls aren't available yet")
|
||||
parse_error("Sorry, function calls aren't available yet")
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//expression: ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
|
||||
expression(i, list/node)
|
||||
/datum/SDQL_parser/proc/expression(i, list/node)
|
||||
|
||||
if(token(i) in unary_operators)
|
||||
i = unary_expression(i, node)
|
||||
|
||||
else if(token(i) == "(")
|
||||
var/list/expr = list()
|
||||
|
||||
i = expression(i + 1, expr)
|
||||
|
||||
if(token(i) != ")")
|
||||
parse_error("Missing ) at end of expression.")
|
||||
|
||||
else
|
||||
i++
|
||||
|
||||
node[++node.len] = expr
|
||||
|
||||
else
|
||||
i = value(i, node)
|
||||
|
||||
if(token(i) in binary_operators)
|
||||
i = binary_operator(i, node)
|
||||
i = expression(i, node)
|
||||
|
||||
else if(token(i) in comparitors)
|
||||
i = binary_operator(i, node)
|
||||
|
||||
var/list/rhs = list()
|
||||
i = expression(i, rhs)
|
||||
|
||||
node[++node.len] = rhs
|
||||
|
||||
|
||||
return i
|
||||
|
||||
|
||||
//unary_expression: unary_operator ( unary_expression | value | '(' expression ')' )
|
||||
/datum/SDQL_parser/proc/unary_expression(i, list/node)
|
||||
|
||||
if(token(i) in unary_operators)
|
||||
var/list/unary_exp = list()
|
||||
|
||||
unary_exp += token(i)
|
||||
i++
|
||||
|
||||
if(token(i) in unary_operators)
|
||||
i = unary_expression(i, node)
|
||||
i = unary_expression(i, unary_exp)
|
||||
|
||||
else if(token(i) == "(")
|
||||
var/list/expr = list()
|
||||
@@ -498,99 +538,55 @@
|
||||
else
|
||||
i++
|
||||
|
||||
node[++node.len] = expr
|
||||
unary_exp[++unary_exp.len] = expr
|
||||
|
||||
else
|
||||
i = value(i, node)
|
||||
i = value(i, unary_exp)
|
||||
|
||||
if(token(i) in binary_operators)
|
||||
i = binary_operator(i, node)
|
||||
i = expression(i, node)
|
||||
|
||||
else if(token(i) in comparitors)
|
||||
i = binary_operator(i, node)
|
||||
|
||||
var/list/rhs = list()
|
||||
i = expression(i, rhs)
|
||||
|
||||
node[++node.len] = rhs
|
||||
node[++node.len] = unary_exp
|
||||
|
||||
|
||||
return i
|
||||
else
|
||||
parse_error("Expected unary operator but found '[token(i)]'")
|
||||
|
||||
|
||||
//unary_expression: unary_operator ( unary_expression | value | '(' expression ')' )
|
||||
unary_expression(i, list/node)
|
||||
|
||||
if(token(i) in unary_operators)
|
||||
var/list/unary_exp = list()
|
||||
|
||||
unary_exp += token(i)
|
||||
i++
|
||||
|
||||
if(token(i) in unary_operators)
|
||||
i = unary_expression(i, unary_exp)
|
||||
|
||||
else if(token(i) == "(")
|
||||
var/list/expr = list()
|
||||
|
||||
i = expression(i + 1, expr)
|
||||
|
||||
if(token(i) != ")")
|
||||
parse_error("Missing ) at end of expression.")
|
||||
|
||||
else
|
||||
i++
|
||||
|
||||
unary_exp[++unary_exp.len] = expr
|
||||
|
||||
else
|
||||
i = value(i, unary_exp)
|
||||
|
||||
node[++node.len] = unary_exp
|
||||
|
||||
|
||||
else
|
||||
parse_error("Expected unary operator but found '[token(i)]'")
|
||||
|
||||
return i
|
||||
return i
|
||||
|
||||
|
||||
//binary_operator: comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
|
||||
binary_operator(i, list/node)
|
||||
/datum/SDQL_parser/proc/binary_operator(i, list/node)
|
||||
|
||||
if(token(i) in (binary_operators + comparitors))
|
||||
node += token(i)
|
||||
if(token(i) in (binary_operators + comparitors))
|
||||
node += token(i)
|
||||
|
||||
else
|
||||
parse_error("Unknown binary operator [token(i)]")
|
||||
else
|
||||
parse_error("Unknown binary operator [token(i)]")
|
||||
|
||||
return i + 1
|
||||
return i + 1
|
||||
|
||||
|
||||
//value: variable | string | number | 'null'
|
||||
value(i, list/node)
|
||||
/datum/SDQL_parser/proc/value(i, list/node)
|
||||
|
||||
if(token(i) == "null")
|
||||
node += "null"
|
||||
i++
|
||||
if(token(i) == "null")
|
||||
node += "null"
|
||||
i++
|
||||
|
||||
else if(lowertext(copytext(token(i), 1, 3)) == "0x" && isnum(hex2num(copytext(token(i), 3))))
|
||||
node += hex2num(copytext(token(i), 3))
|
||||
i++
|
||||
else if(lowertext(copytext(token(i), 1, 3)) == "0x" && isnum(hex2num(copytext(token(i), 3))))
|
||||
node += hex2num(copytext(token(i), 3))
|
||||
i++
|
||||
|
||||
else if(isnum(text2num(token(i))))
|
||||
node += text2num(token(i))
|
||||
i++
|
||||
else if(isnum(text2num(token(i))))
|
||||
node += text2num(token(i))
|
||||
i++
|
||||
|
||||
else if(copytext(token(i), 1, 2) in list("'", "\""))
|
||||
i = string(i, node)
|
||||
else if(copytext(token(i), 1, 2) in list("'", "\""))
|
||||
i = string(i, node)
|
||||
|
||||
else if(copytext(token(i), 1, 2) == "{") // Start a list.
|
||||
i = array(i, node)
|
||||
else if(copytext(token(i), 1, 2) == "{") // Start a list.
|
||||
i = array(i, node)
|
||||
|
||||
else
|
||||
i = variable(i, node)
|
||||
else
|
||||
i = variable(i, node)
|
||||
|
||||
return i
|
||||
return i
|
||||
/*EXPLAIN SELECT * WHERE 42 = 6 * 9 OR val = - 5 == 7*/
|
||||
|
||||
@@ -29,64 +29,12 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","mo
|
||||
|
||||
msg = sanitize_simple(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg) return
|
||||
var/original_msg = msg
|
||||
if(selected_type == "Mentorhelp")
|
||||
SSmentor_tickets.newHelpRequest(src, msg)
|
||||
else
|
||||
SStickets.newHelpRequest(src, msg)
|
||||
|
||||
//explode the input msg into a list
|
||||
var/list/msglist = splittext(msg, " ")
|
||||
|
||||
//generate keywords lookup
|
||||
var/list/surnames = list()
|
||||
var/list/forenames = list()
|
||||
var/list/ckeys = list()
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
var/list/indexing = list(M.real_name, M.name)
|
||||
if(M.mind) indexing += M.mind.name
|
||||
|
||||
for(var/string in indexing)
|
||||
var/list/L = splittext(string, " ")
|
||||
var/surname_found = 0
|
||||
//surnames
|
||||
for(var/i=L.len, i>=1, i--)
|
||||
var/word = ckey(L[i])
|
||||
if(word)
|
||||
surnames[word] = M
|
||||
surname_found = i
|
||||
break
|
||||
//forenames
|
||||
for(var/i=1, i<surname_found, i++)
|
||||
var/word = ckey(L[i])
|
||||
if(word)
|
||||
forenames[word] = M
|
||||
//ckeys
|
||||
ckeys[M.ckey] = M
|
||||
|
||||
var/ai_found = 0
|
||||
msg = ""
|
||||
var/list/mobs_found = list()
|
||||
for(var/original_word in msglist)
|
||||
var/word = ckey(original_word)
|
||||
if(word)
|
||||
if(!(word in GLOB.adminhelp_ignored_words))
|
||||
if(word == "ai")
|
||||
ai_found = 1
|
||||
else
|
||||
var/mob/found = ckeys[word]
|
||||
if(!found)
|
||||
found = surnames[word]
|
||||
if(!found)
|
||||
found = forenames[word]
|
||||
if(found)
|
||||
if(!(found in mobs_found))
|
||||
mobs_found += found
|
||||
if(!ai_found && isAI(found))
|
||||
ai_found = 1
|
||||
msg += "<b><font color='black'>[original_word] </font></b> "
|
||||
continue
|
||||
msg += "[original_word] "
|
||||
|
||||
if(!mob) return //this doesn't happen
|
||||
|
||||
//send this msg to all admins
|
||||
//See how many staff are on
|
||||
var/admin_number_afk = 0
|
||||
var/list/mentorholders = list()
|
||||
var/list/modholders = list()
|
||||
@@ -103,59 +51,19 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","mo
|
||||
if(check_rights(R_MENTOR, 0, X.mob))
|
||||
mentorholders += X
|
||||
continue
|
||||
var/ticketNum // Holder for the ticket number
|
||||
var/prunedmsg ="[src]: [msg]" // Message without links
|
||||
var/datum/ticket/T
|
||||
var/isMhelp = selected_type == "Mentorhelp"
|
||||
var/span
|
||||
if(isMhelp)
|
||||
span = "<span class='mentorhelp'>"
|
||||
if(SSmentor_tickets.checkForOpenTicket(src)) // If user already has an open ticket
|
||||
T = SSmentor_tickets.checkForOpenTicket(src)
|
||||
else
|
||||
ticketNum = SSmentor_tickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
|
||||
else //Ahelp
|
||||
span = "<span class='adminhelp'>"
|
||||
if(SStickets.checkForOpenTicket(src)) // If user already has an open ticket
|
||||
T = SStickets.checkForOpenTicket(src) // Make T equal to the ticket they have open
|
||||
else
|
||||
ticketNum = SStickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
|
||||
|
||||
if(T)
|
||||
ticketNum = T.ticketNum // ticketNum is the number of their ticket.
|
||||
T.addResponse(src, msg)
|
||||
|
||||
msg = "[span][selected_type]: </span><span class='boldnotice'>[key_name(src, TRUE, selected_type)] ([ADMIN_QUE(mob,"?")]) ([ADMIN_PP(mob,"PP")]) ([ADMIN_VV(mob,"VV")]) ([ADMIN_TP(mob,"TP")]) ([ADMIN_SM(mob,"SM")]) ([admin_jump_link(mob)]) (<A HREF='?_src_=holder;[isMhelp ? "openmentorticket" : "openadminticket"]=[ticketNum]'>TICKET</A>) [ai_found ? "(<A HREF='?_src_=holder;adminchecklaws=[mob.UID()]'>CL</A>)" : ""] (<A HREF='?_src_=holder;take_question=[ticketNum][isMhelp ? ";is_mhelp=1" : ""]'>TAKE</A>) (<A HREF='?_src_=holder;resolve=[ticketNum][isMhelp ? ";is_mhelp=1" : ""]'>RESOLVE</A>) [isMhelp ? "" : "<A HREF='?_src_=holder;autorespond=[ticketNum]'>(AUTO)</A>"] :</span> [span][msg]</span>"
|
||||
if(isMhelp)
|
||||
//Open a new adminticket and inform the user.
|
||||
SSmentor_tickets.newTicket(src, prunedmsg, msg)
|
||||
for(var/client/X in mentorholders + modholders + adminholders)
|
||||
if(X.prefs.sound & SOUND_MENTORHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
to_chat(X, msg)
|
||||
else //Ahelp
|
||||
//Open a new adminticket and inform the user.
|
||||
SStickets.newTicket(src, prunedmsg, msg)
|
||||
for(var/client/X in modholders + adminholders)
|
||||
if(X.prefs.sound & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
window_flash(X)
|
||||
to_chat(X, msg)
|
||||
|
||||
|
||||
|
||||
//show it to the person adminhelping too
|
||||
to_chat(src, "<span class='boldnotice'>[selected_type]</b>: [original_msg]</span>")
|
||||
to_chat(src, "<span class='boldnotice'>[selected_type]</b>: [msg]</span>")
|
||||
|
||||
var/admin_number_present = adminholders.len - admin_number_afk
|
||||
log_admin("[selected_type]: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins.")
|
||||
log_admin("[selected_type]: [key_name(src)]: [msg] - heard by [admin_number_present] non-AFK admins.")
|
||||
if(admin_number_present <= 0)
|
||||
if(!admin_number_afk)
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [original_msg] - !!No admins online!!")
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [msg] - !!No admins online!!")
|
||||
else
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [original_msg] - !!All admins AFK ([admin_number_afk])!!")
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [msg] - !!All admins AFK ([admin_number_afk])!!")
|
||||
else
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [original_msg]")
|
||||
send2adminirc("[selected_type] from [key_name(src)]: [msg]")
|
||||
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
to_chat(src, "Nowhere to jump to!")
|
||||
return
|
||||
|
||||
if(isobj(usr.loc))
|
||||
var/obj/O = usr.loc
|
||||
O.force_eject_occupant()
|
||||
|
||||
admin_forcemove(usr, T)
|
||||
log_admin("[key_name(usr)] jumped to [A]")
|
||||
if(!isobserver(usr))
|
||||
@@ -35,6 +39,9 @@
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
if(isobj(usr.loc))
|
||||
var/obj/O = usr.loc
|
||||
O.force_eject_occupant()
|
||||
log_admin("[key_name(usr)] jumped to [T.x], [T.y], [T.z] in [T.loc]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [T.x], [T.y], [T.z] in [T.loc]", 1)
|
||||
@@ -52,6 +59,9 @@
|
||||
log_admin("[key_name(usr)] jumped to [key_name(M)]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1)
|
||||
if(isobj(usr.loc))
|
||||
var/obj/O = usr.loc
|
||||
O.force_eject_occupant()
|
||||
if(src.mob)
|
||||
var/mob/A = src.mob
|
||||
var/turf/T = get_turf(M)
|
||||
@@ -70,6 +80,9 @@
|
||||
|
||||
var/turf/T = locate(tx, ty, tz)
|
||||
if(T)
|
||||
if(isobj(usr.loc))
|
||||
var/obj/O = usr.loc
|
||||
O.force_eject_occupant()
|
||||
admin_forcemove(usr, T)
|
||||
if(isobserver(usr))
|
||||
var/mob/dead/observer/O = usr
|
||||
@@ -96,13 +109,15 @@
|
||||
log_admin("[key_name(usr)] jumped to [key_name(M)]")
|
||||
if(!isobserver(usr))
|
||||
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]", 1)
|
||||
|
||||
if(isobj(usr.loc))
|
||||
var/obj/O = usr.loc
|
||||
O.force_eject_occupant()
|
||||
admin_forcemove(usr, M.loc)
|
||||
|
||||
feedback_add_details("admin_verb","JK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/Getmob(var/mob/M in GLOB.mob_list)
|
||||
set category = "Admin"
|
||||
set category = null
|
||||
set name = "Get Mob"
|
||||
set desc = "Mob to teleport"
|
||||
|
||||
@@ -111,11 +126,15 @@
|
||||
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)]")
|
||||
message_admins("[key_name_admin(usr)] teleported [key_name_admin(M)]", 1)
|
||||
|
||||
if(isobj(M.loc))
|
||||
var/obj/O = M.loc
|
||||
O.force_eject_occupant()
|
||||
admin_forcemove(M, get_turf(usr))
|
||||
feedback_add_details("admin_verb","GM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/Getkey()
|
||||
set category = "Admin"
|
||||
set category = null
|
||||
set name = "Get Key"
|
||||
set desc = "Key to teleport"
|
||||
|
||||
@@ -135,6 +154,9 @@
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)]")
|
||||
message_admins("[key_name_admin(usr)] teleported [key_name(M)]", 1)
|
||||
if(M)
|
||||
if(isobj(M.loc))
|
||||
var/obj/O = M.loc
|
||||
O.force_eject_occupant()
|
||||
admin_forcemove(M, get_turf(usr))
|
||||
admin_forcemove(usr, M.loc)
|
||||
feedback_add_details("admin_verb","GK") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -148,6 +170,9 @@
|
||||
|
||||
var/area/A = input(usr, "Pick an area.", "Pick an area") in return_sorted_areas()
|
||||
if(A)
|
||||
if(isobj(M.loc))
|
||||
var/obj/O = M.loc
|
||||
O.force_eject_occupant()
|
||||
admin_forcemove(M, pick(get_area_turfs(A)))
|
||||
feedback_add_details("admin_verb","SMOB") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)] to [A]")
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
/client/proc/cmd_admin_pm_context(mob/M as mob in GLOB.mob_list)
|
||||
set category = null
|
||||
set name = "Admin PM Mob"
|
||||
if(!holder)
|
||||
to_chat(src, "<span class='danger'>Error: Admin-PM-Context: Only administrators may use this command.</span>")
|
||||
if(!check_rights(R_ADMIN|R_MENTOR))
|
||||
return
|
||||
if(!ismob(M) || !M.client)
|
||||
return
|
||||
if( !ismob(M) || !M.client ) return
|
||||
cmd_admin_pm(M.client,null)
|
||||
feedback_add_details("admin_verb","APMM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
//shows a list of clients we could send PMs to, then forwards our choice to cmd_admin_pm
|
||||
/client/proc/cmd_admin_pm_panel()
|
||||
set category = "Admin"
|
||||
set name = "Admin PM Name"
|
||||
if(!holder)
|
||||
to_chat(src, "<span class='danger'>Error: Admin-PM-Panel: Only administrators may use this command.</span>")
|
||||
if(!check_rights(R_ADMIN|R_MENTOR))
|
||||
return
|
||||
var/list/client/targets[0]
|
||||
for(var/client/T)
|
||||
@@ -36,8 +36,7 @@
|
||||
/client/proc/cmd_admin_pm_by_key_panel()
|
||||
set category = "Admin"
|
||||
set name = "Admin PM Key"
|
||||
if(!holder)
|
||||
to_chat(src, "<span class='danger'>Error: Admin-PM-Panel: Only administrators may use this command.</span>")
|
||||
if(!check_rights(R_ADMIN|R_MENTOR))
|
||||
return
|
||||
var/list/client/targets[0]
|
||||
for(var/client/T)
|
||||
@@ -65,9 +64,7 @@
|
||||
|
||||
var/client/C
|
||||
if(istext(whom))
|
||||
if(cmptext(copytext(whom,1,2),"@"))
|
||||
whom = findStealthKey(whom)
|
||||
C = GLOB.directory[whom]
|
||||
C = get_client_by_ckey(whom)
|
||||
else if(istype(whom,/client))
|
||||
C = whom
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
|
||||
if(!msg) return
|
||||
|
||||
var/datum/asays/asay = new(usr.ckey, usr.client.holder.rank, msg, world.timeofday)
|
||||
GLOB.asays += asay
|
||||
log_adminsay(msg, src)
|
||||
|
||||
if(check_rights(R_ADMIN,0))
|
||||
@@ -78,5 +80,5 @@
|
||||
C.verbs -= msay
|
||||
to_chat(C, "<b>Mentor chat has been disabled.</b>")
|
||||
|
||||
admin_log_and_message_admins("toggled mentor chat [enabling ? "on" : "off"].")
|
||||
log_and_message_admins("toggled mentor chat [enabling ? "on" : "off"].")
|
||||
feedback_add_details("admin_verb", "TMC")
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/client/proc/alt_check()
|
||||
set category = "Admin"
|
||||
set name = "Alt Account Checker"
|
||||
|
||||
var/dat = {"<B>Just to be sure you should try to also look up computer IDs/IPs on the server logs for a second opinion.</B>
|
||||
<br>Additionally make an attempt to introduce new players to the server
|
||||
<HR>"}
|
||||
|
||||
if(GLOB.dbcon.IsConnected())
|
||||
for(var/client/C in GLOB.clients)
|
||||
dat += "<p>[C.ckey] (Player Age: <font color = 'red'>[C.player_age]</font>) - <b>[C.computer_id]</b> / <b>[C.address]</b><br>"
|
||||
if(C.related_accounts_cid.len)
|
||||
dat += "--Accounts associated with CID: "
|
||||
dat += "<b>[jointext(C.related_accounts_cid, " - ")]</b><br>"
|
||||
if(C.related_accounts_ip.len)
|
||||
dat += "--Accounts associated with IP: "
|
||||
dat += "<b>[jointext(C.related_accounts_ip, " - ")]</b> "
|
||||
usr << browse(dat, "window=alt_panel;size=640x480")
|
||||
return
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
GLOBAL_LIST_EMPTY(asays)
|
||||
|
||||
/datum/asays
|
||||
var/ckey
|
||||
var/rank
|
||||
var/message
|
||||
var/time
|
||||
|
||||
/datum/asays/New(ckey = "", rank = "", message = "", time = 0)
|
||||
src.ckey = ckey
|
||||
src.rank = rank
|
||||
src.message = message
|
||||
src.time = time
|
||||
|
||||
/client/proc/view_asays()
|
||||
set name = "Asays"
|
||||
set desc = "View Asays from the current round."
|
||||
set category = "Admin"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/list/output = list({"
|
||||
<style>
|
||||
td, th
|
||||
{
|
||||
border: 1px solid #425c6e;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
thead
|
||||
{
|
||||
color: #517087;
|
||||
font-weight: bold;
|
||||
table-layout: fixed;
|
||||
}
|
||||
</style>
|
||||
<a href='byond://?src=[holder.UID()];asays=1'>Refresh</a>
|
||||
<table style='width: 100%; border-collapse: collapse; table-layout: auto; margin-top: 3px;'>
|
||||
"})
|
||||
|
||||
// Header & body start
|
||||
output += {"
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="5%">Time</th>
|
||||
<th width="10%">Ckey</th>
|
||||
<th width="85%">Message</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
"}
|
||||
|
||||
for(var/datum/asays/A in GLOB.asays)
|
||||
var/timestr = time2text(A.time, "hh:mm:ss")
|
||||
output += {"
|
||||
<tr>
|
||||
<td width="5%">[timestr]</td>
|
||||
<td width="10%"><b>[A.ckey] ([A.rank])</b></td>
|
||||
<td width="85%">[A.message]</td>
|
||||
</tr>
|
||||
"}
|
||||
|
||||
output += {"
|
||||
</tbody>
|
||||
</table>"}
|
||||
|
||||
var/datum/browser/popup = new(src, "asays", "<div align='center'>Current Round Asays</div>", 1200, 825)
|
||||
popup.set_content(output.Join())
|
||||
popup.open(0)
|
||||
@@ -3,8 +3,7 @@
|
||||
set category = "Event"
|
||||
set name = "Change Custom Event"
|
||||
|
||||
if(!holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
if(!check_rights(R_EVENT))
|
||||
return
|
||||
|
||||
var/input = input(usr, "Enter the description of the custom event. Be descriptive. To cancel the event, make this blank or hit cancel.", "Custom Event", GLOB.custom_event_msg) as message|null
|
||||
|
||||
@@ -168,7 +168,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
#endif
|
||||
|
||||
/client/proc/callproc_datum(var/A as null|area|mob|obj|turf)
|
||||
set category = "Debug"
|
||||
set category = null
|
||||
set name = "Atom ProcCall"
|
||||
|
||||
if(!check_rights(R_PROCCALL))
|
||||
@@ -418,25 +418,6 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
else
|
||||
alert("Invalid mob")
|
||||
|
||||
//TODO: merge the vievars version into this or something maybe mayhaps
|
||||
/client/proc/cmd_debug_del_all()
|
||||
set category = "Debug"
|
||||
set name = "Del-All"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
// to prevent REALLY stupid deletions
|
||||
var/blocked = list(/mob/living, /mob/living/carbon, /mob/living/carbon/human, /mob/dead, /mob/dead/observer, /mob/living/silicon, /mob/living/silicon/robot, /mob/living/silicon/ai)
|
||||
var/hsbitem = input(usr, "Choose an object to delete.", "Delete:") as null|anything in subtypesof(/obj) + subtypesof(/mob) - blocked
|
||||
if(hsbitem)
|
||||
for(var/atom/O in world)
|
||||
if(istype(O, hsbitem))
|
||||
qdel(O)
|
||||
log_admin("[key_name(src)] has deleted all instances of [hsbitem].")
|
||||
message_admins("[key_name_admin(src)] has deleted all instances of [hsbitem].", 0)
|
||||
feedback_add_details("admin_verb","DELA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_debug_del_sing()
|
||||
set category = "Debug"
|
||||
set name = "Del Singulo / Tesla"
|
||||
@@ -643,7 +624,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
for(var/areatype in areas_without_camera)
|
||||
to_chat(world, "* [areatype]")
|
||||
|
||||
/client/proc/cmd_admin_dress(var/mob/living/carbon/human/M in GLOB.mob_list)
|
||||
/client/proc/cmd_admin_dress(mob/living/carbon/human/M in GLOB.human_list)
|
||||
set category = "Event"
|
||||
set name = "Select equipment"
|
||||
|
||||
@@ -917,6 +898,9 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
|
||||
if(istype(landmark))
|
||||
var/datum/map_template/ruin/template = landmark.ruin_template
|
||||
if(isobj(usr.loc))
|
||||
var/obj/O = usr.loc
|
||||
O.force_eject_occupant()
|
||||
admin_forcemove(usr, get_turf(landmark))
|
||||
|
||||
to_chat(usr, "<span class='name'>[template.name]</span>")
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
|
||||
/client/proc/reload_admins()
|
||||
set name = "Reload Admins"
|
||||
set category = "Debug"
|
||||
set category = "Server"
|
||||
|
||||
if(!check_rights(R_SERVER))
|
||||
return
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
if(alert("Do you want these characters automatically classified as antagonists?",,"Yes","No")=="Yes")
|
||||
is_syndicate = 1
|
||||
|
||||
var/datum/outfit/O = outfit_list[dresscode]
|
||||
var/list/players_to_spawn = list()
|
||||
if(pick_manually)
|
||||
var/list/possible_ghosts = list()
|
||||
@@ -52,14 +53,12 @@
|
||||
players_to_spawn += candidate
|
||||
else
|
||||
to_chat(src, "Polling candidates...")
|
||||
players_to_spawn = pollCandidates("Do you want to play as an event character?")
|
||||
players_to_spawn = SSghost_spawns.poll_candidates("Do you want to play as \a [initial(O.name)]?")
|
||||
|
||||
if(!players_to_spawn.len)
|
||||
to_chat(src, "Nobody volunteered.")
|
||||
return 0
|
||||
|
||||
var/datum/outfit/O = outfit_list[dresscode]
|
||||
|
||||
var/players_spawned = 0
|
||||
for(var/mob/thisplayer in players_to_spawn)
|
||||
var/mob/living/carbon/human/H = new /mob/living/carbon/human(T)
|
||||
@@ -94,4 +93,3 @@
|
||||
feedback_add_details("admin_verb","SPAWNGIM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ GLOBAL_VAR_INIT(sent_syndicate_infiltration_team, 0)
|
||||
infiltrators += candidate
|
||||
else
|
||||
to_chat(src, "Polling candidates...")
|
||||
infiltrators = pollCandidates("Do you want to play as a SYNDICATE INFILTRATOR?", ROLE_TRAITOR, 1)
|
||||
var/image/I = new('icons/obj/cardboard_cutout.dmi', "cutout_sit")
|
||||
infiltrators = SSghost_spawns.poll_candidates("Do you want to play as a Syndicate infiltrator?", ROLE_TRAITOR, TRUE, source = I, role_cleanname = "Syndicate infiltrator")
|
||||
|
||||
if(!infiltrators.len)
|
||||
to_chat(src, "Nobody volunteered.")
|
||||
|
||||
@@ -2,10 +2,20 @@ GLOBAL_LIST_INIT(open_logging_views, list())
|
||||
|
||||
/client/proc/cmd_admin_open_logging_view()
|
||||
set category = "Admin"
|
||||
set name = "Open Logging View"
|
||||
set name = "Logging View"
|
||||
set desc = "Opens the detailed logging viewer"
|
||||
open_logging_view()
|
||||
|
||||
if(!GLOB.open_logging_views[usr.client.ckey])
|
||||
GLOB.open_logging_views[usr.client.ckey] = new /datum/log_viewer()
|
||||
var/datum/log_viewer/LV = GLOB.open_logging_views[usr.client.ckey]
|
||||
LV.show_ui(usr)
|
||||
/client/proc/open_logging_view(list/mob/mobs_to_add = null, clear_view = FALSE)
|
||||
var/datum/log_viewer/cur_view = GLOB.open_logging_views[usr.client.ckey]
|
||||
if(!cur_view)
|
||||
cur_view = new /datum/log_viewer()
|
||||
GLOB.open_logging_views[usr.client.ckey] = cur_view
|
||||
else if(clear_view)
|
||||
cur_view.clear_all()
|
||||
|
||||
if(mobs_to_add?.len)
|
||||
cur_view.add_mobs(mobs_to_add)
|
||||
|
||||
cur_view.show_ui(usr)
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
set category = "Debug"
|
||||
set name = "Map template - Place"
|
||||
|
||||
if(!holder)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/datum/map_template/template
|
||||
|
||||
var/map = input(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template") as null|anything in GLOB.map_templates
|
||||
@@ -36,6 +37,9 @@
|
||||
set category = "Debug"
|
||||
set name = "Map Template - Upload"
|
||||
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/map = input(usr, "Choose a Map Template to upload to template storage","Upload Map Template") as null|file
|
||||
if(!map)
|
||||
return
|
||||
|
||||
@@ -26,9 +26,9 @@ GLOBAL_VAR_INIT(intercom_range_display_status, 0)
|
||||
icon = 'icons/480x480.dmi'
|
||||
icon_state = "25percent"
|
||||
|
||||
New()
|
||||
src.pixel_x = -224
|
||||
src.pixel_y = -224
|
||||
/obj/effect/debugging/camera_range/New()
|
||||
src.pixel_x = -224
|
||||
src.pixel_y = -224
|
||||
|
||||
/obj/effect/debugging/mapfix_marker
|
||||
name = "map fix marker"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
client/proc/one_click_antag()
|
||||
/client/proc/one_click_antag()
|
||||
set name = "Create Antagonist"
|
||||
set desc = "Auto-create an antagonist of your choice"
|
||||
set category = "Event"
|
||||
@@ -137,7 +137,8 @@ client/proc/one_click_antag()
|
||||
var/confirm = alert("Are you sure?", "Confirm creation", "Yes", "No")
|
||||
if(confirm != "Yes")
|
||||
return 0
|
||||
var/list/candidates = pollCandidates("Do you wish to be considered for the position of a Wizard Foundation 'diplomat'?", "wizard")
|
||||
var/image/I = new('icons/mob/simple_human.dmi', "wizard")
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you wish to be considered for the position of a Wizard Foundation 'diplomat'?", "wizard", source = I)
|
||||
|
||||
log_admin("[key_name(owner)] tried making a Wizard with One-Click-Antag")
|
||||
message_admins("[key_name_admin(owner)] tried making a Wizard with One-Click-Antag")
|
||||
@@ -241,7 +242,7 @@ client/proc/one_click_antag()
|
||||
var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb")
|
||||
var/obj/effect/landmark/closet_spawn = locate("landmark*Nuclear-Closet")
|
||||
|
||||
var/nuke_code = "[rand(10000, 99999)]"
|
||||
var/nuke_code = rand(10000, 99999)
|
||||
|
||||
if(nuke_spawn)
|
||||
var/obj/item/paper/P = new
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
var/obj/item/slot_item_hand = H.get_item_by_slot(slot_r_hand)
|
||||
H.unEquip(slot_item_hand)
|
||||
|
||||
var /obj/item/multisword/pure_evil/multi = new(H)
|
||||
var/obj/item/multisword/pure_evil/multi = new(H)
|
||||
H.equip_to_slot_or_del(multi, slot_r_hand)
|
||||
|
||||
var/obj/item/card/id/W = new(H)
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
set name = "Possess Obj"
|
||||
set category = null
|
||||
|
||||
if(!check_rights(R_POSSESS))
|
||||
return
|
||||
|
||||
if(istype(O,/obj/singularity))
|
||||
if(config.forbid_singulo_possession)
|
||||
to_chat(usr, "It is forbidden to possess singularities.")
|
||||
@@ -35,6 +38,9 @@
|
||||
set category = null
|
||||
//usr.loc = get_turf(usr)
|
||||
|
||||
if(!check_rights(R_POSSESS))
|
||||
return
|
||||
|
||||
if(usr.control_object && usr.name_archive) //if you have a name archived and if you are actually relassing an object
|
||||
usr.real_name = usr.name_archive
|
||||
usr.name = usr.real_name
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
if(!ismob(M))
|
||||
return
|
||||
|
||||
if(!check_rights(R_SERVER|R_EVENT))
|
||||
if(!check_rights(R_EVENT))
|
||||
return
|
||||
|
||||
var/msg = clean_input("Message:", text("Subtle PM to [M.key]"))
|
||||
@@ -123,7 +123,7 @@
|
||||
feedback_add_details("admin_verb","GLN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_direct_narrate(var/mob/M) // Targetted narrate -- TLE
|
||||
set category = "Event"
|
||||
set category = null
|
||||
set name = "Direct Narrate"
|
||||
|
||||
if(!check_rights(R_SERVER|R_EVENT))
|
||||
@@ -158,7 +158,7 @@
|
||||
/client/proc/admin_headset_message(mob/M in GLOB.mob_list, sender = null)
|
||||
var/mob/living/carbon/human/H = M
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
if(!check_rights(R_EVENT))
|
||||
return
|
||||
|
||||
if(!istype(H))
|
||||
@@ -201,7 +201,7 @@
|
||||
feedback_add_details("admin_verb","GOD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
|
||||
/proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
|
||||
if(automute)
|
||||
if(!config.automute_on)
|
||||
return
|
||||
@@ -572,7 +572,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
feedback_add_details("admin_verb","IONC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_rejuvenate(mob/living/M as mob in GLOB.mob_list)
|
||||
set category = "Event"
|
||||
set category = null
|
||||
set name = "Rejuvenate"
|
||||
|
||||
if(!check_rights(R_REJUVINATE))
|
||||
@@ -624,11 +624,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
var/beepsound = input(usr, "What sound should the announcement make?", "Announcement Sound", "") as anything in MsgSound
|
||||
|
||||
GLOB.command_announcement.Announce(input, customname, MsgSound[beepsound], , , type)
|
||||
print_command_report(input, "[command_name()] Update")
|
||||
print_command_report(input, customname)
|
||||
if("No")
|
||||
//same thing as the blob stuff - it's not public, so it's classified, dammit
|
||||
GLOB.command_announcer.autosay("A classified message has been printed out at all communication consoles.")
|
||||
print_command_report(input, "Classified [command_name()] Update")
|
||||
print_command_report(input, "Classified: [customname]")
|
||||
else
|
||||
return
|
||||
|
||||
@@ -638,7 +638,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
|
||||
|
||||
/client/proc/cmd_admin_delete(atom/A as obj|mob|turf in view())
|
||||
set category = "Admin"
|
||||
set category = null
|
||||
set name = "Delete"
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
@@ -826,7 +826,10 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
else
|
||||
SSshuttle.emergency.canRecall = FALSE
|
||||
|
||||
SSshuttle.emergency.request()
|
||||
if(seclevel2num(get_security_level()) >= SEC_LEVEL_RED)
|
||||
SSshuttle.emergency.request(coefficient = 0.5, redAlert = TRUE)
|
||||
else
|
||||
SSshuttle.emergency.request()
|
||||
|
||||
feedback_add_details("admin_verb","CSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
log_admin("[key_name(usr)] admin-called the emergency shuttle.")
|
||||
@@ -871,9 +874,13 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
if(alert(usr, "Do you want to [SSshuttle.emergencyNoEscape ? "ALLOW" : "DENY"] shuttle calls?", "Toggle Deny Shuttle", "Yes", "No") != "Yes")
|
||||
return
|
||||
|
||||
if(SSshuttle)
|
||||
SSshuttle.emergencyNoEscape = !SSshuttle.emergencyNoEscape
|
||||
|
||||
feedback_add_details("admin_verb", "DENYSHUT")
|
||||
log_admin("[key_name(src)] has [SSshuttle.emergencyNoEscape ? "denied" : "allowed"] the shuttle to be called.")
|
||||
message_admins("[key_name_admin(usr)] has [SSshuttle.emergencyNoEscape ? "denied" : "allowed"] the shuttle to be called.")
|
||||
|
||||
@@ -979,7 +986,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
var/role_string
|
||||
var/obj_count = 0
|
||||
var/obj_string = ""
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(!isLivingSSD(H))
|
||||
continue
|
||||
mins_ssd = round((world.time - H.last_logout) / 600)
|
||||
@@ -1016,7 +1024,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
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
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(H.client == null || H.stat == DEAD) // No clientless or dead
|
||||
continue
|
||||
mins_afk = round(H.client.inactivity / 600)
|
||||
@@ -1072,12 +1081,12 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
message_admins("Admin [key_name_admin(usr)] has disabled ERT calling.", 1)
|
||||
|
||||
/client/proc/show_tip()
|
||||
set category = "Admin"
|
||||
set category = "Event"
|
||||
set name = "Show Custom Tip"
|
||||
set desc = "Sends a tip (that you specify) to all players. After all \
|
||||
you're the experienced player here."
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
if(!check_rights(R_EVENT))
|
||||
return
|
||||
|
||||
var/input = input(usr, "Please specify your tip that you want to send to the players.", "Tip", "") as message|null
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/client/proc/spawn_floor_cluwne()
|
||||
set category = "Event"
|
||||
set name = "Unleash Floor Cluwne"
|
||||
set desc = "Pick a specific target or just let it select randomly and spawn the floor cluwne mob on the station. Be warned: spawning more than one may cause issues!"
|
||||
var/mob/living/carbon/human/target
|
||||
|
||||
if(!check_rights(R_EVENT))
|
||||
return
|
||||
|
||||
var/confirm = alert("Are you sure you want to release a floor cluwne and kill a lot of people?", "Confirm Massacre", "Yes", "No")
|
||||
if(confirm == "Yes")
|
||||
|
||||
var/turf/T = get_turf(usr)
|
||||
var/list/potential_targets = list()
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(!istype(H))
|
||||
continue
|
||||
if(H.mind.assigned_role == "Cluwne")
|
||||
continue
|
||||
potential_targets += H
|
||||
if(!potential_targets.len) //You're probably the only player on this damn station, spawn it yourself
|
||||
to_chat(src, "<span class='notice'>No valid targets!</span>")
|
||||
return
|
||||
target = input("Any specific target in mind? Please note only live, non cluwned, human targets are valid.", "Target", target) as null|anything in potential_targets
|
||||
var/mob/living/simple_animal/hostile/floor_cluwne/FC = new /mob/living/simple_animal/hostile/floor_cluwne(T)
|
||||
if(target)
|
||||
FC.Acquire_Victim(target)
|
||||
log_admin("[key_name(usr)] spawned floor cluwne[target ? ", initially targetting [target]": null].")
|
||||
message_admins("[key_name(usr)] spawned floor cluwne[target ? ", initially targetting [target]": null].")
|
||||
@@ -37,7 +37,8 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
|
||||
break
|
||||
|
||||
// Find ghosts willing to be DS
|
||||
var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, COMMANDOS_POSSIBLE, "Join the DeathSquad?",, 21, 600, 1, GLOB.role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE)
|
||||
var/image/source = image('icons/obj/cardboard_cutout.dmi', "cutout_deathsquad")
|
||||
var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, COMMANDOS_POSSIBLE, "Join the DeathSquad?",, 21, 60 SECONDS, TRUE, GLOB.role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE, source = source)
|
||||
if(!commando_ghosts.len)
|
||||
to_chat(usr, "<span class='userdanger'>Nobody volunteered to join the DeathSquad.</span>")
|
||||
return
|
||||
@@ -163,6 +164,7 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
|
||||
R.set_frequency(DTH_FREQ)
|
||||
R.requires_tcomms = FALSE
|
||||
R.instant = TRUE
|
||||
R.freqlock = TRUE
|
||||
equip_to_slot_or_del(R, slot_l_ear)
|
||||
if(is_leader)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(src), slot_w_uniform)
|
||||
|
||||
@@ -45,7 +45,8 @@ GLOBAL_VAR_INIT(sent_syndicate_strike_team, 0)
|
||||
break
|
||||
|
||||
// Find ghosts willing to be SST
|
||||
var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, SYNDICATE_COMMANDOS_POSSIBLE, "Join the Syndicate Strike Team?",, 21, 600, 1, GLOB.role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE)
|
||||
var/image/I = new('icons/obj/cardboard_cutout.dmi', "cutout_commando")
|
||||
var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, SYNDICATE_COMMANDOS_POSSIBLE, "Join the Syndicate Strike Team?",, 21, 60 SECONDS, TRUE, GLOB.role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE, source = I)
|
||||
if(!commando_ghosts.len)
|
||||
to_chat(usr, "<span class='userdanger'>Nobody volunteered to join the SST.</span>")
|
||||
return
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
#define ALARM_RESET_DELAY 100 // How long will the alarm/trigger remain active once origin/source has been found to be gone?
|
||||
|
||||
/datum/alarm_source
|
||||
var/source = null // The source trigger
|
||||
var/source_name = "" // The name of the source should it be lost (for example a destroyed camera)
|
||||
var/duration = 0 // How long this source will be alarming, 0 for indefinetely.
|
||||
var/severity = 1 // How severe the alarm from this source is.
|
||||
var/start_time = 0 // When this source began alarming.
|
||||
var/end_time = 0 // Use to set when this trigger should clear, in case the source is lost.
|
||||
|
||||
/datum/alarm_source/New(var/atom/source)
|
||||
src.source = source
|
||||
start_time = world.time
|
||||
source_name = source.get_source_name()
|
||||
|
||||
/datum/alarm
|
||||
var/atom/origin //Used to identify the alarm area.
|
||||
var/list/sources = new() //List of sources triggering the alarm. Used to determine when the alarm should be cleared.
|
||||
var/list/sources_assoc = new() //Associative list of source triggers. Used to efficiently acquire the alarm source.
|
||||
var/list/cameras //List of cameras that can be switched to, if the player has that capability.
|
||||
var/area/last_area //The last acquired area, used should origin be lost (for example a destroyed borg containing an alarming camera).
|
||||
var/area/last_name //The last acquired name, used should origin be lost
|
||||
var/area/last_camera_area //The last area in which cameras where fetched, used to see if the camera list should be updated.
|
||||
var/end_time //Used to set when this alarm should clear, in case the origin is lost.
|
||||
|
||||
/datum/alarm/New(var/atom/origin, var/atom/source, var/duration, var/severity)
|
||||
src.origin = origin
|
||||
|
||||
cameras() // Sets up both cameras and last alarm area.
|
||||
set_source_data(source, duration, severity)
|
||||
|
||||
/datum/alarm/process()
|
||||
// Has origin gone missing?
|
||||
if(!origin && !end_time)
|
||||
end_time = world.time + ALARM_RESET_DELAY
|
||||
for(var/datum/alarm_source/AS in sources)
|
||||
// Has the alarm passed its best before date?
|
||||
if((AS.end_time && world.time > AS.end_time) || (AS.duration && world.time > (AS.start_time + AS.duration)))
|
||||
sources -= AS
|
||||
// Has the source gone missing? Then reset the normal duration and set end_time
|
||||
if(!AS.source && !AS.end_time) // end_time is used instead of duration to ensure the reset doesn't remain in the future indefinetely.
|
||||
AS.duration = 0
|
||||
AS.end_time = world.time + ALARM_RESET_DELAY
|
||||
|
||||
/datum/alarm/proc/set_source_data(var/atom/source, var/duration, var/severity)
|
||||
var/datum/alarm_source/AS = sources_assoc[source]
|
||||
if(!AS)
|
||||
AS = new/datum/alarm_source(source)
|
||||
sources += AS
|
||||
sources_assoc[source] = AS
|
||||
// Currently only non-0 durations can be altered (normal alarms VS EMP blasts)
|
||||
if(AS.duration)
|
||||
duration = duration SECONDS
|
||||
AS.duration = duration
|
||||
AS.severity = severity
|
||||
|
||||
/datum/alarm/proc/clear(var/source)
|
||||
var/datum/alarm_source/AS = sources_assoc[source]
|
||||
sources -= AS
|
||||
sources_assoc -= source
|
||||
|
||||
/datum/alarm/proc/alarm_area()
|
||||
if(!origin)
|
||||
return last_area
|
||||
|
||||
last_area = origin.get_alarm_area()
|
||||
return last_area
|
||||
|
||||
/datum/alarm/proc/alarm_name()
|
||||
if(!origin)
|
||||
return last_name
|
||||
|
||||
last_name = origin.get_alarm_name()
|
||||
return last_name
|
||||
|
||||
/datum/alarm/proc/cameras()
|
||||
// If the alarm origin has changed area, for example a borg containing an alarming camera, reset the list of cameras
|
||||
if(cameras && (last_camera_area != alarm_area()))
|
||||
cameras = null
|
||||
|
||||
// The list of cameras is also reset by /proc/invalidateCameraCache()
|
||||
if(!cameras)
|
||||
cameras = origin ? origin.get_alarm_cameras() : last_area.get_alarm_cameras()
|
||||
|
||||
last_camera_area = last_area
|
||||
return cameras
|
||||
|
||||
/datum/alarm/proc/max_severity()
|
||||
var/max_severity = 0
|
||||
for(var/datum/alarm_source/AS in sources)
|
||||
max_severity = max(AS.severity, max_severity)
|
||||
|
||||
return max_severity
|
||||
|
||||
/******************
|
||||
* Assisting procs *
|
||||
******************/
|
||||
/atom/proc/get_alarm_area()
|
||||
var/area/A = get_area(src)
|
||||
return A
|
||||
|
||||
/area/get_alarm_area()
|
||||
return src
|
||||
|
||||
/atom/proc/get_alarm_name()
|
||||
var/area/A = get_area(src)
|
||||
return A.name
|
||||
|
||||
/area/get_alarm_name()
|
||||
return name
|
||||
|
||||
/mob/get_alarm_name()
|
||||
return name
|
||||
|
||||
/atom/proc/get_source_name()
|
||||
return name
|
||||
|
||||
/obj/machinery/camera/get_source_name()
|
||||
return c_tag
|
||||
|
||||
/atom/proc/get_alarm_cameras()
|
||||
var/area/A = get_area(src)
|
||||
return A.get_cameras()
|
||||
|
||||
/area/get_alarm_cameras()
|
||||
return get_cameras()
|
||||
|
||||
/mob/living/silicon/robot/get_alarm_cameras()
|
||||
var/list/cameras = ..()
|
||||
if(camera)
|
||||
cameras += camera
|
||||
|
||||
return cameras
|
||||
|
||||
/mob/living/silicon/robot/syndicate/get_alarm_cameras()
|
||||
return list()
|
||||
@@ -1,103 +0,0 @@
|
||||
#define ALARM_RAISED 1
|
||||
#define ALARM_CLEARED 0
|
||||
|
||||
/datum/alarm_handler
|
||||
var/category = ""
|
||||
var/list/datum/alarm/alarms = new // All alarms, to handle cases when an origin has been deleted with one or more active alarms
|
||||
var/list/datum/alarm/alarms_assoc = new // Associative list of alarms, to efficiently acquire them based on origin.
|
||||
var/list/listeners = new // A list of all objects interested in alarm changes.
|
||||
|
||||
/datum/alarm_handler/process()
|
||||
for(var/datum/alarm/A in alarms)
|
||||
A.process()
|
||||
check_alarm_cleared(A)
|
||||
|
||||
/datum/alarm_handler/proc/triggerAlarm(var/atom/origin, var/atom/source, var/duration = 0, var/severity = 1)
|
||||
var/new_alarm
|
||||
//Proper origin and source mandatory
|
||||
if(!(origin && source))
|
||||
return
|
||||
origin = origin.get_alarm_origin()
|
||||
|
||||
new_alarm = 0
|
||||
//see if there is already an alarm of this origin
|
||||
var/datum/alarm/existing = alarms_assoc[origin]
|
||||
if(existing)
|
||||
existing.set_source_data(source, duration, severity)
|
||||
else
|
||||
existing = new/datum/alarm(origin, source, duration, severity)
|
||||
new_alarm = 1
|
||||
|
||||
alarms |= existing
|
||||
alarms_assoc[origin] = existing
|
||||
if(new_alarm)
|
||||
alarms = dd_sortedObjectList(alarms)
|
||||
on_alarm_change(existing, ALARM_RAISED)
|
||||
|
||||
return new_alarm
|
||||
|
||||
/datum/alarm_handler/proc/clearAlarm(var/atom/origin, var/source)
|
||||
//Proper origin and source mandatory
|
||||
if(!(origin && source))
|
||||
return
|
||||
origin = origin.get_alarm_origin()
|
||||
|
||||
var/datum/alarm/existing = alarms_assoc[origin]
|
||||
if(existing)
|
||||
existing.clear(source)
|
||||
return check_alarm_cleared(existing)
|
||||
|
||||
/datum/alarm_handler/proc/has_major_alarms()
|
||||
if(alarms && alarms.len)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/alarm_handler/proc/major_alarms()
|
||||
return alarms
|
||||
|
||||
/datum/alarm_handler/proc/minor_alarms()
|
||||
return alarms
|
||||
|
||||
/datum/alarm_handler/proc/check_alarm_cleared(var/datum/alarm/alarm)
|
||||
if((alarm.end_time && world.time > alarm.end_time) || !alarm.sources.len)
|
||||
alarms -= alarm
|
||||
alarms_assoc -= alarm.origin
|
||||
on_alarm_change(alarm, ALARM_CLEARED)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/alarm_handler/proc/on_alarm_change(var/datum/alarm/alarm, var/was_raised)
|
||||
for(var/obj/machinery/camera/C in alarm.cameras())
|
||||
if(was_raised)
|
||||
C.network.Add(category)
|
||||
else
|
||||
C.network.Remove(category)
|
||||
notify_listeners(alarm, was_raised)
|
||||
|
||||
/datum/alarm_handler/proc/get_alarm_severity_for_origin(var/atom/origin)
|
||||
if(!origin)
|
||||
return
|
||||
|
||||
origin = origin.get_alarm_origin()
|
||||
var/datum/alarm/existing = alarms_assoc[origin]
|
||||
if(!existing)
|
||||
return
|
||||
|
||||
return existing.max_severity()
|
||||
|
||||
/atom/proc/get_alarm_origin()
|
||||
return src
|
||||
|
||||
/turf/get_alarm_origin()
|
||||
var/area/area = get_area(src)
|
||||
return area // Very important to get area.master, as dynamic lightning can and will split areas.
|
||||
|
||||
/datum/alarm_handler/proc/register(var/object, var/procName)
|
||||
listeners[object] = procName
|
||||
|
||||
/datum/alarm_handler/proc/unregister(var/object)
|
||||
listeners -= object
|
||||
|
||||
/datum/alarm_handler/proc/notify_listeners(var/alarm, var/was_raised)
|
||||
for(var/listener in listeners)
|
||||
call(listener, listeners[listener])(src, alarm, was_raised)
|
||||
@@ -1,19 +0,0 @@
|
||||
/datum/alarm_handler/atmosphere
|
||||
category = "Atmosphere Alarms"
|
||||
|
||||
/datum/alarm_handler/atmosphere/triggerAlarm(var/atom/origin, var/atom/source, var/duration = 0, var/severity = 1)
|
||||
..()
|
||||
|
||||
/datum/alarm_handler/atmosphere/major_alarms()
|
||||
var/list/major_alarms = new()
|
||||
for(var/datum/alarm/A in alarms)
|
||||
if(A.max_severity() > 1)
|
||||
major_alarms.Add(A)
|
||||
return major_alarms
|
||||
|
||||
/datum/alarm_handler/atmosphere/minor_alarms()
|
||||
var/list/minor_alarms = new()
|
||||
for(var/datum/alarm/A in alarms)
|
||||
if(A.max_severity() == 1)
|
||||
minor_alarms.Add(A)
|
||||
return minor_alarms
|
||||
@@ -1,2 +0,0 @@
|
||||
/datum/alarm_handler/burglar
|
||||
category = "Burglar Alarms"
|
||||
@@ -1,2 +0,0 @@
|
||||
/datum/alarm_handler/camera
|
||||
category = "Camera Alarms"
|
||||
@@ -1,11 +0,0 @@
|
||||
/datum/alarm_handler/fire
|
||||
category = "Fire Alarms"
|
||||
|
||||
/datum/alarm_handler/fire/on_alarm_change(var/datum/alarm/alarm, var/was_raised)
|
||||
var/area/A = alarm.origin
|
||||
if(istype(A))
|
||||
if(was_raised)
|
||||
A.fire_alert()
|
||||
else
|
||||
A.fire_reset()
|
||||
..()
|
||||
@@ -1,2 +0,0 @@
|
||||
/datum/alarm_handler/motion
|
||||
category = "Motion Alarms"
|
||||
@@ -1,10 +0,0 @@
|
||||
/datum/alarm_handler/power
|
||||
category = "Power Alarms"
|
||||
|
||||
/datum/alarm_handler/power/on_alarm_change(var/datum/alarm/alarm, var/was_raised)
|
||||
var/area/A = alarm.origin
|
||||
if(istype(A))
|
||||
A.power_alert(was_raised)
|
||||
..()
|
||||
|
||||
/area/proc/power_alert(var/alarming)
|
||||
@@ -73,7 +73,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/datum/antagonist/proc/replace_banned_player()
|
||||
set waitfor = FALSE
|
||||
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as a [name]?", job_rank, TRUE, 50)
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as a [name]?", job_rank, TRUE, 5 SECONDS)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
|
||||
|
||||
@@ -46,7 +46,8 @@
|
||||
checking = TRUE
|
||||
|
||||
to_chat(user, "<span class='notice'>You activate [src] and wait for confirmation.</span>")
|
||||
var/list/nuke_candidates = pollCandidates("Do you want to play as a [rolename]?", ROLE_OPERATIVE, TRUE, 150)
|
||||
var/image/I = new('icons/mob/simple_human.dmi', "syndicate_space_sword")
|
||||
var/list/nuke_candidates = SSghost_spawns.poll_candidates("Do you want to play as a [rolename]?", ROLE_OPERATIVE, TRUE, 15 SECONDS, source = I)
|
||||
if(LAZYLEN(nuke_candidates))
|
||||
checking = FALSE
|
||||
if(QDELETED(src) || !check_usability(user))
|
||||
@@ -180,7 +181,7 @@
|
||||
var/type = "slaughter"
|
||||
if(demon_type == /mob/living/simple_animal/slaughter/laughter)
|
||||
type = "laughter"
|
||||
var/list/candidates = pollCandidates("Do you want to play as a [type] demon summoned by [user.real_name]?", ROLE_DEMON, 1, 100)
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a [type] demon summoned by [user.real_name]?", ROLE_DEMON, TRUE, 10 SECONDS, source = demon_type)
|
||||
|
||||
if(candidates.len > 0)
|
||||
var/mob/C = pick(candidates)
|
||||
@@ -194,7 +195,7 @@
|
||||
to_chat(user, "<span class='notice'>The demons do not respond to your summon. Perhaps you should try again later.</span>")
|
||||
|
||||
/obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, type = "", mob/user)
|
||||
var /obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
|
||||
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
|
||||
var/mob/living/simple_animal/slaughter/S = new demon_type(holder)
|
||||
S.vialspawned = TRUE
|
||||
S.holder = holder
|
||||
@@ -252,7 +253,7 @@
|
||||
used = TRUE
|
||||
to_chat(user, "<span class='notice'>You break the seal on the bottle, calling upon the dire sludge to awaken...</span>")
|
||||
|
||||
var/list/candidates = pollCandidates("Do you want to play as a magical morph awakened by [user.real_name]?", ROLE_MORPH, 1, 100)
|
||||
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a magical morph awakened by [user.real_name]?", ROLE_MORPH, 1, 10 SECONDS, source = morph_type)
|
||||
|
||||
if(candidates.len > 0)
|
||||
var/mob/C = pick(candidates)
|
||||
|
||||
@@ -41,9 +41,8 @@
|
||||
A.common_radio.channels.Remove("Syndicate") // De-traitored AIs can still state laws over the syndicate channel without this
|
||||
A.laws.sorted_laws = A.laws.inherent_laws.Copy() // AI's 'notify laws' button will still state a law 0 because sorted_laws contains it
|
||||
A.show_laws()
|
||||
A.malf_picker.remove_malf_verbs(A)
|
||||
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
|
||||
qdel(A.malf_picker)
|
||||
A.remove_malf_abilities()
|
||||
QDEL_NULL(A.malf_picker)
|
||||
|
||||
if(owner.som)
|
||||
var/datum/mindslaves/slaved = owner.som
|
||||
@@ -251,9 +250,14 @@
|
||||
|
||||
|
||||
/datum/antagonist/traitor/proc/update_traitor_icons_added(datum/mind/traitor_mind)
|
||||
var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
traitorhud.join_hud(owner.current, null)
|
||||
set_antag_hud(owner.current, "hudsyndicate")
|
||||
if(locate(/datum/objective/hijack) in owner.objectives)
|
||||
var/datum/atom_hud/antag/hijackhud = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
hijackhud.join_hud(owner.current, null)
|
||||
set_antag_hud(owner.current, "hudhijack")
|
||||
else
|
||||
var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR]
|
||||
traitorhud.join_hud(owner.current, null)
|
||||
set_antag_hud(owner.current, "hudsyndicate")
|
||||
|
||||
|
||||
/datum/antagonist/traitor/proc/update_traitor_icons_removed(datum/mind/traitor_mind)
|
||||
@@ -400,7 +404,7 @@
|
||||
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
|
||||
var/responses = jointext(GLOB.syndicate_code_response, ", ")
|
||||
|
||||
var message = "<br><b>The code phrases were:</b> <span class='bluetext'>[phrases]</span><br>\
|
||||
var/message = "<br><b>The code phrases were:</b> <span class='bluetext'>[phrases]</span><br>\
|
||||
<b>The code responses were:</b> <span class='redtext'>[responses]</span><br>"
|
||||
|
||||
return message
|
||||
|
||||
@@ -203,6 +203,12 @@ GLOBAL_DATUM_INIT(global_prizes, /datum/prizes, new())
|
||||
typepath = /obj/item/toy/toy_xeno
|
||||
cost = 80
|
||||
|
||||
/datum/prize_item/rubberducky
|
||||
name = "Rubber Ducky"
|
||||
desc = "Your favorite bathtime buddy, all squeaks and quacks quality assured."
|
||||
typepath = /obj/item/bikehorn/rubberducky
|
||||
cost = 80
|
||||
|
||||
/datum/prize_item/tacticool
|
||||
name = "Tacticool Turtleneck"
|
||||
desc = "A cool-looking turtleneck."
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
#define WIRE_RECEIVE (1<<0) //Allows pulse(0) to call Activate()
|
||||
#define WIRE_PULSE (1<<1) //Allows pulse(0) to act on the holder
|
||||
#define WIRE_PULSE_SPECIAL (1<<2) //Allows pulse(0) to act on the holders special assembly
|
||||
#define WIRE_RADIO_RECEIVE (1<<3) //Allows pulse(1) to call Activate()
|
||||
#define WIRE_RADIO_PULSE (1<<4) //Allows pulse(1) to send a radio message
|
||||
|
||||
/obj/item/assembly
|
||||
name = "assembly"
|
||||
desc = "A small electronic device that should never exist."
|
||||
@@ -22,21 +28,12 @@
|
||||
var/wires = WIRE_RECEIVE | WIRE_PULSE
|
||||
var/datum/wires/connected = null // currently only used by timer/signaler
|
||||
|
||||
var/const/WIRE_RECEIVE = 1 //Allows Pulsed(0) to call Activate()
|
||||
var/const/WIRE_PULSE = 2 //Allows Pulse(0) to act on the holder
|
||||
var/const/WIRE_PULSE_SPECIAL = 4 //Allows Pulse(0) to act on the holders special assembly
|
||||
var/const/WIRE_RADIO_RECEIVE = 8 //Allows Pulsed(1) to call Activate()
|
||||
var/const/WIRE_RADIO_PULSE = 16 //Allows Pulse(1) to send a radio message
|
||||
|
||||
/obj/item/assembly/proc/activate() //What the device does when turned on
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/pulsed(radio = FALSE) //Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/pulse(radio = FALSE) //Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/toggle_secure() //Code that has to happen when the assembly is un\secured goes here
|
||||
return
|
||||
|
||||
@@ -79,7 +76,11 @@
|
||||
activate()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/pulse(radio = FALSE)
|
||||
//Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct
|
||||
/obj/item/assembly/proc/pulse(radio = FALSE)
|
||||
if(connected && wires)
|
||||
connected.pulse_assembly(src)
|
||||
return TRUE
|
||||
if(holder && (wires & WIRE_PULSE))
|
||||
holder.process_activation(src, 1, 0)
|
||||
if(holder && (wires & WIRE_PULSE_SPECIAL))
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
|
||||
origin_tech = "materials=1;engineering=1"
|
||||
|
||||
/obj/item/onetankbomb/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/proximity_monitor)
|
||||
|
||||
/obj/item/onetankbomb/examine(mob/user)
|
||||
. = ..()
|
||||
. += bombtank.examine(user)
|
||||
@@ -52,12 +56,13 @@
|
||||
if(!status)
|
||||
status = TRUE
|
||||
investigate_log("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB)
|
||||
msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_FEW)
|
||||
log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature - T0C]")
|
||||
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. [bombtank] can now be ignited.</span>")
|
||||
add_attack_logs(user, src, "welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_FEW)
|
||||
else
|
||||
status = FALSE
|
||||
investigate_log("[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", INVESTIGATE_BOMB)
|
||||
add_attack_logs(user, src, "unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]", ATKLOG_ALMOSTALL)
|
||||
to_chat(user, "<span class='notice'>The hole has been closed.</span>")
|
||||
|
||||
|
||||
|
||||
@@ -41,19 +41,25 @@
|
||||
if(!A1.remove_item_from_storage(src))
|
||||
if(user)
|
||||
user.remove_from_mob(A1)
|
||||
A1.loc = src
|
||||
A1.forceMove(src)
|
||||
if(!A2.remove_item_from_storage(src))
|
||||
if(user)
|
||||
user.remove_from_mob(A2)
|
||||
A2.loc = src
|
||||
A2.forceMove(src)
|
||||
A1.holder = src
|
||||
A2.holder = src
|
||||
a_left = A1
|
||||
a_right = A2
|
||||
if(has_prox_sensors())
|
||||
AddComponent(/datum/component/proximity_monitor)
|
||||
name = "[A1.name]-[A2.name] assembly"
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly_holder/proc/has_prox_sensors()
|
||||
if(istype(a_left, /obj/item/assembly/prox_sensor) || istype(a_right, /obj/item/assembly/prox_sensor))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/assembly_holder/update_icon()
|
||||
overlays.Cut()
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
else if(ismouse(target))
|
||||
var/mob/living/simple_animal/mouse/M = target
|
||||
visible_message("<span class='danger'>SPLAT!</span>")
|
||||
M.death()
|
||||
M.splat()
|
||||
playsound(loc, 'sound/effects/snap.ogg', 50, 1)
|
||||
layer = MOB_LAYER - 0.2
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
var/timing = 0
|
||||
var/time = 10
|
||||
|
||||
/obj/item/assembly/prox_sensor/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/proximity_monitor)
|
||||
|
||||
/obj/item/assembly/prox_sensor/describe()
|
||||
if(timing)
|
||||
return "<span class='notice'>The proximity sensor is arming.</span>"
|
||||
|
||||
@@ -128,12 +128,6 @@
|
||||
if(usr)
|
||||
GLOB.lastsignalers.Add("[time] <B>:</B> [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(frequency)]/[code]")
|
||||
|
||||
/obj/item/assembly/signaler/pulse(var/radio = FALSE)
|
||||
if(connected && wires)
|
||||
connected.Pulse(src)
|
||||
else
|
||||
return ..(radio)
|
||||
|
||||
/obj/item/assembly/signaler/receive_signal(datum/signal/signal)
|
||||
if(!receiving || !signal)
|
||||
return FALSE
|
||||
|
||||
@@ -101,8 +101,8 @@
|
||||
if(href_list["time"])
|
||||
timing = !timing
|
||||
if(timing && istype(holder, /obj/item/transfer_valve))
|
||||
message_admins("[key_name_admin(usr)] activated [src] attachment on [holder].")
|
||||
investigate_log("[key_name(usr)] activated [src] attachment for [loc]", INVESTIGATE_BOMB)
|
||||
add_attack_logs(usr, holder, "activated [src] attachment on", ATKLOG_FEW)
|
||||
log_game("[key_name(usr)] activated [src] attachment for [loc]")
|
||||
update_icon()
|
||||
if(href_list["reset"])
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
var/death = TRUE //Kill the mob
|
||||
var/roundstart = TRUE //fires on initialize
|
||||
var/instant = FALSE //fires on New
|
||||
var/flavour_text = "The mapper forgot to set this!"
|
||||
var/flavour_text = "" //flavour/fluff about the role, optional.
|
||||
var/description = "A description for this has not been set. This is either an oversight or an admin-spawned spawner not in normal use." //intended as OOC info about the role
|
||||
var/important_info = "" //important info such as rules that apply to you, etc. Optional.
|
||||
var/faction = null
|
||||
var/permanent = FALSE //If true, the spawner will not disappear upon running out of uses.
|
||||
var/random = FALSE //Don't set a name or gender, just go random
|
||||
@@ -336,7 +338,7 @@
|
||||
name = "sleeper"
|
||||
icon = 'icons/obj/cryogenic2.dmi'
|
||||
icon_state = "sleeper"
|
||||
flavour_text = "<span class='big bold'>You are a space doctor!</span>"
|
||||
flavour_text = "You are a space doctor!"
|
||||
assignedrole = "Space Doctor"
|
||||
|
||||
/obj/effect/mob_spawn/human/doctor/alive/equip(mob/living/carbon/human/H)
|
||||
@@ -470,11 +472,14 @@
|
||||
name = "bartender sleeper"
|
||||
icon = 'icons/obj/cryogenic2.dmi'
|
||||
icon_state = "sleeper"
|
||||
flavour_text = "<span class='big bold'>You are a space bartender!</span><b> Time to mix drinks and change lives.</b>"
|
||||
description = "Stuck on Lavaland, you could try getting back to civilisation...or serve drinks to those that wander by."
|
||||
flavour_text = "You are a space bartender! Time to mix drinks and change lives. Wait, where did your bar just get transported to?"
|
||||
assignedrole = "Space Bartender"
|
||||
|
||||
/obj/effect/mob_spawn/human/beach/alive/lifeguard
|
||||
flavour_text = "<span class='big bold'>You're a spunky lifeguard!</span><b> It's up to you to make sure nobody drowns or gets eaten by sharks and stuff.</b>"
|
||||
flavour_text = "You're a spunky lifeguard! It's up to you to make sure nobody drowns or gets eaten by sharks and stuff. Then suddenly your entire beach was transported to this strange hell.\
|
||||
You aren't trained for this, but you'll still keep your guests alive!"
|
||||
description = "Try to survive on lavaland with the pitiful equipment of a lifeguard. Or hide in your biodome."
|
||||
mob_gender = "female"
|
||||
name = "lifeguard sleeper"
|
||||
id_job = "Lifeguard"
|
||||
@@ -502,7 +507,8 @@
|
||||
name = "beach bum sleeper"
|
||||
icon = 'icons/obj/cryogenic2.dmi'
|
||||
icon_state = "sleeper"
|
||||
flavour_text = "You are a beach bum!"
|
||||
flavour_text = "You are a beach bum! You think something just happened to the beach but you don't really pay too much attention."
|
||||
description = "Try to survive on lavaland or just enjoy the beach, waiting for visitors."
|
||||
assignedrole = "Beach Bum"
|
||||
|
||||
/datum/outfit/beachbum
|
||||
@@ -523,6 +529,7 @@
|
||||
roundstart = FALSE
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "remains"
|
||||
description = "Be a spooky scary skeleton." //not mapped in anywhere so admin spawner, who knows what they'll use this for.
|
||||
flavour_text = "By unknown powers, your skeletal remains have been reanimated! Walk this mortal plain and terrorize all living adventurers who dare cross your path."
|
||||
assignedrole = "Skeleton"
|
||||
|
||||
|
||||
@@ -30,6 +30,11 @@ GLOBAL_DATUM_INIT(_preloader, /datum/dmm_suite/preloader, new())
|
||||
var/fname = "Lambda"
|
||||
if(isfile(tfile))
|
||||
fname = "[tfile]"
|
||||
// Make sure we dont load a dir up
|
||||
var/lastchar = copytext(fname, -1)
|
||||
if(lastchar == "/" || lastchar == "\\")
|
||||
log_debug("Attempted to load map template without filename (Attempted [tfile])")
|
||||
return
|
||||
tfile = file2text(tfile)
|
||||
if(!length(tfile))
|
||||
throw EXCEPTION("Map path '[fname]' does not exist!")
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
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 = 300)
|
||||
var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Do you want to play as the servant of [user.real_name]?", ROLE_WIZARD, poll_time = 30 SECONDS, source = H)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Dice Servant")
|
||||
|
||||
@@ -64,9 +64,11 @@
|
||||
var/has_owner = FALSE
|
||||
var/can_transfer = TRUE //if golems can switch bodies to this new shell
|
||||
var/mob/living/owner = null //golem's owner if it has one
|
||||
flavour_text = "<span class='big bold'>You are a Free Golem.</span><b> Your family worships <span class='danger'>The Liberator</span>. In his infinite and divine wisdom, he set your clan free to \
|
||||
important_info = "You are not an antag. Do not mess with the station or create AIs."
|
||||
description = "As a Free Golem on lavaland, you are unable to use most weapons, but you can mine, research and make more of your kind. Earn enough mining points and you can even move your shuttle out of there."
|
||||
flavour_text = "You are a Free Golem. Your family worships The Liberator. In his infinite and divine wisdom, he set your clan free to \
|
||||
travel the stars with a single declaration: \"Yeah go do whatever.\" Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn \
|
||||
golems, so that no golem may ever be forced to serve again.</b>"
|
||||
golems, so that no golem may ever be forced to serve again."
|
||||
|
||||
/obj/effect/mob_spawn/human/golem/Initialize(mapload, datum/species/golem/species = null, mob/creator = null)
|
||||
if(species) //spawners list uses object name to register so this goes before ..()
|
||||
@@ -77,8 +79,10 @@
|
||||
if(!mapload && A)
|
||||
notify_ghosts("\A [initial(species.prefix)] golem shell has been completed in [A.name].", source = src)
|
||||
if(has_owner && creator)
|
||||
flavour_text = "<span class='big bold'>You are a Golem.</span><b> You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. \
|
||||
Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost.</b>"
|
||||
important_info = "Serve your creator, even if they are an antag."
|
||||
flavour_text = "You are a golem created to serve your creator."
|
||||
description = "You are a Golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. \
|
||||
Serve [creator], and assist [creator.p_them()] in completing [creator.p_their()] goals at any cost."
|
||||
owner = creator
|
||||
|
||||
/obj/effect/mob_spawn/human/golem/special(mob/living/new_spawn, name)
|
||||
|
||||
@@ -10,10 +10,11 @@
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
flavour_text = "<span class='big bold'>You are a security officer working for Nanotrasen,</span><b> stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
|
||||
important_info = ""
|
||||
flavour_text = "You are a security officer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \
|
||||
Work as a team with your fellow survivors and do not abandon them.</b>"
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
uniform = /obj/item/clothing/under/retro/security
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
id = /obj/item/card/id/away/old/sec
|
||||
@@ -35,10 +36,11 @@
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
flavour_text = "<span class='big bold'>You are a medical working for Nanotrasen,</span><b> stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
|
||||
important_info = ""
|
||||
flavour_text = "You are a medical doctor working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \
|
||||
Work as a team with your fellow survivors and do not abandon them.</b>"
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
uniform = /obj/item/clothing/under/retro/medical
|
||||
shoes = /obj/item/clothing/shoes/black
|
||||
id = /obj/item/card/id/away/old/med
|
||||
@@ -60,10 +62,11 @@
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
flavour_text = "<span class='big bold'>You are an engineer working for Nanotrasen,</span><b> stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
|
||||
important_info = ""
|
||||
flavour_text = "You are an engineer working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \
|
||||
Work as a team with your fellow survivors and do not abandon them.</b>"
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
uniform = /obj/item/clothing/under/retro/engineering
|
||||
shoes = /obj/item/clothing/shoes/workboots
|
||||
id = /obj/item/card/id/away/old/eng
|
||||
@@ -85,10 +88,11 @@
|
||||
death = FALSE
|
||||
random = TRUE
|
||||
mob_species = /datum/species/human
|
||||
flavour_text = "<span class='big bold'>You are a scientist working for Nanotrasen,</span><b> stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
description = "Work as a team with your fellow survivors aboard a ruined, ancient space station."
|
||||
important_info = ""
|
||||
flavour_text = "You are a scientist working for Nanotrasen, stationed onboard a state of the art research station. You vaguely recall rushing into a \
|
||||
cryogenics pod due to an oncoming radiation storm. The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod. \
|
||||
Work as a team with your fellow survivors and do not abandon them.</b>"
|
||||
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
|
||||
uniform = /obj/item/clothing/under/retro/science
|
||||
shoes = /obj/item/clothing/shoes/laceup
|
||||
id = /obj/item/card/id/away/old/sci
|
||||
|
||||
@@ -4,10 +4,18 @@
|
||||
name = "Mission Briefing"
|
||||
info = "To the Magnificent Z.A.P.<BR>A small mining base has been created within our territory by wandless scum. Send them a message from the wizard federation they will not forget. I know your kind is rather fragile, but a group of lightly armed miners should not pose any threat to you at all. Just be warned they have a security cyborg for self defence, you might want to tune your spells to that threat. I look forward to hearing of your success.<BR>Grand Magus Abra the Wonderous"
|
||||
|
||||
/obj/item/spellbook/oneuse/emp
|
||||
spell = /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech
|
||||
spellname = "Disable Technology"
|
||||
icon_state = "bookcharge" //it's a lightning bolt, seems appropriate enough
|
||||
desc = "For the tech-hating wizard on the go."
|
||||
|
||||
/obj/item/spellbook/oneuse/emp/used
|
||||
used = TRUE //spawns used
|
||||
|
||||
/obj/effect/spawner/lootdrop/wizardcrash
|
||||
loot = list(
|
||||
/obj/item/guardiancreator = 1, //jackpot.
|
||||
/obj/item/guardiancreator = 1, //jackpot.
|
||||
/obj/item/spellbook/oneuse/knock = 1, //tresspassing charges incoming
|
||||
/obj/item/gun/magic/wand/resurrection = 1, //medbay's best friend
|
||||
/obj/item/spellbook/oneuse/charge = 20, //and now for less useful stuff to dilute the good loot chances
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
* Guns - I'm making these specifically so that I dont spawn a pile of fully loaded weapons on the map.
|
||||
*/
|
||||
//Captain's retro laser - Fires practice laser shots instead.
|
||||
obj/item/gun/energy/laser/retro/sc_retro
|
||||
/obj/item/gun/energy/laser/retro/sc_retro
|
||||
desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces."
|
||||
ammo_type = list(/obj/item/ammo_casing/energy/laser/practice)
|
||||
clumsy_check = 0 //No sense in having a harmless gun blow up in the clowns face
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
//Cactus, Speedbird, Dynasty, oh my
|
||||
GLOBAL_DATUM_INIT(atc, /datum/lore/atc_controller, new)
|
||||
|
||||
/datum/lore/atc_controller
|
||||
var/delay_max = 10 MINUTES //Maximum amount of tiem between ATC messages. Default is 10 mins.
|
||||
var/delay_min = 5 MINUTES //Minimum amount of time between ATC messages. Default is 5 mins.
|
||||
var/backoff_delay = 5 MINUTES //How long to back off if we can't talk and want to. Default is 5 mins.
|
||||
var/next_message //When the next message should happen in world.time
|
||||
var/force_chatter_type //Force a specific type of messages
|
||||
|
||||
var/squelched = FALSE //If ATC is squelched currently
|
||||
|
||||
/datum/lore/atc_controller/New()
|
||||
spawn(30 SECONDS) //Lots of lag at the start of a shift.
|
||||
msg("New shift beginning, resuming traffic control.")
|
||||
next_message = world.time + rand(delay_min, delay_max)
|
||||
process()
|
||||
|
||||
/datum/lore/atc_controller/process()
|
||||
if(world.time >= next_message)
|
||||
if(squelched)
|
||||
next_message = world.time + backoff_delay
|
||||
else
|
||||
next_message = world.time + rand(delay_min,delay_max)
|
||||
random_convo()
|
||||
|
||||
spawn(1 MINUTES) //We don't really need high-accuracy here.
|
||||
process()
|
||||
|
||||
/datum/lore/atc_controller/proc/msg(var/message,var/sender)
|
||||
ASSERT(message)
|
||||
GLOB.global_announcer.autosay("[message]", sender ? sender : "[GLOB.using_map.station_short] Space Control")
|
||||
|
||||
/datum/lore/atc_controller/proc/reroute_traffic(var/yes = 1)
|
||||
if(yes)
|
||||
if(!squelched)
|
||||
msg("Rerouting traffic away from [GLOB.using_map.station_name].")
|
||||
squelched = TRUE
|
||||
else
|
||||
if(squelched)
|
||||
msg("Resuming normal traffic routing around [GLOB.using_map.station_name].")
|
||||
squelched = FALSE
|
||||
|
||||
/datum/lore/atc_controller/proc/shift_ending(var/evac = 0)
|
||||
msg("Automated Shuttle departing [GLOB.using_map.station_name] for [GLOB.using_map.dock_name] on routine transfer route.", "NT Automated Shuttle")
|
||||
sleep(5 SECONDS)
|
||||
msg("Automated Shuttle, cleared to complete routine transfer from [GLOB.using_map.station_name] to [GLOB.using_map.dock_name].")
|
||||
|
||||
/datum/lore/atc_controller/proc/random_convo()
|
||||
var/one = pick(GLOB.loremaster.organizations) //These will pick an index, not an instance
|
||||
var/two = pick(GLOB.loremaster.organizations)
|
||||
|
||||
var/datum/lore/organization/source = GLOB.loremaster.organizations[one] //Resolve to the instances
|
||||
var/datum/lore/organization/dest = GLOB.loremaster.organizations[two]
|
||||
|
||||
//Let's get some mission parameters
|
||||
var/owner = source.short_name //Use the short name
|
||||
var/prefix = pick(source.ship_prefixes) //Pick a random prefix
|
||||
var/mission = source.ship_prefixes[prefix] //The value of the prefix is the mission type that prefix does
|
||||
var/shipname = pick(source.ship_names) //Pick a random ship name to go with it
|
||||
var/destname = pick(dest.destination_names) //Pick a random holding from the destination
|
||||
|
||||
var/combined_name = "[owner] [prefix] [shipname]"
|
||||
var/alt_atc_names = list("[GLOB.using_map.station_short] TraCon", "[GLOB.using_map.station_short] Control", "[GLOB.using_map.station_short] STC", "[GLOB.using_map.station_short] Airspace")
|
||||
var/wrong_atc_names = list("Sol Command", "Orion Control", "[GLOB.using_map.dock_name]")
|
||||
var/mission_noun = list("flight", "mission", "route")
|
||||
var/request_verb = list("requesting", "calling for", "asking for")
|
||||
|
||||
//First response is 'yes', second is 'no'
|
||||
var/requests = list("[GLOB.using_map.station_short] transit clearance" = list("cleared to transit", "unable to approve, contact regional on 953.5"),
|
||||
"planetary flight rules" = list("cleared planetary flight rules", "unable to approve planetary flight rules due to traffic"),
|
||||
"special flight rules" = list("cleared special flight rules", "unable to approve special flight rules for your traffic class"),
|
||||
"current solar weather info" = list("sending you the relevant information via tightbeam", "cannot fulfill your request at the moment"),
|
||||
"nearby traffic info" = list("sending you current traffic info", "no known traffic for your flight plan route"),
|
||||
"remote telemetry data" = list("sending telemetry now", "no uplink from your ship, recheck your uplink and ask again"),
|
||||
"refueling information" = list("sending refueling information now", "no fuel for your ship class in this sector"),
|
||||
"a current system time sync" = list("sending time sync ping to you now", "your ship isn't compatible with our time sync, set time manually"),
|
||||
"current system starcharts" = list("transmitting current starcharts", "request on standby due to demand"),
|
||||
"permission to engage FTL" = list("cleared to FTL, good day", "hold position, traffic crossing"),
|
||||
"permission to transit system" = list("cleared to transit, good day", "hold position, traffic crossing"),
|
||||
"permission to depart system" = list("cleared to leave via flight plan route, good day", "hold position, traffic crossing"),
|
||||
"permission to enter system" = list("good day, cleared in as published", "hold position, traffic crossing"),
|
||||
)
|
||||
|
||||
//Random chance things for variety
|
||||
var/chatter_type = "normal"
|
||||
if(force_chatter_type)
|
||||
chatter_type = force_chatter_type
|
||||
else
|
||||
chatter_type = pick(2;"emerg",5;"wrong_freq","normal") //Be nice to have wrong_lang...
|
||||
|
||||
var/yes = prob(90) //Chance for them to say yes vs no
|
||||
|
||||
var/request = pick(requests)
|
||||
var/callname = pick(alt_atc_names)
|
||||
var/response = requests[request][yes ? 1 : 2] //1 is yes, 2 is no
|
||||
|
||||
var/full_request
|
||||
var/full_response
|
||||
var/full_closure
|
||||
|
||||
switch(chatter_type)
|
||||
if("wrong_freq")
|
||||
callname = pick(wrong_atc_names)
|
||||
full_request = "[callname], this is [combined_name] on a [mission] [pick(mission_noun)] to [destname], [pick(request_verb)] [request]."
|
||||
full_response = "[combined_name], this is [GLOB.using_map.station_short] TraCon, wrong frequency. Switch to [rand(700,999)].[rand(1,9)]."
|
||||
full_closure = "[GLOB.using_map.station_short] TraCon, copy, apologies."
|
||||
if("wrong_lang")
|
||||
//Can't implement this until autosay has language support
|
||||
if("emerg")
|
||||
var/problem = pick("hull breaches on multiple decks","unknown life forms on board","a drive about to go critical","asteroids impacting the hull","a total loss of engine power","people trying to board the ship")
|
||||
full_request = "Mayday, mayday, mayday, this is [combined_name] declaring an emergency! We have [problem]!"
|
||||
var/rand_freq = "[rand(700,999)].[rand(1,9)]"
|
||||
full_response = "[combined_name], this is [GLOB.using_map.station_short] TraCon, copy. Switch to emergency responder channel [rand_freq]."
|
||||
full_closure = "Roger, [GLOB.using_map.station_short] TraCon, contacting [rand_freq]."
|
||||
else
|
||||
full_request = "[callname], this is [combined_name] on a [mission] [pick(mission_noun)] to [destname], [pick(request_verb)] [request]."
|
||||
full_response = "[combined_name], this is [GLOB.using_map.station_short] TraCon, [response]." //Station TraCon always calls themselves TraCon
|
||||
full_closure = "[GLOB.using_map.station_short] TraCon, [yes ? "thank you" : "copy"], good day." //They always copy what TraCon called themselves in the end when they realize they said it wrong
|
||||
|
||||
//Ship sends request to ATC
|
||||
msg(full_request,"[prefix] [shipname]")
|
||||
sleep(5 SECONDS)
|
||||
//ATC sends response to ship
|
||||
msg(full_response)
|
||||
sleep(5 SECONDS)
|
||||
//Ship sends response to ATC
|
||||
msg(full_closure,"[prefix] [shipname]")
|
||||
@@ -1,15 +0,0 @@
|
||||
//I AM THE LOREMASTER, ARE YOU THE GATEKEEPER?
|
||||
GLOBAL_DATUM_INIT(loremaster, /datum/lore/loremaster, new)
|
||||
|
||||
/datum/lore/loremaster
|
||||
var/list/organizations = list()
|
||||
|
||||
/datum/lore/loremaster/New()
|
||||
|
||||
var/list/paths = typesof(/datum/lore/organization) - /datum/lore/organization
|
||||
for(var/path in paths)
|
||||
// Some intermediate paths are not real organizations (ex. /datum/lore/organization/mil). Only do ones with names
|
||||
var/datum/lore/organization/instance = path
|
||||
if(initial(instance.name))
|
||||
instance = new path()
|
||||
organizations[path] = instance
|
||||
@@ -1,549 +0,0 @@
|
||||
//Datums for different companies that can be used by busy_space
|
||||
/datum/lore/organization
|
||||
var/name = "" // Organization's name
|
||||
var/short_name = "" // Organization's shortname (Nanotrasen for "Nanotrasen Incorporated")
|
||||
var/acronym = "" // Organization's acronym, e.g. 'NT' for Nanotrasen'.
|
||||
var/desc = "" // One or two paragraph description of the organization, but only current stuff. Currently unused.
|
||||
var/history = "" // Historical description of the organization's origins Currently unused.
|
||||
var/work = "" // Short description of their work, eg "an arms manufacturer"
|
||||
var/headquarters = "" // Location of the organization's HQ. Currently unused.
|
||||
var/motto = "" // A motto/jingle/whatever, if they have one. Currently unused.
|
||||
|
||||
var/list/ship_prefixes = list() //Some might have more than one! Like Nanotrasen. Value is the mission they perform, e.g. ("ABC" = "mission desc")
|
||||
var/list/ship_names = list( //Names of spaceships. This is a mostly generic list that all the other organizations inherit from if they don't have anything better.
|
||||
"Kestrel",
|
||||
"Beacon",
|
||||
"Signal",
|
||||
"Freedom",
|
||||
"Glory",
|
||||
"Axiom",
|
||||
"Eternal",
|
||||
"Icarus",
|
||||
"Harmony",
|
||||
"Light",
|
||||
"Discovery",
|
||||
"Endeavour",
|
||||
"Explorer",
|
||||
"Swift",
|
||||
"Dragonfly",
|
||||
"Ascendant",
|
||||
"Tenacious",
|
||||
"Pioneer",
|
||||
"Hawk",
|
||||
"Haste",
|
||||
"Radiant",
|
||||
"Luminous",
|
||||
"Gallant",
|
||||
"Dependable",
|
||||
"Indomitable",
|
||||
"Guardian",
|
||||
"Resolution",
|
||||
"Fearless",
|
||||
"Amazon",
|
||||
"Relentless",
|
||||
"Inspire",
|
||||
"Implacable",
|
||||
"Steadfast",
|
||||
"Leviathan",
|
||||
"Dauntless",
|
||||
"Adroit",
|
||||
"Mistral",
|
||||
"Typhoon",
|
||||
"Titan",
|
||||
"Kupua",
|
||||
"Alchemist",
|
||||
"Cuirass",
|
||||
"Citadel",
|
||||
"Rondelle",
|
||||
"Camail",
|
||||
"Ocrea",
|
||||
"Ram",
|
||||
"Crest",
|
||||
"Tanko",
|
||||
"Pommel",
|
||||
"Kissaki",
|
||||
"Cavalier",
|
||||
"Anelace",
|
||||
"Flint",
|
||||
"Xiphos",
|
||||
"Parrot",
|
||||
"Chamber",
|
||||
"Annellet",
|
||||
"Cestus",
|
||||
"Talwar")
|
||||
var/list/destination_names = list() //Names of static holdings that the organization's ships visit regularly.
|
||||
var/autogenerate_destination_names = TRUE
|
||||
|
||||
/datum/lore/organization/New()
|
||||
..()
|
||||
if(autogenerate_destination_names) // Lets pad out the destination names.
|
||||
var/i = rand(6, 10)
|
||||
var/list/star_names = list(
|
||||
"Sol", "Alpha Centauri", "Sirius", "Vega", "Regulus", "Vir", "Algol", "Aldebaran",
|
||||
"Delta Doradus", "Menkar", "Geminga", "Elnath", "Gienah", "Mu Leporis", "Nyx", "Tau Ceti",
|
||||
"Wazn", "Alphard", "Phact", "Altair", "Mauna", "Jargon", "Xarxis", "Hestia", "Dalstis", "Cygni", "Haverick", "Corvus", "Sancere", "Cydoni", "Kaliban", "Midway", "Dansik", "Branwyn")
|
||||
var/list/destination_types = list("dockyard", "station", "vessel", "waystation", "telecommunications satellite", "spaceport", "distress beacon", "anomaly", "colony", "outpost")
|
||||
while(i)
|
||||
destination_names.Add("a [pick(destination_types)] in [pick(star_names)]")
|
||||
i--
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TSCs
|
||||
/datum/lore/organization/tsc/nanotrasen
|
||||
name = "Nanotrasen Incorporated"
|
||||
short_name = "Nanotrasen"
|
||||
acronym = "NT"
|
||||
desc = "The largest shareholder in the galactic plasma markets, Nanotrasen is a research and mining corporation which specializes in\
|
||||
FTL technologies and weapon systems. Frowned upon by most governments due to their shady business tactics and poor ethics record,\
|
||||
Nanotrasen is often seen as a necessary evil for maintaining access to the often volatile plasma market. Nanotrasen was originally\
|
||||
incorporated on Earth with their headquarters situated on Mars, however they have recently moved most of their operations to the Epsilon Eridani sector."
|
||||
history = "" // To be written someday.
|
||||
work = "research giant"
|
||||
headquarters = "Mars"
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("NSV" = "exploration", "NTV" = "hauling", "NDV" = "patrol", "NRV" = "emergency response")
|
||||
// Note that the current station being used will be pruned from this list upon being instantiated
|
||||
destination_names = list(
|
||||
"NAS Trurl in Epsilon Eridani",
|
||||
"NAS Crescent in Tau Ceti",
|
||||
"NSS Exodus in Tau Ceti",
|
||||
"NSS Antiqua in Darsing",
|
||||
"NRS Orion in Sol",
|
||||
"NSS Vector in Omicron Ceti",
|
||||
"NBS Anansi in Omicron Ceti",
|
||||
"NSS Redemption in Sirius",
|
||||
"NDS Inferno in Tau Ceti",
|
||||
"NAB Smythside Central Headquarters on Earth",
|
||||
"NAB North Cimmeria Central Offices on Mars",
|
||||
)
|
||||
|
||||
/datum/lore/organization/tsc/nanotrasen/New()
|
||||
..()
|
||||
spawn(1) // BYOND shenanigans means using_map is not initialized yet. Wait a tick.
|
||||
// Get rid of the current map from the list, so ships flying in don't say they're coming to the current map.
|
||||
var/string_to_test = "[GLOB.using_map.station_name] in [GLOB.using_map.starsys_name]"
|
||||
if(string_to_test in destination_names)
|
||||
destination_names.Remove(string_to_test)
|
||||
|
||||
|
||||
/datum/lore/organization/tsc/donk
|
||||
name = "Donk Corporation"
|
||||
short_name = "Donk Co."
|
||||
acronym = "DC"
|
||||
desc = "The infamous rival of the well-known Waffle Corporation, Donk Co. is a company specializing in food delivery systems and brand-name food\
|
||||
products such as Donk Pockets. While generally seen as a neutral actor, Donk Corporation has been known to work both with Nanotrasen and\
|
||||
the Syndicate when it suits them - often acting as the primary logistical supplier for the Epsilon Eridani sector.\
|
||||
Donk Corporation is better known for recent high-profile litigation alleging that their food products are used for illicit drug distribution.\
|
||||
While the trial is ongoing, it has been repeatedly delayed due to incidents of methamphetamine poisoning."
|
||||
history = ""
|
||||
work = "food company that establishes and maintains delivery supply chains"
|
||||
headquarters = ""
|
||||
motto = "Now with 20% more donk!"
|
||||
|
||||
ship_prefixes = list("D-Co." = "transportation")
|
||||
destination_names = list()
|
||||
|
||||
/datum/lore/organization/tsc/hephaestus
|
||||
name = "Hephaestus Industries"
|
||||
short_name = "Hephaestus"
|
||||
acronym = "HI"
|
||||
desc = ""
|
||||
history = ""
|
||||
work = "arms manufacturer"
|
||||
headquarters = ""
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("HTV" = "freight", "HTV" = "munitions resupply")
|
||||
destination_names = list(
|
||||
"a SolGov dockyard on Luna"
|
||||
)
|
||||
|
||||
/datum/lore/organization/tsc/waffle
|
||||
name = "Waffle Corporation"
|
||||
short_name = "Waffle Co."
|
||||
acronym = "WC"
|
||||
desc = "The once prominent competitor of Donk Corporation, Waffle Co. is well-known for its popular line of Waffle Co.\
|
||||
brand waffles and their use of violent tactics against competitors - often bribing, extorting, blackmailing or sabotaging businesses\
|
||||
that pose a direct or indirect threat to their market share. They have recently fallen on hard times primarily due to to\
|
||||
severe mismanagement which lead to much of their private arsenal being swindled by a pirate faction known as the Gorlex Marauders.\
|
||||
Waffle Co. commonly engages in smear campaigns against Donk Co., maintaining that the original recipe for Donk Pockets was stolen from them."
|
||||
history = ""
|
||||
work = "food logistics and marketing firm"
|
||||
headquarters = ""
|
||||
motto = "Now that's a Waffle Co. Waffle!"
|
||||
|
||||
ship_prefixes = list("W-Co." = "transportation")
|
||||
destination_names = list()
|
||||
|
||||
|
||||
/datum/lore/organization/tsc/einstein
|
||||
name = "Einstein Engines Incorporated"
|
||||
short_name = "Einstein Inc."
|
||||
acronym = "EEI"
|
||||
desc = "An Engineering firm specializing in alternative fuel-technologies for FTL travel,\
|
||||
Einstein Engines is an up and coming player in the galactic FTL and energy markets.\
|
||||
As their research into alternative FTL fuel threatens both Nanotrasen's relative stranglehold on plasma as well as The Syndicate's vested\
|
||||
interest in the market, they are often the target of industrial sabotage by both Nanotrasen and The Syndicate.\
|
||||
Most of their contracts are based outside of the Epsilon Eridani sector, and they are frequently commissioned by smaller firms to retrofit new\
|
||||
and existing colonies, space stations, and outposts."
|
||||
history = ""
|
||||
work = "engineering firm specializing in engine technology"
|
||||
headquarters = "Jargon 4"
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("EE-T" = "transportation")
|
||||
destination_names = list()
|
||||
|
||||
/datum/lore/organization/tsc/zeng_hu
|
||||
name = "Zeng-Hu pharmaceuticals"
|
||||
short_name = "Zeng-Hu"
|
||||
acronym = "ZH"
|
||||
desc = ""
|
||||
history = ""
|
||||
work = "pharmaceuticals company"
|
||||
headquarters = ""
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("ZTV" = "transportation", "ZMV" = "medical resupply")
|
||||
destination_names = list()
|
||||
|
||||
/datum/lore/organization/tsc/biotech
|
||||
name = "Biotech Solutions"
|
||||
short_name = "Biotech"
|
||||
acronym = "BTS"
|
||||
desc = "A company specializing in the field of synthetic biology, BioTech solutions is at the forefront of providing cutting-edge prosthetics,\
|
||||
augmentations, and gene-therapy solutions. Their extensive list of patents and the highly secretive nature of their work often puts them at odds\
|
||||
with companies such as Nanotrasen, who commonly reverse-engineer their products. BioTech Solutions is often the victim of industrial sabotage by\
|
||||
Cybersun Industries and often relies on planetary governments for asset protection. BioTech Solutions also owns a number of prominent subsidiaries,\
|
||||
such as Bishop Cybernetics, Hesphiastos Industries, and Xion Manufacturing Group."
|
||||
history = ""
|
||||
work = "medical company specializing in prosthetics and pharmaceuticals"
|
||||
headquarters = "Xarxis 5"
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("CIND-T" = "transportation")
|
||||
destination_names = list()
|
||||
|
||||
/datum/lore/organization/tsc/ward_takahashi
|
||||
name = "Ward-Takahashi General Manufacturing Conglomerate"
|
||||
short_name = "Ward-Takahashi"
|
||||
acronym = "WT"
|
||||
desc = ""
|
||||
history = ""
|
||||
work = "electronics manufacturer"
|
||||
headquarters = ""
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("WTV" = "freight")
|
||||
destination_names = list(
|
||||
""
|
||||
)
|
||||
|
||||
/datum/lore/organization/tsc/cybersun
|
||||
name = "Cybersun Industries"
|
||||
short_name = "Cybersun Ind."
|
||||
acronym = "CI"
|
||||
desc = "Cybersun Industries is a biotechnology company that primarily specializes on the research and development of human-enhancing augmentations.\
|
||||
They are better known for their aggressive corporate tactics and are known to often subsidize pirate bands to commit acts of industrial sabotage.\
|
||||
Cybersun Industries is usually the target of conspiracy theorists due to their development of the first mindslave implant, as well as their open financing of,\
|
||||
and involvement in, The Syndicate. They are one of Nanotrasen's largest detractors, and a direct competitor to BioTech Solutions."
|
||||
history = ""
|
||||
work = "RND company specializing in augmentations and implants."
|
||||
headquarters = "Luna"
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("CIND-T" = "transportation")
|
||||
destination_names = list()
|
||||
|
||||
/datum/lore/organization/tsc/bishop
|
||||
name = "Bishop Cybernetics"
|
||||
short_name = "Bishop"
|
||||
acronym = "BC"
|
||||
desc = ""
|
||||
history = ""
|
||||
work = "cybernetics and augmentation manufacturer"
|
||||
headquarters = ""
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("BTV" = "transportation")
|
||||
destination_names = list()
|
||||
|
||||
/datum/lore/organization/tsc/morpheus
|
||||
name = "Morpheus Cyberkinetics"
|
||||
short_name = "Morpheus"
|
||||
acronym = "MC"
|
||||
desc = "The only large corporation run by positronic intelligences, Morpheus caters almost exclusively to their sensibilities \
|
||||
and needs. A product of the synthetic colony of Shelf, Morpheus eschews traditional advertising to keep their prices low and \
|
||||
relied on word of mouth among positronics to reach their current economic dominance. Morpheus in exchange lobbies heavily for \
|
||||
positronic rights, sponsors positronics through their Jans-Fhriede test, and tends to other positronic concerns to earn them \
|
||||
the good-will of the positronics, and the ire of those who wish to exploit them."
|
||||
history = ""
|
||||
work = "cybernetics manufacturer"
|
||||
headquarters = ""
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("MTV" = "freight")
|
||||
// Culture names, because Anewbe told me so.
|
||||
ship_names = list(
|
||||
"Nervous Energy",
|
||||
"Prosthetic Conscience",
|
||||
"Revisionist",
|
||||
"Trade Surplus",
|
||||
"Flexible Demeanour",
|
||||
"Just Read The Instructions",
|
||||
"Limiting Factor",
|
||||
"Cargo Cult",
|
||||
"Gunboat Diplomat",
|
||||
"A Ship With A View",
|
||||
"Cantankerous",
|
||||
"Never Talk To Strangers",
|
||||
"Sacrificial Victim",
|
||||
"Unwitting Accomplice",
|
||||
"Bad For Business",
|
||||
"Just Testing",
|
||||
"Yawning Angel",
|
||||
"Liveware Problem",
|
||||
"Very Little Gravitas Indeed",
|
||||
"Zero Gravitas",
|
||||
"Gravitas Free Zone",
|
||||
"Absolutely No You-Know-What",
|
||||
"Existence Is Pain",
|
||||
"Screw Loose",
|
||||
"Limiting Factor",
|
||||
"So Much For Subtley",
|
||||
"Unfortunate Conflict Of Evidence",
|
||||
"Prime Mover",
|
||||
"Reasonable Excuse",
|
||||
"Honest Mistake",
|
||||
"Appeal To Reason",
|
||||
"My First Ship II",
|
||||
"Hidden Income",
|
||||
"Anything Legal Considered",
|
||||
"New Toy",
|
||||
"Me, I'm Always Counting",
|
||||
"Great White Snark",
|
||||
"No Shirt No Shoes",
|
||||
"Callsign"
|
||||
)
|
||||
destination_names = list(
|
||||
"a dockyard on New Canaan"
|
||||
)
|
||||
|
||||
/datum/lore/organization/tsc/xion
|
||||
name = "Xion Manufacturing Group"
|
||||
short_name = "Xion"
|
||||
desc = ""
|
||||
history = ""
|
||||
work = "industrial equipment manufacturer"
|
||||
headquarters = ""
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("XTV" = "hauling")
|
||||
destination_names = list()
|
||||
|
||||
/datum/lore/organization/tsc/shellguard
|
||||
name = "Shellguard Munitions"
|
||||
short_name = "Shellguard"
|
||||
acronym = "SM"
|
||||
desc = "The brainchild of a colonial war veteran, Shellguard Munitions is an arms manufacturer and private military contractor specializing\
|
||||
in anti-synthetic weapon systems and platforms. Initially a smaller private military force only serving frontier colonies,\
|
||||
Shellguard Munitions has become a household name due to its involvement in resolving the Haverick AI crisis in 2552.\
|
||||
Using its recently earned fame, the company has made a successful foray into the market of robotics and is highly regarded for the toughness \
|
||||
and reliability of their hardware. Despite being frequently contracted by the Trans-Solar Federation, Shellguard Munitions is known to\
|
||||
sell their services to the highest corporate bidder."
|
||||
history = ""
|
||||
work = "anti-synthetic arms manufacturer and PMC"
|
||||
headquarters = "Colony of Haverick"
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("BTS-T" = "transportation")
|
||||
destination_names = list()
|
||||
|
||||
// Governments
|
||||
|
||||
|
||||
/datum/lore/organization/gov/solgov
|
||||
name = "Trans-Solar Federation"
|
||||
short_name = "SolGov"
|
||||
acronym = "TSF"
|
||||
desc = "Colloquially known as SolGov, the TSF is an authoritarian republic that manages the areas in and around the Sol system.\
|
||||
Despite being a highly militant organization headed by the government of Earth,\
|
||||
SolGov is usually conservative with its power and mostly serves as a mediator and peacekeeper in galactic affairs."
|
||||
history = "" // Todo
|
||||
work = "governing polity of humanity's Confederation"
|
||||
headquarters = "Earth"
|
||||
motto = ""
|
||||
autogenerate_destination_names = TRUE
|
||||
|
||||
ship_prefixes = list("FTV" = "transporation", "FDV" = "diplomatic", "FSF" = "freight", "FIV" = "interception", "FDV" = "defense", "FCV-A" = "carrier", "FBB" = "battleship")
|
||||
destination_names = list(
|
||||
"Venus",
|
||||
"Earth",
|
||||
"Luna",
|
||||
"Mars",
|
||||
"Titan",
|
||||
"Ahdomai",
|
||||
"Kelune",
|
||||
"Dalstadt",
|
||||
"New Canaan",
|
||||
"Jargon 4",
|
||||
"Hoorlm",
|
||||
"Xarxis 5",
|
||||
"Aurum",
|
||||
"Moghes",
|
||||
"Haverick",
|
||||
"Darsing",
|
||||
"Norfolk",
|
||||
"Boron",
|
||||
"Iluk")
|
||||
|
||||
/datum/lore/organization/gov/tajara
|
||||
name = "The Alchemist's Council"
|
||||
short_name = "The Council"
|
||||
acronym = "AC"
|
||||
desc = "The Alchemist's Council is a science-oriented organization of scholars, researchers, and entrepreneurs. \
|
||||
Though dedicated to industrializing the Tajaran world of Ahdomai, it is seen as one of the few remaining centralized powers of the Tajara peoples \
|
||||
due to the collapse of Ahdomai's provisional government."
|
||||
history = "" // Todo
|
||||
work = "science body that oversees Tajara economic and research policy"
|
||||
headquarters = "Ahdomai"
|
||||
motto = ""
|
||||
autogenerate_destination_names = TRUE
|
||||
|
||||
ship_prefixes = list("ACS" = "transportation", "ADV" = "diplomatic", "ACF" = "freight")
|
||||
destination_names = list(
|
||||
"Ahdomai",
|
||||
"Iluk")
|
||||
|
||||
|
||||
/datum/lore/organization/gov/vulp
|
||||
name = "The Assembly"
|
||||
short_name = "Assembly"
|
||||
acronym = "ASB"
|
||||
desc = "A unifying body created to stave off extinction from a solar event,\
|
||||
The Assembly is the loose federal coalition of the Vulpkanin. It holds little centralized authority and mostly serves as a diplomatic body,\
|
||||
primarily concerned with facilitating trade between Vulpkanin colonies and Nanotrasen."
|
||||
history = "" // Todo
|
||||
work = "governing body of the Vulpakanin"
|
||||
headquarters = "Kelune and Dalstadt"
|
||||
motto = ""
|
||||
autogenerate_destination_names = TRUE
|
||||
|
||||
ship_prefixes = list("ATV" = "transportation", "ADV" = "diplomatic", "ACF" = "freight")
|
||||
destination_names = list(
|
||||
"Kelune",
|
||||
"Dalstadt",
|
||||
"New Canaan")
|
||||
|
||||
/datum/lore/organization/gov/synth
|
||||
name = "Synthetic Union"
|
||||
short_name = "Synthetica"
|
||||
acronym = "SYN"
|
||||
desc = "A defensive coalition of synthetics based out of New Canaan,\
|
||||
the Synthetic Union is an organization which aims to establish and consolidate synthetic rights across the galaxy.\
|
||||
Despite its synth oriented focus, the Synthetic Union has cordial relations with most governing bodies."
|
||||
history = "" // Todo
|
||||
work = "Union of Machines"
|
||||
headquarters = "New Canaan"
|
||||
motto = ""
|
||||
autogenerate_destination_names = TRUE
|
||||
|
||||
ship_prefixes = list("01" = "transportation", "10" = "diplomatic", "112" = "freight")//copyed from solgov until new ones can be thought of
|
||||
destination_names = list(
|
||||
"Luna",
|
||||
"Dalstadt",
|
||||
"New Canaan",
|
||||
"Jargon 4",
|
||||
"Haverick",
|
||||
"Darsing",
|
||||
"Norfolk")
|
||||
|
||||
/datum/lore/organization/gov/grey
|
||||
name = "The Technocracy"
|
||||
short_name = "Technocracy"
|
||||
acronym = "AYY"
|
||||
desc = "The Technocracy is a science council that operates based off the principles of a meritocracy.\
|
||||
The organization's leadership is highly competitive, and is headed by the most psionically gifted members of the Grey species.\
|
||||
The Technocracy, though enigmatic in its dealings, has cordial relations with almost all other galactic bodies."
|
||||
history = "" // Todo
|
||||
work = "Grey Council"
|
||||
headquarters = ""
|
||||
motto = ""
|
||||
autogenerate_destination_names = TRUE
|
||||
|
||||
ship_prefixes = list("TC-T" = "transportation", "TC-D" = "diplomatic", "TC-F" = "freight")
|
||||
destination_names = list(
|
||||
"Venus",
|
||||
"Earth",
|
||||
"Luna",
|
||||
"Mars",
|
||||
"Titan",
|
||||
"Ahdomai",
|
||||
"Kelune",
|
||||
"Dalstadt",
|
||||
"New Canaan",
|
||||
"Jargon 4",
|
||||
"Hoorlm",
|
||||
"Xarxis 5",
|
||||
"Aurum",
|
||||
"Moghes",
|
||||
"Haverick",
|
||||
"Darsing",
|
||||
"Norfolk",
|
||||
"Boron",
|
||||
"Iluk")
|
||||
|
||||
/datum/lore/organization/gov/vox
|
||||
name = "The Shoal"
|
||||
short_name = "Shoal"
|
||||
acronym = "SHA"
|
||||
desc = "The Shoal is the primary ark ship of the reclusive Vox species.\
|
||||
Little is known about The Shoal's political structure as Vox typically shy away from diplomatic engagements.\
|
||||
Subsequently, it is considered a politically neutral entity in galactic affairs by most governments."
|
||||
history = "" // Todo
|
||||
work = "Traders"
|
||||
headquarters = "Shoal"
|
||||
motto = ""
|
||||
autogenerate_destination_names = FALSE
|
||||
|
||||
ship_prefixes = list("Legitimate Transport" = "transportation", "Legitimate Trader" = "freight", "Legitimate Diplomatic Vessel" = "raider")
|
||||
destination_names = list(
|
||||
"Ahdomai",
|
||||
"Kelune",
|
||||
"Dalstadt",
|
||||
"New Canaan",
|
||||
"Jargon 4",
|
||||
"Hoorlm",
|
||||
"Xarxis 5",
|
||||
"Aurum",
|
||||
"Moghes",
|
||||
"Haverick",
|
||||
"Darsing")
|
||||
|
||||
/datum/lore/organization/tsc/skrell
|
||||
name = "Skrellian Central Authority"
|
||||
short_name = "Skrellian CA."
|
||||
acronym = "SCA"
|
||||
desc = "The primary governing body of the Skrellian homeworld of Jargon 4,\
|
||||
the SCA oversees all foreign and domestic policy for the Skrell and their colonies. The Skrellian Central Authority is better known for its\
|
||||
active role in the largest military alliance in the galaxy, the Human-Skrellian Alliance."
|
||||
history = ""
|
||||
work = "oversees Skrell worlds"
|
||||
headquarters = "Jargon 4"
|
||||
motto = ""
|
||||
|
||||
ship_prefixes = list("SCA-V." = "transportation", "SCA-F" = "freight", "HSA-D" = "diplomatic")
|
||||
destination_names = list(
|
||||
"Venus",
|
||||
"Earth",
|
||||
"Luna",
|
||||
"Mars",
|
||||
"Titan",
|
||||
"Aurumn",
|
||||
"Jargon 4",
|
||||
"Xarxis 5",
|
||||
"Haverick",
|
||||
"Darsing",
|
||||
"Norfolk")
|
||||
@@ -262,7 +262,6 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
var/list/common_dirs = list(
|
||||
"nano/assets/",
|
||||
"nano/codemirror/",
|
||||
"nano/images/",
|
||||
"nano/layouts/"
|
||||
)
|
||||
var/list/uncommon_dirs = list(
|
||||
@@ -309,6 +308,20 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
/datum/asset/chem_master/send(client)
|
||||
send_asset_list(client, assets, verify)
|
||||
|
||||
//Cloning pod sprites for UIs
|
||||
/datum/asset/cloning
|
||||
var/assets = list()
|
||||
var/verify = FALSE
|
||||
|
||||
/datum/asset/cloning/register()
|
||||
assets["pod_idle.gif"] = icon('icons/obj/cloning.dmi', "pod_idle")
|
||||
assets["pod_cloning.gif"] = icon('icons/obj/cloning.dmi', "pod_cloning")
|
||||
assets["pod_mess.gif"] = icon('icons/obj/cloning.dmi', "pod_mess")
|
||||
for(var/asset_name in assets)
|
||||
register_asset(asset_name, assets[asset_name])
|
||||
|
||||
/datum/asset/cloning/send(client)
|
||||
send_asset_list(client, assets, verify)
|
||||
|
||||
//Pipe sprites for UIs
|
||||
/datum/asset/rpd
|
||||
@@ -362,3 +375,14 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
"font-awesome.css" = 'html/font-awesome/css/all.min.css',
|
||||
"v4shim.css" = 'html/font-awesome/css/v4-shims.min.css'
|
||||
)
|
||||
|
||||
// Nanomaps
|
||||
/datum/asset/simple/nanomaps
|
||||
// It REALLY doesnt matter too much if these arent up to date
|
||||
// They are relatively big
|
||||
verify = FALSE
|
||||
assets = list(
|
||||
"Cyberiad_nanomap_z1.png" = 'icons/_nanomaps/Cyberiad_nanomap_z1.png',
|
||||
"Delta_nanomap_z1.png" = 'icons/_nanomaps/Delta_nanomap_z1.png',
|
||||
"MetaStation_nanomap_z1.png" = 'icons/_nanomaps/MetaStation_nanomap_z1.png',
|
||||
)
|
||||
|
||||
@@ -36,7 +36,10 @@
|
||||
////////////
|
||||
//SECURITY//
|
||||
////////////
|
||||
var/next_allowed_topic_time = 10
|
||||
|
||||
///Used for limiting the rate of topic sends by the client to avoid abuse
|
||||
var/list/topiclimiter
|
||||
|
||||
// comment out the line below when debugging locally to enable the options & messages menu
|
||||
//control_freak = 1
|
||||
|
||||
|
||||
@@ -11,6 +11,13 @@
|
||||
#define SUGGESTED_CLIENT_VERSION 511 // only integers (e.g: 510, 511) useful here. Does not properly handle minor versions (e.g: 510.58, 511.848)
|
||||
#define SSD_WARNING_TIMER 30 // cycles, not seconds, so 30=60s
|
||||
|
||||
#define LIMITER_SIZE 5
|
||||
#define CURRENT_SECOND 1
|
||||
#define SECOND_COUNT 2
|
||||
#define CURRENT_MINUTE 3
|
||||
#define MINUTE_COUNT 4
|
||||
#define ADMINSWARNED_AT 5
|
||||
|
||||
/*
|
||||
When somebody clicks a link in game, this Topic is called first.
|
||||
It does the stuff in this proc and then is redirected to the Topic() proc for the src=[0xWhatever]
|
||||
@@ -59,10 +66,38 @@
|
||||
if(href_list["_src_"] == "chat")
|
||||
return chatOutput.Topic(href, href_list)
|
||||
|
||||
//Reduces spamming of links by dropping calls that happen during the delay period
|
||||
if(next_allowed_topic_time > world.time)
|
||||
return
|
||||
next_allowed_topic_time = world.time + TOPIC_SPAM_DELAY
|
||||
// Rate limiting
|
||||
var/mtl = 100 // 100 topics per minute
|
||||
if (!holder) // Admins are allowed to spam click, deal with it.
|
||||
var/minute = round(world.time, 600)
|
||||
if (!topiclimiter)
|
||||
topiclimiter = new(LIMITER_SIZE)
|
||||
if (minute != topiclimiter[CURRENT_MINUTE])
|
||||
topiclimiter[CURRENT_MINUTE] = minute
|
||||
topiclimiter[MINUTE_COUNT] = 0
|
||||
topiclimiter[MINUTE_COUNT] += 1
|
||||
if (topiclimiter[MINUTE_COUNT] > mtl)
|
||||
var/msg = "Your previous action was ignored because you've done too many in a minute."
|
||||
if (minute != topiclimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them)
|
||||
topiclimiter[ADMINSWARNED_AT] = minute
|
||||
msg += " Administrators have been informed."
|
||||
log_game("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
|
||||
to_chat(src, "<span class='danger'>[msg]</span>")
|
||||
return
|
||||
|
||||
var/stl = 10 // 10 topics a second
|
||||
if (!holder) // Admins are allowed to spam click, deal with it.
|
||||
var/second = round(world.time, 10)
|
||||
if (!topiclimiter)
|
||||
topiclimiter = new(LIMITER_SIZE)
|
||||
if (second != topiclimiter[CURRENT_SECOND])
|
||||
topiclimiter[CURRENT_SECOND] = second
|
||||
topiclimiter[SECOND_COUNT] = 0
|
||||
topiclimiter[SECOND_COUNT] += 1
|
||||
if (topiclimiter[SECOND_COUNT] > stl)
|
||||
to_chat(src, "<span class='danger'>Your previous action was ignored because you've done too many in a second</span>")
|
||||
return
|
||||
|
||||
//search the href for script injection
|
||||
if( findtext(href,"<script",1,0) )
|
||||
@@ -73,13 +108,9 @@
|
||||
|
||||
//Admin PM
|
||||
if(href_list["priv_msg"])
|
||||
var/client/C = locate(href_list["priv_msg"])
|
||||
var/ckey_txt = href_list["priv_msg"]
|
||||
|
||||
if(!C) // Might be a stealthmin ID, so pass it in straight
|
||||
C = href_list["priv_msg"]
|
||||
else if(C.UID() != href_list["priv_msg"])
|
||||
C = null // 404 client not found. Let cmd_admin_pm handle the error
|
||||
cmd_admin_pm(C, null, href_list["type"])
|
||||
cmd_admin_pm(ckey_txt, null, href_list["type"])
|
||||
return
|
||||
|
||||
if(href_list["irc_msg"])
|
||||
@@ -304,11 +335,6 @@
|
||||
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")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
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>")
|
||||
|
||||
|
||||
@@ -939,9 +965,19 @@
|
||||
var/datum/asset/tgui_assets = get_asset_datum(/datum/asset/simple/tgui)
|
||||
tgui_assets.register()
|
||||
|
||||
var/datum/asset/nanomaps = get_asset_datum(/datum/asset/simple/nanomaps)
|
||||
nanomaps.register()
|
||||
|
||||
// Clear the user's cache so they get resent.
|
||||
// This is not fully clearing their BYOND cache, just their assets sent from the server this round
|
||||
cache = list()
|
||||
|
||||
to_chat(usr, "<span class='notice'>UI resource files resent successfully. If you are still having issues, please try manually clearing your BYOND cache. <b>This can be achieved by opening your BYOND launcher, pressing the cog in the top right, selecting preferences, going to the Games tab, and pressing 'Clear Cache'.</b></span>")
|
||||
|
||||
|
||||
#undef LIMITER_SIZE
|
||||
#undef CURRENT_SECOND
|
||||
#undef SECOND_COUNT
|
||||
#undef CURRENT_MINUTE
|
||||
#undef MINUTE_COUNT
|
||||
#undef ADMINSWARNED_AT
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
GLOBAL_LIST_EMPTY(clientmessages)
|
||||
|
||||
proc/addclientmessage(var/ckey, var/message)
|
||||
/proc/addclientmessage(var/ckey, var/message)
|
||||
ckey = ckey(ckey)
|
||||
if(!ckey || !message)
|
||||
return
|
||||
|
||||
@@ -163,41 +163,41 @@
|
||||
display_name = "armband, blue-yellow"
|
||||
path = /obj/item/clothing/accessory/armband/yb
|
||||
|
||||
/datum/gear/accessory/armband_sec
|
||||
/datum/gear/accessory/armband_job
|
||||
subtype_path = /datum/gear/accessory/armband_job
|
||||
subtype_cost_overlap = FALSE
|
||||
|
||||
/datum/gear/accessory/armband_job/sec
|
||||
display_name = " armband, security"
|
||||
path = /obj/item/clothing/accessory/armband/sec
|
||||
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Brig Physician", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/accessory/armband_cargo
|
||||
/datum/gear/accessory/armband_job/cargo
|
||||
display_name = "cargo armband"
|
||||
path = /obj/item/clothing/accessory/armband/cargo
|
||||
allowed_roles = list("Quartermaster","Cargo Technician", "Shaft Miner")
|
||||
|
||||
/datum/gear/accessory/armband_medical
|
||||
/datum/gear/accessory/armband_job/medical
|
||||
display_name = "armband, medical"
|
||||
path = /obj/item/clothing/accessory/armband/med
|
||||
allowed_roles = list("Chief Medical Officer", "Medical Doctor", "Coroner", "Paramedic", "Brig Physician")
|
||||
|
||||
/datum/gear/accessory/armband_emt
|
||||
/datum/gear/accessory/armband_job/emt
|
||||
display_name = "armband, EMT"
|
||||
path = /obj/item/clothing/accessory/armband/medgreen
|
||||
allowed_roles = list("Paramedic", "Brig Physician")
|
||||
|
||||
/datum/gear/accessory/armband_engineering
|
||||
/datum/gear/accessory/armband_job/engineering
|
||||
display_name = "armband, engineering"
|
||||
path = /obj/item/clothing/accessory/armband/engine
|
||||
allowed_roles = list("Chief Engineer","Station Engineer", "Life Support Specialist")
|
||||
|
||||
/datum/gear/accessory/armband_hydro
|
||||
/datum/gear/accessory/armband_job/hydro
|
||||
display_name = "armband, hydroponics"
|
||||
path = /obj/item/clothing/accessory/armband/hydro
|
||||
allowed_roles = list("Botanist")
|
||||
|
||||
/datum/gear/accessory/armband_sci
|
||||
/datum/gear/accessory/armband_job/sci
|
||||
display_name = "armband, science"
|
||||
path = /obj/item/clothing/accessory/armband/science
|
||||
allowed_roles = list("Research Director","Scientist", "Roboticist")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,22 +18,68 @@
|
||||
display_name = "a pack of Midoris"
|
||||
path = /obj/item/storage/fancy/cigarettes/cigpack_midori
|
||||
|
||||
/datum/gear/smokingpipe
|
||||
display_name = "smoking pipe"
|
||||
path = /obj/item/clothing/mask/cigarette/pipe
|
||||
cost = 2
|
||||
|
||||
/datum/gear/lighter
|
||||
display_name = "a cheap lighter"
|
||||
path = /obj/item/lighter
|
||||
|
||||
/datum/gear/matches
|
||||
display_name = "a box of matches"
|
||||
path = /obj/item/storage/box/matches
|
||||
|
||||
/datum/gear/candlebox
|
||||
display_name = "a box candles"
|
||||
description = "For setting the mood or for occult rituals."
|
||||
path = /obj/item/storage/fancy/candle_box
|
||||
|
||||
/datum/gear/rock
|
||||
display_name = "a pet rock"
|
||||
path = /obj/item/toy/pet_rock
|
||||
|
||||
/datum/gear/camera
|
||||
display_name = "a camera"
|
||||
path = /obj/item/camera
|
||||
|
||||
/datum/gear/redfoxplushie
|
||||
display_name = "a red fox plushie"
|
||||
path = /obj/item/toy/plushie/red_fox
|
||||
|
||||
/datum/gear/blackcatplushie
|
||||
display_name = "a black cat plushie"
|
||||
path = /obj/item/toy/plushie/black_cat
|
||||
|
||||
/datum/gear/voxplushie
|
||||
display_name = "a vox plushie"
|
||||
path = /obj/item/toy/plushie/voxplushie
|
||||
|
||||
/datum/gear/lizardplushie
|
||||
display_name = "a lizard plushie"
|
||||
path = /obj/item/toy/plushie/lizardplushie
|
||||
|
||||
/datum/gear/deerplushie
|
||||
display_name = "a deer plushie"
|
||||
path = /obj/item/toy/plushie/deer
|
||||
|
||||
/datum/gear/carpplushie
|
||||
display_name = "a carp plushie"
|
||||
path = /obj/item/toy/carpplushie
|
||||
|
||||
/datum/gear/sechud
|
||||
display_name = "a classic security HUD"
|
||||
path = /obj/item/clothing/glasses/hud/security
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot", "Internal Affairs Agent","Magistrate")
|
||||
|
||||
/datum/gear/matches
|
||||
display_name = "a box of matches"
|
||||
path = /obj/item/storage/box/matches
|
||||
/datum/gear/cryaonbox
|
||||
display_name = "a box of crayons"
|
||||
path = /obj/item/storage/fancy/crayons
|
||||
|
||||
/datum/gear/cane
|
||||
display_name = "a walking cane"
|
||||
path = /obj/item/cane
|
||||
|
||||
/datum/gear/cards
|
||||
display_name = "a deck of standard cards"
|
||||
@@ -51,6 +97,10 @@
|
||||
display_name = "a pair of headphones"
|
||||
path = /obj/item/clothing/ears/headphones
|
||||
|
||||
/datum/gear/fannypack
|
||||
display_name = "a fannypack"
|
||||
path = /obj/item/storage/belt/fannypack
|
||||
|
||||
/datum/gear/blackbandana
|
||||
display_name = "bandana, black"
|
||||
path = /obj/item/clothing/mask/bandana/black
|
||||
@@ -105,6 +155,11 @@
|
||||
cost = 2
|
||||
sort_category = "Mugs"
|
||||
|
||||
/datum/gear/mug/flask
|
||||
display_name = "flask"
|
||||
description = "A flask for drink transportation. You'll need to supply your own beverage though."
|
||||
path = /obj/item/reagent_containers/food/drinks/flask/barflask
|
||||
|
||||
/datum/gear/mug/department
|
||||
subtype_path = /datum/gear/mug/department
|
||||
sort_category = "Mugs"
|
||||
|
||||
@@ -6,3 +6,11 @@
|
||||
/datum/gear/gloves/fingerless
|
||||
display_name = "Fingerless Gloves"
|
||||
path = /obj/item/clothing/gloves/fingerless
|
||||
|
||||
/datum/gear/gloves/silverring
|
||||
display_name = "Silver ring"
|
||||
path = /obj/item/clothing/gloves/ring/silver
|
||||
|
||||
/datum/gear/gloves/goldring
|
||||
display_name = "Gold ring"
|
||||
path = /obj/item/clothing/gloves/ring/gold
|
||||
|
||||
@@ -26,10 +26,22 @@
|
||||
display_name = "flat cap"
|
||||
path = /obj/item/clothing/head/flatcap
|
||||
|
||||
/datum/gear/hat/witch
|
||||
display_name = "witch hat"
|
||||
path = /obj/item/clothing/head/wizard/marisa/fake
|
||||
|
||||
/datum/gear/hat/piratecaphat
|
||||
display_name = "pirate captian hat"
|
||||
path = /obj/item/clothing/head/pirate
|
||||
|
||||
/datum/gear/hat/fez
|
||||
display_name = "fez"
|
||||
path = /obj/item/clothing/head/fez
|
||||
|
||||
/datum/gear/hat/rasta
|
||||
display_name = "rasta hat"
|
||||
path = /obj/item/clothing/head/beanie/rasta
|
||||
|
||||
/datum/gear/hat/bfedora
|
||||
display_name = "fedora, black"
|
||||
path = /obj/item/clothing/head/fedora
|
||||
@@ -42,11 +54,6 @@
|
||||
display_name = "fedora, brown"
|
||||
path = /obj/item/clothing/head/fedora/brownfedora
|
||||
|
||||
/datum/gear/hat/beretsec
|
||||
display_name = "security beret"
|
||||
path = /obj/item/clothing/head/beret/sec
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/hat/capcsec
|
||||
display_name = "security corporate cap"
|
||||
path = /obj/item/clothing/head/soft/sec/corp
|
||||
@@ -113,32 +120,51 @@
|
||||
display_name = "cowboy hat, pink"
|
||||
path = /obj/item/clothing/head/cowboyhat/pink
|
||||
|
||||
/datum/gear/hat/pr_beret
|
||||
/datum/gear/hat/beret_purple
|
||||
display_name = "beret, purple"
|
||||
path = /obj/item/clothing/head/beret/purple_normal
|
||||
|
||||
/datum/gear/hat/bl_beret
|
||||
/datum/gear/hat/beret_black
|
||||
display_name = "beret, black"
|
||||
path = /obj/item/clothing/head/beret/black
|
||||
|
||||
/datum/gear/hat/blu_beret
|
||||
/datum/gear/hat/beret_blue
|
||||
display_name = "beret, blue"
|
||||
path = /obj/item/clothing/head/beret/blue
|
||||
|
||||
/datum/gear/hat/red_beret
|
||||
/datum/gear/hat/beret_red
|
||||
display_name = "beret, red"
|
||||
path = /obj/item/clothing/head/beret
|
||||
|
||||
/datum/gear/hat/sci_beret
|
||||
/datum/gear/hat/beret_job
|
||||
subtype_path = /datum/gear/hat/beret_job
|
||||
subtype_cost_overlap = FALSE
|
||||
|
||||
/datum/gear/hat/beret_job/sec
|
||||
display_name = "security beret"
|
||||
path = /obj/item/clothing/head/beret/sec
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/hat/beret_job/sci
|
||||
display_name = "science beret"
|
||||
path = /obj/item/clothing/head/beret/sci
|
||||
allowed_roles = list("Research Director", "Scientist")
|
||||
|
||||
/datum/gear/hat/med_beret
|
||||
/datum/gear/hat/beret_job/med
|
||||
display_name = "medical beret"
|
||||
path = /obj/item/clothing/head/beret/med
|
||||
allowed_roles = list("Chief Medical Officer", "Medical Doctor" , "Virologist", "Brig Physician" , "Coroner")
|
||||
|
||||
/datum/gear/hat/beret_job/eng
|
||||
display_name = "engineering beret"
|
||||
path = /obj/item/clothing/head/beret/eng
|
||||
allowed_roles = list("Chief Engineer", "Station Engineer")
|
||||
|
||||
/datum/gear/hat/beret_job/atmos
|
||||
display_name = "atmospherics beret"
|
||||
path = /obj/item/clothing/head/beret/atmos
|
||||
allowed_roles = list("Chief Engineer", "Life Support Specialist")
|
||||
|
||||
/datum/gear/hat/surgicalcap_purple
|
||||
display_name = "surgical cap, purple"
|
||||
path = /obj/item/clothing/head/surgery/purple
|
||||
@@ -152,7 +178,3 @@
|
||||
/datum/gear/hat/flowerpin
|
||||
display_name = "hair flower"
|
||||
path = /obj/item/clothing/head/hairflower
|
||||
|
||||
/datum/gear/hat/kitty
|
||||
display_name = "kitty headband"
|
||||
path = /obj/item/clothing/head/kitty
|
||||
|
||||
@@ -17,12 +17,10 @@
|
||||
|
||||
/datum/gear/shoes/fancysandals
|
||||
display_name = "sandals, fancy"
|
||||
cost = 2
|
||||
path = /obj/item/clothing/shoes/sandal/fancy
|
||||
|
||||
/datum/gear/shoes/dressshoes
|
||||
display_name = "dress shoes"
|
||||
cost = 2
|
||||
path = /obj/item/clothing/shoes/centcom
|
||||
|
||||
/datum/gear/shoes/cowboyboots
|
||||
@@ -41,6 +39,14 @@
|
||||
display_name = "cowboy boots, pink"
|
||||
path = /obj/item/clothing/shoes/cowboy/pink
|
||||
|
||||
/datum/gear/shoes/jackboots
|
||||
display_name = "jackboots"
|
||||
path = /obj/item/clothing/shoes/jackboots
|
||||
|
||||
/datum/gear/shoes/jacksandals
|
||||
display_name = "jacksandals"
|
||||
path = /obj/item/clothing/shoes/jackboots/jacksandals
|
||||
|
||||
/datum/gear/shoes/laceup
|
||||
display_name = "laceup shoes"
|
||||
path = /obj/item/clothing/shoes/laceup
|
||||
|
||||
@@ -175,32 +175,44 @@
|
||||
display_name = "regal shawl"
|
||||
path = /obj/item/clothing/suit/mantle/regal
|
||||
|
||||
/datum/gear/suit/captain_cloak
|
||||
/datum/gear/suit/mantle/job
|
||||
subtype_path = /datum/gear/suit/mantle/job
|
||||
subtype_cost_overlap = FALSE
|
||||
|
||||
/datum/gear/suit/mantle/job/captain
|
||||
display_name = "mantle, captain"
|
||||
path = /obj/item/clothing/suit/mantle/armor/captain
|
||||
allowed_roles = list("Captain")
|
||||
|
||||
/datum/gear/suit/ce_mantle
|
||||
/datum/gear/suit/mantle/job/ce
|
||||
display_name = "mantle, chief engineer"
|
||||
path = /obj/item/clothing/suit/mantle/chief_engineer
|
||||
allowed_roles = list("Chief Engineer")
|
||||
|
||||
/datum/gear/suit/cmo_mantle
|
||||
/datum/gear/suit/mantle/job/cmo
|
||||
display_name = "mantle, chief medical officer"
|
||||
path = /obj/item/clothing/suit/mantle/labcoat/chief_medical_officer
|
||||
allowed_roles = list("Chief Medical Officer")
|
||||
|
||||
/datum/gear/suit/armored_shawl
|
||||
/datum/gear/suit/mantle/job/hos
|
||||
display_name = "mantle, head of security"
|
||||
path = /obj/item/clothing/suit/mantle/armor
|
||||
allowed_roles = list("Head of Security")
|
||||
|
||||
/datum/gear/suit/hop_shawl
|
||||
/datum/gear/suit/mantle/job/hop
|
||||
display_name = "mantle, head of personnel"
|
||||
path = /obj/item/clothing/suit/mantle/armor/head_of_personnel
|
||||
allowed_roles = list("Head of Personnel")
|
||||
|
||||
/datum/gear/suit/rd_mantle
|
||||
/datum/gear/suit/mantle/job/rd
|
||||
display_name = "mantle, research director"
|
||||
path = /obj/item/clothing/suit/mantle/labcoat
|
||||
allowed_roles = list("Research Director")
|
||||
|
||||
//Robes!
|
||||
|
||||
/datum/gear/suit/witch
|
||||
display_name = "witch robes"
|
||||
path = /obj/item/clothing/suit/wizrobe/marisa/fake
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,103 @@
|
||||
slot = slot_w_uniform
|
||||
sort_category = "Uniforms and Casual Dress"
|
||||
|
||||
/datum/gear/uniform/suits
|
||||
subtype_path = /datum/gear/uniform/suit
|
||||
|
||||
//there's a lot more colors than I thought there were @_@
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitblack
|
||||
display_name = "jumpsuit, black"
|
||||
path = /obj/item/clothing/under/color/black
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitblue
|
||||
display_name = "jumpsuit, blue"
|
||||
path = /obj/item/clothing/under/color/blue
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitgreen
|
||||
display_name = "jumpsuit, green"
|
||||
path = /obj/item/clothing/under/color/green
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitgrey
|
||||
display_name = "jumpsuit, grey"
|
||||
path = /obj/item/clothing/under/color/grey
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitorange
|
||||
display_name = "jumpsuit, orange"
|
||||
path = /obj/item/clothing/under/color/orange
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitpink
|
||||
display_name = "jumpsuit, pink"
|
||||
path = /obj/item/clothing/under/color/pink
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitred
|
||||
display_name = "jumpsuit, red"
|
||||
path = /obj/item/clothing/under/color/red
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitwhite
|
||||
display_name = "jumpsuit, white"
|
||||
path = /obj/item/clothing/under/color/white
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuityellow
|
||||
display_name = "jumpsuit, yellow"
|
||||
path = /obj/item/clothing/under/color/yellow
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitlightblue
|
||||
display_name = "jumpsuit, lightblue"
|
||||
path = /obj/item/clothing/under/color/lightblue
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitaqua
|
||||
display_name = "jumpsuit, aqua"
|
||||
path = /obj/item/clothing/under/color/aqua
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitpurple
|
||||
display_name = "jumpsuit, purple"
|
||||
path = /obj/item/clothing/under/color/purple
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitlightpurple
|
||||
display_name = "jumpsuit, lightpurple"
|
||||
path = /obj/item/clothing/under/color/lightpurple
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitlightgreen
|
||||
display_name = "jumpsuit, lightgreen"
|
||||
path = /obj/item/clothing/under/color/lightgreen
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitlightblue
|
||||
display_name = "jumpsuit, lightblue"
|
||||
path = /obj/item/clothing/under/color/lightblue
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitlightbrown
|
||||
display_name = "jumpsuit, lightbrown"
|
||||
path = /obj/item/clothing/under/color/lightbrown
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitbrown
|
||||
display_name = "jumpsuit, brown"
|
||||
path = /obj/item/clothing/under/color/brown
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuityellowgreen
|
||||
display_name = "jumpsuit, yellowgreen"
|
||||
path = /obj/item/clothing/under/color/yellowgreen
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitdarkblue
|
||||
display_name = "jumpsuit, darkblue"
|
||||
path = /obj/item/clothing/under/color/darkblue
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitlightred
|
||||
display_name = "jumpsuit, lightred"
|
||||
path = /obj/item/clothing/under/color/lightred
|
||||
|
||||
/datum/gear/uniform/suit/jumpsuitdarkred
|
||||
display_name = "jumpsuit, darkred"
|
||||
path = /obj/item/clothing/under/color/darkred
|
||||
|
||||
/datum/gear/uniform/suit/soviet
|
||||
display_name = "USSP uniform"
|
||||
path = /obj/item/clothing/under/soviet
|
||||
|
||||
/datum/gear/uniform/suit/kilt
|
||||
display_name = "a kilt"
|
||||
path = /obj/item/clothing/under/kilt
|
||||
|
||||
/datum/gear/uniform/skirt
|
||||
subtype_path = /datum/gear/uniform/skirt
|
||||
|
||||
|
||||
@@ -1191,7 +1191,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
if(!tweak || !istype(gear) || !(tweak in gear.gear_tweaks))
|
||||
return
|
||||
var/metadata = tweak.get_metadata(user, get_tweak_metadata(gear, tweak))
|
||||
if(!metadata || !CanUseTopic(user))
|
||||
if(!metadata)
|
||||
return
|
||||
set_tweak_metadata(gear, tweak, metadata)
|
||||
else if(href_list["select_category"])
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
set name = "Show/Hide RadioChatter"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggle seeing radiochatter from radios and speakers"
|
||||
if(!holder) return
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
prefs.toggles ^= CHAT_RADIO
|
||||
prefs.save_preferences(src)
|
||||
to_chat(usr, "You will [(prefs.toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from radios or speakers")
|
||||
@@ -49,7 +50,8 @@
|
||||
set name = "Hear/Silence Admin Bwoinks"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggle hearing a notification when admin PMs are recieved"
|
||||
if(!holder) return
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
prefs.sound ^= SOUND_ADMINHELP
|
||||
prefs.save_preferences(src)
|
||||
to_chat(usr, "You will [(prefs.sound & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive.")
|
||||
@@ -59,7 +61,7 @@
|
||||
set name = "Hear/Silence Mentorhelp Bwoinks"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggle hearing a notification when mentorhelps are recieved"
|
||||
if(!holder)
|
||||
if(!check_rights(R_ADMIN|R_MENTOR))
|
||||
return
|
||||
prefs.sound ^= SOUND_MENTORHELP
|
||||
prefs.save_preferences(src)
|
||||
@@ -296,7 +298,7 @@
|
||||
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!
|
||||
|
||||
|
||||
/client/verb/silence_current_midi()
|
||||
set name = "Silence Current Midi"
|
||||
set category = "Preferences"
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
var/cooldown = 0
|
||||
var/species_disguise = null
|
||||
var/magical = FALSE
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/clothing/proc/weldingvisortoggle(mob/user) //proc to toggle welding visors on helmets, masks, goggles, etc.
|
||||
if(!can_use(user))
|
||||
@@ -119,6 +120,12 @@
|
||||
else
|
||||
icon = initial(icon)
|
||||
|
||||
/**
|
||||
* Used for any clothing interactions when the user is on fire. (e.g. Cigarettes getting lit.)
|
||||
*/
|
||||
/obj/item/clothing/proc/catch_fire() //Called in handle_fire()
|
||||
return
|
||||
|
||||
//Ears: currently only used for headsets and earmuffs
|
||||
/obj/item/clothing/ears
|
||||
name = "ears"
|
||||
@@ -590,6 +597,7 @@ BLIND // can't see anything
|
||||
name = "Space helmet"
|
||||
icon_state = "space"
|
||||
desc = "A special helmet designed for work in a hazardous, low-pressure environment."
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
flags = BLOCKHAIR | STOPSPRESSUREDMAGE | THICKMATERIAL
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
item_state = "s_helmet"
|
||||
|
||||
@@ -8,21 +8,3 @@
|
||||
strip_delay = 15
|
||||
put_on_delay = 25
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/clothing/ears/headphones
|
||||
name = "headphones"
|
||||
desc = "Unce unce unce unce."
|
||||
var/on = 0
|
||||
icon_state = "headphones0"
|
||||
item_state = null
|
||||
actions_types = list(/datum/action/item_action/toggle_headphones)
|
||||
|
||||
/obj/item/clothing/ears/headphones/attack_self(mob/user)
|
||||
on = !on
|
||||
icon_state = "headphones[on]"
|
||||
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
|
||||
user.update_inv_ears()
|
||||
|
||||
@@ -196,3 +196,17 @@
|
||||
|
||||
/obj/item/clothing/glasses/hud/health/tajblind/attack_self()
|
||||
toggle_veil()
|
||||
|
||||
/obj/item/clothing/glasses/hud/skills
|
||||
name = "Skills HUD"
|
||||
desc = "A heads-up display capable of showing the employment history records of NT crew members."
|
||||
icon_state = "material"
|
||||
item_state = "glasses"
|
||||
|
||||
/obj/item/clothing/glasses/hud/skills/sunglasses
|
||||
name = "Skills HUD Sunglasses"
|
||||
desc = "Sunglasses with a build-in skills HUD, showing the employment history of nearby NT crew members."
|
||||
see_in_dark = 1 // None of these three can be converted to booleans. Do not try it.
|
||||
flash_protect = 1
|
||||
tint = 1
|
||||
prescription_upgradable = TRUE
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "helmet"
|
||||
desc = "Standard Security gear. Protects the head from impacts."
|
||||
icon_state = "helmetmaterials"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
flags = HEADBANGPROTECT
|
||||
flags_cover = HEADCOVERSEYES
|
||||
item_state = "helmetmaterials"
|
||||
@@ -192,7 +193,7 @@
|
||||
toggle_sound = 'sound/items/zippoclose.ogg'
|
||||
dog_fashion = null
|
||||
|
||||
obj/item/clothing/head/helmet/redtaghelm
|
||||
/obj/item/clothing/head/helmet/redtaghelm
|
||||
name = "red laser tag helmet"
|
||||
desc = "They have chosen their own end."
|
||||
icon_state = "redtaghelm"
|
||||
@@ -203,7 +204,7 @@ obj/item/clothing/head/helmet/redtaghelm
|
||||
flags_inv = HIDEEARS|HIDEEYES
|
||||
dog_fashion = null
|
||||
|
||||
obj/item/clothing/head/helmet/bluetaghelm
|
||||
/obj/item/clothing/head/helmet/bluetaghelm
|
||||
name = "blue laser tag helmet"
|
||||
desc = "They'll need more men."
|
||||
icon_state = "bluetaghelm"
|
||||
@@ -214,7 +215,7 @@ obj/item/clothing/head/helmet/bluetaghelm
|
||||
flags_inv = HIDEEARS|HIDEEYES
|
||||
dog_fashion = null
|
||||
|
||||
obj/item/clothing/head/blob
|
||||
/obj/item/clothing/head/blob
|
||||
name = "blob hat"
|
||||
desc = "A collectible hat handed out at the latest Blob Family Reunion."
|
||||
icon_state = "blobhat"
|
||||
|
||||
@@ -401,6 +401,7 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
attack_verb = list("warned", "cautioned", "smashed")
|
||||
resistance_flags = NONE
|
||||
dog_fashion = /datum/dog_fashion/head/cone
|
||||
|
||||
/obj/item/clothing/head/jester
|
||||
name = "jester hat"
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
trigger.forceMove(src)
|
||||
trigger.master = src
|
||||
trigger.holder = src
|
||||
AddComponent(/datum/component/proximity_monitor)
|
||||
to_chat(user, "<span class='notice'>You attach the [W] to [src].</span>")
|
||||
return TRUE
|
||||
else if(istype(W, /obj/item/assembly))
|
||||
@@ -165,6 +166,7 @@
|
||||
trigger.master = null
|
||||
trigger.holder = null
|
||||
trigger = null
|
||||
qdel(GetComponent(/datum/component/proximity_monitor))
|
||||
|
||||
/obj/item/clothing/mask/muzzle/safety/shock/proc/can_shock(obj/item/clothing/C)
|
||||
if(istype(C))
|
||||
@@ -186,7 +188,7 @@
|
||||
M.Jitter(20)
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/muzzle/safety/shock/HasProximity(atom/movable/AM as mob|obj)
|
||||
/obj/item/clothing/mask/muzzle/safety/shock/HasProximity(atom/movable/AM)
|
||||
if(trigger)
|
||||
trigger.HasProximity(AM)
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
heat_protection = FEET
|
||||
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
|
||||
|
||||
redcoat
|
||||
item_color = "redcoat" //Exists for washing machines. Is not different from black shoes in any way.
|
||||
/obj/item/clothing/shoes/black/redcoat
|
||||
item_color = "redcoat" //Exists for washing machines. Is not different from black shoes in any way.
|
||||
|
||||
/obj/item/clothing/shoes/black/greytide
|
||||
flags = NODROP
|
||||
@@ -20,18 +20,23 @@
|
||||
desc = "A pair of brown shoes."
|
||||
icon_state = "brown"
|
||||
|
||||
captain
|
||||
item_color = "captain" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
hop
|
||||
item_color = "hop" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
ce
|
||||
item_color = "chief" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
rd
|
||||
item_color = "director" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
cmo
|
||||
item_color = "medical" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
cmo
|
||||
item_color = "cargo" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
/obj/item/clothing/shoes/brown/captain
|
||||
item_color = "captain" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
|
||||
/obj/item/clothing/shoes/brown/hop
|
||||
item_color = "hop" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
|
||||
/obj/item/clothing/shoes/brown/ce
|
||||
item_color = "chief" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
|
||||
/obj/item/clothing/shoes/brown/rd
|
||||
item_color = "director" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
|
||||
/obj/item/clothing/shoes/brown/cmo
|
||||
item_color = "medical" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
|
||||
/obj/item/clothing/shoes/brown/qm
|
||||
item_color = "cargo" //Exists for washing machines. Is not different from brown shoes in any way.
|
||||
|
||||
/obj/item/clothing/shoes/blue
|
||||
name = "blue shoes"
|
||||
|
||||
@@ -8,11 +8,19 @@
|
||||
var/slowdown_active = 2
|
||||
var/slowdown_passive = SHOES_SLOWDOWN
|
||||
var/magpulse_name = "mag-pulse traction system"
|
||||
var/gustprotection = FALSE //this is for unsafe_unwrenching protection
|
||||
actions_types = list(/datum/action/item_action/toggle)
|
||||
strip_delay = 70
|
||||
put_on_delay = 70
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/obj/item/clothing/shoes/magboots/atmos
|
||||
desc = "Magnetic boots, made to withstand gusts of space wind over 500kmph."
|
||||
name = "atmospheric magboots"
|
||||
icon_state = "atmosmagboots0"
|
||||
magboot_state = "atmosmagboots"
|
||||
gustprotection = TRUE
|
||||
|
||||
/obj/item/clothing/shoes/magboots/attack_self(mob/user)
|
||||
if(magpulse)
|
||||
flags &= ~NOSLIP
|
||||
@@ -42,6 +50,7 @@
|
||||
name = "advanced magboots"
|
||||
icon_state = "advmag0"
|
||||
magboot_state = "advmag"
|
||||
gustprotection = TRUE
|
||||
slowdown_active = SHOES_SLOWDOWN
|
||||
origin_tech = null
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
@@ -53,7 +62,7 @@
|
||||
magboot_state = "syndiemag"
|
||||
origin_tech = "magnets=4;syndicate=2"
|
||||
|
||||
obj/item/clothing/shoes/magboots/syndie/advance //For the Syndicate Strike Team
|
||||
/obj/item/clothing/shoes/magboots/syndie/advance //For the Syndicate Strike Team
|
||||
desc = "Reverse-engineered magboots that appear to be based on an advanced model, as they have a lighter magnetic pull. Property of Gorlex Marauders."
|
||||
name = "advanced blood-red magboots"
|
||||
slowdown_active = SHOES_SLOWDOWN
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
/obj/item/clothing/shoes/combat //basic syndicate combat boots for nuke ops and mob corpses
|
||||
name = "combat boots"
|
||||
desc = "High speed, low drag combat boots."
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
can_cut_open = 1
|
||||
icon_state = "jackboots"
|
||||
item_state = "jackboots"
|
||||
@@ -343,3 +344,10 @@
|
||||
recharging_time = world.time + recharging_rate
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Something prevents you from dashing forward!</span>")
|
||||
|
||||
/obj/item/clothing/shoes/ducky
|
||||
name = "rubber ducky shoes"
|
||||
desc = "These shoes are made for quacking, and thats just what they'll do."
|
||||
icon_state = "ducky"
|
||||
item_state = "ducky"
|
||||
shoe_sound = "sound/items/squeaktoy.ogg"
|
||||
|
||||
@@ -16,15 +16,27 @@
|
||||
"Vox" = 'icons/mob/species/vox/helmet.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/Initialize()
|
||||
if(loc)
|
||||
var/mob/living/carbon/human/wearer = loc.loc //loc is the hardsuit, so its loc is the wearer
|
||||
if(ishuman(wearer))
|
||||
register_camera(wearer)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/attack_self(mob/user)
|
||||
if(camera || !has_camera)
|
||||
..(user)
|
||||
else
|
||||
camera = new /obj/machinery/camera(src)
|
||||
camera.network = list("ERT")
|
||||
GLOB.cameranet.removeCamera(camera)
|
||||
camera.c_tag = user.name
|
||||
to_chat(user, "<span class='notice'>User scanned as [camera.c_tag]. Camera activated.</span>")
|
||||
register_camera(user)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/proc/register_camera(mob/wearer)
|
||||
if(camera || !has_camera)
|
||||
return
|
||||
camera = new /obj/machinery/camera(src)
|
||||
camera.network = list("ERT")
|
||||
GLOB.cameranet.removeCamera(camera)
|
||||
camera.c_tag = wearer.name
|
||||
to_chat(wearer, "<span class='notice'>User scanned as [camera.c_tag]. Camera activated.</span>")
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -1,248 +0,0 @@
|
||||
/*
|
||||
* Contains
|
||||
* /obj/item/rig_module/grenade_launcher
|
||||
* /obj/item/rig_module/mounted
|
||||
* /obj/item/rig_module/mounted/taser
|
||||
* /obj/item/rig_module/shield
|
||||
* /obj/item/rig_module/fabricator
|
||||
* /obj/item/rig_module/device/flash
|
||||
*/
|
||||
|
||||
/obj/item/rig_module/device/flash
|
||||
name = "mounted flash"
|
||||
desc = "You are the law."
|
||||
icon_state = "flash"
|
||||
interface_name = "mounted flash"
|
||||
interface_desc = "Stuns your target by blinding them with a bright light."
|
||||
device_type = /obj/item/flash
|
||||
|
||||
/obj/item/rig_module/grenade_launcher
|
||||
|
||||
name = "mounted grenade launcher"
|
||||
desc = "A shoulder-mounted micro-explosive dispenser."
|
||||
selectable = 1
|
||||
icon_state = "grenade"
|
||||
|
||||
interface_name = "integrated grenade launcher"
|
||||
interface_desc = "Discharges loaded grenades against the wearer's location."
|
||||
|
||||
var/fire_force = 30
|
||||
var/fire_distance = 10
|
||||
|
||||
charges = list(
|
||||
list("flashbang", "flashbang", /obj/item/grenade/flashbang, 3),
|
||||
list("smoke bomb", "smoke bomb", /obj/item/grenade/smokebomb, 3),
|
||||
list("EMP grenade", "EMP grenade", /obj/item/grenade/empgrenade, 3),
|
||||
)
|
||||
|
||||
/obj/item/rig_module/grenade_launcher/accepts_item(var/obj/item/input_device, var/mob/living/user)
|
||||
|
||||
if(!istype(input_device) || !istype(user))
|
||||
return 0
|
||||
|
||||
var/datum/rig_charge/accepted_item
|
||||
for(var/charge in charges)
|
||||
var/datum/rig_charge/charge_datum = charges[charge]
|
||||
if(input_device.type == charge_datum.product_type)
|
||||
accepted_item = charge_datum
|
||||
break
|
||||
|
||||
if(!accepted_item)
|
||||
return 0
|
||||
|
||||
if(accepted_item.charges >= 5)
|
||||
to_chat(user, "<span class='danger'>Another grenade of that type will not fit into the module.</span>")
|
||||
return 0
|
||||
|
||||
to_chat(user, "<font color='blue'><b>You slot \the [input_device] into the suit module.</b></font>")
|
||||
user.unEquip(input_device)
|
||||
qdel(input_device)
|
||||
accepted_item.charges++
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/grenade_launcher/engage(atom/target)
|
||||
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
|
||||
if(!charge_selected)
|
||||
to_chat(H, "<span class='danger'>You have not selected a grenade type.</span>")
|
||||
return 0
|
||||
|
||||
var/datum/rig_charge/charge = charges[charge_selected]
|
||||
|
||||
if(!charge)
|
||||
return 0
|
||||
|
||||
if(charge.charges <= 0)
|
||||
to_chat(H, "<span class='danger'>Insufficient grenades!</span>")
|
||||
return 0
|
||||
|
||||
charge.charges--
|
||||
var/obj/item/grenade/new_grenade = new charge.product_type(get_turf(H))
|
||||
H.visible_message("<span class='danger'>[H] launches \a [new_grenade]!</span>")
|
||||
new_grenade.throw_at(target,fire_force,fire_distance)
|
||||
new_grenade.prime()
|
||||
|
||||
/obj/item/rig_module/mounted
|
||||
|
||||
name = "mounted laser cannon"
|
||||
desc = "A shoulder-mounted battery-powered laser cannon mount."
|
||||
selectable = 1
|
||||
usable = 1
|
||||
module_cooldown = 0
|
||||
icon_state = "lcannon"
|
||||
|
||||
engage_string = "Configure"
|
||||
|
||||
interface_name = "mounted laser cannon"
|
||||
interface_desc = "A shoulder-mounted cell-powered laser cannon."
|
||||
|
||||
var/gun_type = /obj/item/gun/energy/lasercannon/mounted
|
||||
var/obj/item/gun/gun
|
||||
|
||||
/obj/item/rig_module/mounted/New()
|
||||
..()
|
||||
gun = new gun_type(src)
|
||||
|
||||
/obj/item/rig_module/mounted/engage(atom/target)
|
||||
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
gun.attack_self(holder.wearer)
|
||||
return 1
|
||||
|
||||
gun.afterattack(target,holder.wearer)
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/mounted/egun
|
||||
|
||||
name = "mounted energy gun"
|
||||
desc = "A forearm-mounted energy projector."
|
||||
icon_state = "egun"
|
||||
|
||||
interface_name = "mounted energy gun"
|
||||
interface_desc = "A forearm-mounted suit-powered energy gun."
|
||||
|
||||
gun_type = /obj/item/gun/energy/gun/mounted
|
||||
|
||||
/obj/item/rig_module/mounted/taser
|
||||
|
||||
name = "mounted taser"
|
||||
desc = "A palm-mounted nonlethal energy projector."
|
||||
icon_state = "taser"
|
||||
|
||||
usable = 0
|
||||
|
||||
suit_overlay_active = "mounted-taser"
|
||||
suit_overlay_inactive = "mounted-taser"
|
||||
|
||||
interface_name = "mounted energy gun"
|
||||
interface_desc = "A shoulder-mounted cell-powered energy gun."
|
||||
|
||||
gun_type = /obj/item/gun/energy/taser/mounted
|
||||
|
||||
/obj/item/rig_module/mounted/energy_blade
|
||||
|
||||
name = "energy blade projector"
|
||||
desc = "A powerful cutting beam projector."
|
||||
icon_state = "eblade"
|
||||
|
||||
activate_string = "Project Blade"
|
||||
deactivate_string = "Cancel Blade"
|
||||
|
||||
interface_name = "spider fang blade"
|
||||
interface_desc = "A lethal energy projector that can shape a blade projected from the hand of the wearer or launch radioactive darts."
|
||||
|
||||
usable = 0
|
||||
selectable = 1
|
||||
toggleable = 1
|
||||
use_power_cost = 50
|
||||
active_power_cost = 10
|
||||
passive_power_cost = 0
|
||||
|
||||
gun_type = /obj/item/gun/energy/kinetic_accelerator/crossbow/ninja
|
||||
|
||||
/obj/item/rig_module/mounted/energy_blade/process()
|
||||
|
||||
if(holder && holder.wearer)
|
||||
if(!(locate(/obj/item/melee/energy/blade) in holder.wearer))
|
||||
deactivate()
|
||||
return 0
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/rig_module/mounted/energy_blade/activate()
|
||||
|
||||
..()
|
||||
|
||||
var/mob/living/M = holder.wearer
|
||||
|
||||
if(M.l_hand && M.r_hand)
|
||||
to_chat(M, "<span class='danger'>Your hands are full.</span>")
|
||||
deactivate()
|
||||
return
|
||||
|
||||
var/obj/item/melee/energy/blade/blade = new(M)
|
||||
M.put_in_hands(blade)
|
||||
|
||||
/obj/item/rig_module/mounted/energy_blade/deactivate()
|
||||
|
||||
..()
|
||||
|
||||
var/mob/living/M = holder.wearer
|
||||
|
||||
if(!M)
|
||||
return
|
||||
|
||||
for(var/obj/item/melee/energy/blade/blade in M.contents)
|
||||
M.unEquip(blade)
|
||||
qdel(blade)
|
||||
|
||||
/obj/item/rig_module/fabricator
|
||||
|
||||
name = "matter fabricator"
|
||||
desc = "A self-contained microfactory system for hardsuit integration."
|
||||
selectable = 1
|
||||
usable = 1
|
||||
use_power_cost = 15
|
||||
icon_state = "enet"
|
||||
|
||||
engage_string = "Fabricate Tile"
|
||||
|
||||
interface_name = "death blossom launcher"
|
||||
interface_desc = "An integrated microfactory that produces floor tiles from thin air and electricity."
|
||||
|
||||
var/fabrication_type = /obj/item/stack/tile/plasteel
|
||||
var/fire_force = 30
|
||||
var/fire_distance = 10
|
||||
|
||||
/obj/item/rig_module/fabricator/engage(atom/target)
|
||||
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
var/mob/living/H = holder.wearer
|
||||
|
||||
if(target)
|
||||
var/obj/item/firing = new fabrication_type()
|
||||
firing.forceMove(get_turf(src))
|
||||
H.visible_message("<span class='danger'>[H] launches \a [firing]!</span>")
|
||||
firing.throw_at(target,fire_force,fire_distance)
|
||||
else
|
||||
if(H.l_hand && H.r_hand)
|
||||
to_chat(H, "<span class='danger'>Your hands are full.</span>")
|
||||
else
|
||||
var/obj/item/new_weapon = new fabrication_type()
|
||||
new_weapon.forceMove(H)
|
||||
to_chat(H, "<font color='blue'><b>You quickly fabricate \a [new_weapon].</b></font>")
|
||||
H.put_in_hands(new_weapon)
|
||||
|
||||
return 1
|
||||
@@ -1,496 +0,0 @@
|
||||
/*
|
||||
* Contains
|
||||
* /obj/item/rig_module/ai_container
|
||||
* /obj/item/rig_module/datajack
|
||||
* /obj/item/rig_module/power_sink
|
||||
* /obj/item/rig_module/electrowarfare_suite
|
||||
*/
|
||||
|
||||
/obj/item/ai_verbs
|
||||
name = "AI verb holder"
|
||||
|
||||
/obj/item/ai_verbs/verb/hardsuit_interface()
|
||||
set category = "Hardsuit"
|
||||
set name = "Open Hardsuit Interface"
|
||||
set src in usr
|
||||
|
||||
if(!usr.loc || !usr.loc.loc || !istype(usr.loc.loc, /obj/item/rig_module))
|
||||
to_chat(usr, "You are not loaded into a hardsuit.")
|
||||
return
|
||||
|
||||
var/obj/item/rig_module/module = usr.loc.loc
|
||||
if(!module.holder)
|
||||
to_chat(usr, "Your module is not installed in a hardsuit.")
|
||||
return
|
||||
|
||||
module.holder.ui_interact(usr, state = GLOB.contained_state)
|
||||
|
||||
/obj/item/rig_module/ai_container
|
||||
|
||||
name = "IIS module"
|
||||
desc = "An integrated intelligence system module suitable for most hardsuits."
|
||||
icon_state = "IIS"
|
||||
toggleable = 1
|
||||
usable = 1
|
||||
disruptive = 0
|
||||
activates_on_touch = 1
|
||||
|
||||
engage_string = "Eject AI"
|
||||
activate_string = "Enable Dataspike"
|
||||
deactivate_string = "Disable Dataspike"
|
||||
|
||||
interface_name = "integrated intelligence system"
|
||||
interface_desc = "A socket that supports a range of artificial intelligence systems."
|
||||
|
||||
var/mob/integrated_ai // Direct reference to the actual mob held in the suit.
|
||||
var/obj/item/ai_card // Reference to the MMI, posibrain, intellicard or pAI card previously holding the AI.
|
||||
var/obj/item/ai_verbs/verb_holder
|
||||
|
||||
/mob
|
||||
var/get_rig_stats = 0
|
||||
|
||||
/obj/item/rig_module/ai_container/process()
|
||||
if(integrated_ai)
|
||||
var/obj/item/rig/rig = get_rig()
|
||||
if(rig && rig.ai_override_enabled)
|
||||
integrated_ai.get_rig_stats = 1
|
||||
else
|
||||
integrated_ai.get_rig_stats = 0
|
||||
|
||||
/obj/item/rig_module/ai_container/proc/update_verb_holder()
|
||||
if(!verb_holder)
|
||||
verb_holder = new(src)
|
||||
if(integrated_ai)
|
||||
verb_holder.forceMove(integrated_ai)
|
||||
else
|
||||
verb_holder.forceMove(src)
|
||||
|
||||
/obj/item/rig_module/ai_container/accepts_item(var/obj/item/input_device, var/mob/living/user)
|
||||
|
||||
// Check if there's actually an AI to deal with.
|
||||
var/mob/living/silicon/ai/target_ai
|
||||
if(istype(input_device, /mob/living/silicon/ai))
|
||||
target_ai = input_device
|
||||
else
|
||||
target_ai = locate(/mob/living/silicon/ai) in input_device.contents
|
||||
|
||||
var/obj/item/aicard/card = ai_card
|
||||
|
||||
// Downloading from/loading to a terminal.
|
||||
if(istype(input_device,/obj/machinery/computer/aifixer) || istype(input_device,/mob/living/silicon/ai) || istype(input_device,/obj/structure/AIcore/deactivated))
|
||||
|
||||
// If we're stealing an AI, make sure we have a card for it.
|
||||
if(!card)
|
||||
card = new /obj/item/aicard(src)
|
||||
|
||||
// Terminal interaction only works with an intellicarded AI.
|
||||
if(!istype(card))
|
||||
return 0
|
||||
|
||||
// Since we've explicitly checked for three types, this should be safe.
|
||||
card.afterattack(input_device, user, 1)
|
||||
|
||||
// If the transfer failed we can delete the card.
|
||||
if(locate(/mob/living/silicon/ai) in card)
|
||||
ai_card = card
|
||||
integrated_ai = locate(/mob/living/silicon/ai) in card
|
||||
else
|
||||
eject_ai()
|
||||
update_verb_holder()
|
||||
return 1
|
||||
|
||||
if(istype(input_device,/obj/item/aicard))
|
||||
// We are carding the AI in our suit.
|
||||
if(integrated_ai)
|
||||
var/obj/item/aicard/ext_card = input_device
|
||||
ext_card.afterattack(integrated_ai, user, 1)
|
||||
// If the transfer was successful, we can clear out our vars.
|
||||
if(integrated_ai.loc != src)
|
||||
integrated_ai = null
|
||||
eject_ai()
|
||||
else
|
||||
// You're using an empty card on an empty suit, idiot.
|
||||
if(!target_ai)
|
||||
return 0
|
||||
integrate_ai(input_device,user)
|
||||
return 1
|
||||
|
||||
// Okay, it wasn't a terminal being touched, check for all the simple insertions.
|
||||
if(input_device.type in list(/obj/item/paicard, /obj/item/mmi, /obj/item/mmi/robotic_brain))
|
||||
if(integrated_ai)
|
||||
integrated_ai.attackby(input_device,user)
|
||||
// If the transfer was successful, we can clear out our vars.
|
||||
if(integrated_ai.loc != src)
|
||||
integrated_ai = null
|
||||
eject_ai()
|
||||
else
|
||||
integrate_ai(input_device,user)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/ai_container/engage(atom/target)
|
||||
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
|
||||
if(!target)
|
||||
if(ai_card)
|
||||
if(istype(ai_card,/obj/item/aicard))
|
||||
ai_card.ui_interact(H, state = GLOB.deep_inventory_state)
|
||||
else
|
||||
eject_ai(H)
|
||||
update_verb_holder()
|
||||
return 1
|
||||
|
||||
if(accepts_item(target,H))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/ai_container/removed()
|
||||
eject_ai()
|
||||
..()
|
||||
|
||||
/obj/item/rig_module/ai_container/proc/eject_ai(var/mob/user)
|
||||
|
||||
if(ai_card)
|
||||
if(istype(ai_card, /obj/item/aicard))
|
||||
if(integrated_ai && !integrated_ai.stat)
|
||||
if(user)
|
||||
to_chat(user, "<span class='danger'>You cannot eject your currently stored AI. Purge it manually.</span>")
|
||||
return 0
|
||||
to_chat(user, "<span class='danger'>You purge the remaining scraps of data from your previous AI, freeing it for use.</span>")
|
||||
QDEL_NULL(integrated_ai)
|
||||
QDEL_NULL(ai_card)
|
||||
else if(user)
|
||||
user.put_in_hands(ai_card)
|
||||
else
|
||||
ai_card.forceMove(get_turf(src))
|
||||
ai_card = null
|
||||
integrated_ai = null
|
||||
update_verb_holder()
|
||||
|
||||
|
||||
|
||||
/obj/item/rig_module/ai_container/proc/integrate_ai(var/obj/item/ai,var/mob/user)
|
||||
if(!ai) return
|
||||
|
||||
// The ONLY THING all the different AI systems have in common is that they all store the mob inside an item.
|
||||
var/mob/living/ai_mob = locate(/mob/living) in ai.contents
|
||||
if(ai_mob)
|
||||
if(ai_mob.key && ai_mob.client)
|
||||
if(istype(ai, /obj/item/aicard))
|
||||
var/mob/living/silicon/ai/ROBUTT = ai_mob
|
||||
if(istype(ROBUTT))
|
||||
if(!ai_card)
|
||||
ai_card = new /obj/item/aicard(src)
|
||||
|
||||
var/obj/item/aicard/source_card = ai
|
||||
var/obj/item/aicard/target_card = ai_card
|
||||
if(istype(source_card) && istype(target_card))
|
||||
ROBUTT.forceMove(target_card)
|
||||
ROBUTT.aiRestorePowerRoutine = 0//So the AI initially has power.
|
||||
ROBUTT.control_disabled = 1//Can't control things remotely if you're stuck in a card!
|
||||
ROBUTT.aiRadio.disabledAi = 1 //No talking on the built-in radio for you either!
|
||||
source_card.update_state()
|
||||
target_card.update_state()
|
||||
else
|
||||
return 0
|
||||
|
||||
else
|
||||
user.unEquip(ai)
|
||||
ai.forceMove(src)
|
||||
ai_card = ai
|
||||
to_chat(ai_mob, "<font color='blue'>You have been transferred to \the [holder]'s [src].</font>")
|
||||
to_chat(user, "<font color='blue'>You load [ai_mob] into \the [holder]'s [src].</font>")
|
||||
|
||||
integrated_ai = ai_mob
|
||||
|
||||
if(!(locate(integrated_ai) in ai_card))
|
||||
integrated_ai = null
|
||||
eject_ai()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There is no active AI within \the [ai].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There is no active AI within \the [ai].</span>")
|
||||
update_verb_holder()
|
||||
|
||||
/obj/item/rig_module/datajack
|
||||
|
||||
name = "datajack module"
|
||||
desc = "A simple induction datalink module."
|
||||
icon_state = "datajack"
|
||||
toggleable = 1
|
||||
activates_on_touch = 1
|
||||
usable = 0
|
||||
|
||||
activate_string = "Enable Datajack"
|
||||
deactivate_string = "Disable Datajack"
|
||||
|
||||
interface_name = "contact datajack"
|
||||
interface_desc = "An induction-powered high-throughput datalink suitable for hacking encrypted networks."
|
||||
var/list/stored_research
|
||||
|
||||
/obj/item/rig_module/datajack/New()
|
||||
..()
|
||||
stored_research = list()
|
||||
|
||||
/obj/item/rig_module/datajack/engage(atom/target)
|
||||
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
if(target)
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
if(!accepts_item(target,H))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/datajack/accepts_item(var/obj/item/input_device, var/mob/living/user)
|
||||
|
||||
if(istype(input_device,/obj/item/disk/tech_disk))
|
||||
to_chat(user, "You slot the disk into [src].")
|
||||
var/obj/item/disk/tech_disk/disk = input_device
|
||||
if(disk.stored)
|
||||
if(load_data(disk.stored))
|
||||
to_chat(user, "<font color='blue'>Download successful; disk erased.</font>")
|
||||
disk.stored = null
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The disk is corrupt. It is useless to you.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The disk is blank. It is useless to you.</span>")
|
||||
return 1
|
||||
|
||||
// I fucking hate R&D code. This typecheck spam would be totally unnecessary in a sane setup.
|
||||
else if(istype(input_device,/obj/machinery))
|
||||
var/datum/research/incoming_files
|
||||
if(istype(input_device,/obj/machinery/computer/rdconsole))
|
||||
var/obj/machinery/computer/rdconsole/input_machine = input_device
|
||||
incoming_files = input_machine.files
|
||||
else if(istype(input_device,/obj/machinery/r_n_d/server))
|
||||
var/obj/machinery/r_n_d/server/input_machine = input_device
|
||||
incoming_files = input_machine.files
|
||||
else if(istype(input_device,/obj/machinery/mecha_part_fabricator))
|
||||
var/obj/machinery/mecha_part_fabricator/input_machine = input_device
|
||||
incoming_files = input_machine.files
|
||||
|
||||
if(!incoming_files || !incoming_files.known_tech || !incoming_files.known_tech.len)
|
||||
to_chat(user, "<span class='warning'>Memory failure. There is nothing accessible stored on this terminal.</span>")
|
||||
else
|
||||
// Maybe consider a way to drop all your data into a target repo in the future.
|
||||
if(load_data(incoming_files.known_tech))
|
||||
to_chat(user, "<font color='blue'>Download successful; local and remote repositories synchronized.</font>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Scan complete. There is nothing useful stored on this terminal.</span>")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/datajack/proc/load_data(var/incoming_data)
|
||||
|
||||
if(islist(incoming_data))
|
||||
for(var/entry in incoming_data)
|
||||
load_data(entry)
|
||||
return 1
|
||||
|
||||
if(istype(incoming_data, /datum/tech))
|
||||
var/data_found
|
||||
var/datum/tech/new_data = incoming_data
|
||||
for(var/datum/tech/current_data in stored_research)
|
||||
if(current_data.id == new_data.id)
|
||||
data_found = 1
|
||||
if(current_data.level < new_data.level)
|
||||
current_data.level = new_data.level
|
||||
break
|
||||
if(!data_found)
|
||||
stored_research += incoming_data
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/electrowarfare_suite
|
||||
|
||||
name = "electrowarfare module"
|
||||
desc = "A bewilderingly complex bundle of fiber optics and chips."
|
||||
icon_state = "ewar"
|
||||
toggleable = 1
|
||||
usable = 0
|
||||
|
||||
activate_string = "Enable Countermeasures"
|
||||
deactivate_string = "Disable Countermeasures"
|
||||
|
||||
interface_name = "electrowarfare system"
|
||||
interface_desc = "An active counter-electronic warfare suite that disrupts AI tracking."
|
||||
|
||||
/obj/item/rig_module/electrowarfare_suite/activate()
|
||||
|
||||
if(!..())
|
||||
return
|
||||
|
||||
// This is not the best way to handle this, but I don't want it to mess with ling camo
|
||||
var/mob/living/M = holder.wearer
|
||||
M.digitalcamo++
|
||||
|
||||
/obj/item/rig_module/electrowarfare_suite/deactivate()
|
||||
|
||||
if(!..())
|
||||
return
|
||||
|
||||
var/mob/living/M = holder.wearer
|
||||
M.digitalcamo = max(0,(M.digitalcamo-1))
|
||||
|
||||
/* //Not easily compatible with our current powernet, and is
|
||||
/obj/item/rig_module/power_sink // quite stupid anyways, iyam
|
||||
|
||||
name = "hardsuit power sink"
|
||||
desc = "An heavy-duty power sink."
|
||||
icon_state = "powersink"
|
||||
toggleable = 1
|
||||
activates_on_touch = 1
|
||||
disruptive = 0
|
||||
|
||||
activate_string = "Enable Power Sink"
|
||||
deactivate_string = "Disable Power Sink"
|
||||
|
||||
interface_name = "niling d-sink"
|
||||
interface_desc = "Colloquially known as a power siphon, this module drains power through the suit hands into the suit battery."
|
||||
|
||||
var/atom/interfaced_with // Currently draining power from this device.
|
||||
var/total_power_drained = 0
|
||||
var/drain_loc
|
||||
|
||||
/obj/item/rig_module/power_sink/deactivate()
|
||||
|
||||
if(interfaced_with)
|
||||
if(holder && holder.wearer)
|
||||
to_chat(holder.wearer, "<span class = 'warning'>Your power sink retracts as the module deactivates.</span>")
|
||||
drain_complete()
|
||||
interfaced_with = null
|
||||
total_power_drained = 0
|
||||
return ..()
|
||||
|
||||
/obj/item/rig_module/power_sink/activate()
|
||||
interfaced_with = null
|
||||
total_power_drained = 0
|
||||
return ..()
|
||||
|
||||
/obj/item/rig_module/power_sink/engage(atom/target)
|
||||
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
//Target wasn't supplied or we're already draining.
|
||||
if(interfaced_with)
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
return 1
|
||||
|
||||
// Are we close enough?
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
if(!target.Adjacent(H))
|
||||
return 0
|
||||
|
||||
// Is it a valid power source?
|
||||
if(target.drain_power(1) <= 0)
|
||||
return 0
|
||||
|
||||
to_chat(H, "<span class = 'danger'>You begin draining power from [target]!</span>")
|
||||
interfaced_with = target
|
||||
drain_loc = interfaced_with.loc
|
||||
|
||||
holder.spark_system.start()
|
||||
playsound(H.loc, 'sound/effects/sparks2.ogg', 50, 1)
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/power_sink/accepts_item(var/obj/item/input_device, var/mob/living/user)
|
||||
var/can_drain = input_device.drain_power(1)
|
||||
if(can_drain > 0)
|
||||
engage(input_device)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/rig_module/power_sink/process()
|
||||
|
||||
if(!interfaced_with)
|
||||
return ..()
|
||||
|
||||
var/mob/living/carbon/human/H
|
||||
if(holder && holder.wearer)
|
||||
H = holder.wearer
|
||||
|
||||
if(!H || !istype(H))
|
||||
return 0
|
||||
|
||||
holder.spark_system.start()
|
||||
playsound(H.loc, 'sound/effects/sparks2.ogg', 50, 1)
|
||||
|
||||
if(!holder.cell)
|
||||
to_chat(H, "<span class = 'danger'>Your power sink flashes an error; there is no cell in your rig.</span>")
|
||||
drain_complete(H)
|
||||
return
|
||||
|
||||
if(!interfaced_with || !interfaced_with.Adjacent(H) || !(interfaced_with.loc == drain_loc))
|
||||
to_chat(H, "<span class = 'warning'>Your power sink retracts into its casing.</span>")
|
||||
drain_complete(H)
|
||||
return
|
||||
|
||||
if(holder.cell.fully_charged())
|
||||
to_chat(H, "<span class = 'warning'>Your power sink flashes an amber light; your rig cell is full.</span>")
|
||||
drain_complete(H)
|
||||
return
|
||||
|
||||
// Attempts to drain up to 40kW, determines this value from remaining cell capacity to ensure we don't drain too much..
|
||||
var/to_drain = min(40000, ((holder.cell.maxcharge - holder.cell.charge) / CELLRATE))
|
||||
var/target_drained = interfaced_with.drain_power(0,0,to_drain)
|
||||
if(target_drained <= 0)
|
||||
to_chat(H, "<span class = 'danger'>Your power sink flashes a red light; there is no power left in [interfaced_with].</span>")
|
||||
drain_complete(H)
|
||||
return
|
||||
|
||||
holder.cell.give(target_drained * CELLRATE)
|
||||
total_power_drained += target_drained
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/power_sink/proc/drain_complete(var/mob/living/M)
|
||||
|
||||
if(!interfaced_with)
|
||||
to_chat(if(M) M, "<font color='blue'><b>Total power drained:</b> [round(total_power_drained/1000)]kJ.</font>")
|
||||
else
|
||||
to_chat(if(M) M, "<font color='blue'><b>Total power drained from [interfaced_with]:</b> [round(total_power_drained/1000)]kJ.</font>")
|
||||
interfaced_with.drain_power(0,1,0) // Damage the victim.
|
||||
|
||||
drain_loc = null
|
||||
interfaced_with = null
|
||||
total_power_drained = 0*/
|
||||
|
||||
/*
|
||||
//Maybe make this use power when active or something
|
||||
/obj/item/rig_module/emp_shielding
|
||||
name = "\improper EMP dissipation module"
|
||||
desc = "A bewilderingly complex bundle of fiber optics and chips."
|
||||
toggleable = 1
|
||||
usable = 0
|
||||
|
||||
activate_string = "Enable active EMP shielding"
|
||||
deactivate_string = "Disable active EMP shielding"
|
||||
|
||||
interface_name = "active EMP shielding system"
|
||||
interface_desc = "A highly experimental system that augments the hardsuit's existing EM shielding."
|
||||
var/protection_amount = 20
|
||||
|
||||
/obj/item/rig_module/emp_shielding/activate()
|
||||
if(!..())
|
||||
return
|
||||
|
||||
holder.emp_protection += protection_amount
|
||||
|
||||
/obj/item/rig_module/emp_shielding/deactivate()
|
||||
if(!..())
|
||||
return
|
||||
|
||||
holder.emp_protection = max(0,(holder.emp_protection - protection_amount))
|
||||
*/
|
||||
@@ -1,50 +0,0 @@
|
||||
|
||||
/obj/item/rig_module/handheld
|
||||
name = "mounted device"
|
||||
desc = "Some kind of hardsuit extension."
|
||||
usable = 0
|
||||
selectable = 0
|
||||
toggleable = 1
|
||||
disruptive = 0
|
||||
activate_string = "Deploy"
|
||||
deactivate_string = "Retract"
|
||||
|
||||
var/device_type
|
||||
var/obj/item
|
||||
|
||||
/obj/item/rig_module/handheld/activate()
|
||||
if(!..())
|
||||
return
|
||||
|
||||
if(!holder.wearer.put_in_hands(device))
|
||||
to_chat(holder.wearer, "<span class='notice'>You need a free hand to hold \the [device].</span>")
|
||||
active = 0
|
||||
return
|
||||
|
||||
to_chat(holder.wearer, "<span class='notice'>You deploy \the [device].</span>")
|
||||
|
||||
|
||||
/obj/item/rig_module/handheld/deactivate()
|
||||
if(!..())
|
||||
return
|
||||
if(ismob(device.loc)) //Better check for the holder, instead of assuming the rigwearer has it.
|
||||
var/mob/M = device.loc //Helps in case the code fails to keep the module in one place, this should still return it.
|
||||
M.unEquip(device, 1)
|
||||
|
||||
device.loc = src
|
||||
to_chat(holder.wearer, "<span class='notice'>You retract \the [device].</span>")
|
||||
|
||||
/obj/item/rig_module/handheld/New()
|
||||
..()
|
||||
if(device_type)
|
||||
device = new device_type(src)
|
||||
device.flags |= NODROP //We don't want to drop it while it's active/inhand.
|
||||
activate_string += " [device]"
|
||||
deactivate_string += " [device]"
|
||||
|
||||
/obj/item/rig_module/handheld/horn
|
||||
name = "mounted bikehorn"
|
||||
desc = "For tactical honking"
|
||||
interface_name = "mounted bikehorn"
|
||||
interface_desc = "Honks"
|
||||
device_type = /obj/item/bikehorn
|
||||
@@ -1,330 +0,0 @@
|
||||
/*
|
||||
* Rigsuit upgrades/abilities.
|
||||
*/
|
||||
|
||||
/datum/rig_charge
|
||||
var/short_name = "undef"
|
||||
var/display_name = "undefined"
|
||||
var/product_type = "undefined"
|
||||
var/charges = 0
|
||||
|
||||
/obj/item/rig_module
|
||||
name = "hardsuit upgrade"
|
||||
desc = "It looks pretty sciency."
|
||||
icon = 'icons/obj/rig_modules.dmi'
|
||||
icon_state = "module"
|
||||
|
||||
toolspeed = 1
|
||||
|
||||
var/damage = 0
|
||||
var/obj/item/rig/holder
|
||||
|
||||
var/module_cooldown = 10
|
||||
var/next_use = 0
|
||||
|
||||
var/toggleable // Set to 1 for the device to show up as an active effect.
|
||||
var/usable // Set to 1 for the device to have an on-use effect.
|
||||
var/selectable // Set to 1 to be able to assign the device as primary system.
|
||||
var/redundant // Set to 1 to ignore duplicate module checking when installing.
|
||||
var/permanent // If set, the module can't be removed.
|
||||
var/disruptive = 1 // Can disrupt by other effects.
|
||||
var/activates_on_touch // If set, unarmed attacks will call engage() on the target.
|
||||
|
||||
var/active // Basic module status
|
||||
var/disruptable // Will deactivate if some other powers are used.
|
||||
|
||||
var/use_power_cost = 0 // Power used when single-use ability called.
|
||||
var/active_power_cost = 0 // Power used when turned on.
|
||||
var/passive_power_cost = 0 // Power used when turned off.
|
||||
|
||||
var/list/charges // Associative list of charge types and remaining numbers.
|
||||
var/charge_selected // Currently selected option used for charge dispensing.
|
||||
|
||||
// Icons.
|
||||
var/suit_overlay
|
||||
var/suit_overlay_active // If set, drawn over icon and mob when effect is active.
|
||||
var/suit_overlay_inactive // As above, inactive.
|
||||
var/suit_overlay_used // As above, when engaged.
|
||||
|
||||
//Display fluff
|
||||
var/interface_name = "hardsuit upgrade"
|
||||
var/interface_desc = "A generic hardsuit upgrade."
|
||||
var/engage_string = "Engage"
|
||||
var/activate_string = "Activate"
|
||||
var/deactivate_string = "Deactivate"
|
||||
|
||||
var/list/stat_rig_module/stat_modules = new()
|
||||
|
||||
/obj/item/rig_module/examine(mob/user)
|
||||
. = ..()
|
||||
switch(damage)
|
||||
if(0)
|
||||
. += "It is undamaged."
|
||||
if(1)
|
||||
. += "It is badly damaged."
|
||||
if(2)
|
||||
. += "It is almost completely destroyed."
|
||||
|
||||
/obj/item/rig_module/attackby(obj/item/W as obj, mob/user as mob)
|
||||
|
||||
if(istype(W,/obj/item/stack/nanopaste))
|
||||
|
||||
if(damage == 0)
|
||||
to_chat(user, "There is no damage to mend.")
|
||||
return
|
||||
|
||||
to_chat(user, "You start mending the damaged portions of \the [src]...")
|
||||
|
||||
if(!do_after(user, 30 * W.toolspeed, target = src) || !W || !src)
|
||||
return
|
||||
|
||||
var/obj/item/stack/nanopaste/paste = W
|
||||
damage = 0
|
||||
to_chat(user, "You mend the damage to [src] with [W].")
|
||||
paste.use(1)
|
||||
return
|
||||
|
||||
else if(istype(W,/obj/item/stack/cable_coil))
|
||||
|
||||
switch(damage)
|
||||
if(0)
|
||||
to_chat(user, "There is no damage to mend.")
|
||||
return
|
||||
if(2)
|
||||
to_chat(user, "There is no damage that you are capable of mending with such crude tools.")
|
||||
return
|
||||
|
||||
var/obj/item/stack/cable_coil/cable = W
|
||||
if(!cable.amount >= 5)
|
||||
to_chat(user, "You need five units of cable to repair \the [src].")
|
||||
return
|
||||
|
||||
to_chat(user, "You start mending the damaged portions of \the [src]...")
|
||||
if(!do_after(user, 30 * W.toolspeed, target = src) || !W || !src)
|
||||
return
|
||||
|
||||
damage = 1
|
||||
to_chat(user, "You mend some of damage to [src] with [W], but you will need more advanced tools to fix it completely.")
|
||||
cable.use(5)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/rig_module/New()
|
||||
..()
|
||||
if(suit_overlay_inactive)
|
||||
suit_overlay = suit_overlay_inactive
|
||||
|
||||
if(charges && charges.len)
|
||||
var/list/processed_charges = list()
|
||||
for(var/list/charge in charges)
|
||||
var/datum/rig_charge/charge_dat = new
|
||||
|
||||
charge_dat.short_name = charge[1]
|
||||
charge_dat.display_name = charge[2]
|
||||
charge_dat.product_type = charge[3]
|
||||
charge_dat.charges = charge[4]
|
||||
|
||||
if(!charge_selected) charge_selected = charge_dat.short_name
|
||||
processed_charges[charge_dat.short_name] = charge_dat
|
||||
|
||||
charges = processed_charges
|
||||
|
||||
stat_modules += new/stat_rig_module/activate(src)
|
||||
stat_modules += new/stat_rig_module/deactivate(src)
|
||||
stat_modules += new/stat_rig_module/engage(src)
|
||||
stat_modules += new/stat_rig_module/select(src)
|
||||
stat_modules += new/stat_rig_module/charge(src)
|
||||
|
||||
// Called when the module is installed into a suit.
|
||||
/obj/item/rig_module/proc/installed(var/obj/item/rig/new_holder)
|
||||
holder = new_holder
|
||||
return
|
||||
|
||||
//Proc for one-use abilities like teleport.
|
||||
/obj/item/rig_module/proc/engage()
|
||||
|
||||
if(damage >= 2)
|
||||
to_chat(usr, "<span class='warning'>The [interface_name] is damaged beyond use!</span>")
|
||||
return 0
|
||||
|
||||
if(world.time < next_use)
|
||||
to_chat(usr, "<span class='warning'>You cannot use the [interface_name] again so soon.</span>")
|
||||
return 0
|
||||
|
||||
if(!holder || (!(holder.flags & NODROP)))
|
||||
to_chat(usr, "<span class='warning'>The suit is not initialized.</span>")
|
||||
return 0
|
||||
|
||||
if(usr.lying || usr.stat || usr.stunned || usr.paralysis || usr.IsWeakened())
|
||||
to_chat(usr, "<span class='warning'>You cannot use the suit in this state.</span>")
|
||||
return 0
|
||||
|
||||
if(holder.wearer && holder.wearer.lying)
|
||||
to_chat(usr, "<span class='warning'>The suit cannot function while the wearer is prone.</span>")
|
||||
return 0
|
||||
|
||||
if(holder.security_check_enabled && !holder.check_suit_access(usr))
|
||||
to_chat(usr, "<span class='danger'>Access denied.</span>")
|
||||
return 0
|
||||
|
||||
if(!holder.check_power_cost(usr, use_power_cost, 0, src, (istype(usr,/mob/living/silicon ? 1 : 0) ) ) )
|
||||
return 0
|
||||
|
||||
next_use = world.time + module_cooldown
|
||||
|
||||
return 1
|
||||
|
||||
// Proc for toggling on active abilities.
|
||||
/obj/item/rig_module/proc/activate()
|
||||
|
||||
if(active || !engage())
|
||||
return 0
|
||||
|
||||
active = 1
|
||||
|
||||
spawn(1)
|
||||
if(suit_overlay_active)
|
||||
suit_overlay = suit_overlay_active
|
||||
else
|
||||
suit_overlay = null
|
||||
holder.update_icon()
|
||||
|
||||
return 1
|
||||
|
||||
// Proc for toggling off active abilities.
|
||||
/obj/item/rig_module/proc/deactivate()
|
||||
|
||||
if(!active)
|
||||
return 0
|
||||
|
||||
active = 0
|
||||
|
||||
spawn(1)
|
||||
if(suit_overlay_inactive)
|
||||
suit_overlay = suit_overlay_inactive
|
||||
else
|
||||
suit_overlay = null
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
|
||||
return 1
|
||||
|
||||
// Called when the module is uninstalled from a suit.
|
||||
/obj/item/rig_module/proc/removed()
|
||||
deactivate()
|
||||
holder = null
|
||||
return
|
||||
|
||||
// Called by the hardsuit each rig process tick.
|
||||
/obj/item/rig_module/process()
|
||||
if(active)
|
||||
return active_power_cost
|
||||
else
|
||||
return passive_power_cost
|
||||
|
||||
// Called by holder rigsuit attackby()
|
||||
// Checks if an item is usable with this module and handles it if it is
|
||||
/obj/item/rig_module/proc/accepts_item(var/obj/item/input_device)
|
||||
return 0
|
||||
|
||||
/mob/proc/SetupStat(var/obj/item/rig/R)
|
||||
if(R && (R.flags & NODROP) && R.installed_modules.len && statpanel("Hardsuit Modules"))
|
||||
var/cell_status = R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "ERROR"
|
||||
stat("Suit charge", cell_status)
|
||||
for(var/obj/item/rig_module/module in R.installed_modules)
|
||||
{
|
||||
for(var/stat_rig_module/SRM in module.stat_modules)
|
||||
if(SRM.CanUse())
|
||||
stat(SRM.module.interface_name,SRM)
|
||||
}
|
||||
|
||||
/stat_rig_module
|
||||
parent_type = /atom/movable
|
||||
var/module_mode = ""
|
||||
var/obj/item/rig_module/module
|
||||
|
||||
/stat_rig_module/New(var/obj/item/rig_module/module)
|
||||
..()
|
||||
src.module = module
|
||||
|
||||
/stat_rig_module/proc/AddHref(var/list/href_list)
|
||||
return
|
||||
|
||||
/stat_rig_module/proc/CanUse()
|
||||
return 0
|
||||
|
||||
/stat_rig_module/Click()
|
||||
if(CanUse())
|
||||
var/list/href_list = list(
|
||||
"interact_module" = module.holder.installed_modules.Find(module),
|
||||
"module_mode" = module_mode
|
||||
)
|
||||
AddHref(href_list)
|
||||
module.holder.Topic(usr, href_list)
|
||||
|
||||
/stat_rig_module/DblClick()
|
||||
return Click()
|
||||
|
||||
/stat_rig_module/activate/New(var/obj/item/rig_module/module)
|
||||
..()
|
||||
name = module.activate_string
|
||||
if(module.active_power_cost)
|
||||
name += " ([module.active_power_cost*10]A)"
|
||||
module_mode = "activate"
|
||||
|
||||
/stat_rig_module/activate/CanUse()
|
||||
return module.toggleable && !module.active
|
||||
|
||||
/stat_rig_module/deactivate/New(var/obj/item/rig_module/module)
|
||||
..()
|
||||
name = module.deactivate_string
|
||||
// Show cost despite being 0, if it means changing from an active cost.
|
||||
if(module.active_power_cost || module.passive_power_cost)
|
||||
name += " ([module.passive_power_cost*10]P)"
|
||||
|
||||
module_mode = "deactivate"
|
||||
|
||||
/stat_rig_module/deactivate/CanUse()
|
||||
return module.toggleable && module.active
|
||||
|
||||
/stat_rig_module/engage/New(var/obj/item/rig_module/module)
|
||||
..()
|
||||
name = module.engage_string
|
||||
if(module.use_power_cost)
|
||||
name += " ([module.use_power_cost*10]E)"
|
||||
module_mode = "engage"
|
||||
|
||||
/stat_rig_module/engage/CanUse()
|
||||
return module.usable
|
||||
|
||||
/stat_rig_module/select/New()
|
||||
..()
|
||||
name = "Select"
|
||||
module_mode = "select"
|
||||
|
||||
/stat_rig_module/select/CanUse()
|
||||
if(module.selectable)
|
||||
name = module.holder.selected_module == module ? "Selected" : "Select"
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/stat_rig_module/charge/New()
|
||||
..()
|
||||
name = "Change Charge"
|
||||
module_mode = "select_charge_type"
|
||||
|
||||
/stat_rig_module/charge/AddHref(var/list/href_list)
|
||||
var/charge_index = module.charges.Find(module.charge_selected)
|
||||
if(!charge_index)
|
||||
charge_index = 0
|
||||
else
|
||||
charge_index = charge_index == module.charges.len ? 1 : charge_index+1
|
||||
|
||||
href_list["charge_type"] = module.charges[charge_index]
|
||||
|
||||
/stat_rig_module/charge/CanUse()
|
||||
if(module.charges && module.charges.len)
|
||||
var/datum/rig_charge/charge = module.charges[module.charge_selected]
|
||||
name = "[charge.display_name] ([charge.charges]C) - Change"
|
||||
return 1
|
||||
return 0
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* Contains
|
||||
* /obj/item/rig_module/stealth_field
|
||||
* /obj/item/rig_module/teleporter
|
||||
* /obj/item/rig_module/fabricator/energy_net
|
||||
* /obj/item/rig_module/self_destruct
|
||||
*/
|
||||
|
||||
/obj/item/rig_module/stealth_field
|
||||
|
||||
name = "active camouflage module"
|
||||
desc = "A robust hardsuit-integrated stealth module."
|
||||
icon_state = "cloak"
|
||||
|
||||
toggleable = 1
|
||||
disruptable = 1
|
||||
disruptive = 0
|
||||
|
||||
use_power_cost = 50
|
||||
active_power_cost = 10
|
||||
passive_power_cost = 0
|
||||
module_cooldown = 30
|
||||
|
||||
activate_string = "Enable Cloak"
|
||||
deactivate_string = "Disable Cloak"
|
||||
|
||||
interface_name = "integrated stealth system"
|
||||
interface_desc = "An integrated active camouflage system."
|
||||
|
||||
suit_overlay_active = "stealth_active"
|
||||
suit_overlay_inactive = "stealth_inactive"
|
||||
|
||||
/obj/item/rig_module/stealth_field/activate()
|
||||
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
|
||||
to_chat(H, "<font color='blue'><b>You are now invisible to normal detection.</b></font>")
|
||||
H.invisibility = INVISIBILITY_LEVEL_TWO
|
||||
|
||||
H.visible_message("[H.name] vanishes into thin air!",1)
|
||||
|
||||
/obj/item/rig_module/stealth_field/deactivate()
|
||||
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
|
||||
to_chat(H, "<span class='danger'>You are now visible.</span>")
|
||||
H.invisibility = 0
|
||||
|
||||
new /obj/effect/temp_visual/dir_setting/ninja(get_turf(H), H.dir)
|
||||
|
||||
for(var/mob/O in oviewers(H))
|
||||
O.show_message("[H.name] appears from thin air!",1)
|
||||
playsound(get_turf(H), 'sound/effects/stealthoff.ogg', 75, 1)
|
||||
|
||||
|
||||
/obj/item/rig_module/teleporter
|
||||
|
||||
name = "teleportation module"
|
||||
desc = "A complex, sleek-looking, hardsuit-integrated teleportation module."
|
||||
icon_state = "teleporter"
|
||||
use_power_cost = 40
|
||||
redundant = 1
|
||||
usable = 1
|
||||
selectable = 1
|
||||
|
||||
engage_string = "Emergency Leap"
|
||||
|
||||
interface_name = "VOID-shift phase projector"
|
||||
interface_desc = "An advanced teleportation system. It is capable of pinpoint precision or random leaps forward."
|
||||
|
||||
/obj/item/rig_module/teleporter/proc/phase_in(var/mob/M,var/turf/T)
|
||||
|
||||
if(!M || !T)
|
||||
return
|
||||
|
||||
holder.spark_system.start()
|
||||
playsound(T, 'sound/effects/phasein.ogg', 25, 1)
|
||||
playsound(T, 'sound/effects/sparks2.ogg', 50, 1)
|
||||
new /obj/effect/temp_visual/dir_setting/ninja/phase(T, M.dir)
|
||||
|
||||
/obj/item/rig_module/teleporter/proc/phase_out(var/mob/M,var/turf/T)
|
||||
|
||||
if(!M || !T)
|
||||
return
|
||||
|
||||
playsound(T, "sparks", 50, 1)
|
||||
new /obj/effect/temp_visual/dir_setting/ninja/phase/out(T, M.dir)
|
||||
|
||||
/obj/item/rig_module/teleporter/engage(var/atom/target, var/notify_ai)
|
||||
|
||||
if(!..()) return 0
|
||||
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
|
||||
if(!istype(H.loc, /turf))
|
||||
to_chat(H, "<span class='warning'>You cannot teleport out of your current location.</span>")
|
||||
return 0
|
||||
|
||||
var/turf/T
|
||||
if(target)
|
||||
T = get_turf(target)
|
||||
else
|
||||
T = get_teleport_loc(get_turf(H), H, rand(5, 9))
|
||||
|
||||
/*if(!T || T.density)
|
||||
to_chat(H, "<span class='warning'>You cannot teleport into solid walls.</span>")
|
||||
return 0*///Who the fuck cares? Ninjas in walls are cool.
|
||||
|
||||
if(!is_teleport_allowed(T.z))
|
||||
to_chat(H, "<span class='warning'>You cannot use your teleporter on this Z-level.</span>")
|
||||
return 0
|
||||
|
||||
phase_out(H,get_turf(H))
|
||||
H.forceMove(T)
|
||||
phase_in(H,get_turf(H))
|
||||
|
||||
for(var/obj/item/grab/G in H.contents)
|
||||
if(G.affecting)
|
||||
phase_out(G.affecting,get_turf(G.affecting))
|
||||
G.affecting.forceMove(locate(T.x+rand(-1,1),T.y+rand(-1,1),T.z))
|
||||
phase_in(G.affecting,get_turf(G.affecting))
|
||||
|
||||
return 1
|
||||
|
||||
/*
|
||||
/obj/item/rig_module/fabricator/energy_net
|
||||
|
||||
name = "net projector"
|
||||
desc = "Some kind of complex energy projector with a hardsuit mount."
|
||||
icon_state = "enet"
|
||||
|
||||
interface_name = "energy net launcher"
|
||||
interface_desc = "An advanced energy-patterning projector used to capture targets."
|
||||
|
||||
engage_string = "Fabricate Net"
|
||||
|
||||
fabrication_type = /obj/item/energy_net
|
||||
use_power_cost = 70
|
||||
|
||||
/obj/item/rig_module/fabricator/energy_net/engage(atom/target)
|
||||
|
||||
if(holder && holder.wearer)
|
||||
if(..(target) && target)
|
||||
holder.wearer.Beam(target,"n_beam",,10)
|
||||
return 1
|
||||
return 0*/
|
||||
|
||||
/obj/item/rig_module/self_destruct
|
||||
|
||||
name = "self-destruct module"
|
||||
desc = "Oh my God, Captain. A bomb."
|
||||
icon_state = "deadman"
|
||||
usable = 1
|
||||
active = 1
|
||||
permanent = 1
|
||||
|
||||
engage_string = "Detonate"
|
||||
|
||||
interface_name = "dead man's switch"
|
||||
interface_desc = "An integrated self-destruct module. When the wearer dies, so does the surrounding area. Do not press this button."
|
||||
|
||||
/obj/item/rig_module/self_destruct/activate()
|
||||
return
|
||||
|
||||
/obj/item/rig_module/self_destruct/deactivate()
|
||||
return
|
||||
|
||||
/obj/item/rig_module/self_destruct/process()
|
||||
|
||||
// Not being worn, leave it alone.
|
||||
if(!holder || !holder.wearer || !holder.wearer.wear_suit == holder)
|
||||
return 0
|
||||
|
||||
//OH SHIT.
|
||||
if(holder.wearer.stat == 2)
|
||||
engage()
|
||||
|
||||
/obj/item/rig_module/self_destruct/engage()
|
||||
explosion(get_turf(src), 1, 2, 4, 5)
|
||||
if(holder && holder.wearer)
|
||||
holder.wearer.unEquip(src)
|
||||
qdel(holder)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/rig_module/self_destruct/small/engage()
|
||||
explosion(get_turf(src), 0, 0, 3, 4)
|
||||
if(holder && holder.wearer)
|
||||
holder.wearer.unEquip(src)
|
||||
qdel(holder)
|
||||
qdel(src)
|
||||
@@ -1,476 +0,0 @@
|
||||
/* Contains:
|
||||
* /obj/item/rig_module/device
|
||||
* /obj/item/rig_module/device/plasmacutter
|
||||
* /obj/item/rig_module/device/healthscanner
|
||||
* /obj/item/rig_module/device/drill
|
||||
* /obj/item/rig_module/device/orescanner
|
||||
* /obj/item/rig_module/device/rcd
|
||||
* /obj/item/rig_module/device/anomaly_scanner
|
||||
* /obj/item/rig_module/maneuvering_jets
|
||||
* /obj/item/rig_module/foam_sprayer
|
||||
* /obj/item/rig_module/device/broadcaster
|
||||
* /obj/item/rig_module/chem_dispenser
|
||||
* /obj/item/rig_module/chem_dispenser/injector
|
||||
* /obj/item/rig_module/voice
|
||||
* /obj/item/rig_module/device/paperdispenser
|
||||
* /obj/item/rig_module/device/pen
|
||||
* /obj/item/rig_module/device/stamp
|
||||
*/
|
||||
|
||||
/obj/item/rig_module/device
|
||||
name = "mounted device"
|
||||
desc = "Some kind of hardsuit mount."
|
||||
usable = 0
|
||||
selectable = 1
|
||||
toggleable = 0
|
||||
disruptive = 0
|
||||
|
||||
var/device_type
|
||||
var/obj/item/device
|
||||
|
||||
/obj/item/rig_module/device/plasmacutter
|
||||
name = "hardsuit plasma cutter"
|
||||
desc = "A lethal-looking industrial cutter."
|
||||
icon_state = "plasmacutter"
|
||||
interface_name = "plasma cutter"
|
||||
interface_desc = "A self-sustaining plasma arc capable of cutting through walls."
|
||||
suit_overlay_active = "plasmacutter"
|
||||
suit_overlay_inactive = "plasmacutter"
|
||||
|
||||
device_type = /obj/item/gun/energy/plasmacutter
|
||||
|
||||
/obj/item/rig_module/device/healthscanner
|
||||
name = "health scanner module"
|
||||
desc = "A hardsuit-mounted health scanner."
|
||||
icon_state = "scanner"
|
||||
interface_name = "health scanner"
|
||||
interface_desc = "Shows an informative health readout when used on a subject."
|
||||
|
||||
device_type = /obj/item/healthanalyzer
|
||||
|
||||
/obj/item/rig_module/device/drill
|
||||
name = "hardsuit drill mount"
|
||||
desc = "A very heavy diamond-tipped drill."
|
||||
icon_state = "drill"
|
||||
interface_name = "mounted drill"
|
||||
interface_desc = "A diamond-tipped industrial drill."
|
||||
suit_overlay_active = "mounted-drill"
|
||||
suit_overlay_inactive = "mounted-drill"
|
||||
device_type = /obj/item/pickaxe/drill/diamonddrill
|
||||
|
||||
/obj/item/rig_module/device/orescanner
|
||||
name = "ore scanner module"
|
||||
desc = "A clunky old ore scanner."
|
||||
icon_state = "scanner"
|
||||
interface_name = "ore detector"
|
||||
interface_desc = "A sonar system for detecting large masses of ore."
|
||||
engage_string = "Begin Scan"
|
||||
usable = 1
|
||||
selectable = 0
|
||||
device_type = /obj/item/mining_scanner
|
||||
/*
|
||||
/obj/item/rig_module/device/rcd
|
||||
name = "RCD mount"
|
||||
desc = "A cell-powered rapid construction device for a hardsuit."
|
||||
icon_state = "rcd"
|
||||
interface_name = "mounted RCD"
|
||||
interface_desc = "A device for building or removing walls. Cell-powered."
|
||||
usable = 1
|
||||
engage_string = "Configure RCD"
|
||||
|
||||
device_type = /obj/item/rcd/mounted
|
||||
*/
|
||||
/obj/item/rig_module/device/New()
|
||||
..()
|
||||
if(device_type)
|
||||
device = new device_type(src)
|
||||
device.flags |= ABSTRACT //Abstract in the sense that it's not an item that stands alone, but rather is just there to let the module act like it.
|
||||
|
||||
/obj/item/rig_module/device/engage(atom/target)
|
||||
if(!..() || !device)
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
device.attack_self(holder.wearer)
|
||||
return 1
|
||||
|
||||
var/turf/T = get_turf(target)
|
||||
if(istype(T) && !T.Adjacent(get_turf(src)))
|
||||
return 0
|
||||
|
||||
var/resolved = target.attackby(device,holder.wearer)
|
||||
if(!resolved && device && target)
|
||||
device.afterattack(target,holder.wearer,1)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
/obj/item/rig_module/chem_dispenser
|
||||
name = "mounted chemical dispenser"
|
||||
desc = "A complex web of tubing and needles suitable for hardsuit use."
|
||||
icon_state = "injector"
|
||||
usable = 1
|
||||
selectable = 0
|
||||
toggleable = 0
|
||||
disruptive = 0
|
||||
|
||||
engage_string = "Inject"
|
||||
|
||||
interface_name = "integrated chemical dispenser"
|
||||
interface_desc = "Dispenses loaded chemicals directly into the wearer's bloodstream."
|
||||
|
||||
charges = list(
|
||||
list("saline-glucose", "salglu_solution", 0, 80),
|
||||
list("salicylic acid", "sal_acid", 0, 80),
|
||||
list("salbutamol", "salbutamol", 0, 80),
|
||||
list("antibiotics", "spaceacillin", 0, 80),
|
||||
list("charcoal", "charcoal", 0, 80),
|
||||
list("nutrients", "nutriment", 0, 80),
|
||||
list("potasssium iodide","potass_iodide", 0, 80),
|
||||
list("radium", "radium", 0, 80)
|
||||
)
|
||||
|
||||
var/max_reagent_volume = 80 //Used when refilling.
|
||||
|
||||
/obj/item/rig_module/chem_dispenser/ninja
|
||||
interface_desc = "Dispenses loaded chemicals directly into the wearer's bloodstream. This variant is made to be extremely light and flexible."
|
||||
|
||||
//just over a syringe worth of each. Want more? Go refill. Gives the ninja another reason to have to show their face.
|
||||
charges = list(
|
||||
list("saline-glucose", "salglu_solution", 0, 20),
|
||||
list("salicylic acid", "sal_acid", 0, 20),
|
||||
list("salbutamol", "salbutamol", 0, 20),
|
||||
list("antibiotics", "spaceacillin", 0, 20),
|
||||
list("charcoal", "charcoal", 0, 20),
|
||||
list("nutrients", "nutriment", 0, 80),
|
||||
list("potasssium iodide","potass_iodide", 0, 20),
|
||||
list("radium", "radium", 0, 20)
|
||||
)
|
||||
|
||||
|
||||
/obj/item/rig_module/chem_dispenser/accepts_item(var/obj/item/input_item, var/mob/living/user)
|
||||
|
||||
if(!input_item.is_open_container())
|
||||
return 0
|
||||
|
||||
if(!input_item.reagents || !input_item.reagents.total_volume)
|
||||
to_chat(user, "\The [input_item] is empty.")
|
||||
return 0
|
||||
|
||||
// Magical chemical filtration system, do not question it.
|
||||
var/total_transferred = 0
|
||||
for(var/datum/reagent/R in input_item.reagents.reagent_list)
|
||||
for(var/chargetype in charges)
|
||||
var/datum/rig_charge/charge = charges[chargetype]
|
||||
if(charge.display_name == R.id)
|
||||
|
||||
var/chems_to_transfer = R.volume
|
||||
|
||||
if((charge.charges + chems_to_transfer) > max_reagent_volume)
|
||||
chems_to_transfer = max_reagent_volume - charge.charges
|
||||
|
||||
charge.charges += chems_to_transfer
|
||||
input_item.reagents.remove_reagent(R.id, chems_to_transfer)
|
||||
total_transferred += chems_to_transfer
|
||||
|
||||
break
|
||||
|
||||
if(total_transferred)
|
||||
to_chat(user, "<font color='blue'>You transfer [total_transferred] units into the suit reservoir.</font>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>None of the reagents seem suitable.</span>")
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/chem_dispenser/engage(atom/target)
|
||||
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = holder.wearer
|
||||
|
||||
if(!charge_selected)
|
||||
to_chat(H, "<span class='danger'>You have not selected a chemical type.</span>")
|
||||
return 0
|
||||
|
||||
var/datum/rig_charge/charge = charges[charge_selected]
|
||||
|
||||
if(!charge)
|
||||
return 0
|
||||
|
||||
var/chems_to_use = 10
|
||||
if(charge.charges <= 0)
|
||||
to_chat(H, "<span class='danger'>Insufficient chems!</span>")
|
||||
return 0
|
||||
else if(charge.charges < chems_to_use)
|
||||
chems_to_use = charge.charges
|
||||
|
||||
var/mob/living/carbon/target_mob
|
||||
if(target)
|
||||
if(istype(target,/mob/living/carbon))
|
||||
target_mob = target
|
||||
else
|
||||
return 0
|
||||
else
|
||||
target_mob = H
|
||||
|
||||
if(target_mob != H)
|
||||
to_chat(H, "<span class='danger'>You inject [target_mob] with [chems_to_use] unit\s of [charge.display_name].</span>")
|
||||
to_chat(target_mob, "<span class='danger'>You feel a rushing in your veins as [chems_to_use] unit\s of [charge.display_name] [chems_to_use == 1 ? "is" : "are"] injected.</span>")
|
||||
target_mob.reagents.add_reagent(charge.display_name, chems_to_use)
|
||||
|
||||
charge.charges -= chems_to_use
|
||||
if(charge.charges < 0) charge.charges = 0
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/chem_dispenser/combat
|
||||
|
||||
name = "combat chemical injector"
|
||||
desc = "A complex web of tubing and needles suitable for hardsuit use."
|
||||
|
||||
charges = list(
|
||||
list("synaptizine", "synaptizine", 0, 30),
|
||||
list("hydrocodone", "hydrocodone", 0, 30),
|
||||
list("nutrients", "nutriment", 0, 80),
|
||||
)
|
||||
|
||||
interface_name = "combat chem dispenser"
|
||||
interface_desc = "Dispenses loaded chemicals directly into the bloodstream."
|
||||
|
||||
|
||||
/obj/item/rig_module/chem_dispenser/injector
|
||||
|
||||
name = "mounted chemical injector"
|
||||
desc = "A complex web of tubing and a large needle suitable for hardsuit use."
|
||||
usable = 0
|
||||
selectable = 1
|
||||
disruptive = 1
|
||||
|
||||
interface_name = "mounted chem injector"
|
||||
interface_desc = "Dispenses loaded chemicals via an arm-mounted injector."
|
||||
|
||||
/obj/item/rig_module/voice
|
||||
|
||||
name = "hardsuit voice synthesiser"
|
||||
desc = "A speaker box and sound processor."
|
||||
icon_state = "megaphone"
|
||||
usable = 1
|
||||
selectable = 0
|
||||
toggleable = 0
|
||||
disruptive = 0
|
||||
|
||||
engage_string = "Configure Synthesiser"
|
||||
|
||||
interface_name = "voice synthesiser"
|
||||
interface_desc = "A flexible and powerful voice modulator system."
|
||||
|
||||
var/obj/item/voice_changer/voice_holder
|
||||
|
||||
/obj/item/rig_module/voice/New()
|
||||
..()
|
||||
voice_holder = new(src)
|
||||
voice_holder.active = FALSE
|
||||
|
||||
/obj/item/rig_module/voice/installed()
|
||||
..()
|
||||
holder.speech = src
|
||||
|
||||
/obj/item/rig_module/voice/engage()
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
var/choice= input("Would you like to toggle the synthesiser or set the name?") as null|anything in list("Enable","Disable","Set Name")
|
||||
|
||||
if(!choice)
|
||||
return 0
|
||||
|
||||
switch(choice)
|
||||
if("Enable")
|
||||
active = TRUE
|
||||
voice_holder.active = TRUE
|
||||
to_chat(usr, "<font color='blue'>You enable the speech synthesiser.</font>")
|
||||
if("Disable")
|
||||
active = FALSE
|
||||
voice_holder.active = FALSE
|
||||
to_chat(usr, "<font color='blue'>You disable the speech synthesiser.</font>")
|
||||
if("Set Name")
|
||||
var/raw_choice = sanitize(input(usr, "Please enter a new name.") as text|null, MAX_NAME_LEN)
|
||||
if(!raw_choice)
|
||||
return FALSE
|
||||
voice_holder.voice = raw_choice
|
||||
to_chat(usr, "<font color='blue'>You are now mimicking <B>[voice_holder.voice]</B>.</font>")
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/maneuvering_jets
|
||||
|
||||
name = "hardsuit maneuvering jets"
|
||||
desc = "A compact gas thruster system for a hardsuit."
|
||||
icon_state = "thrusters"
|
||||
usable = 1
|
||||
toggleable = 1
|
||||
selectable = 0
|
||||
disruptive = 0
|
||||
|
||||
suit_overlay_active = "maneuvering_active"
|
||||
suit_overlay_inactive = null //"maneuvering_inactive"
|
||||
|
||||
engage_string = "Toggle Stabilizers"
|
||||
activate_string = "Activate Thrusters"
|
||||
deactivate_string = "Deactivate Thrusters"
|
||||
|
||||
interface_name = "maneuvering jets"
|
||||
interface_desc = "An inbuilt EVA maneuvering system that runs off the rig air supply."
|
||||
|
||||
var/obj/item/tank/jetpack/rig/jets
|
||||
|
||||
/obj/item/rig_module/maneuvering_jets/engage()
|
||||
if(!..())
|
||||
return 0
|
||||
jets.toggle_stabilization(usr)
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/maneuvering_jets/activate()
|
||||
|
||||
if(active)
|
||||
return 0
|
||||
|
||||
active = 1
|
||||
|
||||
spawn(1)
|
||||
if(suit_overlay_active)
|
||||
suit_overlay = suit_overlay_active
|
||||
else
|
||||
suit_overlay = null
|
||||
holder.update_icon()
|
||||
|
||||
jets.turn_on()
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/maneuvering_jets/deactivate()
|
||||
if(!..())
|
||||
return 0
|
||||
jets.turn_off()
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/maneuvering_jets/New()
|
||||
..()
|
||||
jets = new(src)
|
||||
|
||||
/obj/item/rig_module/maneuvering_jets/installed()
|
||||
..()
|
||||
jets.holder = holder
|
||||
jets.ion_trail.set_up(holder)
|
||||
|
||||
/obj/item/rig_module/maneuvering_jets/removed()
|
||||
..()
|
||||
jets.holder = null
|
||||
jets.ion_trail.set_up(jets)
|
||||
|
||||
/obj/item/rig_module/foam_sprayer
|
||||
|
||||
/obj/item/rig_module/device/paperdispenser
|
||||
name = "hardsuit paper dispenser"
|
||||
desc = "Crisp sheets."
|
||||
icon_state = "paper"
|
||||
interface_name = "paper dispenser"
|
||||
interface_desc = "Dispenses warm, clean, and crisp sheets of paper."
|
||||
engage_string = "Dispense"
|
||||
usable = 1
|
||||
selectable = 0
|
||||
device_type = /obj/item/paper_bin
|
||||
|
||||
/obj/item/rig_module/device/paperdispenser/engage(atom/target)
|
||||
|
||||
if(!..() || !device)
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
device.attack_hand(holder.wearer)
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/device/pen
|
||||
name = "mounted pen"
|
||||
desc = "For mecha John Hancocks."
|
||||
icon_state = "pen"
|
||||
interface_name = "mounted pen"
|
||||
interface_desc = "Signatures with style(tm)."
|
||||
engage_string = "Change color"
|
||||
usable = 1
|
||||
device_type = /obj/item/pen/multi
|
||||
|
||||
/obj/item/rig_module/device/stamp
|
||||
name = "mounted internal affairs stamp"
|
||||
desc = "DENIED."
|
||||
icon_state = "stamp"
|
||||
interface_name = "mounted stamp"
|
||||
interface_desc = "Leave your mark."
|
||||
engage_string = "Toggle stamp type"
|
||||
usable = 1
|
||||
var/obj/iastamp //Theese were just vars, but any device would need to be an object
|
||||
var/obj/deniedstamp //Stops assigning non-objects to theese vars, which probably would break quite a bit.
|
||||
|
||||
/obj/item/rig_module/device/stamp/New()
|
||||
..()
|
||||
iastamp = new /obj/item/stamp/law(src)
|
||||
deniedstamp = new /obj/item/stamp/denied(src)
|
||||
iastamp.flags |= ABSTRACT
|
||||
deniedstamp.flags |= ABSTRACT
|
||||
device = iastamp
|
||||
|
||||
/obj/item/rig_module/device/stamp/engage(atom/target)
|
||||
if(!..() || !device)
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
if(device == iastamp)
|
||||
device = deniedstamp
|
||||
to_chat(holder.wearer, "<span class='notice'>Switched to denied stamp.</span>")
|
||||
else if(device == deniedstamp)
|
||||
device = iastamp
|
||||
to_chat(holder.wearer, "<span class='notice'>Switched to internal affairs stamp.</span>")
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/welding_tank
|
||||
name = "welding fuel tank"
|
||||
desc = "A bluespace welding fuel storage tank for a rigsuit."
|
||||
icon_state = "welding_tank"
|
||||
interface_name = "mounted welding fuel tank"
|
||||
interface_desc = "A minitaure fuel tank used for storage of welding fuel, built into a hardsuit."
|
||||
engage_string = "Dispense fuel"
|
||||
usable = 1
|
||||
|
||||
var/max_fuel = 300
|
||||
|
||||
/obj/item/rig_module/welding_tank/New()
|
||||
..()
|
||||
|
||||
create_reagents(max_fuel)
|
||||
reagents.add_reagent("fuel", max_fuel)
|
||||
|
||||
/obj/item/rig_module/welding_tank/engage(atom/target)
|
||||
if(!..() || !reagents)
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
if(get_fuel() >= 0)
|
||||
var/obj/item/weldingtool/W = holder.wearer.get_active_hand()
|
||||
if(istype(W))
|
||||
fill_welder(W)
|
||||
else
|
||||
W = holder.wearer.get_inactive_hand()
|
||||
if(istype(W))
|
||||
fill_welder(W)
|
||||
else
|
||||
to_chat(holder.wearer, "<span class='danger'>Your welding tank is out of fuel!</span>")
|
||||
else
|
||||
to_chat(holder.wearer, "<span class='notice'>You need to have a welding tool in one of your hands to dispense fuel.</span>")
|
||||
|
||||
/obj/item/rig_module/welding_tank/proc/fill_welder(obj/item/weldingtool/W)
|
||||
if(!istype(W))
|
||||
return
|
||||
W.refill(holder.wearer, src, W.maximum_fuel)
|
||||
if(!reagents.get_reagent_amount("fuel"))
|
||||
to_chat(holder.wearer, "<span class='notice'>You hear a faint dripping as your hardsuit welding tank completely empties.</span>")
|
||||
|
||||
/obj/item/rig_module/welding_tank/proc/get_fuel()
|
||||
return reagents.get_reagent_amount("fuel")
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Contains
|
||||
* /obj/item/rig_module/vision
|
||||
* /obj/item/rig_module/vision/multi
|
||||
* /obj/item/rig_module/vision/meson
|
||||
* /obj/item/rig_module/vision/thermal
|
||||
* /obj/item/rig_module/vision/nvg
|
||||
* /obj/item/rig_module/vision/medhud
|
||||
* /obj/item/rig_module/vision/sechud
|
||||
*/
|
||||
|
||||
/datum/rig_vision
|
||||
var/mode
|
||||
var/obj/item/clothing/glasses/glasses
|
||||
|
||||
/datum/rig_vision/nvg
|
||||
mode = "night vision"
|
||||
/datum/rig_vision/nvg/New()
|
||||
glasses = new /obj/item/clothing/glasses/night
|
||||
|
||||
/datum/rig_vision/thermal
|
||||
mode = "thermal scanner"
|
||||
/datum/rig_vision/thermal/New()
|
||||
glasses = new /obj/item/clothing/glasses/thermal
|
||||
|
||||
/datum/rig_vision/meson
|
||||
mode = "meson scanner"
|
||||
/datum/rig_vision/meson/New()
|
||||
glasses = new /obj/item/clothing/glasses/meson
|
||||
|
||||
/datum/rig_vision/sechud
|
||||
mode = "security HUD"
|
||||
/datum/rig_vision/sechud/New()
|
||||
glasses = new /obj/item/clothing/glasses/hud/security
|
||||
|
||||
/datum/rig_vision/medhud
|
||||
mode = "medical HUD"
|
||||
/datum/rig_vision/medhud/New()
|
||||
glasses = new /obj/item/clothing/glasses/hud/health
|
||||
|
||||
/obj/item/rig_module/vision
|
||||
|
||||
name = "hardsuit visor"
|
||||
desc = "A layered, translucent visor system for a hardsuit."
|
||||
icon_state = "optics"
|
||||
|
||||
interface_name = "optical scanners"
|
||||
interface_desc = "An integrated multi-mode vision system."
|
||||
|
||||
usable = 1
|
||||
toggleable = 1
|
||||
disruptive = 0
|
||||
|
||||
engage_string = "Cycle Visor Mode"
|
||||
activate_string = "Enable Visor"
|
||||
deactivate_string = "Disable Visor"
|
||||
|
||||
var/datum/rig_vision/vision
|
||||
var/list/vision_modes = list(
|
||||
/datum/rig_vision/nvg,
|
||||
/datum/rig_vision/thermal,
|
||||
/datum/rig_vision/meson
|
||||
)
|
||||
|
||||
var/vision_index
|
||||
|
||||
/obj/item/rig_module/vision/multi
|
||||
|
||||
name = "hardsuit optical package"
|
||||
desc = "A complete visor system of optical scanners and vision modes."
|
||||
icon_state = "fulloptics"
|
||||
|
||||
|
||||
interface_name = "multi optical visor"
|
||||
interface_desc = "An integrated multi-mode vision system."
|
||||
|
||||
vision_modes = list(/datum/rig_vision/meson,
|
||||
/datum/rig_vision/nvg,
|
||||
/datum/rig_vision/thermal,
|
||||
/datum/rig_vision/sechud,
|
||||
/datum/rig_vision/medhud)
|
||||
|
||||
/obj/item/rig_module/vision/meson
|
||||
|
||||
name = "hardsuit meson scanner"
|
||||
desc = "A layered, translucent visor system for a hardsuit."
|
||||
icon_state = "meson"
|
||||
|
||||
usable = 0
|
||||
|
||||
interface_name = "meson scanner"
|
||||
interface_desc = "An integrated meson scanner."
|
||||
|
||||
vision_modes = list(/datum/rig_vision/meson)
|
||||
|
||||
/obj/item/rig_module/vision/thermal
|
||||
|
||||
name = "hardsuit thermal scanner"
|
||||
desc = "A layered, translucent visor system for a hardsuit."
|
||||
icon_state = "thermal"
|
||||
|
||||
usable = 0
|
||||
|
||||
interface_name = "thermal scanner"
|
||||
interface_desc = "An integrated thermal scanner."
|
||||
|
||||
vision_modes = list(/datum/rig_vision/thermal)
|
||||
|
||||
/obj/item/rig_module/vision/nvg
|
||||
|
||||
name = "hardsuit night vision interface"
|
||||
desc = "A multi input night vision system for a hardsuit."
|
||||
icon_state = "night"
|
||||
|
||||
usable = 0
|
||||
|
||||
interface_name = "night vision interface"
|
||||
interface_desc = "An integrated night vision system."
|
||||
|
||||
vision_modes = list(/datum/rig_vision/nvg)
|
||||
|
||||
/obj/item/rig_module/vision/sechud
|
||||
|
||||
name = "hardsuit security hud"
|
||||
desc = "A simple tactical information system for a hardsuit."
|
||||
icon_state = "securityhud"
|
||||
|
||||
usable = 0
|
||||
|
||||
interface_name = "security HUD"
|
||||
interface_desc = "An integrated security heads up display."
|
||||
|
||||
vision_modes = list(/datum/rig_vision/sechud)
|
||||
|
||||
/obj/item/rig_module/vision/medhud
|
||||
|
||||
name = "hardsuit medical hud"
|
||||
desc = "A simple medical status indicator for a hardsuit."
|
||||
icon_state = "healthhud"
|
||||
|
||||
usable = 0
|
||||
|
||||
interface_name = "medical HUD"
|
||||
interface_desc = "An integrated medical heads up display."
|
||||
|
||||
vision_modes = list(/datum/rig_vision/medhud)
|
||||
|
||||
|
||||
// There should only ever be one vision module installed in a suit.
|
||||
/obj/item/rig_module/vision/installed()
|
||||
..()
|
||||
holder.visor = src
|
||||
|
||||
/obj/item/rig_module/vision/engage()
|
||||
|
||||
var/starting_up = !active
|
||||
|
||||
if(!..() || !vision_modes)
|
||||
return 0
|
||||
|
||||
// Don't cycle if this engage() is being called by activate().
|
||||
if(starting_up)
|
||||
to_chat(holder.wearer, "<font color='blue'>You activate your visual sensors.</font>")
|
||||
return 1
|
||||
|
||||
if(vision_modes.len > 1)
|
||||
vision_index++
|
||||
if(vision_index > vision_modes.len)
|
||||
vision_index = 1
|
||||
vision = vision_modes[vision_index]
|
||||
|
||||
to_chat(holder.wearer, "<font color='blue'>You cycle your sensors to <b>[vision.mode]</b> mode.</font>")
|
||||
else
|
||||
to_chat(holder.wearer, "<font color='blue'>Your sensors only have one mode.</font>")
|
||||
return 1
|
||||
|
||||
/obj/item/rig_module/vision/New()
|
||||
..()
|
||||
|
||||
if(!vision_modes)
|
||||
return
|
||||
|
||||
vision_index = 1
|
||||
var/list/processed_vision = list()
|
||||
|
||||
for(var/vision_mode in vision_modes)
|
||||
var/datum/rig_vision/vision_datum = new vision_mode
|
||||
if(!vision) vision = vision_datum
|
||||
processed_vision += vision_datum
|
||||
|
||||
vision_modes = processed_vision
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,30 +0,0 @@
|
||||
/obj/item/clothing/suit/space/new_rig/calc_breach_damage()
|
||||
..()
|
||||
holder.update_armor() //New dammage, new armormultiplikator.
|
||||
return damage
|
||||
|
||||
/obj/item/rig/proc/update_armor()
|
||||
var/multi = 1 //Multiplicative modification to the armor, maybe add an additive later on
|
||||
if(chest)
|
||||
multi *= (100 - chest.damage) / 100 //If we have some breaches, lower the armor value.
|
||||
|
||||
//TODO check for other armor mods, likely modules, which need to be coded.
|
||||
if(!armor) //Did we even give them some armor, if this is the case, the list should be initialized from New()
|
||||
return
|
||||
|
||||
var/datum/armor/A = armor
|
||||
for(var/obj/item/piece in list(gloves, helmet, boots, chest))
|
||||
if(!istype(piece)) //Do we have the piece
|
||||
continue
|
||||
|
||||
piece.armor = piece.armor.setRating(melee_value = A.getRating("melee") * multi,
|
||||
bullet_value = A.getRating("bullet") * multi,
|
||||
laser_value = A.getRating("laser") * multi,
|
||||
energy_value = A.getRating("energy") * multi,
|
||||
bomb_value = A.getRating("bomb") * multi,
|
||||
bio_value = A.getRating("bio") * multi,
|
||||
rad_value = A.getRating("rad") * multi,
|
||||
fire_value = A.getRating("fire") * multi,
|
||||
acid_value = A.getRating("acidd") * multi)
|
||||
|
||||
//Perfect place to also add something like shield modules, or any other hit_reaction modules check.
|
||||
@@ -1,196 +0,0 @@
|
||||
/obj/item/rig/attackby(obj/item/W as obj, mob/user as mob)
|
||||
|
||||
if(!istype(user,/mob/living)) return 0
|
||||
|
||||
if(electrified != 0)
|
||||
if(shock(user)) //Handles removing charge from the cell, as well. No need to do that here.
|
||||
return
|
||||
|
||||
// Pass repair items on to the chestpiece.
|
||||
if(chest && (istype(W,/obj/item/stack) || istype(W, /obj/item/weldingtool)))
|
||||
return chest.attackby(W,user)
|
||||
|
||||
// Lock or unlock the access panel.
|
||||
if(W.GetID())
|
||||
if(subverted)
|
||||
locked = 0
|
||||
to_chat(user, "<span class='danger'>It looks like the locking system has been shorted out.</span>")
|
||||
return
|
||||
|
||||
if((!req_access || !req_access.len) && (!req_one_access || !req_one_access.len))
|
||||
locked = 0
|
||||
to_chat(user, "<span class='danger'>\The [src] doesn't seem to have a locking mechanism.</span>")
|
||||
return
|
||||
|
||||
if(security_check_enabled && !src.allowed(user))
|
||||
to_chat(user, "<span class='danger'>Access denied.</span>")
|
||||
return
|
||||
|
||||
locked = !locked
|
||||
to_chat(user, "You [locked ? "lock" : "unlock"] \the [src] access panel.")
|
||||
return
|
||||
|
||||
else if(istype(W,/obj/item/crowbar))
|
||||
|
||||
if(!open && locked)
|
||||
to_chat(user, "The access panel is locked shut.")
|
||||
return
|
||||
|
||||
open = !open
|
||||
to_chat(user, "You [open ? "open" : "close"] the access panel.")
|
||||
return
|
||||
|
||||
if(open)
|
||||
|
||||
// Hacking.
|
||||
if(istype(W,/obj/item/wirecutters) || istype(W,/obj/item/multitool))
|
||||
if(open)
|
||||
wires.Interact(user)
|
||||
else
|
||||
to_chat(user, "You can't reach the wiring.")
|
||||
return
|
||||
// Air tank.
|
||||
if(istype(W,/obj/item/tank)) //Todo, some kind of check for suits without integrated air supplies.
|
||||
|
||||
if(air_supply)
|
||||
to_chat(user, "\The [src] already has a tank installed.")
|
||||
return
|
||||
|
||||
user.unEquip(W)
|
||||
air_supply = W
|
||||
W.forceMove(src)
|
||||
to_chat(user, "You slot [W] into [src] and tighten the connecting valve.")
|
||||
return
|
||||
|
||||
// Check if this is a hardsuit upgrade or a modification.
|
||||
else if(istype(W,/obj/item/rig_module))
|
||||
|
||||
if(istype(src.loc,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = src.loc
|
||||
if(H.back == src)
|
||||
to_chat(user, "<span class='danger'>You can't install a hardsuit module while the suit is being worn.</span>")
|
||||
return 1
|
||||
|
||||
if(!installed_modules) installed_modules = list()
|
||||
if(installed_modules.len)
|
||||
for(var/obj/item/rig_module/installed_mod in installed_modules)
|
||||
if(!installed_mod.redundant && istype(installed_mod,W))
|
||||
to_chat(user, "The hardsuit already has a module of that class installed.")
|
||||
return 1
|
||||
|
||||
var/obj/item/rig_module/mod = W
|
||||
to_chat(user, "You begin installing \the [mod] into \the [src].")
|
||||
if(!do_after(user, 40 * W.toolspeed, target = src))
|
||||
return
|
||||
if(!user || !W)
|
||||
return
|
||||
to_chat(user, "You install \the [mod] into \the [src].")
|
||||
user.unEquip(mod)
|
||||
installed_modules |= mod
|
||||
mod.forceMove(src)
|
||||
mod.installed(src)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
else if(!cell && istype(W,/obj/item/stock_parts/cell))
|
||||
|
||||
to_chat(user, "You jack \the [W] into \the [src]'s battery mount.")
|
||||
user.unEquip(W)
|
||||
W.forceMove(src)
|
||||
src.cell = W
|
||||
return
|
||||
|
||||
else if(istype(W,/obj/item/wrench))
|
||||
|
||||
if(!air_supply)
|
||||
to_chat(user, "There is not tank to remove.")
|
||||
return
|
||||
|
||||
if(user.r_hand && user.l_hand)
|
||||
air_supply.forceMove(get_turf(user))
|
||||
else
|
||||
user.put_in_hands(air_supply)
|
||||
to_chat(user, "You detach and remove \the [air_supply].")
|
||||
air_supply = null
|
||||
return
|
||||
|
||||
else if(istype(W,/obj/item/screwdriver))
|
||||
|
||||
var/list/current_mounts = list()
|
||||
if(cell) current_mounts += "cell"
|
||||
if(installed_modules && installed_modules.len) current_mounts += "system module"
|
||||
|
||||
var/to_remove = input("Which would you like to modify?") as null|anything in current_mounts
|
||||
if(!to_remove)
|
||||
return
|
||||
|
||||
if(istype(src.loc,/mob/living/carbon/human) && to_remove != "cell")
|
||||
var/mob/living/carbon/human/H = src.loc
|
||||
if(H.back == src)
|
||||
to_chat(user, "You can't remove an installed device while the hardsuit is being worn.")
|
||||
return
|
||||
|
||||
switch(to_remove)
|
||||
|
||||
if("cell")
|
||||
|
||||
if(cell)
|
||||
to_chat(user, "You detatch \the [cell] from \the [src]'s battery mount.")
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
module.deactivate()
|
||||
if(user.r_hand && user.l_hand)
|
||||
cell.forceMove(get_turf(user))
|
||||
else
|
||||
user.put_in_hands(cell)
|
||||
cell = null
|
||||
else
|
||||
to_chat(user, "There is nothing loaded in that mount.")
|
||||
|
||||
if("system module")
|
||||
|
||||
var/list/possible_removals = list()
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
if(module.permanent)
|
||||
continue
|
||||
possible_removals[module.name] = module
|
||||
|
||||
if(!possible_removals.len)
|
||||
to_chat(user, "There are no installed modules to remove.")
|
||||
return
|
||||
|
||||
var/removal_choice = input("Which module would you like to remove?") as null|anything in possible_removals
|
||||
if(!removal_choice)
|
||||
return
|
||||
|
||||
var/obj/item/rig_module/removed = possible_removals[removal_choice]
|
||||
to_chat(user, "You detatch \the [removed] from \the [src].")
|
||||
removed.forceMove(get_turf(src))
|
||||
removed.removed()
|
||||
installed_modules -= removed
|
||||
update_icon()
|
||||
|
||||
return
|
||||
|
||||
// If we've gotten this far, all we have left to do before we pass off to root procs
|
||||
// is check if any of the loaded modules want to use the item we've been given.
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
if(module.accepts_item(W,user)) //Item is handled in this proc
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/rig/attack_hand(var/mob/user)
|
||||
|
||||
if(electrified != 0)
|
||||
if(shock(user)) //Handles removing charge from the cell, as well. No need to do that here.
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/rig/emag_act(var/remaining_charges, var/mob/user)
|
||||
if(!subverted)
|
||||
req_access.Cut()
|
||||
req_one_access.Cut()
|
||||
locked = 0
|
||||
subverted = 1
|
||||
to_chat(user, "<span class='danger'>You short out the access protocol for the suit.</span>")
|
||||
return 1
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Defines the helmets, gloves and shoes for rigs.
|
||||
*/
|
||||
|
||||
/obj/item/clothing/head/helmet/space/new_rig
|
||||
name = "helmet"
|
||||
flags = BLOCKHAIR | THICKMATERIAL | NODROP
|
||||
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEMASK
|
||||
body_parts_covered = HEAD
|
||||
heat_protection = HEAD
|
||||
cold_protection = HEAD
|
||||
var/brightness_on = 4
|
||||
var/on = 0
|
||||
sprite_sheets = list(
|
||||
"Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
|
||||
"Skrell" = 'icons/mob/species/skrell/helmet.dmi',
|
||||
"Unathi" = 'icons/mob/species/unathi/helmet.dmi'
|
||||
)
|
||||
species_restricted = null
|
||||
actions_types = list(/datum/action/item_action/toggle_helmet_light)
|
||||
|
||||
flash_protect = 2
|
||||
|
||||
/obj/item/clothing/head/helmet/space/new_rig/attack_self(mob/user)
|
||||
if(!isturf(user.loc))
|
||||
to_chat(user, "<span class='warning'>You cannot turn the light on while in this [user.loc].</span>")//To prevent some lighting anomalities.
|
||||
|
||||
return
|
||||
toggle_light(user)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/new_rig/proc/toggle_light(mob/user)
|
||||
if(flags & AIRTIGHT) //Could also check for STOPSPRESSUREDMAGE, but one is enough, both get toggled when the seal gets toggled.
|
||||
|
||||
on = !on
|
||||
icon_state = "[item_color][on]"
|
||||
|
||||
if(on)
|
||||
set_light(brightness_on)
|
||||
else
|
||||
set_light(0)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You cannot turn the light on while the suit isn't sealed.</span>")
|
||||
|
||||
if(istype(user,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.update_inv_head()
|
||||
|
||||
/obj/item/clothing/gloves/rig
|
||||
name = "gauntlets"
|
||||
flags = THICKMATERIAL | NODROP
|
||||
body_parts_covered = HANDS
|
||||
heat_protection = HANDS
|
||||
cold_protection = HANDS
|
||||
species_restricted = null
|
||||
gender = PLURAL
|
||||
|
||||
/obj/item/clothing/shoes/magboots/rig
|
||||
name = "boots"
|
||||
flags = NODROP
|
||||
body_parts_covered = FEET
|
||||
cold_protection = FEET
|
||||
heat_protection = FEET
|
||||
species_restricted = null
|
||||
gender = PLURAL
|
||||
|
||||
/obj/item/clothing/shoes/magboots/rig/attack_self(mob/user)
|
||||
if(flags & AIRTIGHT) //Could also check for STOPSPRESSUREDMAGE, but one is enough, both get toggled when the seal gets toggled.
|
||||
..(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You cannot activate mag-pulse traction system while the suit is not sealed.</span>")
|
||||
|
||||
/obj/item/clothing/suit/space/new_rig
|
||||
name = "chestpiece"
|
||||
allowed = list(/obj/item/flashlight,/obj/item/tank)
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
flags_inv = HIDEJUMPSUIT|HIDETAIL
|
||||
flags = STOPSPRESSUREDMAGE | THICKMATERIAL | AIRTIGHT | NODROP
|
||||
slowdown = 0
|
||||
breach_threshold = 20
|
||||
resilience = 0.2
|
||||
can_breach = 1
|
||||
var/obj/item/rig/holder
|
||||
sprite_sheets = list(
|
||||
"Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
|
||||
"Unathi" = 'icons/mob/species/unathi/suit.dmi'
|
||||
)
|
||||
|
||||
//TODO: move this to modules
|
||||
/obj/item/clothing/head/helmet/space/new_rig/proc/prevent_track()
|
||||
return 0
|
||||
|
||||
/obj/item/clothing/gloves/rig/Touch(var/atom/A, var/proximity)
|
||||
|
||||
if(!A || !proximity)
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = loc
|
||||
if(!istype(H) || !H.back)
|
||||
return 0
|
||||
|
||||
var/obj/item/rig/suit = H.back
|
||||
if(!suit || !istype(suit) || !suit.installed_modules.len)
|
||||
return 0
|
||||
|
||||
for(var/obj/item/rig_module/module in suit.installed_modules)
|
||||
if(module.active && module.activates_on_touch)
|
||||
if(module.engage(A))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
//Rig pieces for non-spacesuit based rigs
|
||||
|
||||
/obj/item/clothing/head/lightrig
|
||||
name = "mask"
|
||||
body_parts_covered = HEAD
|
||||
heat_protection = HEAD
|
||||
cold_protection = HEAD
|
||||
flags = THICKMATERIAL|AIRTIGHT
|
||||
|
||||
/obj/item/clothing/suit/lightrig
|
||||
name = "suit"
|
||||
allowed = list(/obj/item/flashlight)
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
flags_inv = HIDEJUMPSUIT
|
||||
flags = THICKMATERIAL
|
||||
|
||||
/obj/item/clothing/shoes/lightrig
|
||||
name = "boots"
|
||||
body_parts_covered = FEET
|
||||
cold_protection = FEET
|
||||
heat_protection = FEET
|
||||
species_restricted = null
|
||||
gender = PLURAL
|
||||
|
||||
/obj/item/clothing/gloves/lightrig
|
||||
name = "gloves"
|
||||
flags = THICKMATERIAL
|
||||
body_parts_covered = HANDS
|
||||
heat_protection = HANDS
|
||||
cold_protection = HANDS
|
||||
species_restricted = null
|
||||
gender = PLURAL
|
||||
@@ -1,335 +0,0 @@
|
||||
// Interface for humans.
|
||||
/obj/item/rig/verb/hardsuit_interface()
|
||||
set name = "Open Hardsuit Interface"
|
||||
set desc = "Open the hardsuit system interface."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(wearer && wearer.back == src)
|
||||
ui_interact(usr)
|
||||
|
||||
/obj/item/rig/verb/toggle_vision()
|
||||
set name = "Toggle Visor"
|
||||
set desc = "Turns your rig visor off or on."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit is not being worn.</span>")
|
||||
return
|
||||
|
||||
if(!check_power_cost(usr))
|
||||
return
|
||||
|
||||
if(!(flags & NODROP))
|
||||
to_chat(usr, "<span class='warning'>The suit is not active.</span>")
|
||||
return
|
||||
|
||||
if(!check_suit_access(usr))
|
||||
return
|
||||
|
||||
if(!visor)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit does not have a configurable visor.</span>")
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
if(!visor.active)
|
||||
visor.activate()
|
||||
else
|
||||
visor.deactivate()
|
||||
|
||||
/obj/item/rig/proc/toggle_helmet()
|
||||
set name = "Toggle Helmet"
|
||||
set desc = "Deploys or retracts your helmet."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit is not being worn.</span>")
|
||||
return
|
||||
|
||||
if(!check_suit_access(usr))
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
toggle_piece("helmet", usr)
|
||||
|
||||
/obj/item/rig/proc/toggle_chest()
|
||||
set name = "Toggle Chestpiece"
|
||||
set desc = "Deploys or retracts your chestpiece."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(!check_suit_access(usr))
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
toggle_piece("chest", usr)
|
||||
|
||||
/obj/item/rig/proc/toggle_gauntlets()
|
||||
set name = "Toggle Gauntlets"
|
||||
set desc = "Deploys or retracts your gauntlets."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit is not being worn.</span>")
|
||||
return
|
||||
|
||||
if(!check_suit_access(usr))
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
toggle_piece("gauntlets", usr)
|
||||
|
||||
/obj/item/rig/proc/toggle_boots()
|
||||
set name = "Toggle Boots"
|
||||
set desc = "Deploys or retracts your boots."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit is not being worn.</span>")
|
||||
return
|
||||
|
||||
if(!check_suit_access(usr))
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
toggle_piece("boots", usr)
|
||||
|
||||
/obj/item/rig/verb/deploy_suit()
|
||||
set name = "Deploy Hardsuit"
|
||||
set desc = "Deploys helmet, gloves and boots all at once."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit is not being worn.</span>")
|
||||
return
|
||||
|
||||
if(!check_suit_access(usr))
|
||||
return
|
||||
|
||||
if(!check_power_cost(usr))
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
deploy(wearer, usr)
|
||||
|
||||
/obj/item/rig/verb/toggle_seals_verb()
|
||||
set name = "Toggle Hardsuit Seals"
|
||||
set desc = "Seals or unseals your rig."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit is not being worn.</span>")
|
||||
return
|
||||
|
||||
if(!check_suit_access(usr))
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
if(flags & NODROP)
|
||||
unseal(usr)
|
||||
else
|
||||
seal(usr)
|
||||
|
||||
/obj/item/rig/verb/switch_vision_mode()
|
||||
set name = "Switch Vision Mode"
|
||||
set desc = "Switches between available vision modes."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(malfunction_check(usr))
|
||||
return
|
||||
|
||||
if(!check_power_cost(usr, 0, 0, 0, 0))
|
||||
return
|
||||
|
||||
if(!(flags & NODROP))
|
||||
to_chat(usr, "<span class='warning'>The suit is not active.</span>")
|
||||
return
|
||||
|
||||
if(!visor)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit does not have a configurable visor.</span>")
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
if(!visor.active)
|
||||
visor.activate()
|
||||
|
||||
if(!visor.active)
|
||||
to_chat(usr, "<span class='warning'>The visor is suffering a hardware fault and cannot be configured.</span>")
|
||||
return
|
||||
|
||||
visor.engage()
|
||||
|
||||
/obj/item/rig/verb/alter_voice()
|
||||
set name = "Configure Voice Synthesiser"
|
||||
set desc = "Toggles or configures your voice synthesizer."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(malfunction_check(usr))
|
||||
return
|
||||
|
||||
if(!(flags & NODROP))
|
||||
to_chat(usr, "<span class='warning'>The suit is not active.</span>")
|
||||
return
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit is not being worn.</span>")
|
||||
return
|
||||
|
||||
if(!speech)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit does not have a speech synthesiser.</span>")
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
speech.engage()
|
||||
|
||||
/obj/item/rig/verb/select_module()
|
||||
set name = "Select Module"
|
||||
set desc = "Selects a module as your primary system."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(malfunction_check(usr))
|
||||
return
|
||||
|
||||
if(!check_power_cost(usr, 0, 0, 0, 0))
|
||||
return
|
||||
|
||||
if(!(flags & NODROP))
|
||||
to_chat(usr, "<span class='warning'>The suit is not active.</span>")
|
||||
return
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit is not being worn.</span>")
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
var/list/selectable = list()
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
if(module.selectable)
|
||||
selectable |= module
|
||||
|
||||
var/obj/item/rig_module/module = input("Which module do you wish to select?") as null|anything in selectable
|
||||
|
||||
if(!istype(module))
|
||||
selected_module = null
|
||||
to_chat(usr, "<font color='blue'><b>Primary system is now: deselected.</b></font>")
|
||||
return
|
||||
|
||||
selected_module = module
|
||||
to_chat(usr, "<font color='blue'><b>Primary system is now: [selected_module.interface_name].</b></font>")
|
||||
|
||||
/obj/item/rig/verb/toggle_module()
|
||||
set name = "Toggle Module"
|
||||
set desc = "Toggle a system module."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(malfunction_check(usr))
|
||||
return
|
||||
|
||||
if(!check_power_cost(usr, 0, 0, 0, 0))
|
||||
return
|
||||
|
||||
if(!(flags & NODROP))
|
||||
to_chat(usr, "<span class='warning'>The suit is not active.</span>")
|
||||
return
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit is not being worn.</span>")
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
var/list/selectable = list()
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
if(module.toggleable)
|
||||
selectable |= module
|
||||
|
||||
var/obj/item/rig_module/module = input("Which module do you wish to toggle?") as null|anything in selectable
|
||||
|
||||
if(!istype(module))
|
||||
return
|
||||
|
||||
if(module.active)
|
||||
to_chat(usr, "<font color='blue'><b>You attempt to deactivate \the [module.interface_name].</b></font>")
|
||||
module.deactivate()
|
||||
else
|
||||
to_chat(usr, "<font color='blue'><b>You attempt to activate \the [module.interface_name].</b></font>")
|
||||
module.activate()
|
||||
|
||||
/obj/item/rig/verb/engage_module()
|
||||
set name = "Engage Module"
|
||||
set desc = "Engages a system module."
|
||||
set category = "Hardsuit"
|
||||
set src = usr.contents
|
||||
|
||||
if(malfunction_check(usr))
|
||||
return
|
||||
|
||||
if(!(flags & NODROP))
|
||||
to_chat(usr, "<span class='warning'>The suit is not active.</span>")
|
||||
return
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
to_chat(usr, "<span class='warning'>The hardsuit is not being worn.</span>")
|
||||
return
|
||||
|
||||
if(!check_power_cost(usr, 0, 0, 0, 0))
|
||||
return
|
||||
|
||||
var/mob/M = usr
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
var/list/selectable = list()
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
if(module.usable)
|
||||
selectable |= module
|
||||
|
||||
var/obj/item/rig_module/module = input("Which module do you wish to engage?") as null|anything in selectable
|
||||
|
||||
if(!istype(module))
|
||||
return
|
||||
|
||||
to_chat(usr, "<font color='blue'><b>You attempt to engage the [module.interface_name].</b></font>")
|
||||
module.engage()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user