mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
## About The Pull Request   ## This PR: * Adds a new type of reagent container; the jerrycan! * Replaces the nutrient bottles in the nutrimax with cans. * Adds some prefilled cans to the maint loot table. ### Can knowledge * Jerrycans can hold a hold an incredible 200u. * They can be printed roundstart at the auto and protolathes for 2 sheets of plastic. * They are balanced by being bulky. * They can be thrown around by without spilling their contents. * They are not beakers and cannot be used to make grenades. The upfront cost associated with buying nutrients will be greater, but it will be cheaper per unit. I would actually like to charge more but this is not really feasible right now due to the heavy department discount. #### Maint loot additions The new maint loot cans have a low weight so far, collectively appearing half as often as basic healing items. The cans that have been added to maint loot are as follows: * space cleaner ( weight: 2) * oil (weight: 2) * diethylamine (weight : 1) * phlogiston (weight: 1) #### Reagent overlay code I have added an option to have reagent containers use a colour matrix to lighten and increase the contrast of the reagent filling overlay in an attempt to prevent dark coloured reagents from completely obliterating all contrast. The math may need to be tweaked but it should offer some improvement provided the filling overlay has some contrast to begin with. ## Why It's Good For The Game The jerrycan is not only a flavourful & setting appropriate way to store reagents, it also offers several design benefits due to its unique combination of high roundstart capacity and bulky size. * It prevents one coworker from hogging a shared reagent container. * The high volume eases grinding and mixing. * It allows reagents to be stolen or borrowed due to being stored outside the safety of an inventory. * The highly visible inhand sprite allows you to see who is holding or transporting reagents. * The smart cap flag increases quality of life by allowing you to throw the container without spilling. * It reduces the tedium associated with dispensing and throwing away botany nutrient bottles, encouraging refilling. * Bulky size prevent players from looting the can unless it is something they really want. * Comes with a large number of visual customisation options for coders who with to add new variants. ## Throwing away the little nutrient bottles when doing botany sucks! ## Changelog 🆑 add: Added a new type of reagent container; the jerrycan. add: Added some prefilled jerrycans to maint loot. balance: Botany nutrients now come in bulk packaging. /🆑 --------- Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
219 lines
7.0 KiB
Plaintext
219 lines
7.0 KiB
Plaintext
/// 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)
|
|
return Turn(new_angle - old_angle) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
|
|
|
|
/**
|
|
* 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
|
|
|
|
///The angle of this matrix
|
|
/matrix/proc/get_angle()
|
|
. = -ATAN2(a,d)
|
|
|
|
/////////////////////
|
|
// 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)
|
|
*/
|
|
|
|
//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)
|
|
|
|
//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).
|
|
* if return_identity_on_fail is true, stack_trace is called instead of CRASH, and an identity is returned.
|
|
*/
|
|
/proc/color_to_full_rgba_matrix(color, return_identity_on_fail = TRUE)
|
|
if(!color)
|
|
return COLOR_MATRIX_IDENTITY
|
|
if(istext(color))
|
|
var/list/L = rgb2num(color)
|
|
if(!L)
|
|
var/message = "Invalid/unsupported color ([color]) argument in color_to_full_rgba_matrix()"
|
|
if(return_identity_on_fail)
|
|
stack_trace(message)
|
|
return COLOR_MATRIX_IDENTITY
|
|
CRASH(message)
|
|
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)
|
|
if(!islist(color)) //invalid format
|
|
CRASH("Invalid/unsupported color ([color]) argument in color_to_full_rgba_matrix()")
|
|
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 = rgb2num(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
|
|
var/message = "Invalid/unsupported color (list of length [L.len]) argument in color_to_full_rgba_matrix()"
|
|
if(return_identity_on_fail)
|
|
stack_trace(message)
|
|
return COLOR_MATRIX_IDENTITY
|
|
CRASH(message)
|