Merge branch 'master' into patch-135
This commit is contained in:
@@ -35,3 +35,8 @@
|
||||
|
||||
//Overthrow time to update heads obj
|
||||
#define OBJECTIVE_UPDATING_TIME 300
|
||||
|
||||
//Gangshit
|
||||
#define NOT_DOMINATING -1
|
||||
#define MAX_LEADERS_GANG 3
|
||||
#define INITIAL_DOM_ATTEMPTS 3
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
//LISTMOS
|
||||
//indices of values in gas lists.
|
||||
#define MOLES 1
|
||||
#define ARCHIVE 2
|
||||
#define GAS_META 3
|
||||
#define META_GAS_SPECIFIC_HEAT 1
|
||||
#define META_GAS_NAME 2
|
||||
#define META_GAS_MOLES_VISIBLE 3
|
||||
@@ -242,20 +239,25 @@
|
||||
|
||||
//HELPERS
|
||||
#define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity())
|
||||
|
||||
#define ADD_GAS(gas_id, out_list)\
|
||||
var/list/tmp_gaslist = GLOB.gaslist_cache[gas_id]; out_list[gas_id] = tmp_gaslist.Copy();
|
||||
|
||||
#define ASSERT_GAS(gas_id, gas_mixture) if (!gas_mixture.gases[gas_id]) { ADD_GAS(gas_id, gas_mixture.gases) };
|
||||
|
||||
#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 */
|
||||
|
||||
//prefer this to gas_mixture/total_moles in performance critical areas
|
||||
#define TOTAL_MOLES(cached_gases, out_var)\
|
||||
out_var = 0;\
|
||||
for(var/total_moles_id in cached_gases){\
|
||||
out_var += cached_gases[total_moles_id][MOLES];\
|
||||
out_var += cached_gases[total_moles_id];\
|
||||
}
|
||||
|
||||
//Unomos - So for whatever reason, garbage collection actually drastically decreases the cost of atmos later in the round. Turning this into a define yields massively improved performance.
|
||||
#define GAS_GARBAGE_COLLECT(GASGASGAS)\
|
||||
var/list/CACHE_GAS = GASGASGAS;\
|
||||
for(var/id in CACHE_GAS){\
|
||||
if(QUANTIZE(CACHE_GAS[id]) <= 0)\
|
||||
CACHE_GAS -= id;\
|
||||
}
|
||||
|
||||
#define ARCHIVE_TEMPERATURE(gas) gas.temperature_archived = gas.temperature
|
||||
|
||||
GLOBAL_LIST_INIT(pipe_paint_colors, list(
|
||||
"amethyst" = rgb(130,43,255), //supplymain
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
#define BALLS_VOLUME_MULT 1
|
||||
|
||||
#define BALLS_SIZE_MIN 1
|
||||
#define BALLS_SIZE_DEF 3
|
||||
#define BALLS_SIZE_MAX 7
|
||||
#define BALLS_SIZE_DEF 2
|
||||
#define BALLS_SIZE_MAX 3
|
||||
|
||||
#define BALLS_SACK_SIZE_MIN 1
|
||||
#define BALLS_SACK_SIZE_DEF 8
|
||||
|
||||
@@ -142,8 +142,9 @@
|
||||
#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity))
|
||||
|
||||
// /obj signals
|
||||
#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
|
||||
#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
|
||||
#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
|
||||
#define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag)
|
||||
#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
|
||||
|
||||
// /obj/item signals
|
||||
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
#define CAT_SOUP "Soups"
|
||||
#define CAT_SPAGHETTI "Spaghettis"
|
||||
#define CAT_SUSHI "Fish"
|
||||
#define CAT_ICE "Frozen"
|
||||
|
||||
#define RCD_FLOORWALL 1
|
||||
#define RCD_AIRLOCK 2
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
#define ROLE_DRONE "drone"
|
||||
#define ROLE_DEATHSQUAD "deathsquad"
|
||||
#define ROLE_LAVALAND "lavaland"
|
||||
#define ROLE_INTERNAL_AFFAIRS "internal affairs agent"
|
||||
#define ROLE_INTERNAL_AFFAIRS "internal affairs agent"
|
||||
#define ROLE_GANG "gangster"
|
||||
|
||||
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
|
||||
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
|
||||
@@ -58,7 +59,8 @@ GLOBAL_LIST_INIT(special_roles, list(
|
||||
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult,
|
||||
ROLE_OVERTHROW = /datum/game_mode/overthrow,
|
||||
ROLE_INTERNAL_AFFAIRS = /datum/game_mode/traitor/internal_affairs,
|
||||
ROLE_SENTIENCE
|
||||
ROLE_SENTIENCE,
|
||||
ROLE_GANG = /datum/game_mode/gang
|
||||
))
|
||||
|
||||
//Job defines for what happens when you fail to qualify for any job during job selection
|
||||
|
||||
@@ -71,6 +71,8 @@
|
||||
#define TRAIT_MUSICIAN "musician"
|
||||
#define TRAIT_CROCRIN_IMMUNE "crocin_immune"
|
||||
#define TRAIT_NYMPHO "nymphomania"
|
||||
#define TRAIT_MASO "masochism"
|
||||
#define TRAIT_ASSBLASTUSA "assblastusa"
|
||||
|
||||
// common trait sources
|
||||
#define TRAIT_GENERIC "generic"
|
||||
|
||||
@@ -58,8 +58,11 @@ GLOBAL_LIST_EMPTY(ipc_antennas_list)
|
||||
//Genitals and Arousal Lists
|
||||
GLOBAL_LIST_EMPTY(cock_shapes_list)//global_lists.dm for the list initializations //Now also _DATASTRUCTURES globals.dm
|
||||
GLOBAL_LIST_EMPTY(cock_shapes_icons) //Associated list for names->icon_states for cockshapes.
|
||||
GLOBAL_LIST_EMPTY(balls_shapes_list)
|
||||
GLOBAL_LIST_EMPTY(balls_shapes_icons)
|
||||
GLOBAL_LIST_EMPTY(breasts_size_list)
|
||||
GLOBAL_LIST_EMPTY(breasts_shapes_list)
|
||||
GLOBAL_LIST_EMPTY(breasts_shapes_icons)
|
||||
GLOBAL_LIST_EMPTY(vagina_shapes_list)
|
||||
GLOBAL_LIST_INIT(cum_into_containers_list, list(/obj/item/reagent_containers/food/snacks/pie)) //Yer fuggin snowflake name list jfc
|
||||
GLOBAL_LIST_INIT(dick_nouns, list("dick","cock","member","shaft"))
|
||||
@@ -123,36 +126,36 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
/mob/living/carbon/proc/has_penis()
|
||||
if(getorganslot("penis"))//slot shared with ovipositor
|
||||
if(istype(getorganslot("penis"), /obj/item/organ/genital/penis))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/proc/has_balls()
|
||||
if(getorganslot("balls"))
|
||||
if(istype(getorganslot("balls"), /obj/item/organ/genital/testicles))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/proc/has_vagina()
|
||||
if(getorganslot("vagina"))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/proc/has_breasts()
|
||||
if(getorganslot("breasts"))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/proc/has_ovipositor()
|
||||
if(getorganslot("penis"))//shared slot
|
||||
if(istype(getorganslot("penis"), /obj/item/organ/genital/ovipositor))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/proc/has_eggsack()
|
||||
if(getorganslot("balls"))
|
||||
if(istype(getorganslot("balls"), /obj/item/organ/genital/eggsack))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/proc/is_bodypart_exposed(bodypart)
|
||||
|
||||
@@ -161,16 +164,16 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
L = get_equipped_items()
|
||||
for(var/obj/item/I in L)
|
||||
if(I.body_parts_covered & GROIN)
|
||||
return 0
|
||||
return 1
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/proc/is_chest_exposed(var/list/L)
|
||||
if(!L)
|
||||
L = get_equipped_items()
|
||||
for(var/obj/item/I in L)
|
||||
if(I.body_parts_covered & CHEST)
|
||||
return 0
|
||||
return 1
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
////////////////////////
|
||||
//DANGER | DEBUG PROCS//
|
||||
@@ -191,40 +194,3 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
H.give_vagina()
|
||||
H.give_womb()
|
||||
H.give_breasts()
|
||||
|
||||
/client/proc/test_mammal_overlays()
|
||||
set name = "Mass Give Mammalitus"
|
||||
set category = "Dangerous"
|
||||
set desc = "Turns every human into a mammal with tails, ears, etc. WARNING: NOT FOR LIVE SERVER USAGE!!"
|
||||
|
||||
log_admin("[src] turned everyone into mammals.")
|
||||
message_admins("[src] turned everyone into mammals.")
|
||||
for(var/mob/living/carbon/human/H in GLOB.mob_list)
|
||||
if(!H.dna)
|
||||
continue
|
||||
var/datum/dna/hdna = H.dna
|
||||
H.set_species(/datum/species/mammal)
|
||||
var/subspec = pick("Fox","Wolf","Fennec")
|
||||
switch(subspec)
|
||||
if("Wolf")
|
||||
hdna.features["mam_tail"] = "Wolf"
|
||||
hdna.features["mam_ears"] = "Wolf"
|
||||
hdna.features["mam_snouts"] = "Wolf"
|
||||
hdna.features["mam_body_markings"] = "Wolf"
|
||||
hdna.features["mcolor"] = "555"
|
||||
hdna.features["mcolor2"] = "999"
|
||||
hdna.features["mcolor3"] = "999"
|
||||
if("Fox")
|
||||
hdna.features["mam_tail"] = "Fox"
|
||||
hdna.features["mam_ears"] = "Fox"
|
||||
hdna.features["mam_snouts"] = "Fox, Long"
|
||||
hdna.features["mam_body_markings"] = "Fox"
|
||||
hdna.features["mcolor"] = "f60"
|
||||
hdna.features["mcolor2"] = "fff"
|
||||
hdna.features["mcolor3"] = "fff"
|
||||
if("Fennec")
|
||||
hdna.features["mam_tail"] = "Fennec"
|
||||
hdna.features["mam_ears"] = "Fennec"
|
||||
hdna.features["mam_snouts"] = "Fox, Short"
|
||||
hdna.features["mam_body_markings"] = "Fox"
|
||||
H.regenerate_icons()
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_dorsal, GLOB.xeno_dorsal_list)
|
||||
//genitals
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, GLOB.cock_shapes_list)
|
||||
|
||||
for(var/K in GLOB.cock_shapes_list)
|
||||
var/datum/sprite_accessory/penis/value = GLOB.cock_shapes_list[K]
|
||||
GLOB.cock_shapes_icons[K] = value.icon_state
|
||||
@@ -54,6 +53,14 @@
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, GLOB.breasts_shapes_list)
|
||||
GLOB.breasts_size_list = list("a","b","c","d","e") //We need the list to choose from initialized, but it's no longer a sprite_accessory thing.
|
||||
for(var/K in GLOB.breasts_shapes_list)
|
||||
var/datum/sprite_accessory/breasts/value = GLOB.breasts_shapes_list[K]
|
||||
GLOB.breasts_shapes_icons[K] = value.icon_state
|
||||
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/testicles, GLOB.balls_shapes_list)
|
||||
for(var/K in GLOB.balls_shapes_list)
|
||||
var/datum/sprite_accessory/testicles/value = GLOB.balls_shapes_list[K]
|
||||
GLOB.balls_shapes_icons[K] = value.icon_state
|
||||
//END OF CIT CHANGES
|
||||
|
||||
//Species
|
||||
|
||||
@@ -77,6 +77,8 @@
|
||||
//CIT CHANGES - genitals and such
|
||||
if(!GLOB.cock_shapes_list.len)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, GLOB.cock_shapes_list)
|
||||
if(!GLOB.balls_shapes_list.len)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/testicles, GLOB.balls_shapes_list)
|
||||
if(!GLOB.vagina_shapes_list.len)
|
||||
init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list)
|
||||
if(!GLOB.breasts_shapes_list.len)
|
||||
@@ -168,6 +170,7 @@
|
||||
"balls_amount" = 2,
|
||||
"balls_sack_size" = BALLS_SACK_SIZE_DEF,
|
||||
"balls_size" = BALLS_SIZE_DEF,
|
||||
"balls_shape" = "Pair",
|
||||
"balls_cum_rate" = CUM_RATE,
|
||||
"balls_cum_mult" = CUM_RATE_MULT,
|
||||
"balls_efficiency" = CUM_EFFICIENCY,
|
||||
@@ -185,7 +188,7 @@
|
||||
"has_breasts" = FALSE,
|
||||
"breasts_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
|
||||
"breasts_size" = pick(GLOB.breasts_size_list),
|
||||
"breasts_shape" = pick(GLOB.breasts_shapes_list),
|
||||
"breasts_shape" = "Pair",
|
||||
"breasts_fluid" = "milk",
|
||||
"has_vag" = FALSE,
|
||||
"vag_shape" = pick(GLOB.vagina_shapes_list),
|
||||
@@ -294,7 +297,7 @@ GLOBAL_LIST_EMPTY(species_list)
|
||||
else
|
||||
return "unknown"
|
||||
|
||||
/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks = null)
|
||||
/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks = null, ignorehelditem = 0)
|
||||
if(!user || !target)
|
||||
return 0
|
||||
var/user_loc = user.loc
|
||||
@@ -327,7 +330,7 @@ GLOBAL_LIST_EMPTY(species_list)
|
||||
drifting = 0
|
||||
user_loc = user.loc
|
||||
|
||||
if((!drifting && user.loc != user_loc) || target.loc != target_loc || user.get_active_held_item() != holding || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke()))
|
||||
if((!drifting && user.loc != user_loc) || target.loc != target_loc || (!ignorehelditem && user.get_active_held_item() != holding) || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke()))
|
||||
. = 0
|
||||
break
|
||||
if (progress)
|
||||
|
||||
@@ -94,6 +94,8 @@
|
||||
// Used to get a properly sanitized multiline input, of max_length
|
||||
/proc/stripped_multiline_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN, no_trim=FALSE)
|
||||
var/name = input(user, message, title, default) as message|null
|
||||
if(isnull(name)) // Return null if canceled.
|
||||
return null
|
||||
if(no_trim)
|
||||
return copytext(html_encode(name), 1, max_length)
|
||||
else
|
||||
|
||||
@@ -109,5 +109,7 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
|
||||
/obj/item/reagent_containers/pill/floorpill = 1,
|
||||
/obj/item/storage/daki = 3, //VERY IMPORTANT CIT CHANGE - adds bodypillows to maint
|
||||
/obj/item/storage/pill_bottle/penis_enlargement = 2,
|
||||
/obj/item/clothing/shoes/wheelys = 1,
|
||||
/obj/item/clothing/shoes/kindleKicks = 1,
|
||||
"" = 3
|
||||
))
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
/datum/component/storage/concrete
|
||||
var/drop_all_on_deconstruct = TRUE
|
||||
var/drop_all_on_destroy = FALSE
|
||||
var/drop_all_on_break = FALSE
|
||||
var/unlock_on_break = FALSE
|
||||
var/transfer_contents_on_component_transfer = FALSE
|
||||
var/list/datum/component/storage/slaves = list()
|
||||
|
||||
@@ -16,6 +18,7 @@
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del)
|
||||
RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, .proc/on_deconstruct)
|
||||
RegisterSignal(parent, COMSIG_OBJ_BREAK, .proc/on_break)
|
||||
|
||||
/datum/component/storage/concrete/Destroy()
|
||||
var/atom/real_location = real_location()
|
||||
@@ -100,6 +103,12 @@
|
||||
if(drop_all_on_deconstruct)
|
||||
do_quick_empty()
|
||||
|
||||
/datum/component/storage/concrete/proc/on_break(datum/source, damage_flag)
|
||||
if(drop_all_on_break)
|
||||
do_quick_empty()
|
||||
if(unlock_on_break)
|
||||
set_locked(source, FALSE)
|
||||
|
||||
/datum/component/storage/concrete/can_see_contents()
|
||||
. = ..()
|
||||
for(var/i in slaves)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/datum/component/storage/concrete/emergency
|
||||
drop_all_on_break = TRUE
|
||||
unlock_on_break = TRUE
|
||||
locked = TRUE
|
||||
|
||||
/datum/component/storage/concrete/emergency/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_ATOM_EMAG_ACT, .proc/unlock_me)
|
||||
|
||||
/datum/component/storage/concrete/emergency/signal_insertion_attempt(datum/source, obj/item/I, mob/M, silent = FALSE, force = FALSE)
|
||||
if(!silent && istype(I, /obj/item/card/emag))
|
||||
silent = TRUE // suppresses the message
|
||||
return ..()
|
||||
|
||||
/datum/component/storage/concrete/check_locked(datum/source, mob/user, message = FALSE)
|
||||
. = locked && GLOB.security_level < SEC_LEVEL_RED
|
||||
if(message && . && user)
|
||||
to_chat(user, "The storage unit will only unlock during a Red or Delta security alert.")
|
||||
|
||||
/datum/component/storage/concrete/emergency/proc/unlock_me(datum/source)
|
||||
if(locked)
|
||||
set_locked(source, FALSE)
|
||||
@@ -156,8 +156,7 @@
|
||||
next += slave.parent
|
||||
|
||||
/datum/component/storage/proc/attack_self(datum/source, mob/M)
|
||||
if(locked)
|
||||
to_chat(M, "<span class='warning'>[parent] seems to be locked!</span>")
|
||||
if(check_locked(source, M, TRUE))
|
||||
return FALSE
|
||||
if((M.get_active_held_item() == parent) && allow_quick_empty)
|
||||
quick_empty(M)
|
||||
@@ -166,8 +165,7 @@
|
||||
if(!isitem(O) || !click_gather || SEND_SIGNAL(O, COMSIG_CONTAINS_STORAGE))
|
||||
return FALSE
|
||||
. = COMPONENT_NO_ATTACK
|
||||
if(locked)
|
||||
to_chat(M, "<span class='warning'>[parent] seems to be locked!</span>")
|
||||
if(check_locked(source, M, TRUE))
|
||||
return FALSE
|
||||
var/atom/A = parent
|
||||
var/obj/item/I = O
|
||||
@@ -238,8 +236,7 @@
|
||||
var/atom/A = parent
|
||||
if((!ishuman(M) && (A.loc != M)) || (M.stat != CONSCIOUS) || M.restrained() || !M.canmove)
|
||||
return
|
||||
if(locked)
|
||||
to_chat(M, "<span class='warning'>[parent] seems to be locked!</span>")
|
||||
if(check_locked(null, M, TRUE))
|
||||
return FALSE
|
||||
A.add_fingerprint(M)
|
||||
to_chat(M, "<span class='notice'>You start dumping out [parent].</span>")
|
||||
@@ -281,7 +278,7 @@
|
||||
|
||||
/datum/component/storage/proc/set_locked(datum/source, new_state)
|
||||
locked = new_state
|
||||
if(locked)
|
||||
if(check_locked())
|
||||
close_all()
|
||||
|
||||
/datum/component/storage/proc/_process_numerical_display()
|
||||
@@ -456,8 +453,7 @@
|
||||
var/atom/A = parent
|
||||
var/atom/dump_destination = dest_object.get_dumping_location()
|
||||
if(A.Adjacent(M) && dump_destination && M.Adjacent(dump_destination))
|
||||
if(locked)
|
||||
to_chat(M, "<span class='warning'>[parent] seems to be locked!</span>")
|
||||
if(check_locked(null, M, TRUE))
|
||||
return FALSE
|
||||
if(dump_destination.storage_contents_dump_act(src, M))
|
||||
playsound(A, "rustle", 50, 1, -5)
|
||||
@@ -563,10 +559,9 @@
|
||||
var/atom/host = parent
|
||||
if(real_location == I.loc)
|
||||
return FALSE //Means the item is already in the storage item
|
||||
if(locked)
|
||||
if(check_locked(null, M, !stop_messages))
|
||||
if(M && !stop_messages)
|
||||
host.add_fingerprint(M)
|
||||
to_chat(M, "<span class='warning'>[host] seems to be locked!</span>")
|
||||
return FALSE
|
||||
if(real_location.contents.len >= max_items)
|
||||
if(!stop_messages)
|
||||
@@ -659,8 +654,10 @@
|
||||
/datum/component/storage/proc/on_check()
|
||||
return TRUE
|
||||
|
||||
/datum/component/storage/proc/check_locked()
|
||||
return locked
|
||||
/datum/component/storage/proc/check_locked(datum/source, mob/user, message = FALSE)
|
||||
. = locked
|
||||
if(message && . && user)
|
||||
to_chat(user, "<span class='warning'>[parent] seems to be locked!</span>")
|
||||
|
||||
/datum/component/storage/proc/signal_take_type(datum/source, type, atom/destination, amount = INFINITY, check_adjacent = FALSE, force = FALSE, mob/user, list/inserted)
|
||||
if(!force)
|
||||
@@ -720,9 +717,7 @@
|
||||
|
||||
if(A.loc == user)
|
||||
. = COMPONENT_NO_ATTACK_HAND
|
||||
if(locked)
|
||||
to_chat(user, "<span class='warning'>[parent] seems to be locked!</span>")
|
||||
else
|
||||
if(!check_locked(source, user, TRUE))
|
||||
show_to(user)
|
||||
A.do_jiggle()
|
||||
|
||||
@@ -747,8 +742,7 @@
|
||||
/datum/component/storage/proc/on_alt_click(datum/source, mob/user)
|
||||
if(!isliving(user) || !user.CanReach(parent))
|
||||
return
|
||||
if(locked)
|
||||
to_chat(user, "<span class='warning'>[parent] seems to be locked!</span>")
|
||||
if(check_locked(source, user, TRUE))
|
||||
return
|
||||
|
||||
var/atom/A = parent
|
||||
|
||||
@@ -364,15 +364,15 @@
|
||||
/datum/symptom/heal/plasma/CanHeal(datum/disease/advance/A)
|
||||
var/mob/living/M = A.affected_mob
|
||||
var/datum/gas_mixture/environment
|
||||
var/list/gases
|
||||
var/plasmamount
|
||||
|
||||
. = 0
|
||||
|
||||
if(M.loc)
|
||||
environment = M.loc.return_air()
|
||||
if(environment)
|
||||
gases = environment.gases
|
||||
if(gases["plasma"] && gases["plasma"][MOLES] > gases["plasma"][GAS_META][META_GAS_MOLES_VISIBLE]) //if there's enough plasma in the air to see
|
||||
plasmamount = environment.gases[/datum/gas/plasma]
|
||||
if(plasmamount && plasmamount > GLOB.meta_gas_visibility[/datum/gas/plasma]) //if there's enough plasma in the air to see
|
||||
. += power * 0.5
|
||||
if(M.reagents.has_reagent("plasma"))
|
||||
. += power * 0.75
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
/datum/ert/amber
|
||||
code = "Amber"
|
||||
leader_role = /datum/antagonist/ert/commander/red
|
||||
roles = list(/datum/antagonist/ert/security/red, /datum/antagonist/ert/medic/red, /datum/antagonist/ert/engineer/red)
|
||||
|
||||
/datum/ert/red
|
||||
leader_role = /datum/antagonist/ert/commander/red
|
||||
|
||||
@@ -103,11 +103,11 @@
|
||||
// Can most things breathe?
|
||||
if(trace_gases)
|
||||
continue
|
||||
if(!(A_gases[/datum/gas/oxygen] && A_gases[/datum/gas/oxygen][MOLES] >= 16))
|
||||
if(A_gases[/datum/gas/oxygen] >= 16)
|
||||
continue
|
||||
if(A_gases[/datum/gas/plasma])
|
||||
continue
|
||||
if(A_gases[/datum/gas/carbon_dioxide] && A_gases[/datum/gas/carbon_dioxide][MOLES] >= 10)
|
||||
if(A_gases[/datum/gas/carbon_dioxide] >= 10)
|
||||
continue
|
||||
|
||||
// Aim for goldilocks temperatures and pressure
|
||||
|
||||
@@ -191,3 +191,18 @@
|
||||
heat_protection = HANDS
|
||||
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
|
||||
resistance_flags = NONE
|
||||
|
||||
/obj/item/clothing/gloves/krav_maga/combatglovesplus
|
||||
name = "combat gloves plus"
|
||||
desc = "These tactical gloves are fireproof and shock resistant, and using nanochip technology it teaches you the powers of krav maga."
|
||||
icon_state = "black"
|
||||
item_state = "blackglovesplus"
|
||||
siemens_coefficient = 0
|
||||
permeability_coefficient = 0.05
|
||||
strip_delay = 80
|
||||
cold_protection = HANDS
|
||||
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
|
||||
heat_protection = HANDS
|
||||
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
|
||||
resistance_flags = NONE
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 50)
|
||||
|
||||
@@ -93,3 +93,12 @@
|
||||
gain_text = "<span class='notice'>You feel more prudish.</span>"
|
||||
lose_text = "<span class='notice'>You don't feel as prudish as before.</span>"
|
||||
medical_record_text = "Patient exhibits a special gene that makes them immune to Crocin and Hexacrocin."
|
||||
|
||||
/datum/quirk/assblastusa
|
||||
name = "Buns of Steel"
|
||||
desc = "You've never skipped ass day. With this trait, you are completely immune to all forms of ass slapping and anyone who tries to slap your rock hard ass usually gets a broken hand."
|
||||
mob_trait = TRAIT_ASSBLASTUSA
|
||||
value = 0
|
||||
medical_record_text = "Patient never skipped ass day."
|
||||
gain_text = "<span class='notice'>Your ass rivals those of golems.</span>"
|
||||
lose_text = "<span class='notice'>Your butt feels more squishy and slappable.</span>"
|
||||
@@ -131,7 +131,7 @@ Credit where due:
|
||||
config_tag = "clockwork_cult"
|
||||
antag_flag = ROLE_SERVANT_OF_RATVAR
|
||||
false_report_weight = 10
|
||||
required_players = 30
|
||||
required_players = 35
|
||||
required_enemies = 3
|
||||
recommended_enemies = 5
|
||||
enemy_minimum_age = 7
|
||||
|
||||
@@ -62,5 +62,6 @@
|
||||
/datum/outfit/syndicate/clownop/leader
|
||||
name = "Clown Operative Leader - Basic"
|
||||
id = /obj/item/card/id/syndicate/nuke_leader
|
||||
gloves = /obj/item/clothing/gloves/krav_maga/combatglovesplus
|
||||
r_hand = /obj/item/nuclear_challenge/clownops
|
||||
command_radio = TRUE
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
/datum/outfit/syndicate/leader
|
||||
name = "Syndicate Leader - Basic"
|
||||
id = /obj/item/card/id/syndicate/nuke_leader
|
||||
gloves = /obj/item/clothing/gloves/krav_maga/combatglovesplus
|
||||
r_hand = /obj/item/nuclear_challenge
|
||||
command_radio = TRUE
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
/datum/objective_item/steal/plasma/check_special_completion(obj/item/tank/T)
|
||||
var/target_amount = text2num(name)
|
||||
var/found_amount = 0
|
||||
found_amount += T.air_contents.gases[/datum/gas/plasma] ? T.air_contents.gases[/datum/gas/plasma][MOLES] : 0
|
||||
found_amount += T.air_contents.gases[/datum/gas/plasma]
|
||||
return found_amount>=target_amount
|
||||
|
||||
|
||||
|
||||
@@ -80,9 +80,21 @@
|
||||
|
||||
/obj/machinery/computer/atmos_alert/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
var/overlay_state = icon_screen
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
if(priority_alarms.len)
|
||||
overlay_state = "alert:2"
|
||||
add_overlay("alert:2")
|
||||
else if(minor_alarms.len)
|
||||
overlay_state = "alert:1"
|
||||
add_overlay("alert:1")
|
||||
else
|
||||
overlay_state = "alert:0"
|
||||
add_overlay("alert:0")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
|
||||
@@ -59,8 +59,8 @@
|
||||
var/total_moles = air_sample.total_moles()
|
||||
if(total_moles)
|
||||
for(var/gas_id in air_sample.gases)
|
||||
var/gas_name = air_sample.gases[gas_id][GAS_META][META_GAS_NAME]
|
||||
signal.data["gases"][gas_name] = air_sample.gases[gas_id][MOLES] / total_moles * 100
|
||||
var/gas_name = GLOB.meta_gas_names[gas_id]
|
||||
signal.data["gases"][gas_name] = air_sample.gases[gas_id] / total_moles * 100
|
||||
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
|
||||
@@ -103,7 +103,9 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
if(data_by_z["[z]"] && last_update["[z]"] && world.time <= last_update["[z]"] + SENSORS_UPDATE_PERIOD)
|
||||
return data_by_z["[z]"]
|
||||
|
||||
var/list/results = list()
|
||||
var/list/results_damaged = list()
|
||||
var/list/results_undamaged = list()
|
||||
|
||||
var/obj/item/clothing/under/U
|
||||
var/obj/item/card/id/I
|
||||
var/turf/pos
|
||||
@@ -114,6 +116,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
var/toxdam
|
||||
var/burndam
|
||||
var/brutedam
|
||||
var/totaldam
|
||||
var/area
|
||||
var/pos_x
|
||||
var/pos_y
|
||||
@@ -157,11 +160,13 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
toxdam = round(H.getToxLoss(),1)
|
||||
burndam = round(H.getFireLoss(),1)
|
||||
brutedam = round(H.getBruteLoss(),1)
|
||||
totaldam = oxydam + toxdam + burndam + brutedam
|
||||
else
|
||||
oxydam = null
|
||||
toxdam = null
|
||||
burndam = null
|
||||
brutedam = null
|
||||
totaldam = 0
|
||||
|
||||
if (nanite_sensors || U.sensor_mode >= SENSOR_COORDS)
|
||||
if (!pos)
|
||||
@@ -174,16 +179,26 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
pos_x = null
|
||||
pos_y = null
|
||||
|
||||
results[++results.len] = list("name" = name, "assignment" = assignment, "ijob" = ijob, "life_status" = life_status, "oxydam" = oxydam, "toxdam" = toxdam, "burndam" = burndam, "brutedam" = brutedam, "area" = area, "pos_x" = pos_x, "pos_y" = pos_y, "can_track" = H.can_track(null))
|
||||
var/total_list = list("name" = name, "assignment" = assignment, "ijob" = ijob, "life_status" = life_status, "oxydam" = oxydam, "toxdam" = toxdam, "burndam" = burndam, "brutedam" = brutedam, "totaldam" = totaldam, "area" = area, "pos_x" = pos_x, "pos_y" = pos_y, "can_track" = H.can_track(null))
|
||||
|
||||
data_by_z["[z]"] = sortTim(results,/proc/sensor_compare)
|
||||
if(totaldam)
|
||||
results_damaged[++results_damaged.len] = total_list
|
||||
else
|
||||
results_undamaged[++results_undamaged.len] = total_list
|
||||
|
||||
var/list/returning = sortTim(results_damaged,/proc/damage_compare) + sortTim(results_undamaged,/proc/ijob_compare)
|
||||
|
||||
data_by_z["[z]"] = returning
|
||||
last_update["[z]"] = world.time
|
||||
|
||||
return results
|
||||
return returning
|
||||
|
||||
/proc/sensor_compare(list/a,list/b)
|
||||
/proc/ijob_compare(list/a,list/b)
|
||||
return a["ijob"] - b["ijob"]
|
||||
|
||||
/proc/damage_compare(list/a,list/b)
|
||||
return b["totaldam"] - a["totaldam"]
|
||||
|
||||
/datum/crewmonitor/ui_act(action,params)
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
if(!istype(AI))
|
||||
|
||||
@@ -76,12 +76,23 @@
|
||||
|
||||
/obj/machinery/computer/station_alert/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
var/overlay_state = icon_screen
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
var/active_alarms = FALSE
|
||||
for(var/cat in alarms)
|
||||
var/list/L = alarms[cat]
|
||||
if(L.len)
|
||||
active_alarms = TRUE
|
||||
if(active_alarms)
|
||||
overlay_state = "alert:2"
|
||||
add_overlay("alert:2")
|
||||
else
|
||||
overlay_state = "alert:0"
|
||||
add_overlay("alert:0")
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
|
||||
@@ -421,14 +421,13 @@
|
||||
if(!istype(T))
|
||||
return
|
||||
var/datum/gas_mixture/GM = new
|
||||
GM.add_gas(/datum/gas/plasma)
|
||||
if(prob(10))
|
||||
GM.gases[/datum/gas/plasma][MOLES] += 100
|
||||
GM.gases[/datum/gas/plasma] += 100
|
||||
GM.temperature = 1500+T0C //should be enough to start a fire
|
||||
T.visible_message("[src] suddenly disgorges a cloud of heated plasma.")
|
||||
qdel(src)
|
||||
else
|
||||
GM.gases[/datum/gas/plasma][MOLES] += 5
|
||||
GM.gases[/datum/gas/plasma] += 5
|
||||
GM.temperature = istype(T) ? T.air.return_temperature() : T20C
|
||||
T.visible_message("[src] suddenly disgorges a cloud of plasma.")
|
||||
T.assume_air(GM)
|
||||
|
||||
@@ -237,9 +237,8 @@
|
||||
cabin_air = new
|
||||
cabin_air.temperature = T20C
|
||||
cabin_air.volume = 200
|
||||
cabin_air.add_gases(/datum/gas/oxygen, /datum/gas/nitrogen)
|
||||
cabin_air.gases[/datum/gas/oxygen][MOLES] = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
|
||||
cabin_air.gases[/datum/gas/nitrogen][MOLES] = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
|
||||
cabin_air.gases[/datum/gas/oxygen] = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
|
||||
cabin_air.gases[/datum/gas/nitrogen] = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
|
||||
return cabin_air
|
||||
|
||||
/obj/mecha/proc/add_radio()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "Graffiti. Damn kids."
|
||||
icon = 'icons/effects/crayondecal.dmi'
|
||||
icon_state = "rune1"
|
||||
plane = GAME_PLANE //makes the graffiti visible over a wall.
|
||||
gender = NEUTER
|
||||
mergeable_decal = FALSE
|
||||
var/do_icon_rotate = TRUE
|
||||
|
||||
@@ -1,347 +1,347 @@
|
||||
// Foam
|
||||
// Similar to smoke, but slower and mobs absorb its reagent through their exposed skin.
|
||||
#define ALUMINUM_FOAM 1
|
||||
#define IRON_FOAM 2
|
||||
#define RESIN_FOAM 3
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam
|
||||
name = "foam"
|
||||
icon_state = "foam"
|
||||
opacity = 0
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
layer = EDGED_TURF_LAYER
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
var/amount = 3
|
||||
animate_movement = 0
|
||||
var/metal = 0
|
||||
var/lifetime = 40
|
||||
var/reagent_divisor = 7
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(
|
||||
/turf/open/space/transit,
|
||||
/turf/open/chasm,
|
||||
/turf/open/lava))
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting
|
||||
name = "firefighting foam"
|
||||
lifetime = 20 //doesn't last as long as normal foam
|
||||
amount = 0 //no spread
|
||||
var/absorbed_plasma = 0
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/MakeSlippery()
|
||||
return
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/process()
|
||||
..()
|
||||
|
||||
var/turf/open/T = get_turf(src)
|
||||
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
|
||||
if(hotspot && istype(T) && T.air)
|
||||
qdel(hotspot)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
var/plas_amt = min(30,G.gases[/datum/gas/plasma][MOLES]) //Absorb some plasma
|
||||
G.gases[/datum/gas/plasma][MOLES] -= plas_amt
|
||||
absorbed_plasma += plas_amt
|
||||
if(G.temperature > T20C)
|
||||
G.temperature = max(G.temperature/2,T20C)
|
||||
G.garbage_collect()
|
||||
T.air_update_turf()
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/kill_foam()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
|
||||
if(absorbed_plasma)
|
||||
var/obj/effect/decal/cleanable/plasma/P = (locate(/obj/effect/decal/cleanable/plasma) in get_turf(src))
|
||||
if(!P)
|
||||
P = new(loc)
|
||||
P.reagents.add_reagent("stable_plasma", absorbed_plasma)
|
||||
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/foam_mob(mob/living/L)
|
||||
if(!istype(L))
|
||||
return
|
||||
L.adjust_fire_stacks(-2)
|
||||
L.ExtinguishMob()
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
/obj/effect/particle_effect/foam/metal
|
||||
name = "aluminium foam"
|
||||
metal = ALUMINUM_FOAM
|
||||
icon_state = "mfoam"
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/MakeSlippery()
|
||||
return
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/smart
|
||||
name = "smart foam"
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/iron
|
||||
name = "iron foam"
|
||||
metal = IRON_FOAM
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/resin
|
||||
name = "resin foam"
|
||||
metal = RESIN_FOAM
|
||||
|
||||
/obj/effect/particle_effect/foam/long_life
|
||||
lifetime = 150
|
||||
|
||||
/obj/effect/particle_effect/foam/Initialize()
|
||||
. = ..()
|
||||
MakeSlippery()
|
||||
create_reagents(1000) //limited by the size of the reagent holder anyway.
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3)
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/MakeSlippery()
|
||||
AddComponent(/datum/component/slippery, 100)
|
||||
|
||||
/obj/effect/particle_effect/foam/Destroy()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/kill_foam()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
switch(metal)
|
||||
if(ALUMINUM_FOAM)
|
||||
new /obj/structure/foamedmetal(get_turf(src))
|
||||
if(IRON_FOAM)
|
||||
new /obj/structure/foamedmetal/iron(get_turf(src))
|
||||
if(RESIN_FOAM)
|
||||
new /obj/structure/foamedmetal/resin(get_turf(src))
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/smart/kill_foam() //Smart foam adheres to area borders for walls
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
if(metal)
|
||||
var/turf/T = get_turf(src)
|
||||
if(isspaceturf(T)) //Block up any exposed space
|
||||
T.PlaceOnTop(/turf/open/floor/plating/foam)
|
||||
for(var/direction in GLOB.cardinals)
|
||||
var/turf/cardinal_turf = get_step(T, direction)
|
||||
if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf!
|
||||
new/obj/structure/foamedmetal(T)
|
||||
break
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/process()
|
||||
lifetime--
|
||||
if(lifetime < 1)
|
||||
kill_foam()
|
||||
return
|
||||
|
||||
var/fraction = 1/initial(reagent_divisor)
|
||||
for(var/obj/O in range(0,src))
|
||||
if(O.type == src.type)
|
||||
continue
|
||||
if(isturf(O.loc))
|
||||
var/turf/T = O.loc
|
||||
if(T.intact && O.level == 1) //hidden under the floor
|
||||
continue
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.reaction(O, VAPOR, fraction)
|
||||
var/hit = 0
|
||||
for(var/mob/living/L in range(0,src))
|
||||
hit += foam_mob(L)
|
||||
if(hit)
|
||||
lifetime++ //this is so the decrease from mobs hit and the natural decrease don't cumulate.
|
||||
var/T = get_turf(src)
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.reaction(T, VAPOR, fraction)
|
||||
|
||||
if(--amount < 0)
|
||||
return
|
||||
spread_foam()
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/foam_mob(mob/living/L)
|
||||
if(lifetime<1)
|
||||
return 0
|
||||
if(!istype(L))
|
||||
return 0
|
||||
var/fraction = 1/initial(reagent_divisor)
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.reaction(L, VAPOR, fraction)
|
||||
lifetime--
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/spread_foam()
|
||||
var/turf/t_loc = get_turf(src)
|
||||
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
|
||||
var/obj/effect/particle_effect/foam/foundfoam = locate() in T //Don't spread foam where there's already foam!
|
||||
if(foundfoam)
|
||||
continue
|
||||
|
||||
if(is_type_in_typecache(T, blacklisted_turfs))
|
||||
continue
|
||||
|
||||
for(var/mob/living/L in T)
|
||||
foam_mob(L)
|
||||
var/obj/effect/particle_effect/foam/F = new src.type(T)
|
||||
F.amount = amount
|
||||
reagents.copy_to(F, (reagents.total_volume))
|
||||
F.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
F.metal = metal
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated
|
||||
kill_foam()
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
//FOAM EFFECT DATUM
|
||||
/datum/effect_system/foam_spread
|
||||
var/amount = 10 // the size of the foam spread.
|
||||
var/obj/chemholder
|
||||
effect_type = /obj/effect/particle_effect/foam
|
||||
var/metal = 0
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/metal
|
||||
effect_type = /obj/effect/particle_effect/foam/metal
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/metal/smart
|
||||
effect_type = /obj/effect/particle_effect/foam/smart
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/long
|
||||
effect_type = /obj/effect/particle_effect/foam/long_life
|
||||
|
||||
/datum/effect_system/foam_spread/New()
|
||||
..()
|
||||
chemholder = new /obj()
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
chemholder.reagents = R
|
||||
R.my_atom = chemholder
|
||||
|
||||
/datum/effect_system/foam_spread/Destroy()
|
||||
qdel(chemholder)
|
||||
chemholder = null
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/foam_spread/set_up(amt=5, loca, datum/reagents/carry = null)
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
|
||||
amount = round(sqrt(amt / 2), 1)
|
||||
carry.copy_to(chemholder, carry.total_volume)
|
||||
|
||||
/datum/effect_system/foam_spread/metal/set_up(amt=5, loca, datum/reagents/carry = null, metaltype)
|
||||
..()
|
||||
metal = metaltype
|
||||
|
||||
/datum/effect_system/foam_spread/start()
|
||||
var/obj/effect/particle_effect/foam/F = new effect_type(location)
|
||||
var/foamcolor = mix_color_from_reagents(chemholder.reagents.reagent_list)
|
||||
chemholder.reagents.copy_to(F, chemholder.reagents.total_volume/amount)
|
||||
F.add_atom_colour(foamcolor, FIXED_COLOUR_PRIORITY)
|
||||
F.amount = amount
|
||||
F.metal = metal
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// FOAM STRUCTURE. Formed by metal foams. Dense and opaque, but easy to break
|
||||
/obj/structure/foamedmetal
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "metalfoam"
|
||||
density = TRUE
|
||||
opacity = 1 // changed in New()
|
||||
anchored = TRUE
|
||||
layer = EDGED_TURF_LAYER
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
name = "foamed metal"
|
||||
desc = "A lightweight foamed metal wall."
|
||||
gender = PLURAL
|
||||
max_integrity = 20
|
||||
CanAtmosPass = ATMOS_PASS_DENSITY
|
||||
|
||||
/obj/structure/foamedmetal/Initialize()
|
||||
. = ..()
|
||||
air_update_turf(1)
|
||||
|
||||
/obj/structure/foamedmetal/Move()
|
||||
var/turf/T = loc
|
||||
. = ..()
|
||||
move_update_air(T)
|
||||
|
||||
/obj/structure/foamedmetal/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
|
||||
|
||||
/obj/structure/foamedmetal/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
to_chat(user, "<span class='warning'>You hit [src] but bounce off it!</span>")
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
|
||||
|
||||
/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target)
|
||||
return !density
|
||||
|
||||
/obj/structure/foamedmetal/iron
|
||||
max_integrity = 50
|
||||
icon_state = "ironfoam"
|
||||
|
||||
//Atmos Backpack Resin, transparent, prevents atmos and filters the air
|
||||
/obj/structure/foamedmetal/resin
|
||||
name = "\improper ATMOS Resin"
|
||||
desc = "A lightweight, transparent resin used to suffocate fires, scrub the air of toxins, and restore the air to a safe temperature."
|
||||
opacity = FALSE
|
||||
icon_state = "atmos_resin"
|
||||
alpha = 120
|
||||
max_integrity = 10
|
||||
|
||||
/obj/structure/foamedmetal/resin/Initialize()
|
||||
. = ..()
|
||||
if(isopenturf(loc))
|
||||
var/turf/open/O = loc
|
||||
O.ClearWet()
|
||||
if(O.air)
|
||||
var/datum/gas_mixture/G = O.air
|
||||
G.temperature = 293.15
|
||||
for(var/obj/effect/hotspot/H in O)
|
||||
qdel(H)
|
||||
var/list/G_gases = G.gases
|
||||
for(var/I in G_gases)
|
||||
if(I == /datum/gas/oxygen || I == /datum/gas/nitrogen)
|
||||
continue
|
||||
G_gases[I][MOLES] = 0
|
||||
G.garbage_collect()
|
||||
O.air_update_turf()
|
||||
for(var/obj/machinery/atmospherics/components/unary/U in O)
|
||||
if(!U.welded)
|
||||
U.welded = TRUE
|
||||
U.update_icon()
|
||||
U.visible_message("<span class='danger'>[U] sealed shut!</span>")
|
||||
for(var/mob/living/L in O)
|
||||
L.ExtinguishMob()
|
||||
for(var/obj/item/Item in O)
|
||||
Item.extinguish()
|
||||
|
||||
/obj/structure/foamedmetal/resin/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && (mover.pass_flags & PASSGLASS))
|
||||
return TRUE
|
||||
. = ..()
|
||||
|
||||
#undef ALUMINUM_FOAM
|
||||
#undef IRON_FOAM
|
||||
#undef RESIN_FOAM
|
||||
// Foam
|
||||
// Similar to smoke, but slower and mobs absorb its reagent through their exposed skin.
|
||||
#define ALUMINUM_FOAM 1
|
||||
#define IRON_FOAM 2
|
||||
#define RESIN_FOAM 3
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam
|
||||
name = "foam"
|
||||
icon_state = "foam"
|
||||
opacity = 0
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
layer = EDGED_TURF_LAYER
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
var/amount = 3
|
||||
animate_movement = 0
|
||||
var/metal = 0
|
||||
var/lifetime = 40
|
||||
var/reagent_divisor = 7
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(
|
||||
/turf/open/space/transit,
|
||||
/turf/open/chasm,
|
||||
/turf/open/lava))
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting
|
||||
name = "firefighting foam"
|
||||
lifetime = 20 //doesn't last as long as normal foam
|
||||
amount = 0 //no spread
|
||||
var/absorbed_plasma = 0
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/MakeSlippery()
|
||||
return
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/process()
|
||||
..()
|
||||
|
||||
var/turf/open/T = get_turf(src)
|
||||
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
|
||||
if(hotspot && istype(T) && T.air)
|
||||
qdel(hotspot)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
var/plas_amt = min(30,G.gases[/datum/gas/plasma]) //Absorb some plasma
|
||||
G.gases[/datum/gas/plasma] -= plas_amt
|
||||
absorbed_plasma += plas_amt
|
||||
if(G.temperature > T20C)
|
||||
G.temperature = max(G.temperature/2,T20C)
|
||||
GAS_GARBAGE_COLLECT(G.gases)
|
||||
T.air_update_turf()
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/kill_foam()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
|
||||
if(absorbed_plasma)
|
||||
var/obj/effect/decal/cleanable/plasma/P = (locate(/obj/effect/decal/cleanable/plasma) in get_turf(src))
|
||||
if(!P)
|
||||
P = new(loc)
|
||||
P.reagents.add_reagent("stable_plasma", absorbed_plasma)
|
||||
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/foam_mob(mob/living/L)
|
||||
if(!istype(L))
|
||||
return
|
||||
L.adjust_fire_stacks(-2)
|
||||
L.ExtinguishMob()
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
/obj/effect/particle_effect/foam/metal
|
||||
name = "aluminium foam"
|
||||
metal = ALUMINUM_FOAM
|
||||
icon_state = "mfoam"
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/MakeSlippery()
|
||||
return
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/smart
|
||||
name = "smart foam"
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/iron
|
||||
name = "iron foam"
|
||||
metal = IRON_FOAM
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/resin
|
||||
name = "resin foam"
|
||||
metal = RESIN_FOAM
|
||||
|
||||
/obj/effect/particle_effect/foam/long_life
|
||||
lifetime = 150
|
||||
|
||||
/obj/effect/particle_effect/foam/Initialize()
|
||||
. = ..()
|
||||
MakeSlippery()
|
||||
create_reagents(1000) //limited by the size of the reagent holder anyway.
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3)
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/MakeSlippery()
|
||||
AddComponent(/datum/component/slippery, 100)
|
||||
|
||||
/obj/effect/particle_effect/foam/Destroy()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/kill_foam()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
switch(metal)
|
||||
if(ALUMINUM_FOAM)
|
||||
new /obj/structure/foamedmetal(get_turf(src))
|
||||
if(IRON_FOAM)
|
||||
new /obj/structure/foamedmetal/iron(get_turf(src))
|
||||
if(RESIN_FOAM)
|
||||
new /obj/structure/foamedmetal/resin(get_turf(src))
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/smart/kill_foam() //Smart foam adheres to area borders for walls
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
if(metal)
|
||||
var/turf/T = get_turf(src)
|
||||
if(isspaceturf(T)) //Block up any exposed space
|
||||
T.PlaceOnTop(/turf/open/floor/plating/foam)
|
||||
for(var/direction in GLOB.cardinals)
|
||||
var/turf/cardinal_turf = get_step(T, direction)
|
||||
if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf!
|
||||
new/obj/structure/foamedmetal(T)
|
||||
break
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/process()
|
||||
lifetime--
|
||||
if(lifetime < 1)
|
||||
kill_foam()
|
||||
return
|
||||
|
||||
var/fraction = 1/initial(reagent_divisor)
|
||||
for(var/obj/O in range(0,src))
|
||||
if(O.type == src.type)
|
||||
continue
|
||||
if(isturf(O.loc))
|
||||
var/turf/T = O.loc
|
||||
if(T.intact && O.level == 1) //hidden under the floor
|
||||
continue
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.reaction(O, VAPOR, fraction)
|
||||
var/hit = 0
|
||||
for(var/mob/living/L in range(0,src))
|
||||
hit += foam_mob(L)
|
||||
if(hit)
|
||||
lifetime++ //this is so the decrease from mobs hit and the natural decrease don't cumulate.
|
||||
var/T = get_turf(src)
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.reaction(T, VAPOR, fraction)
|
||||
|
||||
if(--amount < 0)
|
||||
return
|
||||
spread_foam()
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/foam_mob(mob/living/L)
|
||||
if(lifetime<1)
|
||||
return 0
|
||||
if(!istype(L))
|
||||
return 0
|
||||
var/fraction = 1/initial(reagent_divisor)
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.reaction(L, VAPOR, fraction)
|
||||
lifetime--
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/spread_foam()
|
||||
var/turf/t_loc = get_turf(src)
|
||||
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
|
||||
var/obj/effect/particle_effect/foam/foundfoam = locate() in T //Don't spread foam where there's already foam!
|
||||
if(foundfoam)
|
||||
continue
|
||||
|
||||
if(is_type_in_typecache(T, blacklisted_turfs))
|
||||
continue
|
||||
|
||||
for(var/mob/living/L in T)
|
||||
foam_mob(L)
|
||||
var/obj/effect/particle_effect/foam/F = new src.type(T)
|
||||
F.amount = amount
|
||||
reagents.copy_to(F, (reagents.total_volume))
|
||||
F.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
F.metal = metal
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated
|
||||
kill_foam()
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
//FOAM EFFECT DATUM
|
||||
/datum/effect_system/foam_spread
|
||||
var/amount = 10 // the size of the foam spread.
|
||||
var/obj/chemholder
|
||||
effect_type = /obj/effect/particle_effect/foam
|
||||
var/metal = 0
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/metal
|
||||
effect_type = /obj/effect/particle_effect/foam/metal
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/metal/smart
|
||||
effect_type = /obj/effect/particle_effect/foam/smart
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/long
|
||||
effect_type = /obj/effect/particle_effect/foam/long_life
|
||||
|
||||
/datum/effect_system/foam_spread/New()
|
||||
..()
|
||||
chemholder = new /obj()
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
chemholder.reagents = R
|
||||
R.my_atom = chemholder
|
||||
|
||||
/datum/effect_system/foam_spread/Destroy()
|
||||
qdel(chemholder)
|
||||
chemholder = null
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/foam_spread/set_up(amt=5, loca, datum/reagents/carry = null)
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
|
||||
amount = round(sqrt(amt / 2), 1)
|
||||
carry.copy_to(chemholder, carry.total_volume)
|
||||
|
||||
/datum/effect_system/foam_spread/metal/set_up(amt=5, loca, datum/reagents/carry = null, metaltype)
|
||||
..()
|
||||
metal = metaltype
|
||||
|
||||
/datum/effect_system/foam_spread/start()
|
||||
var/obj/effect/particle_effect/foam/F = new effect_type(location)
|
||||
var/foamcolor = mix_color_from_reagents(chemholder.reagents.reagent_list)
|
||||
chemholder.reagents.copy_to(F, chemholder.reagents.total_volume/amount)
|
||||
F.add_atom_colour(foamcolor, FIXED_COLOUR_PRIORITY)
|
||||
F.amount = amount
|
||||
F.metal = metal
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// FOAM STRUCTURE. Formed by metal foams. Dense and opaque, but easy to break
|
||||
/obj/structure/foamedmetal
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "metalfoam"
|
||||
density = TRUE
|
||||
opacity = 1 // changed in New()
|
||||
anchored = TRUE
|
||||
layer = EDGED_TURF_LAYER
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
name = "foamed metal"
|
||||
desc = "A lightweight foamed metal wall."
|
||||
gender = PLURAL
|
||||
max_integrity = 20
|
||||
CanAtmosPass = ATMOS_PASS_DENSITY
|
||||
|
||||
/obj/structure/foamedmetal/Initialize()
|
||||
. = ..()
|
||||
air_update_turf(1)
|
||||
|
||||
/obj/structure/foamedmetal/Move()
|
||||
var/turf/T = loc
|
||||
. = ..()
|
||||
move_update_air(T)
|
||||
|
||||
/obj/structure/foamedmetal/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
|
||||
|
||||
/obj/structure/foamedmetal/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
to_chat(user, "<span class='warning'>You hit [src] but bounce off it!</span>")
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
|
||||
|
||||
/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target)
|
||||
return !density
|
||||
|
||||
/obj/structure/foamedmetal/iron
|
||||
max_integrity = 50
|
||||
icon_state = "ironfoam"
|
||||
|
||||
//Atmos Backpack Resin, transparent, prevents atmos and filters the air
|
||||
/obj/structure/foamedmetal/resin
|
||||
name = "\improper ATMOS Resin"
|
||||
desc = "A lightweight, transparent resin used to suffocate fires, scrub the air of toxins, and restore the air to a safe temperature."
|
||||
opacity = FALSE
|
||||
icon_state = "atmos_resin"
|
||||
alpha = 120
|
||||
max_integrity = 10
|
||||
|
||||
/obj/structure/foamedmetal/resin/Initialize()
|
||||
. = ..()
|
||||
if(isopenturf(loc))
|
||||
var/turf/open/O = loc
|
||||
O.ClearWet()
|
||||
if(O.air)
|
||||
var/datum/gas_mixture/G = O.air
|
||||
G.temperature = 293.15
|
||||
for(var/obj/effect/hotspot/H in O)
|
||||
qdel(H)
|
||||
var/list/G_gases = G.gases
|
||||
for(var/I in G_gases)
|
||||
if(I == /datum/gas/oxygen || I == /datum/gas/nitrogen)
|
||||
continue
|
||||
G_gases[I] = 0
|
||||
GAS_GARBAGE_COLLECT(G.gases)
|
||||
O.air_update_turf()
|
||||
for(var/obj/machinery/atmospherics/components/unary/U in O)
|
||||
if(!U.welded)
|
||||
U.welded = TRUE
|
||||
U.update_icon()
|
||||
U.visible_message("<span class='danger'>[U] sealed shut!</span>")
|
||||
for(var/mob/living/L in O)
|
||||
L.ExtinguishMob()
|
||||
for(var/obj/item/Item in O)
|
||||
Item.extinguish()
|
||||
|
||||
/obj/structure/foamedmetal/resin/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && (mover.pass_flags & PASSGLASS))
|
||||
return TRUE
|
||||
. = ..()
|
||||
|
||||
#undef ALUMINUM_FOAM
|
||||
#undef IRON_FOAM
|
||||
#undef RESIN_FOAM
|
||||
|
||||
@@ -1,329 +1,328 @@
|
||||
/////////////////////////////////////////////
|
||||
//// SMOKE SYSTEMS
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke
|
||||
name = "smoke"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "smoke"
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
opacity = 0
|
||||
layer = FLY_LAYER
|
||||
anchored = TRUE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
animate_movement = 0
|
||||
var/amount = 4
|
||||
var/lifetime = 5
|
||||
var/opaque = 1 //whether the smoke can block the view when in enough amount
|
||||
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/fade_out(frames = 16)
|
||||
if(alpha == 0) //Handle already transparent case
|
||||
return
|
||||
if(frames == 0)
|
||||
frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame".
|
||||
var/step = alpha / frames
|
||||
for(var/i = 0, i < frames, i++)
|
||||
alpha -= step
|
||||
if(alpha < 160)
|
||||
set_opacity(0) //if we were blocking view, we aren't now because we're fading out
|
||||
stoplag()
|
||||
|
||||
/obj/effect/particle_effect/smoke/Initialize()
|
||||
. = ..()
|
||||
create_reagents(500)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
|
||||
/obj/effect/particle_effect/smoke/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/kill_smoke()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
INVOKE_ASYNC(src, .proc/fade_out)
|
||||
QDEL_IN(src, 10)
|
||||
|
||||
/obj/effect/particle_effect/smoke/process()
|
||||
lifetime--
|
||||
if(lifetime < 1)
|
||||
kill_smoke()
|
||||
return 0
|
||||
for(var/mob/living/L in range(0,src))
|
||||
smoke_mob(L)
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/smoke_mob(mob/living/carbon/C)
|
||||
if(!istype(C))
|
||||
return 0
|
||||
if(lifetime<1)
|
||||
return 0
|
||||
if(C.internal != null || C.has_smoke_protection())
|
||||
return 0
|
||||
if(C.smoke_delay)
|
||||
return 0
|
||||
C.smoke_delay++
|
||||
addtimer(CALLBACK(src, .proc/remove_smoke_delay, C), 10)
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/remove_smoke_delay(mob/living/carbon/C)
|
||||
if(C)
|
||||
C.smoke_delay = 0
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/spread_smoke()
|
||||
var/turf/t_loc = get_turf(src)
|
||||
if(!t_loc)
|
||||
return
|
||||
var/list/newsmokes = list()
|
||||
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
|
||||
var/obj/effect/particle_effect/smoke/foundsmoke = locate() in T //Don't spread smoke where there's already smoke!
|
||||
if(foundsmoke)
|
||||
continue
|
||||
for(var/mob/living/L in T)
|
||||
smoke_mob(L)
|
||||
var/obj/effect/particle_effect/smoke/S = new type(T)
|
||||
reagents.copy_to(S, reagents.total_volume)
|
||||
S.setDir(pick(GLOB.cardinals))
|
||||
S.amount = amount-1
|
||||
S.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
S.lifetime = lifetime
|
||||
if(S.amount>0)
|
||||
if(opaque)
|
||||
S.set_opacity(TRUE)
|
||||
newsmokes.Add(S)
|
||||
|
||||
if(newsmokes.len)
|
||||
spawn(1) //the smoke spreads rapidly but not instantly
|
||||
for(var/obj/effect/particle_effect/smoke/SM in newsmokes)
|
||||
SM.spread_smoke()
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread
|
||||
var/amount = 10
|
||||
effect_type = /obj/effect/particle_effect/smoke
|
||||
|
||||
/datum/effect_system/smoke_spread/set_up(radius = 5, loca)
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
amount = radius
|
||||
|
||||
/datum/effect_system/smoke_spread/start()
|
||||
if(holder)
|
||||
location = get_turf(holder)
|
||||
var/obj/effect/particle_effect/smoke/S = new effect_type(location)
|
||||
S.amount = amount
|
||||
if(S.amount)
|
||||
S.spread_smoke()
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Bad smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/bad
|
||||
lifetime = 8
|
||||
|
||||
/obj/effect/particle_effect/smoke/bad/smoke_mob(mob/living/carbon/M)
|
||||
if(..())
|
||||
M.drop_all_held_items()
|
||||
M.adjustOxyLoss(1)
|
||||
M.emote("cough")
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/bad/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /obj/item/projectile/beam))
|
||||
var/obj/item/projectile/beam/B = mover
|
||||
B.damage = (B.damage/2)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread/bad
|
||||
effect_type = /obj/effect/particle_effect/smoke/bad
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Nanofrost smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/freezing
|
||||
name = "nanofrost smoke"
|
||||
color = "#B2FFFF"
|
||||
opaque = 0
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing
|
||||
effect_type = /obj/effect/particle_effect/smoke/freezing
|
||||
var/blast = 0
|
||||
var/temperature = 2
|
||||
var/weldvents = TRUE
|
||||
var/distcheck = TRUE
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/proc/Chilled(atom/A)
|
||||
if(isopenturf(A))
|
||||
var/turf/open/T = A
|
||||
if(T.air)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
if(!distcheck || get_dist(T, location) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air
|
||||
G.temperature = temperature
|
||||
T.air_update_turf()
|
||||
for(var/obj/effect/hotspot/H in T)
|
||||
qdel(H)
|
||||
var/list/G_gases = G.gases
|
||||
if(G_gases[/datum/gas/plasma])
|
||||
G.assert_gas(/datum/gas/nitrogen)
|
||||
G_gases[/datum/gas/nitrogen][MOLES] += (G_gases[/datum/gas/plasma][MOLES])
|
||||
G_gases[/datum/gas/plasma][MOLES] = 0
|
||||
G.garbage_collect()
|
||||
if (weldvents)
|
||||
for(var/obj/machinery/atmospherics/components/unary/U in T)
|
||||
if(!isnull(U.welded) && !U.welded) //must be an unwelded vent pump or vent scrubber.
|
||||
U.welded = TRUE
|
||||
U.update_icon()
|
||||
U.visible_message("<span class='danger'>[U] was frozen shut!</span>")
|
||||
for(var/mob/living/L in T)
|
||||
L.ExtinguishMob()
|
||||
for(var/obj/item/Item in T)
|
||||
Item.extinguish()
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/set_up(radius = 5, loca, blast_radius = 0)
|
||||
..()
|
||||
blast = blast_radius
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/start()
|
||||
if(blast)
|
||||
for(var/turf/T in RANGE_TURFS(blast, location))
|
||||
Chilled(T)
|
||||
..()
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/decon
|
||||
temperature = 293.15
|
||||
distcheck = FALSE
|
||||
weldvents = FALSE
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Sleep smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/sleeping
|
||||
color = "#9C3636"
|
||||
lifetime = 10
|
||||
|
||||
/obj/effect/particle_effect/smoke/sleeping/smoke_mob(mob/living/carbon/M)
|
||||
if(..())
|
||||
M.Sleeping(200)
|
||||
M.emote("cough")
|
||||
return 1
|
||||
|
||||
/datum/effect_system/smoke_spread/sleeping
|
||||
effect_type = /obj/effect/particle_effect/smoke/sleeping
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Chem smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem
|
||||
lifetime = 10
|
||||
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem/process()
|
||||
if(..())
|
||||
var/turf/T = get_turf(src)
|
||||
var/fraction = 1/initial(lifetime)
|
||||
for(var/atom/movable/AM in T)
|
||||
if(AM.type == src.type)
|
||||
continue
|
||||
if(T.intact && AM.level == 1) //hidden under the floor
|
||||
continue
|
||||
reagents.reaction(AM, TOUCH, fraction)
|
||||
|
||||
reagents.reaction(T, TOUCH, fraction)
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem/smoke_mob(mob/living/carbon/M)
|
||||
if(lifetime<1)
|
||||
return 0
|
||||
if(!istype(M))
|
||||
return 0
|
||||
var/mob/living/carbon/C = M
|
||||
if(C.internal != null || C.has_smoke_protection())
|
||||
return 0
|
||||
var/fraction = 1/initial(lifetime)
|
||||
reagents.copy_to(C, fraction*reagents.total_volume)
|
||||
reagents.reaction(M, INGEST, fraction)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread/chem
|
||||
var/obj/chemholder
|
||||
effect_type = /obj/effect/particle_effect/smoke/chem
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/New()
|
||||
..()
|
||||
chemholder = new /obj()
|
||||
var/datum/reagents/R = new/datum/reagents(500)
|
||||
chemholder.reagents = R
|
||||
R.my_atom = chemholder
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/Destroy()
|
||||
qdel(chemholder)
|
||||
chemholder = null
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, radius = 1, loca, silent = FALSE)
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
amount = radius
|
||||
carry.copy_to(chemholder, carry.total_volume)
|
||||
|
||||
if(!silent)
|
||||
var/contained = ""
|
||||
for(var/reagent in carry.reagent_list)
|
||||
contained += " [reagent] "
|
||||
if(contained)
|
||||
contained = "\[[contained]\]"
|
||||
|
||||
var/where = "[AREACOORD(location)]"
|
||||
if(carry.my_atom.fingerprintslast)
|
||||
var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
|
||||
var/more = ""
|
||||
if(M)
|
||||
more = "[ADMIN_LOOKUPFLW(M)] "
|
||||
message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. Key: [more ? more : carry.my_atom.fingerprintslast].")
|
||||
log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last touched by [carry.my_atom.fingerprintslast].")
|
||||
else
|
||||
message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. No associated key.")
|
||||
log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.")
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/start()
|
||||
var/mixcolor = mix_color_from_reagents(chemholder.reagents.reagent_list)
|
||||
if(holder)
|
||||
location = get_turf(holder)
|
||||
var/obj/effect/particle_effect/smoke/chem/S = new effect_type(location)
|
||||
|
||||
if(chemholder.reagents.total_volume > 1) // can't split 1 very well
|
||||
chemholder.reagents.copy_to(S, chemholder.reagents.total_volume)
|
||||
|
||||
if(mixcolor)
|
||||
S.add_atom_colour(mixcolor, FIXED_COLOUR_PRIORITY) // give the smoke color, if it has any to begin with
|
||||
S.amount = amount
|
||||
if(S.amount)
|
||||
S.spread_smoke() //calling process right now so the smoke immediately attacks mobs.
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Transparent smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
//Same as the base type, but the smoke produced is not opaque
|
||||
/datum/effect_system/smoke_spread/transparent
|
||||
effect_type = /obj/effect/particle_effect/smoke/transparent
|
||||
|
||||
/obj/effect/particle_effect/smoke/transparent
|
||||
opaque = FALSE
|
||||
/////////////////////////////////////////////
|
||||
//// SMOKE SYSTEMS
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke
|
||||
name = "smoke"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "smoke"
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
opacity = 0
|
||||
layer = FLY_LAYER
|
||||
anchored = TRUE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
animate_movement = 0
|
||||
var/amount = 4
|
||||
var/lifetime = 5
|
||||
var/opaque = 1 //whether the smoke can block the view when in enough amount
|
||||
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/fade_out(frames = 16)
|
||||
if(alpha == 0) //Handle already transparent case
|
||||
return
|
||||
if(frames == 0)
|
||||
frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame".
|
||||
var/step = alpha / frames
|
||||
for(var/i = 0, i < frames, i++)
|
||||
alpha -= step
|
||||
if(alpha < 160)
|
||||
set_opacity(0) //if we were blocking view, we aren't now because we're fading out
|
||||
stoplag()
|
||||
|
||||
/obj/effect/particle_effect/smoke/Initialize()
|
||||
. = ..()
|
||||
create_reagents(500)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
|
||||
/obj/effect/particle_effect/smoke/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/kill_smoke()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
INVOKE_ASYNC(src, .proc/fade_out)
|
||||
QDEL_IN(src, 10)
|
||||
|
||||
/obj/effect/particle_effect/smoke/process()
|
||||
lifetime--
|
||||
if(lifetime < 1)
|
||||
kill_smoke()
|
||||
return 0
|
||||
for(var/mob/living/L in range(0,src))
|
||||
smoke_mob(L)
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/smoke_mob(mob/living/carbon/C)
|
||||
if(!istype(C))
|
||||
return 0
|
||||
if(lifetime<1)
|
||||
return 0
|
||||
if(C.internal != null || C.has_smoke_protection())
|
||||
return 0
|
||||
if(C.smoke_delay)
|
||||
return 0
|
||||
C.smoke_delay++
|
||||
addtimer(CALLBACK(src, .proc/remove_smoke_delay, C), 10)
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/remove_smoke_delay(mob/living/carbon/C)
|
||||
if(C)
|
||||
C.smoke_delay = 0
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/spread_smoke()
|
||||
var/turf/t_loc = get_turf(src)
|
||||
if(!t_loc)
|
||||
return
|
||||
var/list/newsmokes = list()
|
||||
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
|
||||
var/obj/effect/particle_effect/smoke/foundsmoke = locate() in T //Don't spread smoke where there's already smoke!
|
||||
if(foundsmoke)
|
||||
continue
|
||||
for(var/mob/living/L in T)
|
||||
smoke_mob(L)
|
||||
var/obj/effect/particle_effect/smoke/S = new type(T)
|
||||
reagents.copy_to(S, reagents.total_volume)
|
||||
S.setDir(pick(GLOB.cardinals))
|
||||
S.amount = amount-1
|
||||
S.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
S.lifetime = lifetime
|
||||
if(S.amount>0)
|
||||
if(opaque)
|
||||
S.set_opacity(TRUE)
|
||||
newsmokes.Add(S)
|
||||
|
||||
if(newsmokes.len)
|
||||
spawn(1) //the smoke spreads rapidly but not instantly
|
||||
for(var/obj/effect/particle_effect/smoke/SM in newsmokes)
|
||||
SM.spread_smoke()
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread
|
||||
var/amount = 10
|
||||
effect_type = /obj/effect/particle_effect/smoke
|
||||
|
||||
/datum/effect_system/smoke_spread/set_up(radius = 5, loca)
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
amount = radius
|
||||
|
||||
/datum/effect_system/smoke_spread/start()
|
||||
if(holder)
|
||||
location = get_turf(holder)
|
||||
var/obj/effect/particle_effect/smoke/S = new effect_type(location)
|
||||
S.amount = amount
|
||||
if(S.amount)
|
||||
S.spread_smoke()
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Bad smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/bad
|
||||
lifetime = 8
|
||||
|
||||
/obj/effect/particle_effect/smoke/bad/smoke_mob(mob/living/carbon/M)
|
||||
if(..())
|
||||
M.drop_all_held_items()
|
||||
M.adjustOxyLoss(1)
|
||||
M.emote("cough")
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/bad/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /obj/item/projectile/beam))
|
||||
var/obj/item/projectile/beam/B = mover
|
||||
B.damage = (B.damage/2)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread/bad
|
||||
effect_type = /obj/effect/particle_effect/smoke/bad
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Nanofrost smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/freezing
|
||||
name = "nanofrost smoke"
|
||||
color = "#B2FFFF"
|
||||
opaque = 0
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing
|
||||
effect_type = /obj/effect/particle_effect/smoke/freezing
|
||||
var/blast = 0
|
||||
var/temperature = 2
|
||||
var/weldvents = TRUE
|
||||
var/distcheck = TRUE
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/proc/Chilled(atom/A)
|
||||
if(isopenturf(A))
|
||||
var/turf/open/T = A
|
||||
if(T.air)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
if(!distcheck || get_dist(T, location) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air
|
||||
G.temperature = temperature
|
||||
T.air_update_turf()
|
||||
for(var/obj/effect/hotspot/H in T)
|
||||
qdel(H)
|
||||
var/list/G_gases = G.gases
|
||||
if(G_gases[/datum/gas/plasma])
|
||||
G_gases[/datum/gas/nitrogen] += (G_gases[/datum/gas/plasma])
|
||||
G_gases[/datum/gas/plasma] = 0
|
||||
GAS_GARBAGE_COLLECT(G.gases)
|
||||
if (weldvents)
|
||||
for(var/obj/machinery/atmospherics/components/unary/U in T)
|
||||
if(!isnull(U.welded) && !U.welded) //must be an unwelded vent pump or vent scrubber.
|
||||
U.welded = TRUE
|
||||
U.update_icon()
|
||||
U.visible_message("<span class='danger'>[U] was frozen shut!</span>")
|
||||
for(var/mob/living/L in T)
|
||||
L.ExtinguishMob()
|
||||
for(var/obj/item/Item in T)
|
||||
Item.extinguish()
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/set_up(radius = 5, loca, blast_radius = 0)
|
||||
..()
|
||||
blast = blast_radius
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/start()
|
||||
if(blast)
|
||||
for(var/turf/T in RANGE_TURFS(blast, location))
|
||||
Chilled(T)
|
||||
..()
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/decon
|
||||
temperature = 293.15
|
||||
distcheck = FALSE
|
||||
weldvents = FALSE
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Sleep smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/sleeping
|
||||
color = "#9C3636"
|
||||
lifetime = 10
|
||||
|
||||
/obj/effect/particle_effect/smoke/sleeping/smoke_mob(mob/living/carbon/M)
|
||||
if(..())
|
||||
M.Sleeping(200)
|
||||
M.emote("cough")
|
||||
return 1
|
||||
|
||||
/datum/effect_system/smoke_spread/sleeping
|
||||
effect_type = /obj/effect/particle_effect/smoke/sleeping
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Chem smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem
|
||||
lifetime = 10
|
||||
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem/process()
|
||||
if(..())
|
||||
var/turf/T = get_turf(src)
|
||||
var/fraction = 1/initial(lifetime)
|
||||
for(var/atom/movable/AM in T)
|
||||
if(AM.type == src.type)
|
||||
continue
|
||||
if(T.intact && AM.level == 1) //hidden under the floor
|
||||
continue
|
||||
reagents.reaction(AM, TOUCH, fraction)
|
||||
|
||||
reagents.reaction(T, TOUCH, fraction)
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem/smoke_mob(mob/living/carbon/M)
|
||||
if(lifetime<1)
|
||||
return 0
|
||||
if(!istype(M))
|
||||
return 0
|
||||
var/mob/living/carbon/C = M
|
||||
if(C.internal != null || C.has_smoke_protection())
|
||||
return 0
|
||||
var/fraction = 1/initial(lifetime)
|
||||
reagents.copy_to(C, fraction*reagents.total_volume)
|
||||
reagents.reaction(M, INGEST, fraction)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread/chem
|
||||
var/obj/chemholder
|
||||
effect_type = /obj/effect/particle_effect/smoke/chem
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/New()
|
||||
..()
|
||||
chemholder = new /obj()
|
||||
var/datum/reagents/R = new/datum/reagents(500)
|
||||
chemholder.reagents = R
|
||||
R.my_atom = chemholder
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/Destroy()
|
||||
qdel(chemholder)
|
||||
chemholder = null
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, radius = 1, loca, silent = FALSE)
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
amount = radius
|
||||
carry.copy_to(chemholder, carry.total_volume)
|
||||
|
||||
if(!silent)
|
||||
var/contained = ""
|
||||
for(var/reagent in carry.reagent_list)
|
||||
contained += " [reagent] "
|
||||
if(contained)
|
||||
contained = "\[[contained]\]"
|
||||
|
||||
var/where = "[AREACOORD(location)]"
|
||||
if(carry.my_atom.fingerprintslast)
|
||||
var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
|
||||
var/more = ""
|
||||
if(M)
|
||||
more = "[ADMIN_LOOKUPFLW(M)] "
|
||||
message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. Key: [more ? more : carry.my_atom.fingerprintslast].")
|
||||
log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last touched by [carry.my_atom.fingerprintslast].")
|
||||
else
|
||||
message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. No associated key.")
|
||||
log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.")
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/start()
|
||||
var/mixcolor = mix_color_from_reagents(chemholder.reagents.reagent_list)
|
||||
if(holder)
|
||||
location = get_turf(holder)
|
||||
var/obj/effect/particle_effect/smoke/chem/S = new effect_type(location)
|
||||
|
||||
if(chemholder.reagents.total_volume > 1) // can't split 1 very well
|
||||
chemholder.reagents.copy_to(S, chemholder.reagents.total_volume)
|
||||
|
||||
if(mixcolor)
|
||||
S.add_atom_colour(mixcolor, FIXED_COLOUR_PRIORITY) // give the smoke color, if it has any to begin with
|
||||
S.amount = amount
|
||||
if(S.amount)
|
||||
S.spread_smoke() //calling process right now so the smoke immediately attacks mobs.
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Transparent smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
//Same as the base type, but the smoke produced is not opaque
|
||||
/datum/effect_system/smoke_spread/transparent
|
||||
effect_type = /obj/effect/particle_effect/smoke/transparent
|
||||
|
||||
/obj/effect/particle_effect/smoke/transparent
|
||||
opaque = FALSE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#define CELSIUS_TO_KELVIN(T_K) ((T_K) + T0C)
|
||||
|
||||
#define OPTIMAL_TEMP_K_PLA_BURN_SCALE(PRESSURE_P,PRESSURE_O,TEMP_O) (((PRESSURE_P) * GLOB.meta_gas_info[/datum/gas/plasma][META_GAS_SPECIFIC_HEAT]) / (((PRESSURE_P) * GLOB.meta_gas_info[/datum/gas/plasma][META_GAS_SPECIFIC_HEAT] + (PRESSURE_O) * GLOB.meta_gas_info[/datum/gas/oxygen][META_GAS_SPECIFIC_HEAT]) / PLASMA_UPPER_TEMPERATURE - (PRESSURE_O) * GLOB.meta_gas_info[/datum/gas/oxygen][META_GAS_SPECIFIC_HEAT] / CELSIUS_TO_KELVIN(TEMP_O)))
|
||||
#define OPTIMAL_TEMP_K_PLA_BURN_SCALE(PRESSURE_P,PRESSURE_O,TEMP_O) (((PRESSURE_P) * GLOB.meta_gas_specific_heats[/datum/gas/plasma]) / (((PRESSURE_P) * GLOB.meta_gas_specific_heats[/datum/gas/plasma] + (PRESSURE_O) * GLOB.meta_gas_specific_heats[/datum/gas/oxygen]) / PLASMA_UPPER_TEMPERATURE - (PRESSURE_O) * GLOB.meta_gas_specific_heats[/datum/gas/oxygen] / CELSIUS_TO_KELVIN(TEMP_O)))
|
||||
#define OPTIMAL_TEMP_K_PLA_BURN_RATIO(PRESSURE_P,PRESSURE_O,TEMP_O) (CELSIUS_TO_KELVIN(TEMP_O) * PLASMA_OXYGEN_FULLBURN * (PRESSURE_P) / (PRESSURE_O))
|
||||
|
||||
/obj/effect/spawner/newbomb
|
||||
@@ -19,12 +19,10 @@
|
||||
var/obj/item/tank/internals/plasma/PT = new(V)
|
||||
var/obj/item/tank/internals/oxygen/OT = new(V)
|
||||
|
||||
PT.air_contents.assert_gas(/datum/gas/plasma)
|
||||
PT.air_contents.gases[/datum/gas/plasma][MOLES] = pressure_p*PT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_p))
|
||||
PT.air_contents.gases[/datum/gas/plasma] = pressure_p*PT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_p))
|
||||
PT.air_contents.temperature = CELSIUS_TO_KELVIN(temp_p)
|
||||
|
||||
OT.air_contents.assert_gas(/datum/gas/oxygen)
|
||||
OT.air_contents.gases[/datum/gas/oxygen][MOLES] = pressure_o*OT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_o))
|
||||
OT.air_contents.gases[/datum/gas/oxygen] = pressure_o*OT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_o))
|
||||
OT.air_contents.temperature = CELSIUS_TO_KELVIN(temp_o)
|
||||
|
||||
V.tank_one = PT
|
||||
|
||||
@@ -449,7 +449,11 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
return 0
|
||||
|
||||
/obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user)
|
||||
|
||||
if(user.has_trait(TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='warning'>You don't want to harm [M]!</span>")
|
||||
return
|
||||
if(user.has_trait(TRAIT_CLUMSY) && prob(50))
|
||||
M = user
|
||||
var/is_human_victim = 0
|
||||
var/obj/item/bodypart/affecting = M.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(ishuman(M))
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
if(isturf(A))
|
||||
return
|
||||
if(istype(A,/obj/item/storage/lockbox))
|
||||
if(istype(A,/obj/item/storage/lockbox) || istype(A, /obj/item/storage/pod))
|
||||
A.emag_act(user)
|
||||
uses = max(uses - 1, 0)
|
||||
if(!uses)
|
||||
|
||||
@@ -248,9 +248,8 @@
|
||||
|
||||
/obj/effect/chrono_field/return_air() //we always have nominal air and temperature
|
||||
var/datum/gas_mixture/GM = new
|
||||
GM.add_gases(/datum/gas/oxygen, /datum/gas/nitrogen)
|
||||
GM.gases[/datum/gas/oxygen][MOLES] = MOLES_O2STANDARD
|
||||
GM.gases[/datum/gas/nitrogen][MOLES] = MOLES_N2STANDARD
|
||||
GM.gases[/datum/gas/oxygen] = MOLES_O2STANDARD
|
||||
GM.gases[/datum/gas/nitrogen] = MOLES_N2STANDARD
|
||||
GM.temperature = T20C
|
||||
return GM
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@
|
||||
var/pre_noise = FALSE
|
||||
var/post_noise = FALSE
|
||||
|
||||
var/datum/team/gang/gang //For marking territory.
|
||||
var/gang_tag_delay = 30 //this is the delay for gang mode tag applications on anything that gang = true on.
|
||||
|
||||
/obj/item/toy/crayon/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] is jamming [src] up [user.p_their()] nose and into [user.p_their()] brain. It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
@@ -288,6 +290,13 @@
|
||||
else if(drawing in numerals)
|
||||
temp = "number"
|
||||
|
||||
// If a gang member is using a gang spraycan, it'll behave differently
|
||||
var/gang_mode = FALSE
|
||||
if(gang && user.mind && user.mind.has_antag_datum(/datum/antagonist/gang)) //Heres a check.
|
||||
gang_mode = TRUE // No more runtimes if a non-gang member sprays a gang can, it just works like normal cans.
|
||||
// discontinue if the area isn't valid for tagging because gang "honour"
|
||||
if(gang_mode && (!can_claim_for_gang(user, target)))
|
||||
return
|
||||
|
||||
var/graf_rot
|
||||
if(drawing in oriented)
|
||||
@@ -310,20 +319,22 @@
|
||||
clicky = CLAMP(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)
|
||||
|
||||
if(!instant)
|
||||
to_chat(user, "<span class='notice'>You start drawing a [temp] on the [target.name]...</span>")
|
||||
to_chat(user, "<span class='notice'>You start drawing a [temp] on the [target.name]...</span>")
|
||||
|
||||
if(pre_noise)
|
||||
audible_message("<span class='notice'>You hear spraying.</span>")
|
||||
playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5)
|
||||
|
||||
var/takes_time = !instant
|
||||
var/takes_time = !instant //For order purposes, since I'm maximum bad.
|
||||
if(gang_mode)
|
||||
takes_time = TRUE
|
||||
|
||||
var/wait_time = 50
|
||||
if(paint_mode == PAINT_LARGE_HORIZONTAL)
|
||||
wait_time *= 3
|
||||
|
||||
if(takes_time)
|
||||
if(!do_after(user, 50, target = target))
|
||||
if(takes_time) //This is what deteremines the time it takes to spray a tag in gang mode. 50 is Default.
|
||||
if(!do_after(user, gang_tag_delay, target = target)) //25 is a good number, but we have gang_tag_delay var now.
|
||||
return
|
||||
|
||||
if(length(text_buffer))
|
||||
@@ -332,26 +343,34 @@
|
||||
|
||||
var/list/turf/affected_turfs = list()
|
||||
|
||||
|
||||
if(actually_paints)
|
||||
switch(paint_mode)
|
||||
if(PAINT_NORMAL)
|
||||
var/obj/effect/decal/cleanable/crayon/C = new(target, paint_color, drawing, temp, graf_rot)
|
||||
C.add_hiddenprint(user)
|
||||
C.pixel_x = clickx
|
||||
C.pixel_y = clicky
|
||||
affected_turfs += target
|
||||
if(PAINT_LARGE_HORIZONTAL)
|
||||
var/turf/left = locate(target.x-1,target.y,target.z)
|
||||
var/turf/right = locate(target.x+1,target.y,target.z)
|
||||
if(is_type_in_list(left, validSurfaces) && is_type_in_list(right, validSurfaces))
|
||||
var/obj/effect/decal/cleanable/crayon/C = new(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON)
|
||||
if(gang_mode)
|
||||
// Double check it wasn't tagged in the meanwhile.
|
||||
if(!can_claim_for_gang(user, target))
|
||||
return
|
||||
tag_for_gang(user, target)
|
||||
affected_turfs += target
|
||||
else
|
||||
switch(paint_mode)
|
||||
if(PAINT_NORMAL)
|
||||
var/obj/effect/decal/cleanable/crayon/C = new(target, paint_color, drawing, temp, graf_rot)
|
||||
C.add_hiddenprint(user)
|
||||
affected_turfs += left
|
||||
affected_turfs += right
|
||||
C.pixel_x = clickx
|
||||
C.pixel_y = clicky
|
||||
affected_turfs += target
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There isn't enough space to paint!</span>")
|
||||
return
|
||||
if(PAINT_LARGE_HORIZONTAL)
|
||||
var/turf/left = locate(target.x-1,target.y,target.z)
|
||||
var/turf/right = locate(target.x+1,target.y,target.z)
|
||||
if(is_type_in_list(left, validSurfaces) && is_type_in_list(right, validSurfaces))
|
||||
var/obj/effect/decal/cleanable/crayon/C = new(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON)
|
||||
C.add_hiddenprint(user)
|
||||
affected_turfs += left
|
||||
affected_turfs += right
|
||||
affected_turfs += target
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There isn't enough space to paint!</span>")
|
||||
return
|
||||
|
||||
if(!instant)
|
||||
to_chat(user, "<span class='notice'>You finish drawing \the [temp].</span>")
|
||||
@@ -373,6 +392,52 @@
|
||||
reagents.trans_to(t, ., volume_multiplier)
|
||||
check_empty(user)
|
||||
|
||||
|
||||
//////////////Gang mode stuff/////////////////
|
||||
/obj/item/toy/crayon/proc/can_claim_for_gang(mob/user, atom/target)
|
||||
// Check area validity.
|
||||
// Reject space, player-created areas, and non-station z-levels.
|
||||
var/area/A = get_area(target)
|
||||
if(!A || (!is_station_level(A.z)) || !A.valid_territory)
|
||||
to_chat(user, "<span class='warning'>[A] is unsuitable for tagging.</span>")
|
||||
return FALSE
|
||||
|
||||
var/spraying_over = FALSE
|
||||
for(var/G in target)
|
||||
var/obj/effect/decal/cleanable/crayon/gang/gangtag = G
|
||||
if(istype(gangtag))
|
||||
var/datum/antagonist/gang/GA = user.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
if(gangtag.gang != GA.gang)
|
||||
spraying_over = TRUE
|
||||
break
|
||||
|
||||
var/occupying_gang = territory_claimed(A, user)
|
||||
if(occupying_gang && !spraying_over)
|
||||
to_chat(user, "<span class='danger'>[A] has already been tagged by the [occupying_gang] gang! You must get rid of or spray over the old tag first!</span>")
|
||||
return FALSE
|
||||
|
||||
// If you pass the gauntlet of checks, you're good to proceed
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/crayon/proc/territory_claimed(area/territory, mob/user)
|
||||
for(var/datum/team/gang/G in GLOB.gangs)
|
||||
if(territory.type in (G.territories|G.new_territories))
|
||||
. = G.name
|
||||
break
|
||||
|
||||
/obj/item/toy/crayon/proc/tag_for_gang(mob/user, atom/target)
|
||||
//Delete any old markings on this tile, including other gang tags
|
||||
for(var/obj/effect/decal/cleanable/crayon/old_marking in target)
|
||||
qdel(old_marking)
|
||||
|
||||
var/datum/antagonist/gang/G = user.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
var/area/territory = get_area(target)
|
||||
|
||||
new /obj/effect/decal/cleanable/crayon/gang(target,G.gang,"graffiti",0,user) // Heres the gang tag.
|
||||
to_chat(user, "<span class='notice'>You tagged [territory] for your gang!</span>")
|
||||
/////////////////Gang end////////////////////
|
||||
|
||||
|
||||
/obj/item/toy/crayon/attack(mob/M, mob/user)
|
||||
if(edible && (M == user))
|
||||
to_chat(user, "You take a bite of the [src.name]. Delicious!")
|
||||
@@ -524,6 +589,7 @@
|
||||
is_capped = TRUE
|
||||
self_contained = FALSE // Don't disappear when they're empty
|
||||
can_change_colour = TRUE
|
||||
gang = TRUE //Gang check is true for all things upon the honored hierarchy of spraycans, except those that are FALSE.
|
||||
|
||||
validSurfaces = list(/turf/open/floor, /turf/closed/wall)
|
||||
reagent_contents = list("welding_fuel" = 1, "ethanol" = 1)
|
||||
@@ -669,6 +735,7 @@
|
||||
icon_capped = "deathcan2_cap"
|
||||
icon_uncapped = "deathcan2"
|
||||
use_overlays = FALSE
|
||||
gang = FALSE
|
||||
|
||||
volume_multiplier = 25
|
||||
charges = 100
|
||||
@@ -683,6 +750,7 @@
|
||||
icon_capped = "clowncan2_cap"
|
||||
icon_uncapped = "clowncan2"
|
||||
use_overlays = FALSE
|
||||
gang = FALSE
|
||||
|
||||
reagent_contents = list("lube" = 1, "banana" = 1)
|
||||
volume_multiplier = 5
|
||||
@@ -695,6 +763,7 @@
|
||||
icon_capped = "mimecan_cap"
|
||||
icon_uncapped = "mimecan"
|
||||
use_overlays = FALSE
|
||||
gang = FALSE
|
||||
|
||||
can_change_colour = FALSE
|
||||
paint_color = "#FFFFFF" //RGB
|
||||
@@ -703,6 +772,26 @@
|
||||
post_noise = FALSE
|
||||
reagent_contents = list("nothing" = 1, "mutetoxin" = 1)
|
||||
|
||||
/obj/item/toy/crayon/spraycan/gang
|
||||
charges = 20 // Charges back to 20, which is the default value for them.
|
||||
gang = TRUE
|
||||
gang_tag_delay = 15 //Its 50% faster than a regular spraycan, for tagging. After-all they did spend points/meet the boss.
|
||||
|
||||
pre_noise = FALSE
|
||||
post_noise = TRUE // Its even more stealthy just a tad.
|
||||
|
||||
/obj/item/toy/crayon/spraycan/gang/Initialize(loc, datum/team/gang/G)
|
||||
..()
|
||||
if(G)
|
||||
gang = G
|
||||
paint_color = G.color
|
||||
update_icon()
|
||||
|
||||
/obj/item/toy/crayon/spraycan/gang/examine(mob/user)
|
||||
. = ..()
|
||||
if(user.mind && user.mind.has_antag_datum(/datum/antagonist/gang) || isobserver(user))
|
||||
to_chat(user, "This spraycan has been specially modified with a stage 2 nozzle kit, making it faster.")
|
||||
|
||||
#undef RANDOM_GRAFFITI
|
||||
#undef RANDOM_LETTER
|
||||
#undef RANDOM_NUMBER
|
||||
|
||||
@@ -358,9 +358,9 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
|
||||
if (total_moles)
|
||||
for(var/id in env_gases)
|
||||
var/gas_level = env_gases[id][MOLES]/total_moles
|
||||
var/gas_level = env_gases[id]/total_moles
|
||||
if(gas_level > 0)
|
||||
dat += "[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_level*100, 0.01)]%<br>"
|
||||
dat += "[GLOB.meta_gas_names[id]]: [round(gas_level*100, 0.01)]%<br>"
|
||||
|
||||
dat += "Temperature: [round(environment.temperature-T0C)]°C<br>"
|
||||
dat += "<br>"
|
||||
|
||||
@@ -428,39 +428,38 @@ SLIME SCANNER
|
||||
if(total_moles)
|
||||
var/list/env_gases = environment.gases
|
||||
|
||||
environment.assert_gases(arglist(GLOB.hardcoded_gases))
|
||||
var/o2_concentration = env_gases[/datum/gas/oxygen][MOLES]/total_moles
|
||||
var/n2_concentration = env_gases[/datum/gas/nitrogen][MOLES]/total_moles
|
||||
var/co2_concentration = env_gases[/datum/gas/carbon_dioxide][MOLES]/total_moles
|
||||
var/plasma_concentration = env_gases[/datum/gas/plasma][MOLES]/total_moles
|
||||
var/o2_concentration = env_gases[/datum/gas/oxygen]/total_moles
|
||||
var/n2_concentration = env_gases[/datum/gas/nitrogen]/total_moles
|
||||
var/co2_concentration = env_gases[/datum/gas/carbon_dioxide]/total_moles
|
||||
var/plasma_concentration = env_gases[/datum/gas/plasma]/total_moles
|
||||
|
||||
if(abs(n2_concentration - N2STANDARD) < 20)
|
||||
to_chat(user, "<span class='info'>Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/nitrogen][MOLES], 0.01)] mol)</span>")
|
||||
to_chat(user, "<span class='info'>Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/nitrogen], 0.01)] mol)</span>")
|
||||
else
|
||||
to_chat(user, "<span class='alert'>Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/nitrogen][MOLES], 0.01)] mol)</span>")
|
||||
to_chat(user, "<span class='alert'>Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/nitrogen], 0.01)] mol)</span>")
|
||||
|
||||
if(abs(o2_concentration - O2STANDARD) < 2)
|
||||
to_chat(user, "<span class='info'>Oxygen: [round(o2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/oxygen][MOLES], 0.01)] mol)</span>")
|
||||
to_chat(user, "<span class='info'>Oxygen: [round(o2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/oxygen], 0.01)] mol)</span>")
|
||||
else
|
||||
to_chat(user, "<span class='alert'>Oxygen: [round(o2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/oxygen][MOLES], 0.01)] mol)</span>")
|
||||
to_chat(user, "<span class='alert'>Oxygen: [round(o2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/oxygen], 0.01)] mol)</span>")
|
||||
|
||||
if(co2_concentration > 0.01)
|
||||
to_chat(user, "<span class='alert'>CO2: [round(co2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/carbon_dioxide][MOLES], 0.01)] mol)</span>")
|
||||
to_chat(user, "<span class='alert'>CO2: [round(co2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/carbon_dioxide], 0.01)] mol)</span>")
|
||||
else
|
||||
to_chat(user, "<span class='info'>CO2: [round(co2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/carbon_dioxide][MOLES], 0.01)] mol)</span>")
|
||||
to_chat(user, "<span class='info'>CO2: [round(co2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/carbon_dioxide], 0.01)] mol)</span>")
|
||||
|
||||
if(plasma_concentration > 0.005)
|
||||
to_chat(user, "<span class='alert'>Plasma: [round(plasma_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/plasma][MOLES], 0.01)] mol)</span>")
|
||||
to_chat(user, "<span class='alert'>Plasma: [round(plasma_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/plasma], 0.01)] mol)</span>")
|
||||
else
|
||||
to_chat(user, "<span class='info'>Plasma: [round(plasma_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/plasma][MOLES], 0.01)] mol)</span>")
|
||||
to_chat(user, "<span class='info'>Plasma: [round(plasma_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/plasma], 0.01)] mol)</span>")
|
||||
|
||||
environment.garbage_collect()
|
||||
GAS_GARBAGE_COLLECT(environment.gases)
|
||||
|
||||
for(var/id in env_gases)
|
||||
if(id in GLOB.hardcoded_gases)
|
||||
continue
|
||||
var/gas_concentration = env_gases[id][MOLES]/total_moles
|
||||
to_chat(user, "<span class='alert'>[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_concentration*100, 0.01)] % ([round(env_gases[id][MOLES], 0.01)] mol)</span>")
|
||||
var/gas_concentration = env_gases[id]/total_moles
|
||||
to_chat(user, "<span class='alert'>[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(env_gases[id], 0.01)] mol)</span>")
|
||||
to_chat(user, "<span class='info'>Temperature: [round(environment.temperature-T0C, 0.01)] °C ([round(environment.temperature, 0.01)] K)</span>")
|
||||
|
||||
/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens
|
||||
@@ -550,8 +549,8 @@ SLIME SCANNER
|
||||
|
||||
var/list/cached_gases = air_contents.gases
|
||||
for(var/id in cached_gases)
|
||||
var/gas_concentration = cached_gases[id][MOLES]/total_moles
|
||||
to_chat(user, "<span class='notice'>[cached_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_concentration*100, 0.01)] % ([round(cached_gases[id][MOLES], 0.01)] mol)</span>")
|
||||
var/gas_concentration = cached_gases[id]/total_moles
|
||||
to_chat(user, "<span class='notice'>[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(cached_gases[id], 0.01)] mol)</span>")
|
||||
to_chat(user, "<span class='notice'>Temperature: [round(temperature - T0C,0.01)] °C ([round(temperature, 0.01)] K)</span>")
|
||||
|
||||
else
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
//Transfer 5% of current tank air contents to turf
|
||||
var/datum/gas_mixture/air_transfer = ptank.air_contents.remove_ratio(release_amount)
|
||||
if(air_transfer.gases[/datum/gas/plasma])
|
||||
air_transfer.gases[/datum/gas/plasma][MOLES] *= 5
|
||||
air_transfer.gases[/datum/gas/plasma] *= 5
|
||||
target.assume_air(air_transfer)
|
||||
//Burn it based on transfered gas
|
||||
target.hotspot_expose((ptank.air_contents.temperature*2) + 380,500)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/brainwashed))
|
||||
target.mind.remove_antag_datum(/datum/antagonist/brainwashed)
|
||||
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/rev/head) || target.mind.unconvertable)
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/rev/head) || target.mind.unconvertable || target.mind.has_antag_datum(/datum/antagonist/gang/boss))
|
||||
if(!silent)
|
||||
target.visible_message("<span class='warning'>[target] seems to resist the implant!</span>", "<span class='warning'>You feel something interfering with your mental conditioning, but you resist it!</span>")
|
||||
var/obj/item/implanter/I = loc
|
||||
@@ -38,9 +38,12 @@
|
||||
I.update_icon()
|
||||
return FALSE
|
||||
|
||||
var/datum/antagonist/gang/gang = target.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
var/datum/antagonist/rev/rev = target.mind.has_antag_datum(/datum/antagonist/rev)
|
||||
if(rev)
|
||||
rev.remove_revolutionary(FALSE, user)
|
||||
if(gang)
|
||||
target.mind.remove_antag_datum(/datum/antagonist/gang)
|
||||
if(!silent)
|
||||
if(target.mind in SSticker.mode.cult)
|
||||
to_chat(target, "<span class='warning'>You feel something interfering with your mental conditioning, but you resist it!</span>")
|
||||
|
||||
@@ -33,24 +33,8 @@
|
||||
/obj/item/implant/adrenalin/activate()
|
||||
. = ..()
|
||||
uses--
|
||||
imp_in.do_adrenaline(150, TRUE, 0, 0, TRUE, list("inaprovaline" = 3, "synaptizine" = 10, "omnizine" = 10, "stimulants" = 10), "<span class='boldnotice'>You feel a sudden surge of energy!</span>")
|
||||
to_chat(imp_in, "<span class='notice'>You feel a sudden surge of energy!</span>")
|
||||
imp_in.SetSleeping(0)
|
||||
imp_in.SetStun(0)
|
||||
imp_in.SetKnockdown(0)
|
||||
imp_in.SetUnconscious(0)
|
||||
imp_in.adjustStaminaLoss(-150)
|
||||
imp_in.stuttering = 0
|
||||
imp_in.updatehealth()
|
||||
imp_in.update_stamina()
|
||||
imp_in.resting = 0
|
||||
imp_in.lying = 0
|
||||
imp_in.update_canmove()
|
||||
|
||||
imp_in.reagents.add_reagent("inaprovaline", 3) //let's give another chance to dumb fucks who forget to breathe
|
||||
imp_in.reagents.add_reagent("synaptizine", 10)
|
||||
imp_in.reagents.add_reagent("omnizine", 10)
|
||||
imp_in.reagents.add_reagent("stimulants", 10)
|
||||
|
||||
if(!uses)
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -49,8 +49,6 @@
|
||||
forkload = null
|
||||
|
||||
else if(user.zone_selected == BODY_ZONE_PRECISE_EYES)
|
||||
if(user.has_trait(TRAIT_CLUMSY) && prob(50))
|
||||
M = user
|
||||
return eyestab(M,user)
|
||||
else
|
||||
return ..()
|
||||
@@ -79,8 +77,6 @@
|
||||
|
||||
/obj/item/kitchen/knife/attack(mob/living/carbon/M, mob/living/carbon/user)
|
||||
if(user.zone_selected == BODY_ZONE_PRECISE_EYES)
|
||||
if(user.has_trait(TRAIT_CLUMSY) && prob(50))
|
||||
M = user
|
||||
return eyestab(M,user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -283,7 +283,7 @@
|
||||
else
|
||||
var/turf/T = get_turf(src)
|
||||
if(!isspaceturf(T))
|
||||
consume_turf(T)
|
||||
shard.consume_turf(T)
|
||||
|
||||
/obj/item/melee/supermatter_sword/afterattack(target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
@@ -330,18 +330,7 @@
|
||||
else if(!isturf(target))
|
||||
shard.Bumped(target)
|
||||
else
|
||||
consume_turf(target)
|
||||
|
||||
/obj/item/melee/supermatter_sword/proc/consume_turf(turf/T)
|
||||
var/oldtype = T.type
|
||||
var/turf/newT = T.ScrapeAway()
|
||||
if(newT.type == oldtype)
|
||||
return
|
||||
playsound(T, 'sound/effects/supermatter.ogg', 50, 1)
|
||||
T.visible_message("<span class='danger'>[T] smacks into [src] and rapidly flashes to ash.</span>",\
|
||||
"<span class='italics'>You hear a loud crack as you are washed with a wave of heat.</span>")
|
||||
shard.Consume()
|
||||
T.CalculateAdjacentTurfs()
|
||||
shard.consume_turf(target)
|
||||
|
||||
/obj/item/melee/supermatter_sword/add_blood_DNA(list/blood_dna)
|
||||
return FALSE
|
||||
|
||||
@@ -591,10 +591,22 @@
|
||||
desc = "An adorable stuffed toy that resembles a slime. It is practically just a hacky sack."
|
||||
icon_state = "plushie_slime"
|
||||
item_state = "plushie_slime"
|
||||
attack_verb = list("blorbled", "slimed", "absorbed")
|
||||
attack_verb = list("blorbled", "slimed", "absorbed", "glomped")
|
||||
squeak_override = list('sound/effects/blobattack.ogg' = 1)
|
||||
gender = FEMALE //given all the jokes and drawings, I'm not sure the xenobiologists would make a slimeboy
|
||||
|
||||
/obj/item/toy/plush/slimeplushie/annie
|
||||
desc = "An adorable stuffed toy that resembles a slimey crewmember."
|
||||
icon_state = "annie"
|
||||
item_state = "annie"
|
||||
|
||||
/obj/item/toy/plush/slimeplushie/paxton
|
||||
desc = "An adorable stuffed toy that resembles a slimey crewmember."
|
||||
icon_state = "paxton"
|
||||
item_state = "paxton"
|
||||
attack_verb = list("CQC'd", "jabroni'd", "powergamed", "robusted", "cakehatted")
|
||||
gender = MALE
|
||||
|
||||
/obj/item/toy/plush/awakenedplushie
|
||||
name = "awakened plushie"
|
||||
desc = "An ancient plushie that has grown enlightened to the true nature of reality."
|
||||
@@ -635,6 +647,13 @@
|
||||
attack_verb = list("lit", "flickered", "flashed")
|
||||
squeak_override = list('sound/weapons/magout.ogg' = 1)
|
||||
|
||||
/obj/item/toy/plush/box
|
||||
name = "cardboard plushie"
|
||||
desc = "A toy box plushie, it holds cotten. Only a baddie would place a bomb through the postal system..."
|
||||
icon_state = "box"
|
||||
item_state = "box"
|
||||
attack_verb = list("open", "closed", "packed", "hidden", "rigged", "bombed", "sent", "gave")
|
||||
|
||||
/obj/item/toy/plush/borgplushie
|
||||
name = "robot plushie"
|
||||
desc = "An adorable stuffed toy of a robot."
|
||||
@@ -659,6 +678,12 @@
|
||||
icon_state = "neeb"
|
||||
item_state = "neeb"
|
||||
|
||||
/obj/item/toy/plush/borgplushie/bhijn
|
||||
desc = "An adorable stuffed toy of a IPC."
|
||||
icon_state = "bhijn"
|
||||
item_state = "bhijn"
|
||||
attack_verb = list("closed", "reworked", "merged")
|
||||
|
||||
/obj/item/toy/plush/bird
|
||||
name = "bird plushie"
|
||||
desc = "An adorable stuffed plushie that resembles an avian."
|
||||
@@ -728,6 +753,10 @@
|
||||
icon_state = "pavel"
|
||||
item_state = "pavel"
|
||||
|
||||
/obj/item/toy/plush/mammal/mason
|
||||
icon_state = "mason"
|
||||
item_state = "mason"
|
||||
|
||||
/obj/item/toy/plush/mammal/oten
|
||||
icon_state = "oten"
|
||||
item_state = "oten"
|
||||
@@ -736,6 +765,10 @@
|
||||
icon_state = "ray"
|
||||
item_state = "ray"
|
||||
|
||||
/obj/item/toy/plush/mammal/redtail
|
||||
icon_state = "redtail"
|
||||
item_state = "redtail"
|
||||
|
||||
/obj/item/toy/plush/mammal/dawud
|
||||
icon_state = "dawud"
|
||||
item_state = "dawud"
|
||||
@@ -743,6 +776,7 @@
|
||||
/obj/item/toy/plush/mammal/edgar
|
||||
icon_state = "edgar"
|
||||
item_state = "edgar"
|
||||
attack_verb = list("collared", "tricked", "headpatted")
|
||||
|
||||
/obj/item/toy/plush/mammal/frank
|
||||
icon_state = "frank"
|
||||
@@ -777,6 +811,16 @@
|
||||
icon_state = "zed"
|
||||
item_state = "zed"
|
||||
|
||||
/obj/item/toy/plush/mammal/justin
|
||||
icon_state = "justin"
|
||||
item_state = "justin"
|
||||
attack_verb = list("buttslapped", "fixed")
|
||||
|
||||
/obj/item/toy/plush/mammal/reece
|
||||
icon_state = "reece"
|
||||
item_state = "reece"
|
||||
attack_verb = list("healed", "cured", "demoted")
|
||||
|
||||
/obj/item/toy/plush/mammal/dog
|
||||
desc = "An adorable stuffed toy that resembles a canine."
|
||||
icon_state = "katlin"
|
||||
@@ -840,6 +884,12 @@
|
||||
icon_state = "drew"
|
||||
item_state = "drew"
|
||||
|
||||
/obj/item/toy/plush/catgirl/trilby
|
||||
desc = "A masked stuffed toy that resembles a feline scientist."
|
||||
icon_state = "trilby"
|
||||
item_state = "trilby"
|
||||
attack_verb = list("pred", "coded", "remembered")
|
||||
|
||||
/obj/item/toy/plush/catgirl/fermis
|
||||
name = "medcat plushie"
|
||||
desc = "An affectionate stuffed toy that resembles a certain medcat, comes complete with battery operated wagging tail!! You get the impression she's cheering you on to to find happiness and be kind to people."
|
||||
|
||||
@@ -153,3 +153,16 @@
|
||||
slot_flags = null
|
||||
to_chat(user, "<span class='notice'>[src] can now be concealed.</span>")
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/shield/makeshift
|
||||
name = "metal shield"
|
||||
desc = "A large shield made of wired and welded sheets of metal. The handle is made of cloth and leather making it unwieldy."
|
||||
armor = list("melee" = 25, "bullet" = 25, "laser" = 5, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 80)
|
||||
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
||||
item_state = "makeshift_shield"
|
||||
materials = list(MAT_METAL = 18000)
|
||||
slot_flags = null
|
||||
block_chance = 25
|
||||
force = 5
|
||||
throwforce = 7
|
||||
|
||||
@@ -252,7 +252,8 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
|
||||
new/datum/stack_recipe("bedsheet", /obj/item/bedsheet, 3), \
|
||||
new/datum/stack_recipe("empty sandbag", /obj/item/emptysandbag, 4), \
|
||||
null, \
|
||||
new/datum/stack_recipe("fingerless gloves", /obj/item/clothing/gloves/fingerless, 1), \
|
||||
new/datum/stack_recipe("fingerless gloves", /obj/item/clothing/gloves/fingerless, 1),\
|
||||
new/datum/stack_recipe("white gloves", /obj/item/clothing/gloves/color/white, 1),\
|
||||
new/datum/stack_recipe("black gloves", /obj/item/clothing/gloves/color/black, 3), \
|
||||
null, \
|
||||
new/datum/stack_recipe("blindfold", /obj/item/clothing/glasses/sunglasses/blindfold, 2), \
|
||||
@@ -281,16 +282,38 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
|
||||
*/
|
||||
GLOBAL_LIST_INIT(cardboard_recipes, list ( \
|
||||
new/datum/stack_recipe("box", /obj/item/storage/box), \
|
||||
new/datum/stack_recipe("sec box", /obj/item/storage/box/seclooking), \
|
||||
new/datum/stack_recipe("light tubes", /obj/item/storage/box/lights/tubes), \
|
||||
new/datum/stack_recipe("light bulbs", /obj/item/storage/box/lights/bulbs), \
|
||||
new/datum/stack_recipe("mouse traps", /obj/item/storage/box/mousetraps), \
|
||||
new/datum/stack_recipe("pizza box", /obj/item/pizzabox), \
|
||||
new/datum/stack_recipe("power cell", /obj/item/storage/box/cells), \
|
||||
new/datum/stack_recipe("02", /obj/item/storage/box/otwo), \
|
||||
null, \
|
||||
new/datum/stack_recipe("lethal ammo box", /obj/item/storage/box/lethalshot), \
|
||||
new/datum/stack_recipe("rubber shot ammo box", /obj/item/storage/box/rubbershot), \
|
||||
new/datum/stack_recipe("bean bag ammo box", /obj/item/storage/box/beanbag), \
|
||||
new/datum/stack_recipe("12g ammo box", /obj/item/storage/box/lethalslugs), \
|
||||
new/datum/stack_recipe("stun slug ammo box", /obj/item/storage/box/stunslug), \
|
||||
new/datum/stack_recipe("tech shell ammo box", /obj/item/storage/box/techsslug), \
|
||||
new/datum/stack_recipe("incendiary ammo box", /obj/item/storage/box/fireshot), \
|
||||
new/datum/stack_recipe("firing pins", /obj/item/storage/box/firingpins), \
|
||||
new/datum/stack_recipe("loose ammo", /obj/item/storage/box/ammoshells), \
|
||||
null, \
|
||||
new/datum/stack_recipe("cardborg suit", /obj/item/clothing/suit/cardborg, 3), \
|
||||
new/datum/stack_recipe("cardborg helmet", /obj/item/clothing/head/cardborg), \
|
||||
new/datum/stack_recipe("pizza box", /obj/item/pizzabox), \
|
||||
new/datum/stack_recipe("folder", /obj/item/folder), \
|
||||
new/datum/stack_recipe("large box", /obj/structure/closet/cardboard, 4), \
|
||||
new/datum/stack_recipe("cardboard cutout", /obj/item/cardboard_cutout, 5), \
|
||||
))
|
||||
null, \
|
||||
new/datum/stack_recipe("colored brown", /obj/item/storage/box/brown), \
|
||||
new/datum/stack_recipe("colored green", /obj/item/storage/box/green), \
|
||||
new/datum/stack_recipe("colored red", /obj/item/storage/box/blue), \
|
||||
new/datum/stack_recipe("colored blue", /obj/item/storage/box/red), \
|
||||
new/datum/stack_recipe("colored yellow", /obj/item/storage/box/yellow), \
|
||||
new/datum/stack_recipe("colored pink", /obj/item/storage/box/pink), \
|
||||
new/datum/stack_recipe("colored purple", /obj/item/storage/box/purple), \
|
||||
))
|
||||
|
||||
/obj/item/stack/sheet/cardboard //BubbleWrap //it's cardboard you fuck
|
||||
name = "cardboard"
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
STR.max_w_class = WEIGHT_CLASS_NORMAL
|
||||
STR.max_items = 21
|
||||
|
||||
|
||||
/*
|
||||
* Backpack Types
|
||||
*/
|
||||
@@ -244,6 +243,18 @@
|
||||
icon_state = "satchel-explorer"
|
||||
item_state = "securitypack"
|
||||
|
||||
/obj/item/storage/backpack/satchel/bone
|
||||
name = "bone satchel"
|
||||
desc = "A bone satchel fashend with watcher wings and large bones from goliath. Can be worn on the belt."
|
||||
icon = 'icons/obj/mining.dmi'
|
||||
icon_state = "goliath_saddle"
|
||||
slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT
|
||||
|
||||
/obj/item/storage/backpack/satchel/bone/ComponentInitialize()
|
||||
. = ..()
|
||||
GET_COMPONENT(STR, /datum/component/storage)
|
||||
STR.max_combined_w_class = 10
|
||||
|
||||
/obj/item/storage/backpack/satchel/cap
|
||||
name = "captain's satchel"
|
||||
desc = "An exclusive satchel for Nanotrasen officers."
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
* ID and security PDA cart boxes,
|
||||
* Handcuff, mousetrap, and pillbottle boxes,
|
||||
* Snap-pops and matchboxes,
|
||||
* Replacement light boxes.
|
||||
* Action Figure Boxes
|
||||
* Various paper bags.
|
||||
* Replacement light boxes,
|
||||
* Ammo types,
|
||||
* Action Figure Boxes,
|
||||
* Various paper bags,
|
||||
* Colored boxes
|
||||
*
|
||||
* For syndicate call-ins see uplink_kits.dm
|
||||
*/
|
||||
@@ -74,7 +76,6 @@
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
|
||||
//Disk boxes
|
||||
/obj/item/storage/box/disks
|
||||
name = "diskette box"
|
||||
@@ -84,7 +85,6 @@
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/disk/data(src)
|
||||
|
||||
|
||||
/obj/item/storage/box/disks_plantgene
|
||||
name = "plant data disks box"
|
||||
illustration = "disk_kit"
|
||||
@@ -117,7 +117,6 @@
|
||||
new /obj/item/crowbar/red(src)
|
||||
new /obj/item/reagent_containers/hypospray/medipen(src)
|
||||
|
||||
|
||||
// Engineer survival box
|
||||
/obj/item/storage/box/engineer/PopulateContents()
|
||||
new /obj/item/clothing/mask/breath(src)
|
||||
@@ -143,6 +142,29 @@
|
||||
..() // we want the regular stuff too
|
||||
new /obj/item/radio/off(src)
|
||||
|
||||
/obj/item/storage/box/seclooking
|
||||
icon_state = "secbox"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/cells
|
||||
name = "box of powercells"
|
||||
desc = "Contains powercells."
|
||||
illustration = "power_cell"
|
||||
|
||||
/obj/item/storage/box/ammoshells
|
||||
name = "box of loose ammo"
|
||||
desc = "Contains loose ammo."
|
||||
illustration = "loose_ammo"
|
||||
|
||||
/obj/item/storage/box/otwo
|
||||
name = "box of o2 supplies"
|
||||
desc = "Contains o2 supplies."
|
||||
illustration = "02"
|
||||
|
||||
/obj/item/storage/box/otwo/PopulateContents()
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/tank/internals/emergency_oxygen/engi(src)
|
||||
|
||||
/obj/item/storage/box/gloves
|
||||
name = "box of latex gloves"
|
||||
desc = "Contains sterile latex gloves."
|
||||
@@ -261,7 +283,6 @@
|
||||
new /obj/item/assembly/flash/handheld(src)
|
||||
new /obj/item/screwdriver(src)
|
||||
|
||||
|
||||
/obj/item/storage/box/teargas
|
||||
name = "box of tear gas grenades (WARNING)"
|
||||
desc = "<B>WARNING: These devices are extremely dangerous and can cause blindness and skin irritation.</B>"
|
||||
@@ -465,7 +486,7 @@
|
||||
/obj/item/storage/box/firingpins
|
||||
name = "box of standard firing pins"
|
||||
desc = "A box full of standard firing pins, to allow newly-developed firearms to operate."
|
||||
illustration = "id"
|
||||
illustration = "firing_pins"
|
||||
|
||||
/obj/item/storage/box/firingpins/PopulateContents()
|
||||
for(var/i in 1 to 5)
|
||||
@@ -474,7 +495,7 @@
|
||||
/obj/item/storage/box/lasertagpins
|
||||
name = "box of laser tag firing pins"
|
||||
desc = "A box full of laser tag firing pins, to allow newly-developed firearms to require wearing brightly coloured plastic armor before being able to be used."
|
||||
illustration = "id"
|
||||
illustration = "firing_pins"
|
||||
|
||||
/obj/item/storage/box/lasertagpins/PopulateContents()
|
||||
for(var/i in 1 to 3)
|
||||
@@ -615,7 +636,6 @@
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/light/bulb(src)
|
||||
|
||||
|
||||
/obj/item/storage/box/deputy
|
||||
name = "box of deputy armbands"
|
||||
desc = "To be issued to those authorized to act as deputy of security."
|
||||
@@ -721,6 +741,46 @@
|
||||
for(var/i in 1 to 6)
|
||||
new /obj/item/ammo_casing/shotgun/beanbag(src)
|
||||
|
||||
/obj/item/storage/box/lethalslugs
|
||||
name = "box of 12g shotgun slugs"
|
||||
desc = "A box full of lethal 12g slug, designed for riot shotguns."
|
||||
icon_state = "12g_box"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/lethalslugs/PopulateContents()
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/projectile/bullet/shotgun_slug(src)
|
||||
|
||||
/obj/item/storage/box/stunslug
|
||||
name = "box of stun slugs"
|
||||
desc = "A box full of stun 12g slugs."
|
||||
icon_state = "stunslug_box"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/stunslug/PopulateContents()
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/projectile/bullet/shotgun_stunslug(src)
|
||||
|
||||
/obj/item/storage/box/techsslug
|
||||
name = "box of tech shotgun shells"
|
||||
desc = "A box full of tech shotgun shells."
|
||||
icon_state = "techslug_box"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/techsslug/PopulateContents()
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/ammo_casing/shotgun/techshell(src)
|
||||
|
||||
/obj/item/storage/box/fireshot
|
||||
name = "box of incendiary ammo"
|
||||
desc = "A box full of tech incendiary ammo."
|
||||
icon_state = "fireshot_box"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/techsslug/PopulateContents()
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/ammo_casing/shotgun/incendiary(src)
|
||||
|
||||
/obj/item/storage/box/actionfigure
|
||||
name = "box of action figures"
|
||||
desc = "The latest set of collectable action figures."
|
||||
@@ -966,7 +1026,6 @@
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/reagent_containers/pill/patch/silver_sulf(src)
|
||||
|
||||
|
||||
/obj/item/storage/box/fountainpens
|
||||
name = "box of fountain pens"
|
||||
|
||||
@@ -1025,3 +1084,32 @@
|
||||
new /obj/item/stock_parts/matter_bin/bluespace(src)
|
||||
new /obj/item/stock_parts/matter_bin/bluespace(src)
|
||||
new /obj/item/stock_parts/matter_bin/bluespace(src)
|
||||
|
||||
//Colored boxes.
|
||||
/obj/item/storage/box/green
|
||||
icon_state = "box_green"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/blue
|
||||
icon_state = "box_blue"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/purple
|
||||
icon_state = "box_purple"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/red
|
||||
icon_state = "box_red"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/yellow
|
||||
icon_state = "box_yellow"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/brown
|
||||
icon_state = "box_brown"
|
||||
illustration = null
|
||||
|
||||
/obj/item/storage/box/pink
|
||||
icon_state = "box_pink"
|
||||
illustration = null
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define STUNBATON_CHARGE_LENIENCY 0.3
|
||||
|
||||
/obj/item/melee/baton
|
||||
name = "stunbaton"
|
||||
desc = "A stun baton for incapacitating people with."
|
||||
@@ -13,7 +15,7 @@
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
|
||||
|
||||
var/stunforce = 140
|
||||
var/status = 0
|
||||
var/status = FALSE
|
||||
var/obj/item/stock_parts/cell/cell
|
||||
var/hitcost = 1000
|
||||
var/throw_hit_chance = 35
|
||||
@@ -44,17 +46,30 @@
|
||||
/obj/item/melee/baton/loaded //this one starts with a cell pre-installed.
|
||||
preload_cell_type = /obj/item/stock_parts/cell/high
|
||||
|
||||
/obj/item/melee/baton/proc/deductcharge(chrgdeductamt)
|
||||
if(cell)
|
||||
//Note this value returned is significant, as it will determine
|
||||
//if a stun is applied or not
|
||||
. = cell.use(chrgdeductamt)
|
||||
if(status && cell.charge < hitcost)
|
||||
//we're below minimum, turn off
|
||||
status = 0
|
||||
update_icon()
|
||||
playsound(loc, "sparks", 75, 1, -1)
|
||||
/obj/item/melee/baton/proc/deductcharge(chrgdeductamt, chargecheck = TRUE)
|
||||
if(!cell)
|
||||
switch_status(FALSE, TRUE)
|
||||
return FALSE
|
||||
//Note this value returned is significant, as it will determine
|
||||
//if a stun is applied or not
|
||||
. = cell.use(chrgdeductamt)
|
||||
if(status && (!. || (chargecheck && cell.charge < hitcost * STUNBATON_CHARGE_LENIENCY)))
|
||||
//we're below minimum, turn off
|
||||
switch_status(FALSE)
|
||||
|
||||
/obj/item/melee/baton/proc/switch_status(new_status = FALSE, silent = FALSE)
|
||||
if(status != new_status)
|
||||
status = new_status
|
||||
if(!silent)
|
||||
playsound(loc, "sparks", 75, 1, -1)
|
||||
if(status)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
|
||||
/obj/item/melee/baton/process()
|
||||
deductcharge(hitcost * 0.004, FALSE)
|
||||
|
||||
/obj/item/melee/baton/update_icon()
|
||||
if(status)
|
||||
@@ -77,7 +92,7 @@
|
||||
if(cell)
|
||||
to_chat(user, "<span class='notice'>[src] already has a cell.</span>")
|
||||
else
|
||||
if(C.maxcharge < hitcost)
|
||||
if(C.maxcharge < hitcost * STUNBATON_CHARGE_LENIENCY)
|
||||
to_chat(user, "<span class='notice'>[src] requires a higher capacity cell.</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
@@ -92,31 +107,25 @@
|
||||
cell.forceMove(get_turf(src))
|
||||
cell = null
|
||||
to_chat(user, "<span class='notice'>You remove the cell from [src].</span>")
|
||||
status = 0
|
||||
update_icon()
|
||||
switch_status(FALSE, TRUE)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/baton/attack_self(mob/user)
|
||||
if(cell && cell.charge > hitcost)
|
||||
status = !status
|
||||
if(cell && cell.charge > hitcost * STUNBATON_CHARGE_LENIENCY)
|
||||
switch_status(!status)
|
||||
to_chat(user, "<span class='notice'>[src] is now [status ? "on" : "off"].</span>")
|
||||
playsound(loc, "sparks", 75, 1, -1)
|
||||
else
|
||||
status = 0
|
||||
switch_status(FALSE, TRUE)
|
||||
if(!cell)
|
||||
to_chat(user, "<span class='warning'>[src] does not have a power source!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] is out of charge.</span>")
|
||||
update_icon()
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user)
|
||||
if(status && user.has_trait(TRAIT_CLUMSY) && prob(50))
|
||||
user.visible_message("<span class='danger'>[user] accidentally hits [user.p_them()]self with [src]!</span>", \
|
||||
"<span class='userdanger'>You accidentally hit yourself with [src]!</span>")
|
||||
user.Knockdown(stunforce*3)
|
||||
deductcharge(hitcost)
|
||||
clowning_around(user)
|
||||
return
|
||||
|
||||
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT)//CIT CHANGE - makes it impossible to baton in stamina softcrit
|
||||
@@ -153,17 +162,21 @@
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
|
||||
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
return 0
|
||||
return FALSE
|
||||
var/stunpwr = stunforce
|
||||
if(iscyborg(loc))
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
if(!R || !R.cell || !R.cell.use(hitcost))
|
||||
return 0
|
||||
if(!istype(R) || !R.cell || !R.cell.use(hitcost))
|
||||
return FALSE
|
||||
else
|
||||
if(!deductcharge(hitcost))
|
||||
return 0
|
||||
var/stuncharge = cell.charge
|
||||
if(!deductcharge(hitcost, FALSE))
|
||||
stunpwr *= round(stuncharge/hitcost)
|
||||
if(stunpwr < stunforce * STUNBATON_CHARGE_LENIENCY)
|
||||
return FALSE
|
||||
|
||||
L.Knockdown(stunforce)
|
||||
L.adjustStaminaLoss(stunforce*0.1, affected_zone = (istype(user) ? user.zone_selected : BODY_ZONE_CHEST))//CIT CHANGE - makes stunbatons deal extra staminaloss. Todo: make this also deal pain when pain gets implemented.
|
||||
L.Knockdown(stunpwr)
|
||||
L.adjustStaminaLoss(stunpwr*0.1, affected_zone = (istype(user) ? user.zone_selected : BODY_ZONE_CHEST))//CIT CHANGE - makes stunbatons deal extra staminaloss. Todo: make this also deal pain when pain gets implemented.
|
||||
L.apply_effect(EFFECT_STUTTER, stunforce)
|
||||
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
|
||||
if(user)
|
||||
@@ -180,11 +193,18 @@
|
||||
H.forcesay(GLOB.hit_appends)
|
||||
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/item/melee/baton/proc/clowning_around(mob/living/user)
|
||||
user.visible_message("<span class='danger'>[user] accidentally hits [user.p_them()]self with [src]!</span>", \
|
||||
"<span class='userdanger'>You accidentally hit yourself with [src]!</span>")
|
||||
user.Knockdown(stunforce*3)
|
||||
deductcharge(hitcost)
|
||||
|
||||
/obj/item/melee/baton/emp_act(severity)
|
||||
. = ..()
|
||||
if (!(. & EMP_PROTECT_SELF))
|
||||
switch_status(FALSE)
|
||||
deductcharge(1000 / severity)
|
||||
|
||||
//Makeshift stun baton. Replacement for stun gloves.
|
||||
@@ -202,12 +222,15 @@
|
||||
hitcost = 2000
|
||||
throw_hit_chance = 10
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
var/obj/item/assembly/igniter/sparkler = 0
|
||||
var/obj/item/assembly/igniter/sparkler
|
||||
|
||||
/obj/item/melee/baton/cattleprod/Initialize()
|
||||
. = ..()
|
||||
sparkler = new (src)
|
||||
sparkler.activate_cooldown = 5
|
||||
|
||||
/obj/item/melee/baton/cattleprod/baton_stun()
|
||||
if(sparkler.activate())
|
||||
..()
|
||||
sparkler?.activate()
|
||||
. = ..()
|
||||
|
||||
#undef STUNBATON_CHARGE_LENIENCY
|
||||
@@ -17,8 +17,7 @@
|
||||
/obj/item/tank/jetpack/New()
|
||||
..()
|
||||
if(gas_type)
|
||||
air_contents.assert_gas(gas_type)
|
||||
air_contents.gases[gas_type][MOLES] = (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)
|
||||
air_contents.gases[gas_type] = (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)
|
||||
|
||||
ion_trail = new
|
||||
ion_trail.set_up(src)
|
||||
@@ -237,3 +236,4 @@
|
||||
var/obj/item/clothing/suit/space/hardsuit/C = wear_suit
|
||||
J = C.jetpack
|
||||
return J
|
||||
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
|
||||
/obj/item/tank/internals/oxygen/New()
|
||||
..()
|
||||
air_contents.assert_gas(/datum/gas/oxygen)
|
||||
air_contents.gases[/datum/gas/oxygen][MOLES] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
air_contents.gases[/datum/gas/oxygen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
@@ -49,9 +48,8 @@
|
||||
|
||||
/obj/item/tank/internals/anesthetic/New()
|
||||
..()
|
||||
air_contents.assert_gases(/datum/gas/oxygen, /datum/gas/nitrous_oxide)
|
||||
air_contents.gases[/datum/gas/oxygen][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
|
||||
air_contents.gases[/datum/gas/nitrous_oxide][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
|
||||
air_contents.gases[/datum/gas/oxygen] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
|
||||
air_contents.gases[/datum/gas/nitrous_oxide] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
|
||||
return
|
||||
|
||||
/*
|
||||
@@ -67,9 +65,8 @@
|
||||
|
||||
/obj/item/tank/internals/air/New()
|
||||
..()
|
||||
air_contents.assert_gases(/datum/gas/oxygen, /datum/gas/nitrogen)
|
||||
air_contents.gases[/datum/gas/oxygen][MOLES] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
|
||||
air_contents.gases[/datum/gas/nitrogen][MOLES] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
|
||||
air_contents.gases[/datum/gas/oxygen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
|
||||
air_contents.gases[/datum/gas/nitrogen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
|
||||
return
|
||||
|
||||
|
||||
@@ -87,8 +84,7 @@
|
||||
|
||||
/obj/item/tank/internals/plasma/New()
|
||||
..()
|
||||
air_contents.assert_gas(/datum/gas/plasma)
|
||||
air_contents.gases[/datum/gas/plasma][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
air_contents.gases[/datum/gas/plasma] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/plasma/attackby(obj/item/W, mob/user, params)
|
||||
@@ -106,7 +102,7 @@
|
||||
|
||||
/obj/item/tank/internals/plasma/full/New()
|
||||
..() // Plasma asserted in parent
|
||||
air_contents.gases[/datum/gas/plasma][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
@@ -124,13 +120,12 @@
|
||||
|
||||
/obj/item/tank/internals/plasmaman/New()
|
||||
..()
|
||||
air_contents.assert_gas(/datum/gas/plasma)
|
||||
air_contents.gases[/datum/gas/plasma][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
air_contents.gases[/datum/gas/plasma] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/plasmaman/full/New()
|
||||
..() // Plasma asserted in parent
|
||||
air_contents.gases[/datum/gas/plasma][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
@@ -144,7 +139,7 @@
|
||||
|
||||
/obj/item/tank/internals/plasmaman/belt/full/New()
|
||||
..() // Plasma asserted in parent
|
||||
air_contents.gases[/datum/gas/plasma][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
@@ -166,8 +161,7 @@
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/New()
|
||||
..()
|
||||
air_contents.assert_gas(/datum/gas/oxygen)
|
||||
air_contents.gases[/datum/gas/oxygen][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
air_contents.gases[/datum/gas/oxygen] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/engi
|
||||
|
||||
@@ -6,27 +6,23 @@
|
||||
item_state = "teleprod"
|
||||
slot_flags = null
|
||||
|
||||
/obj/item/melee/baton/cattleprod/teleprod/attack(mob/living/carbon/M, mob/living/carbon/user)//handles making things teleport when hit
|
||||
..()
|
||||
if(status && user.has_trait(TRAIT_CLUMSY) && prob(50))
|
||||
user.visible_message("<span class='danger'>[user] accidentally hits [user.p_them()]self with [src]!</span>", \
|
||||
"<span class='userdanger'>You accidentally hit yourself with [src]!</span>")
|
||||
if(do_teleport(user, get_turf(user), 50))//honk honk
|
||||
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
|
||||
user.Knockdown(stunforce*3)
|
||||
deductcharge(hitcost)
|
||||
else
|
||||
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
|
||||
user.Knockdown(stunforce*3)
|
||||
deductcharge(hitcost/4)
|
||||
/obj/item/melee/baton/cattleprod/teleprod/baton_stun(mob/living/carbon/M, mob/living/carbon/user)//handles making things teleport when hit
|
||||
. = ..()
|
||||
if(!. || !istype(M) || M.anchored)
|
||||
return
|
||||
else
|
||||
if(status)
|
||||
if(!istype(M) && M.anchored)
|
||||
return .
|
||||
else
|
||||
SEND_SIGNAL(M, COMSIG_LIVING_MINOR_SHOCK)
|
||||
do_teleport(M, get_turf(M), 15)
|
||||
SEND_SIGNAL(M, COMSIG_LIVING_MINOR_SHOCK)
|
||||
do_teleport(M, get_turf(M), 15)
|
||||
|
||||
/obj/item/melee/baton/cattleprod/teleprod/clowning_around(mob/living/user)
|
||||
user.visible_message("<span class='danger'>[user] accidentally hits [user.p_them()]self with [src]!</span>", \
|
||||
"<span class='userdanger'>You accidentally hit yourself with [src]!</span>")
|
||||
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
|
||||
user.Knockdown(stunforce*3)
|
||||
if(do_teleport(user, get_turf(user), 50))
|
||||
deductcharge(hitcost)
|
||||
else
|
||||
deductcharge(hitcost * 0.25)
|
||||
|
||||
/obj/item/melee/baton/cattleprod/attackby(obj/item/I, mob/user, params)//handles sticking a crystal onto a stunprod to make a teleprod
|
||||
if(istype(I, /obj/item/stack/ore/bluespace_crystal))
|
||||
|
||||
@@ -75,11 +75,6 @@
|
||||
return ..()
|
||||
if(user.zone_selected != BODY_ZONE_PRECISE_EYES && user.zone_selected != BODY_ZONE_HEAD)
|
||||
return ..()
|
||||
if(user.has_trait(TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='warning'>You don't want to harm [M]!</span>")
|
||||
return
|
||||
if(user.has_trait(TRAIT_CLUMSY) && prob(50))
|
||||
M = user
|
||||
return eyestab(M,user)
|
||||
|
||||
/obj/item/screwdriver/brass
|
||||
@@ -103,7 +98,7 @@
|
||||
|
||||
/obj/item/screwdriver/abductor/get_belt_overlay()
|
||||
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "screwdriver_nuke")
|
||||
|
||||
|
||||
/obj/item/screwdriver/power
|
||||
name = "hand drill"
|
||||
desc = "A simple powered hand drill. It's fitted with a screw bit."
|
||||
|
||||
@@ -241,6 +241,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
|
||||
//what happens when the obj's health is below integrity_failure level.
|
||||
/obj/proc/obj_break(damage_flag)
|
||||
SEND_SIGNAL(src, COMSIG_OBJ_BREAK, damage_flag)
|
||||
return
|
||||
|
||||
//what happens when the obj's integrity reaches zero.
|
||||
|
||||
@@ -152,8 +152,8 @@
|
||||
pod_moving = 0
|
||||
if(!QDELETED(pod))
|
||||
var/datum/gas_mixture/floor_mixture = loc.return_air()
|
||||
floor_mixture.archive()
|
||||
pod.air_contents.archive()
|
||||
ARCHIVE_TEMPERATURE(floor_mixture)
|
||||
ARCHIVE_TEMPERATURE(pod.air_contents)
|
||||
pod.air_contents.share(floor_mixture, 1) //mix the pod's gas mixture with the tile it's on
|
||||
air_update_turf()
|
||||
|
||||
|
||||
@@ -11,9 +11,8 @@
|
||||
|
||||
/obj/structure/transit_tube_pod/Initialize()
|
||||
. = ..()
|
||||
air_contents.add_gases(/datum/gas/oxygen, /datum/gas/nitrogen)
|
||||
air_contents.gases[/datum/gas/oxygen][MOLES] = MOLES_O2STANDARD
|
||||
air_contents.gases[/datum/gas/nitrogen][MOLES] = MOLES_N2STANDARD
|
||||
air_contents.gases[/datum/gas/oxygen] = MOLES_O2STANDARD
|
||||
air_contents.gases[/datum/gas/nitrogen] = MOLES_N2STANDARD
|
||||
air_contents.temperature = T20C
|
||||
|
||||
|
||||
|
||||
@@ -297,15 +297,14 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
|
||||
continue
|
||||
var/list/S_gases = S.air.gases
|
||||
for(var/id in S_gases)
|
||||
ASSERT_GAS(id, total)
|
||||
total_gases[id][MOLES] += S_gases[id][MOLES]
|
||||
total_gases[id] += S_gases[id]
|
||||
total.temperature += S.air.temperature
|
||||
|
||||
air.copy_from(total)
|
||||
|
||||
var/list/air_gases = air.gases
|
||||
for(var/id in air_gases)
|
||||
air_gases[id][MOLES] /= turf_count //Averages contents of the turfs, ignoring walls and the like
|
||||
air_gases[id] /= turf_count //Averages contents of the turfs, ignoring walls and the like
|
||||
|
||||
air.temperature /= turf_count
|
||||
SSair.add_to_active(src)
|
||||
|
||||
@@ -314,9 +314,8 @@
|
||||
/turf/open/rad_act(pulse_strength)
|
||||
. = ..()
|
||||
if (air.gases[/datum/gas/carbon_dioxide] && air.gases[/datum/gas/oxygen])
|
||||
pulse_strength = min(pulse_strength,air.gases[/datum/gas/carbon_dioxide][MOLES]*1000,air.gases[/datum/gas/oxygen][MOLES]*2000) //Ensures matter is conserved properly
|
||||
air.gases[/datum/gas/carbon_dioxide][MOLES]=max(air.gases[/datum/gas/carbon_dioxide][MOLES]-(pulse_strength/1000),0)
|
||||
air.gases[/datum/gas/oxygen][MOLES]=max(air.gases[/datum/gas/oxygen][MOLES]-(pulse_strength/2000),0)
|
||||
air.assert_gas(/datum/gas/pluoxium)
|
||||
air.gases[/datum/gas/pluoxium][MOLES]+=(pulse_strength/4000)
|
||||
air.garbage_collect()
|
||||
pulse_strength = min(pulse_strength,air.gases[/datum/gas/carbon_dioxide]*1000,air.gases[/datum/gas/oxygen]*2000) //Ensures matter is conserved properly
|
||||
air.gases[/datum/gas/carbon_dioxide]=max(air.gases[/datum/gas/carbon_dioxide]-(pulse_strength/1000),0)
|
||||
air.gases[/datum/gas/oxygen]=max(air.gases[/datum/gas/oxygen]-(pulse_strength/2000),0)
|
||||
air.gases[/datum/gas/pluoxium]+=(pulse_strength/4000)
|
||||
GAS_GARBAGE_COLLECT(air.gases)
|
||||
|
||||
@@ -77,6 +77,19 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/turf/closed/wall/clockwork/try_destroy(obj/item/I, mob/user, turf/T)
|
||||
if(!heated)
|
||||
return ..()
|
||||
if(!istype(I, /obj/item/pickaxe/drill/jackhammer))
|
||||
return FALSE
|
||||
to_chat(user, "<span class='notice'>You begin to smash though [src]...</span>")
|
||||
if(!do_after(user, 70, TRUE, src))
|
||||
return FALSE
|
||||
I.play_tool_sound(src)
|
||||
visible_message("<span class='warning'>[user] smashes through [src] with [I]!</span>", "<span class='italics'>You hear the grinding of metal.</span>")
|
||||
dismantle_wall()
|
||||
return TRUE
|
||||
|
||||
/turf/closed/wall/clockwork/ReplaceWithLattice()
|
||||
..()
|
||||
for(var/obj/structure/lattice/L in src)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -108,20 +108,7 @@
|
||||
to_chat(loc, "<span class='warning'>Combat injection is still recharging.</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/M = loc
|
||||
M.SetSleeping(0)
|
||||
M.SetUnconscious(0)
|
||||
M.SetStun(0)
|
||||
M.SetKnockdown(0)
|
||||
M.reagents.add_reagent("inaprovaline", 3)
|
||||
M.reagents.add_reagent("synaptizine", 10)
|
||||
M.reagents.add_reagent("stimulants", 10)
|
||||
M.adjustStaminaLoss(-150)
|
||||
M.stuttering = 0
|
||||
M.updatehealth()
|
||||
M.update_stamina()
|
||||
M.resting = 0
|
||||
M.lying = 0
|
||||
M.update_canmove()
|
||||
M.do_adrenaline(150, FALSE, 0, 0, TRUE, list("inaprovaline" = 3, "synaptizine" = 10, "omnizine" = 10), "<span class='boldnotice'>You feel a sudden surge of energy!</span>")
|
||||
combat_cooldown = 0
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
|
||||
@@ -12,21 +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.reagents.add_reagent("inaprovaline", 3) //let's give another chance to dumb fucks who forget to breathe
|
||||
user.adjustStaminaLoss(-150)
|
||||
user.stuttering = 0
|
||||
user.updatehealth()
|
||||
user.update_stamina()
|
||||
user.resting = 0
|
||||
user.lying = 0
|
||||
user.update_canmove()
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -220,7 +220,7 @@
|
||||
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)
|
||||
@@ -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,8 +294,8 @@
|
||||
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
|
||||
@@ -279,7 +303,7 @@
|
||||
H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
|
||||
H.add_trait(CULT_EYES)
|
||||
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
|
||||
|
||||
@@ -246,7 +246,7 @@ 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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -433,7 +433,6 @@
|
||||
/datum/supply_pack/security/russianclothing
|
||||
name = "Russian Surplus Clothing"
|
||||
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproff armor, a few union suits and some warm hats!"
|
||||
hidden = TRUE
|
||||
contraband = TRUE
|
||||
cost = 5000 // Its basicly sec suits, good boots/gloves
|
||||
contains = list(/obj/item/clothing/suit/security/officer/russian,
|
||||
@@ -873,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,
|
||||
@@ -882,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 /////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -961,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."
|
||||
|
||||
@@ -117,6 +117,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
"balls_color" = "fff",
|
||||
"balls_amount" = 2,
|
||||
"balls_sack_size" = BALLS_SACK_SIZE_DEF,
|
||||
"balls_shape" = "Single",
|
||||
"balls_size" = BALLS_SIZE_DEF,
|
||||
"balls_cum_rate" = CUM_RATE,
|
||||
"balls_cum_mult" = CUM_RATE_MULT,
|
||||
@@ -701,6 +702,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>"
|
||||
@@ -1458,7 +1460,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
|
||||
@@ -1836,7 +1838,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["cock_color"] = sanitize_hexcolor(new_cockcolor)
|
||||
else
|
||||
user << "<span class='danger'>Invalid color. Your color is not bright enough.</span>"
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
if("cock_length")
|
||||
var/new_length = input(user, "Penis length in inches:\n([COCK_SIZE_MIN]-[COCK_SIZE_MAX])", "Character Preference") as num|null
|
||||
@@ -1858,7 +1860,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["balls_color"] = sanitize_hexcolor(new_ballscolor)
|
||||
else
|
||||
user << "<span class='danger'>Invalid color. Your color is not bright enough.</span>"
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
if("balls_shape")
|
||||
var/new_shape
|
||||
new_shape = input(user, "Testicle Type:", "Character Preference") as null|anything in GLOB.balls_shapes_list
|
||||
if(new_shape)
|
||||
features["balls_shape"] = new_shape
|
||||
|
||||
if("egg_size")
|
||||
var/new_size
|
||||
@@ -1874,7 +1882,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["eggsack_egg_color"] = sanitize_hexcolor(new_egg_color)
|
||||
else
|
||||
user << "<span class='danger'>Invalid color. Your color is not bright enough.</span>"
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
if("breasts_size")
|
||||
var/new_size
|
||||
@@ -1897,7 +1905,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
|
||||
features["breasts_color"] = sanitize_hexcolor(new_breasts_color)
|
||||
else
|
||||
user << "<span class='danger'>Invalid color. Your color is not bright enough.</span>"
|
||||
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
if("vag_shape")
|
||||
var/new_shape
|
||||
@@ -1914,7 +1922,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
|
||||
|
||||
@@ -330,6 +330,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(!(H.has_trait(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)
|
||||
@@ -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
|
||||
@@ -185,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
|
||||
@@ -198,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
|
||||
@@ -212,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
|
||||
@@ -227,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"
|
||||
@@ -280,7 +345,6 @@ Contains:
|
||||
item_flags = NODROP
|
||||
mutantrace_variation = NO_MUTANTRACE_VARIATION
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/carp
|
||||
name = "carp space suit"
|
||||
desc = "A slimming piece of dubious space carp technology, you suspect it won't stand up to hand-to-hand blows."
|
||||
@@ -291,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."
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
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
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user