Merge branch 'master' into upstream-merge-31176

This commit is contained in:
LetterJay
2017-11-09 03:24:38 -06:00
committed by GitHub
1253 changed files with 77070 additions and 91353 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
// it's """VR"""
/obj/machinery/vr_sleeper
name = "virtual reality sleeper"
desc = "a sleeper modified to alter the subconscious state of the user, allowing them to visit virtual worlds"
desc = "A sleeper modified to alter the subconscious state of the user, allowing them to visit virtual worlds."
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "sleeper"
state_open = TRUE
+11 -6
View File
@@ -50,9 +50,12 @@
announceinirc = 1
blockselfban = 1
kickbannedckey = 1
if( !bantype_pass ) return
if( !istext(reason) ) return
if( !isnum(duration) ) return
if( !bantype_pass )
return
if( !istext(reason) )
return
if( !isnum(duration) )
return
var/ckey
var/computerid
@@ -174,7 +177,8 @@
if(BANTYPE_ANY_JOB)
bantype_str = "ANYJOB"
bantype_pass = 1
if( !bantype_pass ) return
if( !bantype_pass )
return
var/bantype_sql
if(bantype_str == "ANY")
@@ -434,7 +438,7 @@
output += "<th width='15%'><b>OPTIONS</b></th>"
output += "</tr>"
var/limit = " LIMIT [bansperpage * page], [bansperpage]"
var/datum/DBQuery/query_search_bans = SSdbcore.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC[limit]")
var/datum/DBQuery/query_search_bans = SSdbcore.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, round_id FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] ORDER BY bantime DESC[limit]")
if(!query_search_bans.warn_execute())
return
@@ -452,6 +456,7 @@
var/unbanckey = query_search_bans.item[11]
var/unbantime = query_search_bans.item[12]
var/edits = query_search_bans.item[13]
var/round_id = query_search_bans.item[14]
var/lcolor = blcolor
var/dcolor = bdcolor
@@ -477,7 +482,7 @@
output += "<tr bgcolor='[dcolor]'>"
output += "<td align='center'>[typedesc]</td>"
output += "<td align='center'><b>[ckey]</b></td>"
output += "<td align='center'>[bantime]</td>"
output += "<td align='center'>[bantime] (Round ID: [round_id])</td>"
output += "<td align='center'><b>[ackey]</b></td>"
output += "<td align='center'>[(unbanned) ? "" : "<b><a href=\"byond://?src=\ref[src];[HrefToken()];dbbanedit=unban;dbbanid=[banid]\">Unban</a></b>"]</td>"
output += "</tr>"
+5 -3
View File
@@ -6,8 +6,10 @@
#define STICKYBAN_MAX_EXISTING_USER_MATCHES 5 //ie, users who were connected before the ban triggered
#define STICKYBAN_MAX_ADMIN_MATCHES 2
/world/IsBanned(key,address,computer_id)
/world/IsBanned(key,address,computer_id,type,real_bans_only=FALSE)
if (!key || !address || !computer_id)
if(real_bans_only)
return FALSE
log_access("Failed Login (invalid data): [key] [address]-[computer_id]")
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided invalid or blank information to the server on connection (byond username, IP, and Computer ID.) Provided information for reference: Username:'[key]' IP:'[address]' Computer ID:'[computer_id]'. (If you continue to get this error, please restart byond or contact byond support.)")
@@ -31,7 +33,7 @@
return list("reason"="whitelist", "desc" = "\nReason: You are not on the white list for this server")
//Guest Checking
if(IsGuestKey(key))
if(!real_bans_only && IsGuestKey(key))
if (CONFIG_GET(flag/guest_ban))
log_access("Failed Login: [key] - Guests not allowed")
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
@@ -41,7 +43,7 @@
//Population Cap Checking
var/extreme_popcap = CONFIG_GET(number/extreme_popcap)
if(extreme_popcap && living_player_count() >= extreme_popcap && !admin)
if(!real_bans_only && extreme_popcap && living_player_count() >= extreme_popcap && !admin)
log_access("Failed Login: [key] - Population cap reached")
return list("reason"="popcap", "desc"= "\nReason: [CONFIG_GET(string/extreme_popcap_message)]")
+9 -5
View File
@@ -25,7 +25,7 @@ GLOBAL_PROTECT(Banlist)
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: [GetExp(GLOB.Banlist["minutes"])]\nBy: [GLOB.Banlist["bannedby"]][appeal]"
else
GLOB.Banlist.cd = "/base/[ckey][id]"
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: <B>PERMENANT</B>\nBy: [GLOB.Banlist["bannedby"]][appeal]"
.["desc"] = "\nReason: [GLOB.Banlist["reason"]]\nExpires: <B>PERMANENT</B>\nBy: [GLOB.Banlist["bannedby"]][appeal]"
.["reason"] = "ckey/id"
return .
else
@@ -65,7 +65,8 @@ GLOBAL_PROTECT(Banlist)
GLOB.Banlist = new("data/banlist.bdb")
log_admin("Loading Banlist")
if (!length(GLOB.Banlist.dir)) log_admin("Banlist is empty.")
if (!length(GLOB.Banlist.dir))
log_admin("Banlist is empty.")
if (!GLOB.Banlist.dir.Find("base"))
log_admin("Banlist missing base dir.")
@@ -89,8 +90,10 @@ GLOBAL_PROTECT(Banlist)
message_admins("Invalid Ban.")
continue
if (!GLOB.Banlist["temp"]) continue
if (GLOB.CMinutes >= GLOB.Banlist["minutes"]) RemoveBan(A)
if (!GLOB.Banlist["temp"])
continue
if (GLOB.CMinutes >= GLOB.Banlist["minutes"])
RemoveBan(A)
return 1
@@ -133,7 +136,8 @@ GLOBAL_PROTECT(Banlist)
GLOB.Banlist["id"] >> id
GLOB.Banlist.cd = "/base"
if (!GLOB.Banlist.dir.Remove(foldername)) return 0
if (!GLOB.Banlist.dir.Remove(foldername))
return 0
if(!usr)
log_admin_private("Ban Expired: [key]")
+2 -1
View File
@@ -594,7 +594,8 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
set name = "Give Disease"
set desc = "Gives a Disease to a mob."
var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in SSdisease.diseases
if(!D) return
if(!D)
return
T.ForceContractDisease(new D)
SSblackbox.add_details("admin_verb","Give Disease") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] gave [key_name(T)] the disease [D].")
+6 -6
View File
@@ -1,7 +1,7 @@
//returns a reason if M is banned from rank, returns 0 otherwise
//returns a reason if M is banned from rank, returns FALSE otherwise
/proc/jobban_isbanned(mob/M, rank)
if(!M || !istype(M) || !M.ckey)
return 0
return FALSE
if(!M.client) //no cache. fallback to a datum/DBQuery
var/datum/DBQuery/query_jobban_check_ban = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(M.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[sanitizeSQL(rank)]'")
@@ -9,17 +9,17 @@
return
if(query_jobban_check_ban.NextRow())
var/reason = query_jobban_check_ban.item[1]
return reason ? reason : 1 //we don't want to return "" if there is no ban reason, as that would evaluate to false
return reason ? reason : TRUE //we don't want to return "" if there is no ban reason, as that would evaluate to false
else
return 0
return FALSE
if(!M.client.jobbancache)
jobban_buildcache(M.client)
if(rank in M.client.jobbancache)
var/reason = M.client.jobbancache[rank]
return (reason) ? reason : 1 //see above for why we need to do this
return 0
return (reason) ? reason : TRUE //see above for why we need to do this
return FALSE
/proc/jobban_buildcache(client/C)
if(!SSdbcore.Connect())
+2 -2
View File
@@ -49,8 +49,8 @@
admin_only = TRUE
/datum/server_tools_command/namecheck/Run(sender, params)
log_admin("IRC Name Check: [sender] on [params]")
message_admins("IRC name checking on [params] from [sender]")
log_admin("Chat Name Check: [sender] on [params]")
message_admins("Name checking [params] from [sender]")
return keywords_lookup(params, 1)
/datum/server_tools_command/adminwho
+9 -5
View File
@@ -6,7 +6,7 @@
if(!SSdbcore.Connect())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return
var/polltype = input("Choose poll type.","Poll Type") in list("Single Option","Text Reply","Rating","Multiple Choice", "Instant Runoff Voting")|null
var/polltype = input("Choose poll type.","Poll Type") as null|anything in list("Single Option","Text Reply","Rating","Multiple Choice", "Instant Runoff Voting")
var/choice_amount = 0
switch(polltype)
if("Single Option")
@@ -18,10 +18,14 @@
if("Multiple Choice")
polltype = POLLTYPE_MULTI
choice_amount = input("How many choices should be allowed?","Select choice amount") as num|null
if(choice_amount == 0)
to_chat(src, "Multiple choice poll must have at least one choice allowed.")
else if (choice_amount == null)
return
switch(choice_amount)
if(0)
to_chat(src, "Multiple choice poll must have at least one choice allowed.")
return
if(1)
polltype = POLLTYPE_OPTION
if(null)
return
if ("Instant Runoff Voting")
polltype = POLLTYPE_IRV
else
+1 -1
View File
@@ -104,7 +104,7 @@
/obj/effect/shuttle_build
name = "shuttle_build"
desc = "Some assembly required"
desc = "Some assembly required."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "syndballoon"
anchored = TRUE
+2 -1
View File
@@ -101,7 +101,8 @@ if it doesn't return 1 and show_msg=1 it will prints a message explaining why th
generally it would be used like so:
/proc/admin_proc()
if(!check_rights(R_ADMIN)) return
if(!check_rights(R_ADMIN))
return
to_chat(world, "you have enough rights!")
NOTE: it checks usr! not src! So if you're checking somebody's rank in a proc which they did not call
+10 -14
View File
@@ -410,9 +410,10 @@
dat += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z])</td></tr>"
dat += "</table>"
if(SSticker.mode.head_revolutionaries.len || SSticker.mode.revolutionaries.len)
var/list/revs = get_antagonists(/datum/antagonist/rev)
if(revs.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Revolutionaries</B></td><td></td></tr>"
for(var/datum/mind/N in SSticker.mode.head_revolutionaries)
for(var/datum/mind/N in get_antagonists(/datum/antagonist/rev/head))
var/mob/M = N.current
if(!M)
dat += "<tr><td><a href='?_src_=vars;[HrefToken()];Vars=\ref[N]'>[N.name]([N.key])</a><i>Head Revolutionary body destroyed!</i></td>"
@@ -421,14 +422,14 @@
dat += "<tr><td><a href='?_src_=holder;[HrefToken()];adminplayeropts=\ref[M]'>[M.real_name]</a> <b>(Leader)</b>[M.client ? "" : " <i>(No Client)</i>"][M.stat == DEAD ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.ckey]'>PM</A></td>"
dat += "<td><A href='?_src_=holder;[HrefToken()];adminplayerobservefollow=\ref[M]'>FLW</a></td></tr>"
for(var/datum/mind/N in SSticker.mode.revolutionaries)
for(var/datum/mind/N in get_antagonists(/datum/antagonist/rev,TRUE))
var/mob/M = N.current
if(M)
dat += "<tr><td><a href='?_src_=holder;[HrefToken()];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(No Client)</i>"][M.stat == DEAD ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.ckey]'>PM</A></td>"
dat += "<td><A href='?_src_=holder;[HrefToken()];adminplayerobservefollow=\ref[M]'>FLW</a></td></tr>"
dat += "</table><table cellspacing=5><tr><td><B>Target(s)</B></td><td></td><td><B>Location</B></td></tr>"
for(var/datum/mind/N in SSticker.mode.get_living_heads())
for(var/datum/mind/N in SSjob.get_living_heads())
var/mob/M = N.current
if(M)
dat += "<tr><td><a href='?_src_=holder;[HrefToken()];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(No Client)</i>"][M.stat == DEAD ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
@@ -440,7 +441,7 @@
dat += "<tr><td><a href='?_src_=vars;[HrefToken()];Vars=\ref[N]'>[N.name]([N.key])</a><i>Head body destroyed!</i></td>"
dat += "<td><A href='?priv_msg=[N.key]'>PM</A></td></tr>"
dat += "</table>"
if(SSticker.mode.changelings.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Changelings</B></td><td></td><td></td></tr>"
for(var/datum/mind/changeling in SSticker.mode.changelings)
@@ -592,20 +593,15 @@
var/list/blob_minds = list()
for(var/mob/camera/blob/B in GLOB.mob_list)
blob_minds |= B.mind
if(istype(SSticker.mode, /datum/game_mode/blob) || blob_minds.len)
dat += "<br><table cellspacing=5><tr><td><B>Blob</B></td><td></td><td></td></tr>"
if(istype(SSticker.mode, /datum/game_mode/blob))
var/datum/game_mode/blob/mode = SSticker.mode
blob_minds |= mode.blob_overminds
dat += "<tr><td><i>Progress: [GLOB.blobs_legit.len]/[mode.blobwincount]</i></td></tr>"
if(blob_minds.len)
dat += "<br><table cellspacing=5><tr><td><B>Blob</B></td><td></td><td></td></tr>"
for(var/datum/mind/blob in blob_minds)
var/mob/M = blob.current
var/mob/camera/blob/M = blob.current
if(M)
dat += "<tr><td><a href='?_src_=holder;[HrefToken()];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(No Client)</i>"][M.stat == DEAD ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.ckey]'>PM</A></td>"
dat += "<td><A href='?_src_=holder;[HrefToken()];adminplayerobservefollow=\ref[M]'>FLW</a></td></tr>"
dat += "<tr><td><i>Progress: [M.blobs_legit.len]/[M.blobwincount]</i></td></tr>"
else
dat += "<tr><td><a href='?_src_=vars;[HrefToken()];Vars=\ref[blob]'>[blob.name]([blob.key])</a><i>Blob not found!</i></td>"
dat += "<td><A href='?priv_msg=[blob.key]'>PM</A></td></tr>"
+14 -11
View File
@@ -215,8 +215,8 @@
return
SSblackbox.add_details("admin_secrets_fun_used","Send CentCom Ferry")
if(!SSshuttle.toggleShuttle("ferry","ferry_home","ferry_away"))
message_admins("[key_name_admin(usr)] moved the centcom ferry")
log_admin("[key_name(usr)] moved the centcom ferry")
message_admins("[key_name_admin(usr)] moved the CentCom ferry")
log_admin("[key_name(usr)] moved the CentCom ferry")
if("togglearrivals")
if(!check_rights(R_ADMIN))
@@ -334,17 +334,19 @@
return
SSblackbox.add_details("admin_secrets_fun_used","Traitor All ([objective])")
for(var/mob/living/H in GLOB.player_list)
if(!(ishuman(H)||istype(H, /mob/living/silicon/))) continue
if(H.stat == DEAD || !H.client || !H.mind || ispAI(H)) continue
if(is_special_character(H)) continue
H.mind.add_antag_datum(ANTAG_DATUM_TRAITOR_CUSTOM)
var/datum/antagonist/traitor/traitordatum = H.mind.has_antag_datum(ANTAG_DATUM_TRAITOR) //original datum self deletes
if(!(ishuman(H)||istype(H, /mob/living/silicon/)))
continue
if(H.stat == DEAD || !H.client || !H.mind || ispAI(H))
continue
if(is_special_character(H))
continue
var/datum/antagonist/traitor/human/T = new(H.mind)
T.give_objectives = FALSE
var/datum/objective/new_objective = new
new_objective.owner = H
new_objective.explanation_text = objective
traitordatum.add_objective(new_objective)
traitordatum.equip(FALSE)
traitordatum.greet()
T.add_objective(new_objective)
H.mind.add_antag_datum(T)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] used everyone is a traitor secret. Objective is [objective]</span>")
log_admin("[key_name(usr)] used everyone is a traitor secret. Objective is [objective]")
@@ -546,7 +548,8 @@
if(!check_rights(R_DEBUG))
return
var/datum/job/J = SSjob.GetJob("Security Officer")
if(!J) return
if(!J)
return
J.total_positions = -1
J.spawn_positions = -1
message_admins("[key_name_admin(usr)] has removed the cap on security officers.")
+149
View File
@@ -0,0 +1,149 @@
#define SOUND_EMITTER_LOCAL "local" //Plays the sound like a normal heard sound
#define SOUND_EMITTER_DIRECT "direct" //Plays the sound directly to hearers regardless of pressure/proximity/et cetera
#define SOUND_EMITTER_RADIUS "radius" //Plays the sound to everyone in a radius
#define SOUND_EMITTER_ZLEVEL "zlevel" //Plays the sound to everyone on the z-level
#define SOUND_EMITTER_GLOBAL "global" //Plays the sound to everyone in the game world
//Admin sound emitters with highly customizable functions!
/obj/effect/sound_emitter
name = "sound emitter"
desc = "Emits sounds, presumably."
icon = 'icons/effects/effects.dmi'
icon_state = "shield2"
invisibility = INVISIBILITY_OBSERVER
anchored = TRUE
density = FALSE
opacity = FALSE
alpha = 175
var/sound_file //The sound file the emitter plays
var/sound_volume = 50 //The volume the sound file is played at
var/play_radius = 3 //Any mobs within this many tiles will hear the sounds played if it's using the appropriate mode
var/motus_operandi = SOUND_EMITTER_LOCAL //The mode this sound emitter is using
var/emitter_range = SOUND_EMITTER_ZLEVEL //The range this emitter's sound is heard at; this isn't a number, but a string (see the defines above)
/obj/effect/sound_emitter/Destroy(force)
if(!force)
return QDEL_HINT_LETMELIVE
. = ..()
/obj/effect/sound_emitter/singularity_act()
return
/obj/effect/sound_emitter/examine(mob/user)
..()
if(!isobserver(user))
return
to_chat(user, "<span class='boldnotice'>Sound File:</span> [sound_file ? sound_file : "None chosen"]")
to_chat(user, "<span class='boldnotice'>Mode:</span> [motus_operandi]</span>")
to_chat(user, "<span class='boldnotice'>Range:</span> [emitter_range]</span>")
to_chat(user, "<b>Sound is playing at [sound_volume]% volume.</b>")
if(user.client.holder)
to_chat(user, "<b>Alt-click it to quickly activate it!</b>")
/obj/effect/sound_emitter/attack_ghost(mob/user)
if(!check_rights_for(user.client, R_SOUNDS))
examine(user)
return
edit_emitter(user)
/obj/effect/sound_emitter/AltClick(mob/user)
if(check_rights_for(user.client, R_SOUNDS))
activate(user)
to_chat(user, "<span class='notice'>Sound emitter activated.</span>")
/obj/effect/sound_emitter/proc/edit_emitter(mob/user)
var/dat = ""
dat += "<b>Label:</b> <a href='?src=\ref[src];edit_label=1'>[maptext ? maptext : "No label set!"]</a><br>"
dat += "<br>"
dat += "<b>Sound File:</b> <a href='?src=\ref[src];edit_sound_file=1'>[sound_file ? sound_file : "No file chosen!"]</a><br>"
dat += "<b>Volume:</b> <a href='?src=\ref[src];edit_volume=1'>[sound_volume]%</a><br>"
dat += "<br>"
dat += "<b>Mode:</b> <a href='?src=\ref[src];edit_mode=1'>[motus_operandi]</a><br>"
if(motus_operandi != SOUND_EMITTER_LOCAL)
dat += "<b>Range:</b> <a href='?src=\ref[src];edit_range=1'>[emitter_range]</a>[emitter_range == SOUND_EMITTER_RADIUS ? "<a href='?src=\ref[src];edit_radius=1'>[play_radius]-tile radius</a>" : ""]<br>"
dat += "<br>"
dat += "<a href='?src=\ref[src];play=1'>Play Sound</a> (interrupts other sound emitter sounds)"
var/datum/browser/popup = new(user, "emitter", "", 500, 600)
popup.set_content(dat)
popup.open()
/obj/effect/sound_emitter/Topic(href, href_list)
..()
if(!ismob(usr) || !usr.client || !check_rights_for(usr.client, R_SOUNDS))
return
var/mob/user = usr
if(href_list["edit_label"])
var/new_label = stripped_input(user, "Choose a new label.", "Sound Emitter")
if(!new_label)
return
maptext = new_label
to_chat(user, "<span class='notice'>Label set to [maptext].</span>")
if(href_list["edit_sound_file"])
var/new_file = input(user, "Choose a sound file.", "Sound Emitter") as null|sound
if(!new_file)
return
sound_file = new_file
to_chat(user, "<span class='notice'>New sound file set to [sound_file].</span>")
if(href_list["edit_volume"])
var/new_volume = input(user, "Choose a volume.", "Sound Emitter", sound_volume) as null|num
if(isnull(new_volume))
return
new_volume = Clamp(new_volume, 0, 100)
sound_volume = new_volume
to_chat(user, "<span class='notice'>Volume set to [sound_volume]%.</span>")
if(href_list["edit_mode"])
var/new_mode
var/mode_list = list("Local (normal sound)" = SOUND_EMITTER_LOCAL, "Direct (not affected by environment/location)" = SOUND_EMITTER_DIRECT)
new_mode = input(user, "Choose a new mode.", "Sound Emitter") as null|anything in mode_list
if(!new_mode)
return
motus_operandi = mode_list[new_mode]
to_chat(user, "<span class='notice'>Mode set to [motus_operandi].</span>")
if(href_list["edit_range"])
var/new_range
var/range_list = list("Radius (all mobs within a radius)" = SOUND_EMITTER_RADIUS, "Z-Level (all mobs on the same z)" = SOUND_EMITTER_ZLEVEL, "Global (all players)" = SOUND_EMITTER_GLOBAL)
new_range = input(user, "Choose a new range.", "Sound Emitter") as null|anything in range_list
if(!new_range)
return
emitter_range = range_list[new_range]
to_chat(user, "<span class='notice'>Range set to [emitter_range].</span>")
if(href_list["edit_radius"])
var/new_radius = input(user, "Choose a radius.", "Sound Emitter", sound_volume) as null|num
if(isnull(new_radius))
return
new_radius = Clamp(new_radius, 0, 127)
play_radius = new_radius
to_chat(user, "<span class='notice'>Audible radius set to [play_radius].</span>")
if(href_list["play"])
activate(user)
edit_emitter(user) //Refresh the UI to see our changes
/obj/effect/sound_emitter/proc/activate(mob/user)
var/list/hearing_mobs = list()
if(motus_operandi == SOUND_EMITTER_LOCAL)
playsound(src, sound_file, sound_volume, FALSE)
return
switch(emitter_range)
if(SOUND_EMITTER_RADIUS)
for(var/mob/M in GLOB.player_list)
if(get_dist(src, M) <= play_radius)
hearing_mobs += M
if(SOUND_EMITTER_ZLEVEL)
for(var/mob/M in GLOB.player_list)
if(M.z == z)
hearing_mobs += M
if(SOUND_EMITTER_GLOBAL)
hearing_mobs = GLOB.player_list.Copy()
for(var/mob/M in hearing_mobs)
if(M.client.prefs.toggles & SOUND_MIDI)
M.playsound_local(M, sound_file, sound_volume, FALSE, channel = CHANNEL_ADMIN, pressure_affected = FALSE)
if(user)
log_admin("[ADMIN_LOOKUPFLW(user)] activated a sound emitter with file \"[sound_file]\" at [COORD(src)]")
flick("shield1", src)
#undef SOUND_EMITTER_LOCAL
#undef SOUND_EMITTER_DIRECT
#undef SOUND_EMITTER_RADIUS
#undef SOUND_EMITTER_ZLEVEL
#undef SOUND_EMITTER_GLOBAL
+35 -28
View File
@@ -165,6 +165,7 @@
return
var/datum/round_event_control/E = locate(href_list["forceevent"]) in SSevents.control
if(E)
E.admin_setup(usr)
var/datum/round_event/event = E.runEvent()
if(event.announceWhen>0)
event.processing = FALSE
@@ -1210,33 +1211,10 @@
cmd_admin_mute(href_list["mute"], text2num(href_list["mute_type"]))
else if(href_list["c_mode"])
if(!check_rights(R_ADMIN))
return
if(SSticker.HasRoundStarted())
return alert(usr, "The game has already started.", null, null, null, null)
var/dat = {"<B>What mode do you wish to play?</B><HR>"}
for(var/mode in config.modes)
dat += {"<A href='?src=\ref[src];[HrefToken()];c_mode2=[mode]'>[config.mode_names[mode]]</A><br>"}
dat += {"<A href='?src=\ref[src];[HrefToken()];c_mode2=secret'>Secret</A><br>"}
dat += {"<A href='?src=\ref[src];[HrefToken()];c_mode2=random'>Random</A><br>"}
dat += {"Now: [GLOB.master_mode]"}
usr << browse(dat, "window=c_mode")
return HandleCMode()
else if(href_list["f_secret"])
if(!check_rights(R_ADMIN))
return
if(SSticker.HasRoundStarted())
return alert(usr, "The game has already started.", null, null, null, null)
if(GLOB.master_mode != "secret")
return alert(usr, "The game mode has to be secret!", null, null, null, null)
var/dat = {"<B>What game mode do you want to force secret to be? Use this if you want to change the game mode, but want the players to believe it's secret. This will only work if the current game mode is secret.</B><HR>"}
for(var/mode in config.modes)
dat += {"<A href='?src=\ref[src];[HrefToken()];f_secret2=[mode]'>[config.mode_names[mode]]</A><br>"}
dat += {"<A href='?src=\ref[src];[HrefToken()];f_secret2=secret'>Random (default)</A><br>"}
dat += {"Now: [GLOB.secret_force_mode]"}
usr << browse(dat, "window=f_secret")
return HandleFSecret()
else if(href_list["c_mode2"])
if(!check_rights(R_ADMIN|R_SERVER))
@@ -1250,7 +1228,7 @@
to_chat(world, "<span class='adminnotice'><b>The mode is now: [GLOB.master_mode]</b></span>")
Game() // updates the main game menu
SSticker.save_mode(GLOB.master_mode)
.(href, list("c_mode"=1))
HandleCMode()
else if(href_list["f_secret2"])
if(!check_rights(R_ADMIN|R_SERVER))
@@ -1264,7 +1242,7 @@
log_admin("[key_name(usr)] set the forced secret mode as [GLOB.secret_force_mode].")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] set the forced secret mode as [GLOB.secret_force_mode].</span>")
Game() // updates the main game menu
.(href, list("f_secret"=1))
HandleFSecret()
else if(href_list["monkeyone"])
if(!check_rights(R_SPAWN))
@@ -2263,7 +2241,7 @@
if(!newname)
return
G.name = newname
var/description = input("Enter centcom message contents:") as message|null
var/description = input("Enter CentCom message contents:") as message|null
if(!description)
return
G.report_message = description
@@ -2296,3 +2274,32 @@
dat += thing_to_check
usr << browse(dat.Join("<br>"), "window=related_[C];size=420x300")
/datum/admins/proc/HandleCMode()
if(!check_rights(R_ADMIN))
return
if(SSticker.HasRoundStarted())
return alert(usr, "The game has already started.", null, null, null, null)
var/dat = {"<B>What mode do you wish to play?</B><HR>"}
for(var/mode in config.modes)
dat += {"<A href='?src=\ref[src];[HrefToken()];c_mode2=[mode]'>[config.mode_names[mode]]</A><br>"}
dat += {"<A href='?src=\ref[src];[HrefToken()];c_mode2=secret'>Secret</A><br>"}
dat += {"<A href='?src=\ref[src];[HrefToken()];c_mode2=random'>Random</A><br>"}
dat += {"Now: [GLOB.master_mode]"}
usr << browse(dat, "window=c_mode")
/datum/admins/proc/HandleFSecret()
if(!check_rights(R_ADMIN))
return
if(SSticker.HasRoundStarted())
return alert(usr, "The game has already started.", null, null, null, null)
if(GLOB.master_mode != "secret")
return alert(usr, "The game mode has to be secret!", null, null, null, null)
var/dat = {"<B>What game mode do you want to force secret to be? Use this if you want to change the game mode, but want the players to believe it's secret. This will only work if the current game mode is secret.</B><HR>"}
for(var/mode in config.modes)
dat += {"<A href='?src=\ref[src];[HrefToken()];f_secret2=[mode]'>[config.mode_names[mode]]</A><br>"}
dat += {"<A href='?src=\ref[src];[HrefToken()];f_secret2=secret'>Random (default)</A><br>"}
dat += {"Now: [GLOB.secret_force_mode]"}
usr << browse(dat, "window=f_secret")
+3 -4
View File
@@ -2,7 +2,8 @@
var/text
for(var/A in typesof(/obj/item))
var/obj/item/O = new A( locate(1,1,1) )
if(!O) continue
if(!O)
continue
var/icon/IL = new(O.lefthand_file)
var/list/Lstates = IL.IconStates()
var/icon/IR = new(O.righthand_file)
@@ -28,7 +29,5 @@
if(text)
var/F = file("broken_icons.txt")
fdel(F)
WRITE_FILE(F, text)
WRITE_FILE(F, text)
to_chat(world, "Completely successfully and written to [F]")
@@ -3,9 +3,11 @@
/proc/_abs(A)
return abs(A)
/*/proc/_animate(atom/A, set_vars, time = 10, loop = 1, easing = LINEAR_EASING, flags_1 = null)
animate(A, set_vars, time, loop, easing, flags_1)
Borked. If anyone wants to fix this be my guest.*/
/proc/_animate(atom/A, set_vars, time = 10, loop = 1, easing = LINEAR_EASING, flags = null)
var/mutable_appearance/MA = new()
for(var/v in set_vars)
MA.vars[v] = set_vars[v]
animate(A, appearance = MA, time, loop, easing, flags)
/proc/_acrccos(A)
return arccos(A)
+25 -3
View File
@@ -237,6 +237,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
. += " (<A HREF='?_src_=holder;[HrefToken(TRUE)];ahelp=[ref_src];ahelp_action=icissue'>IC</A>)"
. += " (<A HREF='?_src_=holder;[HrefToken(TRUE)];ahelp=[ref_src];ahelp_action=close'>CLOSE</A>)"
. += " (<A HREF='?_src_=holder;[HrefToken(TRUE)];ahelp=[ref_src];ahelp_action=resolve'>RSLVE</A>)"
. += " (<A HREF='?_src_=holder;[HrefToken(TRUE)];ahelp=[ref_src];ahelp_action=handleissue'>HANDLE</A>)"
//private
/datum/admin_help/proc/LinkedReplyName(ref_src)
@@ -335,10 +336,10 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
addtimer(CALLBACK(initiator, /client/proc/giveadminhelpverb), 50)
AddInteraction("<font color='green'>Resolved by [key_name].</font>")
to_chat(initiator, "<span class='adminhelp'>Your ticket has been resolved by an admin. The Adminhelp verb will be returned to you shortly.</span>")
if(!silent)
SSblackbox.inc("ahelp_resolve")
var/msg = "Ticket [TicketHref("#[id]")] resolved by [key_name]"
to_chat(initiator, "<span class='adminhelp'>Your ticket has been resolved by an admin. The Adminhelp verb will be returned to you shortly.</span>")
message_admins(msg)
log_admin_private(msg)
@@ -382,6 +383,22 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
AddInteraction("Marked as IC issue by [key_name]")
Resolve(silent = TRUE)
//Let the initiator know their ahelp is being handled
/datum/admin_help/proc/HandleIssue(key_name = key_name_admin(usr))
if(state != AHELP_ACTIVE)
return
var/msg = "<span class ='adminhelp'>Your ticket is now being handled by an admin. Please be patient.</span>"
if(initiator)
to_chat(initiator, msg)
SSblackbox.inc("ahelp_handleissue")
msg = "Ticket [TicketHref("#[id]")] is being handled by [key_name]"
message_admins(msg)
log_admin_private(msg)
AddInteraction("Being handled by [key_name]")
//Show the ticket panel
/datum/admin_help/proc/TicketPanel()
var/list/dat = list("<html><head><title>Ticket #[id]</title></head>")
@@ -442,6 +459,8 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
Close()
if("resolve")
Resolve()
if("handleissue")
HandleIssue()
if("reopen")
Reopen()
@@ -490,6 +509,8 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(handle_spam_prevention(msg,MUTE_ADMINHELP))
return
msg = trim(msg)
if(!msg)
return
@@ -588,8 +609,9 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/proc/send2irc(msg,msg2)
if(SERVER_TOOLS_PRESENT)
SERVER_TOOLS_RELAY_BROADCAST("[msg] | [msg2]")
msg = replacetext(replacetext(msg, "\proper", ""), "\improper", "")
msg2 = replacetext(replacetext(msg2, "\proper", ""), "\improper", "")
SERVER_TOOLS_RELAY_BROADCAST("[msg] | [msg2]")
/proc/send2otherserver(source,msg,type = "Ahelp")
var/comms_key = CONFIG_GET(string/comms_key)
+1 -1
View File
@@ -131,7 +131,7 @@
//clean the message if it's not sent by a high-rank admin
if(!check_rights(R_SERVER|R_DEBUG,0)||irc)//no sending html to the poor bots
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
msg = trim(sanitize(copytext(msg,1,MAX_MESSAGE_LEN)))
if(!msg)
return
+31 -10
View File
@@ -82,6 +82,7 @@
var/valueholder = "derp"
var/objholder = /obj/structure/closet
var/atom/movable/stored = null
var/list/preview = list()
/datum/buildmode/New(client/c)
create_buttons()
@@ -94,6 +95,8 @@
holder.screen -= buttons
holder.click_intercept = null
holder.show_popup_menus = 1
usr.client.images -= preview
preview.Cut()
qdel(src)
return
@@ -150,6 +153,7 @@
if(AREA_BUILDMODE)
dat += "***********************************************************"
dat += "Left Mouse Button on turf/obj/mob = Select corner"
dat += "Right Mouse Button on turf/obj/mob = Reset corner selection"
dat += "Right Mouse Button on buildmode button = Select generator"
dat += "***********************************************************"
if(COPY_BUILDMODE)
@@ -181,7 +185,8 @@
if(varholder in locked && !check_rights(R_DEBUG,0))
return 1
var/thetype = input(user,"Select variable type:" ,"Type") in list("text","number","mob-reference","obj-reference","turf-reference")
if(!thetype) return 1
if(!thetype)
return 1
switch(thetype)
if("text")
valueholder = input(user,"Enter variable value:" ,"Value", "value") as text
@@ -200,7 +205,8 @@
var/datum/mapGenerator/MP = path
options[initial(MP.buildmode_name)] = path
var/type = input(user,"Select Generator Type","Type") as null|anything in options
if(!type) return
if(!type)
return
generator_path = options[type]
cornerA = null
@@ -336,13 +342,20 @@
throw_atom.throw_at(object, 10, 1,user)
log_admin("Build Mode: [key_name(user)] threw [throw_atom] at [object] ([object.x],[object.y],[object.z])")
if(AREA_BUILDMODE)
if(!cornerA)
cornerA = get_turf(object)
return
if(cornerA && !cornerB)
cornerB = get_turf(object)
if(left_click) //rectangular
if(!cornerA)
cornerA = get_turf(object)
preview += image('icons/turf/overlays.dmi',cornerA,"greenOverlay")
usr.client.images -= preview
usr.client.images += preview
return
if(cornerA && !cornerB)
cornerB = get_turf(object)
preview += image('icons/turf/overlays.dmi',cornerB,"blueOverlay")
usr.client.images -= preview
usr.client.images += preview
to_chat(user, "<span class='boldwarning'>Region selected, if you're happy with your selection left click again, otherwise right click.</span>")
return
if(cornerA && cornerB)
if(!generator_path)
to_chat(user, "<span class='warning'>Select generator type first.</span>")
@@ -352,10 +365,18 @@
if(GLOB.reloading_map)
to_chat(user, "<span class='boldwarning'>You are already reloading an area! Please wait for it to fully finish loading before trying to load another!</span>")
return
G.defineRegion(cornerA,cornerB,1)
G.generate()
G.defineRegion(cornerA, cornerB, 1)
for(var/t in G.map)
preview += image('icons/turf/overlays.dmi', t ,"redOverlay")
usr.client.images -= preview
usr.client.images += preview
var/confirm = alert("Are you sure you want run the map generator?", "Run generator", "Yes", "No")
if(confirm == "Yes")
G.generate()
cornerA = null
cornerB = null
usr.client.images -= preview
preview.Cut()
return
//Something wrong - Reset
cornerA = null
+48 -9
View File
@@ -31,7 +31,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set name = "Advanced ProcCall"
set waitfor = 0
if(!check_rights(R_DEBUG)) return
if(!check_rights(R_DEBUG))
return
var/datum/target = null
var/targetselected = 0
@@ -127,8 +128,10 @@ GLOBAL_PROTECT(LastAdminCalledProc)
/world/proc/WrapAdminProcCall(target, procname, list/arguments)
if(target == GLOBAL_PROC)
return call(procname)(arglist(arguments))
else
else if(target != world)
return call(target, procname)(arglist(arguments))
else
log_admin_private("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]")
/proc/IsAdminAdvancedProcCall()
#ifdef TESTING
@@ -261,10 +264,7 @@ GLOBAL_PROTECT(LastAdminCalledProc)
if(ishuman(M))
log_admin("[key_name(src)] has blobized [M.key].")
var/mob/living/carbon/human/H = M
spawn(0)
var/mob/camera/blob/B = H.become_overmind(FALSE)
B.place_blob_core(B.base_point_rate, -1) //place them wherever they are
H.become_overmind()
else
alert("Invalid mob")
@@ -715,8 +715,8 @@ GLOBAL_PROTECT(LastAdminCalledProc)
if(Rad.anchored)
if(!Rad.loaded_tank)
var/obj/item/tank/internals/plasma/Plasma = new/obj/item/tank/internals/plasma(Rad)
ASSERT_GAS("plasma", Plasma.air_contents)
Plasma.air_contents.gases["plasma"][MOLES] = 70
ASSERT_GAS(/datum/gas/plasma, Plasma.air_contents)
Plasma.air_contents.gases[/datum/gas/plasma][MOLES] = 70
Rad.drainratio = 0
Rad.loaded_tank = Plasma
Plasma.loc = Rad
@@ -780,7 +780,7 @@ GLOBAL_PROTECT(LastAdminCalledProc)
/client/proc/cmd_display_init_log()
set category = "Debug"
set name = "Display Initialzie() Log"
set name = "Display Initialize() Log"
set desc = "Displays a list of things that didn't handle Initialize() properly"
usr << browse(replacetext(SSatoms.InitLog(), "\n", "<br>"), "window=initlog")
@@ -873,3 +873,42 @@ GLOBAL_PROTECT(LastAdminCalledProc)
message_admins("<span class='adminnotice'>[key_name_admin(src)] pumped a random event.</span>")
SSblackbox.add_details("admin_verb","Pump Random Event")
log_admin("[key_name(src)] pumped a random event.")
/client/proc/start_line_profiling()
set category = "Profile"
set name = "Start Line Profiling"
set desc = "Starts tracking line by line profiling for code lines that support it"
PROFILE_START
message_admins("<span class='adminnotice'>[key_name_admin(src)] started line by line profiling.</span>")
SSblackbox.add_details("admin_verb","Start Line Profiling")
log_admin("[key_name(src)] started line by line profiling.")
/client/proc/stop_line_profiling()
set category = "Profile"
set name = "Stops Line Profiling"
set desc = "Stops tracking line by line profiling for code lines that support it"
PROFILE_STOP
message_admins("<span class='adminnotice'>[key_name_admin(src)] stopped line by line profiling.</span>")
SSblackbox.add_details("admin_verb","stop Line Profiling")
log_admin("[key_name(src)] stopped line by line profiling.")
/client/proc/show_line_profiling()
set category = "Profile"
set name = "Show Line Profiling"
set desc = "Shows tracked profiling info from code lines that support it"
var/sortlist = list(
"Avg time" = /proc/cmp_profile_avg_time_dsc,
"Total Time" = /proc/cmp_profile_time_dsc,
"Call Count" = /proc/cmp_profile_count_dsc
)
var/sort = input(src, "Sort type?", "Sort Type", "Avg time") as null|anything in sortlist
if (!sort)
return
sort = sortlist[sort]
profile_show(src, sort)
@@ -36,7 +36,8 @@
var/obj/item/organ = input("Select organ/implant:", "Organ Manipulation", null) in organs
organ = organs[organ]
if(!organ) return
if(!organ)
return
var/obj/item/organ/O
var/obj/item/implant/I
+18 -8
View File
@@ -42,7 +42,10 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
/client/proc/print_pointers,
/client/proc/cmd_show_at_list,
/client/proc/cmd_show_at_markers,
/client/proc/manipulate_organs
/client/proc/manipulate_organs,
/client/proc/start_line_profiling,
/client/proc/stop_line_profiling,
/client/proc/show_line_profiling
))
/obj/effect/debugging/mapfix_marker
@@ -194,15 +197,20 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
set category = "Mapping"
set name = "Count Objects On Level"
var/level = input("Which z-level?","Level?") as text
if(!level) return
if(!level)
return
var/num_level = text2num(level)
if(!num_level) return
if(!isnum(num_level)) return
if(!num_level)
return
if(!isnum(num_level))
return
var/type_text = input("Which type path?","Path?") as text
if(!type_text) return
if(!type_text)
return
var/type_path = text2path(type_text)
if(!type_path) return
if(!type_path)
return
var/count = 0
@@ -238,9 +246,11 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
set name = "Count Objects All"
var/type_text = input("Which type path?","") as text
if(!type_text) return
if(!type_text)
return
var/type_path = text2path(type_text)
if(!type_path) return
if(!type_path)
return
var/count = 0
+9 -11
View File
@@ -433,12 +433,13 @@ GLOBAL_PROTECT(VVpixelmovement)
to_chat(src, "Variable appears to be <b>[uppertext(default)]</b>.")
to_chat(src, "Variable contains: [L[index]]")
to_chat(src, "Variable contains: [variable]")
if(default == VV_NUM)
var/dir_text = ""
if(dir < 0 && dir < 16)
if(dir & 1)
var/tdir = variable
if(tdir > 0 && tdir < 16)
if(tdir & 1)
dir_text += "NORTH"
if(dir & 2)
dir_text += "SOUTH"
@@ -450,11 +451,8 @@ GLOBAL_PROTECT(VVpixelmovement)
if(dir_text)
to_chat(usr, "If a direction, direction is: [dir_text]")
var/original_var
if(assoc)
original_var = L[assoc_key]
else
original_var = L[index]
var/original_var = variable
if (O)
L = L.Copy()
var/class
@@ -612,8 +610,8 @@ GLOBAL_PROTECT(VVpixelmovement)
if (O.vv_edit_var(variable, var_new) == FALSE)
to_chat(src, "Your edit was rejected by the object.")
return
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]"
log_world("### VarEdit by [key_name(src)]: [O.type] [variable]=[var_value] => [var_new]")
log_admin("[key_name(src)] modified [original_name]'s [variable] to from [html_encode("[var_value]")] to [html_encode("[var_new]")]")
var/msg = "[key_name_admin(src)] modified [original_name]'s [variable] from [var_value] to [var_new]"
message_admins(msg)
admin_ticket_log(O, msg)
+6 -13
View File
@@ -213,7 +213,6 @@
/datum/admins/proc/makeNukeTeam()
var/datum/game_mode/nuclear/temp = new
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for a nuke team being sent in?", "operative", temp)
var/list/mob/dead/observer/chosen = list()
@@ -246,24 +245,18 @@
nuke.r_code = nuke_code
//Let's find the spawn locations
var/list/turf/synd_spawn = list()
for(var/obj/effect/landmark/A in GLOB.landmarks_list)
if(A.name == "Syndicate-Spawn")
synd_spawn += get_turf(A)
continue
var/leader_chosen
var/leader_chosen = FALSE
var/spawnpos = 1 //Decides where they'll spawn. 1=leader.
for(var/mob/c in chosen)
if(spawnpos > synd_spawn.len)
spawnpos = 2 //Ran out of spawns. Let's loop back to the first non-leader position
if(spawnpos > GLOB.nukeop_start.len)
spawnpos = 1 //Ran out of spawns. Let's loop back to the first non-leader position
var/mob/living/carbon/human/new_character=makeBody(c)
if(!leader_chosen)
leader_chosen = 1
new_character.mind.make_Nuke(synd_spawn[spawnpos],nuke_code,1)
leader_chosen = TRUE
new_character.mind.make_Nuke(pick(GLOB.nukeop_leader_start), nuke_code, TRUE)
else
new_character.mind.make_Nuke(synd_spawn[spawnpos],nuke_code)
new_character.mind.make_Nuke(GLOB.nukeop_start[spawnpos], nuke_code)
spawnpos++
return 1
else
+23 -12
View File
@@ -382,7 +382,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
switch(new_character.mind.special_role)
if("Wizard")
new_character.forceMove(pick(GLOB.wizardstart))
SSticker.mode.equip_wizard(new_character)
var/datum/antagonist/wizard/A = new_character.mind.has_antag_datum(/datum/antagonist/wizard,TRUE)
A.equip_wizard()
if("Syndicate")
new_character.forceMove(pick(GLOB.nukeop_start))
call(/datum/game_mode/proc/equip_syndicate)(new_character)
@@ -398,7 +399,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
else//They may also be a cyborg or AI.
switch(new_character.mind.assigned_role)
if("Cyborg")//More rigging to make em' work and check if they're traitor.
new_character = new_character.Robotize()
new_character = new_character.Robotize(TRUE)
if("AI")
new_character = new_character.AIize()
else
@@ -544,15 +545,20 @@ Traitors and the like can also be revived with the previous role mostly intact.
return
var/devastation = input("Range of total devastation. -1 to none", text("Input")) as num|null
if(devastation == null) return
if(devastation == null)
return
var/heavy = input("Range of heavy impact. -1 to none", text("Input")) as num|null
if(heavy == null) return
if(heavy == null)
return
var/light = input("Range of light impact. -1 to none", text("Input")) as num|null
if(light == null) return
if(light == null)
return
var/flash = input("Range of flash. -1 to none", text("Input")) as num|null
if(flash == null) return
if(flash == null)
return
var/flames = input("Range of flames. -1 to none", text("Input")) as num|null
if(flames == null) return
if(flames == null)
return
if ((devastation != -1) || (heavy != -1) || (light != -1) || (flash != -1) || (flames != -1))
if ((devastation > 20) || (heavy > 20) || (light > 20) || (flames > 20))
@@ -576,9 +582,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
return
var/heavy = input("Range of heavy pulse.", text("Input")) as num|null
if(heavy == null) return
if(heavy == null)
return
var/light = input("Range of light pulse.", text("Input")) as num|null
if(light == null) return
if(light == null)
return
if (heavy || light)
@@ -959,7 +967,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
set name = "Toggle AntagHUD"
set desc = "Toggles the Admin AntagHUD"
if(!holder) return
if(!holder)
return
var/adding_hud = !has_antag_hud()
@@ -1165,7 +1174,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
if(!holder)
return
var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA)
var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL)
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
@@ -1185,6 +1194,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
target.gib(FALSE)
if(ADMIN_PUNISHMENT_BSA)
bluespace_artillery(target)
if(ADMIN_PUNISHMENT_FIREBALL)
new /obj/effect/temp_visual/target(get_turf(target))
var/msg = "[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment]."
message_admins(msg)
@@ -1252,4 +1263,4 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
to_chat(usr, "<span class='danger'>ERROR: Unable to update player flags. Please check logs.</span>")
else
message_admins("[key_name_admin(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name_admin(C)]")
log_admin("[key_name(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name(C)]")
log_admin("[key_name(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name(C)]")
+116 -119
View File
@@ -1,120 +1,117 @@
/obj/item/device/assembly
name = "assembly"
desc = "A small electronic device that should never exist."
icon = 'icons/obj/assemblies/new_assemblies.dmi'
icon_state = ""
#define WIRE_RECEIVE 1
#define WIRE_PULSE 2
#define WIRE_PULSE_SPECIAL 4
#define WIRE_RADIO_RECEIVE 8
#define WIRE_RADIO_PULSE 16
/obj/item/device/assembly
name = "assembly"
desc = "A small electronic device that should never exist."
icon = 'icons/obj/assemblies/new_assemblies.dmi'
icon_state = ""
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_SMALL
materials = list(MAT_METAL=100)
throwforce = 2
throw_speed = 3
throw_range = 7
origin_tech = "magnets=1;engineering=1"
var/secured = 1
var/list/attached_overlays = null
var/obj/item/device/assembly_holder/holder = null
var/wire_type = WIRE_RECEIVE | WIRE_PULSE
var/attachable = 0 // can this be attached to wires
var/datum/wires/connected = null
var/const/WIRE_RECEIVE = 1 //Allows Pulsed(0) to call Activate()
var/const/WIRE_PULSE = 2 //Allows Pulse(0) to act on the holder
var/const/WIRE_PULSE_SPECIAL = 4 //Allows Pulse(0) to act on the holders special assembly
var/const/WIRE_RADIO_RECEIVE = 8 //Allows Pulsed(1) to call Activate()
var/const/WIRE_RADIO_PULSE = 16 //Allows Pulse(1) to send a radio message
var/next_activate = 0 //When we're next allowed to activate - for spam control
/obj/item/device/assembly/proc/on_attach()
/obj/item/device/assembly/proc/on_detach()
/obj/item/device/assembly/proc/holder_movement() //Called when the holder is moved
return
/obj/item/device/assembly/proc/describe() // Called by grenades to describe the state of the trigger (time left, etc)
return "The trigger assembly looks broken!"
/obj/item/device/assembly/proc/is_secured(mob/user)
if(!secured)
to_chat(user, "<span class='warning'>The [name] is unsecured!</span>")
return 0
return 1
//Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
/obj/item/device/assembly/proc/pulsed(radio = 0)
if(wire_type & WIRE_RECEIVE)
spawn(0)
activate()
if(radio && (wire_type & WIRE_RADIO_RECEIVE))
spawn(0)
activate()
return 1
//Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct
/obj/item/device/assembly/proc/pulse(radio = 0)
if(connected && wire_type)
connected.pulse_assembly(src)
return 1
if(holder && (wire_type & WIRE_PULSE))
holder.process_activation(src, 1, 0)
if(holder && (wire_type & WIRE_PULSE_SPECIAL))
holder.process_activation(src, 0, 1)
return 1
// What the device does when turned on
/obj/item/device/assembly/proc/activate()
if(QDELETED(src) || !secured || (next_activate > world.time))
return FALSE
next_activate = world.time + 30
return TRUE
/obj/item/device/assembly/proc/toggle_secure()
secured = !secured
update_icon()
return secured
/obj/item/device/assembly/attackby(obj/item/W, mob/user, params)
if(isassembly(W))
var/obj/item/device/assembly/A = W
if((!A.secured) && (!secured))
holder = new/obj/item/device/assembly_holder(get_turf(src))
holder.assemble(src,A,user)
to_chat(user, "<span class='notice'>You attach and secure \the [A] to \the [src]!</span>")
else
to_chat(user, "<span class='warning'>Both devices must be in attachable mode to be attached together.</span>")
return
if(istype(W, /obj/item/screwdriver))
if(toggle_secure())
to_chat(user, "<span class='notice'>\The [src] is ready!</span>")
else
to_chat(user, "<span class='notice'>\The [src] can now be attached!</span>")
return
..()
/obj/item/device/assembly/examine(mob/user)
..()
if(secured)
to_chat(user, "\The [src] is secured and ready to be used.")
else
to_chat(user, "\The [src] can be attached to other things.")
/obj/item/device/assembly/attack_self(mob/user)
if(!user)
return 0
user.set_machine(src)
interact(user)
return 1
/obj/item/device/assembly/interact(mob/user)
return //HTML MENU FOR WIRES GOES HERE
w_class = WEIGHT_CLASS_SMALL
materials = list(MAT_METAL=100)
throwforce = 2
throw_speed = 3
throw_range = 7
origin_tech = "magnets=1;engineering=1"
var/secured = TRUE
var/list/attached_overlays = null
var/obj/item/device/assembly_holder/holder = null
var/wire_type = WIRE_RECEIVE | WIRE_PULSE
var/attachable = FALSE // can this be attached to wires
var/datum/wires/connected = null
var/next_activate = 0 //When we're next allowed to activate - for spam control
/obj/item/device/assembly/proc/on_attach()
/obj/item/device/assembly/proc/on_detach()
/obj/item/device/assembly/proc/holder_movement() //Called when the holder is moved
return
/obj/item/device/assembly/proc/describe() // Called by grenades to describe the state of the trigger (time left, etc)
return "The trigger assembly looks broken!"
/obj/item/device/assembly/proc/is_secured(mob/user)
if(!secured)
to_chat(user, "<span class='warning'>The [name] is unsecured!</span>")
return FALSE
return TRUE
//Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
/obj/item/device/assembly/proc/pulsed(radio = 0)
if(wire_type & WIRE_RECEIVE)
INVOKE_ASYNC(src, .proc/activate)
if(radio && (wire_type & WIRE_RADIO_RECEIVE))
INVOKE_ASYNC(src, .proc/activate)
return TRUE
//Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct
/obj/item/device/assembly/proc/pulse(radio = 0)
if(connected && wire_type)
connected.pulse_assembly(src)
return TRUE
if(holder && (wire_type & WIRE_PULSE))
holder.process_activation(src, 1, 0)
if(holder && (wire_type & WIRE_PULSE_SPECIAL))
holder.process_activation(src, 0, 1)
return TRUE
// What the device does when turned on
/obj/item/device/assembly/proc/activate()
if(QDELETED(src) || !secured || (next_activate > world.time))
return FALSE
next_activate = world.time + 30
return TRUE
/obj/item/device/assembly/proc/toggle_secure()
secured = !secured
update_icon()
return secured
/obj/item/device/assembly/attackby(obj/item/W, mob/user, params)
if(isassembly(W))
var/obj/item/device/assembly/A = W
if((!A.secured) && (!secured))
holder = new/obj/item/device/assembly_holder(get_turf(src))
holder.assemble(src,A,user)
to_chat(user, "<span class='notice'>You attach and secure \the [A] to \the [src]!</span>")
else
to_chat(user, "<span class='warning'>Both devices must be in attachable mode to be attached together.</span>")
return
if(istype(W, /obj/item/screwdriver))
if(toggle_secure())
to_chat(user, "<span class='notice'>\The [src] is ready!</span>")
else
to_chat(user, "<span class='notice'>\The [src] can now be attached!</span>")
return
..()
/obj/item/device/assembly/examine(mob/user)
..()
if(secured)
to_chat(user, "\The [src] is secured and ready to be used.")
else
to_chat(user, "\The [src] can be attached to other things.")
/obj/item/device/assembly/attack_self(mob/user)
if(!user)
return FALSE
user.set_machine(src)
interact(user)
return TRUE
/obj/item/device/assembly/interact(mob/user)
return //HTML MENU FOR WIRES GOES HERE
+33 -27
View File
@@ -14,12 +14,13 @@
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
origin_tech = "materials=1;engineering=1"
/obj/item/device/onetankbomb/examine(mob/user)
..()
user.examinate(bombtank)
bombtank.examine(user)
/obj/item/device/onetankbomb/update_icon()
if(bombtank)
icon = bombtank.icon
icon_state = bombtank.icon_state
if(bombassembly)
add_overlay(bombassembly.icon_state)
@@ -34,11 +35,11 @@
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
bombassembly.loc = user.loc
bombassembly.forceMove(drop_location())
bombassembly.master = null
bombassembly = null
bombtank.loc = user.loc
bombtank.forceMove(drop_location())
bombtank.master = null
bombtank = null
@@ -51,15 +52,11 @@
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
message_admins("[key_name_admin(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]")
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.</span>")
else
status = FALSE
GLOB.bombers += "[key_name(user)] unwelded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
to_chat(user, "<span class='notice'>The hole has been closed.</span>")
add_fingerprint(user)
..()
/obj/item/device/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
bombassembly.attack_self(user, 1)
bombassembly.attack_self(user, TRUE)
add_fingerprint(user)
return
@@ -84,31 +81,40 @@
// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ----------
/obj/item/tank/proc/bomb_assemble(W,user) //Bomb assembly proc. This turns assembly+tank into a bomb
var/obj/item/device/assembly_holder/S = W
var/mob/M = user
if(isigniter(S.a_left) == isigniter(S.a_right)) //Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it
return
if(!M.temporarilyRemoveItemFromInventory(src)) //Remove the assembly from your hands
//Bomb assembly proc. This turns assembly+tank into a bomb
/obj/item/tank/proc/bomb_assemble(obj/item/device/assembly_holder/assembly, mob/living/user)
//Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it
if(isigniter(assembly.a_left) == isigniter(assembly.a_right))
return
var/obj/item/device/onetankbomb/R = new
if((src in user.get_equipped_items()) && !user.canUnEquip(src))
to_chat(user, "<span class='warning'>[src] is stuck to you!</span>")
return
M.put_in_hands(R) //Equips the bomb if possible, or puts it on the floor.
if(!user.canUnEquip(assembly))
to_chat(user, "<span class='warning'>[assembly] is stuck to your hand!</span>")
return
R.bombassembly = S //Tell the bomb about its assembly part
S.master = R //Tell the assembly about its new owner
S.forceMove(R) //Move the assembly out of the fucking way
var/obj/item/device/onetankbomb/bomb = new
user.transferItemToLoc(src, bomb)
user.transferItemToLoc(assembly, bomb)
R.bombtank = src //Same for tank
master = R
forceMove(R)
R.update_icon()
bomb.bombassembly = assembly //Tell the bomb about its assembly part
assembly.master = bomb //Tell the assembly about its new owner
bomb.bombtank = src //Same for tank
master = bomb
forceMove(bomb)
bomb.update_icon()
user.put_in_hands(bomb) //Equips the bomb if possible, or puts it on the floor.
to_chat(user, "<span class='notice'>You attach [assembly] to [src].</span>")
return
/obj/item/tank/proc/ignite() //This happens when a bomb is told to explode
air_contents.assert_gases("plasma", "o2")
var/fuel_moles = air_contents.gases["plasma"][MOLES] + air_contents.gases["o2"][MOLES]/6
air_contents.assert_gases(/datum/gas/plasma, /datum/gas/oxygen)
var/fuel_moles = air_contents.gases[/datum/gas/plasma][MOLES] + air_contents.gases[/datum/gas/oxygen][MOLES]/6
air_contents.garbage_collect()
var/strength = 1
@@ -164,4 +170,4 @@
if(!T)
return
T.assume_air(removed)
air_update_turf()
air_update_turf()
+13 -20
View File
@@ -146,27 +146,20 @@
/obj/item/device/assembly/flash/proc/terrible_conversion_proc(mob/living/carbon/human/H, mob/user)
if(istype(H) && ishuman(user) && H.stat != DEAD)
if(user.mind && (user.mind in SSticker.mode.head_revolutionaries))
if(H.client)
if(H.stat == CONSCIOUS)
H.mind_initialize() //give them a mind datum if they don't have one.
var/resisted
if(!H.isloyal())
if(user.mind in SSticker.mode.head_revolutionaries)
if(SSticker.mode.add_revolutionary(H.mind))
H.Stun(60)
times_used -- //Flashes less likely to burn out for headrevs when used for conversion
else
resisted = 1
else
resisted = 1
if(resisted)
to_chat(user, "<span class='warning'>This mind seems resistant to the flash!</span>")
else
to_chat(user, "<span class='warning'>They must be conscious before you can convert them!</span>")
else
if(user.mind)
var/datum/antagonist/rev/head/converter = user.mind.has_antag_datum(/datum/antagonist/rev/head)
if(!converter)
return
if(!H.client)
to_chat(user, "<span class='warning'>This mind is so vacant that it is not susceptible to influence!</span>")
return
if(H.stat != CONSCIOUS)
to_chat(user, "<span class='warning'>They must be conscious before you can convert them!</span>")
return
if(converter.add_revolutionary(H.mind))
times_used -- //Flashes less likely to burn out for headrevs when used for conversion
else
to_chat(user, "<span class='warning'>This mind seems resistant to the flash!</span>")
/obj/item/device/assembly/flash/cyborg
+4 -2
View File
@@ -107,7 +107,8 @@ Code:
..()
/obj/item/device/assembly/signaler/proc/signal()
if(!radio_connection) return
if(!radio_connection)
return
var/datum/signal/signal = new
signal.source = src
@@ -173,7 +174,8 @@ Code:
return "The radio receiver is [on?"on":"off"]."
/obj/item/device/assembly/signaler/reciever/receive_signal(datum/signal/signal)
if(!on) return
if(!on)
return
return ..(signal)
@@ -12,12 +12,12 @@
if(!air_contents)
return 0
var/oxy = air_contents.gases["o2"] ? air_contents.gases["o2"][MOLES] : 0
var/tox = air_contents.gases["plasma"] ? air_contents.gases["plasma"][MOLES] : 0
var/oxy = air_contents.gases[/datum/gas/oxygen] ? air_contents.gases[/datum/gas/oxygen][MOLES] : 0
var/tox = air_contents.gases[/datum/gas/plasma] ? air_contents.gases[/datum/gas/plasma][MOLES] : 0
var/trit = air_contents.gases[/datum/gas/tritium] ? air_contents.gases[/datum/gas/tritium][MOLES] : 0
if(active_hotspot)
if(soh)
if(tox > 0.5 && oxy > 0.5)
if((tox > 0.5 || trit > 0.5) && oxy > 0.5)
if(active_hotspot.temperature < exposed_temperature)
active_hotspot.temperature = exposed_temperature
if(active_hotspot.volume < exposed_volume)
@@ -26,11 +26,11 @@
var/igniting = 0
if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && tox > 0.5)
if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && (tox > 0.5 || trit > 0.5))
igniting = 1
if(igniting)
if(oxy < 0.5 || tox < 0.5)
if(oxy < 0.5)
return 0
active_hotspot = new /obj/effect/hotspot(src)
@@ -54,11 +54,11 @@
var/volume = 125
var/temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
var/just_spawned = 1
var/bypassing = 0
var/just_spawned = TRUE
var/bypassing = FALSE
/obj/effect/hotspot/New()
..()
/obj/effect/hotspot/Initialize()
. = ..()
SSair.hotspots += src
perform_exposure()
setDir(pick(GLOB.cardinals))
@@ -67,14 +67,14 @@
/obj/effect/hotspot/proc/perform_exposure()
var/turf/open/location = loc
if(!istype(location) || !(location.air))
return 0
return
location.active_hotspot = src
if(volume > CELL_VOLUME*0.95)
bypassing = 1
bypassing = TRUE
else
bypassing = 0
bypassing = FALSE
if(bypassing)
if(!just_spawned)
@@ -88,17 +88,17 @@
volume = affected.reaction_results["fire"]*FIRE_GROWTH_RATE
location.assume_air(affected)
for(var/A in loc)
for(var/A in location)
var/atom/AT = A
if(AT && AT != src) // It's possible that the item is deleted in temperature_expose
AT.fire_act(temperature, volume)
return 0
return
/obj/effect/hotspot/process()
if(just_spawned)
just_spawned = 0
return 0
just_spawned = FALSE
return
var/turf/open/location = loc
if(!istype(location))
@@ -112,7 +112,13 @@
qdel(src)
return
if(!(location.air) || !location.air.gases["plasma"] || !location.air.gases["o2"] || location.air.gases["plasma"][MOLES] < 0.5 || location.air.gases["o2"][MOLES] < 0.5)
//Nothing to burn
if(!(location.air) || !(location.air.gases[/datum/gas/plasma] || location.air.gases[/datum/gas/tritium]) || !location.air.gases[/datum/gas/oxygen])
qdel(src)
return
//Not enough to burn
if(((!location.air.gases[/datum/gas/plasma] || location.air.gases[/datum/gas/plasma][MOLES] < 0.5) && (!location.air.gases[/datum/gas/tritium] || location.air.gases[/datum/gas/tritium][MOLES] < 0.5)) || location.air.gases[/datum/gas/oxygen][MOLES] < 0.5)
qdel(src)
return
@@ -140,11 +146,8 @@
location.max_fire_temperature_sustained = temperature
if(location.heat_capacity && temperature > location.heat_capacity)
location.to_be_destroyed = 1
/*if(prob(25))
location.ReplaceWithSpace()
return 0*/
return 1
location.to_be_destroyed = TRUE
return TRUE
/obj/effect/hotspot/Destroy()
set_light(0)
@@ -153,8 +156,7 @@
if(istype(T) && T.active_hotspot == src)
T.active_hotspot = null
DestroyTurf()
loc = null
. = ..()
return ..()
/obj/effect/hotspot/proc/DestroyTurf()
if(isturf(loc))
@@ -168,12 +170,13 @@
if(prob(chance_of_deletion))
T.ChangeTurf(T.baseturf)
else
T.to_be_destroyed = 0
T.to_be_destroyed = FALSE
T.max_fire_temperature_sustained = 0
/obj/effect/hotspot/Crossed(mob/living/L)
/obj/effect/hotspot/Crossed(atom/movable/AM, oldLoc)
..()
if(isliving(L))
if(isliving(AM))
var/mob/living/L = AM
L.fire_act(temperature, volume)
/obj/effect/dummy/fire
@@ -186,4 +189,4 @@
/obj/effect/dummy/fire/Initialize()
. = ..()
if(!isliving(loc))
qdel(src)
return INITIALIZE_HINT_QDEL
@@ -43,7 +43,7 @@
var/turf/T = get_step(src, direction)
if(!T)
continue
if(CANATMOSPASS(T, src))
if( !(blocks_air || T.blocks_air) && CANATMOSPASS(T, src) )
LAZYINITLIST(atmos_adjacent_turfs)
LAZYINITLIST(T.atmos_adjacent_turfs)
atmos_adjacent_turfs[T] = TRUE
@@ -27,7 +27,7 @@
var/datum/excited_group/excited_group
var/excited = 0
var/recently_active = 0
var/datum/gas_mixture/air
var/datum/gas_mixture/turf/air
var/obj/effect/hotspot/active_hotspot
var/atmos_cooldown = 0
@@ -6,7 +6,6 @@ What are the archived variables for?
#define MINIMUM_HEAT_CAPACITY 0.0003
#define QUANTIZE(variable) (round(variable,0.0000001))/*I feel the need to document what happens here. Basically this is used to catch most rounding errors, however it's previous value made it so that
once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */
GLOBAL_LIST_INIT(meta_gas_info, meta_gas_list()) //see ATMOSPHERICS/gas_types.dm
GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
@@ -65,19 +64,17 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
//PV = nRT
/datum/gas_mixture/proc/heat_capacity() //joules per kelvin
/datum/gas_mixture/proc/heat_capacity(data = MOLES) //joules per kelvin
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
var/gas_data = cached_gases[id]
. += gas_data[MOLES] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
. += gas_data[data] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
/datum/gas_mixture/proc/heat_capacity_archived() //joules per kelvin
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
var/gas_data = cached_gases[id]
. += gas_data[ARCHIVE] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
/datum/gas_mixture/turf/heat_capacity()
. = ..()
if(!.)
. += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space
//prefer this in performance critical areas
#define TOTAL_MOLES(cached_gases, out_var)\
@@ -192,7 +189,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
amount = min(amount, sum) //Can not take more air than tile has!
if(amount <= 0)
return null
var/datum/gas_mixture/removed = new
var/datum/gas_mixture/removed = new type
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
removed.temperature = temperature
@@ -210,7 +207,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
ratio = min(ratio, 1)
var/list/cached_gases = gases
var/datum/gas_mixture/removed = new
var/datum/gas_mixture/removed = new type
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
removed.temperature = temperature
@@ -225,7 +222,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
/datum/gas_mixture/copy()
var/list/cached_gases = gases
var/datum/gas_mixture/copy = new
var/datum/gas_mixture/copy = new type
var/list/copy_gases = copy.gases
copy.temperature = temperature
@@ -268,8 +265,11 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
gas -= "TEMP"
gases.Cut()
for(var/id in gas)
ADD_GAS(id, gases)
gases[id][MOLES] = text2num(gas[id])
var/path = id
if(!ispath(path))
path = gas_id2path(path) //a lot of these strings can't have embedded expressions (especially for mappers), so support for IDs needs to stick around
ADD_GAS(path, gases)
gases[path][MOLES] = text2num(gas[id])
return 1
/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
@@ -358,8 +358,8 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
sharer_temperature = sharer.temperature_archived
var/temperature_delta = temperature_archived - sharer_temperature
if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity_archived()
var/self_heat_capacity = heat_capacity(ARCHIVE)
sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity(ARCHIVE)
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*temperature_delta* \
@@ -400,8 +400,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
/datum/gas_mixture/react(turf/open/dump_location)
. = 0
if(temperature < TCMB) //just for safety
temperature = TCMB
reaction_results = new
var/list/cached_gases = gases
@@ -439,8 +438,13 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
*/
. |= reaction.react(src, dump_location)
//to_chat(world,reaction.name)
if (. & STOP_REACTIONS)
break
if(.)
garbage_collect()
if(temperature < TCMB) //just for safety
temperature = TCMB
//Takes the amount of the gas you want to PP as an argument
//So I don't have to do some hacky switches/defines/magic strings
@@ -1,9 +1,9 @@
GLOBAL_LIST_INIT(hardcoded_gases, list("o2","n2","co2","plasma")) //the main four gases, which were at one time hardcoded
GLOBAL_LIST_INIT(hardcoded_gases, list(/datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/plasma)) //the main four gases, which were at one time hardcoded
/proc/meta_gas_list()
. = new /list
for(var/gas_path in subtypesof(/datum/gas))
var/list/gas_info = new(5)
. = subtypesof(/datum/gas)
for(var/gas_path in .)
var/list/gas_info = new(6)
var/datum/gas/gas = gas_path
gas_info[META_GAS_SPECIFIC_HEAT] = initial(gas.specific_heat)
@@ -12,7 +12,14 @@ GLOBAL_LIST_INIT(hardcoded_gases, list("o2","n2","co2","plasma")) //the main fou
if(initial(gas.moles_visible) != null)
gas_info[META_GAS_OVERLAY] = new /obj/effect/overlay/gas(initial(gas.gas_overlay))
gas_info[META_GAS_DANGER] = initial(gas.dangerous)
.[initial(gas.id)] = gas_info
gas_info[META_GAS_ID] = initial(gas.id)
.[gas_path] = gas_info
/proc/gas_id2path(id)
var/list/meta_gas = GLOB.meta_gas_info
for(var/path in meta_gas)
if(meta_gas[path][META_GAS_ID] == id)
return path
/*||||||||||||||/----------\||||||||||||||*\
||||||||||||||||[GAS DATUMS]||||||||||||||||
@@ -51,7 +58,7 @@ GLOBAL_LIST_INIT(hardcoded_gases, list("o2","n2","co2","plasma")) //the main fou
specific_heat = 200
name = "Plasma"
gas_overlay = "plasma"
moles_visible = MOLES_PLASMA_VISIBLE
moles_visible = MOLES_GAS_VISIBLE
dangerous = TRUE
/datum/gas/water_vapor
@@ -59,14 +66,14 @@ GLOBAL_LIST_INIT(hardcoded_gases, list("o2","n2","co2","plasma")) //the main fou
specific_heat = 40
name = "Water Vapor"
gas_overlay = "water_vapor"
moles_visible = MOLES_PLASMA_VISIBLE
moles_visible = MOLES_GAS_VISIBLE
/datum/gas/freon
id = "freon"
/datum/gas/hypernoblium
id = "nob"
specific_heat = 2000
name = "Freon"
name = "Hyper-noblium"
gas_overlay = "freon"
moles_visible = MOLES_PLASMA_VISIBLE
moles_visible = MOLES_GAS_VISIBLE
dangerous = TRUE
/datum/gas/nitrous_oxide
@@ -77,15 +84,21 @@ GLOBAL_LIST_INIT(hardcoded_gases, list("o2","n2","co2","plasma")) //the main fou
moles_visible = 1
dangerous = TRUE
/datum/gas/oxygen_agent_b
id = "agent_b"
specific_heat = 300
name = "Oxygen Agent B"
/datum/gas/nitryl
id = "no2"
specific_heat = 20
name = "Nitryl"
gas_overlay = "nitryl"
moles_visible = MOLES_GAS_VISIBLE
dangerous = TRUE
/datum/gas/volatile_fuel
id = "v_fuel"
specific_heat = 30
name = "Volatile Fuel"
/datum/gas/tritium
id = "tritium"
specific_heat = 10
name = "Tritium"
gas_overlay = "tritium"
moles_visible = MOLES_GAS_VISIBLE
dangerous = TRUE
/datum/gas/bz
id = "bz"
@@ -93,6 +106,16 @@ GLOBAL_LIST_INIT(hardcoded_gases, list("o2","n2","co2","plasma")) //the main fou
name = "BZ"
dangerous = TRUE
/datum/gas/stimulum
id = "stim"
specific_heat = 5
name = "Stimulum"
/datum/gas/pluoxium
id = "pluox"
specific_heat = 80
name = "Pluoxium"
/obj/effect/overlay/gas
icon = 'icons/effects/tile_effects.dmi'
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
@@ -19,9 +19,6 @@
/datum/gas_mixture/immutable/merge()
return 0 //we're immutable.
/datum/gas_mixture/immutable/heat_capacity_archived()
return heat_capacity()
/datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
. = ..(sharer, 0)
garbage_collect()
@@ -54,7 +51,7 @@
initial_temperature = TCMB
/datum/gas_mixture/immutable/space/heat_capacity()
return 7000
return HEAT_CAPACITY_VACUUM
/datum/gas_mixture/immutable/space/remove()
return copy() //we're always empty, so we can just return a copy.
@@ -69,8 +66,8 @@
/datum/gas_mixture/immutable/cloner/garbage_collect()
..()
ADD_GAS("n2", gases)
gases["n2"][MOLES] = MOLES_O2STANDARD + MOLES_N2STANDARD
ADD_GAS(/datum/gas/nitrogen, gases)
gases[/datum/gas/nitrogen][MOLES] = MOLES_O2STANDARD + MOLES_N2STANDARD
/datum/gas_mixture/immutable/cloner/heat_capacity()
return (MOLES_O2STANDARD + MOLES_N2STANDARD)*20 //specific heat of nitrogen is 20
@@ -1,6 +1,33 @@
#define NO_REACTION 0
#define REACTING 1
//Plasma fire properties
#define OXYGEN_BURN_RATE_BASE 1.4
#define PLASMA_BURN_RATE_DELTA 9
#define PLASMA_UPPER_TEMPERATURE 1370+T0C
#define PLASMA_MINIMUM_OXYGEN_NEEDED 2
#define PLASMA_MINIMUM_OXYGEN_PLASMA_RATIO 30
#define PLASMA_OXYGEN_FULLBURN 10
#define FIRE_CARBON_ENERGY_RELEASED 100000 //Amount of heat released per mole of burnt carbon into the tile
#define FIRE_PLASMA_ENERGY_RELEASED 3000000 //Amount of heat released per mole of burnt plasma into the tile
//General assmos defines.
#define WATER_VAPOR_FREEZE 200
#define NITRYL_FORMATION_ENERGY 100000
#define TRITIUM_BURN_OXY_FACTOR 100
#define TRITIUM_BURN_TRIT_FACTOR 10
#define SUPER_SATURATION_THRESHOLD 96
#define STIMULUM_HEAT_SCALE 100000
#define STIMULUM_FIRST_RISE 0.65
#define STIMULUM_FIRST_DROP 0.065
#define STIMULUM_SECOND_RISE 0.0009
#define STIMULUM_ABSOLUTE_DROP 0.00000335
#define REACTION_OPPRESSION_THRESHOLD 5
//Plasma fusion properties
#define PLASMA_BINDING_ENERGY 3000000
#define MAX_CATALYST_EFFICENCY 9
#define PLASMA_FUSED_COEFFICENT 0.08
#define CATALYST_COEFFICENT 0.01
#define FUSION_PURITY_THRESHOLD 0.9
#define FUSION_HEAT_DROPOFF 20000+T0C
/datum/controller/subsystem/air/var/list/gas_reactions //this is our singleton of all reactions
/proc/init_gas_reactions()
@@ -35,48 +62,15 @@
/datum/gas_reaction/proc/react(datum/gas_mixture/air, atom/location)
return NO_REACTION
//agent b: converts hot co2 and agent b to oxygen. requires plasma as a catalyst. endothermic
/datum/gas_reaction/agent_b
priority = 2
name = "Agent B"
id = "agent_b"
/datum/gas_reaction/nobliumsupression
priority = INFINITY
name = "Hyper-Noblium Reaction Supression"
id = "nobstop"
/datum/gas_reaction/nobliumsupression/init_reqs()
min_requirements = list(/datum/gas/hypernoblium = REACTION_OPPRESSION_THRESHOLD)
/datum/gas_reaction/agent_b/init_reqs()
min_requirements = list(
"TEMP" = 900,
"agent_b" = MINIMUM_HEAT_CAPACITY,
"plasma" = MINIMUM_HEAT_CAPACITY,
"co2" = MINIMUM_HEAT_CAPACITY
)
/datum/gas_reaction/agent_b/react(datum/gas_mixture/air)
var/list/cached_gases = air.gases
var/reaction_rate = min(cached_gases["co2"][MOLES]*0.75, cached_gases["plasma"][MOLES]*0.25, cached_gases["agent_b"][MOLES]*0.05)
cached_gases["co2"][MOLES] -= reaction_rate
cached_gases["agent_b"][MOLES] -= reaction_rate*0.05
ASSERT_GAS("o2", air) //only need to assert oxygen, as this reaction doesn't occur without the other gases existing
cached_gases["o2"][MOLES] += reaction_rate
air.temperature -= (reaction_rate*20000)/air.heat_capacity()
return REACTING
//freon: does a freezy thing?
/datum/gas_reaction/freon
priority = 1
name = "Freon"
id = "freon"
/datum/gas_reaction/freon/init_reqs()
min_requirements = list("freon" = MOLES_PLASMA_VISIBLE)
/datum/gas_reaction/freon/react(datum/gas_mixture/air, turf/open/location)
. = NO_REACTION
if(location && location.freon_gas_act())
. = REACTING
/datum/gas_reaction/nobliumsupression/react()
return STOP_REACTIONS
//water vapor: puts out fires?
/datum/gas_reaction/water_vapor
@@ -85,12 +79,15 @@
id = "vapor"
/datum/gas_reaction/water_vapor/init_reqs()
min_requirements = list("water_vapor" = MOLES_PLASMA_VISIBLE)
min_requirements = list(/datum/gas/water_vapor = MOLES_GAS_VISIBLE)
/datum/gas_reaction/water_vapor/react(datum/gas_mixture/air, turf/open/location)
. = NO_REACTION
if(location && location.water_vapor_gas_act())
air.gases["water_vapor"][MOLES] -= MOLES_PLASMA_VISIBLE
if (air.temperature <= WATER_VAPOR_FREEZE)
if(location && location.freon_gas_act())
. = REACTING
else if(location && location.water_vapor_gas_act())
air.gases[/datum/gas/water_vapor][MOLES] -= MOLES_GAS_VISIBLE
. = REACTING
//fire: combustion of plasma and volatile fuel (treated as hydrocarbons). creates hotspots. exothermic
@@ -100,7 +97,7 @@
id = "fire"
/datum/gas_reaction/fire/init_reqs()
min_requirements = list("TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST) //doesn't include plasma reqs b/c of volatile fuel stuff - consider finally axing volatile fuel
min_requirements = list("TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST) //doesn't include plasma reqs b/c of other, rarer, burning gases.
/datum/gas_reaction/fire/react(datum/gas_mixture/air, turf/open/location)
var/energy_released = 0
@@ -111,48 +108,59 @@
cached_results[id] = 0
//General volatile gas burn
if(cached_gases["v_fuel"] && cached_gases["v_fuel"][MOLES])
if(cached_gases[/datum/gas/tritium] && cached_gases[/datum/gas/tritium][MOLES])
var/burned_fuel
if(!cached_gases["o2"])
if(!cached_gases[/datum/gas/oxygen])
burned_fuel = 0
else if(cached_gases["o2"][MOLES] < cached_gases["v_fuel"][MOLES])
burned_fuel = cached_gases["o2"][MOLES]
cached_gases["v_fuel"][MOLES] -= burned_fuel
cached_gases["o2"][MOLES] = 0
else if(cached_gases[/datum/gas/oxygen][MOLES] < cached_gases[/datum/gas/tritium][MOLES])
burned_fuel = cached_gases[/datum/gas/oxygen][MOLES]/TRITIUM_BURN_OXY_FACTOR
cached_gases[/datum/gas/tritium][MOLES] -= burned_fuel
else
burned_fuel = cached_gases["v_fuel"][MOLES]
cached_gases["o2"][MOLES] -= cached_gases["v_fuel"][MOLES]
burned_fuel = cached_gases[/datum/gas/tritium][MOLES]*TRITIUM_BURN_TRIT_FACTOR
cached_gases[/datum/gas/tritium][MOLES] -= cached_gases[/datum/gas/tritium][MOLES]/TRITIUM_BURN_TRIT_FACTOR
cached_gases[/datum/gas/oxygen][MOLES] -= cached_gases[/datum/gas/tritium][MOLES]
if(burned_fuel)
energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel
ASSERT_GAS("co2", air)
cached_gases["co2"][MOLES] += burned_fuel
ASSERT_GAS(/datum/gas/carbon_dioxide, air)
cached_gases[/datum/gas/carbon_dioxide][MOLES] += burned_fuel/TRITIUM_BURN_OXY_FACTOR
cached_results[id] += burned_fuel
//Handle plasma burning
if(cached_gases["plasma"] && cached_gases["plasma"][MOLES] > MINIMUM_HEAT_CAPACITY)
if(cached_gases[/datum/gas/plasma] && cached_gases[/datum/gas/plasma][MOLES] > MINIMUM_HEAT_CAPACITY)
var/plasma_burn_rate = 0
var/oxygen_burn_rate = 0
//more plasma released at higher temperatures
var/temperature_scale
var/super_saturation
if(temperature > PLASMA_UPPER_TEMPERATURE)
temperature_scale = 1
else
temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE)
if(temperature_scale > 0)
ASSERT_GAS("o2", air)
var/o2 = cached_gases[/datum/gas/oxygen] ? cached_gases[/datum/gas/oxygen][MOLES] : 0
oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - temperature_scale
if(cached_gases["o2"][MOLES] > cached_gases["plasma"][MOLES]*PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (cached_gases["plasma"][MOLES]*temperature_scale)/PLASMA_BURN_RATE_DELTA
if (o2 > cached_gases[/datum/gas/plasma][MOLES]*PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (cached_gases[/datum/gas/plasma][MOLES]*temperature_scale)/PLASMA_BURN_RATE_DELTA
if(o2 / cached_gases[/datum/gas/plasma][MOLES] > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium.
super_saturation = TRUE
if(o2 > cached_gases[/datum/gas/plasma][MOLES]*PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (cached_gases[/datum/gas/plasma][MOLES]*temperature_scale)/PLASMA_BURN_RATE_DELTA
else
plasma_burn_rate = (temperature_scale*(cached_gases["o2"][MOLES]/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
plasma_burn_rate = (temperature_scale*(o2/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY)
ASSERT_GAS("co2", air)
cached_gases["plasma"][MOLES] = QUANTIZE(cached_gases["plasma"][MOLES] - plasma_burn_rate)
cached_gases["o2"][MOLES] = QUANTIZE(cached_gases["o2"][MOLES] - (plasma_burn_rate * oxygen_burn_rate))
cached_gases["co2"][MOLES] += plasma_burn_rate
ASSERT_GAS(/datum/gas/carbon_dioxide, air) //don't need to assert o2, since if it isn't present we'll never reach this point anyway
cached_gases[/datum/gas/plasma][MOLES] = QUANTIZE(cached_gases[/datum/gas/plasma][MOLES] - plasma_burn_rate)
cached_gases[/datum/gas/oxygen][MOLES] = QUANTIZE(cached_gases[/datum/gas/oxygen][MOLES] - (plasma_burn_rate * oxygen_burn_rate))
if (super_saturation)
ASSERT_GAS(/datum/gas/tritium,air)
cached_gases[/datum/gas/tritium][MOLES] += plasma_burn_rate
else
ASSERT_GAS(/datum/gas/carbon_dioxide,air)
cached_gases[/datum/gas/carbon_dioxide][MOLES] += plasma_burn_rate
energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
@@ -175,9 +183,9 @@
return cached_results[id] ? REACTING : NO_REACTION
//fusion: a terrible idea that was fun to try. turns co2 and plasma into REALLY HOT oxygen and nitrogen. super exothermic lol
//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting.
/datum/gas_reaction/fusion
exclude = TRUE
exclude = FALSE
priority = 2
name = "Plasmic Fusion"
id = "fusion"
@@ -185,36 +193,38 @@
/datum/gas_reaction/fusion/init_reqs()
min_requirements = list(
"ENER" = PLASMA_BINDING_ENERGY * 10,
"plasma" = MINIMUM_HEAT_CAPACITY,
"co2" = MINIMUM_HEAT_CAPACITY
/datum/gas/plasma = MINIMUM_HEAT_CAPACITY,
/datum/gas/tritium = MINIMUM_HEAT_CAPACITY
)
/datum/gas_reaction/fusion/react(datum/gas_mixture/air)
var/list/cached_gases = air.gases
var/temperature = air.temperature
if((cached_gases["plasma"][MOLES]+cached_gases["co2"][MOLES])/air.total_moles() < FUSION_PURITY_THRESHOLD)
//Fusion wont occur if the level of impurities is too high.
if(((cached_gases[/datum/gas/plasma][MOLES]+cached_gases[/datum/gas/tritium][MOLES])/air.total_moles() < FUSION_PURITY_THRESHOLD) || air.return_pressure() < 10*ONE_ATMOSPHERE)
//Fusion wont occur if the level of impurities is too high or if there is too little pressure.
return NO_REACTION
var/old_heat_capacity = air.heat_capacity()
var/carbon_efficency = min(cached_gases["plasma"][MOLES]/cached_gases["co2"][MOLES],MAX_CARBON_EFFICENCY)
var/catalyst_efficency = max(min(cached_gases[/datum/gas/plasma][MOLES]/cached_gases[/datum/gas/tritium][MOLES],MAX_CATALYST_EFFICENCY)-(temperature/FUSION_HEAT_DROPOFF),1)
var/reaction_energy = THERMAL_ENERGY(air)
var/moles_impurities = air.total_moles()-(cached_gases["plasma"][MOLES]+cached_gases["co2"][MOLES])
var/moles_impurities = air.total_moles()-(cached_gases[/datum/gas/plasma][MOLES]+cached_gases[/datum/gas/tritium][MOLES])
var/plasma_fused = (PLASMA_FUSED_COEFFICENT*carbon_efficency)*(temperature/PLASMA_BINDING_ENERGY)
var/carbon_catalyzed = (CARBON_CATALYST_COEFFICENT*carbon_efficency)*(temperature/PLASMA_BINDING_ENERGY)
var/oxygen_added = carbon_catalyzed
var/nitrogen_added = (plasma_fused-oxygen_added)-(THERMAL_ENERGY(air)/PLASMA_BINDING_ENERGY)
var/plasma_fused = (PLASMA_FUSED_COEFFICENT*catalyst_efficency)*(temperature/PLASMA_BINDING_ENERGY)*4
var/tritium_catalyzed = (CATALYST_COEFFICENT*catalyst_efficency)*(temperature/PLASMA_BINDING_ENERGY)
var/oxygen_added = tritium_catalyzed
var/waste_added = (plasma_fused-oxygen_added)-((air.total_moles()*air.heat_capacity())/PLASMA_BINDING_ENERGY)
reaction_energy = max(reaction_energy+((catalyst_efficency*cached_gases[/datum/gas/plasma][MOLES])/((moles_impurities/catalyst_efficency)+2)*10)+((plasma_fused/((moles_impurities/catalyst_efficency)))*PLASMA_BINDING_ENERGY),0)
reaction_energy = max(reaction_energy+((carbon_efficency*cached_gases["plasma"][MOLES])/((moles_impurities/carbon_efficency)+2)*10)+((plasma_fused/(moles_impurities/carbon_efficency))*PLASMA_BINDING_ENERGY),0)
air.assert_gases("o2", "n2")
cached_gases["plasma"][MOLES] -= plasma_fused
cached_gases["co2"][MOLES] -= carbon_catalyzed
cached_gases["o2"][MOLES] += oxygen_added
cached_gases["n2"][MOLES] += nitrogen_added
air.assert_gases(/datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/water_vapor, /datum/gas/nitrous_oxide, /datum/gas/nitryl)
//Fusion produces an absurd amount of waste products now, requiring active filtration.
cached_gases[/datum/gas/plasma][MOLES] = max(cached_gases[/datum/gas/plasma][MOLES] - plasma_fused,0)
cached_gases[/datum/gas/tritium][MOLES] = max(cached_gases[/datum/gas/tritium][MOLES] - tritium_catalyzed,0)
cached_gases[/datum/gas/oxygen][MOLES] += oxygen_added
cached_gases[/datum/gas/nitrogen][MOLES] += waste_added
cached_gases[/datum/gas/water_vapor][MOLES] += waste_added
cached_gases[/datum/gas/nitrous_oxide][MOLES] += waste_added
cached_gases[/datum/gas/nitryl][MOLES] += waste_added
if(reaction_energy > 0)
var/new_heat_capacity = air.heat_capacity()
@@ -223,5 +233,152 @@
//Prevents whatever mechanism is causing it to hit negative temperatures.
return REACTING
/datum/gas_reaction/nitrylformation //The formation of nitryl. Endothermic. Requires N2O as a catalyst.
priority = 3
name = "Nitryl formation"
id = "nitrylformation"
/datum/gas_reaction/nitrylformation/init_reqs()
min_requirements = list(
/datum/gas/oxygen = 20,
/datum/gas/nitrogen = 20,
/datum/gas/nitrous_oxide = 5,
"TEMP" = FIRE_MINIMUM_TEMPERATURE_TO_EXIST*400
)
/datum/gas_reaction/nitrylformation/react(datum/gas_mixture/air)
var/list/cached_gases = air.gases
var/temperature = air.temperature
var/old_heat_capacity = air.heat_capacity()
var/heat_efficency = temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100)
var/energy_used = heat_efficency*NITRYL_FORMATION_ENERGY
ASSERT_GAS(/datum/gas/nitryl,air)
cached_gases[/datum/gas/oxygen][MOLES] -= heat_efficency
cached_gases[/datum/gas/nitrogen][MOLES] -= heat_efficency
cached_gases[/datum/gas/nitryl][MOLES] += heat_efficency*2
if(energy_used > 0)
var/new_heat_capacity = air.heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
air.temperature = max(((temperature*old_heat_capacity - energy_used)/new_heat_capacity),TCMB)
return REACTING
/datum/gas_reaction/bzformation //Formation of BZ by combining plasma and tritium at low pressures. Exothermic.
priority = 4
name = "BZ Gas formation"
id = "bzformation"
/datum/gas_reaction/bzformation/init_reqs()
min_requirements = list(
/datum/gas/tritium = 10,
/datum/gas/plasma = 10
)
/datum/gas_reaction/bzformation/react(datum/gas_mixture/air)
var/list/cached_gases = air.gases
var/temperature = air.temperature
var/pressure = air.return_pressure()
var/old_heat_capacity = air.heat_capacity()
var/reaction_efficency = 1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(cached_gases[/datum/gas/plasma][MOLES]/cached_gases[/datum/gas/tritium][MOLES],1)))
var/energy_released = 2*reaction_efficency*FIRE_CARBON_ENERGY_RELEASED
ASSERT_GAS(/datum/gas/bz,air)
cached_gases[/datum/gas/bz][MOLES]+= reaction_efficency
cached_gases[/datum/gas/tritium][MOLES] = max(cached_gases[/datum/gas/tritium][MOLES]- 2*reaction_efficency,0)
cached_gases[/datum/gas/plasma][MOLES] = max(cached_gases[/datum/gas/plasma][MOLES] - reaction_efficency,0)
if(energy_released > 0)
var/new_heat_capacity = air.heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
air.temperature = max(((temperature*old_heat_capacity + energy_released)/new_heat_capacity),TCMB)
return REACTING
/datum/gas_reaction/stimformation //Stimulum formation follows a strange pattern of how effective it will be at a given temperature, having some multiple peaks and some large dropoffs. Exo and endo thermic.
priority = 5
name = "Stimulum formation"
id = "stimformation"
/datum/gas_reaction/stimformation/init_reqs()
min_requirements = list(
/datum/gas/tritium = 30,
/datum/gas/plasma = 10,
/datum/gas/bz = 20,
/datum/gas/nitryl = 30,
"TEMP" = STIMULUM_HEAT_SCALE/2)
/datum/gas_reaction/stimformation/react(datum/gas_mixture/air)
var/list/cached_gases = air.gases
var/old_heat_capacity = air.heat_capacity()
var/heat_scale = air.temperature/STIMULUM_HEAT_SCALE
var/stim_energy_change
stim_energy_change =heat_scale + (STIMULUM_FIRST_RISE(heat_scale**2)) - (STIMULUM_FIRST_DROP(heat_scale**3)) + (STIMULUM_SECOND_RISE(heat_scale**4)) - (STIMULUM_ABSOLUTE_DROP(heat_scale**5))
ASSERT_GAS(/datum/gas/stimulum,air)
cached_gases[/datum/gas/stimulum][MOLES]+= heat_scale/10
cached_gases[/datum/gas/tritium][MOLES] = max(cached_gases[/datum/gas/tritium][MOLES]- heat_scale,0)
cached_gases[/datum/gas/plasma][MOLES] = max(cached_gases[/datum/gas/plasma][MOLES]- heat_scale,0)
cached_gases[/datum/gas/nitryl][MOLES] = max(cached_gases[/datum/gas/nitryl][MOLES]- heat_scale,0)
if(stim_energy_change)
var/new_heat_capacity = air.heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
air.temperature = max(((air.temperature*old_heat_capacity + stim_energy_change)/new_heat_capacity),TCMB)
return REACTING
/datum/gas_reaction/nobliumformation //Hyper-Nobelium formation is extrememly endothermic, but requires high temperatures to start. Due to its high mass, hyper-nobelium uses large amounts of nitrogen and tritium. BZ can be used as a catalyst to make it less endothermic.
priority = 6
name = "Hyper-Noblium condensation"
id = "nobformation"
/datum/gas_reaction/nobliumformation/init_reqs()
min_requirements = list(
/datum/gas/nitrogen = 10,
/datum/gas/tritium = 5,
"TEMP" = 5000000)
/datum/gas_reaction/nobliumformation/react(datum/gas_mixture/air)
var/list/cached_gases = air.gases
air.assert_gases(/datum/gas/hypernoblium,/datum/gas/bz)
var/old_heat_capacity = air.heat_capacity()
var/nob_formed = (cached_gases[/datum/gas/nitrogen][MOLES]*cached_gases[/datum/gas/tritium][MOLES])/100
var/energy_taken = nob_formed*(10000000/(max(cached_gases[/datum/gas/bz][MOLES],1)))
cached_gases[/datum/gas/tritium][MOLES] = max(cached_gases[/datum/gas/tritium][MOLES]- 10*nob_formed,0)
cached_gases[/datum/gas/nitrogen][MOLES] = max(cached_gases[/datum/gas/nitrogen][MOLES]- 20*nob_formed,0)
cached_gases[/datum/gas/hypernoblium][MOLES]+= nob_formed
if (nob_formed)
var/new_heat_capacity = air.heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
air.temperature = max(((air.temperature*old_heat_capacity - energy_taken)/new_heat_capacity),TCMB)
#undef REACTING
#undef NO_REACTION
#undef OXYGEN_BURN_RATE_BASE
#undef PLASMA_BURN_RATE_DELTA
#undef PLASMA_UPPER_TEMPERATURE
#undef PLASMA_MINIMUM_OXYGEN_NEEDED
#undef PLASMA_MINIMUM_OXYGEN_PLASMA_RATIO
#undef PLASMA_OXYGEN_FULLBURN
#undef FIRE_CARBON_ENERGY_RELEASED
#undef FIRE_PLASMA_ENERGY_RELEASED
#undef WATER_VAPOR_FREEZE
#undef NITRYL_FORMATION_ENERGY
#undef TRITIUM_BURN_OXY_FACTOR
#undef SUPER_SATURATION_THRESHOLD
#undef STIMULUM_HEAT_SCALE
#undef STIMULUM_FIRST_RISE
#undef STIMULUM_FIRST_DROP
#undef STIMULUM_SECOND_RISE
#undef STIMULUM_ABSOLUTE_DROP
#undef REACTION_OPPRESSION_THRESHOLD
#undef PLASMA_BINDING_ENERGY
#undef MAX_CATALYST_EFFICENCY
#undef PLASMA_FUSED_COEFFICENT
#undef CATALYST_COEFFICENT
#undef FUSION_PURITY_THRESHOLD
#undef FUSION_HEAT_DROPOFF
+74 -49
View File
@@ -5,10 +5,10 @@
var/max2
/datum/tlv/New(min2 as num, min1 as num, max1 as num, max2 as num)
src.min2 = min2
src.min1 = min1
src.max1 = max1
src.max2 = max2
if(min2) src.min2 = min2
if(min1) src.min1 = min1
if(max1) src.max1 = max1
if(max2) src.max2 = max2
/datum/tlv/proc/get_danger_level(val as num)
if(max2 != -1 && val >= max2)
@@ -21,13 +21,25 @@
return 1
return 0
/datum/tlv/no_checks
min2 = -1
min1 = -1
max1 = -1
max2 = -1
/datum/tlv/dangerous
min2 = -1
min1 = -1
max1 = 0.2
max2 = 0.5
/obj/item/electronics/airalarm
name = "air alarm electronics"
icon_state = "airalarm_electronics"
/obj/item/wallframe/airalarm
name = "air alarm frame"
desc = "Used for building Air Alarms"
desc = "Used for building Air Alarms."
icon = 'icons/obj/monitors.dmi'
icon_state = "alarm_bitem"
result_path = /obj/machinery/airalarm
@@ -73,44 +85,56 @@
var/datum/radio_frequency/radio_connection
var/list/TLV = list( // Breathable air.
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
"temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), // K
"o2" = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
"n2" = new/datum/tlv(-1, -1, 1000, 1000), // Partial pressure, kpa
"co2" = new/datum/tlv(-1, -1, 5, 10), // Partial pressure, kpa
"plasma" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"n2o" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"bz" = new/datum/tlv(-1, -1, 0.2, 0.5),
"freon" = new/datum/tlv(-1, -1, 0.2, 0.5),
"water_vapor" = new/datum/tlv(-1, -1, 0.2, 0.5)
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
"temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66), // K
/datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
/datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000), // Partial pressure, kpa
/datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10), // Partial pressure, kpa
/datum/gas/plasma = new/datum/tlv/dangerous, // Partial pressure, kpa
/datum/gas/nitrous_oxide = new/datum/tlv/dangerous, // Partial pressure, kpa
/datum/gas/bz = new/datum/tlv/dangerous,
/datum/gas/hypernoblium = new/datum/tlv/dangerous,
/datum/gas/water_vapor = new/datum/tlv/dangerous,
/datum/gas/tritium = new/datum/tlv/dangerous,
/datum/gas/stimulum = new/datum/tlv/dangerous,
/datum/gas/nitryl = new/datum/tlv/dangerous,
/datum/gas/pluoxium = new/datum/tlv/dangerous
)
/obj/machinery/airalarm/server // No checks here.
TLV = list(
"pressure" = new/datum/tlv(-1, -1, -1, -1),
"temperature" = new/datum/tlv(-1, -1, -1, -1),
"o2" = new/datum/tlv(-1, -1, -1, -1),
"n2" = new/datum/tlv(-1, -1, -1, -1),
"co2" = new/datum/tlv(-1, -1, -1, -1),
"plasma" = new/datum/tlv(-1, -1, -1, -1),
"n2o" = new/datum/tlv(-1, -1, -1, -1),
"bz" = new/datum/tlv(-1, -1, -1, -1),
"freon" = new/datum/tlv(-1, -1, -1, -1),
"water_vapor" = new/datum/tlv(-1, -1, -1, -1)
"pressure" = new/datum/tlv/no_checks,
"temperature" = new/datum/tlv/no_checks,
/datum/gas/oxygen = new/datum/tlv/no_checks,
/datum/gas/nitrogen = new/datum/tlv/no_checks,
/datum/gas/carbon_dioxide = new/datum/tlv/no_checks,
/datum/gas/plasma = new/datum/tlv/no_checks,
/datum/gas/nitrous_oxide = new/datum/tlv/no_checks,
/datum/gas/bz = new/datum/tlv/no_checks,
/datum/gas/hypernoblium = new/datum/tlv/no_checks,
/datum/gas/water_vapor = new/datum/tlv/no_checks,
/datum/gas/tritium = new/datum/tlv/no_checks,
/datum/gas/stimulum = new/datum/tlv/no_checks,
/datum/gas/nitryl = new/datum/tlv/no_checks,
/datum/gas/pluoxium = new/datum/tlv/no_checks
)
/obj/machinery/airalarm/kitchen_cold_room // Copypasta: to check temperatures.
TLV = list(
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
"temperature" = new/datum/tlv(200,210,273.15,283.15), // K
"o2" = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
"n2" = new/datum/tlv(-1, -1, 1000, 1000), // Partial pressure, kpa
"co2" = new/datum/tlv(-1, -1, 5, 10), // Partial pressure, kpa
"plasma" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"n2o" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"bz" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"freon" = new/datum/tlv(-1, -1, 0.2, 0.5), // Partial pressure, kpa
"water_vapor" = new/datum/tlv(-1, -1, 0.2, 0.5)
"pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
"temperature" = new/datum/tlv(200,210,273.15,283.15), // K
/datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
/datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000), // Partial pressure, kpa
/datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10), // Partial pressure, kpa
/datum/gas/plasma = new/datum/tlv/dangerous, // Partial pressure, kpa
/datum/gas/nitrous_oxide = new/datum/tlv/dangerous, // Partial pressure, kpa
/datum/gas/bz = new/datum/tlv/dangerous,
/datum/gas/hypernoblium = new/datum/tlv/dangerous,
/datum/gas/water_vapor = new/datum/tlv/dangerous,
/datum/gas/tritium = new/datum/tlv/dangerous,
/datum/gas/stimulum = new/datum/tlv/dangerous,
/datum/gas/nitryl = new/datum/tlv/dangerous,
/datum/gas/pluoxium = new/datum/tlv/dangerous
)
/obj/machinery/airalarm/engine
@@ -237,7 +261,9 @@
"incheck" = info["checks"]&2,
"direction" = info["direction"],
"external" = info["external"],
"extdefault"= (info["external"] == ONE_ATMOSPHERE)
"internal" = info["internal"],
"extdefault"= (info["external"] == ONE_ATMOSPHERE),
"intdefault"= (info["internal"] == 0)
))
data["scrubbers"] = list()
for(var/id_tag in A.air_scrub_names)
@@ -254,8 +280,7 @@
"filter_co2" = info["filter_co2"],
"filter_toxins" = info["filter_toxins"],
"filter_n2o" = info["filter_n2o"],
"filter_bz" = info["filter_bz"],
"filter_freon" = info["filter_freon"],
"filter_rare" = info["filter_rare"],
"filter_water_vapor" = info["filter_water_vapor"]
))
data["mode"] = mode
@@ -312,7 +337,7 @@
if(usr.has_unlimited_silicon_privilege && !wires.is_cut(WIRE_IDSCAN))
locked = !locked
. = TRUE
if("power", "co2_scrub", "tox_scrub", "n2o_scrub", "bz_scrub", "freon_scrub","water_vapor_scrub", "widenet", "scrubbing")
if("power", "co2_scrub", "tox_scrub", "n2o_scrub", "rare_scrub","water_vapor_scrub", "widenet", "scrubbing")
send_signal(device_id, list("[action]" = text2num(params["val"])))
. = TRUE
if("excheck")
@@ -321,15 +346,18 @@
if("incheck")
send_signal(device_id, list("checks" = text2num(params["val"])^2))
. = TRUE
if("set_external_pressure")
if("set_external_pressure", "set_internal_pressure")
var/area/A = get_area(src)
var/target = input("New target pressure:", name, A.air_vent_info[device_id]["external"]) as num|null
var/target = input("New target pressure:", name, A.air_vent_info[device_id][(action == "set_external_pressure" ? "external" : "internal")]) as num|null
if(!isnull(target) && !..())
send_signal(device_id, list("set_external_pressure" = target))
send_signal(device_id, list("[action]" = target))
. = TRUE
if("reset_external_pressure")
send_signal(device_id, list("reset_external_pressure"))
. = TRUE
if("reset_internal_pressure")
send_signal(device_id, list("reset_internal_pressure"))
. = TRUE
if("threshold")
var/env = params["env"]
var/name = params["var"]
@@ -428,8 +456,7 @@
"co2_scrub" = 1,
"tox_scrub" = 0,
"n2o_scrub" = 0,
"bz_scrub" = 0,
"freon_scrub"= 0,
"rare_scrub"= 0,
"water_vapor_scrub"= 0,
"scrubbing" = 1,
"widenet" = 0,
@@ -447,8 +474,7 @@
"co2_scrub" = 1,
"tox_scrub" = 1,
"n2o_scrub" = 1,
"bz_scrub" = 1,
"freon_scrub"= 1,
"rare_scrub"= 1,
"water_vapor_scrub"= 1,
"scrubbing" = 1,
"widenet" = 1,
@@ -479,8 +505,7 @@
"co2_scrub" = 1,
"tox_scrub" = 0,
"n2o_scrub" = 0,
"bz_scrub" = 0,
"freon_scrub"= 0,
"rare_scrub"= 0,
"water_vapor_scrub"= 0,
"scrubbing" = 1,
"widenet" = 0,
@@ -760,4 +785,4 @@
#undef AALARM_MODE_SIPHON
#undef AALARM_MODE_CONTAMINATED
#undef AALARM_MODE_REFILL
#undef AALARM_REPORT_TIMEOUT
#undef AALARM_REPORT_TIMEOUT
@@ -25,6 +25,8 @@ Pipelines + Other Objects -> Pipe network
var/can_unwrench = 0
var/initialize_directions = 0
var/pipe_color
var/piping_layer = PIPING_LAYER_DEFAULT
var/pipe_flags = NONE
var/global/list/iconsetids = list()
var/global/list/pipeimages = list()
@@ -34,12 +36,21 @@ Pipelines + Other Objects -> Pipe network
var/device_type = 0
var/list/obj/machinery/atmospherics/nodes
/obj/machinery/atmospherics/examine(mob/living/user)
..()
if(is_type_in_list(src, GLOB.ventcrawl_machinery) && user.ventcrawler)
to_chat(user, "<span class='notice'>Alt-click to crawl through it.</span>")
var/construction_type
var/pipe_state //icon_state as a pipe item
/obj/machinery/atmospherics/New(loc, process = TRUE)
/obj/machinery/atmospherics/examine(mob/user)
..()
if(is_type_in_list(src, GLOB.ventcrawl_machinery) && isliving(user))
var/mob/living/L = user
if(L.ventcrawler)
to_chat(L, "<span class='notice'>Alt-click to crawl through it.</span>")
/obj/machinery/atmospherics/New(loc, process = TRUE, setdir)
if(!isnull(setdir))
setDir(setdir)
if(pipe_flags & PIPING_CARDINAL_AUTONORMALIZE)
normalize_cardinal_directions()
nodes = new(device_type)
if (!armor)
armor = list(melee = 25, bullet = 10, laser = 10, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 100, acid = 70)
@@ -61,6 +72,13 @@ Pipelines + Other Objects -> Pipe network
return ..()
//return QDEL_HINT_FINDREFERENCE
/obj/machinery/atmospherics/proc/destroy_network()
return
/obj/machinery/atmospherics/proc/build_network()
// Called to build a network from this node
return
/obj/machinery/atmospherics/proc/nullifyNode(I)
if(NODE_I)
var/obj/machinery/atmospherics/N = NODE_I
@@ -80,6 +98,11 @@ Pipelines + Other Objects -> Pipe network
break
return node_connects
/obj/machinery/atmospherics/proc/normalize_cardinal_directions()
if(dir==SOUTH)
setDir(NORTH)
else if(dir==WEST)
setDir(EAST)
//this is called just after the air controller sets up turfs
/obj/machinery/atmospherics/proc/atmosinit(var/list/node_connects)
@@ -91,12 +114,37 @@ Pipelines + Other Objects -> Pipe network
if(can_be_node(target, I))
NODE_I = target
break
update_icon()
/obj/machinery/atmospherics/proc/setPipingLayer(new_layer)
if(pipe_flags & PIPING_DEFAULT_LAYER_ONLY)
new_layer = PIPING_LAYER_DEFAULT
piping_layer = new_layer
pixel_x = (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X
pixel_y = (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
layer = initial(layer) + ((piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE)
/obj/machinery/atmospherics/proc/can_be_node(obj/machinery/atmospherics/target)
if(target.initialize_directions & get_dir(target,src))
return connection_check(target, piping_layer)
//Find a connecting /obj/machinery/atmospherics in specified direction
/obj/machinery/atmospherics/proc/findConnecting(direction, prompted_layer)
for(var/obj/machinery/atmospherics/target in get_step(src, direction))
if(target.initialize_directions & get_dir(target,src))
if(connection_check(target, prompted_layer))
return target
/obj/machinery/atmospherics/proc/connection_check(obj/machinery/atmospherics/target, given_layer)
if(isConnectable(target, given_layer) && target.isConnectable(src, given_layer) && (target.initialize_directions & get_dir(target,src)))
return TRUE
return FALSE
/obj/machinery/atmospherics/proc/isConnectable(obj/machinery/atmospherics/target, given_layer)
if(isnull(given_layer))
given_layer = piping_layer
if((target.piping_layer == given_layer) || (target.pipe_flags & PIPING_ALL_LAYER))
return TRUE
return FALSE
/obj/machinery/atmospherics/proc/pipeline_expansion()
return nodes
@@ -119,14 +167,10 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/replacePipenet()
return
/obj/machinery/atmospherics/proc/build_network()
// Called to build a network from this node
return
/obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference)
if(istype(reference, /obj/machinery/atmospherics/pipe))
var/obj/machinery/atmospherics/pipe/P = reference
qdel(P.parent)
P.destroy_network()
var/I = nodes.Find(reference)
NODE_I = null
update_icon()
@@ -135,12 +179,17 @@ Pipelines + Other Objects -> Pipe network
return
/obj/machinery/atmospherics/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/pipe)) //lets you autodrop
var/obj/item/pipe/pipe = W
if(user.dropItemToGround(pipe))
pipe.setPipingLayer(piping_layer) //align it with us
return TRUE
if(istype(W, /obj/item/wrench))
if(can_unwrench(user))
var/turf/T = get_turf(src)
if (level==1 && isturf(T) && T.intact)
to_chat(user, "<span class='warning'>You must remove the plating first!</span>")
return 1
return TRUE
var/datum/gas_mixture/int_air = return_air()
var/datum/gas_mixture/env_air = loc.return_air()
add_fingerprint(user)
@@ -148,7 +197,7 @@ Pipelines + Other Objects -> Pipe network
var/unsafe_wrenching = FALSE
var/internal_pressure = int_air.return_pressure()-env_air.return_pressure()
playsound(src.loc, W.usesound, 50, 1)
playsound(src, W.usesound, 50, 1)
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
if (internal_pressure > 2*ONE_ATMOSPHERE)
to_chat(user, "<span class='warning'>As you begin unwrenching \the [src] a gush of air blows in your face... maybe you should reconsider?</span>")
@@ -193,7 +242,8 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
if(can_unwrench)
var/obj/item/pipe/stored = new(loc, make_from=src)
var/obj/item/pipe/stored = new construction_type(loc, null, dir, src)
stored.setPipingLayer(piping_layer)
if(!disassembled)
stored.obj_integrity = stored.max_integrity * 0.5
transfer_fingerprints_to(stored)
@@ -224,10 +274,11 @@ Pipelines + Other Objects -> Pipe network
if(unconnected & direction)
underlays += getpipeimage('icons/obj/atmospherics/components/binary_devices.dmi', "pipe_exposed", direction)
/obj/machinery/atmospherics/on_construction(pipe_type, obj_color)
/obj/machinery/atmospherics/on_construction(obj_color, set_layer)
if(can_unwrench)
add_atom_colour(obj_color, FIXED_COLOUR_PRIORITY)
pipe_color = obj_color
setPipingLayer(set_layer)
var/turf/T = get_turf(src)
level = T.intact ? 2 : 1
atmosinit()
@@ -237,18 +288,16 @@ Pipelines + Other Objects -> Pipe network
A.addMember(src)
build_network()
/obj/machinery/atmospherics/Entered(atom/movable/AM)
if(istype(AM, /mob/living))
var/mob/living/L = AM
L.ventcrawl_layer = piping_layer
return ..()
/obj/machinery/atmospherics/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FIVE)
deconstruct(FALSE)
//Find a connecting /obj/machinery/atmospherics in specified direction
/obj/machinery/atmospherics/proc/findConnecting(direction)
for(var/obj/machinery/atmospherics/target in get_step(src, direction))
if(target.initialize_directions & get_dir(target,src))
return target
return ..()
#define VENT_SOUND_DELAY 30
@@ -259,7 +308,7 @@ Pipelines + Other Objects -> Pipe network
if(user in buckled_mobs)// fixes buckle ventcrawl edgecase fuck bug
return
var/obj/machinery/atmospherics/target_move = findConnecting(direction)
var/obj/machinery/atmospherics/target_move = findConnecting(direction, user.ventcrawl_layer)
if(target_move)
if(target_move.can_crawl_through())
if(is_type_in_typecache(target_move, GLOB.ventcrawl_machinery))
@@ -269,14 +318,14 @@ Pipelines + Other Objects -> Pipe network
var/list/pipenetdiff = returnPipenets() ^ target_move.returnPipenets()
if(pipenetdiff.len)
user.update_pipe_vision(target_move)
user.loc = target_move
user.forceMove(target_move)
user.client.eye = target_move //Byond only updates the eye every tick, This smooths out the movement
if(world.time - user.last_played_vent > VENT_SOUND_DELAY)
user.last_played_vent = world.time
playsound(src, 'sound/machines/ventcrawl.ogg', 50, 1, -3)
else
if((direction & initialize_directions) || is_type_in_typecache(src, GLOB.ventcrawl_machinery) && can_crawl_through()) //if we move in a way the pipe can connect, but doesn't - or we're in a vent
user.forceMove(src.loc)
user.forceMove(loc)
user.visible_message("<span class='notice'>You hear something squeezing through the ducts...</span>","<span class='notice'>You climb out the ventilation system.")
user.canmove = 0
spawn(1)
@@ -11,6 +11,7 @@
var/status = 0
var/last_pressure_delta = 0
pipe_flags = PIPING_ONE_PER_TURF
anchored = TRUE
density = TRUE
@@ -21,6 +21,9 @@ Passive gate is similar to the regular pump except:
var/id = null
var/datum/radio_frequency/radio_connection
construction_type = /obj/item/pipe/directional
pipe_state = "passivegate"
/obj/machinery/atmospherics/components/binary/passive_gate/Destroy()
SSradio.remove_object(src,frequency)
return ..()
@@ -167,4 +170,3 @@ Passive gate is similar to the regular pump except:
if(. && on)
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
@@ -26,6 +26,9 @@ Thus, the two variables affect pump operation are set in New():
var/id = null
var/datum/radio_frequency/radio_connection
construction_type = /obj/item/pipe/directional
pipe_state = "pump"
/obj/machinery/atmospherics/components/binary/pump/on
on = TRUE
@@ -15,6 +15,9 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
var/open = FALSE
var/valve_type = "m" //lets us have a nice, clean, OOP update_icon_nopipes()
construction_type = /obj/item/pipe/binary
pipe_state = "mvalve"
/obj/machinery/atmospherics/components/binary/valve/open
open = TRUE
@@ -65,6 +68,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
desc = "A digitally controlled valve."
icon_state = "dvalve_map"
valve_type = "d"
pipe_state = "dvalve"
/obj/machinery/atmospherics/components/binary/valve/digital/attack_ai(mob/user)
return src.attack_hand(user)
@@ -26,6 +26,9 @@ Thus, the two variables affect pump operation are set in New():
var/id = null
var/datum/radio_frequency/radio_connection
construction_type = /obj/item/pipe/directional
pipe_state = "volumepump"
/obj/machinery/atmospherics/components/binary/volume_pump/Destroy()
SSradio.remove_object(src,frequency)
return ..()
@@ -6,10 +6,13 @@
can_unwrench = TRUE
var/on = FALSE
var/target_pressure = ONE_ATMOSPHERE
var/filter_type = ""
var/filter_type = null
var/frequency = 0
var/datum/radio_frequency/radio_connection
construction_type = /obj/item/pipe/trinary/flippable
pipe_state = "filter"
/obj/machinery/atmospherics/components/trinary/filter/flipped
icon_state = "filter_off_f"
flipped = TRUE
@@ -28,6 +31,9 @@
if(frequency)
radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/trinary/filter/New()
..()
/obj/machinery/atmospherics/components/trinary/filter/Destroy()
SSradio.remove_object(src,frequency)
return ..()
@@ -67,7 +73,7 @@
var/output_starting_pressure = air3.return_pressure()
if(output_starting_pressure >= target_pressure)
//No need to mix if target is already full!
//No need to transfer if target is already full!
return
//Calculate necessary moles to transfer using PV=nRT
@@ -86,11 +92,12 @@
if(!removed)
return
var/filtering = filter_type ? TRUE : FALSE
if(filtering && !istext(filter_type))
WARNING("Wrong gas ID in [src]'s filter_type var. filter_type == [filter_type]")
filtering = FALSE
var/filtering = TRUE
if(!ispath(filter_type))
if(filter_type)
filter_type = gas_id2path(filter_type) //support for mappers so they don't need to type out paths
else
filtering = FALSE
if(filtering && removed.gases[filter_type])
var/datum/gas_mixture/filtered_out = new
@@ -102,7 +109,8 @@
removed.gases[filter_type][MOLES] = 0
removed.garbage_collect()
air2.merge(filtered_out)
var/datum/gas_mixture/target = (air2.return_pressure() < target_pressure ? air2 : air1) //if there's no room for the filtered gas; just leave it in air1
target.merge(filtered_out)
air3.merge(removed)
@@ -116,7 +124,7 @@
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_filter", name, 475, 155, master_ui, state)
ui = new(user, src, ui_key, "atmos_filter", name, 475, 180, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/trinary/filter/ui_data()
@@ -124,7 +132,15 @@
data["on"] = on
data["pressure"] = round(target_pressure)
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
data["filter_type"] = filter_type
if(filter_type) //ui code is garbage and this is needed for it to work grr
if(ispath(filter_type)) //we need to send the gas ID. if it's a path, get it from the metainfo list...
data["filter_type"] = GLOB.meta_gas_info[filter_type][META_GAS_ID]
else //...otherwise, it's already in the form we need.
data["filter_type"] = filter_type
else
data["filter_type"] = "none"
return data
/obj/machinery/atmospherics/components/trinary/filter/ui_act(action, params)
@@ -151,9 +167,9 @@
target_pressure = Clamp(pressure, 0, MAX_OUTPUT_PRESSURE)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS)
if("filter")
filter_type = ""
filter_type = null
var/filter_name = "nothing"
var/gas = params["mode"]
var/gas = text2path(params["mode"]) || gas_id2path(params["mode"])
if(gas in GLOB.meta_gas_info)
filter_type = gas
filter_name = GLOB.meta_gas_info[gas][META_GAS_NAME]
@@ -12,6 +12,9 @@
var/node1_concentration = 0.5
var/node2_concentration = 0.5
construction_type = /obj/item/pipe/trinary/flippable
pipe_state = "mixer"
//node 3 is the outlet, nodes 1 & 2 are intakes
/obj/machinery/atmospherics/components/trinary/mixer/flipped
@@ -171,4 +174,3 @@
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
@@ -5,6 +5,7 @@
use_power = IDLE_POWER_USE
device_type = TRINARY
layer = GAS_FILTER_LAYER
pipe_flags = PIPING_ONE_PER_TURF
var/flipped = FALSE
@@ -11,6 +11,7 @@
layer = ABOVE_WINDOW_LAYER
state_open = FALSE
circuit = /obj/item/circuitboard/machine/cryo_tube
pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY
var/on = FALSE
var/autoeject = FALSE
@@ -187,7 +188,7 @@
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
beaker.reagents.trans_to(occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
beaker.reagents.reaction(occupant, VAPOR)
air1.gases["o2"][MOLES] -= 2 / efficiency // Lets use gas for this.
air1.gases[/datum/gas/oxygen][MOLES] -= 2 / efficiency //Let's use gas for this
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
reagent_transfer = 0
@@ -201,7 +202,7 @@
var/datum/gas_mixture/air1 = AIR1
if(!NODE1 || !AIR1 || !air1.gases.len || air1.gases["o2"][MOLES] < 5) // Turn off if the machine won't work.
if(!NODE1 || !AIR1 || !air1.gases.len || air1.gases[/datum/gas/oxygen][MOLES] < 5) // Turn off if the machine won't work.
on = FALSE
update_icon()
return
@@ -217,11 +218,13 @@
if(abs(temperature_delta) > 1)
var/air_heat_capacity = air1.heat_capacity()
var/heat = ((1 - cold_protection) * 0.1 + conduction_coefficient) * temperature_delta * (1 / air_heat_capacity + 1 / heat_capacity)
var/heat = ((1 - cold_protection) * 0.1 + conduction_coefficient) * temperature_delta * (air_heat_capacity * heat_capacity / (air_heat_capacity + heat_capacity))
air1.temperature = max(air1.temperature - heat / air_heat_capacity, TCMB)
mob_occupant.bodytemperature = max(mob_occupant.bodytemperature + heat / heat_capacity, TCMB)
air1.gases["o2"][MOLES] -= 0.5 / efficiency // Magically consume gas? Why not, we run on cryo magic.
air1.gases[/datum/gas/oxygen][MOLES] -= 0.5 / efficiency // Magically consume gas? Why not, we run on cryo magic.
/obj/machinery/atmospherics/components/unary/cryo_cell/power_change()
..()
@@ -291,10 +294,15 @@
var/reagentlist = pretty_string_from_reagent_list(I.reagents.reagent_list)
log_game("[key_name(user)] added an [I] to cyro containing [reagentlist]")
return
if(!on && !occupant && !state_open && (default_deconstruction_screwdriver(user, "pod-o", "pod-off", I) || exchange_parts(user, I)) \
if(!on && !occupant && !state_open && (default_deconstruction_screwdriver(user, "pod-off", "pod-off", I) || exchange_parts(user, I)) \
|| default_change_direction_wrench(user, I) \
|| default_pry_open(I) \
|| default_deconstruction_crowbar(I))
update_icon()
return
else if(istype(I, /obj/item/screwdriver))
to_chat(user, "<span class='notice'>You can't access the maintenance panel while the pod is " \
+ (on ? "active" : (occupant ? "full" : "open")) + ".</span>")
return
return ..()
@@ -3,7 +3,7 @@
icon_state = "he_intact"
name = "heat exchanger"
desc = "Exchanges heat between two input gases. Setup for fast heat transfer"
desc = "Exchanges heat between two input gases. Set up for fast heat transfer."
can_unwrench = TRUE
@@ -12,6 +12,8 @@
var/obj/machinery/atmospherics/components/unary/heat_exchanger/partner = null
var/update_cycle
pipe_state = "heunary"
/obj/machinery/atmospherics/components/unary/heat_exchanger/update_icon()
if(NODE1)
icon_state = "he_intact"
@@ -1,6 +1,6 @@
/obj/machinery/atmospherics/components/unary/outlet_injector
name = "air injector"
desc = "Has a valve and pump attached to it"
desc = "Has a valve and pump attached to it."
icon_state = "inje_map"
use_power = IDLE_POWER_USE
can_unwrench = TRUE
@@ -18,6 +18,8 @@
level = 1
layer = GAS_SCRUBBER_LAYER
pipe_state = "injector"
/obj/machinery/atmospherics/components/unary/outlet_injector/Destroy()
SSradio.remove_object(src,frequency)
return ..()
@@ -188,4 +190,3 @@
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
@@ -3,7 +3,7 @@
icon_state = "o2gen_map"
name = "oxygen generator"
desc = "Generates oxygen"
desc = "Generates oxygen."
dir = SOUTH
initialize_directions = SOUTH
@@ -49,8 +49,8 @@
var/added_oxygen = oxygen_content - total_moles
air_contents.temperature = (current_heat_capacity*air_contents.temperature + 20*added_oxygen*T0C)/(current_heat_capacity+20*added_oxygen)
ASSERT_GAS("o2", air_contents)
air_contents.gases["o2"][MOLES] += added_oxygen
ASSERT_GAS(/datum/gas/oxygen, air_contents)
air_contents.gases[/datum/gas/oxygen][MOLES] += added_oxygen
update_parents()
@@ -8,6 +8,8 @@
use_power = NO_POWER_USE
level = 0
layer = GAS_FILTER_LAYER
pipe_flags = PIPING_ONE_PER_TURF
pipe_state = "connector"
/obj/machinery/atmospherics/components/unary/portables_connector/New()
..()
@@ -9,6 +9,7 @@
density = TRUE
var/gas_type = 0
layer = ABOVE_WINDOW_LAYER
pipe_flags = PIPING_ONE_PER_TURF
/obj/machinery/atmospherics/components/unary/tank/New()
..()
@@ -21,23 +22,20 @@
name = "[name] ([air_contents.gases[gas_type][GAS_META][META_GAS_NAME]])"
/obj/machinery/atmospherics/components/unary/tank/carbon_dioxide
gas_type = "co2"
gas_type = /datum/gas/carbon_dioxide
/obj/machinery/atmospherics/components/unary/tank/toxins
icon_state = "orange"
gas_type = "plasma"
gas_type = /datum/gas/plasma
/obj/machinery/atmospherics/components/unary/tank/oxygen_agent_b
icon_state = "orange_2"
gas_type = "agent_b"
/obj/machinery/atmospherics/components/unary/tank/oxygen
icon_state = "blue"
gas_type = "o2"
gas_type = /datum/gas/oxygen
/obj/machinery/atmospherics/components/unary/tank/nitrogen
icon_state = "red"
gas_type = "n2"
gas_type = /datum/gas/nitrogen
/obj/machinery/atmospherics/components/unary/tank/air
icon_state = "grey"
@@ -46,6 +44,6 @@
/obj/machinery/atmospherics/components/unary/tank/air/New()
..()
var/datum/gas_mixture/air_contents = AIR1
air_contents.assert_gases("o2", "n2")
air_contents.gases["o2"][MOLES] = AIR_CONTENTS * 0.2
air_contents.gases["n2"][MOLES] = AIR_CONTENTS * 0.8
air_contents.assert_gases(/datum/gas/oxygen, /datum/gas/nitrogen)
air_contents.gases[/datum/gas/oxygen][MOLES] = AIR_CONTENTS * 0.2
air_contents.gases[/datum/gas/nitrogen][MOLES] = AIR_CONTENTS * 0.8
@@ -11,6 +11,7 @@
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 80, acid = 30)
layer = OBJ_LAYER
circuit = /obj/item/circuitboard/machine/thermomachine
pipe_flags = PIPING_ONE_PER_TURF | PIPING_DEFAULT_LAYER_ONLY
var/on = FALSE
var/min_temperature = 0
@@ -3,6 +3,8 @@
dir = SOUTH
initialize_directions = SOUTH
device_type = UNARY
pipe_flags = PIPING_ONE_PER_TURF
construction_type = /obj/item/pipe/directional
/obj/machinery/atmospherics/components/unary/SetInitDirections()
initialize_directions = dir
@@ -31,6 +31,8 @@
var/radio_filter_out
var/radio_filter_in
pipe_state = "uvent"
/obj/machinery/atmospherics/components/unary/vent_pump/on
on = TRUE
icon_state = "vent_map_on"
@@ -235,6 +237,9 @@
if("reset_external_pressure" in signal.data)
external_pressure_bound = ONE_ATMOSPHERE
if("reset_internal_pressure" in signal.data)
internal_pressure_bound = 0
if("adjust_internal_pressure" in signal.data)
internal_pressure_bound = Clamp(internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]),0,ONE_ATMOSPHERE*50)
@@ -20,8 +20,7 @@
var/scrub_CO2 = TRUE
var/scrub_Toxins = FALSE
var/scrub_N2O = FALSE
var/scrub_BZ = FALSE
var/scrub_Freon = FALSE
var/scrub_Rare = FALSE
var/scrub_WaterVapor = FALSE
@@ -34,6 +33,8 @@
var/radio_filter_out
var/radio_filter_in
pipe_state = "scrubber"
/obj/machinery/atmospherics/components/unary/vent_scrubber/New()
..()
if(!id_tag)
@@ -70,9 +71,7 @@
amount += idle_power_usage
if(scrub_N2O)
amount += idle_power_usage
if(scrub_BZ)
amount += idle_power_usage
if(scrub_Freon)
if(scrub_Rare)
amount += idle_power_usage
if(scrub_WaterVapor)
amount += idle_power_usage
@@ -125,8 +124,7 @@
"filter_co2" = scrub_CO2,
"filter_toxins" = scrub_Toxins,
"filter_n2o" = scrub_N2O,
"filter_bz" = scrub_BZ,
"filter_freon" = scrub_Freon,
"filter_rare" =scrub_Rare,
"filter_water_vapor" = scrub_WaterVapor,
"sigtype" = "status"
)
@@ -171,10 +169,13 @@
var/datum/gas_mixture/air_contents = AIR1
var/list/env_gases = environment.gases
if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE)
return FALSE
if(scrubbing & SCRUBBING)
var/should_we_scrub = FALSE
for(var/id in env_gases)
if(id == "n2" || id == "o2")
if(id == /datum/gas/nitrogen || id == /datum/gas/oxygen)
continue
if(env_gases[id][MOLES])
should_we_scrub = TRUE
@@ -194,40 +195,55 @@
var/list/filtered_gases = filtered_out.gases
filtered_out.temperature = removed.temperature
if(scrub_Toxins && removed_gases["plasma"])
ADD_GAS("plasma", filtered_out.gases)
filtered_gases["plasma"][MOLES] = removed_gases["plasma"][MOLES]
removed.gases["plasma"][MOLES] = 0
if(scrub_Toxins && removed_gases[/datum/gas/plasma])
ADD_GAS(/datum/gas/plasma, filtered_gases)
filtered_gases[/datum/gas/plasma][MOLES] = removed_gases[/datum/gas/plasma][MOLES]
removed_gases[/datum/gas/plasma][MOLES] = 0
if(scrub_CO2 && removed_gases["co2"])
ADD_GAS("co2", filtered_out.gases)
filtered_gases["co2"][MOLES] = removed_gases["co2"][MOLES]
removed_gases["co2"][MOLES] = 0
if(scrub_CO2 && removed_gases[/datum/gas/carbon_dioxide])
ADD_GAS(/datum/gas/carbon_dioxide, filtered_gases)
filtered_gases[/datum/gas/carbon_dioxide][MOLES] = removed_gases[/datum/gas/carbon_dioxide][MOLES]
removed_gases[/datum/gas/carbon_dioxide][MOLES] = 0
if(removed_gases["agent_b"])
ADD_GAS("agent_b", filtered_out.gases)
filtered_gases["agent_b"][MOLES] = removed_gases["agent_b"][MOLES]
removed_gases["agent_b"][MOLES] = 0
if(scrub_N2O && removed_gases[/datum/gas/nitrous_oxide])
ADD_GAS(/datum/gas/nitrous_oxide, filtered_gases)
filtered_gases[/datum/gas/nitrous_oxide][MOLES] = removed_gases[/datum/gas/nitrous_oxide][MOLES]
removed_gases[/datum/gas/nitrous_oxide][MOLES] = 0
if(scrub_N2O && removed_gases["n2o"])
ADD_GAS("n2o", filtered_out.gases)
filtered_gases["n2o"][MOLES] = removed_gases["n2o"][MOLES]
removed_gases["n2o"][MOLES] = 0
if(scrub_Rare && removed_gases[/datum/gas/bz])
ADD_GAS(/datum/gas/bz, filtered_gases)
filtered_gases[/datum/gas/bz][MOLES] = removed_gases[/datum/gas/bz][MOLES]
removed_gases[/datum/gas/bz][MOLES] = 0
if(scrub_BZ && removed_gases["bz"])
ADD_GAS("bz", filtered_out.gases)
filtered_gases["bz"][MOLES] = removed_gases["bz"][MOLES]
removed_gases["bz"][MOLES] = 0
if(scrub_Rare && removed_gases[/datum/gas/hypernoblium])
ADD_GAS(/datum/gas/hypernoblium, filtered_gases)
filtered_gases[/datum/gas/hypernoblium][MOLES] = removed_gases[/datum/gas/hypernoblium][MOLES]
removed_gases[/datum/gas/hypernoblium][MOLES] = 0
if(scrub_Freon && removed_gases["freon"])
ADD_GAS("freon", filtered_out.gases)
filtered_gases["freon"][MOLES] = removed_gases["freon"][MOLES]
removed_gases["freon"][MOLES] = 0
if(scrub_Rare && removed_gases[/datum/gas/stimulum])
ADD_GAS(/datum/gas/stimulum, filtered_gases)
filtered_gases[/datum/gas/stimulum][MOLES] = removed_gases[/datum/gas/stimulum][MOLES]
removed_gases[/datum/gas/stimulum][MOLES] = 0
if(scrub_WaterVapor && removed_gases["water_vapor"])
ADD_GAS("water_vapor", filtered_out.gases)
filtered_gases["water_vapor"][MOLES] = removed_gases["water_vapor"][MOLES]
removed_gases["water_vapor"][MOLES] = 0
if(scrub_Rare && removed_gases[/datum/gas/pluoxium])
ADD_GAS(/datum/gas/pluoxium, filtered_gases)
filtered_gases[/datum/gas/pluoxium][MOLES] = removed_gases[/datum/gas/pluoxium][MOLES]
removed_gases[/datum/gas/pluoxium][MOLES] = 0
if(scrub_Rare && removed_gases[/datum/gas/nitryl])
ADD_GAS(/datum/gas/nitryl, filtered_gases)
filtered_gases[/datum/gas/nitryl][MOLES] = removed_gases[/datum/gas/nitryl][MOLES]
removed_gases[/datum/gas/nitryl][MOLES] = 0
if(scrub_Rare && removed_gases[/datum/gas/tritium])
ADD_GAS(/datum/gas/tritium, filtered_gases)
filtered_gases[/datum/gas/tritium][MOLES] = removed_gases[/datum/gas/tritium][MOLES]
removed_gases[/datum/gas/tritium][MOLES] = 0
if(scrub_WaterVapor && removed_gases[/datum/gas/water_vapor])
ADD_GAS(/datum/gas/water_vapor, filtered_gases)
filtered_gases[/datum/gas/water_vapor][MOLES] = removed_gases[/datum/gas/water_vapor][MOLES]
removed_gases[/datum/gas/water_vapor][MOLES] = 0
removed.garbage_collect()
@@ -238,8 +254,6 @@
tile.air_update_turf()
else //Just siphoning all air
if(air_contents.return_pressure()>=50*ONE_ATMOSPHERE)
return FALSE
var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume)
@@ -302,15 +316,10 @@
if("toggle_n2o_scrub" in signal.data)
scrub_N2O = !scrub_N2O
if("bz_scrub" in signal.data)
scrub_BZ = text2num(signal.data["bz_scrub"])
if("toggle_bz_scrub" in signal.data)
scrub_BZ = !scrub_BZ
if("freon_scrub" in signal.data)
scrub_Freon = text2num(signal.data["freon_scrub"])
if("toggle_freon_scrub" in signal.data)
scrub_Freon = !scrub_Freon
if("rare_scrub" in signal.data)
scrub_Rare = text2num(signal.data["rare_scrub"])
if("toggle_rare_scrub" in signal.data)
scrub_Rare = !scrub_Rare
if("water_vapor_scrub" in signal.data)
scrub_WaterVapor = text2num(signal.data["water_vapor_scrub"])
@@ -13,19 +13,33 @@
active_power_usage = 4
max_integrity = 150
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 40, acid = 0)
/obj/machinery/meter/Initialize(mapload)
. = ..()
SSair.atmos_machinery += src
if (!target)
target = locate(/obj/machinery/atmospherics/pipe) in loc
var/target_layer = PIPING_LAYER_DEFAULT
/obj/machinery/meter/Destroy()
SSair.atmos_machinery -= src
src.target = null
target = null
return ..()
/obj/machinery/meter/Initialize(mapload, new_piping_layer)
if(!isnull(new_piping_layer))
target_layer = new_piping_layer
SSair.atmos_machinery += src
if(!target)
reattach_to_layer()
return ..()
/obj/machinery/meter/proc/reattach_to_layer()
for(var/obj/machinery/atmospherics/pipe/pipe in loc)
if(pipe.piping_layer == target_layer)
target = pipe
setAttachLayer(pipe.piping_layer)
break
/obj/machinery/meter/proc/setAttachLayer(var/new_layer)
target_layer = new_layer
pixel_x = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X
pixel_y = (new_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
/obj/machinery/meter/process_atmos()
if(!target)
icon_state = "meterX"
@@ -75,7 +89,7 @@
radio_connection.post_signal(src, signal)
/obj/machinery/meter/proc/status()
if (src.target)
if (target)
var/datum/gas_mixture/environment = target.return_air()
if(environment)
. = "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)] K ([round(environment.temperature-T0C,0.01)]&deg;C)."
@@ -91,23 +105,23 @@
/obj/machinery/meter/attackby(obj/item/W, mob/user, params)
if (istype(W, /obj/item/wrench))
playsound(src.loc, W.usesound, 50, 1)
playsound(src, W.usesound, 50, 1)
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
if (do_after(user, 40*W.toolspeed, target = src))
user.visible_message( \
"[user] unfastens \the [src].", \
"<span class='notice'>You unfasten \the [src].</span>", \
"<span class='italics'>You hear ratchet.</span>")
new /obj/item/pipe_meter(src.loc)
new /obj/item/pipe_meter(loc)
qdel(src)
else
return ..()
/obj/machinery/meter/attack_ai(mob/user)
return src.attack_hand(user)
return attack_hand(user)
/obj/machinery/meter/attack_paw(mob/user)
return src.attack_hand(user)
return attack_hand(user)
/obj/machinery/meter/attack_hand(mob/user)
@@ -129,4 +143,4 @@
/obj/machinery/meter/turf/Initialize()
. = ..()
src.target = loc
target = loc
@@ -146,49 +146,34 @@
/obj/machinery/atmospherics/miner/n2o
name = "\improper N2O Gas Miner"
overlay_color = "#FFCCCC"
spawn_id = "n2o"
spawn_id = /datum/gas/nitrous_oxide
/obj/machinery/atmospherics/miner/nitrogen
name = "\improper N2 Gas Miner"
overlay_color = "#CCFFCC"
spawn_id = "n2"
spawn_id = /datum/gas/nitrogen
/obj/machinery/atmospherics/miner/oxygen
name = "\improper O2 Gas Miner"
overlay_color = "#007FFF"
spawn_id = "o2"
spawn_id = /datum/gas/oxygen
/obj/machinery/atmospherics/miner/toxins
name = "\improper Plasma Gas Miner"
overlay_color = "#FF0000"
spawn_id = "plasma"
spawn_id = /datum/gas/plasma
/obj/machinery/atmospherics/miner/carbon_dioxide
name = "\improper CO2 Gas Miner"
overlay_color = "#CDCDCD"
spawn_id = "co2"
spawn_id = /datum/gas/carbon_dioxide
/obj/machinery/atmospherics/miner/bz
name = "\improper BZ Gas Miner"
overlay_color = "#FAFF00"
spawn_id = "bz"
/obj/machinery/atmospherics/miner/freon
name = "\improper Freon Gas Miner"
overlay_color = "#00FFE5"
spawn_id = "freon"
/obj/machinery/atmospherics/miner/volatile_fuel
name = "\improper Volatile Fuel Gas Miner"
overlay_color = "#564040"
spawn_id = "v_fuel"
/obj/machinery/atmospherics/miner/agent_b
name = "\improper Agent B Gas Miner"
overlay_color = "#E81E24"
spawn_id = "agent_b"
spawn_id = /datum/gas/bz
/obj/machinery/atmospherics/miner/water_vapor
name = "\improper Water Vapor Gas Miner"
overlay_color = "#99928E"
spawn_id = "water_vapor"
spawn_id = /datum/gas/water_vapor
@@ -1,47 +0,0 @@
GLOBAL_LIST_EMPTY(bluespace_pipes)
/obj/machinery/atmospherics/pipe/bluespace
name = "bluespace pipe"
desc = "Transmits gas across large distances of space. Developed using bluespace technology."
icon = 'icons/obj/atmospherics/pipes/bluespace.dmi'
icon_state = "map"
dir = SOUTH
initialize_directions = SOUTH
device_type = UNARY
can_buckle = FALSE
/obj/machinery/atmospherics/pipe/bluespace/New()
icon_state = "pipe"
GLOB.bluespace_pipes += src
..()
/obj/machinery/atmospherics/pipe/bluespace/Destroy()
GLOB.bluespace_pipes -= src
for(var/p in GLOB.bluespace_pipes)
var/obj/machinery/atmospherics/pipe/bluespace/P = p
QDEL_NULL(P.parent)
P.build_network()
return ..()
/obj/machinery/atmospherics/pipe/bluespace/SetInitDirections()
initialize_directions = dir
/obj/machinery/atmospherics/pipe/bluespace/pipeline_expansion()
return ..() + GLOB.bluespace_pipes - src
/obj/machinery/atmospherics/components/pipe/bluespace/hide()
update_icon()
/obj/machinery/atmospherics/pipe/bluespace/update_icon(showpipe)
underlays.Cut()
var/turf/T = loc
if(level != 2 && T.intact)
return //no need to update the pipes if they aren't showing
var/connected = 0 //Direction bitset
for(DEVICE_TYPE_LOOP) //adds intact pieces
if(NODE_I)
connected |= icon_addintact(NODE_I)
icon_addbroken(connected) //adds broken pieces
/obj/machinery/atmospherics/pipe/bluespace/paint()
return FALSE
@@ -31,7 +31,7 @@
var/turf/T = loc
if(istype(T))
if(istype(T, /turf/open/lava))
if(islava(T))
environment_temperature = 5000
else if(T.blocks_air)
environment_temperature = T.temperature
@@ -3,7 +3,7 @@
icon_state = "intact"
name = "junction"
desc = "A one meter junction that connects regular and heat-exchanging pipe"
desc = "A one meter junction that connects regular and heat-exchanging pipe."
minimum_temperature_difference = 300
thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
@@ -13,6 +13,9 @@
initialize_directions_he = SOUTH
device_type = BINARY
construction_type = /obj/item/pipe/directional
pipe_state = "junction"
/obj/machinery/atmospherics/pipe/heat_exchanging/junction/SetInitDirections()
switch(dir)
@@ -43,4 +46,4 @@
return 0
init_dir = H.initialize_directions_he
if(init_dir & get_dir(target,src))
return 1
return 1
@@ -3,13 +3,16 @@
icon_state = "manifold"
name = "pipe manifold"
desc = "A manifold composed of regular pipes"
desc = "A manifold composed of regular pipes."
dir = SOUTH
initialize_directions_he = EAST|NORTH|WEST
device_type = TRINARY
construction_type = /obj/item/pipe/trinary
pipe_state = "he_manifold"
/obj/machinery/atmospherics/pipe/heat_exchanging/manifold/SetInitDirections()
switch(dir)
if(NORTH)
@@ -38,12 +41,15 @@
icon_state = "manifold4w"
name = "4-way pipe manifold"
desc = "A manifold composed of heat-exchanging pipes"
desc = "A manifold composed of heat-exchanging pipes."
initialize_directions_he = NORTH|SOUTH|EAST|WEST
device_type = QUATERNARY
construction_type = /obj/item/pipe/quaternary
pipe_state = "he_manifold4w"
/obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w/SetInitDirections()
initialize_directions_he = initial(initialize_directions_he)
@@ -57,4 +63,4 @@
//Add non-broken pieces
for(DEVICE_TYPE_LOOP)
if(NODE_I)
add_overlay(getpipeimage('icons/obj/atmospherics/pipes/heat.dmi', "manifold_intact[invis]", get_dir(src, NODE_I)))
add_overlay(getpipeimage('icons/obj/atmospherics/pipes/heat.dmi', "manifold_intact[invis]", get_dir(src, NODE_I)))
@@ -2,13 +2,16 @@
icon_state = "intact"
name = "pipe"
desc = "A one meter section of heat-exchanging pipe"
desc = "A one meter section of heat-exchanging pipe."
dir = SOUTH
initialize_directions_he = SOUTH|NORTH
device_type = BINARY
construction_type = /obj/item/pipe/binary/bendable
pipe_state = "he"
/obj/machinery/atmospherics/pipe/heat_exchanging/simple/SetInitDirections()
if(dir in GLOB.diagonals)
initialize_directions_he = dir
@@ -30,4 +33,4 @@
/obj/machinery/atmospherics/pipe/heat_exchanging/simple/update_icon()
normalize_dir()
..()
..()
@@ -0,0 +1,127 @@
/obj/machinery/atmospherics/pipe/layer_manifold
name = "pipe-layer manifold"
icon = 'icons/obj/atmospherics/pipes/manifold.dmi'
icon_state = "manifoldlayer"
desc = "A special pipe to bridge pipe layers with."
dir = SOUTH
initialize_directions = NORTH|SOUTH
pipe_flags = PIPING_ALL_LAYER | PIPING_DEFAULT_LAYER_ONLY | PIPING_CARDINAL_AUTONORMALIZE
piping_layer = PIPING_LAYER_DEFAULT
device_type = 0
volume = 260
var/list/front_nodes
var/list/back_nodes
construction_type = /obj/item/pipe/binary
pipe_state = "layer_manifold"
/obj/machinery/atmospherics/pipe/layer_manifold/Initialize()
front_nodes = list()
back_nodes = list()
return ..()
/obj/machinery/atmospherics/pipe/layer_manifold/Destroy()
nullifyAllNodes()
return ..()
/obj/machinery/atmospherics/pipe/layer_manifold/proc/nullifyAllNodes()
var/list/obj/machinery/atmospherics/needs_nullifying = get_all_connected_nodes()
front_nodes = null
back_nodes = null
nodes = list()
for(var/obj/machinery/atmospherics/A in needs_nullifying)
A.disconnect(src)
A.build_network()
/obj/machinery/atmospherics/pipe/layer_manifold/proc/get_all_connected_nodes()
return front_nodes + back_nodes + nodes
/obj/machinery/atmospherics/pipe/layer_manifold/update_icon() //HEAVILY WIP FOR UPDATE ICONS!!
layer = (initial(layer) + (PIPING_LAYER_MAX * PIPING_LAYER_LCHANGE)) //This is above everything else.
var/invis = invisibility ? "-f" : ""
icon_state = "[initial(icon_state)][invis]"
cut_overlays()
for(var/obj/machinery/atmospherics/A in front_nodes)
add_attached_image(A)
for(var/obj/machinery/atmospherics/A in back_nodes)
add_attached_image(A)
/obj/machinery/atmospherics/pipe/layer_manifold/proc/add_attached_image(obj/machinery/atmospherics/A)
var/invis = A.invisibility ? "-f" : ""
if(istype(A, /obj/machinery/atmospherics/pipe/layer_manifold))
for(var/i = PIPING_LAYER_MIN, i <= PIPING_LAYER_MAX, i++)
var/image/I = getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full_layer_long[invis]", get_dir(src, A), A.pipe_color)
I.pixel_x = (i - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X
I.pixel_y = (i - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y
I.layer = layer - 0.01
add_overlay(I)
else
var/image/I = getpipeimage('icons/obj/atmospherics/pipes/manifold.dmi', "manifold_full_layer_long[invis]", get_dir(src, A), A.pipe_color)
I.pixel_x = A.pixel_x
I.pixel_y = A.pixel_y
I.layer = layer - 0.01
add_overlay(I)
/obj/machinery/atmospherics/pipe/layer_manifold/SetInitDirections()
switch(dir)
if(NORTH || SOUTH)
initialize_directions = NORTH|SOUTH
if(EAST || WEST)
initialize_directions = EAST|WEST
/obj/machinery/atmospherics/pipe/layer_manifold/isConnectable(obj/machinery/atmospherics/target, given_layer)
if(!given_layer)
return TRUE
. = ..()
/obj/machinery/atmospherics/pipe/layer_manifold/proc/findAllConnections()
front_nodes = list()
back_nodes = list()
var/list/new_nodes = list()
for(var/iter in PIPING_LAYER_MIN to PIPING_LAYER_MAX)
var/obj/machinery/atmospherics/foundfront = findConnecting(dir, iter)
var/obj/machinery/atmospherics/foundback = findConnecting(turn(dir, 180), iter)
front_nodes += foundfront
back_nodes += foundback
if(foundfront && !QDELETED(foundfront))
new_nodes += foundfront
if(foundback && !QDELETED(foundback))
new_nodes += foundback
update_icon()
return new_nodes
/obj/machinery/atmospherics/pipe/layer_manifold/atmosinit()
normalize_cardinal_directions()
findAllConnections()
var/turf/T = loc // hide if turf is not intact
hide(T.intact)
/obj/machinery/atmospherics/pipe/layer_manifold/setPipingLayer()
piping_layer = PIPING_LAYER_DEFAULT
/obj/machinery/atmospherics/pipe/layer_manifold/pipeline_expansion()
return get_all_connected_nodes()
/obj/machinery/atmospherics/pipe/layer_manifold/disconnect(obj/machinery/atmospherics/reference)
if(istype(reference, /obj/machinery/atmospherics/pipe))
var/obj/machinery/atmospherics/pipe/P = reference
P.destroy_network()
while(reference in get_all_connected_nodes())
if(reference in nodes)
var/I = nodes.Find(reference)
NODE_I = null
if(reference in front_nodes)
var/I = front_nodes.Find(reference)
front_nodes[I] = null
if(reference in back_nodes)
var/I = back_nodes.Find(reference)
back_nodes[I] = null
update_icon()
/obj/machinery/atmospherics/pipe/layer_manifold/relaymove(mob/living/user, dir)
if(initialize_directions & dir)
return ..()
if((NORTH|EAST) & dir)
user.ventcrawl_layer = Clamp(user.ventcrawl_layer + 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
if((SOUTH|WEST) & dir)
user.ventcrawl_layer = Clamp(user.ventcrawl_layer - 1, PIPING_LAYER_MIN, PIPING_LAYER_MAX)
to_chat(user, "You align yourself with the [user.ventcrawl_layer]\th output.")
@@ -6,13 +6,16 @@
icon_state = "manifold"
name = "pipe manifold"
desc = "A manifold composed of regular pipes"
desc = "A manifold composed of regular pipes."
dir = SOUTH
initialize_directions = EAST|NORTH|WEST
device_type = TRINARY
construction_type = /obj/item/pipe/trinary
pipe_state = "manifold"
/obj/machinery/atmospherics/pipe/manifold/SetInitDirections()
switch(dir)
if(NORTH)
@@ -125,7 +128,7 @@
/obj/machinery/atmospherics/pipe/manifold/orange/hidden
level = PIPE_HIDDEN_LEVEL
/obj/machinery/atmospherics/pipe/manifold/purple
pipe_color=rgb(128,0,182)
color=rgb(128,0,182)
@@ -168,4 +171,4 @@
layer = GAS_PIPE_VISIBLE_LAYER
/obj/machinery/atmospherics/pipe/manifold/brown/hidden
level = PIPE_HIDDEN_LEVEL
level = PIPE_HIDDEN_LEVEL
@@ -6,12 +6,15 @@
icon_state = "manifold4w"
name = "4-way pipe manifold"
desc = "A manifold composed of regular pipes"
desc = "A manifold composed of regular pipes."
initialize_directions = NORTH|SOUTH|EAST|WEST
device_type = QUATERNARY
construction_type = /obj/item/pipe/quaternary
pipe_state = "manifold4w"
/obj/machinery/atmospherics/pipe/manifold4w/SetInitDirections()
initialize_directions = initial(initialize_directions)
@@ -160,4 +163,4 @@
layer = GAS_PIPE_VISIBLE_LAYER
/obj/machinery/atmospherics/pipe/manifold4w/brown/hidden
level = PIPE_HIDDEN_LEVEL
level = PIPE_HIDDEN_LEVEL
@@ -24,6 +24,14 @@
if(oldN)
oldN.build_network()
/obj/machinery/atmospherics/pipe/destroy_network()
QDEL_NULL(parent)
/obj/machinery/atmospherics/pipe/build_network()
if(QDELETED(parent))
parent = new
parent.build_pipeline(src)
/obj/machinery/atmospherics/pipe/update_icon() //overridden by manifolds
if(NODE1&&NODE2)
icon_state = "intact[invisibility ? "-f" : "" ]"
@@ -51,14 +59,13 @@
/obj/machinery/atmospherics/pipe/return_air()
return parent.air
/obj/machinery/atmospherics/pipe/build_network()
if(!parent)
parent = new /datum/pipeline()
parent.build_pipeline(src)
/obj/machinery/atmospherics/pipe/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/device/analyzer))
atmosanalyzer_scan(parent.air, user)
if(istype(W, /obj/item/pipe_meter))
var/obj/item/pipe_meter/meter = W
user.dropItemToGround(meter)
meter.setAttachLayer(piping_layer)
else
return ..()
@@ -81,9 +88,7 @@
qdel(meter)
. = ..()
if(parent && !QDELETED(parent))
qdel(parent)
parent = null
QDEL_NULL(parent)
/obj/machinery/atmospherics/pipe/proc/update_node_icon()
for(DEVICE_TYPE_LOOP)
@@ -12,10 +12,15 @@ The regular pipe you see everywhere, including bent ones.
dir = SOUTH
initialize_directions = SOUTH|NORTH
pipe_flags = PIPING_CARDINAL_AUTONORMALIZE
device_type = BINARY
construction_type = /obj/item/pipe/binary/bendable
pipe_state = "simple"
/obj/machinery/atmospherics/pipe/simple/SetInitDirections()
normalize_cardinal_directions()
if(dir in GLOB.diagonals)
initialize_directions = dir
switch(dir)
@@ -24,20 +29,6 @@ The regular pipe you see everywhere, including bent ones.
if(EAST,WEST)
initialize_directions = EAST|WEST
/obj/machinery/atmospherics/pipe/simple/atmosinit()
normalize_dir()
..()
/obj/machinery/atmospherics/pipe/simple/proc/normalize_dir()
if(dir==SOUTH)
setDir(NORTH)
else if(dir==WEST)
setDir(EAST)
/obj/machinery/atmospherics/pipe/simple/update_icon()
normalize_dir()
..()
//Colored pipes, use these for mapping
/obj/machinery/atmospherics/pipe/simple/general
@@ -170,4 +161,4 @@ The regular pipe you see everywhere, including bent ones.
layer = GAS_PIPE_VISIBLE_LAYER
/obj/machinery/atmospherics/pipe/simple/brown/hidden
level = PIPE_HIDDEN_LEVEL
level = PIPE_HIDDEN_LEVEL
@@ -12,7 +12,7 @@
volume = 1000
var/filled = 0.5
var/gas_type = ""
var/gas_type
var/release_pressure = ONE_ATMOSPHERE
var/can_max_release_pressure = (ONE_ATMOSPHERE * 10)
var/can_min_release_pressure = (ONE_ATMOSPHERE / 10)
@@ -41,10 +41,14 @@
"co2" = /obj/machinery/portable_atmospherics/canister/carbon_dioxide,
"plasma" = /obj/machinery/portable_atmospherics/canister/toxins,
"n2o" = /obj/machinery/portable_atmospherics/canister/nitrous_oxide,
"no2" = /obj/machinery/portable_atmospherics/canister/nitryl,
"bz" = /obj/machinery/portable_atmospherics/canister/bz,
"air" = /obj/machinery/portable_atmospherics/canister/air,
"freon" = /obj/machinery/portable_atmospherics/canister/freon,
"water vapor" = /obj/machinery/portable_atmospherics/canister/water_vapor,
"tritium" = /obj/machinery/portable_atmospherics/canister/tritium,
"hyper-noblium" = /obj/machinery/portable_atmospherics/canister/nob,
"stimulum" = /obj/machinery/portable_atmospherics/canister/stimulum,
"pluoxium" = /obj/machinery/portable_atmospherics/canister/pluoxium,
"caution" = /obj/machinery/portable_atmospherics/canister,
)
@@ -59,60 +63,78 @@
name = "n2 canister"
desc = "Nitrogen gas. Reportedly useful for something."
icon_state = "red"
gas_type = "n2"
gas_type = /datum/gas/nitrogen
/obj/machinery/portable_atmospherics/canister/oxygen
name = "o2 canister"
desc = "Oxygen. Necessary for human life."
icon_state = "blue"
gas_type = "o2"
gas_type = /datum/gas/oxygen
/obj/machinery/portable_atmospherics/canister/carbon_dioxide
name = "co2 canister"
desc = "Carbon dioxide. What the fuck is carbon dioxide?"
icon_state = "black"
gas_type = "co2"
gas_type = /datum/gas/carbon_dioxide
/obj/machinery/portable_atmospherics/canister/toxins
name = "plasma canister"
desc = "Plasma gas. The reason YOU are here. Highly toxic."
icon_state = "orange"
gas_type = "plasma"
/obj/machinery/portable_atmospherics/canister/agent_b
name = "agent b canister"
desc = "Oxygen Agent B. You're not quite sure what it does."
gas_type = "agent_b"
gas_type = /datum/gas/plasma
/obj/machinery/portable_atmospherics/canister/bz
name = "BZ canister"
desc = "BZ, a powerful hallucinogenic nerve agent."
icon_state = "purple"
gas_type = "bz"
gas_type = /datum/gas/bz
/obj/machinery/portable_atmospherics/canister/nitrous_oxide
name = "n2o canister"
desc = "Nitrous oxide gas. Known to cause drowsiness."
icon_state = "redws"
gas_type = "n2o"
gas_type = /datum/gas/nitrous_oxide
/obj/machinery/portable_atmospherics/canister/air
name = "air canister"
desc = "Pre-mixed air."
icon_state = "grey"
/obj/machinery/portable_atmospherics/canister/freon
name = "freon canister"
desc = "Freon. Great for the atmosphere!"
/obj/machinery/portable_atmospherics/canister/tritium
name = "tritium canister"
desc = "Tritium. Inhalation might cause irradiation."
icon_state = "green"
gas_type = /datum/gas/tritium
/obj/machinery/portable_atmospherics/canister/nob
name = "hyper-noblium canister"
desc = "Hyper-Noblium. More noble than all other gases."
icon_state = "freon"
gas_type = "freon"
starter_temp = 120
gas_type = /datum/gas/hypernoblium
/obj/machinery/portable_atmospherics/canister/nitryl
name = "nitryl canister"
desc = "Nitryl gas. Feels great 'til the acid eats your lungs."
icon_state = "brown"
gas_type = /datum/gas/nitryl
/obj/machinery/portable_atmospherics/canister/stimulum
name = "stimulum canister"
desc = "Stimulum. High energy gas, high energy people."
icon_state = "darkpurple"
gas_type = /datum/gas/stimulum
/obj/machinery/portable_atmospherics/canister/pluoxium
name = "pluoxium canister"
desc = "Pluoxium. Like oxygen, but more bang for your buck."
icon_state = "darkblue"
gas_type = /datum/gas/pluoxium
/obj/machinery/portable_atmospherics/canister/water_vapor
name = "water vapor canister"
desc = "Water Vapor. We get it, you vape."
icon_state = "water_vapor"
gas_type = "water_vapor"
gas_type = /datum/gas/water_vapor
filled = 1
/obj/machinery/portable_atmospherics/canister/proc/get_time_left()
@@ -148,7 +170,7 @@
name = "prototype canister"
desc = "A prototype canister for a prototype bike, what could go wrong?"
icon_state = "proto"
gas_type = "o2"
gas_type = /datum/gas/oxygen
filled = 1
release_pressure = ONE_ATMOSPHERE*2
@@ -181,9 +203,9 @@
if(starter_temp)
air_contents.temperature = starter_temp
/obj/machinery/portable_atmospherics/canister/air/create_gas()
air_contents.add_gases("o2","n2")
air_contents.gases["o2"][MOLES] = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.gases["n2"][MOLES] = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.add_gases(/datum/gas/oxygen, /datum/gas/nitrogen)
air_contents.gases[/datum/gas/oxygen][MOLES] = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.gases[/datum/gas/nitrogen][MOLES] = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
#define HOLDING 1
#define CONNECTED 2
@@ -273,7 +295,7 @@
return ..()
/obj/machinery/portable_atmospherics/canister/obj_break(damage_flag)
if((flags_1 & BROKEN) || (flags_1 & NODECONSTRUCT_1))
if((stat & BROKEN) || (flags_1 & NODECONSTRUCT_1))
return
canister_break()
@@ -402,7 +424,7 @@
var/gas = air_contents.gases[id]
if(!gas[GAS_META][META_GAS_DANGER])
continue
if(gas[MOLES] > (gas[GAS_META][META_GAS_MOLES_VISIBLE] || MOLES_PLASMA_VISIBLE)) //if moles_visible is undefined, default to plasma visibility
if(gas[MOLES] > (gas[GAS_META][META_GAS_MOLES_VISIBLE] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility
danger[gas[GAS_META][META_GAS_NAME]] = gas[MOLES] //ex. "plasma" = 20
if(danger.len)
@@ -45,11 +45,11 @@
/obj/machinery/portable_atmospherics/proc/connect(obj/machinery/atmospherics/components/unary/portables_connector/new_port)
//Make sure not already connected to something else
if(connected_port || !new_port || new_port.connected_device)
return 0
return FALSE
//Make sure are close enough for a valid connection
if(new_port.loc != get_turf(src))
return 0
return FALSE
//Perform the connection
connected_port = new_port
@@ -58,7 +58,9 @@
connected_port_parent.reconcile_air()
anchored = TRUE //Prevent movement
return 1
pixel_x = new_port.pixel_x
pixel_y = new_port.pixel_y
return TRUE
/obj/machinery/portable_atmospherics/Move()
. = ..()
@@ -67,11 +69,11 @@
/obj/machinery/portable_atmospherics/proc/disconnect()
if(!connected_port)
return 0
return FALSE
anchored = FALSE
connected_port.connected_device = null
connected_port = null
return 1
return TRUE
/obj/machinery/portable_atmospherics/portableConnectorReturnAir()
return air_contents
@@ -1,6 +1,6 @@
#define PUMP_OUT "out"
#define PUMP_IN "in"
#define PUMP_MAX_PRESSURE (ONE_ATMOSPHERE * 10)
#define PUMP_MAX_PRESSURE (ONE_ATMOSPHERE * 25)
#define PUMP_MIN_PRESSURE (ONE_ATMOSPHERE / 10)
#define PUMP_DEFAULT_PRESSURE (ONE_ATMOSPHERE)
@@ -99,8 +99,8 @@
if("power")
on = !on
if(on && !holding)
var/plasma = air_contents.gases["plasma"]
var/n2o = air_contents.gases["n2o"]
var/plasma = air_contents.gases[/datum/gas/plasma]
var/n2o = air_contents.gases[/datum/gas/nitrous_oxide]
if(n2o || plasma)
var/area/A = get_area(src)
message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [A][ADMIN_JMP(src)]")
@@ -138,4 +138,4 @@
holding.loc = get_turf(src)
holding = null
. = TRUE
update_icon()
update_icon()
@@ -7,7 +7,7 @@
var/volume_rate = 1000
volume = 1000
var/list/scrubbing = list("plasma", "co2", "n2o", "agent_b", "bz", "freon", "water_vapor")
var/list/scrubbing = list(/datum/gas/plasma, /datum/gas/carbon_dioxide, /datum/gas/nitrous_oxide, /datum/gas/bz, /datum/gas/nitryl, /datum/gas/tritium, /datum/gas/hypernoblium, /datum/gas/water_vapor)
/obj/machinery/portable_atmospherics/scrubber/Destroy()
var/turf/T = get_turf(src)
+18
View File
@@ -130,6 +130,10 @@
var/backpack_contents = -1
var/suit_store = -1
var/hair_style
var/facial_hair_style
var/skin_tone
/obj/effect/mob_spawn/human/Initialize()
if(ispath(outfit))
outfit = new outfit()
@@ -147,6 +151,20 @@
H.underwear = "Nude"
H.undershirt = "Nude"
H.socks = "Nude"
if(hair_style)
H.hair_style = hair_style
else
H.hair_style = random_hair_style(gender)
if(facial_hair_style)
H.facial_hair_style = facial_hair_style
else
H.facial_hair_style = random_facial_hair_style(gender)
if(skin_tone)
H.skin_tone = skin_tone
else
H.skin_tone = random_skin_tone()
H.update_hair()
H.update_body()
if(outfit)
var/static/list/slots = list("uniform", "r_hand", "l_hand", "suit", "shoes", "gloves", "ears", "glasses", "mask", "head", "belt", "r_pocket", "l_pocket", "back", "id", "neck", "backpack_contents", "suit_store")
for(var/slot in slots)
+13 -1
View File
@@ -170,7 +170,7 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
density = TRUE
icon_state = "offcenter"
use_power = NO_POWER_USE
var/obj/machinery/gateway/centeraway/stationgate = null
var/obj/machinery/gateway/centerstation/stationgate = null
can_link = TRUE
@@ -233,6 +233,18 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
M.client.move_delay = max(world.time + 5, M.client.move_delay)
/obj/machinery/gateway/centeraway/admin
desc = "A mysterious gateway built by unknown hands, this one seems more compact."
/obj/machinery/gateway/centeraway/admin/Initialize()
. = ..()
if(stationgate && !stationgate.awaygate)
stationgate.awaygate = src
/obj/machinery/gateway/centeraway/admin/detect()
return TRUE
/obj/item/paper/fluff/gateway
info = "Congratulations,<br><br>Your station has been selected to carry out the Gateway Project.<br><br>The equipment will be shipped to you at the start of the next quarter.<br> You are to prepare a secure location to house the equipment as outlined in the attached documents.<br><br>--Nanotrasen Blue Space Research"
name = "Confidential Correspondence, Pg 1"
@@ -1,4 +1,34 @@
//Academy Areas
/area/awaymission/academy
name = "Academy Asteroids"
icon_state = "away"
/area/awaymission/academy/headmaster
name = "Academy Fore Block"
icon_state = "away1"
/area/awaymission/academy/classrooms
name = "Academy Classroom Block"
icon_state = "away2"
/area/awaymission/academy/academyaft
name = "Academy Ship Aft Block"
icon_state = "away3"
/area/awaymission/academy/academygate
name = "Academy Gateway"
icon_state = "away4"
/area/awaymission/academy/academycellar
name = "Academy Cellar"
icon_state = "away4"
/area/awaymission/academy/academyengine
name = "Academy Engine"
icon_state = "away4"
//Academy Items
/obj/item/paper/fluff/awaymissions/academy/console_maint
@@ -54,7 +84,7 @@
/obj/structure/academy_wizard_spawner
name = "Academy Defensive System"
desc = "Made by Abjuration Inc"
desc = "Made by Abjuration, Inc."
icon = 'icons/obj/cult.dmi'
icon_state = "forge"
anchored = TRUE
@@ -108,27 +138,12 @@
/obj/structure/academy_wizard_spawner/proc/summon_wizard()
var/turf/T = src.loc
var/mob/living/carbon/human/wizbody = new(T)
wizbody.equipOutfit(/datum/outfit/wizard/academy)
var/obj/item/implant/exile/Implant = new/obj/item/implant/exile(wizbody)
Implant.implant(wizbody)
wizbody.faction |= "wizard"
wizbody.real_name = "Academy Teacher"
wizbody.name = "Academy Teacher"
var/datum/mind/wizmind = new /datum/mind()
wizmind.name = "Wizard Defender"
wizbody.fully_replace_character_name("Academy Teacher")
wizbody.mind_initialize()
var/datum/mind/wizmind = wizbody.mind
wizmind.special_role = "Academy Defender"
var/datum/objective/O = new("Protect Wizard Academy from the intruders")
wizmind.objectives += O
wizmind.transfer_to(wizbody)
SSticker.mode.wizards |= wizmind
wizmind.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt)
wizmind.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile)
wizmind.AddSpell(new /obj/effect/proc_holder/spell/aimed/fireball)
wizmind.add_antag_datum(/datum/antagonist/wizard/academy)
current_wizard = wizbody
give_control()
@@ -1,7 +1,24 @@
/*Cabin areas*/
/area/awaymission/snowforest
name = "Snow Forest"
icon_state = "away"
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
/area/awaymission/cabin
name = "Cabin"
icon_state = "away2"
requires_power = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
/area/awaymission/snowforest/lumbermill
name = "Lumbermill"
icon_state = "away3"
/obj/structure/firepit
name = "firepit"
desc = "warm and toasty"
desc = "Warm and toasty."
icon = 'icons/obj/fireplace.dmi'
icon_state = "firepit-active"
density = FALSE
@@ -1,3 +1,33 @@
//Areas
/area/awaymission/caves/BMP_asteroid
name = "\improper BMP Asteroid Level 1"
icon_state = "awaycontent1"
/area/awaymission/caves/BMP_asteroid/level_two
name = "\improper BMP Asteroid Level 2"
icon_state = "awaycontent2"
/area/awaymission/caves/BMP_asteroid/level_three
name = "\improper BMP Asteroid Level 3"
icon_state = "awaycontent3"
/area/awaymission/caves/BMP_asteroid/level_four
name = "\improper BMP Asteroid Level 4"
icon_state = "awaycontent4"
/area/awaymission/caves/research
name = "Research Outpost"
icon_state = "awaycontent5"
dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
/area/awaymission/caves/northblock //engineering, bridge (not really north but it doesnt really need its own APC)
/area/awaymission/caves/listeningpost
name = "Listening Post"
icon_state = "awaycontent6"
requires_power = FALSE
//caves papers
/obj/item/paper/crumpled/awaymissions/caves/unsafe_area
@@ -1,29 +1,63 @@
//centcomAway items
//centcomAway areas
/area/awaymission/centcomAway
name = "XCC-P5831"
icon_state = "away"
requires_power = FALSE
/area/awaymission/centcomAway/general
name = "XCC-P5831"
music = 'sound/ambience/ambigen3.ogg'
/area/awaymission/centcomAway/maint
name = "XCC-P5831 Maintenance"
icon_state = "away1"
music = 'sound/ambience/ambisin1.ogg'
/area/awaymission/centcomAway/thunderdome
name = "XCC-P5831 Thunderdome"
icon_state = "away2"
music = 'sound/ambience/ambisin2.ogg'
/area/awaymission/centcomAway/cafe
name = "XCC-P5831 Kitchen Arena"
icon_state = "away3"
music = 'sound/ambience/ambisin3.ogg'
/area/awaymission/centcomAway/courtroom
name = "XCC-P5831 Courtroom"
icon_state = "away4"
music = 'sound/ambience/ambisin4.ogg'
/area/awaymission/centcomAway/hangar
name = "XCC-P5831 Hangars"
icon_state = "away4"
music = 'sound/ambience/ambigen5.ogg'
//centcomAway items
/obj/item/paper/pamphlet/centcom/visitor_info
name = "Visitor Info Pamphlet"
info = "<b> XCC-P5831 Visitor Information </b><br>\
Greetings, visitor, to XCC-P5831! As you may know, this outpost was once \
used as Nanotrasen's CENTRAL COMMAND STATION, organizing and coordinating company \
projects across the vastness of space. <br>\
Since the completion of the much more efficient CC-A5831 on March 8, 2553, XCC-P5831 no longer \
acts as NT's base of operations but still plays a very important role its corporate affairs; \
serving as a supply and repair depot, as well as being host to its most important legal proceedings\
and the thrilling pay-per-view broadcasts of <i>PLASTEEL CHEF</i> and <i>THUNDERDOME LIVE</i>.<br> \
We hope you enjoy your stay!"
name = "Visitor Info Pamphlet"
info = "<b> XCC-P5831 Visitor Information </b><br>\
Greetings, visitor, to XCC-P5831! As you may know, this outpost was once \
used as Nanotrasen's CENTRAL COMMAND STATION, organizing and coordinating company \
projects across the vastness of space. <br>\
Since the completion of the much more efficient CC-A5831 on March 8, 2553, XCC-P5831 no longer \
acts as NT's base of operations but still plays a very important role its corporate affairs; \
serving as a supply and repair depot, as well as being host to its most important legal proceedings\
and the thrilling pay-per-view broadcasts of <i>PLASTEEL CHEF</i> and <i>THUNDERDOME LIVE</i>.<br> \
We hope you enjoy your stay!"
/obj/item/paper/fluff/awaymissions/centcom/gateway_memo
name = "Memo to XCC-P5831 QM"
info = "<b>From: XCC-P5831 Management Office</b><br>\
<b>To: Rolf Ingram, XCC-P5831 Quartermaster</b><br>\
Hey, Rolf, once you pack that gateway into the ferry hangar, <i>make absolutely sure</i> \
to deactivate it! As you may know, SS13 has recently got its network up and running, \
which means that until we get this gate shipped off to the next colonization staging \
area, they'll be able to hop straight in here if its hooked up on our end.<br>\
Obviously, that's something I'd very much rather avoid. Our forensics and medical \
teams never did figure out what happened that last time... and I can't wrap my head \
around it myself. Why would a shuttle full of evacuees all snap and beat each other \
to death the moment they reached safety?<br>\
- D. Cereza"
name = "Memo to XCC-P5831 QM"
info = "<b>From: XCC-P5831 Management Office</b><br>\
<b>To: Rolf Ingram, XCC-P5831 Quartermaster</b><br>\
Hey, Rolf, once you pack that gateway into the ferry hangar, <i>make absolutely sure</i> \
to deactivate it! As you may know, SS13 has recently got its network up and running, \
which means that until we get this gate shipped off to the next colonization staging \
area, they'll be able to hop straight in here if its hooked up on our end.<br>\
Obviously, that's something I'd very much rather avoid. Our forensics and medical \
teams never did figure out what happened that last time... and I can't wrap my head \
around it myself. Why would a shuttle full of evacuees all snap and beat each other \
to death the moment they reached safety?<br>\
- D. Cereza"
@@ -1,7 +1,23 @@
//Challenge Areas
/area/awaymission/challenge/start
name = "Where Am I?"
icon_state = "away"
/area/awaymission/challenge/main
name = "Danger Room"
icon_state = "away1"
requires_power = FALSE
/area/awaymission/challenge/end
name = "Administration"
icon_state = "away2"
requires_power = FALSE
/obj/machinery/power/emitter/energycannon
name = "Energy Cannon"
desc = "A heavy duty industrial laser"
desc = "A heavy duty industrial laser."
icon = 'icons/obj/singularity.dmi'
icon_state = "emitter"
anchored = TRUE
@@ -1,4 +1,43 @@
/////////// moonoutpost19 papers
// moonoutpost19
//Areas
/area/awaymission/moonoutpost19
name = "space"
icon_state = "awaycontent1"
/area/awaymission/moonoutpost19/arrivals
name = "MO19 Arrivals"
icon_state = "awaycontent2"
/area/awaymission/moonoutpost19/research
name = "MO19 Research"
icon_state = "awaycontent3"
/area/awaymission/moonoutpost19/syndicate
name = "Syndicate Outpost"
icon_state = "awaycontent4"
/area/awaymission/moonoutpost19/main
name = "Khonsu 19"
always_unpowered = TRUE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
poweralm = FALSE
ambientsounds = list('sound/ambience/ambimine.ogg')
icon_state = "awaycontent5"
/area/awaymission/moonoutpost19/hive
name = "The Hive"
always_unpowered = FALSE
has_gravity = FALSE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
poweralm = FALSE
icon_state = "awaycontent6"
//Papers
/obj/item/paper/crumpled/awaymissions/moonoutpost19/hastey_note
name = "Hastily Written Note"
@@ -1,3 +1,67 @@
//Research Base Areas//--
/area/awaymission/research
name = "Research Outpost"
icon_state = "away"
dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
/area/awaymission/research/interior
name = "Research Inside"
requires_power = TRUE
icon_state = "away2"
/area/awaymission/research/interior/cryo
name = "Research Cryostasis Room"
icon_state = "medbay"
/area/awaymission/research/interior/clonestorage
name = "Research Clone Storage"
icon_state = "cloning"
/area/awaymission/research/interior/genetics
name = "Research Genetics Research"
icon_state = "genetics"
/area/awaymission/research/interior/engineering
name = "Research Engineering"
icon_state = "engine"
/area/awaymission/research/interior/security
name = "Research Security"
icon_state = "security"
/area/awaymission/research/interior/secure
name = "Research Secure Vault"
/area/awaymission/research/interior/maint
name = "Research Maintenance"
icon_state = "maintcentral"
/area/awaymission/research/interior/dorm
name = "Research Dorms"
icon_state = "Sleep"
/area/awaymission/research/interior/escapepods
name = "Research Escape Wing"
icon_state = "exit"
/area/awaymission/research/interior/gateway
name = "Research Gateway"
icon_state = "start"
/area/awaymission/research/interior/bathroom
name = "Research Bathrooms"
icon_state = "restrooms"
/area/awaymission/research/interior/medbay
name = "Research Medbay"
icon_state = "medbay"
/area/awaymission/research/exterior
name = "Research Exterior"
icon_state = "unknown"
//research papers
/obj/item/paper/crumpled/awaymissions/research/sensitive_info
@@ -1,9 +1,46 @@
//Snow Valley Areas//--
/area/awaymission/snowdin
name = "Snowdin Tundra Plains"
icon_state = "awaycontent1"
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
/area/awaymission/snowdin/post
name = "Snowdin Outpost"
requires_power = TRUE
icon_state = "awaycontent2"
/area/awaymission/snowdin/igloo
name = "Snowdin Igloos"
icon_state = "awaycontent3"
/area/awaymission/snowdin/cave
name = "Snowdin Caves"
icon_state = "awaycontent4"
/area/awaymission/snowdin/base
name = "Snowdin Main Base"
icon_state = "awaycontent5"
requires_power = TRUE
/area/awaymission/snowdin/dungeon1
name = "Snowdin Depths"
icon_state = "awaycontent6"
/area/awaymission/snowdin/sekret
name = "Snowdin Operations"
icon_state = "awaycontent7"
requires_power = TRUE
/////////// papers
/obj/item/paper/crumpled/ruins/snowdin/snowdingatewaynotice
name = "scribbled note"
info = {"The gateway has been inactive for months, engineers think it's due to the recent drop in tempature fucking with the
circuitry or something. Without a constant supply of resources from central command, our stock is getting awfully low. Some of the security members have taken to
circuitry or something. Without a constant supply of resources from Central Command, our stock is getting awfully low. Some of the security members have taken to
using the sparse rifle ammo left to hunting some of the wildlife to try and keep our food supply from emptying. God forbid if the heating goes out, I don't want to
die as a fucking popsicle down here."}
@@ -28,9 +65,9 @@
The colder months are finally hitting, some of the machinery seems to be having trouble starting up sometimes. Central sent some portable heaters to help keep the airlocks from
freezing shut along with a couple storage crates with supplies. Nothing on the radio so far, what the hell do they even expect to hear down here, anyway?<br><br><b>September 15th</b>
<br>Another supply shipment through the gateway, they've sent some heavier sets of clothes for the coming winter months. Central said they might encounter issues with shipments
during December to Feburary, so we should try to be frugal with the next shipment.<br><br><b>November 20th</b><br>Final shipment from central for the next few months. Going outside
during December to Feburary, so we should try to be frugal with the next shipment.<br><br><b>November 20th</b><br>Final shipment from Central for the next few months. Going outside
for more than 10-15 minutes without losing feeling in your fingers is difficult. We've finally gotten a signal on the radio, it's mostly some weird static though. One of the researchers is trying to decypher it.
<br><br><b>December 10th</b><br>Signal has gotten much stronger, it almost seems like it's coming from under us according to what the researcher managed to decypher. We're waiting from the go from central before investigating.<br><br>
<br><br><b>December 10th</b><br>Signal has gotten much stronger, it almost seems like it's coming from under us according to what the researcher managed to decypher. We're waiting from the go from Central before investigating.<br><br>
<i>The rest of the paper seems to be a mixture of scribbles and smudged ink.</i>"}
/obj/item/paper/fluff/awaymissions/snowdin/log2
@@ -48,7 +85,7 @@
info = {"You have been assigned a position on a listening outpost. Here you'll be watching over several crewmembers assigned to watching signals of the general area.
As not much is expected in terms of issues, we've only assigned one guard per outpost. Crewmembers are expected to keep to their regulated work schedules and may be
disciplined properly if found slacking. Food hoarding is heavily discouraged as all outposts will be sharing from the same shipment every 2-3 months. Hoarding of supplies
should be punished severely as to prevent future incidients. Mutiny and/or rioting should be reported to central and dealt with swiftly. You're here to secure and protect
should be punished severely as to prevent future incidients. Mutiny and/or rioting should be reported to Central and dealt with swiftly. You're here to secure and protect
Nanotrasen assets, not be a police officer. Do what you must, but make sure it's not messy."}
/obj/item/paper/fluff/awaymissions/snowdin/syndienotice
@@ -162,7 +199,7 @@
/obj/item/clothing/under/syndicate/coldres
name = "insulated tactical turtleneck"
desc = "A non-descript and slightly suspicious looking turtleneck with digital camouflage cargo pants. The interior has been padded with special insulation for both warmth and protection"
desc = "A non-descript and slightly suspicious-looking turtleneck with digital camouflage cargo pants. The interior has been padded with special insulation for both warmth and protection."
armor = list(melee = 20, bullet = 10, laser = 0,energy = 5, bomb = 0, bio = 0, rad = 0, fire = 25, acid = 25)
cold_protection = CHEST|GROIN|ARMS|LEGS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
@@ -0,0 +1,42 @@
//Spacebattle Areas
/area/awaymission/spacebattle
name = "Space Battle"
icon_state = "awaycontent1"
requires_power = FALSE
/area/awaymission/spacebattle/cruiser
name = "Nanotrasen Cruiser"
icon_state = "awaycontent2"
/area/awaymission/spacebattle/syndicate1
name = "Syndicate Assault Ship 1"
icon_state = "awaycontent3"
/area/awaymission/spacebattle/syndicate2
name = "Syndicate Assault Ship 2"
icon_state = "awaycontent4"
/area/awaymission/spacebattle/syndicate3
name = "Syndicate Assault Ship 3"
icon_state = "awaycontent5"
/area/awaymission/spacebattle/syndicate4
name = "Syndicate War Sphere 1"
icon_state = "awaycontent6"
/area/awaymission/spacebattle/syndicate5
name = "Syndicate War Sphere 2"
icon_state = "awaycontent7"
/area/awaymission/spacebattle/syndicate6
name = "Syndicate War Sphere 3"
icon_state = "awaycontent8"
/area/awaymission/spacebattle/syndicate7
name = "Syndicate Fighter"
icon_state = "awaycontent9"
/area/awaymission/spacebattle/secret
name = "Hidden Chamber"
icon_state = "awaycontent10"
@@ -136,18 +136,41 @@ GLOBAL_VAR_INIT(sc_safecode5, "[rand(0,9)]")
/*
* Modified Nar-Sie
*/
/obj/singularity/narsie/mini
/obj/singularity/narsie/sc_Narsie
desc = "Your body becomes weak and your feel your mind slipping away as you try to comprehend what you know can't be possible."
move_self = 0 //Contianed narsie does not move!
grav_pull = 0 //Contained narsie does not pull stuff in!
var/uneatable = list(/turf/open/space, /obj/effect/overlay, /mob/living/simple_animal/hostile/construct)
//Override this to prevent no adminlog runtimes and admin warnings about a singularity without containment
/obj/singularity/narsie/mini/admin_investigate_setup()
/obj/singularity/narsie/sc_Narsie/admin_investigate_setup()
return
/obj/singularity/narsie/mini/process()
/obj/singularity/narsie/sc_Narsie/process()
eat()
if(prob(25))
mezzer()
/obj/singularity/narsie/mini/ex_act()
/obj/singularity/narsie/sc_Narsie/consume(atom/A)
if(is_type_in_list(A, uneatable))
return 0
if(isliving(A))
var/mob/living/L = A
L.gib()
else if(istype(A, /obj/))
var/obj/O = A
O.ex_act(EXPLODE_DEVASTATE)
if(O)
qdel(O)
else if(isturf(A))
var/turf/T = A
if(T.intact)
for(var/obj/O in T.contents)
if(O.level != 1)
continue
if(O.invisibility == INVISIBILITY_MAXIMUM)
src.consume(O)
T.ChangeTurf(/turf/open/space)
return
/obj/singularity/narsie/sc_Narsie/ex_act()
return
@@ -0,0 +1,39 @@
// undergroundoutpost45
//Areas
/area/awaymission/undergroundoutpost45
name = "space"
icon_state = "awaycontent1"
/area/awaymission/undergroundoutpost45/central
name = "UO45 Central Hall"
icon_state = "awaycontent2"
/area/awaymission/undergroundoutpost45/crew_quarters
name = "UO45 Crew Quarters"
icon_state = "awaycontent3"
/area/awaymission/undergroundoutpost45/engineering
name = "UO45 Engineering"
icon_state = "awaycontent4"
/area/awaymission/undergroundoutpost45/mining
name = "UO45 Mining"
icon_state = "awaycontent5"
/area/awaymission/undergroundoutpost45/research
name = "UO45 Research"
icon_state = "awaycontent6"
/area/awaymission/undergroundoutpost45/gateway
name = "UO45 Gateway"
icon_state = "awaycontent7"
/area/awaymission/undergroundoutpost45/caves
name = "UO45 Caves"
icon_state = "awaycontent8"
always_unpowered = TRUE
power_environ = FALSE
power_equip = FALSE
power_light = FALSE
poweralm = FALSE
@@ -4,6 +4,33 @@
* Meat Grinder
*/
//Areas
/area/awaymission/wildwest/mines
name = "Wild West Mines"
icon_state = "away1"
requires_power = FALSE
/area/awaymission/wildwest/gov
name = "Wild West Mansion"
icon_state = "away2"
requires_power = FALSE
/area/awaymission/wildwest/refine
name = "Wild West Refinery"
icon_state = "away3"
requires_power = FALSE
/area/awaymission/wildwest/vault
name = "Wild West Vault"
icon_state = "away3"
/area/awaymission/wildwest/vaultdoors
name = "Wild West Vault Doors" // this is to keep the vault area being entirely lit because of requires_power
icon_state = "away2"
requires_power = FALSE
////////// wildwest papers
/obj/item/paper/fluff/awaymissions/wildwest/grinder
@@ -126,7 +153,7 @@
var/mob/living/carbon/human/M = AM
if(M.stat != DEAD && M.ckey)
visible_message("<span class='warning'>[M] triggered the [src]!</span>")
visible_message("<span class='warning'>[M] triggered [src]!</span>")
triggered = 1
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
+1 -1
View File
@@ -20,7 +20,7 @@ GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "config/away
/obj/effect/landmark/awaystart
name = "away mission spawn"
desc = "Randomly picked away mission spawn points"
desc = "Randomly picked away mission spawn points."
/obj/effect/landmark/awaystart/New()
GLOB.awaydestinations += src
+2 -2
View File
@@ -26,12 +26,12 @@
export_types = list(/obj/item/seeds)
needs_discovery = TRUE // Only for already discovered species
/datum/export/seed/potency.get_cost(obj/O)
/datum/export/seed/potency/get_cost(obj/O)
var/obj/item/seeds/S = O
var/cost = ..()
if(!cost)
return 0
var/potDiff = (S.potency - discoveredPlants[S.type])
return round(..() * potDiff)
-17
View File
@@ -937,23 +937,6 @@
crate_type = /obj/structure/closet/crate/secure/science
dangerous = TRUE
/datum/supply_pack/science/bz_canister
name = "BZ Canister"
cost = 2000
access_any = list(ACCESS_RD, ACCESS_ATMOSPHERICS)
contains = list(/obj/machinery/portable_atmospherics/canister/bz)
crate_name = "bz canister crate"
crate_type = /obj/structure/closet/crate/secure/science
dangerous = TRUE
/datum/supply_pack/science/freon_canister
name = "Freon Canister"
cost = 6000
access_any = list(ACCESS_RD, ACCESS_ATMOSPHERICS)
contains = list(/obj/machinery/portable_atmospherics/canister/freon)
crate_name = "freon canister crate"
crate_type = /obj/structure/closet/crate/secure/science
dangerous = TRUE
/datum/supply_pack/science/research
name = "Machine Prototype Crate"
+1
View File
@@ -663,6 +663,7 @@ GLOBAL_LIST(external_rsc_urls)
return FALSE
if ("key")
return FALSE
. = ..()
/client/proc/change_view(new_size)
+61 -213
View File
@@ -45,7 +45,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/allow_midround_antag = 1
var/preferred_map = null
var/pda_style = MONO
var/uses_glasses_colour = 0
var/screenshake = 100
@@ -228,7 +228,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<HR>"
switch(current_tab)
if (0) // Character Settings#
if (0) // Character Settings
if(path)
var/savefile/S = new /savefile(path)
if(S)
@@ -239,7 +239,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
S["real_name"] >> name
if(!name)
name = "Character[i]"
//if(i!=1) dat += " | "
/*if(i!=1)
dat += " | " */
dat += "<a style='white-space:nowrap;' href='?_src_=prefs;preference=changeslot;num=[i];' [i == default_slot ? "class='linkOn'" : ""]>[name]</a> "
dat += "</center>"
@@ -278,166 +279,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
// dat += "<b>Size:</b> <a href='?_src_=prefs;preference=character_size;task=input'>[character_size]</a><BR>"
dat += "<br>"
dat += "<h2>Body</h2>"
dat += "<a href='?_src_=prefs;preference=all;task=random'>Random Body</A> "
dat += "<a href='?_src_=prefs;preference=all'>Always Random Body: [be_random_body ? "Yes" : "No"]</A><br>"
dat += "<table width='100%'><tr><td width='24%' valign='top'>"
if(CONFIG_GET(flag/join_with_mutant_race))
dat += "<b>Species:</b><BR><a href='?_src_=prefs;preference=species;task=input'>[pref_species.name]</a><BR>"
else
dat += "<b>Species:</b> Human<BR>"
dat += "<b>Underwear:</b><BR><a href ='?_src_=prefs;preference=underwear;task=input'>[underwear]</a><BR>"
dat += "<b>Undershirt:</b><BR><a href ='?_src_=prefs;preference=undershirt;task=input'>[undershirt]</a><BR>"
dat += "<b>Socks:</b><BR><a href ='?_src_=prefs;preference=socks;task=input'>[socks]</a><BR>"
dat += "<b>Backpack:</b><BR><a href ='?_src_=prefs;preference=bag;task=input'>[backbag]</a><BR>"
dat += "<b>Uplink Spawn Location:</b><BR><a href ='?_src_=prefs;preference=uplink_loc;task=input'>[uplink_spawn_loc]</a><BR></td>"
if(pref_species.use_skintones)
dat += "<td valign='top' width='21%'>"
dat += "<h3>Skin Tone</h3>"
dat += "<a href='?_src_=prefs;preference=s_tone;task=input'>[skin_tone]</a><BR>"
dat += "</td>"
if(HAIR in pref_species.species_traits)
dat += "<td valign='top' width='21%'>"
dat += "<h3>Hair Style</h3>"
dat += "<a href='?_src_=prefs;preference=hair_style;task=input'>[hair_style]</a><BR>"
dat += "<a href='?_src_=prefs;preference=previous_hair_style;task=input'>&lt;</a> <a href='?_src_=prefs;preference=next_hair_style;task=input'>&gt;</a><BR>"
dat += "<span style='border:1px solid #161616; background-color: #[hair_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=hair;task=input'>Change</a><BR>"
dat += "</td><td valign='top' width='21%'>"
dat += "<h3>Facial Hair Style</h3>"
dat += "<a href='?_src_=prefs;preference=facial_hair_style;task=input'>[facial_hair_style]</a><BR>"
dat += "<a href='?_src_=prefs;preference=previous_facehair_style;task=input'>&lt;</a> <a href='?_src_=prefs;preference=next_facehair_style;task=input'>&gt;</a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[facial_hair_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=facial;task=input'>Change</a><BR>"
dat += "</td>"
if(EYECOLOR in pref_species.species_traits)
dat += "<td valign='top' width='21%'>"
dat += "<h3>Eye Color</h3>"
dat += "<span style='border: 1px solid #161616; background-color: #[eye_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=eyes;task=input'>Change</a><BR>"
dat += "</td>"
if(CONFIG_GET(flag/join_with_mutant_race)) //We don't allow mutant bodyparts for humans either unless this is true.
if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits))
dat += "<td valign='top' width='14%'>"
dat += "<h3>Mutant Color</h3>"
dat += "<span style='border: 1px solid #161616; background-color: #[features["mcolor"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=mutant_color;task=input'>Change</a><BR>"
dat += "</td>"
if("tail_lizard" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Tail</h3>"
dat += "<a href='?_src_=prefs;preference=tail_lizard;task=input'>[features["tail_lizard"]]</a><BR>"
dat += "</td>"
if("snout" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Snout</h3>"
dat += "<a href='?_src_=prefs;preference=snout;task=input'>[features["snout"]]</a><BR>"
dat += "</td>"
if("horns" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Horns</h3>"
dat += "<a href='?_src_=prefs;preference=horns;task=input'>[features["horns"]]</a><BR>"
dat += "</td>"
if("frills" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Frills</h3>"
dat += "<a href='?_src_=prefs;preference=frills;task=input'>[features["frills"]]</a><BR>"
dat += "</td>"
if("spines" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Spines</h3>"
dat += "<a href='?_src_=prefs;preference=spines;task=input'>[features["spines"]]</a><BR>"
dat += "</td>"
if("body_markings" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Body Markings</h3>"
dat += "<a href='?_src_=prefs;preference=body_markings;task=input'>[features["body_markings"]]</a><BR>"
dat += "</td>"
if("legs" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Legs</h3>"
dat += "<a href='?_src_=prefs;preference=legs;task=input'>[features["legs"]]</a><BR>"
dat += "</td>"
if(CONFIG_GET(flag/join_with_mutant_humans))
if("tail_human" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Tail</h3>"
dat += "<a href='?_src_=prefs;preference=tail_human;task=input'>[features["tail_human"]]</a><BR>"
dat += "</td>"
if("ears" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Ears</h3>"
dat += "<a href='?_src_=prefs;preference=ears;task=input'>[features["ears"]]</a><BR>"
dat += "</td>"
if("wings" in pref_species.mutant_bodyparts && GLOB.r_wings_list.len >1)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Wings</h3>"
dat += "<a href='?_src_=prefs;preference=wings;task=input'>[features["wings"]]</a><BR>"
dat += "</td>"
dat += "</tr></table>"
if (1) // Game Preferences
@@ -573,61 +420,60 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "[features["flavor_text"]]"
else
dat += "[TextPreview(features["flavor_text"])]...<BR>"
if(CONFIG_GET(flag/join_with_mutant_race))//really don't need this check, but fuck un-tabbing all those lines
dat += "<h2>Body</h2>"
dat += "<b>Gender:</b> <a href='?_src_=prefs;preference=gender'>[gender == MALE ? "Male" : "Female"]</a><BR>"
dat += "<b>Species:</b><a href='?_src_=prefs;preference=species;task=input'>[pref_species.id]</a><BR>"
dat += "<a href='?_src_=prefs;preference=all;task=random'>Random Body</A><BR>"
dat += "<a href='?_src_=prefs;preference=all'>Always Random Body: [be_random_body ? "Yes" : "No"]</A><BR>"
if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits))
dat += "<b>Primary Color: </b><span style='border: 1px solid #161616; background-color: #[features["mcolor"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=mutant_color;task=input'>Change</a><BR>"
dat += "<b>Secondary Color: </b><span style='border: 1px solid #161616; background-color: #[features["mcolor2"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=mutant_color2;task=input'>Change</a><BR>"
dat += "<b>Tertiary Color: </b><span style='border: 1px solid #161616; background-color: #[features["mcolor3"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=mutant_color3;task=input'>Change</a><BR>"
if(pref_species.use_skintones)
dat += "<b>Skin Tone: </b><a href='?_src_=prefs;preference=s_tone;task=input'>[skin_tone]</a><BR>"
dat += "<b>Genitals Use Skintone:</b><a href='?_src_=prefs;preference=genital_colour'>[features["genitals_use_skintone"] == TRUE ? "Enabled" : "Disabled"]</a><BR>"
dat += "<h2>Body</h2>"
dat += "<b>Gender:</b> <a href='?_src_=prefs;preference=gender'>[gender == MALE ? "Male" : "Female"]</a><BR>"
dat += "<b>Species:</b><a href='?_src_=prefs;preference=species;task=input'>[pref_species.id]</a><BR>"
dat += "<a href='?_src_=prefs;preference=all;task=random'>Random Body</A><BR>"
dat += "<a href='?_src_=prefs;preference=all'>Always Random Body: [be_random_body ? "Yes" : "No"]</A><BR>"
if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits))
dat += "<b>Primary Color: </b><span style='border: 1px solid #161616; background-color: #[features["mcolor"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=mutant_color;task=input'>Change</a><BR>"
dat += "<b>Secondary Color: </b><span style='border: 1px solid #161616; background-color: #[features["mcolor2"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=mutant_color2;task=input'>Change</a><BR>"
dat += "<b>Tertiary Color: </b><span style='border: 1px solid #161616; background-color: #[features["mcolor3"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=mutant_color3;task=input'>Change</a><BR>"
if(pref_species.use_skintones)
dat += "<b>Skin Tone: </b><a href='?_src_=prefs;preference=s_tone;task=input'>[skin_tone]</a><BR>"
dat += "<b>Genitals Use Skintone:</b><a href='?_src_=prefs;preference=genital_colour'>[features["genitals_use_skintone"] == TRUE ? "Enabled" : "Disabled"]</a><BR>"
if(HAIR in pref_species.species_traits)
dat += "<b>Hair Style: </b><a href='?_src_=prefs;preference=hair_style;task=input'>[hair_style]</a><BR>"
dat += "<b>Hair Color: </b><span style='border:1px solid #161616; background-color: #[hair_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=hair;task=input'>Change</a><BR>"
dat += "<b>Facial Hair Style: </b><a href='?_src_=prefs;preference=facial_hair_style;task=input'>[facial_hair_style]</a><BR>"
dat += "<b>Facial Hair Color: </b><span style='border: 1px solid #161616; background-color: #[facial_hair_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=facial;task=input'>Change</a><BR>"
if(EYECOLOR in pref_species.species_traits)
dat += "<b>Eye Color: </b><span style='border: 1px solid #161616; background-color: #[eye_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=eyes;task=input'>Change</a><BR>"
if("tail_lizard" in pref_species.mutant_bodyparts)
dat += "<b>Tail: </b><a href='?_src_=prefs;preference=tail_lizard;task=input'>[features["tail_lizard"]]</a><BR>"
else if("mam_tail" in pref_species.mutant_bodyparts)
dat += "<b>Tail: </b><a href='?_src_=prefs;preference=mam_tail;task=input'>[features["mam_tail"]]</a><BR>"
else if("tail_human" in pref_species.mutant_bodyparts)
dat += "<b>Tail: </b><a href='?_src_=prefs;preference=tail_human;task=input'>[features["tail_human"]]</a><BR>"
if("snout" in pref_species.mutant_bodyparts)
dat += "<b>Snout: </b><a href='?_src_=prefs;preference=snout;task=input'>[features["snout"]]</a><BR>"
if("horns" in pref_species.mutant_bodyparts)
dat += "<b>Snout: </b><a href='?_src_=prefs;preference=horns;task=input'>[features["horns"]]</a><BR>"
if("frills" in pref_species.mutant_bodyparts)
dat += "<b>Frills: </b><a href='?_src_=prefs;preference=frills;task=input'>[features["frills"]]</a><BR>"
if("spines" in pref_species.mutant_bodyparts)
dat += "<b>Spines: </b><a href='?_src_=prefs;preference=spines;task=input'>[features["spines"]]</a><BR>"
if("body_markings" in pref_species.mutant_bodyparts)
dat += "<b>Body Markings: </b><a href='?_src_=prefs;preference=body_markings;task=input'>[features["body_markings"]]</a><BR>"
else if("mam_body_markings" in pref_species.mutant_bodyparts)
dat += "<b>Body Markings: </b><a href='?_src_=prefs;preference=mam_body_markings;task=input'>[features["mam_body_markings"]]</a><BR>"
if("mam_ears" in pref_species.mutant_bodyparts)
dat += "<b>Ears: </b><a href='?_src_=prefs;preference=mam_ears;task=input'>[features["mam_ears"]]</a><BR>"
else if("ears" in pref_species.mutant_bodyparts)
dat += "<b>Ears: </b><a href='?_src_=prefs;preference=ears;task=input'>[features["ears"]]</a><BR>"
if("legs" in pref_species.mutant_bodyparts)
dat += "<b>Legs: </b><a href='?_src_=prefs;preference=legs;task=input'>[features["legs"]]</a><BR>"
if("taur" in pref_species.mutant_bodyparts)
dat += "<b>Taur: </b><a href='?_src_=prefs;preference=taur;task=input'>[features["taur"]]</a><BR>"
if("wings" in pref_species.mutant_bodyparts && GLOB.r_wings_list.len >1)
dat += "<b>Wings: </b><a href='?_src_=prefs;preference=wings;task=input'>[features["wings"]]</a><BR>"
if("xenohead" in pref_species.mutant_bodyparts)
dat += "<b>Caste: </b><a href='?_src_=prefs;preference=xenohead;task=input'>[features["xenohead"]]</a><BR>"
if("xenotail" in pref_species.mutant_bodyparts)
dat += "<b>Tail: </b><a href='?_src_=prefs;preference=xenotail;task=input'>[features["xenotail"]]</a><BR>"
if("xenodorsal" in pref_species.mutant_bodyparts)
dat += "<b>Dorsal Tubes: </b><a href='?_src_=prefs;preference=xenodorsal;task=input'>[features["xenodorsal"]]</a><BR>"
if(HAIR in pref_species.species_traits)
dat += "<b>Hair Style: </b><a href='?_src_=prefs;preference=hair_style;task=input'>[hair_style]</a><BR>"
dat += "<b>Hair Color: </b><span style='border:1px solid #161616; background-color: #[hair_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=hair;task=input'>Change</a><BR>"
dat += "<b>Facial Hair Style: </b><a href='?_src_=prefs;preference=facial_hair_style;task=input'>[facial_hair_style]</a><BR>"
dat += "<b>Facial Hair Color: </b><span style='border: 1px solid #161616; background-color: #[facial_hair_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=facial;task=input'>Change</a><BR>"
if(EYECOLOR in pref_species.species_traits)
dat += "<b>Eye Color: </b><span style='border: 1px solid #161616; background-color: #[eye_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=eyes;task=input'>Change</a><BR>"
if("tail_lizard" in pref_species.mutant_bodyparts)
dat += "<b>Tail: </b><a href='?_src_=prefs;preference=tail_lizard;task=input'>[features["tail_lizard"]]</a><BR>"
else if("mam_tail" in pref_species.mutant_bodyparts)
dat += "<b>Tail: </b><a href='?_src_=prefs;preference=mam_tail;task=input'>[features["mam_tail"]]</a><BR>"
else if("tail_human" in pref_species.mutant_bodyparts)
dat += "<b>Tail: </b><a href='?_src_=prefs;preference=tail_human;task=input'>[features["tail_human"]]</a><BR>"
if("snout" in pref_species.mutant_bodyparts)
dat += "<b>Snout: </b><a href='?_src_=prefs;preference=snout;task=input'>[features["snout"]]</a><BR>"
if("horns" in pref_species.mutant_bodyparts)
dat += "<b>Snout: </b><a href='?_src_=prefs;preference=horns;task=input'>[features["horns"]]</a><BR>"
if("frills" in pref_species.mutant_bodyparts)
dat += "<b>Frills: </b><a href='?_src_=prefs;preference=frills;task=input'>[features["frills"]]</a><BR>"
if("spines" in pref_species.mutant_bodyparts)
dat += "<b>Spines: </b><a href='?_src_=prefs;preference=spines;task=input'>[features["spines"]]</a><BR>"
if("body_markings" in pref_species.mutant_bodyparts)
dat += "<b>Body Markings: </b><a href='?_src_=prefs;preference=body_markings;task=input'>[features["body_markings"]]</a><BR>"
else if("mam_body_markings" in pref_species.mutant_bodyparts)
dat += "<b>Body Markings: </b><a href='?_src_=prefs;preference=mam_body_markings;task=input'>[features["mam_body_markings"]]</a><BR>"
if("mam_ears" in pref_species.mutant_bodyparts)
dat += "<b>Ears: </b><a href='?_src_=prefs;preference=mam_ears;task=input'>[features["mam_ears"]]</a><BR>"
else if("ears" in pref_species.mutant_bodyparts)
dat += "<b>Ears: </b><a href='?_src_=prefs;preference=ears;task=input'>[features["ears"]]</a><BR>"
if("legs" in pref_species.mutant_bodyparts)
dat += "<b>Legs: </b><a href='?_src_=prefs;preference=legs;task=input'>[features["legs"]]</a><BR>"
if("taur" in pref_species.mutant_bodyparts)
dat += "<b>Taur: </b><a href='?_src_=prefs;preference=taur;task=input'>[features["taur"]]</a><BR>"
if("wings" in pref_species.mutant_bodyparts && GLOB.r_wings_list.len >1)
dat += "<b>Wings: </b><a href='?_src_=prefs;preference=wings;task=input'>[features["wings"]]</a><BR>"
if("xenohead" in pref_species.mutant_bodyparts)
dat += "<b>Caste: </b><a href='?_src_=prefs;preference=xenohead;task=input'>[features["xenohead"]]</a><BR>"
if("xenotail" in pref_species.mutant_bodyparts)
dat += "<b>Tail: </b><a href='?_src_=prefs;preference=xenotail;task=input'>[features["xenotail"]]</a><BR>"
if("xenodorsal" in pref_species.mutant_bodyparts)
dat += "<b>Dorsal Tubes: </b><a href='?_src_=prefs;preference=xenodorsal;task=input'>[features["xenodorsal"]]</a><BR>"
dat += "</td><td width='300px' height='300px' valign='top'>"
@@ -1187,7 +1033,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("species")
var/result = input(user, "Select a species", "Species Selection") as null|anything in CONFIG_GET(keyed_flag_list/roundstart_races)
var/result = input(user, "Select a species", "Species Selection") as null|anything in GLOB.roundstart_races
if(result)
var/newtype = GLOB.species_list[result]
@@ -1825,10 +1671,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.dna.features = features.Copy() //Flavor text is now a DNA feature
character.dna.real_name = character.real_name
var/datum/species/chosen_species
if(pref_species != /datum/species/human && CONFIG_GET(flag/join_with_mutant_race))
if(pref_species.id in GLOB.roundstart_races)
chosen_species = pref_species.type
else
chosen_species = /datum/species/human
pref_species = new /datum/species/human
save_character()
character.set_species(chosen_species, icon_update=0)
//citadel code
+1 -6
View File
@@ -294,14 +294,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
//Species
var/species_id
S["species"] >> species_id
var/list/roundstart_races = CONFIG_GET(keyed_flag_list/roundstart_races)
if(species_id && (species_id in roundstart_races) && CONFIG_GET(flag/join_with_mutant_race))
if(species_id)
var/newtype = GLOB.species_list[species_id]
pref_species = new newtype()
else if (roundstart_races.len)
var/rando_race = pick(roundstart_races)
if (rando_race)
pref_species = new rando_race()
if(!S["features["mcolor"]"] || S["features["mcolor"]"] == "#000")
WRITE_FILE(S["features["mcolor"]"] , "#FFF")
+2 -1
View File
@@ -391,7 +391,8 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
set name = "Show/Hide Radio Chatter"
set category = "Preferences"
set desc = "Toggle seeing radiochatter from nearby radios and speakers"
if(!holder) return
if(!holder)
return
prefs.chat_toggles ^= CHAT_RADIO
prefs.save_preferences()
to_chat(usr, "You will [(prefs.chat_toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from nearby radios or speakers")
+7 -7
View File
@@ -4,12 +4,12 @@
set category = "OOC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
usr << "<span class='danger'> Speech is currently admin-disabled.</span>"
to_chat(usr, "<span class='danger'> Speech is currently admin-disabled.</span>")
return
if(!mob) return
if(IsGuestKey(key))
src << "Guests may not use OOC."
to_chat(src, "Guests may not use OOC.")
return
msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)
@@ -17,23 +17,23 @@
return
if(!(prefs.toggles & CHAT_OOC))
src << "<span class='danger'> You have OOC muted.</span>"
to_chat(src, "<span class='danger'> You have OOC muted.</span>")
return
if(!holder)
if(!GLOB.ooc_allowed)
src << "<span class='danger'> OOC is globally muted</span>"
to_chat(src, "<span class='danger'> OOC is globally muted</span>")
return
if(!GLOB.dooc_allowed && (mob.stat == DEAD))
usr << "<span class='danger'> OOC for dead mobs has been turned off.</span>"
to_chat(usr, "<span class='danger'> OOC for dead mobs has been turned off.</span>")
return
if(prefs.muted & MUTE_OOC)
src << "<span class='danger'> You cannot use OOC (muted).</span>"
to_chat(src, "<span class='danger'> You cannot use OOC (muted).</span>")
return
if(handle_spam_prevention(msg,MUTE_OOC))
return
if(findtext(msg, "byond://"))
src << "<B>Advertising other servers is not allowed.</B>"
to_chat(src, "<B>Advertising other servers is not allowed.</B>")
log_admin("[key_name(src)] has attempted to advertise in LOOC: [msg]")
return
+12 -2
View File
@@ -259,9 +259,19 @@ GLOBAL_VAR_INIT(normal_ooc_colour, OOC_COLOR)
set category = "OOC"
set desc ="Ignore a player's messages on the OOC channel"
var/selection = input("Please, select a player!", "Ignore", null, null) as null|anything in sortKey(GLOB.clients)
if(!selection)
var/see_ghost_names = isobserver(mob)
var/list/choices = list()
for(var/client/C in GLOB.clients)
if(isobserver(C.mob) && see_ghost_names)
choices["[C.mob]([C])"] = C
else
choices[C] = C
choices = sortList(choices)
var/selection = input("Please, select a player!", "Ignore", null, null) as null|anything in choices
if(!selection || !(selection in choices))
return
selection = choices[selection]
if(selection == src)
to_chat(src, "You can't ignore yourself.")
return
+6 -3
View File
@@ -12,7 +12,7 @@
if(!canSuicide())
return
if(confirm == "Yes")
suiciding = 1
suiciding = TRUE
log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].")
message_admins("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].")
var/obj/item/held_item = get_active_held_item()
@@ -21,7 +21,7 @@
if(damagetype)
if(damagetype & SHAME)
adjustStaminaLoss(200)
suiciding = 0
suiciding = FALSE
return
var/damage_mod = 0
for(var/T in list(BRUTELOSS, FIRELOSS, TOXLOSS, OXYLOSS))
@@ -41,11 +41,14 @@
if(damagetype & OXYLOSS)
adjustOxyLoss(200/damage_mod)
if(damagetype & MANUAL_SUICIDE) //Assume the object will handle the death.
return
//If something went wrong, just do normal oxyloss
if(!(damagetype & (BRUTELOSS | FIRELOSS | TOXLOSS | OXYLOSS) ))
adjustOxyLoss(max(200 - getToxLoss() - getFireLoss() - getBruteLoss() - getOxyLoss(), 0))
death(0)
death(FALSE)
return
var/suicide_message = pick("[src] is attempting to bite [p_their()] tongue off! It looks like [p_theyre()] trying to commit suicide.", \
+1 -1
View File
@@ -383,7 +383,7 @@
randomise_action.UpdateButtonIcon()
/obj/item/clothing/mask/chameleon/drone/attack_self(mob/user)
to_chat(user, "<span class='notice'>The [src] does not have a voice changer.</span>")
to_chat(user, "<span class='notice'>[src] does not have a voice changer.</span>")
/obj/item/clothing/shoes/chameleon
name = "black shoes"
+2 -467
View File
@@ -180,23 +180,7 @@
damaged_clothes = 0
cut_overlay(damaged_clothes_icons[index], TRUE)
//Glasses
/obj/item/clothing/glasses
name = "glasses"
icon = 'icons/obj/clothing/glasses.dmi'
w_class = WEIGHT_CLASS_SMALL
flags_cover = GLASSESCOVERSEYES
slot_flags = SLOT_EYES
var/vision_flags = 0
var/darkness_view = 2//Base human is 2
var/invis_view = SEE_INVISIBLE_LIVING
var/invis_override = 0 //Override to allow glasses to set higher than normal see_invis
var/lighting_alpha
var/list/icon/current = list() //the current hud icons
var/vision_correction = 0 //does wearing these glasses correct some of our vision defects?
strip_delay = 20
equip_delay_other = 25
resistance_flags = 0
/*
SEE_SELF // can see self, no matter what
SEE_MOBS // can see all mobs, no matter what
@@ -207,455 +191,6 @@ SEE_PIXELS// if an object is located on an unlit area, but some of its pixels ar
BLIND // can't see anything
*/
//Gloves
/obj/item/clothing/gloves
name = "gloves"
gender = PLURAL //Carn: for grammarically correct text-parsing
w_class = WEIGHT_CLASS_SMALL
icon = 'icons/obj/clothing/gloves.dmi'
siemens_coefficient = 0.5
body_parts_covered = HANDS
slot_flags = SLOT_GLOVES
attack_verb = list("challenged")
var/transfer_prints = FALSE
strip_delay = 20
equip_delay_other = 40
/obj/item/clothing/gloves/worn_overlays(isinhands = FALSE)
. = list()
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedgloves")
if(blood_DNA)
. += mutable_appearance('icons/effects/blood.dmi', "bloodyhands")
/obj/item/clothing/gloves/update_clothes_damaged_state(damaging = TRUE)
..()
if(ismob(loc))
var/mob/M = loc
M.update_inv_gloves()
// Called just before an attack_hand(), in mob/UnarmedAttack()
/obj/item/clothing/gloves/proc/Touch(atom/A, proximity)
return 0 // return 1 to cancel attack_hand()
//Head
/obj/item/clothing/head
name = "head"
icon = 'icons/obj/clothing/hats.dmi'
icon_state = "top_hat"
item_state = "that"
body_parts_covered = HEAD
slot_flags = SLOT_HEAD
var/blockTracking = 0 //For AI tracking
var/can_toggle = null
dynamic_hair_suffix = "+generic"
/obj/item/clothing/head/Initialize()
. = ..()
if(ishuman(loc) && dynamic_hair_suffix)
var/mob/living/carbon/human/H = loc
H.update_hair()
/obj/item/clothing/head/worn_overlays(isinhands = FALSE)
. = list()
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedhelmet")
if(blood_DNA)
. += mutable_appearance('icons/effects/blood.dmi', "helmetblood")
/obj/item/clothing/head/update_clothes_damaged_state(damaging = TRUE)
..()
if(ismob(loc))
var/mob/M = loc
M.update_inv_head()
//Neck
/obj/item/clothing/neck
name = "necklace"
icon = 'icons/obj/clothing/neck.dmi'
body_parts_covered = NECK
slot_flags = SLOT_NECK
strip_delay = 40
equip_delay_other = 40
/obj/item/clothing/neck/worn_overlays(isinhands = FALSE)
. = list()
if(!isinhands)
if(body_parts_covered & HEAD)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask")
if(blood_DNA)
. += mutable_appearance('icons/effects/blood.dmi', "maskblood")
//Mask
/obj/item/clothing/mask
name = "mask"
icon = 'icons/obj/clothing/masks.dmi'
body_parts_covered = HEAD
slot_flags = SLOT_MASK
strip_delay = 40
equip_delay_other = 40
var/mask_adjusted = 0
var/adjusted_flags = null
/obj/item/clothing/mask/worn_overlays(isinhands = FALSE)
. = list()
if(!isinhands)
if(body_parts_covered & HEAD)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask")
if(blood_DNA)
. += mutable_appearance('icons/effects/blood.dmi', "maskblood")
/obj/item/clothing/mask/update_clothes_damaged_state(damaging = TRUE)
..()
if(ismob(loc))
var/mob/M = loc
M.update_inv_wear_mask()
//Proc that moves gas/breath masks out of the way, disabling them and allowing pill/food consumption
/obj/item/clothing/mask/proc/adjustmask(mob/living/user)
if(user && user.incapacitated())
return
mask_adjusted = !mask_adjusted
if(!mask_adjusted)
src.icon_state = initial(icon_state)
gas_transfer_coefficient = initial(gas_transfer_coefficient)
permeability_coefficient = initial(permeability_coefficient)
flags_1 |= visor_flags
flags_inv |= visor_flags_inv
flags_cover |= visor_flags_cover
to_chat(user, "<span class='notice'>You push \the [src] back into place.</span>")
slot_flags = initial(slot_flags)
else
icon_state += "_up"
to_chat(user, "<span class='notice'>You push \the [src] out of the way.</span>")
gas_transfer_coefficient = null
permeability_coefficient = null
flags_1 &= ~visor_flags
flags_inv &= ~visor_flags_inv
flags_cover &= ~visor_flags_cover
if(adjusted_flags)
slot_flags = adjusted_flags
if(user)
user.wear_mask_update(src, toggle_off = mask_adjusted)
user.update_action_buttons_icon() //when mask is adjusted out, we update all buttons icon so the user's potential internal tank correctly shows as off.
//Shoes
/obj/item/clothing/shoes
name = "shoes"
icon = 'icons/obj/clothing/shoes.dmi'
desc = "Comfortable-looking shoes."
gender = PLURAL //Carn: for grammarically correct text-parsing
var/chained = 0
body_parts_covered = FEET
slot_flags = SLOT_FEET
permeability_coefficient = 0.5
slowdown = SHOES_SLOWDOWN
var/blood_state = BLOOD_STATE_NOT_BLOODY
var/list/bloody_shoes = list(BLOOD_STATE_HUMAN = 0,BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
var/offset = 0
var/equipped_before_drop = FALSE
/obj/item/clothing/shoes/worn_overlays(isinhands = FALSE)
. = list()
if(!isinhands)
var/bloody = 0
if(blood_DNA)
bloody = 1
else
bloody = bloody_shoes[BLOOD_STATE_HUMAN]
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedshoe")
if(bloody)
. += mutable_appearance('icons/effects/blood.dmi', "shoeblood")
/obj/item/clothing/shoes/equipped(mob/user, slot)
. = ..()
if(offset && slot_flags & slotdefine2slotbit(slot))
user.pixel_y += offset
worn_y_dimension -= (offset * 2)
user.update_inv_shoes()
equipped_before_drop = TRUE
/obj/item/clothing/shoes/proc/restore_offsets(mob/user)
equipped_before_drop = FALSE
user.pixel_y -= offset
worn_y_dimension = world.icon_size
/obj/item/clothing/shoes/dropped(mob/user)
if(offset && equipped_before_drop)
restore_offsets(user)
. = ..()
/obj/item/clothing/shoes/update_clothes_damaged_state(damaging = TRUE)
..()
if(ismob(loc))
var/mob/M = loc
M.update_inv_shoes()
/obj/item/clothing/shoes/clean_blood()
..()
bloody_shoes = list(BLOOD_STATE_HUMAN = 0,BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
blood_state = BLOOD_STATE_NOT_BLOODY
if(ismob(loc))
var/mob/M = loc
M.update_inv_shoes()
/obj/item/proc/negates_gravity()
return 0
//Suit
/obj/item/clothing/suit
icon = 'icons/obj/clothing/suits.dmi'
name = "suit"
var/fire_resist = T0C+100
allowed = list(/obj/item/tank/internals/emergency_oxygen)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
slot_flags = SLOT_OCLOTHING
var/blood_overlay_type = "suit"
var/togglename = null
/obj/item/clothing/suit/worn_overlays(isinhands = FALSE)
. = list()
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damaged[blood_overlay_type]")
if(blood_DNA)
. += mutable_appearance('icons/effects/blood.dmi', "[blood_overlay_type]blood")
var/mob/living/carbon/human/M = loc
if(ishuman(M) && M.w_uniform)
var/obj/item/clothing/under/U = M.w_uniform
if(istype(U) && U.attached_accessory)
var/obj/item/clothing/accessory/A = U.attached_accessory
if(A.above_suit)
. += U.accessory_overlay
/obj/item/clothing/suit/update_clothes_damaged_state(damaging = TRUE)
..()
if(ismob(loc))
var/mob/M = loc
M.update_inv_wear_suit()
//Spacesuit
//Note: Everything in modules/clothing/spacesuits should have the entire suit grouped together.
// Meaning the the suit is defined directly after the corrisponding helmet. Just like below!
/obj/item/clothing/head/helmet/space
name = "space helmet"
icon_state = "spaceold"
desc = "A special helmet with solar UV shielding to protect your eyes from harmful rays."
flags_1 = STOPSPRESSUREDMAGE_1 | THICKMATERIAL_1
item_state = "spaceold"
permeability_coefficient = 0.01
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50, fire = 80, acid = 70)
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
dynamic_hair_suffix = ""
dynamic_fhair_suffix = ""
cold_protection = HEAD
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
heat_protection = HEAD
max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT
flash_protect = 2
strip_delay = 50
equip_delay_other = 50
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
resistance_flags = 0
dog_fashion = null
/obj/item/clothing/suit/space
name = "space suit"
desc = "A suit that protects against low pressure environments. Has a big 13 on the back."
icon_state = "spaceold"
item_state = "s_suit"
w_class = WEIGHT_CLASS_BULKY
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.02
flags_1 = STOPSPRESSUREDMAGE_1 | THICKMATERIAL_1
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals)
slowdown = 1
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50, fire = 80, acid = 70)
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS
min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
strip_delay = 80
equip_delay_other = 80
resistance_flags = 0
//Under clothing
/obj/item/clothing/under
icon = 'icons/obj/clothing/uniforms.dmi'
name = "under"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
permeability_coefficient = 0.9
slot_flags = SLOT_ICLOTHING
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
var/fitted = FEMALE_UNIFORM_FULL // For use in alternate clothing styles for women
var/has_sensor = HAS_SENSORS // For the crew computer
var/random_sensor = 1
var/sensor_mode = NO_SENSORS
var/can_adjust = 1
var/adjusted = NORMAL_STYLE
var/alt_covers_chest = 0 // for adjusted/rolled-down jumpsuits, 0 = exposes chest and arms, 1 = exposes arms only
var/obj/item/clothing/accessory/attached_accessory
var/mutable_appearance/accessory_overlay
var/mutantrace_variation = NO_MUTANTRACE_VARIATION //Are there special sprites for specific situations? Don't use this unless you need to.
/obj/item/clothing/under/worn_overlays(isinhands = FALSE)
. = list()
if(!isinhands)
if(damaged_clothes)
. += mutable_appearance('icons/effects/item_damage.dmi', "damageduniform")
if(blood_DNA)
. += mutable_appearance('icons/effects/blood.dmi', "uniformblood")
if(accessory_overlay)
. += accessory_overlay
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = I
C.use(1)
has_sensor = HAS_SENSORS
to_chat(user,"<span class='notice'>You repair the suit sensors on [src] with [C].</span>")
return 1
if(!attach_accessory(I, user))
return ..()
/obj/item/clothing/under/update_clothes_damaged_state(damaging = TRUE)
..()
if(ismob(loc))
var/mob/M = loc
M.update_inv_w_uniform()
if(has_sensor > NO_SENSORS)
has_sensor = BROKEN_SENSORS
/obj/item/clothing/under/New()
if(random_sensor)
//make the sensor mode favor higher levels, except coords.
sensor_mode = pick(SENSOR_OFF, SENSOR_LIVING, SENSOR_LIVING, SENSOR_VITALS, SENSOR_VITALS, SENSOR_VITALS, SENSOR_COORDS, SENSOR_COORDS)
adjusted = NORMAL_STYLE
..()
/obj/item/clothing/under/equipped(mob/user, slot)
..()
if(adjusted)
adjusted = NORMAL_STYLE
fitted = initial(fitted)
if(!alt_covers_chest)
body_parts_covered |= CHEST
if(mutantrace_variation && ishuman(user))
var/mob/living/carbon/human/H = user
if(DIGITIGRADE in H.dna.species.species_traits)
adjusted = DIGITIGRADE_STYLE
H.update_inv_w_uniform()
if(attached_accessory && slot != slot_hands && ishuman(user))
var/mob/living/carbon/human/H = user
attached_accessory.on_uniform_equip(src, user)
if(attached_accessory.above_suit)
H.update_inv_wear_suit()
/obj/item/clothing/under/dropped(mob/user)
if(attached_accessory)
attached_accessory.on_uniform_dropped(src, user)
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(attached_accessory.above_suit)
H.update_inv_wear_suit()
..()
/obj/item/clothing/under/proc/attach_accessory(obj/item/I, mob/user, notifyAttach = 1)
. = FALSE
if(istype(I, /obj/item/clothing/accessory))
var/obj/item/clothing/accessory/A = I
if(attached_accessory)
if(user)
to_chat(user, "<span class='warning'>[src] already has an accessory.</span>")
return
else
if(user && !user.temporarilyRemoveItemFromInventory(I))
return
if(!A.attach(src, user))
return
if(user && notifyAttach)
to_chat(user, "<span class='notice'>You attach [I] to [src].</span>")
var/accessory_color = attached_accessory.item_color
if(!accessory_color)
accessory_color = attached_accessory.icon_state
accessory_overlay = mutable_appearance('icons/mob/accessories.dmi', "[accessory_color]")
accessory_overlay.alpha = attached_accessory.alpha
accessory_overlay.color = attached_accessory.color
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
H.update_inv_w_uniform()
H.update_inv_wear_suit()
return TRUE
/obj/item/clothing/under/proc/remove_accessory(mob/user)
if(!isliving(user))
return
if(!can_use(user))
return
if(attached_accessory)
var/obj/item/clothing/accessory/A = attached_accessory
attached_accessory.detach(src, user)
if(user.put_in_hands(A))
to_chat(user, "<span class='notice'>You detach [A] from [src].</span>")
else
to_chat(user, "<span class='notice'>You detach [A] from [src] and it falls on the floor.</span>")
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
H.update_inv_w_uniform()
H.update_inv_wear_suit()
/obj/item/clothing/under/examine(mob/user)
..()
if(can_adjust)
if(adjusted == ALT_STYLE)
to_chat(user, "Alt-click on [src] to wear it normally.")
else
to_chat(user, "Alt-click on [src] to wear it casually.")
if (has_sensor == BROKEN_SENSORS)
to_chat(user, "Its sensors appear to be shorted out.")
else if(has_sensor > NO_SENSORS)
switch(sensor_mode)
if(SENSOR_OFF)
to_chat(user, "Its sensors appear to be disabled.")
if(SENSOR_LIVING)
to_chat(user, "Its binary life sensors appear to be enabled.")
if(SENSOR_VITALS)
to_chat(user, "Its vital tracker appears to be enabled.")
if(SENSOR_COORDS)
to_chat(user, "Its vital tracker and tracking beacon appear to be enabled.")
if(attached_accessory)
to_chat(user, "\A [attached_accessory] is attached to it.")
/proc/generate_female_clothing(index,t_color,icon,type)
var/icon/female_clothing_icon = icon("icon"=icon, "icon_state"=t_color)
var/icon/female_s = icon("icon"='icons/mob/uniform.dmi', "icon_state"="[(type == FEMALE_UNIFORM_FULL) ? "female_full" : "female_top"]")
@@ -799,4 +334,4 @@ BLIND // can't see anything
Shreds.desc = "The sad remains of what used to be [name]."
deconstruct(FALSE)
else
..()
..()
@@ -1,7 +1,22 @@
//Glasses
/obj/item/clothing/glasses
name = "glasses"
icon = 'icons/obj/clothing/glasses.dmi'
w_class = WEIGHT_CLASS_SMALL
flags_cover = GLASSESCOVERSEYES
slot_flags = SLOT_EYES
strip_delay = 20
equip_delay_other = 25
resistance_flags = 0
materials = list(MAT_GLASS = 250)
var/glass_colour_type = null //colors your vision when worn
var/vision_flags = 0
var/darkness_view = 2//Base human is 2
var/invis_view = SEE_INVISIBLE_LIVING
var/invis_override = 0 //Override to allow glasses to set higher than normal see_invis
var/lighting_alpha
var/list/icon/current = list() //the current hud icons
var/vision_correction = 0 //does wearing these glasses correct some of our vision defects?
var/glass_colour_type //colors your vision when worn
/obj/item/clothing/glasses/examine(mob/user)
..()
@@ -28,7 +43,7 @@
var/mob/living/carbon/human/H = src.loc
if(!(H.disabilities & BLIND))
if(H.glasses == src)
to_chat(H, "<span class='danger'>The [src] overloads and blinds you!</span>")
to_chat(H, "<span class='danger'>[src] overloads and blinds you!</span>")
H.flash_act(visual = 1)
H.blind_eyes(3)
H.blur_eyes(5)

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