mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-06-04 13:45:25 +01:00
7f3d763285
## About The Pull Request
- Adds Roach Infusion to the DNA infuser.
- Bonuses include:
- All infused organs are 2x as healthy, notably your heart: Meaning
getting revived after being dead a while is easier
- When being attacked from behind or while lying down, take 50% less
damage from brute attacks
- Lose disgust 32x faster, making it a non-issue
- Higher toxin purge threshold (5 units, up from 3)
- Virus resistance (same as spaceacillin)
- 100 innate bomb armor, preventing explosions from gibbing you
- 90 innate bio armor
- Immunity to appendicitis, radiation, and to being gibbed by nuclear
bombs
- Downsides include:
- Knockdowns are 3x as long
- get 3x as hungry
- Ingest reagents to your stomach 1.5x slower
- Take 2x as much damage from toxins
- Toxins over the purge threshold deal 4x more liver damage (effectively
2x, as the liver has 2x health)
- Becoming a bug
- Roaches are gross
- Adds a way to kill roaches without having them splat. If they are
sprayed with bug spray, they will simply fall over, and can be scooped
up.
https://github.com/tgstation/tgstation/assets/51863163/5078c493-9e28-42cb-ae51-45fa25b67a34
## Why It's Good For The Game
More content for the DNA infuser, which benefits greatly from variety.
While initially it may seem like a lot of bonuses, a lot of them are
very niche, with the exception being the brute resilience which is the
big "actually useful" bonus you gain.
The infusion is intended to be given to Engineers, offering innate
Radiation immunity to allow them to work on the Supermatter without
needing a rad suit. Likewise, if the work goes south and the Supermatter
goes boom, their body will more than likely survive the blast.
## Changelog
🆑 Melbert
add: Adds the Roach infusion to the DNA infuser. Do you want to survive
a nuclear apocalypse? Visit genetics today.
add: Adds a way to kill Roaches without splatting them. Visit botany for
a spray bottle of pestkiller.
qol: Infuser book is more book-like
fix: DNA infuser correctly gives on-success feedback messages
/🆑
---------
Co-authored-by: Jacquerel <hnevard@gmail.com>
266 lines
8.5 KiB
Plaintext
266 lines
8.5 KiB
Plaintext
//Luma coefficients suggested for HDTVs. If you change these, make sure they add up to 1.
|
|
#define LUMA_R 0.213
|
|
#define LUMA_G 0.715
|
|
#define LUMA_B 0.072
|
|
|
|
/// Datum which stores information about a matrix decomposed with decompose().
|
|
/datum/decompose_matrix
|
|
///?
|
|
var/scale_x = 1
|
|
///?
|
|
var/scale_y = 1
|
|
///?
|
|
var/rotation = 0
|
|
///?
|
|
var/shift_x = 0
|
|
///?
|
|
var/shift_y = 0
|
|
|
|
/// Decomposes a matrix into scale, shift and rotation.
|
|
///
|
|
/// If other operations were applied on the matrix, such as shearing, the result
|
|
/// will not be precise.
|
|
///
|
|
/// Negative scales are now supported. =)
|
|
/matrix/proc/decompose()
|
|
var/datum/decompose_matrix/decompose_matrix = new
|
|
. = decompose_matrix
|
|
var/flip_sign = (a*e - b*d < 0)? -1 : 1 // Det < 0 => only 1 axis is flipped - start doing some sign flipping
|
|
// If both axis are flipped, nothing bad happens and Det >= 0, it just treats it like a 180° rotation
|
|
// If only 1 axis is flipped, we need to flip one direction - in this case X, so we flip a, b and the x scaling
|
|
decompose_matrix.scale_x = sqrt(a * a + d * d) * flip_sign
|
|
decompose_matrix.scale_y = sqrt(b * b + e * e)
|
|
decompose_matrix.shift_x = c
|
|
decompose_matrix.shift_y = f
|
|
if(!decompose_matrix.scale_x || !decompose_matrix.scale_y)
|
|
return
|
|
// If only translated, scaled and rotated, a/xs == e/ys and -d/xs == b/xy
|
|
var/cossine = (a/decompose_matrix.scale_x + e/decompose_matrix.scale_y) / 2
|
|
var/sine = (b/decompose_matrix.scale_y - d/decompose_matrix.scale_x) / 2 * flip_sign
|
|
decompose_matrix.rotation = arctan(cossine, sine) * flip_sign
|
|
|
|
/matrix/proc/TurnTo(old_angle, new_angle)
|
|
. = new_angle - old_angle
|
|
Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
|
|
|
|
/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3, parallel = TRUE)
|
|
if(!segments)
|
|
return
|
|
var/segment = 360/segments
|
|
if(!clockwise)
|
|
segment = -segment
|
|
var/list/matrices = list()
|
|
for(var/i in 1 to segments-1)
|
|
var/matrix/M = matrix(transform)
|
|
M.Turn(segment*i)
|
|
matrices += M
|
|
var/matrix/last = matrix(transform)
|
|
matrices += last
|
|
|
|
speed /= segments
|
|
|
|
if(parallel)
|
|
animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL)
|
|
else
|
|
animate(src, transform = matrices[1], time = speed, loops)
|
|
for(var/i in 2 to segments) //2 because 1 is covered above
|
|
animate(transform = matrices[i], time = speed)
|
|
//doesn't have an object argument because this is "Stacking" with the animate call above
|
|
//3 billion% intentional
|
|
|
|
/// Similar to shake but more spasm-y and jerk-y
|
|
/atom/proc/spasm_animation(loops = -1)
|
|
var/list/transforms = list(
|
|
matrix(transform).Translate(-1, 0),
|
|
matrix(transform).Translate(0, 1),
|
|
matrix(transform).Translate(1, 0),
|
|
matrix(transform).Translate(0, -1),
|
|
)
|
|
|
|
animate(src, transform = transforms[1], time = 0.2, loop = loops)
|
|
animate(transform = transforms[2], time = 0.1)
|
|
animate(transform = transforms[3], time = 0.2)
|
|
animate(transform = transforms[4], time = 0.3)
|
|
|
|
/**
|
|
* Shear the transform on either or both axes.
|
|
* * x - X axis shearing
|
|
* * y - Y axis shearing
|
|
*/
|
|
/matrix/proc/Shear(x, y)
|
|
return Multiply(matrix(1, x, 0, y, 1, 0))
|
|
|
|
//Dumps the matrix data in format a-f
|
|
/matrix/proc/tolist()
|
|
. = list()
|
|
. += a
|
|
. += b
|
|
. += c
|
|
. += d
|
|
. += e
|
|
. += f
|
|
|
|
//Dumps the matrix data in a matrix-grid format
|
|
/*
|
|
a d 0
|
|
b e 0
|
|
c f 1
|
|
*/
|
|
/matrix/proc/togrid()
|
|
. = list()
|
|
. += a
|
|
. += d
|
|
. += 0
|
|
. += b
|
|
. += e
|
|
. += 0
|
|
. += c
|
|
. += f
|
|
. += 1
|
|
|
|
///The X pixel offset of this matrix
|
|
/matrix/proc/get_x_shift()
|
|
. = c
|
|
|
|
///The Y pixel offset of this matrix
|
|
/matrix/proc/get_y_shift()
|
|
. = f
|
|
|
|
/////////////////////
|
|
// COLOUR MATRICES //
|
|
/////////////////////
|
|
|
|
/* Documenting a couple of potentially useful color matrices here to inspire ideas
|
|
// Greyscale - indentical to saturation @ 0
|
|
list(LUMA_R,LUMA_R,LUMA_R,0, LUMA_G,LUMA_G,LUMA_G,0, LUMA_B,LUMA_B,LUMA_B,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
// Color inversion
|
|
list(-1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1, 1,1,1,0)
|
|
|
|
// Sepiatone
|
|
list(0.393,0.349,0.272,0, 0.769,0.686,0.534,0, 0.189,0.168,0.131,0, 0,0,0,1, 0,0,0,0)
|
|
*/
|
|
|
|
//Does nothing
|
|
/proc/color_matrix_identity()
|
|
return list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
//Adds/subtracts overall lightness
|
|
//0 is identity, 1 makes everything white, -1 makes everything black
|
|
/proc/color_matrix_lightness(power)
|
|
return list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, power,power,power,0)
|
|
|
|
//Changes distance hues have from grey while maintaining the overall lightness. Greys are unaffected.
|
|
//1 is identity, 0 is greyscale, >1 oversaturates colors
|
|
/proc/color_matrix_saturation(value)
|
|
var/inv = 1 - value
|
|
var/R = round(LUMA_R * inv, 0.001)
|
|
var/G = round(LUMA_G * inv, 0.001)
|
|
var/B = round(LUMA_B * inv, 0.001)
|
|
|
|
return list(R + value,R,R,0, G,G + value,G,0, B,B,B + value,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
//Changes distance colors have from rgb(127,127,127) grey
|
|
//1 is identity. 0 makes everything grey >1 blows out colors and greys
|
|
/proc/color_matrix_contrast(value)
|
|
var/add = (1 - value) / 2
|
|
return list(value,0,0,0, 0,value,0,0, 0,0,value,0, 0,0,0,1, add,add,add,0)
|
|
|
|
//Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting greys
|
|
//0 is identity, 120 moves reds to greens, 240 moves reds to blues
|
|
/proc/color_matrix_rotate_hue(angle)
|
|
var/sin = sin(angle)
|
|
var/cos = cos(angle)
|
|
var/cos_inv_third = 0.333*(1-cos)
|
|
var/sqrt3_sin = sqrt(3)*sin
|
|
return list(
|
|
round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), 0,
|
|
round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), round(cos_inv_third+sqrt3_sin, 0.001), 0,
|
|
round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), round(cos+cos_inv_third, 0.001), 0,
|
|
0,0,0,1,
|
|
0,0,0,0)
|
|
|
|
//These next three rotate values about one axis only
|
|
//x is the red axis, y is the green axis, z is the blue axis.
|
|
/proc/color_matrix_rotate_x(angle)
|
|
var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
|
|
return list(1,0,0,0, 0,cosval,sinval,0, 0,-sinval,cosval,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
/proc/color_matrix_rotate_y(angle)
|
|
var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
|
|
return list(cosval,0,-sinval,0, 0,1,0,0, sinval,0,cosval,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
/proc/color_matrix_rotate_z(angle)
|
|
var/sinval = round(sin(angle), 0.001); var/cosval = round(cos(angle), 0.001)
|
|
return list(cosval,sinval,0,0, -sinval,cosval,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,0)
|
|
|
|
|
|
//Returns a matrix addition of A with B
|
|
/proc/color_matrix_add(list/A, list/B)
|
|
if(!istype(A) || !istype(B))
|
|
return color_matrix_identity()
|
|
if(A.len != 20 || B.len != 20)
|
|
return color_matrix_identity()
|
|
var/list/output = list()
|
|
output.len = 20
|
|
for(var/value in 1 to 20)
|
|
output[value] = A[value] + B[value]
|
|
return output
|
|
|
|
//Returns a matrix multiplication of A with B
|
|
/proc/color_matrix_multiply(list/A, list/B)
|
|
if(!istype(A) || !istype(B))
|
|
return color_matrix_identity()
|
|
if(A.len != 20 || B.len != 20)
|
|
return color_matrix_identity()
|
|
var/list/output = list()
|
|
output.len = 20
|
|
var/x = 1
|
|
var/y = 1
|
|
var/offset = 0
|
|
for(y in 1 to 5)
|
|
offset = (y-1)*4
|
|
for(x in 1 to 4)
|
|
output[offset+x] = round(A[offset+1]*B[x] + A[offset+2]*B[x+4] + A[offset+3]*B[x+8] + A[offset+4]*B[x+12]+(y == 5?B[x+16]:0), 0.001)
|
|
return output
|
|
|
|
///Converts RGB shorthands into RGBA matrices complete of constants rows (ergo a 20 keys list in byond).
|
|
/proc/color_to_full_rgba_matrix(color)
|
|
if(istext(color))
|
|
var/list/L = ReadRGB(color)
|
|
if(!L)
|
|
CRASH("Invalid/unsupported color format argument in color_to_full_rgba_matrix()")
|
|
return list(L[1]/255,0,0,0, 0,L[2]/255,0,0, 0,0,L[3]/255,0, 0,0,0,L.len>3?L[4]/255:1, 0,0,0,0)
|
|
else if(!islist(color)) //invalid format
|
|
return color_matrix_identity()
|
|
var/list/L = color
|
|
switch(L.len)
|
|
if(3 to 5) // row-by-row hexadecimals
|
|
. = list()
|
|
for(var/a in 1 to L.len)
|
|
var/list/rgb = ReadRGB(L[a])
|
|
for(var/b in rgb)
|
|
. += b/255
|
|
if(length(rgb) % 4) // RGB has no alpha instruction
|
|
. += a != 4 ? 0 : 1
|
|
if(L.len < 4) //missing both alphas and constants rows
|
|
. += list(0,0,0,1, 0,0,0,0)
|
|
else if(L.len < 5) //missing constants row
|
|
. += list(0,0,0,0)
|
|
if(9 to 12) //RGB
|
|
. = list(L[1],L[2],L[3],0, L[4],L[5],L[6],0, L[7],L[8],L[9],0, 0,0,0,1)
|
|
for(var/b in 1 to 3) //missing constants row
|
|
. += L.len < 9+b ? 0 : L[9+b]
|
|
. += 0
|
|
if(16 to 20) // RGBA
|
|
. = L.Copy()
|
|
if(L.len < 20) //missing constants row
|
|
for(var/b in 1 to 20-L.len)
|
|
. += 0
|
|
else
|
|
CRASH("Invalid/unsupported color format argument in color_to_full_rgba_matrix()")
|
|
|
|
#undef LUMA_R
|
|
#undef LUMA_G
|
|
#undef LUMA_B
|