Da huge stonking cans update! 2025 edition. (#90318)

## About The Pull Request


![bild](https://github.com/user-attachments/assets/d3643592-4907-4d01-8fc6-3d613aa3e772)

![bild](https://github.com/user-attachments/assets/d859e878-72e3-4200-8c1c-8521e5c499d2)

## 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>
This commit is contained in:
Krysonism
2025-05-08 19:21:10 -04:00
committed by Roxy
co-authored by LemonInTheDark
parent b87c77deed
commit 5f3930ba05
14 changed files with 276 additions and 19 deletions
+5
View File
@@ -507,3 +507,8 @@ GLOBAL_LIST_INIT(heretic_path_to_color, list(
#define CLIENT_COLOR_TEMPORARY_PRIORITY 5 // Temporary flashing effects
#define CLIENT_COLOR_IMPORTANT_PRIORITY 6 // Gameplay important hints signifying antag status or near-death, should be always shown
#define CLIENT_COLOR_OVERRIDE_PRIORITY 7 // For effects that are meant to mask all others for technical reasons
//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
+2
View File
@@ -27,6 +27,8 @@
//Special properties
///If the holder a sealed container - Used if you don't want reagent contents boiling out (plasma, specifically, in which case it only bursts out when at ignition temperatures)
#define SEALED_CONTAINER (1<<10)
/// Prevents spilling and splashing but does prevent pouring and drinking reagents like the badly named spillable var.
#define SMART_CAP (1<<11)
// Is an open container for all intents and purposes.
#define OPENCONTAINER (REFILLABLE | DRAINABLE | TRANSPARENT)
-9
View File
@@ -1,8 +1,3 @@
//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
///?
@@ -221,7 +216,3 @@ round(cos_inv_third+sqrt3_sin, 0.001), round(cos_inv_third-sqrt3_sin, 0.001), ro
stack_trace(message)
return COLOR_MATRIX_IDENTITY
CRASH(message)
#undef LUMA_R
#undef LUMA_G
#undef LUMA_B
+10 -4
View File
@@ -220,22 +220,28 @@ GLOBAL_LIST_INIT(uncommon_loot, list(//uncommon: useful items
/obj/item/stack/medical/mesh = 1,
/obj/item/stack/medical/suture = 1,
/obj/item/stack/medical/bandage = 1,
) = 1,
) = 4,
list(//medical chems
/obj/item/reagent_containers/cup/bottle/multiver = 1,
/obj/item/reagent_containers/hypospray/medipen = 1,
/obj/item/reagent_containers/syringe/convermol = 1,
) = 1,
) = 4,
list(//drinks
/obj/item/reagent_containers/cup/glass/bottle/vodka = 1,
/obj/item/reagent_containers/cup/glass/drinkingglass/filled/nuka_cola = 1,
/obj/item/reagent_containers/cup/soda_cans/grey_bull = 1,
) = 1,
) = 4,
list(//sprayers
/obj/item/reagent_containers/spray = 1,
/obj/item/watertank = 1,
/obj/item/watertank/janitor = 1,
) = 1,
) = 4,
list(//other chems
/obj/item/reagent_containers/cup/jerrycan/oil = 2, //Not the most exciting reagent, but a staple. And you get a cool can for your pyrotechnics.
/obj/item/reagent_containers/cup/jerrycan/space_cleaner = 2, //If you can't find the janitor, the medbay might also appreciate some readymade cleaner.
/obj/item/reagent_containers/cup/jerrycan/sus = 1, //what assitant wouldn't like a vibrant jug o' phlog?
/obj/item/reagent_containers/cup/jerrycan/diethylamine = 1, //Im sure the botanist would appreciate it, but it is also really cool for maintenance science projects.
) = 2,
) = 8,
list(//food
+54 -3
View File
@@ -41,6 +41,8 @@
var/fill_icon = 'icons/obj/medical/reagent_fillings.dmi'
///The sound this container makes when picked up, dropped if there is liquid inside.
var/reagent_container_liquid_sound = null
///If we want to the contrast of the reagent overlay if the reagent mix color is very dark.
var/adjust_color_contrast = FALSE
/obj/item/reagent_containers/apply_fantasy_bonuses(bonus)
. = ..()
@@ -128,7 +130,7 @@
/// Tries to splash the target, called when right-clicking with a reagent container.
/obj/item/reagent_containers/proc/try_splash(mob/user, atom/target)
if (!spillable)
if (!spillable || reagent_flags & SMART_CAP)
return FALSE
if (!reagents?.total_volume)
@@ -209,7 +211,7 @@
. = TRUE
/obj/item/reagent_containers/proc/SplashReagents(atom/target, datum/thrownthing/throwingdatum, override_spillable = FALSE)
if(!reagents || !reagents.total_volume || (!spillable && !override_spillable))
if(!reagents || !reagents.total_volume || (!spillable && !override_spillable) || reagent_flags & SMART_CAP)
return
var/mob/thrown_by = throwingdatum.get_thrower()
@@ -286,7 +288,56 @@
if(threshold <= percent && percent < threshold_end)
filling.icon_state = "[fill_name][fill_icon_thresholds[i]]"
filling.color = mix_color_from_reagents(reagents.reagent_list)
if(!adjust_color_contrast)
filling.color = mix_color_from_reagents(reagents.reagent_list)
. += filling
return
var/list/mix_colors = rgb2num(mix_color_from_reagents(reagents.reagent_list))
//reagent color red
var/float_r = mix_colors[1] / 255
//reagent color green
var/float_g = mix_colors[2] / 255
//reagent color blue
var/float_b = mix_colors[3] / 255
//reagent color alpha
var/float_a = mix_colors.len > 3 ? mix_colors[4] / 255 : 1
//value, used to make modifications depending on if our reagent color is light or dark.
var/float_v = (float_r + float_g + float_b) / 3
//max result of float_b - float_v is 0.6666 so we multiply with 1.5 to get something close to 1 at max blueness.
var/blue_mod = max(float_b - float_v, 0) * 1.5
//red multiplier
var/red_scale = 1.6
//green_multiplier
var/green_scale = 1.5
//blue scale
var/blue_scale = 1.1 * (1 + 0.60 * blue_mod)
//additive red - modifies red across the board by val * 255
var/red_base = -0.07 - (0.035 * float_v)
//additive green - modifies green across the board by val * 255
var/green_base = -0.06 - (0.03 * float_v)
//additive blue - modifies blue across the board by val * 255
var/blue_base = 0.10 - (0.050 * float_v) - (0.40 * blue_mod)
var/list/reagent_color_and_contrast_matrix = list(
//Red - RR, RG, RB, RA
float_r * red_scale, 0, 0, 0,
//Green - GR - GG - GB - GA
0, float_g * green_scale, 0, 0,
///Blue - BR, BG, BB, BA
0.25 * blue_mod, 0.33 * blue_mod, float_b * blue_scale, 0,
//Alpha - AR, AG, AB, AA
0, 0, 0, float_a,
//Constant - CR, CG, CB, CA
red_base, green_base, blue_base, 0)
filling.color = reagent_color_and_contrast_matrix
. += filling
/obj/item/reagent_containers/dropped(mob/user, silent)
@@ -0,0 +1,188 @@
#define LABEL_TEXT "text"
#define LABEL_TEXT_OLD "old"
#define LABEL_INFLAMMABLE "inflammable"
#define LABEL_NT "nt"
#define LABEL_NT_MINI "nt_mini"
#define LABEL_SUSPICIOUS "sus"
#define LABEL_SUSPICIOUS_BLACK "sus_black"
#define LABEL_SUSPICIOUS_MINI "sus_mini"
#define LABEL_SUSPICIOUS_MINI_BLACK "sus_mini_black"
#define LABEL_EZ_NUTRIENT "ez"
#define LABEL_ROBUST_HARVEST "robust"
#define LABEL_LEFT_4_ZED "l4z"
#define LABEL_SPACE_CLEANER "space_cleaner"
#define CAP_BLACK "black"
#define CAP_WHITE "white"
#define CAP_RED "red"
#define CAP_GREEN "green"
#define CAP_BLUE "blue"
/**
* The jerrycan is not only a flavourful, setting appropriate way to store reagents, it 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 without enabling big grenade creation.
* 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 allows 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 customization options for coders who with to add new variants.
**/
/obj/item/reagent_containers/cup/jerrycan
name = "plastic jerrycan"
desc = "A voluminous container made from the finest HDPE.\n\nNow with integrated Smart Cap™ technology to prevent expensive spills when handling industrial liquids."
icon = 'icons/obj/medical/chemical.dmi'
righthand_file = 'icons/mob/inhands/items/chemistry_righthand.dmi'
lefthand_file = 'icons/mob/inhands/items/chemistry_lefthand.dmi'
icon_state = "jerrycan"
inhand_icon_state = "jerrycan"
base_icon_state = "jerrycan"
custom_materials = list(/datum/material/plastic=SHEET_MATERIAL_AMOUNT*2)
w_class = WEIGHT_CLASS_BULKY
volume = 200
obj_flags = UNIQUE_RENAME
reagent_flags = OPENCONTAINER | SMART_CAP
fill_icon_thresholds = list(0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200)
possible_transfer_amounts = list(5, 10, 15, 30, 50, 100, 200)
adjust_color_contrast = TRUE
/**
* If we want the can to have a label. Use the defines at the top, add new ones if you add new labels.
* WARNING: How good any particular label looks is highly dependent on the colour of the reagent in the can.
* Exercise good judgement and choose a label with enough contrast for the intended contents.
**/
var/label_type
///Different cap colours.
var/cap_type
///You can use this var to tone down the strength of the highlight for less shiny types of plastic.
var/highlight_strenght = 1.0
/obj/item/reagent_containers/cup/jerrycan/update_overlays()
. = ..()
var/mutable_appearance/highlight = mutable_appearance(icon, "[base_icon_state]_highlight")
highlight.opacity = highlight.opacity * highlight_strenght
. += highlight
if(label_type)
. += mutable_appearance(icon, "[base_icon_state]_label_[label_type]")
if(cap_type)
. += mutable_appearance(icon, "[base_icon_state]_cap_[cap_type]")
/obj/item/reagent_containers/cup/jerrycan/worn_overlays(mutable_appearance/standing, isinhands, icon_file)
. = ..()
if(!isinhands)
return
if(fill_icon_thresholds && reagents.total_volume)
var/mutable_appearance/inhand_reagent_filling = mutable_appearance(icon_file, "[inhand_icon_state]_reagent_filling")
inhand_reagent_filling.color = mix_color_from_reagents(reagents.reagent_list)
. += inhand_reagent_filling
if(cap_type)
. += mutable_appearance(icon_file, "[base_icon_state]_cap_[cap_type]")
/obj/item/reagent_containers/cup/jerrycan/Initialize(mapload)
. = ..()
update_appearance()
/obj/item/reagent_containers/cup/jerrycan/opaque
fill_icon_thresholds = null
reagent_flags = REFILLABLE | DRAINABLE | SMART_CAP
highlight_strenght = 0.75
/obj/item/reagent_containers/cup/jerrycan/opaque/yellow
icon_state = "jerrycan_yellow"
inhand_icon_state = "jerrycan_yellow"
/obj/item/reagent_containers/cup/jerrycan/eznutriment
name = "E-Z-Nutrient™ can"
desc = "A large container presumably filled to the brim with 'E-Z-Nutrient'-brand plant nutrient. It can't get easier than this."
label_type = LABEL_EZ_NUTRIENT
list_reagents = list(/datum/reagent/plantnutriment/eznutriment = 200)
custom_price = PAYCHECK_CREW * 1
/obj/item/reagent_containers/cup/jerrycan/left4zed
name = "Left 4 Zed™ can"
desc = "A large container labled 'Left 4 Zed' plant nutrient. A good choice when the stronger stuff is unavailable."
label_type = LABEL_LEFT_4_ZED
cap_type = CAP_GREEN
list_reagents = list(/datum/reagent/plantnutriment/left4zednutriment = 200)
custom_price = PAYCHECK_CREW * 1.2
/obj/item/reagent_containers/cup/jerrycan/robustharvest
name = "Robust Harvest™ can"
desc = "A large container labled 'Robust Harvest' plant nutrient. Only trust 'Robust Harvest' for a robust yield."
label_type = LABEL_ROBUST_HARVEST
list_reagents = list(/datum/reagent/plantnutriment/robustharvestnutriment = 200)
custom_price = PAYCHECK_CREW * 1.5
/obj/item/reagent_containers/cup/jerrycan/ammonia
name = "NT-AG ammonia can"
desc = "A large container labled 'NT-AG' anhydrous ammonia. A warning label reads: Store separately from chlorine-based cleaning products!"
label_type = LABEL_TEXT
cap_type = CAP_BLUE
list_reagents = list(/datum/reagent/ammonia = 200)
/obj/item/reagent_containers/cup/jerrycan/diethylamine
name = "NT-AG diethylamine can"
label_type = LABEL_TEXT_OLD
cap_type = CAP_GREEN
desc = "A large container labled 'NT-AG' diethylamine. A disclaimer written in bold letters reads: FOR AGRICULTURAL USE ONLY. RESALE PROHIBITED."
list_reagents = list(/datum/reagent/diethylamine = 200)
/obj/item/reagent_containers/cup/jerrycan/sus
name = "DonkCo great value phlogiston can"
label_type = LABEL_SUSPICIOUS_BLACK
desc = "A large can of phlogiston, ostensibly for removing dried out Donk-pocket™ filling from the production line."
list_reagents = list(/datum/reagent/phlogiston = 200)
/obj/item/reagent_containers/cup/jerrycan/oil
name = "oil can"
label_type = LABEL_INFLAMMABLE
cap_type = CAP_RED
desc = "A large can full of synthetic lubricating oil."
list_reagents = list(/datum/reagent/fuel/oil = 200)
/obj/item/reagent_containers/cup/jerrycan/space_cleaner
name = "BLAM!™-brand non-foaming space cleaner can"
label_type = LABEL_SPACE_CLEANER
cap_type = CAP_RED
desc = "Stubborn stains, grease and grime got you cornered? No duty to retreat when you got BLAM!™ on your side!\nBLAM!™ - A WaffleCo product."
list_reagents = list(/datum/reagent/space_cleaner = 200)
/obj/item/reagent_containers/cup/jerrycan/milk
name = "milk jug"
label_type = LABEL_NT_MINI
cap_type = CAP_BLUE
desc = "A jug of most wholesome milk."
list_reagents = list(/datum/reagent/consumable/milk = 200)
#undef LABEL_TEXT
#undef LABEL_TEXT_OLD
#undef LABEL_INFLAMMABLE
#undef LABEL_NT
#undef LABEL_NT_MINI
#undef LABEL_SUSPICIOUS
#undef LABEL_SUSPICIOUS_BLACK
#undef LABEL_SUSPICIOUS_MINI
#undef LABEL_SUSPICIOUS_MINI_BLACK
#undef LABEL_EZ_NUTRIENT
#undef LABEL_ROBUST_HARVEST
#undef LABEL_LEFT_4_ZED
#undef LABEL_SPACE_CLEANER
#undef CAP_BLACK
#undef CAP_WHITE
#undef CAP_RED
#undef CAP_GREEN
#undef CAP_BLUE
@@ -269,6 +269,18 @@
build_path = /obj/item/reagent_containers/cup/beaker/large
departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SERVICE | DEPARTMENT_BITFLAG_SCIENCE
/datum/design/jerrycan
name = "Jerrycan"
id = "jerrycan"
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
materials = list(/datum/material/plastic =SHEET_MATERIAL_AMOUNT * 2)
category = list(
RND_CATEGORY_INITIAL,
RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_CHEMISTRY,
)
build_path = /obj/item/reagent_containers/cup/jerrycan
departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SERVICE | DEPARTMENT_BITFLAG_SCIENCE
/datum/design/igniter
name = "Igniter"
id = "igniter"
@@ -29,6 +29,7 @@
"dropper",
"pillbottle",
"xlarge_beaker",
"jerrycan",
)
experiments_to_unlock = list(
/datum/experiment/autopsy/human,
+3 -3
View File
@@ -10,9 +10,9 @@
products = list(
/obj/item/cultivator = 3,
/obj/item/plant_analyzer = 4,
/obj/item/reagent_containers/cup/bottle/nutrient/ez = 30,
/obj/item/reagent_containers/cup/bottle/nutrient/l4z = 20,
/obj/item/reagent_containers/cup/bottle/nutrient/rh = 10,
/obj/item/reagent_containers/cup/jerrycan/eznutriment = 6,
/obj/item/reagent_containers/cup/jerrycan/left4zed = 4,
/obj/item/reagent_containers/cup/jerrycan/robustharvest = 3,
/obj/item/reagent_containers/spray/pestspray = 20,
/obj/item/reagent_containers/syringe = 5,
/obj/item/secateurs = 3,
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

+1
View File
@@ -6064,6 +6064,7 @@
#include "code\modules\reagents\reagent_containers\condiment.dm"
#include "code\modules\reagents\reagent_containers\dropper.dm"
#include "code\modules\reagents\reagent_containers\hypospray.dm"
#include "code\modules\reagents\reagent_containers\jerrycan.dm"
#include "code\modules\reagents\reagent_containers\medigel.dm"
#include "code\modules\reagents\reagent_containers\misc.dm"
#include "code\modules\reagents\reagent_containers\patch.dm"