diff --git a/code/__DEFINES/damage_organs.dm b/code/__DEFINES/damage_organs.dm index 9e481ca1ff6..1239ca2a0ec 100644 --- a/code/__DEFINES/damage_organs.dm +++ b/code/__DEFINES/damage_organs.dm @@ -23,6 +23,7 @@ #define DAMAGE_FLAG_DISPERSED 32 // Makes apply_damage calls without specified zone distribute damage rather than randomly choose organ (for humans) #define DAMAGE_FLAG_BIO 64 #define DAMAGE_FLAG_PSIONIC 128 +#define DAMAGE_FLAG_IGNORE_PROSTHETICS 256 // Ignores prosthetics when applying damage, for things like radiation poisoning and toxins. #define STUN "stun" #define WEAKEN "weaken" diff --git a/code/controllers/subsystems/radiation.dm b/code/controllers/subsystems/radiation.dm index 5605b81d557..5cbcb1289d9 100644 --- a/code/controllers/subsystems/radiation.dm +++ b/code/controllers/subsystems/radiation.dm @@ -28,7 +28,7 @@ SUBSYSTEM_DEF(radiation) if(QDELETED(S)) sources -= S else if(S.decay) - S.update_rad_power(S.rad_power - RADIATION_DECAY_RATE) + S.update_rad_power(S.rad_power - (RADIATION_DECAY_RATE + S.accelerated_decay_rate)) if (MC_TICK_CHECK) return @@ -122,12 +122,13 @@ SUBSYSTEM_DEF(radiation) * * This source will send out regular radiation pulses that take walls and distance into account. */ -/datum/controller/subsystem/radiation/proc/radiate(source, power) +/datum/controller/subsystem/radiation/proc/radiate(source, power, increased_decay) if(!(source && power)) //Sanity checking return var/datum/radiation_source/S = new() S.source_turf = get_turf(source) S.update_rad_power(power) + S.accelerated_decay_rate = increased_decay add_source(S) /** diff --git a/code/game/machinery/body_scanner.dm b/code/game/machinery/body_scanner.dm index bc7c1100ce7..6bc4bea2a43 100644 --- a/code/game/machinery/body_scanner.dm +++ b/code/game/machinery/body_scanner.dm @@ -473,7 +473,7 @@ data["blood_volume"] = occupant.get_blood_volume() data["blood_o2"] = blood_oxygenation data["blood_type"] = occupant.dna.b_type - data["rads"] = occupant.total_radiation + data["rads"] = occupant.total_radiation / 100 //4 Gy is a 50% chance of death, total_radiation caps at 1000. data["cloneLoss"] = get_severity(occupant.getCloneLoss(), TRUE) data["oxyLoss"] = get_severity(occupant.getOxyLoss(), TRUE) diff --git a/code/game/objects/items/devices/geiger.dm b/code/game/objects/items/devices/geiger.dm index 376aa35ccdc..7f3ef06edb8 100644 --- a/code/game/objects/items/devices/geiger.dm +++ b/code/game/objects/items/devices/geiger.dm @@ -17,6 +17,8 @@ /obj/item/geiger/feedback_hints(mob/user, distance, is_adjacent) . += ..() + if(distance > 1) + return var/msg = "[scanning ? "ambient" : "stored"] Radiation level: [radiation_count ? radiation_count : "0"] IU/s." if(radiation_count > RAD_LEVEL_VERY_LOW) . += SPAN_WARNING("[msg]") @@ -59,7 +61,6 @@ update_sound(0) return 1 - if(!sound_token) update_sound(1) switch(radiation_count) @@ -84,3 +85,140 @@ icon_state = "geiger_on_5" geiger_volume = 60 sound_token.SetVolume(geiger_volume) + +/obj/item/geiger/dosimeter + name = "combination dosimeter" + desc = "A wrist-worn device for keeping track of recieved radiation doses." + desc_extended = "This advanced radiation monitor will count up the total radiation it has received, in addition to functioning as a normal geiger counter. For it to accurately account for any protective gear, it must be worn beneath it in the wrist slot. Turn it off to reset the count." + icon = 'icons/obj/item/scanner.dmi' + icon_state = "dosimeter_off" + item_state = "dosimeter" + w_class = WEIGHT_CLASS_NORMAL + slot_flags = SLOT_WRISTS + action_button_name = "Toggle dosimeter counter" + matter = list(DEFAULT_WALL_MATERIAL = 100, MATERIAL_GLASS = 50) + origin_tech = list(TECH_MAGNET = 4, TECH_ENGINEERING = 4) + + ///The amount of rads the dosimeter has detected after armor mitigation. + var/current_rate_after_armor = 0 + ///The amount of rads the dosimeter had recorded the last time it checked, used to calculate how many new rads have been absorbed since then. + var/previous_dose = 0 + ///The number of rads the dosimeter has recieved, human max is 1000, but the dosimeter will keep counting. + var/total_dose = 0 + ///Counts up as radiation thresholds are reached, giving the user a warning each time. + var/warning_threshold = 0 + +/obj/item/geiger/dosimeter/feedback_hints(mob/user, distance, is_adjacent) + . += ..() + var/msg = "current Dose rate: [round(current_rate_after_armor,1)] IU/s." + if(current_rate_after_armor > 3) + . += SPAN_WARNING("[msg]") + else if (current_rate_after_armor > 10) + . += SPAN_DANGER("[msg]") + else + . += SPAN_NOTICE("[msg]") + + msg = "total absorbed Dose: [round(total_dose,1)] mGy." + if(total_dose > 250 && total_dose < 500) + . += SPAN_WARNING("[msg]") + else if (total_dose > 500) + . += SPAN_DANGER("[msg]") + else + . += SPAN_NOTICE("[msg]") + +/obj/item/geiger/dosimeter/attack_self(mob/user) + scanning = !scanning + if(scanning) + START_PROCESSING(SSprocessing, src) + if (ishuman(user)) + var/mob/living/carbon/human/H = user + previous_dose = H.total_radiation + else + STOP_PROCESSING(SSprocessing, src) + total_dose = 0 + warning_threshold = 0 + previous_dose = 0 + + to_chat(user, SPAN_NOTICE("[icon2html(src, user)] You switch [src] [scanning ? "on, starting the count" : "off, resetting the count"].")) + update_icon(user) + +/obj/item/geiger/dosimeter/process() + . = ..() + + if (ishuman(loc)) + var/mob/living/carbon/human/H = loc + if(H.wrists == src) + current_rate_after_armor = max(0, H.total_radiation - previous_dose) + total_dose += current_rate_after_armor //Done this way so we're not making an expensive call to check armour every tick, when apply_damage already does it. + previous_dose = total_dose + else + total_dose += radiation_count + current_rate_after_armor = radiation_count + else + total_dose += radiation_count + current_rate_after_armor = radiation_count + + switch(total_dose) + if (100 to 249) //Minor Dose + if (warning_threshold < 1) + warning_threshold++ + visible_message(SPAN_NOTICE("\The [src] chimes a notice: Minor dose recieved."), range = 1) + playsound(src, 'sound/machines/buzz-two.ogg', vol = 20, falloff_exponent = 2) + if (250 to 499) //Moderate Dose + if (warning_threshold < 2) + warning_threshold++ + visible_message(SPAN_WARNING("\The [src] chimes a warning: Moderate dose recieved. Exit radiological zone."), range = 2) + playsound(src, 'sound/machines/buzz-two.ogg', vol = 40, falloff_exponent = 2) + if (500 to 749) //Major Dose + if (warning_threshold < 3) + warning_threshold++ + visible_message(SPAN_WARNING("\The [src] beeps an alert: Major dose recieved. Exit radiological zone promptly, seek medical attention."), range = 3) + playsound(src, 'sound/machines/buzz-two.ogg', vol = 60, falloff_exponent = 2) + if (750 to 998) //Deadly Dose + if (warning_threshold < 4) + warning_threshold++ + visible_message(SPAN_DANGER("\The [src] buzzes urgently: Extreme dose recieved! Exit radiological zone immediately, seek urgent medical attention!" ), range = 5) + playsound(src, 'sound/machines/airalarm.ogg', vol = 60, falloff_exponent = 2) + if (999 to INFINITY) //Max Dose + if (warning_threshold < 5) + warning_threshold++ + visible_message(SPAN_DANGER("\The [src]'s siren screams: FATAL DOSE RECIEVED! RUN FROM RADIOLOGICAL ZONE! LIFE EXPECTANCY WITHOUT TREATMENT IS MINUTES!"), range = 7) + playsound(src, 'sound/machines/airalarm.ogg', vol = 80, falloff_exponent = 2) + +/obj/item/geiger/dosimeter/update_icon() + if(!scanning) + icon_state = "dosimeter_off" + update_sound(0) + return 1 + + if(!sound_token) + update_sound(1) + + switch(current_rate_after_armor) //Only plays the sound if you are actually taking radiation through your armour. + if(-INFINITY to RAD_LEVEL_LOW + 1) //You heal 1 rad per second, so this dose isn't dangerous. + geiger_volume = 0 + sound_token.SetVolume(geiger_volume) + if(RAD_LEVEL_LOW + 1.01 to RAD_LEVEL_MODERATE) + geiger_volume = 5 + sound_token.SetVolume(geiger_volume) + if(RAD_LEVEL_MODERATE + 0.1 to RAD_LEVEL_HIGH) + geiger_volume = 10 + sound_token.SetVolume(geiger_volume) + if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH) + geiger_volume = 20 + sound_token.SetVolume(geiger_volume) + if(RAD_LEVEL_VERY_HIGH + 1 to INFINITY) + geiger_volume = 40 + sound_token.SetVolume(geiger_volume) + + switch(total_dose) + if (-INFINITY to 99) //Negligable dose + icon_state = "dosimeter_on_1" + if (100 to 249) //Minor Dose + icon_state = "dosimeter_on_2" + if (250 to 499) //Moderate Dose + icon_state = "dosimeter_on_3" + if (500 to 749) //Major Dose + icon_state = "dosimeter_on_4" + if (750 to INFINITY) //Deadly Dose + icon_state = "dosimeter_on_5" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index 63f29261487..6c63287cb1d 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -32,6 +32,7 @@ new /obj/item/storage/lockbox/shuttle_blueprints(src) new /obj/item/blueprints/outpost(src) new /obj/item/base_planning_blueprints(src) + new /obj/item/geiger/dosimeter(src) // Chief Engineer - Clothing Satchel // This satchel is used nowhere except in conjunction with the locker above, diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 195b8f7a934..c4ae7bcc783 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -354,10 +354,9 @@ result = abs(result - 100) return round(result) - /obj/item/clothing/proc/update_armor() if(material) - var/melee_armor = 0, bullet_armor = 0, laser_armor = 0, energy_armor = 0, bomb_armor = 0 + var/melee_armor = 0, bullet_armor = 0, laser_armor = 0, energy_armor = 0, bomb_armor = 0, rad_armor = 0 melee_armor = calculate_material_armor(material.protectiveness * material_armor_modifer) @@ -371,8 +370,9 @@ bomb_armor = calculate_material_armor((material.protectiveness * material_armor_modifer) * 0.5) + rad_armor = calculate_material_armor(((material.weight * material_armor_modifer) * 5) - 70) //Weight 15 (glass): 5%, Weight 23(steel): 45%, Weight 32 (lead): 90%. Material armour doesn't cover limbs, so 90% isn't as good as it seems. // Makes sure the numbers stay capped. - for(var/number in list(melee_armor, bullet_armor, laser_armor, energy_armor, bomb_armor)) + for(var/number in list(melee_armor, bullet_armor, laser_armor, energy_armor, bomb_armor, rad_armor)) number = between(0, number, 100) var/datum/component/armor/armor_component = GetComponent(/datum/component/armor) @@ -383,7 +383,8 @@ bullet = bullet_armor, laser = laser_armor, energy = energy_armor, - bomb = bomb_armor + bomb = bomb_armor, + rad = rad_armor ) AddComponent(/datum/component/armor, armor_list) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index e758f917f65..38d344926f4 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -481,6 +481,10 @@ This function restores all organs. def_zone = ran_zone(def_zone) organ = get_organ(check_zone(def_zone)) + if(damage_flags & DAMAGE_FLAG_IGNORE_PROSTHETICS) + if(BP_IS_ROBOTIC(organ)) + return FALSE + //Handle other types of damage if(!(damagetype in list(DAMAGE_BRUTE, DAMAGE_BURN, DAMAGE_PAIN, DAMAGE_CLONE))) if(!stat && damagetype == DAMAGE_PAIN) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 8b662af405c..74f56973390 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -2,25 +2,49 @@ //NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick! -#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point -#define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point -#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 1000K point +///Amount of damage applied when your body temperature just passes the 360.15k safety point +#define HEAT_DAMAGE_LEVEL_1 2 +///Amount of damage applied when your body temperature passes the 400K point +#define HEAT_DAMAGE_LEVEL_2 4 +///Amount of damage applied when your body temperature passes the 1000K point +#define HEAT_DAMAGE_LEVEL_3 8 -#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point -#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point -#define COLD_DAMAGE_LEVEL_3 3 //Amount of damage applied when your body temperature passes the 120K point +///Amount of damage applied when your body temperature just passes the 260.15k safety point +#define COLD_DAMAGE_LEVEL_1 0.5 +///Amount of damage applied when your body temperature passes the 200K point +#define COLD_DAMAGE_LEVEL_2 1.5 +///Amount of damage applied when your body temperature passes the 120K point +#define COLD_DAMAGE_LEVEL_3 3 //Note that gas heat damage is only applied once every FOUR ticks. -#define HEAT_GAS_DAMAGE_LEVEL_1 2 //Amount of damage applied when the current breath's temperature just passes the 360.15k safety point -#define HEAT_GAS_DAMAGE_LEVEL_2 4 //Amount of damage applied when the current breath's temperature passes the 400K point -#define HEAT_GAS_DAMAGE_LEVEL_3 8 //Amount of damage applied when the current breath's temperature passes the 1000K point +///Amount of damage applied when the current breath's temperature just passes the 360.15k safety point +#define HEAT_GAS_DAMAGE_LEVEL_1 2 +///Amount of damage applied when the current breath's temperature passes the 400K point +#define HEAT_GAS_DAMAGE_LEVEL_2 4 +///Amount of damage applied when the current breath's temperature passes the 1000K point +#define HEAT_GAS_DAMAGE_LEVEL_3 8 -#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 260.15k safety point -#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point -#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point +///Amount of damage applied when the current breath's temperature just passes the 260.15k safety point +#define COLD_GAS_DAMAGE_LEVEL_1 0.5 +///Amount of damage applied when the current breath's temperature passes the 200K point +#define COLD_GAS_DAMAGE_LEVEL_2 1.5 +///Amount of damage applied when the current breath's temperature passes the 120K point +#define COLD_GAS_DAMAGE_LEVEL_3 3 +///Multiplies the speed at which radiation is processed. #define RADIATION_SPEED_COEFFICIENT 0.1 +///A dose below this level causes no symptoms. +#define RADIATION_NEGLIGABLE_DOSE 100 +///A dose above this level causes minor symptoms; nausea, vomiting, headaches. +#define RADIATION_MINOR_DOSE 250 +///A dose above this level causes slight organ damage and major symptoms; slowdown, confusion, hallucinations. Usually survivable with consequences. +#define RADIATION_MAJOR_DOSE 500 +///A dose above this level causes heavy organ damage and debilitating symptoms, bleeding, weakness, cloneloss. Usually fatal without treatment. +#define RADIATION_DEADLY_DOSE 750 +///The maximum dose that can be received, above this level all further radiation is taken as damage directly to the body, ignoring armor. Very rapidly fatal. +#define RADIATION_MAX_DOSE 1000 + /mob/living/carbon/human var/oxygen_alert = 0 var/phoron_alert = 0 @@ -199,7 +223,7 @@ if(aid < 3 && prob(10/aid)) //NOSTUTTER at 2 or above prevents it completely. stuttering = max(10/aid, stuttering) -/mob/living/carbon/human/handle_mutations_and_radiation() +/mob/living/carbon/human/handle_mutations_and_radiation(seconds_per_tick) if(InStasis()) return @@ -214,47 +238,85 @@ if(gene.is_active(src)) gene.OnMobLife(src) - total_radiation = clamp(total_radiation,0,100) + /** radiation damage **/ if (total_radiation) if(src.is_diona()) + total_radiation = clamp(total_radiation,0,100) //Dionae processing assumes the radiation will cap at 100. diona_handle_regeneration(get_dionastats()) return - else - var/damage = 0 - total_radiation -= 1 * RADIATION_SPEED_COEFFICIENT - if(prob(25)) - damage = 2 - if (total_radiation > 50) - damage = 3 - total_radiation -= 1 * RADIATION_SPEED_COEFFICIENT - if(prob(5) && prob(100 * RADIATION_SPEED_COEFFICIENT)) - src.apply_radiation(-5 * RADIATION_SPEED_COEFFICIENT) - to_chat(src, SPAN_WARNING("You feel weak.")) - Weaken(3) - if(!lying) - emote("collapse") + if (total_radiation > RADIATION_MAX_DOSE) //Radiation exceeding the maximum threshold causes immediate burns, ignoring armour. + apply_damage(max((total_radiation - RADIATION_MAX_DOSE) * RADIATION_SPEED_COEFFICIENT, 0), DAMAGE_BURN, null, "Radiation Burns", DAMAGE_FLAG_DISPERSED | DAMAGE_FLAG_IGNORE_PROSTHETICS) - if (total_radiation > 75) - src.apply_radiation(-1 * RADIATION_SPEED_COEFFICIENT) - damage = 7 - if(prob(5)) - take_overall_damage(0, 10 * RADIATION_SPEED_COEFFICIENT, used_weapon = "Radiation Burns") - to_chat(src, SPAN_WARNING("You feel a burning sensation!")) - if(prob(1)) - to_chat(src, SPAN_WARNING("You feel strange!")) - adjustCloneLoss(5 * RADIATION_SPEED_COEFFICIENT) - emote("gasp") - hallucination = max(hallucination, 20) //At this level, you're in a constant state of low-level hallucinations. As if you didn't have enough problems. + total_radiation = clamp(total_radiation,0,RADIATION_MAX_DOSE) //The maximum dose that can be received, above this level all further radiation is taken as damage directly to the body, ignoring armor. Very rapidly fatal. + var/damage = 0 - if(damage) - adjustToxLoss(damage * RADIATION_SPEED_COEFFICIENT) - updatehealth() - if(organs.len) - var/obj/item/organ/external/O = pick(organs) - if(istype(O)) O.add_autopsy_data("Radiation Poisoning", damage) + src.apply_radiation(-1 * RADIATION_SPEED_COEFFICIENT * seconds_per_tick) + + if (total_radiation >= RADIATION_DEADLY_DOSE && total_radiation <= RADIATION_MAX_DOSE) //A dose above this level causes heavy organ damage and debilitating symptoms, bleeding, weakness, cloneloss. Usually fatal without treatment. + damage = 3.6 //Net 1.2 damage per second on a healthy liver, because the liver heals for 6 and net 0.1 damage on a victim with dylovene. + hallucination = max(hallucination, 20) + sprint_speed_factor -= 0.3 + sprint_cost_factor += 0.5 + if (prob(total_radiation/200)) //3.75 to 5% chance, scaling with rad level. + adjustCloneLoss(5) + if (prob(total_radiation/200)) + Weaken(3) + if(!lying) + emote("collapse") + if (prob(total_radiation/200)) + to_chat(src, SPAN_DANGER("Patches of your skin burn and slough off!")) + apply_damage(30, DAMAGE_BURN, null, "Radiation Sickness", DAMAGE_FLAG_DISPERSED | DAMAGE_FLAG_IGNORE_PROSTHETICS) + if (prob(total_radiation/200)) + to_chat(src, SPAN_WARNING("You feel terribly sick, everything aches!")) + apply_damage(30, DAMAGE_PAIN, null, "Radiation Sickness", DAMAGE_FLAG_DISPERSED) + delayed_vomit() + if (prob(total_radiation/200)) + to_chat(src, SPAN_WARNING("Your head aches horribly and it's getting hard to walk straight!")) + confused = max(confused, 100) + apply_damage(15, DAMAGE_PAIN, BP_HEAD, "Radiation Sickness") + + else if (total_radiation >= RADIATION_MAJOR_DOSE && total_radiation < RADIATION_DEADLY_DOSE) //A dose above this level causes slight organ damage and major symptoms; slowdown, confusion, hallucinations. Usually survivable with consequences. + damage = 3.1 //Net 0.2 damage per second on a healthy liver, because it heals for 6. + hallucination = max(hallucination, 20) + sprint_speed_factor -= 0.1 + sprint_cost_factor += 0.25 + + if (prob(total_radiation/200)) //2.5 to 3.75% chance, scaling with rad level. + to_chat(src, SPAN_WARNING("Your head aches horribly and your vision blurrs!")) + eye_blurry = max(eye_blurry, 50) + apply_damage(15, DAMAGE_PAIN, BP_HEAD, "Radiation Sickness") + if (prob(total_radiation/200)) + to_chat(src, SPAN_WARNING("You ache all over and it's getting hard to walk straight!")) + confused = max(confused, 50) + apply_damage(10, DAMAGE_PAIN, null, "Radiation Sickness", DAMAGE_FLAG_DISPERSED) + if (prob(total_radiation/200)) + to_chat(src, SPAN_WARNING("You feel terribly sick; your stomach twists painfully!")) + apply_damage(10, DAMAGE_PAIN, BP_CHEST, "Radiation Sickness") + delayed_vomit() + + else if (total_radiation >= RADIATION_MINOR_DOSE && total_radiation < RADIATION_MAJOR_DOSE) //A dose above this level causes minor symptoms; nausea, vomiting, headaches, tiredness. + damage = 2.1 //Net 0.2 damage per second on a damaged liver, because it heals for 4. + sprint_cost_factor += 0.15 + if (prob(total_radiation/100)) //2.5 to 5% chance, scaling with rad level. + to_chat(src, SPAN_WARNING("You feel sick!")) + delayed_vomit() + if (prob(total_radiation/100)) + to_chat(src, SPAN_WARNING("You have a splitting headache!")) + apply_damage(10, DAMAGE_PAIN, BP_HEAD, "Radiation Sickness") + + else if (total_radiation >= RADIATION_NEGLIGABLE_DOSE && total_radiation < RADIATION_MINOR_DOSE) //A dose below this level causes no symptoms. + if(prob(3)) + to_chat(src, SPAN_NOTICE("You feel a little sick.")) + + if(damage) + adjustToxLoss(damage * RADIATION_SPEED_COEFFICIENT * seconds_per_tick) + updatehealth() + if(organs.len) + var/obj/item/organ/external/O = pick(organs) + if(istype(O)) O.add_autopsy_data("Radiation Poisoning", damage) /** breathing **/ diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 2ee3398ab75..69d198e9096 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -25,7 +25,7 @@ aura_check(AURA_TYPE_LIFE) if(!InStasis()) //Mutations and radiation - handle_mutations_and_radiation() + handle_mutations_and_radiation(seconds_per_tick) //Check if we're on fire handle_fire(seconds_per_tick, environment) @@ -52,10 +52,10 @@ /mob/living/proc/handle_breathing() return -/mob/living/proc/handle_mutations_and_radiation() +/mob/living/proc/handle_chemicals_in_body() return -/mob/living/proc/handle_chemicals_in_body() +/mob/living/proc/handle_mutations_and_radiation(seconds_per_tick) return /mob/living/proc/handle_random_events() diff --git a/code/modules/radiation/radiation.dm b/code/modules/radiation/radiation.dm index c1f85c88735..9e52c54b5a2 100644 --- a/code/modules/radiation/radiation.dm +++ b/code/modules/radiation/radiation.dm @@ -7,6 +7,8 @@ var/rad_power /// True for automatic decay. False if owner promises to handle it (i.e. Supermatter, INDRA, etc.) var/decay = TRUE + ///Added to the base decay rate of a source, for sudden spikes of radiation that don't persist as long + var/accelerated_decay_rate /// True for not affecting AREA_FLAG_RAD_SHIELDED areas. var/respect_rad_shielding = FALSE /// True for power falloff with distance. @@ -92,6 +94,7 @@ */ /mob/living/rad_act(severity) if(severity > RAD_LEVEL_VERY_LOW) - apply_damage(severity, DAMAGE_RADIATION, damage_flags = DAMAGE_FLAG_DISPERSED) + var/normal_armour_piercing = severity - (severity / 11) //As damage is split across all 11 limbs, this is subtracted from the armour value to replicate one big hit. + apply_damage(severity, DAMAGE_RADIATION, damage_flags = DAMAGE_FLAG_DISPERSED | DAMAGE_FLAG_IGNORE_PROSTHETICS, armor_pen = normal_armour_piercing) //Metal body parts do not contribute to radiation dose. for(var/atom/I in src) I.rad_act(severity) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm index d9c6bf45cac..9c9fe4d4728 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm @@ -888,7 +888,7 @@ //metabolism = REM * 0.22 M.adjustToxLoss(45 * removed * (0.22/0.25)) // Multiplier is to replace the above line else - M.apply_radiation(-30 * removed) + M.apply_radiation(-90 * removed) /singleton/reagent/hyronalin/overdose(var/mob/living/carbon/M, var/alien, var/removed, var/datum/reagents/holder) if(prob(60)) @@ -919,10 +919,10 @@ //metabolism = REM * 0.195 M.adjustToxLoss(115 * removed * (0.195/0.25)) // Multiplier is to replace the above line else - M.apply_radiation(-70 * removed) + M.apply_radiation(-280 * removed) M.add_chemical_effect(CE_ITCH, M.chem_doses[type]/2) if(prob(60)) - M.take_organ_damage(4 * removed, 0) + M.take_organ_damage(8 * removed, 0) /singleton/reagent/arithrazine/overdose(var/mob/living/carbon/M, var/alien, var/removed, var/datum/reagents/holder) if(prob(50)) diff --git a/code/modules/research/designs/protolathe/tool_designs.dm b/code/modules/research/designs/protolathe/tool_designs.dm index 3c6f6c6b31c..fe828ce8b56 100644 --- a/code/modules/research/designs/protolathe/tool_designs.dm +++ b/code/modules/research/designs/protolathe/tool_designs.dm @@ -20,6 +20,11 @@ req_tech = list(TECH_ENGINEERING = 6, TECH_MATERIAL = 5) build_path = /obj/item/overcapacitor +/datum/design/item/tool/dosimeter + req_tech = list(TECH_ENGINEERING = 4, TECH_MAGNET = 4) + materials = list(DEFAULT_WALL_MATERIAL = 100, MATERIAL_GLASS = 50) + build_path = /obj/item/geiger/dosimeter + /datum/design/item/tool/advanced_light_replacer desc = "A specialised light replacer which stores more lights, refills faster from boxes, and sucks up broken bulbs." req_tech = list(TECH_MAGNET = 3, TECH_MATERIAL = 4) diff --git a/code/modules/supermatter/supermatter.dm b/code/modules/supermatter/supermatter.dm index 71573a52870..f8d7fb6a18c 100644 --- a/code/modules/supermatter/supermatter.dm +++ b/code/modules/supermatter/supermatter.dm @@ -16,20 +16,28 @@ DAMAGE_RATE_LIMIT Controls the maximum rate at which the SM will take damage due to high temperatures. */ -//Controls how much power is produced by each collector in range - this is the main parameter for tweaking SM balance, as it basically controls how the power variable relates to the rest of the game. +///Controls how much power is produced by each collector in range - this is the main parameter for tweaking SM balance, as it basically controls how the power variable relates to the rest of the game. #define POWER_FACTOR 1.0 -#define DECAY_FACTOR 700 //Affects how fast the supermatter power decays -#define CRITICAL_TEMPERATURE 5000 //K +///Affects how fast the supermatter power decays +#define DECAY_FACTOR 700 +///The temperature at which the SM starts taking damage. +#define CRITICAL_TEMPERATURE 5000//K +///Controls how much emitter shots excite the SM. #define CHARGING_FACTOR 0.05 -#define DAMAGE_RATE_LIMIT 4 //damage rate cap at power = 300, scales linearly with power -#define SPACED_DAMAGE_FACTOR 0.5 //multiplier for damage taken in a vacuum, but on a tile. Used to prevent/configure near-instant explosions when vented +///damage rate cap at power = 300, scales linearly with power +#define DAMAGE_RATE_LIMIT 4 +///multiplier for damage taken in a vacuum, but on a tile. Used to prevent/configure near-instant explosions when vented +#define SPACED_DAMAGE_FACTOR 0.5 -//These would be what you would get at point blank, decreases with distance -#define DETONATION_RADS 200 +//These would be what you would get at point blank, does NOT decrease with distance. +///The amount of radiation the whole Z level (except maintenance) will recieve. Rads decay slowly over time. This will give an unprotected person 1275 rads over 100 seconds. +#define DETONATION_RADS 50 +///How many seconds of halucinations affected mobs are given. #define DETONATION_HALLUCINATION 600 - - -#define WARNING_DELAY 20 //seconds between warnings. +///This creates a radiation source of strength 500 at the explosion site. This will kill through a radsuit but falls off rapidly with distance. +#define LOCAL_DETONATION_RADS 500 +///Seconds between warnings. +#define WARNING_DELAY 20 ///to prevent accent sounds from layering #define SUPERMATTER_ACCENT_SOUND_MIN_COOLDOWN 2 SECONDS @@ -142,6 +150,7 @@ var/mob/living/carbon/human/H = mob H.hallucination += max(50, min(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, src) + 1)) ) ) SSradiation.z_radiate(locate(1, 1, z), DETONATION_RADS, TRUE) + SSradiation.radiate(src, LOCAL_DETONATION_RADS) spawn(pull_time) explosion(get_turf(src), explosion_power, explosion_power * 2, explosion_power * 3, explosion_power * 4, 1) qdel(src) @@ -182,8 +191,9 @@ radio.autosay(alert_msg, "Supermatter Monitor", "Engineering") //Public alerts if((damage > emergency_point) && !public_alert) - radio.autosay("WARNING: SUPERMATTER CRYSTAL DELAMINATION IMMINENT!", "Supermatter Monitor") + radio.autosay("WARNING: SUPERMATTER CRYSTAL DELAMINATION IMMINENT! EVACUATE INTO MAINTAINANCE IMMEDIATELY!" , "Supermatter Monitor") //Adds a warning that lets people know maint is safe. public_alert = 1 + make_maint_all_access() //Radiation will persist for a long time after the explosion, so we want to make sure people can get into maint to avoid it. for(var/mob/M in GLOB.player_list) var/turf/T = get_turf(M) if(T && !istype(M, /mob/abstract/new_player) && !isdeaf(M)) diff --git a/html/changelogs/Fenodyree-RadiationDamageRework.yml b/html/changelogs/Fenodyree-RadiationDamageRework.yml new file mode 100644 index 00000000000..300d87de45f --- /dev/null +++ b/html/changelogs/Fenodyree-RadiationDamageRework.yml @@ -0,0 +1,65 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# - (fixes bugs) +# wip +# - (work in progress) +# qol +# - (quality of life) +# soundadd +# - (adds a sound) +# sounddel +# - (removes a sound) +# rscadd +# - (adds a feature) +# rscdel +# - (removes a feature) +# imageadd +# - (adds an image or sprite) +# imagedel +# - (removes an image or sprite) +# spellcheck +# - (fixes spelling or grammar) +# experiment +# - (experimental change) +# balance +# - (balance changes) +# code_imp +# - (misc internal code change) +# refactor +# - (refactors code) +# config +# - (makes a change to the config files) +# admin +# - (makes changes to administrator tools) +# server +# - (miscellaneous changes to server) +################################# + +# Your name. +author: Fenodyree + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit. +# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Adds a dosimeter. Engineering spawns with two. Counts the amount of radiation it's wearer takes and calculates the real rate of exposure after armor." + - imageadd: "Adds sprites to the dosimeter courtesy of The_Ill_fated, with a big thanks!" + - rscadd: "Adds an instruction to shelter in maintanance to the Supermatter Delamination alert. Also unlocks maintanance when it does." + - rscadd: "Adds radiation armour values to makeshift armour, based on weight. Lead plate on the chest blocks 90% of radiation to the chest. Does nothing for your arms and legs though." + - rscadd: "Adds a damage flag that makes certain hits ignore mechanical limbs. Useful for radiation, which shouldn't give metal radaiation burns." + - balance: "Multiplies the max radiation level by 10, to 1000. This means radiation takes much logner to accumulate, radiation protection that isn't the radsuit is worth it now." + - balance: "Increaes the lethality of maximum radiation doses. Any radiation over your maximum is dealt as burn damage." + - balance: "Rebalances radiation damage to be more painful, with more side effects, but less organ damage except at the highest levels." diff --git a/icons/obj/item/scanner.dmi b/icons/obj/item/scanner.dmi index cbc6186420b..3fc5e4edd32 100644 Binary files a/icons/obj/item/scanner.dmi and b/icons/obj/item/scanner.dmi differ diff --git a/maps/sccv_horizon/sccv_horizon.dmm b/maps/sccv_horizon/sccv_horizon.dmm index a425dd69fcb..d55ec3528a7 100644 --- a/maps/sccv_horizon/sccv_horizon.dmm +++ b/maps/sccv_horizon/sccv_horizon.dmm @@ -113254,7 +113254,7 @@ pixel_x = 6; pixel_y = 7 }, -/obj/item/geiger, +/obj/item/geiger/dosimeter, /turf/simulated/floor/tiled/dark/full, /area/horizon/engineering/reactor/indra/monitoring) "oWz" = (