From 21679d960c39d4f5bbb6084b5793b7082df06950 Mon Sep 17 00:00:00 2001 From: forwardslashN <150570209+FslashN@users.noreply.github.com> Date: Thu, 11 Dec 2025 18:25:48 -0600 Subject: [PATCH 1/2] Radiation Wave Insulation Adjustment Makes some adjustment to the way radiation waves spread through insulation. Previously as a radiation wave expanded, insulation (like walls, for example), did very little to stem the overall strength of the wave. With the change: Insulation blockers have a greater impact on the overall insulation effect, reducing the radiation wave intensity. Greater insulation values also have more impact than before. Only the best insulation is taken per tile, so it is not possible to stack insulation values. This change is done for sanity and to reduce computation. Insulating blockers were expanded and adjusted. Blast doors now have great insulation, for example. Additionally, if you open a door, it will have an impact on the overall radiation wave as the door no longer will act as insulation. Previously, doors and other obstacles that could open and closed always counted as an insulation blocker. --- code/__HELPERS/radiation.dm | 26 ++++++++ code/datums/radiation_wave.dm | 63 ++++++++++++------- code/game/machinery/doors/airlock.dm | 5 +- code/game/machinery/doors/door.dm | 4 +- code/game/machinery/doors/firedoor.dm | 6 ++ code/game/machinery/doors/poddoor.dm | 3 + code/game/machinery/doors/shutters.dm | 4 ++ code/game/machinery/doors/windowdoor.dm | 2 + code/game/objects/items/puzzle_pieces.dm | 2 + code/game/objects/structures/false_walls.dm | 2 + code/game/objects/structures/mineral_doors.dm | 5 +- code/modules/ruins/rockplanet_ruin_code.dm | 1 + 12 files changed, 96 insertions(+), 27 deletions(-) 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 4fee94c5c24..36810285f36 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..a208815ffa6 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -26,6 +26,8 @@ armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 70) interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN air_tight = TRUE + rad_insulation = RAD_NO_INSULATION //Generally start open. + rad_insulation_closed = RAD_MEDIUM_INSULATION //Same as airlocks. var/emergency_close_timer = 0 var/nextstate = null var/boltslocked = TRUE @@ -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 dfe16fef601..b13c8f4e167 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' @@ -96,6 +98,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) . = ..() From 5dc3843b81f2c7b3702857cd1133e870a0f659be Mon Sep 17 00:00:00 2001 From: forwardslashN <150570209+FslashN@users.noreply.github.com> Date: Thu, 19 Feb 2026 21:37:29 -0600 Subject: [PATCH 2/2] Merge Fix Fixing merge problems with TMs. --- code/game/machinery/doors/firedoor.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index a208815ffa6..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 @@ -26,8 +28,6 @@ armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 70) interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN air_tight = TRUE - rad_insulation = RAD_NO_INSULATION //Generally start open. - rad_insulation_closed = RAD_MEDIUM_INSULATION //Same as airlocks. var/emergency_close_timer = 0 var/nextstate = null var/boltslocked = TRUE