Skip to content

Commit

Permalink
Reaction rates, pH, purity and more! Brings a heavily improved, less …
Browse files Browse the repository at this point in the history
…explosive and optimised fermichem to tg. (tgstation#56019)

Brings a heavily improved, rewritten, and optimised fermichem to tg. I saw that tg seemed receptive to it, so I thought I’d do it myself. If you know of fermichem – there’s a lot changed and improved, so looking at other documents regarding it will not be accurate.

Revamps the main chemistry reaction handler to allow for over time reactions instead of instant reactions. This revamp allows for simultaneous reactions, exo/endothermic reactions and pH consuming/producing behaviours. Most of the reactions in game will now inherit an easy one size fits all reaction.

Temperature mechanics

    Temperature affects reaction rate
    The higher it is, the faster it is, but be careful, as chem reactions will perform special functions when overheated (presently it DOESN’T explode)
    Temperature will increase or decrease depending on the exo/endothermic nature of the reaction

pH mechanics

    Each reaction requires the pH of a beaker to be within a certain range.
    If you are outside of the optimal, you'll incur impurity, which has a negative effect on the resultant chem
    pH of a beaker will change during a reaction
    Reacting Impure chem effects can vary from chem to chem, but for default will reduce the purity of other reagents in the beaker
    Consuming an impure chem will either cause liver or tox damage dependant on how impure it is as well as reducing consumed volume
    Purity can (presently) only be seen with a chemical analyser
    Impure chems can purposely be made by making the reagent with a low, but not explosive, purity.
    A chem made under the PurityMin will convert into the reagent’s failed chem in the beaker.

Optional catalysts

    Reactions can use an optional catalyst to influence the reaction - at the more framework exists from tmeprature, reaction rate and pH changes as a result of a catalyst. Catalysts can be set to only work on a specific reagent subtype. It is preferable to those building upon this code that optional catalysts only affect a subsection of reagents.
    Presently the only catalyst that uses this is Palladium synthate catalyst - a catalyst that increases the reaction speed of medicines.

Reaction agents

    These are reagents that will consume themselves when added to a beaker - even a full one, and apply effects to the total solution. One example being Tempomyocin which will speed up a reaction, or the buffer reagents which change the pH.

Competitive reactions

These reactions will go towards a certain product depending on the conditions of the holder. The example one given is a little tricky and requires a lot of temperature to push it towards one end.
New and charged reactions

(see the wiki for details)

Acidic /basic buffer - These reagents will adjust the pH of a beaker/solution when added to one. If the beaker is empty it will fill it instead.

Tempomyocin - This will instantly speed up any reaction added it is added to, giving it a short burst of speed. Adding this reagent to a reaction will give it a suddent speed boost up to 3x times - with the output purity of the boost modified by the Tempomyocin's purity.5u per 100u will give you 2x, 10 u per 100u will give you 3x. IIt caps at 3x for a single addition, but there is nothing preventing you from adding multiple doses for multiple boosts.

Purit tester - this will fizzle if the solution it is added to has an inverse purity reagent present.

A few other reactions have been tweaked to make sure they work too. An example being meth - see the wikipage linked above.
A note on all reactions

    The one size fits all reaction for all chems generally won’t create impure chems – it is very forgiving. The only thing to remember is to avoid heating reactions over 900 or you’ll reduce your yield, and try to keep your pH between 5 -9.

This PR doesn’t have specific example chems included (except for the buffers) – they will be atomised out and they use the mechanics in more depth
A note on plumbing

I reached out to Time Green and we worked together to make sure plumbing was fine. Time Green did some of his own tests too, and surprisingly it doesn't look like much needs to be changed.
  • Loading branch information
Thalpy committed Feb 11, 2021
1 parent 1748b5f commit 56f7ac0
Show file tree
Hide file tree
Showing 77 changed files with 3,913 additions and 550 deletions.
1 change: 1 addition & 0 deletions code/__DEFINES/achievements.dm
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#define MEDAL_RUST_ASCENSION "Rust"
#define MEDAL_VOID_ASCENSION "Void"
#define MEDAL_TOOLBOX_SOUL "Toolsoul"
#define MEDAL_CHEM_TUT "Beginner Chemist"

//Skill medal hub IDs
#define MEDAL_LEGENDARY_MINER "Legendary Miner"
Expand Down
2 changes: 2 additions & 0 deletions code/__DEFINES/dcs/signals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@
#define COMSIG_REAGENTS_TEMP_CHANGE "reagents_temp_change"
///from base of [/datum/reagents/proc/handle_reactions]: (num_reactions)
#define COMSIG_REAGENTS_REACTED "reagents_reacted"
///from base of [/datum/reagents/proc/process]: (num_reactions)
#define COMSIG_REAGENTS_REACTION_STEP "reagents_time_step"
///from base of [/atom/proc/expose_reagents]: (/atom, /list, methods, volume_modifier, show_message)
#define COMSIG_REAGENTS_EXPOSE_ATOM "reagents_expose_atom"
///from base of [/obj/proc/expose_reagents]: (/obj, /list, methods, volume_modifier, show_message)
Expand Down
40 changes: 40 additions & 0 deletions code/__DEFINES/reagents.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define TRANSPARENT (1<<5) // Used on containers which you want to be able to see the reagents off.
#define AMOUNT_VISIBLE (1<<6) // For non-transparent containers that still have the general amount of reagents in them visible.
#define NO_REACT (1<<7) // Applied to a reagent holder, the contents will not react with each other.
#define REAGENT_HOLDER_INSTANT_REACT (1<<8) // Applied to a reagent holder, all of the reactions in the reagents datum will be instant. Meant to be used for things like smoke effects where reactions aren't meant to occur

// Is an open container for all intents and purposes.
#define OPENCONTAINER (REFILLABLE | DRAINABLE | TRANSPARENT)
Expand Down Expand Up @@ -43,3 +44,42 @@
#define CONDIMASTER_STYLE_FALLBACK "_"

#define ALLERGIC_REMOVAL_SKIP "Allergy"

//Used in holder.dm/equlibrium.dm to set values and volume limits
///stops floating point errors causing issues with checking reagent amounts
#define CHEMICAL_QUANTISATION_LEVEL 0.0001
///The smallest amount of volume allowed - prevents tiny numbers
#define CHEMICAL_VOLUME_MINIMUM 0.001
///Round to this, to prevent extreme decimal magic and to keep reagent volumes in line with perceived values.
#define CHEMICAL_VOLUME_ROUNDING 0.01
///Default pH for reagents datum
#define CHEMICAL_NORMAL_PH 7.000

//reagent bitflags, used for altering how they works
///allows on_mob_dead() if present in a dead body
#define REAGENT_DEAD_PROCESS (1<<0)
///Do not split the chem at all during processing - ignores all purity effects
#define REAGENT_DONOTSPLIT (1<<1)
///Doesn't appear on handheld health analyzers.
#define REAGENT_INVISIBLE (1<<2)
///When inverted, the inverted chem uses the name of the original chem
#define REAGENT_SNEAKYNAME (1<<3)
///Retains initial volume of chem when splitting for purity effects
#define REAGENT_SPLITRETAINVOL (1<<4)

//Chemical reaction flags, for determining reaction specialties
///Convert into impure/pure on reaction completion
#define REACTION_CLEAR_IMPURE (1<<0)
///Convert into inverse on reaction completion when purity is low enough
#define REACTION_CLEAR_INVERSE (1<<1)
///Clear converted chems retain their purities/inverted purities. Requires 1 or both of the above.
#define REACTION_CLEAR_RETAIN (1<<2)
///Used to create instant reactions
#define REACTION_INSTANT (1<<3)
///Used to force reactions to create a specific amount of heat per 1u created. So if thermic_constant = 5, for 1u of reagent produced, the heat will be forced up arbitarily by 5 irresepective of other reagents. If you use this, keep in mind standard thermic_constant values are 100x what it should be with this enabled.
#define REACTION_HEAT_ARBITARY (1<<4)
///Used to bypass the chem_master transfer block (This is needed for competitive reactions unless you have an end state programmed). More stuff might be added later. When defining this, please add in the comments the associated reactions that it competes with
#define REACTION_COMPETITIVE (1<<5)

///Used to force an equlibrium to end a reaction in reaction_step() (i.e. in a reaction_step() proc return END_REACTION to end it)
#define END_REACTION "end_reaction"
2 changes: 2 additions & 0 deletions code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
#define INIT_ORDER_QUIRKS 60
#define INIT_ORDER_TICKER 55
#define INIT_ORDER_TCG 55
#define INIT_ORDER_REAGENTS 55 //HAS to be before mapping - mapping creates objects, which creates reagents, which relies on lists made in this subsystem
#define INIT_ORDER_MAPPING 50
#define INIT_ORDER_TIMETRACK 47
#define INIT_ORDER_NETWORKS 45
Expand Down Expand Up @@ -161,6 +162,7 @@
#define FIRE_PRIORITY_NPC 20
#define FIRE_PRIORITY_PROCESS 25
#define FIRE_PRIORITY_THROWING 25
#define FIRE_PRIORITY_REAGENTS 26
#define FIRE_PRIORITY_SPACEDRIFT 30
#define FIRE_PRIORITY_FIELDS 30
#define FIRE_PRIOTITY_SMOOTHING 35
Expand Down
14 changes: 10 additions & 4 deletions code/__HELPERS/_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,26 @@

#define LAZYINITLIST(L) if (!L) L = list()
#define UNSETEMPTY(L) if (L && !length(L)) L = null
#define LAZYCOPY(L) (L ? L.Copy() : list() )
///Like LAZYCOPY - copies an input list if the list has entries, If it doesn't the assigned list is nulled
#define LAZYLISTDUPLICATE(L) (L ? L.Copy() : null )
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!length(L)) { L = null; } }
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
#define LAZYOR(L, I) if(!L) { L = list(); } L |= I;
#define LAZYFIND(L, V) (L ? L.Find(V) : 0)
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= length(L) ? L[I] : null) : L[I]) : null)
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
#define LAZYLEN(L) length(L)
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
#define reverseList(L) reverseRange(L.Copy())
///Sets a list to null
#define LAZYNULL(L) L = null
#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += list(V);
#define LAZYREMOVEASSOC(L, K, V) if(L) { if(L[K]) { L[K] -= V; if(!length(L[K])) L -= K; } if(!length(L)) L = null; }
#define LAZYACCESSASSOC(L, I, K) L ? L[I] ? L[I][K] ? L[I][K] : null : null : null
#define QDEL_LAZYLIST(L) for(var/I in L) qdel(I); L = null;
//These methods don't null the list
#define LAZYCOPY(L) (L ? L.Copy() : list() ) //Use LAZYLISTDUPLICATE instead if you want it to null with no entries
#define LAZYCLEARLIST(L) if(L) L.Cut() // Consider LAZYNULL instead
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
#define reverseList(L) reverseRange(L.Copy())

