Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into ilowkeydespiseatmospherics

# Conflicts:
#	_maps/map_files/BoxStation/BoxStation.dmm
This commit is contained in:
ZeroMan
2020-04-30 13:48:48 -04:00
73 changed files with 1977 additions and 5067 deletions
+2
View File
@@ -61,7 +61,9 @@
#define BELOW_MOB_LAYER 3.7
#define LYING_MOB_LAYER 3.8
#define MOB_LOWER_LAYER 3.95
//#define MOB_LAYER 4 //For easy recordkeeping; this is a byond define
#define MOB_UPPER_LAYER 4.05
#define ABOVE_MOB_LAYER 4.1
#define WALL_OBJ_LAYER 4.25
#define EDGED_TURF_LAYER 4.3
+28
View File
@@ -0,0 +1,28 @@
/// true/false
#define SKILL_PROGRESSION_BINARY 1
/// numerical
#define SKILL_PROGRESSION_NUMERICAL 2
/// Enum
#define SKILL_PROGRESSION_ENUM 3
/// Max value of skill for numerical skills
#define SKILL_NUMERICAL_MAX 100
/// Min value of skill for numerical skills
#define SKILL_NUMERICAL_MIN 0
// Standard values for job starting skills
#define STARTING_SKILL_SURGERY_MEDICAL 35 //out of SKILL_NUMERICAL_MAX
// Standard values for job starting skill affinities
#define STARTING_SKILL_AFFINITY_SURGERY_MEDICAL 1.2
// Standard values for skill gain (this is multiplied by affinity)
#define SKILL_GAIN_SURGERY_PER_STEP 0.25
// Misc
/// 40% speedup at 100 skill
#define SURGERY_SKILL_SPEEDUP_NUMERICAL_SCALE(number) clamp(number / 250, 1, 2)
+3
View File
@@ -387,6 +387,9 @@ SUBSYSTEM_DEF(ticker)
for(var/mob/dead/new_player/N in GLOB.player_list)
var/mob/living/carbon/human/player = N.new_character
if(istype(player) && player.mind && player.mind.assigned_role)
var/datum/job/J = SSjob.GetJob(player.mind.assigned_role)
if(J)
J.standard_assign_skills(player.mind)
if(player.mind.assigned_role == "Captain")
captainless=0
if(player.mind.assigned_role != player.mind.special_role)
+1 -1
View File
@@ -352,7 +352,6 @@ SUBSYSTEM_DEF(vote)
if("dynamic")
if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started.
return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
GLOB.master_mode = "dynamic"
var/list/runnable_storytellers = config.get_runnable_storytellers()
var/datum/dynamic_storyteller/picked
for(var/T in runnable_storytellers)
@@ -489,6 +488,7 @@ SUBSYSTEM_DEF(vote)
modes_to_add -= "traitor" // makes it so that traitor is always available
choices.Add(modes_to_add)
if("dynamic")
GLOB.master_mode = "dynamic"
var/list/probabilities = CONFIG_GET(keyed_list/storyteller_weight)
for(var/T in config.storyteller_cache)
var/datum/dynamic_storyteller/S = T
@@ -115,6 +115,33 @@
//Tools & Storage//
///////////////////
/datum/crafting_recipe/upgraded_gauze
name = "Improved Gauze"
result = /obj/item/stack/medical/gauze/adv
time = 1
reqs = list(/obj/item/stack/medical/gauze = 1,
/datum/reagent/space_cleaner/sterilizine = 10)
category = CAT_MISC
subcategory = CAT_TOOL
/datum/crafting_recipe/bruise_pack
name = "Bruise Pack"
result = /obj/item/stack/medical/bruise_pack
time = 1
reqs = list(/obj/item/stack/medical/gauze = 1,
/datum/reagent/medicine/styptic_powder = 10)
category = CAT_MISC
subcategory = CAT_TOOL
/datum/crafting_recipe/burn_pack
name = "Brun Ointment"
result = /obj/item/stack/medical/ointment
time = 1
reqs = list(/obj/item/stack/medical/gauze = 1,
/datum/reagent/medicine/silver_sulfadiazine = 10)
category = CAT_MISC
subcategory = CAT_TOOL
/datum/crafting_recipe/ghettojetpack
name = "Improvised Jetpack"
result = /obj/item/tank/jetpack/improvised
+5
View File
@@ -198,6 +198,7 @@
/datum/component/riding/human/Initialize()
. = ..()
directional_vehicle_layers = list(TEXT_NORTH = MOB_LOWER_LAYER, TEXT_SOUTH = MOB_UPPER_LAYER, TEXT_EAST = MOB_UPPER_LAYER, TEXT_WEST = MOB_UPPER_LAYER)
RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee)
/datum/component/riding/human/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE)
@@ -261,6 +262,10 @@
/datum/component/riding/cyborg
/datum/component/riding/cyborg/Initialize()
. = ..()
directional_vehicle_layers = list(TEXT_NORTH = MOB_LOWER_LAYER, TEXT_SOUTH = MOB_UPPER_LAYER, TEXT_EAST = MOB_UPPER_LAYER, TEXT_WEST = MOB_UPPER_LAYER)
/datum/component/riding/cyborg/ride_check(mob/user)
var/atom/movable/AM = parent
if(user.incapacitated())
+4
View File
@@ -63,7 +63,11 @@
var/force_escaped = FALSE // Set by Into The Sunset command of the shuttle manipulator
var/list/learned_recipes //List of learned recipe TYPES.
/// Our skill holder.
var/datum/skill_holder/skill_holder
/datum/mind/New(var/key)
skill_holder = new
src.key = key
soulOwner = src
martial_art = default_martial_art
+16
View File
@@ -0,0 +1,16 @@
// yeah yeah verbs suck whatever I suck at this fix this someone please - kevinz000
/mob/verb/check_skills()
set name = "Check Skills"
set category = "IC"
set desc = "Check your skills (if you have any..)"
if(!mind)
to_chat(usr, "<span class='warning'>How do you check the skills of [(usr == src)? "yourself when you are" : "something"] without a mind?</span>")
return
if(!mind.skill_holder)
to_chat(usr, "<span class='warning'>How do you check the skills of [(usr == src)? "yourself when you are" : "something"] without the capability for skills? (PROBABLY A BUG, PRESS F1.)</span>")
return
var/datum/browser/B = new(usr, "skilldisplay_[REF(src)]", "Skills of [src]")
B.set_content(mind.skill_holder.html_readout())
B.open()
+95
View File
@@ -0,0 +1,95 @@
GLOBAL_LIST_INIT(skill_datums, init_skill_datums())
/proc/init_skill_datums()
. = list()
for(var/path in subtypesof(/datum/skill))
var/datum/skill/S = path
if(initial(S.abstract_type) == path)
continue
S = new path
.[S.type] = S
/proc/get_skill_datum(path)
return GLOB.skill_datums[path]
/proc/sanitize_skill_value(path, value)
var/datum/skill/S = get_skill_datum(path)
// don't check, if we runtime let it happen.
return S.sanitize_value(value)
/proc/is_skill_value_greater(path, existing, new_value)
var/datum/skill/S = get_skill_datum(path)
// don't check, if we runtime let it happen.
return S.is_value_greater(existing, new_value)
/**
* Skill datums
*/
/datum/skill
/// Our name
var/name
/// Our description
var/desc
/// Our progression type
var/progression_type
/// Abstract type
var/abstract_type = /datum/skill
/**
* Ensures what someone's setting as a value for this skill is valid.
*/
/datum/skill/proc/sanitize_value(new_value)
return new_value
/**
* Checks if a value is greater
*/
/datum/skill/proc/is_value_greater(existing, new_value)
if(!existing)
return TRUE
return new_value > existing
/**
* Standard value "render"
*/
/datum/skill/proc/standard_render_value(value)
return value
// Just saying, the choice to use different sub-parent-types is to force coders to resolve issues as I won't be implementing custom procs to grab skill levels in a certain context.
// Aka: So people don't forget to change checks if they change a skill's progression type.
/datum/skill/binary
abstract_type = /datum/skill/binary
progression_type = SKILL_PROGRESSION_BINARY
/datum/skill/binary/sanitize_value(new_value)
return new_value? TRUE : FALSE
/datum/skill/binary/standard_render_value(value)
return value? "Yes" : "No"
/datum/skill/numerical
abstract_type = /datum/skill/numerical
progression_type = SKILL_PROGRESSION_NUMERICAL
/// Max value of this skill
var/max_value = 100
/// Min value of this skill
var/min_value = 0
/// Display as a percent in standard_render_value?
var/display_as_percent = FALSE
/datum/skill/numerical/sanitize_value(new_value)
return clamp(new_value, min_value, max_value)
/datum/skill/numerical/standard_render_value(value)
return display_as_percent? "[round(value/max_value/100, 0.01)]%" : "[value] / [max_value]"
/datum/skill/enum
abstract_type = /datum/skill/enum
progression_type = SKILL_PROGRESSION_ENUM
/// Valid values for the skill
var/list/valid_values = list()
/datum/skill/enum/sanitize_value(new_value)
if(new_value in valid_values)
return new_value
+78
View File
@@ -0,0 +1,78 @@
/**
* Skill holder datums
*/
/datum/skill_holder
/// Our list of skills and values. Lazylist. Associative. Keys are datum typepaths to the skill.
var/list/skills
/// Same as [skills] but affinities, which are multiplied to increase amount when gaining skills.
var/list/skill_affinities
/**
* Grabs the value of a skill.
*/
/datum/skill_holder/proc/get_skill_value(skill)
if(!ispath(skill))
CRASH("Invalid get_skill_value call. Use typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
if(!skills)
return null
return skills[skill]
/**
* Grabs our affinity for a skill. !!This is a multiplier!!
*/
/datum/skill_holder/proc/get_skill_affinity(skill)
if(!ispath(skill))
CRASH("Invalid get_skill_affinity call. Use typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
if(!skills)
return 1
var/affinity = skill_affinities[skill]
if(isnull(affinity))
return 1
return affinity
/**
* Sets the value of a skill.
*/
/datum/skill_holder/proc/set_skill_value(skill, value)
if(!ispath(skill))
CRASH("Invalid set_skill_value call. Use typepaths.") //until a time when we somehow need text ids for dynamic skills, I'm enforcing this.
LAZYINITLIST(skills)
value = sanitize_skill_value(skill, value)
if(!isnull(value))
skills[skill] = value
return TRUE
return FALSE
/**
* Boosts a skill to a value if not aobve
*/
/datum/skill_holder/proc/boost_skill_value_to(skill, value)
var/current = get_skill_value(skill)
if(!is_skill_value_greater(skill, current, value))
return FALSE
set_skill_value(skill, value)
return TRUE
/**
* Automatic skill increase, multiplied by skill affinity if existing.
* Only works if skill is numerical.
*/
/datum/skill_holder/proc/auto_gain_experience(skill, value)
if(!ispath(skill, /datum/skill/numerical))
CRASH("You cannot auto increment a non numerical skill!")
var/current = get_skill_value(skill)
var/affinity = get_skill_affinity(skill)
boost_skill_value_to(skill, current + (value * affinity))
/**
* Generates a HTML readout of our skills.
* Port to tgui-next when?
*/
/datum/skill_holder/proc/html_readout()
var/list/out = list("<center><h1>Skills</h1></center><hr>")
out += "<table style=\"width:100%\"><tr><th><b>Skill</b><th><b>Value</b></tr>"
for(var/path in skills)
var/datum/skill/S = GLOB.skill_datums[path]
out += "<tr><td>[S.name]</td><td>[S.standard_render_value(skills[path])]</td></tr>"
out += "</table>"
return out.Join("")
+3
View File
@@ -0,0 +1,3 @@
/datum/skill/numerical/surgery
name = "Surgery"
desc = "How proficient you are at doing surgery."
+7 -3
View File
@@ -40,8 +40,10 @@ GLOBAL_VAR_INIT(dynamic_stacking_limit, 90)
GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset)
// Forced threat level, setting this to zero or higher forces the roundstart threat to the value.
GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
// Storyteller picked by the voting.
GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
// Storyteller forced by admins during voting--will be used instead of above.
GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
/datum/game_mode/dynamic
name = "dynamic mode"
@@ -252,7 +254,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
/datum/game_mode/dynamic/send_intercept()
. = "<b><i>Central Command Status Summary</i></b><hr>"
switch(round(threat_level))
if(0 to 20)
if(-INFINITY to 20)
. += "<b>Peaceful Waypoint</b></center><BR>"
. += "Your station orbits deep within controlled, core-sector systems and serves as a waypoint for routine traffic through Nanotrasen's trade empire. Due to the combination of high security, interstellar traffic, and low strategic value, it makes any direct threat of violence unlikely. Your primary enemies will be incompetence and bored crewmen: try to organize team-building events to keep staffers interested and productive. However, even deep in our territory there may be subversive elements, especially for such a high-value target as your station. Keep an eye out, but don't expect much trouble."
set_security_level(SEC_LEVEL_GREEN)
@@ -284,7 +286,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
. += "<b>Black Orbit</b></center><BR>"
. += "As part of a mandatory security protocol, we are required to inform you that as a result of your orbital pattern directly behind an astrological body (oriented from our nearest observatory), your station will be under decreased monitoring and support. It is anticipated that your extreme location and decreased surveillance could pose security risks. Avoid unnecessary risks and attempt to keep your station in one piece."
set_security_level(SEC_LEVEL_AMBER)
if(96 to 100)
if(96 to INFINITY)
. += "<b>Impending Doom</b></center><BR>"
. += "Your station is somehow in the middle of hostile territory, in clear view of any enemy of the corporation. Your likelihood to survive is low, and station destruction is expected and almost inevitable. Secure any sensitive material and neutralize any enemy you will come across. It is important that you at least try to maintain the station.<BR>"
. += "Good luck."
@@ -355,6 +357,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
SSblackbox.record_feedback("tally","dynamic_threat",peaceful_percentage,"Percent of same-vote rounds that are more peaceful")
/datum/game_mode/dynamic/can_start()
if(GLOB.dynamic_forced_storyteller)
GLOB.dynamic_storyteller_type = GLOB.dynamic_forced_storyteller
storyteller = new GLOB.dynamic_storyteller_type // this is where all the initialization happens
storyteller.on_start()
SSblackbox.record_feedback("text","dynamic_storyteller",1,storyteller.name)
+1 -1
View File
@@ -393,7 +393,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
qdel(src)
item_flags &= ~IN_INVENTORY
if(SEND_SIGNAL(src, COMSIG_ITEM_DROPPED,user) & COMPONENT_DROPPED_RELOCATION)
return ITEM_RELOCATED_BY_DROPPED
. = ITEM_RELOCATED_BY_DROPPED
user.update_equipment_speed_mods()
// called just as an item is picked up (loc is not yet changed)
@@ -100,6 +100,7 @@
if(!H.bleedsuppress && H.bleed_rate) //so you can't stack bleed suppression
H.suppress_bloodloss(stop_bleeding)
to_chat(user, "<span class='notice'>You stop the bleeding of [M]!</span>")
H.adjustBruteLoss(-(heal_brute))
return TRUE
to_chat(user, "<span class='notice'>You can not use \the [src] on [M]!</span>")
@@ -127,6 +128,12 @@
stop_bleeding = 900
heal_brute = 0
/obj/item/stack/medical/gauze/adv
name = "sterilized medical gauze"
desc = "A roll of elastic sterilized cloth that is extremely effective at stopping bleeding, heals minor wounds and cleans them."
singular_name = "sterilized medical gauze"
self_delay = 5
/obj/item/stack/medical/gauze/cyborg
custom_materials = null
is_cyborg = 1
+4 -1
View File
@@ -695,7 +695,10 @@
/obj/item/gun/ballistic/revolver,
/obj/item/ammo_box,
/obj/item/toy/gun,
/obj/item/gun/energy/e_gun/mini
/obj/item/gun/energy/e_gun/mini,
/obj/item/gun/ballistic/automatic/magrifle/pistol,
/obj/item/gun/energy/disabler,
/obj/item/gun/energy/taser
))
/obj/item/storage/belt/holster/full/PopulateContents()
+5 -1
View File
@@ -429,6 +429,10 @@
for(var/datum/dynamic_ruleset/roundstart/rule in GLOB.dynamic_forced_roundstart_ruleset)
dat += {"<A href='?src=[REF(src)];[HrefToken()];f_dynamic_roundstart_remove=\ref[rule]'>-> [rule.name] <-</A><br>"}
dat += "<A href='?src=[REF(src)];[HrefToken()];f_dynamic_roundstart_clear=1'>(Clear Rulesets)</A><br>"
dat += "<A href='?src=[REF(src)];[HrefToken()];f_dynamic_storyteller=1'>(Force Storyteller)</A><br>"
if (GLOB.dynamic_forced_storyteller)
var/datum/dynamic_storyteller/S = GLOB.dynamic_forced_storyteller
dat += "<A href='?src=[REF(src)];[HrefToken()];f_dynamic_storyteller_clear=1'>-> [initial(S.name)] <-</A><br>"
dat += "<A href='?src=[REF(src)];[HrefToken()];f_dynamic_options=1'>(Dynamic mode options)</A><br>"
else if (SSticker.IsRoundInProgress())
dat += "<A href='?src=[REF(src)];[HrefToken()];f_dynamic_latejoin=1'>(Force Next Latejoin Ruleset)</A><br>"
@@ -690,7 +694,7 @@
var/prev_dynamic_voting = CONFIG_GET(flag/dynamic_voting)
CONFIG_SET(flag/dynamic_voting,!prev_dynamic_voting)
if (!prev_dynamic_voting)
to_chat(world, "<B>Vote is now a ranked choice of dynamic storytellers.</B>")
to_chat(world, "<B>Vote is now between dynamic storytellers.</B>")
else
to_chat(world, "<B>Vote is now between extended and secret.</B>")
log_admin("[key_name(usr)] [prev_dynamic_voting ? "disabled" : "enabled"] dynamic voting.")
+26
View File
@@ -1394,6 +1394,32 @@
log_admin("[key_name(usr)] removed [rule] from the forced roundstart rulesets.")
message_admins("[key_name(usr)] removed [rule] from the forced roundstart rulesets.", 1)
else if(href_list["f_dynamic_storyteller"])
if(!check_rights(R_ADMIN))
return
if(SSticker && SSticker.mode)
return alert(usr, "The game has already started.", null, null, null, null)
if(GLOB.master_mode != "dynamic")
return alert(usr, "The game mode has to be dynamic mode.", null, null, null, null)
var/list/choices = list()
for(var/T in config.storyteller_cache)
var/datum/dynamic_storyteller/S = T
choices[initial(S.name)] = T
var/choice = choices[input("Select storyteller:", "Storyteller", "Classic") as null|anything in choices]
if(choice)
GLOB.dynamic_forced_storyteller = choice
log_admin("[key_name(usr)] forced the storyteller to [GLOB.dynamic_forced_storyteller].")
message_admins("[key_name(usr)] forced the storyteller to [GLOB.dynamic_forced_storyteller].")
Game()
else if(href_list["f_dynamic_storyteller_clear"])
if(!check_rights(R_ADMIN))
return
GLOB.dynamic_forced_storyteller = null
Game()
log_admin("[key_name(usr)] cleared the forced storyteller. The mode will pick one as normal.")
message_admins("[key_name(usr)] cleared the forced storyteller. The mode will pick one as normal.", 1)
else if(href_list["f_dynamic_latejoin"])
if(!check_rights(R_ADMIN))
return
@@ -6,6 +6,7 @@
status = ORGAN_ROBOTIC
beating = TRUE
organ_flags = ORGAN_NO_SPOIL
no_pump = TRUE
var/true_name = "baseline placebo referencer"
var/cooldown_low = 300
var/cooldown_high = 300
@@ -92,6 +93,7 @@
update_gland_hud()
/obj/item/organ/heart/gland/on_life()
. = ..()
if(!beating)
// alien glands are immune to stopping.
beating = TRUE
+16 -1
View File
@@ -66,6 +66,11 @@
// How much threat this job is worth in dynamic. Is subtracted if the player's not an antag, added if they are.
var/threat = 0
/// Starting skill levels.
var/list/starting_skills
/// Skill affinities to set
var/list/skill_affinities
//Only override this proc
//H is usually a human unless an /equip override transformed it
/datum/job/proc/after_spawn(mob/living/H, mob/M, latejoin = FALSE)
@@ -142,7 +147,6 @@
return TRUE //Available in 0 days = available right now = player is old enough to play.
return FALSE
/datum/job/proc/available_in_days(client/C)
if(!C)
return 0
@@ -166,6 +170,17 @@
/datum/job/proc/radio_help_message(mob/M)
to_chat(M, "<b>Prefix your message with :h to speak on your department's radio. To see other prefixes, look closely at your headset.</b>")
/datum/job/proc/standard_assign_skills(datum/mind/M)
if(!starting_skills)
return
for(var/skill in starting_skills)
M.skill_holder.boost_skill_value_to(skill, starting_skills[skill])
// do wipe affinities though
M.skill_holder.skill_affinities = list()
for(var/skill in skill_affinities)
M.skill_holder.skill_affinities[skill] = skill_affinities[skill]
UNSETEMPTY(M.skill_holder.skill_affinities) //if we didn't set any.
/datum/outfit/job
name = "Standard Gear"
+3
View File
@@ -19,6 +19,9 @@
display_order = JOB_DISPLAY_ORDER_CHEMIST
threat = 1.5
starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL)
skill_affinities = list(/datum/skill/numerical/surgery = STARTING_SKILL_AFFINITY_SURGERY_MEDICAL)
/datum/outfit/job/chemist
name = "Chemist"
jobtype = /datum/job/chemist
@@ -29,6 +29,9 @@
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/insanity)
threat = 2
starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL)
skill_affinities = list(/datum/skill/numerical/surgery = STARTING_SKILL_AFFINITY_SURGERY_MEDICAL)
/datum/outfit/job/cmo
name = "Chief Medical Officer"
jobtype = /datum/job/cmo
@@ -19,6 +19,8 @@
display_order = JOB_DISPLAY_ORDER_GENETICIST
threat = 1.5
starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL)
/datum/outfit/job/geneticist
name = "Geneticist"
jobtype = /datum/job/geneticist
@@ -17,6 +17,9 @@
display_order = JOB_DISPLAY_ORDER_MEDICAL_DOCTOR
threat = 0.5
starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL)
skill_affinities = list(/datum/skill/numerical/surgery = STARTING_SKILL_AFFINITY_SURGERY_MEDICAL)
/datum/outfit/job/doctor
name = "Medical Doctor"
jobtype = /datum/job/doctor
+3
View File
@@ -19,6 +19,9 @@
threat = 0.5
starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL)
skill_affinities = list(/datum/skill/numerical/surgery = STARTING_SKILL_AFFINITY_SURGERY_MEDICAL)
/datum/outfit/job/paramedic
name = "Paramedic"
jobtype = /datum/job/paramedic
@@ -20,6 +20,9 @@
threat = 1.5
starting_skills = list(/datum/skill/numerical/surgery = STARTING_SKILL_SURGERY_MEDICAL)
skill_affinities = list(/datum/skill/numerical/surgery = STARTING_SKILL_AFFINITY_SURGERY_MEDICAL)
/datum/outfit/job/virologist
name = "Virologist"
jobtype = /datum/job/virologist
@@ -65,7 +65,7 @@
qdel(src)
/obj/item/organ/regenerative_core/on_life()
..()
. = ..()
if(owner.health < owner.crit_threshold)
ui_action_click()
@@ -392,6 +392,8 @@
character.update_parallax_teleport()
job.standard_assign_skills(character.mind)
SSticker.minds += character.mind
var/mob/living/carbon/human/humanc
+10 -16
View File
@@ -245,23 +245,17 @@
. = adjusted_amount
*/
/obj/item/organ/brain/on_life()
if(damage >= BRAIN_DAMAGE_DEATH) //rip
to_chat(owner, "<span class='userdanger'>The last spark of life in your brain fizzles out...</span>")
owner.death()
brain_death = TRUE
return
..()
/obj/item/organ/brain/on_death()
if(damage <= BRAIN_DAMAGE_DEATH) //rip
brain_death = FALSE
..()
/obj/item/organ/brain/applyOrganDamage(var/d, var/maximum = maxHealth)
..()
. = ..()
if(!. || !owner)
return
if(damage >= BRAIN_DAMAGE_DEATH) //rip
if(owner.stat != DEAD)
to_chat(owner, "<span class='userdanger'>The last spark of life in your brain fizzles out...</span>")
owner.death()
brain_death = TRUE
else
brain_death = FALSE
/obj/item/organ/brain/check_damage_thresholds(mob/M)
. = ..()
@@ -77,6 +77,9 @@
alien_powers = list(/obj/effect/proc_holder/alien/transfer)
/obj/item/organ/alien/plasmavessel/on_life()
. = ..()
if(!.)
return
//If there are alien weeds on the ground then heal if needed or give some plasma
if(locate(/obj/structure/alien/weeds) in owner.loc)
if(owner.health >= owner.maxHealth)
@@ -23,6 +23,8 @@
/obj/item/organ/body_egg/alien_embryo/on_life()
. = ..()
if(!owner)
return
switch(stage)
if(2, 3)
if(prob(2))
@@ -38,7 +38,7 @@
adjustCloneLoss(damage_amount, forced = forced)
if(STAMINA)
if(BP)
if(damage > 0 ? BP.receive_damage(0, 0, damage_amount) : BP.heal_damage(0, 0, abs(damage_amount)))
if(damage > 0 ? BP.receive_damage(0, 0, damage_amount) : BP.heal_damage(0, 0, abs(damage_amount), FALSE, FALSE))
update_damage_overlays()
else
adjustStaminaLoss(damage_amount, forced = forced)
@@ -101,12 +101,11 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
/obj/item/organ/dwarfgland/on_life() //Primary loop to hook into to start delayed loops for other loops..
. = ..()
dwarf_cycle_ticker()
if(!owner || owner.stat == DEAD)
dwarf_cycle_ticker()
//Handles the delayed tick cycle by just adding on increments per each on_life() tick
/obj/item/organ/dwarfgland/proc/dwarf_cycle_ticker()
if(owner.stat == DEAD)
return //We make sure they are not dead, so they don't increment any tickers.
dwarf_eth_ticker++
dwarf_filth_ticker++
@@ -91,4 +91,9 @@
if((C.dna.features["spines"] != "None" ) && (C.dna.features["tail_lizard"] == "None")) //tbh, it's kinda ugly for them not to have a tail yet have floating spines
C.dna.features["tail_lizard"] = "Smooth"
C.update_body()
if(C.dna.features["legs"] != "digitigrade")
C.dna.features["legs"] = "digitigrade"
for(var/obj/item/bodypart/leggie in C.bodyparts)
if(leggie.body_zone == BODY_ZONE_L_LEG || leggie.body_zone == BODY_ZONE_R_LEG)
leggie.update_limb(FALSE, C)
return ..()
@@ -19,6 +19,11 @@
path_image_color = "#993299"
weather_immunities = list("lava","ash")
var/clean_time = 50 //How long do we take to clean?
var/broom = FALSE //Do we have an speed buff from a broom?
var/adv_mop = FALSE //Do we have a cleaning buff from a better mop?
var/blood = 1
var/trash = 0
var/pests = 0
@@ -75,6 +80,26 @@
to_chat(user, "<span class='warning'>Please close the access panel before locking it.</span>")
else
to_chat(user, "<span class='notice'>\The [src] doesn't seem to respect your authority.</span>")
if(istype(W, /obj/item/mop/advanced))
if(bot_core.allowed(user) && open && adv_mop == TRUE)
to_chat(user, "<span class='notice'>You replace \the [src] old mop with a new better one!</span>")
adv_mop = TRUE
clean_time = 20 //2.5 the speed!
window_name = "Automatic Station Cleaner v2.1 BETA" //New!
qdel(W)
else
to_chat(user, "<span class='notice'>\the [src] already has this mop!</span>")
if(istype(W, /obj/item/twohanded/broom))
if(bot_core.allowed(user) && open && broom == TRUE)
to_chat(user, "<span class='notice'>You add to \the [src] a broom speeding it up!</span>")
broom = TRUE
base_speed = 1 //2x faster!
qdel(W)
else
to_chat(user, "<span class='notice'>\the [src] already has a broom!</span>")
else
return ..()
@@ -221,7 +246,7 @@
icon_state = "cleanbot-c"
visible_message("<span class='notice'>[src] begins to clean up [A].</span>")
mode = BOT_CLEANING
spawn(50)
spawn(clean_time)
if(mode == BOT_CLEANING)
if(A && isturf(A.loc))
var/atom/movable/AM = A
@@ -3,6 +3,10 @@
select_name = "ion"
fire_sound = 'sound/weapons/ionrifle.ogg'
/obj/item/ammo_casing/energy/ion/hos
projectile_type = /obj/item/projectile/ion/weak
e_cost = 300
/obj/item/ammo_casing/energy/declone
projectile_type = /obj/item/projectile/energy/declone
select_name = "declone"
@@ -16,9 +16,6 @@
fire_sound = 'sound/weapons/gunshot.ogg'
e_cost = 100
/obj/item/ammo_casing/energy/electrode/hos
projectile_type = /obj/item/projectile/energy/electrode/security/hos
e_cost = 200
/obj/item/ammo_casing/energy/electrode/old
e_cost = 1000
@@ -52,13 +52,16 @@
/obj/item/gun/energy/e_gun/hos
name = "\improper X-01 MultiPhase Energy Gun"
desc = "This is an expensive, modern recreation of an antique laser gun. This gun has several unique firemodes, but lacks the ability to recharge over time."
desc = "This is an expensive, modern recreation of an antique laser gun. This gun has several unique firemodes, but lacks the ability to recharge over time in exchange for inbuilt advanced firearm EMP shielding."
icon_state = "hoslaser"
force = 10
ammo_type = list(/obj/item/ammo_casing/energy/electrode/hos, /obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser/hos)
ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser/hos, /obj/item/ammo_casing/energy/ion/hos)
ammo_x_offset = 4
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
/obj/item/gun/energy/e_gun/hos/emp_act(severity)
return
/obj/item/gun/energy/e_gun/dragnet
name = "\improper DRAGnet"
desc = "The \"Dynamic Rapid-Apprehension of the Guilty\" net is a revolution in law enforcement technology."
+2
View File
@@ -315,6 +315,8 @@
objs += O
var/obj/O = safepick(objs)
if(O)
if(length(O.buckled_mobs))
return pick(O.buckled_mobs)
return O
//Nothing else is here that we can hit, hit the turf if we haven't.
if(!(T in permutated) && can_hit_target(T, permutated, T == original, TRUE))
@@ -3,7 +3,7 @@
icon_state = "ion"
damage = 0
damage_type = BURN
nodamage = 1
nodamage = TRUE
flag = "energy"
impact_effect_type = /obj/effect/temp_visual/impact_effect/ion
var/emp_radius = 1
@@ -14,4 +14,4 @@
return BULLET_ACT_HIT
/obj/item/projectile/ion/weak
emp_radius = 0
emp_radius = 0
@@ -246,6 +246,13 @@
metabolization_rate = 5 * REAGENTS_METABOLISM
overdose_threshold = 50
/datum/reagent/medicine/silver_sulfadiazine/reaction_obj(obj/O, reac_volume)
if(istype(O, /obj/item/stack/medical/gauze))
var/obj/item/stack/medical/gauze/G = O
reac_volume = min((reac_volume / 10), G.amount)
new/obj/item/stack/medical/ointment(get_turf(G), reac_volume)
G.use(reac_volume)
/datum/reagent/medicine/silver_sulfadiazine/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(iscarbon(M) && M.stat != DEAD)
if(method in list(INGEST, VAPOR, INJECT))
@@ -321,6 +328,12 @@
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine)
..()
/datum/reagent/medicine/styptic_powder/reaction_obj(obj/O, reac_volume)
if(istype(O, /obj/item/stack/medical/gauze))
var/obj/item/stack/medical/gauze/G = O
reac_volume = min((reac_volume / 10), G.amount)
new/obj/item/stack/medical/bruise_pack(get_turf(G), reac_volume)
G.use(reac_volume)
/datum/reagent/medicine/styptic_powder/on_mob_life(mob/living/carbon/M)
M.adjustBruteLoss(-2*REM, 0)
@@ -1045,6 +1045,14 @@
// +20% success propability on each step, useful while operating in less-than-perfect conditions
..()
/datum/reagent/space_cleaner/sterilizine/reaction_obj(obj/O, reac_volume)
if(istype(O, /obj/item/stack/medical/gauze))
var/obj/item/stack/medical/gauze/G = O
reac_volume = min((reac_volume / 10), G.amount)
new/obj/item/stack/medical/gauze/adv(get_turf(G), reac_volume)
G.use(reac_volume)
/datum/reagent/iron
name = "Iron"
description = "Pure iron is a metal."
+3 -5
View File
@@ -12,12 +12,10 @@
var/inflamed
/obj/item/organ/appendix/on_life()
..()
if(!(organ_flags & ORGAN_FAILING))
. = ..()
if(.)
return
var/mob/living/carbon/M = owner
if(M)
M.adjustToxLoss(4, TRUE, TRUE) //forced to ensure people don't use it to gain tox as slime person
owner.adjustToxLoss(4, TRUE, TRUE) //forced to ensure people don't use it to gain tox as slime person
/obj/item/organ/appendix/update_icon_state()
if(inflamed)
@@ -16,7 +16,8 @@
slot = ORGAN_SLOT_STOMACH_AID
/obj/item/organ/cyberimp/chest/nutriment/on_life()
if(synthesizing)
. = ..()
if(!. || synthesizing)
return
if(owner.nutrition <= hunger_threshold)
@@ -59,23 +60,25 @@
var/convalescence_time = 0
/obj/item/organ/cyberimp/chest/reviver/on_life()
. = ..()
if(reviving)
var/do_heal = world.time < convalescence_time
var/do_heal = . && world.time < convalescence_time
if(revive_cost >= MAX_HEAL_COOLDOWN)
do_heal = FALSE
else if(owner.stat && owner.stat != DEAD)
else if(owner?.stat && owner.stat != DEAD)
do_heal = TRUE
else if(!do_heal)
convalescence_time = world.time + DEF_CONVALESCENCE_TIME
if(do_heal)
if(. && (do_heal || world.time < convalescence_time))
addtimer(CALLBACK(src, .proc/heal), 3 SECONDS)
else
cooldown = revive_cost + world.time
reviving = FALSE
to_chat(owner, "<span class='notice'>Your reviver implant shuts down and starts recharging. It will be ready again in [DisplayTimeText(revive_cost)].</span>")
if(owner)
to_chat(owner, "<span class='notice'>Your reviver implant shuts down and starts recharging. It will be ready again in [DisplayTimeText(revive_cost)].</span>")
return
if(cooldown > world.time || owner.stat == CONSCIOUS || owner.stat == DEAD || owner.suiciding)
if(!. || cooldown > world.time || owner.stat == CONSCIOUS || owner.stat == DEAD || owner.suiciding)
return
revive_cost = 0
@@ -102,8 +102,8 @@
slot = ORGAN_SLOT_BRAIN_ANTISTUN
/obj/item/organ/cyberimp/brain/anti_stun/on_life()
..()
if(crit_fail || !(organ_flags & ORGAN_FAILING))
. = ..()
if(!. || crit_fail)
return
owner.adjustStaminaLoss(-3.5, FALSE) //Citadel edit, makes it more useful in Stamina based combat
owner.HealAllImmobilityUpTo(STUN_SET_AMOUNT)
+6 -11
View File
@@ -29,22 +29,17 @@
var/damage_multiplier = 1
/obj/item/organ/ears/on_life()
if(!iscarbon(owner))
return
..()
var/mob/living/carbon/C = owner
if((damage < maxHealth) && (organ_flags & ORGAN_FAILING)) //ear damage can be repaired from the failing condition
organ_flags &= ~ORGAN_FAILING
. = ..()
// genetic deafness prevents the body from using the ears, even if healthy
if(HAS_TRAIT(C, TRAIT_DEAF))
if(owner && HAS_TRAIT(owner, TRAIT_DEAF))
deaf = max(deaf, 1)
else if(!(organ_flags & ORGAN_FAILING)) // if this organ is failing, do not clear deaf stacks.
else if(.) // if this organ is failing, do not clear deaf stacks.
deaf = max(deaf - 1, 0)
if(prob(damage / 20) && (damage > low_threshold))
adjustEarDamage(0, 4)
SEND_SOUND(C, sound('sound/weapons/flash_ring.ogg'))
to_chat(C, "<span class='warning'>The ringing in your ears grows louder, blocking out any external noises for a moment.</span>")
else if((organ_flags & ORGAN_FAILING) && (deaf == 0))
SEND_SOUND(owner, sound('sound/weapons/flash_ring.ogg'))
to_chat(owner, "<span class='warning'>The ringing in your ears grows louder, blocking out any external noises for a moment.</span>")
else if(!. && !deaf)
deaf = 1 //stop being not deaf you deaf idiot
/obj/item/organ/ears/proc/restoreEars()
+54 -40
View File
@@ -1,3 +1,7 @@
#define BLURRY_VISION_ONE 1
#define BLURRY_VISION_TWO 2
#define BLIND_VISION_THREE 3
/obj/item/organ/eyes
name = BODY_ZONE_PRECISE_EYES
icon_state = "eyeballs"
@@ -10,7 +14,7 @@
decay_factor = STANDARD_ORGAN_DECAY
maxHealth = 0.5 * STANDARD_ORGAN_THRESHOLD //half the normal health max since we go blind at 30, a permanent blindness at 50 therefore makes sense unless medicine is administered
high_threshold = 0.3 * STANDARD_ORGAN_THRESHOLD //threshold at 30
low_threshold = 0.15 * STANDARD_ORGAN_THRESHOLD //threshold at 15
low_threshold = 0.2 * STANDARD_ORGAN_THRESHOLD //threshold at 15
low_threshold_passed = "<span class='info'>Distant objects become somewhat less tangible.</span>"
high_threshold_passed = "<span class='info'>Everything starts to look a lot less clear.</span>"
@@ -27,14 +31,17 @@
var/flash_protect = 0
var/see_invisible = SEE_INVISIBLE_LIVING
var/lighting_alpha
var/damaged = FALSE //damaged indicates that our eyes are undergoing some level of negative effect
var/eye_damaged = FALSE //indicates that our eyes are undergoing some level of negative effect
/obj/item/organ/eyes/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = FALSE)
. = ..()
if(!.)
return
if(damage == initial(damage))
clear_eye_trauma()
switch(eye_damaged)
if(BLURRY_VISION_ONE, BLURRY_VISION_TWO)
owner.overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, eye_damaged)
if(BLIND_VISION_THREE)
owner.become_blind(EYE_DAMAGE)
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
old_eye_color = H.eye_color
@@ -48,46 +55,49 @@
owner.update_sight()
/obj/item/organ/eyes/Remove(special = FALSE)
clear_eye_trauma()
. = ..()
var/mob/living/carbon/C = .
if(!QDELETED(C))
if(ishuman(C) && eye_color)
var/mob/living/carbon/human/H = C
H.eye_color = old_eye_color
if(!special)
H.dna.species.handle_body(H)
if(QDELETED(C))
return
switch(eye_damaged)
if(BLURRY_VISION_ONE, BLURRY_VISION_TWO)
C.clear_fullscreen("eye_damage")
if(BLIND_VISION_THREE)
C.cure_blind(EYE_DAMAGE)
if(ishuman(C) && eye_color)
var/mob/living/carbon/human/H = C
H.eye_color = old_eye_color
if(!special)
C.update_tint()
C.update_sight()
H.dna.species.handle_body(H)
if(!special)
C.update_tint()
C.update_sight()
/obj/item/organ/eyes/on_life()
..()
var/mob/living/carbon/C = owner
//since we can repair fully damaged eyes, check if healing has occurred
if((organ_flags & ORGAN_FAILING) && (damage < maxHealth))
organ_flags &= ~ORGAN_FAILING
C.cure_blind(EYE_DAMAGE)
//various degrees of "oh fuck my eyes", from "point a laser at your eye" to "staring at the Sun" intensities
if(damage > 20)
damaged = TRUE
if(organ_flags & ORGAN_FAILING)
C.become_blind(EYE_DAMAGE)
else if(damage > 30)
C.overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 2)
/obj/item/organ/eyes/applyOrganDamage(d, maximum = maxHealth)
. = ..()
if(!.)
return
var/old_damaged = eye_damaged
switch(damage)
if(INFINITY to maxHealth)
eye_damaged = BLIND_VISION_THREE
if(maxHealth to high_threshold)
eye_damaged = BLURRY_VISION_TWO
if(high_threshold to low_threshold)
eye_damaged = BLURRY_VISION_ONE
else
C.overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 1)
//called once since we don't want to keep clearing the screen of eye damage for people who are below 20 damage
else if(damaged)
damaged = FALSE
C.clear_fullscreen("eye_damage")
return
/obj/item/organ/eyes/proc/clear_eye_trauma()
var/mob/living/carbon/C = owner
C.clear_fullscreen("eye_damage")
C.cure_blind(EYE_DAMAGE)
damaged = FALSE
eye_damaged = FALSE
if(eye_damaged == old_damaged || !owner)
return
if(old_damaged == BLIND_VISION_THREE)
owner.cure_blind(EYE_DAMAGE)
else if(eye_damaged == BLIND_VISION_THREE)
owner.become_blind(EYE_DAMAGE)
if(eye_damaged && eye_damaged != BLIND_VISION_THREE)
owner.overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, eye_damaged)
else
owner.clear_fullscreen("eye_damage")
/obj/item/organ/eyes/night_vision
name = "shadow eyes"
@@ -382,4 +392,8 @@
/obj/item/organ/eyes/ipc
name = "ipc eyes"
icon_state = "cybernetic_eyeballs"
icon_state = "cybernetic_eyeballs"
#undef BLURRY_VISION_ONE
#undef BLURRY_VISION_TWO
#undef BLIND_VISION_THREE
+19 -11
View File
@@ -15,6 +15,7 @@
// Heart attack code is in code/modules/mob/living/carbon/human/life.dm
var/beating = 1
var/no_pump = FALSE
var/icon_base = "heart"
attack_verb = list("beat", "thumped")
var/beat = BEAT_NONE//is this mob having a heatbeat sound played? if so, which?
@@ -66,27 +67,28 @@
return S
/obj/item/organ/heart/on_life()
..()
. = ..()
if(!owner || no_pump)
return
if(owner.client && beating)
failed = FALSE
var/sound/slowbeat = sound('sound/health/slowbeat.ogg', repeat = TRUE)
var/sound/fastbeat = sound('sound/health/fastbeat.ogg', repeat = TRUE)
var/mob/living/carbon/H = owner
if(H.health <= H.crit_threshold && beat != BEAT_SLOW)
if(owner.health <= owner.crit_threshold && beat != BEAT_SLOW)
beat = BEAT_SLOW
H.playsound_local(get_turf(H), slowbeat,40,0, channel = CHANNEL_HEARTBEAT)
owner.playsound_local(get_turf(owner), slowbeat,40,0, channel = CHANNEL_HEARTBEAT)
to_chat(owner, "<span class = 'notice'>You feel your heart slow down...</span>")
if(beat == BEAT_SLOW && H.health > H.crit_threshold)
H.stop_sound_channel(CHANNEL_HEARTBEAT)
if(beat == BEAT_SLOW && owner.health > owner.crit_threshold)
owner.stop_sound_channel(CHANNEL_HEARTBEAT)
beat = BEAT_NONE
if(H.jitteriness)
if(H.health > HEALTH_THRESHOLD_FULLCRIT && (!beat || beat == BEAT_SLOW))
H.playsound_local(get_turf(H),fastbeat,40,0, channel = CHANNEL_HEARTBEAT)
if(owner.jitteriness)
if(owner.health > HEALTH_THRESHOLD_FULLCRIT && (!beat || beat == BEAT_SLOW))
owner.playsound_local(get_turf(owner),fastbeat,40,0, channel = CHANNEL_HEARTBEAT)
beat = BEAT_FAST
else if(beat == BEAT_FAST)
H.stop_sound_channel(CHANNEL_HEARTBEAT)
owner.stop_sound_channel(CHANNEL_HEARTBEAT)
beat = BEAT_NONE
if(organ_flags & ORGAN_FAILING) //heart broke, stopped beating, death imminent
@@ -107,6 +109,7 @@ obj/item/organ/heart/slime
icon_state = "cursedheart-off"
icon_base = "cursedheart"
decay_factor = 0
no_pump = TRUE
actions_types = list(/datum/action/item_action/organ_action/cursed_heart)
var/last_pump = 0
var/add_colour = TRUE //So we're not constantly recreating colour datums
@@ -128,6 +131,9 @@ obj/item/organ/heart/slime
return ..()
/obj/item/organ/heart/cursed/on_life()
. = ..()
if(!owner)
return
if(world.time > (last_pump + pump_delay))
if(ishuman(owner) && owner.client) //While this entire item exists to make people suffer, they can't control disconnects.
var/mob/living/carbon/human/H = owner
@@ -208,6 +214,8 @@ obj/item/organ/heart/slime
obj/item/organ/heart/cybernetic/upgraded/on_life()
. = ..()
if(!.)
return
if(dose_available && owner.health <= owner.crit_threshold && !owner.reagents.has_reagent(rid))
owner.reagents.add_reagent(rid, ramount)
used_dose()
@@ -233,7 +241,7 @@ obj/item/organ/heart/cybernetic/upgraded/on_life()
/obj/item/organ/heart/freedom/on_life()
. = ..()
if(owner.health < 5 && world.time > min_next_adrenaline)
if(. && owner.health < 5 && world.time > min_next_adrenaline)
min_next_adrenaline = world.time + rand(250, 600) //anywhere from 4.5 to 10 minutes
to_chat(owner, "<span class='userdanger'>You feel yourself dying, but you refuse to give up!</span>")
owner.heal_overall_damage(15, 15)
+15 -16
View File
@@ -25,25 +25,24 @@
var/cachedmoveCalc = 1
/obj/item/organ/liver/on_life()
var/mob/living/carbon/C = owner
. = ..()
if(!.)//can't process reagents with a failing liver
return
if(istype(C))
if(!(organ_flags & ORGAN_FAILING))//can't process reagents with a failing liver
if(filterToxins && !HAS_TRAIT(owner, TRAIT_TOXINLOVER))
//handle liver toxin filtration
for(var/datum/reagent/toxin/T in owner.reagents.reagent_list)
var/thisamount = owner.reagents.get_reagent_amount(T.type)
if (thisamount && thisamount <= toxTolerance)
owner.reagents.remove_reagent(T.type, 1)
else
damage += (thisamount*toxLethality)
if(filterToxins && !HAS_TRAIT(owner, TRAIT_TOXINLOVER))
//handle liver toxin filtration
for(var/datum/reagent/toxin/T in C.reagents.reagent_list)
var/thisamount = C.reagents.get_reagent_amount(T.type)
if (thisamount && thisamount <= toxTolerance)
C.reagents.remove_reagent(T.type, 1)
else
damage += (thisamount*toxLethality)
//metabolize reagents
owner.reagents.metabolize(owner, can_overdose=TRUE)
//metabolize reagents
C.reagents.metabolize(C, can_overdose=TRUE)
if(damage > 10 && prob(damage/3))//the higher the damage the higher the probability
to_chat(C, "<span class='warning'>You feel a dull pain in your abdomen.</span>")
if(damage > 10 && prob(damage/3))//the higher the damage the higher the probability
to_chat(owner, "<span class='warning'>You feel a dull pain in your abdomen.</span>")
/obj/item/organ/liver/prepare_eat()
var/obj/S = ..()
+9 -8
View File
@@ -446,17 +446,17 @@
if(prob(20))
to_chat(H, "<span class='warning'>You feel [hot_message] in your [name]!</span>")
/obj/item/organ/lungs/on_life()
..()
if((!failed) && ((organ_flags & ORGAN_FAILING)))
if(owner.stat == CONSCIOUS)
/obj/item/organ/lungs/applyOrganDamage(d, maximum = maxHealth)
. = ..()
if(!.)
return
if(!failed && organ_flags & ORGAN_FAILING)
if(owner && owner.stat == CONSCIOUS)
owner.visible_message("<span class='danger'>[owner] grabs [owner.p_their()] throat, struggling for breath!</span>", \
"<span class='userdanger'>You suddenly feel like you can't breathe!</span>")
failed = TRUE
else if(!(organ_flags & ORGAN_FAILING))
failed = FALSE
return
/obj/item/organ/lungs/prepare_eat()
var/obj/S = ..()
@@ -547,5 +547,6 @@
color = "#68e83a"
/obj/item/organ/lungs/yamerol/on_life()
..()
damage += 2 //Yamerol lungs are temporary
. = ..()
if(.)
applyOrganDamage(2) //Yamerol lungs are temporary
+13 -14
View File
@@ -134,18 +134,19 @@
organ_flags &= ~ORGAN_FROZEN
return FALSE
/obj/item/organ/proc/on_life() //repair organ damage if the organ is not failing
if(organ_flags & ORGAN_FAILING)
return
/obj/item/organ/proc/on_life() //repair organ damage if the organ is not failing or synthetic
if(organ_flags & ORGAN_FAILING || !owner)
return FALSE
if(is_cold())
return
///Damage decrements by a percent of its maxhealth
var/healing_amount = -(maxHealth * healing_factor)
///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's health
healing_amount -= owner.satiety > 0 ? 4 * healing_factor * owner.satiety / MAX_SATIETY : 0
if(healing_amount)
applyOrganDamage(healing_amount) //to FERMI_TWEAK
//Make it so each threshold is stuck.
return FALSE
if(damage)
///Damage decrements by a percent of its maxhealth
var/healing_amount = -(maxHealth * healing_factor)
///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's satiety
healing_amount -= owner.satiety > 0 ? 4 * healing_factor * owner.satiety / MAX_SATIETY : 0
if(healing_amount)
applyOrganDamage(healing_amount) //to FERMI_TWEAK
return TRUE
/obj/item/organ/examine(mob/user)
. = ..()
@@ -205,9 +206,7 @@
///Adjusts an organ's damage by the amount "d", up to a maximum amount, which is by default max damage
/obj/item/organ/proc/applyOrganDamage(var/d, var/maximum = maxHealth) //use for damaging effects
if(!d) //Micro-optimization.
return FALSE
if(maximum < damage)
if(!d || maximum < damage) //Micro-optimization.
return FALSE
damage = clamp(damage + d, 0, maximum)
var/mess = check_damage_thresholds()
+12 -21
View File
@@ -17,33 +17,24 @@
low_threshold_cleared = "<span class='info'>The last bouts of pain in your stomach have died out.</span>"
/obj/item/organ/stomach/on_life()
..()
var/datum/reagent/consumable/nutriment/Nutri
. = ..()
if(!owner)
return
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(!(organ_flags & ORGAN_FAILING))
if(.)
H.dna.species.handle_digestion(H)
handle_disgust(H)
Nutri = locate(/datum/reagent/consumable/nutriment) in H.reagents.reagent_list
if(Nutri)
if(prob((damage/40) * Nutri.volume * Nutri.volume))
H.vomit(damage)
to_chat(H, "<span class='warning'>Your stomach reels in pain as you're incapable of holding down all that food!</span>")
else if(Nutri && damage > high_threshold)
if(prob((damage/10) * Nutri.volume * Nutri.volume))
H.vomit(damage)
to_chat(H, "<span class='warning'>Your stomach reels in pain as you're incapable of holding down all that food!</span>")
else if(iscarbon(owner))
var/mob/living/carbon/C = owner
Nutri = locate(/datum/reagent/consumable/nutriment) in C.reagents.reagent_list
if(damage < low_threshold)
if(!damage)
return
var/datum/reagent/consumable/nutriment/Nutri = locate(/datum/reagent/consumable/nutriment) in owner.reagents.reagent_list
if(!Nutri)
return
var/prob_divisor = damage > high_threshold ? 10 : 40
if(prob((damage/prob_divisor) * (Nutri.volume**2)))
owner.vomit(damage)
to_chat(owner, "<span class='warning'>Your stomach reels in pain as you're incapable of holding down all that food!</span>")
/obj/item/organ/stomach/proc/handle_disgust(mob/living/carbon/human/H)
if(H.disgust)
+5 -1
View File
@@ -58,7 +58,10 @@
return FALSE
if(tool)
speed_mod = tool.toolspeed
if(do_after(user, time * speed_mod, target = target))
var/skill_mod = 1
if(user?.mind?.skill_holder)
skill_mod = SURGERY_SKILL_SPEEDUP_NUMERICAL_SCALE(user.mind.skill_holder.get_skill_value(/datum/skill/numerical/surgery))
if(do_after(user, time * speed_mod * skill_mod, target = target))
var/prob_chance = 100
if(implement_type) //this means it isn't a require hand or any item step.
prob_chance = implements[implement_type]
@@ -66,6 +69,7 @@
if((prob(prob_chance) || (iscyborg(user) && !silicons_obey_prob)) && chem_check(target) && !try_to_fail)
if(success(user, target, target_zone, tool, surgery))
user?.mind?.skill_holder?.auto_gain_experience(/datum/skill/numerical/surgery, SKILL_GAIN_SURGERY_PER_STEP)
advance = TRUE
else
if(failure(user, target, target_zone, tool, surgery))
+1 -1
View File
@@ -21,7 +21,7 @@
/obj/item/clothing/head/helmet/blueshirt = 1,
/obj/item/clothing/suit/armor/vest/blueshirt = 1,
/obj/item/clothing/under/rank/security/officer/blueshirt = 1,
/obj/item/clothing/gloves/tackler = 5,
/obj/item/clothing/gloves/tackler = 5,
/obj/item/ssword_kit = 1)
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF