mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-28 07:38:05 +01:00
[MIRROR] Dehardcodes microwave cleaning, allows spray cleaner to work on dense objects such as windows [MDB IGNORE] (#24684)
* Dehardcodes microwave cleaning, allows spray cleaner to work on dense objects such as windows (#79354) ## About The Pull Request - Dehardcodes microwave cleaning - Instead of hard istyping for a rag, soap, or space cleaner, we just use `wash`. - Gets rid of a redundant signal - `COMSIG_ATOM_WASHED`: not only was it misleading (only sent to items), but it was pointless because `COMSIG_COMPONENT_CLEAN_ACT` is the same signal. - Improves microwave attackby code, splitting tool stuff into tool-procs - Allows spray cleaner to work on dense objects such as windows - Clicking on a dense object or mob adjacent to you with spray cleaner will spawn the puff cloud on the target, rather than on your own position. - This will skip the moveloop and just clean everything on the target turf alone. - This means you can spray down a bloody window with a spray bottle, as janitor gods intended. - It also means you can fill the spray with other stuff to spray onto dense objects directly, which might be worth noting. Especially for stuff like Napalm. Fixes #79261 ## Why It's Good For The Game Opens up the sandbox to allow more objects to clean microwaves + better code. ## Changelog 🆑 Melbert qol: Clicking on an adjacent dense object (or mob) with Spray Cleaner will now spritz it rather than doing nothing. This means you can use Spray Cleaner to clean bloodied windows, as the janitor gods intended. It also means you can fill a spray bottle with Napalm, I guess. refactor: Any cleaning object can now clean a microwave. /🆑 * Dehardcodes microwave cleaning, allows spray cleaner to work on dense objects such as windows --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
This commit is contained in:
@@ -125,7 +125,5 @@
|
||||
#define COMSIG_ATOM_GERM_EXPOSED "atom_germ_exposed"
|
||||
/// when atom is picked up from the floor or moved to an elevated structure: (datum/component/germ_exposure)
|
||||
#define COMSIG_ATOM_GERM_UNEXPOSED "atom_germ_unexposed"
|
||||
/// when atom is washed
|
||||
#define COMSIG_ATOM_WASHED "atom_washed"
|
||||
/// signal sent to puzzle pieces by activator
|
||||
#define COMSIG_PUZZLE_COMPLETED "puzzle_completed"
|
||||
|
||||
@@ -25,7 +25,7 @@ GLOBAL_LIST_INIT(floor_diseases, list(
|
||||
|
||||
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(examine))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(handle_movement))
|
||||
RegisterSignal(parent, COMSIG_ATOM_WASHED, PROC_REF(wash)) //Wash germs off dirty things
|
||||
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(wash)) //Wash germs off dirty things
|
||||
|
||||
RegisterSignals(parent, list(
|
||||
COMSIG_ITEM_DROPPED, //Dropped into the world
|
||||
@@ -46,13 +46,13 @@ GLOBAL_LIST_INIT(floor_diseases, list(
|
||||
/datum/component/germ_sensitive/UnregisterFromParent()
|
||||
REMOVE_TRAIT(parent, TRAIT_GERM_SENSITIVE, REF(src))
|
||||
UnregisterSignal(parent, list(
|
||||
COMSIG_ATOM_EXAMINE,
|
||||
COMSIG_MOVABLE_MOVED,
|
||||
COMSIG_ATOM_WASHED,
|
||||
COMSIG_ITEM_DROPPED,
|
||||
COMSIG_ATOM_EXITED,
|
||||
COMSIG_ITEM_PICKUP,
|
||||
COMSIG_ATOM_ENTERED,
|
||||
COMSIG_ATOM_EXAMINE,
|
||||
COMSIG_ATOM_EXITED,
|
||||
COMSIG_COMPONENT_CLEAN_ACT,
|
||||
COMSIG_ITEM_DROPPED,
|
||||
COMSIG_ITEM_PICKUP,
|
||||
COMSIG_MOVABLE_MOVED,
|
||||
))
|
||||
|
||||
/datum/component/germ_sensitive/Destroy()
|
||||
@@ -117,8 +117,10 @@ GLOBAL_LIST_INIT(floor_diseases, list(
|
||||
parent.AddComponent(/datum/component/infective, new random_disease, weak = TRUE)
|
||||
|
||||
/datum/component/germ_sensitive/proc/wash()
|
||||
SIGNAL_HANDLER
|
||||
if(infective)
|
||||
infective = FALSE
|
||||
qdel(parent.GetComponent(/datum/component/infective))
|
||||
return COMPONENT_CLEANED
|
||||
|
||||
#undef GERM_EXPOSURE_DELAY
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
var/lifetime = INFINITY
|
||||
///Are we a part of a stream?
|
||||
var/stream
|
||||
/// String used in combat logs containing reagents present for when the puff hits something
|
||||
var/logging_string
|
||||
|
||||
/obj/effect/decal/chempuff/Destroy(force)
|
||||
user = null
|
||||
@@ -22,28 +24,39 @@
|
||||
/obj/effect/decal/chempuff/blob_act(obj/structure/blob/B)
|
||||
return
|
||||
|
||||
/obj/effect/decal/chempuff/proc/end_life(datum/move_loop/engine)
|
||||
QDEL_IN(src, engine.delay) //Gotta let it stop drifting
|
||||
animate(src, alpha = 0, time = engine.delay)
|
||||
/obj/effect/decal/chempuff/proc/end_life(delay = 0.5 SECONDS)
|
||||
QDEL_IN(src, delay) //Gotta let it stop drifting
|
||||
animate(src, alpha = 0, time = delay)
|
||||
|
||||
/obj/effect/decal/chempuff/proc/loop_ended(datum/move_loop/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(QDELETED(src))
|
||||
return
|
||||
end_life(source)
|
||||
end_life(source.delay)
|
||||
|
||||
/obj/effect/decal/chempuff/proc/check_move(datum/move_loop/source, result)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(QDELETED(src)) //Reasons PLEASE WORK I SWEAR TO GOD
|
||||
return
|
||||
if(result == MOVELOOP_FAILURE) //If we hit something
|
||||
end_life(source)
|
||||
end_life(source.delay)
|
||||
return
|
||||
|
||||
var/puff_reagents_string = reagents.get_reagent_log_string()
|
||||
var/travelled_max_distance = (source.lifetime - source.delay <= 0)
|
||||
var/turf/our_turf = get_turf(src)
|
||||
spray_down_turf(get_turf(src), travelled_max_distance = (source.lifetime - source.delay <= 0))
|
||||
|
||||
for(var/atom/movable/turf_atom in our_turf)
|
||||
if(lifetime < 0) // Did we use up all the puff early?
|
||||
end_life(source.delay)
|
||||
|
||||
/**
|
||||
* Handles going through every movable on the passed turf and calling [spray_down_atom] on them.
|
||||
*
|
||||
* [travelled_max_distance] is used to determine if we're at the end of the life, as in some
|
||||
* contexts an atom may or may not end up being exposed depending on how far we've travelled.
|
||||
*/
|
||||
/obj/effect/decal/chempuff/proc/spray_down_turf(turf/spraying, travelled_max_distance = FALSE)
|
||||
for(var/atom/movable/turf_atom in spraying)
|
||||
if(turf_atom == src || turf_atom.invisibility) //we ignore the puff itself and stuff below the floor
|
||||
continue
|
||||
|
||||
@@ -51,8 +64,7 @@
|
||||
break
|
||||
|
||||
if(!stream)
|
||||
reagents.expose(turf_atom, VAPOR)
|
||||
log_combat(user, turf_atom, "sprayed", sprayer, addition="which had [puff_reagents_string]")
|
||||
spray_down_atom(turf_atom)
|
||||
if(ismob(turf_atom))
|
||||
lifetime -= 1
|
||||
continue
|
||||
@@ -65,23 +77,24 @@
|
||||
if(turf_mob.body_position != STANDING_UP && !travelled_max_distance)
|
||||
continue
|
||||
|
||||
reagents.expose(turf_mob, VAPOR)
|
||||
log_combat(user, turf_mob, "sprayed", sprayer, addition="which had [puff_reagents_string]")
|
||||
spray_down_atom(turf_atom)
|
||||
lifetime -= 1
|
||||
|
||||
else if(travelled_max_distance)
|
||||
reagents.expose(turf_atom, VAPOR)
|
||||
log_combat(user, turf_atom, "sprayed", sprayer, addition="which had [puff_reagents_string]")
|
||||
spray_down_atom(turf_atom)
|
||||
lifetime -= 1
|
||||
|
||||
if(lifetime >= 0 && (!stream || travelled_max_distance))
|
||||
reagents.expose(our_turf, VAPOR)
|
||||
log_combat(user, our_turf, "sprayed", sprayer, addition="which had [puff_reagents_string]")
|
||||
spray_down_atom(spraying)
|
||||
lifetime -= 1
|
||||
|
||||
// Did we use up all the puff early?
|
||||
if(lifetime < 0)
|
||||
end_life(source)
|
||||
/// Actually handles exposing the passed atom to the reagents and logging
|
||||
/obj/effect/decal/chempuff/proc/spray_down_atom(atom/spraying)
|
||||
if(isnull(logging_string))
|
||||
logging_string = reagents.get_reagent_log_string()
|
||||
|
||||
reagents.expose(spraying, VAPOR)
|
||||
log_combat(user, spraying, "sprayed", sprayer, addition = "which had [logging_string]")
|
||||
|
||||
/obj/effect/decal/fakelattice
|
||||
name = "lattice"
|
||||
|
||||
@@ -1374,12 +1374,9 @@
|
||||
// Update icons if this is being carried by a mob
|
||||
/obj/item/wash(clean_types)
|
||||
. = ..()
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_WASHED)
|
||||
|
||||
if(ismob(loc))
|
||||
var/mob/mob_loc = loc
|
||||
mob_loc.regenerate_icons()
|
||||
mob_loc.update_clothing(slot_flags)
|
||||
|
||||
/// Called on [/datum/element/openspace_item_click_handler/proc/on_afterattack]. Check the relative file for information.
|
||||
/obj/item/proc/handle_openspace_click(turf/target, mob/user, proximity_flag, click_parameters)
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
. = ..()
|
||||
|
||||
// All of these will use a full icon state instead
|
||||
if(panel_open || dirty == MAX_MICROWAVE_DIRTINESS || broken || dirty_anim_playing)
|
||||
if(panel_open || dirty >= MAX_MICROWAVE_DIRTINESS || broken || dirty_anim_playing)
|
||||
return .
|
||||
|
||||
var/ingredient_count = 0
|
||||
@@ -296,7 +296,7 @@
|
||||
icon_state = "[base_icon_state]mwb"
|
||||
else if(dirty_anim_playing)
|
||||
icon_state = "[base_icon_state]mwbloody1"
|
||||
else if(dirty == MAX_MICROWAVE_DIRTINESS)
|
||||
else if(dirty >= MAX_MICROWAVE_DIRTINESS)
|
||||
icon_state = open ? "[base_icon_state]mwbloodyo" : "[base_icon_state]mwbloody"
|
||||
else if(operating)
|
||||
icon_state = "[base_icon_state]back_on"
|
||||
@@ -310,80 +310,83 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/microwave/wrench_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
if(dirty >= MAX_MICROWAVE_DIRTINESS)
|
||||
return FALSE
|
||||
if(default_unfasten_wrench(user, tool))
|
||||
update_appearance()
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
/obj/machinery/microwave/crowbar_act(mob/living/user, obj/item/tool)
|
||||
if(operating)
|
||||
return
|
||||
if(!default_deconstruction_crowbar(tool))
|
||||
return
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
/obj/machinery/microwave/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool))
|
||||
update_appearance()
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
/obj/machinery/microwave/wirecutter_act(mob/living/user, obj/item/tool)
|
||||
if(broken != REALLY_BROKEN)
|
||||
return
|
||||
|
||||
user.visible_message(
|
||||
span_notice("[user] starts to fix part of [src]."),
|
||||
span_notice("You start to fix part of [src]..."),
|
||||
)
|
||||
|
||||
if(!tool.use_tool(src, user, 2 SECONDS, volume = 50))
|
||||
return TOOL_ACT_SIGNAL_BLOCKING
|
||||
|
||||
user.visible_message(
|
||||
span_notice("[user] fixes part of [src]."),
|
||||
span_notice("You fix part of [src]."),
|
||||
)
|
||||
broken = KINDA_BROKEN // Fix it a bit
|
||||
update_appearance()
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
/obj/machinery/microwave/welder_act(mob/living/user, obj/item/tool)
|
||||
if(broken != KINDA_BROKEN)
|
||||
return
|
||||
|
||||
user.visible_message(
|
||||
span_notice("[user] starts to fix part of [src]."),
|
||||
span_notice("You start to fix part of [src]..."),
|
||||
)
|
||||
|
||||
if(!tool.use_tool(src, user, 2 SECONDS, amount = 1, volume = 50))
|
||||
return TOOL_ACT_SIGNAL_BLOCKING
|
||||
|
||||
user.visible_message(
|
||||
span_notice("[user] fixes [src]."),
|
||||
span_notice("You fix [src]."),
|
||||
)
|
||||
broken = NOT_BROKEN
|
||||
update_appearance()
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
/obj/machinery/microwave/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking)
|
||||
if(operating)
|
||||
return
|
||||
if(dirty >= MAX_MICROWAVE_DIRTINESS)
|
||||
return
|
||||
if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool))
|
||||
update_appearance()
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
. = ..()
|
||||
if(. & TOOL_ACT_MELEE_CHAIN_BLOCKING)
|
||||
return
|
||||
|
||||
if(panel_open && is_wire_tool(tool))
|
||||
wires.interact(user)
|
||||
return TOOL_ACT_SIGNAL_BLOCKING
|
||||
|
||||
/obj/machinery/microwave/attackby(obj/item/item, mob/living/user, params)
|
||||
if(operating)
|
||||
return
|
||||
|
||||
if(panel_open && is_wire_tool(item))
|
||||
wires.interact(user)
|
||||
return TRUE
|
||||
|
||||
if(broken > NOT_BROKEN)
|
||||
if(broken == REALLY_BROKEN && item.tool_behaviour == TOOL_WIRECUTTER) // If it's broken and they're using a TOOL_WIRECUTTER
|
||||
user.visible_message(span_notice("[user] starts to fix part of \the [src]."), span_notice("You start to fix part of \the [src]..."))
|
||||
if(item.use_tool(src, user, 20))
|
||||
user.visible_message(span_notice("[user] fixes part of \the [src]."), span_notice("You fix part of \the [src]."))
|
||||
broken = KINDA_BROKEN // Fix it a bit
|
||||
else if(broken == KINDA_BROKEN && item.tool_behaviour == TOOL_WELDER) // If it's broken and they're doing the wrench
|
||||
user.visible_message(span_notice("[user] starts to fix part of \the [src]."), span_notice("You start to fix part of \the [src]..."))
|
||||
if(item.use_tool(src, user, 20))
|
||||
user.visible_message(span_notice("[user] fixes \the [src]."), span_notice("You fix \the [src]."))
|
||||
broken = NOT_BROKEN
|
||||
update_appearance()
|
||||
return FALSE //to use some fuel
|
||||
else
|
||||
if(IS_EDIBLE(item))
|
||||
balloon_alert(user, "it's broken!")
|
||||
return TRUE
|
||||
return
|
||||
|
||||
if(istype(item, /obj/item/reagent_containers/spray))
|
||||
var/obj/item/reagent_containers/spray/clean_spray = item
|
||||
open(autoclose = 2 SECONDS)
|
||||
if(clean_spray.reagents.has_reagent(/datum/reagent/space_cleaner, clean_spray.amount_per_transfer_from_this))
|
||||
clean_spray.reagents.remove_reagent(/datum/reagent/space_cleaner, clean_spray.amount_per_transfer_from_this,1)
|
||||
playsound(loc, 'sound/effects/spray3.ogg', 50, TRUE, -6)
|
||||
user.visible_message(span_notice("[user] cleans \the [src]."), span_notice("You clean \the [src]."))
|
||||
dirty = 0
|
||||
update_appearance()
|
||||
else
|
||||
to_chat(user, span_warning("You need more space cleaner!"))
|
||||
return TRUE
|
||||
|
||||
if(istype(item, /obj/item/soap) || istype(item, /obj/item/reagent_containers/cup/rag))
|
||||
var/cleanspeed = 50
|
||||
if(istype(item, /obj/item/soap))
|
||||
var/obj/item/soap/used_soap = item
|
||||
cleanspeed = used_soap.cleanspeed
|
||||
user.visible_message(span_notice("[user] starts to clean \the [src]."), span_notice("You start to clean \the [src]..."))
|
||||
open(autoclose = cleanspeed + 1 SECONDS)
|
||||
if(do_after(user, cleanspeed, target = src))
|
||||
user.visible_message(span_notice("[user] cleans \the [src]."), span_notice("You clean \the [src]."))
|
||||
dirty = 0
|
||||
update_appearance()
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
if(istype(item, /obj/item/stock_parts/cell) && cell_powered)
|
||||
var/swapped = FALSE
|
||||
@@ -402,12 +405,16 @@
|
||||
return TRUE
|
||||
|
||||
if(!anchored)
|
||||
balloon_alert(user, "not secured!")
|
||||
if(IS_EDIBLE(item))
|
||||
balloon_alert(user, "not secured!")
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
if(dirty >= MAX_MICROWAVE_DIRTINESS) // The microwave is all dirty so can't be used!
|
||||
balloon_alert(user, "it's too dirty!")
|
||||
return TRUE
|
||||
if(IS_EDIBLE(item))
|
||||
balloon_alert(user, "it's too dirty!")
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
if(vampire_charging_capable && istype(item, /obj/item/modular_computer/pda) && ingredients.len > 0)
|
||||
balloon_alert(user, "max 1 pda!")
|
||||
@@ -522,6 +529,15 @@
|
||||
if("examine")
|
||||
examine(user)
|
||||
|
||||
/obj/machinery/microwave/wash(clean_types)
|
||||
. = ..()
|
||||
if(operating || !(clean_types & CLEAN_SCRUB))
|
||||
return .
|
||||
|
||||
dirty = 0
|
||||
update_appearance()
|
||||
return . || TRUE
|
||||
|
||||
/obj/machinery/microwave/proc/eject()
|
||||
var/atom/drop_loc = drop_location()
|
||||
for(var/atom/movable/movable_ingredient as anything in ingredients)
|
||||
|
||||
@@ -50,18 +50,23 @@
|
||||
to_chat(user, span_warning("Not enough left!"))
|
||||
return
|
||||
|
||||
spray(target, user)
|
||||
if(proximity_flag && (target.density || ismob(target)))
|
||||
// If we're spraying an adjacent mob or a dense object, we start the spray on ITS tile rather than OURs
|
||||
// This is so we can use a spray bottle to clean stuff like windows without getting blocked by passflags
|
||||
spray(target, user, get_turf(target))
|
||||
else
|
||||
spray(target, user)
|
||||
|
||||
playsound(src.loc, spray_sound, 50, TRUE, -6)
|
||||
playsound(src, spray_sound, 50, TRUE, -6)
|
||||
user.changeNext_move(CLICK_CD_RANGE*2)
|
||||
user.newtonian_move(get_dir(target, user))
|
||||
return
|
||||
|
||||
/// Handles creating a chem puff that travels towards the target atom, exposing reagents to everything it hits on the way.
|
||||
/obj/item/reagent_containers/spray/proc/spray(atom/target, mob/user)
|
||||
/obj/item/reagent_containers/spray/proc/spray(atom/target, mob/user, turf/start_turf = get_turf(src))
|
||||
var/range = max(min(current_range, get_dist(src, target)), 1)
|
||||
|
||||
var/obj/effect/decal/chempuff/reagent_puff = new /obj/effect/decal/chempuff(get_turf(src))
|
||||
var/obj/effect/decal/chempuff/reagent_puff = new(start_turf)
|
||||
|
||||
reagent_puff.create_reagents(amount_per_transfer_from_this)
|
||||
var/puff_reagent_left = range //how many turf, mob or dense objet we can react with before we consider the chem puff consumed
|
||||
@@ -74,9 +79,7 @@
|
||||
var/wait_step = max(round(2+3/range), 2)
|
||||
|
||||
var/puff_reagent_string = reagent_puff.reagents.get_reagent_log_string()
|
||||
var/turf/src_turf = get_turf(src)
|
||||
|
||||
log_combat(user, src_turf, "fired a puff of reagents from", src, addition="with a range of \[[range]\], containing [puff_reagent_string].")
|
||||
log_combat(user, start_turf, "fired a puff of reagents from", src, addition="with a range of \[[range]\], containing [puff_reagent_string].")
|
||||
user.log_message("fired a puff of reagents from \a [src] with a range of \[[range]\] and containing [puff_reagent_string].", LOG_ATTACK)
|
||||
|
||||
// do_spray includes a series of step_towards and sleeps. As a result, it will handle deletion of the chempuff.
|
||||
@@ -84,11 +87,20 @@
|
||||
|
||||
/// Handles exposing atoms to the reagents contained in a spray's chempuff. Deletes the chempuff when it's completed.
|
||||
/obj/item/reagent_containers/spray/proc/do_spray(atom/target, wait_step, obj/effect/decal/chempuff/reagent_puff, range, puff_reagent_left, mob/user)
|
||||
var/datum/move_loop/our_loop = SSmove_manager.move_towards_legacy(reagent_puff, target, wait_step, timeout = range * wait_step, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY)
|
||||
reagent_puff.user = user
|
||||
reagent_puff.sprayer = src
|
||||
reagent_puff.lifetime = puff_reagent_left
|
||||
reagent_puff.stream = stream_mode
|
||||
|
||||
var/turf/target_turf = get_turf(target)
|
||||
var/turf/start_turf = get_turf(reagent_puff)
|
||||
if(target_turf == start_turf) // Don't need to bother movelooping if we don't move
|
||||
reagent_puff.setDir(user.dir)
|
||||
reagent_puff.spray_down_turf(target_turf)
|
||||
reagent_puff.end_life()
|
||||
return
|
||||
|
||||
var/datum/move_loop/our_loop = SSmove_manager.move_towards_legacy(reagent_puff, target, wait_step, timeout = range * wait_step, flags = MOVEMENT_LOOP_START_FAST, priority = MOVEMENT_ABOVE_SPACE_PRIORITY)
|
||||
reagent_puff.RegisterSignal(our_loop, COMSIG_QDELETING, TYPE_PROC_REF(/obj/effect/decal/chempuff, loop_ended))
|
||||
reagent_puff.RegisterSignal(our_loop, COMSIG_MOVELOOP_POSTPROCESS, TYPE_PROC_REF(/obj/effect/decal/chempuff, check_move))
|
||||
|
||||
@@ -181,7 +193,7 @@
|
||||
if(do_after(user, 3 SECONDS, user))
|
||||
if(reagents.total_volume >= amount_per_transfer_from_this)//if not empty
|
||||
user.visible_message(span_suicide("[user] pulls the trigger!"))
|
||||
spray(user)
|
||||
spray(user, user)
|
||||
return BRUTELOSS
|
||||
else
|
||||
user.visible_message(span_suicide("[user] pulls the trigger...but \the [src] is empty!"))
|
||||
|
||||
Reference in New Issue
Block a user