Merge branch 'master' into meteor
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -126,3 +126,18 @@ GLOBAL_LIST(round_end_notifiees)
|
||||
/datum/tgs_chat_command/reload_admins/proc/ReloadAsync()
|
||||
set waitfor = FALSE
|
||||
load_admins()
|
||||
|
||||
/datum/tgs_chat_command/addbunkerbypass
|
||||
name = "whitelist"
|
||||
help_text = "whitelist <ckey>"
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/addbunkerbypass/Run(datum/tgs_chat_user/sender, params)
|
||||
if(!CONFIG_GET(flag/sql_enabled))
|
||||
return "The Database is not enabled!"
|
||||
|
||||
GLOB.bunker_passthrough |= ckey(params)
|
||||
|
||||
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."
|
||||
@@ -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")
|
||||
|
||||
@@ -217,3 +217,7 @@
|
||||
/proc/_step_away(ref, trg, max)
|
||||
step_away(ref, trg, max)
|
||||
|
||||
/proc/_instantiate_at(thing, location)
|
||||
new thing(location)
|
||||
|
||||
|
||||
|
||||
@@ -841,8 +841,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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -150,6 +150,42 @@
|
||||
message_admins("[key_name_admin(src)] set the round end sound to [S]")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Set Round End Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/play_web_sound_manual()
|
||||
set category = "Fun"
|
||||
set name = "Manual Play Internet Sound"
|
||||
if(!check_rights(R_SOUNDS))
|
||||
return
|
||||
|
||||
var/web_sound_input = input("Enter youtube-dl fetched content URL (supported sites only, leave blank to stop playing)", "Send youtube-dl media link") as text|null
|
||||
if(!istext(web_sound_input))
|
||||
return
|
||||
web_sound_input = trim(web_sound_input)
|
||||
if(!length(web_sound_input))
|
||||
log_admin("[key_name(src)] stopped web sound")
|
||||
message_admins("[key_name(src)] stopped web sound")
|
||||
for(var/m in GLOB.player_list)
|
||||
var/mob/M = m
|
||||
var/client/C = M.client
|
||||
if((C.prefs.toggles & SOUND_MIDI) && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded)
|
||||
C.chatOutput.stopMusic()
|
||||
return
|
||||
var/freq = input(usr, "What frequency would you like the sound to play at?",, 1) as null|num
|
||||
if(!freq)
|
||||
return
|
||||
if(web_sound_input && !findtext(web_sound_input, GLOB.is_http_protocol))
|
||||
to_chat(src, "<span class='boldwarning'>BLOCKED: Content URL not using http(s) protocol</span>")
|
||||
to_chat(src, "<span class='warning'>The media provider returned a content URL that isn't using the HTTP or HTTPS protocol</span>")
|
||||
return
|
||||
|
||||
SSblackbox.record_feedback("nested tally", "played_url_manual", 1, list("[ckey]", "[web_sound_input]"))
|
||||
log_admin("[key_name(src)] manually played web sound: [web_sound_input]")
|
||||
message_admins("[key_name(src)] manually played web sound: <a href='web_sound_input'>HREF</a>")
|
||||
for(var/m in GLOB.player_list)
|
||||
var/mob/M = m
|
||||
var/client/C = M.client
|
||||
if((C.prefs.toggles & SOUND_MIDI) && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded)
|
||||
C.chatOutput.sendMusic(web_sound_input, freq)
|
||||
|
||||
/client/proc/stop_sounds()
|
||||
set category = "Debug"
|
||||
set name = "Stop All Playing Sounds"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1249,7 +1249,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
if(!check_rights(R_ADMIN) || !check_rights(R_FUN))
|
||||
return
|
||||
|
||||
var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_ROD, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING)
|
||||
var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING, ADMIN_PUNISHMENT_ROD)
|
||||
|
||||
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
|
||||
|
||||
@@ -1294,6 +1294,9 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
if(!puzzle_imprison(target))
|
||||
to_chat(usr,"<span class='warning'>Imprisonment failed!</span>")
|
||||
return
|
||||
if(ADMIN_PUNISHMENT_PIE)
|
||||
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target))
|
||||
creamy.splat(target)
|
||||
|
||||
var/msg = "[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment]."
|
||||
message_admins(msg)
|
||||
|
||||
@@ -108,10 +108,7 @@
|
||||
to_chat(loc, "<span class='warning'>Combat injection is still recharging.</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/M = loc
|
||||
M.adjustStaminaLoss(-75)
|
||||
M.SetUnconscious(0)
|
||||
M.SetStun(0)
|
||||
M.SetKnockdown(0)
|
||||
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)
|
||||
|
||||
@@ -503,6 +500,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
L.lastattacker = user.real_name
|
||||
L.lastattackerckey = user.ckey
|
||||
|
||||
L.adjustStaminaLoss(35) //because previously it took 5-6 hits to actually "incapacitate" someone for the purposes of the sleep inducement
|
||||
L.Knockdown(140)
|
||||
L.apply_effect(EFFECT_STUTTER, 7)
|
||||
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
icon_state = "blank_blob"
|
||||
desc = "A huge, pulsating yellow mass."
|
||||
max_integrity = 400
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 75, "acid" = 90)
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 5, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 75, "acid" = 90) // Last stand
|
||||
explosion_block = 6
|
||||
point_return = -1
|
||||
health_regen = 0 //we regen in Life() instead of when pulsed
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
max_integrity = 200
|
||||
health_regen = 1
|
||||
point_return = 25
|
||||
armor = list("melee" = 10, "bullet" = 20, "laser" = 15, "energy" = 10, "bomb" = 40, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
var/list/spores = list()
|
||||
var/mob/living/simple_animal/hostile/blob/blobbernaut/naut = null
|
||||
var/max_spores = 3
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
desc = "A thin spire of slightly swaying tendrils."
|
||||
max_integrity = 60
|
||||
point_return = 15
|
||||
armor = list("melee" = 10, "bullet" = 10, "laser" = 0, "energy" = 0, "bomb" = 15, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
var/resource_delay = 0
|
||||
|
||||
/obj/structure/blob/resource/scannerreport()
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
explosion_block = 3
|
||||
point_return = 4
|
||||
atmosblock = TRUE
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
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)
|
||||
@@ -20,14 +21,20 @@
|
||||
|
||||
/obj/structure/blob/shield/update_icon()
|
||||
..()
|
||||
if(obj_integrity <= 75)
|
||||
if(obj_integrity <= 70)
|
||||
icon_state = "blob_shield_damaged"
|
||||
name = "weakened strong blob"
|
||||
desc = "A wall of twitching tendrils."
|
||||
atmosblock = FALSE
|
||||
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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,13 +12,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.adjustStaminaLoss(-75)
|
||||
user.do_adrenaline(100, FALSE, 70, 0, TRUE, list("epinephrine" = 3, "changelingmeth" = 10, "mannitol" = 10, "omnizine" = 10, "changelingadrenaline" = 5), "<span class='notice'>Energy rushes through us.</span>")
|
||||
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,10 +10,10 @@
|
||||
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 = stripped_input(usr, "Please choose a message to transmit.", "Changeling Hivemind", "")
|
||||
var/input = html_decode(stripped_input(usr, "Please choose a message to transmit.", "Changeling Hivemind", ""))
|
||||
user.say(".g[input]")
|
||||
|
||||
/obj/effect/proc_holder/changeling/hivemind_comms/on_purchase(mob/user, is_respec)
|
||||
@@ -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)
|
||||
|
||||
@@ -344,9 +344,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))
|
||||
|
||||
@@ -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++
|
||||
|
||||
@@ -64,11 +64,11 @@
|
||||
/obj/effect/proc_holder/changeling/sting/transformation
|
||||
name = "Transformation Sting"
|
||||
desc = "We silently sting a human, injecting a retrovirus that forces them to transform."
|
||||
helptext = "The victim will transform much like a changeling would. Does not provide a warning to others. Mutations will not be transferred, and monkeys will become human. This ability is somewhat loud, and carries a small risk of our blood gaining violent sensitivity to heat."
|
||||
helptext = "The victim will transform much like a changeling would. Does not provide a warning to others. Mutations will not be transferred, and monkeys will become human. This ability is loud, and might cause our blood to react violently to heat."
|
||||
sting_icon = "sting_transform"
|
||||
chemical_cost = 50
|
||||
dna_cost = 3
|
||||
loudness = 1
|
||||
loudness = 2
|
||||
var/datum/changelingprofile/selected_dna = null
|
||||
action_icon = 'icons/mob/actions/actions_changeling.dmi'
|
||||
action_icon_state = "ling_sting_transform"
|
||||
@@ -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
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
icon_state = "clockwork_helmet"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
flags_inv = HIDEEARS|HIDEHAIR|HIDEFACE
|
||||
flags_inv = HIDEEARS|HIDEHAIR|HIDEFACE|HIDESNOUT
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
armor = list("melee" = 50, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
|
||||
/obj/item/clothing/head/helmet/clockwork/Initialize()
|
||||
|
||||
@@ -44,12 +44,13 @@
|
||||
|
||||
/obj/item/clockwork/slab/cyborg //three scriptures, plus a spear and fabricator
|
||||
clockwork_desc = "A divine link to the Celestial Derelict, allowing for limited recital of scripture."
|
||||
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/ranged_ability/linked_vanguard)
|
||||
quickbound = list(/datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/ranged_ability/linked_vanguard, \
|
||||
/datum/clockwork_scripture/create_object/stargazer)
|
||||
maximum_quickbound = 6 //we usually have one or two unique scriptures, so if ratvar is up let us bind one more
|
||||
actions_types = list()
|
||||
|
||||
/obj/item/clockwork/slab/cyborg/engineer //two scriptures, plus a fabricator
|
||||
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transmission)
|
||||
/obj/item/clockwork/slab/cyborg/engineer //three scriptures, plus a fabricator
|
||||
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transmission, /datum/clockwork_scripture/create_object/stargazer)
|
||||
|
||||
/obj/item/clockwork/slab/cyborg/medical //five scriptures, plus a spear
|
||||
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/linked_vanguard, /datum/clockwork_scripture/ranged_ability/sentinels_compromise, \
|
||||
@@ -61,12 +62,12 @@
|
||||
/obj/item/clockwork/slab/cyborg/peacekeeper //two scriptures, plus a spear
|
||||
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/hateful_manacles, /datum/clockwork_scripture/ranged_ability/judicial_marker)
|
||||
|
||||
/obj/item/clockwork/slab/cyborg/janitor //five scriptures, plus a fabricator
|
||||
/obj/item/clockwork/slab/cyborg/janitor //six scriptures, plus a fabricator
|
||||
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transgression, \
|
||||
/datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor)
|
||||
/datum/clockwork_scripture/create_object/stargazer, /datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor)
|
||||
|
||||
/obj/item/clockwork/slab/cyborg/service //five scriptures, plus xray vision
|
||||
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, \
|
||||
/obj/item/clockwork/slab/cyborg/service //six scriptures, plus xray vision
|
||||
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant,/datum/clockwork_scripture/create_object/stargazer, \
|
||||
/datum/clockwork_scripture/spatial_gateway, /datum/clockwork_scripture/create_object/clockwork_obelisk)
|
||||
|
||||
/obj/item/clockwork/slab/cyborg/miner //two scriptures, plus a spear and xray vision
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -2,6 +2,32 @@
|
||||
// DRIVERS //
|
||||
/////////////
|
||||
|
||||
//Stargazer: Creates a stargazer, a cheap power generator that utilizes starlight.
|
||||
/datum/clockwork_scripture/create_object/stargazer
|
||||
descname = "Generates Power From Starlight"
|
||||
name = "Stargazer"
|
||||
desc = "Forms a weak structure that generates power every second while within three tiles of starlight."
|
||||
invocations = list("Capture their inferior light for us!")
|
||||
channel_time = 50
|
||||
power_cost = 200
|
||||
object_path = /obj/structure/destructible/clockwork/stargazer
|
||||
creator_message = "<span class='brass'>You form a stargazer, which will generate power near starlight.</span>"
|
||||
observer_message = "<span class='warning'>A large lantern-shaped machine forms!</span>"
|
||||
usage_tip = "For obvious reasons, make sure to place this near a window or somewhere else that can see space!"
|
||||
tier = SCRIPTURE_DRIVER
|
||||
one_per_tile = TRUE
|
||||
primary_component = HIEROPHANT_ANSIBLE
|
||||
sort_priority = 1
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Creates a stargazer, which generates power when near starlight."
|
||||
|
||||
/datum/clockwork_scripture/create_object/stargazer/check_special_requirements()
|
||||
var/area/A = get_area(invoker)
|
||||
if(A.outdoors || A.map_name == "Space" || !A.blob_allowed)
|
||||
to_chat(invoker, "<span class='danger'>Stargazers can't be built off-station.</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
//Integration Cog: Creates an integration cog that can be inserted into APCs to passively siphon power.
|
||||
/datum/clockwork_scripture/create_object/integration_cog
|
||||
@@ -18,7 +44,7 @@
|
||||
tier = SCRIPTURE_DRIVER
|
||||
space_allowed = TRUE
|
||||
primary_component = HIEROPHANT_ANSIBLE
|
||||
sort_priority = 1
|
||||
sort_priority = 2
|
||||
important = TRUE
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Creates an integration cog, which can be used to siphon power from an open APC."
|
||||
@@ -39,7 +65,7 @@
|
||||
tier = SCRIPTURE_DRIVER
|
||||
one_per_tile = TRUE
|
||||
primary_component = HIEROPHANT_ANSIBLE
|
||||
sort_priority = 2
|
||||
sort_priority = 3
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Creates a Sigil of Transgression, which will briefly stun and slow the next non-Servant to cross it."
|
||||
|
||||
@@ -59,7 +85,7 @@
|
||||
tier = SCRIPTURE_DRIVER
|
||||
one_per_tile = TRUE
|
||||
primary_component = HIEROPHANT_ANSIBLE
|
||||
sort_priority = 3
|
||||
sort_priority = 4
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Creates a Sigil of Submission, which will convert non-Servants that remain on it."
|
||||
|
||||
@@ -76,7 +102,7 @@
|
||||
usage_tip = "The light can be used from up to two tiles away. Damage taken will GREATLY REDUCE the stun's duration."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
primary_component = BELLIGERENT_EYE
|
||||
sort_priority = 4
|
||||
sort_priority = 5
|
||||
slab_overlay = "volt"
|
||||
ranged_type = /obj/effect/proc_holder/slab/kindle
|
||||
ranged_message = "<span class='brass'><i>You charge the clockwork slab with divine energy.</i>\n\
|
||||
@@ -100,7 +126,7 @@
|
||||
usage_tip = "The manacles are about as strong as zipties, and break when removed."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
primary_component = BELLIGERENT_EYE
|
||||
sort_priority = 5
|
||||
sort_priority = 6
|
||||
ranged_type = /obj/effect/proc_holder/slab/hateful_manacles
|
||||
slab_overlay = "hateful_manacles"
|
||||
ranged_message = "<span class='neovgre_small'><i>You charge the clockwork slab with divine energy.</i>\n\
|
||||
@@ -124,7 +150,7 @@
|
||||
usage_tip = "You cannot reactivate Vanguard while still shielded by it."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
primary_component = VANGUARD_COGWHEEL
|
||||
sort_priority = 6
|
||||
sort_priority = 7
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Allows you to temporarily have quickly regenerating stamina and absorb stuns. All stuns absorbed will affect you when disabled."
|
||||
|
||||
@@ -156,7 +182,7 @@
|
||||
usage_tip = "The Compromise is very fast to invoke, and will remove holy water from the target Servant."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
primary_component = VANGUARD_COGWHEEL
|
||||
sort_priority = 7
|
||||
sort_priority = 8
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Allows you to convert a Servant's brute, burn, and oxygen damage to half toxin damage.<br><b>Click your slab to disable.</b>"
|
||||
slab_overlay = "compromise"
|
||||
@@ -180,7 +206,7 @@
|
||||
usage_tip = "This can't be used while on Reebe, for obvious reasons."
|
||||
tier = SCRIPTURE_DRIVER
|
||||
primary_component = GEIS_CAPACITOR
|
||||
sort_priority = 8
|
||||
sort_priority = 9
|
||||
important = TRUE
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Returns you to Reebe."
|
||||
@@ -238,7 +264,7 @@
|
||||
tier = SCRIPTURE_DRIVER
|
||||
space_allowed = TRUE
|
||||
primary_component = GEIS_CAPACITOR
|
||||
sort_priority = 9
|
||||
sort_priority = 10
|
||||
important = TRUE
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Creates a new Clockwork Slab."
|
||||
@@ -259,6 +285,6 @@
|
||||
tier = SCRIPTURE_DRIVER
|
||||
space_allowed = TRUE
|
||||
primary_component = GEIS_CAPACITOR
|
||||
sort_priority = 10
|
||||
sort_priority = 11
|
||||
quickbind = TRUE
|
||||
quickbind_desc = "Creates a pair of Wraith Spectacles, which grant true sight but cause gradual vision loss."
|
||||
|
||||
@@ -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,70 @@
|
||||
#define STARGAZER_RANGE 3 //How many tiles the stargazer can see out to
|
||||
#define STARGAZER_POWER 7 //How many watts will be produced per second when the stargazer sees starlight
|
||||
|
||||
//Stargazer: A very fragile but cheap generator that creates power from starlight.
|
||||
/obj/structure/destructible/clockwork/stargazer
|
||||
name = "stargazer"
|
||||
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 = "stargazer"
|
||||
unanchored_icon = "stargazer_unwrenched"
|
||||
max_integrity = 40
|
||||
construction_value = 5
|
||||
layer = WALL_OBJ_LAYER
|
||||
break_message = "<span class='warning'>The stargazer's fragile body shatters into pieces!</span>"
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
light_color = "#DAAA18"
|
||||
var/star_light_star_bright = FALSE //If this stargazer can see starlight
|
||||
|
||||
/obj/structure/destructible/clockwork/stargazer/Initialize()
|
||||
. = ..()
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
/obj/structure/destructible/clockwork/stargazer/Destroy()
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
. = ..()
|
||||
|
||||
/obj/structure/destructible/clockwork/stargazer/examine(mob/user)
|
||||
..()
|
||||
if(is_servant_of_ratvar(user))
|
||||
to_chat(user, "<span class='nzcrentr_small'>Generates <b>[DisplayPower(STARGAZER_POWER)]</b> per second while viewing starlight within [STARGAZER_RANGE] tiles.</span>")
|
||||
if(star_light_star_bright)
|
||||
to_chat(user, "[is_servant_of_ratvar(user) ? "<span class='nzcrentr_small'>It can see starlight!</span>" : "It's shining brilliantly!"]")
|
||||
|
||||
/obj/structure/destructible/clockwork/stargazer/process()
|
||||
star_light_star_bright = check_starlight()
|
||||
if(star_light_star_bright)
|
||||
adjust_clockwork_power(STARGAZER_POWER)
|
||||
|
||||
/obj/structure/destructible/clockwork/stargazer/update_anchored(mob/living/user, damage)
|
||||
. = ..()
|
||||
star_light_star_bright = check_starlight()
|
||||
|
||||
/obj/structure/destructible/clockwork/stargazer/proc/check_starlight()
|
||||
var/old_status = star_light_star_bright
|
||||
var/has_starlight
|
||||
if(!anchored)
|
||||
has_starlight = FALSE
|
||||
else
|
||||
for(var/turf/T in view(3, src))
|
||||
if(isspaceturf(T))
|
||||
has_starlight = TRUE
|
||||
break
|
||||
if(has_starlight && anchored)
|
||||
var/area/A = get_area(src)
|
||||
if(A.outdoors || A.map_name == "Space" || !A.blob_allowed)
|
||||
has_starlight = FALSE
|
||||
if(old_status != has_starlight)
|
||||
if(has_starlight)
|
||||
visible_message("<span class='nzcrentr_small'>[src] hums and shines brilliantly!</span>")
|
||||
playsound(src, 'sound/machines/clockcult/stargazer_activate.ogg', 50, TRUE)
|
||||
add_overlay("stargazer_light")
|
||||
set_light(1.5, 5)
|
||||
else
|
||||
if(anchored) //We lost visibility somehow
|
||||
visible_message("<span class='danger'>[src] flickers, and falls dark.</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>[src] whooshes quietly as it slides into a less bulky form.</span>")
|
||||
cut_overlays()
|
||||
set_light(0)
|
||||
return has_starlight
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
//Mech sensor: Activates when stepped on by a mech
|
||||
/obj/structure/destructible/clockwork/trap/trigger/pressure_sensor/mech
|
||||
name = "mech sensor"
|
||||
desc = "A thin plate of brass, barely visible but clearly distinct."
|
||||
clockwork_desc = "A trigger that will activate when a mech controlled by a non-servant runs across it."
|
||||
max_integrity = 5
|
||||
icon_state = "pressure_sensor"
|
||||
alpha = 75
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/trigger/pressure_sensor/mech/Crossed(atom/movable/AM)
|
||||
|
||||
if(!istype(AM,/obj/mecha/))
|
||||
return
|
||||
|
||||
var/obj/mecha/M = AM
|
||||
if(M.occupant && is_servant_of_ratvar(M.occupant))
|
||||
return
|
||||
audible_message("<i>*click*</i>")
|
||||
playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE)
|
||||
activate()
|
||||
@@ -68,7 +68,14 @@
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE //So players can interact with the tile it's on to pull them off
|
||||
buckle_mob(squirrel, TRUE)
|
||||
else
|
||||
visible_message("<span class='danger'>A massive brass spike erupts from the ground!</span>")
|
||||
var/obj/mecha/M = locate() in get_turf(src)
|
||||
if(M)
|
||||
M.take_damage(50,BRUTE,"melee")
|
||||
M.visible_message("<span class='danger'>A massive brass spike erupts from the ground, penetrating \the [M] and shattering the trap into pieces!</span>")
|
||||
addtimer(CALLBACK(src, .proc/take_damage, max_integrity), 1)
|
||||
else
|
||||
visible_message("<span class='danger'>A massive brass spike erupts from the ground!</span>")
|
||||
|
||||
playsound(src, 'sound/machines/clockcult/brass_skewer.ogg', 75, FALSE)
|
||||
icon_state = "[initial(icon_state)]_extended"
|
||||
density = TRUE //Skewers are one-use only
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/obj/structure/destructible/clockwork/trap/power_nullifier
|
||||
name = "power nullifier"
|
||||
desc = "A well hidden set of wires and connections."
|
||||
clockwork_desc = "When triggered, it sets off a 3x3 emp pulse with the center suffering a stronger pulse."
|
||||
icon_state = "electric_trap"
|
||||
break_message = "<span class='warning'>The power nullifier sparks, then slowly crumbles to debris!</span>"
|
||||
max_integrity = 40
|
||||
density = FALSE
|
||||
var/activated = FALSE
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/power_nullifier/activate()
|
||||
if(!activated)
|
||||
activated = TRUE
|
||||
empulse(get_turf(src),1,1,TRUE)
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/power_nullifier/emp_act(var/strength=1)
|
||||
activate()
|
||||
@@ -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,68 @@
|
||||
|
||||
/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)
|
||||
|
||||
/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)
|
||||
|
||||
//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
|
||||
|
||||
@@ -211,8 +211,6 @@
|
||||
else
|
||||
return FALSE
|
||||
|
||||
|
||||
|
||||
/datum/action/innate/cult/spin2win
|
||||
name = "Geometer's Fury"
|
||||
desc = "You draw on the power of the sword's ancient runes, spinning it wildly around you as you become immune to most attacks."
|
||||
@@ -267,7 +265,6 @@
|
||||
return
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/item/clothing/head/culthood
|
||||
name = "ancient cultist hood"
|
||||
icon_state = "culthood"
|
||||
@@ -294,7 +291,6 @@
|
||||
heat_protection = CHEST|GROIN|LEGS|ARMS
|
||||
max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
|
||||
|
||||
|
||||
/obj/item/clothing/head/culthood/alt
|
||||
name = "cultist hood"
|
||||
desc = "An armored hood worn by the followers of Nar'Sie."
|
||||
@@ -313,15 +309,15 @@
|
||||
/obj/item/clothing/suit/cultrobes/alt/ghost
|
||||
item_flags = NODROP | DROPDEL
|
||||
|
||||
|
||||
/obj/item/clothing/head/magus
|
||||
name = "magus helm"
|
||||
icon_state = "magus"
|
||||
item_state = "magus"
|
||||
desc = "A helm worn by the followers of Nar'Sie."
|
||||
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDEEARS|HIDEEYES
|
||||
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDEEARS|HIDEEYES|HIDESNOUT
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 30,"energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 10, "acid" = 10)
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/suit/magusred
|
||||
name = "magus robes"
|
||||
@@ -528,7 +524,12 @@
|
||||
"The shuttle's custodian was found washing the windows with their own blood.",
|
||||
"A shuttle engineer began screaming 'DEATH IS NOT THE END' and ripped out wires until an arc flash seared off her flesh.",
|
||||
"A shuttle inspector started laughing madly over the radio and then threw herself into an engine turbine.",
|
||||
"An assistant was found on the shuttle.",
|
||||
"A medical officer was found pouring out several blood bags onto the shuttle's instrument panels, before slitting both wrists open and screaming 'DEATH IS NOT THE END'.",
|
||||
"A fuel technician was found replacing the fuel with his blood.",
|
||||
"All the lights aboard the shuttle turned a crimson red before blowing out..",
|
||||
"The shuttle dispatcher was found dead with bloody symbols carved into their flesh.",
|
||||
"An engine turbine began leaking blood when it was powered on.",
|
||||
"The shuttle's transponder is emitting the encoded message 'FEAR THE OLD BLOOD' in lieu of its assigned identification signal.")
|
||||
var/message = pick_n_take(curses)
|
||||
message += " The shuttle will be delayed by three minutes."
|
||||
@@ -989,6 +990,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
|
||||
..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -58,18 +58,12 @@
|
||||
<A href='byond://?src=[REF(src)];send=1'>Send Signal</A><BR>
|
||||
<B>Frequency/Code</B> for signaler:<BR>
|
||||
Frequency:
|
||||
<A href='byond://?src=[REF(src)];freq=-10'>-</A>
|
||||
<A href='byond://?src=[REF(src)];freq=-2'>-</A>
|
||||
[format_frequency(src.frequency)]
|
||||
<A href='byond://?src=[REF(src)];freq=2'>+</A>
|
||||
<A href='byond://?src=[REF(src)];freq=10'>+</A><BR>
|
||||
<A href='byond://?src=[REF(src)];set=freq'>Set</A><BR>
|
||||
|
||||
Code:
|
||||
<A href='byond://?src=[REF(src)];code=-5'>-</A>
|
||||
<A href='byond://?src=[REF(src)];code=-1'>-</A>
|
||||
[src.code]
|
||||
<A href='byond://?src=[REF(src)];code=1'>+</A>
|
||||
<A href='byond://?src=[REF(src)];code=5'>+</A><BR>
|
||||
<A href='byond://?src=[REF(src)];set=code'>Set</A><BR>
|
||||
[t1]
|
||||
</TT>"}
|
||||
user << browse(dat, "window=radio")
|
||||
@@ -85,17 +79,23 @@ Code:
|
||||
onclose(usr, "radio")
|
||||
return
|
||||
|
||||
if (href_list["freq"])
|
||||
var/new_frequency = (frequency + text2num(href_list["freq"]))
|
||||
if(new_frequency < MIN_FREE_FREQ || new_frequency > MAX_FREE_FREQ)
|
||||
new_frequency = sanitize_frequency(new_frequency)
|
||||
set_frequency(new_frequency)
|
||||
if (href_list["set"])
|
||||
|
||||
if(href_list["code"])
|
||||
src.code += text2num(href_list["code"])
|
||||
src.code = round(src.code)
|
||||
src.code = min(100, src.code)
|
||||
src.code = max(1, src.code)
|
||||
if(href_list["set"] == "freq")
|
||||
var/new_freq = input(usr, "Input a new signalling frequency", "Remote Signaller Frequency", format_frequency(frequency)) as num|null
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
new_freq = unformat_frequency(new_freq)
|
||||
new_freq = sanitize_frequency(new_freq, TRUE)
|
||||
set_frequency(new_freq)
|
||||
|
||||
if(href_list["set"] == "code")
|
||||
var/new_code = input(usr, "Input a new signalling code", "Remote Signaller Code", code) as num|null
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
new_code = round(new_code)
|
||||
new_code = CLAMP(new_code, 1, 100)
|
||||
code = new_code
|
||||
|
||||
if(href_list["send"])
|
||||
spawn( 0 )
|
||||
@@ -206,4 +206,4 @@ Code:
|
||||
/obj/item/assembly/signaler/cyborg/attackby(obj/item/W, mob/user, params)
|
||||
return
|
||||
/obj/item/assembly/signaler/cyborg/screwdriver_act(mob/living/user, obj/item/I)
|
||||
return
|
||||
return
|
||||
@@ -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
|
||||
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
|
||||
|
||||
@@ -322,14 +316,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,14 +348,13 @@
|
||||
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/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
|
||||
cached_gases[/datum/gas/nitrous_oxide] -= reaction_efficency
|
||||
cached_gases[/datum/gas/plasma] -= 2*reaction_efficency
|
||||
|
||||
|
||||
if(energy_released > 0)
|
||||
@@ -388,16 +380,15 @@
|
||||
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
|
||||
|
||||
if(stim_energy_change)
|
||||
var/new_heat_capacity = air.heat_capacity()
|
||||
@@ -418,15 +409,14 @@
|
||||
|
||||
/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
|
||||
|
||||
|
||||
if (nob_formed)
|
||||
@@ -449,14 +439,13 @@
|
||||
/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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,26 @@ 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/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,16 @@ 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/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/volume_pump/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
@@ -192,4 +202,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,25 @@
|
||||
construction_type = /obj/item/pipe/trinary/flippable
|
||||
pipe_state = "filter"
|
||||
|
||||
/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("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/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("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/trinary/filter/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
@@ -159,11 +178,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 +209,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 +241,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,25 @@
|
||||
pipe_state = "mixer"
|
||||
|
||||
//node 3 is the outlet, nodes 1 & 2 are intakes
|
||||
|
||||
/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("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/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("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/trinary/mixer/layer1
|
||||
piping_layer = PIPING_LAYER_MIN
|
||||
pixel_x = -PIPING_LAYER_P_X
|
||||
|
||||
@@ -183,8 +183,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 +198,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 +220,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,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 ..()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
contents_cost = 700
|
||||
export_types = list(/obj/structure/reagent_dispensers/beerkeg)
|
||||
|
||||
|
||||
/datum/export/large/pipedispenser
|
||||
cost = 500
|
||||
unit_name = "pipe dispenser"
|
||||
@@ -122,7 +121,6 @@
|
||||
unit_name = "packaged antimatter reactor section"
|
||||
export_types = list(/obj/item/am_shielding_container)
|
||||
|
||||
|
||||
/datum/export/large/iv
|
||||
cost = 50
|
||||
unit_name = "iv drip"
|
||||
@@ -133,3 +131,86 @@
|
||||
unit_name = "security barrier"
|
||||
export_types = list(/obj/item/grenade/barrier, /obj/structure/barricade/security)
|
||||
|
||||
/datum/export/large/odysseus
|
||||
cost = 5500
|
||||
unit_name = "working odysseus"
|
||||
export_types = list(/obj/mecha/medical/odysseus)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/ripley
|
||||
cost = 6500
|
||||
unit_name = "working ripley"
|
||||
export_types = list(/obj/mecha/working/ripley)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/firefighter
|
||||
cost = 9000
|
||||
unit_name = "working firefighter"
|
||||
export_types = list(/obj/mecha/working/ripley/firefighter)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/gygax
|
||||
cost = 19000
|
||||
unit_name = "working gygax"
|
||||
export_types = list(/obj/mecha/combat/gygax)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/durand
|
||||
cost = 10000
|
||||
unit_name = "working durand"
|
||||
export_types = list(/obj/mecha/combat/durand)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/phazon
|
||||
cost = 25000 //Little over half do to needing a core
|
||||
unit_name = "working phazon"
|
||||
export_types = list(/obj/mecha/combat/phazon)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/marauder
|
||||
cost = 15000 //Still a Combat class mech - CC tech as well! 150% "normal" boundy price.
|
||||
unit_name = "working marauder"
|
||||
export_types = list(/obj/mecha/combat/marauder)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/deathripley
|
||||
cost = 8500 //Still a "Combat class" mech - Illegal tech as well! 165% "normal" boundy price.
|
||||
unit_name = "working illegally modified"
|
||||
export_types = list(/obj/mecha/working/ripley/deathripley)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/gygaxdark
|
||||
cost = 28500 //Still a Combat class mech - Illegal tech as well! 150% "normal" boundy price.
|
||||
unit_name = "working illegally modified gygax"
|
||||
export_types = list(/obj/mecha/combat/gygax/dark)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/oldripley
|
||||
cost = 6250 //old mech - Scrap metal ! 50% "normal" boundy price.
|
||||
unit_name = "working miner ripley"
|
||||
export_types = list(/obj/mecha/working/ripley/mining)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/honk
|
||||
cost = 12000 //Still a "Combat class" mech - Comats bordem honk!
|
||||
unit_name = "working honker"
|
||||
export_types = list(/obj/mecha/combat/honker)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/reticence
|
||||
cost = 12000 //Still a "Combat class" mech - Has cloking and lethal weaponds.
|
||||
unit_name = "working reticence"
|
||||
export_types = list(/obj/mecha/combat/reticence)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/seraph
|
||||
cost = 25500 //Still a Combat class mech - CC tech as well! 150% "normal" boundy price.
|
||||
unit_name = "working seraph"
|
||||
export_types = list(/obj/mecha/combat/marauder/seraph)
|
||||
include_subtypes = FALSE
|
||||
|
||||
/datum/export/large/mauler
|
||||
cost = 12000 //Still a Combat class mech - CC lethal weaponds.
|
||||
unit_name = "working legally modified marauder"
|
||||
export_types = list(/obj/mecha/combat/marauder/mauler)
|
||||
include_subtypes = FALSE
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
+70
-19
@@ -81,6 +81,21 @@
|
||||
crate_name = "emergency crate"
|
||||
crate_type = /obj/structure/closet/crate/internals
|
||||
|
||||
/datum/supply_pack/emergency/radiatione_emergency
|
||||
name = "Emergenc Radiation Protection Crate"
|
||||
desc = "Survive the Nuclear Apocalypse and Supermatter Engine alike with two sets of Radiation suits. Each set contains a helmet, suit, and Geiger counter. We'll even throw in a few pill bottles that are able to handles radiation and the affects of the poisoning."
|
||||
cost = 2500
|
||||
contains = list(/obj/item/clothing/head/radiation,
|
||||
/obj/item/clothing/head/radiation,
|
||||
/obj/item/clothing/suit/radiation,
|
||||
/obj/item/clothing/suit/radiation,
|
||||
/obj/item/geiger_counter,
|
||||
/obj/item/geiger_counter,
|
||||
/obj/item/storage/pill_bottle/mutarad,
|
||||
/obj/item/storage/firstaid/radbgone)
|
||||
crate_name = "radiation protection crate"
|
||||
crate_type = /obj/structure/closet/crate/radiation
|
||||
|
||||
/datum/supply_pack/emergency/rcds
|
||||
name = "Emergency RCDs"
|
||||
desc = "Bombs going off on station? SME blown and now you need to fix the hole it left behind? Well this crate has a pare of Rcds to be able to easily fix up any problem you may have!"
|
||||
@@ -418,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,
|
||||
@@ -858,8 +872,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,
|
||||
@@ -867,16 +880,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 /////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -946,6 +956,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."
|
||||
@@ -1357,6 +1376,19 @@
|
||||
/obj/item/storage/firstaid/o2)
|
||||
crate_name = "oxygen deprivation kit crate"
|
||||
|
||||
/datum/supply_pack/medical/advrad
|
||||
name = "Radiation Treatment Crate Deluxe"
|
||||
desc = "A crate for when radiation is out of hand... Contains two rad-b-gone kits, one bottle of anti radiation deluxe pill bottle, as well as a radiation treatment deluxe pill bottle!"
|
||||
cost = 3500
|
||||
contains = list(/obj/item/storage/pill_bottle/antirad_plus,
|
||||
/obj/item/storage/pill_bottle/mutarad,
|
||||
/obj/item/storage/firstaid/radbgone,
|
||||
/obj/item/storage/firstaid/radbgone,
|
||||
/obj/item/geiger_counter,
|
||||
/obj/item/geiger_counter)
|
||||
crate_name = "radiation protection crate"
|
||||
crate_type = /obj/structure/closet/crate/radiation
|
||||
|
||||
/datum/supply_pack/medical/surgery
|
||||
name = "Surgical Supplies Crate"
|
||||
desc = "Do you want to perform surgery, but don't have one of those fancy shmancy degrees? Just get started with this crate containing a medical duffelbag, Sterilizine spray and collapsible roller bed."
|
||||
@@ -1515,7 +1547,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!"
|
||||
@@ -1540,6 +1571,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!"
|
||||
@@ -1548,6 +1587,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."
|
||||
@@ -1671,11 +1718,15 @@
|
||||
/obj/item/t_scanner/adv_mining_scanner/lesser,
|
||||
/obj/item/radio/headset/headset_cargo/mining,
|
||||
/obj/item/storage/bag/ore,
|
||||
/obj/item/clothing/suit/hooded/explorer,
|
||||
/obj/item/clothing/suit/hooded/explorer/standard,
|
||||
/obj/item/clothing/mask/gas/explorer)
|
||||
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!"
|
||||
@@ -2645,16 +2696,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,
|
||||
|
||||
@@ -21,6 +21,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/last_ip
|
||||
var/last_id
|
||||
|
||||
//Cooldowns for saving/loading. These are four are all separate due to loading code calling these one after another
|
||||
var/saveprefcooldown
|
||||
var/loadprefcooldown
|
||||
var/savecharcooldown
|
||||
var/loadcharcooldown
|
||||
|
||||
//game-preferences
|
||||
var/lastchangelog = "" //Saved changlog filesize to detect if there was a change
|
||||
var/ooccolor = null
|
||||
@@ -75,13 +81,82 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/eye_color = "000" //Eye color
|
||||
var/datum/species/pref_species = new /datum/species/human() //Mutant race
|
||||
var/list/features = list("mcolor" = "FFF",
|
||||
"tail_lizard" = "Smooth", "tail_human" = "Cat",
|
||||
"snout" = "Round", "horns" = "None", "ears" = "Cat",
|
||||
"wings" = "None", "frills" = "None", "spines" = "None",
|
||||
"body_markings" = "None", "legs" = "Normal Legs", "moth_wings" = "Plain")
|
||||
"tail_lizard" = "Smooth",
|
||||
"tail_human" = "None",
|
||||
"snout" = "Round",
|
||||
"horns" = "None",
|
||||
"ears" = "None",
|
||||
"wings" = "None",
|
||||
"frills" = "None",
|
||||
"spines" = "None",
|
||||
"body_markings" = "None",
|
||||
"legs" = "Normal Legs",
|
||||
"moth_wings" = "Plain",
|
||||
"mcolor2" = "FFF",
|
||||
"mcolor3" = "FFF",
|
||||
"mam_body_markings" = "Plain",
|
||||
"mam_ears" = "None",
|
||||
"mam_snouts" = "None",
|
||||
"mam_tail" = "None",
|
||||
"mam_tail_animated" = "None",
|
||||
"xenodorsal" = "Standard",
|
||||
"xenohead" = "Standard",
|
||||
"xenotail" = "Xenomorph Tail",
|
||||
"taur" = "None",
|
||||
"exhibitionist" = FALSE,
|
||||
"genitals_use_skintone" = FALSE,
|
||||
"has_cock" = FALSE,
|
||||
"cock_shape" = "Human",
|
||||
"cock_length" = 6,
|
||||
"cock_girth_ratio" = COCK_GIRTH_RATIO_DEF,
|
||||
"cock_color" = "fff",
|
||||
"has_sheath" = FALSE,
|
||||
"sheath_color" = "fff",
|
||||
"has_balls" = FALSE,
|
||||
"balls_internal" = FALSE,
|
||||
"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,
|
||||
"balls_efficiency" = CUM_EFFICIENCY,
|
||||
"balls_fluid" = "semen",
|
||||
"has_ovi" = FALSE,
|
||||
"ovi_shape" = "knotted",
|
||||
"ovi_length" = 6,
|
||||
"ovi_color" = "fff",
|
||||
"has_eggsack" = FALSE,
|
||||
"eggsack_internal" = TRUE,
|
||||
"eggsack_color" = "fff",
|
||||
"eggsack_size" = BALLS_SACK_SIZE_DEF,
|
||||
"eggsack_egg_color" = "fff",
|
||||
"eggsack_egg_size" = EGG_GIRTH_DEF,
|
||||
"has_breasts" = FALSE,
|
||||
"breasts_color" = "fff",
|
||||
"breasts_size" = "C",
|
||||
"breasts_shape" = "Pair",
|
||||
"breasts_fluid" = "milk",
|
||||
"has_vag" = FALSE,
|
||||
"vag_shape" = "Human",
|
||||
"vag_color" = "fff",
|
||||
"vag_clits" = 1,
|
||||
"vag_clit_diam" = 0.25,
|
||||
"has_womb" = FALSE,
|
||||
"womb_cum_rate" = CUM_RATE,
|
||||
"womb_cum_mult" = CUM_RATE_MULT,
|
||||
"womb_efficiency" = CUM_EFFICIENCY,
|
||||
"womb_fluid" = "femcum",
|
||||
"ipc_screen" = "Sunburst",
|
||||
"ipc_antenna" = "None",
|
||||
"flavor_text" = ""
|
||||
)
|
||||
|
||||
var/list/custom_names = list()
|
||||
var/preferred_ai_core_display = "Blue"
|
||||
var/prefered_security_department = SEC_DEPT_RANDOM
|
||||
var/custom_species = null
|
||||
|
||||
//Quirk list
|
||||
var/list/positive_quirks = list()
|
||||
@@ -127,6 +202,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
var/action_buttons_screen_locs = list()
|
||||
|
||||
//backgrounds
|
||||
var/mutable_appearance/character_background
|
||||
var/icon/bgstate = "steel"
|
||||
var/list/bgstate_options = list("000", "midgrey", "FFF", "white", "steel", "techmaint", "dark", "plating", "reinforced")
|
||||
|
||||
/datum/preferences/New(client/C)
|
||||
parent = C
|
||||
|
||||
@@ -224,10 +304,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
|
||||
@@ -264,8 +345,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<h2>Body</h2>"
|
||||
dat += "<b>Gender:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=gender'>[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]</a><BR>"
|
||||
dat += "<b>Species:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=species;task=input'>[pref_species.id]</a><BR>"
|
||||
dat += "<b>Custom Species Name:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=custom_species;task=input'>[custom_species ? custom_species : "None"]</a><BR>"
|
||||
dat += "<a style='display:block;width:100px' href='?_src_=prefs;preference=all;task=random'>Random Body</A><BR>"
|
||||
dat += "<b>Always Random Body:</b><a href='?_src_=prefs;preference=all'>[be_random_body ? "Yes" : "No"]</A><BR>"
|
||||
dat += "<br><b>Cycle background:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=cycle_bg;task=input'>[bgstate]</a><BR>"
|
||||
|
||||
var/use_skintones = pref_species.use_skintones
|
||||
if(use_skintones)
|
||||
@@ -621,6 +704,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
else
|
||||
dat += "<b>Testicles Color:</b>"
|
||||
dat += "<span style='border: 1px solid #161616; background-color: #[features["balls_color"]];'> </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 += "<a style='display:block;width:50px' href='?_src_=prefs;preference=has_vag'>[features["has_vag"] == TRUE ? "Yes" : "No"]</a>"
|
||||
@@ -810,10 +894,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<tr><td colspan=4><hr></td></tr>"
|
||||
dat += "<tr><td colspan=4><b><center>[gear_tab]</center></b></td></tr>"
|
||||
dat += "<tr><td colspan=4><hr></td></tr>"
|
||||
dat += "<tr style='vertical-align:top;'><td width=15%><b>Name</b></td>"
|
||||
dat += "<td width=5% style='vertical-align:top'><b>Cost</b></td>"
|
||||
dat += "<td><font size=2><b>Restrictions</b></font></td>"
|
||||
dat += "<td><font size=2><b>Description</b></font></td></tr>"
|
||||
dat += "<tr width=10% style='vertical-align:top;'><td width=15%><b>Name</b></td>"
|
||||
dat += "<td style='vertical-align:top'><b>Cost</b></td>"
|
||||
dat += "<td width=10%><font size=2><b>Restrictions</b></font></td>"
|
||||
dat += "<td width=80%><font size=2><b>Description</b></font></td></tr>"
|
||||
for(var/j in GLOB.loadout_items[gear_tab])
|
||||
var/datum/gear/gear = GLOB.loadout_items[gear_tab][j]
|
||||
var/donoritem
|
||||
@@ -834,9 +918,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<td width = 5% style='vertical-align:top'>[gear.cost]</td><td>"
|
||||
if(islist(gear.restricted_roles))
|
||||
if(gear.restricted_roles.len)
|
||||
dat += "<font size=2>"
|
||||
dat += gear.restricted_roles.Join(";")
|
||||
dat += "</font>"
|
||||
if(gear.restricted_desc)
|
||||
dat += "<font size=2>"
|
||||
dat += gear.restricted_desc
|
||||
dat += "</font>"
|
||||
else
|
||||
dat += "<font size=2>"
|
||||
dat += gear.restricted_roles.Join(";")
|
||||
dat += "</font>"
|
||||
dat += "</td><td><font size=2><i>[gear.description]</i></font></td></tr>"
|
||||
dat += "</table>"
|
||||
|
||||
@@ -1373,7 +1462,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
|
||||
@@ -1385,48 +1474,35 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
if("hair_style")
|
||||
var/new_hair_style
|
||||
if(gender == MALE)
|
||||
new_hair_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in GLOB.hair_styles_male_list
|
||||
else
|
||||
new_hair_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in GLOB.hair_styles_female_list
|
||||
new_hair_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in GLOB.hair_styles_list
|
||||
if(new_hair_style)
|
||||
hair_style = new_hair_style
|
||||
|
||||
if("next_hair_style")
|
||||
if (gender == MALE)
|
||||
hair_style = next_list_item(hair_style, GLOB.hair_styles_male_list)
|
||||
else
|
||||
hair_style = next_list_item(hair_style, GLOB.hair_styles_female_list)
|
||||
hair_style = next_list_item(hair_style, GLOB.hair_styles_list)
|
||||
|
||||
if("previous_hair_style")
|
||||
if (gender == MALE)
|
||||
hair_style = previous_list_item(hair_style, GLOB.hair_styles_male_list)
|
||||
else
|
||||
hair_style = previous_list_item(hair_style, GLOB.hair_styles_female_list)
|
||||
hair_style = previous_list_item(hair_style, GLOB.hair_styles_list)
|
||||
|
||||
if("facial")
|
||||
var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference","#"+facial_hair_color) as color|null
|
||||
if(new_facial)
|
||||
facial_hair_color = sanitize_hexcolor(new_facial)
|
||||
if("facial_hair_style")
|
||||
var/new_facial_hair_style
|
||||
if(gender == MALE)
|
||||
new_facial_hair_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in GLOB.facial_hair_styles_male_list
|
||||
else
|
||||
new_facial_hair_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in GLOB.facial_hair_styles_female_list
|
||||
if(new_facial_hair_style)
|
||||
facial_hair_style = new_facial_hair_style
|
||||
|
||||
if("facial_hair_style")
|
||||
var/new_facial_hair_style
|
||||
new_facial_hair_style = input(user, "Choose your character's facial-hair style:", "Character Preference") as null|anything in GLOB.facial_hair_styles_list
|
||||
if(new_facial_hair_style)
|
||||
facial_hair_style = new_facial_hair_style
|
||||
|
||||
if("next_facehair_style")
|
||||
if (gender == MALE)
|
||||
facial_hair_style = next_list_item(facial_hair_style, GLOB.facial_hair_styles_male_list)
|
||||
else
|
||||
facial_hair_style = next_list_item(facial_hair_style, GLOB.facial_hair_styles_female_list)
|
||||
if("previous_facehair_style")
|
||||
if (gender == MALE)
|
||||
facial_hair_style = previous_list_item(facial_hair_style, GLOB.facial_hair_styles_male_list)
|
||||
else
|
||||
facial_hair_style = previous_list_item(facial_hair_style, GLOB.facial_hair_styles_female_list)
|
||||
facial_hair_style = next_list_item(facial_hair_style, GLOB.facial_hair_styles_list)
|
||||
|
||||
if("previous_facehair_style")
|
||||
facial_hair_style = previous_list_item(facial_hair_style, GLOB.facial_hair_styles_list)
|
||||
|
||||
if("cycle_bg")
|
||||
bgstate = next_list_item(bgstate, bgstate_options)
|
||||
|
||||
if("underwear")
|
||||
var/new_underwear
|
||||
@@ -1463,18 +1539,16 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/newtype = GLOB.species_list[result]
|
||||
pref_species = new newtype()
|
||||
//let's ensure that no weird shit happens on species swapping.
|
||||
custom_species = null
|
||||
if(!("body_markings" in pref_species.default_features))
|
||||
features["body_markings"] = "None"
|
||||
if(!("mam_body_markings" in pref_species.default_features))
|
||||
features["mam_body_markings"] = "None"
|
||||
if("mam_body_markings" in pref_species.default_features && features["mam_body_markings"] == "None")
|
||||
features["mam_body_markings"] = "Plain"
|
||||
if("mam_body_markings" in pref_species.default_features)
|
||||
if(features["mam_body_markings"] == "None")
|
||||
features["mam_body_markings"] = "Plain"
|
||||
if("tail_lizard" in pref_species.default_features)
|
||||
features["tail_lizard"] = "Smooth"
|
||||
if("mam_tail" in pref_species.default_features)
|
||||
features["mam_tail"] = "None"
|
||||
if("mam_ears" in pref_species.default_features)
|
||||
features["mam_ears"] = "None"
|
||||
if(pref_species.id == "felinid")
|
||||
features["mam_tail"] = "Cat"
|
||||
features["mam_ears"] = "Cat"
|
||||
@@ -1488,6 +1562,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(features["mcolor3"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3]))
|
||||
features["mcolor3"] = pref_species.default_color
|
||||
|
||||
if("custom_species")
|
||||
var/new_species = reject_bad_name(input(user, "Choose your species subtype, if unique. This will show up on examinations and health scans. Do not abuse this:", "Character Preference", custom_species) as null|text)
|
||||
if(new_species)
|
||||
custom_species = new_species
|
||||
else
|
||||
custom_species = null
|
||||
|
||||
if("mutant_color")
|
||||
var/new_mutantcolor = input(user, "Choose your character's alien/mutant color:", "Character Preference","#"+features["mcolor"]) as color|null
|
||||
if(new_mutantcolor)
|
||||
@@ -1584,16 +1665,33 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
features["tail_lizard"] = "None"
|
||||
|
||||
if("snout")
|
||||
var/list/snowflake_snouts_list = list()
|
||||
for(var/path in GLOB.snouts_list)
|
||||
var/datum/sprite_accessory/mam_snouts/instance = GLOB.snouts_list[path]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(user.client.ckey)))
|
||||
snowflake_snouts_list[S.name] = path
|
||||
var/new_snout
|
||||
new_snout = input(user, "Choose your character's snout:", "Character Preference") as null|anything in GLOB.snouts_list
|
||||
new_snout = input(user, "Choose your character's snout:", "Character Preference") as null|anything in snowflake_snouts_list
|
||||
if(new_snout)
|
||||
features["snout"] = new_snout
|
||||
features["mam_snouts"] = "None"
|
||||
|
||||
|
||||
if("mam_snouts")
|
||||
var/list/snowflake_mam_snouts_list = list()
|
||||
for(var/path in GLOB.mam_snouts_list)
|
||||
var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[path]
|
||||
if(istype(instance, /datum/sprite_accessory))
|
||||
var/datum/sprite_accessory/S = instance
|
||||
if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(user.client.ckey)))
|
||||
snowflake_mam_snouts_list[S.name] = path
|
||||
var/new_mam_snouts
|
||||
new_mam_snouts = input(user, "Choose your character's snout:", "Character Preference") as null|anything in GLOB.mam_snouts_list
|
||||
new_mam_snouts = input(user, "Choose your character's snout:", "Character Preference") as null|anything in snowflake_mam_snouts_list
|
||||
if(new_mam_snouts)
|
||||
features["mam_snouts"] = new_mam_snouts
|
||||
features["snout"] = "None"
|
||||
|
||||
if("horns")
|
||||
var/new_horns
|
||||
@@ -1601,12 +1699,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(new_horns)
|
||||
features["horns"] = new_horns
|
||||
|
||||
if("ears")
|
||||
var/new_ears
|
||||
new_ears = input(user, "Choose your character's ears:", "Character Preference") as null|anything in GLOB.ears_list
|
||||
if(new_ears)
|
||||
features["ears"] = new_ears
|
||||
|
||||
if("wings")
|
||||
var/new_wings
|
||||
new_wings = input(user, "Choose your character's wings:", "Character Preference") as null|anything in GLOB.r_wings_list
|
||||
@@ -1748,7 +1840,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
|
||||
@@ -1770,7 +1862,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
|
||||
@@ -1786,7 +1884,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
|
||||
@@ -1809,7 +1907,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
|
||||
@@ -1826,7 +1924,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
|
||||
@@ -1843,8 +1941,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
|
||||
|
||||
@@ -2115,6 +2218,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
character.real_name = nameless ? "[real_name] #[rand(10000, 99999)]" : real_name
|
||||
character.name = character.real_name
|
||||
character.nameless = nameless
|
||||
character.custom_species = custom_species
|
||||
|
||||
character.gender = gender
|
||||
character.age = age
|
||||
@@ -2149,34 +2253,29 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
character.dna.features = features.Copy()
|
||||
character.dna.real_name = character.real_name
|
||||
character.dna.nameless = character.nameless
|
||||
character.dna.custom_species = character.custom_species
|
||||
|
||||
if("tail_lizard" in pref_species.default_features)
|
||||
character.dna.species.mutant_bodyparts |= "tail_lizard"
|
||||
else if("mam_tail" in pref_species.default_features)
|
||||
if("mam_tail" in pref_species.default_features)
|
||||
character.dna.species.mutant_bodyparts |= "mam_tail"
|
||||
else if("xenotail" in pref_species.default_features)
|
||||
if("xenotail" in pref_species.default_features)
|
||||
character.dna.species.mutant_bodyparts |= "xenotail"
|
||||
|
||||
if("legs" in pref_species.default_features)
|
||||
if(character.dna.features["legs"] == "Digitigrade Legs")
|
||||
pref_species.species_traits += DIGITIGRADE
|
||||
character.Digitigrade_Leg_Swap(FALSE)
|
||||
|
||||
if(character.dna.features["legs"] == "Normal Legs" && DIGITIGRADE in pref_species.species_traits)
|
||||
pref_species.species_traits -= DIGITIGRADE
|
||||
character.Digitigrade_Leg_Swap(TRUE)
|
||||
|
||||
else if((!"legs" in pref_species.default_features) && DIGITIGRADE in pref_species.species_traits)
|
||||
if(("legs" in character.dna.species.mutant_bodyparts) && character.dna.features["legs"] == "Digitigrade Legs")
|
||||
pref_species.species_traits |= DIGITIGRADE
|
||||
else
|
||||
pref_species.species_traits -= DIGITIGRADE
|
||||
character.Digitigrade_Leg_Swap(TRUE)
|
||||
|
||||
if(DIGITIGRADE in pref_species.species_traits)
|
||||
character.Digitigrade_Leg_Swap(FALSE)
|
||||
else
|
||||
character.Digitigrade_Leg_Swap(TRUE)
|
||||
|
||||
if(icon_updates)
|
||||
character.update_body()
|
||||
character.update_hair()
|
||||
character.update_body_parts()
|
||||
//let's be sure the character updates
|
||||
character.update_body()
|
||||
character.update_hair()
|
||||
character.update_body_parts()
|
||||
|
||||
/datum/preferences/proc/get_default_name(name_id)
|
||||
switch(name_id)
|
||||
|
||||
@@ -58,6 +58,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
/datum/preferences/proc/load_preferences()
|
||||
if(!path)
|
||||
return 0
|
||||
if(world.time < loadprefcooldown)
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to load your preferences a little too fast. Wait half a second, then try again.</span>")
|
||||
return 0
|
||||
loadprefcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
if(!fexists(path))
|
||||
return 0
|
||||
|
||||
@@ -152,6 +157,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
/datum/preferences/proc/save_preferences()
|
||||
if(!path)
|
||||
return 0
|
||||
if(world.time < saveprefcooldown)
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to save your preferences a little too fast. Wait half a second, then try again.</span>")
|
||||
return 0
|
||||
saveprefcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
var/savefile/S = new /savefile(path)
|
||||
if(!S)
|
||||
return 0
|
||||
@@ -204,6 +214,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
/datum/preferences/proc/load_character(slot)
|
||||
if(!path)
|
||||
return 0
|
||||
if(world.time < loadcharcooldown) //This is before the check to see if the filepath exists to ensure that BYOND can't get hung up on read attempts when the hard drive is a little slow
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to load your character a little too fast. Wait half a second, then try again.</span>")
|
||||
return "SLOW THE FUCK DOWN" //the reason this isn't null is to make sure that people don't have their character slots overridden by random chars if they accidentally double-click a slot
|
||||
loadcharcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
if(!fexists(path))
|
||||
return 0
|
||||
var/savefile/S = new /savefile(path)
|
||||
@@ -236,6 +251,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
//Character
|
||||
S["real_name"] >> real_name
|
||||
S["nameless"] >> nameless
|
||||
S["custom_species"] >> custom_species
|
||||
S["name_is_always_random"] >> be_random_name
|
||||
S["body_is_always_random"] >> be_random_body
|
||||
S["gender"] >> gender
|
||||
@@ -260,18 +276,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["feature_lizard_body_markings"] >> features["body_markings"]
|
||||
S["feature_lizard_legs"] >> features["legs"]
|
||||
S["feature_moth_wings"] >> features["moth_wings"]
|
||||
if(!CONFIG_GET(flag/join_with_mutant_humans))
|
||||
features["tail_human"] = "none"
|
||||
features["ears"] = "none"
|
||||
else
|
||||
S["feature_human_tail"] >> features["tail_human"]
|
||||
S["feature_human_ears"] >> features["ears"]
|
||||
S["feature_human_tail"] >> features["tail_human"]
|
||||
S["feature_human_ears"] >> features["ears"]
|
||||
|
||||
//Custom names
|
||||
for(var/custom_name_id in GLOB.preferences_custom_names)
|
||||
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
|
||||
@@ -318,6 +331,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
|
||||
@@ -354,7 +368,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
gender = sanitize_gender(gender, TRUE, TRUE)
|
||||
if(!real_name)
|
||||
real_name = random_unique_name(gender)
|
||||
|
||||
custom_species = reject_bad_name(custom_species)
|
||||
for(var/custom_name_id in GLOB.preferences_custom_names)
|
||||
var/namedata = GLOB.preferences_custom_names[custom_name_id]
|
||||
custom_names[custom_name_id] = reject_bad_name(custom_names[custom_name_id],namedata["allow_numbers"])
|
||||
@@ -388,15 +402,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
uplink_spawn_loc = sanitize_inlist(uplink_spawn_loc, GLOB.uplink_spawn_loc_list, initial(uplink_spawn_loc))
|
||||
features["mcolor"] = sanitize_hexcolor(features["mcolor"], 3, 0)
|
||||
features["tail_lizard"] = sanitize_inlist(features["tail_lizard"], GLOB.tails_list_lizard)
|
||||
features["tail_human"] = sanitize_inlist(features["tail_human"], GLOB.tails_list_human, "None")
|
||||
features["tail_human"] = sanitize_inlist(features["tail_human"], GLOB.tails_list_human)
|
||||
features["snout"] = sanitize_inlist(features["snout"], GLOB.snouts_list)
|
||||
features["horns"] = sanitize_inlist(features["horns"], GLOB.horns_list)
|
||||
features["ears"] = sanitize_inlist(features["ears"], GLOB.ears_list, "None")
|
||||
features["ears"] = sanitize_inlist(features["ears"], GLOB.ears_list)
|
||||
features["frills"] = sanitize_inlist(features["frills"], GLOB.frills_list)
|
||||
features["spines"] = sanitize_inlist(features["spines"], GLOB.spines_list)
|
||||
features["body_markings"] = sanitize_inlist(features["body_markings"], GLOB.body_markings_list)
|
||||
features["feature_lizard_legs"] = sanitize_inlist(features["legs"], GLOB.legs_list, "Normal Legs")
|
||||
features["moth_wings"] = sanitize_inlist(features["moth_wings"], GLOB.moth_wings_list, "Plain")
|
||||
features["feature_lizard_legs"] = sanitize_inlist(features["legs"], GLOB.legs_list)
|
||||
features["moth_wings"] = sanitize_inlist(features["moth_wings"], GLOB.moth_wings_list)
|
||||
|
||||
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
|
||||
job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high))
|
||||
@@ -421,6 +435,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
/datum/preferences/proc/save_character()
|
||||
if(!path)
|
||||
return 0
|
||||
if(world.time < savecharcooldown)
|
||||
if(istype(parent))
|
||||
to_chat(parent, "<span class='warning'>You're attempting to save your character a little too fast. Wait half a second, then try again.</span>")
|
||||
return 0
|
||||
savecharcooldown = world.time + PREF_SAVELOAD_COOLDOWN
|
||||
var/savefile/S = new /savefile(path)
|
||||
if(!S)
|
||||
return 0
|
||||
@@ -431,6 +450,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
//Character
|
||||
WRITE_FILE(S["real_name"] , real_name)
|
||||
WRITE_FILE(S["nameless"] , nameless)
|
||||
WRITE_FILE(S["custom_species"] , custom_species)
|
||||
WRITE_FILE(S["name_is_always_random"] , be_random_name)
|
||||
WRITE_FILE(S["body_is_always_random"] , be_random_body)
|
||||
WRITE_FILE(S["gender"] , gender)
|
||||
@@ -464,6 +484,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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
var/blockTracking = 0 //For AI tracking
|
||||
var/can_toggle = null
|
||||
dynamic_hair_suffix = "+generic"
|
||||
var/muzzle_var = NORMAL_STYLE
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION //not all hats have muzzles
|
||||
|
||||
/obj/item/clothing/head/Initialize()
|
||||
. = ..()
|
||||
@@ -15,6 +17,30 @@
|
||||
var/mob/living/carbon/human/H = loc
|
||||
H.update_hair()
|
||||
|
||||
/obj/item/clothing/head/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_head()
|
||||
|
||||
/obj/item/clothing/head/worn_overlays(isinhands = FALSE)
|
||||
. = list()
|
||||
if(!isinhands)
|
||||
|
||||
@@ -79,8 +79,9 @@
|
||||
name = "atmospheric technician's firefighting helmet"
|
||||
desc = "A firefighter's helmet, able to keep the user cool in any situation."
|
||||
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
heat_protection = HEAD
|
||||
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||
cold_protection = HEAD
|
||||
min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
visor_flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
dog_fashion = null
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/head/helmet/attack_self(mob/user)
|
||||
if(can_toggle && !user.incapacitated())
|
||||
@@ -210,10 +211,11 @@
|
||||
icon_state = "knight_green"
|
||||
item_state = "knight_green"
|
||||
armor = list("melee" = 41, "bullet" = 15, "laser" = 5,"energy" = 5, "bomb" = 5, "bio" = 2, "rad" = 0, "fire" = 0, "acid" = 50)
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
strip_delay = 80
|
||||
dog_fashion = null
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
|
||||
/obj/item/clothing/head/helmet/knight/Initialize(mapload)
|
||||
@@ -242,6 +244,7 @@
|
||||
icon_state = "skull"
|
||||
item_state = "skull"
|
||||
strip_delay = 100
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
//LightToggle
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
icon_state = "captain"
|
||||
item_state = "that"
|
||||
flags_inv = 0
|
||||
armor = list("melee" = 25, "bullet" = 15, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
strip_delay = 60
|
||||
dog_fashion = /datum/dog_fashion/head/captain
|
||||
|
||||
@@ -38,15 +38,28 @@
|
||||
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/clothing/head/caphat/beret
|
||||
name = "captain's beret"
|
||||
desc = "A beret fit for a leader."
|
||||
icon_state = "capberet"
|
||||
|
||||
dog_fashion = null
|
||||
|
||||
//Head of Personnel
|
||||
/obj/item/clothing/head/hopcap
|
||||
name = "head of personnel's cap"
|
||||
icon_state = "hopcap"
|
||||
desc = "The symbol of true bureaucratic micromanagement."
|
||||
armor = list("melee" = 25, "bullet" = 15, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
armor = list("melee" = 30, "bullet" = 25, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
dog_fashion = /datum/dog_fashion/head/hop
|
||||
|
||||
/obj/item/clothing/head/hopcap/beret
|
||||
name = "head of personnel's beret"
|
||||
desc = "The symbol of true bureaucratic micromanagement, although in a fancy form."
|
||||
icon_state = "hopberet"
|
||||
|
||||
dog_fashion = null
|
||||
|
||||
//Chaplain
|
||||
/obj/item/clothing/head/nun_hood
|
||||
name = "nun hood"
|
||||
@@ -164,3 +177,27 @@
|
||||
name = "treasure hunter's fedora"
|
||||
desc = "You got red text today kid, but it doesn't mean you have to like it."
|
||||
icon_state = "curator"
|
||||
|
||||
//Chief Medical Officer
|
||||
/obj/item/clothing/head/beret/cmo
|
||||
name = "chief medical officer's beret"
|
||||
desc = "A fancy beret with a green cross, signifying your status in the station's medbay."
|
||||
icon_state = "cmoberet"
|
||||
|
||||
//Research Director
|
||||
/obj/item/clothing/head/beret/rd
|
||||
name = "research director's beret"
|
||||
desc = "A beret worn only by highly intelligent people."
|
||||
icon_state = "rdberet"
|
||||
|
||||
//Chief Engineer
|
||||
/obj/item/clothing/head/beret/ce
|
||||
name = "chief engineer's beret"
|
||||
desc = "A beret that will surely make you look way cooler than a hard hat, although lack of protection is the price."
|
||||
icon_state = "ceberet"
|
||||
|
||||
//Quartermaster
|
||||
/obj/item/clothing/head/beret/qm
|
||||
name = "quartermaster's beret"
|
||||
desc = "This headwear shows off your Cargonian leadership"
|
||||
icon_state = "qmberet"
|
||||
|
||||
@@ -65,7 +65,8 @@
|
||||
icon_state = "syndicate-helm-black-red"
|
||||
item_state = "syndicate-helm-black-red"
|
||||
desc = "A plastic replica of a Syndicate agent's space helmet. You'll look just like a real murderous Syndicate agent in this! This is a toy, it is not made for use in space!"
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/head/cueball
|
||||
name = "cueball helmet"
|
||||
@@ -73,7 +74,7 @@
|
||||
icon_state = "cueball"
|
||||
item_state="cueball"
|
||||
flags_cover = HEADCOVERSEYES|HEADCOVERSMOUTH
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/snowman
|
||||
name = "Snowman Head"
|
||||
@@ -81,14 +82,14 @@
|
||||
icon_state = "snowman_h"
|
||||
item_state = "snowman_h"
|
||||
flags_cover = HEADCOVERSEYES
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/justice
|
||||
name = "justice hat"
|
||||
desc = "Fight for what's righteous!"
|
||||
icon_state = "justicered"
|
||||
item_state = "justicered"
|
||||
flags_inv = HIDEHAIR|HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR
|
||||
flags_inv = HIDEHAIR|HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT
|
||||
flags_cover = HEADCOVERSEYES
|
||||
|
||||
/obj/item/clothing/head/justice/blue
|
||||
@@ -159,14 +160,14 @@
|
||||
desc = "Bkaw!"
|
||||
icon_state = "chickenhead"
|
||||
item_state = "chickensuit"
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/griffin
|
||||
name = "griffon head"
|
||||
desc = "Why not 'eagle head'? Who knows."
|
||||
icon_state = "griffinhat"
|
||||
item_state = "griffinhat"
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/bearpelt
|
||||
name = "bear pelt hat"
|
||||
@@ -179,7 +180,7 @@
|
||||
icon_state = "xenos"
|
||||
item_state = "xenos_helm"
|
||||
desc = "A helmet made out of chitinous alien hide."
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/fedora
|
||||
name = "fedora"
|
||||
@@ -267,13 +268,13 @@
|
||||
name = "paper sack hat"
|
||||
desc = "A paper sack with crude holes cut out for eyes. Useful for hiding one's identity or ugliness."
|
||||
icon_state = "papersack"
|
||||
flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
|
||||
flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/papersack/smiley
|
||||
name = "paper sack hat"
|
||||
desc = "A paper sack with crude holes cut out for eyes and a sketchy smile drawn on the front. Not creepy at all."
|
||||
icon_state = "papersack_smile"
|
||||
flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS
|
||||
flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/crown
|
||||
name = "crown"
|
||||
@@ -297,7 +298,7 @@
|
||||
name = "foam lobster head"
|
||||
desc = "When everything's going to crab, protecting your head is the best choice."
|
||||
icon_state = "lobster_hat"
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/drfreezehat
|
||||
name = "doctor freeze's wig"
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
visor_flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
|
||||
visor_flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
resistance_flags = FIRE_PROOF
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/head/welding/attack_self(mob/user)
|
||||
weldingvisortoggle(user)
|
||||
@@ -113,7 +114,7 @@
|
||||
icon_state = "hardhat0_pumpkin"
|
||||
item_state = "hardhat0_pumpkin"
|
||||
item_color = "pumpkin"
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
brightness_on = 2 //luminosity when on
|
||||
flags_cover = HEADCOVERSEYES
|
||||
@@ -163,7 +164,7 @@
|
||||
icon_state = "cardborg_h"
|
||||
item_state = "cardborg_h"
|
||||
flags_cover = HEADCOVERSEYES
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/cardborg
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
equip_delay_other = 40
|
||||
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/worn_overlays(isinhands = FALSE)
|
||||
@@ -18,6 +20,31 @@
|
||||
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))
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
visor_flags_inv = HIDEFACE|HIDEFACIALHAIR
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
actions_types = list(/datum/action/item_action/adjust)
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/mask/balaclava/attack_self(mob/user)
|
||||
adjustmask(user)
|
||||
@@ -18,6 +19,7 @@
|
||||
item_state = "luchag"
|
||||
flags_inv = HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/mask/luchador/speechModification(message)
|
||||
if(copytext(message, 1, 2) != "*")
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
flags_cover = MASKCOVERSMOUTH
|
||||
visor_flags_cover = MASKCOVERSMOUTH
|
||||
resistance_flags = NONE
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/mask/breath/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message("<span class='suicide'>[user] is wrapping \the [src]'s tube around [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
|
||||
@@ -3,13 +3,21 @@
|
||||
desc = "A face-covering mask that can be connected to an air supply. While good for concealing your identity, it isn't good for blocking gas flow." //More accurate
|
||||
icon_state = "gas_alt"
|
||||
clothing_flags = BLOCK_GAS_SMOKE_EFFECT | MASKINTERNALS
|
||||
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR
|
||||
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
item_state = "gas_alt"
|
||||
gas_transfer_coefficient = 0.01
|
||||
permeability_coefficient = 0.01
|
||||
flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH
|
||||
resistance_flags = NONE
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/mask/gas/glass
|
||||
name = "glass gas mask"
|
||||
desc = "A face-covering mask that can be connected to an air supply. This one doesn't obscure your face however." //More accurate
|
||||
icon_state = "gas_clear"
|
||||
flags_inv = HIDEEYES
|
||||
|
||||
|
||||
// **** Welding gas mask ****
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
gas_transfer_coefficient = 0.9
|
||||
equip_delay_other = 20
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/mask/muzzle/attack_paw(mob/user)
|
||||
if(iscarbon(user))
|
||||
@@ -30,6 +31,7 @@
|
||||
permeability_coefficient = 0.01
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 25, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
actions_types = list(/datum/action/item_action/adjust)
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/mask/surgical/attack_self(mob/user)
|
||||
adjustmask(user)
|
||||
@@ -39,6 +41,7 @@
|
||||
desc = "Warning: moustache is fake."
|
||||
icon_state = "fake-moustache"
|
||||
flags_inv = HIDEFACE
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/mask/fakemoustache/italian
|
||||
name = "italian moustache"
|
||||
@@ -66,6 +69,7 @@
|
||||
name = "joy mask"
|
||||
desc = "Express your happiness or hide your sorrows with this laughing face with crying tears of joy cutout."
|
||||
icon_state = "joy"
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/mask/pig
|
||||
name = "pig mask"
|
||||
@@ -225,6 +229,7 @@
|
||||
slot_flags = ITEM_SLOT_MASK
|
||||
adjusted_flags = ITEM_SLOT_HEAD
|
||||
icon_state = "bandbotany"
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/mask/bandana/attack_self(mob/user)
|
||||
adjustmask(user)
|
||||
|
||||
@@ -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)
|
||||
@@ -171,17 +171,114 @@
|
||||
icon_state = "stripedbluescarf"
|
||||
item_color = "stripedbluescarf"
|
||||
|
||||
/obj/item/clothing/neck/petcollar //don't really wear this though please c'mon seriously guys
|
||||
///////////
|
||||
//COLLARS//
|
||||
///////////
|
||||
|
||||
/obj/item/clothing/neck/petcollar
|
||||
name = "pet collar"
|
||||
desc = "It's for pets. Though you probably could wear it yourself, you'd doubtless be the subject of ridicule."
|
||||
desc = "It's for pets. Though you probably could wear it yourself, you'd doubtless be the subject of ridicule. It seems to be made out of a polychromic material."
|
||||
icon_state = "petcollar"
|
||||
item_color = "petcollar"
|
||||
alternate_worn_icon = 'icons/mob/neck.dmi' //Because, as it appears, the item itself is normally not directly aware of its worn overlays, so this is about the easiest way, without adding a new var.
|
||||
hasprimary = TRUE
|
||||
primary_color = "#00BBBB"
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small/collar
|
||||
var/tagname = null
|
||||
|
||||
/obj/item/clothing/neck/petcollar/attack_self(mob/user)
|
||||
tagname = copytext(sanitize(input(user, "Would you like to change the name on the tag?", "Name your new pet", "Spot") as null|text),1,MAX_NAME_LEN)
|
||||
name = "[initial(name)] - [tagname]"
|
||||
|
||||
/obj/item/clothing/neck/petcollar/worn_overlays(isinhands, icon_file)
|
||||
. = ..()
|
||||
if(hasprimary | hassecondary | hastertiary)
|
||||
if(!isinhands) //prevents the worn sprites from showing up if you're just holding them
|
||||
if(hasprimary) //checks if overlays are enabled
|
||||
var/mutable_appearance/primary_worn = mutable_appearance(alternate_worn_icon, "[item_color]-primary") //automagical sprite selection
|
||||
primary_worn.color = primary_color //colors the overlay
|
||||
. += primary_worn //adds the overlay onto the buffer list to draw on the mob sprite
|
||||
if(hassecondary)
|
||||
var/mutable_appearance/secondary_worn = mutable_appearance(alternate_worn_icon, "[item_color]-secondary")
|
||||
secondary_worn.color = secondary_color
|
||||
. += secondary_worn
|
||||
if(hastertiary)
|
||||
var/mutable_appearance/tertiary_worn = mutable_appearance(alternate_worn_icon, "[item_color]-tertiary")
|
||||
tertiary_worn.color = tertiary_color
|
||||
. += tertiary_worn
|
||||
|
||||
/obj/item/clothing/neck/petcollar/leather
|
||||
name = "leather pet collar"
|
||||
icon_state = "leathercollar"
|
||||
item_color = "leathercollar"
|
||||
|
||||
hasprimary = TRUE
|
||||
hassecondary = TRUE
|
||||
primary_color = "#222222"
|
||||
secondary_color = "#888888"
|
||||
|
||||
/obj/item/clothing/neck/petcollar/choker
|
||||
desc = "Quite fashionable... if you're somebody who's just read their first BDSM-themed erotica novel."
|
||||
name = "choker"
|
||||
icon_state = "choker"
|
||||
item_color = "choker"
|
||||
|
||||
hasprimary = TRUE
|
||||
primary_color = "#222222"
|
||||
|
||||
/obj/item/clothing/neck/petcollar/locked
|
||||
name = "locked collar"
|
||||
desc = "A collar that has a small lock on it to keep it from being removed."
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/small/collar/locked
|
||||
var/lock = FALSE
|
||||
|
||||
/obj/item/clothing/neck/petcollar/locked/attackby(obj/item/K, mob/user, params)
|
||||
if(istype(K, /obj/item/key/collar))
|
||||
if(lock != FALSE)
|
||||
to_chat(user, "<span class='warning'>With a click the collar unlocks!</span>")
|
||||
lock = FALSE
|
||||
else
|
||||
to_chat(user, "<span class='warning'>With a click the collar locks!</span>")
|
||||
lock = TRUE
|
||||
return
|
||||
|
||||
/obj/item/clothing/neck/petcollar/locked/attack_hand(mob/user)
|
||||
if(loc == user && user.get_item_by_slot(SLOT_NECK) && lock != FALSE)
|
||||
to_chat(user, "<span class='warning'>The collar is locked! You'll need unlock the collar before you can take it off!</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/neck/petcollar/locked/leather
|
||||
name = "leather pet collar"
|
||||
icon_state = "leathercollar"
|
||||
item_color = "leathercollar"
|
||||
|
||||
hasprimary = TRUE
|
||||
hassecondary = TRUE
|
||||
primary_color = "#222222"
|
||||
secondary_color = "#888888"
|
||||
|
||||
/obj/item/clothing/neck/petcollar/locked/choker
|
||||
name = "choker"
|
||||
desc = "Quite fashionable... if you're somebody who's just read their first BDSM-themed erotica novel."
|
||||
icon_state = "choker"
|
||||
item_color = "choker"
|
||||
|
||||
hasprimary = TRUE
|
||||
primary_color = "#222222"
|
||||
|
||||
/obj/item/key/collar
|
||||
name = "Collar Key"
|
||||
desc = "A key for a tiny lock on a collar or bag."
|
||||
|
||||
/obj/item/clothing/neck/petcollar/Initialize()
|
||||
. = ..()
|
||||
new /obj/item/reagent_containers/food/snacks/cookie(src)
|
||||
|
||||
/obj/item/clothing/neck/petcollar/locked/Initialize()
|
||||
. = ..()
|
||||
new /obj/item/key/collar(src)
|
||||
|
||||
//////////////
|
||||
//DOPE BLING//
|
||||
//////////////
|
||||
@@ -191,4 +288,4 @@
|
||||
desc = "Damn, it feels good to be a gangster."
|
||||
icon = 'icons/obj/clothing/neck.dmi'
|
||||
icon_state = "bling"
|
||||
item_color = "bling"
|
||||
item_color = "bling"
|
||||
|
||||
@@ -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,\
|
||||
|
||||
@@ -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)
|
||||
@@ -8,7 +8,7 @@
|
||||
item_state = "spaceold"
|
||||
permeability_coefficient = 0.01
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70)
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
dynamic_hair_suffix = ""
|
||||
dynamic_fhair_suffix = ""
|
||||
cold_protection = HEAD
|
||||
@@ -21,6 +21,7 @@
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
resistance_flags = NONE
|
||||
dog_fashion = null
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/suit/space
|
||||
name = "space suit"
|
||||
|
||||
@@ -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,6 +444,7 @@
|
||||
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)
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
scan_reagents = 1
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/medical
|
||||
@@ -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 = 1
|
||||
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 ..()
|
||||
@@ -750,8 +788,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 +796,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 +808,6 @@
|
||||
item_state = "hardsuit0-ert_commander"
|
||||
item_color = "ert_commander"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////Syndicate Version
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/shielded/syndi
|
||||
@@ -791,7 +822,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)
|
||||
. = ..()
|
||||
|
||||
@@ -8,7 +8,8 @@ Contains:
|
||||
- NASA Voidsuit
|
||||
- Father Christmas' magical clothes
|
||||
- Pirate's spacesuit
|
||||
- ERT hardsuit: command, sec, engi, med
|
||||
- ERT hardsuit: Command, Sec, Engi, Med
|
||||
- ERT High Alarm - Command, Sec, Engi, Med
|
||||
- EVA spacesuit
|
||||
- Freedom's spacesuit (freedom from vacuum's oppression)
|
||||
- Carp hardsuit
|
||||
@@ -64,6 +65,7 @@ Contains:
|
||||
strip_delay = 130
|
||||
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/suit/space/officer
|
||||
name = "officer's jacket"
|
||||
@@ -114,6 +116,7 @@ Contains:
|
||||
desc = "Ho ho ho. Merrry X-mas!"
|
||||
icon_state = "santahat"
|
||||
flags_cover = HEADCOVERSEYES
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/santa
|
||||
|
||||
@@ -137,12 +140,14 @@ Contains:
|
||||
strip_delay = 40
|
||||
equip_delay_other = 20
|
||||
flags_cover = HEADCOVERSEYES
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/head/helmet/space/pirate/bandana
|
||||
name = "royal bandana"
|
||||
desc = "A space-proof bandanna crafted with reflective kevlar."
|
||||
icon_state = "bandana"
|
||||
item_state = "bandana"
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/suit/space/pirate
|
||||
name = "royal waistcoat "
|
||||
@@ -181,6 +186,7 @@ Contains:
|
||||
slowdown = 0
|
||||
strip_delay = 130
|
||||
resistance_flags = ACID_PROOF
|
||||
tauric = TRUE //Citadel Add for tauric hardsuits
|
||||
|
||||
//ERT Security
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/sec
|
||||
@@ -194,7 +200,6 @@ Contains:
|
||||
icon_state = "ert_security"
|
||||
item_state = "ert_security"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/sec
|
||||
tauric = TRUE //Citadel Add for tauric hardsuits
|
||||
|
||||
//ERT Engineering
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/engi
|
||||
@@ -208,7 +213,6 @@ Contains:
|
||||
icon_state = "ert_engineer"
|
||||
item_state = "ert_engineer"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/engi
|
||||
tauric = TRUE //Citadel Add for tauric hardsuits
|
||||
|
||||
//ERT Medical
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/med
|
||||
@@ -223,8 +227,73 @@ Contains:
|
||||
item_state = "ert_medical"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/med
|
||||
species_exception = list(/datum/species/angel)
|
||||
|
||||
//Red alert ERT
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/alert
|
||||
name = "emergency response unit helmet"
|
||||
desc = "Red alert command helmet for the ERT. This one is more armored than its standard version."
|
||||
icon_state = "hardsuit0-ert_commander-alert"
|
||||
item_state = "hardsuit0-ert_commander-alert"
|
||||
item_color = "ert_commander-alert"
|
||||
armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
|
||||
strip_delay = 130
|
||||
item_flags = NODROP
|
||||
brightness_on = 8
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ert/alert
|
||||
name = "emergency response team suit"
|
||||
desc = "Red alert command suit for the ERT. This one is more armored than its standard version."
|
||||
icon_state = "ert_command-alert"
|
||||
item_state = "ert_command-alert"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert
|
||||
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals)
|
||||
armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
|
||||
strip_delay = 130
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
tauric = TRUE //Citadel Add for tauric hardsuits
|
||||
|
||||
//ERT Security
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/alert/sec
|
||||
desc = "Red alert security helmet for the ERT. This one is more armored than its standard version."
|
||||
icon_state = "hardsuit0-ert_security-alert"
|
||||
item_state = "hardsuit0-ert_security-alert"
|
||||
item_color = "ert_security-alert"
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ert/alert/sec
|
||||
desc = "Red alert security suit for the ERT. This one is more armored than its standard version."
|
||||
icon_state = "ert_security-alert"
|
||||
item_state = "ert_security-alert"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert/sec
|
||||
|
||||
//ERT Engineering
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/alert/engi
|
||||
desc = "Red alert engineer helmet for the ERT. This one is more armored than its standard version."
|
||||
icon_state = "hardsuit0-ert_engineer-alert"
|
||||
item_state = "hardsuit0-ert_engineer-alert"
|
||||
item_color = "ert_engineer-alert"
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ert/alert/engi
|
||||
desc = "Red alert engineer suit for the ERT. This one is more armored than its standard version."
|
||||
icon_state = "ert_engineer-alert"
|
||||
item_state = "ert_engineer-alert"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert/engi
|
||||
|
||||
//ERT Medical
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/alert/med
|
||||
desc = "Red alert medical helmet for the ERT. This one is more armored than its standard version."
|
||||
icon_state = "hardsuit0-ert_medical-alert"
|
||||
item_state = "hardsuit0-ert_medical-alert"
|
||||
item_color = "ert_medical-alert"
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ert/alert/med
|
||||
desc = "Red alert medical suit for the ERT. This one is more armored than its standard version."
|
||||
icon_state = "ert_medical-alert"
|
||||
item_state = "ert_medical-alert"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert/med
|
||||
species_exception = list(/datum/species/angel)
|
||||
|
||||
/obj/item/clothing/suit/space/eva
|
||||
name = "EVA suit"
|
||||
icon_state = "space"
|
||||
@@ -250,6 +319,7 @@ Contains:
|
||||
strip_delay = 130
|
||||
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||
resistance_flags = ACID_PROOF | FIRE_PROOF
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/suit/space/freedom
|
||||
name = "eagle suit"
|
||||
@@ -273,7 +343,7 @@ Contains:
|
||||
brightness_on = 0 //luminosity when on
|
||||
actions_types = list()
|
||||
item_flags = NODROP
|
||||
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/carp
|
||||
name = "carp space suit"
|
||||
@@ -285,7 +355,6 @@ Contains:
|
||||
allowed = list(/obj/item/tank/internals, /obj/item/gun/ballistic/automatic/speargun) //I'm giving you a hint here
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/carp
|
||||
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal
|
||||
name = "paranormal response unit helmet"
|
||||
desc = "A helmet worn by those who deal with paranormal threats for a living."
|
||||
@@ -295,6 +364,7 @@ Contains:
|
||||
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||
actions_types = list()
|
||||
resistance_flags = FIRE_PROOF
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ert/paranormal
|
||||
name = "paranormal response team suit"
|
||||
@@ -304,6 +374,7 @@ Contains:
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal
|
||||
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
|
||||
resistance_flags = FIRE_PROOF
|
||||
tauric = TRUE //Citadel Add for tauric hardsuits
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -36,17 +36,11 @@
|
||||
if(tauric == TRUE)
|
||||
center = TRUE
|
||||
dimension_x = 64
|
||||
else if(H.dna.features["taur"] in list("Fox","Wolf","Otie","Drake","Lab","Shepherd","Husky","Eevee","Panther","Horse","Cow","Tiger"))
|
||||
else if(H.dna.features["taur"] in list("Fox","Wolf","Otie","Drake","Lab","Shepherd","Husky","Eevee","Panther","Horse","Cow","Tiger","Deer"))
|
||||
taurmode = PAW_TAURIC
|
||||
if(tauric == TRUE)
|
||||
center = TRUE
|
||||
dimension_x = 64
|
||||
/*
|
||||
else if(H.dna.features["taur"] == "Horse" || "Cow")
|
||||
taurmode = HOOF_TAURIC //tweak this for when the exotics get their own suits, if ever.
|
||||
center = TRUE
|
||||
dimension_x = 64
|
||||
*/
|
||||
else
|
||||
taurmode = NOT_TAURIC
|
||||
if(tauric == TRUE)
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
item_state = "armoralt"
|
||||
blood_overlay_type = "armor"
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
tauric = TRUE //Citadel Add for tauric hardsuits
|
||||
|
||||
/obj/item/clothing/suit/armor/vest/alt
|
||||
desc = "A Type I armored vest that provides decent protection against most types of damage."
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
permeability_coefficient = 0.01
|
||||
clothing_flags = THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 60, "fire" = 30, "acid" = 100)
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDEFACE
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDEFACE|HIDESNOUT
|
||||
resistance_flags = ACID_PROOF
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/suit/bio_suit
|
||||
name = "bio suit"
|
||||
|
||||
@@ -5,7 +5,28 @@
|
||||
item_state = "labcoat"
|
||||
blood_overlay_type = "coat"
|
||||
body_parts_covered = CHEST|ARMS
|
||||
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/soap, /obj/item/sensor_device, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
|
||||
allowed = list(
|
||||
/obj/item/analyzer,
|
||||
/obj/item/stack/medical,
|
||||
/obj/item/dnainjector,
|
||||
/obj/item/reagent_containers/dropper,
|
||||
/obj/item/reagent_containers/syringe,
|
||||
/obj/item/reagent_containers/hypospray,
|
||||
/obj/item/hypospray/mkii,
|
||||
/obj/item/healthanalyzer,
|
||||
/obj/item/flashlight/pen,
|
||||
/obj/item/reagent_containers/glass/bottle,
|
||||
/obj/item/reagent_containers/glass/beaker,
|
||||
/obj/item/reagent_containers/pill,
|
||||
/obj/item/storage/pill_bottle,
|
||||
/obj/item/paper,
|
||||
/obj/item/melee/classic_baton/telescopic,
|
||||
/obj/item/soap,
|
||||
/obj/item/sensor_device,
|
||||
/obj/item/tank/internals/emergency_oxygen,
|
||||
/obj/item/tank/internals/plasmaman
|
||||
)
|
||||
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
togglename = "buttons"
|
||||
species_exception = list(/datum/species/golem)
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
ToggleHood()
|
||||
|
||||
/obj/item/clothing/suit/hooded/item_action_slot_check(slot, mob/user)
|
||||
if(slot == SLOT_WEAR_SUIT)
|
||||
if(slot == SLOT_WEAR_SUIT || slot == SLOT_NECK)
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/suit/hooded/equipped(mob/user, slot)
|
||||
if(slot != SLOT_WEAR_SUIT)
|
||||
if(slot != SLOT_WEAR_SUIT && slot != SLOT_NECK)
|
||||
RemoveHood()
|
||||
..()
|
||||
|
||||
@@ -180,6 +180,7 @@
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/proc/ToggleHelmet()
|
||||
var/mob/living/carbon/human/H = src.loc
|
||||
var/datum/species/pref_species = H.dna.species
|
||||
if(!helmettype)
|
||||
return
|
||||
if(!helmet)
|
||||
@@ -193,6 +194,18 @@
|
||||
to_chat(H, "<span class='warning'>You're already wearing something on your head!</span>")
|
||||
return
|
||||
else if(H.equip_to_slot_if_possible(helmet,SLOT_HEAD,0,0,1))
|
||||
if(helmet.mutantrace_variation)
|
||||
if("mam_snouts" in pref_species.default_features)
|
||||
if(H.dna.features["mam_snouts"] != "None")
|
||||
helmet.muzzle_var = ALT_STYLE
|
||||
|
||||
else if("snout" in pref_species.default_features)
|
||||
if(H.dna.features["snout"] != "None")
|
||||
helmet.muzzle_var = ALT_STYLE
|
||||
else
|
||||
helmet.muzzle_var = NORMAL_STYLE
|
||||
H.update_inv_head()
|
||||
|
||||
to_chat(H, "<span class='notice'>You engage the helmet on the hardsuit.</span>")
|
||||
suittoggled = TRUE
|
||||
H.update_inv_wear_suit()
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
icon_state = "bombsuit"
|
||||
clothing_flags = THICKMATERIAL
|
||||
armor = list("melee" = 20, "bullet" = 0, "laser" = 20,"energy" = 10, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 50)
|
||||
flags_inv = HIDEFACE|HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEFACE|HIDEMASK|HIDEEARS|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
dynamic_hair_suffix = ""
|
||||
dynamic_fhair_suffix = ""
|
||||
cold_protection = HEAD
|
||||
@@ -71,6 +71,7 @@
|
||||
equip_delay_other = 70
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
resistance_flags = NONE
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
|
||||
/obj/item/clothing/suit/bomb_suit
|
||||
@@ -123,13 +124,14 @@
|
||||
icon_state = "rad"
|
||||
desc = "A hood with radiation protective properties. The label reads, 'Made with lead. Please do not consume insulation.'"
|
||||
clothing_flags = THICKMATERIAL
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEFACE|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEFACE|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 60, "rad" = 100, "fire" = 30, "acid" = 30)
|
||||
strip_delay = 60
|
||||
equip_delay_other = 60
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
resistance_flags = NONE
|
||||
rad_flags = RAD_PROTECT_CONTENTS
|
||||
mutantrace_variation = MUTANTRACE_VARIATION
|
||||
|
||||
/obj/item/clothing/suit/radiation
|
||||
name = "radiation suit"
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
CAT_BURGER,
|
||||
CAT_CAKE,
|
||||
CAT_EGG,
|
||||
CAT_SUSHI, //Called Fish
|
||||
CAT_ICE, //Called Frozen
|
||||
CAT_MEAT,
|
||||
CAT_MISCFOOD,
|
||||
CAT_PASTRY,
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
var/category = CAT_NONE //where it shows up in the crafting UI
|
||||
var/subcategory = CAT_NONE
|
||||
|
||||
|
||||
/datum/crafting_recipe/pin_removal
|
||||
name = "Pin Removal"
|
||||
result = /obj/item/gun
|
||||
@@ -54,6 +53,18 @@
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/makeshiftshield
|
||||
name = "Makeshift Metal Shield"
|
||||
result = /obj/item/shield/makeshift
|
||||
reqs = list(/obj/item/stack/cable_coil = 30,
|
||||
/obj/item/stack/sheet/metal = 10,
|
||||
/obj/item/stack/sheet/cloth = 2,
|
||||
/obj/item/stack/sheet/leather = 3)
|
||||
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
time = 100
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/molotov
|
||||
name = "Molotov"
|
||||
result = /obj/item/reagent_containers/food/drinks/bottle/molotov
|
||||
@@ -189,6 +200,16 @@
|
||||
time = 40
|
||||
category = CAT_ROBOT
|
||||
|
||||
/datum/crafting_recipe/Firebot
|
||||
name = "Firebot"
|
||||
result = /mob/living/simple_animal/bot/firebot
|
||||
reqs = list(/obj/item/extinguisher = 1,
|
||||
/obj/item/bodypart/r_arm/robot = 1,
|
||||
/obj/item/assembly/prox_sensor = 1,
|
||||
/obj/item/clothing/head/hardhat/red = 1)
|
||||
time = 40
|
||||
category = CAT_ROBOT
|
||||
|
||||
/datum/crafting_recipe/improvised_pneumatic_cannon //Pretty easy to obtain but
|
||||
name = "Pneumatic Cannon"
|
||||
result = /obj/item/pneumatic_cannon/ghetto
|
||||
@@ -302,6 +323,18 @@
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/irifle
|
||||
name = "Improvised Rifle(7.62mm)"
|
||||
result = /obj/item/gun/ballistic/shotgun/boltaction/improvised
|
||||
reqs = list(/obj/item/weaponcrafting/receiver = 1,
|
||||
/obj/item/pipe = 2,
|
||||
/obj/item/weaponcrafting/stock = 1,
|
||||
/obj/item/stack/packageWrap = 5)
|
||||
tools = list(TOOL_SCREWDRIVER)
|
||||
time = 100
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/chainsaw
|
||||
name = "Chainsaw"
|
||||
result = /obj/item/twohanded/required/chainsaw
|
||||
@@ -385,7 +418,6 @@
|
||||
reqs = list(/obj/item/paper = 5)
|
||||
category = CAT_MISC
|
||||
|
||||
|
||||
/datum/crafting_recipe/flashlight_eyes
|
||||
name = "Flashlight Eyes"
|
||||
result = /obj/item/organ/eyes/robotic/flashlight
|
||||
@@ -435,6 +467,15 @@
|
||||
result = /obj/item/extendohand
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/bluespacehonker
|
||||
name = "Bluespace Bike horn"
|
||||
result = /obj/item/bikehorn/bluespacehonker
|
||||
time = 10
|
||||
reqs = list(/obj/item/stack/ore/bluespace_crystal = 1,
|
||||
/obj/item/toy/crayon/blue = 1,
|
||||
/obj/item/bikehorn = 1)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/chemical_payload
|
||||
name = "Chemical Payload (C4)"
|
||||
result = /obj/item/bombcore/chemical
|
||||
@@ -517,6 +558,14 @@
|
||||
/obj/item/stack/sheet/animalhide/ashdrake = 5)
|
||||
category = CAT_PRIMAL
|
||||
|
||||
/datum/crafting_recipe/bonebag
|
||||
name = "Bone Satchel"
|
||||
result = /obj/item/storage/backpack/satchel/bone
|
||||
time = 30
|
||||
reqs = list(/obj/item/stack/sheet/bone = 3,
|
||||
/obj/item/stack/sheet/sinew = 2)
|
||||
category = CAT_PRIMAL
|
||||
|
||||
/datum/crafting_recipe/gold_horn
|
||||
name = "Golden Bike Horn"
|
||||
result = /obj/item/bikehorn/golden
|
||||
@@ -592,7 +641,6 @@
|
||||
/obj/item/assembly/igniter = 1)
|
||||
category = CAT_MISC
|
||||
|
||||
|
||||
/datum/crafting_recipe/rcl
|
||||
name = "Makeshift Rapid Cable Layer"
|
||||
result = /obj/item/twohanded/rcl/ghetto
|
||||
@@ -686,6 +734,16 @@
|
||||
reqs = list(/obj/item/bedsheet = 1)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/briefcase
|
||||
name = "Hand made Briefcase"
|
||||
result = /obj/item/storage/briefcase/crafted
|
||||
time = 35
|
||||
tools = list(TOOL_WIRECUTTER)
|
||||
reqs = list(/obj/item/stack/sheet/cardboard = 1,
|
||||
/obj/item/stack/sheet/cloth = 2,
|
||||
/obj/item/stack/sheet/leather = 5)
|
||||
category = CAT_CLOTHING
|
||||
|
||||
/datum/crafting_recipe/aitater
|
||||
name = "intelliTater"
|
||||
result = /obj/item/aicard/aitater
|
||||
@@ -696,16 +754,30 @@
|
||||
|
||||
/datum/crafting_recipe/paperwork
|
||||
name = "Filed Paper Work"
|
||||
result = /obj/item/paper/fluff/jobs/cargo/manifest/paperwork_correct
|
||||
time = 90 //Takes time for people to file and complete paper work!
|
||||
result = /obj/item/folder/paperwork_correct
|
||||
time = 60 //Takes time for people to file and complete paper work!
|
||||
reqs = list(/obj/item/pen = 1,
|
||||
/obj/item/paper/fluff/jobs/cargo/manifest/paperwork = 2)
|
||||
/obj/item/folder/paperwork = 2)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/ghettojetpack
|
||||
name = "Improvised Jetpack"
|
||||
result = /obj/item/tank/jetpack/improvised
|
||||
time = 30
|
||||
reqs = list(/obj/item/tank/internals/oxygen/red = 2, /obj/item/extinguisher = 1, /obj/item/pipe = 3, /obj/item/stack/cable_coil = 30)//red oxygen tank so it looks right
|
||||
reqs = list(/obj/item/tank/internals/oxygen = 2,
|
||||
/obj/item/extinguisher = 1,
|
||||
/obj/item/pipe = 3,
|
||||
/obj/item/stack/cable_coil = 30)
|
||||
category = CAT_MISC
|
||||
tools = list(TOOL_WRENCH, TOOL_WELDER, TOOL_WIRECUTTER)
|
||||
|
||||
/datum/crafting_recipe/goldenbox
|
||||
name = "Gold Plated Toolbox"
|
||||
result = /obj/item/storage/toolbox/gold_fake
|
||||
reqs = list(/obj/item/stack/sheet/cardboard = 1, //so we dont null items in crafting
|
||||
/obj/item/stack/cable_coil = 10,
|
||||
/obj/item/stack/sheet/mineral/gold = 1,
|
||||
/obj/item/stock_parts/cell = 1,
|
||||
/datum/reagent/water = 15)
|
||||
time = 40
|
||||
category = CAT_MISC
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
icon = 'icons/obj/toy.dmi'
|
||||
icon_state = "rag"
|
||||
item_flags = NOBLUDGEON
|
||||
container_type = OPENCONTAINER
|
||||
reagent_flags = OPENCONTAINER
|
||||
amount_per_transfer_from_this = 5
|
||||
possible_transfer_amounts = list()
|
||||
volume = 5
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
continue
|
||||
if(H.stat == DEAD)
|
||||
continue
|
||||
if(H.has_trait(TRAIT_VIRUSIMMUNE)) //Don't pick someone who's virus immune, only for it to not do anything.
|
||||
if(HAS_TRAIT(H, TRAIT_VIRUSIMMUNE)) //Don't pick someone who's virus immune, only for it to not do anything.
|
||||
continue
|
||||
var/foundAlready = FALSE // don't infect someone that already has a disease
|
||||
for(var/thing in H.diseases)
|
||||
@@ -51,7 +51,7 @@
|
||||
var/datum/disease/D
|
||||
if(!advanced_virus)
|
||||
if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work.
|
||||
if(!H.dna || (H.has_trait(TRAIT_BLIND))) //A blindness disease would be the worst.
|
||||
if(!H.dna || (HAS_TRAIT(H, TRAIT_BLIND))) //A blindness disease would be the worst.
|
||||
continue
|
||||
D = new virus_type()
|
||||
var/datum/disease/dnaspread/DS = D
|
||||
|
||||
@@ -48,8 +48,6 @@
|
||||
if(!shuttle_spawned)
|
||||
spawn_shuttle()
|
||||
|
||||
|
||||
|
||||
/datum/round_event/pirates/start()
|
||||
if(!paid_off && !shuttle_spawned)
|
||||
spawn_shuttle()
|
||||
@@ -150,7 +148,6 @@
|
||||
to_chat(user,"<span class='notice'>You retrieve the siphoned credits!</span>")
|
||||
credits_stored = 0
|
||||
|
||||
|
||||
/obj/machinery/shuttle_scrambler/proc/send_notification()
|
||||
priority_announce("Data theft signal detected, source registered on local gps units.")
|
||||
|
||||
@@ -222,8 +219,7 @@
|
||||
suit_type = /obj/item/clothing/suit/space
|
||||
helmet_type = /obj/item/clothing/head/helmet/space
|
||||
mask_type = /obj/item/clothing/mask/breath
|
||||
storage_type = /obj/item/tank/internals/oxygen
|
||||
|
||||
storage_type = /obj/item/tank/jetpack/void
|
||||
|
||||
/obj/machinery/loot_locator
|
||||
name = "Booty Locator"
|
||||
@@ -454,4 +450,4 @@
|
||||
|
||||
/datum/export/pirate/cash/get_amount(obj/O)
|
||||
var/obj/item/stack/spacecash/C = O
|
||||
return ..() * C.amount * C.value
|
||||
return ..() * C.amount * C.value
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user