mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Merge pull request #3465 from Yoshax/radiation
Ports radiation rework and stuff from Bay
This commit is contained in:
56
code/controllers/Processes/radiation.dm
Normal file
56
code/controllers/Processes/radiation.dm
Normal file
@@ -0,0 +1,56 @@
|
||||
/datum/controller/process/radiation
|
||||
var/repository/radiation/linked = null
|
||||
|
||||
/datum/controller/process/radiation/setup()
|
||||
name = "radiation controller"
|
||||
schedule_interval = 20 // every 2 seconds
|
||||
linked = radiation_repository
|
||||
|
||||
/datum/controller/process/radiation/doWork()
|
||||
sources_decay()
|
||||
cache_expires()
|
||||
irradiate_targets()
|
||||
|
||||
// Step 1 - Sources Decay
|
||||
/datum/controller/process/radiation/proc/sources_decay()
|
||||
var/list/sources = linked.sources
|
||||
for(var/thing in sources)
|
||||
if(deleted(thing))
|
||||
sources.Remove(thing)
|
||||
continue
|
||||
var/datum/radiation_source/S = thing
|
||||
if(S.decay)
|
||||
S.update_rad_power(S.rad_power - config.radiation_decay_rate)
|
||||
if(S.rad_power <= config.radiation_lower_limit)
|
||||
sources.Remove(S)
|
||||
SCHECK // This scheck probably just wastes resources, but better safe than sorry in this case.
|
||||
|
||||
// Step 2 - Cache Expires
|
||||
/datum/controller/process/radiation/proc/cache_expires()
|
||||
var/list/resistance_cache = linked.resistance_cache
|
||||
for(var/thing in resistance_cache)
|
||||
if(deleted(thing))
|
||||
resistance_cache.Remove(thing)
|
||||
continue
|
||||
var/turf/T = thing
|
||||
if((length(T.contents) + 1) != resistance_cache[T])
|
||||
resistance_cache.Remove(T) // If its stale REMOVE it! It will get added if its needed.
|
||||
SCHECK
|
||||
|
||||
// Step 3 - Registered irradiatable things are checked for radiation
|
||||
/datum/controller/process/radiation/proc/irradiate_targets()
|
||||
var/list/registered_listeners = living_mob_list // For now just use this. Nothing else is interested anyway.
|
||||
if(length(linked.sources) > 0)
|
||||
for(var/thing in registered_listeners)
|
||||
if(deleted(thing))
|
||||
continue
|
||||
var/atom/A = thing
|
||||
var/turf/T = get_turf(thing)
|
||||
var/rads = linked.get_rads_at_turf(T)
|
||||
if(rads)
|
||||
A.rad_act(rads)
|
||||
SCHECK
|
||||
|
||||
/datum/controller/process/radiation/statProcess()
|
||||
..()
|
||||
stat(null, "[linked.sources.len] sources, [linked.resistance_cache.len] cached turfs")
|
||||
@@ -219,6 +219,10 @@ var/list/gamemode_cache = list()
|
||||
|
||||
var/show_human_death_message = 1
|
||||
|
||||
var/radiation_decay_rate = 1 //How much radiation is reduced by each tick
|
||||
var/radiation_resistance_multiplier = 6.5
|
||||
var/radiation_lower_limit = 0.35 //If the radiation level for a turf would be below this, ignore it.
|
||||
|
||||
/datum/configuration/New()
|
||||
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
|
||||
for (var/T in L)
|
||||
@@ -716,6 +720,9 @@ var/list/gamemode_cache = list()
|
||||
if(values.len > 0)
|
||||
language_prefixes = values
|
||||
|
||||
if("radiation_lower_limit")
|
||||
radiation_lower_limit = text2num(value)
|
||||
|
||||
else
|
||||
log_misc("Unknown setting in configuration: '[name]'")
|
||||
|
||||
|
||||
139
code/datums/repositories/radiation.dm
Normal file
139
code/datums/repositories/radiation.dm
Normal file
@@ -0,0 +1,139 @@
|
||||
var/global/repository/radiation/radiation_repository = new()
|
||||
|
||||
/repository/radiation
|
||||
var/list/sources = list() // all radiation source datums
|
||||
var/list/sources_assoc = list() // Sources indexed by turf for de-duplication.
|
||||
var/list/resistance_cache = list() // Cache of turf's radiation resistance.
|
||||
|
||||
// Describes a point source of radiation. Created either in response to a pulse of radiation, or over an irradiated atom.
|
||||
// Sources will decay over time, unless something is renewing their power!
|
||||
/datum/radiation_source
|
||||
var/turf/source_turf // Location of the radiation source.
|
||||
var/rad_power // Strength of the radiation being emitted.
|
||||
var/decay = TRUE // True for automatic decay. False if owner promises to handle it (i.e. supermatter)
|
||||
var/respect_maint = FALSE // True for not affecting RAD_SHIELDED areas.
|
||||
var/flat = FALSE // True for power falloff with distance.
|
||||
var/range // Cached maximum range, used for quick checks against mobs.
|
||||
|
||||
/datum/radiation_source/Destroy()
|
||||
radiation_repository.sources -= src
|
||||
if(radiation_repository.sources_assoc[src.source_turf] == src)
|
||||
radiation_repository.sources -= src.source_turf
|
||||
src.source_turf = null
|
||||
. = ..()
|
||||
|
||||
// TEMPORARY HACK - hard del()'ing sources is too expensive! Until we implement qdel() hints we need to override behavior here
|
||||
/datum/radiation_source/finalize_qdel()
|
||||
if(garbage_collector)
|
||||
garbage_collector.AddTrash(src)
|
||||
else
|
||||
delayed_garbage |= src
|
||||
// TEMPORARY HACK END
|
||||
|
||||
/datum/radiation_source/proc/update_rad_power(var/new_power = null)
|
||||
if(new_power != null && new_power != rad_power)
|
||||
rad_power = new_power
|
||||
. = 1
|
||||
if(. && !flat)
|
||||
range = min(round(sqrt(rad_power / config.radiation_lower_limit)), 31) // R = rad_power / dist**2 - Solve for dist
|
||||
|
||||
// Ray trace from all active radiation sources to T and return the strongest effect.
|
||||
/repository/radiation/proc/get_rads_at_turf(var/turf/T)
|
||||
if(!istype(T)) return 0
|
||||
|
||||
. = 0
|
||||
for(var/value in sources)
|
||||
var/datum/radiation_source/source = value
|
||||
if(source.rad_power < .)
|
||||
continue // Already being affected by a stronger source
|
||||
var/dist = get_dist(source.source_turf, T)
|
||||
if(dist > source.range)
|
||||
continue // Too far to possibly affect
|
||||
if(source.respect_maint)
|
||||
var/atom/A = T.loc
|
||||
if(A.flags & RAD_SHIELDED)
|
||||
continue // In shielded area
|
||||
if(source.flat)
|
||||
. = max(., source.rad_power)
|
||||
continue // No need to ray trace for flat field
|
||||
|
||||
// Okay, now ray trace to find resistence!
|
||||
var/turf/origin = source.source_turf
|
||||
var/working = source.rad_power
|
||||
while(origin != T)
|
||||
origin = get_step_towards(origin, T) //Raytracing
|
||||
if(!(origin in resistance_cache)) //Only get the resistance if we don't already know it.
|
||||
origin.calc_rad_resistance()
|
||||
working = max((working - (origin.cached_rad_resistance * config.radiation_resistance_multiplier)), 0)
|
||||
if(working <= .)
|
||||
break // Already affected by a stronger source (or its zero...)
|
||||
. = max((working * (1 / (dist ** 2))), .) //Butchered version of the inverse square law. Works for this purpose
|
||||
|
||||
// Add a radiation source instance to the repository. It will override any existing source on the same turf.
|
||||
/repository/radiation/proc/add_source(var/datum/radiation_source/S)
|
||||
var/datum/radiation_source/existing = sources_assoc[S.source_turf]
|
||||
if(existing)
|
||||
qdel(existing)
|
||||
sources += S
|
||||
sources_assoc[S.source_turf] = S
|
||||
|
||||
// Creates a temporary radiation source that will decay
|
||||
/repository/radiation/proc/radiate(source, power) //Sends out a radiation pulse, taking walls into account
|
||||
if(!(source && power)) //Sanity checking
|
||||
return
|
||||
var/datum/radiation_source/S = new()
|
||||
S.source_turf = get_turf(source)
|
||||
S.update_rad_power(power)
|
||||
add_source(S)
|
||||
|
||||
// Sets the radiation in a range to a constant value.
|
||||
/repository/radiation/proc/flat_radiate(source, power, range, var/respect_maint = FALSE)
|
||||
if(!(source && power && range))
|
||||
return
|
||||
var/datum/radiation_source/S = new()
|
||||
S.flat = TRUE
|
||||
S.range = range
|
||||
S.respect_maint = respect_maint
|
||||
S.source_turf = get_turf(source)
|
||||
S.update_rad_power(power)
|
||||
add_source(S)
|
||||
|
||||
// Irradiates a full Z-level. Hacky way of doing it, but not too expensive.
|
||||
/repository/radiation/proc/z_radiate(var/atom/source, power, var/respect_maint = FALSE)
|
||||
if(!(power && source))
|
||||
return
|
||||
var/turf/epicentre = locate(round(world.maxx / 2), round(world.maxy / 2), source.z)
|
||||
flat_radiate(epicentre, power, world.maxx, respect_maint)
|
||||
|
||||
/turf
|
||||
var/cached_rad_resistance = 0
|
||||
|
||||
/turf/proc/calc_rad_resistance()
|
||||
cached_rad_resistance = 0
|
||||
for(var/obj/O in src.contents)
|
||||
if(O.rad_resistance) //Override
|
||||
cached_rad_resistance += O.rad_resistance
|
||||
|
||||
else if(O.density) //So open doors don't get counted
|
||||
var/material/M = O.get_material()
|
||||
if(!M) continue
|
||||
cached_rad_resistance += M.weight
|
||||
// Looks like storing the contents length is meant to be a basic check if the cache is stale due to items enter/exiting. Better than nothing so I'm leaving it as is. ~Leshana
|
||||
radiation_repository.resistance_cache[src] = (length(contents) + 1)
|
||||
|
||||
/turf/simulated/wall/calc_rad_resistance()
|
||||
radiation_repository.resistance_cache[src] = (length(contents) + 1)
|
||||
cached_rad_resistance = (density ? material.weight : 0)
|
||||
|
||||
/obj
|
||||
var/rad_resistance = 0 // Allow overriding rad resistance
|
||||
|
||||
// If people expand the system, this may be useful. Here as a placeholder until then
|
||||
/atom/proc/rad_act(var/severity)
|
||||
return 1
|
||||
|
||||
/mob/living/rad_act(var/severity)
|
||||
if(severity)
|
||||
src.apply_effect(severity, IRRADIATE, src.getarmor(null, "rad"))
|
||||
for(var/atom/I in src)
|
||||
I.rad_act(severity)
|
||||
@@ -271,8 +271,7 @@
|
||||
if(explode)
|
||||
explosion(src.loc, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 4, flash_range = 6, adminlog = 0)
|
||||
new /obj/effect/decal/cleanable/greenglow(get_turf(src))
|
||||
for(var/mob/living/L in view(10, src))
|
||||
L.apply_effect(40, IRRADIATE)
|
||||
radiation_repository.radiate(src, 50)
|
||||
|
||||
// This meteor fries toasters.
|
||||
/obj/effect/meteor/emp
|
||||
|
||||
@@ -263,6 +263,7 @@
|
||||
icon = 'icons/obj/doors/Dooruranium.dmi'
|
||||
mineral = "uranium"
|
||||
var/last_event = 0
|
||||
var/rad_power = 7.5
|
||||
|
||||
/obj/machinery/door/airlock/process()
|
||||
// Deliberate no call to parent.
|
||||
@@ -280,15 +281,10 @@
|
||||
/obj/machinery/door/airlock/uranium/process()
|
||||
if(world.time > last_event+20)
|
||||
if(prob(50))
|
||||
radiate()
|
||||
radiation_repository.radiate(src, rad_power)
|
||||
last_event = world.time
|
||||
..()
|
||||
|
||||
/obj/machinery/door/airlock/uranium/proc/radiate()
|
||||
for(var/mob/living/L in range (3,src))
|
||||
L.apply_effect(15,IRRADIATE,0)
|
||||
return
|
||||
|
||||
/obj/machinery/door/airlock/phoron
|
||||
name = "Phoron Airlock"
|
||||
desc = "No way this can end badly."
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
icon = 'icons/obj/doors/rapid_pdoor.dmi'
|
||||
icon_state = null
|
||||
min_force = 20 //minimum amount of force needed to damage the door with a melee weapon
|
||||
|
||||
var/material/implicit_material
|
||||
// Icon states for different shutter types. Simply change this instead of rewriting the update_icon proc.
|
||||
var/icon_state_open = null
|
||||
var/icon_state_opening = null
|
||||
@@ -29,6 +29,13 @@
|
||||
//turning this off prevents awkward zone geometry in places like medbay lobby, for example.
|
||||
block_air_zones = 0
|
||||
|
||||
/obj/machinery/door/blast/initialize()
|
||||
..()
|
||||
implicit_material = get_material_by_name("plasteel")
|
||||
|
||||
/obj/machinery/door/blast/get_material()
|
||||
return implicit_material
|
||||
|
||||
// Proc: Bumped()
|
||||
// Parameters: 1 (AM - Atom that tried to walk through this object)
|
||||
// Description: If we are open returns zero, otherwise returns result of parent function.
|
||||
@@ -46,6 +53,7 @@
|
||||
icon_state = icon_state_closed
|
||||
else
|
||||
icon_state = icon_state_open
|
||||
radiation_repository.resistance_cache.Remove(get_turf(src))
|
||||
return
|
||||
|
||||
// Proc: force_open()
|
||||
|
||||
@@ -362,6 +362,7 @@
|
||||
icon_state = "door1"
|
||||
else
|
||||
icon_state = "door0"
|
||||
radiation_repository.resistance_cache.Remove(get_turf(src))
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -1029,7 +1029,7 @@
|
||||
icon_state = "engivend"
|
||||
icon_deny = "engivend-deny"
|
||||
req_access = list(access_engine_equip)
|
||||
products = list(/obj/item/clothing/glasses/meson = 2,/obj/item/device/multitool = 4,/obj/item/weapon/cell/high = 10,
|
||||
products = list(/obj/item/device/geiger = 4,/obj/item/clothing/glasses/meson = 2,/obj/item/device/multitool = 4,/obj/item/weapon/cell/high = 10,
|
||||
/obj/item/weapon/airlock_electronics = 10,/obj/item/weapon/module/power_control = 10,
|
||||
/obj/item/weapon/circuitboard/airalarm = 10,/obj/item/weapon/circuitboard/firealarm = 10,/obj/item/weapon/circuitboard/status_display = 2,
|
||||
/obj/item/weapon/circuitboard/ai_status_display = 2,/obj/item/weapon/circuitboard/newscaster = 2,/obj/item/weapon/circuitboard/holopad = 2,
|
||||
|
||||
@@ -973,11 +973,7 @@
|
||||
|
||||
process(var/obj/item/mecha_parts/mecha_equipment/generator/nuclear/EG)
|
||||
if(..())
|
||||
for(var/mob/living/carbon/M in view(EG.chassis))
|
||||
if(istype(M,/mob/living/carbon/human))
|
||||
M.apply_effect((EG.rad_per_cycle*3),IRRADIATE,0)
|
||||
else
|
||||
M.apply_effect(EG.rad_per_cycle, IRRADIATE)
|
||||
radiation_repository.radiate(EG, (EG.rad_per_cycle * 3))
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
53
code/game/objects/items/devices/geiger.dm
Normal file
53
code/game/objects/items/devices/geiger.dm
Normal file
@@ -0,0 +1,53 @@
|
||||
#define RAD_LEVEL_LOW 5 //10 // Around the level at which radiation starts to become harmful
|
||||
#define RAD_LEVEL_MODERATE 15 //15
|
||||
#define RAD_LEVEL_HIGH 50 //50
|
||||
#define RAD_LEVEL_VERY_HIGH 100 //100
|
||||
|
||||
//Geiger counter
|
||||
//Rewritten version of TG's geiger counter
|
||||
//I opted to show exact radiation levels
|
||||
|
||||
/obj/item/device/geiger
|
||||
name = "geiger counter"
|
||||
desc = "A handheld device used for detecting and measuring radiation in an area."
|
||||
icon_state = "geiger_off"
|
||||
item_state = "multitool"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
var/scanning = 0
|
||||
var/radiation_count = 0
|
||||
|
||||
/obj/item/device/geiger/New()
|
||||
processing_objects |= src
|
||||
|
||||
/obj/item/device/geiger/process()
|
||||
if(!scanning)
|
||||
return
|
||||
radiation_count = radiation_repository.get_rads_at_turf(get_turf(src))
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/geiger/examine(mob/user)
|
||||
..(user)
|
||||
to_chat(user, "<span class='warning'>[scanning ? "ambient" : "stored"] radiation level: [radiation_count ? radiation_count : "0"]Bq.</span>")
|
||||
|
||||
/obj/item/device/geiger/attack_self(var/mob/user)
|
||||
scanning = !scanning
|
||||
update_icon()
|
||||
to_chat(user, "<span class='notice'>\icon[src] You switch [scanning ? "on" : "off"] [src].</span>")
|
||||
|
||||
/obj/item/device/geiger/update_icon()
|
||||
if(!scanning)
|
||||
icon_state = "geiger_off"
|
||||
return 1
|
||||
|
||||
switch(radiation_count)
|
||||
if(null) icon_state = "geiger_on_1"
|
||||
if(-INFINITY to RAD_LEVEL_LOW) icon_state = "geiger_on_1"
|
||||
if(RAD_LEVEL_LOW + 1 to RAD_LEVEL_MODERATE) icon_state = "geiger_on_2"
|
||||
if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH) icon_state = "geiger_on_3"
|
||||
if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH) icon_state = "geiger_on_4"
|
||||
if(RAD_LEVEL_VERY_HIGH + 1 to INFINITY) icon_state = "geiger_on_5"
|
||||
|
||||
#undef RAD_LEVEL_LOW
|
||||
#undef RAD_LEVEL_MODERATE
|
||||
#undef RAD_LEVEL_HIGH
|
||||
#undef RAD_LEVEL_VERY_HIGH
|
||||
@@ -99,6 +99,8 @@ REAGENT SCANNER
|
||||
if(M.status_flags & FAKEDEATH)
|
||||
OX = fake_oxy > 50 ? "<span class='warning'>Severe oxygen deprivation detected</span>" : "Subject bloodstream oxygen level normal"
|
||||
user.show_message("[OX] | [TX] | [BU] | [BR]")
|
||||
if(M.radiation)
|
||||
user.show_message("<span class='warning'>Radiation detected.</span>")
|
||||
if(istype(M, /mob/living/carbon))
|
||||
var/mob/living/carbon/C = M
|
||||
if(C.reagents.total_volume)
|
||||
|
||||
@@ -155,6 +155,8 @@
|
||||
new /obj/item/clothing/head/radiation(src)
|
||||
new /obj/item/clothing/suit/radiation(src)
|
||||
new /obj/item/clothing/head/radiation(src)
|
||||
new /obj/item/device/geiger(src)
|
||||
new /obj/item/device/geiger(src)
|
||||
|
||||
/*
|
||||
* Bombsuit closet
|
||||
|
||||
@@ -168,8 +168,7 @@
|
||||
/obj/structure/simple_door/process()
|
||||
if(!material.radioactivity)
|
||||
return
|
||||
for(var/mob/living/L in range(1,src))
|
||||
L.apply_effect(round(material.radioactivity/3),IRRADIATE,0)
|
||||
radiation_repository.radiate(src, round(material.radioactivity/3))
|
||||
|
||||
/obj/structure/simple_door/iron/New(var/newloc,var/material_name)
|
||||
..(newloc, "iron")
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
if(can_open == WALL_OPENING)
|
||||
return
|
||||
|
||||
radiation_repository.resistance_cache.Remove(src)
|
||||
|
||||
if(density)
|
||||
can_open = WALL_OPENING
|
||||
//flick("[material.icon_base]fwall_opening", src)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
else if(material.opacity < 0.5 && opacity)
|
||||
set_light(0)
|
||||
|
||||
radiation_repository.resistance_cache.Remove(src)
|
||||
update_connections(1)
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
if(!radiate())
|
||||
return PROCESS_KILL
|
||||
|
||||
/turf/simulated/wall/proc/get_material()
|
||||
return material
|
||||
|
||||
/turf/simulated/wall/bullet_act(var/obj/item/projectile/Proj)
|
||||
if(istype(Proj,/obj/item/projectile/beam))
|
||||
burn(2500)
|
||||
@@ -265,8 +268,7 @@
|
||||
if(!total_radiation)
|
||||
return
|
||||
|
||||
for(var/mob/living/L in range(3,src))
|
||||
L.apply_effect(total_radiation, IRRADIATE,0)
|
||||
radiation_repository.radiate(src, total_radiation)
|
||||
return total_radiation
|
||||
|
||||
/turf/simulated/wall/proc/burn(temperature)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
var/const/enterBelt = 30
|
||||
var/const/radIntervall = 5 // Enough time between enter/leave belt for 10 hits, as per original implementation
|
||||
var/const/leaveBelt = 80
|
||||
var/const/revokeAccess = 135
|
||||
var/const/revokeAccess = 165
|
||||
startWhen = 2
|
||||
announceWhen = 1
|
||||
endWhen = revokeAccess
|
||||
@@ -27,23 +27,21 @@
|
||||
radiate()
|
||||
|
||||
else if(activeFor == leaveBelt)
|
||||
command_announcement.Announce("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert")
|
||||
|
||||
command_announcement.Announce("The station has passed the radiation belt. Please allow for up to one minute while radiation levels dissipate, and report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert")
|
||||
/datum/event/radiation_storm/proc/radiate()
|
||||
var/radiation_level = rand(15, 35)
|
||||
for(var/z in using_map.station_levels)
|
||||
radiation_repository.z_radiate(locate(1, 1, z), radiation_level, 1)
|
||||
|
||||
for(var/mob/living/carbon/C in living_mob_list)
|
||||
var/area/A = get_area(C)
|
||||
if(!A)
|
||||
continue
|
||||
if(!(A.z in using_map.station_levels))
|
||||
continue
|
||||
if(A.flags & RAD_SHIELDED)
|
||||
continue
|
||||
|
||||
if(istype(C,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = C
|
||||
H.apply_effect((rand(15,35)),IRRADIATE,0)
|
||||
if(prob(5))
|
||||
H.apply_effect((rand(40,70)),IRRADIATE,0)
|
||||
if (prob(75))
|
||||
randmutb(H) // Applies bad mutation
|
||||
domutcheck(H,null,MUTCHK_FORCED)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
radiate()
|
||||
|
||||
/datum/event/solar_storm/proc/radiate()
|
||||
// Note: Too complicated to be worth trying to use the radiation system for this. Its only in space anyway, so we make an exception in this case.
|
||||
for(var/mob/living/L in living_mob_list)
|
||||
var/turf/T = get_turf(L)
|
||||
if(!T)
|
||||
@@ -36,8 +37,7 @@
|
||||
continue
|
||||
|
||||
//Todo: Apply some burn damage from the heat of the sun. Until then, enjoy some moderate radiation.
|
||||
L.apply_effect((rand(15,30)),IRRADIATE,blocked = L.getarmor(null, "rad"))
|
||||
|
||||
L.rad_act(rand(15, 30))
|
||||
|
||||
/datum/event/solar_storm/end()
|
||||
command_announcement.Announce("The solar storm has passed the station. It is now safe to resume EVA activities. Please report to medbay if you experience any unusual symptoms. ", "Anomaly Alert")
|
||||
|
||||
@@ -482,7 +482,7 @@ var/list/mining_overlay_cache = list()
|
||||
M.flash_eyes()
|
||||
if(prob(50))
|
||||
M.Stun(5)
|
||||
M.apply_effect(25, IRRADIATE)
|
||||
radiation_repository.flat_radiate(src, 25, 200)
|
||||
if(prob(25))
|
||||
excavate_find(prob(5), finds[1])
|
||||
else if(rand(1,500) == 1)
|
||||
|
||||
@@ -94,7 +94,7 @@ emp_act
|
||||
var/obj/item/organ/external/organ = organs_by_name[organ_name]
|
||||
if(organ)
|
||||
var/weight = organ_rel_size[organ_name]
|
||||
armorval += getarmor_organ(organ, type) * weight
|
||||
armorval += (getarmor_organ(organ, type) * weight)
|
||||
total += weight
|
||||
return (armorval/max(total, 1))
|
||||
|
||||
|
||||
@@ -352,6 +352,7 @@ var/global/list/robot_modules = list(
|
||||
src.modules += new /obj/item/device/pipe_painter(src)
|
||||
src.modules += new /obj/item/device/floor_painter(src)
|
||||
src.modules += new /obj/item/weapon/gripper/no_use/loader(src)
|
||||
src.modules += new /obj/item/device/geiger(src)
|
||||
|
||||
var/datum/matter_synth/metal = new /datum/matter_synth/metal()
|
||||
var/datum/matter_synth/plasteel = new /datum/matter_synth/plasteel()
|
||||
@@ -396,6 +397,7 @@ var/global/list/robot_modules = list(
|
||||
src.modules += new /obj/item/device/pipe_painter(src)
|
||||
src.modules += new /obj/item/device/floor_painter(src)
|
||||
src.emag = new /obj/item/weapon/melee/baton/robot/arm(src)
|
||||
src.modules += new /obj/item/device/geiger(src)
|
||||
|
||||
var/datum/matter_synth/metal = new /datum/matter_synth/metal(40000)
|
||||
var/datum/matter_synth/glass = new /datum/matter_synth/glass(40000)
|
||||
|
||||
@@ -396,17 +396,13 @@
|
||||
/obj/machinery/power/port_gen/pacman/super/UseFuel()
|
||||
//produces a tiny amount of radiation when in use
|
||||
if (prob(2*power_output))
|
||||
for (var/mob/living/L in range(src, 5))
|
||||
L.apply_effect(1, IRRADIATE) //should amount to ~5 rads per minute at max safe power
|
||||
radiation_repository.radiate(src, 4)
|
||||
..()
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/super/explode()
|
||||
//a nice burst of radiation
|
||||
var/rads = 50 + (sheets + sheet_left)*1.5
|
||||
for (var/mob/living/L in range(src, 10))
|
||||
//should really fall with the square of the distance, but that makes the rads value drop too fast
|
||||
//I dunno, maybe physics works different when you live in 2D -- SM radiation also works like this, apparently
|
||||
L.apply_effect(max(20, round(rads/get_dist(L,src))), IRRADIATE)
|
||||
radiation_repository.radiate(src, (max(20, rads)))
|
||||
|
||||
explosion(src.loc, 3, 3, 5, 3)
|
||||
qdel(src)
|
||||
|
||||
@@ -31,6 +31,11 @@ var/global/list/rad_collectors = list()
|
||||
last_power_new = 0
|
||||
|
||||
|
||||
if(P && active)
|
||||
var/rads = radiation_repository.get_rads_at_turf(get_turf(src))
|
||||
if(rads)
|
||||
receive_pulse(rads * 5) //Maths is hard
|
||||
|
||||
if(P)
|
||||
if(P.air_contents.gas["phoron"] == 0)
|
||||
investigate_log("<font color='red'>out of fuel</font>.","singulo")
|
||||
|
||||
@@ -406,15 +406,13 @@
|
||||
var/toxrange = 10
|
||||
var/toxdamage = 4
|
||||
var/radiation = 15
|
||||
var/radiationmin = 3
|
||||
if (src.energy>200)
|
||||
toxdamage = round(((src.energy-150)/50)*4,1)
|
||||
radiation = round(((src.energy-150)/50)*5,1)
|
||||
radiationmin = round((radiation/5),1)//
|
||||
radiation_repository.radiate(src, radiation) //Always radiate at max, so a decent dose of radiation is applied
|
||||
for(var/mob/living/M in view(toxrange, src.loc))
|
||||
if(M.status_flags & GODMODE)
|
||||
continue
|
||||
M.apply_effect(rand(radiationmin,radiation), IRRADIATE)
|
||||
toxdamage = (toxdamage - (toxdamage*M.getarmor(null, "rad")))
|
||||
M.apply_effect(toxdamage, TOX)
|
||||
return
|
||||
@@ -448,13 +446,13 @@
|
||||
/obj/singularity/proc/smwave()
|
||||
for(var/mob/living/M in view(10, src.loc))
|
||||
if(prob(67))
|
||||
M.apply_effect(rand(energy), IRRADIATE)
|
||||
M << "<span class=\"warning\">You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.</span>"
|
||||
M << "<span class=\"notice\">Miraculously, it fails to kill you.</span>"
|
||||
to_chat(M, "<span class=\"warning\">You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.</span>")
|
||||
to_chat(M, "<span class=\"notice\">Miraculously, it fails to kill you.</span>")
|
||||
else
|
||||
M << "<span class=\"danger\">You hear an uneartly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.</span>"
|
||||
M << "<span class=\"danger\">You don't even have a moment to react as you are reduced to ashes by the intense radiation.</span>"
|
||||
M.dust()
|
||||
radiation_repository.radiate(src, rand(energy))
|
||||
return
|
||||
|
||||
/obj/singularity/proc/pulse()
|
||||
|
||||
@@ -23,8 +23,11 @@
|
||||
#define DAMAGE_RATE_LIMIT 3 //damage rate cap at power = 300, scales linearly with power
|
||||
|
||||
|
||||
//These would be what you would get at point blank, decreases with distance
|
||||
#define DETONATION_RADS 200
|
||||
// Base variants are applied to everyone on the same Z level
|
||||
// Range variants are applied on per-range basis: numbers here are on point blank, it scales with the map size (assumes square shaped Z levels)
|
||||
#define DETONATION_RADS 20
|
||||
#define DETONATION_HALLUCINATION_BASE 300
|
||||
#define DETONATION_HALLUCINATION_RANGE 300
|
||||
#define DETONATION_HALLUCINATION 600
|
||||
|
||||
|
||||
@@ -95,6 +98,11 @@
|
||||
anchored = 1
|
||||
grav_pulling = 1
|
||||
exploded = 1
|
||||
var/turf/TS = get_turf(src) // The turf supermatter is on. SM being in a locker, mecha, or other container shouldn't block it's effects that way.
|
||||
if(!TS)
|
||||
return
|
||||
for(var/z in GetConnectedZlevels(TS.z))
|
||||
radiation_repository.z_radiate(locate(1, 1, z), DETONATION_RADS, 1)
|
||||
for(var/mob/living/mob in living_mob_list)
|
||||
var/turf/T = get_turf(mob)
|
||||
if(T && (loc.z == T.z))
|
||||
@@ -102,8 +110,6 @@
|
||||
//Hilariously enough, running into a closet should make you get hit the hardest.
|
||||
var/mob/living/carbon/human/H = mob
|
||||
H.hallucination += max(50, min(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, src) + 1)) ) )
|
||||
var/rads = DETONATION_RADS * sqrt( 1 / (get_dist(mob, src) + 1) )
|
||||
mob.apply_effect(rads, IRRADIATE)
|
||||
spawn(pull_time)
|
||||
explosion(get_turf(src), explosion_power, explosion_power * 2, explosion_power * 3, explosion_power * 4, 1)
|
||||
qdel(src)
|
||||
@@ -258,12 +264,15 @@
|
||||
if(eye_shield < 1)
|
||||
l.hallucination = max(0, min(200, l.hallucination + power * config_hallucination_power * sqrt( 1 / max(1,get_dist(l, src)) ) ) )
|
||||
|
||||
/*
|
||||
//adjusted range so that a power of 170 (pretty high) results in 9 tiles, roughly the distance from the core to the engine monitoring room.
|
||||
//note that the rads given at the maximum range is a constant 0.2 - as power increases the maximum range merely increases.
|
||||
for(var/mob/living/l in range(src, round(sqrt(power / 2))))
|
||||
var/radius = max(get_dist(l, src), 1)
|
||||
var/rads = (power / 10) * ( 1 / (radius**2) )
|
||||
l.apply_effect(rads, IRRADIATE)
|
||||
*/
|
||||
radiation_repository.radiate(src, power * 1.5) //Better close those shutters!
|
||||
|
||||
power -= (power/DECAY_FACTOR)**3 //energy losses due to radiation
|
||||
|
||||
@@ -377,9 +386,8 @@
|
||||
"<span class=\"warning\">The unearthly ringing subsides and you notice you have new radiation burns.</span>", 2)
|
||||
else
|
||||
l.show_message("<span class=\"warning\">You hear an uneartly ringing and notice your skin is covered in fresh radiation burns.</span>", 2)
|
||||
var/rads = 500 * sqrt( 1 / (get_dist(l, src) + 1) )
|
||||
l.apply_effect(rads, IRRADIATE)
|
||||
|
||||
var/rads = 500
|
||||
radiation_repository.radiate(src, rads)
|
||||
|
||||
/obj/machinery/power/supermatter/proc/supermatter_pull()
|
||||
//following is adapted from singulo code
|
||||
|
||||
@@ -15,16 +15,10 @@
|
||||
|
||||
/datum/artifact_effect/radiate/DoEffectAura()
|
||||
if(holder)
|
||||
var/turf/T = get_turf(holder)
|
||||
for (var/mob/living/M in range(src.effectrange,T))
|
||||
M.apply_effect(radiation_amount,IRRADIATE,0)
|
||||
M.updatehealth()
|
||||
radiation_repository.flat_radiate(holder, radiation_amount, src.effectrange)
|
||||
return 1
|
||||
|
||||
/datum/artifact_effect/radiate/DoEffectPulse()
|
||||
if(holder)
|
||||
var/turf/T = get_turf(holder)
|
||||
for (var/mob/living/M in range(src.effectrange,T))
|
||||
M.apply_effect(radiation_amount * 25,IRRADIATE,0)
|
||||
M.updatehealth()
|
||||
radiation_repository.radiate(holder, ((radiation_amount * 25) * (sqrt(src.effectrange)))) //Need to get feedback on this
|
||||
return 1
|
||||
|
||||
@@ -198,8 +198,7 @@
|
||||
radiation = rand() * 15 + 85
|
||||
if(!rad_shield)
|
||||
//irradiate nearby mobs
|
||||
for(var/mob/living/M in view(7,src))
|
||||
M.apply_effect(radiation / 25, IRRADIATE, 0)
|
||||
radiation_repository.radiate(src, radiation / 25)
|
||||
else
|
||||
t_left_radspike = pick(10,15,25)
|
||||
|
||||
@@ -361,4 +360,4 @@
|
||||
scanned_item = null
|
||||
|
||||
add_fingerprint(usr)
|
||||
return 1 // update UIs attached to this object
|
||||
return 1 // update UIs attached to this object
|
||||
@@ -36,6 +36,9 @@ JOBS_HAVE_MINIMAL_ACCESS
|
||||
Configure how fast explosion strength diminishes when travelling up/down z levels. All explosion distances are multiplied by this each time they go up/down z-levels.
|
||||
#MULTI_Z_EXPLOSION_SCALAR 0.5
|
||||
|
||||
# Radiation weakens with distance from the source; stop calculating when the strength falls below this value. Lower values mean radiation reaches smaller (with increasingly trivial damage) at the cost of more CPU usage. Max range = DISTANCE^2 * POWER / RADIATION_LOWER_LIMIT
|
||||
# RADIATION_LOWER_LIMIT 0.35
|
||||
|
||||
## log OOC channel
|
||||
LOG_OOC
|
||||
|
||||
|
||||
5
html/changelogs/Leshana-Radiation.yml
Normal file
5
html/changelogs/Leshana-Radiation.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
author: Leshana
|
||||
delete-after: True
|
||||
changes:
|
||||
- tweak: "Optimized the unified radiation system. Made the radiation cutoff level configurable."
|
||||
- bugfix: "Standing still won't save you from radiation storms."
|
||||
37
html/changelogs/cirra-Radiation.yml
Normal file
37
html/changelogs/cirra-Radiation.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
################################
|
||||
# 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
|
||||
# wip (For works in progress)
|
||||
# tweak
|
||||
# soundadd
|
||||
# sounddel
|
||||
# rscadd (general adding of nice things)
|
||||
# rscdel (general deleting of nice things)
|
||||
# imageadd
|
||||
# imagedel
|
||||
# maptweak
|
||||
# spellcheck (typo fixes)
|
||||
# experiment
|
||||
#################################
|
||||
|
||||
# Your name.
|
||||
author: Cirra
|
||||
|
||||
# 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, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
|
||||
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
|
||||
changes:
|
||||
- rscadd: "Added a unified radiation system. Radiation is lessened by obstacles, and distance."
|
||||
- rscadd: "Added a geiger counter for measuring radiation levels, which can be found in certain vending machines and radiation closets."
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 54 KiB |
@@ -151,6 +151,7 @@
|
||||
#include "code\controllers\Processes\nanoui.dm"
|
||||
#include "code\controllers\Processes\obj.dm"
|
||||
#include "code\controllers\Processes\planet.dm"
|
||||
#include "code\controllers\Processes\radiation.dm"
|
||||
#include "code\controllers\Processes\scheduler.dm"
|
||||
#include "code\controllers\Processes\Shuttle.dm"
|
||||
#include "code\controllers\Processes\sun.dm"
|
||||
@@ -213,6 +214,7 @@
|
||||
#include "code\datums\repositories\cameras.dm"
|
||||
#include "code\datums\repositories\crew.dm"
|
||||
#include "code\datums\repositories\decls.dm"
|
||||
#include "code\datums\repositories\radiation.dm"
|
||||
#include "code\datums\repositories\repository.dm"
|
||||
#include "code\datums\supplypacks\atmospherics.dm"
|
||||
#include "code\datums\supplypacks\contraband.dm"
|
||||
@@ -769,6 +771,7 @@
|
||||
#include "code\game\objects\items\devices\flash.dm"
|
||||
#include "code\game\objects\items\devices\flashlight.dm"
|
||||
#include "code\game\objects\items\devices\floor_painter.dm"
|
||||
#include "code\game\objects\items\devices\geiger.dm"
|
||||
#include "code\game\objects\items\devices\hacktool.dm"
|
||||
#include "code\game\objects\items\devices\lightreplacer.dm"
|
||||
#include "code\game\objects\items\devices\locker_painter.dm"
|
||||
|
||||
Reference in New Issue
Block a user