|
3 | 3 | * Components which return COMPONENT_BLOCK_RADIATION prevent further searching into that object's contents. The object itself will get returned still.
|
4 | 4 | * The ignore list makes those objects never return at all
|
5 | 5 | */
|
6 |
| -/proc/get_rad_contents(atom/location) |
| 6 | +/proc/get_rad_contents(atom/location, emission_type) |
7 | 7 | var/static/list/ignored_things = typecacheof(list(
|
8 |
| - /mob/dead, |
9 | 8 | /mob/camera,
|
| 9 | + /mob/dead, |
10 | 10 | /obj/effect,
|
11 | 11 | /obj/docking_port,
|
12 | 12 | /atom/movable/lighting_object,
|
13 | 13 | /obj/item/projectile,
|
14 |
| - /obj/structure/railing // uhhhh they're highly radiation resistant, or some shit (stops stupid exploits) |
| 14 | + /atom/movable/emissive_blocker, |
15 | 15 | ))
|
16 | 16 | var/list/processing_list = list(location)
|
| 17 | + var/list/window_priority = list() |
| 18 | + var/list/collector_priority = list() |
| 19 | + var/list/other_priority = list() |
17 | 20 | . = list()
|
| 21 | + var/insulation = 1 |
18 | 22 | while(length(processing_list))
|
19 | 23 | var/atom/thing = processing_list[1]
|
20 | 24 | processing_list -= thing
|
21 |
| - if(ignored_things[thing.type]) |
| 25 | + if(!thing || ignored_things[thing.type]) |
22 | 26 | continue
|
23 |
| - . += thing |
| 27 | + switch(emission_type) |
| 28 | + if(ALPHA_RAD) |
| 29 | + insulation = thing.rad_insulation_alpha |
| 30 | + if(BETA_RAD) |
| 31 | + insulation = thing.rad_insulation_beta |
| 32 | + if(GAMMA_RAD) |
| 33 | + insulation = thing.rad_insulation_gamma |
| 34 | + /// 1 means no rad insulation, which means perfectly permeable, so no interaction with it directly, but the contents might be relevant. |
| 35 | + if(insulation < 1) |
| 36 | + if(istype(thing, /obj/structure/window)) |
| 37 | + window_priority += thing |
| 38 | + else if(istype(thing, /obj/machinery/power/rad_collector)) |
| 39 | + collector_priority += thing |
| 40 | + else |
| 41 | + other_priority += thing |
24 | 42 | if((thing.flags_2 & RAD_PROTECT_CONTENTS_2) || (SEND_SIGNAL(thing, COMSIG_ATOM_RAD_PROBE) & COMPONENT_BLOCK_RADIATION))
|
25 | 43 | continue
|
26 | 44 | if(ishuman(thing))
|
27 |
| - var/mob/living/carbon/human/H = thing |
28 |
| - if(H.get_rad_protection() >= 0.99) // I would do exactly equal to 1, but you will never hit anything between 1 and .975, and byond seems to output 0.99999 |
| 45 | + var/mob/living/carbon/human/target_mob = thing |
| 46 | + if(target_mob.get_rad_protection() >= 0.99) // I would do exactly equal to 1, but you will never hit anything between 1 and .975, and byond seems to output 0.99999 |
29 | 47 | continue
|
30 | 48 | processing_list += thing.contents
|
| 49 | + . = window_priority + collector_priority + other_priority |
31 | 50 |
|
32 |
| -/proc/radiation_pulse(atom/source, intensity, range_modifier, log = FALSE, can_contaminate = TRUE, source_radius = 0) |
33 |
| - if(!SSradiation.can_fire) |
34 |
| - return |
35 |
| - for(var/dir in GLOB.cardinal) |
36 |
| - new /datum/radiation_wave(source, dir, intensity, range_modifier, can_contaminate, source_radius) |
| 51 | +/proc/get_rad_contamination_adjacent(atom/location, atom/source) |
| 52 | + var/static/list/ignored_things = typecacheof(list( |
| 53 | + /mob/camera, |
| 54 | + /mob/dead, |
| 55 | + /obj/effect, |
| 56 | + /obj/docking_port, |
| 57 | + /atom/movable/lighting_object, |
| 58 | + /obj/item/projectile, |
| 59 | + /atom/movable/emissive_blocker, |
| 60 | + )) |
| 61 | + var/list/processing_list = list(location) |
| 62 | + // We want to select which clothes and items we contaminate depending on where on the human we are. We assume we are in some form of storage or on the floor otherwise. |
| 63 | + // If the source is a human(like a uranium golem) we just attempt to contaminate all our contents |
| 64 | + if(!ishuman(location) || ishuman(source)) |
| 65 | + processing_list += location.contents |
| 66 | + . = list() |
| 67 | + for(var/atom/thing in processing_list) |
| 68 | + if(thing && source && thing.UID() == source.UID()) |
| 69 | + continue |
| 70 | + if(ignored_things[thing.type]) |
| 71 | + continue |
| 72 | + if((SEND_SIGNAL(thing, COMSIG_ATOM_RAD_CONTAMINATING) & COMPONENT_BLOCK_CONTAMINATION) || thing.flags_2 & RAD_NO_CONTAMINATE_2) |
| 73 | + continue |
| 74 | + if(ishuman(thing) || ishuman(thing.loc)) |
| 75 | + var/mob/living/carbon/human/target_mob = ishuman(thing) ? thing : thing.loc |
| 76 | + var/passed = TRUE |
| 77 | + var/zone |
| 78 | + var/pocket = FALSE |
| 79 | + // Check if we hold the contamination source, have it in our pockets or in our belts or if it's inside us |
| 80 | + if(target_mob.UID() == location.UID()) |
| 81 | + // If it's in our hands check if it can permeate our gloves |
| 82 | + if((source && (target_mob.r_hand && target_mob.r_hand.UID() == source.UID()) || (target_mob.l_hand && target_mob.l_hand.UID() == source.UID()))) |
| 83 | + zone = HANDS |
37 | 84 |
|
38 |
| - var/list/things = get_rad_contents(source) //copypasta because I don't want to put special code in waves to handle their origin |
39 |
| - for(var/k in 1 to length(things)) |
40 |
| - var/atom/thing = things[k] |
41 |
| - if(!thing) |
| 85 | + // If it's in our pockets check against our jumpsuit only |
| 86 | + else if((target_mob?.l_store && target_mob?.l_store?.UID() == source?.UID()) || (target_mob?.r_store && target_mob?.r_store.UID() == source?.UID())) |
| 87 | + zone = LOWER_TORSO |
| 88 | + pocket = TRUE |
| 89 | + |
| 90 | + // If it's on our belt check against both our outer layer and jumpsuit |
| 91 | + if(location.loc.UID() == target_mob.UID() && istype(location, /obj/item/storage/belt)) |
| 92 | + zone = LOWER_TORSO |
| 93 | + |
| 94 | + // If on the floor check if it can permeate our shoes |
| 95 | + if(istype(location, /turf/)) |
| 96 | + zone = FEET |
| 97 | + |
| 98 | + // zone being unchanged here means the item is inside the mob |
| 99 | + var/list/results = target_mob.rad_contaminate_zone(zone, pocket) |
| 100 | + passed = results[1] |
| 101 | + results -= results[1] |
| 102 | + . |= results |
| 103 | + if(!passed) |
| 104 | + continue |
| 105 | + . += thing |
| 106 | + |
| 107 | +/proc/get_rad_contamination_target(atom/location, atom/source) |
| 108 | + var/static/list/ignored_things = typecacheof(list( |
| 109 | + /mob/camera, |
| 110 | + /mob/dead, |
| 111 | + /obj/effect, |
| 112 | + /obj/docking_port, |
| 113 | + /atom/movable/lighting_object, |
| 114 | + /obj/item/projectile, |
| 115 | + /atom/movable/emissive_blocker, |
| 116 | + )) |
| 117 | + var/list/processing_list = list(location) + location.contents |
| 118 | + . = list() |
| 119 | + while(length(processing_list)) |
| 120 | + var/atom/thing = processing_list[1] |
| 121 | + processing_list -= thing |
| 122 | + if(thing?.UID() == source?.UID()) |
| 123 | + continue |
| 124 | + if(ignored_things[thing.type]) |
| 125 | + continue |
| 126 | + if((SEND_SIGNAL(thing, COMSIG_ATOM_RAD_CONTAMINATING) & COMPONENT_BLOCK_CONTAMINATION) || thing.flags_2 & RAD_NO_CONTAMINATE_2) |
42 | 127 | continue
|
43 |
| - thing.rad_act(intensity) |
| 128 | + /// If it's a human check for rad protection on all areas |
| 129 | + if(ishuman(thing)) |
| 130 | + var/mob/living/carbon/human/target_mob = thing |
| 131 | + var/zone = 0 |
| 132 | + var/list/contaminate = list() |
| 133 | + var/list/results = list() |
| 134 | + var/passed = TRUE |
| 135 | + for(var/i in 0 to 9) |
| 136 | + zone = (1<<i) |
| 137 | + results = target_mob.rad_contaminate_zone(zone) |
| 138 | + passed = results[1] || passed |
| 139 | + results -= results[1] |
| 140 | + contaminate |= results |
| 141 | + . |= contaminate |
| 142 | + if(!passed) |
| 143 | + continue |
| 144 | + for(var/atom/human_content in target_mob.contents) |
| 145 | + if(!istype(human_content, /obj/item/clothing)) |
| 146 | + . |= human_content |
| 147 | + . += thing |
| 148 | + |
| 149 | + |
| 150 | +/proc/radiation_pulse(atom/source, intensity, emission_type = ALPHA_RAD, log = FALSE) |
| 151 | + if(!SSradiation.can_fire || intensity < RAD_BACKGROUND_RADIATION) |
| 152 | + return |
| 153 | + var/datum/radiation_wave/wave = new /datum/radiation_wave(source, intensity, emission_type) |
| 154 | + |
| 155 | + var/turf/start_turf = source |
| 156 | + |
| 157 | + // Find the turf where we are |
| 158 | + while(!istype(start_turf, /turf)) |
| 159 | + start_turf = start_turf.loc |
| 160 | + |
| 161 | + var/list/things = get_rad_contents(start_turf, emission_type) // Radiate the waves origin frist |
| 162 | + // Adjust the weights so the source tile doesn't get all the rads |
| 163 | + wave.weight_sum = RAD_SOURCE_WEIGHT |
| 164 | + wave.weights = list(wave.weight_sum) |
| 165 | + for(var/atom/thing in things) |
| 166 | + if(thing.UID() == source.UID()) |
| 167 | + // Don't block our own radiation |
| 168 | + source.base_rad_act(source ,intensity, emission_type) |
| 169 | + else |
| 170 | + wave.weight_sum = wave.weight_sum * thing.base_rad_act(source ,intensity * wave.weight_sum, emission_type) |
| 171 | + // Add the rest of the weight back |
| 172 | + wave.weight_sum += (1 - RAD_SOURCE_WEIGHT) |
| 173 | + // We can do this because we are on one tile so we have one weight |
| 174 | + wave.weights[1] = wave.weight_sum |
44 | 175 |
|
45 | 176 | var/static/last_huge_pulse = 0
|
46 |
| - if(intensity > 3000 && world.time > last_huge_pulse + 200) |
| 177 | + if(intensity > 12000 && world.time > last_huge_pulse + 200) |
47 | 178 | last_huge_pulse = world.time
|
48 | 179 | log = TRUE
|
49 | 180 | if(log)
|
50 | 181 | var/turf/_source_T = isturf(source) ? source : get_turf(source)
|
51 |
| - log_game("Radiation pulse with intensity: [intensity] and range modifier: [range_modifier] in [loc_name(_source_T)] ") |
| 182 | + log_game("Radiation pulse with intensity: [intensity] in [loc_name(_source_T)] ") |
52 | 183 | return TRUE
|
53 | 184 |
|
54 | 185 | /proc/get_rad_contamination(atom/location)
|
|
58 | 189 | if(!thing)
|
59 | 190 | continue
|
60 | 191 | var/datum/component/radioactive/radiation = thing.GetComponent(/datum/component/radioactive)
|
61 |
| - if(radiation && rad_strength < radiation.strength) |
62 |
| - rad_strength = radiation.strength |
| 192 | + if(radiation && rad_strength < (radiation.alpha_strength + radiation.beta_strength + radiation.gamma_strength)) |
| 193 | + rad_strength = (radiation.alpha_strength + radiation.beta_strength + radiation.gamma_strength) |
63 | 194 | return rad_strength
|
| 195 | + |
| 196 | +/// Contaminate things that share our immediate location(periodic) |
| 197 | +/proc/contaminate_adjacent(atom/source, intensity, emission_type) |
| 198 | + // If the source is a turf it is it's location |
| 199 | + var/atom/location = isturf(source) ? source : source.loc |
| 200 | + // Are we on a turf or in something else |
| 201 | + var/is_source_on_turf = isturf(location) |
| 202 | + var/contamination_chance = is_source_on_turf ? CONTAMINATION_CHANCE_TURF : CONTAMINATION_CHANCE_OTHER |
| 203 | + var/list/contamination_contents = get_rad_contamination_adjacent(location, source) |
| 204 | + for(var/atom/thing in contamination_contents) |
| 205 | + if(prob(contamination_chance)) |
| 206 | + thing.AddComponent(/datum/component/radioactive, intensity, source, emission_type) |
| 207 | + |
| 208 | +/// Contaminate the contents of a target(single instance) |
| 209 | +/proc/contaminate_target(atom/target, atom/source, intensity, emission_type) |
| 210 | + var/list/contamination_contents = get_rad_contamination_target(target, source) |
| 211 | + for(var/atom/thing in contamination_contents) |
| 212 | + thing.AddComponent(/datum/component/radioactive, intensity, source, emission_type) |
0 commit comments