/// Passed into BINARY_INSERT to compare keys
#define COMPARE_KEY __BIN_LIST[__BIN_MID]
Expand Down
4 changes: 4 additions & 0 deletions code/__HELPERS/reagents.dm
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/proc/chem_recipes_do_conflict(datum/chemical_reaction/r1, datum/chemical_reaction/r2)
//We have to check to see if either is competitive so can ignore it (competitive reagents are supposed to conflict)
if((r1.reaction_flags & REACTION_COMPETITIVE) || (r2.reaction_flags & REACTION_COMPETITIVE))
return FALSE

//do the non-list tests first, because they are cheaper
if(r1.required_container != r2.required_container)
return FALSE
Expand Down
7 changes: 7 additions & 0 deletions code/_compile_options.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
//#define REFERENCE_TRACKING
#ifdef REFERENCE_TRACKING

/*
* Enables debug messages for every single reaction step. This is 1 message per 0.5s for a SINGLE reaction. Useful for tracking down bugs/asking me for help in the main reaction handiler (equilibrium.dm).
*
* * Requires TESTING to be defined to work.
*/
//#define REAGENTS_TESTING

///Run a lookup on things hard deleting by default.
//#define GC_FAILURE_HARD_LOOKUP
#ifdef GC_FAILURE_HARD_LOOKUP
Expand Down
15 changes: 15 additions & 0 deletions code/_globalvars/bitfields.dm
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,18 @@ DEFINE_BITFIELD(zap_flags, list(
"ZAP_OBJ_DAMAGE" = ZAP_OBJ_DAMAGE,
"ZAP_GENERATES_POWER" = ZAP_GENERATES_POWER,
))

