diff --git a/code/__DEFINES/alerts.dm b/code/__DEFINES/alerts.dm index d309ebd8d2e..43ec8199d0f 100644 --- a/code/__DEFINES/alerts.dm +++ b/code/__DEFINES/alerts.dm @@ -23,6 +23,7 @@ #define ALERT_IRRADIATED "irradiated" #define ALERT_EMBEDDED_OBJECT "embeddedobject" #define ALERT_SHOES_KNOT "shoealert" +#define ALERT_RADIOACTIVE_AREA "radioactive_area" //antag related #define ALERT_HYPNOSIS "hypnosis" diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm index f5975008a16..5e6d7491d94 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm @@ -112,3 +112,5 @@ /// From /datum/element/immerse/proc/add_submerge_overlay(): (visual_overlay) #define COMSIG_MOVABLE_EDIT_UNIQUE_IMMERSE_OVERLAY "movable_edit_unique_submerge_overlay" +/// From base of area/Exited(): (area/left, direction) +#define COMSIG_MOVABLE_EXITED_AREA "movable_exited_area" diff --git a/code/__DEFINES/radiation.dm b/code/__DEFINES/radiation.dm index 2ab5860763a..0d44b072a09 100644 --- a/code/__DEFINES/radiation.dm +++ b/code/__DEFINES/radiation.dm @@ -43,7 +43,7 @@ Ask Mothblocks if they're around /// The minimum exposure time before uranium structures can irradiate #define URANIUM_RADIATION_MINIMUM_EXPOSURE_TIME (3 SECONDS) /// The minimum exposure time before the radioactive nebula can irradiate -#define NEBULA_RADIATION_MINIMUM_EXPOSURE_TIME (10 SECONDS) +#define NEBULA_RADIATION_MINIMUM_EXPOSURE_TIME (6 SECONDS) /// Return values of [proc/get_perceived_radiation_danger] // If you change these, update /datum/looping_sound/geiger as well. @@ -54,3 +54,13 @@ Ask Mothblocks if they're around /// The time before geiger counters reset back to normal without any radiation pulses #define TIME_WITHOUT_RADIATION_BEFORE_RESET (5 SECONDS) + +// Radiation exposure params + +// For the radioactive nebula outside +/// Base chance the nebula has of applying irradiation +#define RADIATION_EXPOSURE_NEBULA_BASE_CHANCE 20 +/// The chance we add to the base chance every time we fail to irradiate +#define RADIATION_EXPOSURE_NEBULA_CHANCE_INCREMENT 10 +/// Time it takes for the next irradiation check +#define RADIATION_EXPOSURE_NEBULA_CHECK_INTERVAL 5 SECONDS diff --git a/code/datums/components/radioactive_exposure.dm b/code/datums/components/radioactive_exposure.dm new file mode 100644 index 00000000000..0819b46f7df --- /dev/null +++ b/code/datums/components/radioactive_exposure.dm @@ -0,0 +1,78 @@ +/// For directly applying to carbons to irradiate them, without pulses +/datum/component/radioactive_exposure + dupe_mode = COMPONENT_DUPE_ALLOWED + + /// Base irradiation chance + var/irradiation_chance_base + /// Chance we have of applying irradiation + var/irradiation_chance + /// The amount the base chance is increased after every failed irradiation check + var/irradiation_chance_increment + /// Time till we attempt the next irradiation check + var/irradiation_interval + /// The source of irradiation, for logging + var/source + /// Area's where the component isnt removed if we cross to them + var/list/radioactive_areas + +/datum/component/radioactive_exposure/Initialize( + minimum_exposure_time, + irradiation_chance_base, + irradiation_chance_increment, + irradiation_interval, + source, + radioactive_areas + ) + + if(!iscarbon(parent)) + return COMPONENT_INCOMPATIBLE + + src.irradiation_chance_base = irradiation_chance_base + src.irradiation_chance = irradiation_chance_base + src.irradiation_chance_increment = irradiation_chance_increment + src.irradiation_interval = irradiation_interval + src.source = source + src.radioactive_areas = radioactive_areas + + // We use generally long times, so it's probably easier and more interpretable to just use a timer instead of processing the component + addtimer(CALLBACK(src, PROC_REF(attempt_irradiate)), minimum_exposure_time) + + RegisterSignal(parent, COMSIG_MOVABLE_EXITED_AREA, PROC_REF(on_exited)) + + var/mob/living/living_parent = parent + living_parent.throw_alert(ALERT_RADIOACTIVE_AREA, /atom/movable/screen/alert/radioactive_area) + +/// Try and irradiate them. If we chance fail, we come back harder +/datum/component/radioactive_exposure/proc/attempt_irradiate() + if(!SSradiation.wearing_rad_protected_clothing(parent) && SSradiation.can_irradiate_basic(parent)) + if(prob(irradiation_chance)) + SSradiation.irradiate(parent) + var/atom/atom = parent + atom.investigate_log("was irradiated by [source].", INVESTIGATE_RADIATION) + else + irradiation_chance += irradiation_chance_increment + else // we're immune, either through species, clothing, already being irradiated, etcetera + // we slowly decrease the prob chance untill we hit the base probability again + irradiation_chance = max(irradiation_chance - irradiation_chance_increment, irradiation_chance_base) + + // Even if they are immune, or got irradiated plan a new check in-case they lose their protection or irradiation + addtimer(CALLBACK(src, PROC_REF(attempt_irradiate)), irradiation_interval) + +/datum/component/radioactive_exposure/proc/on_exited(atom/movable/also_parent, area/old_area, direction) + SIGNAL_HANDLER + + if(istype(get_area(parent), radioactive_areas)) //we left to another area that is also radioactive, so dont do anything + return + + qdel(src) + +/datum/component/radioactive_exposure/Destroy(force, silent) + var/mob/living/carbon/human/human_parent = parent + human_parent.clear_alert(ALERT_RADIOACTIVE_AREA) + + return ..() + +/atom/movable/screen/alert/radioactive_area + name = "Radioactive Area" + desc = "This place is no good! We need to get some protection or get out fast!" + icon_state = ALERT_RADIOACTIVE_AREA diff --git a/code/datums/elements/radioactive.dm b/code/datums/elements/radioactive.dm index c949692930c..1ce915747aa 100644 --- a/code/datums/elements/radioactive.dm +++ b/code/datums/elements/radioactive.dm @@ -18,13 +18,13 @@ /datum/element/radioactive/New() START_PROCESSING(SSdcs, src) -/datum/element/radioactive/Attach(\ - datum/target, \ - range = 3, \ - threshold = RAD_LIGHT_INSULATION, \ - chance = URANIUM_IRRADIATION_CHANCE, \ - minimum_exposure_time = URANIUM_RADIATION_MINIMUM_EXPOSURE_TIME,\ -) +/datum/element/radioactive/Attach( + datum/target, + range = 3, + threshold = RAD_LIGHT_INSULATION, + chance = URANIUM_IRRADIATION_CHANCE, + minimum_exposure_time = URANIUM_RADIATION_MINIMUM_EXPOSURE_TIME, + ) . = ..() diff --git a/code/datums/station_traits/negative_traits.dm b/code/datums/station_traits/negative_traits.dm index 9edbb68046d..f2417eade98 100644 --- a/code/datums/station_traits/negative_traits.dm +++ b/code/datums/station_traits/negative_traits.dm @@ -545,11 +545,13 @@ VAR_PROTECTED/send_care_package_time = 5 MINUTES ///The glow of 'fake' radioactive objects in space var/nebula_radglow = "#66ff33" + /// Area's that are part of the radioactive nebula + var/radioactive_areas = /area/space /datum/station_trait/nebula/hostile/radiation/New() . = ..() - for(var/area/target as anything in get_areas(/area/space)) + for(var/area/target as anything in get_areas(radioactive_areas)) RegisterSignals(target, list(COMSIG_AREA_ENTERED, COMSIG_AREA_INITIALIZED_IN), PROC_REF(on_entered)) RegisterSignal(target, COMSIG_AREA_EXITED, PROC_REF(on_exited)) @@ -574,25 +576,32 @@ var/datum/round_event_control/modified_event = locate(/datum/round_event_control/radiation_storm) in SSevents.control modified_event.weight = 0 -///They entered space? START BOMBING WITH RADS HAHAHAHA -/datum/station_trait/nebula/hostile/radiation/proc/on_entered(area/space, atom/movable/enterer) +///They entered space? START BOMBING WITH RADS HAHAHAHA. old_area can be null for new objects +/datum/station_trait/nebula/hostile/radiation/proc/on_entered(area/space, atom/movable/enterer, area/old_area) SIGNAL_HANDLER - if(!ismovable(enterer)) - return + if(iscarbon(enterer))//Don't actually make EVERY. SINGLE. THING. RADIOACTIVE. Just irradiate people + if(!istype(old_area, radioactive_areas)) //old area wasnt radioactive + enterer.AddComponent( \ + /datum/component/radioactive_exposure, \ + minimum_exposure_time = NEBULA_RADIATION_MINIMUM_EXPOSURE_TIME, \ + irradiation_chance_base = RADIATION_EXPOSURE_NEBULA_BASE_CHANCE, \ + irradiation_chance_increment = RADIATION_EXPOSURE_NEBULA_CHANCE_INCREMENT, \ + irradiation_interval = RADIATION_EXPOSURE_NEBULA_CHECK_INTERVAL, \ + source = src, \ + radioactive_areas = radioactive_areas, \ + ) - enterer.AddElement(/datum/element/radioactive, range = 0, minimum_exposure_time = NEBULA_RADIATION_MINIMUM_EXPOSURE_TIME) - //Don't actually make EVERY. SINGLE. THING. radioactive, just make them glow so people arent killed instantly - if(!SSradiation.can_irradiate_basic(enterer)) + else if(isobj(enterer)) //and fake the rest //outline clashes too much with other outlines and creates pretty ugly lines enterer.add_filter(GLOW_NEBULA, 2, list("type" = "drop_shadow", "color" = nebula_radglow, "size" = 2)) ///Called when an atom leaves space, so we can remove the radiation effect -/datum/station_trait/nebula/hostile/radiation/proc/on_exited(area/space, atom/movable/exiter) +/datum/station_trait/nebula/hostile/radiation/proc/on_exited(area/space, atom/movable/exiter, direction) SIGNAL_HANDLER - exiter.RemoveElement(/datum/element/radioactive, range = 0, minimum_exposure_time = NEBULA_RADIATION_MINIMUM_EXPOSURE_TIME) exiter.remove_filter(GLOW_NEBULA) + // The component handles its own removal /datum/station_trait/nebula/hostile/radiation/apply_nebula_effect(effect_strength = 0) //big bombad now diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm index 8b61846c1ed..08c88cd65f1 100644 --- a/code/datums/weather/weather_types/radiation_storm.dm +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -24,6 +24,10 @@ target_trait = ZTRAIT_STATION immunity_type = TRAIT_RADSTORM_IMMUNE + /// Chance we get a negative mutation, if we fail we get a positive one + var/negative_mutation_chance = 90 + /// Chance we mutate + var/mutate_chance = 40 /datum/weather/rad_storm/telegraph() ..() @@ -31,7 +35,7 @@ /datum/weather/rad_storm/weather_act(mob/living/L) - if(!prob(40)) + if(!prob(mutate_chance)) return if(!ishuman(L)) @@ -51,11 +55,7 @@ H.random_mutate_unique_features() if(prob(50)) - if(prob(90)) - H.easy_random_mutate(NEGATIVE+MINOR_NEGATIVE) - else - H.easy_random_mutate(POSITIVE) - H.domutcheck() + do_mutate(L) /datum/weather/rad_storm/end() if(..()) @@ -63,6 +63,13 @@ priority_announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert", ANNOUNCER_RADIATIONPASSED) //SKYRAT EDIT CHANGE status_alarm(FALSE) +/datum/weather/rad_storm/proc/do_mutate(mob/living/carbon/human/mutant) + if(prob(negative_mutation_chance)) + mutant.easy_random_mutate(NEGATIVE+MINOR_NEGATIVE) + else + mutant.easy_random_mutate(POSITIVE) + mutant.domutcheck() + /datum/weather/rad_storm/proc/status_alarm(active) //Makes the status displays show the radiation warning for those who missed the announcement. var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS) if(!frequency) @@ -88,10 +95,14 @@ end_message = null + mutate_chance = 0.1 + ///Chance we pulse a living during the storm - var/radiation_chance = 20 + var/radiation_chance = 5 /datum/weather/rad_storm/nebula/weather_act(mob/living/living) + ..() + if(!prob(radiation_chance)) return @@ -103,7 +114,6 @@ max_range = 0, threshold = RAD_LIGHT_INSULATION, chance = URANIUM_IRRADIATION_CHANCE, - minimum_exposure_time = NEBULA_RADIATION_MINIMUM_EXPOSURE_TIME, ) /datum/weather/rad_storm/nebula/status_alarm(active) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 893c5e3684e..c4a02ecebbc 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -472,6 +472,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) */ /area/Exited(atom/movable/gone, direction) SEND_SIGNAL(src, COMSIG_AREA_EXITED, gone, direction) + SEND_SIGNAL(gone, COMSIG_MOVABLE_EXITED_AREA, src, direction) if(!gone.important_recursive_contents?[RECURSIVE_CONTENTS_AREA_SENSITIVE]) return diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi index 78421d72472..7cc03330969 100755 Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ diff --git a/tgstation.dme b/tgstation.dme index af15fbf999e..a0b880ad217 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1078,6 +1078,7 @@ #include "code\datums\components\puzzgrid.dm" #include "code\datums\components\radiation_countdown.dm" #include "code\datums\components\radioactive_emitter.dm" +#include "code\datums\components\radioactive_exposure.dm" #include "code\datums\components\reagent_refiller.dm" #include "code\datums\components\redirect_attack_hand_from_turf.dm" #include "code\datums\components\regenerator.dm"