Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into dissection
This commit is contained in:
@@ -106,6 +106,7 @@
|
||||
#define SKINTONE 23 //uses skin tones
|
||||
#define HORNCOLOR 24
|
||||
|
||||
//organ slots
|
||||
#define ORGAN_SLOT_BRAIN "brain"
|
||||
#define ORGAN_SLOT_APPENDIX "appendix"
|
||||
#define ORGAN_SLOT_RIGHT_ARM_AUG "r_arm_device"
|
||||
@@ -129,3 +130,8 @@
|
||||
#define ORGAN_SLOT_BRAIN_ANTISTUN "brain_antistun"
|
||||
#define ORGAN_SLOT_TAIL "tail"
|
||||
#define ORGAN_SLOT_PENIS "penis"
|
||||
|
||||
////organ defines
|
||||
#define STANDARD_ORGAN_THRESHOLD 100
|
||||
#define STANDARD_ORGAN_HEALING 0.001
|
||||
#define STANDARD_ORGAN_DECAY 0.00222 //designed to fail organs when left to decay for ~15 minutes
|
||||
@@ -23,8 +23,9 @@
|
||||
#define AI_DETECT_HUD "19"
|
||||
#define NANITE_HUD "20"
|
||||
#define DIAG_NANITE_FULL_HUD "21"
|
||||
#define RAD_HUD "22" //radation alerts for medical huds
|
||||
//for antag huds. these are used at the /mob level
|
||||
#define ANTAG_HUD "22"
|
||||
#define ANTAG_HUD "23"
|
||||
|
||||
//by default everything in the hud_list of an atom is an image
|
||||
//a value in hud_list with one of these will change that behavior
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
#define COLOR_INPUT_ENABLED "#D3B5B5"
|
||||
|
||||
#define COLOR_DARKMODE_INFO_BUTTONS_BG "#40628A"
|
||||
#define COLOR_DARKMODE_ISSUE_BUTTON_BG "#ce4242"
|
||||
#define COLOR_DARKMODE_BACKGROUND "#202020"
|
||||
#define COLOR_DARKMODE_DARKBACKGROUND "#171717"
|
||||
#define COLOR_DARKMODE_TEXT "#f0f0f0"
|
||||
#define COLOR_DARKMODE_ISSUE_BUTTON_BG "#A92C2C"
|
||||
#define COLOR_DARKMODE_BACKGROUND "#272727"
|
||||
#define COLOR_DARKMODE_DARKBACKGROUND "#242424"
|
||||
#define COLOR_DARKMODE_TEXT "#E0E0E0"
|
||||
|
||||
#define COLOR_WHITEMODE_INFO_BUTTONS_BG "#90b3dd"
|
||||
#define COLOR_WHITEMODE_ISSUE_BUTTON_BG "#ef7f7f"
|
||||
#define COLOR_WHITEMODE_BACKGROUND "#ffffff"
|
||||
#define COLOR_WHITEMODE_DARKBACKGROUND "#eeeeee"
|
||||
#define COLOR_WHITEMODE_INFO_BUTTONS_BG "#90B3DD"
|
||||
#define COLOR_WHITEMODE_ISSUE_BUTTON_BG "#EF7F7F"
|
||||
#define COLOR_WHITEMODE_BACKGROUND "#F0F0F0"
|
||||
#define COLOR_WHITEMODE_DARKBACKGROUND "#E6E6E6"
|
||||
#define COLOR_WHITEMODE_TEXT "#000000"
|
||||
|
||||
#define COLOR_FLOORTILE_GRAY "#8D8B8B"
|
||||
|
||||
@@ -121,8 +121,13 @@
|
||||
#define COMSIG_MOVABLE_HEAR "movable_hear" //from base of atom/movable/Hear(): (message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
|
||||
|
||||
// /mind signals
|
||||
#define COMSIG_MIND_TRANSFER "mind_transfer" //from base of mind/transfer_to(): (new_character, old_character)
|
||||
|
||||
// /mob signals
|
||||
#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed)
|
||||
#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize() (can_reenter_corpse)
|
||||
#define COMPONENT_BLOCK_GHOSTING 1
|
||||
#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
|
||||
#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (magic, holy, protection_sources)
|
||||
#define COMPONENT_BLOCK_MAGIC 1
|
||||
@@ -132,6 +137,7 @@
|
||||
#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
|
||||
#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" //from base of mob/RangedAttack(): (atom/A, params)
|
||||
#define COMSIG_MOB_THROW "mob_throw" //from base of /mob/throw_item(): (atom/target)
|
||||
#define COMSIG_MOB_KEY_CHANGE "mob_key_change" //from base of /mob/transfer_ckey()
|
||||
#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //from base of /mob/update_sight(): ()
|
||||
#define COMSIG_MOB_SAY "mob_say" // from /mob/living/say(): (proc args list)
|
||||
#define COMPONENT_UPPERCASE_SPEECH 1
|
||||
@@ -159,6 +165,8 @@
|
||||
#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)
|
||||
|
||||
// /machinery signals
|
||||
#define COMSIG_MACHINE_EJECT_OCCUPANT "eject_occupant" //from base of obj/machinery/dropContents() (occupant)
|
||||
|
||||
// /obj/item signals
|
||||
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#define CHECK_BITFIELD(variable, flag) (variable & (flag))
|
||||
#define TOGGLE_BITFIELD(variable, flag) (variable ^= (flag))
|
||||
|
||||
#define CHECK_MULTIPLE_BITFIELDS(flagvar, flags) (((flagvar) & (flags)) == (flags))
|
||||
|
||||
GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768))
|
||||
|
||||
// for /datum/var/datum_flags
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#define LOG_GAME (1 << 12)
|
||||
#define LOG_ADMIN_PRIVATE (1 << 13)
|
||||
#define LOG_ASAY (1 << 14)
|
||||
#define LOG_VIRUS (1 << 15)
|
||||
|
||||
//Individual logging panel pages
|
||||
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK)
|
||||
|
||||
@@ -314,7 +314,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define MAP_MAXZ 6
|
||||
|
||||
// Defib stats
|
||||
#define DEFIB_TIME_LIMIT 120
|
||||
#define DEFIB_TIME_LIMIT 960
|
||||
#define DEFIB_TIME_LOSS 60
|
||||
|
||||
// Diagonal movement
|
||||
|
||||
+11
-3
@@ -204,8 +204,6 @@
|
||||
|
||||
#define MAX_CHICKENS 50
|
||||
|
||||
#define UNHEALING_EAR_DAMAGE 100
|
||||
|
||||
|
||||
#define INCORPOREAL_MOVE_BASIC 1
|
||||
#define INCORPOREAL_MOVE_SHADOW 2 // leaves a trail of shadows
|
||||
@@ -234,11 +232,15 @@
|
||||
#define OFFSET_S_STORE "s_store"
|
||||
#define OFFSET_FACEMASK "mask"
|
||||
#define OFFSET_HEAD "head"
|
||||
#define OFFSET_FACE "face"
|
||||
#define OFFSET_EYES "eyes"
|
||||
#define OFFSET_LIPS "lips"
|
||||
#define OFFSET_BELT "belt"
|
||||
#define OFFSET_BACK "back"
|
||||
#define OFFSET_SUIT "suit"
|
||||
#define OFFSET_NECK "neck"
|
||||
#define OFFSET_HAIR "hair"
|
||||
#define OFFSET_FHAIR "fhair"
|
||||
#define OFFSET_MUTPARTS "mutantparts"
|
||||
|
||||
//MINOR TWEAKS/MISC
|
||||
#define AGE_MIN 18 //youngest a character can be //CITADEL EDIT - 17 --> 18
|
||||
@@ -257,6 +259,9 @@
|
||||
|
||||
#define MAX_QUIRKS 6 //The maximum amount of quirks one character can have at roundstart
|
||||
|
||||
#define MAX_REVIVE_FIRE_DAMAGE 180
|
||||
#define MAX_REVIVE_BRUTE_DAMAGE 180
|
||||
|
||||
// AI Toggles
|
||||
#define AI_CAMERA_LUMINOSITY 5
|
||||
#define AI_VOX // Comment out if you don't want VOX to be enabled and have players download the voice sounds.
|
||||
@@ -265,3 +270,6 @@
|
||||
#define BODYPART_LIFE_UPDATE_HEALTH (1<<0)
|
||||
|
||||
#define HUMAN_FIRE_STACK_ICON_NUM 3
|
||||
|
||||
#define PULL_PRONE_SLOWDOWN 0.6
|
||||
#define HUMAN_CARRY_SLOWDOWN 0
|
||||
@@ -31,3 +31,6 @@
|
||||
#define MOVESPEED_ID_PAI_SPACEWALK_SPEEDMOD "PAI_SPACEWALK_MODIFIER"
|
||||
|
||||
#define MOVESPEED_ID_SANITY "MOOD_SANITY"
|
||||
|
||||
#define MOVESPEED_ID_PRONE_DRAGGING "PRONE_DRAG"
|
||||
#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY"
|
||||
@@ -10,6 +10,7 @@
|
||||
#define UNIQUE_RENAME (1<<6) // can you customize the description/name of the thing?
|
||||
#define USES_TGUI (1<<7) //put on things that use tgui on ui_interact instead of custom/old UI.
|
||||
#define FROZEN (1<<8)
|
||||
#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
|
||||
|
||||
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
|
||||
|
||||
@@ -38,3 +39,12 @@
|
||||
#define THICKMATERIAL (1<<5) //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body.
|
||||
#define VOICEBOX_TOGGLABLE (1<<6) // The voicebox in this clothing can be toggled.
|
||||
#define VOICEBOX_DISABLED (1<<7) // The voicebox is currently turned off.
|
||||
|
||||
// Flags for the organ_flags var on /obj/item/organ
|
||||
|
||||
#define ORGAN_SYNTHETIC (1<<0) //Synthetic organs, or cybernetic organs. Reacts to EMPs and don't deteriorate or heal
|
||||
#define ORGAN_FROZEN (1<<1) //Frozen organs, don't deteriorate
|
||||
#define ORGAN_FAILING (1<<2) //Failing organs perform damaging effects until replaced or fixed
|
||||
#define ORGAN_EXTERNAL (1<<3) //Was this organ implanted/inserted/etc, if true will not be removed during species change.
|
||||
#define ORGAN_VITAL (1<<4) //Currently only the brain
|
||||
#define ORGAN_NO_SPOIL (1<<5) //Currently only the brain
|
||||
|
||||
@@ -34,3 +34,17 @@
|
||||
#define DEL_REAGENT 1 // reagent deleted (fully cleared)
|
||||
#define ADD_REAGENT 2 // reagent added
|
||||
#define REM_REAGENT 3 // reagent removed (may still exist)
|
||||
|
||||
//reagent bitflags, used for altering how they works
|
||||
#define REAGENT_DEAD_PROCESS (1<<0) //calls on_mob_dead() if present in a dead body
|
||||
#define REAGENT_DONOTSPLIT (1<<1) //Do not split the chem at all during processing
|
||||
#define REAGENT_ONLYINVERSE (1<<2) //Only invert chem, no splitting
|
||||
#define REAGENT_ONMOBMERGE (1<<3) //Call on_mob_life proc when reagents are merging.
|
||||
#define REAGENT_INVISIBLE (1<<4) //Doesn't appear on handheld health analyzers.
|
||||
#define REAGENT_FORCEONNEW (1<<5) //Forces a on_new() call without a data overhead
|
||||
#define REAGENT_SNEAKYNAME (1<<6) //When inverted, the inverted chem uses the name of the original chem
|
||||
#define REAGENT_SPLITRETAINVOL (1<<7) //Retains initial volume of chem when splitting
|
||||
|
||||
//Chemical reaction flags, for determining reaction specialties
|
||||
#define REACTION_CLEAR_IMPURE (1<<0) //Convert into impure/pure on reaction completion
|
||||
#define REACTION_CLEAR_INVERSE (1<<1) //Convert into inverse on reaction completion when purity is low enough
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#define UNCONSCIOUS 2
|
||||
#define DEAD 3
|
||||
|
||||
//Maximum healthiness an individual can have
|
||||
#define MAX_SATIETY 600
|
||||
|
||||
// bitflags for machine stat variable
|
||||
#define BROKEN (1<<0)
|
||||
#define NOPOWER (1<<1)
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
#define TOOL_ANALYZER "analyzer"
|
||||
#define TOOL_MINING "mining"
|
||||
#define TOOL_SHOVEL "shovel"
|
||||
#define TOOL_RETRACTOR "retractor"
|
||||
#define TOOL_HEMOSTAT "hemostat"
|
||||
#define TOOL_CAUTERY "cautery"
|
||||
#define TOOL_DRILL "drill"
|
||||
#define TOOL_SCALPEL "scalpel"
|
||||
#define TOOL_SAW "saw"
|
||||
|
||||
|
||||
// If delay between the start and the end of tool operation is less than MIN_TOOL_SOUND_DELAY,
|
||||
|
||||
@@ -170,6 +170,7 @@
|
||||
#define OBESITY "obesity"
|
||||
#define MAGIC_TRAIT "magic"
|
||||
#define TRAUMA_TRAIT "trauma"
|
||||
#define DISEASE_TRAIT "disease"
|
||||
#define SPECIES_TRAIT "species"
|
||||
#define ORGAN_TRAIT "organ"
|
||||
#define JOB_TRAIT "job"
|
||||
|
||||
@@ -58,6 +58,10 @@
|
||||
if (CONFIG_GET(flag/log_game))
|
||||
WRITE_LOG(GLOB.world_game_log, "GAME: [text]")
|
||||
|
||||
/proc/log_virus(text)
|
||||
if (CONFIG_GET(flag/log_virus))
|
||||
WRITE_LOG(GLOB.world_virus_log, "VIRUS: [text]")
|
||||
|
||||
/proc/log_access(text)
|
||||
if (CONFIG_GET(flag/log_access))
|
||||
WRITE_LOG(GLOB.world_game_log, "ACCESS: [text]")
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
for(var/file in args)
|
||||
src << browse_rsc(file)
|
||||
|
||||
/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list("txt","log","htm", "html"))
|
||||
/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list("txt","log","htm", "html", "md"))
|
||||
var/path = root
|
||||
|
||||
for(var/i=0, i<max_iterations, i++)
|
||||
|
||||
+39
-1
@@ -159,6 +159,44 @@
|
||||
processing_list.Cut(1, 2)
|
||||
processing_list += A.contents
|
||||
|
||||
/** recursive_organ_check
|
||||
* inputs: O (object to start with)
|
||||
* outputs:
|
||||
* description: A pseudo-recursive loop based off of the recursive mob check, this check looks for any organs held
|
||||
* within 'O', toggling their frozen flag. This check excludes items held within other safe organ
|
||||
* storage units, so that only the lowest level of container dictates whether we do or don't decompose
|
||||
*/
|
||||
/proc/recursive_organ_check(atom/O)
|
||||
|
||||
var/list/processing_list = list(O)
|
||||
var/list/processed_list = list()
|
||||
var/index = 1
|
||||
var/obj/item/organ/found_organ
|
||||
|
||||
while(index <= length(processing_list))
|
||||
|
||||
var/atom/A = processing_list[index]
|
||||
|
||||
if(istype(A, /obj/item/organ))
|
||||
found_organ = A
|
||||
found_organ.organ_flags ^= ORGAN_FROZEN
|
||||
|
||||
else if(istype(A, /mob/living/carbon))
|
||||
var/mob/living/carbon/Q = A
|
||||
for(var/organ in Q.internal_organs)
|
||||
found_organ = organ
|
||||
found_organ.organ_flags ^= ORGAN_FROZEN
|
||||
|
||||
for(var/atom/B in A) //objects held within other objects are added to the processing list, unless that object is something that can hold organs safely
|
||||
if(!processed_list[B] && !istype(B, /obj/structure/closet/crate/freezer) && !istype(B, /obj/structure/closet/secure_closet/freezer))
|
||||
processing_list+= B
|
||||
|
||||
index++
|
||||
processed_list[A] = A
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Better recursive loop, technically sort of not actually recursive cause that shit is retarded, enjoy.
|
||||
//No need for a recursive limit either
|
||||
/proc/recursive_mob_check(atom/O,client_check=1,sight_check=1,include_radio=1)
|
||||
@@ -473,7 +511,7 @@
|
||||
|
||||
G_found.client.prefs.copy_to(new_character)
|
||||
new_character.dna.update_dna_identity()
|
||||
new_character.key = G_found.key
|
||||
G_found.transfer_ckey(new_character, FALSE)
|
||||
|
||||
return new_character
|
||||
|
||||
|
||||
@@ -791,3 +791,6 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
rearranged += cword
|
||||
message = "[prefix][jointext(rearranged," ")]"
|
||||
. = message
|
||||
|
||||
#define is_alpha(X) ((text2ascii(X) <= 122) && (text2ascii(X) >= 97))
|
||||
#define is_digit(X) ((length(X) == 1) && (length(text2num(X)) == 1))
|
||||
@@ -32,6 +32,7 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"UNIQUE_RENAME" = UNIQUE_RENAME,
|
||||
"USES_TGUI" = USES_TGUI,
|
||||
"FROZEN" = FROZEN,
|
||||
"SHOVABLE_ONTO" = SHOVABLE_ONTO
|
||||
),
|
||||
"datum_flags" = list(
|
||||
"DF_USE_TAG" = DF_USE_TAG,
|
||||
@@ -171,10 +172,32 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"rad_flags" = list(
|
||||
"RAD_PROTECT_CONTENTS" = RAD_PROTECT_CONTENTS,
|
||||
"RAD_NO_CONTAMINATE" = RAD_NO_CONTAMINATE,
|
||||
),
|
||||
),
|
||||
"disease_flags" = list(
|
||||
"CURABLE" = CURABLE,
|
||||
"CAN_CARRY" = CAN_CARRY,
|
||||
"CAN_RESIST" = CAN_RESIST
|
||||
),
|
||||
))
|
||||
),
|
||||
"chemical_flags" = list(
|
||||
"REAGENT_DEAD_PROCESS" = REAGENT_DEAD_PROCESS,
|
||||
"REAGENT_DONOTSPLIT" = REAGENT_DONOTSPLIT,
|
||||
"REAGENT_ONLYINVERSE" = REAGENT_ONLYINVERSE,
|
||||
"REAGENT_ONMOBMERGE" = REAGENT_ONMOBMERGE,
|
||||
"REAGENT_INVISIBLE" = REAGENT_INVISIBLE,
|
||||
"REAGENT_FORCEONNEW" = REAGENT_FORCEONNEW,
|
||||
"REAGENT_SNEAKYNAME" = REAGENT_SNEAKYNAME,
|
||||
"REAGENT_SPLITRETAINVOL" = REAGENT_SPLITRETAINVOL
|
||||
),
|
||||
"clear_conversion" = list(
|
||||
"REACTION_CLEAR_IMPURE" = REACTION_CLEAR_IMPURE,
|
||||
"REACTION_CLEAR_INVERSE" = REACTION_CLEAR_INVERSE
|
||||
),
|
||||
"organ_flags" = list(
|
||||
"ORGAN_SYNTHETIC" = ORGAN_SYNTHETIC,
|
||||
"ORGAN_FROZEN" = ORGAN_FROZEN,
|
||||
"ORGAN_FAILING" = ORGAN_FAILING,
|
||||
"ORGAN_EXTERNAL" = ORGAN_EXTERNAL,
|
||||
"ORGAN_VITAL" = ORGAN_VITAL,
|
||||
"ORGAN_NO_SPOIL" = ORGAN_NO_SPOIL
|
||||
),
|
||||
))
|
||||
|
||||
@@ -26,6 +26,8 @@ GLOBAL_VAR(query_debug_log)
|
||||
GLOBAL_PROTECT(query_debug_log)
|
||||
GLOBAL_VAR(world_job_debug_log)
|
||||
GLOBAL_PROTECT(world_job_debug_log)
|
||||
GLOBAL_VAR(world_virus_log)
|
||||
GLOBAL_PROTECT(world_virus_log)
|
||||
|
||||
GLOBAL_LIST_EMPTY(bombers)
|
||||
GLOBAL_PROTECT(bombers)
|
||||
|
||||
@@ -55,6 +55,17 @@
|
||||
|
||||
var/obj/item/W = get_active_held_item()
|
||||
|
||||
if(!W && A.Adjacent(src) && (isobj(A) || ismob(A)))
|
||||
var/atom/movable/C = A
|
||||
if(C.can_buckle && C.has_buckled_mobs())
|
||||
if(C.buckled_mobs.len > 1)
|
||||
var/unbuckled = input(src, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in C.buckled_mobs
|
||||
if(C.user_unbuckle_mob(unbuckled,src))
|
||||
return
|
||||
else
|
||||
if(C.user_unbuckle_mob(C.buckled_mobs[1],src))
|
||||
return
|
||||
|
||||
if(!W && get_dist(src,A) <= interaction_range)
|
||||
A.attack_robot(src)
|
||||
return
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
var/image/item_overlay = image(holding)
|
||||
item_overlay.alpha = 92
|
||||
|
||||
if(!user.can_equip(holding, slot_id, disable_warning = TRUE))
|
||||
if(!user.can_equip(holding, slot_id, TRUE))
|
||||
item_overlay.color = "#FF0000"
|
||||
else
|
||||
item_overlay.color = "#00ff00"
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
|
||||
/datum/config_entry/flag/log_game // log game events
|
||||
|
||||
/datum/config_entry/flag/log_virus // log virology data
|
||||
|
||||
/datum/config_entry/flag/log_vote // log voting
|
||||
|
||||
/datum/config_entry/flag/log_whisper // log client whisper
|
||||
|
||||
@@ -294,7 +294,7 @@ Versioning
|
||||
var/lakey = L.lastattackerckey
|
||||
var/sqlbrute = L.getBruteLoss()
|
||||
var/sqlfire = L.getFireLoss()
|
||||
var/sqlbrain = L.getBrainLoss()
|
||||
var/sqlbrain = L.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
var/sqloxy = L.getOxyLoss()
|
||||
var/sqltox = L.getToxLoss()
|
||||
var/sqlclone = L.getCloneLoss()
|
||||
@@ -308,7 +308,7 @@ Versioning
|
||||
|
||||
if(!SSdbcore.Connect())
|
||||
return
|
||||
|
||||
|
||||
sqlname = sanitizeSQL(sqlname)
|
||||
sqlkey = sanitizeSQL(sqlkey)
|
||||
sqljob = sanitizeSQL(sqljob)
|
||||
|
||||
@@ -110,6 +110,9 @@ SUBSYSTEM_DEF(job)
|
||||
if(job.required_playtime_remaining(player.client))
|
||||
JobDebug("FOC player not enough xp, Player: [player]")
|
||||
continue
|
||||
if(!player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
JobDebug("FOC non-human failed, Player: [player]")
|
||||
continue
|
||||
if(flag && (!(flag in player.client.prefs.be_special)))
|
||||
JobDebug("FOC flag failed, Player: [player], Flag: [flag], ")
|
||||
continue
|
||||
@@ -145,6 +148,10 @@ SUBSYSTEM_DEF(job)
|
||||
JobDebug("GRJ player not old enough, Player: [player]")
|
||||
continue
|
||||
|
||||
if(!player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
JobDebug("GRJ non-human failed, Player: [player]")
|
||||
continue
|
||||
|
||||
if(job.required_playtime_remaining(player.client))
|
||||
JobDebug("GRJ player not enough xp, Player: [player]")
|
||||
continue
|
||||
@@ -327,6 +334,10 @@ SUBSYSTEM_DEF(job)
|
||||
if(job.required_playtime_remaining(player.client))
|
||||
JobDebug("DO player not enough xp, Player: [player], Job:[job.title]")
|
||||
continue
|
||||
|
||||
if(!player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
JobDebug("DO non-human failed, Player: [player], Job:[job.title]")
|
||||
continue
|
||||
|
||||
if(player.mind && job.title in player.mind.restricted_roles)
|
||||
JobDebug("DO incompatible with antagonist role, Player: [player], Job:[job.title]")
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s imaginary friend?", ROLE_PAI, null, null, 75, friend)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
friend.key = C.key
|
||||
C.transfer_ckey(friend, FALSE)
|
||||
friend_initialized = TRUE
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s split personality?", ROLE_PAI, null, null, 75, stranger_backseat)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
stranger_backseat.key = C.key
|
||||
C.transfer_ckey(stranger_backseat, FALSE)
|
||||
log_game("[key_name(stranger_backseat)] became [key_name(owner)]'s split personality.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(stranger_backseat)] became [ADMIN_LOOKUPFLW(owner)]'s split personality.")
|
||||
else
|
||||
@@ -184,7 +184,7 @@
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s brainwashed mind?", null, null, null, 75, stranger_backseat)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
stranger_backseat.key = C.key
|
||||
C.transfer_ckey(stranger_backseat, FALSE)
|
||||
else
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -26,5 +26,5 @@
|
||||
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
|
||||
ears.ear_damage = max(ears.ear_damage - 0.1, 0)
|
||||
ears.deaf = max(ears.deaf - 1, (ears.damage < ears.maxHealth ? 0 : 1)) // Do not clear deafness if our ears are too damaged
|
||||
ears.damage = max(ears.damage - 0.1, 0)
|
||||
|
||||
+107
-107
@@ -1,108 +1,108 @@
|
||||
/datum/component/footstep
|
||||
var/steps = 0
|
||||
var/volume
|
||||
var/e_range
|
||||
|
||||
/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1)
|
||||
if(!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
volume = volume_
|
||||
e_range = e_range_
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep)
|
||||
|
||||
/datum/component/footstep/proc/play_footstep()
|
||||
var/turf/open/T = get_turf(parent)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
var/mob/living/LM = parent
|
||||
var/v = volume
|
||||
var/e = e_range
|
||||
if(!T.footstep || LM.buckled || LM.lying || !LM.canmove || LM.resting || LM.buckled || LM.throwing || LM.movement_type & (VENTCRAWLING | FLYING))
|
||||
if (LM.lying && !LM.buckled && !(!T.footstep || LM.movement_type & (VENTCRAWLING | FLYING))) //play crawling sound if we're lying
|
||||
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(LM, TRAIT_SILENT_STEP))
|
||||
return
|
||||
|
||||
if(iscarbon(LM))
|
||||
var/mob/living/carbon/C = LM
|
||||
if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG))
|
||||
return
|
||||
if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK)
|
||||
v /= 2
|
||||
e -= 5
|
||||
steps++
|
||||
|
||||
if(steps >= 3)
|
||||
steps = 0
|
||||
|
||||
else
|
||||
return
|
||||
|
||||
if(prob(80) && !LM.has_gravity(T)) // don't need to step as often when you hop around
|
||||
return
|
||||
|
||||
//begin playsound shenanigans//
|
||||
|
||||
//for barefooted non-clawed mobs like monkeys
|
||||
if(isbarefoot(LM))
|
||||
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
|
||||
GLOB.barefootstep[T.barefootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.barefootstep[T.barefootstep][3] + e)
|
||||
return
|
||||
|
||||
//for xenomorphs, dogs, and other clawed mobs
|
||||
if(isclawfoot(LM))
|
||||
if(isalienadult(LM)) //xenos are stealthy and get quieter footsteps
|
||||
v /= 3
|
||||
e -= 5
|
||||
|
||||
playsound(T, pick(GLOB.clawfootstep[T.clawfootstep][1]),
|
||||
GLOB.clawfootstep[T.clawfootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.clawfootstep[T.clawfootstep][3] + e)
|
||||
return
|
||||
|
||||
//for megafauna and other large and imtimidating mobs such as the bloodminer
|
||||
if(isheavyfoot(LM))
|
||||
playsound(T, pick(GLOB.heavyfootstep[T.heavyfootstep][1]),
|
||||
GLOB.heavyfootstep[T.heavyfootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.heavyfootstep[T.heavyfootstep][3] + e)
|
||||
return
|
||||
|
||||
//for slimes
|
||||
if(isslime(LM))
|
||||
playsound(T, 'sound/effects/footstep/slime1.ogg', 15 * v)
|
||||
return
|
||||
|
||||
//for (simple) humanoid mobs (clowns, russians, pirates, etc.)
|
||||
if(isshoefoot(LM))
|
||||
if(!ishuman(LM))
|
||||
playsound(T, pick(GLOB.footstep[T.footstep][1]),
|
||||
GLOB.footstep[T.footstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.footstep[T.footstep][3] + e)
|
||||
return
|
||||
if(ishuman(LM)) //for proper humans, they're special
|
||||
var/mob/living/carbon/human/H = LM
|
||||
var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET))
|
||||
|
||||
if (H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle") //are we a naga or tentacle taur creature
|
||||
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
|
||||
return
|
||||
|
||||
if(H.shoes || feetCover) //are we wearing shoes
|
||||
playsound(T, pick(GLOB.footstep[T.footstep][1]),
|
||||
GLOB.footstep[T.footstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.footstep[T.footstep][3] + e)
|
||||
|
||||
if((!H.shoes && !feetCover)) //are we NOT wearing shoes
|
||||
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
|
||||
GLOB.barefootstep[T.barefootstep][2] * v,
|
||||
TRUE,
|
||||
/datum/component/footstep
|
||||
var/steps = 0
|
||||
var/volume
|
||||
var/e_range
|
||||
|
||||
/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1)
|
||||
if(!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
volume = volume_
|
||||
e_range = e_range_
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep)
|
||||
|
||||
/datum/component/footstep/proc/play_footstep()
|
||||
var/turf/open/T = get_turf(parent)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
var/mob/living/LM = parent
|
||||
var/v = volume
|
||||
var/e = e_range
|
||||
if(!T.footstep || LM.buckled || LM.lying || !LM.canmove || LM.resting || LM.buckled || LM.throwing || LM.movement_type & (VENTCRAWLING | FLYING))
|
||||
if (LM.lying && !LM.buckled && !(!T.footstep || LM.movement_type & (VENTCRAWLING | FLYING))) //play crawling sound if we're lying
|
||||
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(LM, TRAIT_SILENT_STEP))
|
||||
return
|
||||
|
||||
if(iscarbon(LM))
|
||||
var/mob/living/carbon/C = LM
|
||||
if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG))
|
||||
return
|
||||
if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK)
|
||||
v /= 2
|
||||
e -= 5
|
||||
steps++
|
||||
|
||||
if(steps >= 3)
|
||||
steps = 0
|
||||
|
||||
else
|
||||
return
|
||||
|
||||
if(prob(80) && !LM.has_gravity(T)) // don't need to step as often when you hop around
|
||||
return
|
||||
|
||||
//begin playsound shenanigans//
|
||||
|
||||
//for barefooted non-clawed mobs like monkeys
|
||||
if(isbarefoot(LM))
|
||||
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
|
||||
GLOB.barefootstep[T.barefootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.barefootstep[T.barefootstep][3] + e)
|
||||
return
|
||||
|
||||
//for xenomorphs, dogs, and other clawed mobs
|
||||
if(isclawfoot(LM))
|
||||
if(isalienadult(LM)) //xenos are stealthy and get quieter footsteps
|
||||
v /= 3
|
||||
e -= 5
|
||||
|
||||
playsound(T, pick(GLOB.clawfootstep[T.clawfootstep][1]),
|
||||
GLOB.clawfootstep[T.clawfootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.clawfootstep[T.clawfootstep][3] + e)
|
||||
return
|
||||
|
||||
//for megafauna and other large and imtimidating mobs such as the bloodminer
|
||||
if(isheavyfoot(LM))
|
||||
playsound(T, pick(GLOB.heavyfootstep[T.heavyfootstep][1]),
|
||||
GLOB.heavyfootstep[T.heavyfootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.heavyfootstep[T.heavyfootstep][3] + e)
|
||||
return
|
||||
|
||||
//for slimes
|
||||
if(isslime(LM))
|
||||
playsound(T, 'sound/effects/footstep/slime1.ogg', 15 * v)
|
||||
return
|
||||
|
||||
//for (simple) humanoid mobs (clowns, russians, pirates, etc.)
|
||||
if(isshoefoot(LM))
|
||||
if(!ishuman(LM))
|
||||
playsound(T, pick(GLOB.footstep[T.footstep][1]),
|
||||
GLOB.footstep[T.footstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.footstep[T.footstep][3] + e)
|
||||
return
|
||||
if(ishuman(LM)) //for proper humans, they're special
|
||||
var/mob/living/carbon/human/H = LM
|
||||
var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET))
|
||||
|
||||
if (H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle") //are we a naga or tentacle taur creature
|
||||
playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
|
||||
return
|
||||
|
||||
if(H.shoes || feetCover) //are we wearing shoes
|
||||
playsound(T, pick(GLOB.footstep[T.footstep][1]),
|
||||
GLOB.footstep[T.footstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.footstep[T.footstep][3] + e)
|
||||
|
||||
if((!H.shoes && !feetCover)) //are we NOT wearing shoes
|
||||
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
|
||||
GLOB.barefootstep[T.barefootstep][2] * v,
|
||||
TRUE,
|
||||
GLOB.barefootstep[T.barefootstep][3] + e)
|
||||
@@ -162,12 +162,12 @@
|
||||
if(!Process_Spacemove(direction) || !isturf(AM.loc))
|
||||
return
|
||||
step(AM, direction)
|
||||
|
||||
|
||||
if((direction & (direction - 1)) && (AM.loc == next)) //moved diagonally
|
||||
last_move_diagonal = TRUE
|
||||
else
|
||||
last_move_diagonal = FALSE
|
||||
|
||||
|
||||
handle_vehicle_layer()
|
||||
handle_vehicle_offsets()
|
||||
else
|
||||
@@ -195,21 +195,47 @@
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
|
||||
|
||||
/datum/component/riding/human/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE)
|
||||
var/mob/living/carbon/human/H = parent
|
||||
H.remove_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING)
|
||||
. = ..()
|
||||
|
||||
/datum/component/riding/human/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE)
|
||||
. = ..()
|
||||
var/mob/living/carbon/human/H = parent
|
||||
H.add_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING, multiplicative_slowdown = HUMAN_CARRY_SLOWDOWN)
|
||||
|
||||
/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target)
|
||||
var/mob/living/carbon/human/AM = parent
|
||||
if(AM.a_intent == INTENT_DISARM && (target in AM.buckled_mobs))
|
||||
var/mob/living/carbon/human/H = parent
|
||||
if(H.a_intent == INTENT_DISARM && (target in H.buckled_mobs))
|
||||
force_dismount(target)
|
||||
|
||||
/datum/component/riding/human/handle_vehicle_layer()
|
||||
var/atom/movable/AM = parent
|
||||
if(AM.buckled_mobs && AM.buckled_mobs.len)
|
||||
if(AM.dir == SOUTH)
|
||||
AM.layer = ABOVE_MOB_LAYER
|
||||
for(var/mob/M in AM.buckled_mobs) //ensure proper layering of piggyback and carry, sometimes weird offsets get applied
|
||||
M.layer = MOB_LAYER
|
||||
if(!AM.buckle_lying)
|
||||
if(AM.dir == SOUTH)
|
||||
AM.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
AM.layer = OBJ_LAYER
|
||||
else
|
||||
AM.layer = OBJ_LAYER
|
||||
if(AM.dir == NORTH)
|
||||
AM.layer = OBJ_LAYER
|
||||
else
|
||||
AM.layer = ABOVE_MOB_LAYER
|
||||
else
|
||||
AM.layer = MOB_LAYER
|
||||
|
||||
/datum/component/riding/human/get_offsets(pass_index)
|
||||
var/mob/living/carbon/human/H = parent
|
||||
if(H.buckle_lying)
|
||||
return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(0, 6), TEXT_WEST = list(0, 6))
|
||||
else
|
||||
return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(-6, 4), TEXT_WEST = list( 6, 4))
|
||||
|
||||
|
||||
/datum/component/riding/human/force_dismount(mob/living/user)
|
||||
var/atom/movable/AM = parent
|
||||
AM.unbuckle_mob(user)
|
||||
@@ -273,12 +299,15 @@
|
||||
M.throw_at(target, 14, 5, AM)
|
||||
M.Knockdown(60)
|
||||
|
||||
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1)
|
||||
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, riding_target_override = null)
|
||||
var/atom/movable/AM = parent
|
||||
var/amount_equipped = 0
|
||||
for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
|
||||
var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
|
||||
inhand.rider = user
|
||||
if(!riding_target_override)
|
||||
inhand.rider = user
|
||||
else
|
||||
inhand.rider = riding_target_override
|
||||
inhand.parent = AM
|
||||
if(user.put_in_hands(inhand, TRUE))
|
||||
amount_equipped++
|
||||
@@ -318,7 +347,7 @@
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_offhand/equipped()
|
||||
if(loc != rider)
|
||||
if(loc != rider && loc != parent)
|
||||
selfdeleting = TRUE
|
||||
qdel(src)
|
||||
. = ..()
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
|
||||
/datum/component/storage/proc/quick_empty(mob/M)
|
||||
var/atom/A = parent
|
||||
if((!ishuman(M) && (A.loc != M)) || (M.stat != CONSCIOUS) || M.restrained() || !M.canmove)
|
||||
if(!M.canUseStorage() || !A.Adjacent(M) || M.incapacitated())
|
||||
return
|
||||
if(check_locked(null, M, TRUE))
|
||||
return FALSE
|
||||
|
||||
@@ -24,8 +24,9 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
var/unlock_note
|
||||
var/unlock_code
|
||||
var/failsafe_code
|
||||
var/datum/ui_state/checkstate
|
||||
|
||||
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20)
|
||||
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate)
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
@@ -57,6 +58,7 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
active = _enabled
|
||||
gamemode = _gamemode
|
||||
telecrystals = starting_tc
|
||||
checkstate = _checkstate
|
||||
if(!lockable)
|
||||
active = TRUE
|
||||
locked = FALSE
|
||||
@@ -115,6 +117,7 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
|
||||
/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
|
||||
state = checkstate ? checkstate : state
|
||||
active = TRUE
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
@@ -123,6 +126,12 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
ui.set_style("syndicate")
|
||||
ui.open()
|
||||
|
||||
/datum/component/uplink/ui_host(mob/user)
|
||||
if(istype(parent, /obj/item/implant)) //implants are like organs, not really located inside mobs codewise.
|
||||
var/obj/item/implant/I = parent
|
||||
return I.imp_in
|
||||
return ..()
|
||||
|
||||
/datum/component/uplink/ui_data(mob/user)
|
||||
if(!user.mind)
|
||||
return
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/datum/component/virtual_reality
|
||||
dupe_mode = COMPONENT_DUPE_ALLOWED //mindswap memes, shouldn't stack up otherwise.
|
||||
var/datum/mind/mastermind // where is my mind t. pixies
|
||||
var/datum/mind/current_mind
|
||||
var/obj/machinery/vr_sleeper/vr_sleeper
|
||||
var/datum/action/quit_vr/quit_action
|
||||
var/you_die_in_the_game_you_die_for_real = FALSE
|
||||
var/datum/component/virtual_reality/inception //The component works on a very fragile link betwixt mind, ckey and death.
|
||||
|
||||
/datum/component/virtual_reality/Initialize(mob/M, obj/machinery/vr_sleeper/gaming_pod, yolo = FALSE, new_char = TRUE)
|
||||
if(!ismob(parent) || !istype(M))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
var/mob/vr_M = parent
|
||||
mastermind = M.mind
|
||||
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED), .proc/game_over)
|
||||
RegisterSignal(M, COMSIG_MOB_KEY_CHANGE, .proc/switch_player)
|
||||
RegisterSignal(mastermind, COMSIG_MIND_TRANSFER, .proc/switch_player)
|
||||
you_die_in_the_game_you_die_for_real = yolo
|
||||
quit_action = new()
|
||||
if(gaming_pod)
|
||||
vr_sleeper = gaming_pod
|
||||
RegisterSignal(vr_sleeper, COMSIG_ATOM_EMAG_ACT, .proc/you_only_live_once)
|
||||
RegisterSignal(vr_sleeper, COMSIG_MACHINE_EJECT_OCCUPANT, .proc/revert_to_reality)
|
||||
vr_M.ckey = M.ckey
|
||||
var/datum/component/virtual_reality/clusterfk = M.GetComponent(/datum/component/virtual_reality)
|
||||
if(clusterfk && !clusterfk.inception)
|
||||
clusterfk.inception = src
|
||||
SStgui.close_user_uis(M, src)
|
||||
|
||||
/datum/component/virtual_reality/RegisterWithParent()
|
||||
var/mob/M = parent
|
||||
current_mind = M.mind
|
||||
quit_action.Grant(M)
|
||||
RegisterSignal(quit_action, COMSIG_ACTION_TRIGGER, .proc/revert_to_reality)
|
||||
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED), .proc/game_over)
|
||||
RegisterSignal(M, COMSIG_MOB_GHOSTIZE, .proc/be_a_quitter)
|
||||
RegisterSignal(M, COMSIG_MOB_KEY_CHANGE, .proc/pass_me_the_remote)
|
||||
RegisterSignal(current_mind, COMSIG_MIND_TRANSFER, .proc/pass_me_the_remote)
|
||||
mastermind.current.audiovisual_redirect = M
|
||||
if(vr_sleeper)
|
||||
vr_sleeper.vr_mob = M
|
||||
|
||||
/datum/component/virtual_reality/UnregisterFromParent()
|
||||
quit_action.Remove(parent)
|
||||
UnregisterSignal(parent, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED, COMSIG_MOB_KEY_CHANGE, COMSIG_MOB_GHOSTIZE))
|
||||
UnregisterSignal(current_mind, COMSIG_MIND_TRANSFER)
|
||||
UnregisterSignal(quit_action, COMSIG_ACTION_TRIGGER)
|
||||
current_mind = null
|
||||
mastermind.current.audiovisual_redirect = null
|
||||
|
||||
/datum/component/virtual_reality/proc/switch_player(datum/source, mob/new_mob, mob/old_mob)
|
||||
if(vr_sleeper || !new_mob.mind)
|
||||
// Machineries currently don't deal up with the occupant being polymorphed et similar... Or did something fuck up?
|
||||
revert_to_reality()
|
||||
return
|
||||
old_mob.audiovisual_redirect = null
|
||||
new_mob.audiovisual_redirect = parent
|
||||
|
||||
/datum/component/virtual_reality/proc/action_trigger(datum/signal_source, datum/action/source)
|
||||
if(source != quit_action)
|
||||
return COMPONENT_ACTION_BLOCK_TRIGGER
|
||||
revert_to_reality(signal_source)
|
||||
|
||||
/datum/component/virtual_reality/proc/you_only_live_once()
|
||||
if(you_die_in_the_game_you_die_for_real || vr_sleeper?.only_current_user_can_interact)
|
||||
return FALSE
|
||||
you_die_in_the_game_you_die_for_real = TRUE
|
||||
return TRUE
|
||||
|
||||
/datum/component/virtual_reality/proc/pass_me_the_remote(datum/source, mob/new_mob)
|
||||
if(new_mob == mastermind.current)
|
||||
revert_to_reality(source)
|
||||
return TRUE
|
||||
new_mob.TakeComponent(src)
|
||||
return TRUE
|
||||
|
||||
/datum/component/virtual_reality/PostTransfer()
|
||||
if(!ismob(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
/datum/component/virtual_reality/proc/revert_to_reality(datum/source)
|
||||
quit_it()
|
||||
|
||||
/datum/component/virtual_reality/proc/game_over(datum/source)
|
||||
quit_it(TRUE, TRUE)
|
||||
|
||||
/datum/component/virtual_reality/proc/be_a_quitter(datum/source, can_reenter_corpse)
|
||||
quit_it()
|
||||
return COMPONENT_BLOCK_GHOSTING
|
||||
|
||||
/datum/component/virtual_reality/proc/virtual_reality_in_a_virtual_reality(mob/player, killme = FALSE, datum/component/virtual_reality/yo_dawg)
|
||||
var/mob/M = parent
|
||||
quit_it(FALSE, killme, player, yo_dawg)
|
||||
yo_dawg.inception = null
|
||||
if(killme)
|
||||
M.death(FALSE)
|
||||
|
||||
/datum/component/virtual_reality/proc/quit_it(deathcheck = FALSE, cleanup = FALSE, mob/override)
|
||||
var/mob/M = parent
|
||||
var/mob/dreamer = override ? override : mastermind.current
|
||||
if(!mastermind)
|
||||
to_chat(M, "<span class='warning'>You feel a dreadful sensation, something terrible happened. You try to wake up, but you find yourself unable to...</span>")
|
||||
else
|
||||
var/key_transfer = FALSE
|
||||
if(inception?.parent)
|
||||
inception.virtual_reality_in_a_virtual_reality(dreamer, cleanup, src)
|
||||
else
|
||||
key_transfer = TRUE
|
||||
if(key_transfer)
|
||||
M.transfer_ckey(dreamer, FALSE)
|
||||
dreamer.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
dreamer.audiovisual_redirect = null
|
||||
if(deathcheck && you_die_in_the_game_you_die_for_real)
|
||||
to_chat(mastermind, "<span class='warning'>You feel everything fading away...</span>")
|
||||
dreamer.death(FALSE)
|
||||
if(cleanup)
|
||||
var/obj/effect/vr_clean_master/cleanbot = locate() in get_area(M)
|
||||
if(cleanbot)
|
||||
LAZYADD(cleanbot.corpse_party, M)
|
||||
if(vr_sleeper)
|
||||
vr_sleeper.vr_mob = null
|
||||
vr_sleeper = null
|
||||
qdel(src)
|
||||
|
||||
/datum/component/virtual_reality/Destroy()
|
||||
var/datum/action/quit_vr/delet_me = quit_action
|
||||
. = ..()
|
||||
qdel(delet_me)
|
||||
@@ -94,10 +94,23 @@
|
||||
TOXIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=toxin' id='toxin'>[M.getToxLoss()]</a>
|
||||
OXY:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=oxygen' id='oxygen'>[M.getOxyLoss()]</a>
|
||||
CLONE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=clone' id='clone'>[M.getCloneLoss()]</a>
|
||||
BRAIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brain' id='brain'>[M.getBrainLoss()]</a>
|
||||
BRAIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brain' id='brain'>[M.getOrganLoss(ORGAN_SLOT_BRAIN)]</a>
|
||||
STAMINA:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=stamina' id='stamina'>[M.getStaminaLoss()]</a>
|
||||
AROUSAL:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=arousal' id='arousal'>[M.getArousalLoss()]</a>
|
||||
</font>
|
||||
"}
|
||||
if(GLOB.Debug2)
|
||||
atomsnowflake += {"
|
||||
HEART:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=heart' id='heart'>[M.getOrganLoss(ORGAN_SLOT_HEART)]</a>
|
||||
LIVER:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=liver' id='liver'>[M.getOrganLoss(ORGAN_SLOT_LIVER)]</a>
|
||||
LUNGS:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=lungs' id='lungs'>[M.getOrganLoss(ORGAN_SLOT_LUNGS)]</a>
|
||||
EYES:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=eye_sight' id='eye_sight'>[M.getOrganLoss(ORGAN_SLOT_EYES)]</a>
|
||||
EARS:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=ears' id='ears'>[M.getOrganLoss(ORGAN_SLOT_EARS)]</a>
|
||||
STOMACH:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=stomach' id='stomach'>[M.getOrganLoss(ORGAN_SLOT_STOMACH)]</a>
|
||||
TONGUE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=tongue' id='tongue'>[M.getOrganLoss(ORGAN_SLOT_TONGUE)]</a>
|
||||
APPENDIX:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=appendix' id='appendix'>[M.getOrganLoss(ORGAN_SLOT_APPENDIX)]</a>
|
||||
"}
|
||||
atomsnowflake += {"
|
||||
</font>
|
||||
"}
|
||||
else
|
||||
atomsnowflake += "<a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=name'><b id='name'>[D]</b></a>"
|
||||
@@ -1334,8 +1347,8 @@
|
||||
L.adjustOxyLoss(amount)
|
||||
newamt = L.getOxyLoss()
|
||||
if("brain")
|
||||
L.adjustBrainLoss(amount)
|
||||
newamt = L.getBrainLoss()
|
||||
L.adjustOrganLoss(ORGAN_SLOT_BRAIN, amount)
|
||||
newamt = L.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
if("clone")
|
||||
L.adjustCloneLoss(amount)
|
||||
newamt = L.getCloneLoss()
|
||||
@@ -1345,6 +1358,30 @@
|
||||
if("arousal")
|
||||
L.adjustArousalLoss(amount)
|
||||
newamt = L.getArousalLoss()
|
||||
if("heart")
|
||||
L.adjustOrganLoss(ORGAN_SLOT_HEART, amount)
|
||||
newamt = L.getOrganLoss(ORGAN_SLOT_HEART)
|
||||
if("liver")
|
||||
L.adjustOrganLoss(ORGAN_SLOT_LIVER, amount)
|
||||
newamt = L.getOrganLoss(ORGAN_SLOT_LIVER)
|
||||
if("lungs")
|
||||
L.adjustOrganLoss(ORGAN_SLOT_LUNGS, amount)
|
||||
newamt = L.getOrganLoss(ORGAN_SLOT_LUNGS)
|
||||
if("eye_sight")
|
||||
L.adjustOrganLoss(ORGAN_SLOT_EYES, amount)
|
||||
newamt = L.getOrganLoss(ORGAN_SLOT_EYES)
|
||||
if("ears")
|
||||
L.adjustOrganLoss(ORGAN_SLOT_EARS, amount)
|
||||
newamt = L.getOrganLoss(ORGAN_SLOT_EARS)
|
||||
if("stomach")
|
||||
L.adjustOrganLoss(ORGAN_SLOT_STOMACH, amount)
|
||||
newamt = L.getOrganLoss(ORGAN_SLOT_STOMACH)
|
||||
if("tongue")
|
||||
L.adjustOrganLoss(ORGAN_SLOT_TONGUE, amount)
|
||||
newamt = L.getOrganLoss(ORGAN_SLOT_TONGUE)
|
||||
if("appendix")
|
||||
L.adjustOrganLoss(ORGAN_SLOT_APPENDIX, amount)
|
||||
newamt = L.getOrganLoss(ORGAN_SLOT_APPENDIX)
|
||||
else
|
||||
to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]")
|
||||
return
|
||||
@@ -1360,4 +1397,4 @@
|
||||
return
|
||||
var/mob/living/carbon/human/H = locate(href_list["copyoutfit"]) in GLOB.carbon_list
|
||||
if(istype(H))
|
||||
H.copy_outfit()
|
||||
H.copy_outfit()
|
||||
|
||||
@@ -144,3 +144,9 @@
|
||||
if(!((locate(thing) in bodyparts) || (locate(thing) in internal_organs)))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/proc/CanSpreadAirborneDisease()
|
||||
return !is_mouth_covered()
|
||||
|
||||
/mob/living/carbon/CanSpreadAirborneDisease()
|
||||
return !((head && (head.flags_cover & HEADCOVERSMOUTH) && (head.armor.getRating("bio") >= 25)) || (wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH) && (wear_mask.armor.getRating("bio") >= 25)))
|
||||
@@ -55,6 +55,13 @@
|
||||
D.after_add()
|
||||
infectee.med_hud_set_status()
|
||||
|
||||
var/turf/source_turf = get_turf(infectee)
|
||||
log_virus("[key_name(infectee)] was infected by virus: [src.admin_details()] at [loc_name(source_turf)]")
|
||||
|
||||
//Return a string for admin logging uses, should describe the disease in detail
|
||||
/datum/disease/proc/admin_details()
|
||||
return "[src.name] : [src.type]"
|
||||
|
||||
/datum/disease/proc/stage_act()
|
||||
var/cure = has_cure()
|
||||
|
||||
@@ -65,15 +72,17 @@
|
||||
|
||||
if(!cure)
|
||||
if(prob(stage_prob))
|
||||
stage = min(stage + 1,max_stages)
|
||||
update_stage(min(stage + 1,max_stages))
|
||||
else
|
||||
if(prob(cure_chance))
|
||||
stage = max(stage - 1, 1)
|
||||
update_stage(max(stage - 1, 1))
|
||||
|
||||
if(disease_flags & CURABLE)
|
||||
if(cure && prob(cure_chance))
|
||||
cure()
|
||||
|
||||
/datum/disease/proc/update_stage(new_stage)
|
||||
stage = new_stage
|
||||
|
||||
/datum/disease/proc/has_cure()
|
||||
if(!(disease_flags & CURABLE))
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
var/id = ""
|
||||
var/processing = FALSE
|
||||
var/mutable = TRUE //set to FALSE to prevent most in-game methods of altering the disease via virology
|
||||
var/oldres
|
||||
var/oldres //To prevent setting new cures unless resistance changes.
|
||||
|
||||
// The order goes from easy to cure to hard to cure.
|
||||
// The order goes from easy to cure to hard to cure. Keep in mind that sentient diseases pick two cures from tier 6 and up, ensure they wont react away in bodies.
|
||||
var/static/list/advance_cures = list(
|
||||
list( // level 1
|
||||
"copper", "silver", "iodine", "iron", "carbon"
|
||||
@@ -110,15 +110,22 @@
|
||||
return
|
||||
|
||||
if(symptoms && symptoms.len)
|
||||
|
||||
if(!processing)
|
||||
processing = TRUE
|
||||
for(var/datum/symptom/S in symptoms)
|
||||
S.Start(src)
|
||||
if(S.Start(src)) //this will return FALSE if the symptom is neutered
|
||||
S.next_activation = world.time + rand(S.symptom_delay_min * 10, S.symptom_delay_max * 10)
|
||||
S.on_stage_change(src)
|
||||
|
||||
for(var/datum/symptom/S in symptoms)
|
||||
S.Activate(src)
|
||||
|
||||
// Tell symptoms stage changed
|
||||
/datum/disease/advance/update_stage(new_stage)
|
||||
..()
|
||||
for(var/datum/symptom/S in symptoms)
|
||||
S.on_stage_change(src)
|
||||
|
||||
// Compares type then ID.
|
||||
/datum/disease/advance/IsSame(datum/disease/advance/D)
|
||||
|
||||
@@ -138,9 +145,18 @@
|
||||
A.properties = properties.Copy()
|
||||
A.id = id
|
||||
A.mutable = mutable
|
||||
A.oldres = oldres
|
||||
//this is a new disease starting over at stage 1, so processing is not copied
|
||||
return A
|
||||
|
||||
//Describe this disease to an admin in detail (for logging)
|
||||
/datum/disease/advance/admin_details()
|
||||
var/list/name_symptoms = list()
|
||||
for(var/datum/symptom/S in symptoms)
|
||||
name_symptoms += S.name
|
||||
return "[name] sym:[english_list(name_symptoms)] r:[totalResistance()] s:[totalStealth()] ss:[totalStageSpeed()] t:[totalTransmittable()]"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
NEW PROCS
|
||||
@@ -191,6 +207,10 @@
|
||||
/datum/disease/advance/proc/Refresh(new_name = FALSE)
|
||||
GenerateProperties()
|
||||
AssignProperties()
|
||||
if(processing && symptoms && symptoms.len)
|
||||
for(var/datum/symptom/S in symptoms)
|
||||
S.Start(src)
|
||||
S.on_stage_change(src)
|
||||
id = null
|
||||
|
||||
var/the_id = GetDiseaseID()
|
||||
@@ -342,28 +362,28 @@
|
||||
return id
|
||||
|
||||
|
||||
// Add a symptom, if it is over the limit (with a small chance to be able to go over)
|
||||
// we take a random symptom away and add the new one.
|
||||
// Add a symptom, if it is over the limit we take a random symptom away and add the new one.
|
||||
/datum/disease/advance/proc/AddSymptom(datum/symptom/S)
|
||||
|
||||
if(HasSymptom(S))
|
||||
return
|
||||
|
||||
if(symptoms.len < (VIRUS_SYMPTOM_LIMIT - 1) + rand(-1, 1))
|
||||
symptoms += S
|
||||
else
|
||||
if(!(symptoms.len < (VIRUS_SYMPTOM_LIMIT - 1) + rand(-1, 1)))
|
||||
RemoveSymptom(pick(symptoms))
|
||||
symptoms += S
|
||||
symptoms += S
|
||||
S.OnAdd(src)
|
||||
|
||||
// Simply removes the symptom.
|
||||
/datum/disease/advance/proc/RemoveSymptom(datum/symptom/S)
|
||||
symptoms -= S
|
||||
S.OnRemove(src)
|
||||
|
||||
// Neuter a symptom, so it will only affect stats
|
||||
/datum/disease/advance/proc/NeuterSymptom(datum/symptom/S)
|
||||
if(!S.neutered)
|
||||
S.neutered = TRUE
|
||||
S.name += " (neutered)"
|
||||
S.OnRemove(src)
|
||||
|
||||
/*
|
||||
|
||||
@@ -417,7 +437,7 @@
|
||||
|
||||
var/i = VIRUS_SYMPTOM_LIMIT
|
||||
|
||||
var/datum/disease/advance/D = new(0, null)
|
||||
var/datum/disease/advance/D = new()
|
||||
D.symptoms = list()
|
||||
|
||||
var/list/symptoms = list()
|
||||
@@ -445,9 +465,6 @@
|
||||
D.AssignName(new_name)
|
||||
D.Refresh()
|
||||
|
||||
for(var/datum/disease/advance/AD in SSdisease.active_diseases)
|
||||
AD.Refresh()
|
||||
|
||||
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list))
|
||||
if(!is_station_level(H.z))
|
||||
continue
|
||||
@@ -458,8 +475,8 @@
|
||||
var/list/name_symptoms = list()
|
||||
for(var/datum/symptom/S in D.symptoms)
|
||||
name_symptoms += S.name
|
||||
message_admins("[key_name_admin(user)] has triggered a custom virus outbreak of [D.name]! It has these symptoms: [english_list(name_symptoms)]")
|
||||
|
||||
message_admins("[key_name_admin(user)] has triggered a custom virus outbreak of [D.admin_details()]")
|
||||
log_virus("[key_name(user)] has triggered a custom virus outbreak of [D.admin_details()]!")
|
||||
|
||||
/datum/disease/advance/proc/totalStageSpeed()
|
||||
return properties["stage_rate"]
|
||||
|
||||
@@ -144,5 +144,5 @@ Bonus
|
||||
/datum/symptom/asphyxiation/proc/Asphyxiate_death(mob/living/M, datum/disease/advance/A)
|
||||
var/get_damage = rand(25,35) * power
|
||||
M.adjustOxyLoss(get_damage)
|
||||
M.adjustBrainLoss(get_damage/2)
|
||||
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, get_damage/2)
|
||||
return 1
|
||||
|
||||
@@ -55,7 +55,7 @@ Bonus
|
||||
to_chat(M, "<span class='userdanger'>You can't think straight!</span>")
|
||||
M.confused = min(100 * power, M.confused + 8)
|
||||
if(brain_damage)
|
||||
M.adjustBrainLoss(3 * power, 80)
|
||||
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3 * power, 80)
|
||||
M.updatehealth()
|
||||
|
||||
return
|
||||
|
||||
@@ -70,6 +70,6 @@ BONUS
|
||||
addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 6)
|
||||
addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 12)
|
||||
addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 18)
|
||||
if(infective)
|
||||
if(infective && M.CanSpreadAirborneDisease())
|
||||
A.spread(1)
|
||||
|
||||
|
||||
@@ -50,9 +50,9 @@ Bonus
|
||||
if(5)
|
||||
if(power > 2)
|
||||
var/obj/item/organ/ears/ears = M.getorganslot(ORGAN_SLOT_EARS)
|
||||
if(istype(ears) && ears.ear_damage < UNHEALING_EAR_DAMAGE)
|
||||
if(istype(ears) && ears.damage < ears.maxHealth)
|
||||
to_chat(M, "<span class='userdanger'>Your ears pop painfully and start bleeding!</span>")
|
||||
ears.ear_damage = max(ears.ear_damage, UNHEALING_EAR_DAMAGE)
|
||||
ears.damage = max(ears.damage, ears.maxHealth)
|
||||
M.emote("scream")
|
||||
else
|
||||
to_chat(M, "<span class='userdanger'>Your ears pop and begin ringing loudly!</span>")
|
||||
|
||||
@@ -219,8 +219,10 @@
|
||||
level = 8
|
||||
passive_message = "<span class='notice'>The pain from your wounds makes you feel oddly sleepy...</span>"
|
||||
var/deathgasp = FALSE
|
||||
var/stabilize = FALSE
|
||||
var/active_coma = FALSE //to prevent multiple coma procs
|
||||
threshold_desc = "<b>Stealth 2:</b> Host appears to die when falling into a coma.<br>\
|
||||
<b>Resistance 4:</b> The virus also stabilizes the host while they are in critical condition.<br>\
|
||||
<b>Stage Speed 7:</b> Increases healing speed."
|
||||
|
||||
/datum/symptom/heal/coma/Start(datum/disease/advance/A)
|
||||
@@ -228,9 +230,25 @@
|
||||
return
|
||||
if(A.properties["stage_rate"] >= 7)
|
||||
power = 1.5
|
||||
if(A.properties["resistance"] >= 4)
|
||||
stabilize = TRUE
|
||||
if(A.properties["stealth"] >= 2)
|
||||
deathgasp = TRUE
|
||||
|
||||
/datum/symptom/heal/coma/on_stage_change(datum/disease/advance/A) //mostly copy+pasted from the code for self-respiration's TRAIT_NOBREATH stuff
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(A.stage >= 4 && stabilize)
|
||||
ADD_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT)
|
||||
else
|
||||
REMOVE_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT)
|
||||
return TRUE
|
||||
|
||||
/datum/symptom/heal/coma/End(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
REMOVE_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT)
|
||||
|
||||
/datum/symptom/heal/coma/CanHeal(datum/disease/advance/A)
|
||||
var/mob/living/M = A.affected_mob
|
||||
if(HAS_TRAIT(M, TRAIT_DEATHCOMA))
|
||||
|
||||
@@ -50,3 +50,19 @@ Bonus
|
||||
if(prob(base_message_chance))
|
||||
to_chat(M, "<span class='notice'>[pick("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe.")]</span>")
|
||||
return
|
||||
|
||||
/datum/symptom/oxygen/on_stage_change(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return FALSE
|
||||
var/mob/living/carbon/M = A.affected_mob
|
||||
if(A.stage >= 4)
|
||||
ADD_TRAIT(M, TRAIT_NOBREATH, DISEASE_TRAIT)
|
||||
else
|
||||
REMOVE_TRAIT(M, TRAIT_NOBREATH, DISEASE_TRAIT)
|
||||
return TRUE
|
||||
|
||||
/datum/symptom/oxygen/End(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
if(A.stage >= 4)
|
||||
REMOVE_TRAIT(A.affected_mob, TRAIT_NOBREATH, DISEASE_TRAIT)
|
||||
@@ -51,7 +51,7 @@
|
||||
M.hallucination = max(0, M.hallucination - 10)
|
||||
|
||||
if(A.stage >= 5)
|
||||
M.adjustBrainLoss(-3)
|
||||
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -3)
|
||||
if(trauma_heal_mild && iscarbon(M))
|
||||
var/mob/living/carbon/C = M
|
||||
if(prob(10))
|
||||
@@ -100,8 +100,8 @@
|
||||
else if(M.eye_blind || M.eye_blurry)
|
||||
M.set_blindness(0)
|
||||
M.set_blurriness(0)
|
||||
else if(eyes.eye_damage > 0)
|
||||
M.adjust_eye_damage(-1)
|
||||
else if(eyes.damage > 0)
|
||||
eyes.applyOrganDamage(-1)
|
||||
else
|
||||
if(prob(base_message_chance))
|
||||
to_chat(M, "<span class='notice'>[pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink.","Your ears feel great.","Your healing feels more acute.")]</span>")
|
||||
to_chat(M, "<span class='notice'>[pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink.","Your ears feel great.","Your healing feels more acute.")]</span>")
|
||||
|
||||
@@ -48,4 +48,5 @@ Bonus
|
||||
M.emote("sniff")
|
||||
else
|
||||
M.emote("sneeze")
|
||||
A.spread(4 + power)
|
||||
if(M.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth
|
||||
A.spread(4 + power)
|
||||
@@ -8,12 +8,14 @@
|
||||
level = 5
|
||||
severity = 0
|
||||
|
||||
/datum/symptom/undead_adaptation/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
/datum/symptom/undead_adaptation/OnAdd(datum/disease/advance/A)
|
||||
A.process_dead = TRUE
|
||||
A.infectable_biotypes |= MOB_UNDEAD
|
||||
|
||||
/datum/symptom/undead_adaptation/OnRemove(datum/disease/advance/A)
|
||||
A.process_dead = FALSE
|
||||
A.infectable_biotypes -= MOB_UNDEAD
|
||||
|
||||
/datum/symptom/inorganic_adaptation
|
||||
name = "Inorganic Biology"
|
||||
desc = "The virus can survive and replicate even in an inorganic environment, increasing its resistance and infection rate."
|
||||
@@ -24,7 +26,8 @@
|
||||
level = 5
|
||||
severity = 0
|
||||
|
||||
/datum/symptom/inorganic_adaptation/Start(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
A.infectable_biotypes |= MOB_INORGANIC
|
||||
/datum/symptom/inorganic_adaptation/OnAdd(datum/disease/advance/A)
|
||||
A.infectable_biotypes |= MOB_INORGANIC
|
||||
|
||||
/datum/symptom/inorganic_adaptation/OnRemove(datum/disease/advance/A)
|
||||
A.infectable_biotypes -= MOB_INORGANIC
|
||||
@@ -38,11 +38,10 @@
|
||||
return
|
||||
CRASH("We couldn't assign an ID!")
|
||||
|
||||
// Called when processing of the advance disease, which holds this symptom, starts.
|
||||
// Called when processing of the advance disease that holds this symptom infects a host and upon each Refresh() of that advance disease.
|
||||
/datum/symptom/proc/Start(datum/disease/advance/A)
|
||||
if(neutered)
|
||||
return FALSE
|
||||
next_activation = world.time + rand(symptom_delay_min * 10, symptom_delay_max * 10) //so it doesn't instantly activate on infection
|
||||
return TRUE
|
||||
|
||||
// Called when the advance disease is going to be deleted or when the advance disease stops processing.
|
||||
@@ -60,6 +59,11 @@
|
||||
next_activation = world.time + rand(symptom_delay_min * 10, symptom_delay_max * 10)
|
||||
return TRUE
|
||||
|
||||
/datum/symptom/proc/on_stage_change(datum/disease/advance/A)
|
||||
if(neutered)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/symptom/proc/Copy()
|
||||
var/datum/symptom/new_symp = new type
|
||||
new_symp.name = name
|
||||
@@ -69,3 +73,9 @@
|
||||
|
||||
/datum/symptom/proc/generate_threshold_desc()
|
||||
return
|
||||
|
||||
/datum/symptom/proc/OnAdd(datum/disease/advance/A) //Overload when a symptom needs to be active before processing, like changing biotypes.
|
||||
return
|
||||
|
||||
/datum/symptom/proc/OnRemove(datum/disease/advance/A) //But dont forget to remove them too.
|
||||
return
|
||||
@@ -45,7 +45,7 @@ Bonus
|
||||
return
|
||||
var/mob/living/carbon/M = A.affected_mob
|
||||
var/obj/item/organ/eyes/eyes = M.getorganslot(ORGAN_SLOT_EYES)
|
||||
if(istype(eyes))
|
||||
if(eyes)
|
||||
switch(A.stage)
|
||||
if(1, 2)
|
||||
if(prob(base_message_chance) && !suppress_warning)
|
||||
@@ -53,20 +53,20 @@ Bonus
|
||||
if(3, 4)
|
||||
to_chat(M, "<span class='warning'><b>Your eyes burn!</b></span>")
|
||||
M.blur_eyes(10)
|
||||
M.adjust_eye_damage(1)
|
||||
eyes.applyOrganDamage(1)
|
||||
else
|
||||
M.blur_eyes(20)
|
||||
M.adjust_eye_damage(5)
|
||||
if(eyes.eye_damage >= 10)
|
||||
eyes.applyOrganDamage(5)
|
||||
if(eyes.damage >= 10)
|
||||
M.become_nearsighted(EYE_DAMAGE)
|
||||
if(prob(eyes.eye_damage - 10 + 1))
|
||||
if(prob(eyes.damage - 10 + 1))
|
||||
if(!remove_eyes)
|
||||
if(!HAS_TRAIT(M, TRAIT_BLIND))
|
||||
to_chat(M, "<span class='userdanger'>You go blind!</span>")
|
||||
M.become_blind(EYE_DAMAGE)
|
||||
eyes.applyOrganDamage(eyes.maxHealth)
|
||||
else
|
||||
M.visible_message("<span class='warning'>[M]'s eyes fall off their sockets!</span>", "<span class='userdanger'>Your eyes fall off their sockets!</span>")
|
||||
eyes.Remove(M)
|
||||
eyes.forceMove(get_turf(M))
|
||||
else
|
||||
to_chat(M, "<span class='userdanger'>Your eyes burn horrifically!</span>")
|
||||
to_chat(M, "<span class='userdanger'>Your eyes burn horrifically!</span>")
|
||||
|
||||
@@ -27,8 +27,10 @@
|
||||
A.update_icon()
|
||||
if(prob(3))
|
||||
to_chat(affected_mob, "<span class='warning'>You feel a stabbing pain in your abdomen!</span>")
|
||||
affected_mob.adjustOrganLoss(ORGAN_SLOT_APPENDIX, 5)
|
||||
affected_mob.Stun(rand(40,60))
|
||||
affected_mob.adjustToxLoss(1)
|
||||
if(3)
|
||||
if(prob(1))
|
||||
affected_mob.vomit(95)
|
||||
affected_mob.adjustOrganLoss(ORGAN_SLOT_APPENDIX, 15)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
if(prob(2))
|
||||
to_chat(affected_mob, "<span class='danger'>You don't feel like yourself.</span>")
|
||||
if(prob(5))
|
||||
affected_mob.adjustBrainLoss(1, 170)
|
||||
affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1, 170)
|
||||
affected_mob.updatehealth()
|
||||
if(3)
|
||||
if(prob(2))
|
||||
@@ -32,7 +32,7 @@
|
||||
if(prob(2))
|
||||
affected_mob.emote("drool")
|
||||
if(prob(10))
|
||||
affected_mob.adjustBrainLoss(2, 170)
|
||||
affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2, 170)
|
||||
affected_mob.updatehealth()
|
||||
if(prob(2))
|
||||
to_chat(affected_mob, "<span class='danger'>Your try to remember something important...but can't.</span>")
|
||||
@@ -43,7 +43,7 @@
|
||||
if(prob(2))
|
||||
affected_mob.emote("drool")
|
||||
if(prob(15))
|
||||
affected_mob.adjustBrainLoss(3, 170)
|
||||
affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 170)
|
||||
affected_mob.updatehealth()
|
||||
if(prob(2))
|
||||
to_chat(affected_mob, "<span class='danger'>Strange buzzing fills your head, removing all thoughts.</span>")
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
if(affected_mob.mind)
|
||||
affected_mob.mind.transfer_to(new_mob)
|
||||
else
|
||||
new_mob.key = affected_mob.key
|
||||
affected_mob.transfer_ckey(new_mob)
|
||||
|
||||
new_mob.name = affected_mob.real_name
|
||||
new_mob.real_name = new_mob.name
|
||||
@@ -82,7 +82,7 @@
|
||||
to_chat(affected_mob, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
|
||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(affected_mob)]) to replace a jobbaned player.")
|
||||
affected_mob.ghostize(0)
|
||||
affected_mob.key = C.key
|
||||
C.transfer_ckey(affected_mob)
|
||||
else
|
||||
to_chat(new_mob, "Your mob has been claimed by death! Appeal your job ban if you want to avoid this in the future!")
|
||||
new_mob.death()
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
"<span class='userdanger'>[A] kicks your head, knocking you out!</span>")
|
||||
playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1)
|
||||
D.SetSleeping(300)
|
||||
D.adjustBrainLoss(15, 150)
|
||||
D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 15, 150)
|
||||
return TRUE
|
||||
|
||||
/datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
D.apply_damage(rand(5,10), BRUTE, BODY_ZONE_HEAD)
|
||||
A.apply_damage(rand(5,10), BRUTE, BODY_ZONE_HEAD)
|
||||
if(!istype(D.head,/obj/item/clothing/head/helmet/) && !istype(D.head,/obj/item/clothing/head/hardhat))
|
||||
D.adjustBrainLoss(5)
|
||||
D.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
|
||||
A.Stun(rand(10,45))
|
||||
D.Knockdown(rand(5,30))//CIT CHANGE - makes stuns from martial arts always use Knockdown instead of Stun for the sake of consistency
|
||||
if(5,6)
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
H.visible_message("<span class='warning'>[user] delivers a heavy hit to [H]'s head, knocking [H.p_them()] out cold!</span>", \
|
||||
"<span class='userdanger'>[user] knocks you unconscious!</span>")
|
||||
H.SetSleeping(600)
|
||||
H.adjustBrainLoss(15, 150)
|
||||
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 15, 150)
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
+5
-3
@@ -19,9 +19,9 @@
|
||||
- IMPORTANT NOTE 2, if you want a player to become a ghost, use mob.ghostize() It does all the hard work for you.
|
||||
|
||||
- When creating a new mob which will be a new IC character (e.g. putting a shade in a construct or randomly selecting
|
||||
a ghost to become a xeno during an event). Simply assign the key or ckey like you've always done.
|
||||
a ghost to become a xeno during an event), use this mob proc.
|
||||
|
||||
new_mob.key = key
|
||||
mob.transfer_ckey(new_mob)
|
||||
|
||||
The Login proc will handle making a new mind for that mobtype (including setting up stuff like mind.name). Simple!
|
||||
However if you want that mind to have any special properties like being a traitor etc you will have to do that
|
||||
@@ -89,6 +89,7 @@
|
||||
return language_holder
|
||||
|
||||
/datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0)
|
||||
var/old_character = current
|
||||
if(current) // remove ourself from our old body's mind variable
|
||||
current.mind = null
|
||||
SStgui.on_transfer(current, new_character)
|
||||
@@ -99,7 +100,7 @@
|
||||
|
||||
if(key)
|
||||
if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours
|
||||
new_character.ghostize(1) //we'll need to ghostize so that key isn't mobless.
|
||||
new_character.ghostize(TRUE, TRUE) //we'll need to ghostize so that key isn't mobless.
|
||||
else
|
||||
key = new_character.key
|
||||
|
||||
@@ -123,6 +124,7 @@
|
||||
transfer_martial_arts(new_character)
|
||||
if(active || force_key_move)
|
||||
new_character.key = key //now transfer the key to link the client to our new body
|
||||
SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character)
|
||||
|
||||
//CIT CHANGE - makes arousal update when transfering bodies
|
||||
if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs.
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
H.update_action_buttons_icon()
|
||||
if(implants)
|
||||
for(var/implant_type in implants)
|
||||
var/obj/item/implant/I = new implant_type(H)
|
||||
var/obj/item/implant/I = new implant_type
|
||||
I.implant(H, null, TRUE)
|
||||
|
||||
H.update_body()
|
||||
|
||||
@@ -103,7 +103,6 @@
|
||||
/obj/structure/cable,
|
||||
/obj/machinery/atmospherics,
|
||||
/obj/item/ammo_casing,
|
||||
/obj/item/implant,
|
||||
/obj/singularity
|
||||
))
|
||||
if(!can_contaminate || blacklisted[thing.type])
|
||||
|
||||
@@ -521,7 +521,7 @@
|
||||
itemUser.adjustToxLoss(-1.5, forced = TRUE) //Because Slime People are people too
|
||||
itemUser.adjustOxyLoss(-1.5)
|
||||
itemUser.adjustStaminaLoss(-1.5)
|
||||
itemUser.adjustBrainLoss(-1.5)
|
||||
itemUser.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1.5)
|
||||
itemUser.adjustCloneLoss(-0.5) //Becasue apparently clone damage is the bastion of all health
|
||||
//Heal all those around you, unbiased
|
||||
for(var/mob/living/L in view(7, owner))
|
||||
@@ -533,7 +533,7 @@
|
||||
L.adjustToxLoss(-3.5, forced = TRUE) //Because Slime People are people too
|
||||
L.adjustOxyLoss(-3.5)
|
||||
L.adjustStaminaLoss(-3.5)
|
||||
L.adjustBrainLoss(-3.5)
|
||||
L.adjustOrganLoss(ORGAN_SLOT_BRAIN, -3.5)
|
||||
L.adjustCloneLoss(-1) //Becasue apparently clone damage is the bastion of all health
|
||||
else if(issilicon(L))
|
||||
L.adjustBruteLoss(-3.5)
|
||||
|
||||
@@ -259,9 +259,9 @@
|
||||
status_type = STATUS_EFFECT_REPLACE
|
||||
alert_type = null
|
||||
var/mutable_appearance/marked_underlay
|
||||
var/obj/item/twohanded/required/kinetic_crusher/hammer_synced
|
||||
var/obj/item/twohanded/kinetic_crusher/hammer_synced
|
||||
|
||||
/datum/status_effect/crusher_mark/on_creation(mob/living/new_owner, obj/item/twohanded/required/kinetic_crusher/new_hammer_synced)
|
||||
/datum/status_effect/crusher_mark/on_creation(mob/living/new_owner, obj/item/twohanded/kinetic_crusher/new_hammer_synced)
|
||||
. = ..()
|
||||
if(.)
|
||||
hammer_synced = new_hammer_synced
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
medical_record_text = "Patient has a tumor in their brain that is slowly driving them to brain death."
|
||||
|
||||
/datum/quirk/brainproblems/on_process()
|
||||
quirk_holder.adjustBrainLoss(0.2)
|
||||
quirk_holder.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2)
|
||||
|
||||
/datum/quirk/nearsighted //t. errorage
|
||||
name = "Nearsighted"
|
||||
@@ -345,16 +345,19 @@
|
||||
gain_text = "<span class='danger'>You find yourself unable to speak!</span>"
|
||||
lose_text = "<span class='notice'>You feel a growing strength in your vocal chords.</span>"
|
||||
medical_record_text = "Functionally mute, patient is unable to use their voice in any capacity."
|
||||
var/datum/brain_trauma/severe/mute/mute
|
||||
|
||||
/datum/quirk/mute/add()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
H.gain_trauma(TRAIT_MUTE, TRAUMA_RESILIENCE_SURGERY)
|
||||
mute = new
|
||||
H.gain_trauma(mute, TRAUMA_RESILIENCE_SURGERY)
|
||||
|
||||
/datum/quirk/mute/on_process()
|
||||
if(quirk_holder.mind && LAZYLEN(quirk_holder.mind.antag_datums))
|
||||
to_chat(quirk_holder, "<span class='boldannounce'>Your antagonistic nature has caused your voice to be heard.</span>")
|
||||
qdel(src)
|
||||
|
||||
|
||||
/datum/quirk/unstable
|
||||
name = "Unstable"
|
||||
desc = "Due to past troubles, you are unable to recover your sanity if you lose it. Be very careful managing your mood!"
|
||||
@@ -363,3 +366,21 @@
|
||||
gain_text = "<span class='danger'>There's a lot on your mind right now.</span>"
|
||||
lose_text = "<span class='notice'>Your mind finally feels calm.</span>"
|
||||
medical_record_text = "Patient's mind is in a vulnerable state, and cannot recover from traumatic events."
|
||||
|
||||
/datum/quirk/blindness
|
||||
name = "Blind"
|
||||
desc = "You are completely blind, nothing can counteract this."
|
||||
value = -4
|
||||
gain_text = "<span class='danger'>You can't see anything.</span>"
|
||||
lose_text = "<span class='notice'>You miraculously gain back your vision.</span>"
|
||||
medical_record_text = "Subject has permanent blindness."
|
||||
|
||||
/datum/quirk/blindness/add()
|
||||
quirk_holder.become_blind(ROUNDSTART_TRAIT)
|
||||
|
||||
/datum/quirk/blindness/on_spawn()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
var/obj/item/clothing/glasses/sunglasses/blindfold/white/glasses = new(get_turf(H))
|
||||
if(!H.equip_to_slot_if_possible(glasses, SLOT_GLASSES, bypass_equip_delay_self = TRUE)) //if you can't put it on the user's eyes, put it in their hands, otherwise put it on their eyes eyes
|
||||
H.put_in_hands(glasses)
|
||||
H.regenerate_icons()
|
||||
|
||||
@@ -235,6 +235,11 @@
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, P, def_zone)
|
||||
. = P.on_hit(src, 0, def_zone)
|
||||
|
||||
//used on altdisarm() for special interactions between the shoved victim (target) and the src, with user being the one shoving the target on it.
|
||||
// IMPORTANT: if you wish to add a new own shove_act() to a certain object, remember to add SHOVABLE_ONTO to its obj_flags bitfied var first.
|
||||
/atom/proc/shove_act(mob/living/target, mob/living/user)
|
||||
return FALSE
|
||||
|
||||
/atom/proc/in_contents_of(container)//can take class or object instance as argument
|
||||
if(ispath(container))
|
||||
if(istype(src.loc, container))
|
||||
|
||||
+18
-1
@@ -18,7 +18,7 @@
|
||||
/datum/atom_hud/data
|
||||
|
||||
/datum/atom_hud/data/human/medical
|
||||
hud_icons = list(STATUS_HUD, HEALTH_HUD, NANITE_HUD)
|
||||
hud_icons = list(STATUS_HUD, HEALTH_HUD, NANITE_HUD, RAD_HUD)
|
||||
|
||||
/datum/atom_hud/data/human/medical/basic
|
||||
|
||||
@@ -162,6 +162,7 @@
|
||||
holder.icon_state = "hud[RoundHealth(src)]"
|
||||
var/icon/I = icon(icon, icon_state, dir)
|
||||
holder.pixel_y = I.Height() - world.icon_size
|
||||
med_hud_set_radstatus()
|
||||
|
||||
//for carbon suit sensors
|
||||
/mob/living/carbon/med_hud_set_health()
|
||||
@@ -211,6 +212,22 @@
|
||||
holder.icon_state = "hudhealthy"
|
||||
|
||||
|
||||
/mob/living/proc/med_hud_set_radstatus()
|
||||
var/image/radholder = hud_list[RAD_HUD]
|
||||
var/icon/I = icon(icon, icon_state, dir)
|
||||
radholder.pixel_y = I.Height() - world.icon_size
|
||||
var/mob/living/M = src
|
||||
var/rads = M.radiation
|
||||
switch(rads)
|
||||
if(-INFINITY to RAD_MOB_SAFE)
|
||||
radholder.icon_state = "hudradsafe"
|
||||
if((RAD_MOB_SAFE+1) to RAD_MOB_MUTATE)
|
||||
radholder.icon_state = "hudraddanger"
|
||||
if((RAD_MOB_MUTATE+1) to RAD_MOB_VOMIT)
|
||||
radholder.icon_state = "hudradlethal"
|
||||
if((RAD_MOB_VOMIT+1) to INFINITY)
|
||||
radholder.icon_state = "hudradnuke"
|
||||
|
||||
/***********************************************
|
||||
Security HUDs! Basic mode shows only the job.
|
||||
************************************************/
|
||||
|
||||
@@ -290,7 +290,6 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
|
||||
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_midround_delay_max + GLOB.dynamic_midround_delay_min)
|
||||
midround_injection_cooldown = round(CLAMP(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_midround_delay_min, GLOB.dynamic_midround_delay_max)) + world.time
|
||||
message_admins("Dynamic Mode initialized with a Threat Level of... [threat_level]!")
|
||||
log_game("DYNAMIC: Dynamic Mode initialized with a Threat Level of... [threat_level]!")
|
||||
return TRUE
|
||||
|
||||
@@ -420,7 +419,6 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
return FALSE
|
||||
starting_rule = pickweight(drafted_rules)
|
||||
|
||||
message_admins("Picking a [istype(starting_rule, /datum/dynamic_ruleset/roundstart/delayed/) ? " delayed " : ""] ruleset [starting_rule.name]")
|
||||
log_game("DYNAMIC: Picking a [istype(starting_rule, /datum/dynamic_ruleset/roundstart/delayed/) ? " delayed " : ""] ruleset [starting_rule.name]")
|
||||
|
||||
roundstart_rules -= starting_rule
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
ruletype = "Midround"
|
||||
/// If the ruleset should be restricted from ghost roles.
|
||||
var/restrict_ghost_roles = TRUE
|
||||
/// What type the ruleset is restricted to.
|
||||
/// What type the ruleset is restricted to.
|
||||
var/required_type = /mob/living/carbon/human
|
||||
var/list/living_players = list()
|
||||
var/list/living_antags = list()
|
||||
@@ -101,7 +101,7 @@
|
||||
log_game("DYNAMIC: Polling [possible_volunteers.len] players to apply for the [name] ruleset.")
|
||||
|
||||
candidates = pollGhostCandidates("The mode is looking for volunteers to become [antag_flag] for [name]", antag_flag, SSticker.mode, antag_flag, poll_time = 300)
|
||||
|
||||
|
||||
if(!candidates || candidates.len <= 0)
|
||||
message_admins("The ruleset [name] received no applications.")
|
||||
log_game("DYNAMIC: The ruleset [name] received no applications.")
|
||||
@@ -194,7 +194,7 @@
|
||||
..()
|
||||
for(var/mob/living/player in living_players)
|
||||
if(issilicon(player)) // Your assigned role doesn't change when you are turned into a silicon.
|
||||
living_players -= player
|
||||
living_players -= player
|
||||
continue
|
||||
if(is_centcom_level(player.z))
|
||||
living_players -= player // We don't autotator people in CentCom
|
||||
@@ -407,7 +407,7 @@
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/generate_ruleset_body(mob/applicant)
|
||||
var/obj/vent = pick_n_take(vents)
|
||||
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
|
||||
new_xeno.key = applicant.key
|
||||
applicant.transfer_ckey(new_xeno, FALSE)
|
||||
message_admins("[ADMIN_LOOKUPFLW(new_xeno)] has been made into an alien by the midround ruleset.")
|
||||
log_game("DYNAMIC: [key_name(new_xeno)] was spawned as an alien by the midround ruleset.")
|
||||
return new_xeno
|
||||
|
||||
@@ -155,9 +155,9 @@
|
||||
var/obj/item/U = new uplink_type(H, H.key, tc)
|
||||
H.equip_to_slot_or_del(U, SLOT_IN_BACKPACK)
|
||||
|
||||
var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H)
|
||||
var/obj/item/implant/weapons_auth/W = new
|
||||
W.implant(H)
|
||||
var/obj/item/implant/explosive/E = new/obj/item/implant/explosive(H)
|
||||
var/obj/item/implant/explosive/E = new
|
||||
E.implant(H)
|
||||
H.faction |= ROLE_SYNDICATE
|
||||
H.update_icons()
|
||||
|
||||
@@ -88,17 +88,50 @@
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params)
|
||||
if(!state_open && !occupant)
|
||||
if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
|
||||
return
|
||||
/obj/machinery/sleeper/screwdriver_act(mob/living/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(..())
|
||||
return
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='warning'>[src] is currently occupied!</span>")
|
||||
return
|
||||
if(state_open)
|
||||
to_chat(user, "<span class='warning'>[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!</span>")
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/sleeper/wrench_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/crowbar_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
return TRUE
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/default_pry_open(obj/item/I) //wew
|
||||
. = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR
|
||||
if(.)
|
||||
I.play_tool_sound(src, 50)
|
||||
visible_message("<span class='notice'>[usr] pries open [src].</span>", "<span class='notice'>You pry open [src].</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/sleeper/AltClick(mob/user)
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
return
|
||||
return ..()
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/sleeper/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Alt-click [src] to [state_open ? "close" : "open"] it.</span>")
|
||||
|
||||
/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
|
||||
@@ -146,7 +179,7 @@
|
||||
data["occupant"]["toxLoss"] = mob_occupant.getToxLoss()
|
||||
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
|
||||
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
|
||||
data["occupant"]["brainLoss"] = mob_occupant.getBrainLoss()
|
||||
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
data["occupant"]["reagents"] = list()
|
||||
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
|
||||
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
|
||||
@@ -190,7 +223,7 @@
|
||||
if(inject_chem(chem, usr))
|
||||
. = TRUE
|
||||
if(scrambled_chems && prob(5))
|
||||
to_chat(usr, "<span class='warning'>Chem System Re-route detected, results may not be as expected!</span>")
|
||||
to_chat(usr, "<span class='warning'>Chemical system re-route detected, results may not be as expected!</span>")
|
||||
|
||||
/obj/machinery/sleeper/emag_act(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -186,6 +186,7 @@ Class Procs:
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
L.update_canmove()
|
||||
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/proc/can_be_occupant(atom/movable/am)
|
||||
@@ -498,6 +499,7 @@ Class Procs:
|
||||
/obj/machinery/Exited(atom/movable/AM, atom/newloc)
|
||||
. = ..()
|
||||
if (AM == occupant)
|
||||
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8
|
||||
@@ -566,6 +568,7 @@ Class Procs:
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)) || !is_operational())
|
||||
return
|
||||
if(inserted_modify_id)
|
||||
|
||||
@@ -242,13 +242,14 @@
|
||||
var/obj/item/I = pick_n_take(unattached_flesh)
|
||||
if(isorgan(I))
|
||||
var/obj/item/organ/O = I
|
||||
O.organ_flags &= ~ORGAN_FROZEN
|
||||
O.Insert(mob_occupant)
|
||||
else if(isbodypart(I))
|
||||
var/obj/item/bodypart/BP = I
|
||||
BP.attach_limb(mob_occupant)
|
||||
|
||||
//Premature clones may have brain damage.
|
||||
mob_occupant.adjustBrainLoss(-((speed_coeff / 2) * dmg_mult))
|
||||
mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, -((speed_coeff / 2) * dmg_mult))
|
||||
|
||||
use_power(7500) //This might need tweaking.
|
||||
|
||||
@@ -262,6 +263,7 @@
|
||||
for(var/i in unattached_flesh)
|
||||
if(isorgan(i))
|
||||
var/obj/item/organ/O = i
|
||||
O.organ_flags &= ~ORGAN_FROZEN
|
||||
O.Insert(mob_occupant)
|
||||
else if(isbodypart(i))
|
||||
var/obj/item/bodypart/BP = i
|
||||
@@ -347,6 +349,9 @@
|
||||
if(mess) //Clean that mess and dump those gibs!
|
||||
for(var/obj/fl in unattached_flesh)
|
||||
fl.forceMove(T)
|
||||
if(istype(fl, /obj/item/organ))
|
||||
var/obj/item/organ/O = fl
|
||||
O.organ_flags &= ~ORGAN_FROZEN
|
||||
unattached_flesh.Cut()
|
||||
mess = FALSE
|
||||
new /obj/effect/gibspawner/generic(get_turf(src))
|
||||
@@ -444,7 +449,7 @@
|
||||
unattached_flesh.Cut()
|
||||
|
||||
H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health
|
||||
H.setBrainLoss(CLONE_INITIAL_DAMAGE)
|
||||
//H.setOrganLoss(ORGAN_SLOT_BRAIN, CLONE_INITIAL_DAMAGE)
|
||||
// In addition to being cellularly damaged and having barely any
|
||||
|
||||
// brain function, they also have no limbs or internal organs.
|
||||
@@ -460,8 +465,9 @@
|
||||
|
||||
for(var/o in H.internal_organs)
|
||||
var/obj/item/organ/organ = o
|
||||
if(!istype(organ) || organ.vital)
|
||||
if(!istype(organ) || (organ.organ_flags & ORGAN_VITAL))
|
||||
continue
|
||||
organ.organ_flags |= ORGAN_FROZEN
|
||||
organ.Remove(H, special=TRUE)
|
||||
organ.forceMove(src)
|
||||
unattached_flesh += organ
|
||||
|
||||
@@ -374,7 +374,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
else
|
||||
if((ACCESS_HOP in scan.access) && ((target_dept==1) || !target_dept))
|
||||
region_access |= 1
|
||||
region_access |= 6
|
||||
get_subordinates("Head of Personnel")
|
||||
if((ACCESS_HOS in scan.access) && ((target_dept==2) || !target_dept))
|
||||
region_access |= 2
|
||||
@@ -388,6 +387,9 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
if((ACCESS_CE in scan.access) && ((target_dept==5) || !target_dept))
|
||||
region_access |= 5
|
||||
get_subordinates("Chief Engineer")
|
||||
if((ACCESS_QM in scan.access) && ((target_dept==6) || !target_dept))
|
||||
region_access |= 6
|
||||
get_subordinates("Quartermaster")
|
||||
if(region_access)
|
||||
authenticated = 1
|
||||
else if ((!( authenticated ) && issilicon(usr)) && (!modify))
|
||||
@@ -607,7 +609,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
typed_circuit.target_dept = target_dept
|
||||
else
|
||||
target_dept = typed_circuit.target_dept
|
||||
var/list/dept_list = list("general","security","medical","science","engineering")
|
||||
var/list/dept_list = list("civilian","security","medical","science","engineering","cargo")
|
||||
name = "[dept_list[target_dept]] department console"
|
||||
|
||||
/obj/machinery/computer/card/minor/hos
|
||||
@@ -631,3 +633,9 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
icon_screen = "idce"
|
||||
|
||||
light_color = LIGHT_COLOR_YELLOW
|
||||
|
||||
/obj/machinery/computer/card/minor/qm
|
||||
target_dept = 6
|
||||
icon_screen = "idqm"
|
||||
|
||||
light_color = LIGHT_COLOR_ORANGE
|
||||
@@ -159,11 +159,11 @@
|
||||
|
||||
if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL)
|
||||
if(!autoprocess)
|
||||
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoprocess</a>"
|
||||
dat += "<a href='byond://?src=[REF(src)];task=autoprocess'>Autoclone</a>"
|
||||
else
|
||||
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoprocess</a>"
|
||||
dat += "<a href='byond://?src=[REF(src)];task=stopautoprocess'>Stop autoclone</a>"
|
||||
else
|
||||
dat += "<span class='linkOff'>Autoprocess</span>"
|
||||
dat += "<span class='linkOff'>Autoclone</span>"
|
||||
dat += "<h3>Cloning Pod Status</h3>"
|
||||
dat += "<div class='statusDisplay'>[temp] </div>"
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
dat += "<h4>[src.active_record.fields["name"]]</h4>"
|
||||
dat += "Scan ID [src.active_record.fields["id"]] <a href='byond://?src=[REF(src)];clone=[active_record.fields["id"]]'>Clone</a><br>"
|
||||
|
||||
var/obj/item/implant/health/H = locate(src.active_record.fields["imp"])
|
||||
var/obj/item/implant/health/H = locate(active_record.fields["imp"])
|
||||
|
||||
if ((H) && (istype(H)))
|
||||
dat += "<b>Health Implant Data:</b><br />[H.sensehealth()]<br><br />"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/obj/machinery/computer/prisoner
|
||||
@@ -35,11 +35,11 @@
|
||||
dat += "<HR>Chemical Implants<BR>"
|
||||
var/turf/Tr = null
|
||||
for(var/obj/item/implant/chem/C in GLOB.tracked_chem_implants)
|
||||
Tr = get_turf(C)
|
||||
if((Tr) && (Tr.z != src.z))
|
||||
continue//Out of range
|
||||
if(!C.imp_in)
|
||||
continue
|
||||
Tr = get_turf(C.imp_in)
|
||||
if((Tr) && (Tr.z != src.z))
|
||||
continue//Out of range
|
||||
dat += "ID: [C.imp_in.name] | Remaining Units: [C.reagents.total_volume] <BR>"
|
||||
dat += "| Inject: "
|
||||
dat += "<A href='?src=[REF(src)];inject1=[REF(C)]'>(<font class='bad'>(1)</font>)</A>"
|
||||
@@ -48,9 +48,9 @@
|
||||
dat += "********************************<BR>"
|
||||
dat += "<HR>Tracking Implants<BR>"
|
||||
for(var/obj/item/implant/tracking/T in GLOB.tracked_implants)
|
||||
if(!isliving(T.imp_in))
|
||||
if(!T.imp_in || !isliving(T.imp_in))
|
||||
continue
|
||||
Tr = get_turf(T)
|
||||
Tr = get_turf(T.imp_in)
|
||||
if((Tr) && (Tr.z != src.z))
|
||||
continue//Out of range
|
||||
|
||||
|
||||
@@ -124,14 +124,14 @@
|
||||
L[avoid_assoc_duplicate_keys(A.name, areaindex)] = R
|
||||
|
||||
for(var/obj/item/implant/tracking/I in GLOB.tracked_implants)
|
||||
if(!I.imp_in || !isliving(I.loc))
|
||||
if(!I.imp_in || !isliving(I.imp_in))
|
||||
continue
|
||||
else
|
||||
var/mob/living/M = I.loc
|
||||
var/mob/living/M = I.imp_in
|
||||
if(M.stat == DEAD)
|
||||
if(M.timeofdeath + 6000 < world.time)
|
||||
continue
|
||||
if(is_eligible(I))
|
||||
if(is_eligible(M))
|
||||
L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = I
|
||||
|
||||
var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in L
|
||||
|
||||
@@ -0,0 +1,497 @@
|
||||
/*
|
||||
* Cryogenic refrigeration unit. Basically a despawner.
|
||||
* Stealing a lot of concepts/code from sleepers due to massive laziness.
|
||||
* The despawn tick will only fire if it's been more than time_till_despawned ticks
|
||||
* since time_entered, which is world.time when the occupant moves in.
|
||||
* ~ Zuhayr
|
||||
*/
|
||||
|
||||
|
||||
//Main cryopod console.
|
||||
|
||||
/obj/machinery/computer/cryopod
|
||||
name = "cryogenic oversight console"
|
||||
desc = "An interface between crew and the cryogenic storage oversight systems."
|
||||
icon = 'icons/obj/Cryogenic2.dmi'
|
||||
icon_state = "cellconsole_1"
|
||||
circuit = /obj/item/circuitboard/cryopodcontrol
|
||||
density = FALSE
|
||||
interaction_flags_machine = INTERACT_MACHINE_OFFLINE
|
||||
req_one_access = list(ACCESS_HEADS, ACCESS_ARMORY) //Heads of staff or the warden can go here to claim recover items from their department that people went were cryodormed with.
|
||||
var/mode = null
|
||||
|
||||
var/menu = 1 //Which menu screen to display
|
||||
|
||||
//Used for logging people entering cryosleep and important items they are carrying.
|
||||
var/list/frozen_crew = list()
|
||||
var/list/frozen_items = list()
|
||||
|
||||
// Used for containing rare items traitors need to steal, so it's not
|
||||
// game-over if they get iced
|
||||
var/list/objective_items = list()
|
||||
// A cache of theft datums so you don't have to re-create them for
|
||||
// each item check
|
||||
var/list/theft_cache = list()
|
||||
|
||||
var/allow_items = TRUE
|
||||
|
||||
/obj/machinery/computer/cryopod/attack_ai()
|
||||
attack_hand()
|
||||
|
||||
/obj/machinery/computer/cryopod/ui_interact(mob/user = usr)
|
||||
if(!is_operational())
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
add_fingerprint(user)
|
||||
|
||||
var/dat = ""
|
||||
|
||||
dat += "<h2>Welcome, [user.real_name].</h2><hr/>"
|
||||
dat += "<br><br>"
|
||||
|
||||
switch(src.menu)
|
||||
if(1)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=2'>View crew storage log</a><br><br>"
|
||||
if(allow_items)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=3'>View objects storage log</a><br><br>"
|
||||
dat += "<a href='byond://?src=[REF(src)];item=1'>Recover object</a><br><br>"
|
||||
dat += "<a href='byond://?src=[REF(src)];allitems=1'>Recover all objects</a><br>"
|
||||
if(2)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=1'><< Back</a><br><br>"
|
||||
dat += "<h3>Recently stored Crew</h3><br/><hr/><br/>"
|
||||
if(!frozen_crew.len)
|
||||
dat += "There has been no storage usage at this terminal.<br/>"
|
||||
else
|
||||
for(var/person in frozen_crew)
|
||||
dat += "[person]<br/>"
|
||||
dat += "<hr/>"
|
||||
if(3)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=1'><< Back</a><br><br>"
|
||||
dat += "<h3>Recently stored objects</h3><br/><hr/><br/>"
|
||||
if(!frozen_items.len)
|
||||
dat += "There has been no storage usage at this terminal.<br/>"
|
||||
else
|
||||
for(var/obj/item/I in frozen_items)
|
||||
dat += "[I.name]<br/>"
|
||||
dat += "<hr/>"
|
||||
|
||||
var/datum/browser/popup = new(user, "cryopod_console", "Cryogenic System Control")
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/cryopod/Topic(href, href_list)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
var/mob/user = usr
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
if(href_list["item"])
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(!allow_items) return
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
var/obj/item/I = input(user, "Please choose which object to retrieve.","Object recovery",null) as null|anything in frozen_items
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
if(!I)
|
||||
return
|
||||
|
||||
if(!(I in frozen_items))
|
||||
to_chat(user, "<span class='notice'>\The [I] is no longer in storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>The console beeps happily as it disgorges \the [I].</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
I.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && !issiliconoradminghost(user))
|
||||
user.put_in_hands(I)
|
||||
frozen_items -= I
|
||||
updateUsrDialog()
|
||||
|
||||
else if(href_list["allitems"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(!allow_items) return
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>The console beeps happily as it disgorges the desired objects.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
for(var/obj/item/I in frozen_items)
|
||||
I.forceMove(drop_location())
|
||||
frozen_items -= I
|
||||
updateUsrDialog()
|
||||
|
||||
else if (href_list["menu"])
|
||||
src.menu = text2num(href_list["menu"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
updateUsrDialog()
|
||||
|
||||
ui_interact(usr)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/item/circuitboard/cryopodcontrol
|
||||
name = "Circuit board (Cryogenic Oversight Console)"
|
||||
build_path = "/obj/machinery/computer/cryopod"
|
||||
|
||||
/obj/machinery/computer/cryopod/contents_explosion()
|
||||
return
|
||||
|
||||
//Cryopods themselves.
|
||||
/obj/machinery/cryopod
|
||||
name = "cryogenic freezer"
|
||||
desc = "Suited for Cyborgs and Humanoids, the pod is a safe place for personnel affected by the Space Sleep Disorder to get some rest."
|
||||
icon = 'icons/obj/cryogenic2.dmi'
|
||||
icon_state = "cryopod-open"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
state_open = TRUE
|
||||
|
||||
var/on_store_message = "has entered long-term storage."
|
||||
var/on_store_name = "Cryogenic Oversight"
|
||||
|
||||
// 15 minutes-ish safe period before being despawned.
|
||||
var/time_till_despawn = 15 * 600 // This is reduced by 90% if a player manually enters cryo
|
||||
var/despawn_world_time = null // Used to keep track of the safe period.
|
||||
|
||||
var/obj/machinery/computer/cryopod/control_computer
|
||||
var/last_no_computer_message = 0
|
||||
|
||||
// These items are preserved when the process() despawn proc occurs.
|
||||
var/list/preserve_items = list(
|
||||
/obj/item/hand_tele,
|
||||
/obj/item/card/id/captains_spare,
|
||||
/obj/item/aicard,
|
||||
/obj/item/mmi,
|
||||
/obj/item/paicard,
|
||||
/obj/item/gun,
|
||||
/obj/item/pinpointer,
|
||||
/obj/item/clothing/shoes/magboots,
|
||||
/obj/item/areaeditor/blueprints,
|
||||
/obj/item/clothing/head/helmet/space,
|
||||
/obj/item/clothing/suit/space,
|
||||
/obj/item/clothing/suit/armor,
|
||||
/obj/item/defibrillator/compact,
|
||||
/obj/item/reagent_containers/hypospray/CMO,
|
||||
/obj/item/clothing/accessory/medal/gold/captain,
|
||||
/obj/item/clothing/gloves/krav_maga,
|
||||
/obj/item/nullrod,
|
||||
/obj/item/tank/jetpack,
|
||||
/obj/item/documents,
|
||||
/obj/item/nuke_core_container
|
||||
)
|
||||
// These items will NOT be preserved
|
||||
var/list/do_not_preserve_items = list (
|
||||
/obj/item/mmi/posibrain,
|
||||
/obj/item/gun/energy/laser/mounted,
|
||||
/obj/item/gun/energy/e_gun/advtaser/mounted,
|
||||
/obj/item/gun/ballistic/revolver/grenadelauncher/cyborg,
|
||||
/obj/item/gun/energy/disabler/cyborg,
|
||||
/obj/item/gun/energy/e_gun/advtaser/cyborg,
|
||||
/obj/item/gun/energy/printer,
|
||||
/obj/item/gun/energy/kinetic_accelerator/cyborg,
|
||||
/obj/item/gun/energy/laser/cyborg
|
||||
)
|
||||
|
||||
/obj/machinery/cryopod/Initialize(mapload)
|
||||
. = ..()
|
||||
update_icon()
|
||||
find_control_computer(mapload)
|
||||
|
||||
/obj/machinery/cryopod/proc/find_control_computer(urgent = FALSE)
|
||||
for(var/obj/machinery/computer/cryopod/C in get_area(src))
|
||||
control_computer = C
|
||||
if(C)
|
||||
return C
|
||||
break
|
||||
|
||||
// Don't send messages unless we *need* the computer, and less than five minutes have passed since last time we messaged
|
||||
if(!control_computer && urgent && last_no_computer_message + 5*60*10 < world.time)
|
||||
log_admin("Cryopod in [get_area(src)] could not find control computer!")
|
||||
message_admins("Cryopod in [get_area(src)] could not find control computer!")
|
||||
last_no_computer_message = world.time
|
||||
|
||||
return control_computer != null
|
||||
|
||||
/obj/machinery/cryopod/close_machine(mob/user)
|
||||
if(!control_computer)
|
||||
find_control_computer(TRUE)
|
||||
if((isnull(user) || istype(user)) && state_open && !panel_open)
|
||||
..(user)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant && mob_occupant.stat != DEAD)
|
||||
to_chat(occupant, "<span class='boldnotice'>You feel cool air surround you. You go numb as your senses turn inward.</span>")
|
||||
if(mob_occupant.client)//if they're logged in
|
||||
despawn_world_time = world.time + (time_till_despawn * 0.1)
|
||||
else
|
||||
despawn_world_time = world.time + time_till_despawn
|
||||
icon_state = "cryopod"
|
||||
|
||||
/obj/machinery/cryopod/open_machine()
|
||||
..()
|
||||
icon_state = "cryopod-open"
|
||||
density = TRUE
|
||||
name = initial(name)
|
||||
|
||||
/obj/machinery/cryopod/container_resist(mob/living/user)
|
||||
visible_message("<span class='notice'>[occupant] emerges from [src]!</span>",
|
||||
"<span class='notice'>You climb out of [src]!</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/cryopod/relaymove(mob/user)
|
||||
container_resist(user)
|
||||
|
||||
/obj/machinery/cryopod/process()
|
||||
if(!occupant)
|
||||
return
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(mob_occupant)
|
||||
// Eject dead people
|
||||
if(mob_occupant.stat == DEAD)
|
||||
open_machine()
|
||||
|
||||
if(!(world.time > despawn_world_time + 100))//+ 10 seconds
|
||||
return
|
||||
|
||||
if(!mob_occupant.client && mob_occupant.stat < 2) //Occupant is living and has no client.
|
||||
if(!control_computer)
|
||||
find_control_computer(urgent = TRUE)//better hope you found it this time
|
||||
|
||||
despawn_occupant()
|
||||
|
||||
#define CRYO_DESTROY 0
|
||||
#define CRYO_PRESERVE 1
|
||||
#define CRYO_OBJECTIVE 2
|
||||
|
||||
/obj/machinery/cryopod/proc/should_preserve_item(obj/item/I)
|
||||
for(var/datum/objective_item/steal/T in control_computer.theft_cache)
|
||||
if(istype(I, T.targetitem) && T.check_special_completion(I))
|
||||
return CRYO_OBJECTIVE
|
||||
for(var/T in preserve_items)
|
||||
if(istype(I, T) && !(I.type in do_not_preserve_items))
|
||||
return CRYO_PRESERVE
|
||||
return CRYO_DESTROY
|
||||
|
||||
// This function can not be undone; do not call this unless you are sure
|
||||
/obj/machinery/cryopod/proc/despawn_occupant()
|
||||
if(!control_computer)
|
||||
find_control_computer()
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
|
||||
//Handle Borg stuff first
|
||||
if(iscyborg(mob_occupant))
|
||||
var/mob/living/silicon/robot/R = mob_occupant
|
||||
if(!istype(R)) return ..()
|
||||
|
||||
R.contents -= R.mmi
|
||||
qdel(R.mmi)
|
||||
for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc
|
||||
for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags
|
||||
if(should_preserve_item(O) != CRYO_DESTROY) // Preserve important things inside the item
|
||||
continue
|
||||
O.forceMove(src)
|
||||
R.module.remove_module(I, TRUE) //delete the module itself so it doesn't transfer over.
|
||||
|
||||
//Drop all items into the pod.
|
||||
for(var/obj/item/I in mob_occupant)
|
||||
mob_occupant.doUnEquip(I)
|
||||
I.forceMove(src)
|
||||
|
||||
if(I.contents.len) //Make sure we catch anything not handled by qdel() on the items.
|
||||
if(should_preserve_item(I) != CRYO_DESTROY) // Don't remove the contents of things that need preservation
|
||||
continue
|
||||
for(var/obj/item/O in I.contents)
|
||||
if(istype(O, /obj/item/tank)) //Stop eating pockets, you fuck!
|
||||
continue
|
||||
O.forceMove(src)
|
||||
|
||||
//Delete all items not on the preservation list.
|
||||
var/list/items = contents
|
||||
items -= mob_occupant // Don't delete the occupant
|
||||
|
||||
for(var/obj/item/I in items)
|
||||
if(istype(I, /obj/item/pda))
|
||||
var/obj/item/pda/P = I
|
||||
QDEL_NULL(P.id)
|
||||
qdel(P)
|
||||
continue
|
||||
|
||||
var/preserve = should_preserve_item(I)
|
||||
if(preserve == CRYO_DESTROY)
|
||||
qdel(I)
|
||||
else if(control_computer && control_computer.allow_items)
|
||||
control_computer.frozen_items += I
|
||||
if(preserve == CRYO_OBJECTIVE)
|
||||
control_computer.objective_items += I
|
||||
I.loc = null
|
||||
else
|
||||
I.forceMove(loc)
|
||||
|
||||
//Update any existing objectives involving this mob.
|
||||
for(var/datum/objective/O in GLOB.objectives)
|
||||
// We don't want revs to get objectives that aren't for heads of staff. Letting
|
||||
// them win or lose based on cryo is silly so we remove the objective.
|
||||
if(istype(O,/datum/objective/mutiny) && O.target == mob_occupant.mind)
|
||||
qdel(O)
|
||||
else if(O.target && istype(O.target, /datum/mind))
|
||||
if(O.target == mob_occupant.mind)
|
||||
if(O.owner && O.owner.current)
|
||||
to_chat(O.owner.current, "<BR><span class='userdanger'>You get the feeling your target is no longer within reach. Time for Plan [pick("A","B","C","D","X","Y","Z")]. Objectives updated!</span>")
|
||||
O.target = null
|
||||
spawn(10) //This should ideally fire after the occupant is deleted.
|
||||
if(!O)
|
||||
return
|
||||
O.find_target()
|
||||
O.update_explanation_text()
|
||||
if(!(O.target))
|
||||
O.owner.objectives -= O
|
||||
qdel(O)
|
||||
|
||||
if(mob_occupant.mind && mob_occupant.mind.assigned_role)
|
||||
//Handle job slot/tater cleanup.
|
||||
var/job = mob_occupant.mind.assigned_role
|
||||
SSjob.FreeRole(job)
|
||||
if(mob_occupant.mind.objectives.len)
|
||||
mob_occupant.mind.objectives.Cut()
|
||||
mob_occupant.mind.special_role = null
|
||||
|
||||
// Delete them from datacore.
|
||||
|
||||
var/announce_rank = null
|
||||
for(var/datum/data/record/R in GLOB.data_core.medical)
|
||||
if((R.fields["name"] == mob_occupant.real_name))
|
||||
qdel(R)
|
||||
for(var/datum/data/record/T in GLOB.data_core.security)
|
||||
if((T.fields["name"] == mob_occupant.real_name))
|
||||
qdel(T)
|
||||
for(var/datum/data/record/G in GLOB.data_core.general)
|
||||
if((G.fields["name"] == mob_occupant.real_name))
|
||||
announce_rank = G.fields["rank"]
|
||||
qdel(G)
|
||||
|
||||
for(var/obj/machinery/computer/cloning/cloner in world)
|
||||
for(var/datum/data/record/R in cloner.records)
|
||||
if(R.fields["name"] == mob_occupant.real_name)
|
||||
cloner.records.Remove(R)
|
||||
|
||||
//Make an announcement and log the person entering storage.
|
||||
if(control_computer)
|
||||
control_computer.frozen_crew += "[mob_occupant.real_name]"
|
||||
|
||||
if(GLOB.announcement_systems.len)
|
||||
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
|
||||
announcer.announce("CRYOSTORAGE", mob_occupant.real_name, announce_rank, list())
|
||||
visible_message("<span class='notice'>\The [src] hums and hisses as it moves [mob_occupant.real_name] into storage.</span>")
|
||||
|
||||
// Ghost and delete the mob.
|
||||
if(!mob_occupant.get_ghost(1))
|
||||
mob_occupant.ghostize(0) // Players who cryo out may not re-enter the round
|
||||
|
||||
QDEL_NULL(occupant)
|
||||
open_machine()
|
||||
name = initial(name)
|
||||
|
||||
#undef CRYO_DESTROY
|
||||
#undef CRYO_PRESERVE
|
||||
#undef CRYO_OBJECTIVE
|
||||
|
||||
/obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user)
|
||||
if(!istype(target) || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || !ismob(target) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
|
||||
return
|
||||
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='boldnotice'>The cryo pod is already occupied!</span>")
|
||||
return
|
||||
|
||||
if(target.stat == DEAD)
|
||||
to_chat(user, "<span class='notice'>Dead people can not be put into cryo.</span>")
|
||||
return
|
||||
|
||||
if(target.client && user != target)
|
||||
if(iscyborg(target))
|
||||
to_chat(user, "<span class='danger'>You can't put [target] into [src]. They're online.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>You can't put [target] into [src]. They're conscious.</span>")
|
||||
return
|
||||
else if(target.client)
|
||||
if(alert(target,"Would you like to enter cryosleep?",,"Yes","No") == "No")
|
||||
return
|
||||
|
||||
var/generic_plsnoleave_message = " Please adminhelp before leaving the round, even if there are no administrators online!"
|
||||
|
||||
if(target == user && world.time - target.client.cryo_warned > 5 MINUTES)//if we haven't warned them in the last 5 minutes
|
||||
var/caught = FALSE
|
||||
if(target.mind.assigned_role in GLOB.command_positions)
|
||||
alert("<span class='userdanger'>You're a Head of Staff![generic_plsnoleave_message] Be sure to put your locker items back into your locker!</span>")
|
||||
caught = TRUE
|
||||
if(iscultist(target) || is_servant_of_ratvar(target))
|
||||
to_chat(target, "<span class='userdanger'>You're a Cultist![generic_plsnoleave_message]</span>")
|
||||
caught = TRUE
|
||||
if(is_devil(target))
|
||||
alert("<span class='userdanger'>You're a Devil![generic_plsnoleave_message]</span>")
|
||||
caught = TRUE
|
||||
if(istype(SSticker.mode, /datum/antagonist/gang))
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/gang))
|
||||
alert("<span class='userdanger'>You're a Gangster![generic_plsnoleave_message]</span>")
|
||||
caught = TRUE
|
||||
if(istype(SSticker.mode, /datum/antagonist/rev))
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/rev/head))
|
||||
alert("<span class='userdanger'>You're a Head Revolutionary![generic_plsnoleave_message]</span>")
|
||||
caught = TRUE
|
||||
else if(target.mind.has_antag_datum(/datum/antagonist/rev))
|
||||
alert("<span class='userdanger'>You're a Revolutionary![generic_plsnoleave_message]</span>")
|
||||
caught = TRUE
|
||||
|
||||
if(caught)
|
||||
target.client.cryo_warned = world.time
|
||||
return
|
||||
|
||||
if(!target || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
|
||||
return
|
||||
//rerun the checks in case of shenanigans
|
||||
|
||||
if(target == user)
|
||||
visible_message("[user] starts climbing into the cryo pod.")
|
||||
else
|
||||
visible_message("[user] starts putting [target] into the cryo pod.")
|
||||
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='boldnotice'>\The [src] is in use.</span>")
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
to_chat(target, "<span class='boldnotice'>If you ghost, log out or close your client now, your character will shortly be permanently removed from the round.</span>")
|
||||
name = "[name] ([occupant.name])"
|
||||
log_admin("<span class='notice'>[key_name(target)] entered a stasis pod.</span>")
|
||||
message_admins("[key_name_admin(target)] entered a stasis pod. (<A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
|
||||
add_fingerprint(target)
|
||||
|
||||
//Attacks/effects.
|
||||
/obj/machinery/cryopod/blob_act()
|
||||
return //Sorta gamey, but we don't really want these to be destroyed.
|
||||
@@ -89,11 +89,11 @@
|
||||
return C
|
||||
return null
|
||||
|
||||
/obj/machinery/dna_scannernew/close_machine(mob/living/carbon/user)
|
||||
/obj/machinery/dna_scannernew/close_machine(atom/movable/target)
|
||||
if(!state_open)
|
||||
return FALSE
|
||||
|
||||
..(user)
|
||||
..(target)
|
||||
|
||||
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
|
||||
var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
|
||||
@@ -111,7 +111,7 @@
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/dna_scannernew/open_machine()
|
||||
if(state_open)
|
||||
if(state_open || panel_open)
|
||||
return FALSE
|
||||
|
||||
..()
|
||||
@@ -126,23 +126,48 @@
|
||||
return
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params)
|
||||
|
||||
if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))//sent icon_state is irrelevant...
|
||||
update_icon()//..since we're updating the icon here, since the scanner can be unpowered when opened/closed
|
||||
/obj/machinery/dna_scannernew/screwdriver_act(mob/living/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(..())
|
||||
return
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='warning'>[src] is currently occupied!</span>")
|
||||
return
|
||||
if(state_open)
|
||||
to_chat(user, "<span class='warning'>[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!</span>")
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, icon_state, icon_state, I)) //sent icon_state is irrelevant...
|
||||
update_icon() //..since we're updating the icon here, since the scanner can be unpowered when opened/closed
|
||||
return
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/dna_scannernew/wrench_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/dna_scannernew/crowbar_act(mob/living/user, obj/item/I)
|
||||
. = ..()
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
|
||||
return TRUE
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
/obj/machinery/dna_scannernew/default_pry_open(obj/item/I) //wew
|
||||
. = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR
|
||||
if(.)
|
||||
I.play_tool_sound(src, 50)
|
||||
visible_message("<span class='notice'>[usr] pries open [src].</span>", "<span class='notice'>You pry open [src].</span>")
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/dna_scannernew/interact(mob/user)
|
||||
toggle_open(user)
|
||||
|
||||
/obj/machinery/dna_scannernew/AltClick(mob/user)
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/dna_scannernew/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
|
||||
return
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
H.key = C.key
|
||||
C.transfer_ckey(H)
|
||||
|
||||
if(grab_ghost_when == CLONER_FRESH_CLONE)
|
||||
H.grab_ghost()
|
||||
|
||||
@@ -136,16 +136,17 @@ The console is located at computer/gulag_teleporter.dm
|
||||
linked_reclaimer.stored_items[occupant] = list()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
for(var/obj/item/W in mob_occupant)
|
||||
if(!is_type_in_typecache(W, telegulag_required_items) && mob_occupant.temporarilyRemoveItemFromInventory(W))
|
||||
if(istype(W, /obj/item/restraints/handcuffs))
|
||||
W.forceMove(get_turf(src))
|
||||
continue
|
||||
if(linked_reclaimer)
|
||||
linked_reclaimer.stored_items[mob_occupant] += W
|
||||
linked_reclaimer.contents += W
|
||||
W.forceMove(linked_reclaimer)
|
||||
else
|
||||
W.forceMove(src)
|
||||
if(!is_type_in_typecache(W, telegulag_required_items))
|
||||
if(mob_occupant.temporarilyRemoveItemFromInventory(W))
|
||||
if(istype(W, /obj/item/restraints/handcuffs))
|
||||
W.forceMove(get_turf(src))
|
||||
continue
|
||||
if(linked_reclaimer)
|
||||
linked_reclaimer.stored_items[mob_occupant] += W
|
||||
linked_reclaimer.contents += W
|
||||
W.forceMove(linked_reclaimer)
|
||||
else
|
||||
W.forceMove(src)
|
||||
|
||||
/obj/machinery/gulag_teleporter/proc/handle_prisoner(obj/item/id, datum/data/record/R)
|
||||
if(!ishuman(occupant))
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
to_chat(user, "<span class='warning'>[src] is currently occupied!</span>")
|
||||
return
|
||||
if(state_open)
|
||||
to_chat(user, "<span class='warning'>[src] must be closed to [panel_open ? "close" : "open"] it's maintenance hatch!</span>")
|
||||
to_chat(user, "<span class='warning'>[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!</span>")
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
|
||||
return
|
||||
|
||||
@@ -210,13 +210,13 @@
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/machinery/suit_storage_unit/proc/cook()
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(uv_cycles)
|
||||
uv_cycles--
|
||||
uv = TRUE
|
||||
locked = TRUE
|
||||
update_icon()
|
||||
if(occupant)
|
||||
var/mob/living/mob_occupant = occupant
|
||||
if(uv_super)
|
||||
mob_occupant.adjustFireLoss(rand(20, 36))
|
||||
else
|
||||
@@ -245,10 +245,27 @@
|
||||
visible_message("<span class='notice'>[src]'s door slides open. The glowing yellow lights dim to a gentle green.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>[src]'s door slides open, barraging you with the nauseating smell of charred flesh.</span>")
|
||||
mob_occupant.radiation = 0
|
||||
playsound(src, 'sound/machines/airlockclose.ogg', 25, 1)
|
||||
for(var/obj/item/I in src) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
|
||||
SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
|
||||
var/datum/component/radioactive/contamination = I.GetComponent(/datum/component/radioactive)
|
||||
var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such.
|
||||
if(suit)
|
||||
things_to_clear += suit
|
||||
things_to_clear += suit.GetAllContents()
|
||||
if(helmet)
|
||||
things_to_clear += helmet
|
||||
things_to_clear += helmet.GetAllContents()
|
||||
if(mask)
|
||||
things_to_clear += mask
|
||||
things_to_clear += mask.GetAllContents()
|
||||
if(storage)
|
||||
things_to_clear += storage
|
||||
things_to_clear += storage.GetAllContents()
|
||||
if(occupant)
|
||||
things_to_clear += occupant
|
||||
things_to_clear += occupant.GetAllContents()
|
||||
for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
|
||||
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
|
||||
var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive)
|
||||
if(contamination)
|
||||
qdel(contamination)
|
||||
open_machine(FALSE)
|
||||
|
||||
@@ -421,6 +421,7 @@
|
||||
"name" = "[customsender]",
|
||||
"job" = "[customjob]",
|
||||
"message" = custommessage,
|
||||
"emoji_message" = emoji_parse(custommessage),
|
||||
"targets" = list("[customrecepient.owner] ([customrecepient.ownjob])")
|
||||
))
|
||||
// this will log the signal and transmit it to the target
|
||||
|
||||
@@ -106,10 +106,11 @@
|
||||
return "Everyone"
|
||||
return data["targets"][1]
|
||||
|
||||
/datum/signal/subspace/pda/proc/format_message()
|
||||
/datum/signal/subspace/pda/proc/format_message(emojify = FALSE)
|
||||
var/message = emojify ? data["emoji_message"] : data["message"]
|
||||
if (logged && data["photo"])
|
||||
return "\"[data["message"]]\" (<a href='byond://?src=[REF(logged)];photo=1'>Photo</a>)"
|
||||
return "\"[data["message"]]\""
|
||||
return "\"[message]\" (<a href='byond://?src=[REF(logged)];photo=1'>Photo</a>)"
|
||||
return "\"[message]\""
|
||||
|
||||
/datum/signal/subspace/pda/broadcast()
|
||||
if (!logged) // Can only go through if a message server logs it
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
<font color="[patient.getToxLoss() < 60 ? "#3d5bc3" : "#c51e1e"]"><b>Toxin Content:</b> [patient.getToxLoss()]%</font><br />
|
||||
<font color="[patient.getFireLoss() < 60 ? "#3d5bc3" : "#c51e1e"]"><b>Burn Severity:</b> [patient.getFireLoss()]%</font><br />
|
||||
<span class='danger'>[patient.getCloneLoss() ? "Subject appears to have cellular damage." : ""]</span><br />
|
||||
<span class='danger'>[patient.getBrainLoss() ? "Significant brain damage detected." : ""]</span><br />
|
||||
<span class='danger'>[patient.getOrganLoss(ORGAN_SLOT_BRAIN) ? "Significant brain damage detected." : ""]</span><br />
|
||||
<span class='danger'>[length(patient.get_traumas()) ? "Brain Traumas detected." : ""]</span><br />
|
||||
"}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
energy_drain = 10
|
||||
force = 15
|
||||
harmful = TRUE
|
||||
tool_behaviour = TOOL_DRILL
|
||||
toolspeed = 0.9
|
||||
var/drill_delay = 7
|
||||
var/drill_level = DRILL_BASIC
|
||||
|
||||
@@ -141,6 +143,7 @@
|
||||
drill_delay = 4
|
||||
drill_level = DRILL_HARDENED
|
||||
force = 15
|
||||
toolspeed = 0.7
|
||||
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/mining_scanner
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
var/dam_force = 20
|
||||
var/obj/mecha/working/ripley/cargo_holder
|
||||
harmful = TRUE
|
||||
tool_behaviour = TOOL_RETRACTOR
|
||||
toolspeed = 0.8
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj)
|
||||
if(..())
|
||||
|
||||
@@ -279,12 +279,12 @@
|
||||
name = "\improper Melon Seed \"Scattershot\""
|
||||
desc = "A weapon for combat exosuits. Shoots a spread of pellets, shaped as seed."
|
||||
icon_state = "mecha_scatter"
|
||||
equip_cooldown = 30
|
||||
equip_cooldown = 20
|
||||
projectile = /obj/item/projectile/bullet/seed
|
||||
projectiles = 4
|
||||
projectile_energy_cost = 55
|
||||
projectiles = 20
|
||||
projectile_energy_cost = 25
|
||||
projectiles_per_shot = 10
|
||||
variance = 20
|
||||
variance = 25
|
||||
harmful = TRUE
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
buckled_mob.clear_alert("buckled")
|
||||
buckled_mobs -= buckled_mob
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force)
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, src, force)
|
||||
|
||||
post_unbuckle_mob(.)
|
||||
|
||||
|
||||
@@ -421,10 +421,10 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
//the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't.
|
||||
//if this is being done by a mob other than M, it will include the mob equipper, who is trying to equip the item to mob M. equipper will be null otherwise.
|
||||
//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen.
|
||||
//Set disable_warning to 1 if you wish it to not give you outputs.
|
||||
//Set disable_warning to TRUE if you wish it to not give you outputs.
|
||||
/obj/item/proc/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
|
||||
if(!M)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
return M.can_equip(src, slot, disable_warning, bypass_equip_delay_self)
|
||||
|
||||
@@ -514,12 +514,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
|
||||
log_combat(user, M, "attacked", "[src.name]", "(INTENT: [uppertext(user.a_intent)])")
|
||||
|
||||
M.adjust_blurriness(3)
|
||||
M.adjust_eye_damage(rand(2,4))
|
||||
var/obj/item/organ/eyes/eyes = M.getorganslot(ORGAN_SLOT_EYES)
|
||||
if (!eyes)
|
||||
return
|
||||
if(eyes.eye_damage >= 10)
|
||||
M.adjust_blurriness(3)
|
||||
eyes.applyOrganDamage(rand(2,4))
|
||||
if(eyes.damage >= 10)
|
||||
M.adjust_blurriness(15)
|
||||
if(M.stat != DEAD)
|
||||
to_chat(M, "<span class='danger'>Your eyes start to bleed profusely!</span>")
|
||||
@@ -533,7 +533,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
M.adjust_blurriness(10)
|
||||
M.Unconscious(20)
|
||||
M.Knockdown(40)
|
||||
if (prob(eyes.eye_damage - 10 + 1))
|
||||
if (prob(eyes.damage - 10 + 1))
|
||||
M.become_blind(EYE_DAMAGE)
|
||||
to_chat(M, "<span class='danger'>You go blind!</span>")
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ RSF
|
||||
to_chat(user, "Fabricating Cookie..")
|
||||
var/obj/item/reagent_containers/food/snacks/cookie/S = new /obj/item/reagent_containers/food/snacks/cookie(T)
|
||||
if(toxin)
|
||||
S.reagents.add_reagent("chloralhydratedelayed", 10)
|
||||
S.reagents.add_reagent("chloralhydrate", 10)
|
||||
if (iscyborg(user))
|
||||
var/mob/living/silicon/robot/R = user
|
||||
R.cell.charge -= 100
|
||||
|
||||
@@ -17,26 +17,27 @@
|
||||
/obj/item/organ/body_egg/Insert(var/mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
ADD_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC)
|
||||
START_PROCESSING(SSobj, src)
|
||||
owner.med_hud_set_status()
|
||||
INVOKE_ASYNC(src, .proc/AddInfectionImages, owner)
|
||||
|
||||
/obj/item/organ/body_egg/Remove(var/mob/living/carbon/M, special = 0)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(owner)
|
||||
REMOVE_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC)
|
||||
owner.med_hud_set_status()
|
||||
INVOKE_ASYNC(src, .proc/RemoveInfectionImages, owner)
|
||||
..()
|
||||
|
||||
/obj/item/organ/body_egg/process()
|
||||
/obj/item/organ/body_egg/on_death()
|
||||
. = ..()
|
||||
if(!owner)
|
||||
return
|
||||
if(!(src in owner.internal_organs))
|
||||
Remove(owner)
|
||||
return
|
||||
egg_process()
|
||||
|
||||
/obj/item/organ/body_egg/on_life()
|
||||
. = ..()
|
||||
egg_process()
|
||||
|
||||
|
||||
/obj/item/organ/body_egg/proc/egg_process()
|
||||
return
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
name = "Department Management Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/card/minor
|
||||
var/target_dept = 1
|
||||
var/list/dept_list = list("General","Security","Medical","Science","Engineering")
|
||||
var/list/dept_list = list("Civilian","Security","Medical","Science","Engineering","Cargo")
|
||||
|
||||
/obj/item/circuitboard/computer/card/minor/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
|
||||
@@ -399,6 +399,7 @@
|
||||
/obj/machinery/smartfridge/food = "food",
|
||||
/obj/machinery/smartfridge/drinks = "drinks",
|
||||
/obj/machinery/smartfridge/extract = "slimes",
|
||||
/obj/machinery/smartfridge/organ = "organs",
|
||||
/obj/machinery/smartfridge/chemistry = "chems",
|
||||
/obj/machinery/smartfridge/chemistry/virology = "viruses",
|
||||
/obj/machinery/smartfridge/disks = "disks")
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#define RANDOM_GRAFFITI "Random Graffiti"
|
||||
#define RANDOM_LETTER "Random Letter"
|
||||
#define RANDOM_PUNCTUATION "Random Punctuation"
|
||||
#define RANDOM_NUMBER "Random Number"
|
||||
#define RANDOM_SYMBOL "Random Symbol"
|
||||
#define RANDOM_DRAWING "Random Drawing"
|
||||
#define RANDOM_ORIENTED "Random Oriented"
|
||||
#define RANDOM_RUNE "Random Rune"
|
||||
#define RANDOM_ANY "Random Anything"
|
||||
@@ -32,16 +35,16 @@
|
||||
var/drawtype
|
||||
var/text_buffer = ""
|
||||
|
||||
var/list/graffiti = list("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa","body","cyka","arrow","star","poseur tag","prolizard","antilizard", "tile") //cit edit
|
||||
var/list/letters = list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z")
|
||||
var/list/numerals = list("0","1","2","3","4","5","6","7","8","9")
|
||||
var/list/oriented = list("arrow","body") // These turn to face the same way as the drawer
|
||||
var/list/runes = list("rune1","rune2","rune3","rune4","rune5","rune6")
|
||||
var/list/randoms = list(RANDOM_ANY, RANDOM_RUNE, RANDOM_ORIENTED,
|
||||
RANDOM_NUMBER, RANDOM_GRAFFITI, RANDOM_LETTER)
|
||||
var/list/graffiti_large_h = list("yiffhell", "secborg", "paint")
|
||||
var/static/list/graffiti = list("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa","body","cyka","star","poseur tag","prolizard","antilizard", "tile")
|
||||
var/static/list/symbols = list("danger","firedanger","electricdanger","biohazard","radiation","safe","evac","space","med","trade","shop","food","peace","like","skull","nay","heart","credit")
|
||||
var/static/list/drawings = list("smallbrush","brush","largebrush","splatter","snake","stickman","carp","ghost","clown","taser","disk","fireaxe","toolbox","corgi","cat","toilet","blueprint","beepsky","scroll","bottle","shotgun")
|
||||
var/static/list/oriented = list("arrow","line","thinline","shortline","body","chevron","footprint","clawprint","pawprint") // These turn to face the same way as the drawer
|
||||
var/static/list/runes = list("rune1","rune2","rune3","rune4","rune5","rune6")
|
||||
var/static/list/randoms = list(RANDOM_ANY, RANDOM_RUNE, RANDOM_ORIENTED,
|
||||
RANDOM_NUMBER, RANDOM_GRAFFITI, RANDOM_LETTER, RANDOM_SYMBOL, RANDOM_PUNCTUATION, RANDOM_DRAWING)
|
||||
var/static/list/graffiti_large_h = list("yiffhell", "secborg", "paint")
|
||||
|
||||
var/list/all_drawables
|
||||
var/static/list/all_drawables = graffiti + symbols + drawings + oriented + runes + graffiti_large_h
|
||||
|
||||
var/paint_mode = PAINT_NORMAL
|
||||
|
||||
@@ -54,8 +57,6 @@
|
||||
var/instant = FALSE
|
||||
var/self_contained = TRUE // If it deletes itself when it is empty
|
||||
|
||||
var/list/validSurfaces = list(/turf/open/floor)
|
||||
|
||||
var/edible = TRUE // That doesn't mean eating it is a good idea
|
||||
|
||||
var/list/reagent_contents = list("nutriment" = 1)
|
||||
@@ -71,6 +72,9 @@
|
||||
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/proc/isValidSurface(surface)
|
||||
return istype(surface, /turf/open/floor)
|
||||
|
||||
/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>")
|
||||
return (BRUTELOSS|OXYLOSS)
|
||||
@@ -81,7 +85,6 @@
|
||||
if(name == "crayon")
|
||||
name = "[item_color] crayon"
|
||||
|
||||
all_drawables = graffiti + letters + numerals + oriented + runes + graffiti_large_h
|
||||
drawtype = pick(all_drawables)
|
||||
|
||||
refill()
|
||||
@@ -153,55 +156,62 @@
|
||||
to_chat(user, "<span class='notice'>The cap on [src] is now [is_capped ? "on" : "off"].</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/item/toy/crayon/ui_data()
|
||||
var/list/data = list()
|
||||
data["drawables"] = list()
|
||||
var/list/D = data["drawables"]
|
||||
/obj/item/toy/crayon/proc/staticDrawables()
|
||||
|
||||
. = list()
|
||||
|
||||
var/list/g_items = list()
|
||||
D += list(list("name" = "Graffiti", "items" = g_items))
|
||||
. += list(list("name" = "Graffiti", "items" = g_items))
|
||||
for(var/g in graffiti)
|
||||
g_items += list(list("item" = g))
|
||||
|
||||
var/list/glh_items = list()
|
||||
D += list(list("name" = "Graffiti Large Horizontal", "items" = glh_items))
|
||||
. += list(list("name" = "Graffiti Large Horizontal", "items" = glh_items))
|
||||
for(var/glh in graffiti_large_h)
|
||||
glh_items += list(list("item" = glh))
|
||||
|
||||
var/list/L_items = list()
|
||||
D += list(list("name" = "Letters", "items" = L_items))
|
||||
for(var/L in letters)
|
||||
L_items += list(list("item" = L))
|
||||
var/list/S_items = list()
|
||||
. += list(list("name" = "Symbols", "items" = S_items))
|
||||
for(var/S in symbols)
|
||||
S_items += list(list("item" = S))
|
||||
|
||||
var/list/N_items = list()
|
||||
D += list(list(name = "Numerals", "items" = N_items))
|
||||
for(var/N in numerals)
|
||||
N_items += list(list("item" = N))
|
||||
var/list/D_items = list()
|
||||
. += list(list("name" = "Drawings", "items" = D_items))
|
||||
for(var/D in drawings)
|
||||
D_items += list(list("item" = D))
|
||||
|
||||
var/list/O_items = list()
|
||||
D += list(list(name = "Oriented", "items" = O_items))
|
||||
. += list(list(name = "Oriented", "items" = O_items))
|
||||
for(var/O in oriented)
|
||||
O_items += list(list("item" = O))
|
||||
|
||||
var/list/R_items = list()
|
||||
D += list(list(name = "Runes", "items" = R_items))
|
||||
. += list(list(name = "Runes", "items" = R_items))
|
||||
for(var/R in runes)
|
||||
R_items += list(list("item" = R))
|
||||
|
||||
var/list/rand_items = list()
|
||||
D += list(list(name = "Random", "items" = rand_items))
|
||||
. += list(list(name = "Random", "items" = rand_items))
|
||||
for(var/i in randoms)
|
||||
rand_items += list(list("item" = i))
|
||||
|
||||
data["selected_stencil"] = drawtype
|
||||
data["text_buffer"] = text_buffer
|
||||
|
||||
data["has_cap"] = has_cap
|
||||
data["is_capped"] = is_capped
|
||||
data["can_change_colour"] = can_change_colour
|
||||
data["current_colour"] = paint_color
|
||||
/obj/item/toy/crayon/ui_data()
|
||||
|
||||
return data
|
||||
var/static/list/crayon_drawables
|
||||
|
||||
if (!crayon_drawables)
|
||||
crayon_drawables = staticDrawables()
|
||||
|
||||
. = list()
|
||||
.["drawables"] = crayon_drawables
|
||||
.["selected_stencil"] = drawtype
|
||||
.["text_buffer"] = text_buffer
|
||||
|
||||
.["has_cap"] = has_cap
|
||||
.["is_capped"] = is_capped
|
||||
.["can_change_colour"] = can_change_colour
|
||||
.["current_colour"] = paint_color
|
||||
|
||||
/obj/item/toy/crayon/ui_act(action, list/params)
|
||||
if(..())
|
||||
@@ -216,6 +226,7 @@
|
||||
if(stencil in all_drawables + randoms)
|
||||
drawtype = stencil
|
||||
. = TRUE
|
||||
text_buffer = ""
|
||||
if(stencil in graffiti_large_h)
|
||||
paint_mode = PAINT_LARGE_HORIZONTAL
|
||||
text_buffer = ""
|
||||
@@ -223,8 +234,13 @@
|
||||
paint_mode = PAINT_NORMAL
|
||||
if("select_colour")
|
||||
if(can_change_colour)
|
||||
paint_color = input(usr,"","Choose Color",paint_color) as color|null
|
||||
. = TRUE
|
||||
var/chosen_colour = input(usr,"","Choose Color",paint_color) as color|null
|
||||
|
||||
if (!isnull(chosen_colour))
|
||||
paint_color = chosen_colour
|
||||
. = TRUE
|
||||
else
|
||||
. = FALSE
|
||||
if("enter_text")
|
||||
var/txt = stripped_input(usr,"Choose what to write.",
|
||||
"Scribbles",default = text_buffer)
|
||||
@@ -235,18 +251,16 @@
|
||||
update_icon()
|
||||
|
||||
/obj/item/toy/crayon/proc/crayon_text_strip(text)
|
||||
var/list/base = string2charlist(lowertext(text))
|
||||
var/list/out = list()
|
||||
for(var/a in base)
|
||||
if(a in (letters|numerals))
|
||||
out += a
|
||||
return jointext(out,"")
|
||||
var/static/regex/crayon_r = new /regex(@"[^\w!?,.=%#&+\/\-]")
|
||||
return replacetext(lowertext(text), crayon_r, "")
|
||||
|
||||
/obj/item/toy/crayon/afterattack(atom/target, mob/user, proximity, params)
|
||||
. = ..()
|
||||
if(!proximity || !check_allowed_items(target))
|
||||
return
|
||||
|
||||
var/static/list/punctuation = list("!","?",".",",","/","+","-","=","%","#","&")
|
||||
|
||||
var/cost = 1
|
||||
if(paint_mode == PAINT_LARGE_HORIZONTAL)
|
||||
cost = 5
|
||||
@@ -264,13 +278,19 @@
|
||||
if(istype(target, /obj/effect/decal/cleanable))
|
||||
target = target.loc
|
||||
|
||||
if(!is_type_in_list(target,validSurfaces))
|
||||
if(!isValidSurface(target))
|
||||
return
|
||||
|
||||
var/drawing = drawtype
|
||||
switch(drawtype)
|
||||
if(RANDOM_LETTER)
|
||||
drawing = pick(letters)
|
||||
drawing = ascii2text(rand(97, 122)) // a-z
|
||||
if(RANDOM_PUNCTUATION)
|
||||
drawing = pick(punctuation)
|
||||
if(RANDOM_SYMBOL)
|
||||
drawing = pick(symbols)
|
||||
if(RANDOM_DRAWING)
|
||||
drawing = pick(drawings)
|
||||
if(RANDOM_GRAFFITI)
|
||||
drawing = pick(graffiti)
|
||||
if(RANDOM_RUNE)
|
||||
@@ -278,17 +298,24 @@
|
||||
if(RANDOM_ORIENTED)
|
||||
drawing = pick(oriented)
|
||||
if(RANDOM_NUMBER)
|
||||
drawing = pick(numerals)
|
||||
drawing = ascii2text(rand(48, 57)) // 0-9
|
||||
if(RANDOM_ANY)
|
||||
drawing = pick(all_drawables)
|
||||
|
||||
var/temp = "rune"
|
||||
if(drawing in letters)
|
||||
var/ascii = (length(drawing) == 1) ? TRUE : FALSE
|
||||
if(ascii && is_alpha(drawing))
|
||||
temp = "letter"
|
||||
else if(drawing in graffiti)
|
||||
temp = "graffiti"
|
||||
else if(drawing in numerals)
|
||||
else if(ascii && is_digit(drawing))
|
||||
temp = "number"
|
||||
else if(drawing in punctuation)
|
||||
temp = "punctuation mark"
|
||||
else if(drawing in symbols)
|
||||
temp = "symbol"
|
||||
else if(drawing in drawings)
|
||||
temp = "drawing"
|
||||
else if(drawing in graffiti|oriented)
|
||||
temp = "graffiti"
|
||||
|
||||
// If a gang member is using a gang spraycan, it'll behave differently
|
||||
var/gang_mode = FALSE
|
||||
@@ -338,7 +365,7 @@
|
||||
return
|
||||
|
||||
if(length(text_buffer))
|
||||
drawing = copytext(text_buffer,1,2)
|
||||
drawing = text_buffer[1]
|
||||
|
||||
|
||||
var/list/turf/affected_turfs = list()
|
||||
@@ -362,7 +389,7 @@
|
||||
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))
|
||||
if(isValidSurface(left) && isValidSurface(right))
|
||||
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
|
||||
@@ -377,8 +404,9 @@
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You spray a [temp] on \the [target.name]</span>")
|
||||
|
||||
if(length(text_buffer))
|
||||
if(length(text_buffer) > 1)
|
||||
text_buffer = copytext(text_buffer,2)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
if(post_noise)
|
||||
audible_message("<span class='notice'>You hear spraying.</span>")
|
||||
@@ -516,7 +544,7 @@
|
||||
|
||||
charges = -1
|
||||
|
||||
/obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity)
|
||||
/obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity, params)
|
||||
paint_color = rgb(rand(0,255), rand(0,255), rand(0,255))
|
||||
. = ..()
|
||||
|
||||
@@ -591,12 +619,14 @@
|
||||
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)
|
||||
|
||||
pre_noise = TRUE
|
||||
post_noise = FALSE
|
||||
|
||||
/obj/item/toy/crayon/spraycan/isValidSurface(surface)
|
||||
return (istype(surface, /turf/open/floor) || istype(surface, /turf/closed/wall))
|
||||
|
||||
/obj/item/toy/crayon/spraycan/suicide_act(mob/user)
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(is_capped || !actually_paints)
|
||||
@@ -622,8 +652,8 @@
|
||||
|
||||
return (OXYLOSS)
|
||||
|
||||
/obj/item/toy/crayon/spraycan/New()
|
||||
..()
|
||||
/obj/item/toy/crayon/spraycan/Initialize()
|
||||
. = ..()
|
||||
// If default crayon red colour, pick a more fun spraycan colour
|
||||
if(!paint_color)
|
||||
paint_color = pick("#DA0000","#FF9300","#FFF200","#A8E61D","#00B7EF",
|
||||
@@ -640,7 +670,7 @@
|
||||
to_chat(user, "It is empty.")
|
||||
to_chat(user, "<span class='notice'>Alt-click [src] to [ is_capped ? "take the cap off" : "put the cap on"].</span>")
|
||||
|
||||
/obj/item/toy/crayon/spraycan/afterattack(atom/target, mob/user, proximity)
|
||||
/obj/item/toy/crayon/spraycan/afterattack(atom/target, mob/user, proximity, params)
|
||||
if(!proximity)
|
||||
return
|
||||
|
||||
@@ -656,8 +686,7 @@
|
||||
playsound(user.loc, 'sound/effects/spray.ogg', 25, 1, 5)
|
||||
|
||||
var/mob/living/carbon/C = target
|
||||
user.visible_message("<span class='danger'>[user] sprays [src] into the face of [target]!</span>")
|
||||
to_chat(target, "<span class='userdanger'>[user] sprays [src] into your face!</span>")
|
||||
C.visible_message("<span class='danger'>[user] sprays [src] into the face of [C]!</span>", "<span class='userdanger'>[user] sprays [src] into your face!</span>")
|
||||
|
||||
if(C.client)
|
||||
C.blur_eyes(3)
|
||||
@@ -678,13 +707,20 @@
|
||||
|
||||
return
|
||||
|
||||
if(istype(target, /obj/structure/window))
|
||||
if(isobj(target))
|
||||
if(actually_paints)
|
||||
if(color_hex2num(paint_color) < 350 && !istype(target, /obj/structure/window) && !istype(target, /obj/effect/decal/cleanable/crayon)) //Colors too dark are rejected
|
||||
to_chat(usr, "<span class='warning'>A color that dark on an object like this? Surely not...</span>")
|
||||
return FALSE
|
||||
|
||||
target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY)
|
||||
if(color_hex2num(paint_color) < 255)
|
||||
target.set_opacity(255)
|
||||
else
|
||||
target.set_opacity(initial(target.opacity))
|
||||
|
||||
if(istype(target, /obj/structure/window))
|
||||
if(color_hex2num(paint_color) < 255)
|
||||
target.set_opacity(255)
|
||||
else
|
||||
target.set_opacity(initial(target.opacity))
|
||||
|
||||
. = use_charges(user, 2)
|
||||
var/fraction = min(1, . / reagents.maximum_volume)
|
||||
reagents.reaction(target, TOUCH, fraction * volume_multiplier)
|
||||
@@ -692,6 +728,7 @@
|
||||
|
||||
if(pre_noise || post_noise)
|
||||
playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5)
|
||||
user.visible_message("[user] coats [target] with spray paint!", "<span class='notice'>You coat [target] with spray paint.</span>")
|
||||
return
|
||||
|
||||
. = ..()
|
||||
@@ -709,7 +746,7 @@
|
||||
desc = "A metallic container containing shiny synthesised paint."
|
||||
charges = -1
|
||||
|
||||
/obj/item/toy/crayon/spraycan/borg/afterattack(atom/target,mob/user,proximity)
|
||||
/obj/item/toy/crayon/spraycan/borg/afterattack(atom/target,mob/user,proximity, params)
|
||||
var/diff = ..()
|
||||
if(!iscyborg(user))
|
||||
to_chat(user, "<span class='notice'>How did you get this?</span>")
|
||||
@@ -754,7 +791,9 @@
|
||||
|
||||
reagent_contents = list("lube" = 1, "banana" = 1)
|
||||
volume_multiplier = 5
|
||||
validSurfaces = list(/turf/open/floor)
|
||||
|
||||
/obj/item/toy/crayon/spraycan/lubecan/isValidSurface(surface)
|
||||
return istype(surface, /turf/open/floor)
|
||||
|
||||
/obj/item/toy/crayon/spraycan/mimecan
|
||||
name = "silent spraycan"
|
||||
@@ -792,8 +831,16 @@
|
||||
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.")
|
||||
|
||||
/obj/item/toy/crayon/spraycan/infinite
|
||||
name = "infinite spraycan"
|
||||
charges = -1
|
||||
desc = "Now with 30% more bluespace technology."
|
||||
|
||||
#undef RANDOM_GRAFFITI
|
||||
#undef RANDOM_LETTER
|
||||
#undef RANDOM_PUNCTUATION
|
||||
#undef RANDOM_SYMBOL
|
||||
#undef RANDOM_DRAWING
|
||||
#undef RANDOM_NUMBER
|
||||
#undef RANDOM_ORIENTED
|
||||
#undef RANDOM_RUNE
|
||||
|
||||
@@ -440,9 +440,20 @@
|
||||
|
||||
do_help(H, user)
|
||||
|
||||
/obj/item/twohanded/shockpaddles/proc/can_defib(mob/living/carbon/H)
|
||||
/obj/item/twohanded/shockpaddles/proc/can_defib(mob/living/carbon/H) //Our code here is different than tg, if it breaks in testing; BUG_PROBABLE_CAUSE
|
||||
var/obj/item/organ/heart = H.getorgan(/obj/item/organ/heart)
|
||||
if(H.suiciding || H.hellbound || HAS_TRAIT(H, TRAIT_HUSK))
|
||||
return
|
||||
if((world.time - H.timeofdeath) > tlimit)
|
||||
return
|
||||
if((H.getBruteLoss() >= MAX_REVIVE_BRUTE_DAMAGE) || (H.getFireLoss() >= MAX_REVIVE_FIRE_DAMAGE))
|
||||
return
|
||||
if(!heart || (heart.organ_flags & ORGAN_FAILING))
|
||||
return
|
||||
var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/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)
|
||||
if(QDELETED(BR) || BR.brain_death || (BR.organ_flags & ORGAN_FAILING) || H.suiciding)
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/item/twohanded/shockpaddles/proc/shock_touching(dmg, mob/H)
|
||||
if(req_defib)
|
||||
@@ -557,14 +568,12 @@
|
||||
if(do_after(user, primetimer, target = H)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
|
||||
user.visible_message("<span class='notice'>[user] places [src] on [H]'s chest.</span>", "<span class='warning'>You place [src] on [H]'s chest.</span>")
|
||||
playsound(src, 'sound/machines/defib_charge.ogg', 75, 0)
|
||||
var/tplus = world.time - H.timeofdeath
|
||||
// past this much time the patient is unrecoverable
|
||||
// (in deciseconds)
|
||||
// brain damage starts setting in on the patient after
|
||||
// some time left rotting
|
||||
// patients rot when they are killed, and die when they are dead
|
||||
var/tplus = world.time - H.timeofdeath //length of time spent dead
|
||||
var/tloss = deathtimer
|
||||
var/total_burn = 0
|
||||
var/total_brute = 0
|
||||
var/obj/item/organ/heart = H.getorgan(/obj/item/organ/heart)
|
||||
if(do_after(user, primetimer2, target = H)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
|
||||
for(var/obj/item/carried_item in H.contents)
|
||||
if(istype(carried_item, /obj/item/clothing/suit/space))
|
||||
@@ -589,16 +598,26 @@
|
||||
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>"
|
||||
else if (tplus > tlimit)
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Body has decayed for too long. Further attempts futile.</span>"
|
||||
else if (!H.getorgan(/obj/item/organ/heart))
|
||||
else if (!heart)
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's heart is missing.</span>"
|
||||
else if (heart.organ_flags & ORGAN_FAILING)
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's heart too damaged.</span>"
|
||||
else if(total_burn >= 180 || total_brute >= 180)
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Severe tissue damage makes recovery of patient impossible via defibrillator. Further attempts futile.</span>"
|
||||
else if(H.get_ghost())
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - No activity in patient's brain. Further attempts may be successful.</span>"
|
||||
else
|
||||
var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
|
||||
if(!BR || BR.damaged_brain)
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain is missing or damaged beyond point of no return. Further attempts futile.</span>"
|
||||
if(BR) //BUG_PROBABLE_CAUSE - slight difference between us and tg
|
||||
if(BR.organ_flags & ORGAN_FAILING)
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain tissue is damaged making recovery of patient impossible via defibrillator. Further attempts futile.</span>"
|
||||
if(BR.brain_death)
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain damaged beyond point of no return. Further attempts futile.</span>"
|
||||
if(H.suiciding || BR.brainmob?.suiciding)
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - No intelligence pattern can be detected in patient's brain. Further attempts futile.</span>"
|
||||
else
|
||||
failed = "<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's brain is missing. Further attempts futile.</span>"
|
||||
|
||||
|
||||
if(failed)
|
||||
user.visible_message(failed)
|
||||
@@ -623,7 +642,7 @@
|
||||
H.Jitter(100)
|
||||
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK)
|
||||
if(tplus > tloss)
|
||||
H.adjustBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))), 150)
|
||||
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, max(0, min(99, ((tlimit - tplus) / tlimit * 100))), 150)
|
||||
log_combat(user, H, "revived", defib)
|
||||
if(req_defib)
|
||||
if(defib.healdisk)
|
||||
@@ -641,7 +660,11 @@
|
||||
playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
|
||||
else if(H.undergoing_cardiac_arrest())
|
||||
H.set_heartattack(FALSE)
|
||||
user.visible_message("<span class='notice'>[req_defib ? "[defib]" : "[src]"] pings: Patient's heart is now beating again.</span>")
|
||||
if(!(heart.organ_flags & ORGAN_FAILING))
|
||||
H.set_heartattack(FALSE)
|
||||
user.visible_message("<span class='notice'>[req_defib ? "[defib]" : "[src]"] pings: Patient's heart is now beating again.</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed, heart damage detected.</span>")
|
||||
playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
||||
|
||||
|
||||
|
||||
@@ -714,6 +714,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
return
|
||||
if((last_text && world.time < last_text + 10) || (everyone && last_everyone && world.time < last_everyone + PDA_SPAM_DELAY))
|
||||
return
|
||||
var/emoji_message = emoji_parse(message)
|
||||
if(prob(1))
|
||||
message += "\nSent from my PDA"
|
||||
// Send the signal
|
||||
@@ -734,7 +735,8 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
"name" = "[owner]",
|
||||
"job" = "[ownjob]",
|
||||
"message" = message,
|
||||
"targets" = string_targets
|
||||
"targets" = string_targets,
|
||||
"emoji_message" = emoji_message
|
||||
))
|
||||
if (picture)
|
||||
signal.data["photo"] = picture
|
||||
@@ -751,13 +753,13 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
// Log it in our logs
|
||||
tnote += "<i><b>→ To [target_text]:</b></i><br>[signal.format_message()]<br>"
|
||||
// Show it to ghosts
|
||||
var/ghost_message = "<span class='name'>[owner] </span><span class='game say'>PDA Message</span> --> <span class='name'>[target_text]</span>: <span class='message'>[signal.format_message()]</span>"
|
||||
var/ghost_message = "<span class='name'>[owner] </span><span class='game say'>PDA Message</span> --> <span class='name'>[target_text]</span>: <span class='message'>[signal.format_message(TRUE)]</span>"
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(isobserver(M) && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTPDA))
|
||||
to_chat(M, "[FOLLOW_LINK(M, user)] [ghost_message]")
|
||||
// Log in the talk log
|
||||
user.log_talk(message, LOG_PDA, tag="PDA: [initial(name)] to [target_text]")
|
||||
to_chat(user, "<span class='info'>Message sent to [target_text]: \"[message]\"</span>")
|
||||
to_chat(user, "<span class='info'>Message sent to [target_text]: \"[emoji_message]\"</span>")
|
||||
if (!silent)
|
||||
playsound(src, 'sound/machines/terminal_success.ogg', 15, 1)
|
||||
// Reset the photo
|
||||
@@ -787,7 +789,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
hrefstart = "<a href='?src=[REF(L)];track=[html_encode(signal.data["name"])]'>"
|
||||
hrefend = "</a>"
|
||||
|
||||
to_chat(L, "[icon2html(src)] <b>Message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], </b>[signal.format_message()] (<a href='byond://?src=[REF(src)];choice=Message;skiprefresh=1;target=[REF(signal.source)]'>Reply</a>)")
|
||||
to_chat(L, "[icon2html(src)] <b>Message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], </b>[signal.format_message(TRUE)] (<a href='byond://?src=[REF(src)];choice=Message;skiprefresh=1;target=[REF(signal.source)]'>Reply</a>)")
|
||||
|
||||
update_icon(TRUE)
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
data["occupant"]["toxLoss"] = mob_occupant.getToxLoss()
|
||||
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
|
||||
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
|
||||
data["occupant"]["brainLoss"] = mob_occupant.getBrainLoss()
|
||||
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
data["occupant"]["reagents"] = list()
|
||||
if(mob_occupant.reagents.reagent_list.len)
|
||||
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
if(BODY_ZONE_PRECISE_MOUTH)
|
||||
|
||||
if((M.head && M.head.flags_cover & HEADCOVERSMOUTH) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
|
||||
if(M.is_mouth_covered())
|
||||
to_chat(user, "<span class='notice'>You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first.</span>")
|
||||
return
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
if(!M.radiation)
|
||||
to_chat(user, "<span class='notice'>[icon2html(src, user)] Radiation levels within normal boundaries.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='boldannounce'>[icon2html(src, user)] Subject is irradiated. Radiation levels: [M.radiation].</span>")
|
||||
to_chat(user, "<span class='boldannounce'>[icon2html(src, user)] Subject is irradiated. Radiation levels: [M.radiation] rad.</span>")
|
||||
|
||||
if(rad_strength)
|
||||
to_chat(user, "<span class='boldannounce'>[icon2html(src, user)] Target contains radioactive contamination. Radioactive strength: [rad_strength]</span>")
|
||||
|
||||
@@ -167,8 +167,19 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
gpstag = "Eerie Signal"
|
||||
desc = "Report to a coder immediately."
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
var/obj/item/implant/gps/implant
|
||||
|
||||
/obj/item/gps/mining/internal
|
||||
/obj/item/gps/internal/Initialize(mapload, obj/item/implant/gps/_implant)
|
||||
. = ..()
|
||||
implant = _implant
|
||||
|
||||
/obj/item/gps/internal/Destroy()
|
||||
if(implant?.imp_in)
|
||||
qdel(implant)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/gps/internal/mining
|
||||
icon_state = "gps-m"
|
||||
gpstag = "MINER"
|
||||
desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life."
|
||||
|
||||
@@ -413,3 +413,16 @@
|
||||
/obj/item/radio/off // Station bounced radios, their only difference is spawning with the speakers off, this was made to help the lag.
|
||||
listening = 0 // And it's nice to have a subtype too for future features.
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
/obj/item/radio/internal
|
||||
var/obj/item/implant/radio/implant
|
||||
|
||||
/obj/item/radio/internal/Initialize(mapload, obj/item/implant/radio/_implant)
|
||||
. = ..()
|
||||
implant = _implant
|
||||
|
||||
/obj/item/radio/internal/Destroy()
|
||||
if(implant?.imp_in)
|
||||
qdel(implant)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -135,7 +135,7 @@ SLIME SCANNER
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.undergoing_cardiac_arrest() && H.stat != DEAD)
|
||||
to_chat(user, "<span class='danger'>Subject suffering from heart attack: Apply defibrillation or other electric shock immediately!</span>")
|
||||
if(H.undergoing_liver_failure() && H.stat != DEAD)
|
||||
if(H.undergoing_liver_failure() && H.stat != DEAD) //might be depreciated BUG_PROBABLE_CAUSE
|
||||
to_chat(user, "<span class='danger'>Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!</span>")
|
||||
|
||||
var/msg = "<span class='info'>*---------*\nAnalyzing results for [M]:\n\tOverall status: [mob_status]\n"
|
||||
@@ -157,12 +157,8 @@ SLIME SCANNER
|
||||
msg += "\t<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>\n"
|
||||
if(advanced)
|
||||
msg += "\t<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>\n"
|
||||
if (M.getBrainLoss() >= 200 || !M.getorgan(/obj/item/organ/brain))
|
||||
msg += "\t<span class='alert'>Subject's brain function is non-existent.</span>\n"
|
||||
else if (M.getBrainLoss() >= 120)
|
||||
msg += "\t<span class='alert'>Severe brain damage detected. Subject likely to have mental traumas.</span>\n"
|
||||
else if (M.getBrainLoss() >= 45)
|
||||
msg += "\t<span class='alert'>Brain damage detected.</span>\n"
|
||||
if (!M.getorgan(/obj/item/organ/brain))
|
||||
to_chat(user, "\t<span class='alert'>Subject lacks a brain.</span>") //Unsure how this won't proc for 50% of the cit playerbase (This is a joke everyone on cit a cute.)
|
||||
if(ishuman(M) && advanced) // Should I make this not advanced?
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/liver/L = H.getorganslot("liver")
|
||||
@@ -194,6 +190,14 @@ SLIME SCANNER
|
||||
if(Br.cached_size>5)
|
||||
msg += "\t<span class='info'>Subject has a sizeable bosom with a [Br.size] cup.</span>\n"
|
||||
|
||||
if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 200 || !M.getorgan(/obj/item/organ/brain))
|
||||
msg += "\t<span class='alert'>Subject's brain function is non-existent.</span>\n"
|
||||
else if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 120)
|
||||
msg += "\t<span class='alert'>Severe brain damage detected. Subject likely to have mental traumas.</span>\n"
|
||||
else if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 45)
|
||||
msg += "\t<span class='alert'>Brain damage detected.</span>\n"
|
||||
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/C = M
|
||||
if(LAZYLEN(C.get_traumas()))
|
||||
var/list/trauma_text = list()
|
||||
@@ -212,11 +216,10 @@ SLIME SCANNER
|
||||
if(C.roundstart_quirks.len)
|
||||
msg += "\t<span class='info'>Subject has the following physiological traits: [C.get_trait_string()].</span>\n"
|
||||
if(advanced)
|
||||
msg += "\t<span class='info'>Brain Activity Level: [(200 - M.getBrainLoss())/2]%.</span>\n"
|
||||
msg += "\t<span class='info'>Brain Activity Level: [(200 - M.getOrganLoss(ORGAN_SLOT_BRAIN))/2]%.</span>\n"
|
||||
if(M.radiation)
|
||||
msg += "\t<span class='alert'>Subject is irradiated.</span>\n"
|
||||
if(advanced)
|
||||
msg += "\t<span class='info'>Radiation Level: [M.radiation]%.</span>\n"
|
||||
msg += "\t<span class='info'>Radiation Level: [M.radiation] rad</span>\n"
|
||||
|
||||
if(advanced && M.hallucinating())
|
||||
msg += "\t<span class='info'>Subject is hallucinating.</span>\n"
|
||||
@@ -247,11 +250,11 @@ SLIME SCANNER
|
||||
healthy = FALSE
|
||||
msg += "\t<span class='alert'>Subject is deaf.</span>\n"
|
||||
else
|
||||
if(ears.ear_damage)
|
||||
msg += "\t<span class='alert'>Subject has [ears.ear_damage > UNHEALING_EAR_DAMAGE? "permanent ": "temporary "]hearing damage.</span>\n"
|
||||
if(ears.damage)
|
||||
to_chat(user, "\t<span class='alert'>Subject has [ears.damage > ears.maxHealth ? "permanent ": "temporary "]hearing damage.</span>")
|
||||
healthy = FALSE
|
||||
if(ears.deaf)
|
||||
msg += "\t<span class='alert'>Subject is [ears.ear_damage > UNHEALING_EAR_DAMAGE ? "permanently ": "temporarily "] deaf.</span>\n"
|
||||
to_chat(user, "\t<span class='alert'>Subject is [ears.damage > ears.maxHealth ? "permanently ": "temporarily "] deaf.</span>")
|
||||
healthy = FALSE
|
||||
if(healthy)
|
||||
msg += "\t<span class='info'>Healthy.</span>\n"
|
||||
@@ -267,13 +270,13 @@ SLIME SCANNER
|
||||
if(HAS_TRAIT(C, TRAIT_NEARSIGHT))
|
||||
msg += "\t<span class='alert'>Subject is nearsighted.</span>\n"
|
||||
healthy = FALSE
|
||||
if(eyes.eye_damage > 30)
|
||||
if(eyes.damage > 30)
|
||||
msg += "\t<span class='alert'>Subject has severe eye damage.</span>\n"
|
||||
healthy = FALSE
|
||||
else if(eyes.eye_damage > 20)
|
||||
else if(eyes.damage > 20)
|
||||
msg += "\t<span class='alert'>Subject has significant eye damage.</span>\n"
|
||||
healthy = FALSE
|
||||
else if(eyes.eye_damage)
|
||||
else if(eyes.damage)
|
||||
msg += "\t<span class='alert'>Subject has minor eye damage.</span>\n"
|
||||
healthy = FALSE
|
||||
if(healthy)
|
||||
@@ -297,6 +300,59 @@ SLIME SCANNER
|
||||
for(var/obj/item/bodypart/org in damaged)
|
||||
msg += "\t\t<span class='info'>[capitalize(org.name)]: [(org.brute_dam > 0) ? "<font color='red'>[org.brute_dam]</font></span>" : "<font color='red'>0</font>"]-[(org.burn_dam > 0) ? "<font color='#FF8000'>[org.burn_dam]</font>" : "<font color='#FF8000'>0</font>"]\n"
|
||||
|
||||
//Organ damages report
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/minor_damage
|
||||
var/major_damage
|
||||
var/max_damage
|
||||
var/report_organs = FALSE
|
||||
|
||||
//Piece together the lists to be reported
|
||||
for(var/O in H.internal_organs)
|
||||
var/obj/item/organ/organ = O
|
||||
if(organ.organ_flags & ORGAN_FAILING)
|
||||
report_organs = TRUE //if we report one organ, we report all organs, even if the lists are empty, just for consistency
|
||||
if(max_damage)
|
||||
max_damage += ", " //prelude the organ if we've already reported an organ
|
||||
max_damage += organ.name //this just slaps the organ name into the string of text
|
||||
else
|
||||
max_damage = "\t<span class='alert'>Non-Functional Organs: " //our initial statement
|
||||
max_damage += organ.name
|
||||
else if(organ.damage > organ.high_threshold)
|
||||
report_organs = TRUE
|
||||
if(major_damage)
|
||||
major_damage += ", "
|
||||
major_damage += organ.name
|
||||
else
|
||||
major_damage = "\t<span class='info'>Severely Damaged Organs: "
|
||||
major_damage += organ.name
|
||||
else if(organ.damage > organ.low_threshold)
|
||||
report_organs = TRUE
|
||||
if(minor_damage)
|
||||
minor_damage += ", "
|
||||
minor_damage += organ.name
|
||||
else
|
||||
minor_damage = "\t<span class='info'>Mildly Damaged Organs: "
|
||||
minor_damage += organ.name
|
||||
|
||||
if(report_organs) //we either finish the list, or set it to be empty if no organs were reported in that category
|
||||
if(!max_damage)
|
||||
max_damage = "\t<span class='alert'>Non-Functional Organs: </span>"
|
||||
else
|
||||
max_damage += "</span>"
|
||||
if(!major_damage)
|
||||
major_damage = "\t<span class='info'>Severely Damaged Organs: </span>"
|
||||
else
|
||||
major_damage += "</span>"
|
||||
if(!minor_damage)
|
||||
minor_damage = "\t<span class='info'>Mildly Damaged Organs: </span>"
|
||||
else
|
||||
minor_damage += "</span>"
|
||||
msg += "[minor_damage]"
|
||||
msg += "[major_damage]"
|
||||
msg += "[max_damage]"
|
||||
|
||||
|
||||
// Species and body temperature
|
||||
if(ishuman(M))
|
||||
@@ -385,7 +441,7 @@ SLIME SCANNER
|
||||
if(M.reagents.reagent_list.len)
|
||||
var/list/datum/reagent/reagents = list()
|
||||
for(var/datum/reagent/R in M.reagents.reagent_list)
|
||||
if(R.invisible)
|
||||
if(R.chemical_flags & REAGENT_INVISIBLE)
|
||||
continue
|
||||
reagents += R
|
||||
|
||||
@@ -404,6 +460,21 @@ SLIME SCANNER
|
||||
msg += "<span class='danger'>[R.name]</span>\n"
|
||||
else
|
||||
msg += "<span class='notice'>Subject is not addicted to any reagents.</span>\n"
|
||||
|
||||
if(M.reagents.has_reagent("fermiTox"))
|
||||
var/datum/reagent/fermiTox = M.reagents.has_reagent("fermiTox")
|
||||
switch(fermiTox.volume)
|
||||
if(5 to 10)
|
||||
msg += "<span class='notice'>Subject contains a low amount of toxic isomers.</span>\n"
|
||||
if(10 to 25)
|
||||
msg += "<span class='danger'>Subject contains toxic isomers.</span>\n"
|
||||
if(25 to 50)
|
||||
msg += "<span class='danger'>Subject contains a substantial amount of toxic isomers.</span>\n"
|
||||
if(50 to 95)
|
||||
msg += "<span class='danger'>Subject contains a high amount of toxic isomers.</span>\n"
|
||||
if(95 to INFINITY)
|
||||
msg += "<span class='danger'>Subject contains a extremely dangerous amount of toxic isomers.</span>\n"
|
||||
|
||||
msg += "*---------*</span>"
|
||||
to_chat(user, msg)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user