DEFINE_BITFIELD(chemical_flags, list(
"REAGENT_DEAD_PROCESS" = REAGENT_DEAD_PROCESS,
"REAGENT_DONOTSPLIT" = REAGENT_DONOTSPLIT,
"REAGENT_INVISIBLE" = REAGENT_INVISIBLE,
"REAGENT_SNEAKYNAME" = REAGENT_SNEAKYNAME,
"REAGENT_SPLITRETAINVOL" = REAGENT_SPLITRETAINVOL,
))

DEFINE_BITFIELD(reaction_flags, list(
"REACTION_CLEAR_IMPURE" = REACTION_CLEAR_IMPURE,
"REACTION_CLEAR_INVERSE" = REACTION_CLEAR_INVERSE,
"REACTION_CLEAR_RETAIN" = REACTION_CLEAR_RETAIN,
"REACTION_INSTANT" = REACTION_INSTANT,
))
42 changes: 42 additions & 0 deletions code/controllers/subsystem/processing/reagents.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//Used for active reactions in reagents/equilibrium datums

PROCESSING_SUBSYSTEM_DEF(reagents)
name = "Reagents"
init_order = INIT_ORDER_REAGENTS
priority = FIRE_PRIORITY_REAGENTS
wait = 0.25 SECONDS //You might think that rate_up_lim has to be set to half, but since everything is normalised around delta_time, it automatically adjusts it to be per second. Magic!
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
///What time was it when we last ticked
var/previous_world_time = 0

