Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bidons and Chemistry QOL #9131

Draft
wants to merge 17 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions code/__defines/flags.dm
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
/// This atom is queued for an overlay update.
#define ATOM_AWAITING_OVERLAY_UPDATE (1<<5)

///The Reagent cannot be refilled
#define ATOM_REAGENTS_NO_REFILL (1<<6)


/* -- /turf/var/turf_flags -- */

Expand Down
3 changes: 3 additions & 0 deletions code/game/atoms.dm
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ var/global/list/pre_init_created_atoms // atom creation ordering means some stuf
/atom/proc/is_open_container()
return atom_flags & ATOM_REAGENTS_IS_OPEN

/atom/proc/can_refill()
return atom_flags & ~ATOM_REAGENTS_NO_REFILL

/*//Convenience proc to see whether a container can be accessed in a certain way.

proc/can_subract_container()
Expand Down
5 changes: 4 additions & 1 deletion code/game/machinery/machinery.dm
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ Class Procs:
var/obj/item/circuitboard/circuit = null
var/list/materials = list() //Exclusively used for machines that take materials - lathes, fabricators etc. Honestly overdue for a whole lathe/fab refactor at some point.

var/anchor_type = null //What type of object can be anchored to a machine
var/anchor_direction = null //The immediate directions an object can be anchored to a machine. If null, any direction is allowed.

var/speed_process = FALSE //If false, SSmachines. If true, SSfastprocess.

required_dexterity = MOB_DEXTERITY_TOUCHSCREENS
Expand Down Expand Up @@ -486,4 +489,4 @@ Class Procs:
S.amount = round(materials[mat] / S.perunit)
else
qdel(S) //Prevents stacks smaller than 1
return
return
1 change: 1 addition & 0 deletions code/modules/reagents/holder/holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@




hex37 marked this conversation as resolved.
Show resolved Hide resolved
for(var/datum/reagent/current in reagent_list)
if(current.id == id)
if(current.id == "blood")
Expand Down
29 changes: 18 additions & 11 deletions code/modules/reagents/machinery/dispenser/reagent_tank.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,41 @@
anchored = 0
pressure_resistance = 2*ONE_ATMOSPHERE

var/volume = 5000

var/has_hose = TRUE
var/obj/item/hose_connector/input/active/InputSocket
var/obj/item/hose_connector/output/active/OutputSocket

atom_flags = ATOM_REAGENTS_NO_REFILL
var/amount_per_transfer_from_this = 10
var/possible_transfer_amounts = list(10,25,50,100)

/obj/structure/reagent_dispensers/attackby(obj/item/W as obj, mob/user as mob)
src.add_fingerprint(user)

/obj/structure/reagent_dispensers/Destroy()
QDEL_NULL(InputSocket)
QDEL_NULL(OutputSocket)
if(has_hose)
QDEL_NULL(InputSocket)
QDEL_NULL(OutputSocket)

..()

/obj/structure/reagent_dispensers/Initialize()
var/datum/reagents/R = new/datum/reagents(5000)
var/datum/reagents/R = new/datum/reagents(volume)
reagents = R
R.my_atom = src
if (!possible_transfer_amounts)
src.verbs -= /obj/structure/reagent_dispensers/verb/set_APTFT

InputSocket = new(src)
InputSocket.carrier = src
OutputSocket = new(src)
OutputSocket.carrier = src

if(has_hose)
InputSocket = new(src)
InputSocket.carrier = src
OutputSocket = new(src)
OutputSocket.carrier = src
. = ..()



/obj/structure/reagent_dispensers/examine(mob/user)
. = ..()
if(get_dist(user, src) <= 2)
Expand All @@ -57,6 +63,9 @@
if (N)
amount_per_transfer_from_this = N

/obj/structure/reagent_dispensers/blob_act()
qdel(src)

/obj/structure/reagent_dispensers/ex_act(severity)
switch(severity)
if(1.0)
Expand All @@ -75,8 +84,6 @@
else
return

/obj/structure/reagent_dispensers/blob_act()
qdel(src)



Expand Down
27 changes: 18 additions & 9 deletions code/modules/reagents/reagent_containers/_reagent_containers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
src.verbs -= /obj/item/reagent_containers/verb/set_APTFT
create_reagents(volume)

/obj/item/reagent_containers/on_reagent_change()
update_icon()

/obj/item/reagent_containers/attack_self(mob/user as mob)
return

Expand All @@ -38,12 +41,14 @@
return 0

if(!target.reagents || !target.reagents.total_volume)
to_chat(user, "<span class='notice'>[target] is empty.</span>")
return 1
if(target.can_refill())
return 0
else
to_chat(user, "<span class='notice'>[target] is empty.</span>")
return 1

if(reagents && !reagents.get_free_space())
to_chat(user, "<span class='notice'>[src] is full.</span>")
return 1
return 0

var/trans = target.reagents.trans_to_obj(src, target:amount_per_transfer_from_this)
to_chat(user, "<span class='notice'>You fill [src] with [trans] units of the contents of [target].</span>")
Expand Down Expand Up @@ -98,12 +103,12 @@
return FALSE

user.setClickCooldown(user.get_attack_speed(src)) //puts a limit on how fast people can eat/drink things
if(user == target)
if(user == target)
self_feed_message(user)
reagents.trans_to_mob(user, issmall(user) ? CEILING(amount_per_transfer_from_this/2, 1) : amount_per_transfer_from_this, CHEM_INGEST)
feed_sound(user)
return TRUE

else
other_feed_message_start(user, target)
if(!do_mob(user, target))
Expand All @@ -116,8 +121,8 @@
feed_sound(user)
return TRUE

/obj/item/reagent_containers/proc/standard_pour_into(var/mob/user, var/atom/target) // This goes into afterattack and yes, it's atom-level
if(!target.is_open_container() || !target.reagents)
/obj/item/reagent_containers/proc/standard_pour_into(var/mob/user, var/atom/target, var/pour_all = FALSE) // This goes into afterattack and yes, it's atom-level
if(!target.is_open_container() || !target.reagents || !target.can_refill())
return 0

if(!reagents || !reagents.total_volume)
Expand All @@ -128,6 +133,10 @@
to_chat(user, "<span class='notice'>[target] is full.</span>")
return 1

var/trans = reagents.trans_to(target, amount_per_transfer_from_this)
var/trans = 0
if(pour_all)
trans = reagents.trans_to(target, reagents.total_volume)
else
trans = reagents.trans_to(target, amount_per_transfer_from_this)
hex37 marked this conversation as resolved.
Show resolved Hide resolved
to_chat(user, "<span class='notice'>You transfer [trans] units of the solution to [target].</span>")
return 1
172 changes: 172 additions & 0 deletions code/modules/reagents/reagent_containers/bidon.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@

//this is big movable beaker
/obj/structure/reagent_dispensers/bidon
name = "B.I.D.O.N. canister"
desc = "Blue-Ink Dispenser Omnitech-Nanochem. A canister with acid-resistant linings intended for handling big volumes of chemicals."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ater pinged me about this being a bit questionable word salad like a month ago and the suggested replacement was:
Banded Industrial Drum for Organic Nonvolatiles
If Omnitech-Nanochem is a company you want namedropped it should probably be just in the desc and not the acronym.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this marked as resolved, no changes were made?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies, forgot to push a name change fix.

icon = 'icons/obj/machines/chemistry.dmi'
icon_state = "bidon"
amount_per_transfer_from_this = 30
possible_transfer_amounts = list(10,30,60,120,200,300)
var/filling_states = list(10,20,30,40,50,60,70,80,100)
unacidable = 1
anchored = 0
var/obj/machinery/anchored_machine
density = TRUE
volume = 6000
var/lid = TRUE
var/starting_reagent
var/starting_volume = 0
has_hose=FALSE
atom_flags = EMPTY_BITFIELD

/obj/structure/reagent_dispensers/bidon/Initialize()
. = ..()
if(starting_reagent && starting_volume)
reagents.add_reagent(starting_reagent, starting_volume)

/obj/structure/reagent_dispensers/bidon/advanced
name = "stasis B.I.D.O.N. canister"
desc = "An advanced B.I.D.O.N. canister with stasis function."
icon_state = "bidon_adv"
atom_flags = ATOM_REAGENTS_SKIP_REACTIONS // It's a stasis BIDON, shouldn't allow chems to react inside it.
filling_states = list(20,40,60,80,100)
volume = 9000

/obj/structure/reagent_dispensers/bidon/trigger
name = "trigger-stasis B.I.D.O.N. canister"
desc = "An advanced B.I.D.O.N. canister with a stasis function that can be temporarily disabled with a multitool."
icon_state = "bidon_adv"
atom_flags = ATOM_REAGENTS_SKIP_REACTIONS //Tho its not a subtype its meant to be
filling_states = list(20,40,60,80,100)
volume = 9000
var/timer_till_mixing = 120
var/timing = FALSE

/obj/structure/reagent_dispensers/bidon/trigger/examine(mob/user)
. = ..()
if(timing)
to_chat(user, SPAN_DANGER("[timer_till_mixing] seconds until stasis is disabled."))
else
to_chat(user, SPAN_NOTICE("[src]'s timer isn't activated."))

/obj/structure/reagent_dispensers/bidon/trigger/attackby(obj/item/I, mob/user)
if(!timing)
if(I.is_multitool())
timing=TRUE
to_chat(user, SPAN_NOTICE("You start the timer."))
spawn(10 * timer_till_mixing)
timer_end()
timing=FALSE
return
hex37 marked this conversation as resolved.
Show resolved Hide resolved
else
. = ..()
update_icon()

/obj/structure/reagent_dispensers/bidon/trigger/proc/timer_end()
atom_flags &= ~(ATOM_REAGENTS_SKIP_REACTIONS)
spawn(10)
atom_flags |= ATOM_REAGENTS_SKIP_REACTIONS
reagents.handle_reactions()
hex37 marked this conversation as resolved.
Show resolved Hide resolved

/obj/structure/reagent_dispensers/bidon/Initialize(mapload, ...)
. = ..()
update_icon()

/obj/structure/reagent_dispensers/bidon/examine(mob/user)
. = ..()
if(get_dist(user, src) <= 2)
if(lid)
to_chat(user, SPAN_NOTICE("It has lid on it."))
if(reagents.total_volume)
to_chat(user, SPAN_NOTICE("It's filled with [reagents.total_volume]/[volume] units of reagents."))
hex37 marked this conversation as resolved.
Show resolved Hide resolved

/obj/structure/reagent_dispensers/bidon/attack_hand(mob/user as mob)
//Prevent the bidon from being messed with while it is anchored.
if(anchored)
to_chat(user, SPAN_NOTICE("You can't remove the lid while the canister is anchored!"))
return
lid = !lid
if(lid)
to_chat(user, SPAN_NOTICE("You put the lid on."))
atom_flags &= ~(ATOM_REAGENTS_IS_OPEN)
else
atom_flags |= ATOM_REAGENTS_IS_OPEN
to_chat(user, SPAN_NOTICE("You removed the lid."))
playsound(src,'sound/items/trayhit2.ogg',50,1)
update_icon()

/obj/structure/reagent_dispensers/bidon/attackby(obj/item/I, mob/user)

//Handle attaching the BIDON to a valid machine, should one exist
if(I.is_wrench())
if(anchored)
anchored = FALSE
anchored_machine = null
playsound(src, I.usesound, 50, 1)
else
Comment on lines +101 to +105
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if(anchored)
anchored = FALSE
anchored_machine = null
playsound(src, I.usesound, 50, 1)
else
if(anchored)
anchored = FALSE
anchored_machine = null
playsound(src, I.usesound, 50, 1)

and dedent everything that was in the else block

var/list/directions = list(WEST, NORTH, SOUTH, EAST)
for(var/direction_from_obj in directions)
for (var/obj/machinery/valid_machine in get_step(get_turf(src), direction_from_obj))
Comment on lines +106 to +108
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var/list/directions = list(WEST, NORTH, SOUTH, EAST)
for(var/direction_from_obj in directions)
for (var/obj/machinery/valid_machine in get_step(get_turf(src), direction_from_obj))
for (var/obj/machinery/valid_machine in orange(1))

anchor_direction is bound to cardinals, and reverse_direction() respects diagonals, so the equality will much more concisely exclude diagonal candidates.

if(valid_machine.anchor_type && ispath(valid_machine.anchor_type, /obj/structure/reagent_dispensers/bidon))
hex37 marked this conversation as resolved.
Show resolved Hide resolved
if(valid_machine.anchor_direction)
if(valid_machine.anchor_direction == reverse_direction(direction_from_obj))
anchored_machine = valid_machine
break
else
anchored_machine = valid_machine
break
Comment on lines +110 to +116
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if(valid_machine.anchor_direction)
if(valid_machine.anchor_direction == reverse_direction(direction_from_obj))
anchored_machine = valid_machine
break
else
anchored_machine = valid_machine
break
if(!valid_machine.anchor_direction || valid_machine.anchor_direction == get_dir(valid_machine, src))
anchored_machine = valid_machine
break

if(anchored_machine)
to_chat(user, SPAN_NOTICE("You [anchored ? "detach" : "attach"] the B.I.D.O.N canister to the [anchored_machine]."))
Comment on lines +117 to +118
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code doesn't detach the machine.

anchored = TRUE
playsound(src, I.usesound, 50, 1)
//Remove the lid if it is currently sealed, so we don't have to deal with checking for it
if(lid)
to_chat(user, SPAN_NOTICE("The machine removes the lid automatically!"))
lid = FALSE
atom_flags |= ATOM_REAGENTS_IS_OPEN
playsound(src,'sound/items/trayhit2.ogg',50,1)
update_icon()
return
hex37 marked this conversation as resolved.
Show resolved Hide resolved
else if(lid)
to_chat(user, SPAN_NOTICE("Remove the lid first."))
return
. = ..()
update_icon()
Comment on lines +130 to +131
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
. = ..()
update_icon()
else
. = ..()
update_icon()


/obj/structure/reagent_dispensers/bidon/update_icon()
cut_overlays()
if(lid)
var/mutable_appearance/lid_icon = mutable_appearance(icon, "[icon_state]_lid")
add_overlay(lid_icon)
if(anchored)
var/mutable_appearance/anchor_icon = mutable_appearance(icon, "bidon_anchored")
add_overlay(anchor_icon)
if(reagents.total_volume)
var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "[icon_state][get_filling_state()]")
if(!istype(src,/obj/structure/reagent_dispensers/bidon/advanced))
filling.color = reagents.get_color()
add_overlay(filling)

/obj/structure/reagent_dispensers/bidon/proc/get_filling_state()
var/percent = round((reagents.total_volume / volume) * 100)
for(var/increment in filling_states)
if(increment >= percent)
return increment

/obj/structure/reagent_dispensers/bidon/advanced/examine(mob/user)
if(!..(user, 2))
return
if(reagents.reagent_list.len)
for(var/I in reagents.reagent_list)
var/datum/reagent/R = I
to_chat(user, "<span class='notice'>[R.volume] units of [R.name]</span>")
hex37 marked this conversation as resolved.
Show resolved Hide resolved

//Preset Bidon of Animal Protein for testing
/obj/structure/reagent_dispensers/bidon/protein_can
starting_reagent = "protein"


//Department starting protein to get the process off the ground
/obj/structure/reagent_dispensers/bidon/protein_can/si
starting_reagent = "protein"
starting_volume = 1000
hex37 marked this conversation as resolved.
Show resolved Hide resolved
9 changes: 9 additions & 0 deletions code/modules/reagents/reagent_containers/glass.dm
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,19 @@
for(var/type in can_be_placed_into) //Is it something it can be placed into?
if(istype(target, type))
return 1


//Disarm intent tries to empty the beaker
if(user.a_intent == I_DISARM)
if(standard_pour_into(user, target, TRUE))
return
hex37 marked this conversation as resolved.
Show resolved Hide resolved

if(standard_dispenser_refill(user, target)) //Are they clicking a water tank/some dispenser?
return 1

if(standard_pour_into(user, target)) //Pouring into another beaker?
return

if(user.a_intent == I_HURT)
if(standard_splash_mob(user,target))
return 1
Expand Down
Loading