Merge remote-tracking branch 'upstream/master' into RCDMEMES
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
|
||||
|
||||
@@ -56,9 +56,6 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
#define FLYING (1<<1)
|
||||
#define VENTCRAWLING (1<<2)
|
||||
|
||||
// Flags for reagents
|
||||
#define REAGENT_NOREACT (1<<0)
|
||||
|
||||
//Fire and Acid stuff, for resistance_flags
|
||||
#define LAVA_PROOF (1<<0)
|
||||
#define FIRE_PROOF (1<<1) //100% immune to fire damage (but not necessarily to lava or heat)
|
||||
|
||||
@@ -218,6 +218,9 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
|
||||
//Gets the turf this atom inhabits
|
||||
#define get_turf(A) (get_step(A, 0))
|
||||
|
||||
//Same as above except gets the area instead
|
||||
#define get_area(A) (isarea(A) ? A : get_step(A, 0)?.loc)
|
||||
|
||||
//Ghost orbit types:
|
||||
#define GHOST_ORBIT_CIRCLE "circle"
|
||||
#define GHOST_ORBIT_TRIANGLE "triangle"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define LIQUID 2
|
||||
#define GAS 3
|
||||
|
||||
// container_type defines
|
||||
// reagents_flags defines
|
||||
#define INJECTABLE (1<<0) // Makes it possible to add reagents through droppers and syringes.
|
||||
#define DRAWABLE (1<<1) // Makes it possible to remove reagents through syringes.
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#define TRANSPARENT (1<<4) // Used on containers which you want to be able to see the reagents off.
|
||||
#define AMOUNT_VISIBLE (1<<5) // For non-transparent containers that still have the general amount of reagents in them visible.
|
||||
#define NO_REACT (1<<6) // Applied to a reagent holder, the contents will not react with each other.
|
||||
|
||||
// Is an open container for all intents and purposes.
|
||||
#define OPENCONTAINER (REFILLABLE | DRAINABLE | TRANSPARENT)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,61 @@
|
||||
// trait accessor defines
|
||||
#define ADD_TRAIT(target, trait, source) \
|
||||
do { \
|
||||
var/list/_L; \
|
||||
if (!target.status_traits) { \
|
||||
target.status_traits = list(); \
|
||||
_L = target.status_traits; \
|
||||
_L[trait] = list(source); \
|
||||
} else { \
|
||||
_L = target.status_traits; \
|
||||
if (_L[trait]) { \
|
||||
_L[trait] |= list(source); \
|
||||
} else { \
|
||||
_L[trait] = list(source); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#define REMOVE_TRAIT(target, trait, sources) \
|
||||
do { \
|
||||
var/list/_L = target.status_traits; \
|
||||
var/list/_S; \
|
||||
if (sources && !islist(sources)) { \
|
||||
_S = list(sources); \
|
||||
} else { \
|
||||
_S = sources\
|
||||
}; \
|
||||
if (_L && _L[trait]) { \
|
||||
for (var/_T in _L[trait]) { \
|
||||
if ((!_S && (_T != ROUNDSTART_TRAIT)) || (_T in _S)) { \
|
||||
_L[trait] -= _T \
|
||||
} \
|
||||
};\
|
||||
if (!length(_L[trait])) { \
|
||||
_L -= trait \
|
||||
}; \
|
||||
if (!length(_L)) { \
|
||||
target.status_traits = null \
|
||||
}; \
|
||||
} \
|
||||
} while (0)
|
||||
#define REMOVE_TRAITS_NOT_IN(target, sources) \
|
||||
do { \
|
||||
var/list/_L = target.status_traits; \
|
||||
var/list/_S = sources; \
|
||||
if (_L) { \
|
||||
for (var/_T in _L) { \
|
||||
_L[_T] &= _S;\
|
||||
if (!length(_L[_T])) { \
|
||||
_L -= _T } \
|
||||
};\
|
||||
if (!length(_L)) { \
|
||||
target.status_traits = null\
|
||||
};\
|
||||
}\
|
||||
} while (0)
|
||||
#define HAS_TRAIT(target, trait) (target.status_traits ? (target.status_traits[trait] ? TRUE : FALSE) : FALSE)
|
||||
#define HAS_TRAIT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (source in target.status_traits[trait]) : FALSE) : FALSE)
|
||||
|
||||
//mob traits
|
||||
#define TRAIT_BLIND "blind"
|
||||
#define TRAIT_MUTE "mute"
|
||||
@@ -72,6 +130,10 @@
|
||||
#define TRAIT_CROCRIN_IMMUNE "crocin_immune"
|
||||
#define TRAIT_NYMPHO "nymphomania"
|
||||
#define TRAIT_MASO "masochism"
|
||||
#define TRAIT_EMPATH "empath"
|
||||
#define TRAIT_FRIENDLY "friendly"
|
||||
#define TRAIT_ASSBLASTUSA "assblastusa"
|
||||
#define TRAIT_CULT_EYES "cult_eyes"
|
||||
|
||||
// common trait sources
|
||||
#define TRAIT_GENERIC "generic"
|
||||
@@ -94,4 +156,3 @@
|
||||
#define STASIS_MUTE "stasis"
|
||||
#define GENETICS_SPELL "genetics_spell"
|
||||
#define EYES_COVERED "eyes_covered"
|
||||
#define CULT_EYES "cult_eyes"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -8,12 +8,6 @@
|
||||
#define Z_TURFS(ZLEVEL) block(locate(1,1,ZLEVEL), locate(world.maxx, world.maxy, ZLEVEL))
|
||||
#define CULT_POLL_WAIT 2400
|
||||
|
||||
/proc/get_area(atom/A)
|
||||
if(isarea(A))
|
||||
return A
|
||||
var/turf/T = get_turf(A)
|
||||
return T ? T.loc : null
|
||||
|
||||
/proc/get_area_name(atom/X, format_text = FALSE)
|
||||
var/area/A = isarea(X) ? X : get_area(X)
|
||||
if(!A)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -115,9 +115,6 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"GOLIATH_RESISTANCE" = GOLIATH_RESISTANCE,
|
||||
"GOLIATH_WEAKNESS" = GOLIATH_WEAKNESS
|
||||
),
|
||||
"reagents_holder_flags" = list(
|
||||
"REAGENT_NOREACT" = REAGENT_NOREACT
|
||||
),
|
||||
"flags_1" = list(
|
||||
"NOJAUNT_1" = NOJAUNT_1,
|
||||
"UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1,
|
||||
@@ -158,13 +155,14 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"SMOOTH_BORDER" = SMOOTH_BORDER,
|
||||
"SMOOTH_QUEUED" = SMOOTH_QUEUED,
|
||||
),
|
||||
"container_type" = list(
|
||||
"reagents_holder_flags" = list(
|
||||
"INJECTABLE" = INJECTABLE,
|
||||
"DRAWABLE" = DRAWABLE,
|
||||
"REFILLABLE" = REFILLABLE,
|
||||
"DRAINABLE" = DRAINABLE,
|
||||
"TRANSPARENT" = TRANSPARENT,
|
||||
"AMOUNT_VISIBLE" = AMOUNT_VISIBLE,
|
||||
"NO_REACT" = NO_REACT,
|
||||
),
|
||||
"car_traits" = list(
|
||||
"CAN_KIDNAP" = CAN_KIDNAP,
|
||||
|
||||
@@ -40,6 +40,54 @@ GLOBAL_LIST_EMPTY(caps_list)
|
||||
GLOBAL_LIST_INIT(ghost_forms_with_directions_list, list("ghost")) //stores the ghost forms that support directional sprites
|
||||
GLOBAL_LIST_INIT(ghost_forms_with_accessories_list, list("ghost")) //stores the ghost forms that support hair and other such things
|
||||
|
||||
GLOBAL_LIST_INIT(ai_core_display_screens, list(
|
||||
":thinking:",
|
||||
"Alien",
|
||||
"Angel",
|
||||
"Banned",
|
||||
"Bliss",
|
||||
"Blue",
|
||||
"Clown",
|
||||
"Database",
|
||||
"Dorf",
|
||||
"Firewall",
|
||||
"Fuzzy",
|
||||
"Gentoo",
|
||||
"Glitchman",
|
||||
"Gondola",
|
||||
"Goon",
|
||||
"Hades",
|
||||
"Heartline",
|
||||
"Helios",
|
||||
"House",
|
||||
"Inverted",
|
||||
"Matrix",
|
||||
"Monochrome",
|
||||
"Murica",
|
||||
"Nanotrasen",
|
||||
"Not Malf",
|
||||
"President",
|
||||
"Random",
|
||||
"Rainbow",
|
||||
"Red",
|
||||
"Red October",
|
||||
"Static",
|
||||
"Syndicat Meow",
|
||||
"TechDemon",
|
||||
"Text",
|
||||
"Too Deep",
|
||||
"Triumvirate",
|
||||
"Triumvirate-M",
|
||||
"Weird"))
|
||||
|
||||
/proc/resolve_ai_icon(input)
|
||||
if(!input || !(input in GLOB.ai_core_display_screens))
|
||||
return "ai"
|
||||
else
|
||||
if(input == "Random")
|
||||
input = pick(GLOB.ai_core_display_screens - "Random")
|
||||
return "ai-[lowertext(input)]"
|
||||
|
||||
GLOBAL_LIST_INIT(security_depts_prefs, list(SEC_DEPT_RANDOM, SEC_DEPT_NONE, SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, SEC_DEPT_SCIENCE, SEC_DEPT_SUPPLY))
|
||||
|
||||
//Backpacks
|
||||
@@ -117,7 +165,7 @@ GLOBAL_LIST_INIT(TAGGERLOCATIONS, list("Disposals",
|
||||
"CMO Office", "Chemistry", "Research", "RD Office",
|
||||
"Robotics", "HoP Office", "Library", "Chapel", "Theatre",
|
||||
"Bar", "Kitchen", "Hydroponics", "Janitor Closet","Genetics",
|
||||
"Circuitry", "Toxins", "Dormitories", "Virology",
|
||||
"Circuitry", "Toxins", "Dormitories", "Virology",
|
||||
"Xenobiology", "Law Office","Detective's Office"))
|
||||
|
||||
GLOBAL_LIST_INIT(station_prefixes, world.file2list("strings/station_prefixes.txt") + "")
|
||||
|
||||
@@ -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
|
||||
))
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#define NEXT_PAGE_ID "__next__"
|
||||
#define DEFAULT_CHECK_DELAY 20
|
||||
|
||||
GLOBAL_LIST_EMPTY(radial_menus)
|
||||
|
||||
/obj/screen/radial
|
||||
icon = 'icons/mob/radial.dmi'
|
||||
@@ -10,14 +13,19 @@
|
||||
icon_state = "radial_slice"
|
||||
var/choice
|
||||
var/next_page = FALSE
|
||||
var/tooltips = FALSE
|
||||
|
||||
/obj/screen/radial/slice/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
icon_state = "radial_slice_focus"
|
||||
if(tooltips)
|
||||
openToolTip(usr, src, params, title = name)
|
||||
|
||||
/obj/screen/radial/slice/MouseExited(location, control, params)
|
||||
. = ..()
|
||||
icon_state = "radial_slice"
|
||||
if(tooltips)
|
||||
closeToolTip(usr)
|
||||
|
||||
/obj/screen/radial/slice/Click(location, control, params)
|
||||
if(usr.client == parent.current_user)
|
||||
@@ -30,6 +38,14 @@
|
||||
name = "Close Menu"
|
||||
icon_state = "radial_center"
|
||||
|
||||
/obj/screen/radial/center/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
icon_state = "radial_center_focus"
|
||||
|
||||
/obj/screen/radial/center/MouseExited(location, control, params)
|
||||
. = ..()
|
||||
icon_state = "radial_center"
|
||||
|
||||
/obj/screen/radial/center/Click(location, control, params)
|
||||
if(usr.client == parent.current_user)
|
||||
parent.finished = TRUE
|
||||
@@ -48,6 +64,9 @@
|
||||
var/atom/anchor
|
||||
var/image/menu_holder
|
||||
var/finished = FALSE
|
||||
var/datum/callback/custom_check_callback
|
||||
var/next_check = 0
|
||||
var/check_delay = DEFAULT_CHECK_DELAY
|
||||
|
||||
var/radius = 32
|
||||
var/starting_angle = 0
|
||||
@@ -57,7 +76,7 @@
|
||||
var/max_elements
|
||||
var/pages = 1
|
||||
var/current_page = 1
|
||||
|
||||
|
||||
var/hudfix_method = TRUE //TRUE to change anchor to user, FALSE to shift by py_shift
|
||||
var/py_shift = 0
|
||||
var/entry_animation = TRUE
|
||||
@@ -75,7 +94,7 @@
|
||||
restrict_to_dir(NORTH) //I was going to parse screen loc here but that's more effort than it's worth.
|
||||
|
||||
//Sets defaults
|
||||
//These assume 45 deg min_angle
|
||||
//These assume 45 deg min_angle
|
||||
/datum/radial_menu/proc/restrict_to_dir(dir)
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
@@ -91,18 +110,19 @@
|
||||
starting_angle = 180
|
||||
ending_angle = 45
|
||||
|
||||
/datum/radial_menu/proc/setup_menu()
|
||||
/datum/radial_menu/proc/setup_menu(use_tooltips)
|
||||
if(ending_angle > starting_angle)
|
||||
zone = ending_angle - starting_angle
|
||||
else
|
||||
zone = 360 - starting_angle + ending_angle
|
||||
|
||||
|
||||
max_elements = round(zone / min_angle)
|
||||
var/paged = max_elements < choices.len
|
||||
if(elements.len < max_elements)
|
||||
var/elements_to_add = max_elements - elements.len
|
||||
for(var/i in 1 to elements_to_add) //Create all elements
|
||||
var/obj/screen/radial/new_element = new /obj/screen/radial/slice
|
||||
var/obj/screen/radial/slice/new_element = new /obj/screen/radial/slice
|
||||
new_element.tooltips = use_tooltips
|
||||
new_element.parent = src
|
||||
elements += new_element
|
||||
|
||||
@@ -163,7 +183,7 @@
|
||||
else
|
||||
E.pixel_y = py
|
||||
E.pixel_x = px
|
||||
|
||||
|
||||
//Visuals
|
||||
E.alpha = 255
|
||||
E.mouse_opacity = MOUSE_OPACITY_ICON
|
||||
@@ -183,7 +203,7 @@
|
||||
E.next_page = FALSE
|
||||
if(choices_icons[choice_id])
|
||||
E.add_overlay(choices_icons[choice_id])
|
||||
|
||||
|
||||
/datum/radial_menu/New()
|
||||
close_button = new
|
||||
close_button.parent = src
|
||||
@@ -200,7 +220,7 @@
|
||||
/datum/radial_menu/proc/get_next_id()
|
||||
return "c_[choices.len]"
|
||||
|
||||
/datum/radial_menu/proc/set_choices(list/new_choices)
|
||||
/datum/radial_menu/proc/set_choices(list/new_choices, use_tooltips)
|
||||
if(choices.len)
|
||||
Reset()
|
||||
for(var/E in new_choices)
|
||||
@@ -211,7 +231,7 @@
|
||||
var/I = extract_image(new_choices[E])
|
||||
if(I)
|
||||
choices_icons[id] = I
|
||||
setup_menu()
|
||||
setup_menu(use_tooltips)
|
||||
|
||||
|
||||
/datum/radial_menu/proc/extract_image(E)
|
||||
@@ -220,7 +240,7 @@
|
||||
MA.layer = ABOVE_HUD_LAYER
|
||||
MA.appearance_flags |= RESET_TRANSFORM
|
||||
return MA
|
||||
|
||||
|
||||
|
||||
/datum/radial_menu/proc/next_page()
|
||||
if(pages > 1)
|
||||
@@ -243,28 +263,49 @@
|
||||
if(current_user)
|
||||
current_user.images -= menu_holder
|
||||
|
||||
/datum/radial_menu/proc/wait()
|
||||
/datum/radial_menu/proc/wait(atom/user, atom/anchor, require_near = FALSE)
|
||||
while (current_user && !finished && !selected_choice)
|
||||
if(require_near && !in_range(anchor, user))
|
||||
return
|
||||
if(custom_check_callback && next_check < world.time)
|
||||
if(!custom_check_callback.Invoke())
|
||||
return
|
||||
else
|
||||
next_check = world.time + check_delay
|
||||
stoplag(1)
|
||||
|
||||
/datum/radial_menu/Destroy()
|
||||
Reset()
|
||||
hide()
|
||||
QDEL_NULL(custom_check_callback)
|
||||
. = ..()
|
||||
|
||||
/*
|
||||
Presents radial menu to user anchored to anchor (or user if the anchor is currently in users screen)
|
||||
Presents radial menu to user anchored to anchor (or user if the anchor is currently in users screen)
|
||||
Choices should be a list where list keys are movables or text used for element names and return value
|
||||
and list values are movables/icons/images used for element icons
|
||||
*/
|
||||
/proc/show_radial_menu(mob/user,atom/anchor,list/choices)
|
||||
/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE)
|
||||
if(!user || !anchor || !length(choices))
|
||||
return
|
||||
if(!uniqueid)
|
||||
uniqueid = "defmenu_[REF(user)]_[REF(anchor)]"
|
||||
|
||||
if(GLOB.radial_menus[uniqueid])
|
||||
return
|
||||
|
||||
var/datum/radial_menu/menu = new
|
||||
if(!user)
|
||||
user = usr
|
||||
GLOB.radial_menus[uniqueid] = menu
|
||||
if(radius)
|
||||
menu.radius = radius
|
||||
if(istype(custom_check))
|
||||
menu.custom_check_callback = custom_check
|
||||
menu.anchor = anchor
|
||||
menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud
|
||||
menu.set_choices(choices)
|
||||
menu.set_choices(choices, tooltips)
|
||||
menu.show_to(user)
|
||||
menu.wait()
|
||||
menu.wait(user, anchor, require_near)
|
||||
var/answer = menu.selected_choice
|
||||
qdel(menu)
|
||||
GLOB.radial_menus -= uniqueid
|
||||
return answer
|
||||
76
code/_onclick/hud/radial_persistent.dm
Normal file
76
code/_onclick/hud/radial_persistent.dm
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
A derivative of radial menu which persists onscreen until closed and invokes a callback each time an element is clicked
|
||||
*/
|
||||
|
||||
/obj/screen/radial/persistent/center
|
||||
name = "Close Menu"
|
||||
icon_state = "radial_center"
|
||||
|
||||
/obj/screen/radial/persistent/center/Click(location, control, params)
|
||||
if(usr.client == parent.current_user)
|
||||
parent.element_chosen(null,usr)
|
||||
|
||||
/obj/screen/radial/persistent/center/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
icon_state = "radial_center_focus"
|
||||
|
||||
/obj/screen/radial/persistent/center/MouseExited(location, control, params)
|
||||
. = ..()
|
||||
icon_state = "radial_center"
|
||||
|
||||
|
||||
|
||||
/datum/radial_menu/persistent
|
||||
var/uniqueid
|
||||
var/datum/callback/select_proc_callback
|
||||
|
||||
/datum/radial_menu/persistent/New()
|
||||
close_button = new /obj/screen/radial/persistent/center
|
||||
close_button.parent = src
|
||||
|
||||
|
||||
/datum/radial_menu/persistent/element_chosen(choice_id,mob/user)
|
||||
select_proc_callback.Invoke(choices_values[choice_id])
|
||||
|
||||
|
||||
/datum/radial_menu/persistent/proc/change_choices(list/newchoices, tooltips)
|
||||
if(!newchoices.len)
|
||||
return
|
||||
Reset()
|
||||
set_choices(newchoices,tooltips)
|
||||
|
||||
/datum/radial_menu/persistent/Destroy()
|
||||
QDEL_NULL(select_proc_callback)
|
||||
GLOB.radial_menus -= uniqueid
|
||||
Reset()
|
||||
hide()
|
||||
. = ..()
|
||||
|
||||
/*
|
||||
Creates a persistent radial menu and shows it to the user, anchored to anchor (or user if the anchor is currently in users screen).
|
||||
Choices should be a list where list keys are movables or text used for element names and return value
|
||||
and list values are movables/icons/images used for element icons
|
||||
Select_proc is the proc to be called each time an element on the menu is clicked, and should accept the chosen element as its final argument
|
||||
Clicking the center button will return a choice of null
|
||||
*/
|
||||
/proc/show_radial_menu_persistent(mob/user, atom/anchor, list/choices, datum/callback/select_proc, uniqueid, radius, tooltips = FALSE)
|
||||
if(!user || !anchor || !length(choices) || !select_proc)
|
||||
return
|
||||
if(!uniqueid)
|
||||
uniqueid = "defmenu_[REF(user)]_[REF(anchor)]"
|
||||
|
||||
if(GLOB.radial_menus[uniqueid])
|
||||
return
|
||||
|
||||
var/datum/radial_menu/persistent/menu = new
|
||||
menu.uniqueid = uniqueid
|
||||
GLOB.radial_menus[uniqueid] = menu
|
||||
if(radius)
|
||||
menu.radius = radius
|
||||
menu.select_proc_callback = select_proc
|
||||
menu.anchor = anchor
|
||||
menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud
|
||||
menu.set_choices(choices, tooltips)
|
||||
menu.show_to(user)
|
||||
return menu
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
to_chat(user, "<span class='warning'>You're too exhausted.</span>") // CIT CHANGE - ditto
|
||||
return // CIT CHANGE - ditto
|
||||
|
||||
if(force && user.has_trait(TRAIT_PACIFISM))
|
||||
if(force && HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
|
||||
return
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ SUBSYSTEM_DEF(throwing)
|
||||
return
|
||||
|
||||
dist_travelled++
|
||||
|
||||
|
||||
if (dist_travelled > MAX_THROWING_DIST)
|
||||
finalize()
|
||||
return
|
||||
@@ -154,7 +154,7 @@ SUBSYSTEM_DEF(throwing)
|
||||
/datum/thrownthing/proc/hitcheck()
|
||||
for (var/thing in get_turf(thrownthing))
|
||||
var/atom/movable/AM = thing
|
||||
if (AM == thrownthing)
|
||||
if (AM == thrownthing || (AM == thrower && !ismob(thrownthing)))
|
||||
continue
|
||||
if (AM.density && !(AM.pass_flags & LETPASSTHROW) && !(AM.flags_1 & ON_BORDER_1))
|
||||
finalize(hit=TRUE, target=AM)
|
||||
|
||||
@@ -195,11 +195,16 @@
|
||||
/datum/action/item_action/toggle_firemode
|
||||
name = "Toggle Firemode"
|
||||
|
||||
/datum/action/item_action/rcl
|
||||
/datum/action/item_action/rcl_col
|
||||
name = "Change Cable Color"
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "rcl_rainbow"
|
||||
|
||||
/datum/action/item_action/rcl_gui
|
||||
name = "Toggle Fast Wiring Gui"
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "rcl_gui"
|
||||
|
||||
/datum/action/item_action/startchainsaw
|
||||
name = "Pull The Starting Cord"
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
lose_text = "<span class='notice'>You feel smart again.</span>"
|
||||
|
||||
/datum/brain_trauma/mild/dumbness/on_gain()
|
||||
owner.add_trait(TRAIT_DUMB, TRAUMA_TRAIT)
|
||||
ADD_TRAIT(owner, TRAIT_DUMB, TRAUMA_TRAIT)
|
||||
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "dumb", /datum/mood_event/oblivious)
|
||||
..()
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/dumbness/on_lose()
|
||||
owner.remove_trait(TRAIT_DUMB, TRAUMA_TRAIT)
|
||||
REMOVE_TRAIT(owner, TRAIT_DUMB, TRAUMA_TRAIT)
|
||||
owner.derpspeech = 0
|
||||
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "dumb")
|
||||
..()
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
lose_text = "<span class='notice'>You suddenly remember how to speak.</span>"
|
||||
|
||||
/datum/brain_trauma/severe/mute/on_gain()
|
||||
owner.add_trait(TRAIT_MUTE, TRAUMA_TRAIT)
|
||||
ADD_TRAIT(owner, TRAIT_MUTE, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/mute/on_lose()
|
||||
owner.remove_trait(TRAIT_MUTE, TRAUMA_TRAIT)
|
||||
REMOVE_TRAIT(owner, TRAIT_MUTE, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/aphasia
|
||||
@@ -121,7 +121,7 @@
|
||||
stress -= 4
|
||||
|
||||
/datum/brain_trauma/severe/monophobia/proc/check_alone()
|
||||
if(owner.has_trait(TRAIT_BLIND))
|
||||
if(HAS_TRAIT(owner, TRAIT_BLIND))
|
||||
return TRUE
|
||||
for(var/mob/M in oview(owner, 7))
|
||||
if(!isliving(M)) //ghosts ain't people
|
||||
@@ -183,11 +183,11 @@
|
||||
lose_text = "<span class='notice'>You feel in control of your hands again.</span>"
|
||||
|
||||
/datum/brain_trauma/severe/discoordination/on_gain()
|
||||
owner.add_trait(TRAIT_MONKEYLIKE, TRAUMA_TRAIT)
|
||||
ADD_TRAIT(owner, TRAIT_MONKEYLIKE, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/discoordination/on_lose()
|
||||
owner.remove_trait(TRAIT_MONKEYLIKE, TRAUMA_TRAIT)
|
||||
REMOVE_TRAIT(owner, TRAIT_MONKEYLIKE, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/pacifism
|
||||
@@ -198,9 +198,9 @@
|
||||
lose_text = "<span class='notice'>You no longer feel compelled to not harm.</span>"
|
||||
|
||||
/datum/brain_trauma/severe/pacifism/on_gain()
|
||||
owner.add_trait(TRAIT_PACIFISM, TRAUMA_TRAIT)
|
||||
ADD_TRAIT(owner, TRAIT_PACIFISM, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/severe/pacifism/on_lose()
|
||||
owner.remove_trait(TRAIT_PACIFISM, TRAUMA_TRAIT)
|
||||
REMOVE_TRAIT(owner, TRAIT_PACIFISM, TRAUMA_TRAIT)
|
||||
..()
|
||||
@@ -192,7 +192,7 @@
|
||||
return //no random switching
|
||||
|
||||
/datum/brain_trauma/severe/split_personality/brainwashing/on_hear(message, speaker, message_language, raw_message, radio_freq)
|
||||
if(owner.has_trait(TRAIT_DEAF) || owner == speaker)
|
||||
if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == speaker)
|
||||
return message
|
||||
if(findtext(message, codeword))
|
||||
message = replacetext(message, codeword, "<span class='warning'>[codeword]</span>")
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
if(ishuman(AM))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
if(H.has_trait(TRAIT_PIERCEIMMUNE))
|
||||
if(HAS_TRAIT(H, TRAIT_PIERCEIMMUNE))
|
||||
return
|
||||
|
||||
if((flags & CALTROP_IGNORE_WALKERS) && H.m_intent == MOVE_INTENT_WALK)
|
||||
@@ -46,7 +46,7 @@
|
||||
return
|
||||
|
||||
var/damage = rand(min_damage, max_damage)
|
||||
if(H.has_trait(TRAIT_LIGHT_STEP))
|
||||
if(HAS_TRAIT(H, TRAIT_LIGHT_STEP))
|
||||
damage *= 0.75
|
||||
H.apply_damage(damage, BRUTE, picked_def_zone)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
if (!wearer)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return
|
||||
if(!wearer.has_trait(TRAIT_DEAF))
|
||||
if(!HAS_TRAIT(wearer, TRAIT_DEAF))
|
||||
var/obj/item/organ/ears/ears = wearer.getorganslot(ORGAN_SLOT_EARS)
|
||||
if (ears)
|
||||
ears.deaf = max(ears.deaf - 1, (ears.ear_damage < UNHEALING_EAR_DAMAGE ? 0 : 1)) // Do not clear deafness while above the unhealing ear damage threshold
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
/datum/component/mood/Initialize()
|
||||
if(!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
|
||||
START_PROCESSING(SSmood, src)
|
||||
|
||||
RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event)
|
||||
@@ -150,17 +150,17 @@
|
||||
else
|
||||
owner.crit_threshold -= (holdmyinsanityeffect - insanity_effect)
|
||||
|
||||
if(owner.has_trait(TRAIT_DEPRESSION))
|
||||
if(HAS_TRAIT(owner, TRAIT_DEPRESSION))
|
||||
if(prob(0.05))
|
||||
add_event(null, "depression", /datum/mood_event/depression)
|
||||
clear_event(null, "jolly")
|
||||
if(owner.has_trait(TRAIT_JOLLY))
|
||||
if(HAS_TRAIT(owner, TRAIT_JOLLY))
|
||||
if(prob(0.05))
|
||||
add_event(null, "jolly", /datum/mood_event/jolly)
|
||||
clear_event(null, "depression")
|
||||
|
||||
holdmyinsanityeffect = insanity_effect
|
||||
|
||||
|
||||
HandleNutrition(owner)
|
||||
|
||||
/datum/component/mood/proc/DecreaseSanity(amount, minimum = SANITY_INSANE)
|
||||
|
||||
@@ -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)
|
||||
|
||||
22
code/datums/components/storage/concrete/emergency.dm
Normal file
22
code/datums/components/storage/concrete/emergency.dm
Normal file
@@ -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
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
var/gc_destroyed //Time when this object was destroyed.
|
||||
var/list/active_timers //for SStimer
|
||||
var/list/datum_components //for /datum/components
|
||||
var/list/status_traits
|
||||
var/list/comp_lookup //it used to be for looking up components which had registered a signal but now anything can register
|
||||
var/list/signal_procs
|
||||
var/signal_enabled = FALSE
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
/mob/living/carbon/AirborneContractDisease(datum/disease/D, force_spread)
|
||||
if(internal)
|
||||
return
|
||||
if(has_trait(TRAIT_NOBREATH))
|
||||
if(HAS_TRAIT(src, TRAIT_NOBREATH))
|
||||
return
|
||||
..()
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
|
||||
/mob/living/carbon/human/CanContractDisease(datum/disease/D)
|
||||
if(dna)
|
||||
if(has_trait(TRAIT_VIRUSIMMUNE) && !D.bypasses_immunity)
|
||||
if(HAS_TRAIT(src, TRAIT_VIRUSIMMUNE) && !D.bypasses_immunity)
|
||||
return FALSE
|
||||
|
||||
for(var/thing in D.required_organs)
|
||||
|
||||
@@ -233,7 +233,7 @@
|
||||
|
||||
/datum/symptom/heal/coma/CanHeal(datum/disease/advance/A)
|
||||
var/mob/living/M = A.affected_mob
|
||||
if(M.has_trait(TRAIT_DEATHCOMA))
|
||||
if(HAS_TRAIT(M, TRAIT_DEATHCOMA))
|
||||
return power
|
||||
else if(M.IsUnconscious() || M.stat == UNCONSCIOUS)
|
||||
return power * 0.9
|
||||
@@ -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
|
||||
|
||||
@@ -85,14 +85,14 @@
|
||||
if(4, 5)
|
||||
M.restoreEars()
|
||||
|
||||
if(M.has_trait(TRAIT_BLIND, EYE_DAMAGE))
|
||||
if(HAS_TRAIT_FROM(M, TRAIT_BLIND, EYE_DAMAGE))
|
||||
if(prob(20))
|
||||
to_chat(M, "<span class='notice'>Your vision slowly returns...</span>")
|
||||
M.cure_blind(EYE_DAMAGE)
|
||||
M.cure_nearsighted(EYE_DAMAGE)
|
||||
M.blur_eyes(35)
|
||||
|
||||
else if(M.has_trait(TRAIT_NEARSIGHT, EYE_DAMAGE))
|
||||
else if(HAS_TRAIT_FROM(M, TRAIT_NEARSIGHT, EYE_DAMAGE))
|
||||
to_chat(M, "<span class='notice'>You can finally focus your eyes on distant objects.</span>")
|
||||
M.cure_nearsighted(EYE_DAMAGE)
|
||||
M.blur_eyes(10)
|
||||
|
||||
@@ -61,7 +61,7 @@ Bonus
|
||||
M.become_nearsighted(EYE_DAMAGE)
|
||||
if(prob(eyes.eye_damage - 10 + 1))
|
||||
if(!remove_eyes)
|
||||
if(!M.has_trait(TRAIT_BLIND))
|
||||
if(!HAS_TRAIT(M, TRAIT_BLIND))
|
||||
to_chat(M, "<span class='userdanger'>You go blind!</span>")
|
||||
M.become_blind(EYE_DAMAGE)
|
||||
else
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(L.has_trait(TRAIT_EMOTEMUTE))
|
||||
if(HAS_TRAIT(L, TRAIT_EMOTEMUTE))
|
||||
return FALSE
|
||||
|
||||
/datum/emote/sound
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
|
||||
/obj/item/twohanded/bostaff/attack(mob/target, mob/living/user)
|
||||
add_fingerprint(user)
|
||||
if((user.has_trait(TRAIT_CLUMSY)) && prob(50))
|
||||
if((HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
|
||||
to_chat(user, "<span class ='warning'>You club yourself over the head with [src].</span>")
|
||||
user.Knockdown(60)
|
||||
if(ishuman(user))
|
||||
|
||||
@@ -125,3 +125,11 @@
|
||||
/datum/mood_event/surgery
|
||||
description = "<span class='boldwarning'>HE'S CUTTING ME OPEN!!</span>\n"
|
||||
mood_change = -8
|
||||
|
||||
/datum/mood_event/sad_empath
|
||||
description = "<span class='warning'>Someone seems upset...</span>\n"
|
||||
mood_change = -2
|
||||
timeout = 600
|
||||
|
||||
/datum/mood_event/sad_empath/add_effects(mob/sadtarget)
|
||||
description = "<span class='warning'>[sadtarget.name] seems upset...</span>\n"
|
||||
|
||||
@@ -75,3 +75,27 @@
|
||||
description = "<span class='nicegreen'>There is something soothing about this music.</span>\n"
|
||||
mood_change = 3
|
||||
timeout = 600
|
||||
|
||||
/datum/mood_event/betterhug
|
||||
description = "<span class='nicegreen'>Someone was very nice to me.</span>\n"
|
||||
mood_change = 3
|
||||
timeout = 3000
|
||||
|
||||
/datum/mood_event/betterhug/add_effects(mob/friend)
|
||||
description = "<span class='nicegreen'>[friend.name] was very nice to me.</span>\n"
|
||||
|
||||
/datum/mood_event/besthug
|
||||
description = "<span class='nicegreen'>Someone is great to be around, they make me feel so happy!</span>\n"
|
||||
mood_change = 5
|
||||
timeout = 3000
|
||||
|
||||
/datum/mood_event/besthug/add_effects(mob/friend)
|
||||
description = "<span class='nicegreen'>[friend.name] is great to be around, [friend.p_they()] makes me feel so happy!</span>\n"
|
||||
|
||||
/datum/mood_event/happy_empath
|
||||
description = "<span class='warning'>Someone seems happy!</span>\n"
|
||||
mood_change = 2
|
||||
timeout = 600
|
||||
|
||||
/datum/mood_event/happy_empath/add_effects(var/mob/happytarget)
|
||||
description = "<span class='warning'>[happytarget.name]'s happiness is infectious!</span>\n"
|
||||
|
||||
@@ -86,12 +86,12 @@
|
||||
/datum/mutation/human/clumsy/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.add_trait(TRAIT_CLUMSY, GENETIC_MUTATION)
|
||||
ADD_TRAIT(owner, TRAIT_CLUMSY, GENETIC_MUTATION)
|
||||
|
||||
/datum/mutation/human/clumsy/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.remove_trait(TRAIT_CLUMSY, GENETIC_MUTATION)
|
||||
REMOVE_TRAIT(owner, TRAIT_CLUMSY, GENETIC_MUTATION)
|
||||
|
||||
|
||||
//Tourettes causes you to randomly stand in place and shout.
|
||||
@@ -125,12 +125,12 @@
|
||||
/datum/mutation/human/deaf/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.add_trait(TRAIT_DEAF, GENETIC_MUTATION)
|
||||
ADD_TRAIT(owner, TRAIT_DEAF, GENETIC_MUTATION)
|
||||
|
||||
/datum/mutation/human/deaf/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.remove_trait(TRAIT_DEAF, GENETIC_MUTATION)
|
||||
REMOVE_TRAIT(owner, TRAIT_DEAF, GENETIC_MUTATION)
|
||||
|
||||
|
||||
//Monified turns you into a monkey.
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
/datum/mutation/human/cold_resistance/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.add_trait(TRAIT_RESISTCOLD, "cold_resistance")
|
||||
// owner.add_trait(TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
|
||||
ADD_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
|
||||
// ADD_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
|
||||
|
||||
/datum/mutation/human/cold_resistance/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.remove_trait(TRAIT_RESISTCOLD, "cold_resistance")
|
||||
// owner.remove_trait(TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
|
||||
REMOVE_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
|
||||
// REMOVE_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
|
||||
|
||||
/datum/mutation/human/cold_resistance/on_life(mob/living/carbon/human/owner)
|
||||
if(owner.getFireLoss())
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
/datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.add_trait(TRAIT_STUNIMMUNE, TRAIT_HULK)
|
||||
owner.add_trait(TRAIT_PUSHIMMUNE, TRAIT_HULK)
|
||||
ADD_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_HULK)
|
||||
ADD_TRAIT(owner, TRAIT_PUSHIMMUNE, TRAIT_HULK)
|
||||
owner.update_body_parts()
|
||||
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "hulk", /datum/mood_event/hulk)
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
/datum/mutation/human/hulk/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.remove_trait(TRAIT_STUNIMMUNE, TRAIT_HULK)
|
||||
owner.remove_trait(TRAIT_PUSHIMMUNE, TRAIT_HULK)
|
||||
REMOVE_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_HULK)
|
||||
REMOVE_TRAIT(owner, TRAIT_PUSHIMMUNE, TRAIT_HULK)
|
||||
owner.update_body_parts()
|
||||
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "hulk")
|
||||
|
||||
|
||||
@@ -30,12 +30,12 @@
|
||||
/datum/mutation/human/mute/on_acquiring(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.add_trait(TRAIT_MUTE, GENETIC_MUTATION)
|
||||
ADD_TRAIT(owner, TRAIT_MUTE, GENETIC_MUTATION)
|
||||
|
||||
/datum/mutation/human/mute/on_losing(mob/living/carbon/human/owner)
|
||||
if(..())
|
||||
return
|
||||
owner.remove_trait(TRAIT_MUTE, GENETIC_MUTATION)
|
||||
REMOVE_TRAIT(owner, TRAIT_MUTE, GENETIC_MUTATION)
|
||||
|
||||
|
||||
/datum/mutation/human/smile
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
switch(M.lingcheck())
|
||||
if (LINGHIVE_LING)
|
||||
var/mob/living/L = M
|
||||
if (!L.has_trait(CHANGELING_HIVEMIND_MUTE))
|
||||
if (!HAS_TRAIT(L, CHANGELING_HIVEMIND_MUTE))
|
||||
to_chat(M, msg)
|
||||
if(LINGHIVE_LINK)
|
||||
to_chat(M, msg)
|
||||
@@ -35,7 +35,7 @@
|
||||
if(prob(40))
|
||||
to_chat(M, "<i><font color=#800080>We can faintly sense an outsider trying to communicate through the hivemind...</font></i>")
|
||||
if(LINGHIVE_LING)
|
||||
if (user.has_trait(CHANGELING_HIVEMIND_MUTE))
|
||||
if (HAS_TRAIT(user, CHANGELING_HIVEMIND_MUTE))
|
||||
to_chat(user, "<span class='warning'>The poison in the air hinders our ability to interact with the hivemind.</span>")
|
||||
return FALSE
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
@@ -52,7 +52,7 @@
|
||||
to_chat(M, msg)
|
||||
if(LINGHIVE_LING)
|
||||
var/mob/living/L = M
|
||||
if (!L.has_trait(CHANGELING_HIVEMIND_MUTE))
|
||||
if (!HAS_TRAIT(L, CHANGELING_HIVEMIND_MUTE))
|
||||
to_chat(M, msg)
|
||||
if(LINGHIVE_OUTSIDER)
|
||||
if(prob(40))
|
||||
|
||||
@@ -465,13 +465,13 @@
|
||||
|
||||
/datum/status_effect/hippocraticOath/on_apply()
|
||||
//Makes the user passive, it's in their oath not to harm!
|
||||
owner.add_trait(TRAIT_PACIFISM, "hippocraticOath")
|
||||
ADD_TRAIT(owner, TRAIT_PACIFISM, "hippocraticOath")
|
||||
var/datum/atom_hud/H = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
H.add_hud_to(owner)
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/hippocraticOath/on_remove()
|
||||
owner.remove_trait(TRAIT_PACIFISM, "hippocraticOath")
|
||||
REMOVE_TRAIT(owner, TRAIT_PACIFISM, "hippocraticOath")
|
||||
var/datum/atom_hud/H = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
H.remove_hud_from(owner)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
to_chat(quirk_holder, gain_text)
|
||||
quirk_holder.roundstart_quirks += src
|
||||
if(mob_trait)
|
||||
quirk_holder.add_trait(mob_trait, ROUNDSTART_TRAIT)
|
||||
ADD_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
|
||||
START_PROCESSING(SSquirks, src)
|
||||
add()
|
||||
if(spawn_effects)
|
||||
@@ -35,7 +35,7 @@
|
||||
to_chat(quirk_holder, lose_text)
|
||||
quirk_holder.roundstart_quirks -= src
|
||||
if(mob_trait)
|
||||
quirk_holder.remove_trait(mob_trait, ROUNDSTART_TRAIT, TRUE)
|
||||
REMOVE_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
|
||||
SSquirks.quirk_objects -= src
|
||||
return ..()
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
quirk_holder.roundstart_quirks -= src
|
||||
to_mob.roundstart_quirks += src
|
||||
if(mob_trait)
|
||||
quirk_holder.remove_trait(mob_trait, ROUNDSTART_TRAIT)
|
||||
to_mob.add_trait(mob_trait, ROUNDSTART_TRAIT)
|
||||
REMOVE_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
|
||||
ADD_TRAIT(to_mob, mob_trait, ROUNDSTART_TRAIT)
|
||||
quirk_holder = to_mob
|
||||
on_transfer()
|
||||
|
||||
@@ -111,7 +111,7 @@ Use this as a guideline
|
||||
|
||||
mob_trait = TRAIT_NEARSIGHT
|
||||
///This define is in __DEFINES/traits.dm and is the actual "trait" that the game tracks
|
||||
///You'll need to use "has_trait(X, sources)" checks around the code to check this; for instance, the Ageusia trait is checked in taste code
|
||||
///You'll need to use "HAS_TRAIT_FROM(src, X, sources)" checks around the code to check this; for instance, the Ageusia trait is checked in taste code
|
||||
///If you need help finding where to put it, the declaration finder on GitHub is the best way to locate it
|
||||
|
||||
gain_text = "<span class='danger'>Things far away from you start looking blurry.</span>"
|
||||
|
||||
@@ -35,6 +35,14 @@
|
||||
lose_text = "<span class='danger'>You no longer feel like drinking would ease your pain.</span>"
|
||||
medical_record_text = "Patient has unusually efficient liver metabolism and can slowly regenerate wounds by drinking alcoholic beverages."
|
||||
|
||||
/datum/quirk/empath
|
||||
name = "Empath"
|
||||
desc = "Whether it's a sixth sense or careful study of body language, it only takes you a quick glance at someone to understand how they feel."
|
||||
value = 2
|
||||
mob_trait = TRAIT_EMPATH
|
||||
gain_text = "<span class='notice'>You feel in tune with those around you.</span>"
|
||||
lose_text = "<span class='danger'>You feel isolated from others.</span>"
|
||||
|
||||
/datum/quirk/freerunning
|
||||
name = "Freerunning"
|
||||
desc = "You're great at quick moves! You can climb tables more quickly."
|
||||
@@ -43,6 +51,15 @@
|
||||
gain_text = "<span class='notice'>You feel lithe on your feet!</span>"
|
||||
lose_text = "<span class='danger'>You feel clumsy again.</span>"
|
||||
|
||||
/datum/quirk/friendly
|
||||
name = "Friendly"
|
||||
desc = "You give the best hugs, especially when you're in the right mood."
|
||||
value = 1
|
||||
mob_trait = TRAIT_FRIENDLY
|
||||
gain_text = "<span class='notice'>You want to hug someone.</span>"
|
||||
lose_text = "<span class='danger'>You no longer feel compelled to hug others.</span>"
|
||||
mood_quirk = TRUE
|
||||
|
||||
/datum/quirk/jolly
|
||||
name = "Jolly"
|
||||
desc = "You sometimes just feel happy, for no reason at all."
|
||||
|
||||
@@ -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>"
|
||||
@@ -33,7 +33,7 @@
|
||||
if(prob(40))
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.dna && !H.has_trait(TRAIT_RADIMMUNE))
|
||||
if(H.dna && !HAS_TRAIT(H, TRAIT_RADIMMUNE))
|
||||
if(prob(max(0,100-resist)))
|
||||
H.randmuti()
|
||||
if(prob(50))
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
var/flags_1 = NONE
|
||||
var/interaction_flags_atom = NONE
|
||||
var/container_type = NONE
|
||||
var/datum/reagents/reagents = null
|
||||
|
||||
//This atom's HUD (med/sec, etc) images. Associative list.
|
||||
@@ -203,16 +202,16 @@
|
||||
return is_refillable() && is_drainable()
|
||||
|
||||
/atom/proc/is_injectable(allowmobs = TRUE)
|
||||
return reagents && (container_type & (INJECTABLE | REFILLABLE))
|
||||
return reagents && (reagents.reagents_holder_flags & (INJECTABLE | REFILLABLE))
|
||||
|
||||
/atom/proc/is_drawable(allowmobs = TRUE)
|
||||
return reagents && (container_type & (DRAWABLE | DRAINABLE))
|
||||
return reagents && (reagents.reagents_holder_flags & (DRAWABLE | DRAINABLE))
|
||||
|
||||
/atom/proc/is_refillable()
|
||||
return reagents && (container_type & REFILLABLE)
|
||||
return reagents && (reagents.reagents_holder_flags & REFILLABLE)
|
||||
|
||||
/atom/proc/is_drainable()
|
||||
return reagents && (container_type & DRAINABLE)
|
||||
return reagents && (reagents.reagents_holder_flags & DRAINABLE)
|
||||
|
||||
|
||||
/atom/proc/AllowDrop()
|
||||
@@ -261,7 +260,7 @@
|
||||
to_chat(user, desc)
|
||||
|
||||
if(reagents)
|
||||
if(container_type & TRANSPARENT)
|
||||
if(reagents.reagents_holder_flags & TRANSPARENT)
|
||||
to_chat(user, "It contains:")
|
||||
if(reagents.reagent_list.len)
|
||||
if(user.can_see_reagents()) //Show each individual reagent
|
||||
@@ -274,7 +273,7 @@
|
||||
to_chat(user, "[total_volume] units of various reagents")
|
||||
else
|
||||
to_chat(user, "Nothing.")
|
||||
else if(container_type & AMOUNT_VISIBLE)
|
||||
else if(reagents.reagents_holder_flags & AMOUNT_VISIBLE)
|
||||
if(reagents.total_volume)
|
||||
to_chat(user, "<span class='notice'>It has [reagents.total_volume] unit\s left.</span>")
|
||||
else
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
var/atom/movable/pulling
|
||||
var/grab_state = 0
|
||||
var/throwforce = 0
|
||||
var/can_be_z_moved = TRUE
|
||||
|
||||
/atom/movable/vv_edit_var(var_name, var_value)
|
||||
var/static/list/banned_edits = list("step_x", "step_y", "step_size")
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
|
||||
//helper for getting the appropriate health status
|
||||
/proc/RoundHealth(mob/living/M)
|
||||
if(M.stat == DEAD || (M.has_trait(TRAIT_FAKEDEATH)))
|
||||
if(M.stat == DEAD || (HAS_TRAIT(M, TRAIT_FAKEDEATH)))
|
||||
return "health-100" //what's our health? it doesn't matter, we're dead, or faking
|
||||
var/maxi_health = M.maxHealth
|
||||
if(iscarbon(M) && M.health < 0)
|
||||
@@ -172,7 +172,7 @@
|
||||
var/image/holder = hud_list[STATUS_HUD]
|
||||
var/icon/I = icon(icon, icon_state, dir)
|
||||
holder.pixel_y = I.Height() - world.icon_size
|
||||
if(stat == DEAD || (has_trait(TRAIT_FAKEDEATH)))
|
||||
if(stat == DEAD || (HAS_TRAIT(src, TRAIT_FAKEDEATH)))
|
||||
holder.icon_state = "huddead"
|
||||
else
|
||||
holder.icon_state = "hudhealthy"
|
||||
@@ -182,9 +182,9 @@
|
||||
var/icon/I = icon(icon, icon_state, dir)
|
||||
var/virus_threat = check_virus()
|
||||
holder.pixel_y = I.Height() - world.icon_size
|
||||
if(has_trait(TRAIT_XENO_HOST))
|
||||
if(HAS_TRAIT(src, TRAIT_XENO_HOST))
|
||||
holder.icon_state = "hudxeno"
|
||||
else if(stat == DEAD || (has_trait(TRAIT_FAKEDEATH)))
|
||||
else if(stat == DEAD || (HAS_TRAIT(src, TRAIT_FAKEDEATH)))
|
||||
if(tod)
|
||||
var/tdelta = round(world.time - timeofdeath)
|
||||
if(tdelta < (DEFIB_TIME_LIMIT * 10))
|
||||
@@ -242,7 +242,7 @@
|
||||
var/icon/IC = icon(icon, icon_state, dir)
|
||||
holder.pixel_y = IC.Height() - world.icon_size
|
||||
holder.icon_state = "hud_imp_chem"
|
||||
if(has_trait(TRAIT_MINDSHIELD))
|
||||
if(HAS_TRAIT(src, TRAIT_MINDSHIELD))
|
||||
holder = hud_list[IMPLOYAL_HUD]
|
||||
var/icon/IC = icon(icon, icon_state, dir)
|
||||
holder.pixel_y = IC.Height() - world.icon_size
|
||||
|
||||
@@ -64,7 +64,7 @@ Credit where due:
|
||||
return FALSE
|
||||
if(isliving(M))
|
||||
var/mob/living/L = M
|
||||
if(L.has_trait(TRAIT_MINDSHIELD))
|
||||
if(HAS_TRAIT(L, TRAIT_MINDSHIELD))
|
||||
return FALSE
|
||||
if(ishuman(M) || isbrain(M) || isguardian(M) || issilicon(M) || isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab) || istype(M, /mob/camera/eminence))
|
||||
return TRUE
|
||||
@@ -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
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
return FALSE
|
||||
else
|
||||
return FALSE
|
||||
if(M.has_trait(TRAIT_MINDSHIELD) || issilicon(M) || isbot(M) || isdrone(M) || is_servant_of_ratvar(M) || !M.client)
|
||||
if(HAS_TRAIT(M, TRAIT_MINDSHIELD) || issilicon(M) || isbot(M) || isdrone(M) || is_servant_of_ratvar(M) || !M.client)
|
||||
return FALSE //can't convert machines, shielded, braindead, or ratvar's dogs
|
||||
return 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
|
||||
|
||||
|
||||
|
||||
@@ -182,11 +182,11 @@
|
||||
|
||||
//Get the clone body ready
|
||||
maim_clone(H)
|
||||
H.add_trait(TRAIT_STABLEHEART, "cloning")
|
||||
H.add_trait(TRAIT_EMOTEMUTE, "cloning")
|
||||
H.add_trait(TRAIT_MUTE, "cloning")
|
||||
H.add_trait(TRAIT_NOBREATH, "cloning")
|
||||
H.add_trait(TRAIT_NOCRITDAMAGE, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_MUTE, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
|
||||
H.Unconscious(80)
|
||||
|
||||
clonemind.transfer_to(H)
|
||||
@@ -361,11 +361,11 @@
|
||||
if(!mob_occupant)
|
||||
return
|
||||
|
||||
mob_occupant.remove_trait(TRAIT_STABLEHEART, "cloning")
|
||||
mob_occupant.remove_trait(TRAIT_EMOTEMUTE, "cloning")
|
||||
mob_occupant.remove_trait(TRAIT_MUTE, "cloning")
|
||||
mob_occupant.remove_trait(TRAIT_NOCRITDAMAGE, "cloning")
|
||||
mob_occupant.remove_trait(TRAIT_NOBREATH, "cloning")
|
||||
REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, "cloning")
|
||||
REMOVE_TRAIT(mob_occupant, TRAIT_EMOTEMUTE, "cloning")
|
||||
REMOVE_TRAIT(mob_occupant, TRAIT_MUTE, "cloning")
|
||||
REMOVE_TRAIT(mob_occupant, TRAIT_NOCRITDAMAGE, "cloning")
|
||||
REMOVE_TRAIT(mob_occupant, TRAIT_NOBREATH, "cloning")
|
||||
|
||||
if(grab_ghost_when == CLONER_MATURE_CLONE)
|
||||
mob_occupant.grab_ghost()
|
||||
@@ -452,7 +452,7 @@
|
||||
|
||||
// brain function, they also have no limbs or internal organs.
|
||||
|
||||
if(!H.has_trait(TRAIT_NODISMEMBER))
|
||||
if(!HAS_TRAIT(H, TRAIT_NODISMEMBER))
|
||||
var/static/list/zones = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
|
||||
for(var/zone in zones)
|
||||
var/obj/item/bodypart/BP = H.get_bodypart(zone)
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#define ARCADE_WEIGHT_TRICK 4
|
||||
#define ARCADE_WEIGHT_USELESS 2
|
||||
#define ARCADE_WEIGHT_RARE 1
|
||||
|
||||
|
||||
/obj/machinery/computer/arcade
|
||||
name = "random arcade"
|
||||
desc = "random arcade machine"
|
||||
@@ -6,55 +11,66 @@
|
||||
icon_screen = "invaders"
|
||||
clockwork = TRUE //it'd look weird
|
||||
var/list/prizes = list(
|
||||
/obj/item/storage/box/snappops = 8,
|
||||
/obj/item/toy/talking/AI = 8,
|
||||
/obj/item/toy/talking/codex_gigas = 8,
|
||||
/obj/item/clothing/under/syndicate/tacticool = 8,
|
||||
/obj/item/toy/sword = 8,
|
||||
/obj/item/toy/gun = 8,
|
||||
/obj/item/gun/ballistic/shotgun/toy/crossbow = 8,
|
||||
/obj/item/storage/box/fakesyndiesuit = 8,
|
||||
/obj/item/storage/crayons = 8,
|
||||
/obj/item/toy/spinningtoy = 8,
|
||||
/obj/item/toy/prize/ripley = 4,
|
||||
/obj/item/toy/prize/fireripley = 4,
|
||||
/obj/item/toy/prize/deathripley = 4,
|
||||
/obj/item/toy/prize/gygax = 4,
|
||||
/obj/item/toy/prize/durand = 4,
|
||||
/obj/item/toy/prize/honk = 4,
|
||||
/obj/item/toy/prize/marauder = 4,
|
||||
/obj/item/toy/prize/seraph = 4,
|
||||
/obj/item/toy/prize/mauler = 4,
|
||||
/obj/item/toy/prize/odysseus = 4,
|
||||
/obj/item/toy/prize/phazon = 4,
|
||||
/obj/item/toy/prize/reticence = 4,
|
||||
/obj/item/toy/cards/deck = 8,
|
||||
/obj/item/toy/nuke = 8,
|
||||
/obj/item/toy/minimeteor = 8,
|
||||
/obj/item/toy/redbutton = 8,
|
||||
/obj/item/toy/talking/owl = 8,
|
||||
/obj/item/toy/talking/griffin = 8,
|
||||
/obj/item/coin/antagtoken = 8,
|
||||
/obj/item/stack/tile/fakespace/loaded = 8,
|
||||
/obj/item/stack/tile/fakepit/loaded = 8,
|
||||
/obj/item/toy/toy_xeno = 8,
|
||||
/obj/item/storage/box/actionfigure = 4,
|
||||
/obj/item/restraints/handcuffs/fake = 8,
|
||||
/obj/item/grenade/chem_grenade/glitter/pink = 4,
|
||||
/obj/item/grenade/chem_grenade/glitter/blue = 4,
|
||||
/obj/item/grenade/chem_grenade/glitter/white = 4,
|
||||
/obj/item/toy/eightball = 8,
|
||||
/obj/item/toy/windupToolbox = 8,
|
||||
/obj/item/toy/clockwork_watch = 8,
|
||||
/obj/item/toy/toy_dagger = 8,
|
||||
/obj/item/extendohand/acme = 4,
|
||||
/obj/item/hot_potato/harmless/toy = 4,
|
||||
/obj/item/card/emagfake = 4,
|
||||
/obj/item/clothing/shoes/wheelys = 8,
|
||||
/obj/item/clothing/shoes/kindleKicks = 8,
|
||||
/obj/item/storage/belt/military/snack = 8,
|
||||
/obj/item/toy/plush/random = 450
|
||||
)//plushies have a 0.6 chance
|
||||
/obj/item/toy/balloon = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/beach_ball = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/cattoy = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/clockwork_watch = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/dummy = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/eightball = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/eightball/haunted = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/storage/box/actionfigure = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/foamblade = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/gun = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/gun/justicar = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/gun/m41 = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/katana = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/minimeteor = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/nuke = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/plush/random = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/redbutton = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/spinningtoy = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/sword = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/sword/cx = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/sword/darksabre = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/talking/AI = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/talking/codex_gigas = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/talking/griffin = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/talking/owl = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/toy_dagger = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/toy_xeno = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/toy/windupToolbox = ARCADE_WEIGHT_TRICK,
|
||||
|
||||
/obj/item/twohanded/dualsaber/toy = ARCADE_WEIGHT_RARE,
|
||||
/mob/living/simple_animal/bot/secbot/grievous/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/clothing/mask/facehugger/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/gun/ballistic/automatic/toy/pistol/unrestricted = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/hot_potato/harmless/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/twohanded/dualsaber/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/twohanded/hypereutactic/toy = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/twohanded/hypereutactic/toy/rainbow = ARCADE_WEIGHT_RARE,
|
||||
|
||||
/obj/item/storage/box/snappops = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/clothing/under/syndicate/tacticool = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/gun/ballistic/shotgun/toy/crossbow = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/storage/box/fakesyndiesuit = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/storage/crayons = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/coin/antagtoken = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/stack/tile/fakespace/loaded = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/stack/tile/fakepit/loaded = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/restraints/handcuffs/fake = ARCADE_WEIGHT_TRICK,
|
||||
|
||||
/obj/item/grenade/chem_grenade/glitter/pink = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/grenade/chem_grenade/glitter/blue = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/grenade/chem_grenade/glitter/white = ARCADE_WEIGHT_TRICK,
|
||||
|
||||
/obj/item/extendohand/acme = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/card/emagfake = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/clothing/shoes/wheelys = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/clothing/shoes/kindleKicks = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/storage/belt/military/snack = ARCADE_WEIGHT_RARE,
|
||||
|
||||
/obj/item/clothing/mask/fakemoustache/italian = ARCADE_WEIGHT_RARE
|
||||
)
|
||||
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
|
||||
@@ -74,7 +90,8 @@
|
||||
|
||||
/obj/machinery/computer/arcade/proc/prizevend(mob/user)
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade)
|
||||
if(prob(0.0001)) //1 in a million
|
||||
|
||||
if(prob(1) && prob(1) && prob(1)) //Proper 1 in a million
|
||||
new /obj/item/gun/energy/pulse/prize(src)
|
||||
SSmedals.UnlockMedal(MEDAL_PULSE, usr.client)
|
||||
|
||||
@@ -124,6 +141,8 @@
|
||||
var/blocked = FALSE //Player cannot attack/heal while set
|
||||
var/turtle = 0
|
||||
|
||||
var/turn_speed = 5 //Measured in deciseconds.
|
||||
|
||||
/obj/machinery/computer/arcade/battle/Reset()
|
||||
var/name_action
|
||||
var/name_part1
|
||||
@@ -172,7 +191,7 @@
|
||||
if(turtle > 0)
|
||||
turtle--
|
||||
|
||||
sleep(10)
|
||||
sleep(turn_speed)
|
||||
enemy_hp -= attackamt
|
||||
arcade_action(usr)
|
||||
|
||||
@@ -185,7 +204,7 @@
|
||||
updateUsrDialog()
|
||||
turtle++
|
||||
|
||||
sleep(10)
|
||||
sleep(turn_speed)
|
||||
player_mp -= pointamt
|
||||
player_hp += healamt
|
||||
blocked = TRUE
|
||||
@@ -202,7 +221,7 @@
|
||||
turtle--
|
||||
|
||||
updateUsrDialog()
|
||||
sleep(10)
|
||||
sleep(turn_speed)
|
||||
arcade_action(usr)
|
||||
|
||||
if (href_list["close"])
|
||||
@@ -211,10 +230,10 @@
|
||||
|
||||
else if (href_list["newgame"]) //Reset everything
|
||||
temp = "New Round"
|
||||
player_hp = 30
|
||||
player_mp = 10
|
||||
enemy_hp = 45
|
||||
enemy_mp = 20
|
||||
player_hp = initial(player_hp)
|
||||
player_mp = initial(player_mp)
|
||||
enemy_hp = initial(enemy_hp)
|
||||
enemy_mp = initial(enemy_mp)
|
||||
gameover = FALSE
|
||||
turtle = 0
|
||||
|
||||
@@ -260,7 +279,7 @@
|
||||
|
||||
if (player_mp <= 0)
|
||||
gameover = TRUE
|
||||
sleep(10)
|
||||
sleep(turn_speed)
|
||||
temp = "You have been drained! GAME OVER"
|
||||
playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10)
|
||||
if(obj_flags & EMAGGED)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -450,7 +450,7 @@
|
||||
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if((mob_occupant.has_trait(TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
|
||||
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
|
||||
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
return
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
if(connected && connected.is_operational())
|
||||
if(connected.occupant) //set occupant_status message
|
||||
viable_occupant = connected.occupant
|
||||
if(viable_occupant.has_dna() && !viable_occupant.has_trait(TRAIT_RADIMMUNE) && !viable_occupant.has_trait(TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification
|
||||
if(viable_occupant.has_dna() && !HAS_TRAIT(viable_occupant, TRAIT_RADIMMUNE) && !HAS_TRAIT(viable_occupant, TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification
|
||||
occupant_status += "[viable_occupant.name] => "
|
||||
switch(viable_occupant.stat)
|
||||
if(CONSCIOUS)
|
||||
@@ -523,7 +523,7 @@
|
||||
var/mob/living/carbon/viable_occupant = null
|
||||
if(connected)
|
||||
viable_occupant = connected.occupant
|
||||
if(!istype(viable_occupant) || !viable_occupant.dna || viable_occupant.has_trait(TRAIT_RADIMMUNE) || viable_occupant.has_trait(TRAIT_NOCLONE))
|
||||
if(!istype(viable_occupant) || !viable_occupant.dna || HAS_TRAIT(viable_occupant, TRAIT_RADIMMUNE) || HAS_TRAIT(viable_occupant, TRAIT_NOCLONE))
|
||||
viable_occupant = null
|
||||
return viable_occupant
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
|
||||
if(istype(mob_occupant))
|
||||
if(locate_computer(/obj/machinery/computer/cloning))
|
||||
if(!mob_occupant.suiciding && !(mob_occupant.has_trait(TRAIT_NOCLONE)) && !mob_occupant.hellbound)
|
||||
if(!mob_occupant.suiciding && !(HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && !mob_occupant.hellbound)
|
||||
mob_occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src)
|
||||
|
||||
// DNA manipulators cannot operate on severed heads or brains
|
||||
|
||||
@@ -763,7 +763,7 @@
|
||||
|
||||
if(ishuman(user) && prob(40) && src.density)
|
||||
var/mob/living/carbon/human/H = user
|
||||
if((H.has_trait(TRAIT_DUMB)) && Adjacent(user))
|
||||
if((HAS_TRAIT(H, TRAIT_DUMB)) && Adjacent(user))
|
||||
playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
|
||||
if(!istype(H.head, /obj/item/clothing/head/helmet))
|
||||
H.visible_message("<span class='danger'>[user] headbutts the airlock.</span>", \
|
||||
|
||||
@@ -42,11 +42,11 @@
|
||||
icon_state = "pod_1"
|
||||
//Get the clone body ready
|
||||
maim_clone(H)
|
||||
H.add_trait(TRAIT_STABLEHEART, "cloning")
|
||||
H.add_trait(TRAIT_EMOTEMUTE, "cloning")
|
||||
H.add_trait(TRAIT_MUTE, "cloning")
|
||||
H.add_trait(TRAIT_NOBREATH, "cloning")
|
||||
H.add_trait(TRAIT_NOCRITDAMAGE, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_MUTE, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
|
||||
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
|
||||
H.Unconscious(80)
|
||||
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
|
||||
@@ -268,7 +268,7 @@
|
||||
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
if((mob_occupant.has_trait(TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
|
||||
if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2))
|
||||
scantemp = "<font class='bad'>Subject no longer contains the fundamental materials required to create a living clone.</font>"
|
||||
playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
return
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
say("Subject is not organic.")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1)
|
||||
return
|
||||
if(!allow_living && !(C.stat == DEAD || C.has_trait(TRAIT_FAKEDEATH))) //I mean, the machines scanners arent advanced enough to tell you're alive
|
||||
if(!allow_living && !(C.stat == DEAD || HAS_TRAIT(C, TRAIT_FAKEDEATH))) //I mean, the machines scanners arent advanced enough to tell you're alive
|
||||
say("Subject is still alive.")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1)
|
||||
return
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
icon = 'icons/obj/machines/limbgrower.dmi'
|
||||
icon_state = "limbgrower_idleoff"
|
||||
density = TRUE
|
||||
container_type = OPENCONTAINER
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 10
|
||||
active_power_usage = 100
|
||||
@@ -34,7 +33,7 @@
|
||||
)
|
||||
|
||||
/obj/machinery/limbgrower/Initialize()
|
||||
create_reagents(100)
|
||||
create_reagents(100, OPENCONTAINER)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/limbgrower
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -485,7 +485,7 @@
|
||||
threatcount += 4
|
||||
|
||||
if(shoot_unloyal)
|
||||
if (!perp.has_trait(TRAIT_MINDSHIELD))
|
||||
if (!HAS_TRAIT(perp, TRAIT_MINDSHIELD))
|
||||
threatcount += 4
|
||||
|
||||
return threatcount
|
||||
|
||||
@@ -257,8 +257,7 @@
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Initialize()
|
||||
. = ..()
|
||||
create_reagents(max_volume)
|
||||
reagents.set_reacting(FALSE)
|
||||
create_reagents(max_volume, NO_REACT)
|
||||
syringes = new
|
||||
known_reagents = list("epinephrine"="Epinephrine","charcoal"="Charcoal")
|
||||
processed_reagents = new
|
||||
@@ -274,7 +273,7 @@
|
||||
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/critfail()
|
||||
..()
|
||||
if(reagents)
|
||||
reagents.set_reacting(TRUE)
|
||||
DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/can_attach(obj/mecha/medical/M)
|
||||
if(..())
|
||||
|
||||
@@ -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()
|
||||
@@ -446,13 +445,13 @@
|
||||
var/mob/living/L = user
|
||||
if(!Adjacent(target))
|
||||
if(selected && selected.is_ranged())
|
||||
if(L.has_trait(TRAIT_PACIFISM) && selected.harmful)
|
||||
if(HAS_TRAIT(L, TRAIT_PACIFISM) && selected.harmful)
|
||||
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
|
||||
return
|
||||
if(selected.action(target,params))
|
||||
selected.start_cooldown()
|
||||
else if(selected && selected.is_melee())
|
||||
if(isliving(target) && selected.harmful && L.has_trait(TRAIT_PACIFISM))
|
||||
if(isliving(target) && selected.harmful && HAS_TRAIT(L, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
|
||||
return
|
||||
if(selected.action(target,params))
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
..()
|
||||
if(ishuman(O))
|
||||
var/mob/living/carbon/human/H = O
|
||||
if(H.shoes && blood_state && bloodiness && !H.has_trait(TRAIT_LIGHT_STEP))
|
||||
if(H.shoes && blood_state && bloodiness && !HAS_TRAIT(H, TRAIT_LIGHT_STEP))
|
||||
var/obj/item/clothing/shoes/S = H.shoes
|
||||
var/add_blood = 0
|
||||
if(bloodiness >= BLOOD_GAIN_PER_STEP)
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/Crossed(mob/living/L)
|
||||
if(istype(L) && has_gravity(loc))
|
||||
playsound(loc, 'sound/effects/gib_step.ogg', L.has_trait(TRAIT_LIGHT_STEP) ? 20 : 50, 1)
|
||||
playsound(loc, 'sound/effects/gib_step.ogg', HAS_TRAIT(L, TRAIT_LIGHT_STEP) ? 20 : 50, 1)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
if(!victim.client || !istype(victim))
|
||||
return
|
||||
to_chat(victim, "<span class='notice'>You feel fast!</span>")
|
||||
victim.add_trait(TRAIT_GOTTAGOREALLYFAST, "yellow_orb")
|
||||
ADD_TRAIT(victim, TRAIT_GOTTAGOREALLYFAST, "yellow_orb")
|
||||
sleep(duration)
|
||||
victim.remove_trait(TRAIT_GOTTAGOREALLYFAST, "yellow_orb")
|
||||
REMOVE_TRAIT(victim, TRAIT_GOTTAGOREALLYFAST, "yellow_orb")
|
||||
to_chat(victim, "<span class='notice'>You slow down.</span>")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -256,7 +256,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
can_handle_hot = TRUE
|
||||
else if(C.gloves && (C.gloves.max_heat_protection_temperature > 360))
|
||||
can_handle_hot = TRUE
|
||||
else if(C.has_trait(TRAIT_RESISTHEAT) || C.has_trait(TRAIT_RESISTHEATHANDS))
|
||||
else if(HAS_TRAIT(C, TRAIT_RESISTHEAT) || HAS_TRAIT(C, TRAIT_RESISTHEATHANDS))
|
||||
can_handle_hot = TRUE
|
||||
|
||||
if(can_handle_hot)
|
||||
@@ -449,10 +449,10 @@ 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))
|
||||
if(HAS_TRAIT(user, 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))
|
||||
if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
|
||||
M = user
|
||||
var/is_human_victim = 0
|
||||
var/obj/item/bodypart/affecting = M.get_bodypart(BODY_ZONE_HEAD)
|
||||
@@ -523,7 +523,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
M.adjust_blurriness(15)
|
||||
if(M.stat != DEAD)
|
||||
to_chat(M, "<span class='danger'>Your eyes start to bleed profusely!</span>")
|
||||
if(!(M.has_trait(TRAIT_BLIND) || M.has_trait(TRAIT_NEARSIGHT)))
|
||||
if(!(HAS_TRAIT(M, TRAIT_BLIND) || HAS_TRAIT(M, TRAIT_NEARSIGHT)))
|
||||
to_chat(M, "<span class='danger'>You become nearsighted!</span>")
|
||||
M.become_nearsighted(EYE_DAMAGE)
|
||||
if(prob(50))
|
||||
|
||||
@@ -161,13 +161,18 @@ RLD
|
||||
user.visible_message("<span class='suicide'>[user] sets the RCD to 'Wall' and points it down [user.p_their()] throat! It looks like [user.p_theyre()] trying to commit suicide..</span>")
|
||||
return (BRUTELOSS)
|
||||
|
||||
/obj/item/construction/rcd/verb/toggle_window_type()
|
||||
set name = "Toggle Window Type"
|
||||
/obj/item/construction/rcd/verb/toggle_window_type_verb()
|
||||
set name = "RCD : Toggle Window Type"
|
||||
set category = "Object"
|
||||
set src in usr // What does this do?
|
||||
set src in view(1)
|
||||
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
|
||||
toggle_window_type(usr)
|
||||
|
||||
/obj/item/construction/rcd/proc/toggle_window_type(mob/user)
|
||||
var/window_type_name
|
||||
|
||||
if (window_type == /obj/structure/window/fulltile)
|
||||
window_type = /obj/structure/window/reinforced/fulltile
|
||||
window_type_name = "reinforced glass"
|
||||
@@ -175,17 +180,14 @@ RLD
|
||||
window_type = /obj/structure/window/fulltile
|
||||
window_type_name = "glass"
|
||||
|
||||
to_chat(usr, "<span class='notice'>You change \the [src]'s window mode to [window_type_name].</span>")
|
||||
to_chat(user, "<span class='notice'>You change \the [src]'s window mode to [window_type_name].</span>")
|
||||
|
||||
/obj/item/construction/rcd/verb/change_airlock_access()
|
||||
set name = "Change Airlock Access"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
/obj/item/construction/rcd/verb/change_airlock_access(mob/user)
|
||||
|
||||
if (!ishuman(usr) && !usr.has_unlimited_silicon_privilege)
|
||||
return ..(usr)
|
||||
if (!ishuman(user) && !user.has_unlimited_silicon_privilege)
|
||||
return
|
||||
|
||||
var/t1 = text("")
|
||||
var/t1 = ""
|
||||
|
||||
|
||||
if(use_one_access)
|
||||
@@ -216,24 +218,23 @@ RLD
|
||||
|
||||
t1 += "<p><a href='?src=[REF(src)];close=1'>Close</a></p>\n"
|
||||
|
||||
var/datum/browser/popup = new(usr, "airlock_electronics", "Access Control", 900, 500)
|
||||
var/datum/browser/popup = new(user, "rcd_access", "Access Control", 900, 500)
|
||||
popup.set_content(t1)
|
||||
popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
onclose(usr, "airlock")
|
||||
onclose(user, "rcd_access")
|
||||
|
||||
/obj/item/construction/rcd/Topic(href, href_list)
|
||||
..()
|
||||
if (usr.stat || usr.restrained())
|
||||
return
|
||||
if (href_list["close"])
|
||||
usr << browse(null, "window=airlock")
|
||||
usr << browse(null, "window=rcd_access")
|
||||
return
|
||||
|
||||
if (href_list["access"])
|
||||
toggle_access(href_list["access"])
|
||||
|
||||
change_airlock_access()
|
||||
change_airlock_access(usr)
|
||||
|
||||
/obj/item/construction/rcd/proc/toggle_access(acc)
|
||||
if (acc == "all")
|
||||
@@ -253,16 +254,77 @@ RLD
|
||||
if (!conf_access.len)
|
||||
conf_access = null
|
||||
|
||||
/obj/item/construction/rcd/verb/change_airlock_setting()
|
||||
set name = "Change Airlock Setting"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
/obj/item/construction/rcd/proc/get_airlock_image(airlock_type)
|
||||
var/obj/machinery/door/airlock/proto = airlock_type
|
||||
var/ic = initial(proto.icon)
|
||||
var/mutable_appearance/MA = mutable_appearance(ic, "closed")
|
||||
if(!initial(proto.glass))
|
||||
MA.overlays += "fill_closed"
|
||||
//Not scaling these down to button size because they look horrible then, instead just bumping up radius.
|
||||
return MA
|
||||
|
||||
var/airlockcat = input(usr, "Select whether the airlock is solid or glass.") in list("Solid", "Glass")
|
||||
/obj/item/construction/rcd/proc/check_menu(mob/living/user)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(user.incapacitated() || !user.Adjacent(src))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/construction/rcd/proc/change_airlock_setting(mob/user)
|
||||
if(!user)
|
||||
return
|
||||
|
||||
var/list/solid_or_glass_choices = list(
|
||||
"Solid" = get_airlock_image(/obj/machinery/door/airlock),
|
||||
"Glass" = get_airlock_image(/obj/machinery/door/airlock/glass)
|
||||
)
|
||||
|
||||
var/list/solid_choices = list(
|
||||
"Standard" = get_airlock_image(/obj/machinery/door/airlock),
|
||||
"Public" = get_airlock_image(/obj/machinery/door/airlock/public),
|
||||
"Engineering" = get_airlock_image(/obj/machinery/door/airlock/engineering),
|
||||
"Atmospherics" = get_airlock_image(/obj/machinery/door/airlock/atmos),
|
||||
"Security" = get_airlock_image(/obj/machinery/door/airlock/security),
|
||||
"Command" = get_airlock_image(/obj/machinery/door/airlock/command),
|
||||
"Medical" = get_airlock_image(/obj/machinery/door/airlock/medical),
|
||||
"Research" = get_airlock_image(/obj/machinery/door/airlock/research),
|
||||
"Freezer" = get_airlock_image(/obj/machinery/door/airlock/freezer),
|
||||
"Science" = get_airlock_image(/obj/machinery/door/airlock/science),
|
||||
"Virology" = get_airlock_image(/obj/machinery/door/airlock/virology),
|
||||
"Mining" = get_airlock_image(/obj/machinery/door/airlock/mining),
|
||||
"Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance),
|
||||
"External" = get_airlock_image(/obj/machinery/door/airlock/external),
|
||||
"External Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance/external),
|
||||
"Airtight Hatch" = get_airlock_image(/obj/machinery/door/airlock/hatch),
|
||||
"Maintenance Hatch" = get_airlock_image(/obj/machinery/door/airlock/maintenance_hatch)
|
||||
)
|
||||
|
||||
var/list/glass_choices = list(
|
||||
"Standard" = get_airlock_image(/obj/machinery/door/airlock/glass),
|
||||
"Public" = get_airlock_image(/obj/machinery/door/airlock/public/glass),
|
||||
"Engineering" = get_airlock_image(/obj/machinery/door/airlock/engineering/glass),
|
||||
"Atmospherics" = get_airlock_image(/obj/machinery/door/airlock/atmos/glass),
|
||||
"Security" = get_airlock_image(/obj/machinery/door/airlock/security/glass),
|
||||
"Command" = get_airlock_image(/obj/machinery/door/airlock/command/glass),
|
||||
"Medical" = get_airlock_image(/obj/machinery/door/airlock/medical/glass),
|
||||
"Research" = get_airlock_image(/obj/machinery/door/airlock/research/glass),
|
||||
"Science" = get_airlock_image(/obj/machinery/door/airlock/science/glass),
|
||||
"Virology" = get_airlock_image(/obj/machinery/door/airlock/virology/glass),
|
||||
"Mining" = get_airlock_image(/obj/machinery/door/airlock/mining/glass),
|
||||
"Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance/glass),
|
||||
"External" = get_airlock_image(/obj/machinery/door/airlock/external/glass),
|
||||
"External Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance/external/glass)
|
||||
)
|
||||
|
||||
var/airlockcat = show_radial_menu(user, src, solid_or_glass_choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE)
|
||||
if(!check_menu(user))
|
||||
return
|
||||
switch(airlockcat)
|
||||
if("Solid")
|
||||
if(advanced_airlock_setting == 1)
|
||||
var/airlockpaint = input(usr, "Select the type of the airlock.") in list("Standard", "Public", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Freezer", "Science", "Virology", "Mining", "Maintenance", "External", "External Maintenance", "Airtight Hatch", "Maintenance Hatch")
|
||||
var/airlockpaint = show_radial_menu(user, src, solid_choices, radius = 42, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE)
|
||||
if(!check_menu(user))
|
||||
return
|
||||
switch(airlockpaint)
|
||||
if("Standard")
|
||||
airlock_type = /obj/machinery/door/airlock
|
||||
@@ -305,7 +367,9 @@ RLD
|
||||
|
||||
if("Glass")
|
||||
if(advanced_airlock_setting == 1)
|
||||
var/airlockpaint = input(usr, "Select the type of the airlock.") in list("Standard", "Public", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Science", "Virology", "Mining", "Maintenance", "External", "External Maintenance")
|
||||
var/airlockpaint = show_radial_menu(user, src , glass_choices, radius = 42, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE)
|
||||
if(!check_menu(user))
|
||||
return
|
||||
switch(airlockpaint)
|
||||
if("Standard")
|
||||
airlock_type = /obj/machinery/door/airlock/glass
|
||||
@@ -356,8 +420,8 @@ RLD
|
||||
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return TRUE
|
||||
|
||||
/obj/item/construction/rcd/New()
|
||||
..()
|
||||
/obj/item/construction/rcd/Initialize()
|
||||
. = ..()
|
||||
GLOB.rcd_list += src
|
||||
|
||||
/obj/item/construction/rcd/Destroy()
|
||||
@@ -366,19 +430,46 @@ RLD
|
||||
|
||||
/obj/item/construction/rcd/attack_self(mob/user)
|
||||
..()
|
||||
switch(mode)
|
||||
if(1)
|
||||
mode = 2
|
||||
to_chat(user, "<span class='notice'>You change RCD's mode to 'Airlock'.</span>")
|
||||
if(2)
|
||||
mode = 3
|
||||
to_chat(user, "<span class='notice'>You change RCD's mode to 'Deconstruct'.</span>")
|
||||
if(3)
|
||||
mode = 4
|
||||
to_chat(user, "<span class='notice'>You change RCD's mode to 'Grilles & Windows'.</span>")
|
||||
if(4)
|
||||
mode = 1
|
||||
to_chat(user, "<span class='notice'>You change RCD's mode to 'Floor & Walls'.</span>")
|
||||
var/list/choices = list(
|
||||
"Airlock" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlock"),
|
||||
"Deconstruct" = image(icon= 'icons/mob/radial.dmi', icon_state = "delete"),
|
||||
"Grilles & Windows" = image(icon = 'icons/mob/radial.dmi', icon_state = "grillewindow"),
|
||||
"Floors & Walls" = image(icon = 'icons/mob/radial.dmi', icon_state = "wallfloor")
|
||||
)
|
||||
if(mode == RCD_AIRLOCK)
|
||||
choices += list(
|
||||
"Change Access" = image(icon = 'icons/mob/radial.dmi', icon_state = "access"),
|
||||
"Change Airlock Type" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlocktype")
|
||||
)
|
||||
else if(mode == RCD_WINDOWGRILLE)
|
||||
choices += list(
|
||||
"Change Window Type" = image(icon = 'icons/mob/radial.dmi', icon_state = "windowtype")
|
||||
)
|
||||
var/choice = show_radial_menu(user,src,choices, custom_check = CALLBACK(src,.proc/check_menu,user))
|
||||
if(!check_menu(user))
|
||||
return
|
||||
switch(choice)
|
||||
if("Floors & Walls")
|
||||
mode = RCD_FLOORWALL
|
||||
if("Airlock")
|
||||
mode = RCD_AIRLOCK
|
||||
if("Deconstruct")
|
||||
mode = RCD_DECONSTRUCT
|
||||
if("Grilles & Windows")
|
||||
mode = RCD_WINDOWGRILLE
|
||||
if("Change Access")
|
||||
change_airlock_access(user)
|
||||
return
|
||||
if("Change Airlock Type")
|
||||
change_airlock_setting(user)
|
||||
return
|
||||
if("Change Window Type")
|
||||
toggle_window_type(user)
|
||||
return
|
||||
else
|
||||
return
|
||||
playsound(src, 'sound/effects/pop.ogg', 50, 0)
|
||||
to_chat(user, "<span class='notice'>You change RCD's mode to '[choice]'.</span>")
|
||||
|
||||
/obj/item/construction/rcd/proc/target_check(atom/A, mob/user) // only returns true for stuff the device can actually work with
|
||||
if((isturf(A) && A.density && mode==RCD_DECONSTRUCT) || (isturf(A) && !A.density) || (istype(A, /obj/machinery/door/airlock) && mode==RCD_DECONSTRUCT) || istype(A, /obj/structure/grille) || (istype(A, /obj/structure/window) && mode==RCD_DECONSTRUCT) || istype(A, /obj/structure/girder))
|
||||
|
||||
@@ -14,13 +14,14 @@
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
var/max_amount = 90
|
||||
var/active = FALSE
|
||||
actions_types = list(/datum/action/item_action/rcl)
|
||||
actions_types = list(/datum/action/item_action/rcl_col,/datum/action/item_action/rcl_gui)
|
||||
var/list/colors = list("red", "yellow", "green", "blue", "pink", "orange", "cyan", "white")
|
||||
var/current_color_index = 1
|
||||
var/ghetto = FALSE
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
var/datum/component/mobhook
|
||||
var/datum/radial_menu/persistent/wiring_gui_menu
|
||||
|
||||
/obj/item/twohanded/rcl/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
@@ -85,7 +86,8 @@
|
||||
/obj/item/twohanded/rcl/Destroy()
|
||||
QDEL_NULL(loaded)
|
||||
last = null
|
||||
setActive(FALSE, null) // setactive(FALSE) removes mobhook
|
||||
QDEL_NULL(mobhook)
|
||||
QDEL_NULL(wiring_gui_menu)
|
||||
return ..()
|
||||
|
||||
/obj/item/twohanded/rcl/update_icon()
|
||||
@@ -115,20 +117,28 @@
|
||||
if(loaded)
|
||||
QDEL_NULL(loaded)
|
||||
loaded = null
|
||||
QDEL_NULL(wiring_gui_menu)
|
||||
unwield(user)
|
||||
setActive(wielded, user)
|
||||
active = wielded
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/twohanded/rcl/pickup(mob/user)
|
||||
..()
|
||||
getMobhook(user)
|
||||
|
||||
|
||||
|
||||
/obj/item/twohanded/rcl/dropped(mob/wearer)
|
||||
..()
|
||||
if(mobhook)
|
||||
setActive(FALSE, mobhook.parent)
|
||||
active = FALSE
|
||||
QDEL_NULL(mobhook)
|
||||
last = null
|
||||
|
||||
/obj/item/twohanded/rcl/attack_self(mob/user)
|
||||
..()
|
||||
setActive(wielded, user)
|
||||
active = wielded
|
||||
if(!active)
|
||||
last = null
|
||||
else if(!last)
|
||||
@@ -137,17 +147,24 @@
|
||||
last = C
|
||||
break
|
||||
|
||||
/obj/item/twohanded/rcl/proc/setActive(toggle, mob/user)
|
||||
active = toggle
|
||||
if (active && user)
|
||||
if (mobhook && mobhook.parent != user)
|
||||
obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
|
||||
if(to_hook)
|
||||
if(mobhook && mobhook.parent != to_hook)
|
||||
QDEL_NULL(mobhook)
|
||||
if (!mobhook)
|
||||
mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/trigger)))
|
||||
mobhook = to_hook.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/trigger)))
|
||||
else
|
||||
QDEL_NULL(mobhook)
|
||||
|
||||
/obj/item/twohanded/rcl/proc/trigger(mob/user)
|
||||
if(active)
|
||||
layCable(user)
|
||||
if(wiring_gui_menu) //update the wire options as you move
|
||||
wiringGuiUpdate(user)
|
||||
|
||||
|
||||
//previous contents of trigger(), lays cable each time the player moves
|
||||
/obj/item/twohanded/rcl/proc/layCable(mob/user)
|
||||
if(!isturf(user.loc))
|
||||
return
|
||||
if(is_empty(user, 0))
|
||||
@@ -156,7 +173,7 @@
|
||||
|
||||
if(prob(2) && ghetto) //Give ghetto RCLs a 2% chance to jam, requiring it to be reactviated manually.
|
||||
to_chat(user, "<span class='warning'>[src]'s wires jam!</span>")
|
||||
setActive(FALSE, user)
|
||||
active = FALSE
|
||||
return
|
||||
else
|
||||
if(last)
|
||||
@@ -179,6 +196,91 @@
|
||||
is_empty(user) //If we've run out, display message
|
||||
update_icon()
|
||||
|
||||
//searches the current tile for a stub cable of the same colour
|
||||
/obj/item/twohanded/rcl/proc/findLinkingCable(mob/user)
|
||||
var/turf/T
|
||||
if(!isturf(user.loc))
|
||||
return
|
||||
|
||||
T = get_turf(user)
|
||||
if(T.intact || !T.can_have_cabling())
|
||||
return
|
||||
|
||||
for(var/obj/structure/cable/C in T)
|
||||
if(!C)
|
||||
continue
|
||||
if(C.cable_color != GLOB.cable_colors[colors[current_color_index]])
|
||||
continue
|
||||
if(C.d1 == 0)
|
||||
return C
|
||||
break
|
||||
return
|
||||
|
||||
|
||||
/obj/item/twohanded/rcl/proc/wiringGuiGenerateChoices(mob/user)
|
||||
var/fromdir = 0
|
||||
var/obj/structure/cable/linkingCable = findLinkingCable(user)
|
||||
if(linkingCable)
|
||||
fromdir = linkingCable.d2
|
||||
|
||||
var/list/wiredirs = list("1","5","4","6","2","10","8","9")
|
||||
for(var/icondir in wiredirs)
|
||||
var/dirnum = text2num(icondir)
|
||||
var/cablesuffix = "[min(fromdir,dirnum)]-[max(fromdir,dirnum)]"
|
||||
if(fromdir == dirnum) //cables can't loop back on themselves
|
||||
cablesuffix = "invalid"
|
||||
var/image/img = image(icon = 'icons/mob/radial.dmi', icon_state = "cable_[cablesuffix]")
|
||||
img.color = GLOB.cable_colors[colors[current_color_index]]
|
||||
wiredirs[icondir] = img
|
||||
return wiredirs
|
||||
|
||||
/obj/item/twohanded/rcl/proc/showWiringGui(mob/user)
|
||||
var/list/choices = wiringGuiGenerateChoices(user)
|
||||
|
||||
wiring_gui_menu = show_radial_menu_persistent(user, src , choices, select_proc = CALLBACK(src, .proc/wiringGuiReact, user), radius = 42)
|
||||
|
||||
/obj/item/twohanded/rcl/proc/wiringGuiUpdate(mob/user)
|
||||
if(!wiring_gui_menu)
|
||||
return
|
||||
|
||||
wiring_gui_menu.entry_animation = FALSE //stop the open anim from playing each time we update
|
||||
var/list/choices = wiringGuiGenerateChoices(user)
|
||||
|
||||
wiring_gui_menu.change_choices(choices,FALSE)
|
||||
|
||||
|
||||
//Callback used to respond to interactions with the wiring menu
|
||||
/obj/item/twohanded/rcl/proc/wiringGuiReact(mob/living/user,choice)
|
||||
if(!choice) //close on a null choice (the center button)
|
||||
QDEL_NULL(wiring_gui_menu)
|
||||
return
|
||||
|
||||
choice = text2num(choice)
|
||||
|
||||
if(!isturf(user.loc))
|
||||
return
|
||||
if(is_empty(user, 0))
|
||||
to_chat(user, "<span class='warning'>\The [src] is empty!</span>")
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(user)
|
||||
if(T.intact || !T.can_have_cabling())
|
||||
return
|
||||
|
||||
loaded.item_color = colors[current_color_index]
|
||||
|
||||
var/obj/structure/cable/linkingCable = findLinkingCable(user)
|
||||
if(linkingCable)
|
||||
if(choice != linkingCable.d2)
|
||||
loaded.cable_join(linkingCable, user, FALSE, choice)
|
||||
last = null
|
||||
else
|
||||
last = loaded.place_turf(get_turf(src), user, choice)
|
||||
|
||||
is_empty(user) //If we've run out, display message
|
||||
|
||||
wiringGuiUpdate(user)
|
||||
|
||||
|
||||
/obj/item/twohanded/rcl/pre_loaded/Initialize() //Comes preloaded with cable, for testing stuff
|
||||
. = ..()
|
||||
@@ -192,12 +294,21 @@
|
||||
update_icon()
|
||||
|
||||
/obj/item/twohanded/rcl/ui_action_click(mob/user, action)
|
||||
if(istype(action, /datum/action/item_action/rcl))
|
||||
if(istype(action, /datum/action/item_action/rcl_col))
|
||||
current_color_index++;
|
||||
if (current_color_index > colors.len)
|
||||
current_color_index = 1
|
||||
var/cwname = colors[current_color_index]
|
||||
to_chat(user, "Color changed to [cwname]!")
|
||||
if(loaded)
|
||||
loaded.item_color= colors[current_color_index]
|
||||
if(wiring_gui_menu)
|
||||
wiringGuiUpdate(user)
|
||||
else if(istype(action, /datum/action/item_action/rcl_gui))
|
||||
if(wiring_gui_menu) //The menu is already open, close it
|
||||
QDEL_NULL(wiring_gui_menu)
|
||||
else //open the menu
|
||||
showWiringGui(user)
|
||||
|
||||
/obj/item/twohanded/rcl/ghetto
|
||||
actions_types = list()
|
||||
|
||||
@@ -331,7 +331,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
//make sure what we're clicking is valid for the current category
|
||||
var/static/list/make_pipe_whitelist
|
||||
if(!make_pipe_whitelist)
|
||||
make_pipe_whitelist = typecacheof(list(/obj/structure/lattice, /obj/structure/girder, /obj/item/pipe))
|
||||
make_pipe_whitelist = typecacheof(list(/obj/structure/lattice, /obj/structure/girder, /obj/item/pipe, /obj/structure/window, /obj/structure/grille))
|
||||
var/can_make_pipe = (isturf(A) || is_type_in_typecache(A, make_pipe_whitelist))
|
||||
|
||||
. = FALSE
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
/obj/item/areaeditor/blueprints/attack_self(mob/user)
|
||||
. = ..()
|
||||
if(!legend)
|
||||
var/area/A = get_area()
|
||||
var/area/A = get_area(user)
|
||||
if(get_area_type() == AREA_STATION)
|
||||
. += "<p>According to \the [src], you are now in <b>\"[html_encode(A.name)]\"</b>.</p>"
|
||||
. += "<p><a href='?src=[REF(src)];edit_area=1'>Change area name</a></p>"
|
||||
@@ -140,12 +140,10 @@
|
||||
legend = FALSE
|
||||
|
||||
|
||||
/obj/item/areaeditor/proc/get_area()
|
||||
var/turf/T = get_turf(usr)
|
||||
var/area/A = T.loc
|
||||
return A
|
||||
|
||||
/obj/item/areaeditor/proc/get_area_type(area/A = get_area())
|
||||
/obj/item/areaeditor/proc/get_area_type(area/A)
|
||||
if(!A)
|
||||
A = get_area(usr)
|
||||
if(A.outdoors)
|
||||
return AREA_SPACE
|
||||
var/list/SPECIALS = list(
|
||||
@@ -183,7 +181,7 @@
|
||||
return ""
|
||||
|
||||
/obj/item/areaeditor/proc/edit_area()
|
||||
var/area/A = get_area()
|
||||
var/area/A = get_area(usr)
|
||||
var/prevname = "[A.name]"
|
||||
var/str = stripped_input(usr,"New area name:", "Area Creation", "", MAX_NAME_LEN)
|
||||
if(!str || !length(str) || str==prevname) //cancel
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
/obj/item/organ/body_egg/Insert(var/mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
owner.add_trait(TRAIT_XENO_HOST, TRAIT_GENERIC)
|
||||
ADD_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC)
|
||||
START_PROCESSING(SSobj, src)
|
||||
owner.med_hud_set_status()
|
||||
INVOKE_ASYNC(src, .proc/AddInfectionImages, owner)
|
||||
@@ -24,7 +24,7 @@
|
||||
/obj/item/organ/body_egg/Remove(var/mob/living/carbon/M, special = 0)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(owner)
|
||||
owner.remove_trait(TRAIT_XENO_HOST, TRAIT_GENERIC)
|
||||
REMOVE_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC)
|
||||
owner.med_hud_set_status()
|
||||
INVOKE_ASYNC(src, .proc/RemoveInfectionImages, owner)
|
||||
..()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -102,7 +102,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
icon_state = "cigoff"
|
||||
throw_speed = 0.5
|
||||
item_state = "cigoff"
|
||||
container_type = INJECTABLE
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
body_parts_covered = null
|
||||
grind_results = list()
|
||||
@@ -123,8 +122,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
|
||||
/obj/item/clothing/mask/cigarette/Initialize()
|
||||
. = ..()
|
||||
create_reagents(chem_volume)
|
||||
reagents.set_reacting(FALSE) // so it doesn't react until you light it
|
||||
create_reagents(chem_volume, INJECTABLE | NO_REACT) // so it doesn't react until you light it
|
||||
if(list_reagents)
|
||||
reagents.add_reagent_list(list_reagents)
|
||||
if(starts_lit)
|
||||
@@ -184,7 +182,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
qdel(src)
|
||||
return
|
||||
// allowing reagents to react after being lit
|
||||
reagents.set_reacting(TRUE)
|
||||
DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
|
||||
reagents.handle_reactions()
|
||||
icon_state = icon_on
|
||||
item_state = icon_on
|
||||
@@ -325,7 +323,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
list_reagents = list("space_drugs" = 15, "lipolicide" = 35)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/rollie/mindbreaker
|
||||
list_reagents = list("mindbreaker" = 35, "lipolicide" = 15)
|
||||
list_reagents = list("mindbreaker" = 35, "lipolicide" = 15)
|
||||
|
||||
/obj/item/cigbutt/roach
|
||||
name = "roach"
|
||||
@@ -720,8 +718,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
|
||||
/obj/item/clothing/mask/vape/Initialize(mapload, param_color)
|
||||
. = ..()
|
||||
create_reagents(chem_volume)
|
||||
reagents.set_reacting(FALSE) // so it doesn't react until you light it
|
||||
DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
|
||||
reagents.add_reagent("nicotine", 50)
|
||||
if(!icon_state)
|
||||
if(!param_color)
|
||||
@@ -790,13 +787,12 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
if(reagents.total_volume > 0)
|
||||
to_chat(user, "<span class='notice'>You empty [src] of all reagents.</span>")
|
||||
reagents.clear_reagents()
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/vape/equipped(mob/user, slot)
|
||||
if(slot == SLOT_WEAR_MASK)
|
||||
if(!screw)
|
||||
to_chat(user, "<span class='notice'>You start puffing on the vape.</span>")
|
||||
reagents.set_reacting(TRUE)
|
||||
DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else //it will not start if the vape is opened.
|
||||
to_chat(user, "<span class='warning'>You need to close the cap first!</span>")
|
||||
@@ -804,7 +800,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
/obj/item/clothing/mask/vape/dropped(mob/user)
|
||||
var/mob/living/carbon/C = user
|
||||
if(C.get_item_by_slot(SLOT_WEAR_MASK) == src)
|
||||
reagents.set_reacting(FALSE)
|
||||
ENABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/clothing/mask/vape/proc/hand_reagents()//had to rename to avoid duplicate error
|
||||
|
||||
@@ -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>")
|
||||
@@ -252,7 +254,7 @@
|
||||
cost = 0
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if (H.has_trait(TRAIT_TAGGER))
|
||||
if (HAS_TRAIT(H, TRAIT_TAGGER))
|
||||
cost *= 0.5
|
||||
var/charges_used = use_charges(user, cost)
|
||||
if(!charges_used)
|
||||
@@ -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
|
||||
|
||||
@@ -444,7 +444,7 @@
|
||||
|
||||
/obj/item/twohanded/shockpaddles/proc/can_defib(mob/living/carbon/H)
|
||||
var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
|
||||
return (!H.suiciding && !(H.has_trait(TRAIT_NOCLONE)) && !H.hellbound && ((world.time - H.timeofdeath) < tlimit) && (H.getBruteLoss() < 180) && (H.getFireLoss() < 180) && H.getorgan(/obj/item/organ/heart) && BR && !BR.damaged_brain)
|
||||
return (!H.suiciding && !(HAS_TRAIT(H, TRAIT_NOCLONE)) && !H.hellbound && ((world.time - H.timeofdeath) < tlimit) && (H.getBruteLoss() < 180) && (H.getFireLoss() < 180) && H.getorgan(/obj/item/organ/heart) && BR && !BR.damaged_brain)
|
||||
|
||||
/obj/item/twohanded/shockpaddles/proc/shock_touching(dmg, mob/H)
|
||||
if(req_defib)
|
||||
@@ -585,7 +585,7 @@
|
||||
shock_touching(30, H)
|
||||
var/failed
|
||||
|
||||
if (H.suiciding || (H.has_trait(TRAIT_NOCLONE)))
|
||||
if (H.suiciding || (HAS_TRAIT(H, TRAIT_NOCLONE)))
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Recovery of patient impossible. Further attempts futile.</span>"
|
||||
else if (H.hellbound)
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's soul appears to be on another plane of existence. Further attempts futile.</span>"
|
||||
|
||||
@@ -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>"
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
add_fingerprint(user)
|
||||
if(istype(M) && on && user.zone_selected in list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH))
|
||||
|
||||
if((user.has_trait(TRAIT_CLUMSY) || user.has_trait(TRAIT_DUMB)) && prob(50)) //too dumb to use flashlight properly
|
||||
if((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50)) //too dumb to use flashlight properly
|
||||
return ..() //just hit them in the head
|
||||
|
||||
if(!user.IsAdvancedToolUser())
|
||||
@@ -86,7 +86,7 @@
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] directs [src] to [M]'s eyes.</span>", \
|
||||
"<span class='danger'>You direct [src] to [M]'s eyes.</span>")
|
||||
if(M.stat == DEAD || (M.has_trait(TRAIT_BLIND)) || !M.flash_act(visual = 1)) //mob is dead or fully blind
|
||||
if(M.stat == DEAD || (HAS_TRAIT(M, TRAIT_BLIND)) || !M.flash_act(visual = 1)) //mob is dead or fully blind
|
||||
to_chat(user, "<span class='warning'>[M]'s pupils don't react to the light!</span>")
|
||||
else if(M.dna && M.dna.check_mutation(XRAY)) //mob has X-ray vision
|
||||
to_chat(user, "<span class='danger'>[M]'s pupils give an eerie glow!</span>")
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
/obj/item/instrument/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/musicaltuner))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if (H.has_trait(TRAIT_MUSICIAN))
|
||||
if (HAS_TRAIT(H, TRAIT_MUSICIAN))
|
||||
if (!tune_time)
|
||||
H.visible_message("[H] tunes the [src] to perfection!", "<span class='notice'>You tune the [src] to perfection!</span>")
|
||||
tune_time = 300
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
if (!user.IsAdvancedToolUser())
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return
|
||||
if(user.has_trait(TRAIT_NOGUNS))
|
||||
if(HAS_TRAIT(user, TRAIT_NOGUNS))
|
||||
to_chat(user, "<span class='warning'>Your fingers can't press the button!</span>")
|
||||
return
|
||||
if(ishuman(user))
|
||||
|
||||
@@ -95,7 +95,7 @@ SLIME SCANNER
|
||||
/obj/item/healthanalyzer/attack(mob/living/M, mob/living/carbon/human/user)
|
||||
|
||||
// Clumsiness/brain damage check
|
||||
if ((user.has_trait(TRAIT_CLUMSY) || user.has_trait(TRAIT_DUMB)) && prob(50))
|
||||
if ((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50))
|
||||
to_chat(user, "<span class='notice'>You stupidly try to analyze the floor's vitals!</span>")
|
||||
user.visible_message("<span class='warning'>[user] has analyzed the floor's vitals!</span>")
|
||||
var/msg = "<span class='info'>*---------*\nAnalyzing results for The floor:\n\tOverall status: <b>Healthy</b>\n"
|
||||
@@ -127,7 +127,7 @@ SLIME SCANNER
|
||||
var/brute_loss = M.getBruteLoss()
|
||||
var/mob_status = (M.stat == DEAD ? "<span class='alert'><b>Deceased</b></span>" : "<b>[round(M.health/M.maxHealth,0.01)*100] % healthy</b>")
|
||||
|
||||
if(M.has_trait(TRAIT_FAKEDEATH) && !advanced)
|
||||
if(HAS_TRAIT(M, TRAIT_FAKEDEATH) && !advanced)
|
||||
mob_status = "<span class='alert'><b>Deceased</b></span>"
|
||||
oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss
|
||||
|
||||
@@ -199,10 +199,10 @@ SLIME SCANNER
|
||||
msg += "\t<span class='info'><b>==EAR STATUS==</b></span>\n"
|
||||
if(istype(ears))
|
||||
var/healthy = TRUE
|
||||
if(C.has_trait(TRAIT_DEAF, GENETIC_MUTATION))
|
||||
if(HAS_TRAIT_FROM(C, TRAIT_DEAF, GENETIC_MUTATION))
|
||||
healthy = FALSE
|
||||
msg += "\t<span class='alert'>Subject is genetically deaf.</span>\n"
|
||||
else if(C.has_trait(TRAIT_DEAF))
|
||||
else if(HAS_TRAIT(C, TRAIT_DEAF))
|
||||
healthy = FALSE
|
||||
msg += "\t<span class='alert'>Subject is deaf.</span>\n"
|
||||
else
|
||||
@@ -220,10 +220,10 @@ SLIME SCANNER
|
||||
msg += "\t<span class='info'><b>==EYE STATUS==</b></span>\n"
|
||||
if(istype(eyes))
|
||||
var/healthy = TRUE
|
||||
if(C.has_trait(TRAIT_BLIND))
|
||||
if(HAS_TRAIT(C, TRAIT_BLIND))
|
||||
msg += "\t<span class='alert'>Subject is blind.</span>\n"
|
||||
healthy = FALSE
|
||||
if(C.has_trait(TRAIT_NEARSIGHT))
|
||||
if(HAS_TRAIT(C, TRAIT_NEARSIGHT))
|
||||
msg += "\t<span class='alert'>Subject is nearsighted.</span>\n"
|
||||
healthy = FALSE
|
||||
if(eyes.eye_damage > 30)
|
||||
@@ -290,7 +290,7 @@ SLIME SCANNER
|
||||
msg += "<span class='info'>Body temperature: [round(M.bodytemperature-T0C,0.1)] °C ([round(M.bodytemperature*1.8-459.67,0.1)] °F)</span>\n"
|
||||
|
||||
// Time of death
|
||||
if(M.tod && (M.stat == DEAD || ((M.has_trait(TRAIT_FAKEDEATH)) && !advanced)))
|
||||
if(M.tod && (M.stat == DEAD || ((HAS_TRAIT(M, TRAIT_FAKEDEATH)) && !advanced)))
|
||||
msg += "<span class='info'>Time of Death:</span> [M.tod]\n"
|
||||
var/tdelta = round(world.time - M.timeofdeath)
|
||||
if(tdelta < (DEFIB_TIME_LIMIT * 10))
|
||||
@@ -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
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
/obj/item/dnainjector/proc/inject(mob/living/carbon/M, mob/user)
|
||||
prepare()
|
||||
|
||||
if(M.has_dna() && !M.has_trait(TRAIT_RADIMMUNE) && !M.has_trait(TRAIT_NOCLONE))
|
||||
if(M.has_dna() && !HAS_TRAIT(M, TRAIT_RADIMMUNE) && !HAS_TRAIT(M, TRAIT_NOCLONE))
|
||||
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
|
||||
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
|
||||
for(var/datum/mutation/human/HM in remove_mutations)
|
||||
@@ -313,7 +313,7 @@
|
||||
to_chat(user, "<span class='notice'>You can't modify [M]'s DNA while [M.p_theyre()] dead.</span>")
|
||||
return FALSE
|
||||
|
||||
if(M.has_dna() && !(M.has_trait(TRAIT_NOCLONE)))
|
||||
if(M.has_dna() && !(HAS_TRAIT(M, TRAIT_NOCLONE)))
|
||||
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
|
||||
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
|
||||
var/endtime = world.time+duration
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed")
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
resistance_flags = FIRE_PROOF
|
||||
container_type = AMOUNT_VISIBLE
|
||||
var/max_water = 50
|
||||
var/last_use = 1
|
||||
var/chem = "water"
|
||||
@@ -56,7 +55,7 @@
|
||||
|
||||
/obj/item/extinguisher/Initialize()
|
||||
. = ..()
|
||||
create_reagents(max_water)
|
||||
create_reagents(max_water, AMOUNT_VISIBLE)
|
||||
reagents.add_reagent(chem, max_water)
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user