Merge branch 'master' into batch-check-injuries

# Conflicts:
#	code/modules/mob/living/carbon/human/human_defense.dm
This commit is contained in:
Carlen White
2019-07-14 20:46:11 -04:00
1265 changed files with 32219 additions and 18801 deletions
+3
View File
@@ -164,8 +164,11 @@
vr_human.name = H.name
vr_human.real_name = H.real_name
vr_human.socks = H.socks
vr_human.socks_color = H.socks_color
vr_human.undershirt = H.undershirt
vr_human.shirt_color = H.shirt_color
vr_human.underwear = H.underwear
vr_human.undie_color = H.undie_color
vr_human.updateappearance(TRUE, TRUE, TRUE)
vr_human.give_genitals(TRUE) //CITADEL ADD
if(outfit)
+1 -1
View File
@@ -4,7 +4,7 @@
var/F = file("[GLOB.log_directory]/[subject].html")
WRITE_FILE(F, "<small>[TIME_STAMP("hh:mm:ss", FALSE)] [REF(src)] ([x],[y],[z])</small> || [src] [message]<br>")
/client/proc/investigate_show(subject in list("notes, memos, watchlist", INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION, INVESTIGATE_CIRCUIT, INVESTIGATE_NANITES) )
/client/proc/investigate_show(subject in list("notes, memos, watchlist", INVESTIGATE_RCD, INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION, INVESTIGATE_CIRCUIT, INVESTIGATE_NANITES) )
set name = "Investigate"
set category = "Admin"
if(!holder)
+1 -1
View File
@@ -80,7 +80,7 @@ GLOBAL_VAR(antag_prototypes)
var/list/result = list()
if(!current)
result += "<span class='bad'>No body!</span>"
if(current && current.has_trait(TRAIT_MINDSHIELD))
if(current && HAS_TRAIT(current, TRAIT_MINDSHIELD))
result += "<span class='good'>Mindshielded</span>"
//Move these to mob
if(iscyborg(current))
+3 -3
View File
@@ -78,13 +78,13 @@ GLOBAL_LIST(round_end_notifiees)
/datum/tgs_chat_command/notify
name = "notify"
help_text = "Pings the invoker when the round ends"
admin_only = TRUE
admin_only = FALSE
/datum/tgs_chat_command/notify/Run(datum/tgs_chat_user/sender, params)
if(!SSticker.IsRoundInProgress() && SSticker.HasRoundStarted())
return "[sender.mention], the round has already ended!"
LAZYINITLIST(GLOB.round_end_notifiees)
GLOB.round_end_notifiees[sender.mention] = TRUE
GLOB.round_end_notifiees["<@[sender.mention]>"] = TRUE
return "I will notify [sender.mention] when the round ends."
/datum/tgs_chat_command/sdql
@@ -140,4 +140,4 @@ GLOBAL_LIST(round_end_notifiees)
log_admin("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
message_admins("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
return "[params] has been added to the current round's bunker bypass list."
return "[params] has been added to the current round's bunker bypass list."
+5 -2
View File
@@ -15,6 +15,9 @@
H.real_name = random_unique_name(H.gender)
H.name = H.real_name
H.underwear = random_underwear(H.gender)
H.undie_color = random_color()
H.undershirt = random_undershirt(H.gender)
H.shirt_color = random_color()
H.skin_tone = random_skin_tone()
H.hair_style = random_hair_style(H.gender)
H.facial_hair_style = random_facial_hair_style(H.gender)
@@ -26,8 +29,8 @@
// Mutant randomizing, doesn't affect the mob appearance unless it's the specific mutant.
H.dna.features["mcolor"] = random_short_color()
H.dna.features["tail_lizard"] = pick(GLOB.tails_list_lizard)
H.dna.features["snout"] = pick(GLOB.snouts_list)
H.dna.features["horns"] = pick(GLOB.horns_list)
H.dna.features["snout"] = pick(GLOB.snouts_list)
H.dna.features["horns"] = pick(GLOB.horns_list)
H.dna.features["frills"] = pick(GLOB.frills_list)
H.dna.features["spines"] = pick(GLOB.spines_list)
H.dna.features["body_markings"] = pick(GLOB.body_markings_list)
+1 -1
View File
@@ -422,7 +422,7 @@
H.equip_to_slot_or_del(I, SLOT_W_UNIFORM)
qdel(olduniform)
if(droptype == "Yes")
I.item_flags |= NODROP
ADD_TRAIT(I, TRAIT_NODROP, ADMIN_TRAIT)
else
to_chat(H, "You're not kawaii enough for this.")
+8 -1
View File
@@ -903,6 +903,13 @@
else
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=alien;jobban4=[REF(M)]'>Alien</a></td>"
//Gang
if(jobban_isbanned(M, ROLE_GANG) || isbanned_dept)
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=gang;jobban4=[REF(M)]'><font color=red>Gang</font></a></td>"
else
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=gang;jobban4=[REF(M)]'>Gang</a></td>"
//Other Roles (black)
dat += "<table cellpadding='1' cellspacing='0' width='100%'>"
dat += "<tr bgcolor='000000'><th colspan='5'><a href='?src=[REF(src)];[HrefToken()];jobban3=otherroles;jobban4=[REF(M)]' style='color: white;'>Other Roles</a></th></tr><tr align='center'>"
@@ -974,7 +981,7 @@
if("ghostroles")
joblist += list(ROLE_PAI, ROLE_POSIBRAIN, ROLE_DRONE , ROLE_DEATHSQUAD, ROLE_LAVALAND, ROLE_SENTIENCE)
if("teamantags")
joblist += list(ROLE_OPERATIVE, ROLE_REV, ROLE_CULTIST, ROLE_SERVANT_OF_RATVAR, ROLE_ABDUCTOR, ROLE_ALIEN)
joblist += list(ROLE_OPERATIVE, ROLE_REV, ROLE_CULTIST, ROLE_SERVANT_OF_RATVAR, ROLE_ABDUCTOR, ROLE_ALIEN, ROLE_GANG)
if("convertantags")
joblist += list(ROLE_REV, ROLE_CULTIST, ROLE_SERVANT_OF_RATVAR, ROLE_ALIEN)
if("otherroles")
+46 -57
View File
@@ -29,69 +29,62 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/callproc()
set category = "Debug"
set name = "Advanced ProcCall"
set waitfor = 0
set waitfor = FALSE
if(!check_rights(R_DEBUG))
return
var/datum/target = null
var/targetselected = 0
var/targetselected = FALSE
var/returnval = null
switch(alert("Proc owned by something?",,"Yes","No"))
if("Yes")
targetselected = 1
var/list/value = vv_get_value(default_class = VV_ATOM_REFERENCE, classes = list(VV_ATOM_REFERENCE, VV_DATUM_REFERENCE, VV_MOB_REFERENCE, VV_CLIENT))
if (!value["class"] || !value["value"])
return
target = value["value"]
if("No")
target = null
targetselected = 0
var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
if(!procname)
return
//hascall() doesn't support proc paths (eg: /proc/gib(), it only supports "gib")
var/testname = procname
if(targetselected)
//Find one of the 3 possible ways they could have written /proc/PROCNAME
if(findtext(procname, "/proc/"))
testname = replacetext(procname, "/proc/", "")
else if(findtext(procname, "/proc"))
testname = replacetext(procname, "/proc", "")
else if(findtext(procname, "proc/"))
testname = replacetext(procname, "proc/", "")
//Clear out any parenthesis if they're a dummy
testname = replacetext(testname, "()", "")
if(targetselected && !hascall(target,testname))
to_chat(usr, "<font color='red'>Error: callproc(): type [target.type] has no proc named [procname].</font>")
return
else
var/procpath = text2path(procname)
if (!procpath)
to_chat(usr, "<font color='red'>Error: callproc(): proc [procname] does not exist. (Did you forget the /proc/ part?)</font>")
if(alert("Proc owned by something?",,"Yes","No") == "Yes")
targetselected = TRUE
var/list/value = vv_get_value(default_class = VV_ATOM_REFERENCE, classes = list(VV_ATOM_REFERENCE, VV_DATUM_REFERENCE, VV_MOB_REFERENCE, VV_CLIENT))
if (!value["class"] || !value["value"])
return
target = value["value"]
var/procpath = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
if(!procpath)
return
//strip away everything but the proc name
var/list/proclist = splittext(procpath, "/")
if (!length(proclist))
return
var/procname = proclist[proclist.len]
var/proctype = ("verb" in proclist) ? "verb" :"proc"
if(targetselected)
if(!hascall(target, procname))
to_chat(usr, "<span class='warning'>Error: callproc(): type [target.type] has no [proctype] named [procpath].</span>")
return
else
procpath = "/[proctype]/[procname]"
if(!text2path(procpath))
to_chat(usr, "<span class='warning'>Error: callproc(): [procpath] does not exist.</span>")
return
var/list/lst = get_callproc_args()
if(!lst)
return
if(targetselected)
if(!target)
to_chat(usr, "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>")
to_chat(usr, "<span class='warning'>Error: callproc(): owner of proc no longer exists.</span>")
return
var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no argument"]."
log_admin(msg)
message_admins(msg)
admin_ticket_log(target, msg)
returnval = WrapAdminProcCall(target, procname, lst) // Pass the lst as an argument list to the proc
returnval = WrapAdminProcCall(target, procname, lst)
else
//this currently has no hascall protection. wasn't able to get it working.
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
message_admins("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
var/msg = "[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no argument"]."
log_admin(msg)
message_admins(msg)
returnval = WrapAdminProcCall(GLOBAL_PROC, procpath, lst) //calling globals needs full qualified name (e.g /proc/foo)
. = get_callproc_returnval(returnval, procname)
if(.)
to_chat(usr, .)
@@ -111,8 +104,8 @@ GLOBAL_LIST_EMPTY(AdminProcCallSpamPrevention)
GLOBAL_PROTECT(AdminProcCallSpamPrevention)
/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
if(target && procname == "Del")
to_chat(usr, "Calling Del() is not allowed")
if(target != GLOBAL_PROC && procname == "Del")
to_chat(usr, "<span class='warning'>Calling Del() is not allowed</span>")
return
if(target != GLOBAL_PROC && !target.CanProcCall(procname))
@@ -159,7 +152,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
/client/proc/callproc_datum(datum/A as null|area|mob|obj|turf)
set category = "Debug"
set name = "Atom ProcCall"
set waitfor = 0
set waitfor = FALSE
if(!check_rights(R_DEBUG))
return
@@ -168,7 +161,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!procname)
return
if(!hascall(A,procname))
to_chat(usr, "<font color='red'>Error: callproc_datum(): type [A.type] has no proc named [procname].</font>")
to_chat(usr, "<span class='warning'>Error: callproc_datum(): type [A.type] has no proc named [procname].</span>")
return
var/list/lst = get_callproc_args()
if(!lst)
@@ -177,8 +170,8 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(!A || !IsValidSrc(A))
to_chat(usr, "<span class='warning'>Error: callproc_datum(): owner of proc no longer exists.</span>")
return
log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
log_admin(msg)
message_admins(msg)
admin_ticket_log(A, msg)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Atom ProcCall") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -188,8 +181,6 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(.)
to_chat(usr, .)
/client/proc/get_callproc_args()
var/argnum = input("Number of arguments","Number:",0) as num|null
if(isnull(argnum))
@@ -213,7 +204,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
. = ""
if(islist(returnval))
var/list/returnedlist = returnval
. = "<font color='blue'>"
. = "<span class='notice'>"
if(returnedlist.len)
var/assoc_check = returnedlist[1]
if(istext(assoc_check) && (returnedlist[assoc_check] != null))
@@ -227,11 +218,10 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
. += "\n[elem]"
else
. = "[procname] returned an empty list"
. += "</font>"
. += "</span>"
else
. = "<font color='blue'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</font>"
. = "<span class='notice'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</span>"
/client/proc/Cell()
set category = "Debug"
@@ -841,8 +831,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if(Rad.anchored)
if(!Rad.loaded_tank)
var/obj/item/tank/internals/plasma/Plasma = new/obj/item/tank/internals/plasma(Rad)
Plasma.air_contents.assert_gas(/datum/gas/plasma)
Plasma.air_contents.gases[/datum/gas/plasma][MOLES] = 70
Plasma.air_contents.gases[/datum/gas/plasma] = 70
Rad.drainratio = 0
Rad.loaded_tank = Plasma
Plasma.forceMove(Rad)
+2 -3
View File
@@ -9,10 +9,9 @@
var/list/lines = list("<span class='adminnotice'>[AREACOORD(target)]: [env.temperature] K ([env.temperature - T0C] C), [env.return_pressure()] kPa[(burning)?(", <font color='red'>burning</font>"):(null)]</span>")
for(var/id in env_gases)
var/gas = env_gases[id]
var/moles = gas[MOLES]
var/moles = env_gases[id]
if (moles >= 0.00001)
lines += "[gas[GAS_META][META_GAS_NAME]]: [moles] mol"
lines += "[GLOB.meta_gas_names[id]]: [moles] mol"
to_chat(usr, lines.Join("\n"))
/client/proc/air_status(turf/target)
+5 -5
View File
@@ -25,8 +25,8 @@
cross.icon_state = "kingyellow"
font_color = "blue"
prayer_type = "CHAPLAIN PRAYER"
if(SSreligion.deity)
deity = SSreligion.deity
if(GLOB.deity)
deity = GLOB.deity
else if(iscultist(usr))
cross.icon_state = "tome"
font_color = "red"
@@ -34,14 +34,14 @@
deity = "Nar'Sie"
else if(isliving(usr))
var/mob/living/L = usr
if(L.has_trait(TRAIT_SPIRITUAL))
if(HAS_TRAIT(L, TRAIT_SPIRITUAL))
cross.icon_state = "holylight"
font_color = "blue"
prayer_type = "SPIRITUAL PRAYER"
var/msg_tmp = msg
msg = "<span class='adminnotice'>[icon2html(cross, GLOB.admins)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""]: </font>[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]:</b> <span class='linkify'>[msg]</span></span>"
for(var/client/C in GLOB.admins)
if(C.prefs.chat_toggles & CHAT_PRAYER)
to_chat(C, msg)
@@ -30,9 +30,12 @@
var/combat_armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 50, "rad" = 50, "fire" = 90, "acid" = 90)
/obj/item/clothing/suit/armor/abductor/vest/proc/toggle_nodrop()
item_flags ^= NODROP
if(HAS_TRAIT_FROM(src, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT))
REMOVE_TRAIT(src, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT)
else
ADD_TRAIT(src, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT)
if(ismob(loc))
to_chat(loc, "<span class='notice'>Your vest is now [item_flags & NODROP ? "locked" : "unlocked"].</span>")
to_chat(loc, "<span class='notice'>Your vest is now [HAS_TRAIT_FROM(src, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT) ? "locked" : "unlocked"].</span>")
/obj/item/clothing/suit/armor/abductor/vest/proc/flip_mode()
switch(mode)
@@ -108,20 +111,7 @@
to_chat(loc, "<span class='warning'>Combat injection is still recharging.</span>")
return
var/mob/living/carbon/human/M = loc
M.SetSleeping(0)
M.SetUnconscious(0)
M.SetStun(0)
M.SetKnockdown(0)
M.reagents.add_reagent("inaprovaline", 3)
M.reagents.add_reagent("synaptizine", 10)
M.reagents.add_reagent("stimulants", 10)
M.adjustStaminaLoss(-150)
M.stuttering = 0
M.updatehealth()
M.update_stamina()
M.resting = 0
M.lying = 0
M.update_canmove()
M.do_adrenaline(150, FALSE, 0, 0, TRUE, list("inaprovaline" = 3, "synaptizine" = 10, "omnizine" = 10), "<span class='boldnotice'>You feel a sudden surge of energy!</span>")
combat_cooldown = 0
START_PROCESSING(SSobj, src)
@@ -17,7 +17,7 @@
var/obj/item/clothing/suit/armor/abductor/vest/V = locate() in H
if(V)
console.AddVest(V)
V.item_flags |= NODROP
ADD_TRAIT(V, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT)
var/obj/item/storage/backpack/B = locate() in H
if(B)
@@ -272,10 +272,10 @@
/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0)
..()
owner.add_trait(TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
/obj/item/organ/heart/gland/electric/Remove(mob/living/carbon/M, special = 0)
owner.remove_trait(TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
..()
/obj/item/organ/heart/gland/electric/activate()
@@ -75,7 +75,7 @@
dat+="<br>"
dat += "<a href='?src=[REF(src)];select_disguise=1'>Select Agent Vest Disguise</a><br>"
dat += "<a href='?src=[REF(src)];toggle_vest=1'>[vest.item_flags & NODROP ? "Unlock" : "Lock"] Vest</a><br>"
dat += "<a href='?src=[REF(src)];toggle_vest=1'>[HAS_TRAIT_FROM(vest, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT) ? "Unlock" : "Lock"] Vest</a><br>"
else
dat += "<span class='bad'>NO AGENT VEST DETECTED</span>"
var/datum/browser/popup = new(user, "computer", "Abductor Console", 400, 500)
@@ -126,8 +126,20 @@
if(vest)
vest.flip_mode()
/obj/machinery/abductor/console/proc/SelectDisguise(remote = 0)
var/entry_name = input( "Choose Disguise", "Disguise") as null|anything in disguises
/obj/machinery/abductor/console/proc/SelectDisguise(remote = FALSE)
var/list/disguises2 = list()
for(var/name in disguises)
var/datum/icon_snapshot/snap = disguises[name]
var/image/dummy = image(snap.icon, src, snap.icon_state)
dummy.overlays = snap.overlays
disguises2[name] = dummy
var/entry_name
if(remote)
entry_name = show_radial_menu(usr, camera.eyeobj, disguises2)
else
entry_name = show_radial_menu(usr, src, disguises2)
var/datum/icon_snapshot/chosen = disguises[entry_name]
if(chosen && vest && (remote || in_range(usr,src)))
vest.SetDisguise(chosen)
@@ -57,7 +57,7 @@
return ..()
/mob/living/simple_animal/hostile/blob/proc/blob_chat(msg)
var/spanned_message = say_quote(msg, get_spans())
var/spanned_message = say_quote(msg)
var/rendered = "<font color=\"#EE4000\"><b>\[Blob Telepathy\] [real_name]</b> [spanned_message]</font>"
for(var/M in GLOB.mob_list)
if(isovermind(M) || istype(M, /mob/living/simple_animal/hostile/blob))
@@ -9,6 +9,7 @@
point_return = 4
atmosblock = TRUE
armor = list("melee" = 25, "bullet" = 25, "laser" = 15, "energy" = 10, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
var/weakened
/obj/structure/blob/shield/scannerreport()
if(atmosblock)
@@ -25,10 +26,15 @@
name = "weakened strong blob"
desc = "A wall of twitching tendrils."
atmosblock = FALSE
armor = list("melee" = 15, "bullet" = 15, "laser" = 5, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
if(!weakened)
armor = armor.setRating("melee" = 15, "bullet" = 15, "laser" = 5, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
weakened = TRUE
else
icon_state = initial(icon_state)
name = initial(name)
desc = initial(desc)
atmosblock = TRUE
air_update_turf(1)
if(weakened)
armor = armor.setRating("melee" = 25, "bullet" = 25, "laser" = 15, "energy" = 10, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
weakened = FALSE
air_update_turf(1)
@@ -210,7 +210,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
src.log_talk(message, LOG_SAY)
var/message_a = say_quote(message, get_spans())
var/message_a = say_quote(message)
var/rendered = "<span class='big'><font color=\"#EE4000\"><b>\[Blob Telepathy\] [name](<font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</font>)</b> [message_a]</font></span>"
for(var/mob/M in GLOB.mob_list)
@@ -169,7 +169,7 @@
to_chat(owner.current, "We have reached our capacity for abilities.")
return
if(owner.current.has_trait(TRAIT_DEATHCOMA))//To avoid potential exploits by buying new powers while in stasis, which clears your verblist.
if(HAS_TRAIT(owner.current, TRAIT_DEATHCOMA))//To avoid potential exploits by buying new powers while in stasis, which clears your verblist.
to_chat(owner.current, "We lack the energy to evolve new abilities right now.")
return
@@ -239,7 +239,7 @@
if(verbose)
to_chat(user, "<span class='warning'>[target] is not compatible with our biology.</span>")
return
if((target.has_trait(TRAIT_NOCLONE)) || (target.has_trait(TRAIT_NOCLONE)))
if((HAS_TRAIT(target, TRAIT_NOCLONE)) || (HAS_TRAIT(target, TRAIT_NOCLONE)))
if(verbose)
to_chat(user, "<span class='warning'>DNA of [target] is ruined beyond usability!</span>")
return
@@ -269,8 +269,11 @@
prof.protected = protect
prof.underwear = H.underwear
prof.undie_color = H.undie_color
prof.undershirt = H.undershirt
prof.shirt_color = H.shirt_color
prof.socks = H.socks
prof.socks_color = H.socks_color
var/list/slots = list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store")
for(var/slot in slots)
@@ -503,8 +506,11 @@
var/list/item_state_list = list()
var/underwear
var/undie_color
var/undershirt
var/shirt_color
var/socks
var/socks_color
/datum/changelingprofile/Destroy()
qdel(dna)
@@ -68,7 +68,7 @@
if(req_stat < user.stat)
to_chat(user, "<span class='warning'>We are incapacitated.</span>")
return 0
if((user.has_trait(TRAIT_DEATHCOMA)) && (!ignores_fakedeath))
if((HAS_TRAIT(user, TRAIT_DEATHCOMA)) && (!ignores_fakedeath))
to_chat(user, "<span class='warning'>We are incapacitated.</span>")
return 0
return 1
@@ -1,8 +1,9 @@
/obj/effect/proc_holder/changeling/adrenaline
name = "Adrenaline Sacs"
desc = "We evolve additional sacs of adrenaline throughout our body."
helptext = "Removes all stuns instantly and adds a short-term reduction in further stuns. Can be used while unconscious. Continued use poisons the body."
helptext = "Removes all stuns instantly and adds a short-term reduction in further stuns. Can be used while unconscious. Continued use poisons the body. This ability is loud, and might cause our blood to react violently to heat."
chemical_cost = 30
loudness = 2
dna_cost = 2
req_human = 1
req_stat = UNCONSCIOUS
@@ -12,21 +13,5 @@
//Recover from stuns.
/obj/effect/proc_holder/changeling/adrenaline/sting_action(mob/living/user)
to_chat(user, "<span class='notice'>Energy rushes through us.[user.lying ? " We arise." : ""]</span>")
user.SetSleeping(0)
user.SetUnconscious(0)
user.SetStun(0)
user.SetKnockdown(0)
user.reagents.add_reagent("changelingadrenaline", 10)
user.reagents.add_reagent("changelinghaste", 2) //For a really quick burst of speed
user.reagents.add_reagent("inaprovaline", 3) //let's give another chance to dumb fucks who forget to breathe
user.adjustStaminaLoss(-150)
user.stuttering = 0
user.updatehealth()
user.update_stamina()
user.resting = 0
user.lying = 0
user.update_canmove()
return TRUE
user.do_adrenaline(0, FALSE, 70, 0, TRUE, list("epinephrine" = 3, "changelingmeth" = 10, "mannitol" = 10, "regen_jelly" = 10, "changelingadrenaline" = 5), "<span class='notice'>Energy rushes through us.</span>", 0, 0.75, 0)
return TRUE
@@ -33,7 +33,7 @@
RV.action.Grant(user)
/obj/effect/proc_holder/changeling/fakedeath/can_sting(mob/living/user)
if(user.has_trait(TRAIT_DEATHCOMA, "changeling"))
if(HAS_TRAIT_FROM(user, TRAIT_DEATHCOMA, "changeling"))
to_chat(user, "<span class='warning'>We are already reviving.</span>")
return
if(!user.stat) //Confirmation for living changelings if they want to fake their death
@@ -10,7 +10,7 @@
action_background_icon_state = "bg_ling"
/obj/effect/proc_holder/changeling/hivemind_comms/sting_action(var/mob/living/user)
if (user.has_trait(CHANGELING_HIVEMIND_MUTE))
if (HAS_TRAIT(user, CHANGELING_HIVEMIND_MUTE))
to_chat(user, "<span class='warning'>The poison in the air hinders our ability to interact with the hivemind.</span>")
return
var/input = html_decode(stripped_input(usr, "Please choose a message to transmit.", "Changeling Hivemind", ""))
@@ -47,7 +47,7 @@ GLOBAL_LIST_EMPTY(hivemind_bank)
action_background_icon_state = "bg_ling"
/obj/effect/proc_holder/changeling/hivemind_upload/sting_action(var/mob/living/user)
if (user.has_trait(CHANGELING_HIVEMIND_MUTE))
if (HAS_TRAIT(user, CHANGELING_HIVEMIND_MUTE))
to_chat(user, "<span class='warning'>The poison in the air hinders our ability to interact with the hivemind.</span>")
return
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
@@ -86,7 +86,7 @@ GLOBAL_LIST_EMPTY(hivemind_bank)
/obj/effect/proc_holder/changeling/hivemind_download/can_sting(mob/living/carbon/user)
if(!..())
return
if (user.has_trait(CHANGELING_HIVEMIND_MUTE))
if (HAS_TRAIT(user, CHANGELING_HIVEMIND_MUTE))
to_chat(user, "<span class='warning'>The poison in the air hinders our ability to interact with the hivemind.</span>")
return
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
@@ -155,7 +155,7 @@
item_state = "arm_blade"
lefthand_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi'
item_flags = NEEDS_PERMIT | ABSTRACT | NODROP | DROPDEL
item_flags = NEEDS_PERMIT | ABSTRACT | DROPDEL
w_class = WEIGHT_CLASS_HUGE
force = 25
throwforce = 0 //Just to be on the safe side
@@ -169,6 +169,7 @@
/obj/item/melee/arm_blade/Initialize(mapload,silent,synthetic)
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
if(ismob(loc) && !silent)
loc.visible_message("<span class='warning'>A grotesque blade forms around [loc.name]\'s arm!</span>", "<span class='warning'>Our arm twists and mutates, transforming it into a deadly blade.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
if(synthetic)
@@ -242,7 +243,7 @@
item_state = "tentacle"
lefthand_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi'
item_flags = NEEDS_PERMIT | ABSTRACT | NODROP | DROPDEL | NOBLUDGEON
item_flags = NEEDS_PERMIT | ABSTRACT | DROPDEL | NOBLUDGEON
flags_1 = NONE
w_class = WEIGHT_CLASS_HUGE
ammo_type = /obj/item/ammo_casing/magic/tentacle
@@ -256,6 +257,7 @@
/obj/item/gun/magic/tentacle/Initialize(mapload, silent)
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
if(ismob(loc))
if(!silent)
loc.visible_message("<span class='warning'>[loc.name]\'s arm starts stretching inhumanly!</span>", "<span class='warning'>Our arm twists and mutates, transforming it into a tentacle.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
@@ -344,9 +346,8 @@
if(isitem(target))
var/obj/item/I = target
if(!I.anchored)
to_chat(firer, "<span class='notice'>You pull [I] towards yourself.</span>")
H.throw_mode_on()
I.throw_at(H, 10, 2)
to_chat(firer, "<span class='notice'>You pull [I] right into your grasp.</span>")
H.put_in_hands(I) //Because throwing it is goofy as fuck and unreliable. If you land the tentacle despite the penalties to accuracy, you should have your reward.
. = 1
else if(isliving(target))
@@ -428,7 +429,7 @@
/obj/item/shield/changeling
name = "shield-like mass"
desc = "A mass of tough, boney tissue. You can still see the fingers as a twisted pattern in the shield."
item_flags = ABSTRACT | NODROP | DROPDEL
item_flags = ABSTRACT | DROPDEL
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "ling_shield"
lefthand_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi'
@@ -439,6 +440,7 @@
/obj/item/shield/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
if(ismob(loc))
loc.visible_message("<span class='warning'>The end of [loc.name]\'s hand inflates rapidly, forming a huge shield-like mass!</span>", "<span class='warning'>We inflate our hand into a strong shield.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
@@ -480,13 +482,14 @@
name = "flesh mass"
icon_state = "lingspacesuit"
desc = "A huge, bulky mass of pressure and temperature-resistant organic tissue, evolved to facilitate space travel."
item_flags = NODROP | DROPDEL
item_flags = DROPDEL
clothing_flags = STOPSPRESSUREDAMAGE //Not THICKMATERIAL because it's organic tissue, so if somebody tries to inject something into it, it still ends up in your blood. (also balance but muh fluff)
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/oxygen)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) //No armor at all.
/obj/item/clothing/suit/space/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
if(ismob(loc))
loc.visible_message("<span class='warning'>[loc.name]\'s flesh rapidly inflates, forming a bloated mass around [loc.p_their()] body!</span>", "<span class='warning'>We inflate our flesh, creating a spaceproof suit!</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
START_PROCESSING(SSobj, src)
@@ -500,11 +503,15 @@
name = "flesh mass"
icon_state = "lingspacehelmet"
desc = "A covering of pressure and temperature-resistant organic tissue with a glass-like chitin front."
item_flags = NODROP | DROPDEL
item_flags = DROPDEL
clothing_flags = STOPSPRESSUREDAMAGE
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
/obj/item/clothing/head/helmet/space/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
/***************************************\
|*****************ARMOR*****************|
\***************************************/
@@ -530,7 +537,7 @@
name = "chitinous mass"
desc = "A tough, hard covering of black chitin."
icon_state = "lingarmor"
item_flags = NODROP | DROPDEL
item_flags = DROPDEL
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 10, "bio" = 4, "rad" = 0, "fire" = 90, "acid" = 90)
flags_inv = HIDEJUMPSUIT
@@ -539,6 +546,7 @@
/obj/item/clothing/suit/armor/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
if(ismob(loc))
loc.visible_message("<span class='warning'>[loc.name]\'s flesh turns black, quickly transforming into a hard, chitinous mass!</span>", "<span class='warning'>We harden our flesh, creating a suit of armor!</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
@@ -546,6 +554,10 @@
name = "chitinous mass"
desc = "A tough, hard covering of black chitin with transparent chitin in front."
icon_state = "lingarmorhelmet"
item_flags = NODROP | DROPDEL
item_flags = DROPDEL
armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 10, "bio" = 4, "rad" = 0, "fire" = 90, "acid" = 90)
flags_inv = HIDEEARS|HIDEHAIR|HIDEEYES|HIDEFACIALHAIR|HIDEFACE
/obj/item/clothing/head/helmet/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
@@ -29,7 +29,7 @@
O.forceMove(get_turf(user))
user.reagents.add_reagent("mutadone", 10)
user.reagents.add_reagent("pen_acid", 20)
user.reagents.add_reagent("pen_jelly", 20)
user.reagents.add_reagent("antihol", 10)
user.reagents.add_reagent("mannitol", 25)
@@ -37,7 +37,7 @@
if(!.)
return
if(user.has_trait(CHANGELING_DRAIN) || ((user.stat != DEAD) && !(user.has_trait(TRAIT_DEATHCOMA))))
if(HAS_TRAIT(user, CHANGELING_DRAIN) || ((user.stat != DEAD) && !(HAS_TRAIT(user, TRAIT_DEATHCOMA))))
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
changeling.purchasedpowers -= src
return FALSE
@@ -19,7 +19,7 @@
if(active)
to_chat(user, "<span class='notice'>Our muscles tense and strengthen.</span>")
else
user.remove_trait(TRAIT_GOTTAGOFAST, "changeling_muscles")
REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
to_chat(user, "<span class='notice'>Our muscles relax.</span>")
if(stacks >= 10)
to_chat(user, "<span class='danger'>We collapse in exhaustion.</span>")
@@ -32,12 +32,12 @@
/obj/effect/proc_holder/changeling/strained_muscles/proc/muscle_loop(mob/living/carbon/user)
while(active)
user.add_trait(TRAIT_GOTTAGOFAST, "changeling_muscles")
ADD_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
if(user.stat != CONSCIOUS || user.staminaloss >= 90)
active = !active
to_chat(user, "<span class='notice'>Our muscles relax without the energy to strengthen them.</span>")
user.Knockdown(40)
user.remove_trait(TRAIT_GOTTAGOFAST, "changeling_muscles")
REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
break
stacks++
@@ -91,7 +91,7 @@
/obj/effect/proc_holder/changeling/sting/transformation/can_sting(mob/user, mob/living/carbon/target)
if(!..())
return
if((target.has_trait(TRAIT_HUSK)) || !iscarbon(target) || (NOTRANSSTING in target.dna.species.species_traits))
if((HAS_TRAIT(target, TRAIT_HUSK)) || !iscarbon(target) || (NOTRANSSTING in target.dna.species.species_traits))
to_chat(user, "<span class='warning'>Our sting appears ineffective against its DNA.</span>")
return 0
return 1
@@ -134,7 +134,7 @@
return
if(isliving(target))
var/mob/living/L = target
if((L.has_trait(TRAIT_HUSK)) || !L.has_dna())
if((HAS_TRAIT(L, TRAIT_HUSK)) || !L.has_dna())
to_chat(user, "<span class='warning'>Our sting appears ineffective against its DNA.</span>")
return 0
return 1
@@ -11,7 +11,11 @@
/obj/item/clothing/glasses/changeling
name = "flesh"
item_flags = NODROP
/obj/item/clothing/glasses/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/glasses/changeling/attack_hand(mob/user)
@@ -23,7 +27,11 @@
/obj/item/clothing/under/changeling
name = "flesh"
item_flags = NODROP
/obj/item/clothing/under/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/under/changeling/attack_hand(mob/user)
@@ -35,9 +43,13 @@
/obj/item/clothing/suit/changeling
name = "flesh"
item_flags = NODROP
allowed = list(/obj/item/changeling)
/obj/item/clothing/suit/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/suit/changeling/attack_hand(mob/user)
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
@@ -48,7 +60,10 @@
/obj/item/clothing/head/changeling
name = "flesh"
item_flags = NODROP
/obj/item/clothing/head/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/head/changeling/attack_hand(mob/user)
@@ -60,7 +75,11 @@
/obj/item/clothing/shoes/changeling
name = "flesh"
item_flags = NODROP
/obj/item/clothing/shoes/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/shoes/changeling/attack_hand(mob/user)
@@ -72,7 +91,11 @@
/obj/item/clothing/gloves/changeling
name = "flesh"
item_flags = NODROP
/obj/item/clothing/gloves/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/gloves/changeling/attack_hand(mob/user)
@@ -84,7 +107,11 @@
/obj/item/clothing/mask/changeling
name = "flesh"
item_flags = NODROP
/obj/item/clothing/mask/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/clothing/mask/changeling/attack_hand(mob/user)
@@ -96,10 +123,14 @@
/obj/item/changeling
name = "flesh"
item_flags = NODROP
slot_flags = ALL
allowed = list(/obj/item/changeling)
/obj/item/changeling/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/changeling/attack_hand(mob/user)
if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling))
@@ -21,17 +21,17 @@
/obj/item/clothing/head/helmet/clockwork/ratvar_act()
if(GLOB.ratvar_awakens)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
armor = getArmor(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100)
clothing_flags |= STOPSPRESSUREDAMAGE
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
else if(GLOB.ratvar_approaches)
armor = list("melee" = 70, "bullet" = 80, "laser" = -15, "energy" = 25, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
armor = getArmor(melee = 70, bullet = 80, laser = -15, energy = 25, bomb = 70, bio = 0, rad = 0, fire = 100, acid = 100)
clothing_flags |= STOPSPRESSUREDAMAGE
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
else
armor = list("melee" = 60, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
armor = getArmor(melee = 60, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100)
clothing_flags &= ~STOPSPRESSUREDAMAGE
max_heat_protection_temperature = initial(max_heat_protection_temperature)
min_cold_protection_temperature = initial(min_cold_protection_temperature)
@@ -69,7 +69,7 @@
heat_protection = CHEST|GROIN|LEGS
resistance_flags = FIRE_PROOF | ACID_PROOF
armor = list("melee" = 60, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
allowed = list(/obj/item/clockwork, /obj/item/clothing/glasses/wraith_spectacles, /obj/item/clothing/glasses/judicial_visor, /obj/item/mmi/posibrain/soul_vessel)
allowed = list(/obj/item/clockwork, /obj/item/clothing/glasses/wraith_spectacles, /obj/item/clothing/glasses/judicial_visor, /obj/item/mmi/posibrain/soul_vessel, /obj/item/reagent_containers/food/drinks/holyoil)
/obj/item/clothing/suit/armor/clockwork/Initialize()
. = ..()
@@ -82,17 +82,17 @@
/obj/item/clothing/suit/armor/clockwork/ratvar_act()
if(GLOB.ratvar_awakens)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
armor = getArmor(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100)
clothing_flags |= STOPSPRESSUREDAMAGE
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
else if(GLOB.ratvar_approaches)
armor = list("melee" = 70, "bullet" = 80, "laser" = -15, "energy" = 25, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
armor = getArmor(melee = 70, bullet = 80, laser = -15, energy = 25, bomb = 70, bio = 0, rad = 0, fire = 100, acid = 100)
clothing_flags |= STOPSPRESSUREDAMAGE
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
else
armor = list("melee" = 60, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
armor = getArmor(melee = 60, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100)
clothing_flags &= ~STOPSPRESSUREDAMAGE
max_heat_protection_temperature = initial(max_heat_protection_temperature)
min_cold_protection_temperature = initial(min_cold_protection_temperature)
@@ -148,12 +148,12 @@
/obj/item/clothing/gloves/clockwork/ratvar_act()
if(GLOB.ratvar_awakens)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
armor = getArmor(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100)
clothing_flags |= STOPSPRESSUREDAMAGE
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
else
armor = list("melee" = 80, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
armor = getArmor(melee = 80, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100)
clothing_flags &= ~STOPSPRESSUREDAMAGE
max_heat_protection_temperature = initial(max_heat_protection_temperature)
min_cold_protection_temperature = initial(min_cold_protection_temperature)
@@ -21,8 +21,9 @@
/obj/item/clockwork/construct_chassis/Destroy()
GLOB.poi_list -= src
var/list/spawners = GLOB.mob_spawners[name]
LAZYREMOVE(spawners, src)
LAZYREMOVE(GLOB.mob_spawners[name], src)
if(!LAZYLEN(GLOB.mob_spawners[name]))
GLOB.mob_spawners -= name
. = ..()
/obj/item/clockwork/construct_chassis/examine(mob/user)
@@ -32,7 +32,7 @@
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
if(src == H.glasses && !up)
if(H.has_trait(TRAIT_BLIND))
if(HAS_TRAIT(H, TRAIT_BLIND))
to_chat(H, "<span class='heavy_brass'>\"You're blind, idiot. Stop embarrassing yourself.\"</span>")
return
if(blind_cultist(H))
@@ -76,7 +76,7 @@
..()
if(slot != SLOT_GLASSES || up)
return
if(user.has_trait(TRAIT_BLIND))
if(HAS_TRAIT(user, TRAIT_BLIND))
to_chat(user, "<span class='heavy_brass'>\"You're blind, idiot. Stop embarrassing yourself.\"</span>" )
return
if(blind_cultist(user)) //Cultists instantly go blind
@@ -115,11 +115,11 @@
var/obj/item/clothing/glasses/wraith_spectacles/WS = L.glasses
desc = "[glasses_right && !WS.up ? "<font color=#DAAA18><b>":""]You are [glasses_right ? "":"not "]wearing wraith spectacles[glasses_right && !WS.up ? "!</b></font>":"."]<br>\
You have taken <font color=#DAAA18><b>[W.eye_damage_done]</b></font> eye damage from them.<br>"
if(L.has_trait(TRAIT_NEARSIGHT))
if(HAS_TRAIT(L, TRAIT_NEARSIGHT))
desc += "<font color=#DAAA18><b>You are nearsighted!</b></font><br>"
else if(glasses_right && !WS.up)
desc += "You will become nearsighted at <font color=#DAAA18><b>[W.nearsight_breakpoint]</b></font> eye damage.<br>"
if(L.has_trait(TRAIT_BLIND))
if(HAS_TRAIT(L, TRAIT_BLIND))
desc += "<font color=#DAAA18><b>You are blind!</b></font>"
else if(glasses_right && !WS.up)
desc += "You will become blind at <font color=#DAAA18><b>[W.blind_breakpoint]</b></font> eye damage."
@@ -153,18 +153,18 @@
qdel(src)
/datum/status_effect/wraith_spectacles/proc/apply_eye_damage(mob/living/carbon/human/H)
if(H.has_trait(TRAIT_BLIND))
if(HAS_TRAIT(H, TRAIT_BLIND))
return
H.adjust_eye_damage(0.5)
eye_damage_done += 0.5
if(eye_damage_done >= 20)
H.adjust_blurriness(2)
if(eye_damage_done >= nearsight_breakpoint)
if(!H.has_trait(TRAIT_NEARSIGHT))
if(!HAS_TRAIT(H, TRAIT_NEARSIGHT))
to_chat(H, "<span class='nzcrentr'>Your vision doubles, then trembles. Darkness begins to close in. You can't keep this up!</span>")
H.become_nearsighted(EYE_DAMAGE)
if(eye_damage_done >= blind_breakpoint)
if(!H.has_trait(TRAIT_BLIND))
if(!HAS_TRAIT(H, TRAIT_BLIND))
to_chat(H, "<span class='nzcrentr_large'>A piercing white light floods your vision. Suddenly, all goes dark!</span>")
H.become_blind(EYE_DAMAGE)
@@ -19,6 +19,7 @@
bubble_icon = "clock"
light_color = "#E42742"
death_sound = 'sound/magic/clockwork/anima_fragment_death.ogg'
speech_span = SPAN_ROBOT
var/playstyle_string = "<span class='heavy_brass'>You are a bug, yell at whoever spawned you!</span>"
var/empower_string = "<span class='heavy_brass'>You have nothing to empower, yell at the coders!</span>" //Shown to the mob when the herald beacon activates
@@ -26,9 +27,6 @@
. = ..()
update_values()
/mob/living/simple_animal/hostile/clockwork/get_spans()
return ..() | SPAN_ROBOT
/mob/living/simple_animal/hostile/clockwork/Login()
..()
add_servant_of_ratvar(src, TRUE)
@@ -110,7 +110,7 @@
if(!(BI.resistance_flags & ON_FIRE))
BI.fire_act()
continue
if(is_servant_of_ratvar(L) || (L.has_trait(TRAIT_BLIND)) || L.anti_magic_check(TRUE, TRUE))
if(is_servant_of_ratvar(L) || (HAS_TRAIT(L, TRAIT_BLIND)) || L.anti_magic_check(TRUE, TRUE))
continue
if(L.stat || L.lying)
continue
@@ -0,0 +1,86 @@
/obj/structure/destructible/clockwork/reflector
name = "reflector"
desc = "A large lantern-shaped machine made of thin brass. It looks fragile."
clockwork_desc = "A lantern-shaped generator that produces power when near starlight."
icon_state = "reflector"
unanchored_icon = "reflector_unwrenched"
max_integrity = 40
construction_value = 5
layer = WALL_OBJ_LAYER
break_message = "<span class='warning'>The reflectors's fragile shield shatters into pieces!</span>"
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
light_color = "#DAAA18"
var/list/allowed_projectile_typecache = list(
/obj/item/projectile/beam
)
var/ini_dir = null
/obj/structure/destructible/clockwork/reflector/Initialize()
. = ..()
allowed_projectile_typecache = typecacheof(allowed_projectile_typecache)
/obj/structure/destructible/clockwork/reflector/ComponentInitialize()
. = ..()
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS ,null,CALLBACK(src, .proc/can_be_rotated),CALLBACK(src,.proc/after_rotation))
/obj/structure/destructible/clockwork/reflector/bullet_act(obj/item/projectile/P)
if(!anchored || !allowed_projectile_typecache[P.type] || !(P.dir in GLOB.cardinals))
return ..()
if(auto_reflect(P, P.dir, get_turf(P), P.Angle) != -1)
return ..()
return -1
/obj/structure/destructible/clockwork/reflector/proc/auto_reflect(obj/item/projectile/P, pdir, turf/ploc, pangle)
//Yell at me if this exists already.
var/real_angle = 0
switch(dir)
if(NORTH)
real_angle = 0
if(EAST)
real_angle = 90
if(SOUTH)
real_angle = 180
if(WEST)
real_angle = 270
var/incidence = GET_ANGLE_OF_INCIDENCE(real_angle, (P.Angle + 180))
if(abs(incidence) > 90 && abs(incidence) < 270)
return FALSE
var/new_angle = SIMPLIFY_DEGREES(real_angle + incidence)
P.setAngle(new_angle)
P.ignore_source_check = TRUE
P.range = P.decayedRange
P.decayedRange = max(P.decayedRange--, 0)
return -1
/obj/structure/destructible/clockwork/reflector/proc/can_be_rotated(mob/user,rotation_type)
if(anchored)
to_chat(user, "<span class='warning'>[src] cannot be rotated while it is fastened to the floor!</span>")
return FALSE
return TRUE
/obj/structure/destructible/clockwork/reflector/Move()
. = ..()
setDir(ini_dir)
/obj/structure/destructible/clockwork/reflector/proc/after_rotation(mob/user,rotation_type)
ini_dir = dir
add_fingerprint(user)
/obj/structure/destructible/clockwork/reflector/wrench_act(mob/living/user, obj/item/I)
if(!is_servant_of_ratvar(user))
return ..()
anchored = !anchored
to_chat(user, "<span class='notice'>You [anchored ? "secure" : "unsecure"] \the [src].</span>")
I.play_tool_sound(src)
return TRUE
+5 -3
View File
@@ -339,7 +339,7 @@
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "disintegrate"
item_state = null
item_flags = NEEDS_PERMIT | ABSTRACT | NODROP | DROPDEL
item_flags = NEEDS_PERMIT | ABSTRACT | DROPDEL
w_class = WEIGHT_CLASS_HUGE
throwforce = 0
@@ -350,11 +350,13 @@
var/health_cost = 0 //The amount of health taken from the user when invoking the spell
var/datum/action/innate/cult/blood_spell/source
/obj/item/melee/blood_magic/New(loc, spell)
/obj/item/melee/blood_magic/Initialize(mapload, spell)
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CULT_TRAIT)
source = spell
uses = source.charges
health_cost = source.health_cost
..()
/obj/item/melee/blood_magic/Destroy()
if(!QDELETED(source))
+81 -35
View File
@@ -13,7 +13,7 @@
var/give_equipment = FALSE
var/datum/team/cult/cult_team
/datum/antagonist/cult/get_team()
return cult_team
@@ -115,7 +115,7 @@
cult_team.rise(current)
if(cult_team.cult_ascendent)
cult_team.ascend(current)
/datum/antagonist/cult/remove_innate_effects(mob/living/mob_override)
. = ..()
var/mob/living/current = owner.current
@@ -131,7 +131,7 @@
var/mob/living/carbon/human/H = current
H.eye_color = initial(H.eye_color)
H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
H.remove_trait(CULT_EYES)
REMOVE_TRAIT(H, TRAIT_CULT_EYES, "valid_cultist")
H.update_body()
H.cut_overlays()
H.regenerate_icons()
@@ -220,12 +220,12 @@
throwing.Remove(current)
current.update_action_buttons_icon()
current.remove_status_effect(/datum/status_effect/cult_master)
if(ishuman(current))
var/mob/living/carbon/human/H = current
H.eye_color = initial(H.eye_color)
H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
H.remove_trait(CULT_EYES)
REMOVE_TRAIT(H, TRAIT_CULT_EYES, "valid_cultist")
H.cut_overlays()
H.regenerate_icons()
@@ -241,7 +241,31 @@
var/reckoning_complete = FALSE
var/cult_risen = FALSE
var/cult_ascendent = FALSE
/datum/team/cult/New()
. = ..()
START_PROCESSING(SSprocessing, src)
/datum/team/cult/Destroy()
STOP_PROCESSING(SSprocessing, src)
return ..()
/datum/team/cult/process()
if(SSticker.current_state == GAME_STATE_FINISHED)
return
var/datum/objective/sacrifice/sac_objective = locate() in objectives
if(!sac_objective || sac_objective.check_completion())
return
var/datum/mind/sacrificial = sac_objective.get_target()
var/mob/living/sac_current = sacrificial.current
if(!sacrificial || !sac_current) //target is gone for good but not sacrified.
sort_sacrifice(TRUE)
return
if(QDELETED(sac_objective.target_current) || sac_objective.target_current != sac_current) //target is now a different mob (monkey, simple mob)
sac_objective.sac_image = sac_current.get_sac_image()
sac_objective.target_current = sac_current
sac_objective.update_explanation_text()
/datum/team/cult/proc/check_size()
if(cult_ascendent)
return
@@ -262,7 +286,7 @@
to_chat(B.current, "<span class='cultlarge'>The veil weakens as your cult grows, your eyes begin to glow...")
addtimer(CALLBACK(src, .proc/rise, B.current), 200)
cult_risen = TRUE
if(ratio > CULT_ASCENDENT && !cult_ascendent)
for(var/datum/mind/B in members)
if(B.current)
@@ -270,16 +294,16 @@
to_chat(B.current, "<span class='cultlarge'>Your cult is ascendent and the red harvest approaches - you cannot hide your true nature for much longer!!")
addtimer(CALLBACK(src, .proc/ascend, B.current), 200)
cult_ascendent = TRUE
/datum/team/cult/proc/rise(cultist)
if(ishuman(cultist))
var/mob/living/carbon/human/H = cultist
H.eye_color = "f00"
H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
H.add_trait(CULT_EYES)
ADD_TRAIT(H, TRAIT_CULT_EYES, "valid_cultist")
H.update_body()
/datum/team/cult/proc/ascend(cultist)
if(ishuman(cultist))
var/mob/living/carbon/human/H = cultist
@@ -289,48 +313,70 @@
/datum/team/cult/proc/setup_objectives()
//SAC OBJECTIVE , todo: move this to objective internals
sort_sacrifice()
//SUMMON OBJECTIVE
var/datum/objective/eldergod/summon_objective = new()
summon_objective.team = src
objectives += summon_objective
/datum/team/cult/proc/sort_sacrifice(replacement = FALSE)
var/list/target_candidates = list()
var/datum/objective/sacrifice/sac_objective = new
sac_objective.team = src
var/datum/objective/sacrifice/sac_objective = locate() in GLOB.objectives
if(!sac_objective)
sac_objective = new
sac_objective.team = src
for(var/mob/living/carbon/human/player in GLOB.player_list)
if(player.mind && !player.mind.has_antag_datum(/datum/antagonist/cult) && !is_convertable_to_cult(player) && player.stat != DEAD)
target_candidates += player.mind
if(target_candidates.len == 0)
if(!length(target_candidates))
message_admins("Cult Sacrifice: Could not find unconvertible target, checking for convertible target.")
for(var/mob/living/carbon/human/player in GLOB.player_list)
if(player.mind && !player.mind.has_antag_datum(/datum/antagonist/cult) && player.stat != DEAD)
target_candidates += player.mind
listclearnulls(target_candidates)
if(LAZYLEN(target_candidates))
sac_objective.target = pick(target_candidates)
sac_objective.update_explanation_text()
if(!LAZYLEN(target_candidates))
message_admins("Cult Sacrifice: Could not find unconvertible or convertible target. Proceeding to next stage!")
sac_objective.sacced = TRUE
return
var/datum/mind/new_target = pick(target_candidates)
if(replacement)
for(var/datum/mind/H in members)
if(H.current)
to_chat(H.current, "<span class='danger'>Nar'Sie</span> murmurs, <span class='cultlarge'>[sac_objective.target] is beyond your reach. Sacrifice [new_target] instead...</span></span>")
sac_objective.target = new_target
sac_objective.target_current = new_target.current
sac_objective.update_explanation_text()
var/datum/job/sacjob = SSjob.GetJob(sac_objective.target.assigned_role)
var/datum/preferences/sacface = sac_objective.target.current.client.prefs
var/icon/reshape = get_flat_human_icon(null, sacjob, sacface, list(SOUTH))
reshape.Shift(SOUTH, 4)
reshape.Shift(EAST, 1)
reshape.Crop(7,4,26,31)
reshape.Crop(-5,-3,26,30)
sac_objective.sac_image = reshape
sac_objective.sac_image = sac_objective.target_current.get_sac_image()
objectives += sac_objective
objectives += sac_objective
else
message_admins("Cult Sacrifice: Could not find unconvertible or convertible target. WELP!")
/mob/proc/get_sac_image()
var/icon/reshape = icon(icon, icon_state, SOUTH)
reshape.Shift(SOUTH, 4)
reshape.Shift(EAST, 1)
reshape.Crop(7,4,26,31)
reshape.Crop(-5,-3,26,30)
return reshape
/mob/living/carbon/human/get_sac_image()
var/datum/job/sacjob = SSjob.GetJob(mind.assigned_role)
var/datum/preferences/sacface = client.prefs
var/icon/reshape = get_flat_human_icon(null, sacjob, sacface, list(SOUTH))
reshape.Shift(SOUTH, 4)
reshape.Shift(EAST, 1)
reshape.Crop(7,4,26,31)
reshape.Crop(-5,-3,26,30)
return reshape
//SUMMON OBJECTIVE
var/datum/objective/eldergod/summon_objective = new()
summon_objective.team = src
objectives += summon_objective
/datum/objective/sacrifice
var/sacced = FALSE
var/sac_image
var/mob/living/target_current
/datum/objective/sacrifice/check_completion()
return sacced || completed
+1 -4
View File
@@ -342,10 +342,7 @@
if(cooldown>world.time)
to_chat(owner, "<span class='cultbold'>You aren't ready to place another blood mark yet!</span>")
return
if(owner.orbiting && owner.orbiting.orbiting)
target = owner.orbiting.orbiting
else
target = get_turf(owner)
target = owner.orbiting?.parent || get_turf(owner)
if(!target)
return
C.cult_team.blood_target = target
+22 -5
View File
@@ -64,9 +64,14 @@
/obj/item/melee/cultblade/ghost
name = "eldritch sword"
force = 19 //can't break normal airlocks
item_flags = NEEDS_PERMIT | NODROP | DROPDEL
item_flags = NEEDS_PERMIT | DROPDEL
flags_1 = NONE
/obj/item/melee/cultblade/ghost/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CULT_TRAIT)
/obj/item/melee/cultblade/pickup(mob/living/user)
..()
if(!iscultist(user))
@@ -298,7 +303,12 @@
item_state = "cult_hoodalt"
/obj/item/clothing/head/culthood/alt/ghost
item_flags = NODROP | DROPDEL
item_flags = DROPDEL
/obj/item/clothing/head/culthood/alt/ghost/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CULT_TRAIT)
/obj/item/clothing/suit/cultrobes/alt
name = "cultist robes"
@@ -307,7 +317,11 @@
item_state = "cultrobesalt"
/obj/item/clothing/suit/cultrobes/alt/ghost
item_flags = NODROP | DROPDEL
item_flags = DROPDEL
/obj/item/clothing/suit/cultrobes/alt/ghost/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CULT_TRAIT)
/obj/item/clothing/head/magus
name = "magus helm"
@@ -796,7 +810,7 @@
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "disintegrate"
item_state = null
item_flags = ABSTRACT | NODROP | DROPDEL
item_flags = ABSTRACT | DROPDEL
w_class = WEIGHT_CLASS_HUGE
throwforce = 0
throw_range = 0
@@ -805,6 +819,9 @@
var/firing = FALSE
var/angle
/obj/item/blood_beam/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CULT_TRAIT)
/obj/item/blood_beam/afterattack(atom/A, mob/living/user, flag, params)
. = ..()
@@ -990,6 +1007,6 @@
continue
throw_at(Next, 3, 1, D.thrower)
return
throw_at(D.thrower, 7, 1, D.thrower)
throw_at(D.thrower, 7, 1, null)
else
..()
+4 -4
View File
@@ -123,7 +123,7 @@ structure_check() searches for nearby cultist structures required for the invoca
continue
if(ishuman(L))
var/mob/living/carbon/human/H = L
if((H.has_trait(TRAIT_MUTE)) || H.silent)
if((HAS_TRAIT(H, TRAIT_MUTE)) || H.silent)
continue
if(L.stat)
continue
@@ -246,18 +246,18 @@ structure_check() searches for nearby cultist structures required for the invoca
return 0
to_chat(convertee, "<span class='cult italic'><b>Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
and something evil takes root.</b></span>")
to_chat(convertee, "<span class='cult italic'>Do you wish to embrace the Geometer of Blood? <a href='?src=\ref[src];signmeup=1'>Click here to stop resisting the truth.</a> Or you could choose to continue resisting...</span>")
to_chat(convertee, "<span class='cult italic'>Do you wish to embrace the Geometer of Blood? <a href='?src=\ref[src];signmeup=1'>Click here to become a follower of Nar'sie.</a> Or you could choose to continue resisting and suffer a fate worse than death...</span>")
currentconversionman = convertee
conversiontimeout = world.time + (10 SECONDS)
convertee.Stun(100)
convertee.add_trait(TRAIT_MUTE, "conversionrune")
ADD_TRAIT(convertee, TRAIT_MUTE, "conversionrune")
conversionresult = FALSE
while(world.time < conversiontimeout && convertee && !conversionresult)
stoplag(1)
currentconversionman = null
if(!convertee)
return FALSE
convertee.remove_trait(TRAIT_MUTE, "conversionrune")
REMOVE_TRAIT(convertee, TRAIT_MUTE, "conversionrune")
if(get_turf(convertee) != get_turf(src))
return FALSE
if(!conversionresult)
@@ -94,7 +94,7 @@
visible_message("<span class='warning'>[src] easily breaks out of [p_their()] handcuffs!</span>", \
"<span class='notice'>With just a thought your handcuffs fall off.</span>")
/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE)
/mob/living/carbon/true_devil/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
if(incapacitated())
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
return FALSE
@@ -7,11 +7,11 @@
/datum/antagonist/highlander/apply_innate_effects(mob/living/mob_override)
var/mob/living/L = owner.current || mob_override
L.add_trait(TRAIT_NOGUNS, "highlander")
ADD_TRAIT(L, TRAIT_NOGUNS, "highlander")
/datum/antagonist/highlander/remove_innate_effects(mob/living/mob_override)
var/mob/living/L = owner.current || mob_override
L.remove_trait(TRAIT_NOGUNS, "highlander")
REMOVE_TRAIT(L, TRAIT_NOGUNS, "highlander")
/datum/antagonist/highlander/proc/forge_objectives()
var/datum/objective/steal/steal_objective = new
@@ -60,7 +60,7 @@
W.access += get_all_centcom_access()
W.assignment = "Highlander"
W.registered_name = H.real_name
W.item_flags |= NODROP
ADD_TRAIT(W, TRAIT_NODROP, HIGHLANDER)
W.update_label(H.real_name)
H.equip_to_slot_or_del(W, SLOT_WEAR_ID)
@@ -65,9 +65,13 @@
/obj/item/pinpointer/syndicate_cyborg // Cyborg pinpointers just look for a random operative.
name = "cyborg syndicate pinpointer"
desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives."
item_flags = NODROP
flags_1 = NONE
/obj/item/pinpointer/syndicate_cyborg/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT)
/obj/item/pinpointer/syndicate_cyborg/scan_for_target()
target = null
var/list/possible_targets = list()
@@ -37,7 +37,7 @@
if(M == user)
to_chat(user,"<span class='warning'>You cannot convert yourself!</span>")
return
if(M.has_trait(TRAIT_MINDSHIELD))
if(HAS_TRAIT(M, TRAIT_MINDSHIELD))
to_chat(user, "<span class='danger'>This mind is too strong to convert, try to remove whatever is protecting it first!</span>")
return
M.visible_message("<span class='warning'>[user] is attempting to implant [M].</span>")
@@ -1,13 +1,21 @@
//Harvest; activated ly clicking the target, will try to drain their essence.
/mob/living/simple_animal/revenant/ClickOn(atom/A, params) //revenants can't interact with the world directly.
A.examine(src)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
ShiftClickOn(A)
return
if(modifiers["alt"])
AltClickNoInteract(src, A)
return
if(ishuman(A))
if(A in drained_mobs)
to_chat(src, "<span class='revenwarning'>[A]'s soul is dead and empty.</span>" )
else if(in_range(src, A))
Harvest(A)
//Harvest; activated ly clicking the target, will try to drain their essence.
/mob/living/simple_animal/revenant/proc/Harvest(mob/living/carbon/human/target)
if(!castcheck(0))
return
@@ -17,7 +17,7 @@
return FALSE
if(new_owner.unconvertable)
return FALSE
if(new_owner.current && new_owner.current.has_trait(TRAIT_MINDSHIELD))
if(new_owner.current && HAS_TRAIT(new_owner.current, TRAIT_MINDSHIELD))
return FALSE
/datum/antagonist/rev/apply_innate_effects(mob/living/mob_override)
+2 -4
View File
@@ -100,6 +100,7 @@
deathmessage = "explodes with a sharp pop!"
light_color = LIGHT_COLOR_CYAN
hud_type = /datum/hud/swarmer
speech_span = SPAN_ROBOT
var/resources = 0 //Resource points, generated by consuming metal/glass
var/max_resources = 100
@@ -126,9 +127,6 @@
if(statpanel("Status"))
stat("Resources:",resources)
/mob/living/simple_animal/hostile/swarmer/get_spans()
return ..() | SPAN_ROBOT
/mob/living/simple_animal/hostile/swarmer/emp_act()
. = ..()
if(. & EMP_PROTECT_SELF)
@@ -666,7 +664,7 @@
set_light(0)
/mob/living/simple_animal/hostile/swarmer/proc/swarmer_chat(msg)
var/rendered = "<B>Swarm communication - [src]</b> [say_quote(msg, get_spans())]"
var/rendered = "<B>Swarm communication - [src]</b> [say_quote(msg)]"
for(var/i in GLOB.mob_list)
var/mob/M = i
if(isswarmer(M))
@@ -130,6 +130,7 @@
if(!owner.current||owner.current.stat==DEAD)
return
to_chat(owner.current, "<span class='userdanger'> Target eliminated: [victim.name]</span>")
LAZYINITLIST(targets_stolen)
for(var/objective_ in victim.objectives)
if(istype(objective_, /datum/objective/assassinate/internal))
var/datum/objective/assassinate/internal/objective = objective_
@@ -18,7 +18,7 @@
/datum/antagonist/traitor/on_gain()
if(owner.current && isAI(owner.current))
traitor_kind = TRAITOR_AI
SSticker.mode.traitors += owner
owner.special_role = special_role
if(give_objectives)
@@ -48,7 +48,7 @@
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
A.malf_picker.remove_malf_verbs(A)
qdel(A.malf_picker)
SSticker.mode.traitors -= owner
if(!silent && owner.current)
to_chat(owner.current,"<span class='userdanger'> You are no longer the [special_role]! </span>")
@@ -244,14 +244,16 @@
return
var/mob/traitor_mob=owner.current
to_chat(traitor_mob, "<U><B>The Syndicate provided you with the following information on how to identify their agents:</B></U>")
to_chat(traitor_mob, "<B>Code Phrase</B>: <span class='danger'>[GLOB.syndicate_code_phrase]</span>")
to_chat(traitor_mob, "<B>Code Response</B>: <span class='danger'>[GLOB.syndicate_code_response]</span>")
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
var/responses = jointext(GLOB.syndicate_code_response, ", ")
antag_memory += "<b>Code Phrase</b>: [GLOB.syndicate_code_phrase]<br>"
antag_memory += "<b>Code Response</b>: [GLOB.syndicate_code_response]<br>"
var/dat = "<U><B>The Syndicate have provided you with the following codewords to identify fellow agents:</B></U>\n"
dat += "<B>Code Phrase</B>: <span class='blue'>[phrases]</span>\n"
dat += "<B>Code Response</B>: <span class='red'>[responses]</span>"
to_chat(traitor_mob, dat)
to_chat(traitor_mob, "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.")
antag_memory += "<b>Code Phrase</b>: <span class='blue'>[phrases]</span><br>"
antag_memory += "<b>Code Response</b>: <span class='red'>[responses]</span><br>"
/datum/antagonist/traitor/proc/add_law_zero()
var/mob/living/silicon/ai/killer = owner.current
@@ -356,8 +358,14 @@
return result.Join("<br>")
/datum/antagonist/traitor/roundend_report_footer()
return "<br><b>The code phrases were:</b> <span class='codephrase'>[GLOB.syndicate_code_phrase]</span><br>\
<b>The code responses were:</b> <span class='codephrase'>[GLOB.syndicate_code_response]</span><br>"
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
var/responses = jointext(GLOB.syndicate_code_response, ", ")
var message = "<br><b>The code phrases were:</b> <span class='bluetext'>[phrases]</span><br>\
<b>The code responses were:</b> <span class='redtext'>[responses]</span><br>"
return message
/datum/antagonist/traitor/is_gamemode_hero()
return SSticker.mode.name == "traitor"
+2 -1
View File
@@ -27,6 +27,7 @@
var/datum/wires/connected = null
var/next_activate = 0 //When we're next allowed to activate - for spam control
var/activate_cooldown = 3 SECONDS
/obj/item/assembly/get_part_rating()
return 1
@@ -78,7 +79,7 @@
/obj/item/assembly/proc/activate()
if(QDELETED(src) || !secured || (next_activate > world.time))
return FALSE
next_activate = world.time + 30
next_activate = world.time + activate_cooldown
return TRUE
+202 -203
View File
@@ -1,203 +1,202 @@
/obj/item/onetankbomb
name = "bomb"
icon = 'icons/obj/tank.dmi'
item_state = "assembly"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
throwforce = 5
w_class = WEIGHT_CLASS_NORMAL
throw_speed = 2
throw_range = 4
flags_1 = CONDUCT_1
var/status = FALSE //0 - not readied //1 - bomb finished with welder
var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
/obj/item/onetankbomb/IsSpecialAssembly()
return TRUE
/obj/item/onetankbomb/examine(mob/user)
bombtank.examine(user)
/obj/item/onetankbomb/update_icon()
cut_overlays()
if(bombtank)
icon = bombtank.icon
icon_state = bombtank.icon_state
if(bombassembly)
add_overlay(bombassembly.icon_state)
copy_overlays(bombassembly)
add_overlay("bomb_assembly")
/obj/item/onetankbomb/wrench_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='notice'>You disassemble [src]!</span>")
if(bombassembly)
bombassembly.forceMove(drop_location())
bombassembly.master = null
bombassembly = null
if(bombtank)
bombtank.forceMove(drop_location())
bombtank.master = null
bombtank = null
qdel(src)
return TRUE
/obj/item/onetankbomb/welder_act(mob/living/user, obj/item/I)
. = FALSE
if(status)
to_chat(user, "<span class='notice'>[bombtank] already has a pressure hole!</span>")
return
if(!I.tool_start_check(user, amount=0))
return
if(I.use_tool(src, user, 0, volume=40))
status = TRUE
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
message_admins("[ADMIN_LOOKUPFLW(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>")
add_fingerprint(user)
return TRUE
/obj/item/onetankbomb/analyzer_act(mob/living/user, obj/item/I)
bombtank.analyzer_act(user, I)
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
bombassembly.attack_self(user, TRUE)
add_fingerprint(user)
return
/obj/item/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
sleep(10)
if(QDELETED(src))
return
if(status)
bombtank.ignite() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file
else
bombtank.release()
//Assembly / attached device memes
/obj/item/onetankbomb/Crossed(atom/movable/AM as mob|obj) //for mousetraps
. = ..()
if(bombassembly)
bombassembly.Crossed(AM)
/obj/item/onetankbomb/on_found(mob/finder) //for mousetraps
if(bombassembly)
bombassembly.on_found(finder)
/obj/item/onetankbomb/attack_hand() //also for mousetraps
. = ..()
if(.)
return
if(bombassembly)
bombassembly.attack_hand()
/obj/item/onetankbomb/Move()
. = ..()
if(bombassembly)
bombassembly.setDir(dir)
bombassembly.Move()
/obj/item/onetankbomb/dropped()
. = ..()
if(bombassembly)
bombassembly.dropped()
// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ----------
//Bomb assembly proc. This turns assembly+tank into a bomb
/obj/item/tank/proc/bomb_assemble(obj/item/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
if((src in user.get_equipped_items(TRUE)) && !user.canUnEquip(src))
to_chat(user, "<span class='warning'>[src] is stuck to you!</span>")
return
if(!user.canUnEquip(assembly))
to_chat(user, "<span class='warning'>[assembly] is stuck to your hand!</span>")
return
var/obj/item/onetankbomb/bomb = new
user.transferItemToLoc(src, bomb)
user.transferItemToLoc(assembly, bomb)
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(/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/datum/gas_mixture/bomb_mixture = air_contents.copy()
var/strength = 1
var/turf/ground_zero = get_turf(loc)
if(master)
qdel(master)
qdel(src)
if(bomb_mixture.temperature > (T0C + 400))
strength = (fuel_moles/15)
if(strength >=1)
explosion(ground_zero, round(strength,1), round(strength*2,1), round(strength*3,1), round(strength*4,1))
else if(strength >=0.5)
explosion(ground_zero, 0, 1, 2, 4)
else if(strength >=0.2)
explosion(ground_zero, -1, 0, 1, 2)
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
else if(bomb_mixture.temperature > (T0C + 250))
strength = (fuel_moles/20)
if(strength >=1)
explosion(ground_zero, 0, round(strength,1), round(strength*2,1), round(strength*3,1))
else if (strength >=0.5)
explosion(ground_zero, -1, 0, 1, 2)
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
else if(bomb_mixture.temperature > (T0C + 100))
strength = (fuel_moles/25)
if (strength >=1)
explosion(ground_zero, -1, 0, round(strength,1), round(strength*3,1))
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
ground_zero.air_update_turf()
/obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out.
var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles())
var/turf/T = get_turf(src)
if(!T)
return
T.assume_air(removed)
air_update_turf()
/obj/item/onetankbomb
name = "bomb"
icon = 'icons/obj/tank.dmi'
item_state = "assembly"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
throwforce = 5
w_class = WEIGHT_CLASS_NORMAL
throw_speed = 2
throw_range = 4
flags_1 = CONDUCT_1
var/status = FALSE //0 - not readied //1 - bomb finished with welder
var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
/obj/item/onetankbomb/IsSpecialAssembly()
return TRUE
/obj/item/onetankbomb/examine(mob/user)
bombtank.examine(user)
/obj/item/onetankbomb/update_icon()
cut_overlays()
if(bombtank)
icon = bombtank.icon
icon_state = bombtank.icon_state
if(bombassembly)
add_overlay(bombassembly.icon_state)
copy_overlays(bombassembly)
add_overlay("bomb_assembly")
/obj/item/onetankbomb/wrench_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='notice'>You disassemble [src]!</span>")
if(bombassembly)
bombassembly.forceMove(drop_location())
bombassembly.master = null
bombassembly = null
if(bombtank)
bombtank.forceMove(drop_location())
bombtank.master = null
bombtank = null
qdel(src)
return TRUE
/obj/item/onetankbomb/welder_act(mob/living/user, obj/item/I)
. = FALSE
if(status)
to_chat(user, "<span class='notice'>[bombtank] already has a pressure hole!</span>")
return
if(!I.tool_start_check(user, amount=0))
return
if(I.use_tool(src, user, 0, volume=40))
status = TRUE
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
message_admins("[ADMIN_LOOKUPFLW(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>")
add_fingerprint(user)
return TRUE
/obj/item/onetankbomb/analyzer_act(mob/living/user, obj/item/I)
bombtank.analyzer_act(user, I)
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
bombassembly.attack_self(user, TRUE)
add_fingerprint(user)
return
/obj/item/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
sleep(10)
if(QDELETED(src))
return
if(status)
bombtank.ignite() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file
else
bombtank.release()
//Assembly / attached device memes
/obj/item/onetankbomb/Crossed(atom/movable/AM as mob|obj) //for mousetraps
. = ..()
if(bombassembly)
bombassembly.Crossed(AM)
/obj/item/onetankbomb/on_found(mob/finder) //for mousetraps
if(bombassembly)
bombassembly.on_found(finder)
/obj/item/onetankbomb/attack_hand() //also for mousetraps
. = ..()
if(.)
return
if(bombassembly)
bombassembly.attack_hand()
/obj/item/onetankbomb/Move()
. = ..()
if(bombassembly)
bombassembly.setDir(dir)
bombassembly.Move()
/obj/item/onetankbomb/dropped()
. = ..()
if(bombassembly)
bombassembly.dropped()
// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ----------
//Bomb assembly proc. This turns assembly+tank into a bomb
/obj/item/tank/proc/bomb_assemble(obj/item/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
if((src in user.get_equipped_items(TRUE)) && !user.canUnEquip(src))
to_chat(user, "<span class='warning'>[src] is stuck to you!</span>")
return
if(!user.canUnEquip(assembly))
to_chat(user, "<span class='warning'>[assembly] is stuck to your hand!</span>")
return
var/obj/item/onetankbomb/bomb = new
user.transferItemToLoc(src, bomb)
user.transferItemToLoc(assembly, bomb)
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
var/fuel_moles = air_contents.gases[/datum/gas/plasma] + air_contents.gases[/datum/gas/oxygen]/6
GAS_GARBAGE_COLLECT(air_contents.gases)
var/datum/gas_mixture/bomb_mixture = air_contents.copy()
var/strength = 1
var/turf/ground_zero = get_turf(loc)
if(master)
qdel(master)
qdel(src)
if(bomb_mixture.temperature > (T0C + 400))
strength = (fuel_moles/15)
if(strength >=1)
explosion(ground_zero, round(strength,1), round(strength*2,1), round(strength*3,1), round(strength*4,1))
else if(strength >=0.5)
explosion(ground_zero, 0, 1, 2, 4)
else if(strength >=0.2)
explosion(ground_zero, -1, 0, 1, 2)
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
else if(bomb_mixture.temperature > (T0C + 250))
strength = (fuel_moles/20)
if(strength >=1)
explosion(ground_zero, 0, round(strength,1), round(strength*2,1), round(strength*3,1))
else if (strength >=0.5)
explosion(ground_zero, -1, 0, 1, 2)
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
else if(bomb_mixture.temperature > (T0C + 100))
strength = (fuel_moles/25)
if (strength >=1)
explosion(ground_zero, -1, 0, round(strength,1), round(strength*3,1))
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
else
ground_zero.assume_air(bomb_mixture)
ground_zero.hotspot_expose(1000, 125)
ground_zero.air_update_turf()
/obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out.
var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles())
var/turf/T = get_turf(src)
if(!T)
return
T.assume_air(removed)
air_update_turf()
+1 -1
View File
@@ -43,7 +43,7 @@
holder.update_icon()
/obj/item/assembly/flash/proc/clown_check(mob/living/carbon/human/user)
if(user.has_trait(TRAIT_CLUMSY) && prob(50))
if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
flash_carbon(user, user, 15, 0)
return FALSE
return TRUE
+4 -4
View File
@@ -18,7 +18,7 @@
if(!armed)
if(ishuman(usr))
var/mob/living/carbon/human/user = usr
if((user.has_trait(TRAIT_DUMB) || user.has_trait(TRAIT_CLUMSY)) && prob(50))
if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
to_chat(user, "<span class='warning'>Your hand slips, setting off the trigger!</span>")
pulse(FALSE)
update_icon()
@@ -38,7 +38,7 @@
var/obj/item/bodypart/affecting = null
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(H.has_trait(TRAIT_PIERCEIMMUNE))
if(HAS_TRAIT(H, TRAIT_PIERCEIMMUNE))
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
armed = FALSE
update_icon()
@@ -70,7 +70,7 @@
if(!armed)
to_chat(user, "<span class='notice'>You arm [src].</span>")
else
if((user.has_trait(TRAIT_DUMB) || user.has_trait(TRAIT_CLUMSY)) && prob(50))
if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
var/which_hand = BODY_ZONE_PRECISE_L_HAND
if(!(user.active_hand_index % 2))
which_hand = BODY_ZONE_PRECISE_R_HAND
@@ -87,7 +87,7 @@
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/assembly/mousetrap/attack_hand(mob/living/carbon/human/user)
if(armed)
if((user.has_trait(TRAIT_DUMB) || user.has_trait(TRAIT_CLUMSY)) && prob(50))
if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
var/which_hand = BODY_ZONE_PRECISE_L_HAND
if(!(user.active_hand_index % 2))
which_hand = BODY_ZONE_PRECISE_R_HAND
@@ -14,9 +14,9 @@
if(!air_contents)
return 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
var/oxy = air_contents.gases[/datum/gas/oxygen]
var/tox = air_contents.gases[/datum/gas/plasma]
var/trit = air_contents.gases[/datum/gas/tritium]
if(active_hotspot)
if(soh)
if((tox > 0.5 || trit > 0.5) && oxy > 0.5)
@@ -162,7 +162,7 @@
color = list(LERP(0.3, 1, 1-greyscale_fire) * heat_r,0.3 * heat_g * greyscale_fire,0.3 * heat_b * greyscale_fire, 0.59 * heat_r * greyscale_fire,LERP(0.59, 1, 1-greyscale_fire) * heat_g,0.59 * heat_b * greyscale_fire, 0.11 * heat_r * greyscale_fire,0.11 * heat_g * greyscale_fire,LERP(0.11, 1, 1-greyscale_fire) * heat_b, 0,0,0)
alpha = heat_a
#define INSUFFICIENT(path) (!location.air.gases[path] || location.air.gases[path][MOLES] < 0.5)
#define INSUFFICIENT(path) (location.air.gases[path] < 0.5)
/obj/effect/hotspot/process()
if(just_spawned)
just_spawned = FALSE
@@ -184,7 +184,7 @@
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)
if((location.air.gases[/datum/gas/plasma] < 0.5 && location.air.gases[/datum/gas/tritium] < 0.5) || location.air.gases[/datum/gas/oxygen] < 0.5)
qdel(src)
return
@@ -88,7 +88,7 @@
temperature_archived = temperature
/turf/open/archive()
air.archive()
ARCHIVE_TEMPERATURE(air)
archived_cycle = SSair.times_fired
temperature_archived = temperature
@@ -121,10 +121,9 @@
if (nonoverlaying_gases[id])
continue
var/gas = gases[id]
var/gas_meta = gas[GAS_META]
var/gas_overlay = gas_meta[META_GAS_OVERLAY]
if(gas_overlay && gas[MOLES] > gas_meta[META_GAS_MOLES_VISIBLE])
. += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(gas[MOLES] / MOLES_GAS_VISIBLE_STEP, 1))]
var/gas_overlay = GLOB.meta_gas_overlays[id]
if(gas_overlay && gas > GLOB.meta_gas_visibility[id])
. += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(gas / MOLES_GAS_VISIBLE_STEP, 1))]
/proc/typecache_of_gases_with_no_overlays()
. = list()
@@ -215,7 +214,7 @@
if (planet_atmos) //share our air with the "atmosphere" "above" the turf
var/datum/gas_mixture/G = new
G.copy_from_turf(src)
G.archive()
ARCHIVE_TEMPERATURE(G)
if(our_air.compare(G))
if(!our_excited_group)
var/datum/excited_group/EG = new
@@ -232,6 +231,11 @@
atmos_cooldown = cached_atmos_cooldown
/turf/open/space/process_cell(fire_count) //dumb hack to prevent space pollution
. = ..()
var/datum/gas_mixture/immutable/I = space_gas
I.after_process_cell()
/turf/proc/process_cell_reaction()
SSair.remove_from_react_queue(src)
@@ -327,7 +331,7 @@
A.merge(T.air)
for(var/id in A_gases)
A_gases[id][MOLES] /= turflen
A_gases[id] /= turflen
for(var/t in turf_list)
var/turf/open/T = t
@@ -5,82 +5,38 @@ What are the archived variables for?
*/
#define MINIMUM_HEAT_CAPACITY 0.0003
#define MINIMUM_MOLE_COUNT 0.01
#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())
/proc/init_gaslist_cache()
. = list()
for(var/id in GLOB.meta_gas_info)
var/list/cached_gas = new(3)
.[id] = cached_gas
cached_gas[MOLES] = 0
cached_gas[ARCHIVE] = 0
cached_gas[GAS_META] = GLOB.meta_gas_info[id]
//Unomos - global list inits for all of the meta gas lists.
//This setup allows procs to only look at one list instead of trying to dig around in lists-within-lists
GLOBAL_LIST_INIT(meta_gas_specific_heats, meta_gas_heat_list())
GLOBAL_LIST_INIT(meta_gas_names, meta_gas_name_list())
GLOBAL_LIST_INIT(meta_gas_visibility, meta_gas_visibility_list())
GLOBAL_LIST_INIT(meta_gas_overlays, meta_gas_overlay_list())
GLOBAL_LIST_INIT(meta_gas_dangers, meta_gas_danger_list())
GLOBAL_LIST_INIT(meta_gas_ids, meta_gas_id_list())
GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list())
/datum/gas_mixture
var/list/gases
var/list/gases = list()
var/temperature = 0 //kelvins
var/tmp/temperature_archived = 0
var/volume = CELL_VOLUME //liters
var/last_share = 0
var/list/reaction_results
var/list/reaction_results = list()
var/list/analyzer_results //used for analyzer feedback - not initialized until its used
var/gc_share = FALSE // Whether to call garbage_collect() on the sharer during shares, used for immutable mixtures
/datum/gas_mixture/New(volume)
gases = new
if (!isnull(volume))
src.volume = volume
reaction_results = new
//listmos procs
//use the macros in performance intensive areas. for their definitions, refer to code/__DEFINES/atmospherics.dm
//assert_gas(gas_id) - used to guarantee that the gas list for this id exists in gas_mixture.gases.
//Must be used before adding to a gas. May be used before reading from a gas.
/datum/gas_mixture/proc/assert_gas(gas_id)
ASSERT_GAS(gas_id, src)
//assert_gases(args) - shorthand for calling ASSERT_GAS() once for each gas type.
/datum/gas_mixture/proc/assert_gases()
for(var/id in args)
ASSERT_GAS(id, src)
//add_gas(gas_id) - similar to assert_gas(), but does not check for an existing
//gas list for this id. This can clobber existing gases.
//Used instead of assert_gas() when you know the gas does not exist. Faster than assert_gas().
/datum/gas_mixture/proc/add_gas(gas_id)
ADD_GAS(gas_id, gases)
//add_gases(args) - shorthand for calling add_gas() once for each gas_type.
/datum/gas_mixture/proc/add_gases()
var/cached_gases = gases
for(var/id in args)
ADD_GAS(id, cached_gases)
//garbage_collect() - removes any gas list which is empty.
//If called with a list as an argument, only removes gas lists with IDs from that list.
//Must be used after subtracting from a gas. Must be used after assert_gas()
//if assert_gas() was called only to read from the gas.
//By removing empty gases, processing speed is increased.
/datum/gas_mixture/proc/garbage_collect(list/tocheck)
var/list/cached_gases = gases
for(var/id in (tocheck || cached_gases))
if(QUANTIZE(cached_gases[id][MOLES]) <= 0 && QUANTIZE(cached_gases[id][ARCHIVE]) <= 0)
cached_gases -= id
//PV = nRT
/datum/gas_mixture/proc/heat_capacity(data = MOLES) //joules per kelvin
/datum/gas_mixture/proc/heat_capacity() //joules per kelvin
var/list/cached_gases = gases
var/list/cached_gasheats = GLOB.meta_gas_specific_heats
. = 0
for(var/id in cached_gases)
var/gas_data = cached_gases[id]
. += gas_data[data] * gas_data[GAS_META][META_GAS_SPECIFIC_HEAT]
. += cached_gases[id] * cached_gasheats[id]
/datum/gas_mixture/turf/heat_capacity()
. = ..()
@@ -108,10 +64,6 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
/datum/gas_mixture/proc/thermal_energy() //joules
return THERMAL_ENERGY(src) //see code/__DEFINES/atmospherics.dm; use the define in performance critical areas
/datum/gas_mixture/proc/archive()
//Update archived versions of variables
//Returns: 1 in all cases
/datum/gas_mixture/proc/merge(datum/gas_mixture/giver)
//Merges all air from giver into self. Deletes giver.
//Returns: 1 if we are mutable, 0 otherwise
@@ -156,14 +108,6 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
//Performs various reactions such as combustion or fusion (LOL)
//Returns: 1 if any reaction took place; 0 otherwise
/datum/gas_mixture/archive()
var/list/cached_gases = gases
temperature_archived = temperature
for(var/id in cached_gases)
cached_gases[id][ARCHIVE] = cached_gases[id][MOLES]
return 1
/datum/gas_mixture/merge(datum/gas_mixture/giver)
if(!giver)
@@ -181,8 +125,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
var/list/giver_gases = giver.gases
//gas transfer
for(var/giver_id in giver_gases)
ASSERT_GAS(giver_id, src)
cached_gases[giver_id][MOLES] += giver_gases[giver_id][MOLES]
cached_gases[giver_id] += giver_gases[giver_id]
return 1
@@ -198,10 +141,9 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
removed.temperature = temperature
for(var/id in cached_gases)
ADD_GAS(id, removed.gases)
removed_gases[id][MOLES] = QUANTIZE((cached_gases[id][MOLES] / sum) * amount)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
garbage_collect()
removed_gases[id] = QUANTIZE((cached_gases[id] / sum) * amount)
cached_gases[id] -= removed_gases[id]
GAS_GARBAGE_COLLECT(gases)
return removed
@@ -216,11 +158,10 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
removed.temperature = temperature
for(var/id in cached_gases)
ADD_GAS(id, removed.gases)
removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES] * ratio)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
removed_gases[id] = QUANTIZE(cached_gases[id] * ratio)
cached_gases[id] -= removed_gases[id]
garbage_collect()
GAS_GARBAGE_COLLECT(gases)
return removed
@@ -231,8 +172,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
copy.temperature = temperature
for(var/id in cached_gases)
ADD_GAS(id, copy.gases)
copy_gases[id][MOLES] = cached_gases[id][MOLES]
copy_gases[id] = cached_gases[id]
return copy
@@ -243,8 +183,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
temperature = sample.temperature
for(var/id in sample_gases)
ASSERT_GAS(id,src)
cached_gases[id][MOLES] = sample_gases[id][MOLES]
cached_gases[id] = sample_gases[id]
//remove all gases not in the sample
cached_gases &= sample_gases
@@ -272,8 +211,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
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])
gases[path] = text2num(gas[id])
return 1
/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
@@ -296,26 +234,25 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
var/moved_moles = 0
var/abs_moved_moles = 0
//we're gonna define these vars outside of this for loop because as it turns out, var declaration is pricy
var/delta
var/gas_heat_capacity
//and also cache this shit rq because that results in sanic speed for reasons byond explanation
var/list/cached_gasheats = GLOB.meta_gas_specific_heats
//GAS TRANSFER
for(var/id in sharer_gases - cached_gases) // create gases not in our cache
ADD_GAS(id, gases)
for(var/id in cached_gases) // transfer gases
ASSERT_GAS(id, sharer)
for(var/id in cached_gases | sharer_gases) // transfer gases
var/gas = cached_gases[id]
var/sharergas = sharer_gases[id]
var/delta = QUANTIZE(gas[ARCHIVE] - sharergas[ARCHIVE])/(atmos_adjacent_turfs+1) //the amount of gas that gets moved between the mixtures
delta = QUANTIZE(cached_gases[id] - sharer_gases[id])/(atmos_adjacent_turfs+1) //the amount of gas that gets moved between the mixtures
if(delta && abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/gas_heat_capacity = delta * gas[GAS_META][META_GAS_SPECIFIC_HEAT]
gas_heat_capacity = delta * cached_gasheats[id]
if(delta > 0)
heat_capacity_self_to_sharer += gas_heat_capacity
else
heat_capacity_sharer_to_self -= gas_heat_capacity //subtract here instead of adding the absolute value because we know that delta is negative.
gas[MOLES] -= delta
sharergas[MOLES] += delta
cached_gases[id] -= delta
sharer_gases[id] += delta
moved_moles += delta
abs_moved_moles += abs(delta)
@@ -338,11 +275,8 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.1) // <10% change in sharer heat capacity
temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
if(length(cached_gases ^ sharer_gases)) //if all gases were present in both mixtures, we know that no gases are 0
garbage_collect(cached_gases - sharer_gases) //any gases the sharer had, we are guaranteed to have. gases that it didn't have we are not.
sharer.garbage_collect(sharer_gases - cached_gases) //the reverse is equally true
if (initial(sharer.gc_share))
sharer.garbage_collect()
GAS_GARBAGE_COLLECT(sharer.gases)
if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/our_moles
TOTAL_MOLES(cached_gases,our_moles)
@@ -356,8 +290,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(ARCHIVE)
sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity(ARCHIVE)
var/self_heat_capacity = heat_capacity()
sharer_heat_capacity = sharer_heat_capacity || sharer.heat_capacity()
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*temperature_delta* \
@@ -376,9 +310,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
for(var/id in cached_gases | sample_gases) // compare gases from either mixture
var/gas_moles = cached_gases[id]
gas_moles = gas_moles ? gas_moles[MOLES] : 0
var/sample_moles = sample_gases[id]
sample_moles = sample_moles ? sample_moles[MOLES] : 0
var/delta = abs(gas_moles - sample_moles)
if(delta > MINIMUM_MOLES_DELTA_TO_MOVE && \
delta > gas_moles * MINIMUM_AIR_RATIO_TO_MOVE)
@@ -425,7 +357,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
for(var/id in min_reqs)
if (id == "TEMP" || id == "ENER")
continue
if(!cached_gases[id] || cached_gases[id][MOLES] < min_reqs[id])
if(cached_gases[id] < min_reqs[id])
continue reaction_loop
//at this point, all minimum requirements for the reaction are satisfied.
@@ -449,7 +381,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache())
if (. & STOP_REACTIONS)
break
if(.)
garbage_collect()
GAS_GARBAGE_COLLECT(gases)
if(temperature < TCMB) //just for safety
temperature = TCMB
@@ -1,33 +1,66 @@
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
GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(/datum/gas/oxygen, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/pluoxium, /datum/gas/stimulum, /datum/gas/nitryl))) //unable to react amongst themselves
/proc/meta_gas_list()
. = subtypesof(/datum/gas)
for(var/gas_path in .)
var/list/gas_info = new(7)
var/datum/gas/gas = gas_path
gas_info[META_GAS_SPECIFIC_HEAT] = initial(gas.specific_heat)
gas_info[META_GAS_NAME] = initial(gas.name)
gas_info[META_GAS_MOLES_VISIBLE] = initial(gas.moles_visible)
if(initial(gas.moles_visible) != null)
gas_info[META_GAS_OVERLAY] = new /list(FACTOR_GAS_VISIBLE_MAX)
for(var/i in 1 to FACTOR_GAS_VISIBLE_MAX)
gas_info[META_GAS_OVERLAY][i] = new /obj/effect/overlay/gas(initial(gas.gas_overlay), i * 255 / FACTOR_GAS_VISIBLE_MAX)
gas_info[META_GAS_FUSION_POWER] = initial(gas.fusion_power)
gas_info[META_GAS_DANGER] = initial(gas.dangerous)
gas_info[META_GAS_ID] = initial(gas.id)
.[gas_path] = gas_info
/proc/gas_id2path(id)
var/list/meta_gas = GLOB.meta_gas_info
var/list/meta_gas = GLOB.meta_gas_ids
if(id in meta_gas)
return id
for(var/path in meta_gas)
if(meta_gas[path][META_GAS_ID] == id)
if(meta_gas[path] == id)
return path
return ""
//Unomos - oh god oh fuck oh shit oh lord have mercy this is messy as fuck oh god
//my addiction to seeing better performance numbers isn't healthy, kids
//you see this shit, children?
//i am not a good idol. don't take after me.
//this is literally worse than my alcohol addiction
/proc/meta_gas_heat_list()
. = subtypesof(/datum/gas)
for(var/gas_path in .)
var/datum/gas/gas = gas_path
.[gas_path] = initial(gas.specific_heat)
/proc/meta_gas_name_list()
. = subtypesof(/datum/gas)
for(var/gas_path in .)
var/datum/gas/gas = gas_path
.[gas_path] = initial(gas.name)
/proc/meta_gas_visibility_list()
. = subtypesof(/datum/gas)
for(var/gas_path in .)
var/datum/gas/gas = gas_path
.[gas_path] = initial(gas.moles_visible)
/proc/meta_gas_overlay_list()
. = subtypesof(/datum/gas)
for(var/gas_path in .)
var/datum/gas/gas = gas_path
.[gas_path] = 0 //gotta make sure if(GLOB.meta_gas_overlays[gaspath]) doesn't break
if(initial(gas.moles_visible) != null)
.[gas_path] = new /list(FACTOR_GAS_VISIBLE_MAX)
for(var/i in 1 to FACTOR_GAS_VISIBLE_MAX)
.[gas_path][i] = new /obj/effect/overlay/gas(initial(gas.gas_overlay), i * 255 / FACTOR_GAS_VISIBLE_MAX)
/proc/meta_gas_danger_list()
. = subtypesof(/datum/gas)
for(var/gas_path in .)
var/datum/gas/gas = gas_path
.[gas_path] = initial(gas.dangerous)
/proc/meta_gas_id_list()
. = subtypesof(/datum/gas)
for(var/gas_path in .)
var/datum/gas/gas = gas_path
.[gas_path] = initial(gas.id)
/proc/meta_gas_fusion_list()
. = subtypesof(/datum/gas)
for(var/gas_path in .)
var/datum/gas/gas = gas_path
.[gas_path] = initial(gas.fusion_power)
/*||||||||||||||/----------\||||||||||||||*\
||||||||||||||||[GAS DATUMS]||||||||||||||||
||||||||||||||||\__________/||||||||||||||||
@@ -7,22 +7,18 @@
/datum/gas_mixture/immutable/New()
..()
garbage_collect()
/datum/gas_mixture/immutable/garbage_collect()
temperature = initial_temperature
temperature_archived = initial_temperature
gases.Cut()
/datum/gas_mixture/immutable/archive()
return 1 //nothing changes, so we do nothing and the archive is successful
/datum/gas_mixture/immutable/merge()
return 0 //we're immutable.
/datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
. = ..(sharer, 0)
garbage_collect()
temperature = initial_temperature
temperature_archived = initial_temperature
gases.Cut()
/datum/gas_mixture/immutable/react()
return 0 //we're immutable.
@@ -43,6 +39,10 @@
. = ..()
temperature = initial_temperature
/datum/gas_mixture/immutable/proc/after_process_cell()
temperature = initial_temperature
temperature_archived = initial_temperature
gases.Cut()
//used by space tiles
/datum/gas_mixture/immutable/space
@@ -62,10 +62,13 @@
/datum/gas_mixture/immutable/cloner
initial_temperature = T20C
/datum/gas_mixture/immutable/cloner/garbage_collect()
/datum/gas_mixture/immutable/cloner/New()
..()
ADD_GAS(/datum/gas/nitrogen, gases)
gases[/datum/gas/nitrogen][MOLES] = MOLES_O2STANDARD + MOLES_N2STANDARD
gases[/datum/gas/nitrogen] = MOLES_O2STANDARD + MOLES_N2STANDARD
/datum/gas_mixture/immutable/cloner/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
. = ..(sharer, 0)
gases[/datum/gas/nitrogen] = MOLES_O2STANDARD + MOLES_N2STANDARD
/datum/gas_mixture/immutable/cloner/heat_capacity()
return (MOLES_O2STANDARD + MOLES_N2STANDARD)*20 //specific heat of nitrogen is 20
@@ -60,7 +60,7 @@
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
air.gases[/datum/gas/water_vapor] -= MOLES_GAS_VISIBLE
. = REACTING
//tritium combustion: combustion of oxygen and tritium (treated as hydrocarbons). creates hotspots. exothermic
@@ -86,21 +86,20 @@
var/turf/open/location = isturf(holder) ? holder : null
var/burned_fuel = 0
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
if(cached_gases[/datum/gas/oxygen] < cached_gases[/datum/gas/tritium])
burned_fuel = cached_gases[/datum/gas/oxygen]/TRITIUM_BURN_OXY_FACTOR
cached_gases[/datum/gas/tritium] -= burned_fuel
else
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]
burned_fuel = cached_gases[/datum/gas/tritium]*TRITIUM_BURN_TRIT_FACTOR
cached_gases[/datum/gas/tritium] -= cached_gases[/datum/gas/tritium]/TRITIUM_BURN_TRIT_FACTOR
cached_gases[/datum/gas/oxygen] -= cached_gases[/datum/gas/tritium]
if(burned_fuel)
energy_released += FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel
energy_released += (FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel)
if(location && prob(10) && burned_fuel > TRITIUM_MINIMUM_RADIATION_ENERGY) //woah there let's not crash the server
radiation_pulse(location, energy_released/TRITIUM_BURN_RADIOACTIVITY_FACTOR)
ASSERT_GAS(/datum/gas/water_vapor, air) //oxygen+more-or-less hydrogen=H2O
cached_gases[/datum/gas/water_vapor][MOLES] += burned_fuel/TRITIUM_BURN_OXY_FACTOR
cached_gases[/datum/gas/water_vapor] += burned_fuel/TRITIUM_BURN_OXY_FACTOR
cached_results["fire"] += burned_fuel
@@ -157,23 +156,21 @@
temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE)
if(temperature_scale > 0)
oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - temperature_scale
if(cached_gases[/datum/gas/oxygen][MOLES] / cached_gases[/datum/gas/plasma][MOLES] > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium.
if(cached_gases[/datum/gas/oxygen] / cached_gases[/datum/gas/plasma] > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium.
super_saturation = TRUE
if(cached_gases[/datum/gas/oxygen][MOLES] > 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(cached_gases[/datum/gas/oxygen] > cached_gases[/datum/gas/plasma]*PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (cached_gases[/datum/gas/plasma]*temperature_scale)/PLASMA_BURN_RATE_DELTA
else
plasma_burn_rate = (temperature_scale*(cached_gases[/datum/gas/oxygen][MOLES]/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
plasma_burn_rate = (temperature_scale*(cached_gases[/datum/gas/oxygen]/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY)
plasma_burn_rate = min(plasma_burn_rate,cached_gases[/datum/gas/plasma][MOLES],cached_gases[/datum/gas/oxygen][MOLES]/oxygen_burn_rate) //Ensures matter is conserved properly
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))
plasma_burn_rate = min(plasma_burn_rate,cached_gases[/datum/gas/plasma],cached_gases[/datum/gas/oxygen]/oxygen_burn_rate) //Ensures matter is conserved properly
cached_gases[/datum/gas/plasma] = QUANTIZE(cached_gases[/datum/gas/plasma] - plasma_burn_rate)
cached_gases[/datum/gas/oxygen] = QUANTIZE(cached_gases[/datum/gas/oxygen] - (plasma_burn_rate * oxygen_burn_rate))
if (super_saturation)
ASSERT_GAS(/datum/gas/tritium,air)
cached_gases[/datum/gas/tritium][MOLES] += plasma_burn_rate
cached_gases[/datum/gas/tritium] += plasma_burn_rate
else
ASSERT_GAS(/datum/gas/carbon_dioxide,air)
cached_gases[/datum/gas/carbon_dioxide][MOLES] += plasma_burn_rate
cached_gases[/datum/gas/carbon_dioxide] += plasma_burn_rate
energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
@@ -231,21 +228,21 @@
var/old_heat_capacity = air.heat_capacity()
var/reaction_energy = 0
var/mediation = FUSION_MEDIATION_FACTOR*(air.heat_capacity()-(cached_gases[/datum/gas/plasma][MOLES]*cached_gases[/datum/gas/plasma][GAS_META][META_GAS_SPECIFIC_HEAT]))/(air.total_moles()-cached_gases[/datum/gas/plasma][MOLES]) //This is the average specific heat of the mixture,not including plasma.
var/mediation = FUSION_MEDIATION_FACTOR*(air.heat_capacity()-(cached_gases[/datum/gas/plasma]*GLOB.meta_gas_specific_heats[/datum/gas/plasma]))/(air.total_moles()-cached_gases[/datum/gas/plasma]) //This is the average specific heat of the mixture,not including plasma.
var/gases_fused = air.total_moles() - cached_gases[/datum/gas/plasma][MOLES]
var/plasma_differential = (cached_gases[/datum/gas/plasma][MOLES] - gases_fused) / air.total_moles()
var/gases_fused = air.total_moles() - cached_gases[/datum/gas/plasma]
var/plasma_differential = (cached_gases[/datum/gas/plasma] - gases_fused) / air.total_moles()
var/reaction_efficiency = FUSION_EFFICIENCY_BASE ** -((plasma_differential ** 2) / FUSION_EFFICIENCY_DIVISOR) //https://www.desmos.com/calculator/6jjx3vdrvx
var/gas_power = 0
for (var/gas_id in cached_gases)
gas_power += reaction_efficiency * (cached_gases[gas_id][GAS_META][META_GAS_FUSION_POWER]*cached_gases[gas_id][MOLES])
gas_power += reaction_efficiency * (GLOB.meta_gas_fusions[gas_id]*cached_gases[gas_id])
var/power_ratio = gas_power/mediation
cached_scan_results[id] = power_ratio //used for analyzer feedback
for (var/gas_id in cached_gases) //and now we fuse
cached_gases[gas_id][MOLES] = 0
cached_gases[gas_id] = 0
var/radiation_power = (FUSION_RADIATION_FACTOR * power_ratio) / (power_ratio + FUSION_RADIATION_CONSTANT) //https://www.desmos.com/calculator/4i1f296phl
var/zap_power = ((FUSION_ZAP_POWER_ASYMPTOTE * power_ratio) / (power_ratio + FUSION_ZAP_POWER_CONSTANT)) + FUSION_ZAP_POWER_BASE //https://www.desmos.com/calculator/n0zkdpxnrr
@@ -255,33 +252,30 @@
if (power_ratio > FUSION_SUPER_TIER_THRESHOLD) //power ratio 50+: SUPER TIER. The gases become so energized that they fuse into a ton of tritium, which is pretty nice! Until you consider the fact that everything just exploded, the canister is probably going to break and you're irradiated.
reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_SUPER * (power_ratio / FUSION_ENERGY_DIVISOR_SUPER)
cached_gases[/datum/gas/tritium][MOLES] += gases_fused * FUSION_GAS_CREATION_FACTOR_TRITIUM //60% of the gas is converted to energy, 40% to trit
cached_gases[/datum/gas/tritium] += gases_fused * FUSION_GAS_CREATION_FACTOR_TRITIUM //60% of the gas is converted to energy, 40% to trit
fusion_prepare_to_die_edition_rng = 100 //Wait a minute..
do_explosion = TRUE
zap_range = FUSION_ZAP_RANGE_SUPER
else if (power_ratio > FUSION_HIGH_TIER_THRESHOLD) //power ratio 20-50; High tier. The reaction is so energized that it fuses into a small amount of stimulum, and some pluoxium. Very dangerous, but super cool and super useful.
reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_HIGH * (power_ratio / FUSION_ENERGY_DIVISOR_HIGH)
air.assert_gases(/datum/gas/stimulum, /datum/gas/pluoxium)
cached_gases[/datum/gas/stimulum][MOLES] += gases_fused * FUSION_GAS_CREATION_FACTOR_STIM //40% of the gas is converted to energy, 60% to stim and pluox
cached_gases[/datum/gas/pluoxium][MOLES] += gases_fused * FUSION_GAS_CREATION_FACTOR_PLUOX
cached_gases[/datum/gas/stimulum] += gases_fused * FUSION_GAS_CREATION_FACTOR_STIM //40% of the gas is converted to energy, 60% to stim and pluox
cached_gases[/datum/gas/pluoxium] += gases_fused * FUSION_GAS_CREATION_FACTOR_PLUOX
fusion_prepare_to_die_edition_rng = power_ratio //Now we're getting into dangerous territory
do_explosion = TRUE
zap_range = FUSION_ZAP_RANGE_HIGH
else if (power_ratio > FUSION_MID_TIER_THRESHOLD) //power_ratio 5 to 20; Mediation is overpowered, fusion reaction starts to break down.
reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_MID * (power_ratio / FUSION_ENERGY_DIVISOR_MID)
air.assert_gases(/datum/gas/nitryl,/datum/gas/nitrous_oxide)
cached_gases[/datum/gas/nitryl][MOLES] += gases_fused * FUSION_GAS_CREATION_FACTOR_NITRYL //20% of the gas is converted to energy, 80% to nitryl and N2O
cached_gases[/datum/gas/nitrous_oxide][MOLES] += gases_fused * FUSION_GAS_CREATION_FACTOR_N2O
cached_gases[/datum/gas/nitryl] += gases_fused * FUSION_GAS_CREATION_FACTOR_NITRYL //20% of the gas is converted to energy, 80% to nitryl and N2O
cached_gases[/datum/gas/nitrous_oxide] += gases_fused * FUSION_GAS_CREATION_FACTOR_N2O
fusion_prepare_to_die_edition_rng = power_ratio * FUSION_MID_TIER_RAD_PROB_FACTOR //Still unlikely, but don't stand next to the reaction unprotected
zap_range = FUSION_ZAP_RANGE_MID
else //power ratio 0 to 5; Gas power is overpowered. Fusion isn't nearly as powerful.
reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_LOW * (power_ratio / FUSION_ENERGY_DIVISOR_LOW)
air.assert_gases(/datum/gas/bz, /datum/gas/carbon_dioxide)
cached_gases[/datum/gas/bz][MOLES] += gases_fused * FUSION_GAS_CREATION_FACTOR_BZ //10% of the gas is converted to energy, 90% to BZ and CO2
cached_gases[/datum/gas/carbon_dioxide][MOLES] += gases_fused * FUSION_GAS_CREATION_FACTOR_CO2
cached_gases[/datum/gas/bz] += gases_fused * FUSION_GAS_CREATION_FACTOR_BZ //10% of the gas is converted to energy, 90% to BZ and CO2
cached_gases[/datum/gas/carbon_dioxide] += gases_fused * FUSION_GAS_CREATION_FACTOR_CO2
fusion_prepare_to_die_edition_rng = power_ratio * FUSION_LOW_TIER_RAD_PROB_FACTOR //Low, but still something to look out for
zap_range = FUSION_ZAP_RANGE_LOW
@@ -291,6 +285,7 @@
if(do_explosion)
explosion(location, 0, 0, 5, power_ratio, TRUE, TRUE) //large shockwave, the actual radius is quite small - people will recognize that you're doing fusion
radiation_pulse(location, radiation_power) //You mean causing a super-tier fusion reaction in the halls is a bad idea?
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, 30000)//The science is cool though.
playsound(location, 'sound/effects/supermatter.ogg', 100, 0)
else
playsound(location, 'sound/effects/phasein.ogg', 75, 0)
@@ -322,14 +317,13 @@
var/temperature = air.temperature
var/old_heat_capacity = air.heat_capacity()
var/heat_efficency = min(temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100),cached_gases[/datum/gas/oxygen][MOLES],cached_gases[/datum/gas/nitrogen][MOLES])
var/heat_efficency = min(temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100),cached_gases[/datum/gas/oxygen],cached_gases[/datum/gas/nitrogen])
var/energy_used = heat_efficency*NITRYL_FORMATION_ENERGY
ASSERT_GAS(/datum/gas/nitryl,air)
if ((cached_gases[/datum/gas/oxygen][MOLES] - heat_efficency < 0 )|| (cached_gases[/datum/gas/nitrogen][MOLES] - heat_efficency < 0)) //Shouldn't produce gas from nothing.
if ((cached_gases[/datum/gas/oxygen] - heat_efficency < 0 )|| (cached_gases[/datum/gas/nitrogen] - heat_efficency < 0)) //Shouldn't produce gas from nothing.
return NO_REACTION
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
cached_gases[/datum/gas/oxygen] -= heat_efficency
cached_gases[/datum/gas/nitrogen] -= heat_efficency
cached_gases[/datum/gas/nitryl] += heat_efficency*2
if(energy_used > 0)
var/new_heat_capacity = air.heat_capacity()
@@ -355,15 +349,22 @@
var/pressure = air.return_pressure()
var/old_heat_capacity = air.heat_capacity()
var/reaction_efficency = min(1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(cached_gases[/datum/gas/plasma][MOLES]/cached_gases[/datum/gas/nitrous_oxide][MOLES],1))),cached_gases[/datum/gas/nitrous_oxide][MOLES],cached_gases[/datum/gas/plasma][MOLES]/2)
var/reaction_efficency = min(1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(cached_gases[/datum/gas/plasma]/cached_gases[/datum/gas/nitrous_oxide],1))),cached_gases[/datum/gas/nitrous_oxide],cached_gases[/datum/gas/plasma]/2)
var/energy_released = 2*reaction_efficency*FIRE_CARBON_ENERGY_RELEASED
if ((cached_gases[/datum/gas/nitrous_oxide][MOLES] - reaction_efficency < 0 )|| (cached_gases[/datum/gas/plasma][MOLES] - (2*reaction_efficency) < 0)) //Shouldn't produce gas from nothing.
if(cached_gases[/datum/gas/miasma] && cached_gases[/datum/gas/miasma] > 0)
energy_released /= cached_gases[/datum/gas/miasma]*0.1
if(cached_gases[/datum/gas/bz] && cached_gases[/datum/gas/bz] > 0)
energy_released *= cached_gases[/datum/gas/bz]*0.1
if ((cached_gases[/datum/gas/nitrous_oxide] - reaction_efficency < 0 )|| (cached_gases[/datum/gas/plasma] - (2*reaction_efficency) < 0)) //Shouldn't produce gas from nothing.
return NO_REACTION
ASSERT_GAS(/datum/gas/bz,air)
cached_gases[/datum/gas/bz][MOLES] += reaction_efficency
cached_gases[/datum/gas/nitrous_oxide][MOLES] -= reaction_efficency
cached_gases[/datum/gas/plasma][MOLES] -= 2*reaction_efficency
cached_gases[/datum/gas/bz] += reaction_efficency
if(reaction_efficency == cached_gases[/datum/gas/nitrous_oxide])
cached_gases[/datum/gas/bz] -= min(pressure,1)
cached_gases[/datum/gas/oxygen] += min(pressure,1)
cached_gases[/datum/gas/nitrous_oxide] -= reaction_efficency
cached_gases[/datum/gas/plasma] -= 2*reaction_efficency
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, (reaction_efficency**0.5)*BZ_RESEARCH_AMOUNT)
if(energy_released > 0)
var/new_heat_capacity = air.heat_capacity()
@@ -388,17 +389,17 @@
var/list/cached_gases = air.gases
var/old_heat_capacity = air.heat_capacity()
var/heat_scale = min(air.temperature/STIMULUM_HEAT_SCALE,cached_gases[/datum/gas/tritium][MOLES],cached_gases[/datum/gas/plasma][MOLES],cached_gases[/datum/gas/nitryl][MOLES])
var/heat_scale = min(air.temperature/STIMULUM_HEAT_SCALE,cached_gases[/datum/gas/tritium],cached_gases[/datum/gas/plasma],cached_gases[/datum/gas/nitryl])
var/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)
if ((cached_gases[/datum/gas/tritium][MOLES] - heat_scale < 0 )|| (cached_gases[/datum/gas/plasma][MOLES] - heat_scale < 0) || (cached_gases[/datum/gas/nitryl][MOLES] - heat_scale < 0)) //Shouldn't produce gas from nothing.
if ((cached_gases[/datum/gas/tritium] - heat_scale < 0 )|| (cached_gases[/datum/gas/plasma] - heat_scale < 0) || (cached_gases[/datum/gas/nitryl] - heat_scale < 0)) //Shouldn't produce gas from nothing.
return NO_REACTION
cached_gases[/datum/gas/stimulum][MOLES]+= heat_scale/10
cached_gases[/datum/gas/tritium][MOLES] -= heat_scale
cached_gases[/datum/gas/plasma][MOLES] -= heat_scale
cached_gases[/datum/gas/nitryl][MOLES] -= heat_scale
cached_gases[/datum/gas/stimulum]+= heat_scale/10
cached_gases[/datum/gas/tritium] -= heat_scale
cached_gases[/datum/gas/plasma] -= heat_scale
cached_gases[/datum/gas/nitryl] -= heat_scale
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, STIMULUM_RESEARCH_AMOUNT*max(stim_energy_change,0))
if(stim_energy_change)
var/new_heat_capacity = air.heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
@@ -418,16 +419,16 @@
/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 = min((cached_gases[/datum/gas/nitrogen][MOLES]+cached_gases[/datum/gas/tritium][MOLES])/100,cached_gases[/datum/gas/tritium][MOLES]/10,cached_gases[/datum/gas/nitrogen][MOLES]/20)
var/energy_taken = nob_formed*(NOBLIUM_FORMATION_ENERGY/(max(cached_gases[/datum/gas/bz][MOLES],1)))
if ((cached_gases[/datum/gas/tritium][MOLES] - 10*nob_formed < 0) || (cached_gases[/datum/gas/nitrogen][MOLES] - 20*nob_formed < 0))
var/nob_formed = min((cached_gases[/datum/gas/nitrogen]+cached_gases[/datum/gas/tritium])/100,cached_gases[/datum/gas/tritium]/10,cached_gases[/datum/gas/nitrogen]/20)
var/energy_taken = nob_formed*(NOBLIUM_FORMATION_ENERGY/(max(cached_gases[/datum/gas/bz],1)))
if ((cached_gases[/datum/gas/tritium] - 10*nob_formed < 0) || (cached_gases[/datum/gas/nitrogen] - 20*nob_formed < 0))
return NO_REACTION
cached_gases[/datum/gas/tritium][MOLES] -= 10*nob_formed
cached_gases[/datum/gas/nitrogen][MOLES] -= 20*nob_formed
cached_gases[/datum/gas/hypernoblium][MOLES]+= nob_formed
cached_gases[/datum/gas/tritium] -= 10*nob_formed
cached_gases[/datum/gas/nitrogen] -= 20*nob_formed
cached_gases[/datum/gas/hypernoblium]+= nob_formed
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, nob_formed*NOBLIUM_RESEARCH_AMOUNT)
if (nob_formed)
var/new_heat_capacity = air.heat_capacity()
@@ -449,14 +450,14 @@
/datum/gas_reaction/miaster/react(datum/gas_mixture/air, datum/holder)
var/list/cached_gases = air.gases
// As the name says it, it needs to be dry
if(cached_gases[/datum/gas/water_vapor] && cached_gases[/datum/gas/water_vapor][MOLES]/air.total_moles() > 0.1)
if(cached_gases[/datum/gas/water_vapor] && cached_gases[/datum/gas/water_vapor]/air.total_moles() > 0.1)
return
//Replace miasma with oxygen
var/cleaned_air = min(cached_gases[/datum/gas/miasma][MOLES], 20 + (air.temperature - FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20)
cached_gases[/datum/gas/miasma][MOLES] -= cleaned_air
ASSERT_GAS(/datum/gas/oxygen,air)
cached_gases[/datum/gas/oxygen][MOLES] += cleaned_air
var/cleaned_air = min(cached_gases[/datum/gas/miasma], 20 + (air.temperature - FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20)
cached_gases[/datum/gas/miasma] -= cleaned_air
cached_gases[/datum/gas/oxygen] += cleaned_air
//Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable
air.temperature += cleaned_air * 0.002
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, cleaned_air*MIASMA_RESEARCH_AMOUNT)//Turns out the burning of miasma is kinda interesting to scientists
File diff suppressed because it is too large Load Diff
@@ -28,6 +28,30 @@ Thus, the two variables affect pump operation are set in New():
construction_type = /obj/item/pipe/directional
pipe_state = "pump"
/obj/machinery/atmospherics/components/binary/pump/examine(mob/user)
. = ..()
to_chat(user,"<span class='notice'>You can hold <b>Ctrl</b> and click on it to toggle it on and off.</span>")
to_chat(user,"<span class='notice'>You can hold <b>Alt</b> and click on it to maximize its pressure.</span>")
/obj/machinery/atmospherics/components/binary/pump/CtrlClick(mob/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
on = !on
update_icon()
investigate_log("Pump, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
return ..()
/obj/machinery/atmospherics/components/binary/pump/AltClick(mob/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
target_pressure = MAX_OUTPUT_PRESSURE
to_chat(user,"<span class='notice'>You maximize the pressure on the [src].</span>")
investigate_log("Pump, [src.name], was maximized by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Pump, [src.name], was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
/obj/machinery/atmospherics/components/binary/pump/layer1
piping_layer = PIPING_LAYER_MIN
pixel_x = -PIPING_LAYER_P_X
@@ -28,6 +28,21 @@ Thus, the two variables affect pump operation are set in New():
construction_type = /obj/item/pipe/directional
pipe_state = "volumepump"
/obj/machinery/atmospherics/components/binary/volume_pump/examine(mob/user)
. = ..()
to_chat(user,"<span class='notice'>You can hold <b>Ctrl</b> and click on it to toggle it on and off.</span>")
to_chat(user,"<span class='notice'>You can hold <b>Alt</b> and click on it to maximize its pressure.</span>")
/obj/machinery/atmospherics/components/binary/volume_pump/CtrlClick(mob/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
on = !on
update_icon()
investigate_log("Volume Pump, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Volume Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
return ..()
/obj/machinery/atmospherics/components/binary/volume_pump/layer1
piping_layer = PIPING_LAYER_MIN
pixel_x = -PIPING_LAYER_P_X
@@ -192,4 +207,4 @@ Thus, the two variables affect pump operation are set in New():
else
investigate_log("Pump, [src.name], was unwrenched by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Pump, [src.name], was unwrenched by [ADMIN_LOOKUPFLW(user)] at [A]")
return TRUE
return TRUE
@@ -12,6 +12,30 @@
construction_type = /obj/item/pipe/trinary/flippable
pipe_state = "filter"
/obj/machinery/atmospherics/components/trinary/filter/examine(mob/user)
. = ..()
to_chat(user,"<span class='notice'>You can hold <b>Ctrl</b> and click on it to toggle it on and off.</span>")
to_chat(user,"<span class='notice'>You can hold <b>Alt</b> and click on it to maximize its pressure.</span>")
/obj/machinery/atmospherics/components/trinary/filter/CtrlClick(mob/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
on = !on
update_icon()
investigate_log("Filter, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Filter, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
return ..()
/obj/machinery/atmospherics/components/trinary/filter/AltClick(mob/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
target_pressure = MAX_OUTPUT_PRESSURE
to_chat(user,"<span class='notice'>You maximize the pressure on the [src].</span>")
investigate_log("Filter, [src.name], was maximized by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Filter, [src.name], was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
/obj/machinery/atmospherics/components/trinary/filter/layer1
piping_layer = PIPING_LAYER_MIN
pixel_x = -PIPING_LAYER_P_X
@@ -159,11 +183,10 @@
var/datum/gas_mixture/filtered_out = new
filtered_out.temperature = removed.temperature
filtered_out.add_gas(filter_type)
filtered_out.gases[filter_type][MOLES] = removed.gases[filter_type][MOLES]
filtered_out.gases[filter_type] = removed.gases[filter_type]
removed.gases[filter_type][MOLES] = 0
removed.garbage_collect()
removed.gases[filter_type] = 0
GAS_GARBAGE_COLLECT(removed.gases)
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)
@@ -191,9 +214,8 @@
data["filter_types"] = list()
data["filter_types"] += list(list("name" = "Nothing", "path" = "", "selected" = !filter_type))
for(var/path in GLOB.meta_gas_info)
var/list/gas = GLOB.meta_gas_info[path]
data["filter_types"] += list(list("name" = gas[META_GAS_NAME], "id" = gas[META_GAS_ID], "selected" = (path == gas_id2path(filter_type))))
for(var/path in GLOB.meta_gas_ids)
data["filter_types"] += list(list("name" = GLOB.meta_gas_names[path], "id" = GLOB.meta_gas_ids[path], "selected" = (path == gas_id2path(filter_type))))
return data
@@ -224,9 +246,9 @@
filter_type = null
var/filter_name = "nothing"
var/gas = gas_id2path(params["mode"])
if(gas in GLOB.meta_gas_info)
if(gas in GLOB.meta_gas_names)
filter_type = gas
filter_name = GLOB.meta_gas_info[gas][META_GAS_NAME]
filter_name = GLOB.meta_gas_names[gas]
investigate_log("was set to filter [filter_name] by [key_name(usr)]", INVESTIGATE_ATMOS)
. = TRUE
update_icon()
@@ -14,7 +14,31 @@
pipe_state = "mixer"
//node 3 is the outlet, nodes 1 & 2 are intakes
/obj/machinery/atmospherics/components/trinary/mixer/examine(mob/user)
. = ..()
to_chat(user,"<span class='notice'>You can hold <b>Ctrl</b> and click on it to toggle it on and off.</span>")
to_chat(user,"<span class='notice'>You can hold <b>Alt</b> and click on it to maximize its pressure.</span>")
/obj/machinery/atmospherics/components/trinary/mixer/CtrlClick(mob/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
on = !on
update_icon()
investigate_log("Mixer, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Mixer, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
return ..()
/obj/machinery/atmospherics/components/trinary/mixer/AltClick(mob/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
target_pressure = MAX_OUTPUT_PRESSURE
to_chat(user,"<span class='notice'>You maximize the pressure on the [src].</span>")
investigate_log("Mixer, [src.name], was maximized by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
message_admins("Mixer, [src.name], was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
//node 3 is the outlet, nodes 1 & 2 are intakes
/obj/machinery/atmospherics/components/trinary/mixer/layer1
piping_layer = PIPING_LAYER_MIN
pixel_x = -PIPING_LAYER_P_X
@@ -167,10 +167,11 @@
on = FALSE
update_icon()
playsound(src, 'sound/machines/cryo_warning.ogg', volume) // Bug the doctors.
radio.talk_into(src, "Patient fully restored", radio_channel, get_spans(), get_default_language())
var/msg = "Patient fully restored."
if(autoeject) // Eject if configured.
radio.talk_into(src, "Auto ejecting patient now", radio_channel, get_spans(), get_default_language())
msg += " Auto ejecting patient now."
open_machine()
radio.talk_into(src, msg, radio_channel)
return
var/datum/gas_mixture/air1 = airs[1]
@@ -183,8 +184,8 @@
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
beaker.reagents.trans_to(occupant, 1, efficiency * 0.25) // Transfer reagents.
beaker.reagents.reaction(occupant, VAPOR)
air1.gases[/datum/gas/oxygen][MOLES] -= max(0,air1.gases[/datum/gas/oxygen][MOLES] - 2 / efficiency) //Let's use gas for this
air1.garbage_collect()
air1.gases[/datum/gas/oxygen] -= max(0,air1.gases[/datum/gas/oxygen] - 2 / efficiency) //Let's use gas for this
GAS_GARBAGE_COLLECT(air1.gases)
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
reagent_transfer = 0
@@ -198,7 +199,7 @@
var/datum/gas_mixture/air1 = airs[1]
if(!nodes[1] || !airs[1] || !air1.gases.len || air1.gases[/datum/gas/oxygen][MOLES] < 5) // Turn off if the machine won't work.
if(!nodes[1] || !airs[1] || !air1.gases.len || air1.gases[/datum/gas/oxygen] < 5) // Turn off if the machine won't work.
on = FALSE
update_icon()
return
@@ -220,8 +221,8 @@
air1.temperature = max(air1.temperature - heat / air_heat_capacity, TCMB)
mob_occupant.adjust_bodytemperature(heat / heat_capacity, TCMB)
air1.gases[/datum/gas/oxygen][MOLES] = max(0,air1.gases[/datum/gas/oxygen][MOLES] - 0.5 / efficiency) // Magically consume gas? Why not, we run on cryo magic.
air1.garbage_collect()
air1.gases[/datum/gas/oxygen] = max(0,air1.gases[/datum/gas/oxygen] - 0.5 / efficiency) // Magically consume gas? Why not, we run on cryo magic.
GAS_GARBAGE_COLLECT(air1.gases)
/obj/machinery/atmospherics/components/unary/cryo_cell/power_change()
..()
@@ -17,9 +17,8 @@
air_contents.volume = volume
air_contents.temperature = T20C
if(gas_type)
air_contents.assert_gas(gas_type)
air_contents.gases[gas_type][MOLES] = AIR_CONTENTS
name = "[name] ([air_contents.gases[gas_type][GAS_META][META_GAS_NAME]])"
air_contents.gases[gas_type] = AIR_CONTENTS
name = "[name] ([GLOB.meta_gas_names[gas_type]])"
/obj/machinery/atmospherics/components/unary/tank/carbon_dioxide
gas_type = /datum/gas/carbon_dioxide
@@ -44,6 +43,5 @@
/obj/machinery/atmospherics/components/unary/tank/air/New()
..()
var/datum/gas_mixture/air_contents = airs[1]
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
air_contents.gases[/datum/gas/oxygen] = AIR_CONTENTS * 0.2
air_contents.gases[/datum/gas/nitrogen] = AIR_CONTENTS * 0.8
@@ -1,18 +1,22 @@
/obj/machinery/atmospherics/components/unary/thermomachine
name = "thermomachine"
desc = "Heats or cools gas in connected pipes."
icon = 'icons/obj/atmospherics/components/thermomachine.dmi'
icon_state = "freezer"
var/icon_state_off = "freezer"
var/icon_state_on = "freezer_1"
var/icon_state_open = "freezer-o"
name = "thermomachine"
desc = "Heats or cools gas in connected pipes."
density = TRUE
max_integrity = 300
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/icon_state_off = "freezer"
var/icon_state_on = "freezer_1"
var/icon_state_open = "freezer-o"
var/min_temperature = 0
var/max_temperature = 0
var/target_temperature = T20C
@@ -45,6 +49,13 @@
if(showpipe)
add_overlay(getpipeimage(icon, "scrub_cap", initialize_directions))
/obj/machinery/atmospherics/components/unary/thermomachine/examine(mob/user)
. = ..()
. += "<span class='notice'>The thermostat is set to [target_temperature]K ([(T0C-target_temperature)*-1]C).</span>"
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Efficiency <b>[(heat_capacity/5000)*100]%</b>.</span>"
. += "<span class='notice'>Temperature range <b>[min_temperature]K - [max_temperature]K ([(T0C-min_temperature)*-1]C - [(T0C-max_temperature)*-1]C)</b>.</span>"
/obj/machinery/atmospherics/components/unary/thermomachine/process_atmos()
..()
if(!on || !nodes[1])
@@ -155,6 +166,16 @@
update_icon()
/obj/machinery/atmospherics/components/unary/thermomachine/CtrlClick(mob/living/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
return
on = !on
update_icon()
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", INVESTIGATE_ATMOS)
message_admins("[src.name] was turned [on ? "on" : "off"] [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
/obj/machinery/atmospherics/components/unary/thermomachine/freezer
name = "freezer"
icon_state = "freezer"
@@ -174,6 +195,13 @@
if(target_temperature == initial(target_temperature))
target_temperature = min_temperature
/obj/machinery/atmospherics/components/unary/thermomachine/freezer/on/coldroom
name = "cold room freezer"
/obj/machinery/atmospherics/components/unary/thermomachine/freezer/on/coldroom/Initialize()
. = ..()
target_temperature = T0C-80
/obj/machinery/atmospherics/components/unary/thermomachine/freezer/RefreshParts()
..()
var/L
@@ -181,6 +209,15 @@
L += M.rating
min_temperature = max(T0C - (initial(min_temperature) + L * 15), TCMB) //73.15K with T1 stock parts
/obj/machinery/atmospherics/components/unary/thermomachine/freezer/AltClick(mob/living/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
return
target_temperature = min_temperature
investigate_log("was set to [target_temperature] K by [key_name(usr)]", INVESTIGATE_ATMOS)
message_admins("[src.name] was minimized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
/obj/machinery/atmospherics/components/unary/thermomachine/heater
name = "heater"
icon_state = "heater"
@@ -201,3 +238,12 @@
for(var/obj/item/stock_parts/micro_laser/M in component_parts)
L += M.rating
max_temperature = T20C + (initial(max_temperature) * L) //573.15K with T1 stock parts
/obj/machinery/atmospherics/components/unary/thermomachine/heater/AltClick(mob/living/user)
var/area/A = get_area(src)
var/turf/T = get_turf(src)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
return
target_temperature = max_temperature
investigate_log("was set to [target_temperature] K by [key_name(usr)]", INVESTIGATE_ATMOS)
message_admins("[src.name] was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
@@ -1,330 +1,328 @@
#define SIPHONING 0
#define SCRUBBING 1
/obj/machinery/atmospherics/components/unary/vent_scrubber
name = "air scrubber"
desc = "Has a valve and pump attached to it."
icon_state = "scrub_map"
use_power = IDLE_POWER_USE
idle_power_usage = 10
active_power_usage = 60
can_unwrench = TRUE
welded = FALSE
level = 1
layer = GAS_SCRUBBER_LAYER
var/id_tag = null
var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing
var/filter_types = list(/datum/gas/carbon_dioxide)
var/volume_rate = 200
var/widenet = 0 //is this scrubber acting on the 3x3 area around it.
var/list/turf/adjacent_turfs = list()
var/frequency = FREQ_ATMOS_CONTROL
var/datum/radio_frequency/radio_connection
var/radio_filter_out
var/radio_filter_in
pipe_state = "scrubber"
/obj/machinery/atmospherics/components/unary/vent_scrubber/layer1
piping_layer = PIPING_LAYER_MIN
pixel_x = -PIPING_LAYER_P_X
pixel_y = -PIPING_LAYER_P_Y
/obj/machinery/atmospherics/components/unary/vent_scrubber/layer3
piping_layer = PIPING_LAYER_MAX
pixel_x = PIPING_LAYER_P_X
pixel_y = PIPING_LAYER_P_Y
/obj/machinery/atmospherics/components/unary/vent_scrubber/New()
..()
if(!id_tag)
id_tag = assign_uid_vents()
for(var/f in filter_types)
if(istext(f))
filter_types -= f
filter_types += gas_id2path(f)
/obj/machinery/atmospherics/components/unary/vent_scrubber/on
on = TRUE
icon_state = "scrub_map_on"
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer1
piping_layer = PIPING_LAYER_MIN
pixel_x = -PIPING_LAYER_P_X
pixel_y = -PIPING_LAYER_P_Y
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3
piping_layer = PIPING_LAYER_MAX
pixel_x = PIPING_LAYER_P_X
pixel_y = PIPING_LAYER_P_Y
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
var/area/A = get_area(src)
if (A)
A.air_scrub_names -= id_tag
A.air_scrub_info -= id_tag
SSradio.remove_object(src,frequency)
radio_connection = null
adjacent_turfs.Cut()
return ..()
/obj/machinery/atmospherics/components/unary/vent_scrubber/auto_use_power()
if(!on || welded || !is_operational() || !powered(power_channel))
return FALSE
var/amount = idle_power_usage
if(scrubbing & SCRUBBING)
amount += idle_power_usage * length(filter_types)
else //scrubbing == SIPHONING
amount = active_power_usage
if(widenet)
amount += amount * (adjacent_turfs.len * (adjacent_turfs.len / 2))
use_power(amount, power_channel)
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/update_icon_nopipes()
cut_overlays()
if(showpipe)
add_overlay(getpipeimage(icon, "scrub_cap", initialize_directions))
if(welded)
icon_state = "scrub_welded"
return
if(!nodes[1] || !on || !is_operational())
icon_state = "scrub_off"
return
if(scrubbing & SCRUBBING)
if(widenet)
icon_state = "scrub_wide"
else
icon_state = "scrub_on"
else //scrubbing == SIPHONING
icon_state = "scrub_purge"
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
radio_connection = SSradio.add_object(src, frequency, radio_filter_in)
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/broadcast_status()
if(!radio_connection)
return FALSE
var/list/f_types = list()
for(var/path in GLOB.meta_gas_info)
var/list/gas = GLOB.meta_gas_info[path]
f_types += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in filter_types)))
var/datum/signal/signal = new(list(
"tag" = id_tag,
"frequency" = frequency,
"device" = "VS",
"timestamp" = world.time,
"power" = on,
"scrubbing" = scrubbing,
"widenet" = widenet,
"filter_types" = f_types,
"sigtype" = "status"
))
var/area/A = get_area(src)
if(!A.air_scrub_names[id_tag])
name = "\improper [A.name] air scrubber #[A.air_scrub_names.len + 1]"
A.air_scrub_names[id_tag] = name
A.air_scrub_info[id_tag] = signal.data
radio_connection.post_signal(src, signal, radio_filter_out)
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/atmosinit()
radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null
radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null
if(frequency)
set_frequency(frequency)
broadcast_status()
check_turfs()
..()
/obj/machinery/atmospherics/components/unary/vent_scrubber/process_atmos()
..()
if(welded || !is_operational())
return FALSE
if(!nodes[1] || !on)
on = FALSE
return FALSE
scrub(loc)
if(widenet)
for(var/turf/tile in adjacent_turfs)
scrub(tile)
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/scrub(var/turf/tile)
if(!istype(tile))
return FALSE
var/datum/gas_mixture/environment = tile.return_air()
var/datum/gas_mixture/air_contents = airs[1]
var/list/env_gases = environment.gases
if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE)
return FALSE
if(scrubbing & SCRUBBING)
if(length(env_gases & filter_types))
var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles()
//Take a gas sample
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
//Nothing left to remove from the tile
if(isnull(removed))
return FALSE
var/list/removed_gases = removed.gases
//Filter it
var/datum/gas_mixture/filtered_out = new
var/list/filtered_gases = filtered_out.gases
filtered_out.temperature = removed.temperature
for(var/gas in filter_types & removed_gases)
filtered_out.add_gas(gas)
filtered_gases[gas][MOLES] = removed_gases[gas][MOLES]
removed_gases[gas][MOLES] = 0
removed.garbage_collect()
//Remix the resulting gases
air_contents.merge(filtered_out)
tile.assume_air(removed)
tile.air_update_turf()
else //Just siphoning all air
var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume)
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
air_contents.merge(removed)
tile.air_update_turf()
update_parents()
return TRUE
//There is no easy way for an object to be notified of changes to atmos can pass flags
// So we check every machinery process (2 seconds)
/obj/machinery/atmospherics/components/unary/vent_scrubber/process()
if(widenet)
check_turfs()
//we populate a list of turfs with nonatmos-blocked cardinal turfs AND
// diagonal turfs that can share atmos with *both* of the cardinal turfs
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/check_turfs()
adjacent_turfs.Cut()
var/turf/T = get_turf(src)
if(istype(T))
adjacent_turfs = T.GetAtmosAdjacentTurfs(alldir = 1)
/obj/machinery/atmospherics/components/unary/vent_scrubber/receive_signal(datum/signal/signal)
if(!is_operational() || !signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
return 0
var/mob/signal_sender = signal.data["user"]
if("power" in signal.data)
on = text2num(signal.data["power"])
if("power_toggle" in signal.data)
on = !on
if("widenet" in signal.data)
widenet = text2num(signal.data["widenet"])
if("toggle_widenet" in signal.data)
widenet = !widenet
var/old_scrubbing = scrubbing
if("scrubbing" in signal.data)
scrubbing = text2num(signal.data["scrubbing"])
if("toggle_scrubbing" in signal.data)
scrubbing = !scrubbing
if(scrubbing != old_scrubbing)
investigate_log(" was toggled to [scrubbing ? "scrubbing" : "siphon"] mode by [key_name(signal_sender)]",INVESTIGATE_ATMOS)
if("toggle_filter" in signal.data)
filter_types ^= gas_id2path(signal.data["toggle_filter"])
if("set_filters" in signal.data)
filter_types = list()
for(var/gas in signal.data["set_filters"])
filter_types += gas_id2path(gas)
if("init" in signal.data)
name = signal.data["init"]
return
if("status" in signal.data)
broadcast_status()
return //do not update_icon
broadcast_status()
update_icon()
return
/obj/machinery/atmospherics/components/unary/vent_scrubber/power_change()
..()
update_icon_nopipes()
/obj/machinery/atmospherics/components/unary/vent_scrubber/welder_act(mob/living/user, obj/item/I)
if(!I.tool_start_check(user, amount=0))
return TRUE
to_chat(user, "<span class='notice'>Now welding the scrubber.</span>")
if(I.use_tool(src, user, 20, volume=50))
if(!welded)
user.visible_message("[user] welds the scrubber shut.","You weld the scrubber shut.", "You hear welding.")
welded = TRUE
else
user.visible_message("[user] unwelds the scrubber.", "You unweld the scrubber.", "You hear welding.")
welded = FALSE
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_unwrench(mob/user)
. = ..()
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
/obj/machinery/atmospherics/components/unary/vent_scrubber/examine(mob/user)
..()
if(welded)
to_chat(user, "It seems welded shut.")
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_crawl_through()
return !welded
/obj/machinery/atmospherics/components/unary/vent_scrubber/attack_alien(mob/user)
if(!welded || !(do_after(user, 20, target = src)))
return
user.visible_message("[user] furiously claws at [src]!", "You manage to clear away the stuff blocking the scrubber.", "You hear loud scraping noises.")
welded = FALSE
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
playsound(loc, 'sound/weapons/bladeslice.ogg', 100, 1)
#undef SIPHONING
#undef SCRUBBING
#define SIPHONING 0
#define SCRUBBING 1
/obj/machinery/atmospherics/components/unary/vent_scrubber
name = "air scrubber"
desc = "Has a valve and pump attached to it."
icon_state = "scrub_map"
use_power = IDLE_POWER_USE
idle_power_usage = 10
active_power_usage = 60
can_unwrench = TRUE
welded = FALSE
level = 1
layer = GAS_SCRUBBER_LAYER
var/id_tag = null
var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing
var/filter_types = list(/datum/gas/carbon_dioxide)
var/volume_rate = 200
var/widenet = 0 //is this scrubber acting on the 3x3 area around it.
var/list/turf/adjacent_turfs = list()
var/frequency = FREQ_ATMOS_CONTROL
var/datum/radio_frequency/radio_connection
var/radio_filter_out
var/radio_filter_in
pipe_state = "scrubber"
/obj/machinery/atmospherics/components/unary/vent_scrubber/layer1
piping_layer = PIPING_LAYER_MIN
pixel_x = -PIPING_LAYER_P_X
pixel_y = -PIPING_LAYER_P_Y
/obj/machinery/atmospherics/components/unary/vent_scrubber/layer3
piping_layer = PIPING_LAYER_MAX
pixel_x = PIPING_LAYER_P_X
pixel_y = PIPING_LAYER_P_Y
/obj/machinery/atmospherics/components/unary/vent_scrubber/New()
..()
if(!id_tag)
id_tag = assign_uid_vents()
for(var/f in filter_types)
if(istext(f))
filter_types -= f
filter_types += gas_id2path(f)
/obj/machinery/atmospherics/components/unary/vent_scrubber/on
on = TRUE
icon_state = "scrub_map_on"
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer1
piping_layer = PIPING_LAYER_MIN
pixel_x = -PIPING_LAYER_P_X
pixel_y = -PIPING_LAYER_P_Y
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer3
piping_layer = PIPING_LAYER_MAX
pixel_x = PIPING_LAYER_P_X
pixel_y = PIPING_LAYER_P_Y
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
var/area/A = get_area(src)
if (A)
A.air_scrub_names -= id_tag
A.air_scrub_info -= id_tag
SSradio.remove_object(src,frequency)
radio_connection = null
adjacent_turfs.Cut()
return ..()
/obj/machinery/atmospherics/components/unary/vent_scrubber/auto_use_power()
if(!on || welded || !is_operational() || !powered(power_channel))
return FALSE
var/amount = idle_power_usage
if(scrubbing & SCRUBBING)
amount += idle_power_usage * length(filter_types)
else //scrubbing == SIPHONING
amount = active_power_usage
if(widenet)
amount += amount * (adjacent_turfs.len * (adjacent_turfs.len / 2))
use_power(amount, power_channel)
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/update_icon_nopipes()
cut_overlays()
if(showpipe)
add_overlay(getpipeimage(icon, "scrub_cap", initialize_directions))
if(welded)
icon_state = "scrub_welded"
return
if(!nodes[1] || !on || !is_operational())
icon_state = "scrub_off"
return
if(scrubbing & SCRUBBING)
if(widenet)
icon_state = "scrub_wide"
else
icon_state = "scrub_on"
else //scrubbing == SIPHONING
icon_state = "scrub_purge"
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
radio_connection = SSradio.add_object(src, frequency, radio_filter_in)
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/broadcast_status()
if(!radio_connection)
return FALSE
var/list/f_types = list()
for(var/path in GLOB.meta_gas_ids)
f_types += list(list("gas_id" = GLOB.meta_gas_ids[path], "gas_name" = GLOB.meta_gas_names[path], "enabled" = (path in filter_types)))
var/datum/signal/signal = new(list(
"tag" = id_tag,
"frequency" = frequency,
"device" = "VS",
"timestamp" = world.time,
"power" = on,
"scrubbing" = scrubbing,
"widenet" = widenet,
"filter_types" = f_types,
"sigtype" = "status"
))
var/area/A = get_area(src)
if(!A.air_scrub_names[id_tag])
name = "\improper [A.name] air scrubber #[A.air_scrub_names.len + 1]"
A.air_scrub_names[id_tag] = name
A.air_scrub_info[id_tag] = signal.data
radio_connection.post_signal(src, signal, radio_filter_out)
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/atmosinit()
radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null
radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null
if(frequency)
set_frequency(frequency)
broadcast_status()
check_turfs()
..()
/obj/machinery/atmospherics/components/unary/vent_scrubber/process_atmos()
..()
if(welded || !is_operational())
return FALSE
if(!nodes[1] || !on)
on = FALSE
return FALSE
scrub(loc)
if(widenet)
for(var/turf/tile in adjacent_turfs)
scrub(tile)
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/scrub(var/turf/tile)
if(!istype(tile))
return FALSE
var/datum/gas_mixture/environment = tile.return_air()
var/datum/gas_mixture/air_contents = airs[1]
var/list/env_gases = environment.gases
if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE)
return FALSE
if(scrubbing & SCRUBBING)
if(length(env_gases & filter_types))
var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles()
//Take a gas sample
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
//Nothing left to remove from the tile
if(isnull(removed))
return FALSE
var/list/removed_gases = removed.gases
//Filter it
var/datum/gas_mixture/filtered_out = new
var/list/filtered_gases = filtered_out.gases
filtered_out.temperature = removed.temperature
for(var/gas in filter_types & removed_gases)
filtered_gases[gas] = removed_gases[gas]
removed_gases[gas] = 0
GAS_GARBAGE_COLLECT(removed.gases)
//Remix the resulting gases
air_contents.merge(filtered_out)
tile.assume_air(removed)
tile.air_update_turf()
else //Just siphoning all air
var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume)
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
air_contents.merge(removed)
tile.air_update_turf()
update_parents()
return TRUE
//There is no easy way for an object to be notified of changes to atmos can pass flags
// So we check every machinery process (2 seconds)
/obj/machinery/atmospherics/components/unary/vent_scrubber/process()
if(widenet)
check_turfs()
//we populate a list of turfs with nonatmos-blocked cardinal turfs AND
// diagonal turfs that can share atmos with *both* of the cardinal turfs
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/check_turfs()
adjacent_turfs.Cut()
var/turf/T = get_turf(src)
if(istype(T))
adjacent_turfs = T.GetAtmosAdjacentTurfs(alldir = 1)
/obj/machinery/atmospherics/components/unary/vent_scrubber/receive_signal(datum/signal/signal)
if(!is_operational() || !signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
return 0
var/mob/signal_sender = signal.data["user"]
if("power" in signal.data)
on = text2num(signal.data["power"])
if("power_toggle" in signal.data)
on = !on
if("widenet" in signal.data)
widenet = text2num(signal.data["widenet"])
if("toggle_widenet" in signal.data)
widenet = !widenet
var/old_scrubbing = scrubbing
if("scrubbing" in signal.data)
scrubbing = text2num(signal.data["scrubbing"])
if("toggle_scrubbing" in signal.data)
scrubbing = !scrubbing
if(scrubbing != old_scrubbing)
investigate_log(" was toggled to [scrubbing ? "scrubbing" : "siphon"] mode by [key_name(signal_sender)]",INVESTIGATE_ATMOS)
if("toggle_filter" in signal.data)
filter_types ^= gas_id2path(signal.data["toggle_filter"])
if("set_filters" in signal.data)
filter_types = list()
for(var/gas in signal.data["set_filters"])
filter_types += gas_id2path(gas)
if("init" in signal.data)
name = signal.data["init"]
return
if("status" in signal.data)
broadcast_status()
return //do not update_icon
broadcast_status()
update_icon()
return
/obj/machinery/atmospherics/components/unary/vent_scrubber/power_change()
..()
update_icon_nopipes()
/obj/machinery/atmospherics/components/unary/vent_scrubber/welder_act(mob/living/user, obj/item/I)
if(!I.tool_start_check(user, amount=0))
return TRUE
to_chat(user, "<span class='notice'>Now welding the scrubber.</span>")
if(I.use_tool(src, user, 20, volume=50))
if(!welded)
user.visible_message("[user] welds the scrubber shut.","You weld the scrubber shut.", "You hear welding.")
welded = TRUE
else
user.visible_message("[user] unwelds the scrubber.", "You unweld the scrubber.", "You hear welding.")
welded = FALSE
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_unwrench(mob/user)
. = ..()
if(. && on && is_operational())
to_chat(user, "<span class='warning'>You cannot unwrench [src], turn it off first!</span>")
return FALSE
/obj/machinery/atmospherics/components/unary/vent_scrubber/examine(mob/user)
..()
if(welded)
to_chat(user, "It seems welded shut.")
/obj/machinery/atmospherics/components/unary/vent_scrubber/can_crawl_through()
return !welded
/obj/machinery/atmospherics/components/unary/vent_scrubber/attack_alien(mob/user)
if(!welded || !(do_after(user, 20, target = src)))
return
user.visible_message("[user] furiously claws at [src]!", "You manage to clear away the stuff blocking the scrubber.", "You hear loud scraping noises.")
welded = FALSE
update_icon()
pipe_vision_img = image(src, loc, layer = ABOVE_HUD_LAYER, dir = dir)
pipe_vision_img.plane = ABOVE_HUD_PLANE
playsound(loc, 'sound/weapons/bladeslice.ogg', 100, 1)
#undef SIPHONING
#undef SCRUBBING
@@ -145,7 +145,7 @@
var/member_gases = member.air_temporary.gases
for(var/id in member_gases)
member_gases[id][MOLES] *= member.volume/air.volume
member_gases[id] *= member.volume/air.volume
member.air_temporary.temperature = air.temperature
@@ -254,4 +254,4 @@
G.copy_from(total_gas_mixture)
var/list/G_gases = G.gases
for(var/id in G_gases)
G_gases[id][MOLES] *= G.volume/total_gas_mixture.volume
G_gases[id] *= G.volume/total_gas_mixture.volume
@@ -131,8 +131,7 @@
if(!isopenturf(O))
return FALSE
var/datum/gas_mixture/merger = new
merger.assert_gas(spawn_id)
merger.gases[spawn_id][MOLES] = (spawn_mol)
merger.gases[spawn_id] = (spawn_mol)
merger.temperature = spawn_temp
O.assume_air(merger)
O.air_update_turf(TRUE)
@@ -204,16 +204,14 @@
/obj/machinery/portable_atmospherics/canister/proc/create_gas()
if(gas_type)
air_contents.add_gas(gas_type)
if(starter_temp)
air_contents.temperature = starter_temp
air_contents.gases[gas_type][MOLES] = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.gases[gas_type] = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
if(starter_temp)
air_contents.temperature = starter_temp
/obj/machinery/portable_atmospherics/canister/air/create_gas()
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)
air_contents.gases[/datum/gas/oxygen] = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.gases[/datum/gas/nitrogen] = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
#define HOLDING (1<<0)
#define CONNECTED (1<<1)
@@ -439,10 +437,10 @@
var/list/danger = list()
for(var/id in air_contents.gases)
var/gas = air_contents.gases[id]
if(!gas[GAS_META][META_GAS_DANGER])
if(!GLOB.meta_gas_dangers[id])
continue
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(gas > (GLOB.meta_gas_visibility[id] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility
danger[GLOB.meta_gas_names[id]] = gas //ex. "plasma" = 20
if(danger.len)
message_admins("[ADMIN_LOOKUPFLW(usr)] opened a canister that contains the following at [ADMIN_VERBOSEJMP(src)]:")
@@ -1,146 +1,144 @@
/obj/machinery/portable_atmospherics/scrubber
name = "portable air scrubber"
icon_state = "pscrubber:0"
density = TRUE
var/on = FALSE
var/volume_rate = 1000
volume = 1000
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)
T.assume_air(air_contents)
air_update_turf()
return ..()
/obj/machinery/portable_atmospherics/scrubber/update_icon()
icon_state = "pscrubber:[on]"
cut_overlays()
if(holding)
add_overlay("scrubber-open")
if(connected_port)
add_overlay("scrubber-connector")
/obj/machinery/portable_atmospherics/scrubber/process_atmos()
..()
if(!on)
return
if(holding)
scrub(holding.air_contents)
else
var/turf/T = get_turf(src)
scrub(T.return_air())
/obj/machinery/portable_atmospherics/scrubber/proc/scrub(var/datum/gas_mixture/mixture)
var/transfer_moles = min(1, volume_rate / mixture.volume) * mixture.total_moles()
var/datum/gas_mixture/filtering = mixture.remove(transfer_moles) // Remove part of the mixture to filter.
var/datum/gas_mixture/filtered = new
if(!filtering)
return
filtered.temperature = filtering.temperature
for(var/gas in filtering.gases & scrubbing)
filtered.add_gas(gas)
filtered.gases[gas][MOLES] = filtering.gases[gas][MOLES] // Shuffle the "bad" gasses to the filtered mixture.
filtering.gases[gas][MOLES] = 0
filtering.garbage_collect() // Now that the gasses are set to 0, clean up the mixture.
air_contents.merge(filtered) // Store filtered out gasses.
mixture.merge(filtering) // Returned the cleaned gas.
if(!holding)
air_update_turf()
/obj/machinery/portable_atmospherics/scrubber/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(is_operational())
if(prob(50 / severity))
on = !on
update_icon()
/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "portable_scrubber", name, 420, 435, master_ui, state)
ui.open()
/obj/machinery/portable_atmospherics/scrubber/ui_data()
var/data = list()
data["on"] = on
data["connected"] = connected_port ? 1 : 0
data["pressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
data["id_tag"] = -1 //must be defined in order to reuse code between portable and vent scrubbers
data["filter_types"] = list()
for(var/path in GLOB.meta_gas_info)
var/list/gas = GLOB.meta_gas_info[path]
data["filter_types"] += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in scrubbing)))
if(holding)
data["holding"] = list()
data["holding"]["name"] = holding.name
data["holding"]["pressure"] = round(holding.air_contents.return_pressure())
return data
/obj/machinery/portable_atmospherics/scrubber/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
. = TRUE
if("eject")
if(holding)
holding.forceMove(drop_location())
holding = null
. = TRUE
if("toggle_filter")
scrubbing ^= gas_id2path(params["val"])
. = TRUE
update_icon()
/obj/machinery/portable_atmospherics/scrubber/huge
name = "huge air scrubber"
icon_state = "scrubber:0"
anchored = TRUE
active_power_usage = 500
idle_power_usage = 10
volume_rate = 1500
volume = 50000
var/movable = FALSE
/obj/machinery/portable_atmospherics/scrubber/huge/movable
movable = TRUE
/obj/machinery/portable_atmospherics/scrubber/huge/update_icon()
icon_state = "scrubber:[on]"
/obj/machinery/portable_atmospherics/scrubber/huge/process_atmos()
if((!anchored && !movable) || !is_operational())
on = FALSE
update_icon()
use_power = on ? ACTIVE_POWER_USE : IDLE_POWER_USE
if(!on)
return
..()
if(!holding)
var/turf/T = get_turf(src)
for(var/turf/AT in T.GetAtmosAdjacentTurfs(alldir = TRUE))
scrub(AT.return_air())
/obj/machinery/portable_atmospherics/scrubber/huge/attackby(obj/item/W, mob/user)
if(default_unfasten_wrench(user, W))
if(!movable)
on = FALSE
else
return ..()
/obj/machinery/portable_atmospherics/scrubber
name = "portable air scrubber"
icon_state = "pscrubber:0"
density = TRUE
var/on = FALSE
var/volume_rate = 1000
volume = 1000
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)
T.assume_air(air_contents)
air_update_turf()
return ..()
/obj/machinery/portable_atmospherics/scrubber/update_icon()
icon_state = "pscrubber:[on]"
cut_overlays()
if(holding)
add_overlay("scrubber-open")
if(connected_port)
add_overlay("scrubber-connector")
/obj/machinery/portable_atmospherics/scrubber/process_atmos()
..()
if(!on)
return
if(holding)
scrub(holding.air_contents)
else
var/turf/T = get_turf(src)
scrub(T.return_air())
/obj/machinery/portable_atmospherics/scrubber/proc/scrub(var/datum/gas_mixture/mixture)
var/transfer_moles = min(1, volume_rate / mixture.volume) * mixture.total_moles()
var/datum/gas_mixture/filtering = mixture.remove(transfer_moles) // Remove part of the mixture to filter.
var/datum/gas_mixture/filtered = new
if(!filtering)
return
filtered.temperature = filtering.temperature
for(var/gas in filtering.gases & scrubbing)
filtered.gases[gas] = filtering.gases[gas] // Shuffle the "bad" gasses to the filtered mixture.
filtering.gases[gas] = 0
GAS_GARBAGE_COLLECT(filtering.gases)
air_contents.merge(filtered) // Store filtered out gasses.
mixture.merge(filtering) // Returned the cleaned gas.
if(!holding)
air_update_turf()
/obj/machinery/portable_atmospherics/scrubber/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(is_operational())
if(prob(50 / severity))
on = !on
update_icon()
/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "portable_scrubber", name, 420, 435, master_ui, state)
ui.open()
/obj/machinery/portable_atmospherics/scrubber/ui_data()
var/data = list()
data["on"] = on
data["connected"] = connected_port ? 1 : 0
data["pressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
data["id_tag"] = -1 //must be defined in order to reuse code between portable and vent scrubbers
data["filter_types"] = list()
for(var/path in GLOB.meta_gas_ids)
data["filter_types"] += list(list("gas_id" = GLOB.meta_gas_ids[path], "gas_name" = GLOB.meta_gas_names[path], "enabled" = (path in scrubbing)))
if(holding)
data["holding"] = list()
data["holding"]["name"] = holding.name
data["holding"]["pressure"] = round(holding.air_contents.return_pressure())
return data
/obj/machinery/portable_atmospherics/scrubber/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
. = TRUE
if("eject")
if(holding)
holding.forceMove(drop_location())
holding = null
. = TRUE
if("toggle_filter")
scrubbing ^= gas_id2path(params["val"])
. = TRUE
update_icon()
/obj/machinery/portable_atmospherics/scrubber/huge
name = "huge air scrubber"
icon_state = "scrubber:0"
anchored = TRUE
active_power_usage = 500
idle_power_usage = 10
volume_rate = 1500
volume = 50000
var/movable = FALSE
/obj/machinery/portable_atmospherics/scrubber/huge/movable
movable = TRUE
/obj/machinery/portable_atmospherics/scrubber/huge/update_icon()
icon_state = "scrubber:[on]"
/obj/machinery/portable_atmospherics/scrubber/huge/process_atmos()
if((!anchored && !movable) || !is_operational())
on = FALSE
update_icon()
use_power = on ? ACTIVE_POWER_USE : IDLE_POWER_USE
if(!on)
return
..()
if(!holding)
var/turf/T = get_turf(src)
for(var/turf/AT in T.GetAtmosAdjacentTurfs(alldir = TRUE))
scrub(AT.return_air())
/obj/machinery/portable_atmospherics/scrubber/huge/attackby(obj/item/W, mob/user)
if(default_unfasten_wrench(user, W))
if(!movable)
on = FALSE
else
return ..()
@@ -497,14 +497,14 @@
W.registered_name = H.real_name
W.update_label(W.registered_name, W.assignment)
// The shielded hardsuit is already NODROP
// The shielded hardsuit is already TRAIT_NODROP
no_drops += H.get_item_by_slot(SLOT_GLOVES)
no_drops += H.get_item_by_slot(SLOT_SHOES)
no_drops += H.get_item_by_slot(SLOT_W_UNIFORM)
no_drops += H.get_item_by_slot(SLOT_EARS)
for(var/i in no_drops)
var/obj/item/I = i
I.item_flags |= NODROP
ADD_TRAIT(I, TRAIT_NODROP, CAPTURE_THE_FLAG_TRAIT)
/datum/outfit/ctf/instagib
r_hand = /obj/item/gun/energy/laser/instakill
+8 -3
View File
@@ -68,13 +68,18 @@
GLOB.poi_list |= src
LAZYADD(GLOB.mob_spawners[job_description ? job_description : name], src)
/obj/effect/mob_spawn/Destroy()
GLOB.poi_list -= src
LAZYREMOVE(GLOB.mob_spawners[job_description ? job_description : name], src)
if(!LAZYLEN(GLOB.mob_spawners[job_description ? job_description : name]))
GLOB.mob_spawners -= job_description ? job_description : name
var/job_name = job_description ? job_description : name
LAZYREMOVE(GLOB.mob_spawners[job_name], src)
if(!LAZYLEN(GLOB.mob_spawners[job_name]))
GLOB.mob_spawners -= job_name
return ..()
/obj/effect/mob_spawn/proc/can_latejoin() //If it can be taken from the lobby.
return ghost_usable
/obj/effect/mob_spawn/proc/special(mob/M)
return
+1 -1
View File
@@ -12,7 +12,7 @@
var/obj/item/tank/T = O
if(!T.air_contents.gases[gas_type])
return FALSE
return T.air_contents.gases[gas_type][MOLES] >= moles_required
return T.air_contents.gases[gas_type] >= moles_required
/datum/bounty/item/engineering/gas/nitryl_tank
name = "Full Tank of Nitryl"
@@ -131,6 +131,24 @@
unit_name = "security barrier"
export_types = list(/obj/item/grenade/barrier, /obj/structure/barricade/security)
/datum/export/large/gas_canister
cost = 10 //Base cost of canister. You get more for nice gases inside.
unit_name = "Gas Canister"
export_types = list(/obj/machinery/portable_atmospherics/canister)
/datum/export/large/gas_canister/get_cost(obj/O)
var/obj/machinery/portable_atmospherics/canister/C = O
var/worth = 10
var/gases = C.air_contents.gases
worth += gases[/datum/gas/bz]*4
worth += gases[/datum/gas/stimulum]*25
worth += gases[/datum/gas/hypernoblium]*1000
worth += gases[/datum/gas/miasma]*15
worth += gases[/datum/gas/tritium]*7
worth += gases[/datum/gas/pluoxium]*6
worth += gases[/datum/gas/nitryl]*30
return worth
/datum/export/large/odysseus
cost = 5500
unit_name = "working odysseus"
+3 -3
View File
@@ -80,13 +80,13 @@
// Paper work done correctly
/datum/export/paperwork_correct
cost = 50
cost = 150
unit_name = "correct paperwork"
export_types = list(/obj/item/paper/fluff/jobs/cargo/manifest/paperwork_correct)
export_types = list(/obj/item/folder/paperwork_correct)
// Paper work not done retruned
/datum/export/paperwork_incorrect
cost = -500 // Failed to meet NT standers
unit_name = "returned incorrect paperwork"
export_types = list(/obj/item/paper/fluff/jobs/cargo/manifest/paperwork)
export_types = list(/obj/item/folder/paperwork)
+4 -2
View File
@@ -97,12 +97,14 @@
return C
//Paperwork for NT
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork
/obj/item/folder/paperwork
name = "Incomplete Paperwork"
desc = "These should've been filled out four months ago! Unfinished grant papers issued by Nanotrasen's finance department. Complete this page for additional funding."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "docs_generic"
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork_correct
/obj/item/folder/paperwork_correct
name = "Finished Paperwork"
desc = "A neat stack of filled-out forms, in triplicate and signed. Is there anything more satisfying? Make sure they get stamped."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "docs_verified"
+101 -27
View File
@@ -433,7 +433,6 @@
/datum/supply_pack/security/russianclothing
name = "Russian Surplus Clothing"
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproff armor, a few union suits and some warm hats!"
hidden = TRUE
contraband = TRUE
cost = 5000 // Its basicly sec suits, good boots/gloves
contains = list(/obj/item/clothing/suit/security/officer/russian,
@@ -517,14 +516,16 @@
/datum/supply_pack/security/armory/ballistic
name = "Combat Shotguns Crate"
desc = "For when the enemy absolutely needs to be replaced with lead. Contains three Aussec-designed Combat Shotguns, and three Shotgun Bandoliers. Requires Armory access to open."
desc = "For when the enemy absolutely needs to be replaced with lead. Contains three Aussec-designed Combat Shotguns, with three Shotgun Bandoliers, as well as seven buchshot and 12g shotgun slugs. Requires Armory access to open."
cost = 8000
contains = list(/obj/item/gun/ballistic/shotgun/automatic/combat,
/obj/item/gun/ballistic/shotgun/automatic/combat,
/obj/item/gun/ballistic/shotgun/automatic/combat,
/obj/item/storage/belt/bandolier,
/obj/item/storage/belt/bandolier,
/obj/item/storage/belt/bandolier)
/obj/item/storage/belt/bandolier,
/obj/item/storage/box/lethalshot,
/obj/item/storage/box/lethalslugs)
crate_name = "combat shotguns crate"
/datum/supply_pack/security/armory/dragnetgun
@@ -568,7 +569,7 @@
/datum/supply_pack/security/armory/fire
name = "Incendiary Weapons Crate"
desc = "Burn, baby burn. Contains three incendiary grenades, three plasma canisters, and a flamethrower. Requires Brige access to open."
desc = "Burn, baby burn. Contains three incendiary grenades, seven incendiary slugs, three plasma canisters, and a flamethrower. Requires Brige access to open."
cost = 1500
access = ACCESS_HEADS
contains = list(/obj/item/flamethrower/full,
@@ -577,7 +578,8 @@
/obj/item/tank/internals/plasma,
/obj/item/grenade/chem_grenade/incendiary,
/obj/item/grenade/chem_grenade/incendiary,
/obj/item/grenade/chem_grenade/incendiary)
/obj/item/grenade/chem_grenade/incendiary,
/obj/item/storage/box/fireshot)
crate_name = "incendiary weapons crate"
crate_type = /obj/structure/closet/crate/secure/plasma
dangerous = TRUE
@@ -630,11 +632,13 @@
/datum/supply_pack/security/armory/riotshotguns
name = "Riot Shotgun Crate"
desc = "For when the greytide gets really uppity. Contains three riot Shotguns. Requires Armory access to open."
desc = "For when the greytide gets really uppity. Contains three riot shotguns, seven rubber shot and beanbag shells. Requires Armory access to open."
cost = 6000
contains = list(/obj/item/gun/ballistic/shotgun/riot,
/obj/item/gun/ballistic/shotgun/riot,
/obj/item/gun/ballistic/shotgun/riot)
/obj/item/gun/ballistic/shotgun/riot,
/obj/item/storage/box/rubbershot,
/obj/item/storage/box/beanbag)
crate_name = "riot shotgun crate"
/datum/supply_pack/security/armory/swat
@@ -751,13 +755,24 @@
/datum/supply_pack/engineering/engihardsuit
name = "Engineering Hardsuit"
desc = "Poly 'Who stole all the hardsuits!' Well now you can get more hardsuits if needed! NOTE ONE HARDSUIT IS IN THIS CRATE, as well as one air tank and maks!"
desc = "Poly 'Who stole all the hardsuits!' Well now you can get more hardsuits if needed! NOTE ONE HARDSUIT IS IN THIS CRATE, as well as one air tank and mask!"
cost = 2500
contains = list(/obj/item/tank/internals/air,
/obj/item/clothing/mask/gas,
/obj/item/clothing/suit/space/hardsuit/engine)
crate_name = "engineering hardsuit"
/datum/supply_pack/engineering/atmoshardsuit
name = "Atmospherics Hardsuit"
desc = "Too many techs and not enough hardsuits? Time to buy some more! Comes with gas mask and air tank. Ask the CE to open."
cost = 5000
access = ACCESS_CE
contains = list(/obj/item/tank/internals/air,
/obj/item/clothing/mask/gas,
/obj/item/clothing/suit/space/hardsuit/engine/atmos)
crate_name = "atmospherics hardsuit"
crate_type = /obj/structure/closet/crate/secure/engineering
/datum/supply_pack/engineering/industrialrcd
name = "Industrial RCD"
desc = "A industrial RCD in case the station has gone through more then one meteor storm and the CE needs to bring out the somthing a bit more reliable. Dose not contain spare ammo for the industrial RCD or any other RCD modles."
@@ -873,8 +888,7 @@
/datum/supply_pack/engineering/shield_sat
name = "Shield Generator Satellite"
desc = "Protect the very existence of this station with these Anti-Meteor defenses. Contains three Shield Generator Satellites."
cost = 3000
special = TRUE
cost = 4000
contains = list(
/obj/machinery/satellite/meteor_shield,
/obj/machinery/satellite/meteor_shield,
@@ -882,16 +896,13 @@
)
crate_name= "shield sat crate"
/datum/supply_pack/engineering/shield_sat_control
name = "Shield System Control Board"
desc = "A control system for the Shield Generator Satellite system."
cost = 5000
special = TRUE
cost = 4000
contains = list(/obj/item/circuitboard/computer/sat_control)
crate_name= "shield control board crate"
//////////////////////////////////////////////////////////////////////////////
//////////////////////// Engine Construction /////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -961,6 +972,15 @@
crate_name = "grounding rod crate"
crate_type = /obj/structure/closet/crate/engineering/electrical
/datum/supply_pack/engine/mason
name = "M.A.S.O.N RIG Crate"
desc = "The rare M.A.S.O.N RIG. Requires CE access to open."
cost = 15000
access = ACCESS_CE
contains = list(/obj/item/clothing/suit/space/hardsuit/ancient/mason)
crate_name = "M.A.S.O.N Rig"
crate_type = /obj/structure/closet/crate/secure/engineering
/datum/supply_pack/engine/PA
name = "Particle Accelerator Crate"
desc = "A supermassive black hole or hyper-powered teslaball are the perfect way to spice up any party! This \"My First Apocalypse\" kit contains everything you need to build your own Particle Accelerator! Ages 10 and up."
@@ -1137,7 +1157,7 @@
/datum/supply_pack/materials/bz
name = "BZ Canister Crate"
desc = "Contains a canister of BZ. Requires Toxins access to open."
cost = 5000
cost = 7500 // Costs 3 credits more than what you can get for selling it.
access = ACCESS_TOX_STORAGE
contains = list(/obj/machinery/portable_atmospherics/canister/bz)
crate_name = "BZ canister crate"
@@ -1536,6 +1556,15 @@
crate_type = /obj/structure/closet/crate/secure/science
dangerous = TRUE
/datum/supply_pack/science/tech_slugs
name = "Tech Slug Ammo Shells"
desc = "A new type of shell that is able to be made into a few different dangerous types. Contains two boxes of tech slugs, 14 shells in all."
cost = 1000
contains = list(/obj/item/storage/box/techsslug,
/obj/item/storage/box/techsslug)
crate_name = "tech slug crate"
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Service //////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -1543,7 +1572,6 @@
/datum/supply_pack/service
group = "Service"
/datum/supply_pack/service/advlighting
name = "Advanced Lighting crate"
desc = "Thanks to advanced lighting tech we here at the Lamp Factory have be able to produce more lamps and lamp items! This crate has three lamps, a box of lights and a state of the art rapid-light-device!"
@@ -1568,6 +1596,14 @@
/obj/item/stack/packageWrap)
crate_name = "cargo supplies crate"
/datum/supply_pack/service/food_cart
name = "Food Cart Crate"
desc = "Want to sell food on the go? Cook lost their cart? Well we just so happen to have a few carts to spare!"
cost = 1000
contains = list(/obj/machinery/food_cart)
crate_name = "food cart crate"
crate_type = /obj/structure/closet/crate
/datum/supply_pack/service/noslipfloor
name = "High-traction Floor Tiles"
desc = "Make slipping a thing of the past with sixty industrial-grade anti-slip floortiles!"
@@ -1576,6 +1612,14 @@
/obj/item/stack/tile/noslip/thirty)
crate_name = "high-traction floor tiles crate"
/datum/supply_pack/service/icecream_cart
name = "Ice Cream Cart Crate"
desc = "Plasma fire a to hot for you, want a nice treat after a hard days work? Well now we have the cart for you! This Ice Cream Vat has everthing you need to make you and your friends so ice cream treats! This cart comes stocked with some ingredients for each type of scoopable icecream."
cost = 2750 //Comes prestocked with basic ingredients
contains = list(/obj/machinery/icecream_vat)
crate_name = "ice cream vat crate"
crate_type = /obj/structure/closet/crate
/datum/supply_pack/service/janitor
name = "Janitorial Supplies Crate"
desc = "Fight back against dirt and grime with Nanotrasen's Janitorial Essentials(tm)! Contains three buckets, caution signs, and cleaner grenades. Also has a single mop, spray cleaner, rag, NT soap and a trash bag."
@@ -1704,6 +1748,10 @@
crate_name = "shaft miner starter kit"
crate_type = /obj/structure/closet/crate/secure
//////////////////////////////////////////////////////////////////////////////
/////////////////////////// Vending Restocks /////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/datum/supply_pack/service/vending/bartending
name = "Bartending Supply Crate"
desc = "Bring on the booze with vending machine refills, as well as a free book containing the well-kept secrets to the bartending trade!"
@@ -1912,6 +1960,17 @@
crate_name = "hydroponics backpack crate"
crate_type = /obj/structure/closet/crate/secure
/datum/supply_pack/organic/mre
name = "MRE supply kit (emergency rations)"
desc = "The lights are out. Oxygen's running low. You've run out of food except space weevils. Don't let this be you! Order our NT branded MRE kits today! This pack contains 5 MRE packs with a randomized menu and an oxygen tank."
cost = 2000
contains = list(/obj/item/storage/box/mre/menu1/safe,
/obj/item/storage/box/mre/menu1/safe,
/obj/item/storage/box/mre/menu2/safe,
/obj/item/storage/box/mre/menu2/safe,
/obj/item/storage/box/mre/menu3)
crate_name = "MRE crate (emergency rations)"
/datum/supply_pack/organic/pizza
name = "Pizza Crate"
desc = "Best prices on this side of the galaxy. All deliveries are guaranteed to be 99% anomaly-free!"
@@ -2204,7 +2263,8 @@
/obj/item/storage/fancy/cigarettes/cigpack_shadyjims,
/obj/item/clothing/mask/gas/syndicate,
/obj/item/clothing/neck/necklace/dope,
/obj/item/vending_refill/donksoft)
/obj/item/vending_refill/donksoft,
/obj/item/circuitboard/computer/arcade/amputation)
crate_name = "crate"
/datum/supply_pack/costumes_toys/foamforce
@@ -2656,6 +2716,7 @@
/obj/item/restraints/handcuffs/fake/kinky,
/obj/item/clothing/head/kitty/genuine, // Why its illegal
/obj/item/clothing/head/kitty/genuine,
/obj/item/storage/pill_bottle/penis_enlargement,
/obj/structure/reagent_dispensers/keg/aphro)
crate_name = "lewd kit"
crate_type = /obj/structure/closet/crate
@@ -2673,16 +2734,16 @@
name = "Freelance Paper work"
desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (10) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up.
cost = 400 // Net of 0 credits
contains = list(/obj/item/paper/fluff/jobs/cargo/manifest/paperwork,
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork,
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork,
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork,
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork,
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork,
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork,
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork,
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork,
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork,
contains = list(/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/pen/fountain,
/obj/item/pen/fountain,
/obj/item/pen/fountain,
@@ -2690,6 +2751,19 @@
/obj/item/pen/fountain)
crate_name = "Paperwork"
/datum/supply_pack/misc/randomised/promiscuous
name = "Promiscuous Organs"
desc = "Do YOU want to have more genital? Well we have just the thing for you~. This crate has two autosurgeon, that will let you have a new sex, organ to impress that hot stud and or chick."
cost = 4000 //Only get 2!
contraband = TRUE
var/num_contained = 2
contains = list(/obj/item/autosurgeon/penis,
/obj/item/autosurgeon/testicles,
/obj/item/autosurgeon/vagina,
/obj/item/autosurgeon/breasts,
/obj/item/autosurgeon/womb)
crate_name = "promiscuous organs"
/datum/supply_pack/misc/toner
name = "Toner Crate"
desc = "Spent too much ink printing butt pictures? Fret not, with these six toner refills, you'll be printing butts 'till the cows come home!'"
+9 -9
View File
@@ -29,7 +29,7 @@
var/effectQuiet = FALSE //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc)
var/effectMissile = FALSE //If true, the pod deletes the second it lands. If you give it an explosion, it will act like a missile exploding as it hits the ground
var/effectCircle = FALSE //If true, allows the pod to come in at any angle. Bit of a weird feature but whatever its here
var/style = STYLE_STANDARD //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the POD_STYLES list in cargo.dm defines to get the proper icon/name/desc for the pod.
var/style = STYLE_STANDARD //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the POD_STYLES list in cargo.dm defines to get the proper icon/name/desc for the pod.
var/reversing = FALSE //If true, the pod will not send any items. Instead, after opening, it will close again (picking up items/mobs) and fly back to centcom
var/landingSound //Admin sound to play when the pod lands
var/openingSound //Admin sound to play when the pod opens
@@ -76,7 +76,7 @@
/obj/structure/closet/supplypod/tool_interact(obj/item/W, mob/user)
if (bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways.
return FALSE
return FALSE
else
..()
@@ -86,13 +86,15 @@
/obj/structure/closet/supplypod/contents_explosion() //Supplypods also protect their contents from the harmful effects of fucking exploding.
return
/obj/structure/closet/supplypod/prevent_content_explosion() //Useful for preventing epicenter explosions from damaging contents
return TRUE
/obj/structure/closet/supplypod/toggle(mob/living/user) //Supplypods shouldn't be able to be manually opened under any circumstances, as the open() proc generates supply order datums
return
/obj/structure/closet/supplypod/proc/preOpen() //Called before the open() proc. Handles anything that occurs right as the pod lands.
var/turf/T = get_turf(src)
var/list/B = explosionSize //Mostly because B is more readable than explosionSize :p
var/boomTotal = 0 //A counter used to check if the explosion does nothing
if (landingSound)
playsound(get_turf(src), landingSound, soundVolume, 0, 0)
for (var/mob/living/M in T)
@@ -108,10 +110,8 @@
M.gib() //After adjusting the fuck outta that brute loss we finish the job with some satisfying gibs
M.adjustBruteLoss(damage)
for (var/i in B)
boomTotal += i //Count up all the values of the explosion
if (boomTotal != 0) //If the explosion list isn't all zeroes, call an explosion
if (B[1] || B[2] || B[3] || B[4]) //If the explosion list isn't all zeroes, call an explosion
explosion(get_turf(src), B[1], B[2], B[3], flame_range = B[4], silent = effectQuiet, ignorecap = istype(src, /obj/structure/closet/supplypod/centcompod)) //less advanced equipment than bluespace pod, so larger explosion when landing
else if (!effectQuiet) //If our explosion list IS all zeroes, we still make a nice explosion sound (unless the effectQuiet var is true)
playsound(src, "explosion", landingSound ? 15 : 80, 1)
@@ -150,10 +150,10 @@
playsound(get_turf(holder), leavingSound, soundVolume, 0, 0)
if (reversing) //If we're reversing, we call the close proc. This sends the pod back up to centcom
close(holder)
else if (bluespace) //If we're a bluespace pod, then delete ourselves (along with our holder, if a seperate holder exists)
if (style != STYLE_INVISIBLE)
else if (bluespace) //If we're a bluespace pod, then delete ourselves (along with our holder, if a seperate holder exists)
if (style != STYLE_INVISIBLE)
do_sparks(5, TRUE, holder) //Create some sparks right before closing
qdel(src) //Delete ourselves and the holder
qdel(src) //Delete ourselves and the holder
if (holder != src)
qdel(holder)
+45
View File
@@ -467,6 +467,51 @@ GLOBAL_LIST_EMPTY(asset_datums)
"stamp-law" = 'icons/stamp_icons/large_stamp-law.png'
)
/datum/asset/spritesheet/simple/minesweeper
name = "minesweeper"
assets = list(
"1" = 'icons/UI_Icons/minesweeper_tiles/one.png',
"2" = 'icons/UI_Icons/minesweeper_tiles/two.png',
"3" = 'icons/UI_Icons/minesweeper_tiles/three.png',
"4" = 'icons/UI_Icons/minesweeper_tiles/four.png',
"5" = 'icons/UI_Icons/minesweeper_tiles/five.png',
"6" = 'icons/UI_Icons/minesweeper_tiles/six.png',
"7" = 'icons/UI_Icons/minesweeper_tiles/seven.png',
"8" = 'icons/UI_Icons/minesweeper_tiles/eight.png',
"empty" = 'icons/UI_Icons/minesweeper_tiles/empty.png',
"flag" = 'icons/UI_Icons/minesweeper_tiles/flag.png',
"hidden" = 'icons/UI_Icons/minesweeper_tiles/hidden.png',
"mine" = 'icons/UI_Icons/minesweeper_tiles/mine.png',
"minehit" = 'icons/UI_Icons/minesweeper_tiles/minehit.png'
)
/datum/asset/spritesheet/simple/pills
name = "pills"
assets = list(
"pill1" = 'icons/UI_Icons/Pills/pill1.png',
"pill2" = 'icons/UI_Icons/Pills/pill2.png',
"pill3" = 'icons/UI_Icons/Pills/pill3.png',
"pill4" = 'icons/UI_Icons/Pills/pill4.png',
"pill5" = 'icons/UI_Icons/Pills/pill5.png',
"pill6" = 'icons/UI_Icons/Pills/pill6.png',
"pill7" = 'icons/UI_Icons/Pills/pill7.png',
"pill8" = 'icons/UI_Icons/Pills/pill8.png',
"pill9" = 'icons/UI_Icons/Pills/pill9.png',
"pill10" = 'icons/UI_Icons/Pills/pill10.png',
"pill11" = 'icons/UI_Icons/Pills/pill11.png',
"pill12" = 'icons/UI_Icons/Pills/pill12.png',
"pill13" = 'icons/UI_Icons/Pills/pill13.png',
"pill14" = 'icons/UI_Icons/Pills/pill14.png',
"pill15" = 'icons/UI_Icons/Pills/pill15.png',
"pill16" = 'icons/UI_Icons/Pills/pill16.png',
"pill17" = 'icons/UI_Icons/Pills/pill17.png',
"pill18" = 'icons/UI_Icons/Pills/pill18.png',
"pill19" = 'icons/UI_Icons/Pills/pill19.png',
"pill20" = 'icons/UI_Icons/Pills/pill20.png',
"pill21" = 'icons/UI_Icons/Pills/pill21.png',
"pill22" = 'icons/UI_Icons/Pills/pill22.png',
)
/datum/asset/simple/IRV
assets = list(
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js',
+87 -36
View File
@@ -59,6 +59,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/preferred_map = null
var/pda_style = MONO
var/pda_color = "#808000"
var/pda_skin = PDA_SKIN_ALT
var/uses_glasses_colour = 0
@@ -70,8 +71,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/gender = MALE //gender of character (well duh)
var/age = 30 //age of character
var/underwear = "Nude" //underwear type
var/undie_color = "#FFFFFF"
var/undershirt = "Nude" //undershirt type
var/shirt_color = "#FFFFFF"
var/socks = "Nude" //socks type
var/socks_color = "#FFFFFF"
var/backbag = DBACKPACK //backpack type
var/hair_style = "Bald" //Hair type
var/hair_color = "000" //Hair color
@@ -117,6 +121,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
"balls_color" = "fff",
"balls_amount" = 2,
"balls_sack_size" = BALLS_SACK_SIZE_DEF,
"balls_shape" = "Single",
"balls_size" = BALLS_SIZE_DEF,
"balls_cum_rate" = CUM_RATE,
"balls_cum_mult" = CUM_RATE_MULT,
@@ -153,6 +158,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
)
var/list/custom_names = list()
var/preferred_ai_core_display = "Blue"
var/prefered_security_department = SEC_DEPT_RANDOM
var/custom_species = null
@@ -302,10 +308,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
old_group = namedata["group"]
dat += "<br>"
dat += "<a href ='?_src_=prefs;preference=[custom_name_id];task=input'><b>[namedata["pref_name"]]:</b> [custom_names[custom_name_id]]</a> "
dat += "<br>"
dat += "<b>Custom job preferences:</b><BR>"
dat += "<a href='?_src_=prefs;preference=sec_dept;task=input'><b>Prefered security department:</b> [prefered_security_department]</a><BR></td>"
dat += "<br><br>"
dat += "<b>Custom job preferences:</b><BR>"
dat += "<a href='?_src_=prefs;preference=ai_core_icon;task=input'><b>Preferred AI Core Display:</b> [preferred_ai_core_display]</a><br>"
dat += "<a href='?_src_=prefs;preference=sec_dept;task=input'><b>Preferred Security Department:</b> [prefered_security_department]</a><BR></td>"
dat += "</tr></table>"
//Character Appearance
@@ -670,8 +677,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>Clothing & Equipment</h2>"
dat += "<b>Underwear:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=underwear;task=input'>[underwear]</a>"
if(UNDIE_COLORABLE(GLOB.underwear_list[underwear]))
dat += "<b>Underwear Color:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=undie_color;task=input'>[undie_color]</a>"
dat += "<b>Undershirt:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=undershirt;task=input'>[undershirt]</a>"
if(UNDIE_COLORABLE(GLOB.undershirt_list[undershirt]))
dat += "<b>Undershirt Color:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=shirt_color;task=input'>[shirt_color]</a>"
dat += "<b>Socks:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=socks;task=input'>[socks]</a>"
if(UNDIE_COLORABLE(GLOB.socks_list[socks]))
dat += "<b>Socks Color:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=socks_color;task=input'>[socks_color]</a>"
dat += "<b>Backpack:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=bag;task=input'>[backbag]</a>"
dat += "<b>Uplink Location:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=uplink_loc;task=input'>[uplink_spawn_loc]</a>"
dat += "</td>"
@@ -682,47 +695,48 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
if(pref_species.use_skintones)
dat += "<b>Genitals use skintone:</b><a href='?_src_=prefs;preference=genital_colour'>[features["genitals_use_skintone"] == TRUE ? "Yes" : "No"]</a>"
dat += "<b>Has Penis:</b>"
dat += "<h3>Penis</h3>"
dat += "<a style='display:block;width:50px' href='?_src_=prefs;preference=has_cock'>[features["has_cock"] == TRUE ? "Yes" : "No"]</a>"
if(features["has_cock"] == TRUE)
if(features["has_cock"])
if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE)
dat += "<b>Penis Color:</b>"
dat += "<span style='border: 1px solid #161616; background-color: #[skintone2hex(skin_tone)];'>&nbsp;&nbsp;&nbsp;</span>(Skin tone overriding)<br>"
dat += "<b>Penis Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[skintone2hex(skin_tone)];'>&nbsp;&nbsp;&nbsp;</span>(Skin tone overriding)</a><br>"
else
dat += "<b>Penis Color:</b>"
dat += "<b>Penis Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[features["cock_color"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=cock_color;task=input'>Change</a><br>"
dat += "<b>Penis Shape:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=cock_shape;task=input'>[features["cock_shape"]]</a>"
dat += "<b>Penis Length:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=cock_length;task=input'>[features["cock_length"]] inch(es)</a>"
dat += "<b>Has Testicles:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=has_balls'>[features["has_balls"] == TRUE ? "Yes" : "No"]</a>"
if(features["has_balls"] == TRUE)
if(features["has_balls"])
if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE)
dat += "<b>Testicles Color:</b>"
dat += "<b>Testicles Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[skintone2hex(skin_tone)];'>&nbsp;&nbsp;&nbsp;</span>(Skin tone overriding)<br>"
else
dat += "<b>Testicles Color:</b>"
dat += "<b>Testicles Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[features["balls_color"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=balls_color;task=input'>Change</a><br>"
dat += "<b>Testicles showing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=balls_shape;task=input'>[features["balls_shape"]]</a>"
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<b>Has Vagina:</b>"
dat += "<h3>Vagina</h3>"
dat += "<a style='display:block;width:50px' href='?_src_=prefs;preference=has_vag'>[features["has_vag"] == TRUE ? "Yes" : "No"]</a>"
if(features["has_vag"])
dat += "<b>Vagina Type:</b> <a style='display:block;width:100px' href='?_src_=prefs;preference=vag_shape;task=input'>[features["vag_shape"]]</a>"
if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE)
dat += "<b>Vagina Color:</b>"
dat += "<b>Vagina Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[skintone2hex(skin_tone)];'>&nbsp;&nbsp;&nbsp;</span>(Skin tone overriding)<br>"
else
dat += "<b>Vagina Color:</b>"
dat += "<b>Vagina Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[features["vag_color"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=vag_color;task=input'>Change</a><br>"
dat += "<b>Has Womb:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=has_womb'>[features["has_womb"] == TRUE ? "Yes" : "No"]</a>"
dat += "</td>"
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<b>Has Breasts:</b>"
dat += "<h3>Breasts</h3>"
dat += "<a style='display:block;width:50px' href='?_src_=prefs;preference=has_breasts'>[features["has_breasts"] == TRUE ? "Yes" : "No"]</a>"
if(features["has_breasts"])
if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE)
dat += "<b>Color:</b>"
dat += "<b>Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[skintone2hex(skin_tone)];'>&nbsp;&nbsp;&nbsp;</span>(Skin tone overriding)<br>"
else
dat += "<b>Color:</b>"
dat += "<b>Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[features["breasts_color"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=breasts_color;task=input'>Change</a><br>"
dat += "<b>Cup Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_size;task=input'>[features["breasts_size"]]</a>"
dat += "<b>Breast Shape:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_shape;task=input'>[features["breasts_shape"]]</a>"
@@ -742,6 +756,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<br>"
dat += "<b>PDA Color:</b> <span style='border:1px solid #161616; background-color: [pda_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=pda_color;task=input'>Change</a><BR>"
dat += "<b>PDA Style:</b> <a href='?_src_=prefs;task=input;preference=pda_style'>[pda_style]</a><br>"
dat += "<b>PDA Reskin:</b> <a href='?_src_=prefs;task=input;preference=pda_skin'>[pda_skin]</a><br>"
dat += "<br>"
dat += "<b>Ghost Ears:</b> <a href='?_src_=prefs;preference=ghost_ears'>[(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]</a><br>"
dat += "<b>Ghost Radio:</b> <a href='?_src_=prefs;preference=ghost_radio'>[(chat_toggles & CHAT_GHOSTRADIO) ? "All Messages":"No Messages"]</a><br>"
@@ -1392,10 +1407,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
facial_hair_style = random_facial_hair_style(gender)
if("underwear")
underwear = random_underwear(gender)
undie_color = random_color()
if("undershirt")
undershirt = random_undershirt(gender)
shirt_color = random_color()
if("socks")
socks = random_socks()
socks_color = random_color()
if(BODY_ZONE_PRECISE_EYES)
eye_color = random_eye_color()
if("s_tone")
@@ -1458,7 +1476,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN)
if("flavor_text")
var/msg = stripped_multiline_input(usr,"Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!","Flavor Text",html_decode(features["flavor_text"]), MAX_MESSAGE_LEN*2, TRUE) as null|message
var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", html_decode(features["flavor_text"]), MAX_MESSAGE_LEN*2, TRUE)
if(!isnull(msg))
msg = copytext(msg, 1, MAX_MESSAGE_LEN*2)
features["flavor_text"] = msg
@@ -1501,29 +1519,35 @@ GLOBAL_LIST_EMPTY(preferences_datums)
bgstate = next_list_item(bgstate, bgstate_options)
if("underwear")
var/new_underwear
if(gender == MALE)
new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in GLOB.underwear_m
else
new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in GLOB.underwear_f
var/new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in GLOB.underwear_list
if(new_underwear)
underwear = new_underwear
if("undie_color")
var/n_undie_color = input(user, "Choose your underwear's color.", "Character Preference", undie_color) as color|null
if(n_undie_color)
undie_color = n_undie_color
if("undershirt")
var/new_undershirt
if(gender == MALE)
new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in GLOB.undershirt_m
else
new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in GLOB.undershirt_f
var/new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in GLOB.undershirt_list
if(new_undershirt)
undershirt = new_undershirt
if("shirt_color")
var/n_shirt_color = input(user, "Choose your undershirt's color.", "Character Preference", shirt_color) as color|null
if(n_shirt_color)
shirt_color = n_shirt_color
if("socks")
var/new_socks
new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in GLOB.socks_list
var/new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in GLOB.socks_list
if(new_socks)
socks = new_socks
if("socks_color")
var/n_socks_color = input(user, "Choose your socks' color.", "Character Preference", socks_color) as color|null
if(n_socks_color)
socks_color = n_socks_color
if("eyes")
var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference","#"+eye_color) as color|null
if(new_eyes)
@@ -1836,7 +1860,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
features["cock_color"] = sanitize_hexcolor(new_cockcolor)
else
user << "<span class='danger'>Invalid color. Your color is not bright enough.</span>"
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("cock_length")
var/new_length = input(user, "Penis length in inches:\n([COCK_SIZE_MIN]-[COCK_SIZE_MAX])", "Character Preference") as num|null
@@ -1858,7 +1882,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
features["balls_color"] = sanitize_hexcolor(new_ballscolor)
else
user << "<span class='danger'>Invalid color. Your color is not bright enough.</span>"
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("balls_shape")
var/new_shape
new_shape = input(user, "Testicle Type:", "Character Preference") as null|anything in GLOB.balls_shapes_list
if(new_shape)
features["balls_shape"] = new_shape
if("egg_size")
var/new_size
@@ -1874,7 +1904,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
features["eggsack_egg_color"] = sanitize_hexcolor(new_egg_color)
else
user << "<span class='danger'>Invalid color. Your color is not bright enough.</span>"
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("breasts_size")
var/new_size
@@ -1897,7 +1927,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
features["breasts_color"] = sanitize_hexcolor(new_breasts_color)
else
user << "<span class='danger'>Invalid color. Your color is not bright enough.</span>"
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("vag_shape")
var/new_shape
@@ -1914,7 +1944,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
features["vag_color"] = sanitize_hexcolor(new_vagcolor)
else
user << "<span class='danger'>Invalid color. Your color is not bright enough.</span>"
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("ooccolor")
var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference",ooccolor) as color|null
@@ -1931,8 +1961,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(new_loc)
uplink_spawn_loc = new_loc
if("ai_core_icon")
var/ai_core_icon = input(user, "Choose your preferred AI core display screen:", "AI Core Display Screen Selection") as null|anything in GLOB.ai_core_display_screens
if(ai_core_icon)
preferred_ai_core_display = ai_core_icon
if("sec_dept")
var/department = input(user, "Choose your prefered security department:", "Security Departments") as null|anything in GLOB.security_depts_prefs
var/department = input(user, "Choose your preferred security department:", "Security Departments") as null|anything in GLOB.security_depts_prefs
if(department)
prefered_security_department = department
@@ -1971,6 +2006,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/pickedPDAColor = input(user, "Choose your PDA Interface color.", "Character Preference",pda_color) as color|null
if(pickedPDAColor)
pda_color = pickedPDAColor
if("pda_skin")
var/pickedPDASkin = input(user, "Choose your PDA reskin.", "Character Preference", pda_skin) as null|anything in GLOB.pda_reskins
if(pickedPDASkin)
pda_skin = pickedPDASkin
else
switch(href_list["preference"])
@@ -1981,6 +2020,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
arousable = !arousable
if("has_cock")
features["has_cock"] = !features["has_cock"]
if(features["has_cock"] == FALSE)
features["has_balls"] = FALSE
if("has_balls")
features["has_balls"] = !features["has_balls"]
if("has_ovi")
@@ -1995,6 +2036,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["has_breasts"] = !features["has_breasts"]
if("has_vag")
features["has_vag"] = !features["has_vag"]
if(features["has_vag"] == FALSE)
features["has_womb"] = FALSE
if("has_womb")
features["has_womb"] = !features["has_womb"]
if("exhibitionist")
@@ -2221,8 +2264,16 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.hair_style = hair_style
character.facial_hair_style = facial_hair_style
character.underwear = underwear
character.saved_underwear = underwear
character.undershirt = undershirt
character.saved_undershirt = undershirt
character.socks = socks
character.saved_socks = socks
character.undie_color = undie_color
character.shirt_color = shirt_color
character.socks_color = socks_color
character.backbag = backbag
+17 -4
View File
@@ -108,6 +108,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["tip_delay"] >> tip_delay
S["pda_style"] >> pda_style
S["pda_color"] >> pda_color
S["pda_skin"] >> pda_skin
//citadel code
S["arousable"] >> arousable
@@ -144,6 +145,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
be_special = SANITIZE_LIST(be_special)
pda_style = sanitize_inlist(pda_style, GLOB.pda_styles, initial(pda_style))
pda_color = sanitize_hexcolor(pda_color, 6, 1, initial(pda_color))
pda_skin = sanitize_inlist(pda_skin, GLOB.pda_reskins, PDA_SKIN_ALT)
screenshake = sanitize_integer(screenshake, 0, 800, initial(screenshake))
damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake))
@@ -200,6 +202,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["tip_delay"], tip_delay)
WRITE_FILE(S["pda_style"], pda_style)
WRITE_FILE(S["pda_color"], pda_color)
WRITE_FILE(S["pda_skin"], pda_skin)
//citadel code
WRITE_FILE(S["screenshake"], screenshake)
@@ -263,8 +266,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["hair_style_name"] >> hair_style
S["facial_style_name"] >> facial_hair_style
S["underwear"] >> underwear
S["undie_color"] >> undie_color
S["undershirt"] >> undershirt
S["shirt_color"] >> shirt_color
S["socks"] >> socks
S["socks_color"] >> socks_color
S["backbag"] >> backbag
S["uplink_loc"] >> uplink_spawn_loc
S["feature_mcolor"] >> features["mcolor"]
@@ -284,6 +290,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
var/savefile_slot_name = custom_name_id + "_name" //TODO remove this
S[savefile_slot_name] >> custom_names[custom_name_id]
S["preferred_ai_core_display"] >> preferred_ai_core_display
S["prefered_security_department"] >> prefered_security_department
//Jobs
@@ -330,6 +337,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_has_balls"] >> features["has_balls"]
S["feature_balls_color"] >> features["balls_color"]
S["feature_balls_size"] >> features["balls_size"]
S["feature_balls_shape"] >> features["balls_shape"]
S["feature_balls_sack_size"] >> features["balls_sack_size"]
S["feature_balls_fluid"] >> features["balls_fluid"]
//breasts features
@@ -383,14 +391,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(gender == MALE)
hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_male_list)
facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_male_list)
underwear = sanitize_inlist(underwear, GLOB.underwear_m)
undershirt = sanitize_inlist(undershirt, GLOB.undershirt_m)
else
hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_female_list)
facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_female_list)
underwear = sanitize_inlist(underwear, GLOB.underwear_f)
undershirt = sanitize_inlist(undershirt, GLOB.undershirt_f)
underwear = sanitize_inlist(underwear, GLOB.underwear_list)
undie_color = sanitize_hexcolor(undie_color, 6, 1, initial(undie_color))
undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list)
shirt_color = sanitize_hexcolor(shirt_color, 6, 1, initial(shirt_color))
socks = sanitize_inlist(socks, GLOB.socks_list)
socks_color = sanitize_hexcolor(socks_color, 6, 1, initial(socks_color))
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
hair_color = sanitize_hexcolor(hair_color, 3, 0)
facial_hair_color = sanitize_hexcolor(facial_hair_color, 3, 0)
@@ -460,8 +469,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["hair_style_name"] , hair_style)
WRITE_FILE(S["facial_style_name"] , facial_hair_style)
WRITE_FILE(S["underwear"] , underwear)
WRITE_FILE(S["undie_color"] , undie_color)
WRITE_FILE(S["undershirt"] , undershirt)
WRITE_FILE(S["shirt_color"] , shirt_color)
WRITE_FILE(S["socks"] , socks)
WRITE_FILE(S["socks_color"] , socks_color)
WRITE_FILE(S["backbag"] , backbag)
WRITE_FILE(S["uplink_loc"] , uplink_spawn_loc)
WRITE_FILE(S["species"] , pref_species.id)
@@ -482,6 +494,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
var/savefile_slot_name = custom_name_id + "_name" //TODO remove this
WRITE_FILE(S[savefile_slot_name],custom_names[custom_name_id])
WRITE_FILE(S["preferred_ai_core_display"] , preferred_ai_core_display)
WRITE_FILE(S["prefered_security_department"] , prefered_security_department)
//Jobs
+17 -4
View File
@@ -60,7 +60,7 @@
to_chat(owner, "<span class='warning'>You shouldn't be able to toggle a camogear helmetmask if you're not wearing it</span>")
if(new_headgear)
// Force drop the item in the headslot, even though
// it's NODROP_1
// it's TRAIT_NODROP
D.dropItemToGround(target, TRUE)
qdel(old_headgear)
// where is `SLOT_HEAD` defined? WHO KNOWS
@@ -226,6 +226,19 @@
CL.flags_cover = initial(PCL.flags_cover)
target.icon = initial(picked_item.icon)
/datum/action/item_action/chameleon/change/pda/update_item(obj/item/pda/picked_item)
if(!istype(target, /obj/item/pda))
return ..()
var/obj/item/pda/P = target
P.name = initial(picked_item.name)
P.desc = initial(picked_item.desc)
P.icon_state = initial(picked_item.icon_state)
P.item_state = initial(picked_item.item_state)
P.item_color = initial(picked_item.item_color)
P.overlays_offsets = initial(picked_item.overlays_offsets)
P.set_new_overlays()
P.update_icon()
/datum/action/item_action/chameleon/change/Trigger()
if(!IsAvailable())
return
@@ -405,12 +418,12 @@
/obj/item/clothing/head/chameleon/drone
// The camohat, I mean, holographic hat projection, is part of the
// drone itself.
item_flags = NODROP
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
// which means it offers no protection, it's just air and light
/obj/item/clothing/head/chameleon/drone/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
chameleon_action.random_look()
var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = new(src)
togglehatmask_action.UpdateButtonIcon()
@@ -459,13 +472,13 @@
/obj/item/clothing/mask/chameleon/drone
//Same as the drone chameleon hat, undroppable and no protection
item_flags = NODROP
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
// Can drones use the voice changer part? Let's not find out.
vchange = 0
/obj/item/clothing/mask/chameleon/drone/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
chameleon_action.random_look()
var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = new(src)
togglehatmask_action.UpdateButtonIcon()
@@ -584,7 +597,7 @@
/obj/item/pda/chameleon
name = "PDA"
var/datum/action/item_action/chameleon/change/chameleon_action
var/datum/action/item_action/chameleon/change/pda/chameleon_action
/obj/item/pda/chameleon/Initialize()
. = ..()
+31 -1
View File
@@ -43,6 +43,8 @@
/obj/item/clothing/Initialize()
. = ..()
if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE))
actions_types += /datum/action/item_action/toggle_voice_box
if(ispath(pocket_storage_component_path))
LoadComponent(pocket_storage_component_path)
@@ -135,7 +137,7 @@
update_clothes_damaged_state(TRUE)
if(ismob(loc)) //It's not important enough to warrant a message if nobody's wearing it
var/mob/M = loc
M.visible_message("<span class='warning'>[M]'s [name] starts to fall apart!", "<span class='warning'>Your [name] starts to fall apart!</span>")
to_chat(M, "<span class='warning'>Your [name] starts to fall apart!</span>")
/obj/item/clothing/proc/update_clothes_damaged_state(damaging = TRUE)
var/index = "[REF(initial(icon))]-[initial(icon_state)]"
@@ -216,6 +218,34 @@ BLIND // can't see anything
..()
/obj/item/clothing/under/CtrlClick(mob/user)
. = ..()
if (!(item_flags & IN_INVENTORY))
return
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if(has_sensor == LOCKED_SENSORS)
to_chat(user, "The controls are locked.")
return
if(has_sensor == BROKEN_SENSORS)
to_chat(user, "The sensors have shorted out!")
return
if(has_sensor <= NO_SENSORS)
to_chat(user, "This suit does not have any sensors.")
return
sensor_mode = SENSOR_COORDS
to_chat(user, "<span class='notice'>Your suit will now report your exact vital lifesigns as well as your coordinate position.</span>")
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.w_uniform == src)
H.update_suit_sensors()
/obj/item/clothing/under/AltClick(mob/user)
if(..())
return 1
+8 -5
View File
@@ -45,7 +45,7 @@
/obj/item/clothing/glasses/proc/thermal_overload()
if(ishuman(src.loc))
var/mob/living/carbon/human/H = src.loc
if(!(H.has_trait(TRAIT_BLIND)))
if(!(HAS_TRAIT(H, TRAIT_BLIND)))
if(H.glasses == src)
to_chat(H, "<span class='danger'>[src] overloads and blinds you!</span>")
H.flash_act(visual = 1)
@@ -98,7 +98,7 @@
desc = "A pair of snazzy goggles used to protect against chemical spills. Fitted with an analyzer for scanning items and reagents."
icon_state = "purple"
item_state = "glasses"
scan_reagents = 1 //You can see reagents while wearing science goggles
scan_reagents = TRUE //You can see reagents while wearing science goggles
actions_types = list(/datum/action/item_action/toggle_research_scanner)
glass_colour_type = /datum/client_colour/glass_colour/purple
resistance_flags = ACID_PROOF
@@ -202,7 +202,7 @@
/obj/item/clothing/glasses/sunglasses/reagent
name = "beer goggles"
desc = "A pair of sunglasses outfitted with apparatus to scan reagents."
scan_reagents = 1
scan_reagents = TRUE
/obj/item/clothing/glasses/sunglasses/garb
name = "black gar glasses"
@@ -377,11 +377,14 @@
item_state = "godeye"
vision_flags = SEE_TURFS|SEE_MOBS|SEE_OBJS
darkness_view = 8
scan_reagents = 1
item_flags = NODROP
scan_reagents = TRUE
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
resistance_flags = LAVA_PROOF | FIRE_PROOF
/obj/item/clothing/glasses/godeye/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, EYE_OF_GOD_TRAIT)
/obj/item/clothing/glasses/godeye/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, src) && W != src && W.loc == user)
if(W.icon_state == "godeye")
+34 -29
View File
@@ -7,6 +7,7 @@
permeability_coefficient = 0.05
item_color="yellow"
resistance_flags = NONE
var/can_be_cut = 1
/obj/item/clothing/gloves/color/fyellow //Cheap Chinese Crap
desc = "These gloves are cheap knockoffs of the coveted ones - no way this can end badly."
@@ -17,6 +18,7 @@
permeability_coefficient = 0.05
item_color="yellow"
resistance_flags = NONE
var/can_be_cut = 1
/obj/item/clothing/gloves/color/fyellow/New()
..()
@@ -30,6 +32,38 @@
. = ..()
siemens_coefficient = pick(0,0,0,0.5,0.5,0.5,0.75)
/obj/item/clothing/gloves/cut
desc = "These gloves would protect the wearer from electric shock.. if the fingers were covered."
name = "fingerless insulated gloves"
icon_state = "yellowcut"
item_state = "yglovescut"
siemens_coefficient = 1
permeability_coefficient = 1
resistance_flags = NONE
transfer_prints = TRUE
/obj/item/clothing/gloves/cut/family
desc = "The old gloves your great grandfather stole from Engineering, many moons ago. They've seen some tough times recently."
name = "fingerless insulated gloves"
/obj/item/clothing/gloves/color/yellow/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wirecutters))
if(can_be_cut && icon_state == initial(icon_state))//only if not dyed
to_chat(user, "<span class='notice'>You snip the fingertips off of [src].</span>")
I.play_tool_sound(src)
new /obj/item/clothing/gloves/cut(drop_location())
qdel(src)
..()
/obj/item/clothing/gloves/color/fyellow/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wirecutters))
if(can_be_cut && icon_state == initial(icon_state))//only if not dyed
to_chat(user, "<span class='notice'>You snip the fingertips off of [src].</span>")
I.play_tool_sound(src)
new /obj/item/clothing/gloves/cut(drop_location())
qdel(src)
..()
/obj/item/clothing/gloves/color/black
desc = "These gloves are fire-resistant."
name = "black gloves"
@@ -184,32 +218,3 @@
/obj/item/clothing/gloves/color/white/redcoat
item_color = "redcoat" //Exists for washing machines. Is not different from white gloves in any way.
/obj/item/clothing/gloves/color/random
name = "random gloves"
desc = "These gloves are supposed to be a random color..."
icon_state = "random_gloves"
item_state = "wgloves"
item_color = "mime"
/obj/item/clothing/gloves/color/random/Initialize()
..()
var/list/gloves = list(
/obj/item/clothing/gloves/color/orange = 1,
/obj/item/clothing/gloves/color/red = 1,
/obj/item/clothing/gloves/color/blue = 1,
/obj/item/clothing/gloves/color/purple = 1,
/obj/item/clothing/gloves/color/green = 1,
/obj/item/clothing/gloves/color/grey = 1,
/obj/item/clothing/gloves/color/light_brown = 1,
/obj/item/clothing/gloves/color/brown = 1,
/obj/item/clothing/gloves/color/white = 1,
/obj/item/clothing/gloves/color/rainbow = 1)
var/obj/item/clothing/gloves/color/selected = pick(gloves)
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
H.equip_to_slot_or_del(new selected(H), SLOT_GLOVES)
else
new selected(loc)
return INITIALIZE_HINT_QDEL
@@ -27,7 +27,7 @@
/obj/item/clothing/gloves/combat
name = "combat gloves"
desc = "These tactical gloves are fireproof and shock resistant."
icon_state = "black"
icon_state = "combat"
item_state = "blackgloves"
siemens_coefficient = 0
permeability_coefficient = 0.05
+2
View File
@@ -54,6 +54,8 @@
tint = 2
/obj/item/clothing/head/helmet/blueshirt
name = "blue helmet"
desc = "A reliable, blue tinted helmet reminding you that you <i>still</i> owe that engineer a beer."
icon_state = "blueshift"
item_state = "blueshift"
+83 -1
View File
@@ -1,3 +1,8 @@
//defines the drill hat's yelling setting
#define DRILL_DEFAULT "default"
#define DRILL_SHOUTING "shouting"
#define DRILL_YELLING "yelling"
#define DRILL_CANADIAN "canadian"
//Chef
/obj/item/clothing/head/chefhat
@@ -42,6 +47,7 @@
name = "captain's beret"
desc = "A beret fit for a leader."
icon_state = "capberet"
dynamic_hair_suffix = ""
dog_fashion = null
@@ -57,6 +63,7 @@
name = "head of personnel's beret"
desc = "The symbol of true bureaucratic micromanagement, although in a fancy form."
icon_state = "hopberet"
dynamic_hair_suffix = ""
dog_fashion = null
@@ -114,9 +121,12 @@
/obj/item/clothing/head/beret/highlander
desc = "That was white fabric. <i>Was.</i>"
item_flags = NODROP
dog_fashion = null //THIS IS FOR SLAUGHTER, NOT PUPPIES
/obj/item/clothing/head/beret/highlander/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, HIGHLANDER)
//Security
/obj/item/clothing/head/HoS
@@ -148,6 +158,73 @@
strip_delay = 60
dog_fashion = /datum/dog_fashion/head/warden
/obj/item/clothing/head/warden/drill
name = "warden's campaign hat"
desc = "A special armored campaign hat with the security insignia emblazoned on it. Uses reinforced fabric to offer sufficient protection. Has the letters 'FMJ' enscribed on its side."
icon_state = "wardendrill"
item_state = "wardendrill"
dog_fashion = null
var/mode = DRILL_DEFAULT
/obj/item/clothing/head/warden/drill/screwdriver_act(mob/living/carbon/human/user, obj/item/I)
if(..())
return TRUE
switch(mode)
if(DRILL_DEFAULT)
to_chat(user, "<span class='notice'>You set the voice circuit to the middle position.</span>")
mode = DRILL_SHOUTING
if(DRILL_SHOUTING)
to_chat(user, "<span class='notice'>You set the voice circuit to the last position.</span>")
mode = DRILL_YELLING
if(DRILL_YELLING)
to_chat(user, "<span class='notice'>You set the voice circuit to the first position.</span>")
mode = DRILL_DEFAULT
if(DRILL_CANADIAN)
to_chat(user, "<span class='danger'>You adjust voice circuit but nothing happens, probably because it's broken.</span>")
return TRUE
/obj/item/clothing/head/warden/drill/wirecutter_act(mob/living/user, obj/item/I)
if(mode != DRILL_CANADIAN)
to_chat(user, "<span class='danger'>You broke the voice circuit!</span>")
mode = DRILL_CANADIAN
return TRUE
/obj/item/clothing/head/warden/drill/equipped(mob/M, slot)
. = ..()
if (slot == SLOT_HEAD)
RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech)
else
UnregisterSignal(M, COMSIG_MOB_SAY)
/obj/item/clothing/head/warden/drill/dropped(mob/M)
. = ..()
UnregisterSignal(M, COMSIG_MOB_SAY)
/obj/item/clothing/head/warden/drill/proc/handle_speech(datum/source, mob/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
if(message[1] != "*")
switch (mode)
if(DRILL_SHOUTING)
message += "!"
if(DRILL_YELLING)
message += "!!"
if(DRILL_CANADIAN)
message = " [message]"
var/list/canadian_words = strings("canadian_replacement.json", "canadian")
for(var/key in canadian_words)
var/value = canadian_words[key]
if(islist(value))
value = pick(value)
message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]")
message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]")
message = replacetextEx(message, " [key]", " [value]")
if(prob(30))
message += pick(", eh?", ", EH?")
speech_args[SPEECH_MESSAGE] = message
/obj/item/clothing/head/beret/sec
name = "security beret"
desc = "A robust beret with the security insignia emblazoned on it. Uses reinforced fabric to offer sufficient protection."
@@ -201,3 +278,8 @@
name = "quartermaster's beret"
desc = "This headwear shows off your Cargonian leadership"
icon_state = "qmberet"
#undef DRILL_DEFAULT
#undef DRILL_SHOUTING
#undef DRILL_YELLING
#undef DRILL_CANADIAN
+24 -9
View File
@@ -221,9 +221,12 @@
icon_state = "shamebrero"
item_state = "shamebrero"
desc = "Once it's on, it never comes off."
item_flags = NODROP
dog_fashion = null
/obj/item/clothing/head/sombrero/shamebrero/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, SHAMEBRERO_TRAIT)
/obj/item/clothing/head/cone
desc = "This cone is trying to warn you of something!"
name = "warning cone"
@@ -330,9 +333,21 @@
icon_state = "beretblack"
dynamic_hair_suffix = ""
/obj/item/clothing/head/frenchberet/speechModification(M)
if(copytext(M, 1, 2) != "*")
M = " [M]"
/obj/item/clothing/head/frenchberet/equipped(mob/M, slot)
. = ..()
if (slot == SLOT_HEAD)
RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech)
else
UnregisterSignal(M, COMSIG_MOB_SAY)
/obj/item/clothing/head/frenchberet/dropped(mob/M)
. = ..()
UnregisterSignal(M, COMSIG_MOB_SAY)
/obj/item/clothing/head/frenchberet/proc/handle_speech(datum/source, mob/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
if(message[1] != "*")
message = " [message]"
var/list/french_words = strings("french_replacement.json", "french")
for(var/key in french_words)
@@ -340,10 +355,10 @@
if(islist(value))
value = pick(value)
M = replacetextEx(M, " [uppertext(key)]", " [uppertext(value)]")
M = replacetextEx(M, " [capitalize(key)]", " [capitalize(value)]")
M = replacetextEx(M, " [key]", " [value]")
message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]")
message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]")
message = replacetextEx(message, " [key]", " [value]")
if(prob(3))
M += pick(" Honh honh honh!"," Honh!"," Zut Alors!")
return trim(M)
message += pick(" Honh honh honh!"," Honh!"," Zut Alors!")
speech_args[SPEECH_MESSAGE] = trim(message)
+42 -25
View File
@@ -5,12 +5,54 @@
slot_flags = ITEM_SLOT_MASK
strip_delay = 40
equip_delay_other = 40
var/modifies_speech = FALSE
var/mask_adjusted = 0
var/adjusted_flags = null
var/muzzle_var = NORMAL_STYLE
mutantrace_variation = NO_MUTANTRACE_VARIATION //most masks have overrides, but not all probably.
/obj/item/clothing/mask/attack_self(mob/user)
if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE))
TOGGLE_BITFIELD(clothing_flags, VOICEBOX_DISABLED)
var/status = !CHECK_BITFIELD(clothing_flags, VOICEBOX_DISABLED)
to_chat(user, "<span class='notice'>You turn the voice box in [src] [status ? "on" : "off"].</span>")
/obj/item/clothing/mask/equipped(mob/M, slot)
. = ..()
if (slot == SLOT_WEAR_MASK && modifies_speech)
RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech)
else
UnregisterSignal(M, COMSIG_MOB_SAY)
if(!ishuman(M))
return
var/mob/living/carbon/human/H = M
var/datum/species/pref_species = H.dna.species
if(mutantrace_variation)
if("mam_snouts" in pref_species.default_features)
if(H.dna.features["mam_snouts"] != "None")
muzzle_var = ALT_STYLE
else
muzzle_var = NORMAL_STYLE
else if("snout" in pref_species.default_features)
if(H.dna.features["snout"] != "None")
muzzle_var = ALT_STYLE
else
muzzle_var = NORMAL_STYLE
else
muzzle_var = NORMAL_STYLE
H.update_inv_wear_mask()
/obj/item/clothing/mask/dropped(mob/M)
. = ..()
UnregisterSignal(M, COMSIG_MOB_SAY)
/obj/item/clothing/mask/proc/handle_speech()
/obj/item/clothing/mask/worn_overlays(isinhands = FALSE)
. = list()
if(!isinhands)
@@ -20,31 +62,6 @@
IF_HAS_BLOOD_DNA(src)
. += mutable_appearance('icons/effects/blood.dmi', "maskblood")
/obj/item/clothing/mask/equipped(mob/user, slot)
..()
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/datum/species/pref_species = H.dna.species
if(mutantrace_variation)
if("mam_snouts" in pref_species.default_features)
if(H.dna.features["mam_snouts"] != "None")
muzzle_var = ALT_STYLE
else
muzzle_var = NORMAL_STYLE
else if("snout" in pref_species.default_features)
if(H.dna.features["snout"] != "None")
muzzle_var = ALT_STYLE
else
muzzle_var = NORMAL_STYLE
else
muzzle_var = NORMAL_STYLE
H.update_inv_wear_mask()
/obj/item/clothing/mask/update_clothes_damaged_state(damaging = TRUE)
..()
if(ismob(loc))
+5 -3
View File
@@ -20,9 +20,11 @@
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
w_class = WEIGHT_CLASS_SMALL
mutantrace_variation = MUTANTRACE_VARIATION
modifies_speech = TRUE
/obj/item/clothing/mask/luchador/speechModification(message)
if(copytext(message, 1, 2) != "*")
/obj/item/clothing/mask/luchador/handle_speech(datum/source, list/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
if(message[1] != "*")
message = replacetext(message, "captain", "CAPITÁN")
message = replacetext(message, "station", "ESTACIÓN")
message = replacetext(message, "sir", "SEÑOR")
@@ -42,7 +44,7 @@
message = uppertext(message) //Things end up looking better this way (no mixed cases), and it fits the macho wrestler image.
if(prob(25))
message += " OLE!"
return message
speech_args[SPEECH_MESSAGE] = message
/obj/item/clothing/mask/luchador/tecnicos
name = "Tecnicos Mask"
+79 -64
View File
@@ -46,10 +46,12 @@
/obj/item/clothing/mask/fakemoustache/italian
name = "italian moustache"
desc = "Made from authentic Italian moustache hairs. Gives the wearer an irresistable urge to gesticulate wildly."
modifies_speech = TRUE
/obj/item/clothing/mask/fakemoustache/italian/speechModification(M)
if(copytext(M, 1, 2) != "*")
M = " [M]"
/obj/item/clothing/mask/fakemoustache/italian/handle_speech(datum/source, list/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
if(message[1] != "*")
message = " [message]"
var/list/italian_words = strings("italian_replacement.json", "italian")
for(var/key in italian_words)
@@ -57,13 +59,13 @@
if(islist(value))
value = pick(value)
M = replacetextEx(M, " [uppertext(key)]", " [uppertext(value)]")
M = replacetextEx(M, " [capitalize(key)]", " [capitalize(value)]")
M = replacetextEx(M, " [key]", " [value]")
message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]")
message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]")
message = replacetextEx(message, " [key]", " [value]")
if(prob(3))
M += pick(" Ravioli, ravioli, give me the formuoli!"," Mamma-mia!"," Mamma-mia! That's a spicy meat-ball!", " La la la la la funiculi funicula!")
return trim(M)
message += pick(" Ravioli, ravioli, give me the formuoli!"," Mamma-mia!"," Mamma-mia! That's a spicy meat-ball!", " La la la la la funiculi funicula!")
speech_args[SPEECH_MESSAGE] = trim(message)
/obj/item/clothing/mask/joy
name = "joy mask"
@@ -73,36 +75,28 @@
/obj/item/clothing/mask/pig
name = "pig mask"
desc = "A rubber pig mask."
desc = "A rubber pig mask with a builtin voice modulator."
icon_state = "pig"
item_state = "pig"
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
clothing_flags = VOICEBOX_TOGGLABLE
w_class = WEIGHT_CLASS_SMALL
actions_types = list(/datum/action/item_action/toggle_voice_box)
var/voicechange = 0
modifies_speech = TRUE
/obj/item/clothing/mask/pig/attack_self(mob/user)
voicechange = !voicechange
to_chat(user, "<span class='notice'>You turn the voice box [voicechange ? "on" : "off"]!</span>")
/obj/item/clothing/mask/pig/handle_speech(datum/source, list/speech_args)
if(!CHECK_BITFIELD(clothing_flags, VOICEBOX_DISABLED))
speech_args[SPEECH_MESSAGE] = pick("Oink!","Squeeeeeeee!","Oink Oink!")
/obj/item/clothing/mask/pig/speechModification(message)
if(voicechange)
message = pick("Oink!","Squeeeeeeee!","Oink Oink!")
return message
/obj/item/clothing/mask/spig //needs to be different otherwise you could turn the speedmodification off and on
/obj/item/clothing/mask/pig/cursed //needs to be different otherwise you could turn the speedmodification off and on
name = "Pig face"
desc = "It looks like a mask, but closer inspection reveals it's melded onto this persons face!" //It's only ever going to be attached to your face.
icon_state = "pig"
item_state = "pig"
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
w_class = WEIGHT_CLASS_SMALL
var/voicechange = 1
flags_inv = HIDEFACIALHAIR
clothing_flags = NONE
/obj/item/clothing/mask/spig/speechModification(message)
if(voicechange)
message = pick("Oink!","Squeeeeeeee!","Oink Oink!")
return message
/obj/item/clothing/mask/pig/cursed/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CURSED_MASK_TRAIT)
playsound(get_turf(src), 'sound/magic/pighead_curse.ogg', 50, 1)
///frog mask - reeee!!
/obj/item/clothing/mask/frog
@@ -112,47 +106,55 @@
item_state = "frog"
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
w_class = WEIGHT_CLASS_SMALL
var/voicechange = TRUE
clothing_flags = VOICEBOX_TOGGLABLE
modifies_speech = TRUE
/obj/item/clothing/mask/frog/attack_self(mob/user)
voicechange = !voicechange
to_chat(user, "<span class='notice'>You turn the voice box [voicechange ? "on" : "off"]!</span>")
/obj/item/clothing/mask/frog/speechModification(message) //whenever you speak
if(voicechange)
/obj/item/clothing/mask/frog/handle_speech(datum/source, list/speech_args) //whenever you speak
if(!CHECK_BITFIELD(clothing_flags, VOICEBOX_DISABLED))
if(prob(5)) //sometimes, the angry spirit finds others words to speak.
message = pick("HUUUUU!!","SMOOOOOKIN'!!","Hello my baby, hello my honey, hello my rag-time gal.", "Feels bad, man.", "GIT DIS GUY OFF ME!!" ,"SOMEBODY STOP ME!!", "NORMIES, GET OUT!!")
speech_args[SPEECH_MESSAGE] = pick("HUUUUU!!","SMOOOOOKIN'!!","Hello my baby, hello my honey, hello my rag-time gal.", "Feels bad, man.", "GIT DIS GUY OFF ME!!" ,"SOMEBODY STOP ME!!", "NORMIES, GET OUT!!")
else
message = pick("Ree!!", "Reee!!","REEE!!","REEEEE!!") //but its usually just angry gibberish,
return message
speech_args[SPEECH_MESSAGE] = pick("Ree!!", "Reee!!","REEE!!","REEEEE!!") //but its usually just angry gibberish,
/obj/item/clothing/mask/frog/cursed
item_flags = NODROP //reee!!
clothing_flags = NONE
/obj/item/clothing/mask/frog/cursed/attack_self(mob/user)
return //no voicebox to alter.
/obj/item/clothing/mask/frog/cursed/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CURSED_MASK_TRAIT)
/obj/item/clothing/mask/frog/cursed/equipped(mob/user, slot)
var/mob/living/carbon/C = user
if(C.wear_mask == src)
to_chat(user, "<span class='warning'><B>[src] was cursed! Ree!!</B></span>")
if(C.wear_mask == src && HAS_TRAIT_FROM(src, TRAIT_NODROP, CURSED_ITEM_TRAIT))
to_chat(user, "<span class='userdanger'><B>[src] was cursed! Ree!!</B></span>")
return ..()
/obj/item/clothing/mask/cowmask
name = "Cowface"
desc = "It looks like a mask, but closer inspection reveals it's melded onto this persons face!"
name = "Cow mask with a builtin voice modulator."
desc = "A rubber cow mask,"
icon = 'icons/mob/mask.dmi'
icon_state = "cowmask"
item_state = "cowmask"
clothing_flags = VOICEBOX_TOGGLABLE
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
w_class = WEIGHT_CLASS_SMALL
var/voicechange = 1
modifies_speech = TRUE
/obj/item/clothing/mask/cowmask/speechModification(message)
if(voicechange)
message = pick("Moooooooo!","Moo!","Moooo!")
return message
/obj/item/clothing/mask/cowmask/handle_speech(datum/source, list/speech_args)
if(!CHECK_BITFIELD(clothing_flags, VOICEBOX_DISABLED))
speech_args[SPEECH_MESSAGE] = pick("Moooooooo!","Moo!","Moooo!")
/obj/item/clothing/mask/cowmask/cursed
name = "cow face"
desc = "It looks like a cow mask, but closer inspection reveals it's melded onto this persons face!"
flags_inv = HIDEFACIALHAIR
clothing_flags = NONE
/obj/item/clothing/mask/cowmask/cursed/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CURSED_MASK_TRAIT)
playsound(get_turf(src), 'sound/magic/cowhead_curse.ogg', 50, 1)
/obj/item/clothing/mask/horsehead
name = "horse head mask"
@@ -161,12 +163,23 @@
item_state = "horsehead"
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDEEYES|HIDEEARS
w_class = WEIGHT_CLASS_SMALL
var/voicechange = 1
clothing_flags = VOICEBOX_TOGGLABLE
/obj/item/clothing/mask/horsehead/speechModification(message)
if(voicechange)
message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
return message
/obj/item/clothing/mask/horsehead/handle_speech(datum/source, list/speech_args)
if(!CHECK_BITFIELD(clothing_flags, VOICEBOX_DISABLED))
speech_args[SPEECH_MESSAGE] = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
/obj/item/clothing/mask/horsehead/cursed
name = "horse face"
desc = "It initially looks like a mask, but it's melded into the poor person's face."
clothing_flags = NONE
flags_inv = HIDEFACIALHAIR
/obj/item/clothing/mask/horsehead/cursed/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CURSED_MASK_TRAIT)
playsound(get_turf(src), 'sound/magic/horsehead_curse.ogg', 50, 1)
/obj/item/clothing/mask/rat
name = "rat mask"
@@ -285,16 +298,18 @@
item_state = "gondola"
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
w_class = WEIGHT_CLASS_SMALL
modifies_speech = TRUE
/obj/item/clothing/mask/gondola/speechModification(M)
if(copytext(M, 1, 2) != "*")
M = " [M]"
/obj/item/clothing/mask/gondola/handle_speech(datum/source, list/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
if(message[1] != "*")
message = " [message]"
var/list/spurdo_words = strings("spurdo_replacement.json", "spurdo")
for(var/key in spurdo_words)
var/value = spurdo_words[key]
if(islist(value))
value = pick(value)
M = replacetextEx(M,regex(uppertext(key),"g"), "[uppertext(value)]")
M = replacetextEx(M,regex(capitalize(key),"g"), "[capitalize(value)]")
M = replacetextEx(M,regex(key,"g"), "[value]")
return trim(M)
message = replacetextEx(message,regex(uppertext(key),"g"), "[uppertext(value)]")
message = replacetextEx(message,regex(capitalize(key),"g"), "[capitalize(value)]")
message = replacetextEx(message,regex(key,"g"), "[value]")
speech_args[SPEECH_MESSAGE] = trim(message)
+1 -1
View File
@@ -66,7 +66,7 @@
var/obj/item/organ/heart/heart = M.getorganslot(ORGAN_SLOT_HEART)
var/obj/item/organ/lungs/lungs = M.getorganslot(ORGAN_SLOT_LUNGS)
if(!(M.stat == DEAD || (M.has_trait(TRAIT_FAKEDEATH))))
if(!(M.stat == DEAD || (HAS_TRAIT(M, TRAIT_FAKEDEATH))))
if(heart && istype(heart))
heart_strength = "<span class='danger'>an unstable</span>"
if(heart.beating)
+6 -2
View File
@@ -46,7 +46,8 @@
/datum/outfit/ert/commander/alert
name = "ERT Commander - High Alert"
suit = /obj/item/clothing/suit/space/hardsuit/ert/alert
glasses = /obj/item/clothing/glasses/thermal/eyepatch
backpack_contents = list(/obj/item/storage/box/engineer=1,\
/obj/item/melee/baton/loaded=1,\
@@ -80,7 +81,8 @@
/datum/outfit/ert/security/alert
name = "ERT Security - High Alert"
suit = /obj/item/clothing/suit/space/hardsuit/ert/alert/sec
backpack_contents = list(/obj/item/storage/box/engineer=1,\
/obj/item/storage/box/handcuffs=1,\
/obj/item/clothing/mask/gas/sechailer/swat=1,\
@@ -117,6 +119,7 @@
/datum/outfit/ert/medic/alert
name = "ERT Medic - High Alert"
suit = /obj/item/clothing/suit/space/hardsuit/ert/alert/med
backpack_contents = list(/obj/item/storage/box/engineer=1,\
/obj/item/melee/baton/loaded=1,\
/obj/item/clothing/mask/gas/sechailer/swat=1,\
@@ -153,6 +156,7 @@
/datum/outfit/ert/engineer/alert
name = "ERT Engineer - High Alert"
suit = /obj/item/clothing/suit/space/hardsuit/ert/alert/engi
backpack_contents = list(/obj/item/storage/box/engineer=1,\
/obj/item/melee/baton/loaded=1,\
/obj/item/clothing/mask/gas/sechailer/swat=1,\
+6 -2
View File
@@ -9,7 +9,7 @@
/obj/item/clothing/shoes/combat //basic syndicate combat boots for nuke ops and mob corpses
name = "combat boots"
desc = "High speed, low drag combat boots."
icon_state = "jackboots"
icon_state = "combat"
item_state = "jackboots"
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
@@ -157,7 +157,11 @@
icon_state = "cultalt"
/obj/item/clothing/shoes/cult/alt/ghost
item_flags = NODROP | DROPDEL
item_flags = DROPDEL
/obj/item/clothing/shoes/cult/alt/ghost/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CULT_TRAIT)
/obj/item/clothing/shoes/cyborg
name = "cyborg boots"
+36
View File
@@ -0,0 +1,36 @@
/obj/item/clothing/shoes/clown_shoes/taeclowndo
var/list/spelltypes = list (
/obj/effect/proc_holder/spell/targeted/conjure_item/summon_pie,
/obj/effect/proc_holder/spell/aimed/banana_peel,
/obj/effect/proc_holder/spell/targeted/touch/megahonk,
/obj/effect/proc_holder/spell/targeted/touch/bspie,
)
var/list/spells = list()
/obj/item/clothing/shoes/clown_shoes/taeclowndo/equipped(mob/user, slot)
. = ..()
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(!(HAS_TRAIT(H, TRAIT_CLUMSY)) && !(H.mind && H.mind.assigned_role == "Clown"))
return
if(slot == SLOT_SHOES)
spells = new
for(var/spell in spelltypes)
var/obj/effect/proc_holder/spell/S = new spell
spells += S
S.charge_counter = 0
S.start_recharge()
H.mind.AddSpell(S)
/obj/item/clothing/shoes/clown_shoes/taeclowndo/dropped(mob/user)
. = ..()
if(!ishuman(user))
return
var/mob/living/carbon/human/H = user
if(H.get_item_by_slot(SLOT_SHOES) == src)
for(var/spell in spells)
var/obj/effect/proc_holder/spell/S = spell
H.mind.spell_list.Remove(S)
qdel(S)
+6 -11
View File
@@ -27,7 +27,6 @@
armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 1000)
resistance_flags = FIRE_PROOF | ACID_PROOF
var/list/chronosafe_items = list(/obj/item/chrono_eraser, /obj/item/gun/energy/chrono_gun)
var/list/hands_nodrop = list()
var/obj/item/clothing/head/helmet/space/chronos/helmet = null
var/obj/effect/chronos_cam/camera = null
var/datum/action/innate/chrono_teleport/teleport_now = new
@@ -97,8 +96,7 @@
user.anchored = FALSE
teleporting = 0
for(var/obj/item/I in user.held_items)
if(I in hands_nodrop)
I.item_flags &= ~NODROP
REMOVE_TRAIT(I, TRAIT_NODROP, CHRONOSUIT_TRAIT)
if(camera)
camera.remove_target_ui()
camera.forceMove(user)
@@ -131,11 +129,8 @@
user.ExtinguishMob()
hands_nodrop = list()
for(var/obj/item/I in user.held_items)
if(!(I.item_flags & NODROP))
hands_nodrop += I
I.item_flags |= NODROP
ADD_TRAIT(I, TRAIT_NODROP, CHRONOSUIT_TRAIT)
user.animate_movement = NO_STEPS
user.changeNext_move(8 + phase_in_ds)
user.notransform = 1
@@ -194,9 +189,9 @@
if(user.head && istype(user.head, /obj/item/clothing/head/helmet/space/chronos))
to_chat(user, "\[ <span style='color: #00ff00;'>ok</span> \] Mounting /dev/helm")
helmet = user.head
helmet.item_flags |= NODROP
ADD_TRAIT(helmet, TRAIT_NODROP, CHRONOSUIT_TRAIT)
helmet.suit = src
src.item_flags |= NODROP
ADD_TRAIT(src, TRAIT_NODROP, CHRONOSUIT_TRAIT)
to_chat(user, "\[ <span style='color: #00ff00;'>ok</span> \] Starting brainwave scanner")
to_chat(user, "\[ <span style='color: #00ff00;'>ok</span> \] Starting ui display driver")
to_chat(user, "\[ <span style='color: #00ff00;'>ok</span> \] Initializing chronowalk4-view")
@@ -215,7 +210,7 @@
activating = 1
var/mob/living/carbon/human/user = src.loc
var/hard_landing = teleporting && force
item_flags &= ~NODROP
REMOVE_TRAIT(src, TRAIT_NODROP, CHRONOSUIT_TRAIT)
cooldown = world.time + cooldowntime * 1.5
activated = 0
activating = 0
@@ -236,7 +231,7 @@
to_chat(user, "\[ <span style='color: #ff5500;'>ok</span> \] Unmounting /dev/helmet")
to_chat(user, "logout")
if(helmet)
helmet.item_flags &= ~NODROP
REMOVE_TRAIT(helmet, TRAIT_NODROP, CHRONOSUIT_TRAIT)
helmet.suit = null
helmet = null
if(camera)
@@ -897,7 +897,7 @@
usermessage("You're already wearing something on your back!", "boldwarning")
return FALSE
user.equip_to_slot_if_possible(pack,SLOT_BACK,0,0,1)
pack.item_flags |= NODROP
ADD_TRAIT(pack, TRAIT_NODROP, FLIGHTSUIT_TRAIT)
resync()
user.visible_message("<span class='notice'>A [pack.name] extends from [user]'s [name] and clamps to [user.p_their()] back!</span>")
user.update_inv_wear_suit()
@@ -911,7 +911,7 @@
return FALSE
if(pack.flight && forced)
pack.disable_flight(1)
pack.item_flags &= ~NODROP
REMOVE_TRAIT_FROM(pack, TRAIT_NODROP, FLIGHTSUIT_TRAIT)
resync()
if(user)
user.transferItemToLoc(pack, src, TRUE)
@@ -935,14 +935,14 @@
usermessage("You're already wearing something on your feet!", "boldwarning")
return FALSE
user.equip_to_slot_if_possible(shoes,SLOT_SHOES,0,0,1)
shoes.item_flags |= NODROP
ADD_TRAIT(shoes, TRAIT_NODROP, FLIGHTSUIT_TRAIT)
user.visible_message("<span class='notice'>[user]'s [name] extends a pair of [shoes.name] over [user.p_their()] feet!</span>")
user.update_inv_wear_suit()
playsound(src.loc, 'sound/mecha/mechmove03.ogg', 50, 1)
deployedshoes = TRUE
/obj/item/clothing/suit/space/hardsuit/flightsuit/proc/retract_flightshoes(forced = FALSE)
shoes.item_flags &= ~NODROP
REMOVE_TRAIT_FROM(shoes, TRAIT_NODROP, FLIGHTSUIT_TRAIT)
playsound(src, 'sound/mecha/mechmove03.ogg', 50, 1)
if(user)
user.transferItemToLoc(shoes, src, TRUE)
+50 -17
View File
@@ -435,7 +435,6 @@
. = ..()
AddComponent(/datum/component/anti_magic, TRUE, FALSE)
//Medical hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/medical
name = "medical hardsuit helmet"
@@ -445,7 +444,8 @@
item_color = "medical"
flash_protect = 0
armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 75)
scan_reagents = 1
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
scan_reagents = TRUE
/obj/item/clothing/suit/space/hardsuit/medical
icon_state = "hardsuit-medical"
@@ -467,7 +467,7 @@
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 100, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 80)
var/obj/machinery/doppler_array/integrated/bomb_radar
scan_reagents = 1
scan_reagents = TRUE
actions_types = list(/datum/action/item_action/toggle_helmet_light, /datum/action/item_action/toggle_research_scanner)
/obj/item/clothing/head/helmet/space/hardsuit/rd/Initialize()
@@ -499,8 +499,6 @@
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/rd
tauric = TRUE //Citadel Add for tauric hardsuits
//Security hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/security
name = "security hardsuit helmet"
@@ -510,7 +508,6 @@
item_color = "sec"
armor = list("melee" = 35, "bullet" = 15, "laser" = 30,"energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 50, "fire" = 75, "acid" = 75)
/obj/item/clothing/suit/space/hardsuit/security
icon_state = "hardsuit-sec"
name = "security hardsuit"
@@ -532,7 +529,6 @@
item_color = "hos"
armor = list("melee" = 45, "bullet" = 25, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 100, "rad" = 50, "fire" = 95, "acid" = 95)
/obj/item/clothing/suit/space/hardsuit/security/hos
icon_state = "hardsuit-hos"
name = "head of security's hardsuit"
@@ -623,6 +619,49 @@
var/footstep = 1
var/datum/component/mobhook
/obj/item/clothing/suit/space/hardsuit/ancient/mason
name = "M.A.S.O.N RIG"
desc = "The Multi-Augmented Severe Operations Networked Resource Integration Gear is an man-portable tank designed for extreme environmental situations. It is excessively bulky, but rated for all but the most atomic of hazards. The specialized armor is surprisingly weak to conventional weaponry. The exo slot can attach most storge bags on to the suit."
icon_state = "hardsuit-ancient"
item_state = "anc_hardsuit"
armor = list("melee" = 10, "bullet" = 5, "laser" = 5, "energy" = 500, "bomb" = 500, "bio" = 500, "rad" = 500, "fire" = 500, "acid" = 500)
slowdown = 6 //Slow
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage, /obj/item/construction/rcd, /obj/item/pipe_dispenser)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ancient/mason
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
/obj/item/clothing/head/helmet/space/hardsuit/ancient/mason
name = "M.A.S.O.N RIG helmet"
desc = "The M.A.S.O.N RIG helmet is complimentary to the rest of the armor. It features a very large, high powered flood lamp and robust flash protection."
icon_state = "hardsuit0-ancient"
item_state = "anc_helm"
armor = list("melee" = 10, "bullet" = 5, "laser" = 5, "energy" = 500, "bomb" = 500, "bio" = 500, "rad" = 500, "fire" = 500, "acid" = 500)
item_color = "ancient"
brightness_on = 16
scan_reagents = TRUE
flash_protect = 5 //We will not be flash by bombs
tint = 1
var/obj/machinery/doppler_array/integrated/bomb_radar
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
/obj/item/clothing/head/helmet/space/hardsuit/ancient/mason/Initialize()
. = ..()
bomb_radar = new /obj/machinery/doppler_array/integrated(src)
/obj/item/clothing/head/helmet/space/hardsuit/ancient/mason/equipped(mob/living/carbon/human/user, slot)
..()
if (slot == SLOT_HEAD)
var/datum/atom_hud/DHUD = GLOB.huds[DATA_HUD_DIAGNOSTIC_BASIC]
DHUD.add_hud_to(user)
/obj/item/clothing/head/helmet/space/hardsuit/ancient/mason/dropped(mob/living/carbon/human/user)
..()
if (user.head == src)
var/datum/atom_hud/DHUD = GLOB.huds[DATA_HUD_DIAGNOSTIC_BASIC]
DHUD.remove_hud_from(user)
/obj/item/clothing/suit/space/hardsuit/ancient/proc/on_mob_move()
var/mob/living/carbon/human/H = loc
if(!istype(H) || H.wear_suit != src)
@@ -692,7 +731,6 @@
return 1
return 0
/obj/item/clothing/suit/space/hardsuit/shielded/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
@@ -728,12 +766,15 @@
icon_state = "ert_medical"
item_state = "ert_medical"
item_color = "ert_medical"
item_flags = NODROP //Dont want people changing into the other teams gear
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf
armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95)
slowdown = 0
max_charges = 5
/obj/item/clothing/suit/space/hardsuit/shielded/ctf/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CAPTURE_THE_FLAG_TRAIT)
/obj/item/clothing/suit/space/hardsuit/shielded/ctf/red
name = "red shielded hardsuit"
icon_state = "ert_security"
@@ -750,8 +791,6 @@
item_state = "ert_command"
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/blue
/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf
name = "shielded hardsuit helmet"
desc = "Standard issue hardsuit helmet for playing capture the flag."
@@ -760,7 +799,6 @@
item_color = "ert_medical"
armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95)
/obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red
icon_state = "hardsuit0-ert_security"
item_state = "hardsuit0-ert_security"
@@ -773,10 +811,6 @@
item_state = "hardsuit0-ert_commander"
item_color = "ert_commander"
//////Syndicate Version
/obj/item/clothing/suit/space/hardsuit/shielded/syndi
@@ -791,7 +825,6 @@
slowdown = 0
tauric = TRUE //Citadel Add for tauric hardsuits
/obj/item/clothing/suit/space/hardsuit/shielded/syndi/Initialize()
jetpack = new /obj/item/tank/jetpack/suit(src)
. = ..()

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