mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-09 14:15:22 +01:00
Merge branch 'master' into admin-additions
This commit is contained in:
@@ -146,7 +146,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
|
||||
|
||||
if(kickbannedckey)
|
||||
if(banned_mob && banned_mob.client && banned_mob.client.ckey == banckey)
|
||||
del(banned_mob.client)
|
||||
qdel(banned_mob.client)
|
||||
|
||||
if(isjobban)
|
||||
jobban_client_fullban(ckey, job)
|
||||
@@ -211,7 +211,7 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
|
||||
query.Execute()
|
||||
while(query.NextRow())
|
||||
ban_id = query.item[1]
|
||||
ban_number++;
|
||||
ban_number++
|
||||
|
||||
if(ban_number == 0)
|
||||
to_chat(usr, "<span class='warning'>Database update failed due to no bans fitting the search criteria. If this is not a legacy ban you should contact the database admin.</span>")
|
||||
@@ -314,7 +314,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
|
||||
query.Execute()
|
||||
while(query.NextRow())
|
||||
pckey = query.item[1]
|
||||
ban_number++;
|
||||
ban_number++
|
||||
|
||||
if(ban_number == 0)
|
||||
to_chat(usr, "<span class='warning'>Database update failed due to a ban id not being present in the database.</span>")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -58,9 +58,6 @@ GLOBAL_PROTECT(banlist_savefile) // Obvious reasons
|
||||
GLOB.CMinutes = (world.realtime / 10) / 60
|
||||
return 1
|
||||
|
||||
/hook/startup/proc/loadBans()
|
||||
return LoadBans()
|
||||
|
||||
/proc/LoadBans()
|
||||
|
||||
GLOB.banlist_savefile = new("data/banlist.bdb")
|
||||
@@ -106,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
|
||||
@@ -72,12 +72,13 @@ GLOBAL_VAR_INIT(nologevent, 0)
|
||||
body += "\[<A href='?_src_=holder;editrights=rank;ckey=[M.ckey]'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\] "
|
||||
body += "\[<A href='?_src_=holder;getplaytimewindow=[M.UID()]'>" + M.client.get_exp_type(EXP_TYPE_CREW) + " as [EXP_TYPE_CREW]</a>\]"
|
||||
|
||||
if(istype(M, /mob/new_player))
|
||||
if(isnewplayer(M))
|
||||
body += " <B>Hasn't Entered Game</B> "
|
||||
else
|
||||
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)
|
||||
@@ -148,7 +149,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
|
||||
body += {" | <A href='?_src_=holder;cryossd=[M.UID()]'>Cryo</A> "}
|
||||
|
||||
if(M.client)
|
||||
if(!istype(M, /mob/new_player))
|
||||
if(!isnewplayer(M))
|
||||
body += "<br><br>"
|
||||
body += "<b>Transformation:</b>"
|
||||
body += "<br>"
|
||||
@@ -1005,13 +1006,13 @@ GLOBAL_VAR_INIT(gamma_ship_location, 1) // 0 = station , 1 = space
|
||||
/proc/kick_clients_in_lobby(message, kick_only_afk = 0)
|
||||
var/list/kicked_client_names = list()
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(istype(C.mob, /mob/new_player))
|
||||
if(isnewplayer(C.mob))
|
||||
if(kick_only_afk && !C.is_afk()) //Ignore clients who are not afk
|
||||
continue
|
||||
if(message)
|
||||
to_chat(C, message)
|
||||
kicked_client_names.Add("[C.ckey]")
|
||||
del(C)
|
||||
qdel(C)
|
||||
return kicked_client_names
|
||||
|
||||
//returns 1 to let the dragdrop code know we are trapping this event
|
||||
|
||||
@@ -11,10 +11,6 @@
|
||||
/proc/investigate_subject2file(var/subject)
|
||||
return file("[INVESTIGATE_DIR][subject].html")
|
||||
|
||||
/hook/startup/proc/resetInvestigate()
|
||||
investigate_reset()
|
||||
return 1
|
||||
|
||||
/proc/investigate_reset()
|
||||
if(fdel(INVESTIGATE_DIR)) return 1
|
||||
return 0
|
||||
|
||||
@@ -56,11 +56,12 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
|
||||
testing(msg)
|
||||
#endif
|
||||
|
||||
/hook/startup/proc/loadAdmins()
|
||||
load_admins()
|
||||
return 1
|
||||
|
||||
/proc/load_admins()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='boldannounce'>Admin reload blocked: Advanced ProcCall detected.</span>")
|
||||
message_admins("[key_name(usr)] attempted to reload admins via advanced proc-call")
|
||||
log_admin("[key_name(usr)] attempted to reload admins via advanced proc-call")
|
||||
return
|
||||
//clear the datums references
|
||||
GLOB.admin_datums.Cut()
|
||||
for(var/client/C in GLOB.admins)
|
||||
@@ -68,6 +69,10 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
|
||||
C.holder = null
|
||||
GLOB.admins.Cut()
|
||||
|
||||
// Remove all profiler access
|
||||
for(var/A in world.GetConfig("admin"))
|
||||
world.SetConfig("APP/admin", A, null)
|
||||
|
||||
if(config.admin_legacy_system)
|
||||
load_admin_ranks()
|
||||
|
||||
@@ -98,6 +103,9 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
|
||||
//create the admin datum and store it for later use
|
||||
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
|
||||
|
||||
if(D.rights & R_DEBUG || D.rights & R_VIEWRUNTIMES) // Grants profiler access to anyone with R_DEBUG or R_VIEWRUNTIMES
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
|
||||
//find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
D.associate(GLOB.directory[ckey])
|
||||
|
||||
@@ -122,6 +130,9 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
|
||||
if(istext(rights)) rights = text2num(rights)
|
||||
var/datum/admins/D = new /datum/admins(rank, rights, ckey)
|
||||
|
||||
if(D.rights & R_DEBUG || D.rights & R_VIEWRUNTIMES) // Grants profiler access to anyone with R_DEBUG or R_VIEWRUNTIMES
|
||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||
|
||||
//find the client for a ckey if they are connected and associate them with the new admin datum
|
||||
D.associate(GLOB.directory[ckey])
|
||||
if(!GLOB.admin_datums)
|
||||
|
||||
@@ -37,6 +37,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*/
|
||||
@@ -126,7 +127,6 @@ GLOBAL_LIST_INIT(admin_verbs_spawn, list(
|
||||
/client/proc/admin_deserialize
|
||||
))
|
||||
GLOBAL_LIST_INIT(admin_verbs_server, list(
|
||||
/client/proc/ToRban,
|
||||
/client/proc/Set_Holiday,
|
||||
/datum/admins/proc/startnow,
|
||||
/datum/admins/proc/restart,
|
||||
@@ -249,6 +249,8 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
verbs += GLOB.admin_verbs_server
|
||||
if(holder.rights & R_DEBUG)
|
||||
verbs += GLOB.admin_verbs_debug
|
||||
spawn(1)
|
||||
control_freak = 0 // Setting control_freak to 0 allows you to use the Profiler and other client-side tools
|
||||
if(holder.rights & R_POSSESS)
|
||||
verbs += GLOB.admin_verbs_possess
|
||||
if(holder.rights & R_PERMISSIONS)
|
||||
@@ -269,6 +271,9 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
verbs += GLOB.admin_verbs_proccall
|
||||
if(holder.rights & R_VIEWRUNTIMES)
|
||||
verbs += /client/proc/view_runtimes
|
||||
spawn(1) // This setting exposes the profiler for people with R_VIEWRUNTIMES. They must still have it set in cfg/admin.txt
|
||||
control_freak = 0
|
||||
|
||||
|
||||
/client/proc/remove_admin_verbs()
|
||||
verbs.Remove(
|
||||
@@ -334,7 +339,7 @@ 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!
|
||||
else if(istype(mob,/mob/new_player))
|
||||
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
|
||||
//ghostize
|
||||
@@ -539,7 +544,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
message_admins("[key_name_admin(src)] has warned [key_name_admin(C)] resulting in a [AUTOBANTIME] minute ban")
|
||||
log_admin("[key_name(src)] has warned [key_name(C)] resulting in a [AUTOBANTIME] minute ban")
|
||||
to_chat(C, "<font color='red'><BIG><B>You have been autobanned due to a warning by [ckey].</B></BIG><br>This is a temporary ban, it will be removed in [AUTOBANTIME] minutes.")
|
||||
del(C)
|
||||
qdel(C)
|
||||
else
|
||||
message_admins("[key_name_admin(src)] has warned [warned_ckey] resulting in a [AUTOBANTIME] minute ban")
|
||||
log_admin("[key_name(src)] has warned [warned_ckey] resulting in a [AUTOBANTIME] minute ban")
|
||||
@@ -823,7 +828,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!
|
||||
|
||||
@@ -854,10 +859,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!
|
||||
|
||||
|
||||
@@ -56,10 +56,6 @@ DEBUG
|
||||
jobban_loadbanfile()
|
||||
*/
|
||||
|
||||
/hook/startup/proc/loadJobBans()
|
||||
jobban_loadbanfile()
|
||||
return 1
|
||||
|
||||
/proc/jobban_loadbanfile()
|
||||
if(config.ban_legacy_system)
|
||||
var/savefile/S=new("data/job_full.ban")
|
||||
|
||||
@@ -16,6 +16,11 @@ GLOBAL_PROTECT(admin_datums) // This is protected because we dont want people ma
|
||||
var/admincaster_signature //What you'll sign the newsfeeds as
|
||||
|
||||
/datum/admins/New(initial_rank = "Temporary Admin", initial_rights = 0, ckey)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='boldannounce'>Admin rank creation blocked: Advanced ProcCall detected.</span>")
|
||||
message_admins("[key_name(usr)] attempted to create a new admin rank via advanced proc-call")
|
||||
log_admin("[key_name(usr)] attempted to edit feedback a new admin rank via advanced proc-call")
|
||||
return
|
||||
if(!ckey)
|
||||
error("Admin datum created without a ckey argument. Datum has been deleted")
|
||||
qdel(src)
|
||||
@@ -26,10 +31,20 @@ GLOBAL_PROTECT(admin_datums) // This is protected because we dont want people ma
|
||||
GLOB.admin_datums[ckey] = src
|
||||
|
||||
/datum/admins/Destroy()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='boldannounce'>Admin rank deletion blocked: Advanced ProcCall detected.</span>")
|
||||
message_admins("[key_name(usr)] attempted to delete an admin rank via advanced proc-call")
|
||||
log_admin("[key_name(usr)] attempted to delete an admin rank via advanced proc-call")
|
||||
return
|
||||
..()
|
||||
return QDEL_HINT_HARDDEL_NOW
|
||||
|
||||
/datum/admins/proc/associate(client/C)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='boldannounce'>Rank association blocked: Advanced ProcCall detected.</span>")
|
||||
message_admins("[key_name(usr)] attempted to associate an admin rank to a new client via advanced proc-call")
|
||||
log_admin("[key_name(usr)] attempted to associate an admin rank to a new client via advanced proc-call")
|
||||
return
|
||||
if(istype(C))
|
||||
owner = C
|
||||
owner.holder = src
|
||||
@@ -39,6 +54,11 @@ GLOBAL_PROTECT(admin_datums) // This is protected because we dont want people ma
|
||||
GLOB.admins |= C
|
||||
|
||||
/datum/admins/proc/disassociate()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='boldannounce'>Rank disassociation blocked: Advanced ProcCall detected.</span>")
|
||||
message_admins("[key_name(usr)] attempted to disassociate an admin rank from a client via advanced proc-call")
|
||||
log_admin("[key_name(usr)] attempted to disassociate an admin rank from a client via advanced proc-call")
|
||||
return
|
||||
if(owner)
|
||||
GLOB.admins -= owner
|
||||
owner.remove_admin_verbs()
|
||||
@@ -88,6 +108,11 @@ you will have to do something like if(client.holder.rights & R_ADMIN) yourself.
|
||||
return 0
|
||||
|
||||
/client/proc/deadmin()
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='boldannounce'>Deadmin blocked: Advanced ProcCall detected.</span>")
|
||||
message_admins("[key_name(usr)] attempted to de-admin a client via advanced proc-call")
|
||||
log_admin("[key_name(usr)] attempted to de-admin a client via advanced proc-call")
|
||||
return
|
||||
GLOB.admin_datums -= ckey
|
||||
if(holder)
|
||||
holder.disassociate()
|
||||
|
||||
@@ -102,6 +102,11 @@
|
||||
to_chat(usr, "<span class='notice'>Admin rank changed.</span>")
|
||||
|
||||
/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
to_chat(usr, "<span class='boldannounce'>Admin edit blocked: Advanced ProcCall detected.</span>")
|
||||
message_admins("[key_name(usr)] attempted to edit admin ranks via advanced proc-call")
|
||||
log_admin("[key_name(usr)] attempted to edit admin ranks via advanced proc-call")
|
||||
return
|
||||
if(config.admin_legacy_system)
|
||||
return
|
||||
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
else
|
||||
M_job = "Living"
|
||||
|
||||
else if(istype(M,/mob/new_player))
|
||||
else if(isnewplayer(M))
|
||||
M_job = "New player"
|
||||
|
||||
else if(isobserver(M))
|
||||
@@ -356,7 +356,7 @@
|
||||
dat += "<td>[M.real_name]</td>"
|
||||
else if(istype(M, /mob/living/silicon/pai))
|
||||
dat += "<td>pAI</td>"
|
||||
else if(istype(M, /mob/new_player))
|
||||
else if(isnewplayer(M))
|
||||
dat += "<td>New Player</td>"
|
||||
else if(isobserver(M))
|
||||
dat += "<td>Ghost</td>"
|
||||
@@ -404,7 +404,8 @@
|
||||
<td><A href='?src=[usr.UID()];priv_msg=[M.client ? M.client.UID() : null]'>PM</A> [ADMIN_FLW(M, "FLW")] </td>[close ? "</tr>" : ""]"}
|
||||
|
||||
/datum/admins/proc/check_antagonists()
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
if(SSticker && SSticker.current_state >= GAME_STATE_PLAYING)
|
||||
var/dat = "<html><head><title>Round Status</title></head><body><h1><B>Round Status</B></h1>"
|
||||
dat += "Current Game Mode: <B>[SSticker.mode.name]</B><BR>"
|
||||
@@ -490,6 +491,9 @@
|
||||
if(SSticker.mode.wizards.len)
|
||||
dat += check_role_table("Wizards", SSticker.mode.wizards)
|
||||
|
||||
if(SSticker.mode.apprentices.len)
|
||||
dat += check_role_table("Apprentices", SSticker.mode.apprentices)
|
||||
|
||||
if(SSticker.mode.raiders.len)
|
||||
dat += check_role_table("Raiders", SSticker.mode.raiders)
|
||||
|
||||
@@ -567,6 +571,15 @@
|
||||
if(SSticker.mode.ert.len)
|
||||
dat += check_role_table("ERT", SSticker.mode.ert)
|
||||
|
||||
//list active security force count, so admins know how bad things are
|
||||
var/list/sec_list = check_active_security_force()
|
||||
dat += "<br><table cellspacing=5><tr><td><b>Security</b></td><td></td></tr>"
|
||||
dat += "<tr><td>Total: </td><td>[sec_list[1]]</td>"
|
||||
dat += "<tr><td>Active: </td><td>[sec_list[2]]</td>"
|
||||
dat += "<tr><td>Dead: </td><td>[sec_list[3]]</td>"
|
||||
dat += "<tr><td>Antag: </td><td>[sec_list[4]]</td>"
|
||||
dat += "</table>"
|
||||
|
||||
dat += "</body></html>"
|
||||
usr << browse(dat, "window=roundstatus;size=400x500")
|
||||
else
|
||||
|
||||
@@ -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)
|
||||
@@ -186,9 +190,13 @@
|
||||
var/err = query_list_notes.ErrorMsg()
|
||||
log_game("SQL ERROR obtaining ckey from notes table. Error : \[[err]\]\n")
|
||||
return
|
||||
to_chat(usr, "<span class='notice'>Started regex note search for [search]. Please wait for results...</span>")
|
||||
message_admins("[usr.ckey] has started a note search with the following regex: [search] | CPU usage may be higher.")
|
||||
while(query_list_notes.NextRow())
|
||||
index_ckey = query_list_notes.item[1]
|
||||
output += "<a href='?_src_=holder;shownoteckey=[index_ckey]'>[index_ckey]</a><br>"
|
||||
CHECK_TICK
|
||||
message_admins("The note search started by [usr.ckey] has complete. CPU should return to normal.")
|
||||
else
|
||||
output += "<center><a href='?_src_=holder;addnoteempty=1'>\[Add Note\]</a></center>"
|
||||
output += ruler
|
||||
|
||||
+20
-11
@@ -909,7 +909,12 @@
|
||||
log_admin("[key_name(usr)] booted [key_name(M)].")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] booted [key_name_admin(M)].</span>", 1)
|
||||
//M.client = null
|
||||
del(M.client)
|
||||
qdel(M.client)
|
||||
|
||||
else if(href_list["open_logging_view"])
|
||||
var/mob/M = locateUID(href_list["open_logging_view"])
|
||||
if(ismob(M))
|
||||
usr.client.open_logging_view(list(M), TRUE)
|
||||
|
||||
//Player Notes
|
||||
else if(href_list["addnote"])
|
||||
@@ -1011,8 +1016,7 @@
|
||||
log_admin("[key_name(usr)] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.</span>")
|
||||
|
||||
del(M.client)
|
||||
//qdel(M) // See no reason why to delete mob. Important stuff can be lost. And ban can be lifted before round ends.
|
||||
qdel(M.client)
|
||||
if("No")
|
||||
var/reason = input(usr,"Please state the reason","Reason") as message|null
|
||||
if(!reason)
|
||||
@@ -1032,8 +1036,7 @@
|
||||
feedback_inc("ban_perma",1)
|
||||
DB_ban_record(BANTYPE_PERMA, M, -1, reason)
|
||||
|
||||
del(M.client)
|
||||
//qdel(M)
|
||||
qdel(M.client)
|
||||
if("Cancel")
|
||||
return
|
||||
|
||||
@@ -2691,14 +2694,16 @@
|
||||
if("monkey")
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
feedback_add_details("admin_secrets_fun_used","M")
|
||||
for(var/mob/living/carbon/human/H in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
spawn(0)
|
||||
H.monkeyize()
|
||||
ok = 1
|
||||
if("corgi")
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
feedback_add_details("admin_secrets_fun_used","M")
|
||||
for(var/mob/living/carbon/human/H in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
spawn(0)
|
||||
H.corgize()
|
||||
ok = 1
|
||||
@@ -2769,7 +2774,8 @@
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
feedback_add_details("admin_secrets_fun_used","PW")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] teleported all players to the prison station.</span>", 1)
|
||||
for(var/mob/living/carbon/human/H in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
var/turf/loc = find_loc(H)
|
||||
var/security = 0
|
||||
if(!is_station_level(loc.z) || GLOB.prisonwarped.Find(H))
|
||||
@@ -3102,7 +3108,8 @@
|
||||
if("manifest")
|
||||
var/dat = "<b>Showing Crew Manifest.</b><hr>"
|
||||
dat += "<table cellspacing=5><tr><th>Name</th><th>Position</th></tr>"
|
||||
for(var/mob/living/carbon/human/H in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(H.ckey)
|
||||
dat += text("<tr><td>[]</td><td>[]</td></tr>", H.name, H.get_assignment())
|
||||
dat += "</table>"
|
||||
@@ -3112,7 +3119,8 @@
|
||||
if("DNA")
|
||||
var/dat = "<b>Showing DNA from blood.</b><hr>"
|
||||
dat += "<table cellspacing=5><tr><th>Name</th><th>DNA</th><th>Blood Type</th></tr>"
|
||||
for(var/mob/living/carbon/human/H in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(H.dna && H.ckey)
|
||||
dat += "<tr><td>[H]</td><td>[H.dna.unique_enzymes]</td><td>[H.dna.blood_type]</td></tr>"
|
||||
dat += "</table>"
|
||||
@@ -3120,7 +3128,8 @@
|
||||
if("fingerprints")
|
||||
var/dat = "<b>Showing Fingerprints.</b><hr>"
|
||||
dat += "<table cellspacing=5><tr><th>Name</th><th>Fingerprints</th></tr>"
|
||||
for(var/mob/living/carbon/human/H in GLOB.mob_list)
|
||||
for(var/thing in GLOB.human_list)
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(H.ckey)
|
||||
if(H.dna && H.dna.uni_identity)
|
||||
dat += "<tr><td>[H]</td><td>[md5(H.dna.uni_identity)]</td></tr>"
|
||||
|
||||
@@ -430,7 +430,7 @@
|
||||
else if(expression[start + 1] == "\[" && islist(v))
|
||||
var/list/L = v
|
||||
var/index = SDQL_expression(source, expression[start + 2])
|
||||
if(isnum(index) && (!IsInteger(index) || L.len < index))
|
||||
if(isnum(index) && (!ISINTEGER(index) || L.len < index))
|
||||
to_chat(world, "<span class='danger'>Invalid list index: [index]</span>")
|
||||
return null
|
||||
return L[index]
|
||||
@@ -444,9 +444,9 @@
|
||||
|
||||
if(object == world) // Global proc.
|
||||
procname = "/proc/[procname]"
|
||||
return call(procname)(arglist(new_args))
|
||||
return (WrapAdminProcCall(GLOBAL_PROC, procname, new_args))
|
||||
|
||||
return call(object, procname)(arglist(new_args))
|
||||
return (WrapAdminProcCall(object, procname, new_args))
|
||||
|
||||
/proc/SDQL2_tokenize(query_text)
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","mo
|
||||
var/admin_number_ignored = 0 //Holds the number of admins without +BAN (so admins who are not really admins)
|
||||
var/admin_number_decrease = 0 //Holds the number of admins with are afk, ignored or both
|
||||
for(var/client/X in GLOB.admins)
|
||||
admin_number_total++;
|
||||
admin_number_total++
|
||||
var/invalid = 0
|
||||
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
|
||||
admin_number_ignored++
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
var/list/client/targets[0]
|
||||
for(var/client/T)
|
||||
if(T.mob)
|
||||
if(istype(T.mob, /mob/new_player))
|
||||
if(isnewplayer(T.mob))
|
||||
targets["(New Player) - [T]"] = T
|
||||
else if(istype(T.mob, /mob/dead/observer))
|
||||
targets["[T.mob.name](Ghost) - [T]"] = T
|
||||
@@ -42,7 +42,7 @@
|
||||
var/list/client/targets[0]
|
||||
for(var/client/T)
|
||||
if(T.mob)
|
||||
if(istype(T.mob, /mob/new_player))
|
||||
if(isnewplayer(T.mob))
|
||||
targets["[T] - (New Player)"] = T
|
||||
else if(istype(T.mob, /mob/dead/observer))
|
||||
targets["[T] - [T.mob.name](Ghost)"] = T
|
||||
|
||||
@@ -80,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,7 +1,6 @@
|
||||
/client/proc/atmosscan()
|
||||
set category = "Mapping"
|
||||
set name = "Check Piping"
|
||||
set background = 1
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
@@ -12,17 +11,18 @@
|
||||
|
||||
to_chat(usr, "Checking for disconnected pipes...")
|
||||
//all plumbing - yes, some things might get stated twice, doesn't matter.
|
||||
for(var/obj/machinery/atmospherics/plumbing in world)
|
||||
for(var/thing in SSair.atmos_machinery)
|
||||
var/obj/machinery/atmospherics/plumbing = thing
|
||||
if(plumbing.nodealert)
|
||||
to_chat(usr, "Unconnected [plumbing.name] located at [plumbing.x],[plumbing.y],[plumbing.z] ([get_area(plumbing.loc)])")
|
||||
|
||||
//Manifolds
|
||||
for(var/obj/machinery/atmospherics/pipe/manifold/pipe in world)
|
||||
for(var/obj/machinery/atmospherics/pipe/manifold/pipe in SSair.atmos_machinery)
|
||||
if(!pipe.node1 || !pipe.node2 || !pipe.node3)
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")
|
||||
|
||||
//Pipes
|
||||
for(var/obj/machinery/atmospherics/pipe/simple/pipe in world)
|
||||
for(var/obj/machinery/atmospherics/pipe/simple/pipe in SSair.atmos_machinery)
|
||||
if(!pipe.node1 || !pipe.node2)
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])")
|
||||
|
||||
|
||||
@@ -85,18 +85,80 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
return
|
||||
message_admins("[key_name_admin(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
|
||||
log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
|
||||
returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
|
||||
returnval = WrapAdminProcCall(target, procname, lst) // Pass the lst as an argument list to the proc
|
||||
else
|
||||
//this currently has no hascall protection. wasn't able to get it working.
|
||||
message_admins("[key_name_admin(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
|
||||
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
|
||||
returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc
|
||||
returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
|
||||
|
||||
to_chat(usr, "<font color='blue'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</font>")
|
||||
feedback_add_details("admin_verb","APC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
// All these vars are related to proc call protection
|
||||
// If you add more of these, for the love of fuck, protect them
|
||||
|
||||
/// Who is currently calling procs
|
||||
GLOBAL_VAR(AdminProcCaller)
|
||||
GLOBAL_PROTECT(AdminProcCaller)
|
||||
/// How many procs have been called
|
||||
GLOBAL_VAR_INIT(AdminProcCallCount, 0)
|
||||
GLOBAL_PROTECT(AdminProcCallCount)
|
||||
/// UID of the admin who last called
|
||||
GLOBAL_VAR(LastAdminCalledTargetUID)
|
||||
GLOBAL_PROTECT(LastAdminCalledTargetUID)
|
||||
/// Last target to have a proc called on it
|
||||
GLOBAL_VAR(LastAdminCalledTarget)
|
||||
GLOBAL_PROTECT(LastAdminCalledTarget)
|
||||
/// Last proc called
|
||||
GLOBAL_VAR(LastAdminCalledProc)
|
||||
GLOBAL_PROTECT(LastAdminCalledProc)
|
||||
/// List to handle proc call spam prevention
|
||||
GLOBAL_LIST_EMPTY(AdminProcCallSpamPrevention)
|
||||
GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
|
||||
|
||||
// Wrapper for proccalls where the datum is flagged as vareditted
|
||||
/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
|
||||
if(target && procname == "Del")
|
||||
to_chat(usr, "Calling Del() is not allowed")
|
||||
return
|
||||
|
||||
if(target != GLOBAL_PROC && !target.CanProcCall(procname))
|
||||
to_chat(usr, "Proccall on [target.type]/proc/[procname] is disallowed!")
|
||||
return
|
||||
var/current_caller = GLOB.AdminProcCaller
|
||||
var/ckey = usr ? usr.client.ckey : GLOB.AdminProcCaller
|
||||
if(!ckey)
|
||||
CRASH("WrapAdminProcCall with no ckey: [target] [procname] [english_list(arguments)]")
|
||||
if(current_caller && current_caller != ckey)
|
||||
if(!GLOB.AdminProcCallSpamPrevention[ckey])
|
||||
to_chat(usr, "<span class='adminnotice'>Another set of admin called procs are still running, your proc will be run after theirs finish.</span>")
|
||||
GLOB.AdminProcCallSpamPrevention[ckey] = TRUE
|
||||
UNTIL(!GLOB.AdminProcCaller)
|
||||
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
|
||||
GLOB.AdminProcCallSpamPrevention -= ckey
|
||||
else
|
||||
UNTIL(!GLOB.AdminProcCaller)
|
||||
GLOB.LastAdminCalledProc = procname
|
||||
if(target != GLOBAL_PROC)
|
||||
GLOB.LastAdminCalledTargetUID = target.UID()
|
||||
GLOB.AdminProcCaller = ckey //if this runtimes, too bad for you
|
||||
++GLOB.AdminProcCallCount
|
||||
. = world.WrapAdminProcCall(target, procname, arguments)
|
||||
if(--GLOB.AdminProcCallCount == 0)
|
||||
GLOB.AdminProcCaller = null
|
||||
|
||||
//adv proc call this, ya nerds
|
||||
/world/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
|
||||
if(target == GLOBAL_PROC)
|
||||
return call(procname)(arglist(arguments))
|
||||
else if(target != world)
|
||||
return call(target, procname)(arglist(arguments))
|
||||
else
|
||||
to_chat(usr, "<span class='boldannounce'>Call to world/proc/[procname] blocked: Advanced ProcCall detected.</span>")
|
||||
message_admins("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]")
|
||||
log_admin("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]l")
|
||||
|
||||
/proc/IsAdminAdvancedProcCall()
|
||||
#ifdef TESTING
|
||||
@@ -131,7 +193,7 @@ GLOBAL_PROTECT(AdminProcCaller)
|
||||
log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
|
||||
|
||||
spawn()
|
||||
var/returnval = call(A,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
|
||||
var/returnval = WrapAdminProcCall(A, procname, lst) // Pass the lst as an argument list to the proc
|
||||
to_chat(src, "<span class='notice'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</span>")
|
||||
|
||||
feedback_add_details("admin_verb","DPC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -251,7 +313,7 @@ GLOBAL_PROTECT(AdminProcCaller)
|
||||
alert("That mob doesn't seem to exist, close the panel and try again.")
|
||||
return
|
||||
|
||||
if(istype(M, /mob/new_player))
|
||||
if(isnewplayer(M))
|
||||
alert("The mob must not be a new_player.")
|
||||
return
|
||||
|
||||
@@ -382,7 +444,7 @@ GLOBAL_PROTECT(AdminProcCaller)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
//This gets a confirmation check because it's way easier to accidentally hit this and delete things than it is with del-all
|
||||
//This gets a confirmation check because it's way easier to accidentally hit this and delete things than it is with qdel-all
|
||||
var/confirm = alert("This will delete ALL Singularities and Tesla orbs except for any that are on away mission z-levels or the centcomm z-level. Are you sure you want to delete them?", "Confirm Panic Button", "Yes", "No")
|
||||
if(confirm != "Yes")
|
||||
return
|
||||
@@ -428,7 +490,7 @@ GLOBAL_PROTECT(AdminProcCaller)
|
||||
id.icon_state = "gold"
|
||||
id:access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access()
|
||||
else
|
||||
var/obj/item/card/id/id = new/obj/item/card/id(M);
|
||||
var/obj/item/card/id/id = new/obj/item/card/id(M)
|
||||
id.icon_state = "gold"
|
||||
id:access = get_all_accesses()+get_all_centcom_access()+get_all_syndicate_access()
|
||||
id.registered_name = H.real_name
|
||||
@@ -487,7 +549,8 @@ GLOBAL_PROTECT(AdminProcCaller)
|
||||
for(var/area/A in world)
|
||||
areas_all |= A.type
|
||||
|
||||
for(var/obj/machinery/power/apc/APC in world)
|
||||
for(var/thing in GLOB.apcs)
|
||||
var/obj/machinery/power/apc/APC = thing
|
||||
var/area/A = get_area(APC)
|
||||
if(!A)
|
||||
continue
|
||||
@@ -496,7 +559,8 @@ GLOBAL_PROTECT(AdminProcCaller)
|
||||
else
|
||||
areas_with_multiple_APCs |= A.type
|
||||
|
||||
for(var/obj/machinery/alarm/alarm in world)
|
||||
for(var/thing in GLOB.air_alarms)
|
||||
var/obj/machinery/alarm/alarm = thing
|
||||
var/area/A = get_area(alarm)
|
||||
if(!A)
|
||||
continue
|
||||
@@ -505,31 +569,31 @@ GLOBAL_PROTECT(AdminProcCaller)
|
||||
else
|
||||
areas_with_multiple_air_alarms |= A.type
|
||||
|
||||
for(var/obj/machinery/requests_console/RC in world)
|
||||
for(var/obj/machinery/requests_console/RC in GLOB.machines)
|
||||
var/area/A = get_area(RC)
|
||||
if(!A)
|
||||
continue
|
||||
areas_with_RC |= A.type
|
||||
|
||||
for(var/obj/machinery/light/L in world)
|
||||
for(var/obj/machinery/light/L in GLOB.machines)
|
||||
var/area/A = get_area(L)
|
||||
if(!A)
|
||||
continue
|
||||
areas_with_light |= A.type
|
||||
|
||||
for(var/obj/machinery/light_switch/LS in world)
|
||||
for(var/obj/machinery/light_switch/LS in GLOB.machines)
|
||||
var/area/A = get_area(LS)
|
||||
if(!A)
|
||||
continue
|
||||
areas_with_LS |= A.type
|
||||
|
||||
for(var/obj/item/radio/intercom/I in world)
|
||||
for(var/obj/item/radio/intercom/I in GLOB.global_radios)
|
||||
var/area/A = get_area(I)
|
||||
if(!A)
|
||||
continue
|
||||
areas_with_intercom |= A.type
|
||||
|
||||
for(var/obj/machinery/camera/C in world)
|
||||
for(var/obj/machinery/camera/C in GLOB.machines)
|
||||
var/area/A = get_area(C)
|
||||
if(!A)
|
||||
continue
|
||||
@@ -579,7 +643,7 @@ GLOBAL_PROTECT(AdminProcCaller)
|
||||
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"
|
||||
|
||||
@@ -814,21 +878,6 @@ GLOBAL_PROTECT(AdminProcCaller)
|
||||
else
|
||||
alert("Invalid mob")
|
||||
|
||||
/client/proc/reload_nanoui_resources()
|
||||
set category = "Debug"
|
||||
set name = "Reload NanoUI Resources"
|
||||
set desc = "Force the client to redownload NanoUI Resources"
|
||||
|
||||
// Close open NanoUIs.
|
||||
SSnanoui.close_user_uis(usr)
|
||||
|
||||
// Re-load the assets.
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/nanoui)
|
||||
assets.register()
|
||||
|
||||
// Clear the user's cache so they get resent.
|
||||
usr.client.cache = list()
|
||||
|
||||
/client/proc/view_runtimes()
|
||||
set category = "Debug"
|
||||
set name = "View Runtimes"
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
if(T.active_hotspot)
|
||||
burning = 1
|
||||
|
||||
to_chat(usr, "<span class='notice'>@[target.x],[target.y]: O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("<span class='warning'>BURNING</span>"):(null)]</span>")
|
||||
for(var/datum/gas/trace_gas in GM.trace_gases)
|
||||
to_chat(usr, "[trace_gas.type]: [trace_gas.moles]")
|
||||
to_chat(usr, "<span class='notice'>@[target.x],[target.y]: O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] N2O: [GM.sleeping_agent] Agent B: [GM.agent_b] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("<span class='warning'>BURNING</span>"):(null)]</span>")
|
||||
|
||||
message_admins("[key_name_admin(usr)] has checked the air status of [target]")
|
||||
log_admin("[key_name(usr)] has checked the air status of [target]")
|
||||
|
||||
@@ -48,7 +48,8 @@ GLOBAL_VAR_INIT(sent_honksquad, 0)
|
||||
commandos += candidate//Add their ghost to commandos.
|
||||
|
||||
//Spawns HONKsquad and equips them.
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(honksquad_number<=0) break
|
||||
if(L.name == "HONKsquad")
|
||||
honk_leader_selected = honksquad_number == 1?1:0
|
||||
|
||||
@@ -66,7 +66,8 @@ GLOBAL_VAR_INIT(sent_syndicate_infiltration_team, 0)
|
||||
var/list/sit_spawns = list()
|
||||
var/list/sit_spawns_leader = list()
|
||||
var/list/sit_spawns_mgmt = list()
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(L.name == "Syndicate-Infiltrator")
|
||||
sit_spawns += L
|
||||
if(L.name == "Syndicate-Infiltrator-Leader")
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ GLOBAL_VAR_INIT(intercom_range_display_status, 0)
|
||||
qdel(M)
|
||||
|
||||
if(GLOB.intercom_range_display_status)
|
||||
for(var/obj/item/radio/intercom/I in world)
|
||||
for(var/obj/item/radio/intercom/I in GLOB.global_radios)
|
||||
for(var/turf/T in orange(7,I))
|
||||
var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T)
|
||||
if(!(F in view(7,I.loc)))
|
||||
|
||||
@@ -627,6 +627,7 @@ GLOBAL_LIST_INIT(VVpixelmovement, list("step_x", "step_y", "step_size", "bound_h
|
||||
if(!O.vv_edit_var(variable, var_new))
|
||||
to_chat(src, "Your edit was rejected by the object.")
|
||||
return
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_VAR_EDIT, args)
|
||||
log_world("### VarEdit by [src]: [O.type] [variable]=[html_encode("[var_new]")]")
|
||||
log_admin("[key_name(src)] modified [original_name]'s [variable] to [var_new]")
|
||||
var/msg = "[key_name_admin(src)] modified [original_name]'s [variable] to [var_new]"
|
||||
|
||||
@@ -267,7 +267,7 @@ client/proc/one_click_antag()
|
||||
var/I = image('icons/mob/mob.dmi', loc = synd_mind_1.current, icon_state = "synd")
|
||||
synd_mind.current.client.images += I
|
||||
|
||||
for(var/obj/machinery/nuclearbomb/bomb in world)
|
||||
for(var/obj/machinery/nuclearbomb/bomb in GLOB.machines)
|
||||
bomb.r_code = nuke_code // All the nukes are set to this code.
|
||||
return 1
|
||||
|
||||
@@ -455,7 +455,8 @@ client/proc/one_click_antag()
|
||||
if(candidates.len)
|
||||
var/raiders = min(antnum, candidates.len)
|
||||
//Spawns vox raiders and equips them.
|
||||
for(var/obj/effect/landmark/L in world)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(L.name == "voxstart")
|
||||
if(raiders<=0)
|
||||
break
|
||||
@@ -583,7 +584,8 @@ client/proc/one_click_antag()
|
||||
var/teamOneMembers = 5
|
||||
var/teamTwoMembers = 5
|
||||
var/datum/preferences/A = new()
|
||||
for(var/obj/effect/landmark/L in world)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(L.name == "tdome1")
|
||||
if(teamOneMembers<=0)
|
||||
break
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -73,9 +73,11 @@
|
||||
..()
|
||||
if((ishuman(hit_atom)))
|
||||
var/mob/living/carbon/human/H = hit_atom
|
||||
if(H.r_hand == src) return
|
||||
if(H.l_hand == src) return
|
||||
var/mob/A = H.LAssailant
|
||||
if(H.r_hand == src)
|
||||
return
|
||||
if(H.l_hand == src)
|
||||
return
|
||||
var/mob/A = thrownby
|
||||
if((H in GLOB.team_alpha) && (A in GLOB.team_alpha))
|
||||
to_chat(A, "<span class='warning'>He's on your team!</span>")
|
||||
return
|
||||
@@ -89,4 +91,3 @@
|
||||
playsound(src, 'sound/items/dodgeball.ogg', 50, 1)
|
||||
visible_message("<span class='danger'>[H] HAS BEEN ELIMINATED!</span>")
|
||||
H.melt()
|
||||
return
|
||||
|
||||
@@ -53,7 +53,7 @@ GLOBAL_LIST_EMPTY(sounds_cache)
|
||||
set name = "Play Server Sound"
|
||||
if(!check_rights(R_SOUNDS)) return
|
||||
|
||||
var/list/sounds = file2list("sound/serversound_list.txt");
|
||||
var/list/sounds = file2list("sound/serversound_list.txt")
|
||||
sounds += GLOB.sounds_cache
|
||||
|
||||
var/melody = input("Select a sound from the server to play", "Server sound list") as null|anything in sounds
|
||||
@@ -71,7 +71,7 @@ GLOBAL_LIST_EMPTY(sounds_cache)
|
||||
var/A = alert("This will play a sound at every intercomm, are you sure you want to continue? This works best with short sounds, beware.","Warning","Yep","Nope")
|
||||
if(A != "Yep") return
|
||||
|
||||
var/list/sounds = file2list("sound/serversound_list.txt");
|
||||
var/list/sounds = file2list("sound/serversound_list.txt")
|
||||
sounds += GLOB.sounds_cache
|
||||
|
||||
var/melody = input("Select a sound from the server to play", "Server sound list") as null|anything in sounds
|
||||
|
||||
@@ -627,7 +627,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
print_command_report(input, "[command_name()] Update")
|
||||
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.");
|
||||
GLOB.command_announcer.autosay("A classified message has been printed out at all communication consoles.")
|
||||
print_command_report(input, "Classified [command_name()] Update")
|
||||
else
|
||||
return
|
||||
@@ -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.")
|
||||
@@ -874,6 +877,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
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 +983,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 +1021,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)
|
||||
|
||||
@@ -30,7 +30,7 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
|
||||
// Find the nuclear auth code
|
||||
var/nuke_code
|
||||
var/temp_code
|
||||
for(var/obj/machinery/nuclearbomb/N in world)
|
||||
for(var/obj/machinery/nuclearbomb/N in GLOB.machines)
|
||||
temp_code = text2num(N.r_code)
|
||||
if(temp_code)//if it's actually a number. It won't convert any non-numericals.
|
||||
nuke_code = N.r_code
|
||||
@@ -48,7 +48,8 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
|
||||
var/commando_number = COMMANDOS_POSSIBLE //for selecting a leader
|
||||
var/is_leader = TRUE // set to FALSE after leader is spawned
|
||||
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
|
||||
if(commando_number <= 0)
|
||||
break
|
||||
@@ -109,7 +110,8 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
|
||||
commando_number--
|
||||
|
||||
//Spawns the rest of the commando gear.
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(L.name == "Commando_Manual")
|
||||
//new /obj/item/gun/energy/pulse_rifle(L.loc)
|
||||
var/obj/item/paper/P = new(L.loc)
|
||||
@@ -120,7 +122,8 @@ GLOBAL_VAR_INIT(sent_strike_team, 0)
|
||||
P.stamp(stamp)
|
||||
qdel(stamp)
|
||||
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(L.name == "Commando-Bomb")
|
||||
new /obj/effect/spawner/newbomb/timer/syndicate(L.loc)
|
||||
qdel(L)
|
||||
|
||||
@@ -38,7 +38,7 @@ GLOBAL_VAR_INIT(sent_syndicate_strike_team, 0)
|
||||
// Find the nuclear auth code
|
||||
var/nuke_code
|
||||
var/temp_code
|
||||
for(var/obj/machinery/nuclearbomb/N in world)
|
||||
for(var/obj/machinery/nuclearbomb/N in GLOB.machines)
|
||||
temp_code = text2num(N.r_code)
|
||||
if(temp_code)//if it's actually a number. It won't convert any non-numericals.
|
||||
nuke_code = N.r_code
|
||||
@@ -53,7 +53,8 @@ GLOBAL_VAR_INIT(sent_syndicate_strike_team, 0)
|
||||
GLOB.sent_syndicate_strike_team = 1
|
||||
|
||||
//Spawns commandos and equips them.
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
|
||||
if(syndicate_commando_number <= 0)
|
||||
break
|
||||
|
||||
@@ -17,8 +17,6 @@ GLOBAL_LIST_INIT(admin_verbs_show_debug_verbs, list(
|
||||
/client/proc/print_jobban_old,
|
||||
/client/proc/print_jobban_old_filter,
|
||||
/client/proc/forceEvent,
|
||||
/client/proc/nanomapgen_DumpImage,
|
||||
/client/proc/reload_nanoui_resources,
|
||||
/client/proc/admin_redo_space_transitions,
|
||||
/client/proc/make_turf_space_map,
|
||||
/client/proc/vv_by_ref
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
sources_assoc[source] = AS
|
||||
// Currently only non-0 durations can be altered (normal alarms VS EMP blasts)
|
||||
if(AS.duration)
|
||||
duration = SecondsToTicks(duration)
|
||||
duration = duration SECONDS
|
||||
AS.duration = duration
|
||||
AS.severity = severity
|
||||
|
||||
|
||||
@@ -194,7 +194,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
/obj/machinery/computer/mob_battle_terminal/proc/eject_card(override = 0)
|
||||
if(!override)
|
||||
if(ready && SSmob_hunt.battle_turn != team)
|
||||
audible_message("You can't recall on your rival's turn!", null, 2)
|
||||
atom_say("You can't recall on your rival's turn!")
|
||||
return
|
||||
card.mob_data = mob_info
|
||||
mob_info = null
|
||||
@@ -202,7 +202,7 @@
|
||||
start_battle()
|
||||
else if(option == 2)
|
||||
ready = 0
|
||||
audible_message("[team] Player cancels their battle challenge.", null, 5)
|
||||
atom_say("[team] Player cancels their battle challenge.")
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
var/message = "[mob_info.mob_name] attacks!"
|
||||
if(mob_info.nickname)
|
||||
message = "[mob_info.nickname] attacks!"
|
||||
audible_message(message, null, 5)
|
||||
atom_say(message)
|
||||
SSmob_hunt.launch_attack(team, mob_info.get_raw_damage(), mob_info.get_attack_type())
|
||||
|
||||
/obj/machinery/computer/mob_battle_terminal/proc/start_battle()
|
||||
@@ -255,7 +255,7 @@
|
||||
if(!card) //don't do anything if there isn't a card inserted
|
||||
return
|
||||
ready = 1
|
||||
audible_message("[team] Player is ready for battle! Waiting for rival...", null, 5)
|
||||
atom_say("[team] Player is ready for battle! Waiting for rival...")
|
||||
SSmob_hunt.start_check()
|
||||
|
||||
/obj/machinery/computer/mob_battle_terminal/proc/receive_attack(raw_damage, datum/mob_type/attack_type)
|
||||
@@ -268,7 +268,7 @@
|
||||
SSmob_hunt.end_turn()
|
||||
|
||||
/obj/machinery/computer/mob_battle_terminal/proc/surrender()
|
||||
audible_message("[team] Player surrenders the battle!", null, 5)
|
||||
atom_say("[team] Player surrenders the battle!")
|
||||
SSmob_hunt.end_battle(team, 1)
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
var/datum/data/pda/app/mob_hunter_game/client = P.current_app
|
||||
var/total_catch_mod = client.catch_mod + catch_mod //negative values decrease the chance of the mob running, positive values makes it more likely to flee
|
||||
if(!client.connected) //must be connected to attempt captures
|
||||
P.audible_message("[bicon(P)] No server connection. Capture aborted.", null, 4)
|
||||
P.atom_say("No server connection. Capture aborted.")
|
||||
return
|
||||
|
||||
if(mob_info.is_trap) //traps work even if you ran into them before, which is why this is before the clients_encountered check
|
||||
@@ -79,7 +79,7 @@
|
||||
return
|
||||
else //deal with the new hunter by either running away or getting caught
|
||||
clients_encountered += client
|
||||
var/message = "[bicon(P)] "
|
||||
var/message = null
|
||||
var/effective_run_chance = mob_info.run_chance + total_catch_mod
|
||||
if((effective_run_chance > 0) && prob(effective_run_chance))
|
||||
message += "Capture failed! [name] escaped [P.owner ? "from [P.owner]" : "from this hunter"]!"
|
||||
@@ -91,7 +91,7 @@
|
||||
else
|
||||
message += "Capture error! Try again."
|
||||
clients_encountered -= client //if the capture registration failed somehow, let them have another chance with this mob
|
||||
P.audible_message(message, null, 4)
|
||||
P.atom_say(message)
|
||||
|
||||
/obj/effect/nanomob/proc/despawn()
|
||||
if(SSmob_hunt)
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
for(var/areapath in typesof(A))
|
||||
possible_areas[areapath] -= 2
|
||||
//removes "bad areas" which shouldn't be on-station but are subtypes of station areas. probably should the unused ones and consider repathing the rest
|
||||
var/list/bad_areas = list(subtypesof(/area/construction), /area/solar/derelict_starboard, /area/solar/derelict_aft, /area/solar/constructionsite)
|
||||
var/list/bad_areas = list(subtypesof(/area/construction), /area/solar/derelict_starboard, /area/solar/derelict_aft)
|
||||
for(var/A in bad_areas)
|
||||
possible_areas -= A
|
||||
//weight check, remove negative or zero weight areas from the list, then return the list.
|
||||
|
||||
@@ -59,8 +59,7 @@
|
||||
cooldown--
|
||||
if(cooldown <= 0)
|
||||
return FALSE
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
addtimer(CALLBACK(src, .proc/process_cooldown), 10)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/Destroy()
|
||||
@@ -94,8 +93,7 @@
|
||||
if(!secured || cooldown > 0)
|
||||
return FALSE
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
addtimer(CALLBACK(src, .proc/process_cooldown), 10)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/toggle_secure()
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
health_scan = M.health
|
||||
if(health_scan <= alarm_health)
|
||||
pulse()
|
||||
audible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
|
||||
audible_message("[bicon(src)] *beep* *beep*")
|
||||
toggle_scan()
|
||||
return
|
||||
return
|
||||
|
||||
@@ -127,13 +127,12 @@
|
||||
/obj/item/assembly/infra/proc/trigger_beam()
|
||||
if(!secured || !on || cooldown > 0)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
audible_message("[bicon(src)] *beep* *beep*", null, 3)
|
||||
cooldown = 2
|
||||
pulse(FALSE)
|
||||
audible_message("[bicon(src)] *beep* *beep*", hearing_distance = 3)
|
||||
if(first)
|
||||
qdel(first)
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
addtimer(CALLBACK(src, .proc/process_cooldown), 10)
|
||||
|
||||
/obj/item/assembly/infra/interact(mob/user)//TODO: change this this to the wire control panel
|
||||
if(!secured) return
|
||||
|
||||
@@ -47,11 +47,10 @@
|
||||
/obj/item/assembly/prox_sensor/proc/sense()
|
||||
if(!secured || !scanning || cooldown > 0)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
pulse(FALSE)
|
||||
visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
|
||||
addtimer(CALLBACK(src, .proc/process_cooldown), 10)
|
||||
|
||||
/obj/item/assembly/prox_sensor/process()
|
||||
if(timing && (time >= 0))
|
||||
|
||||
@@ -41,8 +41,7 @@
|
||||
if(cooldown > 0)
|
||||
return FALSE
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
addtimer(CALLBACK(src, .proc/process_cooldown), 10)
|
||||
|
||||
signal()
|
||||
return TRUE
|
||||
|
||||
@@ -39,12 +39,11 @@
|
||||
/obj/item/assembly/timer/proc/timer_end()
|
||||
if(!secured || cooldown > 0)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
cooldown = 2
|
||||
pulse(FALSE)
|
||||
if(loc)
|
||||
loc.visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
|
||||
cooldown = 2
|
||||
spawn(10)
|
||||
process_cooldown()
|
||||
addtimer(CALLBACK(src, .proc/process_cooldown), 10)
|
||||
|
||||
/obj/item/assembly/timer/process()
|
||||
if(timing && (time > 0))
|
||||
|
||||
@@ -1,454 +0,0 @@
|
||||
/obj/machinery/computer/general_air_control/atmos_automation
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_screen = "area_atmos"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/atmos_automation
|
||||
req_one_access_txt = "24;10"
|
||||
Mtoollink = 1
|
||||
|
||||
show_sensors = 0
|
||||
var/on = 0
|
||||
|
||||
name = "Atmospherics Automations Console"
|
||||
|
||||
var/list/datum/automation/automations = list()
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/receive_signal(datum/signal/signal)
|
||||
if(!signal || signal.encryption) return
|
||||
|
||||
var/id_tag = signal.data["tag"]
|
||||
if(!id_tag)
|
||||
return
|
||||
|
||||
sensor_information[id_tag] = signal.data
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/process()
|
||||
if(on)
|
||||
for(var/datum/automation/A in automations)
|
||||
A.process()
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/update_icon()
|
||||
icon_state = initial(icon_state)
|
||||
// Broken
|
||||
if(stat & BROKEN)
|
||||
icon_state += "b"
|
||||
|
||||
// Powered
|
||||
else if(stat & NOPOWER)
|
||||
icon_state = initial(icon_state)
|
||||
icon_state += "0"
|
||||
else if(on)
|
||||
icon_state += "_active"
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/proc/request_device_refresh(device)
|
||||
send_signal(list("tag"=device, "status"))
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/proc/send_signal(list/data, filter = RADIO_ATMOSIA)//filter's here so the AAC can cross communicate to things like vents, which have a different filter
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
signal.data=data
|
||||
signal.data["sigtype"]="command"
|
||||
signal.data["advcontrol"]=1//AAC balancing, you need to manually get up to the machine to make it listen to this
|
||||
radio_connection.post_signal(src, signal, range = 8, filter = filter)
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/proc/selectValidChildFor(datum/automation/parent, mob/user, list/valid_returntypes)
|
||||
var/list/choices=list()
|
||||
for(var/childtype in GLOB.automation_types)
|
||||
var/datum/automation/A = new childtype(src)
|
||||
if(A.returntype == null)
|
||||
continue
|
||||
if(!(A.returntype in valid_returntypes))
|
||||
continue
|
||||
choices[A.name]=A
|
||||
if(choices.len==0)
|
||||
testing("Unable to find automations with returntype in [english_list(valid_returntypes)]!")
|
||||
return 0
|
||||
var/label=input(user, "Select new automation:", "Automations", "Cancel") as null|anything in choices
|
||||
if(!label)
|
||||
return 0
|
||||
return choices[label]
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/return_text()
|
||||
var/out=..()
|
||||
|
||||
if(on)
|
||||
out += "<a href=\"?src=[UID()];on=1\" style=\"font-size:large;font-weight:bold;color:red;\">RUNNING</a>"
|
||||
else
|
||||
out += "<a href=\"?src=[UID()];on=1\" style=\"font-size:large;font-weight:bold;color:green;\">STOPPED</a>"
|
||||
|
||||
out += {"
|
||||
<h2>Automations</h2>
|
||||
<p>\[
|
||||
<a href="?src=[UID()];add=1">
|
||||
Add
|
||||
</a>
|
||||
|
|
||||
<a href="?src=[UID()];reset=*">
|
||||
Reset All
|
||||
</a>
|
||||
|
|
||||
<a href="?src=[UID()];remove=*">
|
||||
Clear
|
||||
</a>
|
||||
\]</p>
|
||||
<p>\[
|
||||
<a href="?src=[UID()];dump=1">
|
||||
Export
|
||||
</a>
|
||||
|
|
||||
<a href="?src=[UID()];read=1">
|
||||
Import
|
||||
</a>
|
||||
\]</p>"}
|
||||
if(automations.len==0)
|
||||
out += "<i>No automations present.</i>"
|
||||
else
|
||||
for(var/datum/automation/A in automations)
|
||||
out += {"
|
||||
<fieldset>
|
||||
<legend>
|
||||
<a href="?src=[UID()];label=\ref[A]">[A.label]</a>
|
||||
(<a href="?src=[UID()];reset=\ref[A]">Reset</a> |
|
||||
<a href="?src=[UID()];remove=\ref[A]">×</a>)
|
||||
</legend>
|
||||
[A.GetText()]
|
||||
</fieldset>
|
||||
"}
|
||||
return out
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/Topic(href,href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["on"])
|
||||
on = !on
|
||||
updateUsrDialog()
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
if(href_list["add"])
|
||||
var/new_child=selectValidChildFor(null,usr,list(0))
|
||||
if(!new_child)
|
||||
return 1
|
||||
automations += new_child
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["label"])
|
||||
var/datum/automation/A=locate(href_list["label"])
|
||||
if(!A) return 1
|
||||
var/nl=input(usr, "Please enter a label for this automation task.") as text|null
|
||||
if(!nl) return 1
|
||||
nl = copytext(sanitize(nl), 1, 50)
|
||||
A.label=nl
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["reset"])
|
||||
if(href_list["reset"]=="*")
|
||||
for(var/datum/automation/A in automations)
|
||||
if(!A) continue
|
||||
A.OnReset()
|
||||
else
|
||||
var/datum/automation/A=locate(href_list["reset"])
|
||||
if(!A) return 1
|
||||
A.OnReset()
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["remove"])
|
||||
if(href_list["remove"]=="*")
|
||||
var/confirm=alert("Are you sure you want to remove ALL automations?","Automations","Yes","No")
|
||||
if(confirm == "No") return 0
|
||||
for(var/datum/automation/A in automations)
|
||||
if(!A) continue
|
||||
A.OnRemove()
|
||||
automations.Remove(A)
|
||||
else
|
||||
var/datum/automation/A=locate(href_list["remove"])
|
||||
if(!A) return 1
|
||||
A.OnRemove()
|
||||
automations.Remove(A)
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["read"])
|
||||
var/code = input("Input exported AAC code.","Automations","") as message|null
|
||||
if(!code) return 0
|
||||
ReadCode(code)
|
||||
updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["dump"])
|
||||
input("Exported AAC code:","Automations",DumpCode()) as message|null
|
||||
return 0
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/proc/MakeCompare(datum/automation/a, datum/automation/b, comparetype)
|
||||
var/datum/automation/compare/compare=new(src)
|
||||
compare.comparator = comparetype
|
||||
compare.children[1] = a
|
||||
compare.children[2] = b
|
||||
return compare
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/proc/MakeNumber(value)
|
||||
var/datum/automation/static_value/val = new(src)
|
||||
val.value=value
|
||||
return val
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/proc/MakeGetSensorData(sns_tag,field)
|
||||
var/datum/automation/get_sensor_data/sensor=new(src)
|
||||
sensor.sensor=sns_tag
|
||||
sensor.field=field
|
||||
return sensor
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/proc/DumpCode()
|
||||
var/list/json[0]
|
||||
for(var/datum/automation/A in automations)
|
||||
json += list(A.Export())
|
||||
return json_encode(json)
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/proc/ReadCode(jsonStr)
|
||||
automations.Cut()
|
||||
var/list/json = json_decode(jsonStr)
|
||||
if(json.len>0)
|
||||
for(var/list/cData in json)
|
||||
if(isnull(cData) || !("type" in cData))
|
||||
testing("AAC: Null cData in root JS array.")
|
||||
continue
|
||||
var/Atype=text2path(cData["type"])
|
||||
if(!(Atype in GLOB.automation_types))
|
||||
testing("AAC: Unrecognized Atype [Atype].")
|
||||
continue
|
||||
var/datum/automation/A = new Atype(src)
|
||||
A.Import(cData)
|
||||
automations += A
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/burnchamber
|
||||
var/injector_tag="inc_in"
|
||||
var/output_tag="inc_out"
|
||||
var/sensor_tag="inc_sensor"
|
||||
frequency=AIRLOCK_FREQ
|
||||
var/temperature=1000
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/burnchamber/New()
|
||||
..()
|
||||
|
||||
// On State
|
||||
// Pretty much this:
|
||||
/*
|
||||
if(get_sensor("inc_sensor","temperature") < 200)
|
||||
set_injector_state("inc_in",1)
|
||||
set_vent_pump_power("inc_out",0)
|
||||
else
|
||||
set_vent_pump_power("inc_out",1
|
||||
*/
|
||||
|
||||
var/datum/automation/get_sensor_data/sensor=new(src)
|
||||
sensor.sensor=sensor_tag
|
||||
sensor.field="temperature"
|
||||
|
||||
var/datum/automation/static_value/val = new(src)
|
||||
val.value=temperature - 800
|
||||
|
||||
var/datum/automation/compare/compare=new(src)
|
||||
compare.comparator = "Less Than"
|
||||
compare.children[1] = sensor
|
||||
compare.children[2] = val
|
||||
|
||||
var/datum/automation/set_injector_power/inj_on=new(src)
|
||||
inj_on.injector=injector_tag
|
||||
inj_on.state=1
|
||||
|
||||
var/datum/automation/set_vent_pump_power/vp_on=new(src)
|
||||
vp_on.vent_pump=output_tag
|
||||
vp_on.state=1
|
||||
|
||||
var/datum/automation/set_vent_pump_power/vp_off=new(src)
|
||||
vp_off.vent_pump=output_tag
|
||||
vp_off.state=0
|
||||
|
||||
var/datum/automation/if_statement/i = new (src)
|
||||
i.label = "Fuel Injector On"
|
||||
i.condition = compare
|
||||
i.children_then.Add(inj_on)
|
||||
i.children_then.Add(vp_off)
|
||||
i.children_else.Add(vp_on)
|
||||
|
||||
automations += i
|
||||
|
||||
// Off state
|
||||
/*
|
||||
if(get_sensor("inc_sensor","temperature") > 1000)
|
||||
set_injector_state("inc_in",0)
|
||||
*/
|
||||
sensor=new(src)
|
||||
sensor.sensor=sensor_tag
|
||||
sensor.field="temperature"
|
||||
|
||||
val = new(src)
|
||||
val.value=temperature
|
||||
|
||||
compare=new(src)
|
||||
compare.comparator = "Greater Than"
|
||||
compare.children[1] = sensor
|
||||
compare.children[2] = val
|
||||
|
||||
var/datum/automation/set_injector_power/inj_off=new(src)
|
||||
inj_off.injector=injector_tag
|
||||
inj_off.state=0
|
||||
|
||||
i = new (src)
|
||||
i.label = "Fuel Injector Off"
|
||||
i.condition = compare
|
||||
i.children_then.Add(inj_off)
|
||||
|
||||
automations += i
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/air_mixing
|
||||
var/n2_injector_tag="air_n2_in"
|
||||
var/o2_injector_tag="air_o2_in"
|
||||
var/output_tag="air_out"
|
||||
var/sensor_tag="air_sensor"
|
||||
frequency=ATMOS_DISTRO_FREQ
|
||||
var/temperature=1000
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/air_mixing/New()
|
||||
..()
|
||||
buildO2()
|
||||
buildN2()
|
||||
buildOutletVent()
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/air_mixing/proc/buildO2()
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Oxygen Injection
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
var/datum/automation/set_injector_power/inj_on=new(src)
|
||||
inj_on.injector=o2_injector_tag
|
||||
inj_on.state=1
|
||||
|
||||
var/datum/automation/set_injector_power/inj_off=new(src)
|
||||
inj_off.injector=o2_injector_tag
|
||||
inj_off.state=0
|
||||
|
||||
var/datum/automation/if_statement/i = new (src)
|
||||
i.label = "Oxygen Injection"
|
||||
i.condition = MakeCompare(
|
||||
MakeGetSensorData(sensor_tag,"oxygen"),
|
||||
MakeNumber(20),
|
||||
"Less Than or Equal to"
|
||||
)
|
||||
i.children_then.Add(inj_on)
|
||||
i.children_else.Add(inj_off)
|
||||
|
||||
automations += i
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/air_mixing/proc/buildN2()
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Nitrogen Injection
|
||||
///////////////////////////////////////////////////////////////
|
||||
/*
|
||||
if(get_sensor_data("pressure") < 100)
|
||||
injector_on()
|
||||
else
|
||||
if(get_sensor_data("pressure") > 5000)
|
||||
injector_off()
|
||||
*/
|
||||
|
||||
var/datum/automation/set_injector_power/inj_on=new(src)
|
||||
inj_on.injector=n2_injector_tag
|
||||
inj_on.state=1
|
||||
|
||||
var/datum/automation/set_injector_power/inj_off=new(src)
|
||||
inj_off.injector=n2_injector_tag
|
||||
inj_off.state=0
|
||||
|
||||
var/datum/automation/if_statement/if_on = new (src)
|
||||
if_on.label = "Nitrogen Injection"
|
||||
if_on.condition = MakeCompare(
|
||||
MakeGetSensorData(sensor_tag,"pressure"),
|
||||
MakeNumber(100),
|
||||
"Less Than"
|
||||
)
|
||||
if_on.children_then.Add(inj_on)
|
||||
|
||||
|
||||
var/datum/automation/if_statement/if_off=new(src)
|
||||
if_off.condition=MakeCompare(
|
||||
MakeGetSensorData(sensor_tag,"pressure"),
|
||||
MakeNumber(5000),
|
||||
"Greater Than"
|
||||
)
|
||||
if_off.children_then.Add(inj_off)
|
||||
|
||||
if_on.children_else.Add(if_off)
|
||||
|
||||
automations += if_on
|
||||
|
||||
/obj/machinery/computer/general_air_control/atmos_automation/air_mixing/proc/buildOutletVent()
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Outlet Management
|
||||
///////////////////////////////////////////////////////////////
|
||||
/*
|
||||
if(get_sensor_data("pressure") >= 5000 && get_sensor_data("oxygen") >= 20)
|
||||
vent_on()
|
||||
else
|
||||
if(get_sensor_data("oxygen") < 20 || get_sensor_data("pressure") < 100)
|
||||
vent_off()
|
||||
*/
|
||||
|
||||
var/datum/automation/set_vent_pump_power/vp_on=new(src)
|
||||
vp_on.vent_pump=output_tag
|
||||
vp_on.state=1
|
||||
|
||||
var/datum/automation/set_vent_pump_power/vp_off=new(src)
|
||||
vp_off.vent_pump=output_tag
|
||||
vp_off.state=0
|
||||
|
||||
var/datum/automation/if_statement/if_on=new(src)
|
||||
if_on.label="Air Output"
|
||||
|
||||
var/datum/automation/and/and_on=new(src)
|
||||
and_on.children.Add(
|
||||
MakeCompare(
|
||||
MakeGetSensorData(sensor_tag,"pressure"),
|
||||
MakeNumber(5000),
|
||||
"Greater Than or Equal to"
|
||||
)
|
||||
)
|
||||
and_on.children.Add(
|
||||
MakeCompare(
|
||||
MakeGetSensorData(sensor_tag,"oxygen"),
|
||||
MakeNumber(20),
|
||||
"Greater Than or Equal to"
|
||||
)
|
||||
)
|
||||
if_on.condition=and_on
|
||||
if_on.children_then.Add(vp_on)
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
var/datum/automation/if_statement/if_off=new(src)
|
||||
|
||||
var/datum/automation/or/or_off=new(src)
|
||||
or_off.children.Add(
|
||||
MakeCompare(
|
||||
MakeGetSensorData(sensor_tag,"pressure"),
|
||||
MakeNumber(100),
|
||||
"Less Than"
|
||||
)
|
||||
)
|
||||
or_off.children.Add(
|
||||
MakeCompare(
|
||||
MakeGetSensorData(sensor_tag,"oxygen"),
|
||||
MakeNumber(20),
|
||||
"Less Than"
|
||||
)
|
||||
)
|
||||
if_off.condition=or_off
|
||||
if_off.children_then.Add(vp_off)
|
||||
|
||||
if_on.children_else.Add(if_off)
|
||||
|
||||
automations += if_on
|
||||
@@ -1,44 +0,0 @@
|
||||
|
||||
|
||||
/datum/automation/set_valve_state
|
||||
name = "Digital Valve: Set Open/Closed"
|
||||
var/valve=null
|
||||
var/state=0
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["valve"]=valve
|
||||
json["state"]=state
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
valve = json["valve"]
|
||||
state = text2num(json["state"])
|
||||
|
||||
process()
|
||||
if(valve)
|
||||
parent.send_signal(list ("tag" = valve, "command"="valve_set","valve_set"=state))
|
||||
return 0
|
||||
|
||||
GetText()
|
||||
return "Set digital valve <a href=\"?src=[UID()];set_subject=1\">[fmtString(valve)]</a> to <a href=\"?src=[UID()];set_state=1\">[state?"open":"closed"]</a>."
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["set_state"])
|
||||
state=!state
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["set_subject"])
|
||||
var/list/valves=list()
|
||||
for(var/obj/machinery/atmospherics/binary/valve/digital/V in world)
|
||||
if(!isnull(V.id_tag) && V.frequency == parent.frequency)
|
||||
valves|=V.id_tag
|
||||
if(valves.len==0)
|
||||
to_chat(usr, "<span class='warning'>Unable to find any digital valves on this frequency.</span>")
|
||||
return
|
||||
valve = input("Select a valve:", "Sensor Data", valve) as null|anything in valves
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
@@ -1,42 +0,0 @@
|
||||
/datum/automation/set_emitter_power
|
||||
name = "Emitter: Set Power"
|
||||
var/emitter=null
|
||||
var/on=0
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["emitter"]=emitter
|
||||
json["on"]=on
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
emitter = json["emitter"]
|
||||
on = text2num(json["on"])
|
||||
|
||||
process()
|
||||
if(emitter)
|
||||
parent.send_signal(list("tag" = emitter, "command"="set", "state" = on, "hiddenprints" = parent.fingerprintshidden))
|
||||
return 0
|
||||
|
||||
GetText()
|
||||
return "Set emitter <a href=\"?src=[UID()];set_subject=1\">[fmtString(emitter)]</a> to <a href=\"?src=[UID()];set_power=1\">[on?"on":"off"]</a>."
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["set_power"])
|
||||
on=!on
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["set_subject"])
|
||||
var/list/emitters=list()
|
||||
for(var/obj/machinery/power/emitter/E in GLOB.machines)
|
||||
if(!isnull(E.id_tag) && E.frequency == parent.frequency)
|
||||
emitters|=E.id_tag
|
||||
if(emitters.len==0)
|
||||
to_chat(usr, "<span class='warning'>Unable to find any emitters on this frequency.</span>")
|
||||
return
|
||||
emitter = input("Select an emitter:", "Emitter", emitter) as null|anything in emitters
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
@@ -1,83 +0,0 @@
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Injector
|
||||
////////////////////////////////////////////
|
||||
/datum/automation/set_injector_power
|
||||
name = "Injector: Power"
|
||||
var/injector=null
|
||||
var/state=0
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["injector"]=injector
|
||||
json["state"]=state
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
injector = json["injector"]
|
||||
state = text2num(json["state"])
|
||||
|
||||
process()
|
||||
if(injector)
|
||||
parent.send_signal(list ("tag" = injector, "power"=state))
|
||||
return 0
|
||||
|
||||
GetText()
|
||||
return "Set injector <a href=\"?src=[UID()];set_injector=1\">[fmtString(injector)]</a> power to <a href=\"?src=[UID()];toggle_state=1\">[state ? "on" : "off"]</a>."
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["toggle_state"])
|
||||
state = !state
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["set_injector"])
|
||||
var/list/injector_names=list()
|
||||
for(var/obj/machinery/atmospherics/unary/outlet_injector/I in GLOB.machines)
|
||||
if(!isnull(I.id_tag) && I.frequency == parent.frequency)
|
||||
injector_names|=I.id_tag
|
||||
injector = input("Select an injector:", "Sensor Data", injector) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
/datum/automation/set_injector_rate
|
||||
name = "Injector: Rate"
|
||||
var/injector = null
|
||||
var/rate = 0
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["injector"] = injector
|
||||
json["rate"] = rate
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
injector = json["injector"]
|
||||
rate = text2num(json["rate"])
|
||||
|
||||
process()
|
||||
if(injector)
|
||||
parent.send_signal(list ("tag" = injector, "set_volume_rate"=rate))
|
||||
return 0
|
||||
|
||||
GetText()
|
||||
return "Set injector <a href=\"?src=[UID()];set_injector=1\">[fmtString(injector)]</a> transfer rate to <a href=\"?src=[UID()];set_rate=1\">[rate]</a> L/s."
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["set_rate"])
|
||||
rate = input("Set rate in L/s.", "Rate", rate) as num
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["set_injector"])
|
||||
var/list/injector_names=list()
|
||||
for(var/obj/machinery/atmospherics/unary/outlet_injector/I in GLOB.machines)
|
||||
if(!isnull(I.id_tag) && I.frequency == parent.frequency)
|
||||
injector_names|=I.id_tag
|
||||
injector = input("Select an injector:", "Sensor Data", injector) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
@@ -1,153 +0,0 @@
|
||||
/datum/automation/set_scrubber_mode
|
||||
name="Scrubber: Mode"
|
||||
|
||||
var/scrubber=null
|
||||
var/mode=1
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["scrubber"]=scrubber
|
||||
json["mode"]=mode
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
scrubber = json["scrubber"]
|
||||
mode = text2num(json["mode"])
|
||||
|
||||
New(var/obj/machinery/computer/general_air_control/atmos_automation/aa)
|
||||
..(aa)
|
||||
children=list(null)
|
||||
|
||||
process()
|
||||
if(scrubber)
|
||||
parent.send_signal(list ("tag" = scrubber, "sigtype"="command", "scrubbing"=mode),filter = RADIO_FROM_AIRALARM)
|
||||
return 0
|
||||
|
||||
GetText()
|
||||
return "Set Scrubber <a href=\"?src=[UID()];set_scrubber=1\">[fmtString(scrubber)]</a> mode to <a href=\"?src=[UID()];set_mode=1\">[mode?"Scrubbing":"Syphoning"]</a>."
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..()) return
|
||||
if(href_list["set_mode"])
|
||||
mode=!mode
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["set_scrubber"])
|
||||
var/list/injector_names=list()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_scrubber/S in GLOB.machines)
|
||||
if(!isnull(S.id_tag) && S.frequency == parent.frequency)
|
||||
injector_names|=S.id_tag
|
||||
scrubber = input("Select a scrubber:", "Scrubbers", scrubber) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
/datum/automation/set_scrubber_power
|
||||
name="Scrubber: Power"
|
||||
|
||||
var/scrubber=null
|
||||
var/state=0
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["scrubber"]=scrubber
|
||||
json["state"]=state
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
scrubber = json["scrubber"]
|
||||
state = text2num(json["state"])
|
||||
|
||||
New(var/obj/machinery/computer/general_air_control/atmos_automation/aa)
|
||||
..(aa)
|
||||
|
||||
process()
|
||||
if(scrubber)
|
||||
parent.send_signal(list ("tag" = scrubber, "sigtype"="command", "power"=state),filter = RADIO_FROM_AIRALARM)
|
||||
|
||||
GetText()
|
||||
return "Set Scrubber <a href=\"?src=[UID()];set_scrubber=1\">[fmtString(scrubber)]</a> power to <a href=\"?src=[UID()];set_power=1\">[state ? "on" : "off"]</a>."
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..()) return
|
||||
if(href_list["set_power"])
|
||||
state = !state
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["set_scrubber"])
|
||||
var/list/injector_names=list()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_scrubber/S in GLOB.machines)
|
||||
if(!isnull(S.id_tag) && S.frequency == parent.frequency)
|
||||
injector_names|=S.id_tag
|
||||
scrubber = input("Select a scrubber:", "Scrubbers", scrubber) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
GLOBAL_LIST_INIT(gas_labels, list(
|
||||
"co2" = "CO<sub>2</sub>",
|
||||
"tox" = "Plasma",
|
||||
"n2o" = "N<sub>2</sub>O",
|
||||
"o2" = "O<sub>2</sub>",
|
||||
"n2" = "N<sub>2</sub>"
|
||||
))
|
||||
/datum/automation/set_scrubber_gasses
|
||||
name="Scrubber: Gasses"
|
||||
|
||||
var/scrubber=null
|
||||
var/list/gasses=list(
|
||||
"co2" = 1,
|
||||
"tox" = 0,
|
||||
"n2o" = 0,
|
||||
"o2" = 0,
|
||||
"n2" = 0
|
||||
)
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["scrubber"]=scrubber
|
||||
json["gasses"]=gasses
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
scrubber = json["scrubber"]
|
||||
|
||||
var/list/newgasses=json["gasses"]
|
||||
for(var/key in newgasses)
|
||||
gasses[key]=newgasses[key]
|
||||
|
||||
|
||||
New(var/obj/machinery/computer/general_air_control/atmos_automation/aa)
|
||||
..(aa)
|
||||
|
||||
process()
|
||||
if(scrubber)
|
||||
var/list/data = list ("tag" = scrubber, "sigtype"="command")
|
||||
for(var/gas in gasses)
|
||||
data[gas+"_scrub"]=gasses[gas]
|
||||
parent.send_signal(data,filter = RADIO_FROM_AIRALARM)
|
||||
|
||||
GetText()
|
||||
var/txt = "Set Scrubber <a href=\"?src=[UID()];set_scrubber=1\">[fmtString(scrubber)]</a> to scrub "
|
||||
for(var/gas in gasses)
|
||||
txt += " [GLOB.gas_labels[gas]] (<a href=\"?src=[UID()];tog_gas=[gas]\">[gasses[gas] ? "on" : "off"]</a>),"
|
||||
return txt
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..()) return
|
||||
if(href_list["tog_gas"])
|
||||
var/gas = href_list["tog_gas"]
|
||||
if(!(gas in gasses))
|
||||
return
|
||||
gasses[gas] = !gasses[gas]
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["set_scrubber"])
|
||||
var/list/injector_names=list()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_scrubber/S in GLOB.machines)
|
||||
if(!isnull(S.id_tag) && S.frequency == parent.frequency)
|
||||
injector_names|=S.id_tag
|
||||
scrubber = input("Select a scrubber:", "Scrubbers", scrubber) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
@@ -1,56 +0,0 @@
|
||||
|
||||
///////////////////////////////////////////
|
||||
// sensor data
|
||||
///////////////////////////////////////////
|
||||
|
||||
/datum/automation/get_sensor_data
|
||||
name = "Sensor: Get Data"
|
||||
var/field="temperature"
|
||||
var/sensor=null
|
||||
|
||||
returntype=AUTOM_RT_NUM
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["sensor"]=sensor
|
||||
json["field"]=field
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
sensor = json["sensor"]
|
||||
field = json["field"]
|
||||
|
||||
Evaluate()
|
||||
if(sensor && field && (sensor in parent.sensor_information))
|
||||
return parent.sensor_information[sensor][field]
|
||||
return 0
|
||||
|
||||
GetText()
|
||||
return "<a href=\"?src=[UID()];set_field=1\">[fmtString(field)]</a> from sensor <a href=\"?src=[UID()];set_sensor=1\">[fmtString(sensor)]</a>"
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["set_field"])
|
||||
field = input("Select a sensor output:", "Sensor Data", field) as null|anything in list(
|
||||
"temperature",
|
||||
"pressure",
|
||||
"oxygen",
|
||||
"toxins",
|
||||
"nitrogen",
|
||||
"carbon_dioxide"
|
||||
)
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["set_sensor"])
|
||||
var/list/sensor_list = list()
|
||||
for(var/obj/machinery/air_sensor/G in GLOB.machines)
|
||||
if(!isnull(G.id_tag) && G.frequency == parent.frequency)
|
||||
sensor_list|=G.id_tag
|
||||
for(var/obj/machinery/meter/M in GLOB.machines)
|
||||
if(!isnull(M.id_tag) && M.frequency == parent.frequency)
|
||||
sensor_list|=M.id_tag
|
||||
sensor = input("Select a sensor:", "Sensor Data", field) as null|anything in sensor_list
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
@@ -1,314 +0,0 @@
|
||||
/datum/automation/set_vent_pump_mode
|
||||
name="Vent Pump: Mode"
|
||||
|
||||
var/vent_pump = null
|
||||
var/mode = "stabilize"
|
||||
var/vent_type = 0//0 for unary vents, 1 for DP vents
|
||||
|
||||
var/list/modes = list("stabilize","purge")
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["vent_pump"] = vent_pump
|
||||
json["mode"] = mode
|
||||
json["vent_type"] = vent_type
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
vent_pump = json["vent_pump"]
|
||||
mode = json["mode"]
|
||||
vent_type = text2num(json["vent_type"])
|
||||
|
||||
process()
|
||||
if(vent_pump)
|
||||
var/dirvalue = (mode == "stabilize" ? 1 : mode == "purge" ? 0 : 1)
|
||||
parent.send_signal(list("tag" = vent_pump, "direction" = dirvalue), filter = (vent_type ? RADIO_ATMOSIA : RADIO_FROM_AIRALARM))
|
||||
return 0
|
||||
|
||||
GetText()
|
||||
return "Set <a href=\"?src=[UID()];toggle_type=1\">[vent_type ? "Dual-Port" : "Unary"]</a> vent pump <a href=\"?src=[UID()];set_vent_pump=1\">[fmtString(vent_pump)]</a> mode to <a href=\"?src=[UID()];set_mode=1\">[mode]</a>."
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["set_mode"])
|
||||
mode = input("Select a mode to put this pump into.",mode) in modes
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["set_vent_pump"])
|
||||
var/list/injector_names = list()
|
||||
if(!vent_type)
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/I in GLOB.machines)
|
||||
if(!isnull(I.id_tag) && I.frequency == parent.frequency)
|
||||
injector_names |= I.id_tag
|
||||
else
|
||||
for(var/obj/machinery/atmospherics/binary/dp_vent_pump/I in world)
|
||||
// to_chat(world, "test")
|
||||
if(!isnull(I.id_tag) && I.frequency == parent.frequency)
|
||||
injector_names |= I.id_tag
|
||||
|
||||
vent_pump = input("Select a vent:", "Vent Pumps", vent_pump) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["toggle_type"])
|
||||
vent_type = !vent_type
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
/datum/automation/set_vent_pump_power
|
||||
name="Vent Pump: Power"
|
||||
|
||||
var/vent_pump = null
|
||||
var/state = 0
|
||||
var/mode = 0//0 for unary vents, 1 for DP vents.
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["vent_pump"] = vent_pump
|
||||
json["state"] = state
|
||||
json["mode"] = mode
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
vent_pump = json["vent_pump"]
|
||||
state = text2num(json["state"])
|
||||
mode = text2num(json["mode"])
|
||||
|
||||
process()
|
||||
if(vent_pump)
|
||||
parent.send_signal(list ("tag" = vent_pump, "power" = state), filter = (mode ? RADIO_ATMOSIA : RADIO_FROM_AIRALARM))
|
||||
|
||||
GetText()
|
||||
return "Set <a href=\"?src=[UID()];toggle_mode=1\">[mode ? "Dual-Port" : "Unary"]</a> vent pump <a href=\"?src=[UID()];set_vent_pump=1\">[fmtString(vent_pump)]</a> power to <a href=\"?src=[UID()];set_power=1\">[state ? "on" : "off"]</a>."
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["set_power"])
|
||||
state = !state
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["set_vent_pump"])
|
||||
var/list/injector_names=list()
|
||||
if(!mode)
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/I in GLOB.machines)
|
||||
if(!isnull(I.id_tag) && I.frequency == parent.frequency)
|
||||
injector_names|=I.id_tag
|
||||
else
|
||||
for(var/obj/machinery/atmospherics/binary/dp_vent_pump/I in world)
|
||||
if(!isnull(I.id_tag) && I.frequency == parent.frequency)
|
||||
injector_names|=I.id_tag
|
||||
vent_pump = input("Select a vent:", "Vent Pumps", vent_pump) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["toggle_mode"])
|
||||
mode = !mode
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
/datum/automation/set_vent_pump_pressure//controls the internal/external pressure bounds of a vent pump.
|
||||
name = "Vent Pump: Pressure Settings"
|
||||
|
||||
var/vent_pump = null
|
||||
var/intpressureout = 0//these 2 are for DP vents, if it's a unary vent you're sending to it will take intpressureout as var
|
||||
var/intpressurein = 0
|
||||
var/extpressure = 0
|
||||
var/mode = 0//0 for unary vents, 1 for DP vents.
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["vent_pump"] = vent_pump
|
||||
json["intpressureout"] = intpressureout
|
||||
json["intpressurein"] = intpressurein
|
||||
json["extpressure"] = extpressure
|
||||
json["mode"] = mode
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
vent_pump = json["vent_pump"]
|
||||
intpressureout = text2num(json["intpressureout"])
|
||||
intpressurein = text2num(json["intpressurein"])
|
||||
extpressure = text2num(json["extpressure"])
|
||||
mode = text2num(json["mode"])
|
||||
|
||||
New(var/obj/machinery/computer/general_air_control/atmos_automation/aa)
|
||||
..(aa)
|
||||
|
||||
process()
|
||||
if(vent_pump)
|
||||
var/list/data = list( \
|
||||
"tag" = vent_pump, \
|
||||
)
|
||||
var/filter = RADIO_ATMOSIA
|
||||
if(mode)//it's a DP vent
|
||||
if(intpressurein)
|
||||
data.Add(list("set_input_pressure" = intpressurein))
|
||||
if(intpressureout)
|
||||
data.Add(list("set_output_pressure" = intpressureout))
|
||||
if(extpressure)
|
||||
data.Add(list("set_external_pressure" = extpressure))
|
||||
|
||||
else
|
||||
if(intpressureout)
|
||||
data.Add(list("set_internal_pressure" = intpressureout))
|
||||
if(extpressure)
|
||||
data.Add(list("set_external_pressure" = extpressure))
|
||||
filter = RADIO_FROM_AIRALARM
|
||||
|
||||
parent.send_signal(data, filter)
|
||||
|
||||
GetText()
|
||||
if(mode)//DP vent
|
||||
return {"Set <a href=\"?src=[UID()];swap_modes=1\">dual-port</a> vent pump <a href=\"?src=[UID()];set_vent_pump=1\">[fmtString(vent_pump)]</a>
|
||||
pressure bounds: internal outwards: <a href=\"?src=[UID()];set_intpressure_out=1">[fmtString(intpressureout)]</a>
|
||||
internal inwards: <a href=\"?src=[UID()];set_intpressure_in=1">[fmtString(intpressurein)]</a>
|
||||
external: <a href=\"?src=[UID()];set_external=1">[fmtString(extpressure)]</a>
|
||||
"}//well that was a lot to type
|
||||
else
|
||||
return {"Set <a href=\"?src=[UID()];swap_modes=1\">unary</a> vent pump <a href=\"?src=[UID()];set_vent_pump=1\">[fmtString(vent_pump)]</a>
|
||||
pressure bounds: internal: <a href=\"?src=[UID()];set_intpressure_out=1">[fmtString(intpressureout)]</a>
|
||||
external: <a href=\"?src=[UID()];set_external=1">[fmtString(extpressure)]</a>
|
||||
"}//copy paste FTW
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["set_vent_pump"])
|
||||
var/list/injector_names=list()
|
||||
if(mode)//DP vent selection
|
||||
for(var/obj/machinery/atmospherics/binary/dp_vent_pump/I in world)
|
||||
if(!isnull(I.id_tag) && I.frequency == parent.frequency)
|
||||
injector_names|=I.id_tag
|
||||
else
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/I in GLOB.machines)
|
||||
if(!isnull(I.id_tag) && I.frequency == parent.frequency)
|
||||
injector_names|=I.id_tag
|
||||
vent_pump = input("Select a vent:", "Vent Pumps", vent_pump) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["set_intpressure_out"])
|
||||
var/response = input("Set new pressure, in kPa. \[0-[50*ONE_ATMOSPHERE]\]") as num
|
||||
intpressureout = text2num(response)
|
||||
intpressureout = between(0, intpressureout, 50*ONE_ATMOSPHERE)
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["set_intpressure_in"])
|
||||
var/response = input("Set new pressure, in kPa. \[0-[50*ONE_ATMOSPHERE]\]") as num
|
||||
intpressurein = text2num(response)
|
||||
intpressurein = between(0, intpressurein, 50*ONE_ATMOSPHERE)
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["set_external"])
|
||||
var/response = input(usr,"Set new pressure, in kPa. \[0-[50*ONE_ATMOSPHERE]\]") as num
|
||||
extpressure = text2num(response)
|
||||
extpressure = between(0, extpressure, 50*ONE_ATMOSPHERE)
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["swap_modes"])
|
||||
mode = !mode
|
||||
vent_pump = null//if we don't clear this is could get glitchy, by which I mean not at all, whatever, stay clean
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
/datum/automation/set_vent_pressure_checks
|
||||
name = "Vent Pump: Pressure Checks"
|
||||
|
||||
var/vent_pump = null
|
||||
var/checks = 1
|
||||
var/mode = 0//1 for DP vent, 0 for unary vent
|
||||
/*
|
||||
checks bitflags
|
||||
1 = external
|
||||
2 = internal in (regular internal for unaries)
|
||||
4 = internal out (ignored by unaries)
|
||||
*/
|
||||
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["vent_pump"] = vent_pump
|
||||
json["checks"] = checks
|
||||
json["mode"] = mode
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
vent_pump = json["vent_pump"]
|
||||
checks = text2num(json["checks"])
|
||||
mode = text2num(json["mode"])
|
||||
|
||||
New(var/obj/machinery/computer/general_air_control/atmos_automation/aa)
|
||||
..(aa)
|
||||
|
||||
process()
|
||||
if(vent_pump)
|
||||
parent.send_signal(list("tag" = vent_pump, "checks" = checks), filter = (mode ? RADIO_ATMOSIA : RADIO_FROM_AIRALARM))//not gonna bother with a sanity check here, there *should* not be any problems
|
||||
|
||||
GetText()
|
||||
if(mode)
|
||||
return {"Set <a href=\"?src=[UID()];swap_modes=1\">dual-port</a> vent pump <a href=\"?src=[UID()];set_vent_pump=1\">[fmtString(vent_pump)]</a> pressure checks to:
|
||||
external <a href=\"?src=[UID()];togglecheck=1\">[checks&1 ? "Enabled" : "Disabled"]</a>
|
||||
internal inwards <a href=\"?src=[UID()];togglecheck=2\">[checks&2 ? "Enabled" : "Disabled"]</a>
|
||||
internal outwards <a href=\"?src=[UID()];togglecheck=4\">[checks&4 ? "Enabled" : "Disabled"]</a>
|
||||
"}
|
||||
else
|
||||
return {"Set <a href=\"?src=[UID()];swap_modes=1\">unary</a> vent pump <a href=\"?src=[UID()];set_vent_pump=1\">[fmtString(vent_pump)]</a> pressure checks to:
|
||||
external: <a href=\"?src=[UID()];togglecheck=1\">[checks&1 ? "Enabled" : "Disabled"]</a>,
|
||||
internal: <a href=\"?src=[UID()];togglecheck=2\">[checks&2 ? "Enabled" : "Disabled"]</a>
|
||||
"}
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if(href_list["set_vent_pump"])
|
||||
var/list/injector_names=list()
|
||||
if(mode)//DP vent selection
|
||||
for(var/obj/machinery/atmospherics/binary/dp_vent_pump/I in world)
|
||||
if(!isnull(I.id_tag) && I.frequency == parent.frequency)
|
||||
injector_names|=I.id_tag
|
||||
else
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/I in GLOB.machines)
|
||||
if(!isnull(I.id_tag) && I.frequency == parent.frequency)
|
||||
injector_names|=I.id_tag
|
||||
vent_pump = input("Select a vent:", "Vent Pumps", vent_pump) as null|anything in injector_names
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["swap_modes"])
|
||||
mode = !mode
|
||||
vent_pump = null//if we don't clear this is could get glitchy, by which I mean not at all, whatever, stay clean
|
||||
if(!mode && checks&4)//disable this bitflag since we're switching to unaries
|
||||
checks &= ~4
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["togglecheck"])
|
||||
var/bitflagvalue = text2num(href_list["togglecheck"])
|
||||
if(mode)
|
||||
if(!(bitflagvalue in list(1, 2, 4)))
|
||||
return 0
|
||||
else if(!(bitflagvalue in list(1, 2)))
|
||||
return 0
|
||||
|
||||
if(checks&bitflagvalue)//the bitflag is on ATM
|
||||
checks &= ~bitflagvalue
|
||||
else//can't not be off
|
||||
checks |= bitflagvalue
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
@@ -1,457 +0,0 @@
|
||||
GLOBAL_LIST_INIT(automation_types, subtypesof(/datum/automation))
|
||||
|
||||
#define AUTOM_RT_NULL 0
|
||||
#define AUTOM_RT_NUM 1
|
||||
#define AUTOM_RT_STRING 2
|
||||
/datum/automation
|
||||
// Name of the Automation
|
||||
var/name="Base Automation"
|
||||
|
||||
// For labelling what shit does on the AAC.
|
||||
var/label="Unnamed Script"
|
||||
var/desc ="No Description."
|
||||
|
||||
var/obj/machinery/computer/general_air_control/atmos_automation/parent
|
||||
var/list/valid_child_returntypes=list()
|
||||
var/list/datum/automation/children=list()
|
||||
|
||||
var/returntype=AUTOM_RT_NULL
|
||||
|
||||
/datum/automation/New(var/obj/machinery/computer/general_air_control/atmos_automation/aa)
|
||||
parent=aa
|
||||
|
||||
/datum/automation/proc/GetText()
|
||||
return "[type] doesn't override GetText()!"
|
||||
|
||||
/datum/automation/proc/OnReset()
|
||||
return
|
||||
|
||||
/datum/automation/proc/OnRemove()
|
||||
return
|
||||
|
||||
/datum/automation/process()
|
||||
return
|
||||
|
||||
/datum/automation/proc/Evaluate()
|
||||
return 0
|
||||
|
||||
/datum/automation/proc/Export()
|
||||
var/list/R = list("type"=type)
|
||||
|
||||
if(initial(label)!=label)
|
||||
R["label"]=label
|
||||
|
||||
if(initial(desc)!=desc)
|
||||
R["desc"]=desc
|
||||
|
||||
if(children.len>0)
|
||||
var/list/C=list()
|
||||
for(var/datum/automation/A in children)
|
||||
C += list(A.Export())
|
||||
R["children"]=C
|
||||
|
||||
return R
|
||||
|
||||
/datum/automation/proc/unpackChild(var/list/cData)
|
||||
if(isnull(cData) || !("type" in cData))
|
||||
return null
|
||||
var/Atype=text2path(cData["type"])
|
||||
if(!(Atype in GLOB.automation_types))
|
||||
return null
|
||||
var/datum/automation/A = new Atype(parent)
|
||||
A.Import(cData)
|
||||
return A
|
||||
|
||||
/datum/automation/proc/unpackChildren(var/list/childList)
|
||||
. = list()
|
||||
if(childList.len>0)
|
||||
for(var/list/cData in childList)
|
||||
if(isnull(cData) || !("type" in cData))
|
||||
. += null
|
||||
continue
|
||||
var/Atype=text2path(cData["type"])
|
||||
if(!(Atype in GLOB.automation_types))
|
||||
continue
|
||||
var/datum/automation/A = new Atype(parent)
|
||||
A.Import(cData)
|
||||
. += A
|
||||
|
||||
/datum/automation/proc/packChildren(var/list/childList)
|
||||
. = list()
|
||||
if(childList.len>0)
|
||||
for(var/datum/automation/A in childList)
|
||||
if(isnull(A) || !istype(A))
|
||||
. += null
|
||||
continue
|
||||
. += list(A.Export())
|
||||
|
||||
/datum/automation/proc/Import(var/list/json)
|
||||
if("label" in json)
|
||||
label = json["label"]
|
||||
|
||||
if("desc" in json)
|
||||
desc = json["desc"]
|
||||
|
||||
if("children" in json)
|
||||
children = unpackChildren(json["children"])
|
||||
|
||||
/datum/automation/proc/fmtString(var/str)
|
||||
if(str==null || str == "")
|
||||
return "-----"
|
||||
return str
|
||||
|
||||
/datum/automation/Topic(href,href_list)
|
||||
if(parent.Topic("src=[parent.UID()]", list("src" = parent)))//dumb hack to check sanity, empty topic shouldn't trigger a 1 on anything but sanity checks
|
||||
return 1
|
||||
|
||||
if(href_list["add"])
|
||||
var/new_child=selectValidChildFor(usr)
|
||||
if(!new_child) return 1
|
||||
children += new_child
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["remove"])
|
||||
if(href_list["remove"]=="*")
|
||||
var/confirm=alert("Are you sure you want to remove ALL automations?","Automations","Yes","No")
|
||||
if(confirm == "No") return 0
|
||||
for(var/datum/automation/A in children)
|
||||
A.OnRemove()
|
||||
children.Remove(A)
|
||||
else
|
||||
var/datum/automation/A=locate(href_list["remove"])
|
||||
if(!A) return 1
|
||||
var/confirm=alert("Are you sure you want to remove this automation?","Automations","Yes","No")
|
||||
if(confirm == "No") return 0
|
||||
A.OnRemove()
|
||||
children.Remove(A)
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
if(href_list["reset"])
|
||||
if(href_list["reset"]=="*")
|
||||
for(var/datum/automation/A in children)
|
||||
A.OnReset()
|
||||
else
|
||||
var/datum/automation/A=locate(href_list["reset"])
|
||||
if(!A) return 1
|
||||
A.OnReset()
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
return 0 // 1 if handled
|
||||
|
||||
/datum/automation/proc/selectValidChildFor(var/mob/user, var/list/returntypes=valid_child_returntypes)
|
||||
return parent.selectValidChildFor(src, user, returntypes)
|
||||
|
||||
///////////////////////////////////////////
|
||||
// AND
|
||||
///////////////////////////////////////////
|
||||
/datum/automation/and
|
||||
name = "AND statement"
|
||||
returntype=AUTOM_RT_NUM
|
||||
valid_child_returntypes=list(AUTOM_RT_NUM)
|
||||
|
||||
Evaluate()
|
||||
if(children.len==0) return 0
|
||||
for(var/datum/automation/stmt in children)
|
||||
if(!stmt.Evaluate())
|
||||
return 0
|
||||
return 1
|
||||
|
||||
GetText()
|
||||
var/out="AND (<a href=\"?src=[UID()];add=1\">Add</a>)"
|
||||
if(children.len>0)
|
||||
out += "<ul>"
|
||||
for(var/datum/automation/stmt in children)
|
||||
out += {"<li>
|
||||
\[<a href="?src=[UID()];reset=\ref[stmt]">Reset</a> |
|
||||
<a href="?src=[UID()];remove=\ref[stmt]">×</a>\]
|
||||
[stmt.GetText()]
|
||||
</li>"}
|
||||
out += "</ul>"
|
||||
else
|
||||
out += "<blockquote><i>No statements to evaluate.</i></blockquote>"
|
||||
return out
|
||||
|
||||
///////////////////////////////////////////
|
||||
// OR
|
||||
///////////////////////////////////////////
|
||||
|
||||
/datum/automation/or
|
||||
name = "OR statement"
|
||||
returntype=AUTOM_RT_NUM
|
||||
valid_child_returntypes=list(AUTOM_RT_NUM)
|
||||
|
||||
Evaluate()
|
||||
if(children.len==0) return 0
|
||||
for(var/datum/automation/stmt in children)
|
||||
if(stmt.Evaluate())
|
||||
return 1
|
||||
return 0
|
||||
|
||||
GetText()
|
||||
var/out="OR (<a href=\"?src=[UID()];add=1\">Add</a>)"
|
||||
if(children.len>0)
|
||||
out += "<ul>"
|
||||
for(var/datum/automation/stmt in children)
|
||||
out += {"<li>
|
||||
\[<a href="?src=[UID()];reset=\ref[stmt]">Reset</a> |
|
||||
<a href="?src=[UID()];remove=\ref[stmt]">×</a>\]
|
||||
[stmt.GetText()]
|
||||
</li>"}
|
||||
out += "</ul>"
|
||||
else
|
||||
out += "<blockquote><i>No statements to evaluate.</i></blockquote>"
|
||||
return out
|
||||
|
||||
///////////////////////////////////////////
|
||||
// if .. then
|
||||
///////////////////////////////////////////
|
||||
|
||||
/datum/automation/if_statement
|
||||
name = "IF statement"
|
||||
var/datum/automation/condition=null
|
||||
valid_child_returntypes=list(AUTOM_RT_NULL)
|
||||
var/list/valid_conditions=list(AUTOM_RT_NUM)
|
||||
|
||||
var/list/children_then=list()
|
||||
var/list/children_else=list()
|
||||
|
||||
Export()
|
||||
var/list/R = ..()
|
||||
|
||||
if(children_then.len>0)
|
||||
R["then"]=packChildren(children_then)
|
||||
|
||||
if(children_else.len>0)
|
||||
R["else"]=packChildren(children_else)
|
||||
|
||||
if(condition)
|
||||
R["condition"]=condition.Export()
|
||||
|
||||
return R
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
|
||||
if("then" in json)
|
||||
children_then = unpackChildren(json["then"])
|
||||
|
||||
if("else" in json)
|
||||
children_else = unpackChildren(json["else"])
|
||||
|
||||
if("condition" in json)
|
||||
condition = unpackChild(json["condition"])
|
||||
|
||||
GetText()
|
||||
var/out="<b>IF</b> (<a href=\"?src=[UID()];set_condition=1\">SET</a>):<blockquote>"
|
||||
if(condition)
|
||||
out += condition.GetText()
|
||||
else
|
||||
out += "<i>Not set</i>"
|
||||
out += "</blockquote>"
|
||||
out += "<b>THEN:</b> (<a href=\"?src=[UID()];add=then\">Add</a>)"
|
||||
if(children_then.len>0)
|
||||
out += "<ul>"
|
||||
for(var/datum/automation/stmt in children_then)
|
||||
out += {"<li>
|
||||
\[<a href="?src=[UID()];reset=\ref[stmt];context=then">Reset</a> |
|
||||
<a href="?src=[UID()];remove=\ref[stmt];context=then">×</a>\]
|
||||
[stmt.GetText()]
|
||||
</li>"}
|
||||
out += "</ul>"
|
||||
else
|
||||
out += "<blockquote><i>(No statements to run)</i></blockquote>"
|
||||
out += "<b>ELSE:</b> (<a href=\"?src=[UID()];add=else\">Add</a>)"
|
||||
if(children_then.len>0)
|
||||
out += "<ul>"
|
||||
for(var/datum/automation/stmt in children_else)
|
||||
out += {"<li>
|
||||
\[<a href="?src=[UID()];reset=\ref[stmt];context=else">Reset</a> |
|
||||
<a href="?src=[UID()];remove=\ref[stmt];context=else">×</a>\]
|
||||
[stmt.GetText()]
|
||||
</li>"}
|
||||
out += "</ul>"
|
||||
else
|
||||
out += "<blockquote><i>(No statements to run)</i></blockquote>"
|
||||
return out
|
||||
|
||||
Topic(href,href_list)
|
||||
if(href_list["add"])
|
||||
var/new_child=selectValidChildFor(usr)
|
||||
if(!new_child) return 1
|
||||
switch(href_list["add"])
|
||||
if("then")
|
||||
children_then += new_child
|
||||
if("else")
|
||||
children_else += new_child
|
||||
else
|
||||
warning("Unknown add value given to [type]/Topic():[__LINE__]: [href]")
|
||||
return 1
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["remove"])
|
||||
if(href_list["remove"]=="*")
|
||||
var/confirm=input("Are you sure you want to remove ALL automations?","Automations","No") in list("Yes","No")
|
||||
if(confirm == "No") return 0
|
||||
for(var/datum/automation/A in children_then)
|
||||
A.OnRemove()
|
||||
children_then.Remove(A)
|
||||
for(var/datum/automation/A in children_else)
|
||||
A.OnRemove()
|
||||
children_else.Remove(A)
|
||||
else
|
||||
var/datum/automation/A=locate(href_list["remove"])
|
||||
if(!A) return 1
|
||||
var/confirm=input("Are you sure you want to remove this automation?","Automations","No") in list("Yes","No")
|
||||
if(confirm == "No") return 0
|
||||
A.OnRemove()
|
||||
switch(href_list["context"])
|
||||
if("then")
|
||||
children_then.Remove(A)
|
||||
if("else")
|
||||
children_else.Remove(A)
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["reset"])
|
||||
if(href_list["reset"]=="*")
|
||||
for(var/datum/automation/A in children_then)
|
||||
A.OnReset()
|
||||
for(var/datum/automation/A in children_else)
|
||||
A.OnReset()
|
||||
else
|
||||
var/datum/automation/A=locate(href_list["reset"])
|
||||
if(!A) return 1
|
||||
A.OnReset()
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["set_condition"])
|
||||
var/new_condition = selectValidChildFor(usr,valid_conditions)
|
||||
testing("Selected condition: [new_condition]")
|
||||
if(!new_condition)
|
||||
return 1
|
||||
condition = new_condition
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
process()
|
||||
if(condition)
|
||||
if(condition.Evaluate())
|
||||
for(var/datum/automation/stmt in children_then)
|
||||
stmt.process()
|
||||
else
|
||||
for(var/datum/automation/stmt in children_else)
|
||||
stmt.process()
|
||||
|
||||
///////////////////////////////////////////
|
||||
// compare
|
||||
///////////////////////////////////////////
|
||||
|
||||
/datum/automation/compare
|
||||
name = "comparison"
|
||||
var/comparator="Greater Than"
|
||||
returntype=AUTOM_RT_NUM
|
||||
valid_child_returntypes=list(AUTOM_RT_NUM)
|
||||
|
||||
New(var/obj/machinery/computer/general_air_control/atmos_automation/aa)
|
||||
..(aa)
|
||||
children=list(null,null)
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["cmp"]=comparator
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
comparator = json["cmp"]
|
||||
|
||||
Evaluate()
|
||||
if(children.len<2)
|
||||
return 0
|
||||
var/datum/automation/d_left =children[1]
|
||||
var/datum/automation/d_right=children[2]
|
||||
if(!d_left || !d_right)
|
||||
return 0
|
||||
var/left=d_left.Evaluate()
|
||||
var/right=d_right.Evaluate()
|
||||
switch(comparator)
|
||||
if("Greater Than")
|
||||
return left>right
|
||||
if("Greater Than or Equal to")
|
||||
return left>=right
|
||||
if("Less Than")
|
||||
return left<right
|
||||
if("Less Than or Equal to")
|
||||
return left<=right
|
||||
if("Equal to")
|
||||
return left==right
|
||||
if("NOT Equal To")
|
||||
return left!=right
|
||||
else
|
||||
return 0
|
||||
|
||||
GetText()
|
||||
var/datum/automation/left =children[1]
|
||||
var/datum/automation/right=children[2]
|
||||
|
||||
var/out = "<a href=\"?src=[UID()];set_field=1\">(Set Left)</a> ("
|
||||
if(left==null)
|
||||
out += "-----"
|
||||
else
|
||||
out += left.GetText()
|
||||
|
||||
out += ") is <a href=\"?src=[UID()];set_comparator=left\">[comparator]</a>: <a href=\"?src=[UID()];set_field=2\">(Set Right)</a> ("
|
||||
|
||||
if(right==null)
|
||||
out += "-----"
|
||||
else
|
||||
out += right.GetText()
|
||||
out +=")"
|
||||
return out
|
||||
|
||||
Topic(href,href_list)
|
||||
if(href_list["set_comparator"])
|
||||
comparator = input("Select a comparison operator:", "Compare", "Greater Than") in list("Greater Than","Greater Than or Equal to","Less Than","Less Than or Equal to","Equal to","NOT Equal To")
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
if(href_list["set_field"])
|
||||
var/idx = text2num(href_list["set_field"])
|
||||
var/new_child = selectValidChildFor(usr)
|
||||
if(!new_child)
|
||||
return 1
|
||||
children[idx] = new_child
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
///////////////////////////////////////////
|
||||
// static value
|
||||
///////////////////////////////////////////
|
||||
|
||||
/datum/automation/static_value
|
||||
name = "Number"
|
||||
|
||||
var/value=0
|
||||
|
||||
returntype=AUTOM_RT_NUM
|
||||
|
||||
Evaluate()
|
||||
return value
|
||||
|
||||
Export()
|
||||
var/list/json = ..()
|
||||
json["value"]=value
|
||||
return json
|
||||
|
||||
Import(var/list/json)
|
||||
..(json)
|
||||
value = text2num(json["value"])
|
||||
|
||||
GetText()
|
||||
return "<a href=\"?src=[UID()];set_value=1\">[value]</a>"
|
||||
|
||||
Topic(href,href_list)
|
||||
if(href_list["set_value"])
|
||||
value = input("Set a value:", "Static Value", value) as num
|
||||
parent.updateUsrDialog()
|
||||
return 1
|
||||
@@ -48,7 +48,7 @@ GLOBAL_DATUM_INIT(the_gateway, /obj/machinery/gateway/centerstation, null)
|
||||
..()
|
||||
update_icon()
|
||||
wait = world.time + config.gateway_delay //+ thirty minutes default
|
||||
awaygate = locate(/obj/machinery/gateway/centeraway) in world
|
||||
awaygate = locate(/obj/machinery/gateway/centeraway) in GLOB.machines
|
||||
|
||||
/obj/machinery/gateway/centerstation/update_density_from_dir()
|
||||
return
|
||||
@@ -103,7 +103,7 @@ GLOBAL_DATUM_INIT(the_gateway, /obj/machinery/gateway/centerstation, null)
|
||||
if(!powered())
|
||||
return
|
||||
if(!awaygate)
|
||||
awaygate = locate(/obj/machinery/gateway/centeraway) in world
|
||||
awaygate = locate(/obj/machinery/gateway/centeraway) in GLOB.machines
|
||||
if(!awaygate)
|
||||
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
|
||||
return
|
||||
@@ -180,7 +180,7 @@ GLOBAL_DATUM_INIT(the_gateway, /obj/machinery/gateway/centerstation, null)
|
||||
/obj/machinery/gateway/centeraway/Initialize()
|
||||
..()
|
||||
update_icon()
|
||||
stationgate = locate(/obj/machinery/gateway/centerstation) in world
|
||||
stationgate = locate(/obj/machinery/gateway/centerstation) in GLOB.machines
|
||||
|
||||
|
||||
/obj/machinery/gateway/centeraway/update_density_from_dir()
|
||||
@@ -219,7 +219,7 @@ GLOBAL_DATUM_INIT(the_gateway, /obj/machinery/gateway/centerstation, null)
|
||||
if(linked.len != 8)
|
||||
return
|
||||
if(!stationgate)
|
||||
stationgate = locate(/obj/machinery/gateway/centerstation) in world
|
||||
stationgate = locate(/obj/machinery/gateway/centerstation) in GLOB.machines
|
||||
if(!stationgate)
|
||||
to_chat(user, "<span class='notice'>Error: No destination found.</span>")
|
||||
return
|
||||
|
||||
@@ -1,72 +1,82 @@
|
||||
GLOBAL_DATUM_INIT(maploader, /dmm_suite, new())
|
||||
dmm_suite{
|
||||
/*
|
||||
/*
|
||||
|
||||
dmm_suite version 1.0
|
||||
Released January 30th, 2011.
|
||||
dmm_suite version 1.0
|
||||
Released January 30th, 2011.
|
||||
|
||||
defines the object /dmm_suite
|
||||
- Provides the proc load_map()
|
||||
- Loads the specified map file onto the specified z-level.
|
||||
- provides the proc write_map()
|
||||
- Returns a text string of the map in dmm format
|
||||
ready for output to a file.
|
||||
- provides the proc save_map()
|
||||
- Returns a .dmm file if map is saved
|
||||
- Returns FALSE if map fails to save
|
||||
defines the object /dmm_suite
|
||||
- Provides the proc load_map()
|
||||
- Loads the specified map file onto the specified z-level.
|
||||
- provides the proc write_map()
|
||||
- Returns a text string of the map in dmm format
|
||||
ready for output to a file.
|
||||
- provides the proc save_map()
|
||||
- Returns a .dmm file if map is saved
|
||||
- Returns FALSE if map fails to save
|
||||
|
||||
The dmm_suite provides saving and loading of map files in BYOND's native DMM map
|
||||
format. It approximates the map saving and loading processes of the Dream Maker
|
||||
and Dream Seeker programs so as to allow editing, saving, and loading of maps at
|
||||
runtime.
|
||||
The dmm_suite provides saving and loading of map files in BYOND's native DMM map
|
||||
format. It approximates the map saving and loading processes of the Dream Maker
|
||||
and Dream Seeker programs so as to allow editing, saving, and loading of maps at
|
||||
runtime.
|
||||
|
||||
------------------------
|
||||
------------------------
|
||||
|
||||
To save a map at runtime, create an instance of /dmm_suite, and then call
|
||||
write_map(), which accepts three arguments:
|
||||
- A turf representing one corner of a three dimensional grid (Required).
|
||||
- Another turf representing the other corner of the same grid (Required).
|
||||
- Any, or a combination, of several bit flags (Optional, see documentation).
|
||||
To save a map at runtime, create an instance of /dmm_suite, and then call
|
||||
write_map(), which accepts three arguments:
|
||||
- A turf representing one corner of a three dimensional grid (Required).
|
||||
- Another turf representing the other corner of the same grid (Required).
|
||||
- Any, or a combination, of several bit flags (Optional, see documentation).
|
||||
|
||||
The order in which the turfs are supplied does not matter, the /dmm_writer will
|
||||
determine the grid containing both, in much the same way as DM's block() function.
|
||||
write_map() will then return a string representing the saved map in dmm format;
|
||||
this string can then be saved to a file, or used for any other purose.
|
||||
The order in which the turfs are supplied does not matter, the /dmm_writer will
|
||||
determine the grid containing both, in much the same way as DM's block() function.
|
||||
write_map() will then return a string representing the saved map in dmm format;
|
||||
this string can then be saved to a file, or used for any other purose.
|
||||
|
||||
------------------------
|
||||
------------------------
|
||||
|
||||
To load a map at runtime, create an instance of /dmm_suite, and then call load_map(),
|
||||
which accepts two arguments:
|
||||
- A .dmm file to load (Required).
|
||||
- A number representing the z-level on which to start loading the map (Optional).
|
||||
To load a map at runtime, create an instance of /dmm_suite, and then call load_map(),
|
||||
which accepts two arguments:
|
||||
- A .dmm file to load (Required).
|
||||
- A number representing the z-level on which to start loading the map (Optional).
|
||||
|
||||
The /dmm_suite will load the map file starting on the specified z-level. If no
|
||||
z-level was specified, world.maxz will be increased so as to fit the map. Note
|
||||
that if you wish to load a map onto a z-level that already has objects on it,
|
||||
you will have to handle the removal of those objects. Otherwise the new map will
|
||||
simply load the new objects on top of the old ones.
|
||||
The /dmm_suite will load the map file starting on the specified z-level. If no
|
||||
z-level was specified, world.maxz will be increased so as to fit the map. Note
|
||||
that if you wish to load a map onto a z-level that already has objects on it,
|
||||
you will have to handle the removal of those objects. Otherwise the new map will
|
||||
simply load the new objects on top of the old ones.
|
||||
|
||||
Also note that all type paths specified in the .dmm file must exist in the world's
|
||||
code, and that the /dmm_reader trusts that files to be loaded are in fact valid
|
||||
.dmm files. Errors in the .dmm format will cause runtime errors.
|
||||
Also note that all type paths specified in the .dmm file must exist in the world's
|
||||
code, and that the /dmm_reader trusts that files to be loaded are in fact valid
|
||||
.dmm files. Errors in the .dmm format will cause runtime errors.
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
verb/load_map(var/dmm_file as file, var/x_offset as num, var/y_offset as num, var/z_offset as num, do_sleep as num){
|
||||
// dmm_file: A .dmm file to load (Required).
|
||||
// z_offset: A number representing the z-level on which to start loading the map (Optional).
|
||||
}
|
||||
verb/write_map(var/turf/t1 as turf, var/turf/t2 as turf, var/flags as num){
|
||||
// t1: A turf representing one corner of a three dimensional grid (Required).
|
||||
// t2: Another turf representing the other corner of the same grid (Required).
|
||||
// flags: Any, or a combination, of several bit flags (Optional, see documentation).
|
||||
}
|
||||
GLOBAL_DATUM_INIT(maploader, /datum/dmm_suite, new())
|
||||
|
||||
// save_map is included as a legacy proc. Use write_map instead.
|
||||
verb/save_map(var/turf/t1 as turf, var/turf/t2 as turf, var/map_name as text, var/flags as num){
|
||||
// t1: A turf representing one corner of a three dimensional grid (Required).
|
||||
// t2: Another turf representing the other corner of the same grid (Required).
|
||||
// map_name: A valid name for the map to be saved, such as "castle" (Required).
|
||||
// flags: Any, or a combination, of several bit flags (Optional, see documentation).
|
||||
}
|
||||
}
|
||||
/datum/dmm_suite
|
||||
var/static/quote = "\""
|
||||
|
||||
// These regexes are global - meaning that starting the maploader again mid-load will
|
||||
// reset progress - which means we need to track our index per-map, or we'll
|
||||
// eternally recurse
|
||||
// /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g
|
||||
var/static/regex/dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g")
|
||||
// /^[\s\n]+"?|"?[\s\n]+$|^"|"$/g
|
||||
var/static/regex/trimQuotesRegex = new/regex({"^\[\\s\n]+"?|"?\[\\s\n]+$|^"|"$"}, "g")
|
||||
// /^[\s\n]+|[\s\n]+$/
|
||||
var/static/regex/trimRegex = new/regex("^\[\\s\n]+|\[\\s\n]+$", "g")
|
||||
var/static/list/modelCache = list()
|
||||
|
||||
var/static/list/letter_digits = list(
|
||||
"a", "b", "c", "d", "e",
|
||||
"f", "g", "h", "i", "j",
|
||||
"k", "l", "m", "n", "o",
|
||||
"p", "q", "r", "s", "t",
|
||||
"u", "v", "w", "x", "y",
|
||||
"z",
|
||||
"A", "B", "C", "D", "E",
|
||||
"F", "G", "H", "I", "J",
|
||||
"K", "L", "M", "N", "O",
|
||||
"P", "Q", "R", "S", "T",
|
||||
"U", "V", "W", "X", "Y",
|
||||
"Z"
|
||||
)
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
///////////////////////////////////////////////////////////////
|
||||
//SS13 Optimized Map loader
|
||||
// SS13 Optimized Map loader
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
//As of 3.6.2016
|
||||
//global datum that will preload variables on atoms instanciation
|
||||
// As of 3.6.2016
|
||||
// global datum that will preload variables on atoms instanciation
|
||||
GLOBAL_VAR_INIT(use_preloader, FALSE)
|
||||
GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
|
||||
/dmm_suite
|
||||
// These regexes are global - meaning that starting the maploader again mid-load will
|
||||
// reset progress - which means we need to track our index per-map, or we'll
|
||||
// eternally recurse
|
||||
// /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g
|
||||
var/static/regex/dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g")
|
||||
// /^[\s\n]+"?|"?[\s\n]+$|^"|"$/g
|
||||
var/static/regex/trimQuotesRegex = new/regex({"^\[\\s\n]+"?|"?\[\\s\n]+$|^"|"$"}, "g")
|
||||
// /^[\s\n]+|[\s\n]+$/
|
||||
var/static/regex/trimRegex = new/regex("^\[\\s\n]+|\[\\s\n]+$", "g")
|
||||
var/static/list/modelCache = list()
|
||||
GLOBAL_DATUM_INIT(_preloader, /datum/dmm_suite/preloader, new())
|
||||
|
||||
/**
|
||||
* Construct the model map and control the loading process
|
||||
@@ -37,13 +25,18 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
* atmos will attempt to start before it's ready, causing runtimes galore if init is
|
||||
* allowed to romp unchecked.
|
||||
*/
|
||||
/dmm_suite/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num)
|
||||
var/tfile = dmm_file//the map file we're creating
|
||||
/datum/dmm_suite/proc/load_map(dmm_file, x_offset = 0, y_offset = 0, z_offset = 0, shouldCropMap = FALSE, measureOnly = FALSE)
|
||||
var/tfile = dmm_file// the map file we're creating
|
||||
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) == 0)
|
||||
if(!length(tfile))
|
||||
throw EXCEPTION("Map path '[fname]' does not exist!")
|
||||
|
||||
if(!x_offset)
|
||||
@@ -57,7 +50,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
var/list/grid_models = list()
|
||||
var/key_len = 0
|
||||
|
||||
var/dmm_suite/loaded_map/LM = new
|
||||
var/datum/dmm_suite/loaded_map/LM = new
|
||||
// This try-catch is used as a budget "Finally" clause, as the dirt count
|
||||
// needs to be reset
|
||||
var/watch = start_watch()
|
||||
@@ -76,7 +69,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
if(!key_len)
|
||||
key_len = length(key)
|
||||
else
|
||||
throw EXCEPTION("Inconsistant key length in DMM")
|
||||
throw EXCEPTION("Inconsistent key length in DMM")
|
||||
if(!measureOnly)
|
||||
grid_models[key] = dmmRegex.group[2]
|
||||
|
||||
@@ -86,17 +79,17 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
throw EXCEPTION("Coords before model definition in DMM")
|
||||
|
||||
var/xcrdStart = text2num(dmmRegex.group[3]) + x_offset - 1
|
||||
//position of the currently processed square
|
||||
// position of the currently processed square
|
||||
var/xcrd
|
||||
var/ycrd = text2num(dmmRegex.group[4]) + y_offset - 1
|
||||
var/zcrd = text2num(dmmRegex.group[5]) + z_offset - 1
|
||||
|
||||
if(!measureOnly)
|
||||
if(zcrd > world.maxz)
|
||||
if(cropMap)
|
||||
if(shouldCropMap)
|
||||
continue
|
||||
else
|
||||
GLOB.space_manager.increase_max_zlevel_to(zcrd) //create a new z_level if needed
|
||||
GLOB.space_manager.increase_max_zlevel_to(zcrd) // create a new z_level if needed
|
||||
|
||||
bounds[MAP_MINX] = min(bounds[MAP_MINX], xcrdStart)
|
||||
bounds[MAP_MINZ] = min(bounds[MAP_MINZ], zcrd)
|
||||
@@ -118,7 +111,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
bounds[MAP_MINY] = min(bounds[MAP_MINY], ycrd)
|
||||
ycrd += gridLines.len - 1 // Start at the top and work down
|
||||
|
||||
if(!cropMap && ycrd > world.maxy)
|
||||
if(!shouldCropMap && ycrd > world.maxy)
|
||||
if(!measureOnly)
|
||||
world.maxy = ycrd // Expand Y here. X is expanded in the loop below
|
||||
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], ycrd)
|
||||
@@ -133,9 +126,9 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
for(var/line in gridLines)
|
||||
if(ycrd <= world.maxy && ycrd >= 1)
|
||||
xcrd = xcrdStart
|
||||
for(var/tpos = 1 to length(line) - key_len + 1 step key_len)
|
||||
for(var/tpos = 1 to (length(line) - key_len + 1) step key_len)
|
||||
if(xcrd > world.maxx)
|
||||
if(cropMap)
|
||||
if(shouldCropMap)
|
||||
break
|
||||
else
|
||||
world.maxx = xcrd
|
||||
@@ -152,7 +145,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
maxx = max(maxx, xcrd)
|
||||
++xcrd
|
||||
--ycrd
|
||||
bounds[MAP_MAXX] = max(bounds[MAP_MAXX], cropMap ? min(maxx, world.maxx) : maxx)
|
||||
bounds[MAP_MAXX] = max(bounds[MAP_MAXX], shouldCropMap ? min(maxx, world.maxx) : maxx)
|
||||
|
||||
CHECK_TICK
|
||||
catch(var/exception/e)
|
||||
@@ -175,8 +168,8 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
if(!measureOnly)
|
||||
for(var/t in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]), locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ])))
|
||||
var/turf/T = t
|
||||
//we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs
|
||||
T.AfterChange(1, keep_cabling = TRUE)
|
||||
// we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs
|
||||
T.AfterChange(TRUE, keep_cabling = TRUE)
|
||||
return bounds
|
||||
|
||||
/**
|
||||
@@ -196,14 +189,14 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
* 4) Instanciates the atom with its variables
|
||||
*
|
||||
*/
|
||||
/dmm_suite/proc/parse_grid(model as text,xcrd as num,ycrd as num,zcrd as num, dmm_suite/loaded_map/LM)
|
||||
/datum/dmm_suite/proc/parse_grid(model = "", xcrd = 0, ycrd = 0, zcrd = 0, datum/dmm_suite/loaded_map/LM)
|
||||
/*Method parse_grid()
|
||||
- Accepts a text string containing a comma separated list of type paths of the
|
||||
same construction as those contained in a .dmm file, and instantiates them.
|
||||
*/
|
||||
|
||||
var/list/members //will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/dangerous/explored)
|
||||
var/list/members_attributes //will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
|
||||
var/list/members // will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/dangerous/explored)
|
||||
var/list/members_attributes // will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
|
||||
var/list/cached = modelCache[model]
|
||||
var/index
|
||||
|
||||
@@ -212,7 +205,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
members_attributes = cached[2]
|
||||
else
|
||||
/////////////////////////////////////////////////////////
|
||||
//Constructing members and corresponding variables lists
|
||||
// Constructing members and corresponding variables lists
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
members = list()
|
||||
@@ -223,13 +216,13 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
var/dpos
|
||||
|
||||
do
|
||||
//finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/dangerous/explored)
|
||||
dpos = find_next_delimiter_position(model, old_position, ",", "{", "}") //find next delimiter (comma here) that's not within {...}
|
||||
// finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/dangerous/explored)
|
||||
dpos = find_next_delimiter_position(model, old_position, ",", "{", "}") // find next delimiter (comma here) that's not within {...}
|
||||
|
||||
var/full_def = trim_text(copytext(model, old_position, dpos)) //full definition, e.g : /obj/foo/bar{variables=derp}
|
||||
var/full_def = trim_text(copytext(model, old_position, dpos)) // full definition, e.g : /obj/foo/bar{variables=derp}
|
||||
var/variables_start = findtext(full_def, "{")
|
||||
var/atom_text = trim_text(copytext(full_def, 1, variables_start))
|
||||
var/atom_def = text2path(atom_text) //path definition, e.g /obj/foo/bar
|
||||
var/atom_def = text2path(atom_text) // path definition, e.g /obj/foo/bar
|
||||
old_position = dpos + 1
|
||||
|
||||
if(!atom_def) // Skip the item if the path does not exist. Fix your crap, mappers!
|
||||
@@ -237,14 +230,14 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
continue
|
||||
members.Add(atom_def)
|
||||
|
||||
//transform the variables in text format into a list (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
|
||||
// transform the variables in text format into a list (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
|
||||
var/list/fields = list()
|
||||
|
||||
if(variables_start)//if there's any variable
|
||||
full_def = copytext(full_def,variables_start+1,length(full_def))//removing the last '}'
|
||||
if(variables_start) // if there's any variable
|
||||
full_def = copytext(full_def, variables_start + 1, length(full_def)) // removing the last '}'
|
||||
fields = readlist(full_def, ";")
|
||||
|
||||
//then fill the members_attributes list with the corresponding variables
|
||||
// then fill the members_attributes list with the corresponding variables
|
||||
members_attributes.len++
|
||||
members_attributes[index++] = fields
|
||||
|
||||
@@ -255,24 +248,23 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
|
||||
|
||||
////////////////
|
||||
//Instanciation
|
||||
// Instanciation
|
||||
////////////////
|
||||
|
||||
//The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
|
||||
// The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
|
||||
|
||||
//first instance the /area and remove it from the members list
|
||||
// first instance the /area and remove it from the members list
|
||||
index = members.len
|
||||
|
||||
var/turf/crds = locate(xcrd,ycrd,zcrd)
|
||||
var/turf/crds = locate(xcrd, ycrd, zcrd)
|
||||
if(members[index] != /area/template_noop)
|
||||
// We assume `members[index]` is an area path, as above, yes? I will operate
|
||||
// on that assumption.
|
||||
if(!ispath(members[index], /area))
|
||||
throw EXCEPTION("Oh no, I thought this was an area!")
|
||||
|
||||
var/atom/instance
|
||||
GLOB._preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation
|
||||
instance = LM.area_path_to_real_area(members[index])
|
||||
GLOB._preloader.setup(members_attributes[index]) // preloader for assigning set variables on atom creation
|
||||
var/atom/instance = LM.area_path_to_real_area(members[index])
|
||||
|
||||
if(crds)
|
||||
instance.contents.Add(crds)
|
||||
@@ -280,45 +272,46 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
if(GLOB.use_preloader && instance)
|
||||
GLOB._preloader.load(instance)
|
||||
|
||||
//then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect
|
||||
// then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect
|
||||
|
||||
var/first_turf_index = 1
|
||||
while(!ispath(members[first_turf_index],/turf)) //find first /turf object in members
|
||||
while(!ispath(members[first_turf_index], /turf)) // find first /turf object in members
|
||||
first_turf_index++
|
||||
|
||||
//instanciate the first /turf
|
||||
// instanciate the first /turf
|
||||
var/turf/T
|
||||
if(members[first_turf_index] != /turf/template_noop)
|
||||
T = instance_atom(members[first_turf_index],members_attributes[first_turf_index],xcrd,ycrd,zcrd)
|
||||
T = instance_atom(members[first_turf_index], members_attributes[first_turf_index], xcrd, ycrd, zcrd)
|
||||
|
||||
if(T)
|
||||
//if others /turf are presents, simulates the underlays piling effect
|
||||
// if others /turf are presents, simulates the underlays piling effect
|
||||
index = first_turf_index + 1
|
||||
while(index <= members.len - 1) // Last item is an /area
|
||||
var/mlen = members.len - 1
|
||||
while(index <= mlen) // Last item is an /area
|
||||
var/underlay
|
||||
if(istype(T, /turf)) // I blame this on the stupid clown who coded the BYOND map editor
|
||||
underlay = T.appearance
|
||||
T = instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)//instance new turf
|
||||
if(ispath(members[index],/turf))
|
||||
T = instance_atom(members[index], members_attributes[index], xcrd, ycrd, zcrd) // instance new turf
|
||||
if(ispath(members[index], /turf))
|
||||
T.underlays += underlay
|
||||
|
||||
index++
|
||||
|
||||
//finally instance all remainings objects/mobs
|
||||
for(index in 1 to first_turf_index-1)
|
||||
instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)
|
||||
// finally instance all remainings objects/mobs
|
||||
for(index in 1 to first_turf_index - 1)
|
||||
instance_atom(members[index], members_attributes[index], xcrd, ycrd, zcrd)
|
||||
CHECK_TICK
|
||||
|
||||
////////////////
|
||||
//Helpers procs
|
||||
// Helpers procs
|
||||
////////////////
|
||||
|
||||
//Instance an atom at (x,y,z) and gives it the variables in attributes
|
||||
/dmm_suite/proc/instance_atom(path,list/attributes, x, y, z)
|
||||
// Instance an atom at (x, y, z) and gives it the variables in attributes
|
||||
/datum/dmm_suite/proc/instance_atom(path, list/attributes, x, y, z)
|
||||
var/atom/instance
|
||||
GLOB._preloader.setup(attributes, path)
|
||||
|
||||
var/turf/T = locate(x,y,z)
|
||||
var/turf/T = locate(x, y, z)
|
||||
if(T)
|
||||
if(ispath(path, /turf))
|
||||
T.ChangeTurf(path, defer_change = TRUE, keep_icon = FALSE)
|
||||
@@ -326,115 +319,111 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
else if(ispath(path, /area))
|
||||
|
||||
else
|
||||
instance = new path (T)//first preloader pass
|
||||
instance = new path(T) // first preloader pass
|
||||
|
||||
if(GLOB.use_preloader && instance)//second preloader pass, for those atoms that don't ..() in New()
|
||||
if(GLOB.use_preloader && instance) // second preloader pass, for those atoms that don't ..() in New()
|
||||
GLOB._preloader.load(instance)
|
||||
|
||||
return instance
|
||||
|
||||
//text trimming (both directions) helper proc
|
||||
//optionally removes quotes before and after the text (for variable name)
|
||||
/dmm_suite/proc/trim_text(what as text,trim_quotes=0)
|
||||
// text trimming (both directions) helper proc
|
||||
// optionally removes quotes before and after the text (for variable name)
|
||||
/datum/dmm_suite/proc/trim_text(what, trim_quotes = FALSE)
|
||||
if(trim_quotes)
|
||||
return trimQuotesRegex.Replace(what, "")
|
||||
else
|
||||
return trimRegex.Replace(what, "")
|
||||
|
||||
|
||||
//find the position of the next delimiter,skipping whatever is comprised between opening_escape and closing_escape
|
||||
//returns 0 if reached the last delimiter
|
||||
/dmm_suite/proc/find_next_delimiter_position(text as text,initial_position as num, delimiter=",",opening_escape=quote,closing_escape=quote)
|
||||
// find the position of the next delimiter, skipping whatever is comprised between opening_escape and closing_escape
|
||||
// returns 0 if reached the last delimiter
|
||||
/datum/dmm_suite/proc/find_next_delimiter_position(text, initial_position = 0, delimiter = ",", opening_escape = quote, closing_escape = quote)
|
||||
var/position = initial_position
|
||||
var/next_delimiter = findtext(text,delimiter,position,0)
|
||||
var/next_opening = findtext(text,opening_escape,position,0)
|
||||
var/next_delimiter = findtext(text, delimiter, position, 0)
|
||||
var/next_opening = findtext(text, opening_escape, position, 0)
|
||||
|
||||
while((next_opening != 0) && (next_opening < next_delimiter))
|
||||
position = findtext(text,closing_escape,next_opening + 1,0)+1
|
||||
next_delimiter = findtext(text,delimiter,position,0)
|
||||
next_opening = findtext(text,opening_escape,position,0)
|
||||
position = findtext(text, closing_escape, next_opening + 1, 0) + 1
|
||||
next_delimiter = findtext(text, delimiter, position, 0)
|
||||
next_opening = findtext(text, opening_escape, position, 0)
|
||||
|
||||
return next_delimiter
|
||||
|
||||
|
||||
//build a list from variables in text form (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
|
||||
//return the filled list
|
||||
/dmm_suite/proc/readlist(text as text, delimiter=",")
|
||||
|
||||
// build a list from variables in text form (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
|
||||
// return the filled list
|
||||
/datum/dmm_suite/proc/readlist(text, delimiter = ",")
|
||||
var/list/to_return = list()
|
||||
|
||||
var/position
|
||||
var/old_position = 1
|
||||
|
||||
do
|
||||
//find next delimiter that is not within "..."
|
||||
position = find_next_delimiter_position(text,old_position,delimiter)
|
||||
// find next delimiter that is not within "..."
|
||||
position = find_next_delimiter_position(text, old_position, delimiter)
|
||||
|
||||
//check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo",var2=7))
|
||||
var/equal_position = findtext(text,"=",old_position, position)
|
||||
// check if this is a simple variable (as in list(var1, var2)) or an associative one (as in list(var1="foo", var2=7))
|
||||
var/equal_position = findtext(text, "=", old_position, position)
|
||||
|
||||
var/trim_left = trim_text(copytext(text,old_position,(equal_position ? equal_position : position)),1)//the name of the variable, must trim quotes to build a BYOND compliant associatives list
|
||||
var/trim_left = trim_text(copytext(text, old_position, (equal_position ? equal_position : position)), 1) // the name of the variable, must trim quotes to build a BYOND compliant associatives list
|
||||
old_position = position + 1
|
||||
|
||||
if(equal_position)//associative var, so do the association
|
||||
var/trim_right = trim_text(copytext(text,equal_position+1,position))//the content of the variable
|
||||
if(equal_position) // associative var, so do the association
|
||||
var/trim_right = trim_text(copytext(text, equal_position + 1, position)) // the content of the variable
|
||||
|
||||
//Check for string
|
||||
// Check for string
|
||||
// Make it read to the next delimiter, instead of the quote
|
||||
if(findtext(trim_right,quote,1,2))
|
||||
var/endquote = findtext(trim_right,quote,-1)
|
||||
if(findtext(trim_right, quote, 1, 2))
|
||||
var/endquote = findtext(trim_right, quote, -1)
|
||||
if(!endquote)
|
||||
log_runtime(EXCEPTION("Terminating quote not found!"), src)
|
||||
// Our map writer escapes quotes and curly brackets to avoid
|
||||
// letting our simple parser choke on meanly-crafted names/etc
|
||||
// - so we decode it here so it's back to good ol' legibility
|
||||
trim_right = dmm_decode(copytext(trim_right,2,endquote))
|
||||
trim_right = dmm_decode(copytext(trim_right, 2, endquote))
|
||||
|
||||
//Check for number
|
||||
// Check for number
|
||||
else if(isnum(text2num(trim_right)))
|
||||
trim_right = text2num(trim_right)
|
||||
|
||||
//Check for null
|
||||
// Check for null
|
||||
else if(trim_right == "null")
|
||||
trim_right = null
|
||||
|
||||
//Check for list
|
||||
else if(copytext(trim_right,1,5) == "list")
|
||||
trim_right = readlist(copytext(trim_right,6,length(trim_right)))
|
||||
// Check for list
|
||||
else if(copytext(trim_right, 1, 5) == "list")
|
||||
trim_right = readlist(copytext(trim_right, 6, length(trim_right)))
|
||||
|
||||
//Check for file
|
||||
else if(copytext(trim_right,1,2) == "'")
|
||||
trim_right = file(copytext(trim_right,2,length(trim_right)))
|
||||
// Check for file
|
||||
else if(copytext(trim_right, 1, 2) == "'")
|
||||
trim_right = file(copytext(trim_right, 2, length(trim_right)))
|
||||
|
||||
//Check for path
|
||||
// Check for path
|
||||
else if(ispath(text2path(trim_right)))
|
||||
trim_right = text2path(trim_right)
|
||||
|
||||
to_return[trim_left] = trim_right
|
||||
|
||||
else//simple var
|
||||
else// simple var
|
||||
to_return[trim_left] = null
|
||||
|
||||
while(position != 0)
|
||||
|
||||
return to_return
|
||||
|
||||
/dmm_suite/Destroy()
|
||||
/datum/dmm_suite/Destroy()
|
||||
..()
|
||||
return QDEL_HINT_HARDDEL_NOW
|
||||
|
||||
//////////////////
|
||||
//Preloader datum
|
||||
// Preloader datum
|
||||
//////////////////
|
||||
|
||||
// This ain't re-entrant, but we had this before the maploader update
|
||||
/dmm_suite/preloader
|
||||
parent_type = /datum
|
||||
/datum/dmm_suite/preloader
|
||||
var/list/attributes
|
||||
var/target_path
|
||||
var/json_ready = 0
|
||||
|
||||
/dmm_suite/preloader/proc/setup(list/the_attributes, path)
|
||||
/datum/dmm_suite/preloader/proc/setup(list/the_attributes, path)
|
||||
if(the_attributes.len)
|
||||
json_ready = 0
|
||||
if("map_json_data" in the_attributes)
|
||||
@@ -443,25 +432,24 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
attributes = the_attributes
|
||||
target_path = path
|
||||
|
||||
/dmm_suite/preloader/proc/load(atom/what)
|
||||
/datum/dmm_suite/preloader/proc/load(atom/A)
|
||||
if(json_ready)
|
||||
var/json_data = attributes["map_json_data"]
|
||||
var/json_data = dmm_decode(attributes["map_json_data"])
|
||||
attributes -= "map_json_data"
|
||||
json_data = dmm_decode(json_data)
|
||||
try
|
||||
what.deserialize(json_decode(json_data))
|
||||
catch(var/exception/e)
|
||||
A.deserialize(json_decode(json_data))
|
||||
catch(var/exception/E)
|
||||
log_runtime(EXCEPTION("Bad json data: '[json_data]'"), src)
|
||||
throw e
|
||||
throw E
|
||||
for(var/attribute in attributes)
|
||||
var/value = attributes[attribute]
|
||||
if(islist(value))
|
||||
value = deepCopyList(value)
|
||||
what.vars[attribute] = value
|
||||
A.vars[attribute] = value
|
||||
GLOB.use_preloader = FALSE
|
||||
|
||||
// If the map loader fails, make this safe
|
||||
/dmm_suite/preloader/proc/reset()
|
||||
/datum/dmm_suite/preloader/proc/reset()
|
||||
GLOB.use_preloader = FALSE
|
||||
attributes = list()
|
||||
target_path = null
|
||||
@@ -470,12 +458,11 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new())
|
||||
// so that one can have separate "unpowered" areas for ruins or whatever,
|
||||
// yet have a single area type for use of mapping, instead of creating
|
||||
// a new area type for each new ruin
|
||||
/dmm_suite/loaded_map
|
||||
parent_type = /datum
|
||||
/datum/dmm_suite/loaded_map
|
||||
var/list/area_list = list()
|
||||
var/index = 1 // To store the state of the regex
|
||||
|
||||
/dmm_suite/loaded_map/proc/area_path_to_real_area(area/A)
|
||||
/datum/dmm_suite/loaded_map/proc/area_path_to_real_area(area/A)
|
||||
if(!ispath(A, /area))
|
||||
throw EXCEPTION("Wrong argument to `area_path_to_real_area`")
|
||||
|
||||
|
||||
@@ -5,28 +5,12 @@
|
||||
#define DMM_IGNORE_PLAYERS 16
|
||||
#define DMM_IGNORE_MOBS 24
|
||||
#define DMM_USE_JSON 32
|
||||
/dmm_suite
|
||||
var/quote = "\""
|
||||
var/list/letter_digits = list(
|
||||
"a","b","c","d","e",
|
||||
"f","g","h","i","j",
|
||||
"k","l","m","n","o",
|
||||
"p","q","r","s","t",
|
||||
"u","v","w","x","y",
|
||||
"z",
|
||||
"A","B","C","D","E",
|
||||
"F","G","H","I","J",
|
||||
"K","L","M","N","O",
|
||||
"P","Q","R","S","T",
|
||||
"U","V","W","X","Y",
|
||||
"Z"
|
||||
)
|
||||
|
||||
/dmm_suite/save_map(var/turf/t1 as turf, var/turf/t2 as turf, var/map_name as text, var/flags as num)
|
||||
//Check for illegal characters in file name... in a cheap way.
|
||||
if(!((ckeyEx(map_name)==map_name) && ckeyEx(map_name)))
|
||||
/datum/dmm_suite/proc/save_map(turf/t1, turf/t2, map_name = "", flags = 0)
|
||||
// Check for illegal characters in file name... in a cheap way.
|
||||
if(!((ckeyEx(map_name) == map_name) && ckeyEx(map_name)))
|
||||
CRASH("Invalid text supplied to proc save_map, invalid characters or empty string.")
|
||||
//Check for valid turfs.
|
||||
// Check for valid turfs.
|
||||
if(!isturf(t1) || !isturf(t2))
|
||||
CRASH("Invalid arguments supplied to proc save_map, arguments were not turfs.")
|
||||
|
||||
@@ -35,17 +19,17 @@
|
||||
if(fexists(map_path))
|
||||
fdel(map_path)
|
||||
var/saved_map = file(map_path)
|
||||
var/map_text = write_map(t1,t2,flags,saved_map)
|
||||
var/map_text = write_map(t1, t2, flags, saved_map)
|
||||
saved_map << map_text
|
||||
return saved_map
|
||||
|
||||
/dmm_suite/write_map(var/turf/t1 as turf, var/turf/t2 as turf, var/flags as num)
|
||||
//Check for valid turfs.
|
||||
/datum/dmm_suite/proc/write_map(turf/t1, turf/t2, flags = 0)
|
||||
// Check for valid turfs.
|
||||
if(!isturf(t1) || !isturf(t2))
|
||||
CRASH("Invalid arguments supplied to proc write_map, arguments were not turfs.")
|
||||
|
||||
var/turf/ne = locate(max(t1.x,t2.x),max(t1.y,t2.y),max(t1.z,t2.z)) // Outer corner
|
||||
var/turf/sw = locate(min(t1.x,t2.x),min(t1.y,t2.y),min(t1.z,t2.z)) // Inner corner
|
||||
var/turf/ne = locate(max(t1.x, t2.x), max(t1.y, t2.y), max(t1.z, t2.z)) // Outer corner
|
||||
var/turf/sw = locate(min(t1.x, t2.x), min(t1.y, t2.y), min(t1.z, t2.z)) // Inner corner
|
||||
var/list/templates[0]
|
||||
var/list/template_buffer = list()
|
||||
var/template_buffer_text
|
||||
@@ -54,37 +38,40 @@
|
||||
var/total_timer = start_watch()
|
||||
var/timer = start_watch()
|
||||
log_debug("Reading turfs...")
|
||||
|
||||
// Read the contents of all the turfs we were given
|
||||
for(var/pos_z in sw.z to ne.z)
|
||||
for(var/pos_y in ne.y to sw.y step -1) // We're reversing this because the map format is silly
|
||||
for(var/pos_x in sw.x to ne.x)
|
||||
var/turf/test_turf = locate(pos_x,pos_y,pos_z)
|
||||
var/turf/test_turf = locate(pos_x, pos_y, pos_z)
|
||||
var/test_template = make_template(test_turf, flags)
|
||||
var/template_number = templates.Find(test_template)
|
||||
if(!template_number)
|
||||
templates.Add(test_template)
|
||||
template_number = templates.len
|
||||
template_number = length(templates)
|
||||
template_buffer += "[template_number],"
|
||||
CHECK_TICK
|
||||
|
||||
template_buffer += ";"
|
||||
|
||||
template_buffer += "."
|
||||
template_buffer_text = jointext(template_buffer,"")
|
||||
|
||||
template_buffer_text = jointext(template_buffer, "")
|
||||
log_debug("Reading turfs took [stop_watch(timer)]s.")
|
||||
|
||||
if(templates.len == 0)
|
||||
if(length(templates) == 0)
|
||||
CRASH("No templates found!")
|
||||
var/key_length = round/*floor*/(log(letter_digits.len,templates.len-1)+1)
|
||||
var/list/keys[templates.len]
|
||||
|
||||
var/key_length = round(log(length(letter_digits), length(templates) - 1) + 1) // or floor
|
||||
var/list/keys[length(templates)]
|
||||
|
||||
// Write the list of key/model pairs to the file
|
||||
timer = start_watch()
|
||||
log_debug("Writing out key/model pairs to file header...")
|
||||
var/list/key_models = list()
|
||||
for(var/key_pos in 1 to templates.len)
|
||||
keys[key_pos] = get_model_key(key_pos,key_length)
|
||||
for(var/key_pos in 1 to length(templates))
|
||||
keys[key_pos] = get_model_key(key_pos, key_length)
|
||||
key_models += "\"[keys[key_pos]]\" = ([templates[key_pos]])\n"
|
||||
CHECK_TICK
|
||||
|
||||
dmm_text += jointext(key_models,"")
|
||||
log_debug("Writing key/model pairs complete, took [stop_watch(timer)]s.")
|
||||
|
||||
@@ -92,58 +79,69 @@
|
||||
// Loop over all z in our zone
|
||||
timer = start_watch()
|
||||
log_debug("Writing out key map...")
|
||||
|
||||
var/list/key_map = list()
|
||||
for(var/z_pos=1;TRUE;z_pos=findtext(template_buffer_text,".",z_pos)+1)
|
||||
if(z_pos>=length(template_buffer_text)) break
|
||||
if(z_level) key_map += "\n"
|
||||
for(var/z_pos = 1; TRUE; z_pos = findtext(template_buffer_text, ".", z_pos) + 1)
|
||||
if(z_pos >= length(template_buffer_text))
|
||||
break
|
||||
|
||||
if(z_level)
|
||||
key_map += "\n"
|
||||
|
||||
key_map += "\n(1,1,[++z_level]) = {\"\n"
|
||||
var/z_block = copytext(template_buffer_text,z_pos,findtext(template_buffer_text,".",z_pos))
|
||||
for(var/y_pos=1;TRUE;y_pos=findtext(z_block,";",y_pos)+1)
|
||||
if(y_pos>=length(z_block)) break
|
||||
var/y_block = copytext(z_block,y_pos,findtext(z_block,";",y_pos))
|
||||
var/z_block = copytext(template_buffer_text, z_pos, findtext(template_buffer_text, ".", z_pos))
|
||||
for(var/y_pos = 1; TRUE; y_pos = findtext(z_block, ";", y_pos) + 1)
|
||||
if(y_pos >= length(z_block))
|
||||
break
|
||||
|
||||
var/y_block = copytext(z_block, y_pos, findtext(z_block, ";", y_pos))
|
||||
// A row of keys
|
||||
for(var/x_pos=1;TRUE;x_pos=findtext(y_block,",",x_pos)+1)
|
||||
if(x_pos>=length(y_block)) break
|
||||
var/x_block = copytext(y_block,x_pos,findtext(y_block,",",x_pos))
|
||||
for(var/x_pos = 1; TRUE; x_pos = findtext(y_block, ",", x_pos) + 1)
|
||||
if(x_pos >= length(y_block))
|
||||
break
|
||||
|
||||
var/x_block = copytext(y_block, x_pos, findtext(y_block, ",", x_pos))
|
||||
var/key_number = text2num(x_block)
|
||||
var/temp_key = keys[key_number]
|
||||
key_map += temp_key
|
||||
CHECK_TICK
|
||||
key_map += "\n"
|
||||
key_map += "\"}"
|
||||
dmm_text += jointext(key_map,"")
|
||||
|
||||
dmm_text += jointext(key_map, "")
|
||||
log_debug("Writing key map complete, took [stop_watch(timer)]s.")
|
||||
log_debug("TOTAL TIME: [stop_watch(total_timer)]s.")
|
||||
|
||||
return dmm_text
|
||||
|
||||
/dmm_suite/proc/make_template(var/turf/model as turf, var/flags as num)
|
||||
var/use_json = 0
|
||||
if(flags & DMM_USE_JSON)
|
||||
use_json = 1
|
||||
/datum/dmm_suite/proc/make_template(turf/model, flags = 0)
|
||||
var/use_json = (flags & DMM_USE_JSON) ? TRUE : FALSE
|
||||
|
||||
var/template = ""
|
||||
var/turf_template = ""
|
||||
var/list/obj_template = list()
|
||||
var/list/mob_template = list()
|
||||
var/area_template = ""
|
||||
|
||||
|
||||
|
||||
// Turf
|
||||
if(!(flags & DMM_IGNORE_TURFS))
|
||||
turf_template = "[model.type][check_attributes(model,use_json=use_json)],"
|
||||
else turf_template = "[world.turf],"
|
||||
else
|
||||
turf_template = "[world.turf],"
|
||||
|
||||
// Objects loop
|
||||
if(!(flags & DMM_IGNORE_OBJS))
|
||||
for(var/obj/O in model.contents)
|
||||
if(O.dont_save || QDELETED(O))
|
||||
continue
|
||||
|
||||
obj_template += "[O.type][check_attributes(O,use_json=use_json)],"
|
||||
|
||||
// Mobs Loop
|
||||
for(var/mob/M in model.contents)
|
||||
if(M.dont_save || QDELETED(M))
|
||||
continue
|
||||
|
||||
if(M.client)
|
||||
if(!(flags & DMM_IGNORE_PLAYERS))
|
||||
mob_template += "[M.type][check_attributes(M,use_json=use_json)],"
|
||||
@@ -155,65 +153,68 @@
|
||||
if(!(flags & DMM_IGNORE_AREAS))
|
||||
var/area/m_area = model.loc
|
||||
area_template = "[m_area.type][check_attributes(m_area,use_json=use_json)]"
|
||||
else area_template = "[world.area]"
|
||||
else
|
||||
area_template = "[world.area]"
|
||||
|
||||
template = "[jointext(obj_template,"")][jointext(mob_template,"")][turf_template][area_template]"
|
||||
return template
|
||||
|
||||
/dmm_suite/proc/check_attributes(var/atom/A,use_json=0)
|
||||
/datum/dmm_suite/proc/check_attributes(atom/A, use_json = FALSE)
|
||||
var/attributes_text = "{"
|
||||
var/list/attributes = list()
|
||||
if(!use_json)
|
||||
for(var/V in A.vars)
|
||||
CHECK_TICK
|
||||
if((!issaved(A.vars[V])) || (A.vars[V]==initial(A.vars[V]))) continue
|
||||
if((!issaved(A.vars[V])) || (A.vars[V] == initial(A.vars[V])))
|
||||
continue
|
||||
|
||||
attributes += var_to_dmm(A.vars[V], V)
|
||||
else
|
||||
var/list/yeah = A.serialize()
|
||||
var/list/to_encode = A.serialize()
|
||||
// We'll want to write out vars that are important to the editor
|
||||
// So that the map is legible as before
|
||||
for(var/thing in A.map_important_vars())
|
||||
for(var/T in A.map_important_vars())
|
||||
// Save vars that are important for the map editor, so that
|
||||
// json-encoded maps are legible for standard editors
|
||||
if(A.vars[thing] != initial(A.vars[thing]))
|
||||
yeah -= thing
|
||||
attributes += var_to_dmm(A.vars[thing],thing)
|
||||
if(A.vars[T] != initial(A.vars[T]))
|
||||
to_encode -= T
|
||||
attributes += var_to_dmm(A.vars[T], T)
|
||||
|
||||
// Remove useless info
|
||||
yeah -= "type"
|
||||
if(yeah.len)
|
||||
var/json_stuff = json_encode(yeah)
|
||||
to_encode -= "type"
|
||||
if(length(to_encode))
|
||||
var/json_stuff = json_encode(to_encode)
|
||||
attributes += var_to_dmm(json_stuff, "map_json_data")
|
||||
if(attributes.len == 0)
|
||||
|
||||
if(length(attributes) == 0)
|
||||
return
|
||||
|
||||
// Trim a trailing semicolon - `var_to_dmm` always appends a semicolon,
|
||||
// so the last one will be trailing.
|
||||
if(copytext(attributes_text, length(attributes_text)-1, 0) == "; ")
|
||||
attributes_text = copytext(attributes_text, 1, length(attributes_text)-1)
|
||||
if(copytext(attributes_text, length(attributes_text) - 1, 0) == "; ")
|
||||
attributes_text = copytext(attributes_text, 1, length(attributes_text) - 1)
|
||||
|
||||
attributes_text = "{[jointext(attributes,"; ")]}"
|
||||
return attributes_text
|
||||
|
||||
|
||||
/dmm_suite/proc/get_model_key(var/which as num, var/key_length as num)
|
||||
/datum/dmm_suite/proc/get_model_key(which, key_length)
|
||||
var/list/key = list()
|
||||
var/working_digit = which-1
|
||||
var/working_digit = which - 1
|
||||
for(var/digit_pos in key_length to 1 step -1)
|
||||
var/place_value = round/*floor*/(working_digit/(letter_digits.len**(digit_pos-1)))
|
||||
working_digit-=place_value*(letter_digits.len**(digit_pos-1))
|
||||
key += letter_digits[place_value+1]
|
||||
var/place_value = round/*floor*/(working_digit / (length(letter_digits) ** (digit_pos - 1)))
|
||||
working_digit -= place_value * (length(letter_digits) ** (digit_pos - 1))
|
||||
key += letter_digits[place_value + 1]
|
||||
|
||||
return jointext(key,"")
|
||||
|
||||
|
||||
/dmm_suite/proc/var_to_dmm(attr, name)
|
||||
/datum/dmm_suite/proc/var_to_dmm(attr, name)
|
||||
if(istext(attr))
|
||||
// dmm_encode will strip out characters that would be capable of disrupting
|
||||
// parsing - namely, quotes and curly braces
|
||||
return "[name] = \"[dmm_encode(attr)]\""
|
||||
else if(isnum(attr)||ispath(attr))
|
||||
else if(isnum(attr) || ispath(attr))
|
||||
return "[name] = [attr]"
|
||||
else if(isicon(attr)||isfile(attr))
|
||||
else if(isicon(attr) || isfile(attr))
|
||||
if(length("[attr]") == 0)
|
||||
// The DM map reader is unable to read files that have a '' file/icon entry
|
||||
return
|
||||
|
||||
@@ -191,26 +191,27 @@
|
||||
origin_tech = null
|
||||
selfcharge = 1
|
||||
can_charge = 0
|
||||
var/inawaymission = 1
|
||||
// Selfcharge is enabled and disabled, and used as the away mission tracker
|
||||
selfcharge = TRUE
|
||||
|
||||
/obj/item/gun/energy/laser/awaymission_aeg/process()
|
||||
var/turf/my_loc = get_turf(src)
|
||||
if(is_away_level(my_loc.z))
|
||||
if(inawaymission)
|
||||
return ..()
|
||||
/obj/item/gun/energy/laser/awaymission_aeg/Initialize(mapload)
|
||||
. = ..()
|
||||
// Force update it incase it spawns outside an away mission and shouldnt be charged
|
||||
onTransitZ(new_z = loc.z)
|
||||
|
||||
/obj/item/gun/energy/laser/awaymission_aeg/onTransitZ(old_z, new_z)
|
||||
if(is_away_level(new_z))
|
||||
if(ismob(loc))
|
||||
to_chat(loc, "<span class='notice'>Your [src] activates, starting to draw power from a nearby wireless power source.</span>")
|
||||
inawaymission = 1
|
||||
selfcharge = TRUE
|
||||
else
|
||||
if(inawaymission)
|
||||
if(selfcharge)
|
||||
if(ismob(loc))
|
||||
to_chat(loc, "<span class='danger'>Your [src] deactivates, as it is out of range from its power source.</span>")
|
||||
cell.charge = 0
|
||||
inawaymission = 0
|
||||
selfcharge = FALSE
|
||||
update_icon()
|
||||
|
||||
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/terror_black_toxin
|
||||
name = "beaker 'Black Terror Venom'"
|
||||
|
||||
|
||||
@@ -7,32 +7,32 @@
|
||||
|
||||
/area/awaymission/centcomAway/general
|
||||
name = "XCC-P5831"
|
||||
music = "music/ambigen3.ogg"
|
||||
ambientsounds = list('sound/ambience/ambigen3.ogg')
|
||||
|
||||
/area/awaymission/centcomAway/maint
|
||||
name = "XCC-P5831 Maintenance"
|
||||
icon_state = "away1"
|
||||
music = "music/ambisin1.ogg"
|
||||
ambientsounds = list('sound/ambience/ambisin1.ogg')
|
||||
|
||||
/area/awaymission/centcomAway/thunderdome
|
||||
name = "XCC-P5831 Thunderdome"
|
||||
icon_state = "away2"
|
||||
music = "music/ambisin2.ogg"
|
||||
ambientsounds = list('sound/ambience/ambisin2.ogg')
|
||||
|
||||
/area/awaymission/centcomAway/cafe
|
||||
name = "XCC-P5831 Kitchen Arena"
|
||||
icon_state = "away3"
|
||||
music = "music/ambisin3.ogg"
|
||||
ambientsounds = list('sound/ambience/ambisin3.ogg')
|
||||
|
||||
/area/awaymission/centcomAway/courtroom
|
||||
name = "XCC-P5831 Courtroom"
|
||||
icon_state = "away4"
|
||||
music = "music/ambisin4.ogg"
|
||||
ambientsounds = list('sound/ambience/ambisin4.ogg')
|
||||
|
||||
/area/awaymission/centcomAway/hangar
|
||||
name = "XCC-P5831 Hangars"
|
||||
icon_state = "away4"
|
||||
music = "music/ambigen5.ogg"
|
||||
ambientsounds = list('sound/ambience/ambigen5.ogg')
|
||||
|
||||
//centcomAway items
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
/obj/item/paper/fluff/ruins/oldstation/damagereport
|
||||
name = "Damage Report"
|
||||
info = "<b>*Damage Report*</b><br><br><b>Alpha Station</b> - Destroyed<br><br><b>Beta Station</b> - Catastrophic Damage. Medical, destroyed. Atmospherics, partially destroyed. Engine Core, destroyed.<br><br><b>Charlie Station</b> - Intact. Loss of oxygen to eastern side of main corridor.<br><br><b>Delta Station</b> - Intact. <b>WARNING</b>: Unknown force occupying Delta Station. Intent unknown. Species unknown. Numbers unknown.<br><br>Recommendation - Reestablish station powernet via solar array. Reestablish station atmospherics system to restore air."
|
||||
info = "<b>*Damage Report*</b><br><br><b>Alpha Station</b> - Destroyed<br><br><b>Beta Station</b> - Catastrophic Damage. Medical, destroyed. Atmospherics, partially destroyed. Engine Core, destroyed.<br><br><b>Charlie Station</b> - Intact. Loss of oxygen to eastern side of main corridor.<br><br><b>Theta Station</b> - Intact. <b>WARNING</b>: Unknown force occupying Theta Station. Intent unknown. Species unknown. Numbers unknown.<br><br>Recommendation - Reestablish station powernet via solar array. Reestablish station atmospherics system to restore air."
|
||||
|
||||
/obj/item/paper/fluff/ruins/oldstation/protosuit
|
||||
name = "B01-RIG Hardsuit Report"
|
||||
@@ -145,7 +145,7 @@
|
||||
info = "Artificial Program's report to surviving crewmembers.<br><br>Crew were placed into cryostasis on March 10th, 2445.<br><br>Crew were awoken from cryostasis around June, 2557.<br><br> \
|
||||
<b>SIGNIFICANT EVENTS OF NOTE</b><br>1: The primary radiation detectors were taken offline after 112 years due to power failure, secondary radiation detectors showed no residual \
|
||||
radiation on station. Deduction, primarily detector was malfunctioning and was producing a radiation signal when there was none.<br><br>2: A data burst from a nearby Nanotrasen Space \
|
||||
Station was received, this data burst contained research data that has been uploaded to our RnD labs.<br><br>3: Unknown invasion force has occupied Delta station."
|
||||
Station was received, this data burst contained research data that has been uploaded to our RnD labs.<br><br>3: Unknown invasion force has occupied Theta station."
|
||||
|
||||
/obj/item/paper/fluff/ruins/oldstation/generator_manual
|
||||
name = "S.U.P.E.R.P.A.C.M.A.N.-type portable generator manual"
|
||||
@@ -321,6 +321,7 @@
|
||||
name = "Beta Station Atmospherics"
|
||||
icon_state = "red"
|
||||
has_gravity = FALSE
|
||||
ambientsounds = ENGINEERING_SOUNDS
|
||||
|
||||
/area/ruin/space/ancientstation/betanorth
|
||||
name = "Beta Station North Corridor"
|
||||
@@ -333,6 +334,7 @@
|
||||
/area/ruin/space/ancientstation/engi
|
||||
name = "Charlie Station Engineering"
|
||||
icon_state = "engine"
|
||||
ambientsounds = ENGINEERING_SOUNDS
|
||||
|
||||
/area/ruin/space/ancientstation/comm
|
||||
name = "Charlie Station Command"
|
||||
@@ -350,16 +352,16 @@
|
||||
name = "Charlie Station Security"
|
||||
icon_state = "red"
|
||||
|
||||
/area/ruin/space/ancientstation/deltacorridor
|
||||
name = "Delta Station Main Corridor"
|
||||
/area/ruin/space/ancientstation/thetacorridor
|
||||
name = "Theta Station Main Corridor"
|
||||
icon_state = "green"
|
||||
|
||||
/area/ruin/space/ancientstation/proto
|
||||
name = "Delta Station Prototype Lab"
|
||||
name = "Theta Station Prototype Lab"
|
||||
icon_state = "toxlab"
|
||||
|
||||
/area/ruin/space/ancientstation/rnd
|
||||
name = "Delta Station Research and Development"
|
||||
name = "Theta Station Research and Development"
|
||||
icon_state = "toxlab"
|
||||
|
||||
/area/ruin/space/ancientstation/hivebot
|
||||
|
||||
@@ -117,10 +117,8 @@
|
||||
if("Peace")
|
||||
to_chat(user, "<B>Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.</B>")
|
||||
to_chat(user, "You feel as if you just narrowly avoided a terrible fate...")
|
||||
for(var/mob/living/simple_animal/hostile/faithless/F in world)
|
||||
F.health = -10
|
||||
F.stat = 2
|
||||
F.icon_state = "faithless_dead"
|
||||
for(var/mob/living/simple_animal/hostile/faithless/F in GLOB.mob_living_list)
|
||||
F.death()
|
||||
|
||||
|
||||
///////////////Meatgrinder//////////////
|
||||
@@ -220,7 +218,8 @@
|
||||
to_chat(user, "<span class='warning'>The communicator buzzes, and you hear the voice again: 'Really? I think not. Get them!'</span>")
|
||||
if(option_threat)
|
||||
to_chat(user, "<span class='warning'>The communicator buzzes, and you hear the voice again: 'Oh really now?' You hear a clicking sound. 'Team, get back here. We have trouble'. Then the line goes dead.</span>")
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(L.name == "wildwest_syndipod")
|
||||
var/obj/spacepod/syndi/P = new /obj/spacepod/syndi(get_turf(L))
|
||||
P.name = "Syndi Recon Pod"
|
||||
|
||||
@@ -56,7 +56,8 @@ GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "config/away
|
||||
GLOB.space_manager.remove_dirt(zlev)
|
||||
log_world(" Away mission loaded: [map]")
|
||||
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(L.name != "awaystart")
|
||||
continue
|
||||
GLOB.awaydestinations.Add(L)
|
||||
@@ -89,7 +90,8 @@ GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "config/away
|
||||
|
||||
//map_transition_config.Add(AWAY_MISSION_LIST)
|
||||
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
for(var/thing in GLOB.landmarks_list)
|
||||
var/obj/effect/landmark/L = thing
|
||||
if(L.name != "awaystart")
|
||||
continue
|
||||
GLOB.awaydestinations.Add(L)
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
return "buildmode_[key]"
|
||||
|
||||
/datum/buildmode_mode/proc/show_help(mob/user)
|
||||
CRASH("No help defined, yell at a coder")
|
||||
to_chat(user, "<span class='warning'>There is no help defined for this mode, this is a bug.</span>")
|
||||
CRASH("No help defined, yell at a coder")
|
||||
|
||||
/datum/buildmode_mode/proc/change_settings(mob/user)
|
||||
to_chat(user, "<span class='warning'>There is no configuration available for this mode</span>")
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
var/matrix/mat = matrix()
|
||||
mat.Translate(0, 16)
|
||||
mat.Scale(1, sqrt((x_offset * x_offset) + (y_offset * y_offset)) / 32)
|
||||
mat.Turn(90 - Atan2(x_offset, y_offset)) // So... You pass coords in order x,y to this version of atan2. It should be called acsc2.
|
||||
mat.Turn(90 - ATAN2(x_offset, y_offset)) // So... You pass coords in order x,y to this version of atan2. It should be called acsc2.
|
||||
mat.Translate(atom_a.pixel_x, atom_a.pixel_y)
|
||||
|
||||
transform = mat
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
var/plasma = 0
|
||||
var/cdiox = 0
|
||||
var/nitrox = 0
|
||||
var/agentbx = 0
|
||||
|
||||
|
||||
/datum/buildmode_mode/atmos/show_help(mob/user)
|
||||
@@ -29,6 +30,7 @@
|
||||
plasma = input(user, "Plasma ratio", "Input", 0) as num|null
|
||||
cdiox = input(user, "CO2 ratio", "Input", 0) as num|null
|
||||
nitrox = input(user, "N2O ratio", "Input", 0) as num|null
|
||||
agentbx = input(user, "Agent B ratio", "Input", 0) as num|null
|
||||
|
||||
/datum/buildmode_mode/atmos/proc/ppratio_to_moles(ppratio)
|
||||
// ideal gas equation: Pressure * Volume = Moles * r * Temperature
|
||||
@@ -52,11 +54,8 @@
|
||||
S.air.nitrogen = ppratio_to_moles(nitrogen)
|
||||
S.air.toxins = ppratio_to_moles(plasma)
|
||||
S.air.carbon_dioxide = ppratio_to_moles(cdiox)
|
||||
S.air.trace_gases.Cut()
|
||||
if(nitrox)
|
||||
var/datum/gas/TG = new /datum/gas/sleeping_agent
|
||||
TG.moles = ppratio_to_moles(nitrox)
|
||||
S.air.trace_gases += TG
|
||||
S.air.sleeping_agent = ppratio_to_moles(nitrox)
|
||||
S.air.agent_b = ppratio_to_moles(agentbx)
|
||||
S.update_visuals()
|
||||
S.air_update_turf()
|
||||
else if(ctrl_click) // overwrite "default" unsimulated air
|
||||
@@ -65,7 +64,8 @@
|
||||
T.nitrogen = ppratio_to_moles(nitrogen)
|
||||
T.toxins = ppratio_to_moles(plasma)
|
||||
T.carbon_dioxide = ppratio_to_moles(cdiox)
|
||||
// no interface for trace gases on unsim turfs
|
||||
T.sleeping_agent = ppratio_to_moles(nitrox)
|
||||
T.agent_b = ppratio_to_moles(agentbx)
|
||||
T.air_update_turf()
|
||||
|
||||
// admin log
|
||||
|
||||
@@ -22,6 +22,6 @@
|
||||
if(stored)
|
||||
DuplicateObject(stored, perfectcopy=1, sameloc=0,newloc=T)
|
||||
else if(right_click)
|
||||
if(ismovableatom(object)) // No copying turfs for now.
|
||||
if(ismovable(object)) // No copying turfs for now.
|
||||
to_chat(user, "<span class='notice'>[object] set as template.</span>")
|
||||
stored = object
|
||||
|
||||
@@ -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")
|
||||
@@ -177,6 +177,12 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
|
||||
|
||||
//DEFINITIONS FOR ASSET DATUMS START HERE.
|
||||
/datum/asset/simple/tgui
|
||||
assets = list(
|
||||
"tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js',
|
||||
"tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css'
|
||||
)
|
||||
|
||||
/datum/asset/simple/paper
|
||||
assets = list(
|
||||
"large_stamp-clown.png" = 'icons/paper_icons/large_stamp-clown.png',
|
||||
@@ -344,3 +350,15 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
|
||||
/datum/asset/mob_hunt/send(client)
|
||||
send_asset_list(client, assets, verify)
|
||||
|
||||
// Fontawesome
|
||||
/datum/asset/simple/fontawesome
|
||||
verify = FALSE
|
||||
assets = list(
|
||||
"fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
|
||||
"fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
|
||||
"fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot',
|
||||
"fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff',
|
||||
"font-awesome.css" = 'html/font-awesome/css/all.min.css',
|
||||
"v4shim.css" = 'html/font-awesome/css/v4-shims.min.css'
|
||||
)
|
||||
|
||||
@@ -59,10 +59,6 @@
|
||||
var/karma = 0
|
||||
var/karma_spent = 0
|
||||
var/karma_tab = 0
|
||||
/////////////////////////////////////////////
|
||||
// /vg/: MEDIAAAAAAAA
|
||||
// Set on login.
|
||||
var/datum/media_manager/media = null
|
||||
|
||||
var/topic_debugging = 0 //if set to true, allows client to see nanoUI errors -- yes i realize this is messy but it'll make live testing infinitely easier
|
||||
|
||||
@@ -85,10 +81,10 @@
|
||||
// If set to true, this client can interact with atoms such as buttons and doors on top of regular machinery interaction
|
||||
var/advanced_admin_interaction = FALSE
|
||||
|
||||
// Has the client been varedited by an admin? [Inherits from datum now]
|
||||
// var/var_edited = FALSE
|
||||
|
||||
var/client_keysend_amount = 0
|
||||
var/next_keysend_reset = 0
|
||||
var/next_keysend_trip_reset = 0
|
||||
var/keysend_tripped = FALSE
|
||||
|
||||
// Last world.time that the player tried to request their resources.
|
||||
var/last_ui_resource_send = 0
|
||||
|
||||
@@ -432,7 +432,13 @@
|
||||
//////////////
|
||||
//DISCONNECT//
|
||||
//////////////
|
||||
|
||||
/client/Del()
|
||||
if(!gc_destroyed)
|
||||
Destroy() //Clean up signals and timers.
|
||||
return ..()
|
||||
|
||||
/client/Destroy()
|
||||
if(holder)
|
||||
holder.owner = null
|
||||
GLOB.admins -= src
|
||||
@@ -442,7 +448,8 @@
|
||||
movingmob.client_mobs_in_contents -= mob
|
||||
UNSETEMPTY(movingmob.client_mobs_in_contents)
|
||||
Master.UpdateTickRate()
|
||||
return ..()
|
||||
..() //Even though we're going to be hard deleted there are still some things that want to know the destroy is happening
|
||||
return QDEL_HINT_HARDDEL_NOW
|
||||
|
||||
|
||||
/client/proc/donator_check()
|
||||
@@ -556,7 +563,7 @@
|
||||
if(GLOB.panic_bunker_enabled)
|
||||
var/threshold = config.panic_bunker_threshold
|
||||
src << "Server is not accepting connections from never-before-seen players until player count is less than [threshold]. Please try again later."
|
||||
del(src)
|
||||
qdel(src)
|
||||
return // Dont insert or they can just go in again
|
||||
|
||||
var/DBQuery/query_insert = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')")
|
||||
@@ -906,3 +913,35 @@
|
||||
return TRUE
|
||||
|
||||
#undef SSD_WARNING_TIMER
|
||||
|
||||
/client/verb/resend_ui_resources()
|
||||
set name = "Reload UI Resources"
|
||||
set desc = "Reload your UI assets if they are not working"
|
||||
set category = "Special Verbs"
|
||||
|
||||
if(last_ui_resource_send > world.time)
|
||||
to_chat(usr, "<span class='warning'>You requested your UI resource files too quickly. Please try again in [(last_ui_resource_send - world.time)/10] seconds.</span>")
|
||||
return
|
||||
|
||||
var/choice = alert(usr, "This will reload your NanoUI and TGUI resources. If you have any open UIs this may break them. Are you sure?", "Resource Reloading", "Yes", "No")
|
||||
if(choice == "Yes")
|
||||
// 600 deciseconds = 1 minute
|
||||
last_ui_resource_send = world.time + 60 SECONDS
|
||||
|
||||
// Close their open UIs
|
||||
SSnanoui.close_user_uis(usr)
|
||||
SStgui.close_user_uis(usr)
|
||||
|
||||
// Resend the resources
|
||||
var/datum/asset/nano_assets = get_asset_datum(/datum/asset/nanoui)
|
||||
nano_assets.register()
|
||||
|
||||
var/datum/asset/tgui_assets = get_asset_datum(/datum/asset/simple/tgui)
|
||||
tgui_assets.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>")
|
||||
|
||||
|
||||
@@ -9,39 +9,6 @@ GLOBAL_LIST_EMPTY(gear_datums)
|
||||
category = cat
|
||||
..()
|
||||
|
||||
/hook/startup/proc/populate_gear_list()
|
||||
//create a list of gear datums to sort
|
||||
for(var/geartype in subtypesof(/datum/gear))
|
||||
var/datum/gear/G = geartype
|
||||
|
||||
var/use_name = initial(G.display_name)
|
||||
var/use_category = initial(G.sort_category)
|
||||
|
||||
if(G == initial(G.subtype_path))
|
||||
continue
|
||||
|
||||
if(!use_name)
|
||||
error("Loadout - Missing display name: [G]")
|
||||
continue
|
||||
if(!initial(G.cost))
|
||||
error("Loadout - Missing cost: [G]")
|
||||
continue
|
||||
if(!initial(G.path))
|
||||
error("Loadout - Missing path definition: [G]")
|
||||
continue
|
||||
|
||||
if(!GLOB.loadout_categories[use_category])
|
||||
GLOB.loadout_categories[use_category] = new /datum/loadout_category(use_category)
|
||||
var/datum/loadout_category/LC = GLOB.loadout_categories[use_category]
|
||||
GLOB.gear_datums[use_name] = new geartype
|
||||
LC.gear[use_name] = GLOB.gear_datums[use_name]
|
||||
|
||||
GLOB.loadout_categories = sortAssoc(GLOB.loadout_categories)
|
||||
for(var/loadout_category in GLOB.loadout_categories)
|
||||
var/datum/loadout_category/LC = GLOB.loadout_categories[loadout_category]
|
||||
LC.gear = sortAssoc(LC.gear)
|
||||
return 1
|
||||
|
||||
/datum/gear
|
||||
var/display_name //Name/index. Must be unique.
|
||||
var/description //Description of this gear. If left blank will default to the description of the pathed item.
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -42,11 +42,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 +108,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
|
||||
|
||||
@@ -175,32 +175,36 @@
|
||||
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")
|
||||
|
||||
@@ -54,7 +54,6 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
return C.player_age
|
||||
else
|
||||
return max(0, days - C.player_age)
|
||||
return 0
|
||||
|
||||
#define MAX_SAVE_SLOTS 30 // Save slots for regular players
|
||||
#define MAX_SAVE_SLOTS_MEMBER 30 // Save slots for BYOND members
|
||||
@@ -189,6 +188,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
// OOC Metadata:
|
||||
var/metadata = ""
|
||||
var/slot_name = ""
|
||||
var/saved = FALSE // Indicates whether the character comes from the database or not
|
||||
|
||||
// Whether or not to use randomized character slots
|
||||
var/randomslot = 0
|
||||
@@ -264,10 +264,12 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
dat += "<a href='?_src_=prefs;preference=name'><span class='[be_random_name ? "good" : "bad"]'>(Always Randomize)</span></a><br>"
|
||||
dat += "</td><td width='405px' height='25px' valign='left'>"
|
||||
dat += "<center>"
|
||||
dat += "Slot <b>[slot_name]</b> - "
|
||||
dat += "Slot <b>[default_slot][saved ? "" : " (empty)"]</b><br>"
|
||||
dat += "<a href=\"byond://?_src_=prefs;preference=open_load_dialog\">Load slot</a> - "
|
||||
dat += "<a href=\"byond://?_src_=prefs;preference=save\">Save slot</a> - "
|
||||
dat += "<a href=\"byond://?_src_=prefs;preference=reload\">Reload slot</a>"
|
||||
if(saved)
|
||||
dat += " - <a href=\"byond://?_src_=prefs;preference=clear\"><span class='bad'>Clear slot</span></a>"
|
||||
dat += "</center>"
|
||||
dat += "</td></tr></table>"
|
||||
dat += "<table width='100%'><tr><td width='405px' height='200px' valign='top'>"
|
||||
@@ -624,6 +626,9 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
if(job.admin_only)
|
||||
continue
|
||||
|
||||
if(job.hidden_from_job_prefs)
|
||||
continue
|
||||
|
||||
index += 1
|
||||
if((index >= limit) || (job.title in splitJobs))
|
||||
if((index < limit) && (lastJob != null))
|
||||
@@ -2001,6 +2006,11 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
windowflashing = !windowflashing
|
||||
|
||||
if("afk_watch")
|
||||
if(!afk_watch)
|
||||
to_chat(user, "<span class='info'>You will now get put into cryo dorms after [config.auto_cryo_afk] minutes. \
|
||||
Then after [config.auto_despawn_afk] minutes you will be fully despawned. You will receive a visual and auditory warning before you will be put into cryodorms.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='info'>Automatic cryoing turned off.</span>")
|
||||
afk_watch = !afk_watch
|
||||
|
||||
if("UIcolor")
|
||||
@@ -2071,6 +2081,11 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
|
||||
load_preferences(user)
|
||||
load_character(user)
|
||||
|
||||
if("clear")
|
||||
if(!saved || real_name != input("This will clear the current slot permanently. Please enter the character's full name to confirm."))
|
||||
return FALSE
|
||||
clear_character_slot(user)
|
||||
|
||||
if("open_load_dialog")
|
||||
if(!IsGuestKey(user.key))
|
||||
open_load_dialog(user)
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
UI_style_alpha='[UI_style_alpha]',
|
||||
be_role='[sanitizeSQL(list2params(be_special))]',
|
||||
default_slot='[default_slot]',
|
||||
toggles='[num2text(toggles, Ceiling(log(10, (TOGGLES_TOTAL))))]',
|
||||
toggles='[num2text(toggles, CEILING(log(10, (TOGGLES_TOTAL)), 1))]',
|
||||
atklog='[atklog]',
|
||||
sound='[sound]',
|
||||
randomslot='[randomslot]',
|
||||
@@ -121,6 +121,7 @@
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/load_character(client/C,slot)
|
||||
saved = FALSE
|
||||
|
||||
if(!slot) slot = default_slot
|
||||
slot = sanitize_integer(slot, 1, max_save_slots, initial(default_slot))
|
||||
@@ -262,6 +263,8 @@
|
||||
loadout_gear = params2list(query.item[51])
|
||||
autohiss_mode = text2num(query.item[52])
|
||||
|
||||
saved = TRUE
|
||||
|
||||
//Sanitize
|
||||
var/datum/species/SP = GLOB.all_species[species]
|
||||
metadata = sanitize_text(metadata, initial(metadata))
|
||||
@@ -320,6 +323,10 @@
|
||||
if(!rlimb_data) src.rlimb_data = list()
|
||||
if(!loadout_gear) loadout_gear = list()
|
||||
|
||||
// Check if the current body accessory exists
|
||||
if(!GLOB.body_accessory_by_name[body_accessory])
|
||||
body_accessory = null
|
||||
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/save_character(client/C)
|
||||
@@ -470,6 +477,8 @@
|
||||
log_game("SQL ERROR during character slot saving. Error : \[[err]\]\n")
|
||||
message_admins("SQL ERROR during character slot saving. Error : \[[err]\]\n")
|
||||
return
|
||||
|
||||
saved = TRUE
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/load_random_character_slot(client/C)
|
||||
@@ -491,3 +500,20 @@
|
||||
load_character(C,pick(saves))
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/clear_character_slot(client/C)
|
||||
. = FALSE
|
||||
// Is there a character in that slot?
|
||||
var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' AND slot='[default_slot]'")
|
||||
query.Execute()
|
||||
if(!query.RowCount())
|
||||
return
|
||||
|
||||
var/DBQuery/query2 = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' AND slot='[default_slot]'")
|
||||
if(!query2.Execute())
|
||||
var/err = query2.ErrorMsg()
|
||||
log_game("SQL ERROR during character slot clearing. Error : \[[err]\]\n")
|
||||
message_admins("SQL ERROR during character slot clearing. Error : \[[err]\]\n")
|
||||
return
|
||||
|
||||
saved = FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
..()
|
||||
initialize_outfits()
|
||||
|
||||
/datum/action/chameleon_outfit/Destroy()
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
return ..()
|
||||
|
||||
/datum/action/chameleon_outfit/proc/initialize_outfits()
|
||||
var/static/list/standard_outfit_options
|
||||
if(!standard_outfit_options)
|
||||
@@ -140,29 +144,29 @@
|
||||
UpdateButtonIcon()
|
||||
|
||||
/datum/action/item_action/chameleon/change/proc/update_item(obj/item/picked_item)
|
||||
// Species-related variables are lists, which can not be retrieved using initial(). As such, we need to instantiate the picked item.
|
||||
var/obj/item/P = new picked_item(null)
|
||||
|
||||
target.name = P.name
|
||||
target.desc = P.desc
|
||||
target.icon_state = P.icon_state
|
||||
target.name = initial(picked_item.name)
|
||||
target.desc = initial(picked_item.desc)
|
||||
target.icon_state = initial(picked_item.icon_state)
|
||||
|
||||
if(isitem(target))
|
||||
var/obj/item/I = target
|
||||
|
||||
I.item_state = P.item_state
|
||||
I.item_color = P.item_color
|
||||
I.item_state = initial(picked_item.item_state)
|
||||
I.item_color = initial(picked_item.item_color)
|
||||
|
||||
I.icon_override = P.icon_override
|
||||
I.sprite_sheets = P.sprite_sheets
|
||||
I.icon_override = initial(picked_item.icon_override)
|
||||
if(initial(picked_item.sprite_sheets))
|
||||
// Species-related variables are lists, which can not be retrieved using initial(). As such, we need to instantiate the picked item.
|
||||
var/obj/item/P = new picked_item(null)
|
||||
I.sprite_sheets = P.sprite_sheets
|
||||
qdel(P)
|
||||
|
||||
if(istype(I, /obj/item/clothing) && istype(P, /obj/item/clothing))
|
||||
if(istype(I, /obj/item/clothing) && istype(initial(picked_item), /obj/item/clothing))
|
||||
var/obj/item/clothing/CL = I
|
||||
var/obj/item/clothing/PCL = P
|
||||
CL.flags_cover = PCL.flags_cover
|
||||
var/obj/item/clothing/PCL = picked_item
|
||||
CL.flags_cover = initial(PCL.flags_cover)
|
||||
|
||||
target.icon = P.icon
|
||||
qdel(P)
|
||||
target.icon = initial(picked_item.icon)
|
||||
|
||||
/datum/action/item_action/chameleon/change/Trigger()
|
||||
if(!IsAvailable())
|
||||
@@ -198,7 +202,7 @@
|
||||
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/clothing/under/chameleon/Initialize()
|
||||
/obj/item/clothing/under/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/clothing/under
|
||||
@@ -206,11 +210,15 @@
|
||||
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/under, /obj/item/clothing/under/color, /obj/item/clothing/under/rank), only_root_path = TRUE)
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/clothing/under/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/under/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/clothing/under/chameleon/broken/Initialize()
|
||||
/obj/item/clothing/under/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -229,7 +237,7 @@
|
||||
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/clothing/suit/chameleon/Initialize()
|
||||
/obj/item/clothing/suit/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/clothing/suit
|
||||
@@ -237,11 +245,15 @@
|
||||
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/suit/armor/abductor), only_root_path = TRUE)
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/clothing/suit/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/suit/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/clothing/suit/chameleon/broken/Initialize()
|
||||
/obj/item/clothing/suit/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -261,7 +273,7 @@
|
||||
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/clothing/glasses/chameleon/Initialize()
|
||||
/obj/item/clothing/glasses/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/clothing/glasses
|
||||
@@ -269,11 +281,15 @@
|
||||
chameleon_action.chameleon_blacklist = list()
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/clothing/glasses/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/glasses/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/clothing/glasses/chameleon/broken/Initialize()
|
||||
/obj/item/clothing/glasses/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -289,7 +305,7 @@
|
||||
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/clothing/glasses/hud/security/chameleon/Initialize()
|
||||
/obj/item/clothing/glasses/hud/security/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/clothing/glasses
|
||||
@@ -297,11 +313,15 @@
|
||||
chameleon_action.chameleon_blacklist = list()
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/clothing/glasses/hud/security/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/glasses/hud/security/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/clothing/glasses/hud/security/chameleon/broken/Initialize()
|
||||
/obj/item/clothing/glasses/hud/security/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -316,7 +336,7 @@
|
||||
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/clothing/gloves/chameleon/Initialize()
|
||||
/obj/item/clothing/gloves/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/clothing/gloves
|
||||
@@ -324,11 +344,15 @@
|
||||
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/gloves, /obj/item/clothing/gloves/color), only_root_path = TRUE)
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/clothing/gloves/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/gloves/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/clothing/gloves/chameleon/broken/Initialize()
|
||||
/obj/item/clothing/gloves/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -347,7 +371,7 @@
|
||||
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/clothing/head/chameleon/Initialize()
|
||||
/obj/item/clothing/head/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/clothing/head
|
||||
@@ -355,11 +379,15 @@
|
||||
chameleon_action.chameleon_blacklist = list()
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/clothing/head/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/head/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/clothing/head/chameleon/broken/Initialize()
|
||||
/obj/item/clothing/head/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -389,7 +417,7 @@
|
||||
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/clothing/mask/chameleon/Initialize()
|
||||
/obj/item/clothing/mask/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
chameleon_action = new(src)
|
||||
@@ -402,13 +430,14 @@
|
||||
|
||||
/obj/item/clothing/mask/chameleon/Destroy()
|
||||
QDEL_NULL(voice_changer)
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/mask/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/clothing/mask/chameleon/broken/Initialize()
|
||||
/obj/item/clothing/mask/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -423,7 +452,7 @@
|
||||
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/clothing/shoes/chameleon/Initialize()
|
||||
/obj/item/clothing/shoes/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/clothing/shoes
|
||||
@@ -431,6 +460,10 @@
|
||||
chameleon_action.chameleon_blacklist = list()
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/clothing/shoes/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/shoes/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
@@ -442,7 +475,7 @@
|
||||
desc = "A pair of black shoes."
|
||||
flags = NOSLIP
|
||||
|
||||
/obj/item/clothing/shoes/chameleon/noslip/broken/Initialize()
|
||||
/obj/item/clothing/shoes/chameleon/noslip/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -455,18 +488,22 @@
|
||||
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/storage/backpack/chameleon/Initialize()
|
||||
/obj/item/storage/backpack/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/storage/backpack
|
||||
chameleon_action.chameleon_name = "Backpack"
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/storage/backpack/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/backpack/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/storage/backpack/chameleon/broken/Initialize()
|
||||
/obj/item/storage/backpack/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -475,7 +512,7 @@
|
||||
desc = "Holds tools."
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/storage/belt/chameleon/Initialize()
|
||||
/obj/item/storage/belt/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
chameleon_action = new(src)
|
||||
@@ -483,11 +520,15 @@
|
||||
chameleon_action.chameleon_name = "Belt"
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/storage/belt/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/belt/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/storage/belt/chameleon/broken/Initialize()
|
||||
/obj/item/storage/belt/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -495,18 +536,22 @@
|
||||
name = "radio headset"
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/radio/headset/chameleon/Initialize()
|
||||
/obj/item/radio/headset/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/radio/headset
|
||||
chameleon_action.chameleon_name = "Headset"
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/radio/headset/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/headset/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/radio/headset/chameleon/broken/Initialize()
|
||||
/obj/item/radio/headset/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -514,7 +559,7 @@
|
||||
name = "PDA"
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/pda/chameleon/Initialize()
|
||||
/obj/item/pda/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/pda
|
||||
@@ -522,24 +567,32 @@
|
||||
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/pda/heads), only_root_path = TRUE)
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/pda/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/pda/chameleon/emp_act(severity)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise()
|
||||
|
||||
/obj/item/pda/chameleon/broken/Initialize()
|
||||
/obj/item/pda/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
/obj/item/stamp/chameleon
|
||||
var/datum/action/item_action/chameleon/change/chameleon_action
|
||||
|
||||
/obj/item/stamp/chameleon/Initialize()
|
||||
/obj/item/stamp/chameleon/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action = new(src)
|
||||
chameleon_action.chameleon_type = /obj/item/stamp
|
||||
chameleon_action.chameleon_name = "Stamp"
|
||||
chameleon_action.initialize_disguises()
|
||||
|
||||
/obj/item/stamp/chameleon/broken/Initialize()
|
||||
/obj/item/stamp/chameleon/Destroy()
|
||||
QDEL_NULL(chameleon_action)
|
||||
return ..()
|
||||
|
||||
/obj/item/stamp/chameleon/broken/Initialize(mapload)
|
||||
. = ..()
|
||||
chameleon_action.emp_randomise(INFINITY)
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
|
||||
/obj/item/clothing/head/soft/sec/corp
|
||||
name = "corporate security cap"
|
||||
desc = "It's baseball hat in corpotate colours."
|
||||
desc = "It's a baseball hat in corporate colours."
|
||||
icon_state = "corpsoft"
|
||||
item_color = "corp"
|
||||
|
||||
|
||||
@@ -86,21 +86,25 @@
|
||||
name = "orange shoes"
|
||||
icon_state = "orange"
|
||||
item_color = "orange"
|
||||
var/obj/item/restraints/handcuffs/shackles
|
||||
|
||||
/obj/item/clothing/shoes/orange/attack_self(mob/user as mob)
|
||||
if(src.chained)
|
||||
src.chained = null
|
||||
src.slowdown = SHOES_SLOWDOWN
|
||||
new /obj/item/restraints/handcuffs( user.loc )
|
||||
src.icon_state = "orange"
|
||||
return
|
||||
/obj/item/clothing/shoes/orange/Destroy()
|
||||
QDEL_NULL(shackles)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/shoes/orange/attackby(obj/H, loc, params)
|
||||
..()
|
||||
if(istype(H, /obj/item/restraints/handcuffs) && !chained && !(H.flags & NODROP))
|
||||
if(src.icon_state != "orange") return
|
||||
qdel(H)
|
||||
src.chained = 1
|
||||
src.slowdown = 15
|
||||
src.icon_state = "orange1"
|
||||
return
|
||||
/obj/item/clothing/shoes/orange/attack_self(mob/user)
|
||||
if(shackles)
|
||||
user.put_in_hands(shackles)
|
||||
shackles = null
|
||||
slowdown = SHOES_SLOWDOWN
|
||||
icon_state = "orange"
|
||||
|
||||
/obj/item/clothing/shoes/orange/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/restraints/handcuffs) && !shackles)
|
||||
if(user.drop_item())
|
||||
I.forceMove(src)
|
||||
shackles = I
|
||||
slowdown = 15
|
||||
icon_state = "orange1"
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -73,16 +73,15 @@ obj/item/clothing/shoes/magboots/syndie/advance //For the Syndicate Strike Team
|
||||
shoe_sound = "clownstep"
|
||||
origin_tech = "magnets=4;syndicate=2"
|
||||
var/enabled_waddle = TRUE
|
||||
var/datum/component/waddle
|
||||
|
||||
/obj/item/clothing/shoes/magboots/clown/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(slot == slot_shoes && enabled_waddle)
|
||||
waddle = user.AddComponent(/datum/component/waddling)
|
||||
user.AddElement(/datum/element/waddling)
|
||||
|
||||
/obj/item/clothing/shoes/magboots/clown/dropped(mob/user)
|
||||
. = ..()
|
||||
QDEL_NULL(waddle)
|
||||
user.RemoveElement(/datum/element/waddling)
|
||||
|
||||
/obj/item/clothing/shoes/magboots/clown/CtrlClick(mob/living/user)
|
||||
if(!isliving(user))
|
||||
|
||||
@@ -71,16 +71,15 @@
|
||||
var/footstep = 1 //used for squeeks whilst walking
|
||||
shoe_sound = "clownstep"
|
||||
var/enabled_waddle = TRUE
|
||||
var/datum/component/waddle
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(slot == slot_shoes && enabled_waddle)
|
||||
waddle = user.AddComponent(/datum/component/waddling)
|
||||
user.AddElement(/datum/element/waddling)
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/dropped(mob/user)
|
||||
. = ..()
|
||||
QDEL_NULL(waddle)
|
||||
user.RemoveElement(/datum/element/waddling)
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/CtrlClick(mob/living/user)
|
||||
if(!isliving(user))
|
||||
|
||||
@@ -531,7 +531,7 @@
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/shielded/process()
|
||||
if(world.time > recharge_cooldown && current_charges < max_charges)
|
||||
current_charges = Clamp((current_charges + recharge_rate), 0, max_charges)
|
||||
current_charges = clamp((current_charges + recharge_rate), 0, max_charges)
|
||||
playsound(loc, 'sound/magic/charge.ogg', 50, TRUE)
|
||||
if(current_charges == max_charges)
|
||||
playsound(loc, 'sound/machines/ding.ogg', 50, TRUE)
|
||||
|
||||
@@ -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,21 +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.
|
||||
|
||||
for(var/obj/item/piece in list(gloves, helmet, boots, chest))
|
||||
if(!istype(piece)) //Do we have the piece
|
||||
continue
|
||||
if(islist(armor)) //Did we even give them some armor, if this is the case, the list should be initialized from New()
|
||||
var/list/L = armor
|
||||
for(var/armortype in L)
|
||||
piece.armor[armortype] = L[armortype]*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()
|
||||
@@ -1,70 +0,0 @@
|
||||
/datum/wires/rig
|
||||
random = 1
|
||||
holder_type = /obj/item/rig
|
||||
wire_count = 5
|
||||
|
||||
#define RIG_SECURITY 1
|
||||
#define RIG_AI_OVERRIDE 2
|
||||
#define RIG_SYSTEM_CONTROL 4
|
||||
#define RIG_INTERFACE_LOCK 8
|
||||
#define RIG_INTERFACE_SHOCK 16
|
||||
/*
|
||||
* Rig security can be snipped to disable ID access checks on rig.
|
||||
* Rig AI override can be pulsed to toggle whether or not the AI can take control of the suit.
|
||||
* System control can be pulsed to toggle some malfunctions.
|
||||
* Interface lock can be pulsed to toggle whether or not the interface can be accessed.
|
||||
*/
|
||||
|
||||
/datum/wires/rig/UpdateCut(var/index, var/mended)
|
||||
|
||||
var/obj/item/rig/rig = holder
|
||||
switch(index)
|
||||
if(RIG_SECURITY)
|
||||
if(mended)
|
||||
rig.req_access = initial(rig.req_access)
|
||||
rig.req_one_access = initial(rig.req_one_access)
|
||||
if(RIG_INTERFACE_SHOCK)
|
||||
rig.electrified = mended ? 0 : -1
|
||||
rig.shock(usr,100)
|
||||
|
||||
/datum/wires/rig/UpdatePulsed(var/index)
|
||||
|
||||
var/obj/item/rig/rig = holder
|
||||
switch(index)
|
||||
if(RIG_SECURITY)
|
||||
rig.security_check_enabled = !rig.security_check_enabled
|
||||
rig.visible_message("\The [rig] twitches as several suit locks [rig.security_check_enabled?"close":"open"].")
|
||||
if(RIG_AI_OVERRIDE)
|
||||
rig.ai_override_enabled = !rig.ai_override_enabled
|
||||
rig.visible_message("A small red light on [rig] [rig.ai_override_enabled?"goes dead":"flickers on"].")
|
||||
if(RIG_SYSTEM_CONTROL)
|
||||
rig.malfunctioning += 10
|
||||
if(rig.malfunction_delay <= 0)
|
||||
rig.malfunction_delay = 20
|
||||
rig.shock(usr,100)
|
||||
if(RIG_INTERFACE_LOCK)
|
||||
rig.interface_locked = !rig.interface_locked
|
||||
rig.visible_message("\The [rig] clicks audibly as the software interface [rig.interface_locked?"darkens":"brightens"].")
|
||||
if(RIG_INTERFACE_SHOCK)
|
||||
if(rig.electrified != -1)
|
||||
rig.electrified = 30
|
||||
rig.shock(usr,100)
|
||||
|
||||
/datum/wires/rig/GetWireName(index)
|
||||
switch(index)
|
||||
if(RIG_SECURITY)
|
||||
return "ID check"
|
||||
if(RIG_AI_OVERRIDE)
|
||||
return "AI control"
|
||||
if(RIG_SYSTEM_CONTROL)
|
||||
return "System control"
|
||||
if(RIG_INTERFACE_LOCK)
|
||||
return "Interface lock"
|
||||
if(RIG_INTERFACE_SHOCK)
|
||||
return "Electrification"
|
||||
|
||||
/datum/wires/rig/CanUse(var/mob/living/L)
|
||||
var/obj/item/rig/rig = holder
|
||||
if(rig.open)
|
||||
return 1
|
||||
return 0
|
||||
@@ -1,46 +0,0 @@
|
||||
/obj/item/rig/unathi
|
||||
name = "NT breacher chassis control module"
|
||||
desc = "A cheap NT knock-off of an Unathi battle-rig. Looks like a fish, moves like a fish, steers like a cow."
|
||||
suit_type = "NT breacher"
|
||||
icon_state = "breacher_rig_cheap"
|
||||
armor = list(melee = 30, bullet = 30, laser = 30, energy = 30, bomb = 45, bio = 100, rad = 50)
|
||||
emp_protection = -20
|
||||
active_slowdown = 6
|
||||
offline_slowdown = 10
|
||||
vision_restriction = 1
|
||||
offline_vision_restriction = 2
|
||||
|
||||
chest_type = /obj/item/clothing/suit/space/new_rig/unathi
|
||||
helm_type = /obj/item/clothing/head/helmet/space/new_rig/unathi
|
||||
glove_type = /obj/item/clothing/gloves/rig/unathi
|
||||
boot_type = /obj/item/clothing/shoes/magboots/rig/unathi
|
||||
|
||||
/obj/item/rig/unathi/fancy
|
||||
name = "breacher chassis control module"
|
||||
desc = "An authentic Unathi breacher chassis. Huge, bulky and absurdly heavy. It must be like wearing a tank."
|
||||
suit_type = "breacher chassis"
|
||||
icon_state = "breacher_rig"
|
||||
armor = list(melee = 45, bullet = 45, laser = 45, energy = 45, bomb = 45, bio = 100, rad = 75) //Takes TEN TIMES as much damage to stop someone in a breacher. In exchange, it's slow. //Whoever made this was on meth
|
||||
vision_restriction = 0
|
||||
|
||||
/obj/item/clothing/head/helmet/space/new_rig/unathi
|
||||
icon = 'icons/obj/clothing/species/unathi/hats.dmi'
|
||||
species_restricted = list("Unathi")
|
||||
|
||||
/obj/item/clothing/suit/space/new_rig/unathi
|
||||
icon = 'icons/obj/clothing/species/unathi/suits.dmi'
|
||||
species_restricted = list("Unathi")
|
||||
|
||||
/obj/item/clothing/gloves/rig/unathi
|
||||
icon = 'icons/obj/clothing/species/unathi/gloves.dmi'
|
||||
species_restricted = list("Unathi")
|
||||
sprite_sheets = list(
|
||||
"Unathi" = 'icons/mob/species/unathi/gloves.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/shoes/magboots/rig/unathi
|
||||
icon = 'icons/obj/clothing/species/unathi/shoes.dmi'
|
||||
species_restricted = list("Unathi")
|
||||
sprite_sheets = list(
|
||||
"Unathi" = 'icons/mob/species/unathi/feet.dmi'
|
||||
)
|
||||
@@ -1,28 +0,0 @@
|
||||
/obj/item/clothing/head/helmet/space/new_rig/combat
|
||||
|
||||
/obj/item/rig/combat
|
||||
name = "combat hardsuit control module"
|
||||
desc = "A sleek and dangerous hardsuit for active combat."
|
||||
icon_state = "security_rig"
|
||||
suit_type = "combat hardsuit"
|
||||
armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100)
|
||||
active_slowdown = 1
|
||||
offline_slowdown = 3
|
||||
offline_vision_restriction = 1
|
||||
|
||||
helm_type = /obj/item/clothing/head/helmet/space/new_rig/combat
|
||||
allowed = list(/obj/item/gun,/obj/item/flashlight,/obj/item/tank,/obj/item/melee/baton)
|
||||
|
||||
|
||||
/obj/item/rig/combat/equipped
|
||||
|
||||
|
||||
initial_modules = list(
|
||||
/obj/item/rig_module/mounted,
|
||||
/obj/item/rig_module/vision/thermal,
|
||||
/obj/item/rig_module/grenade_launcher,
|
||||
/obj/item/rig_module/ai_container,
|
||||
// /obj/item/rig_module/power_sink,
|
||||
/obj/item/rig_module/electrowarfare_suite,
|
||||
/obj/item/rig_module/chem_dispenser/combat
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user