diff --git a/code/__HELPERS/radiation.dm b/code/__HELPERS/radiation.dm index d77add64e50..a7c04f11518 100644 --- a/code/__HELPERS/radiation.dm +++ b/code/__HELPERS/radiation.dm @@ -22,6 +22,32 @@ continue processing_list += thing.contents +//same as base but also returns a list of insulation values. +/proc/get_rad_insulation_contents(atom/location, datum/radiation_wave/src_wave, width = 1) + var/static/list/ignored_things = typecacheof(list( + /mob/dead, + /mob/camera, + /obj/effect, + /obj/docking_port, + /atom/movable/lighting_object, + /obj/projectile, + )) + var/list/processing_list = list(location) + var/best_insulation = RAD_NO_INSULATION + var/return_list = list() + while(processing_list.len) + var/atom/thing = processing_list[1] + processing_list -= thing + if(ignored_things[thing.type]) + continue + return_list += thing + if (!(SEND_SIGNAL(thing, COMSIG_ATOM_RAD_WAVE_PASSING, src_wave, width) & COMPONENT_RAD_WAVE_HANDLED)) + best_insulation = min(thing.rad_insulation, best_insulation) + if((thing.flags_1 & RAD_PROTECT_CONTENTS_1) || (SEND_SIGNAL(thing, COMSIG_ATOM_RAD_PROBE) & COMPONENT_BLOCK_RADIATION)) + continue + processing_list += thing.contents + return list(return_list, best_insulation) + /proc/radiation_pulse(atom/source, intensity, range_modifier, log=FALSE, can_contaminate=TRUE) // fusion will never ever be balanced. god bless it intensity = min(intensity, INFINITY) diff --git a/code/datums/radiation_wave.dm b/code/datums/radiation_wave.dm index 10e3b28e722..9f5828fb8fd 100644 --- a/code/datums/radiation_wave.dm +++ b/code/datums/radiation_wave.dm @@ -65,50 +65,67 @@ qdel(src) return - var/list/atoms = get_rad_atoms() + var/width = steps + var/cmove_dir = move_dir + if(cmove_dir == NORTH || cmove_dir == SOUTH) + width-- + width = 1+(2*width) + + var/list/atoms_and_insulation = get_rad_atoms(width) + var/list/atoms = atoms_and_insulation[1] if(radiate(atoms, FLOOR(min(strength,remaining_contam), 1))) //oof ow ouch remaining_contam = max(0,remaining_contam-((min(strength,remaining_contam)-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT)) - check_obstructions(atoms) // reduce our overall strength if there are radiation insulators -/datum/radiation_wave/proc/get_rad_atoms() + var/insulation_tally = atoms_and_insulation[2] + if(insulation_tally) + var/insulation_total = atoms_and_insulation[3] + var/average_insulation = insulation_total / insulation_tally + // Determines how much the width dilutes the obstacle's effect. + // Using the square root of width (width ** 0.5) prevents the obstacles from becoming irrelevant at long distances. + var/spread_factor = max(1, width ** 0.5) + + // The exponent calculates the effective "thickness" of the wall relative to the wave size. + var/obstacle_density = insulation_tally / spread_factor + + // Apply the reduction. + intensity *= (average_insulation ** obstacle_density) + +/datum/radiation_wave/proc/get_rad_atoms(width = 1) var/list/atoms = list() var/distance = steps var/cmove_dir = move_dir var/cmaster_turf = master_turf + var/insulation_total = 0 + var/insulation_tally = 0 if(cmove_dir == NORTH || cmove_dir == SOUTH) distance-- //otherwise corners overlap - atoms += get_rad_contents(cmaster_turf) + var/list/master_turf_contents = get_rad_insulation_contents(cmaster_turf, src, width) + atoms += master_turf_contents[1] + var/best_insulation = master_turf_contents[2] + if(best_insulation != RAD_NO_INSULATION) + insulation_total += best_insulation + insulation_tally++ var/turf/place + var/list/place_turf_contents for(var/dir in __dirs) //There should be just 2 dirs in here, left and right of the direction of movement place = cmaster_turf for(var/i in 1 to distance) place = get_step(place, dir) if(!is_valid_rad_turf(place)) break // the break here is important. if a rad wave was travelling parallel to a virtual z edge, and the loop didn't break, it could "clip through" - atoms += get_rad_contents(place) - - return atoms - -/datum/radiation_wave/proc/check_obstructions(list/atoms) - var/width = steps - var/cmove_dir = move_dir - if(cmove_dir == NORTH || cmove_dir == SOUTH) - width-- - width = 1+(2*width) - - for(var/k in 1 to atoms.len) - var/atom/thing = atoms[k] - if(!thing) - continue - if (SEND_SIGNAL(thing, COMSIG_ATOM_RAD_WAVE_PASSING, src, width) & COMPONENT_RAD_WAVE_HANDLED) - continue - if (thing.rad_insulation != RAD_NO_INSULATION) - intensity *= (1-((1-thing.rad_insulation)/width)) + place_turf_contents = get_rad_insulation_contents(place, src, width) + atoms += place_turf_contents[1] + best_insulation = place_turf_contents[2] + if(best_insulation != RAD_NO_INSULATION) + insulation_total += place_turf_contents[2] + insulation_tally++ + + return list(atoms, insulation_tally, insulation_total) /datum/radiation_wave/proc/radiate(list/atoms, strength) var/can_contam = strength >= RAD_MINIMUM_CONTAMINATION diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index f0337b15902..3704589b556 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -112,7 +112,8 @@ var/prying_so_hard = FALSE flags_1 = RAD_PROTECT_CONTENTS_1 | RAD_NO_CONTAMINATE_1 | HTML_USE_INITAL_ICON_1 - rad_insulation = RAD_MEDIUM_INSULATION + rad_insulation = RAD_MEDIUM_INSULATION //Generally start closed. + rad_insulation_closed = RAD_MEDIUM_INSULATION var/static/list/airlock_overlays = list() @@ -1285,6 +1286,7 @@ layer = OPEN_DOOR_LAYER update_icon(ALL, AIRLOCK_OPEN, TRUE) operating = FALSE + rad_insulation = RAD_NO_INSULATION if(delayed_close_requested) delayed_close_requested = FALSE addtimer(CALLBACK(src, PROC_REF(close)), 1) @@ -1340,6 +1342,7 @@ update_icon(ALL, AIRLOCK_CLOSED, 1) operating = FALSE delayed_close_requested = FALSE + rad_insulation = rad_insulation_closed if(safe) CheckForMobs() return TRUE diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index c0079df011f..dc3998339f9 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -44,7 +44,7 @@ var/unres_sides = 0 //Unrestricted sides. A bitflag for which direction (if any) can open the door with no access var/safety_mode = FALSE ///Whether or not the airlock can be opened with bare hands while unpowered var/can_crush = TRUE /// Whether or not the door can crush mobs. - + var/rad_insulation_closed = RAD_NO_INSULATION /// How much rad_insulation it has when closed, so that it can be modified for closed/open state. /obj/machinery/door/examine(mob/user) . = ..() @@ -343,6 +343,7 @@ operating = FALSE air_update_turf(1) update_freelook_sight() + rad_insulation = RAD_NO_INSULATION if(autoclose) addtimer(CALLBACK(src, PROC_REF(close)), autoclose) return 1 @@ -360,6 +361,7 @@ return operating = TRUE + rad_insulation = rad_insulation_closed do_animate("closing") layer = closingLayer diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 3486cedd93d..0fc426d102e 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -16,6 +16,8 @@ max_integrity = 300 resistance_flags = FIRE_PROOF heat_proof = TRUE + rad_insulation = RAD_NO_INSULATION //Generally start open. + rad_insulation_closed = RAD_MEDIUM_INSULATION //Same as airlocks. glass = TRUE sub_door = TRUE explosion_block = 1 @@ -60,6 +62,7 @@ icon_state = "door_closed" opacity = TRUE density = TRUE + rad_insulation = RAD_MEDIUM_INSULATION //see also turf/AfterChange for adjacency shennanigans @@ -341,6 +344,7 @@ icon_state = "door_closed" opacity = TRUE density = TRUE + rad_insulation = RAD_MEDIUM_INSULATION /obj/machinery/door/firedoor/border_only/close() if(density) @@ -472,6 +476,7 @@ icon_state = "door_closed" opacity = TRUE density = TRUE + rad_insulation = RAD_MEDIUM_INSULATION /obj/machinery/door/firedoor/window name = "firelock window shutter" @@ -483,6 +488,7 @@ resistance_flags = 0 // not fireproof heat_proof = FALSE assemblytype = /obj/structure/firelock_frame/window + rad_insulation_closed = RAD_LIGHT_INSULATION //Not as good as firedoors. /obj/item/electronics/firelock name = "firelock circuitry" diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index 9d9b8fd0fbe..6ca3f16600d 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -17,6 +17,8 @@ poddoor = TRUE assemblytype = /obj/structure/poddoor_assembly smoothing_groups = list(SMOOTH_GROUP_AIRLOCK) + rad_insulation = RAD_HEAVY_INSULATION + rad_insulation_closed = RAD_HEAVY_INSULATION var/open_sound = 'sound/machines/airlocks/blastdoor.ogg' var/close_sound = 'sound/machines/airlocks/blastdoor.ogg' @@ -97,6 +99,7 @@ icon_state = "open" density = FALSE opacity = FALSE + rad_insulation = RAD_NO_INSULATION /obj/machinery/door/poddoor/ert name = "hardened blast door" diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index 57efb72443e..9f4be1d58b3 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -12,6 +12,7 @@ icon_state = "open" density = FALSE opacity = FALSE + rad_insulation = RAD_NO_INSULATION /obj/machinery/door/poddoor/shutters/indestructible name = "hardened shutters" @@ -21,6 +22,7 @@ icon_state = "open" density = FALSE opacity = FALSE + rad_insulation = RAD_NO_INSULATION /obj/machinery/door/poddoor/gates gender = PLURAL @@ -32,6 +34,8 @@ close_sound = 'sound/machines/airlocks/gate.ogg' glass = TRUE opacity = FALSE + rad_insulation = RAD_NO_INSULATION //Offer no insulation. + rad_insulation_closed = RAD_NO_INSULATION /obj/machinery/door/poddoor/gates/indestructible name = "hardened gates" diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 588e2804f52..a9435f2f0bc 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -17,6 +17,8 @@ CanAtmosPass = ATMOS_PASS_PROC interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN set_dir_on_move = FALSE + rad_insulation = RAD_LIGHT_INSULATION + rad_insulation_closed = RAD_LIGHT_INSULATION var/obj/item/electronics/airlock/electronics = null var/reinf = 0 var/shards = 2 diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index 5ac10eaadb1..1ebde410e66 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -152,6 +152,8 @@ glass = TRUE opacity = FALSE move_resist = MOVE_FORCE_OVERPOWERING + rad_insulation = RAD_NO_INSULATION //Offer no insulation. Redefining to make clear in case parent changes. + rad_insulation_closed = RAD_NO_INSULATION /obj/machinery/door/keycard/gates/do_animate(animation) switch(animation) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index 87932e81553..ef71f1d9ba1 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -19,6 +19,7 @@ CanAtmosPass = ATMOS_PASS_DENSITY flags_1 = RAD_PROTECT_CONTENTS_1 | RAD_NO_CONTAMINATE_1 rad_insulation = RAD_MEDIUM_INSULATION + var/rad_insulation_closed = RAD_MEDIUM_INSULATION var/mineral = /obj/item/stack/sheet/metal var/mineral_amount = 2 var/walltype = /turf/closed/wall @@ -57,6 +58,7 @@ set_opacity(density) opening = FALSE update_appearance() + rad_insulation = density? rad_insulation_closed : RAD_NO_INSULATION air_update_turf(TRUE) /obj/structure/falsewall/update_icon()//Calling icon_update will refresh the smoothwalls if it's closed, otherwise it will make sure the icon is correct if it's open diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm index d32d6520aae..ed8468ea8ac 100644 --- a/code/game/objects/structures/mineral_doors.dm +++ b/code/game/objects/structures/mineral_doors.dm @@ -15,7 +15,7 @@ CanAtmosPass = ATMOS_PASS_DENSITY flags_1 = RAD_PROTECT_CONTENTS_1 | RAD_NO_CONTAMINATE_1 rad_insulation = RAD_MEDIUM_INSULATION - + var/rad_insulation_closed = RAD_MEDIUM_INSULATION var/door_opened = FALSE //if it's open or not. var/isSwitchingStates = FALSE //don't try to change stats if we're already opening @@ -98,7 +98,7 @@ air_update_turf(TRUE) update_appearance() isSwitchingStates = FALSE - + rad_insulation = RAD_NO_INSULATION if(close_delay != -1) addtimer(CALLBACK(src, PROC_REF(Close)), close_delay) @@ -120,6 +120,7 @@ air_update_turf(TRUE) update_appearance() isSwitchingStates = FALSE + rad_insulation = rad_insulation_closed /obj/structure/mineral_door/update_icon_state() icon_state = "[initial(icon_state)][door_opened ? "open":""]" diff --git a/code/modules/ruins/rockplanet_ruin_code.dm b/code/modules/ruins/rockplanet_ruin_code.dm index 970265ab50e..504d11ee6d2 100644 --- a/code/modules/ruins/rockplanet_ruin_code.dm +++ b/code/modules/ruins/rockplanet_ruin_code.dm @@ -40,6 +40,7 @@ is_open = FALSE density = FALSE opacity = FALSE + rad_insulation = RAD_NO_INSULATION /obj/machinery/door/poddoor/crusher/automatic/Initialize(mapload) . = ..()