/datum/controller/subsystem/processing/reagents/Initialize()
. = ..()
//So our first step isn't insane
previous_world_time = world.time
//Build GLOB lists - see holder.dm
build_chemical_reagent_list()
build_chemical_reactions_list()
return

/datum/controller/subsystem/processing/reagents/fire(resumed = FALSE)
if (!resumed)
currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/current_run = currentrun

//Attempt to realtime reactions in a way that doesn't make them overtly dangerous
var/delta_realtime = (world.time - previous_world_time)/10 //normalise to s from ds
previous_world_time = world.time

while(current_run.len)
var/datum/thing = current_run[current_run.len]
current_run.len--
if(QDELETED(thing))
stack_trace("Found qdeleted thing in [type], in the current_run list.")
processing -= thing
else if(thing.process(delta_realtime) == PROCESS_KILL) //we are realtime
// fully stop so that a future START_PROCESSING will work
STOP_PROCESSING(src, thing)
if (MC_TICK_CHECK)
return
6 changes: 6 additions & 0 deletions code/datums/achievements/misc_achievements.dm
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,9 @@
desc = "My eternal soul was destroyed to make a toolbox look funny and all I got was this achievement..."
database_id = MEDAL_TOOLBOX_SOUL
icon = "toolbox_soul"

/datum/award/achievement/misc/chemistry_tut
name = "Perfect chemistry blossom"
desc = "Passed the chemistry tutorial with perfect purity!"
database_id = MEDAL_CHEM_TUT
icon = "chem_tut"
6 changes: 6 additions & 0 deletions code/datums/components/plumbing/reaction_chamber.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@
RC.emptying = TRUE //If we move this up, it'll instantly get turned off since any reaction always sets the reagent_total to zero. Other option is make the reaction update
//everything for every chemical removed, wich isn't a good option either.
RC.on_reagent_change(reagents) //We need to check it now, because some reactions leave nothing left.


