Merge branch 'master' of https://github.com/ArchieBeepBoop/Hyper-Station-13 into syndicateleague2

This commit is contained in:
Dip
2020-11-10 14:05:51 -03:00
80 changed files with 1523 additions and 426 deletions
+4
View File
@@ -12,6 +12,8 @@
#define ROBOTICIST (1<<8)
#define AI_JF (1<<9)
#define CYBORG (1<<10)
#define JR_OFFICER (1<<11)
#define JR_ENGINEER (1<<12)
#define MEDSCI (1<<1)
@@ -23,6 +25,8 @@
#define DOCTOR (1<<4)
#define GENETICIST (1<<5)
#define VIROLOGIST (1<<6)
#define JR_DOCTOR (1<<7)
#define JR_SCIENTIST (1<<9)
#define CIVILIAN (1<<2)
+3 -2
View File
@@ -66,8 +66,9 @@
#define SPACEVINE_LAYER 4.8
#define SPACEVINE_MOB_LAYER 4.9
//#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define
#define GASFIRE_LAYER 5.05
#define RIPPLE_LAYER 5.1
#define ABOVE_FLY_LAYER 5.1
#define GASFIRE_LAYER 5.2
#define RIPPLE_LAYER 5.3
#define GHOST_LAYER 6
#define LOW_LANDMARK_LAYER 9
+1
View File
@@ -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)
+2
View File
@@ -272,3 +272,5 @@
#define PULL_PRONE_SLOWDOWN 0.6
#define HUMAN_CARRY_SLOWDOWN 0
#define TYPING_INDICATOR_TIMEOUT 10 MINUTES
+1
View File
@@ -184,6 +184,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"
+4
View File
@@ -61,6 +61,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]")
+2
View File
@@ -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)
@@ -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
+5 -2
View File
@@ -34,9 +34,10 @@ SUBSYSTEM_DEF(input)
"O" = "ooc",
"Ctrl+O" = "looc",
"T" = "say",
"Ctrl+T" = "whisper",
"Ctrl+T" = "say_indicator",
"Y" = "whisper",
"M" = "me",
"Ctrl+M" = "subtle",
"Ctrl+M" = "me_indicator",
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
"Any" = "\"KeyDown \[\[*\]\]\"",
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
@@ -50,7 +51,9 @@ SUBSYSTEM_DEF(input)
"Tab" = "\".winset \\\"mainwindow.macro=old_default input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
"O" = "ooc",
"T" = "say",
"Ctrl+T" = "say_indicator",
"M" = "me",
"Ctrl+M" = "me_indicator",
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
"Any" = "\"KeyDown \[\[*\]\]\"",
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
+1 -1
View File
@@ -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
+6
View File
@@ -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)))
+11 -2
View File
@@ -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 -17
View File
@@ -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)
@@ -137,10 +144,16 @@
A.symptoms += S.Copy()
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 +204,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 +359,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 +434,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()
@@ -444,10 +461,6 @@
return
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,7 +471,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()
@@ -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)
@@ -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)
@@ -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,8 +26,8 @@
level = 5
severity = 0
/datum/symptom/inorganic_adaptation/Start(datum/disease/advance/A)
if(!..())
return
/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
@@ -27,7 +27,7 @@
var/list/exclusive_roles = list()
/// If set, there needs to be a certain amount of players doing those roles (among the players who won't be drafted) for the rule to be drafted IMPORTANT: DOES NOT WORK ON ROUNDSTART RULESETS.
var/list/enemy_roles = list()
/// If enemy_roles was set, this is the amount of enemy job workers needed per GLOB.dynamic_chaos_level range (0-0.5, 0.5-1.0) IMPORTANT: DOES NOT WORK ON ROUNDSTART RULESETS.
/// If enemy_roles was set, this is the amount of enemy job workers needed per threat_level range (0-10,10-20,etc) IMPORTANT: DOES NOT WORK ON ROUNDSTART RULESETS.
var/required_enemies = list(1,1,0,0,0,0,0,0,0,0)
/// The rule needs this many candidates (post-trimming) to be executed (example: Cult needs 4 players at round start)
var/required_candidates = 0
@@ -26,9 +26,8 @@
continue // Dead players cannot count as opponents
if (M.mind && M.mind.assigned_role && (M.mind.assigned_role in enemy_roles) && (!(M in candidates) || (M.mind.assigned_role in restricted_roles)))
job_check++ // Checking for "enemies" (such as sec officers). To be counters, they must either not be candidates to that rule, or have a job that restricts them from it
var/chaos = min(max(round(GLOB.dynamic_chaos_level * 2), 0), 9)
if (job_check < required_enemies[chaos])
var/threat = max(min(round(mode.threat_level/10),9),1) //min() to stop index errors at 100 threat //Max to stop breaking at 0 threat.
if (job_check < required_enemies[threat])
return FALSE
return ..()
@@ -104,7 +103,7 @@
typepath = /datum/round_event/pirates
antag_flag = ROLE_TRAITOR
enemy_roles = list("AI","Security Officer","Head of Security","Captain")
required_enemies = list(2,2,2,2,1,1,1,1,0,0)
required_enemies = list(3,3,2,2,2,1,1,1,1,0)
weight = 3
cost = 0
earliest_start = 50 MINUTES
@@ -120,82 +119,6 @@
return FALSE
return ..()
/* //not currently functional
//////////////////////////////////////////
// //
// LEWD //
// //
//////////////////////////////////////////
//Might move this to midround antags, but I don't want it messing with the weights of regular antags right now
//Only drops one horny antag at a time anyways
/datum/dynamic_ruleset/event/lewd
name = "Horny Traitor"
//config_tag = "pirates"
//typepath = /datum/round_event/pirates
antag_flag = ROLE_LEWD_TRAITOR
antag_datum = /datum/antagonist/traitor/lewd
enemy_roles = list()
required_enemies = list(0,0,0,0,0,0,0,0,0,0)
protected_roles = list("AI","Cyborg")
restricted_roles = list("Cyborg","AI")
weight = 300 //JAY CHANGE THIS WHEN YOU ARE DONE TESTING
cost = 0
earliest_start = 50 MINUTES
//blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
occurances_max = 2
chaos_min = 0
chaos_max = 2.5
minimum_required_age = 7
admin_required = TRUE
var/list/mob/living/carbon/human/lewd_candidates = list()
var/list/mob/living/carbon/human/targets = list()
var/num_lewd_traitors = 1 //The number of lewds to drop in
var/numTraitors = 0 //Variable for later. Don't touch.
earliest_start = 0 MINUTES
/datum/dynamic_ruleset/event/lewd/ready(forced = FALSE)
//to_chat(GLOB.admins, "makeLewd_traitors called")
//var/datum/game_mode/traitor/lewd/temp = new
//if(CONFIG_GET(flag/protect_roles_from_antagonist))
//continue
//if(CONFIG_GET(flag/protect_assistant_from_antagonist))
//continue
//var/mob/living/carbon/human/T = null
for(var/mob/living/carbon/human/target in CURRENT_LIVING_PLAYERS)
if(target.client.prefs.noncon)
if(!(target.job in restricted_roles))
targets += target
if(lewd_candidates.len)
numTraitors = min(candidates.len, targets.len, num_lewd_traitors)
if(numTraitors == 0)
to_chat(GLOB.admins, "No lewd traitors created. Are there any valid targets?")
return 0
return ..()
return 0
/datum/dynamic_ruleset/event/lewd/execute(forced = FALSE)
var/mob/living/carbon/human/H = null
if(numTraitors)
for(var/i = 0, i<numTraitors, i++)
H = pick(lewd_candidates)
H.mind.make_LewdTraitor()
lewd_candidates.Remove(H)
return TRUE
return FALSE
*/
//////////////////////////////////////////////
// //
// SPIDERS //
@@ -207,8 +130,8 @@
//config_tag = "spiders"
typepath = /datum/round_event/spider_infestation
enemy_roles = list("AI","Security Officer","Head of Security","Captain")
required_enemies = list(2,2,1,1,0,0,0,0,0,0)
weight = 3
required_enemies = list(3,2,2,2,2,1,1,1,0,0)
weight = 2
cost = 5
requirements = list(101,20,15,10,10,10,10,10,10,10)
high_population_requirement = 15
@@ -228,7 +151,7 @@
//config_tag = "ventclog"
typepath = /datum/round_event/vent_clog
enemy_roles = list("Chemist","Medical Doctor","Chief Medical Officer")
required_enemies = list(1,1,1,1,1,1,0,0,0,0)
required_enemies = list(2,2,2,2,2,2,2,2,2,0)
cost = 2
weight = 1
repeatable_weight_decrease = 1
@@ -249,7 +172,7 @@
else if(mode.threat_level > 15 && mode.threat > 15 && prob(30))
name = "Clogged Vents: Catastrophic"
cost = 15
required_enemies = list(4,4,4,3,3,3,2,1,1,0)
required_enemies = list(4,4,4,3,3,3,2,1,1,1)
typepath = /datum/round_event/vent_clog/catastrophic
chaos_min = 1.8
else
@@ -293,12 +216,12 @@
//config_tag = "meteor_wave"
typepath = /datum/round_event/meteor_wave
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Captain","Cyborg")
required_enemies = list(2,2,2,2,2,1,1,1,0,0)
required_enemies = list(2,2,2,2,2,2,2,2,1,1)
cost = 0
weight = 2
earliest_start = 45 MINUTES
repeatable_weight_decrease = 2
requirements = list(101,101,15,15,15,15,15,15,10,10)
requirements = list(101,101,25,25,20,20,15,15,10,10)
high_population_requirement = 30
//property_weights = list("extended" = -2)
occurances_max = 2
@@ -315,14 +238,14 @@
name = "Meteor Wave: Catastrophic"
cost = 10
typepath = /datum/round_event/meteor_wave/catastrophic
required_enemies = list(3,3,3,3,3,2,2,1,1,0)
required_enemies = list(3,3,3,3,3,2,2,2,2,2)
requirements = list(101,101,40,30,30,30,30,30,30,30)
chaos_min = 2.0
else
name = "Meteor Wave: Normal"
cost = 5
typepath = /datum/round_event/meteor_wave
chaos_min = 1.2
chaos_min = 1.5
required_enemies = list(2,2,2,2,1,1,1,1,0,0)
return ..()
@@ -338,11 +261,11 @@
typepath = /datum/round_event/anomaly/anomaly_bluespace
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain")
required_enemies = list(2,2,2,1,1,1,1,1,1,0)
weight = 3
weight = 2
earliest_start = 20 MINUTES
repeatable_weight_decrease = 2
cost = 0
requirements = list(101,101,5,5,5,5,5,5,5,5)
requirements = list(101,101,10,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
//property_weights = list("extended" = 1)
@@ -358,8 +281,8 @@
weight = 3
earliest_start = 20 MINUTES
repeatable_weight_decrease = 2
cost = 3
requirements = list(101,5,5,5,5,5,5,5,5,5)
cost = 2
requirements = list(101,101,10,5,5,5,5,5,5,5)
high_population_requirement = 10
repeatable = TRUE
//property_weights = list("extended" = 1)
@@ -370,10 +293,10 @@
name = "Anomaly: Gravitational"
//config_tag = "anomaly_gravitational"
typepath = /datum/round_event/anomaly/anomaly_grav
weight = 4
weight = 3
repeatable_weight_decrease = 1
cost = 0
requirements = list(5,4,3,2,1,0,0,0,0,0)
requirements = list(101,4,3,2,1,0,0,0,0,0)
high_population_requirement = 5
repeatable = TRUE
//property_weights = list("extended" = 1)
@@ -407,7 +330,7 @@
cost = 0
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg")
required_enemies = list(3,3,3,2,2,2,2,2,2,0)
requirements = list(101,101,10,10,10,10,10,10,10,10)
requirements = list(101,101,101,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
//property_weights = list("extended" = 1)
@@ -427,7 +350,7 @@
required_enemies = list(0,0,0,0,0,0,0,0,0,0)
weight = 0 //This is changed in nuclearbomb.dm
occurances_max = 1
requirements = list(10,5,0,0,0,0,0,0,0,0) //SECURE THAT DISK
requirements = list(10,10,10,10,10,10,10,10,10,10) //SECURE THAT DISK
cost = 50
chaos_min = 0.5
@@ -457,7 +380,7 @@
repeatable_weight_decrease = 1
cost = 0
enemy_roles = list("Chief Engineer","Station Engineer","Atmospheric Technician","Research Director","Scientist","Captain","Cyborg")
required_enemies = list(2,1,1,1,1,1,0,0,0,0)
required_enemies = list(3,2,2,2,1,1,1,0,0,0)
requirements = list(101,25,20,15,15,15,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
@@ -469,10 +392,10 @@
name = "Carp Migration"
//config_tag = "carp_migration"
typepath = /datum/round_event/carp_migration
weight = 5
repeatable_weight_decrease = 3
weight = 4
repeatable_weight_decrease = 2
cost = 4
requirements = list(101,5,5,1,1,1,1,1,1,1)
requirements = list(101,5,5,5,5,1,1,1,1,1)
high_population_requirement = 10
earliest_start = 10 MINUTES
repeatable = TRUE
@@ -563,8 +486,8 @@
weight = 2
earliest_start = 30 MINUTES
repeatable_weight_decrease = 1
enemy_roles = list("Medical Doctor","Chief Medical Officer")
required_enemies = list(2,2,2,2,2,2,2,2,2,0)
enemy_roles = list("Medical Doctor","Chief Medical Officer", "Chemist")
required_enemies = list(3,3,2,2,2,2,2,2,2,1)
requirements = list(101,101,101,10,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
@@ -579,7 +502,7 @@
weight = 2
repeatable_weight_decrease = 2
enemy_roles = list("Chemist","Chief Medical Officer","Geneticist","Medical Doctor","AI","Captain")
required_enemies = list(1,1,1,1,1,1,1,1,1,0)
required_enemies = list(2,2,2,2,1,1,1,1,1,0)
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
//property_weights = list("extended" = 1,"chaos" = 1)
@@ -592,13 +515,13 @@
cost = 0
weight = 1
enemy_roles = list("Head of Security","Security Officer","AI","Captain","Shaft Miner")
required_enemies = list(2,2,2,2,2,2,2,2,2,0)
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
requirements = list(101,101,40,35,30,30,30,30,25,20)
high_population_requirement = 30
earliest_start = 40 MINUTES
//property_weights = list("teamwork" = 1,"chaos" = 1, "extended" = -1)
occurances_max = 1
chaos_min = 1.0
chaos_min = 1.3
/datum/dynamic_ruleset/event/wormholes
@@ -624,12 +547,12 @@
weight = 1
earliest_start = 40 MINUTES
enemy_roles = list("AI","Security Officer","Head of Security","Captain","Station Engineer","Atmos Technician","Chief Engineer")
required_enemies = list(4,4,4,4,3,3,3,3,2,0)
required_enemies = list(4,4,4,4,3,3,3,3,2,2)
requirements = list(101,101,50,40,40,40,40,35,30,30)
high_population_requirement = 5
//property_weights = list("extended" = -2)
occurances_max = 1
chaos_min = 2.0
chaos_min = 1.5
/datum/dynamic_ruleset/event/sentient_disease
name = "Sentient Disease"
@@ -640,7 +563,7 @@
required_candidates = 1
weight = 4
cost = -5
requirements = list(101,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"!
requirements = list(101,101,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"!
//property_weights = list("story_potential" = 1, "extended" = 1, "valid" = -2)
high_population_requirement = 5
occurances_max = 1
@@ -655,7 +578,7 @@
required_candidates = 1
weight = 4
cost = 5
requirements = list(101,30,27,24,21,18,15,15,10,10)
requirements = list(101,101,23,21,18,18,15,15,10,10)
high_population_requirement = 15
//property_weights = list("story_potential" = -2, "extended" = -1)
occurances_max = 1 //Skyrat change.
@@ -667,7 +590,7 @@
typepath = /datum/round_event/immovable_rod
enemy_roles = list("Research Director","Chief Engineer","Station Engineer","Captain","Chaplain","AI")
required_enemies = list(2,2,2,2,2,2,1,1,1,0)
requirements = list(101,101,18,16,14,12,10,8,6,6)
requirements = list(101,101,20,18,16,14,12,10,8,6)
high_population_requirement = 15
cost = 0
occurances_max = 2
@@ -741,29 +664,16 @@
repeatable = TRUE
occurances_max = 2
/datum/dynamic_ruleset/event/disease_outbreak/execute() //I do not know why this is necessary
var/datum/round_event_control/E = locate(/datum/round_event_control/disease_outbreak) in SSevents.control
var/datum/round_event/event = E.runEvent() //But it is.
event.announceWhen = -1 //So it isn't double announced.
return ..()
/datum/dynamic_ruleset/event/falsealarm //I THINK IT WORKS
/datum/dynamic_ruleset/event/falsealarm
name = "False Alarm"
controller = /datum/round_event_control/falsealarm
typepath = /datum/round_event/falsealarm
requirements = list(0,0,0,0,0,0,0,0,0,0)
requirements = list(5,5,5,5,5,5,5,5,5,5) //Tell me lieeeess
high_population_requirement = 0
weight = 5
repeatable = TRUE
occurances_max = 5
///datum/dynamic_ruleset/event/falsealarm/execute() //I do not know why this is necessary
//var/datum/round_event_control/E = locate(/datum/round_event_control/falsealarm) in SSevents.control
//var/datum/round_event/event = E.runEvent()
//event.announceWhen = -1 //So it isn't double announced.
//E.runEvent()
//return ..()
/datum/dynamic_ruleset/event/grid_check
name = "Grid Check"
typepath = /datum/round_event/grid_check
@@ -801,7 +711,7 @@
typepath = /datum/round_event/grey_tide
enemy_roles = list("Chief Engineer","Station Engineer","Captain","Atmospheric Technician","AI","Cyborg")
required_enemies = list(3,2,2,2,2,2,1,1,1,0)
requirements = list(101,101,5,5,5,5,5,5,5,5)
requirements = list(101,101,101,5,5,5,5,5,5,5)
high_population_requirement = 0
repeatable = TRUE
weight = 4
@@ -813,7 +723,8 @@
typepath = /datum/round_event/ghost_role/sentience
requirements = list(101,101,0,0,0,0,0,0,0,0)
high_population_requirement = 0
weight = 1
weight = 5
repeatable_weight_decrease = 1
/datum/dynamic_ruleset/event/shuttle_loan
name = "Shuttle Loan"
@@ -844,8 +755,8 @@
/datum/dynamic_ruleset/event/spontaneous_appendicitis
name = "Spontaneous Appendicitis"
typepath = /datum/round_event/spontaneous_appendicitis
enemy_roles = list("Medical Doctor","Chief Medical Officer")
required_enemies = list(2,2,1,1,1,1,1,1,1,0)
enemy_roles = list("Medical Doctor","Chief Medical Officer","Roboticist")
required_enemies = list(2,2,2,2,2,2,2,1,1,1)
requirements = list(5,5,5,5,5,5,5,5,0,0)
high_population_requirement = 5
weight = 5
@@ -282,8 +282,8 @@
antag_flag = ROLE_LEWD_TRAITOR
antag_datum = /datum/antagonist/traitor/lewd
//minimum_required_age = 7
protected_roles = list("AI","Cyborg")
restricted_roles = list("Cyborg","AI")
protected_roles = list("AI","Cyborg", "Positronic Brain")
restricted_roles = list("Cyborg","AI", "Positronic Brain")
required_candidates = 1
weight = 2
cost = 0
@@ -16,7 +16,7 @@
required_candidates = 1
weight = 5
cost = 10
requirements = list(101,40,30,25,20,20,15,15,15,15)
requirements = list(101,101,30,25,20,20,15,15,15,15)
high_population_requirement = 10
var/autotraitor_cooldown = 450 // 15 minutes (ticks once per 2 sec)
chaos_min = 2.5
@@ -31,9 +31,9 @@
//protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Cyborg")
restricted_roles = list("Cyborg")
//required_candidates = 1
//weight = 5
weight = 5
cost = 0
requirements = list(101,25,25,20,20,15,15,10,10,5)
requirements = list(101,25,25,20,20,15,15,10,10,10)
high_population_requirement = 10
//var/autotraitor_cooldown = 450 // 15 minutes (ticks once per 2 sec)
chaos_min = 2.0
@@ -76,9 +76,9 @@
protected_roles = list("AI","Cyborg")
restricted_roles = list("Cyborg","AI")
required_candidates = 1
weight = 3
weight = 2
cost = 0
requirements = list(101,10,10,10,10,10,10,10,10,10)
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
chaos_min = 0.1
chaos_max = 2.5
@@ -115,17 +115,6 @@
M.mind.restricted_roles = restricted_roles
return TRUE
/*
/datum/dynamic_ruleset/roundstart/traitor/lewd/execute()
var/datum/mind/M = null
if(numTraitors)
for(var/i = 0, i<numTraitors, i++)
M = pick(assigned)
assigned.Remove(M)
M.make_LewdTraitor()
return TRUE
return FALSE
*/
//////////////////////////////////////////
// //
@@ -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
@@ -30,7 +30,6 @@
/obj/item/storage/firstaid/regular/PopulateContents()
if(empty)
return
new /obj/item/stack/medical/plaster_gauze(src)
new /obj/item/stack/medical/gauze(src)
new /obj/item/stack/medical/bruise_pack(src)
new /obj/item/stack/medical/bruise_pack(src)
+1
View File
@@ -107,6 +107,7 @@ GLOBAL_VAR(restart_counter)
GLOB.picture_log_directory = "data/picture_logs/[override_dir]"
GLOB.world_game_log = "[GLOB.log_directory]/game.log"
GLOB.world_virus_log = "[GLOB.log_directory]/virus.log"
GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
@@ -5,25 +5,48 @@ is currently following.
*/
GLOBAL_LIST_INIT(disease_ability_singletons, list(
new /datum/disease_ability/action/cough(),
new /datum/disease_ability/action/sneeze(),
new /datum/disease_ability/action/infect(),
new /datum/disease_ability/symptom/cough(),
new /datum/disease_ability/symptom/sneeze(),\
new /datum/disease_ability/symptom/hallucigen(),
new /datum/disease_ability/symptom/choking(),
new /datum/disease_ability/symptom/confusion(),
new /datum/disease_ability/symptom/youth(),
new /datum/disease_ability/symptom/vomit(),
new /datum/disease_ability/symptom/voice_change(),
new /datum/disease_ability/symptom/visionloss(),
new /datum/disease_ability/symptom/viraladaptation(),
new /datum/disease_ability/symptom/vitiligo(),
new /datum/disease_ability/symptom/sensory_restoration(),
new /datum/disease_ability/symptom/itching(),
new /datum/disease_ability/symptom/weight_loss(),
new /datum/disease_ability/symptom/metabolism_heal(),
new /datum/disease_ability/symptom/coma_heal()
new /datum/disease_ability/action/cough,
new /datum/disease_ability/action/sneeze,
new /datum/disease_ability/action/infect,
new /datum/disease_ability/symptom/mild/cough,
new /datum/disease_ability/symptom/mild/sneeze,
new /datum/disease_ability/symptom/medium/shedding,
new /datum/disease_ability/symptom/medium/beard,
new /datum/disease_ability/symptom/medium/hallucigen,
new /datum/disease_ability/symptom/medium/choking,
new /datum/disease_ability/symptom/medium/confusion,
new /datum/disease_ability/symptom/medium/vomit,
new /datum/disease_ability/symptom/medium/voice_change,
new /datum/disease_ability/symptom/medium/visionloss,
new /datum/disease_ability/symptom/medium/deafness,
new /datum/disease_ability/symptom/powerful/narcolepsy,
new /datum/disease_ability/symptom/medium/fever,
new /datum/disease_ability/symptom/medium/shivering,
new /datum/disease_ability/symptom/medium/headache,
new /datum/disease_ability/symptom/medium/nano_boost,
new /datum/disease_ability/symptom/medium/nano_destroy,
new /datum/disease_ability/symptom/medium/viraladaptation,
new /datum/disease_ability/symptom/medium/viralevolution,
new /datum/disease_ability/symptom/medium/vitiligo,
new /datum/disease_ability/symptom/medium/revitiligo,
new /datum/disease_ability/symptom/medium/itching,
new /datum/disease_ability/symptom/medium/heal/weight_loss,
new /datum/disease_ability/symptom/medium/heal/sensory_restoration,
new /datum/disease_ability/symptom/medium/heal/mind_restoration,
new /datum/disease_ability/symptom/powerful/fire,
new /datum/disease_ability/symptom/powerful/flesh_eating,
// new /datum/disease_ability/symptom/powerful/genetic_mutation,
new /datum/disease_ability/symptom/powerful/inorganic_adaptation,
new /datum/disease_ability/symptom/powerful/heal/starlight,
new /datum/disease_ability/symptom/powerful/heal/oxygen,
new /datum/disease_ability/symptom/powerful/heal/chem,
new /datum/disease_ability/symptom/powerful/heal/metabolism,
new /datum/disease_ability/symptom/powerful/heal/dark,
new /datum/disease_ability/symptom/powerful/heal/water,
new /datum/disease_ability/symptom/powerful/heal/plasma,
new /datum/disease_ability/symptom/powerful/heal/radiation,
new /datum/disease_ability/symptom/powerful/heal/coma,
new /datum/disease_ability/symptom/powerful/youth
))
/datum/disease_ability
@@ -54,7 +77,13 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
stage_speed += initial(S.stage_speed)
transmittable += initial(S.transmittable)
threshold_block += "<br><br>[initial(S.threshold_desc)]"
stat_block = "Resistance: [resistance]<br>Stealth: [stealth]<br>Stage Speed: [stage_speed]<br>Transmissibility: [transmittable]<br><br>"
stat_block = "Resistance: [resistance]<br>Stealth: [stealth]<br>Stage Speed: [stage_speed]<br>Transmissibility: [transmittable]<br><br>"
if(symptoms.len == 1) //lazy boy's dream
name = initial(S.name)
if(short_desc == "")
short_desc = initial(S.desc)
if(long_desc == "")
long_desc = initial(S.desc)
/datum/disease_ability/proc/CanBuy(mob/camera/disease/D)
if(world.time < D.next_adaptation_time)
@@ -77,8 +106,10 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
for(var/T in symptoms)
var/datum/symptom/S = new T()
SD.symptoms += S
S.OnAdd(SD)
if(SD.processing)
S.Start(SD)
if(S.Start(SD))
S.next_activation = world.time + rand(S.symptom_delay_min * 10, S.symptom_delay_max * 10)
SD.Refresh()
for(var/T in actions)
var/datum/action/A = new T()
@@ -105,6 +136,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
var/datum/symptom/S = locate(T) in SD.symptoms
if(S)
SD.symptoms -= S
S.OnRemove(SD)
if(SD.processing)
S.End(SD)
qdel(S)
@@ -152,8 +184,9 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
return FALSE
to_chat(D, "<span class='notice'>You force [L.real_name] to cough.</span>")
L.emote("cough")
var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
SD.spread(2)
if(L.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth
var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
SD.spread(2)
StartCooldown()
return TRUE
@@ -185,11 +218,12 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
return FALSE
to_chat(D, "<span class='notice'>You force [L.real_name] to sneeze.</span>")
L.emote("sneeze")
var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
if(L.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth
var/datum/disease/advance/sentient_disease/SD = D.hosts[L]
for(var/mob/living/M in oview(4, SD.affected_mob))
if(is_A_facing_B(SD.affected_mob, M) && disease_air_spread_walk(get_turf(SD.affected_mob), get_turf(M)))
M.AirborneContractDisease(SD, TRUE)
for(var/mob/living/M in oview(4, SD.affected_mob))
if(is_A_facing_B(SD.affected_mob, M) && disease_air_spread_walk(get_turf(SD.affected_mob), get_turf(M)))
M.AirborneContractDisease(SD, TRUE)
StartCooldown()
return TRUE
@@ -235,143 +269,192 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
StartCooldown()
return TRUE
//passive symptom abilities
/*******************BASE SYMPTOM TYPES*******************/
// cost is for convenience and can be changed. If you're changing req_tot_points then don't use the subtype...
//healing costs more so you have to techswitch from naughty disease otherwise we'd have friendly disease for easy greentext (no fun!)
/datum/disease_ability/symptom/cough
name = "Involuntary Coughing"
symptoms = list(/datum/symptom/cough)
/datum/disease_ability/symptom/mild
cost = 2
required_total_points = 4
category = "Symptom (Weak)"
/datum/disease_ability/symptom/medium
cost = 4
required_total_points = 8
category = "Symptom"
/datum/disease_ability/symptom/medium/heal
cost = 5
category = "Symptom (+)"
/datum/disease_ability/symptom/powerful
cost = 4
required_total_points = 16
category = "Symptom (Strong)"
/datum/disease_ability/symptom/powerful/heal
cost = 8
category = "Symptom (Strong+)"
/******MILD******/
/datum/disease_ability/symptom/mild/cough
name = "Involuntary Coughing"
symptoms = list(/datum/symptom/cough)
short_desc = "Cause victims to cough intermittently."
long_desc = "Cause victims to cough intermittently, spreading your infection if your transmissibility is high."
/datum/disease_ability/symptom/sneeze
/datum/disease_ability/symptom/mild/sneeze
name = "Involuntary Sneezing"
symptoms = list(/datum/symptom/sneeze)
cost = 2
required_total_points = 4
short_desc = "Cause victims to sneeze intermittently."
long_desc = "Cause victims to sneeze intermittently, spreading your infection and also increasing transmissibility and resistance, at the cost of stealth."
/datum/disease_ability/symptom/beard
//I don't think I need to justify the fact that this is the best symptom
name = "Beard Growth"
symptoms = list(/datum/symptom/beard)
cost = 1
required_total_points = 8
short_desc = "Cause all victims to grow a luscious beard."
long_desc = "Cause all victims to grow a luscious beard. Decreases stats slightly. Ineffective against Santa Claus."
/******MEDIUM******/
/datum/disease_ability/symptom/hallucigen
name = "Hallucinations"
/datum/disease_ability/symptom/medium/shedding
symptoms = list(/datum/symptom/shedding)
/datum/disease_ability/symptom/medium/beard
symptoms = list(/datum/symptom/beard)
short_desc = "Cause all victims to grow a luscious beard."
long_desc = "Cause all victims to grow a luscious beard. Ineffective against Santa Claus."
/datum/disease_ability/symptom/medium/hallucigen
symptoms = list(/datum/symptom/hallucigen)
cost = 4
required_total_points = 8
short_desc = "Cause victims to hallucinate."
long_desc = "Cause victims to hallucinate. Decreases stats, especially resistance."
/datum/disease_ability/symptom/choking
name = "Choking"
/datum/disease_ability/symptom/medium/choking
symptoms = list(/datum/symptom/choking)
cost = 4
required_total_points = 8
short_desc = "Cause victims to choke."
long_desc = "Cause victims to choke, threatening asphyxiation. Decreases stats, especially transmissibility."
/datum/disease_ability/symptom/confusion
name = "Confusion"
/datum/disease_ability/symptom/medium/confusion
symptoms = list(/datum/symptom/confusion)
cost = 4
required_total_points = 8
short_desc = "Cause victims to become confused."
long_desc = "Cause victims to become confused intermittently."
/datum/disease_ability/symptom/youth
name = "Eternal Youth"
symptoms = list(/datum/symptom/youth)
cost = 4
required_total_points = 8
short_desc = "Cause victims to become eternally young."
long_desc = "Cause victims to become eternally young. Provides boosts to all stats except transmissibility."
/datum/disease_ability/symptom/vomit
name = "Vomiting"
/datum/disease_ability/symptom/medium/vomit
symptoms = list(/datum/symptom/vomit)
cost = 4
required_total_points = 8
short_desc = "Cause victims to vomit."
long_desc = "Cause victims to vomit. Slightly increases transmissibility. Vomiting also also causes the victims to lose nutrition and removes some toxin damage."
/datum/disease_ability/symptom/voice_change
name = "Voice Changing"
/datum/disease_ability/symptom/medium/voice_change
symptoms = list(/datum/symptom/voice_change)
cost = 4
required_total_points = 8
short_desc = "Change the voice of victims."
long_desc = "Change the voice of victims, causing confusion in communications."
/datum/disease_ability/symptom/visionloss
name = "Vision Loss"
/datum/disease_ability/symptom/medium/visionloss
symptoms = list(/datum/symptom/visionloss)
cost = 4
required_total_points = 8
short_desc = "Damage the eyes of victims, eventually causing blindness."
long_desc = "Damage the eyes of victims, eventually causing blindness. Decreases all stats."
/datum/disease_ability/symptom/viraladaptation
name = "Self-Adaptation"
/datum/disease_ability/symptom/medium/deafness
symptoms = list(/datum/symptom/deafness)
/datum/disease_ability/symptom/medium/fever
symptoms = list(/datum/symptom/fever)
/datum/disease_ability/symptom/medium/shivering
symptoms = list(/datum/symptom/shivering)
/datum/disease_ability/symptom/medium/headache
symptoms = list(/datum/symptom/headache)
/datum/disease_ability/symptom/medium/nano_boost
symptoms = list(/datum/symptom/nano_boost)
/datum/disease_ability/symptom/medium/nano_destroy
symptoms = list(/datum/symptom/nano_destroy)
/datum/disease_ability/symptom/medium/viraladaptation
symptoms = list(/datum/symptom/viraladaptation)
cost = 4
required_total_points = 8
short_desc = "Cause your infection to become more resistant to detection and eradication."
long_desc = "Cause your infection to mimic the function of normal body cells, becoming much harder to spot and to eradicate, but reducing its speed."
/datum/disease_ability/symptom/vitiligo
name = "Skin Paleness"
/datum/disease_ability/symptom/medium/viralevolution
symptoms = list(/datum/symptom/viralevolution)
/datum/disease_ability/symptom/medium/vitiligo
symptoms = list(/datum/symptom/vitiligo)
cost = 1
required_total_points = 8
short_desc = "Cause victims to become pale."
long_desc = "Cause victims to become pale. Decreases all stats."
/datum/disease_ability/symptom/sensory_restoration
name = "Sensory Restoration"
symptoms = list(/datum/symptom/sensory_restoration)
cost = 4
required_total_points = 8
short_desc = "Regenerate eye and ear damage of victims."
long_desc = "Regenerate eye and ear damage of victims."
/datum/disease_ability/symptom/medium/revitiligo
symptoms = list(/datum/symptom/revitiligo)
/datum/disease_ability/symptom/itching
name = "Itching"
/datum/disease_ability/symptom/medium/itching
symptoms = list(/datum/symptom/itching)
cost = 4
required_total_points = 8
short_desc = "Cause victims to itch."
long_desc = "Cause victims to itch, increasing all stats except stealth."
/datum/disease_ability/symptom/weight_loss
name = "Weight Loss"
/datum/disease_ability/symptom/medium/heal/weight_loss
symptoms = list(/datum/symptom/weight_loss)
cost = 4
required_total_points = 8
short_desc = "Cause victims to lose weight."
long_desc = "Cause victims to lose weight, and make it almost impossible for them to gain nutrition from food. Reduced nutrition allows your infection to spread more easily from hosts, especially by sneezing."
/datum/disease_ability/symptom/metabolism_heal
name = "Metabolic Boost"
/datum/disease_ability/symptom/medium/heal/sensory_restoration
symptoms = list(/datum/symptom/sensory_restoration)
short_desc = "Regenerate eye and ear damage of victims."
long_desc = "Regenerate eye and ear damage of victims."
/datum/disease_ability/symptom/medium/heal/mind_restoration
symptoms = list(/datum/symptom/mind_restoration)
/******POWERFUL******/
/datum/disease_ability/symptom/powerful/fire
symptoms = list(/datum/symptom/fire)
/datum/disease_ability/symptom/powerful/flesh_eating
symptoms = list(/datum/symptom/flesh_eating)
/*
/datum/disease_ability/symptom/powerful/genetic_mutation
symptoms = list(/datum/symptom/genetic_mutation)
cost = 8
*/
/datum/disease_ability/symptom/powerful/inorganic_adaptation
symptoms = list(/datum/symptom/inorganic_adaptation)
/datum/disease_ability/symptom/powerful/narcolepsy
symptoms = list(/datum/symptom/narcolepsy)
/datum/disease_ability/symptom/powerful/youth
symptoms = list(/datum/symptom/youth)
short_desc = "Cause victims to become eternally young."
long_desc = "Cause victims to become eternally young. Provides boosts to all stats except transmissibility."
/****HEALING SUBTYPE****/
/datum/disease_ability/symptom/powerful/heal/starlight
symptoms = list(/datum/symptom/heal/starlight)
/datum/disease_ability/symptom/powerful/heal/oxygen
symptoms = list(/datum/symptom/oxygen)
/datum/disease_ability/symptom/powerful/heal/chem
symptoms = list(/datum/symptom/heal/chem)
/datum/disease_ability/symptom/powerful/heal/metabolism
symptoms = list(/datum/symptom/heal/metabolism)
cost = 4
required_total_points = 16
short_desc = "Increase the metabolism of victims, causing them to process chemicals and grow hungry faster."
long_desc = "Increase the metabolism of victims, causing them to process chemicals twice as fast and grow hungry more quickly."
/datum/disease_ability/symptom/coma_heal
name = "Regenerative Coma"
/datum/disease_ability/symptom/powerful/heal/dark
symptoms = list(/datum/symptom/heal/darkness)
/datum/disease_ability/symptom/powerful/heal/water
symptoms = list(/datum/symptom/heal/water)
/datum/disease_ability/symptom/powerful/heal/plasma
symptoms = list(/datum/symptom/heal/plasma)
/datum/disease_ability/symptom/powerful/heal/radiation
symptoms = list(/datum/symptom/heal/radiation)
/datum/disease_ability/symptom/powerful/heal/coma
symptoms = list(/datum/symptom/heal/coma)
cost = 8
required_total_points = 16
short_desc = "Cause victims to fall into a healing coma when hurt."
long_desc = "Cause victims to fall into a healing coma when hurt."
@@ -51,6 +51,7 @@
if(cures.len)
return
var/list/not_used = advance_cures.Copy()
not_used.Cut(1, 6) // Removes the first five tiers of cures.
cures = list(pick(pick_n_take(not_used)), pick(pick_n_take(not_used)))
// Get the cure name from the cure_id
@@ -18,7 +18,7 @@ the new instance inside the host to be updated to the template's stats.
layer = BELOW_MOB_LAYER
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
sight = SEE_SELF|SEE_THRU
initial_language_holder = /datum/language_holder/empty
initial_language_holder = /datum/language_holder/universal
var/freemove = TRUE
var/freemove_end = 0
@@ -43,7 +43,7 @@ the new instance inside the host to be updated to the template's stats.
var/move_delay = 1
var/next_adaptation_time = 0
var/adaptation_cooldown = 1200
var/adaptation_cooldown = 600
var/list/purchased_abilities
var/list/unpurchased_abilities
@@ -118,10 +118,28 @@ the new instance inside the host to be updated to the template's stats.
follow_next(Dir & NORTHWEST)
last_move_tick = world.time
/mob/camera/disease/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
. = ..()
var/atom/movable/to_follow = speaker
if(radio_freq)
var/atom/movable/virtualspeaker/V = speaker
to_follow = V.source
var/link
if(to_follow in hosts)
link = FOLLOW_LINK(src, to_follow)
else
link = ""
// Recompose the message, because it's scrambled by default
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
to_chat(src, "[link] [message]")
/mob/camera/disease/mind_initialize()
. = ..()
if(!mind.has_antag_datum(/datum/antagonist/disease))
mind.add_antag_datum(/datum/antagonist/disease)
var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
medsensor.add_hud_to(src)
/mob/camera/disease/proc/pick_name()
var/static/list/taken_names
@@ -247,9 +265,12 @@ the new instance inside the host to be updated to the template's stats.
if(!move_listener)
move_listener = L.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/follow_mob)))
else
L.TakeComponent(move_listener)
if(QDELING(move_listener))
move_listener = null
if(L)
L.TakeComponent(move_listener)
if(QDELING(move_listener))
move_listener = null
else
QDEL_NULL(move_listener)
follow_mob()
/mob/camera/disease/proc/follow_next(reverse = FALSE)
+1 -1
View File
@@ -1103,7 +1103,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
#undef APPEARANCE_CATEGORY_COLUMN
#undef MAX_MUTANT_ROWS
/datum/preferences/proc/SetChoices(mob/user, limit = 17, list/splitJobs = list("Chief Engineer"), widthPerColumn = 295, height = 620)
/datum/preferences/proc/SetChoices(mob/user, limit = 22, list/splitJobs = list("Chief Engineer"), widthPerColumn = 295, height = 620)
if(!SSjob)
return
+1 -1
View File
@@ -8,7 +8,7 @@
/datum/round_event/heart_attack/start()
var/list/heart_attack_contestants = list()
for(var/mob/living/carbon/human/H in shuffle(GLOB.player_list))
if(!H.client || H.stat == DEAD || H.InCritical() || !H.can_heartattack() || H.has_status_effect(STATUS_EFFECT_EXERCISED) || (/datum/disease/heart_failure in H.diseases) || H.undergoing_cardiac_arrest())
if(!H.client || H.z != SSmapping.station_start || H.stat == DEAD || H.InCritical() || !H.can_heartattack() || H.has_status_effect(STATUS_EFFECT_EXERCISED) || (/datum/disease/heart_failure in H.diseases) || H.undergoing_cardiac_arrest())
continue
if(H.satiety <= -60) //Multiple junk food items recently
heart_attack_contestants[H] = 3
+3 -3
View File
@@ -12,8 +12,8 @@ Captain
supervisors = "Kinaris officials and Space law"
selection_color = "#ccccff"
req_admin_notify = 1
minimal_player_age = 20
exp_requirements = 480
minimal_player_age = 30
exp_requirements = 3000
exp_type = EXP_TYPE_COMMAND
exp_type_department = EXP_TYPE_COMMAND
@@ -84,7 +84,7 @@ Head of Personnel
selection_color = "#ddddff"
req_admin_notify = 1
minimal_player_age = 20
exp_requirements = 180
exp_requirements = 1500
exp_type = EXP_TYPE_SERVICE
exp_type_department = EXP_TYPE_SERVICE
+9 -5
View File
@@ -12,15 +12,15 @@ Quartermaster is a real head fuck you
spawn_positions = 1
supervisors = "the captain"
selection_color = "#d7b088"
minimal_player_age = 10
minimal_player_age = 7
exp_type = EXP_TYPE_SUPPLY
exp_type_department = EXP_TYPE_SUPPLY
exp_requirements = 300
exp_requirements = 1200
outfit = /datum/outfit/job/quartermaster
access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_VAULT)
minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_VAULT)
access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_KEYCARD_AUTH, ACCESS_RC_ANNOUNCE, ACCESS_SEC_DOORS, ACCESS_HEADS, ACCESS_VAULT)
minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_KEYCARD_AUTH, ACCESS_RC_ANNOUNCE, ACCESS_SEC_DOORS, ACCESS_HEADS, ACCESS_VAULT)
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/insanity)
@@ -35,6 +35,10 @@ Quartermaster is a real head fuck you
glasses = /obj/item/clothing/glasses/sunglasses
l_hand = /obj/item/clipboard
id = /obj/item/card/id/silver
ears = /obj/item/radio/headset/heads/qm
backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced = 1)
chameleon_extras = /obj/item/stamp/qm
/*
@@ -81,7 +85,7 @@ Shaft Miner
selection_color = "#dcba97"
custom_spawn_text = "Remember, you are a miner, not a hunter. Hunting monsters is not a requirement of your job, the only requirement of your job is to provide materials for the station. Don't be afraid to run away if you're inexperienced with fighting the mining area's locals."
minimal_player_age = 1
exp_requirements = 120
exp_requirements = 600
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_SUPPLY
+73 -8
View File
@@ -13,8 +13,8 @@ Chief Engineer
supervisors = "the captain"
selection_color = "#ffeeaa"
req_admin_notify = 1
minimal_player_age = 20
exp_requirements = 300
minimal_player_age = 14
exp_requirements = 1500
exp_type = EXP_TYPE_ENGINEERING
exp_type_department = EXP_TYPE_ENGINEERING
@@ -79,8 +79,9 @@ Station Engineer
minimal_player_age = 1
supervisors = "the chief engineer"
selection_color = "#fff5cc"
exp_requirements = 120
exp_type = EXP_TYPE_CREW
exp_requirements = 300
exp_type = EXP_TYPE_ENGINEERING
exp_type_department = EXP_TYPE_ENGINEERING
outfit = /datum/outfit/job/engineer
@@ -136,14 +137,16 @@ Atmospheric Technician
minimal_player_age = 2
supervisors = "the chief engineer"
selection_color = "#fff5cc"
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_requirements = 600
exp_type = EXP_TYPE_ENGINEERING
exp_type_department = EXP_TYPE_ENGINEERING
outfit = /datum/outfit/job/atmos
access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS, ACCESS_EMERGENCY_STORAGE, ACCESS_CONSTRUCTION, ACCESS_MINERAL_STOREROOM)
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS,
ACCESS_EMERGENCY_STORAGE, ACCESS_CONSTRUCTION, ACCESS_MINERAL_STOREROOM)
/datum/outfit/job/atmos
name = "Atmospheric Technician"
@@ -169,3 +172,65 @@ Atmospheric Technician
suit = /obj/item/clothing/suit/space/hardsuit/engine/atmos
suit_store = /obj/item/tank/internals/oxygen
internals_slot = SLOT_S_STORE
/*
Junior Engineer
*/
/datum/job/junior_engineer
title = "Engineering Intern"
flag = JR_ENGINEER
department_head = list("Chief Engineer")
department_flag = ENGSEC
faction = "Station"
total_positions = 2
spawn_positions = 2
minimal_player_age = 0
supervisors = "the chief engineer, and any other more experienced engineers"
selection_color = "#fff5cc"
exp_requirements = 120
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/engineer/junior
access = list(ACCESS_TECH_STORAGE, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_MAINT_TUNNELS,
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_TECH_STORAGE, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_MAINT_TUNNELS,
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM)
/datum/outfit/job/engineer/junior
name = "Engineering Intern"
jobtype = /datum/job/junior_engineer
belt = /obj/item/storage/belt/utility/full/engi
l_pocket = /obj/item/pda/engineering
ears = /obj/item/radio/headset/headset_eng
uniform = /obj/item/clothing/under/rank/engineer
shoes = /obj/item/clothing/shoes/workboots
head = /obj/item/clothing/head/hardhat
r_pocket = /obj/item/t_scanner
backpack = /obj/item/storage/backpack/industrial
satchel = /obj/item/storage/backpack/satchel/eng
duffelbag = /obj/item/storage/backpack/duffelbag/engineering
box = /obj/item/storage/box/engineer
pda_slot = SLOT_L_STORE
backpack_contents = list(/obj/item/modular_computer/tablet/preset/advanced=1)
/datum/outfit/job/engineer/junior/gloved/
name = "Station Engineer (Gloves)"
gloves = /obj/item/clothing/gloves/color/yellow
/datum/outfit/job/engineer/junior/gloved/rig/junior
name = "Station Engineer (Hardsuit)"
mask = /obj/item/clothing/mask/breath
suit = /obj/item/clothing/suit/space/hardsuit/engine
suit_store = /obj/item/tank/internals/oxygen
head = null
internals_slot = SLOT_S_STORE
/datum/job/junior_engineer/after_spawn(mob/living/carbon/human/H, mob/M) //Instead of going through the process of adding spawnpoints
var/turf/T
var/spawn_point = locate(/obj/effect/landmark/start/station_engineer) in GLOB.start_landmarks_list
T = get_turf(spawn_point)
H.Move(T)
+1
View File
@@ -45,6 +45,7 @@
var/outfit = null
//Minutes required in specified job or department type.
var/exp_requirements = 0
var/exp_type = ""
+11 -1
View File
@@ -1,3 +1,5 @@
//This file also determines the order for the choose your occupation chances screen.
//Engineering
/datum/job/chief_engineer
alt_titles = list("Head Engineer", "Construction Coordinator", "Project Manager")
@@ -8,6 +10,8 @@
/datum/job/atmos
alt_titles = list("Firefighter", "Life Support Specialist")
/datum/job/junior_engineer
//Service
/datum/job/assistant
alt_titles = list("Civilian", "Visitor", "Businessman", "Trader", "Entertainer", "Tourist")
@@ -49,12 +53,14 @@
/datum/job/roboticist
alt_titles = list("Biomechanical Engineer", "Mechatronic Engineer", "Mechanic")
/datum/job/junior_scientist
//Medical
/datum/job/cmo
alt_titles = list("Medical Director")
/datum/job/doctor
alt_titles = list("Nurse", "Surgeon", "Physician")
alt_titles = list("Nurse", "Surgeon", "Physician", "Paramedic")
/datum/job/chemist
alt_titles = list("Pharmacist", "Pharmacologist")
@@ -65,6 +71,8 @@
/datum/job/geneticist
alt_titles = list("Gene Therapist")
/datum/job/junior_doctor
//Security
/datum/job/hos
alt_titles = list("Chief of Security", "Security Commander")
@@ -78,6 +86,8 @@
/datum/job/detective
alt_titles = list("Forensics Technician", "Private Investigator", "Gumshoe")
/datum/job/junior_officer
//Supply
/datum/job/qm
alt_titles = list("Supply Chief")
+63 -8
View File
@@ -13,8 +13,8 @@ Chief Medical Officer
supervisors = "the captain"
selection_color = "#ffddf0"
req_admin_notify = 1
minimal_player_age = 10
exp_requirements = 300
minimal_player_age = 14
exp_requirements = 1500
exp_type = EXP_TYPE_MEDICAL
exp_type_department = EXP_TYPE_MEDICAL
@@ -94,6 +94,8 @@ Medical Doctor
satchel = /obj/item/storage/backpack/satchel/med
duffelbag = /obj/item/storage/backpack/duffelbag/med
backpack_contents = list(/obj/item/storage/hypospraykit/regular)
chameleon_extras = /obj/item/gun/syringe
/*
@@ -110,8 +112,10 @@ Chemist
minimal_player_age = 1
supervisors = "the chief medical officer"
selection_color = "#ffeef0"
exp_type = EXP_TYPE_CREW
exp_requirements = 60
exp_requirements = 480
exp_type = EXP_TYPE_MEDICAL
exp_type_department = EXP_TYPE_MEDICAL
outfit = /datum/outfit/job/chemist
@@ -133,6 +137,8 @@ Chemist
duffelbag = /obj/item/storage/backpack/duffelbag/med
l_hand = /obj/item/fermichem/pHbooklet
backpack_contents = list(/obj/item/storage/hypospraykit/regular)
chameleon_extras = /obj/item/gun/syringe
/*
@@ -148,8 +154,9 @@ Geneticist
spawn_positions = 2
supervisors = "the chief medical officer and research director"
selection_color = "#ffeef0"
exp_type = EXP_TYPE_CREW
exp_requirements = 30
exp_requirements = 480
exp_type = EXP_TYPE_MEDICAL
exp_type_department = EXP_TYPE_MEDICAL
outfit = /datum/outfit/job/geneticist
@@ -186,8 +193,9 @@ Virologist
minimal_player_age = 2
supervisors = "the chief medical officer"
selection_color = "#ffeef0"
exp_type = EXP_TYPE_CREW
exp_requirements = 120
exp_requirements = 600
exp_type = EXP_TYPE_MEDICAL
exp_type_department = EXP_TYPE_MEDICAL
outfit = /datum/outfit/job/virologist
@@ -209,3 +217,50 @@ Virologist
backpack = /obj/item/storage/backpack/virology
satchel = /obj/item/storage/backpack/satchel/vir
duffelbag = /obj/item/storage/backpack/duffelbag/med
/*
Junior Doctor
*/
/datum/job/junior_doctor
title = "Medical Resident"
flag = JR_DOCTOR
department_head = list("Chief Medical Officer")
department_flag = MEDSCI
faction = "Station"
total_positions = 2
spawn_positions = 2
minimal_player_age = 0
supervisors = "the chief medical officer, and any other senior medical staff"
selection_color = "#ffeef0"
exp_requirements = 120
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/doctor/junior
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
/datum/outfit/job/doctor/junior
name = "Medical Resident"
jobtype = /datum/job/junior_doctor
belt = /obj/item/pda/medical
ears = /obj/item/radio/headset/headset_med
uniform = /obj/item/clothing/under/rank/medical
shoes = /obj/item/clothing/shoes/sneakers/white
suit = /obj/item/clothing/suit/toggle/labcoat
l_hand = /obj/item/storage/firstaid/regular
suit_store = /obj/item/flashlight/pen
backpack = /obj/item/storage/backpack/medic
satchel = /obj/item/storage/backpack/satchel/med
duffelbag = /obj/item/storage/backpack/duffelbag/med
chameleon_extras = /obj/item/gun/syringe
/datum/job/junior_doctor/after_spawn(mob/living/carbon/human/H, mob/M) //Instead of going through the process of adding spawnpoints
var/turf/T
var/spawn_point = locate(/obj/effect/landmark/start/medical_doctor) in GLOB.start_landmarks_list
T = get_turf(spawn_point)
H.Move(T)
+54 -8
View File
@@ -13,10 +13,10 @@ Research Director
supervisors = "the captain"
selection_color = "#ffddff"
req_admin_notify = 1
minimal_player_age = 10
exp_type_department = EXP_TYPE_SCIENCE
exp_requirements = 300
minimal_player_age = 14
exp_requirements = 1500
exp_type = EXP_TYPE_SCIENCE
exp_type_department = EXP_TYPE_SCIENCE
outfit = /datum/outfit/job/rd
@@ -71,12 +71,13 @@ Scientist
department_flag = MEDSCI
faction = "Station"
total_positions = 5
spawn_positions = 3
spawn_positions = 2
minimal_player_age = 1
supervisors = "the research director"
selection_color = "#ffeeff"
exp_requirements = 120
exp_type = EXP_TYPE_CREW
exp_requirements = 480
exp_type = EXP_TYPE_SCIENCE
exp_type_department = EXP_TYPE_SCIENCE
outfit = /datum/outfit/job/scientist
@@ -111,8 +112,10 @@ Roboticist
minimal_player_age = 2
supervisors = "the research director"
selection_color = "#ffeeff"
exp_requirements = 120
exp_type = EXP_TYPE_CREW
exp_requirements = 300
exp_type = EXP_TYPE_SCIENCE
exp_type_department = EXP_TYPE_SCIENCE
outfit = /datum/outfit/job/roboticist
@@ -133,3 +136,46 @@ Roboticist
satchel = /obj/item/storage/backpack/satchel/tox
pda_slot = SLOT_L_STORE
/*
Junior Scientist
*/
/datum/job/junior_scientist
title = "Research Student"
flag = JR_SCIENTIST
department_head = list("Research Director")
department_flag = MEDSCI
faction = "Station"
total_positions = 2
spawn_positions = 1
minimal_player_age = 0
supervisors = "the research director, and any other senior science staff"
selection_color = "#ffeeff"
exp_requirements = 120
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/scientist/junior
access = list(ACCESS_ROBOTICS, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE, ACCESS_GENETICS)
minimal_access = list(ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM)
/datum/outfit/job/scientist/junior
name = "Scientist"
jobtype = /datum/job/scientist
belt = /obj/item/pda/toxins
ears = /obj/item/radio/headset/headset_sci
uniform = /obj/item/clothing/under/rank/scientist
shoes = /obj/item/clothing/shoes/sneakers/white
suit = /obj/item/clothing/suit/toggle/labcoat/science
backpack = /obj/item/storage/backpack/science
satchel = /obj/item/storage/backpack/satchel/tox
/datum/job/junior_scientist/after_spawn(mob/living/carbon/human/H, mob/M) //Instead of going through the process of adding spawnpoints
var/turf/T
var/spawn_point = locate(/obj/effect/landmark/start/scientist) in GLOB.start_landmarks_list
T = get_turf(spawn_point)
H.Move(T)
+153 -10
View File
@@ -20,7 +20,7 @@ Head of Security
selection_color = "#ffdddd"
req_admin_notify = 1
minimal_player_age = 20
exp_requirements = 420
exp_requirements = 2000
exp_type = EXP_TYPE_SECURITY
exp_type_department = EXP_TYPE_SECURITY
@@ -87,9 +87,10 @@ Warden
spawn_positions = 1
supervisors = "the head of security"
selection_color = "#ffeeee"
minimal_player_age = 3
exp_requirements = 360
exp_type = EXP_TYPE_CREW
minimal_player_age = 9
exp_requirements = 720
exp_type = EXP_TYPE_SECURITY
exp_type_department = EXP_TYPE_SECURITY
outfit = /datum/outfit/job/warden
@@ -118,7 +119,9 @@ Warden
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
r_pocket = /obj/item/assembly/flash/handheld
l_pocket = /obj/item/restraints/handcuffs
suit_store = /obj/item/gun/energy/e_gun/advtaser
//suit_store = /obj/item/gun/energy/e_gun/advtaser
suit_store = /obj/item/gun/energy/pumpaction/defender
backpack_contents = list(/obj/item/melee/baton/loaded=1)
backpack = /obj/item/storage/backpack/security
@@ -143,9 +146,10 @@ Detective
spawn_positions = 1
supervisors = "the head of security"
selection_color = "#ffeeee"
minimal_player_age = 2
minimal_player_age = 5
exp_requirements = 300
exp_type = EXP_TYPE_CREW
exp_type = EXP_TYPE_SECURITY
exp_type_department = EXP_TYPE_SECURITY
outfit = /datum/outfit/job/detective
@@ -199,9 +203,10 @@ Security Officer
spawn_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions()
supervisors = "the head of security, and the head of your assigned department (if applicable)"
selection_color = "#ffeeee"
minimal_player_age = 1
exp_requirements = 300
exp_type = EXP_TYPE_CREW
minimal_player_age = 5
exp_requirements = 420
exp_type = EXP_TYPE_SECURITY
exp_type_department = EXP_TYPE_SECURITY
outfit = /datum/outfit/job/security
@@ -344,3 +349,141 @@ GLOBAL_LIST_INIT(available_depts, list(SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, S
/obj/item/radio/headset/headset_sec/alt/department/sci
keyslot = new /obj/item/encryptionkey/headset_sec
keyslot2 = new /obj/item/encryptionkey/headset_sci
/*
Junior Security Officer
*/
/datum/job/junior_officer
title = "Rookie"
flag = JR_OFFICER
department_head = list("Head of Security")
department_flag = ENGSEC
faction = "Station"
total_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions()
spawn_positions = 5 //Handled in /datum/controller/occupations/proc/setup_officer_positions()
supervisors = "the head of security, and the head of your assigned department (if applicable), and any other senior officer"
selection_color = "#ffeeee"
minimal_player_age = 3
exp_requirements = 300
exp_type = EXP_TYPE_CREW
outfit = /datum/outfit/job/security/junior
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_FORENSICS_LOCKERS, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_MINERAL_STOREROOM) //BUT SEE /DATUM/JOB/WARDEN/GET_ACCESS()
mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM)
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic)
/datum/job/junior_officer/get_access()
var/list/L = list()
L |= ..() | check_config_for_sec_maint()
return L
/datum/job/junior_officer/after_spawn(mob/living/carbon/human/H, mob/M)
// Assign department security
var/department
if(M && M.client && M.client.prefs)
department = M.client.prefs.prefered_security_department
if(!LAZYLEN(GLOB.available_depts) || department == "None")
return
else if(department in GLOB.available_depts)
LAZYREMOVE(GLOB.available_depts, department)
else
department = pick_n_take(GLOB.available_depts)
var/ears = null
var/accessory = null
var/list/dep_access = null
var/destination = null
var/spawn_point = locate(/obj/effect/landmark/start/security_officer) in GLOB.start_landmarks_list
switch(department)
if(SEC_DEPT_SUPPLY)
ears = /obj/item/radio/headset/headset_sec/alt/department/supply
dep_access = list(ACCESS_MAILSORTING, ACCESS_MINING, ACCESS_MINING_STATION)
destination = /area/security/checkpoint/supply
spawn_point = locate(/obj/effect/landmark/start/depsec/supply) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/cargo
if(SEC_DEPT_ENGINEERING)
ears = /obj/item/radio/headset/headset_sec/alt/department/engi
dep_access = list(ACCESS_CONSTRUCTION, ACCESS_ENGINE)
destination = /area/security/checkpoint/engineering
spawn_point = locate(/obj/effect/landmark/start/depsec/engineering) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/engine
if(SEC_DEPT_MEDICAL)
ears = /obj/item/radio/headset/headset_sec/alt/department/med
dep_access = list(ACCESS_MEDICAL)
destination = /area/security/checkpoint/medical
spawn_point = locate(/obj/effect/landmark/start/depsec/medical) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/medblue
if(SEC_DEPT_SCIENCE)
ears = /obj/item/radio/headset/headset_sec/alt/department/sci
dep_access = list(ACCESS_RESEARCH)
destination = /area/security/checkpoint/science
spawn_point = locate(/obj/effect/landmark/start/depsec/science) in GLOB.department_security_spawns
accessory = /obj/item/clothing/accessory/armband/science
if(accessory)
var/obj/item/clothing/under/U = H.w_uniform
U.attach_accessory(new accessory)
if(ears)
if(H.ears)
qdel(H.ears)
H.equip_to_slot_or_del(new ears(H),SLOT_EARS)
var/obj/item/card/id/W = H.wear_id
W.access |= dep_access
var/teleport = 0
if(!CONFIG_GET(flag/sec_start_brig))
if(destination || spawn_point)
teleport = 1
if(teleport)
var/turf/T
if(spawn_point)
T = get_turf(spawn_point)
H.Move(T)
else
var/safety = 0
while(safety < 25)
T = safepick(get_area_turfs(destination))
if(T && !H.Move(T))
safety += 1
continue
else
break
if(department)
to_chat(M, "<b>You have been assigned to [department]!</b>")
else
to_chat(M, "<b>You have not been assigned to any department. Patrol the halls and help where needed.</b>")
/datum/outfit/job/security/junior
name = "Security Officer"
jobtype = /datum/job/officer
belt = /obj/item/pda/security
ears = /obj/item/radio/headset/headset_sec/alt
uniform = /obj/item/clothing/under/rank/security
gloves = /obj/item/clothing/gloves/color/black
head = /obj/item/clothing/head/helmet/sec
suit = /obj/item/clothing/suit/armor/vest/alt
shoes = /obj/item/clothing/shoes/jackboots
l_pocket = /obj/item/restraints/handcuffs
r_pocket = /obj/item/assembly/flash/handheld
suit_store = /obj/item/gun/energy/e_gun/advtaser
backpack_contents = list(/obj/item/melee/baton/loaded=1)
backpack = /obj/item/storage/backpack/security
satchel = /obj/item/storage/backpack/satchel/sec
duffelbag = /obj/item/storage/backpack/duffelbag/sec
box = /obj/item/storage/box/security
implants = list(/obj/item/implant/mindshield)
chameleon_extras = list(/obj/item/gun/energy/e_gun/advtaser, /obj/item/clothing/glasses/hud/security/sunglasses, /obj/item/clothing/head/helmet)
//The helmet is necessary because /obj/item/clothing/head/helmet/sec is overwritten in the chameleon list by the standard helmet, which has the same name and icon state
+7 -7
View File
@@ -11,10 +11,10 @@ AI
selection_color = "#ccffcc"
supervisors = "your laws"
req_admin_notify = TRUE
minimal_player_age = 5
exp_requirements = 1200
exp_type = EXP_TYPE_CREW
// exp_type_department = EXP_TYPE_SILICON
minimal_player_age = 14
exp_requirements = 1800
//exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_SILICON
var/do_special_check = TRUE
/datum/job/ai/equip(mob/living/carbon/human/H, visualsOnly, announce, latejoin, outfit_override)
@@ -78,9 +78,9 @@ Cyborg
spawn_positions = 1
supervisors = "your laws and the AI" //Nodrak
selection_color = "#ddffdd"
// minimal_player_age = 0
// exp_requirements = 120
// exp_type = EXP_TYPE_CREW
minimal_player_age = 0
exp_requirements = 300
exp_type = EXP_TYPE_CREW
/datum/job/cyborg/equip(mob/living/carbon/human/H, visualsOnly = FALSE, announce = TRUE, latejoin = FALSE, outfit_override = null)
return H.Robotize(FALSE, latejoin)
+8 -4
View File
@@ -10,7 +10,8 @@ GLOBAL_LIST_INIT(command_positions, list(
GLOBAL_LIST_INIT(engineering_positions, list(
"Chief Engineer",
"Station Engineer",
"Atmospheric Technician"))
"Atmospheric Technician",
"Engineering Intern"))
GLOBAL_LIST_INIT(medical_positions, list(
@@ -18,13 +19,15 @@ GLOBAL_LIST_INIT(medical_positions, list(
"Medical Doctor",
"Geneticist",
"Virologist",
"Chemist"))
"Chemist",
"Medical Resident"))
GLOBAL_LIST_INIT(science_positions, list(
"Research Director",
"Scientist",
"Roboticist"))
"Roboticist",
"Research Student"))
GLOBAL_LIST_INIT(supply_positions, list(
"Quartermaster",
@@ -48,7 +51,8 @@ GLOBAL_LIST_INIT(security_positions, list(
"Head of Security",
"Warden",
"Detective",
"Security Officer"))
"Security Officer",
"Rookie"))
GLOBAL_LIST_INIT(nonhuman_positions, list(
+1 -1
View File
@@ -4,4 +4,4 @@
resist()
return
return ..()
return ..()
+3
View File
@@ -31,5 +31,8 @@
loc = destination
Moved(oldloc, NONE, TRUE)
/mob/camera/canUseStorage()
return FALSE
/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE)
return
+3
View File
@@ -21,6 +21,9 @@ INITIALIZE_IMMEDIATE(/mob/dead)
set_focus(src)
return INITIALIZE_HINT_NORMAL
/mob/dead/canUseStorage()
return FALSE
/mob/dead/dust(just_ash, drop_items, force) //ghosts can't be vaporised.
return
@@ -85,6 +85,9 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/icon_limbs //Overrides the icon used for the limbs of this species. Mainly for downstream, and also because hardcoded icons disgust me. Implemented and maintained as a favor in return for a downstream's implementation of synths.
/// Our default override for typing indicator state
var/typing_indicator_state
///////////
// PROCS //
///////////
@@ -0,0 +1,2 @@
/mob/living/carbon/human/get_typing_indicator_icon_state()
return dna?.species?.typing_indicator_state || ..()
+5
View File
@@ -373,6 +373,11 @@
if(stat || IsUnconscious() || IsStun() || IsKnockdown() || recoveringstam || (!ignore_restraints && restrained(ignore_grab))) // CIT CHANGE - adds recoveringstam check here
return TRUE
/mob/living/canUseStorage()
if (get_num_arms() <= 0)
return FALSE
return TRUE
/mob/living/proc/InCritical()
return (health <= crit_threshold && (stat == SOFT_CRIT || stat == UNCONSCIOUS))
@@ -5,6 +5,8 @@
hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD,NANITE_HUD,DIAG_NANITE_FULL_HUD)
pressure_resistance = 10
typing_indicator_enabled = TRUE
var/resize = 1 //Badminnery resize
var/lastattacker = null
var/lastattackerckey = null
@@ -1,6 +1,8 @@
/mob/living/Moved()
. = ..()
update_turf_movespeed(loc)
//Hide typing indicator if we move.
clear_typing_indicator()
if(is_shifted)
is_shifted = FALSE
pixel_x = get_standard_pixel_x_offset(lying)
+2 -1
View File
@@ -8,7 +8,8 @@
/mob/living/silicon/proc/post_lawchange(announce = TRUE)
throw_alert("newlaw", /obj/screen/alert/newlaw)
if(announce && last_lawchange_announce != world.time)
to_chat(src, "<b>Your laws have been changed.</b>")
to_chat(src, "<span class='big bold'><font color = red>Your laws have been changed.</font color></span>")
SEND_SOUND(src, 'hyperstation/sound/misc/ai_laws_update.ogg')
addtimer(CALLBACK(src, .proc/show_laws), 0)
last_lawchange_announce = world.time
+3
View File
@@ -830,6 +830,9 @@
/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
return
/mob/proc/canUseStorage()
return FALSE
/mob/proc/faction_check_mob(mob/target, exact_match)
if(exact_match) //if we need an exact match, we need to do some bullfuckery.
var/list/faction_src = faction.Copy()
+14 -1
View File
@@ -126,4 +126,17 @@
///Whether the mob is updating glide size when movespeed updates or not
var/updating_glide_size = TRUE
var/updating_glide_size = TRUE
var/flavor_text = ""
var/flavor_text_2 = "" //version of the above that only lasts for the current round.
///////TYPING INDICATORS///////
/// Set to true if we want to show typing indicators.
var/typing_indicator_enabled = FALSE
/// Default icon_state of our typing indicator. Currently only supports paths (because anything else is, as of time of typing this, unnecesary.
var/typing_indicator_state = /obj/effect/overlay/typing_indicator
/// The timer that will remove our indicator for early aborts (like when an user finishes their message)
var/typing_indicator_timerid
/// Current state of our typing indicator. Used for cut overlay, DO NOT RUNTIME ASSIGN OTHER THAN FROM SHOW/CLEAR. Used to absolutely ensure we do not get stuck overlays.
var/mutable_appearance/typing_indicator_current
+47 -16
View File
@@ -1,17 +1,60 @@
//Speech verbs.
/mob/verb/say_verb(message as text)
set name = "Say"
// the _keybind verbs uses "as text" versus "as text|null" to force a popup when pressed by a keybind.
/mob/verb/say_typing_indicator()
set name = "say_indicator"
set hidden = TRUE
set category = "IC"
display_typing_indicator()
var/message = input(usr, "", "say") as text|null
// If they don't type anything just drop the message.
clear_typing_indicator() // clear it immediately!
if(!length(message))
return
return say_verb(message)
/mob/verb/say_verb(message as text)
set name = "say"
set category = "IC"
if(!length(message))
return
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
if(message)
say(message)
clear_typing_indicator() // clear it immediately!
say(message)
/mob/verb/me_typing_indicator()
set name = "me_indicator"
set hidden = TRUE
set category = "IC"
display_typing_indicator()
var/message = input(usr, "", "me") as message|null
// If they don't type anything just drop the message.
clear_typing_indicator() // clear it immediately!
if(!length(message))
return
return me_verb(message)
/mob/verb/me_verb(message as message)
set name = "me"
set category = "IC"
if(!length(message))
return
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
clear_typing_indicator() // clear it immediately!
usr.emote("me",1,message,TRUE)
/mob/verb/whisper_verb(message as text)
set name = "Whisper"
set category = "IC"
if(!length(message))
return
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
@@ -20,18 +63,6 @@
/mob/proc/whisper(message, datum/language/language=null)
say(message, language) //only living mobs actually whisper, everything else just talks
/mob/verb/me_verb(message as message)
set name = "Me"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
usr.emote("me",1,message,TRUE)
/mob/proc/say_dead(var/message)
var/name = real_name
var/alt_name = ""
-3
View File
@@ -1,8 +1,6 @@
//////////////////////////////////////////////////////
////////////////////SUBTLE COMMAND////////////////////
//////////////////////////////////////////////////////
/mob
var/flavor_text = "" //tired of fucking double checking this
/mob/proc/update_flavor_text()
set src in usr
@@ -54,7 +52,6 @@ proc/get_top_level_mob(var/mob/S)
message = null
mob_type_blacklist_typecache = list(/mob/living/brain)
/datum/emote/living/subtle/proc/check_invalid(mob/user, input)
. = TRUE
if(copytext(input,1,5) == "says")
+56
View File
@@ -0,0 +1,56 @@
/// state = overlay/image/object/type/whatever add_overlay will accept
GLOBAL_LIST_EMPTY(typing_indicator_overlays)
/// Fetches the typing indicator we'll use from GLOB.typing_indicator_overlays
/mob/proc/get_indicator_overlay(state)
. = GLOB.typing_indicator_overlays[state]
if(.)
return
// doesn't exist, make it and cache it
if(ispath(state))
. = GLOB.typing_indicator_overlays[state] = state
// We only support paths for now because anything else isn't necessary yet.
/// Gets the state we will use for typing indicators. Defaults to src.typing_indicator_state
/mob/proc/get_typing_indicator_icon_state()
return typing_indicator_state
/// Generates the mutable appearance for typing indicator. Should prevent stuck overlays.
/mob/proc/generate_typing_indicator()
var/state = get_typing_indicator_icon_state()
if(ispath(state))
var/atom/thing = new state(null)
var/mutable_appearance/generated = new(thing)
return generated
else
CRASH("Unsupported typing indicator state: [state]")
/**
* Displays typing indicator.
* @param timeout_override - Sets how long until this will disappear on its own without the user finishing their message or logging out. Defaults to src.typing_indicator_timeout
* @param state_override - Sets the state that we will fetch. Defaults to src.get_typing_indicator_icon_state()
* @param force - shows even if src.typing_indcator_enabled is FALSE.
*/
/mob/proc/display_typing_indicator(timeout_override = TYPING_INDICATOR_TIMEOUT, state_override = generate_typing_indicator(), force = FALSE)
if((!typing_indicator_enabled && !force) || typing_indicator_current)
return
typing_indicator_current = state_override
add_overlay(state_override)
typing_indicator_timerid = addtimer(CALLBACK(src, .proc/clear_typing_indicator), timeout_override, TIMER_STOPPABLE)
/**
* Removes typing indicator.
*/
/mob/proc/clear_typing_indicator()
cut_overlay(typing_indicator_current)
typing_indicator_current = null
if(typing_indicator_timerid)
deltimer(typing_indicator_timerid)
typing_indicator_timerid = null
/// Default typing indicator
/obj/effect/overlay/typing_indicator
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
icon = 'icons/mob/talk.dmi'
icon_state = "normal_typing"
appearance_flags = RESET_COLOR | TILE_BOUND | PIXEL_SCALE
layer = ABOVE_FLY_LAYER
@@ -76,3 +76,26 @@
if(S.emptrig == TRUE)
var/obj/item/projectile/bullet/dart/syringe/dart/D = BB
D.emptrig = TRUE
//Chemlight was here, adding dumb bussing things
/obj/item/ammo_casing/chemgun_debug
name = "dart synthesiser"
desc = "A high-power spring, linked to an energy-based dart synthesiser."
projectile_type = /obj/item/projectile/bullet/dart/syringe/debug
firing_effect_type = null
/obj/item/ammo_casing/chemgun_debug/ready_proj(atom/target, mob/living/user, quiet, zone_override = "")
if(!BB)
return
if(istype(loc, /obj/item/gun/chem/debug))
var/obj/item/gun/chem/debug/CGD = loc
if(CGD.syringes_left <= 0)
return
if(!CGD.infinite)
CGD.reagents.trans_to(BB, 10)
else
CGD.reagents.copy_to(BB, 10)
BB.name = "chemical dart"
CGD.syringes_left--
..()
+60 -1
View File
@@ -43,4 +43,63 @@
syringes_left++
if(chambered && !chambered.BB)
chambered.newshot()
last_synth = world.time
last_synth = world.time
//Chemlight was here, adding dumb busing things
/obj/item/gun/chem/debug
name = "experimental reagent gun"
desc = "a reagent gun seemingly made to be a part of the user, suggesting the individual generates reagents in their body for it to work."
icon_state = "syringe_pistol"
item_state = "gun" //Smaller inhand
suppressed = TRUE //Softer fire sound
can_unsuppress = FALSE //Permanently silenced
time_per_syringe = 150
syringes_left = 6
max_syringes = 6
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
var/infinite = FALSE
/obj/item/gun/chem/debug/Initialize()
. = ..()
chambered = new /obj/item/ammo_casing/chemgun_debug(src)
START_PROCESSING(SSobj, src)
create_reagents(100, OPENCONTAINER | NO_REACT)
/obj/item/gun/chem/debug/Destroy()
. = ..()
STOP_PROCESSING(SSobj, src)
/obj/item/gun/chem/debug/attack_self(mob/user)
var/list/reagent_ids = sortList(GLOB.chemical_reagents_list)
var/choose_operation = input(user, "Select an option", "Reagent fabricator", "cancel") in list("Select reagent", "Enable production", "Cancel")
if (choose_operation == "Select reagent")
reagents.clear_reagents()
var/chosen_reagent
switch(alert(usr, "Choose a method.", "Add Reagents", "Enter ID", "Choose ID"))
if("Enter ID")
var/valid_id
while(!valid_id)
chosen_reagent = stripped_input(usr, "Enter the ID of the reagent you want to add to your syringes.")
if(!chosen_reagent) //Get me out of here!
break
for(var/ID in reagent_ids)
if(ID == chosen_reagent)
valid_id = 1
if(!valid_id)
to_chat(usr, "<span class='warning'>A reagent with that ID doesn't exist!</span>")
if("Choose ID")
chosen_reagent = input(usr, "Choose a reagent to add to your syringes.", "Choose a reagent.") as null|anything in reagent_ids
if(chosen_reagent)
reagents.add_reagent(chosen_reagent, 100, null)
else if (choose_operation == "Enable production")
if(!infinite)
infinite = TRUE
to_chat(user, "Now constantly generating reagents.")
else
infinite = FALSE
to_chat(user, "Reagents generation now off.")
else
return
@@ -79,3 +79,10 @@
target.visible_message("<span class='danger'>\The [src] fails to land on target!</span>")
return TRUE
//Chemlight was here, adding dumb bussing things
/obj/item/projectile/bullet/dart/syringe/debug
name = "syringe"
icon_state = "syringeproj"
damage = 0
@@ -195,6 +195,8 @@
B.reagents.add_reagent("blood", 20, data)
wait = TRUE
update_icon()
var/turf/source_turf = get_turf(src)
log_virus("A culture bottle was printed for the virus [A.admin_details()] at [loc_name(source_turf)] by [key_name(usr)]")
addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 50)
. = TRUE
if("create_vaccine_bottle")
@@ -702,3 +702,11 @@
id = "royalbluecarpet"
results = list("royalbluecarpet" = 2)
required_reagents = list("carpet" = 1, "clonexadone" = 1)
/datum/chemical_reaction/synth_blood
name = "Synthetic Blood"
id = "syntheticblood"
results = list("syntheticblood" = 3)
required_reagents = list("salglu_solution" = 1, "iron" = 1, "stable_plasma" = 1)
mix_message = "The mixture congeals and gives off a faint copper scent."
required_temp = 350
@@ -0,0 +1,131 @@
// This is more or less my funny tongue being being coded in. - Ken
/obj/item/reagent_containers/chemical_tongue
name = "synthetic reagent tongue"
desc = "A cybernetic organ with the ability to produce reagents, neat!"
icon = 'icons/mob/dogborg.dmi'
icon_state = "synthtongue"
amount_per_transfer_from_this = 5
volume = 200
possible_transfer_amounts = list()
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
spillable = FALSE
splashable = FALSE
reagent_flags = OPENCONTAINER | NO_REACT
var/list/fun_ids = list("growthchem", "shrinkchem", "aphro", "aphro+", "penis_enlarger", "breast_enlarger", "space_drugs", "lithium")
/obj/item/reagent_containers/chemical_tongue/attack(mob/M, mob/user, obj/target)
if(user.a_intent == INTENT_HARM && user.zone_selected == BODY_ZONE_PRECISE_MOUTH)
if(M != user)
M.visible_message("<span class='danger'>[user] locks their lips with [M], attempting to give a deep kiss to [M].</span>", \
"<span class='userdanger'>[user] locks their lips with yours, you feel what might be a tongue pushing past your lips then towards your throat!</span>")
if(!do_mob(user, M, 80))
return
playsound(M.loc,'sound/effects/attackblob.ogg', rand(10,50), 1)
if(isliving(M))
var/mob/living/deepkiss = M
deepkiss.adjustOxyLoss(10)
if(!reagents || !reagents.total_volume)
M.visible_message("<span class='warning'>[user] pulls away from the kiss as their tongue in [M]'s mouth soon follows, slurping back into [user]'s muzzle.</span>", \
"<span class='userwarning'>[user] thrusts their tongue down your throat! Pulling it back up as it slithers up then out from your mouth.</span>")
return // The drink might be empty after the delay, such as by spam-feeding
M.visible_message("<span class='warning'>[user] pulls away from the kiss as their tongue in [M]'s mouth soon follows, slurping back into [user]'s muzzle, leaving a long strand of liquid from their lips to [M]'s own before wiping it away.</span>", \
"<span class='userwarning'>[user] thrusts their tongue down your throat! Pulling it back up as it slithers up then out from your mouth. You feel a strange liquid in your throat!</span>")
log_combat(user, M, "fed", reagents.log_list())
var/fraction = min(5/reagents.total_volume, 1)
reagents.reaction(M, INGEST, fraction)
addtimer(CALLBACK(reagents, /datum/reagents.proc/copy_to, M, 10), 5)
if(user.a_intent == INTENT_GRAB && user.zone_selected == BODY_ZONE_PRECISE_MOUTH)
if(M != user)
M.visible_message("<span class='warning'>[user] lightly places their lips on [M]'s providing a kiss.</span>", \
"<span class='userwarning'>[user] lightly places their lips against your, you can feel tongue pushing against your lips in the kiss.</span>")
if(!do_mob(user, M, 40))
return
playsound(M.loc,'sound/effects/attackblob.ogg', rand(10,50), 1)
if(!reagents || !reagents.total_volume)
M.visible_message("<span class='warning'>[user] breaks away from the kiss with [M]'s.</span>", \
"<span class='userwarning'>[user] rolls their tongue around the inside of your mouth, before pulling away.</span>")
return // The drink might be empty after the delay, such as by spam-feeding
M.visible_message("<span class='warning'>[user] breaks away from the kiss with [M]'s.</span>", \
"<span class='userwarning'>[user] rolls their tongue around the inside of your mouth, before pulling away. You can almost taste something as [user]'s tongue was laced in something.</span>")
log_combat(user, M, "fed", reagents.log_list())
var/fraction = min(5/reagents.total_volume, 1)
reagents.reaction(M, INGEST, fraction)
addtimer(CALLBACK(reagents, /datum/reagents.proc/copy_to, M, 5), 5)
if(user.a_intent == INTENT_DISARM && user.zone_selected == BODY_ZONE_PRECISE_MOUTH)
if(M != user)
M.visible_message("<span class='warning'>[user] attempts nuzzles into [M]'s.</span>", \
"<span class='userwarning'>[user] attempts to bump his snout against yours.</span>")
if(!do_mob(user, M, 10))
return
playsound(M.loc,'sound/effects/attackblob.ogg', rand(10,50), 1)
if(!reagents || !reagents.total_volume)
M.visible_message("<span class='warning'>[user] playfully licks over [M]'s lips.</span>", \
"<span class='userwarning'>[user] playfully licks over your lips.</span>")
return // The drink might be empty after the delay, such as by spam-feeding
M.visible_message("<span class='warning'>[user] playfully licks over [M]'s lips.</span>", \
"<span class='userwarning'>[user] playfully licks over your lips, leaving some chemicals along it.</span>")
log_combat(user, M, "fed", reagents.log_list())
var/fraction = min(5/reagents.total_volume, 1)
reagents.reaction(M, INGEST, fraction)
addtimer(CALLBACK(reagents, /datum/reagents.proc/copy_to, M, 1), 5)
if(user.a_intent == INTENT_HELP)
if(M != user && user.zone_selected == BODY_ZONE_PRECISE_MOUTH)
M.visible_message("<span class='notice'>[user] affectionately licks [M]'s lips.</span>", \
"<span class='userwarning'>[user] affectionately licks over your lips.</span>")
playsound(M.loc,'sound/effects/attackblob.ogg', rand(10,50), 1)
else
if(M != user)
M.visible_message("<span class='notice'>[user] affectionately licks [M].</span>", \
"<span class='userwarning'>[user] affectionately licks over you.</span>")
playsound(M.loc,'sound/effects/attackblob.ogg', rand(10,50), 1)
else
return
/obj/item/reagent_containers/chemical_tongue/attack_self(mob/user)
var/chosen_reagent
var/list/reagent_ids = sortList(GLOB.chemical_reagents_list)
var/quick_select = input(user, "Select an option", "Press start") in list("Quick Select", "Debug", "Cancel")
switch (quick_select)
if("Quick Select")
reagents.clear_reagents()
amount_per_transfer_from_this = 5
chosen_reagent = input(user, "What reagent do you want to dispense?") as null|anything in fun_ids
if(chosen_reagent)
reagents.add_reagent(chosen_reagent, 20, null)
if("Debug")
var/operation_selection = input(user, "Select an option", "Reagent fabricator", "cancel") in list("Select reagent", "Clear reagents", "Select transfer amount", "Cancel")
switch (operation_selection)
if("Select reagent")
switch(alert(usr, "Choose a method.", "Add Reagents", "Enter ID", "Choose ID"))
if("Enter ID")
var/valid_id
while(!valid_id)
chosen_reagent = stripped_input(usr, "Enter the ID of the reagent you want to add.")
if(!chosen_reagent) //Get me out of here!
break
for(var/ID in reagent_ids)
if(ID == chosen_reagent)
valid_id = 1
if(!valid_id)
to_chat(usr, "<span class='warning'>A reagent with that ID doesn't exist!</span>")
if("Choose ID")
chosen_reagent = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in reagent_ids
if(chosen_reagent)
reagents.add_reagent(chosen_reagent, 20, null)
if("Clear reagents")
reagents.clear_reagents()
if("Select transfer amount")
var/transfer_select = input(user, "Select the amount of reagents you'd like to transfer.", "Transfer amount") as num|null
if(transfer_select)
amount_per_transfer_from_this = max(min(round(text2num(transfer_select)),20),1)
else
return
@@ -525,3 +525,76 @@
#undef COMBAT_WAIT_INJECT
#undef COMBAT_SELF_SPRAY
#undef COMBAT_SELF_INJECT
//Chemlight was here.
/obj/item/reagent_containers/hypospray/debug
name = "retractable hypospray syringe"
desc = "An advanced chemical synthesizer and injection system, designed for heavy-duty medical equipment."
icon = 'icons/obj/syringe.dmi'
item_state = "hypo"
icon_state = "borghypo"
amount_per_transfer_from_this = 5
volume = 200
possible_transfer_amounts = list()
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
reagent_flags = OPENCONTAINER | NO_REACT
slot_flags = ITEM_SLOT_BELT
infinite = TRUE
var/list/fun_ids = list("growthchem", "shrinkchem", "aphro", "aphro+", "penis_enlarger", "breast_enlarger", "space_drugs", "lithium")
/obj/item/reagent_containers/hypospray/debug/attack_self(mob/user)
var/chosen_reagent
var/list/reagent_ids = sortList(GLOB.chemical_reagents_list)
var/quick_select = input(user, "Select an option", "Press start") in list("Quick menu", "Debug", "Cancel")
switch (quick_select)
if("Quick menu")
var/list_selection = input(user, "Choose an catagory", "List Choice") in list("Emergency Meds", "Fun Chemicals", "Self Defense", "Cancel")
switch(list_selection)
if("Emergency Meds")
reagents.clear_reagents()
amount_per_transfer_from_this = 10
reagents.add_reagent_list(list("atropine" = 10, "oxandrolone" = 20, "sal_acid" = 20, "salbutamol" = 10))
if("Self Defense")
reagents.clear_reagents()
amount_per_transfer_from_this = 10
reagents.add_reagent_list(list("tirizene" = 14, "tiresolution" = 21, "bonehurtingjuice" = 14,)) // OOF
if("Fun Chemicals")
reagents.clear_reagents()
amount_per_transfer_from_this = 5
chosen_reagent = input(user, "What reagent do you want to dispense?") as null|anything in fun_ids
if(chosen_reagent)
reagents.add_reagent(chosen_reagent, 20, null)
if("Debug")
var/operation_selection = input(user, "Select an option", "Reagent fabricator", "cancel") in list("Select reagent", "Clear reagents", "Select transfer amount", "Cancel")
switch (operation_selection)
if("Select reagent")
switch(alert(usr, "Choose a method.", "Add Reagents", "Enter ID", "Choose ID"))
if("Enter ID")
var/valid_id
while(!valid_id)
chosen_reagent = stripped_input(usr, "Enter the ID of the reagent you want to add.")
if(!chosen_reagent) //Get me out of here!
break
for(var/ID in reagent_ids)
if(ID == chosen_reagent)
valid_id = 1
if(!valid_id)
to_chat(usr, "<span class='warning'>A reagent with that ID doesn't exist!</span>")
if("Choose ID")
chosen_reagent = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in reagent_ids
if(chosen_reagent)
reagents.add_reagent(chosen_reagent, 20, null)
if("Clear reagents")
reagents.clear_reagents()
if("Select transfer amount")
var/transfer_select = input(user, "Select the amount of reagents you'd like to inject.", "Transfer amount") as num|null
if(transfer_select)
amount_per_transfer_from_this = max(min(round(text2num(transfer_select)),20),1)
else
return
@@ -47,7 +47,7 @@
"<span class='userdanger'>[user] forces [M] to [apply_method] [src].</span>")
var/makes_me_think = pick(strings("redpill.json", "redpill_questions"))
if(icon_state == "pill4" && prob(5)) //you take the red pill - you stay in Wonderland, and I show you how deep the rabbit hole goes
if(icon_state == "pill4" && prob(10)) //you take the red pill - you stay in Wonderland, and I show you how deep the rabbit hole goes
addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, M, "<span class='notice'>[makes_me_think]</span>"), 50)
log_combat(user, M, "fed", reagents.log_list())
@@ -159,10 +159,11 @@
/datum/design/large_beaker
name = "Large Beaker"
id = "large_beaker"
build_type = AUTOLATHE
build_type = AUTOLATHE | PROTOLATHE
materials = list(MAT_GLASS = 2500)
build_path = /obj/item/reagent_containers/glass/beaker/large
category = list("initial", "Medical")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/healthanalyzer
name = "Health Analyzer"
@@ -208,7 +209,8 @@
/datum/design/hypoviallarge
name = "Large Hypovial"
id = "large_hypovial"
build_type = AUTOLATHE
build_type = AUTOLATHE | PROTOLATHE
materials = list(MAT_METAL = 2500)
build_path = /obj/item/reagent_containers/glass/bottle/vial/large
category = list("initial","Medical")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
@@ -960,3 +960,14 @@
build_path = /obj/item/hypospray/mkii/disposable
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/adv_hypo
name = "Hypospray MK.II"
desc = "A new development from DeForest Medical, this hypospray takes 30-unit vials as the drug supply for easy swapping."
id = "hypo2"
build_type = PROTOLATHE
materials = list(MAT_METAL = 500, MAT_GLASS = 500, MAT_SILVER = 500)
construction_time = 40
build_path = /obj/item/hypospray/mkii
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+3 -3
View File
@@ -12,7 +12,7 @@
"destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab",
"space_heater", "xlarge_beaker", "sec_rshot", "sec_bshot", "sec_slug", "sec_Islug", "sec_dart", "sec_38", "sec_38lethal",
"rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass","chem_pack","medkit_cabinet",
"disposable_hypospray","plastic_knife","plastic_fork","plastic_spoon")
"disposable_hypospray","plastic_knife","plastic_fork","plastic_spoon","large_beaker")
/datum/techweb_node/mmi
id = "mmi"
@@ -81,7 +81,7 @@
display_name = "Advanced Biotechnology"
description = "Advanced Biotechnology"
prereq_ids = list("biotech")
design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med","smartdartgun","medicinalsmartdart", "pHmeter")
design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med","smartdartgun","medicinalsmartdart", "pHmeter", "large_hypovial")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -673,7 +673,7 @@
display_name = "Medical Weaponry"
description = "Weapons using medical technology."
prereq_ids = list("adv_biotech", "adv_weaponry")
design_ids = list("rapidsyringe", "shotgundartcryostatis")
design_ids = list("rapidsyringe", "shotgundartcryostatis", "hypo2")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000)
export_price = 5000
@@ -0,0 +1,171 @@
// Testing things
/obj/effect/proc_holder/spell/self/Alteration_Mechanical
name = "Alter figure"
desc = "Change and alter your physical form."
human_req = 1
clothes_req = 0
charge_max = 100
cooldown_min = 50
action_icon = 'icons/mob/actions/actions_changeling.dmi'
action_icon_state = "ling_transform"
action_background_icon_state = "bg_spell"
still_recharging_msg = "<span class='notice'>Your reagents are still recharging.</span>"
invocation = null //what is uttered when the wizard casts the spell
invocation_emote_self = null
school = null
sound = 'sound/effects/pop.ogg'
var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread
var/pshoom_or_beepboopblorpzingshadashwoosh = 'sound/items/rped.ogg'
/obj/effect/proc_holder/spell/self/Alteration_Mechanical/cast(mob/living/carbon/human/user)
var/mob/living/carbon/human/H = user
var/list/reagent_options = sortList(GLOB.chemical_reagents_list)
H.visible_message("<span class='notice'> user] gains a look of \
concentration while standing perfectly still.\
Their body seems to shift and starts reshaping itself.</span>",
"<span class='notice'>You focus intently on altering your body while \
standing perfectly still...</span>")
var/select_alteration = input(user, "Select what part of your form to alter", "Form Alteration", "cancel") in list("Genitals", "Penis", "Vagina", "Penis Length", "Breast Size", "Penis Production", "Breast Production", "Alter Height", "Cancel")
do_sparks(5, FALSE, user.loc)
if (select_alteration == "Genitals")
var/list/organs = list()
var/operation = input("Select organ operation.", "Organ Manipulation", "cancel") in list("add sexual organ", "remove sexual organ", "cancel")
switch(operation)
if("add sexual organ")
var/new_organ = input("Select sexual organ:", "Organ Manipulation") in list("Penis", "Testicles", "Breasts", "Vagina", "Womb", "Cancel")
if(new_organ == "Penis")
H.give_penis()
else if(new_organ == "Testicles")
H.give_balls()
else if(new_organ == "Breasts")
H.give_breasts()
else if(new_organ == "Vagina")
H.give_vagina()
else if(new_organ == "Womb")
H.give_womb()
else
return
if("remove sexual organ")
for(var/obj/item/organ/genital/X in H.internal_organs)
var/obj/item/organ/I = X
organs["[I.name] ([I.type])"] = I
var/obj/item/organ = input("Select sexual organ:", "Organ Manipulation", null) in organs
organ = organs[organ]
if(!organ)
return
var/obj/item/organ/genital/O
if(isorgan(organ))
O = organ
O.Remove(H)
organ.forceMove(get_turf(H))
qdel(organ)
H.update_genitals()
else if (select_alteration == "Penis")
for(var/obj/item/organ/genital/penis/X in H.internal_organs)
qdel(X)
var/new_shape
new_shape = input(user, "Choose your character's dong", "Genital Alteration") as null|anything in GLOB.cock_shapes_list
if(new_shape)
H.dna.features["cock_shape"] = new_shape
H.update_genitals()
H.give_balls()
H.give_penis()
H.apply_overlay()
else if (select_alteration == "Vagina")
for(var/obj/item/organ/genital/vagina/X in H.internal_organs)
qdel(X)
var/new_shape
new_shape = input(user, "Choose your character's pussy", "Genital Alteration") as null|anything in GLOB.vagina_shapes_list
if(new_shape)
H.dna.features["vag_shape"] = new_shape
H.update_genitals()
H.give_womb()
H.give_vagina()
H.apply_overlay()
else if (select_alteration == "Penis Length")
for(var/obj/item/organ/genital/penis/X in H.internal_organs)
qdel(X)
var/new_length
new_length = input(user, "Penis length in inches:\n([COCK_SIZE_MIN]-[COCK_SIZE_MAX])", "Genital Alteration") as num|null
if(new_length)
H.dna.features["cock_length"] = max(min( round(text2num(new_length)), COCK_SIZE_MAX),COCK_SIZE_MIN)
H.update_genitals()
H.apply_overlay()
H.give_balls()
H.give_penis()
else if (select_alteration == "Breast Size")
for(var/obj/item/organ/genital/breasts/X in H.internal_organs)
qdel(X)
var/new_size
new_size = input(user, "Breast Size", "Genital Alteration") as null|anything in GLOB.breasts_size_list
if(new_size)
H.dna.features["breasts_size"] = new_size
H.update_genitals()
H.apply_overlay()
H.give_breasts()
else if (select_alteration == "Penis Production")
if(H.getorganslot("testicles"))
var/obj/item/organ/genital/testicles/T = H.getorganslot("testicles")
var/new_fluid_penis
switch(alert(usr, "Choose a method.", "Add Reagents", "Enter ID", "Choose ID"))
if("Enter ID")
var/valid_id
while(!valid_id)
new_fluid_penis = stripped_input(usr, "Enter the ID of the reagent you want to add to your testicles.")
if(!new_fluid_penis) //Get me out of here!
break
for(var/ID in reagent_options)
if(ID == new_fluid_penis)
valid_id = 1
if(!valid_id)
to_chat(usr, "<span class='warning'>A reagent with that ID doesn't exist!</span>")
if("Choose ID")
new_fluid_penis = input(usr, "Choose a reagent to add to your testicles.", "Choose a reagent.") as null|anything in reagent_options
if(new_fluid_penis)
T.fluid_id = new_fluid_penis
H.update_genitals()
H.apply_overlay()
else
to_chat(user, "You need balls for this to work.")
else if(select_alteration == "Breast Production")
if(H.getorganslot("breasts"))
var/obj/item/organ/genital/testicles/B = H.getorganslot("breasts")
var/new_fluid_breasts
switch(alert(usr, "Choose a method.", "Add Reagents", "Enter ID", "Choose ID"))
if("Enter ID")
var/valid_id
while(!valid_id)
new_fluid_breasts = stripped_input(usr, "Enter the ID of the reagent you want to add to your breasts.")
if(!new_fluid_breasts) //Get me out of here!
break
for(var/ID in reagent_options)
if(ID == new_fluid_breasts)
valid_id = 1
if(!valid_id)
to_chat(usr, "<span class='warning'>A reagent with that ID doesn't exist!</span>")
if("Choose ID")
new_fluid_breasts = input(usr, "Choose a reagent to add to your breasts.", "Choose a reagent.") as null|anything in reagent_options
if(new_fluid_breasts)
B.fluid_id = new_fluid_breasts
H.update_genitals()
H.apply_overlay()
else
to_chat(user, "You need functioning breasts for this to work.")
else if (select_alteration == "Alter Height")
var/altered_height
altered_height = input(user, "Choose your desired sprite size:\n([MIN_BODYSIZE]-400%)", "Height Alteration") as num|null
if(altered_height)
H.size_multiplier = (max(min( round(text2num(altered_height)),400),MIN_BODYSIZE))/100
playsound(user.loc, pshoom_or_beepboopblorpzingshadashwoosh, 40, 1)
do_sparks(5, FALSE, user.loc)
H.visible_message("<span class='danger'>[pick("[H] shifts in size!", "[H] alters in height!", "[H] reshapes into a new stature!")]</span>")
else
return
@@ -234,3 +234,10 @@
name = "surgical toolset implant"
desc = "A set of surgical tools hidden behind a concealed panel on the user's arm."
contents = newlist(/obj/item/retractor/augment, /obj/item/hemostat/augment, /obj/item/cautery/augment, /obj/item/surgicaldrill/augment, /obj/item/scalpel/augment, /obj/item/circular_saw/augment, /obj/item/surgical_drapes)
//Ignore this one this is for a bus character.
/obj/item/organ/cyberimp/arm/COMPound
name = "chemical cybernetics implant"
desc = "A powerful cybernetic implant that contains chemical fabrication modules built into the user's arm."
contents = newlist(/obj/item/reagent_containers/hypospray/debug, /obj/item/gun/chem/debug, /obj/item/reagent_containers/chemical_tongue, /obj/item/fermichem/pHmeter)