Files
Aurora.3/code/modules/detectivework/tools/rag.dm
Fluffy 9636363e60 Refactored the attack proc (#19908)
Refactored the attack proc signature.
Added signals and components for the attack proc.
Added signals and components for the attackby proc.
Adjusted some leftover attackby procs signatures.
Added grep test to ensure people don't keep adding attack/attackby procs
with the wrong signature.
2024-10-06 21:30:00 +00:00

320 lines
11 KiB
Plaintext

/mob
var/bloody_hands = null
var/datum/weakref/bloody_hands_mob
var/track_footprint = 0
var/list/feet_blood_DNA
var/track_footprint_type
var/footprint_color
/obj/item/clothing/gloves
var/transfer_blood = 0
var/datum/weakref/bloody_hands_mob
/obj/item/clothing/shoes/
var/track_footprint = 0
/obj/item/reagent_containers/glass/rag
name = "rag"
desc = "For cleaning up messes, you suppose."
w_class = WEIGHT_CLASS_TINY
icon = 'icons/obj/janitor.dmi'
icon_state = "rag"
amount_per_transfer_from_this = 5
possible_transfer_amounts = list(5)
volume = 10
can_be_placed_into = null
atom_flags = ATOM_FLAG_OPEN_CONTAINER
item_flags = ITEM_FLAG_NO_BLUDGEON
unacidable = FALSE
fragile = FALSE
drop_sound = 'sound/items/drop/cloth.ogg'
pickup_sound = 'sound/items/pickup/cloth.ogg'
var/on_fire = 0
var/burn_time = 20 //if the rag burns for too long it turns to ashes
var/cleantime = 30
var/last_clean
var/clean_msg = FALSE
/obj/item/reagent_containers/glass/rag/Initialize()
. = ..()
update_name()
update_icon()
/obj/item/reagent_containers/glass/rag/Destroy()
STOP_PROCESSING(SSprocessing, src) //so we don't continue turning to ash while gc'd
return ..()
/obj/item/reagent_containers/glass/rag/attack_self(mob/user)
if(on_fire)
user.visible_message(SPAN_WARNING("\The [user] stamps out \the [src]."), SPAN_WARNING("You stamp out \the [src]."))
user.unEquip(src)
extinguish()
else
remove_contents(user)
/obj/item/reagent_containers/glass/rag/attackby(obj/item/attacking_item, mob/user)
if(!on_fire && attacking_item.isFlameSource())
ignite()
if(on_fire)
visible_message(SPAN_WARNING("\The [user] lights \the [src] with \the [attacking_item]."))
else
to_chat(user, SPAN_WARNING("You manage to singe \the [src], but fail to light it."))
return TRUE
. = ..()
update_name()
update_icon()
/obj/item/reagent_containers/glass/rag/proc/update_name(var/base_name = initial(name))
SEND_SIGNAL(src, COMSIG_BASENAME_SETNAME, args)
if(on_fire)
name = "burning [base_name]"
else if(reagents.total_volume)
name = "damp [base_name]"
else
name = "dry [base_name]"
/obj/item/reagent_containers/glass/rag/update_icon()
if(on_fire)
icon_state = "[initial(icon_state)]_lit"
else if(reagents.total_volume)
icon_state = "[initial(icon_state)]_wet"
else
icon_state = "[initial(icon_state)]"
var/obj/item/reagent_containers/food/drinks/bottle/B = loc
if(istype(B))
B.update_icon()
/obj/item/reagent_containers/glass/rag/on_reagent_change()
update_name()
update_icon()
/obj/item/reagent_containers/glass/rag/proc/remove_contents(mob/user, atom/trans_dest = null)
if(!trans_dest && !user.loc)
return
if(reagents.total_volume)
var/target_text = trans_dest? "\the [trans_dest]" : "\the [user.loc]"
user.visible_message(SPAN_DANGER("\The [user] begins to wring out \the [src] over \the [target_text]."), SPAN_NOTICE("You begin to wring out \the [src] over \the [target_text]."))
if(do_after(user, reagents.total_volume*5)) //50 for a fully soaked rag
if(trans_dest)
reagents.trans_to(trans_dest, reagents.total_volume)
else
reagents.splash(user.loc, reagents.total_volume)
user.visible_message(SPAN_DANGER("\The [user] wrings out \the [src] over \the [target_text]."), SPAN_NOTICE("You finish wringing out \the [src]."))
update_name()
update_icon()
/obj/item/reagent_containers/glass/rag/proc/wipe_down(atom/A, mob/user)
if(!reagents.total_volume)
to_chat(user, SPAN_WARNING("\The [name] is dry!"))
else
if (!(last_clean && world.time < last_clean + 120) )
user.visible_message("<b>[user]</b> starts to wipe [A] with [src].")
clean_msg = TRUE
last_clean = world.time
else
clean_msg = FALSE
playsound(loc, 'sound/effects/mop.ogg', 25, 1)
update_name()
update_icon()
if(do_after(user,cleantime))
if(clean_msg)
user.visible_message("<b>[user]</b> finishes wiping [A].")
A.on_rag_wipe(src)
/obj/item/reagent_containers/glass/rag/attack(mob/living/target_mob, mob/living/user, target_zone)
if(isliving(target_mob))
var/mob/living/M = target_mob
if(on_fire)
user.visible_message(SPAN_DANGER("\The [user] hits \the [target_mob] with \the [src]!"))
user.do_attack_animation(src)
M.IgniteMob()
else if(ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
if(LAZYLEN(affecting.wounds))
for (var/datum/wound/W in affecting.wounds)
if(W.bandaged || W.clamped)
continue
to_chat(user, SPAN_NOTICE("You begin to bandage \a [W.desc] on [M]'s [affecting.name] with a rag."))
if(!do_mob(user, M, W.damage/10)) // takes twice as long as a normal bandage
to_chat(user, SPAN_NOTICE("You must stand still to bandage wounds."))
return
for(var/_R in reagents.reagent_volumes)
var/singleton/reagent/R = GET_SINGLETON(_R)
var/strength = R.germ_adjust * reagents.reagent_volumes[_R]/4
if(ispath(_R, /singleton/reagent/alcohol/ethanol))
var/singleton/reagent/alcohol/ethanol/A = R
strength = strength * (A.strength/100)
W.germ_level -= min(strength, W.germ_level)//Clean the wound a bit.
if (W.germ_level <= 0)
W.disinfected = TRUE//The wound becomes disinfected if fully cleaned
break
reagents.trans_to_mob(H, reagents.total_volume*0.75, CHEM_TOUCH) // most of it gets on the skin
reagents.trans_to_mob(H, reagents.total_volume*0.25, CHEM_BLOOD) // some gets in the wound
user.visible_message(SPAN_NOTICE("\The [user] bandages \a [W.desc] on [M]'s [affecting.name] with [src], tying it in place."), \
SPAN_NOTICE("You bandage \a [W.desc] on [M]'s [affecting.name] with [src], tying it in place."))
W.bandage()
qdel(src) // the rag is used up, it'll be all bloody and useless after
return // we can only do one at a time
else if(reagents.total_volume)
if(user.zone_sel.selecting == BP_MOUTH && !(M.wear_mask && M.wear_mask.item_flags & ITEM_FLAG_AIRTIGHT))
user.do_attack_animation(src)
user.visible_message(
SPAN_DANGER("\The [user] smothers [target_mob] with [src]!"),
SPAN_WARNING("You smother [target_mob] with [src]!"),
"You hear some struggling and muffled cries of surprise."
)
//it's inhaled, so... maybe CHEM_BLOOD doesn't make a whole lot of sense but it's the best we can do for now
//^HA HA HA
reagents.trans_to_mob(target_mob, amount_per_transfer_from_this, CHEM_BREATHE)
update_name()
update_icon()
else
wipe_down(target_mob, user)
return
return ..()
/obj/item/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user as mob, proximity)
if(!proximity)
return
if(istype(A, /obj/structure/sink))
return
else if(istype(A, /obj/structure/reagent_dispensers) || istype(A, /obj/structure/mopbucket) || istype(A, /obj/item/reagent_containers/glass))
if(!REAGENTS_FREE_SPACE(reagents))
to_chat(user, SPAN_WARNING("\The [src] is already soaked."))
return
if(A.reagents && A.reagents.trans_to_obj(src, reagents.maximum_volume))
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
user.visible_message(SPAN_NOTICE("\The [user] soaks \the [src] using \the [A]."), SPAN_NOTICE("You soak \the [src] using \the [A]."))
update_name()
update_icon()
return
else if(!on_fire && istype(A) && (src in user))
if(A.is_open_container() && !(A in user))
remove_contents(user, A)
else if(!ismob(A)) //mobs are handled in attack() - this prevents us from wiping down people while smothering them.
wipe_down(A, user)
return
/obj/item/reagent_containers/glass/rag/fire_act(exposed_temperature, exposed_volume)
. = ..()
if(exposed_temperature >= 50 + T0C)
ignite()
if(exposed_temperature >= 900 + T0C)
new /obj/effect/decal/cleanable/ash(get_turf(src))
qdel(src)
//rag must have a minimum of 2 units fuel and at least 80% of the reagents must be fuel.
//maybe generalize flammable reagents someday
/obj/item/reagent_containers/glass/rag/proc/can_ignite()
var/fuel = 0
for(var/fuel_type in reagents.reagent_volumes)
if(ispath(fuel_type, /singleton/reagent/fuel) || ispath(fuel_type, /singleton/reagent/alcohol))
fuel += reagents.reagent_volumes[fuel_type]
return (fuel >= 2 && fuel >= reagents.total_volume*0.8)
/obj/item/reagent_containers/glass/rag/proc/ignite()
if(on_fire)
return
if(!can_ignite())
return
//also copied from matches
if(REAGENT_VOLUME(reagents, /singleton/reagent/toxin/phoron)) // the phoron explodes when exposed to fire
visible_message(SPAN_DANGER("\The [src] conflagrates violently!"))
var/datum/effect/effect/system/reagents_explosion/e = new()
e.set_up(round(REAGENT_VOLUME(reagents, /singleton/reagent/toxin/phoron) / 2.5, 1), get_turf(src), 0, 0)
e.start()
qdel(src)
return
START_PROCESSING(SSprocessing, src)
set_light(2, null, "#E38F46")
on_fire = 1
update_name()
update_icon()
/obj/item/reagent_containers/glass/rag/proc/extinguish()
STOP_PROCESSING(SSprocessing, src)
set_light(0)
on_fire = 0
//rags sitting around with 1 second of burn time left is dumb.
//ensures players always have a few seconds of burn time left when they light their rag
if(burn_time <= 5)
visible_message(SPAN_WARNING("\The [src] falls apart!"))
if(istype(loc, /obj/item/reagent_containers/food/drinks/bottle))
var/obj/item/reagent_containers/food/drinks/bottle/B = loc
B.delete_rag()
else
new /obj/effect/decal/cleanable/ash(get_turf(src))
qdel(src)
return
update_name()
update_icon()
/obj/item/reagent_containers/glass/rag/process(seconds_per_tick)
if(!can_ignite())
visible_message(SPAN_WARNING("\The [src] burns out."))
extinguish()
//copied from matches
if(isliving(loc))
var/mob/living/M = loc
M.IgniteMob()
var/turf/location = get_turf(src)
if(location)
location.hotspot_expose(700, 5)
if(burn_time <= 0)
STOP_PROCESSING(SSprocessing, src)
if(istype(loc, /obj/item/reagent_containers/food/drinks/bottle))
var/obj/item/reagent_containers/food/drinks/bottle/B = loc
B.delete_rag()
else
new /obj/effect/decal/cleanable/ash(location)
qdel(src)
return
for(var/fuel_type in reagents.reagent_volumes)
if(ispath(fuel_type, /singleton/reagent/fuel) || ispath(fuel_type, /singleton/reagent/alcohol))
reagents.remove_reagent(fuel_type, ((reagents.maximum_volume/25) * seconds_per_tick))
break
update_name()
update_icon()
burn_time -= seconds_per_tick
/obj/item/reagent_containers/glass/rag/advanced
name = "microfiber cloth"
desc = "A synthetic fiber cloth; the split fibers and the size of the individual filaments make it more effective for cleaning purposes."
w_class = WEIGHT_CLASS_TINY
icon = 'icons/obj/janitor.dmi'
icon_state = "advrag"
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5)
volume = 10
cleantime = 15
/obj/item/reagent_containers/glass/rag/advanced/idris
name = "Idris advanced service cloth"
desc = "An advanced rag developed and sold by Idris Incorporated at a steep price. Its dry-clean design and advanced insulating synthetic weave make this the pinnacle of service cloths for any self-respecting chef or bartender!"
icon_state = "idrisrag"
volume = 15
/obj/item/reagent_containers/glass/rag/handkerchief
name = "handkerchief"
desc = "For cleaning a lady's hand, your bruised ego or a crime scene."
volume = 5
icon_state = "handkerchief"