/datum/component/plumbing/reaction_chamber/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net)
if(reagents.is_reacting == TRUE) //Let the thing react in peace
return
return ..()
2 changes: 1 addition & 1 deletion code/datums/quirks/negative.dm
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@
if("Psychologist")
heirloom_type = /obj/item/storage/pill_bottle
if("Chemist")
heirloom_type = /obj/item/book/manual/wiki/chemistry
heirloom_type = pick(/obj/item/book/manual/wiki/chemistry, /obj/item/ph_booklet)
if("Virologist")
heirloom_type = /obj/item/reagent_containers/syringe
//Engineering
Expand Down
5 changes: 4 additions & 1 deletion code/game/atoms.dm
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,10 @@
if(length(reagents.reagent_list))
if(user.can_see_reagents()) //Show each individual reagent
for(var/datum/reagent/R in reagents.reagent_list)
. += "[R.volume] units of [R.name]"
. += "[round(R.volume, 0.01)] units of [R.name]"
if(reagents.is_reacting)
. += "<span class='warning'>It is currently reacting!</span>"
. += "<span class='notice'>The solution's pH is [round(reagents.ph, 0.01)] and has a temperature of [reagents.chem_temp]K.</span>"
else //Otherwise, just show the total volume
var/total_volume = 0
for(var/datum/reagent/R in reagents.reagent_list)
Expand Down
2 changes: 2 additions & 0 deletions code/game/machinery/Sleeper.dm
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@
data["occupant"]["reagents"] = list()
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
if(R.chemical_flags & REAGENT_INVISIBLE) //Don't show hidden chems
continue
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
return data

Expand Down
4 changes: 4 additions & 0 deletions code/game/machinery/medical_kiosk.dm
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,17 @@
if(altPatient.reagents.reagent_list.len) //Chemical Analysis details.
for(var/r in altPatient.reagents.reagent_list)
var/datum/reagent/reagent = r
if(reagent.chemical_flags & REAGENT_INVISIBLE) //Don't show hidden chems
continue
chemical_list += list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01)))
if(reagent.overdosed)
overdose_list += list(list("name" = reagent.name))
var/obj/item/organ/stomach/belly = altPatient.getorganslot(ORGAN_SLOT_STOMACH)
if(belly?.reagents.reagent_list.len) //include the stomach contents if it exists
for(var/bile in belly.reagents.reagent_list)
var/datum/reagent/bit = bile
if(bit.chemical_flags & REAGENT_INVISIBLE) //Don't show hidden chems
continue
if(!belly.food_reagents[bit.type])
chemical_list += list(list("name" = bit.name, "volume" = round(bit.volume, 0.01)))
else
Expand Down
4 changes: 2 additions & 2 deletions code/game/objects/effects/effect_system/effects_foam.dm
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@

/obj/effect/particle_effect/foam/Initialize()
. = ..()
create_reagents(1000) //limited by the size of the reagent holder anyway.
create_reagents(1000, REAGENT_HOLDER_INSTANT_REACT) //limited by the size of the reagent holder anyway. Works without instant possibly edit in future
START_PROCESSING(SSfastprocess, src)
playsound(src, 'sound/effects/bubbles2.ogg', 80, TRUE, -3)

Expand Down Expand Up @@ -224,7 +224,7 @@
/datum/effect_system/foam_spread/New()
..()
chemholder = new /obj()
var/datum/reagents/R = new/datum/reagents(1000)
var/datum/reagents/R = new/datum/reagents(1000, REAGENT_HOLDER_INSTANT_REACT) //same as above
chemholder.reagents = R
R.my_atom = chemholder

