Files
Bubberstation/code/__HELPERS/maths.dm
LemonInTheDark 22d57da140 Readds Alien Vore (#68312)
* Readds Alien Vore

Aliens can now eat people again. Behavior was removed by #43991 (b6c41e3b32)
because nasku thought it was weird, and the code was really bad.

I think it's funny, and I've made the code not trashtier.

Basically, an alien can agressive grab any living mob. If they stay next
to the mob, facing them for 13 seconds, they will "eat" the mob,
IE:insert them into a list on their custom stomach.

The xeno can then hit an action button to spit out the mob, alongside
some acid.

If the mob is alive enough to pull out a weapon inside the xeno/has one
on it, they can attack the xeno from inside, dealing damage to the
creature and its stomach. If the stomach drops below a threshold, the
mob gibs the xeno and escapes.

I've done my best to steer things away from horny and into gross, though
I'm aware you fucks do your best to blur that line.

Anyway something something balance change something something lets xenos
abduct people more easily, I'm mostly doing this cause I think it has
soul.

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
2022-07-17 01:55:12 -07:00

158 lines
5.8 KiB
Plaintext

///Calculate the angle between two movables and the west|east coordinate
/proc/get_angle(atom/movable/start, atom/movable/end)//For beams.
if(!start || !end)
return 0
var/dy =(32 * end.y + end.pixel_y) - (32 * start.y + start.pixel_y)
var/dx =(32 * end.x + end.pixel_x) - (32 * start.x + start.pixel_x)
if(!dy)
return (dx >= 0) ? 90 : 270
. = arctan(dx/dy)
if(dy < 0)
. += 180
else if(dx < 0)
. += 360
/// Angle between two arbitrary points and horizontal line same as [/proc/get_angle]
/proc/get_angle_raw(start_x, start_y, start_pixel_x, start_pixel_y, end_x, end_y, end_pixel_x, end_pixel_y)
var/dy = (32 * end_y + end_pixel_y) - (32 * start_y + start_pixel_y)
var/dx = (32 * end_x + end_pixel_x) - (32 * start_x + start_pixel_x)
if(!dy)
return (dx >= 0) ? 90 : 270
. = arctan(dx/dy)
if(dy < 0)
. += 180
else if(dx < 0)
. += 360
///for getting the angle when animating something's pixel_x and pixel_y
/proc/get_pixel_angle(y, x)
if(!y)
return (x >= 0) ? 90 : 270
. = arctan(x/y)
if(y < 0)
. += 180
else if(x < 0)
. += 360
/**
* 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() unnessecarrily 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
///Format a power value in W, kW, MW, or GW.
/proc/display_power(powerused)
if(powerused < 1000) //Less than a kW
return "[powerused] W"
else if(powerused < 1000000) //Less than a MW
return "[round((powerused * 0.001),0.01)] kW"
else if(powerused < 1000000000) //Less than a GW
return "[round((powerused * 0.000001),0.001)] MW"
return "[round((powerused * 0.000000001),0.0001)] GW"
///Format an energy value in J, kJ, MJ, or GJ. 1W = 1J/s.
/proc/display_joules(units)
if (units < 1000) // Less than a kJ
return "[round(units, 0.1)] J"
else if (units < 1000000) // Less than a MJ
return "[round(units * 0.001, 0.01)] kJ"
else if (units < 1000000000) // Less than a GJ
return "[round(units * 0.000001, 0.001)] MJ"
return "[round(units * 0.000000001, 0.0001)] GJ"
/proc/joules_to_energy(joules)
return joules * (1 SECONDS) / SSmachines.wait
/proc/energy_to_joules(energy_units)
return energy_units * SSmachines.wait / (1 SECONDS)
///Format an energy value measured in Power Cell units.
/proc/display_energy(units)
// APCs process every (SSmachines.wait * 0.1) seconds, and turn 1 W of
// excess power into watts when charging cells.
// With the current configuration of wait=20 and CELLRATE=0.002, this
// means that one unit is 1 kJ.
return display_joules(energy_to_joules(units) WATTS)
///chances are 1:value. anyprob(1) will always return true
/proc/anyprob(value)
return (rand(1,value)==value)
///counts the number of bits in Byond's 16-bit width field, in constant time and memory!
/proc/bit_count(bit_field)
var/temp = bit_field - ((bit_field >> 1) & 46811) - ((bit_field >> 2) & 37449) //0133333 and 0111111 respectively
temp = ((temp + (temp >> 3)) & 29127) % 63 //070707
return temp
/// Returns the name of the mathematical tuple of same length as the number arg (rounded down).
/proc/make_tuple(number)
var/static/list/units_prefix = list("", "un", "duo", "tre", "quattuor", "quin", "sex", "septen", "octo", "novem")
var/static/list/tens_prefix = list("", "decem", "vigin", "trigin", "quadragin", "quinquagin", "sexagin", "septuagin", "octogin", "nongen")
var/static/list/one_to_nine = list("monuple", "double", "triple", "quadruple", "quintuple", "sextuple", "septuple", "octuple", "nonuple")
number = round(number)
switch(number)
if(0)
return "empty tuple"
if(1 to 9)
return one_to_nine[number]
if(10 to 19)
return "[units_prefix[(number%10)+1]]decuple"
if(20 to 99)
return "[units_prefix[(number%10)+1]][tens_prefix[round((number % 100)/10)+1]]tuple"
if(100)
return "centuple"
else //It gets too tedious to use latin prefixes from here.
return "[number]-tuple"
/// Takes a value, and a threshold it has to at least match
/// returns the correctly signed value max'd to the threshold
/proc/at_least(new_value, threshold)
var/sign = SIGN(new_value)
// SIGN will return 0 if the value is 0, so we just go to the positive threshold
if(!sign)
return threshold
if(sign == 1)
return max(new_value, threshold)
if(sign == -1)
return min(new_value, threshold * -1)