mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-30 07:28:53 +01:00
Radiation Refactor (#19270)
* Part 1 * WIP * The rest of these * More stuff * Whoops, did that wrong * typo * gweeen * This all works * SHOWER * Rads * awa * rad * Update life.dm * edits * Makes lvl 3 rads give you a warning. You should already know by this point, but this makes it EXTRA clear you're getting fucked * Update vorestation.dme * aaa * propagate * gwah * more fixes * AAA * Update radiation.dm * Update radiation.dm * mobs rads * rads * fix this * Update _reagents.dm * these * Get rid of these * rad * Update config.txt * fixed * Update radiation_effects.dm
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Get a list of turfs in a line from `starting_atom` to `ending_atom`.
|
||||
*
|
||||
* Uses the ultra-fast [Bresenham Line-Drawing Algorithm](https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm).
|
||||
*/
|
||||
/proc/get_line(atom/starting_atom, atom/ending_atom)
|
||||
var/current_x_step = starting_atom.x//start at x and y, then add 1 or -1 to these to get every turf from starting_atom to ending_atom
|
||||
var/current_y_step = starting_atom.y
|
||||
var/starting_z = starting_atom.z
|
||||
|
||||
var/list/line = list(get_turf(starting_atom))//get_turf(atom) is faster than locate(x, y, z)
|
||||
|
||||
var/x_distance = ending_atom.x - current_x_step //x distance
|
||||
var/y_distance = ending_atom.y - current_y_step
|
||||
|
||||
var/abs_x_distance = abs(x_distance)//Absolute value of x distance
|
||||
var/abs_y_distance = abs(y_distance)
|
||||
|
||||
var/x_distance_sign = SIGN(x_distance) //Sign of x distance (+ or -)
|
||||
var/y_distance_sign = SIGN(y_distance)
|
||||
|
||||
var/x = abs_x_distance >> 1 //Counters for steps taken, setting to distance/2
|
||||
var/y = abs_y_distance >> 1 //Bit-shifting makes me l33t. It also makes get_line() unnecessarily fast.
|
||||
|
||||
if(abs_x_distance >= abs_y_distance) //x distance is greater than y
|
||||
for(var/distance_counter in 0 to (abs_x_distance - 1))//It'll take abs_x_distance steps to get there
|
||||
y += abs_y_distance
|
||||
|
||||
if(y >= abs_x_distance) //Every abs_y_distance steps, step once in y direction
|
||||
y -= abs_x_distance
|
||||
current_y_step += y_distance_sign
|
||||
|
||||
current_x_step += x_distance_sign //Step on in x direction
|
||||
line += locate(current_x_step, current_y_step, starting_z)//Add the turf to the list
|
||||
else
|
||||
for(var/distance_counter in 0 to (abs_y_distance - 1))
|
||||
x += abs_x_distance
|
||||
|
||||
if(x >= abs_y_distance)
|
||||
x -= abs_y_distance
|
||||
current_x_step += x_distance_sign
|
||||
|
||||
current_y_step += y_distance_sign
|
||||
line += locate(current_x_step, current_y_step, starting_z)
|
||||
return line
|
||||
@@ -0,0 +1,85 @@
|
||||
/// Whether or not it's possible for this atom to be irradiated
|
||||
#define CAN_IRRADIATE(atom) (ismob(##atom))
|
||||
|
||||
/// Calculates the max chance for a radiation_pulse via a radioactive reagent
|
||||
#define CALCULATE_RAD_MAX_CHANCE(rad_power) (20 + (15 * (rad_power - 1)))
|
||||
|
||||
/// Sends out a pulse of radiation, eminating from the source.
|
||||
/// Radiation is performed by collecting all radiatables within the max range (0 means source only, 1 means adjacent, etc),
|
||||
/// then makes their way towards them. A number, starting at 1, is multiplied
|
||||
/// by the insulation amounts of whatever is in the way (for example, walls lowering it down).
|
||||
/// If this number hits equal or below the threshold, then the target can no longer be irradiated.
|
||||
/// If the number is above the threshold, then the chance is the chance that the target will be irradiated.
|
||||
/// As a consumer, this means that max_range going up usually means you want to lower the threshold too,
|
||||
/// as well as the other way around.
|
||||
/// If max_range is high, but threshold is too high, then it usually won't reach the source at the max range in time.
|
||||
/// If max_range is low, but threshold is too low, then it basically guarantees everyone nearby, even if there's walls
|
||||
/// and such in the way, can be irradiated.
|
||||
/// You can also pass in a minimum exposure time. If this is set, then this radiation pulse
|
||||
/// will not irradiate the source unless they have been around *any* radioactive source for that
|
||||
/// period of time.
|
||||
/// The chance to get irradiated diminishes over range, and from objects that block radiation.
|
||||
/// Assuming there is nothing in the way, the chance will determine what the chance is to get irradiated from half of max_range.
|
||||
/// Example: If chance is equal to 30%, and max_range is equal to 8,
|
||||
/// then the chance for a thing to get irradiated is 30% if they are 4 turfs away from the pulse source.
|
||||
/// Also, strength is how much radiation the target will get if they fail their RNG check / linger for too long.
|
||||
/proc/radiation_pulse(
|
||||
atom/source,
|
||||
max_range,
|
||||
threshold,
|
||||
chance = DEFAULT_RADIATION_CHANCE,
|
||||
minimum_exposure_time = 0,
|
||||
strength = 100
|
||||
)
|
||||
if(!SSradiation.can_fire)
|
||||
return
|
||||
|
||||
var/datum/radiation_pulse_information/pulse_information = new
|
||||
pulse_information.source_ref = WEAKREF(source)
|
||||
pulse_information.max_range = max_range
|
||||
pulse_information.threshold = threshold
|
||||
pulse_information.chance = chance
|
||||
pulse_information.minimum_exposure_time = minimum_exposure_time
|
||||
pulse_information.turfs_to_process = RANGE_TURFS(max_range, source)
|
||||
pulse_information.strength = strength
|
||||
|
||||
SSradiation.processing += pulse_information
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/radiation_pulse_information
|
||||
var/datum/weakref/source_ref
|
||||
var/max_range
|
||||
var/threshold
|
||||
var/chance
|
||||
var/minimum_exposure_time
|
||||
var/list/turfs_to_process
|
||||
var/strength
|
||||
|
||||
#define MEDIUM_RADIATION_THRESHOLD_RANGE 0.5
|
||||
#define EXTREME_RADIATION_CHANCE 30
|
||||
|
||||
/// Gets the perceived "danger" of radiation pulse, given the threshold to the target.
|
||||
/// Returns a RADIATION_DANGER_* define, see [code/__DEFINES/radiation.dm]
|
||||
/proc/get_perceived_radiation_danger(datum/radiation_pulse_information/pulse_information, insulation_to_target)
|
||||
if (insulation_to_target > pulse_information.threshold)
|
||||
// We could get irradiated! The only thing stopping us now is chance, so scale based on that.
|
||||
if (pulse_information.chance >= EXTREME_RADIATION_CHANCE)
|
||||
return PERCEIVED_RADIATION_DANGER_EXTREME
|
||||
else
|
||||
return PERCEIVED_RADIATION_DANGER_HIGH
|
||||
else
|
||||
// We're out of the threshold from being irradiated, but by how much?
|
||||
if (insulation_to_target / pulse_information.threshold <= MEDIUM_RADIATION_THRESHOLD_RANGE)
|
||||
return PERCEIVED_RADIATION_DANGER_MEDIUM
|
||||
else
|
||||
return PERCEIVED_RADIATION_DANGER_LOW
|
||||
|
||||
/// A common proc used to send COMSIG_ATOM_PROPAGATE_RAD_PULSE to adjacent atoms
|
||||
/// Only used for uranium (false/tram)walls to spread their radiation pulses
|
||||
/atom/proc/propagate_radiation_pulse()
|
||||
for(var/atom/atom in orange(1,src))
|
||||
SEND_SIGNAL(atom, COMSIG_ATOM_PROPAGATE_RAD_PULSE, src)
|
||||
|
||||
#undef MEDIUM_RADIATION_THRESHOLD_RANGE
|
||||
#undef EXTREME_RADIATION_CHANCE
|
||||
@@ -0,0 +1,8 @@
|
||||
///Returns the distance between two atoms
|
||||
/proc/get_dist_euclidean(atom/first_location, atom/second_location)
|
||||
var/dx = first_location.x - second_location.x
|
||||
var/dy = first_location.y - second_location.y
|
||||
|
||||
var/dist = sqrt(dx ** 2 + dy ** 2)
|
||||
|
||||
return dist
|
||||
@@ -7,13 +7,6 @@
|
||||
//Checks if all high bits in req_mask are set in bitfield
|
||||
#define BIT_TEST_ALL(bitfield, req_mask) ((~(bitfield) & (req_mask)) == 0)
|
||||
|
||||
//supposedly the fastest way to do this according to https://gist.github.com/Giacom/be635398926bb463b42a
|
||||
#define RANGE_TURFS(RADIUS, CENTER) \
|
||||
block( \
|
||||
locate(max(CENTER.x-(RADIUS),1), max(CENTER.y-(RADIUS),1), CENTER.z), \
|
||||
locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \
|
||||
)
|
||||
|
||||
//Returns the middle-most value
|
||||
/proc/dd_range(var/low, var/high, var/num)
|
||||
return max(low,min(high,num))
|
||||
|
||||
Reference in New Issue
Block a user