Expand Down
5 changes: 3 additions & 2 deletions code/game/objects/effects/effect_system/effects_smoke.dm
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,9 @@
/datum/effect_system/smoke_spread/chem/New()
..()
chemholder = new /obj()
var/datum/reagents/R = new/datum/reagents(500)
var/datum/reagents/R = new (500, REAGENT_HOLDER_INSTANT_REACT) //This is a safety for now to prevent smoke generating more smoke as the smoke reagents react in the smoke. This is prevented naturally from happening even if this is off, but I want to be sure that any edge cases are prevented before I get a chance to rework smoke reactions (specifically adding water or reacting away stabilizing agent in the middle of it).
chemholder.reagents = R

R.my_atom = chemholder

/datum/effect_system/smoke_spread/chem/Destroy()
Expand All @@ -288,7 +289,7 @@
contained = "\[[contained]\]"

var/where = "[AREACOORD(location)]"
if(carry.my_atom.fingerprintslast)
if(carry.my_atom?.fingerprintslast) //Some reagents don't have a my_atom in some cases
var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
var/more = ""
if(M)
Expand Down
4 changes: 4 additions & 0 deletions code/game/objects/items/devices/scanners.dm
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,8 @@ GENE SCANNER
render_list += "<span class='notice ml-1'>Subject contains the following reagents in their blood:</span>\n"
for(var/r in M.reagents.reagent_list)
var/datum/reagent/reagent = r
if(reagent.chemical_flags & REAGENT_INVISIBLE) //Don't show hidden chems on scanners
continue
render_list += "<span class='notice ml-2'>[round(reagent.volume, 0.001)] units of [reagent.name][reagent.overdosed ? "</span> - <span class='boldannounce'>OVERDOSING</span>" : ".</span>"]\n"
else
render_list += "<span class='notice ml-1'>Subject contains no reagents in their blood.</span>\n"
Expand All @@ -439,6 +441,8 @@ GENE SCANNER
render_list += "<span class='notice ml-1'>Subject contains the following reagents in their stomach:</span>\n"
for(var/bile in belly.reagents.reagent_list)
var/datum/reagent/bit = bile
if(bit.chemical_flags & REAGENT_INVISIBLE) //Don't show hidden chems on scanners
continue
if(!belly.food_reagents[bit.type])
render_list += "<span class='notice ml-2'>[round(bit.volume, 0.001)] units of [bit.name][bit.overdosed ? "</span> - <span class='boldannounce'>OVERDOSING</span>" : ".</span>"]\n"
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
new /obj/item/storage/box/pillbottles(src)
new /obj/item/storage/box/medigels(src)
new /obj/item/storage/box/medigels(src)
new /obj/item/ph_booklet(src)
new /obj/item/reagent_containers/dropper(src)
new /obj/item/reagent_containers/glass/bottle/acidic_buffer(src) //hopefully they get the hint

/obj/structure/closet/secure_closet/chemical/heisenberg //contains one of each beaker, syringe etc.
name = "advanced chemical closet"
Expand Down
5 changes: 5 additions & 0 deletions code/modules/asset_cache/asset_list_items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,8 @@
/proc/sanitize_css_class_name(name)
var/static/regex/regex = new(@"[^a-zA-Z0-9]","g")
return replacetext(name, regex, "")

/datum/asset/simple/tutorial_advisors
assets = list(
"chem_help_advisor.gif" = 'icons/UI_Icons/Advisors/chem_help_advisor.gif',
)
3 changes: 2 additions & 1 deletion code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list(
reagents.expose(C, TOUCH)
var/permeability = 1 - C.get_permeability_protection(list(HEAD))
C.apply_damage(min(30 * permeability, reagents.total_volume), BURN, BODY_ZONE_HEAD)
reagents.remove_any((reagents.total_volume/2))
if(reagents.reagent_list) //This can runtime if reagents has nothing in it.
reagents.remove_any((reagents.total_volume/2))
C.Paralyze(60)
user.changeNext_move(CLICK_CD_MELEE)
return ..()
Expand Down
Loading

0 comments on commit 56f7ac0

Please sign in to comment.