mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-02-07 14:59:13 +00:00
* 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>
158 lines
5.8 KiB
Plaintext
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)
|