diff --git a/code/__DEFINES/acid.dm b/code/__DEFINES/acid.dm new file mode 100644 index 00000000000..86199b67495 --- /dev/null +++ b/code/__DEFINES/acid.dm @@ -0,0 +1,21 @@ +/// The acid power required to destroy most closed turfs. +#define ACID_POWER_MELT_TURF 200 +/// The maximum amount of damage (per tick) acid can deal to an [/obj]. +#define OBJ_ACID_DAMAGE_MAX 300 +/// Maximum acid volume that can be applied to an [/obj]. +#define OBJ_ACID_VOLUME_MAX 300 +/// Maximum acid volume that can be applied to a [/mob/living]. +#define MOB_ACID_VOLUME_MAX 1000 +/// Maximum acid volume that can be applied to a [/turf]. +#define TURF_ACID_VOLUME_MAX 12000 + +// Acid decay rate constants. +/// The constant factor for the acid decay rate. +#define ACID_DECAY_BASE 1 +/// The scaling factor for the acid decay rate. +#define ACID_DECAY_SCALING 1 + +/// The default icon state for the acid overlay. Not to be confused with the error icon state. +#define ACID_OVERLAY_DEFAULT "default" +/// The combined acid power and acid volume required to burn hands. +#define ACID_LEVEL_HANDBURN 20 diff --git a/code/__DEFINES/cleaning.dm b/code/__DEFINES/cleaning.dm index 53f4887fa20..343956a0655 100644 --- a/code/__DEFINES/cleaning.dm +++ b/code/__DEFINES/cleaning.dm @@ -3,18 +3,28 @@ // Different kinds of things that can be cleaned. // Use these when overriding the wash proc or registering for the clean signals to check if your thing should be cleaned -#define CLEAN_TYPE_BLOOD (1 << 0) -#define CLEAN_TYPE_RUNES (1 << 1) -#define CLEAN_TYPE_FINGERPRINTS (1 << 2) -#define CLEAN_TYPE_FIBERS (1 << 3) -#define CLEAN_TYPE_RADIATION (1 << 4) -#define CLEAN_TYPE_DISEASE (1 << 5) -#define CLEAN_TYPE_WEAK (1 << 6) // Special type, add this flag to make some cleaning processes non-instant. Currently only used for showers when removing radiation. -#define CLEAN_TYPE_PAINT (1 << 7) +/// Cleans blood off of the cleanable atom. +#define CLEAN_TYPE_BLOOD (1 << 0) +/// Cleans runes off of the cleanable atom. +#define CLEAN_TYPE_RUNES (1 << 1) +/// Cleans fingerprints off of the cleanable atom. +#define CLEAN_TYPE_FINGERPRINTS (1 << 2) +/// Cleans fibres off of the cleanable atom. +#define CLEAN_TYPE_FIBERS (1 << 3) +/// Cleans radiation off of the cleanable atom. +#define CLEAN_TYPE_RADIATION (1 << 4) +/// Cleans diseases off of the cleanable atom. +#define CLEAN_TYPE_DISEASE (1 << 5) +/// Special type, add this flag to make some cleaning processes non-instant. Currently only used for showers when removing radiation. +#define CLEAN_TYPE_WEAK (1 << 6) +/// Cleans paint off of the cleanable atom. +#define CLEAN_TYPE_PAINT (1 << 7) +/// Cleans acid off of the cleanable atom. +#define CLEAN_TYPE_ACID (1 << 8) // Different cleaning methods. // Use these when calling the wash proc for your cleaning apparatus -#define CLEAN_WASH (CLEAN_TYPE_BLOOD | CLEAN_TYPE_RUNES | CLEAN_TYPE_DISEASE) +#define CLEAN_WASH (CLEAN_TYPE_BLOOD | CLEAN_TYPE_RUNES | CLEAN_TYPE_DISEASE | CLEAN_TYPE_ACID) #define CLEAN_SCRUB (CLEAN_WASH | CLEAN_TYPE_FINGERPRINTS | CLEAN_TYPE_FIBERS | CLEAN_TYPE_PAINT) #define CLEAN_RAD CLEAN_TYPE_RADIATION #define CLEAN_ALL (ALL & ~CLEAN_TYPE_WEAK) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 14d5a38b64d..c605f5ea3d2 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -161,10 +161,21 @@ //from base of atom/movable/on_exit_storage(): (datum/component/storage/concrete/master_storage) #define CONSIG_STORAGE_EXITED "storage_exited" -///from base of atom/expose_reagents(): +///from base of atom/expose_reagents(): (/list, /datum/reagents, methods, volume_modifier, show_message) #define COMSIG_ATOM_EXPOSE_REAGENTS "atom_expose_reagents" /// Prevents the atom from being exposed to reagents if returned on [COMPONENT_ATOM_EXPOSE_REAGENTS] #define COMPONENT_NO_EXPOSE_REAGENTS (1<<0) +///from base of [/datum/reagent/proc/expose_atom]: (/datum/reagent, reac_volume) +#define COMSIG_ATOM_EXPOSE_REAGENT "atom_expose_reagent" +///from base of [/datum/reagent/proc/expose_atom]: (/atom, reac_volume) +#define COMSIG_REAGENT_EXPOSE_ATOM "reagent_expose_atom" +///from base of [/datum/reagent/proc/expose_atom]: (/obj, reac_volume) +#define COMSIG_REAGENT_EXPOSE_OBJ "reagent_expose_obj" +///from base of [/datum/reagent/proc/expose_atom]: (/mob/living, reac_volume, methods, show_message, touch_protection, /mob/camera/blob) // ovemind arg is only used by blob reagents. +#define COMSIG_REAGENT_EXPOSE_MOB "reagent_expose_mob" +///from base of [/datum/reagent/proc/expose_atom]: (/turf, reac_volume) +#define COMSIG_REAGENT_EXPOSE_TURF "reagent_expose_turf" + ///Called right before the atom changes the value of light_range to a different one, from base atom/set_light_range(): (new_range) #define COMSIG_ATOM_SET_LIGHT_RANGE "atom_set_light_range" ///Called right before the atom changes the value of light_power to a different one, from base atom/set_light_power(): (new_power) @@ -653,6 +664,8 @@ ///Called on an object to "clean it", such as removing blood decals/overlays, etc. The clean types bitfield is sent with it. Return TRUE if any cleaning was necessary and thus performed. #define COMSIG_COMPONENT_CLEAN_ACT "clean_act" + ///Returned by cleanable components when they are cleaned. + #define COMPONENT_CLEANED (1<<0) //Creamed diff --git a/code/controllers/subsystem/acid.dm b/code/controllers/subsystem/acid.dm deleted file mode 100644 index 49c4f58ffa9..00000000000 --- a/code/controllers/subsystem/acid.dm +++ /dev/null @@ -1,37 +0,0 @@ -SUBSYSTEM_DEF(acid) - name = "Acid" - priority = FIRE_PRIORITY_ACID - flags = SS_NO_INIT|SS_BACKGROUND - runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - - var/list/currentrun = list() - var/list/processing = list() - -/datum/controller/subsystem/acid/stat_entry(msg) - msg = "P:[length(processing)]" - return ..() - - -/datum/controller/subsystem/acid/fire(resumed = FALSE) - if (!resumed) - src.currentrun = processing.Copy() - - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - - while (currentrun.len) - var/obj/O = currentrun[currentrun.len] - currentrun.len-- - if (!O || QDELETED(O)) - processing -= O - if (MC_TICK_CHECK) - return - continue - - if(O.acid_level && O.acid_processing()) - else - O.update_icon() - processing -= O - - if (MC_TICK_CHECK) - return diff --git a/code/controllers/subsystem/processing/acid.dm b/code/controllers/subsystem/processing/acid.dm new file mode 100644 index 00000000000..a92880f51e3 --- /dev/null +++ b/code/controllers/subsystem/processing/acid.dm @@ -0,0 +1,6 @@ +/// The subsystem used to tick [/datum/component/acid] instances. +PROCESSING_SUBSYSTEM_DEF(acid) + name = "Acid" + priority = FIRE_PRIORITY_ACID + flags = SS_NO_INIT|SS_BACKGROUND + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME diff --git a/code/datums/components/acid.dm b/code/datums/components/acid.dm new file mode 100644 index 00000000000..80487255bd7 --- /dev/null +++ b/code/datums/components/acid.dm @@ -0,0 +1,215 @@ +/** Component representing acid applied to an object. + * + * Must be attached to an atom. + * Processes, repeatedly damaging whatever it is attached to. + * If the parent atom is a turf it applies acid to the contents of the turf. + */ +/datum/component/acid + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// The strength of the acid on the parent [/atom]. + var/acid_power + /// The volume of acid on the parent [/atom]. + var/acid_volume + /// The maximum volume of acid on the parent [/atom]. + var/max_volume = INFINITY + /// The ambiant sound of acid eating away at the parent [/atom]. + var/datum/looping_sound/acid/sizzle + /// Used exclusively for melting turfs. TODO: Move integrity to the atom level so that this can be dealt with there. + var/parent_integrity = 30 + /// The proc used to handle the parent [/atom] when processing. TODO: Unify damage and resistance flags so that this doesn't need to exist! + var/datum/callback/process_effect + +/datum/component/acid/Initialize(_acid_power, _acid_volume, _max_volume=null) + if((_acid_power) <= 0 || (_acid_volume <= 0)) + stack_trace("Acid component added with insufficient acid power ([_acid_power]) or acid volume ([_acid_power]).") + return COMPONENT_INCOMPATIBLE // Not enough acid or the acid's too weak, either one. + if(!isatom(parent)) + stack_trace("Acid component added to [parent] ([parent?.type]) which is not a /atom subtype.") + return COMPONENT_INCOMPATIBLE // Incompatible type. TODO: Rework take_damage to the atom level and move this there. + + if(isobj(parent)) + var/obj/parent_object = parent + if(parent_object.resistance_flags & UNACIDABLE) // The parent object cannot have acid. Should never happen, will happen. + stack_trace("Acid component added to unacidable object [parent].") + return COMPONENT_INCOMPATIBLE + + max_volume = OBJ_ACID_VOLUME_MAX + process_effect = CALLBACK(src, .proc/process_obj, parent) + else if(isliving(parent)) + max_volume = MOB_ACID_VOLUME_MAX + process_effect = CALLBACK(src, .proc/process_mob, parent) + else if(isturf(parent)) + max_volume = TURF_ACID_VOLUME_MAX + process_effect = CALLBACK(src, .proc/process_turf, parent) + + acid_power = _acid_power + set_volume(_acid_volume) + + var/atom/parent_atom = parent + RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/on_update_overlays) + parent_atom.update_icon() + sizzle = new(list(parent), TRUE) + START_PROCESSING(SSacid, src) + +/datum/component/acid/Destroy(force, silent) + STOP_PROCESSING(SSacid, src) + if(sizzle) + QDEL_NULL(sizzle) + if(process_effect) + QDEL_NULL(process_effect) + UnregisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS) + if(parent && !QDELING(parent)) + var/atom/parent_atom = parent + parent_atom.update_icon() + return ..() + +/datum/component/acid/RegisterWithParent() + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine) + RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/on_clean) + RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand) + RegisterSignal(parent, COMSIG_ATOM_EXPOSE_REAGENT, .proc/on_expose_reagent) + if(isturf(parent)) + RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/on_crossed) + +/datum/component/acid/UnregisterFromParent() + UnregisterSignal(parent, list( + COMSIG_PARENT_EXAMINE, + COMSIG_COMPONENT_CLEAN_ACT, + COMSIG_ATOM_ATTACK_HAND, + COMSIG_ATOM_EXPOSE_REAGENT)) + + if(isturf(parent)) + UnregisterSignal(parent, COMSIG_MOVABLE_CROSSED) + +/// Averages corrosive power and sums volume. +/datum/component/acid/InheritComponent(datum/component/C, i_am_original, _acid_power, _acid_volume) + acid_power = ((acid_power * acid_volume) + (_acid_power * _acid_volume)) / (acid_volume + _acid_volume) + set_volume(acid_volume + _acid_volume) + +/// Sets the acid volume to a new value. Limits the acid volume by the amount allowed to exist on the parent atom. +/datum/component/acid/proc/set_volume(new_volume) + acid_volume = clamp(new_volume, 0, max_volume) + if(!acid_volume) + qdel(src) + + +/// Handles the slow corrosion of the parent [/atom]. +/datum/component/acid/process() + process_effect?.InvokeAsync() + if(QDELING(src)) //The process effect deals damage, and on turfs diminishes the acid volume, potentially destroying the component. Let's not destroy it twice. + return + set_volume(acid_volume - (ACID_DECAY_BASE + (ACID_DECAY_SCALING*round(sqrt(acid_volume))))) + +/// Handles processing on a [/obj]. +/datum/component/acid/proc/process_obj(obj/target) + if(target.resistance_flags & ACID_PROOF) + return + target.take_damage(min(1 + round(sqrt(acid_power * acid_volume)*0.3), OBJ_ACID_DAMAGE_MAX), BURN, ACID, 0) + +/// Handles processing on a [/mob/living]. +/datum/component/acid/proc/process_mob(mob/living/target) + target.acid_act(acid_power, acid_volume) + +/// Handles processing on a [/turf]. +/datum/component/acid/proc/process_turf(turf/target_turf) + var/acid_used = min(acid_volume * 0.05, 20) + var/applied_targets = 0 + for(var/am in target_turf) + var/atom/movable/target_movable = am + if(target_movable.acid_act(acid_power, acid_used)) + applied_targets++ + + if(applied_targets) + set_volume(acid_volume - (acid_used * applied_targets)) + + // Snowflake code for handling acid melting walls. TODO: Move integrity handling to the atom level so this can be desnowflaked. + if(acid_power < ACID_POWER_MELT_TURF) + return + + switch(parent_integrity--) + if(-INFINITY to 0) + target_turf.visible_message("[target_turf] collapses under its own weight into a puddle of goop and undigested debris!") + target_turf.acid_melt() + if(0 to 4) + target_turf.visible_message("[target_turf] begins to crumble under the acid!") + if(4 to 8) + target_turf.visible_message("[target_turf] is struggling to withstand the acid!") + if(8 to 16) + target_turf.visible_message("[target_turf] is being melted by the acid!") + if(16 to 24) + target_turf.visible_message("[target_turf] is holding up against the acid!") + + +/// Used to maintain the acid overlay on the parent [/atom]. +/datum/component/acid/proc/on_update_overlays(atom/parent_atom, list/overlays) + SIGNAL_HANDLER + + overlays += mutable_appearance('icons/effects/acid.dmi', parent_atom.custom_acid_overlay || ACID_OVERLAY_DEFAULT) + +/// Alerts any examiners to the acid on the parent atom. +/datum/component/acid/proc/on_examine(atom/A, mob/user, list/examine_list) + SIGNAL_HANDLER + + examine_list += "[A.p_theyre()] covered in corrosive liquid!" + +/// Makes it possible to clean acid off of objects. +/datum/component/acid/proc/on_clean(atom/A, clean_types) + SIGNAL_HANDLER + + if(!(clean_types & CLEAN_TYPE_ACID)) + return NONE + qdel(src) + return COMPONENT_CLEANED + +/// Handles water diluting the acid on the object. +/datum/component/acid/proc/on_expose_reagent(atom/parent_atom, datum/reagent/exposing_reagent, reac_volume) + SIGNAL_HANDLER + + if(!istype(exposing_reagent, /datum/reagent/water)) + return NONE + + acid_power /= (acid_volume / (acid_volume + reac_volume)) + set_volume(acid_volume + reac_volume) + return NONE + + +/// Handles searing the hand of anyone who tries to touch this without protection. +/datum/component/acid/proc/on_attack_hand(atom/parent_atom, mob/living/carbon/user) + SIGNAL_HANDLER + + if(!istype(user)) + return NONE + if((parent_atom == user) || (parent_atom.loc == user)) + return NONE // So people can take their own clothes off. + if((acid_power * acid_volume) < ACID_LEVEL_HANDBURN) + return NONE + if(user.gloves?.resistance_flags & (UNACIDABLE|ACID_PROOF)) + return NONE + + var/obj/item/bodypart/affecting = user.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") + if(!affecting?.receive_damage(0, 5)) + return NONE + + to_chat(user, "The acid on \the [parent_atom] burns your hand!") + playsound(parent_atom, 'sound/weapons/sear.ogg', 50, TRUE) + user.update_damage_overlays() + return COMPONENT_NO_ATTACK_HAND + +/// Handles searing the feet of whoever walks over this without protection. Only active if the parent is a turf. +/datum/component/acid/proc/on_crossed(atom/parent_atom, mob/living/crosser) + SIGNAL_HANDLER + + if(!isliving(crosser)) + return + if(crosser.movement_type & FLYING) + return + if(crosser.m_intent & MOVE_INTENT_WALK) + return + if(prob(60)) + return + + var/acid_used = min(acid_volume * 0.05, 20) + if(crosser.acid_act(acid_power, acid_used, FEET)) + playsound(crosser, 'sound/weapons/sear.ogg', 50, TRUE) + to_chat(crosser, "The acid on the [parent] burns you!") + set_volume(max(acid_volume - acid_used, 10)) diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm index 3ef793899be..c3627cc80dc 100644 --- a/code/datums/components/bloodysoles.dm +++ b/code/datums/components/bloodysoles.dm @@ -206,12 +206,12 @@ SIGNAL_HANDLER if(!(clean_types & CLEAN_TYPE_BLOOD) || last_blood_state == BLOOD_STATE_NOT_BLOODY) - return + return NONE bloody_shoes = list(BLOOD_STATE_HUMAN = 0, BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) last_blood_state = BLOOD_STATE_NOT_BLOODY update_icon() - return TRUE + return COMPONENT_CLEANED /** diff --git a/code/datums/components/creamed.dm b/code/datums/components/creamed.dm index 2abdf6cff0a..d390e14c3ae 100644 --- a/code/datums/components/creamed.dm +++ b/code/datums/components/creamed.dm @@ -58,6 +58,9 @@ GLOBAL_LIST_INIT(creamable, typecacheof(list( ///Callback to remove pieface /datum/component/creamed/proc/clean_up(datum/source, clean_types) - if(clean_types & CLEAN_TYPE_BLOOD) + SIGNAL_HANDLER + + . = NONE + if(!(clean_types & CLEAN_TYPE_BLOOD)) qdel(src) - return TRUE + return COMPONENT_CLEANED diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm index 9a6f40ec95e..8214a374170 100644 --- a/code/datums/components/decal.dm +++ b/code/datums/components/decal.dm @@ -89,9 +89,10 @@ /datum/component/decal/proc/clean_react(datum/source, clean_types) SIGNAL_HANDLER + . = NONE if(clean_types & cleanable) qdel(src) - return TRUE + return COMPONENT_CLEANED /datum/component/decal/proc/examine(datum/source, mob/user, list/examine_list) SIGNAL_HANDLER diff --git a/code/datums/components/forensics.dm b/code/datums/components/forensics.dm index 2622c0e2d6b..9d451a06b72 100644 --- a/code/datums/components/forensics.dm +++ b/code/datums/components/forensics.dm @@ -54,15 +54,16 @@ /datum/component/forensics/proc/clean_act(datum/source, clean_types) SIGNAL_HANDLER + . = NONE if(clean_types & CLEAN_TYPE_FINGERPRINTS) wipe_fingerprints() - . = TRUE + . = COMPONENT_CLEANED if(clean_types & CLEAN_TYPE_BLOOD) wipe_blood_DNA() - . = TRUE + . = COMPONENT_CLEANED if(clean_types & CLEAN_TYPE_FIBERS) wipe_fibers() - . = TRUE + . = COMPONENT_CLEANED /datum/component/forensics/proc/add_fingerprint_list(list/_fingerprints) //list(text) if(!length(_fingerprints)) diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm index 7bf6c87afca..372f381aedb 100644 --- a/code/datums/components/infective.dm +++ b/code/datums/components/infective.dm @@ -51,9 +51,10 @@ /datum/component/infective/proc/clean(datum/source, clean_types) SIGNAL_HANDLER + . = NONE if(clean_types & required_clean_types) qdel(src) - return TRUE + return COMPONENT_CLEANED /datum/component/infective/proc/try_infect_buckle(datum/source, mob/M, force) SIGNAL_HANDLER diff --git a/code/datums/components/radioactive.dm b/code/datums/components/radioactive.dm index 5f2c28b5c6c..bdbb9cf56d1 100644 --- a/code/datums/components/radioactive.dm +++ b/code/datums/components/radioactive.dm @@ -99,18 +99,19 @@ SIGNAL_HANDLER if(QDELETED(src)) - return + return COMPONENT_CLEANED if(!(clean_types & CLEAN_TYPE_RADIATION)) - return + return COMPONENT_CLEANED if(!(clean_types & CLEAN_TYPE_WEAK)) qdel(src) - return + return COMPONENT_CLEANED strength = max(0, (strength - (RAD_BACKGROUND_RADIATION * 2))) if(strength <= RAD_BACKGROUND_RADIATION) qdel(src) + return COMPONENT_CLEANED #undef RAD_AMOUNT_LOW #undef RAD_AMOUNT_MEDIUM diff --git a/code/datums/components/thermite.dm b/code/datums/components/thermite.dm index 23f020adb7f..cd8546c6a17 100644 --- a/code/datums/components/thermite.dm +++ b/code/datums/components/thermite.dm @@ -84,7 +84,7 @@ //Thermite is just some loose powder, you could probably clean it with your hands. << todo? qdel(src) - return TRUE + return COMPONENT_CLEANED /datum/component/thermite/proc/flame_react(datum/source, exposed_temperature, exposed_volume) SIGNAL_HANDLER diff --git a/code/datums/looping_sounds/acid.dm b/code/datums/looping_sounds/acid.dm new file mode 100644 index 00000000000..e461e5d02ce --- /dev/null +++ b/code/datums/looping_sounds/acid.dm @@ -0,0 +1,5 @@ +/// Soundloop for the acid component. +/datum/looping_sound/acid + mid_sounds = list('sound/items/welder.ogg' = 1) + mid_length = 10 + volume = 150 diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1d9584981b6..f31bd028cb5 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -74,6 +74,9 @@ /// Radiation insulation types var/rad_insulation = RAD_NO_INSULATION + /// The icon state intended to be used for the acid component. Used to override the default acid overlay icon state. + var/custom_acid_overlay = null + ///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.) ///The list referenced by this var can be shared by multiple objects and should not be directly modified. Instead, use [set_custom_materials][/atom/proc/set_custom_materials]. var/list/custom_materials @@ -786,6 +789,7 @@ */ /atom/proc/acid_act(acidpwr, acid_volume) SEND_SIGNAL(src, COMSIG_ATOM_ACID_ACT, acidpwr, acid_volume) + return FALSE /** * Respond to an emag being used on our atom @@ -990,7 +994,7 @@ */ /atom/proc/wash(clean_types) . = FALSE - if(SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, clean_types)) + if(SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, clean_types) & COMPONENT_CLEANED) . = TRUE // Basically "if has washable coloration" diff --git a/code/game/objects/effects/alien_acid.dm b/code/game/objects/effects/alien_acid.dm deleted file mode 100644 index 3c40c1366f2..00000000000 --- a/code/game/objects/effects/alien_acid.dm +++ /dev/null @@ -1,93 +0,0 @@ -/obj/effect/acid - gender = PLURAL - name = "acid" - desc = "Burbling corrosive stuff." - icon_state = "acid" - density = FALSE - opacity = FALSE - anchored = TRUE - resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF - layer = ABOVE_NORMAL_TURF_LAYER - var/turf/target - - -/obj/effect/acid/Initialize(mapload, acid_pwr, acid_amt) - . = ..() - - target = get_turf(src) - - if(acid_amt) - acid_level = min(acid_amt*acid_pwr, 12000) //capped so the acid effect doesn't last a half hour on the floor. - - //handle APCs and newscasters and stuff nicely - pixel_x = target.pixel_x + rand(-4,4) - pixel_y = target.pixel_y + rand(-4,4) - - START_PROCESSING(SSobj, src) - - -/obj/effect/acid/Destroy() - STOP_PROCESSING(SSobj, src) - target = null - return ..() - -/obj/effect/acid/process() - if(!target) - qdel(src) - return FALSE - - if(prob(5)) - playsound(loc, 'sound/items/welder.ogg', 100, TRUE) - - for(var/obj/O in target) - if(prob(20) && !(resistance_flags & UNACIDABLE)) - if(O.acid_level < acid_level*0.3) - var/acid_used = min(acid_level*0.05, 20) - O.acid_act(10, acid_used) - acid_level = max(0, acid_level - acid_used*10) - - acid_level = max(acid_level - (5 + 2*round(sqrt(acid_level))), 0) - if(acid_level <= 0) - qdel(src) - return FALSE - return TRUE - -/obj/effect/acid/Crossed(AM as mob|obj) - . = ..() - if(isliving(AM)) - var/mob/living/L = AM - if(L.movement_type & FLYING) - return - if(L.m_intent != MOVE_INTENT_WALK && prob(40)) - var/acid_used = min(acid_level*0.05, 20) - if(L.acid_act(10, acid_used, "feet")) - acid_level = max(0, acid_level - acid_used*10) - playsound(L, 'sound/weapons/sear.ogg', 50, TRUE) - to_chat(L, "[src] burns you!") - -//xenomorph corrosive acid -/obj/effect/acid/alien - var/target_strength = 30 - - -/obj/effect/acid/alien/process() - . = ..() - if(.) - if(prob(45)) - playsound(loc, 'sound/items/welder.ogg', 100, TRUE) - target_strength-- - if(target_strength <= 0) - target.visible_message("[target] collapses under its own weight into a puddle of goop and undigested debris!") - target.acid_melt() - qdel(src) - else - - switch(target_strength) - if(24) - visible_message("[target] is holding up against the acid!") - if(16) - visible_message("[target] is being melted by the acid!") - if(8) - visible_message("[target] is struggling to withstand the acid!") - if(4) - visible_message("[target] begins to crumble under the acid!") diff --git a/code/game/objects/effects/decals/remains.dm b/code/game/objects/effects/decals/remains.dm index 790b6c5a592..a09d686f510 100644 --- a/code/game/objects/effects/decals/remains.dm +++ b/code/game/objects/effects/decals/remains.dm @@ -8,6 +8,7 @@ playsound(src, 'sound/items/welder.ogg', 150, TRUE) new /obj/effect/decal/cleanable/greenglow(drop_location()) qdel(src) + return TRUE /obj/effect/decal/remains/human desc = "They look like human remains. They have a strange aura about them." diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm index b6748426de0..b9a36855442 100644 --- a/code/game/objects/effects/effects.dm +++ b/code/game/objects/effects/effects.dm @@ -15,7 +15,7 @@ return /obj/effect/acid_act() - return + return FALSE /obj/effect/blob_act(obj/structure/blob/B) return diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm index e0c96d05d7c..87bcb854396 100644 --- a/code/game/objects/effects/glowshroom.dm +++ b/code/game/objects/effects/glowshroom.dm @@ -208,11 +208,11 @@ take_damage(5, BURN, 0, 0) /obj/structure/glowshroom/acid_act(acidpwr, acid_volume) - . = 1 visible_message("[src] melts away!") var/obj/effect/decal/cleanable/molten_object/I = new (get_turf(src)) I.desc = "Looks like this was \an [src] some time ago." qdel(src) + return TRUE /obj/structure/glowshroom/attackby(obj/item/I, mob/living/user, params) if (istype(I, /obj/item/plant_analyzer)) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 1bfdaf105f8..d0dc6475956 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -365,15 +365,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb C.update_damage_overlays() return - if(acid_level > 20 && !ismob(loc))// so we can still remove the clothes on us that have acid. - var/mob/living/carbon/C = user - if(istype(C)) - if(!C.gloves || (!(C.gloves.resistance_flags & (UNACIDABLE|ACID_PROOF)))) - to_chat(user, "The acid on [src] burns your hand!") - var/obj/item/bodypart/affecting = C.get_bodypart("[(user.active_hand_index % 2 == 0) ? "r" : "l" ]_arm") - if(affecting && affecting.receive_damage( 0, 5 )) // 5 burn damage - C.update_damage_overlays() - if(!(interaction_flags_item & INTERACT_ITEM_ATTACK_HAND_PICKUP)) //See if we're supposed to auto pickup. return diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 199874bfdc7..dcda346c968 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -493,6 +493,7 @@ visible_message("The acid smacks into [src] and rapidly flashes to ash.",\ "You hear a loud crack as you are washed with a wave of heat.") consume_everything() + return TRUE /obj/item/melee/supermatter_sword/bullet_act(obj/projectile/P) visible_message("[P] smacks into [src] and rapidly flashes to ash.",\ diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 9a57ee62856..38ce00352a9 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -151,31 +151,15 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e ///the obj's reaction when touched by acid /obj/acid_act(acidpwr, acid_volume) - if(!(resistance_flags & UNACIDABLE) && acid_volume) - - if(!acid_level) - SSacid.processing[src] = src - update_icon() - var/acid_cap = acidpwr * 300 //so we cannot use huge amounts of weak acids to do as well as strong acids. - if(acid_level < acid_cap) - acid_level = min(acid_level + acidpwr * acid_volume, acid_cap) - return 1 - -///the proc called by the acid subsystem to process the acid that's on the obj -/obj/proc/acid_processing() - . = TRUE - if(!(resistance_flags & ACID_PROOF)) - if(prob(33)) - playsound(loc, 'sound/items/welder.ogg', 150, TRUE) - take_damage(min(1 + round(sqrt(acid_level)*0.3), 300), BURN, ACID, 0) - - acid_level = max(acid_level - (5 + 3*round(sqrt(acid_level))), 0) - if(!acid_level) + . = ..() + if((resistance_flags & UNACIDABLE) || (acid_volume <= 0) || acidpwr <= 0) return FALSE + AddComponent(/datum/component/acid, acidpwr, acid_volume) + return TRUE + ///called when the obj is destroyed by acid. /obj/proc/acid_melt() - SSacid.processing -= src deconstruct(FALSE) //// FIRE diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 4104a1424ba..2b26cf1bb41 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -22,8 +22,6 @@ var/resistance_flags = NONE // INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ON_FIRE | UNACIDABLE | ACID_PROOF - var/acid_level = 0 //how much acid is on that obj - var/persistence_replacement //have something WAY too amazing to live to the next round? Set a new path here. Overuse of this var will make me upset. var/current_skin //Has the item been reskinned? var/list/unique_reskin //List of options to reskin. @@ -355,8 +353,6 @@ /obj/update_overlays() . = ..() - if(acid_level) - . += GLOB.acid_overlay if(resistance_flags & ON_FIRE) . += custom_fire_overlay ? custom_fire_overlay : GLOB.fire_overlay diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index ed92fb3fbcf..5317efdf3d4 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -302,7 +302,7 @@ busy = FALSE reagents.remove_any(5) - reagents.expose(user, TOUCH) + reagents.expose(user, TOUCH, 5 / max(reagents.total_volume, 5)) if(washing_face) SEND_SIGNAL(user, COMSIG_COMPONENT_CLEAN_FACE_ACT, CLEAN_WASH) @@ -389,8 +389,7 @@ return 1 busy = FALSE O.wash(CLEAN_WASH) - O.acid_level = 0 - reagents.expose(O, TOUCH) + reagents.expose(O, TOUCH, 5 / max(reagents.total_volume, 5)) user.visible_message("[user] washes [O] using [src].", \ "You wash [O] using [src].") return 1 @@ -566,10 +565,7 @@ return TRUE busy = FALSE O.wash(CLEAN_WASH) - O.acid_level = 0 - create_reagents(5) - reagents.add_reagent(dispensedreagent, 5) - reagents.expose(O, TOUCH) + reagents.expose(O, TOUCH, 5 / max(reagents.total_volume, 5)) user.visible_message("[user] washes [O] using [src].", \ "You wash [O] using [src].") return TRUE diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index 9411630a726..736b6fb2bb8 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -251,7 +251,7 @@ /turf/closed/wall/acid_act(acidpwr, acid_volume) if(explosion_block >= 2) acidpwr = min(acidpwr, 50) //we reduce the power so strong walls never get melted. - . = ..() + return ..() /turf/closed/wall/acid_melt() dismantle_wall(1) diff --git a/code/game/turfs/open/floor/reinf_floor.dm b/code/game/turfs/open/floor/reinf_floor.dm index 6ce8f41aa61..138bd093fdc 100644 --- a/code/game/turfs/open/floor/reinf_floor.dm +++ b/code/game/turfs/open/floor/reinf_floor.dm @@ -49,7 +49,7 @@ /turf/open/floor/engine/acid_act(acidpwr, acid_volume) acidpwr = min(acidpwr, 50) //we reduce the power so reinf floor never get melted. - . = ..() + return ..() /turf/open/floor/engine/ex_act(severity,target) var/shielded = is_shielded() diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm index 68048a2e70d..f294b7d915c 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -28,7 +28,7 @@ return src /turf/open/lava/acid_act(acidpwr, acid_volume) - return + return FALSE /turf/open/lava/MakeDry(wet_setting = TURF_WET_WATER) return diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index fdcd2759309..ad5b05bd1ec 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -501,22 +501,18 @@ GLOBAL_LIST_EMPTY(station_turfs) return /turf/acid_act(acidpwr, acid_volume) - . = 1 - var/acid_type = /obj/effect/acid - if(acidpwr >= 200) //alien acid power - acid_type = /obj/effect/acid/alien - var/has_acid_effect = FALSE + . = ..() + if((acidpwr <= 0) || (acid_volume <= 0)) + return FALSE + + AddComponent(/datum/component/acid, acidpwr, acid_volume) for(var/obj/O in src) if(intact && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) - return - if(istype(O, acid_type)) - var/obj/effect/acid/A = O - A.acid_level = min(acid_volume * acidpwr, 12000)//capping acid level to limit power of the acid - has_acid_effect = 1 continue + O.acid_act(acidpwr, acid_volume) - if(!has_acid_effect) - new acid_type(src, acidpwr, acid_volume) + + return . || TRUE /turf/proc/acid_melt() return diff --git a/code/modules/antagonists/blob/blobstrains/_reagent.dm b/code/modules/antagonists/blob/blobstrains/_reagent.dm index 0113013c957..5b7522c8d31 100644 --- a/code/modules/antagonists/blob/blobstrains/_reagent.dm +++ b/code/modules/antagonists/blob/blobstrains/_reagent.dm @@ -25,9 +25,11 @@ color = "#FFFFFF" taste_description = "bad code and slime" can_synth = FALSE + penetrates_skin = NONE -/datum/reagent/blob/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) - if(M.stat == DEAD || istype(M, /mob/living/simple_animal/hostile/blob)) +/datum/reagent/blob/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) + ..() + if(exposed_mob.stat == DEAD || istype(exposed_mob, /mob/living/simple_animal/hostile/blob)) return 0 //the dead, and blob mobs, don't cause reactions return round(reac_volume * min(1.5 - touch_protection, 1), 0.1) //full touch protection means 50% volume, any prot below 0.5 means 100% volume. diff --git a/code/modules/antagonists/blob/blobstrains/blazing_oil.dm b/code/modules/antagonists/blob/blobstrains/blazing_oil.dm index 1a717787dec..2383dccf87f 100644 --- a/code/modules/antagonists/blob/blobstrains/blazing_oil.dm +++ b/code/modules/antagonists/blob/blobstrains/blazing_oil.dm @@ -31,11 +31,11 @@ taste_description = "burning oil" color = "#B68D00" -/datum/reagent/blob/blazing_oil/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/blazing_oil/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() - M.adjust_fire_stacks(round(reac_volume/10)) - M.IgniteMob() - if(M) - M.apply_damage(0.8*reac_volume, BURN, wound_bonus=CANT_WOUND) - if(iscarbon(M)) - M.emote("scream") + exposed_mob.adjust_fire_stacks(round(reac_volume/10)) + exposed_mob.IgniteMob() + if(exposed_mob) + exposed_mob.apply_damage(0.8*reac_volume, BURN, wound_bonus=CANT_WOUND) + if(iscarbon(exposed_mob)) + exposed_mob.emote("scream") diff --git a/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm b/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm index ebfc84f008d..8dea4c1ab5b 100644 --- a/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm +++ b/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm @@ -16,17 +16,17 @@ color = "#8BA6E9" taste_description = "brain freeze" -/datum/reagent/blob/cryogenic_poison/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/cryogenic_poison/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() - if(M.reagents) - M.reagents.add_reagent(/datum/reagent/consumable/frostoil, 0.3*reac_volume) - M.reagents.add_reagent(/datum/reagent/consumable/ice, 0.3*reac_volume) - M.reagents.add_reagent(/datum/reagent/blob/cryogenic_poison, 0.3*reac_volume) - M.apply_damage(0.2*reac_volume, BRUTE, wound_bonus=CANT_WOUND) + if(exposed_mob.reagents) + exposed_mob.reagents.add_reagent(/datum/reagent/consumable/frostoil, 0.3*reac_volume) + exposed_mob.reagents.add_reagent(/datum/reagent/consumable/ice, 0.3*reac_volume) + exposed_mob.reagents.add_reagent(/datum/reagent/blob/cryogenic_poison, 0.3*reac_volume) + exposed_mob.apply_damage(0.2*reac_volume, BRUTE, wound_bonus=CANT_WOUND) -/datum/reagent/blob/cryogenic_poison/on_mob_life(mob/living/carbon/M) - M.adjustBruteLoss(0.5*REAGENTS_EFFECT_MULTIPLIER, FALSE) - M.adjustFireLoss(0.5*REAGENTS_EFFECT_MULTIPLIER, FALSE) - M.adjustToxLoss(0.5*REAGENTS_EFFECT_MULTIPLIER, FALSE) +/datum/reagent/blob/cryogenic_poison/on_mob_life(mob/living/carbon/exposed_mob) + exposed_mob.adjustBruteLoss(0.5*REAGENTS_EFFECT_MULTIPLIER, FALSE) + exposed_mob.adjustFireLoss(0.5*REAGENTS_EFFECT_MULTIPLIER, FALSE) + exposed_mob.adjustToxLoss(0.5*REAGENTS_EFFECT_MULTIPLIER, FALSE) . = 1 ..() diff --git a/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm b/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm index 4f2f802f78b..59b14d611b7 100644 --- a/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm +++ b/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm @@ -24,17 +24,17 @@ name = "Distributed Neurons" color = "#E88D5D" -/datum/reagent/blob/distributed_neurons/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/distributed_neurons/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() - M.apply_damage(0.6*reac_volume, TOX) - if(O && ishuman(M)) - if(M.stat == UNCONSCIOUS || M.stat == HARD_CRIT) - M.death() //sleeping in a fight? bad plan. - if(M.stat == DEAD && O.can_buy(5)) - var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore(get_turf(M)) - BS.overmind = O - BS.update_icons() - O.blob_mobs.Add(BS) - BS.Zombify(M) - O.add_points(-5) - to_chat(O, "Spent 5 resources for the zombification of [M].") + exposed_mob.apply_damage(0.6*reac_volume, TOX) + if(overmind && ishuman(exposed_mob)) + if(exposed_mob.stat == UNCONSCIOUS || exposed_mob.stat == HARD_CRIT) + exposed_mob.death() //sleeping in a fight? bad plan. + if(exposed_mob.stat == DEAD && overmind.can_buy(5)) + var/mob/living/simple_animal/hostile/blob/blobspore/spore = new/mob/living/simple_animal/hostile/blob/blobspore(get_turf(exposed_mob)) + spore.overmind = overmind + spore.update_icons() + overmind.blob_mobs.Add(spore) + spore.Zombify(exposed_mob) + overmind.add_points(-5) + to_chat(overmind, "Spent 5 resources for the zombification of [exposed_mob].") diff --git a/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm b/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm index 02a8c914d12..f92f71c5388 100644 --- a/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm +++ b/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm @@ -29,9 +29,9 @@ taste_description = "pop rocks" color = "#83ECEC" -/datum/reagent/blob/electromagnetic_web/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/electromagnetic_web/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() if(prob(reac_volume*2)) - M.emp_act(EMP_LIGHT) - if(M) - M.apply_damage(reac_volume, BURN, wound_bonus=CANT_WOUND) + exposed_mob.emp_act(EMP_LIGHT) + if(exposed_mob) + exposed_mob.apply_damage(reac_volume, BURN, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/energized_jelly.dm b/code/modules/antagonists/blob/blobstrains/energized_jelly.dm index 1bf4b0b54f4..305d22d540f 100644 --- a/code/modules/antagonists/blob/blobstrains/energized_jelly.dm +++ b/code/modules/antagonists/blob/blobstrains/energized_jelly.dm @@ -26,9 +26,9 @@ taste_description = "gelatin" color = "#EFD65A" -/datum/reagent/blob/energized_jelly/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/energized_jelly/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() - M.losebreath += round(0.2*reac_volume) - M.adjustStaminaLoss(reac_volume * 1.2) - if(M) - M.apply_damage(0.6*reac_volume, OXY) + exposed_mob.losebreath += round(0.2*reac_volume) + exposed_mob.adjustStaminaLoss(reac_volume * 1.2) + if(exposed_mob) + exposed_mob.apply_damage(0.6*reac_volume, OXY) diff --git a/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm b/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm index 3324df30f9b..c49a103f6d6 100644 --- a/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm +++ b/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm @@ -17,7 +17,7 @@ else if(damage_flag != MELEE && damage_flag != BULLET && damage_flag != LASER) return damage * 1.5 return ..() - + /datum/blobstrain/reagent/explosive_lattice/on_sporedeath(mob/living/spore) var/obj/effect/temp_visual/explosion/fast/effect = new /obj/effect/temp_visual/explosion/fast(get_turf(spore)) effect.alpha = 150 @@ -31,18 +31,23 @@ taste_description = "the bomb" color = "#8B2500" -/datum/reagent/blob/explosive_lattice/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/explosive_lattice/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) var/initial_volume = reac_volume reac_volume = ..() if(reac_volume >= 10) //if it's not a spore cloud, bad time incoming - var/obj/effect/temp_visual/explosion/fast/E = new /obj/effect/temp_visual/explosion/fast(get_turf(M)) - E.alpha = 150 - for(var/mob/living/L in orange(get_turf(M), 1)) - if(ROLE_BLOB in L.faction) //no friendly fire + var/obj/effect/temp_visual/explosion/fast/ex_effect = new /obj/effect/temp_visual/explosion/fast(get_turf(exposed_mob)) + ex_effect.alpha = 150 + for(var/mob/living/nearby_mob in orange(get_turf(exposed_mob), 1)) + if(ROLE_BLOB in nearby_mob.faction) //no friendly fire continue - var/aoe_volume = ..(L, TOUCH, initial_volume, 0, L.get_permeability_protection(), O) - L.apply_damage(0.4*aoe_volume, BRUTE, wound_bonus=CANT_WOUND) - if(M) - M.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) + exposed_mob = nearby_mob + methods = TOUCH + reac_volume = initial_volume + show_message = FALSE + touch_protection = nearby_mob.get_permeability_protection() + var/aoe_volume = ..() + nearby_mob.apply_damage(0.4*aoe_volume, BRUTE, wound_bonus=CANT_WOUND) + if(exposed_mob) + exposed_mob.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) else - M.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) + exposed_mob.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/networked_fibers.dm b/code/modules/antagonists/blob/blobstrains/networked_fibers.dm index cc08a4a197d..f559e722f40 100644 --- a/code/modules/antagonists/blob/blobstrains/networked_fibers.dm +++ b/code/modules/antagonists/blob/blobstrains/networked_fibers.dm @@ -36,8 +36,8 @@ taste_description = "efficiency" color = "#4F4441" -/datum/reagent/blob/networked_fibers/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/networked_fibers/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() - M.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) - if(!QDELETED(M)) - M.apply_damage(0.6*reac_volume, BURN, wound_bonus=CANT_WOUND) + exposed_mob.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) + if(!QDELETED(exposed_mob)) + exposed_mob.apply_damage(0.6*reac_volume, BURN, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm b/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm index 2281e1b59be..a8fd6c45b6b 100644 --- a/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm +++ b/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm @@ -39,14 +39,13 @@ taste_description = "a sponge" color = "#AAAABB" -/datum/reagent/blob/pressurized_slime/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/pressurized_slime/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() - var/turf/open/T = get_turf(M) - if(istype(T) && prob(reac_volume)) - T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS) - M.adjust_fire_stacks(-(reac_volume / 10)) - M.apply_damage(0.4*reac_volume, BRUTE, wound_bonus=CANT_WOUND) - if(M) - M.apply_damage(0.4*reac_volume, OXY) - if(M) - M.adjustStaminaLoss(reac_volume) + var/turf/open/location_turf = get_turf(exposed_mob) + if(istype(location_turf) && prob(reac_volume)) + location_turf.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS) + exposed_mob.adjust_fire_stacks(-(reac_volume / 10)) + exposed_mob.apply_damage(0.4*reac_volume, BRUTE, wound_bonus=CANT_WOUND) + if(exposed_mob) + exposed_mob.adjustStaminaLoss(reac_volume, FALSE) + exposed_mob.apply_damage(0.4 * reac_volume, OXY) diff --git a/code/modules/antagonists/blob/blobstrains/reactive_spines.dm b/code/modules/antagonists/blob/blobstrains/reactive_spines.dm index 8286bb63fe9..24d344e328b 100644 --- a/code/modules/antagonists/blob/blobstrains/reactive_spines.dm +++ b/code/modules/antagonists/blob/blobstrains/reactive_spines.dm @@ -24,7 +24,8 @@ taste_description = "rock" color = "#9ACD32" -/datum/reagent/blob/reactive_spines/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) - if(M.stat == DEAD || istype(M, /mob/living/simple_animal/hostile/blob)) +/datum/reagent/blob/reactive_spines/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) + ..() + if(exposed_mob.stat == DEAD || istype(exposed_mob, /mob/living/simple_animal/hostile/blob)) return 0 //the dead, and blob mobs, don't cause reactions - M.adjustBruteLoss(reac_volume) + exposed_mob.adjustBruteLoss(reac_volume) diff --git a/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm b/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm index 499f29da3c1..0df84417c6d 100644 --- a/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm +++ b/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm @@ -15,13 +15,13 @@ taste_description = "heaven" color = "#A88FB7" -/datum/reagent/blob/regenerative_materia/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/regenerative_materia/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() - M.adjust_drugginess(reac_volume) - if(M.reagents) - M.reagents.add_reagent(/datum/reagent/blob/regenerative_materia, 0.2*reac_volume) - M.reagents.add_reagent(/datum/reagent/toxin/spore, 0.2*reac_volume) - M.apply_damage(0.7*reac_volume, TOX) + exposed_mob.adjust_drugginess(reac_volume) + if(exposed_mob.reagents) + exposed_mob.reagents.add_reagent(/datum/reagent/blob/regenerative_materia, 0.2*reac_volume) + exposed_mob.reagents.add_reagent(/datum/reagent/toxin/spore, 0.2*reac_volume) + exposed_mob.apply_damage(0.7*reac_volume, TOX) /datum/reagent/blob/regenerative_materia/on_mob_life(mob/living/carbon/C) C.adjustToxLoss(1*REAGENTS_EFFECT_MULTIPLIER) diff --git a/code/modules/antagonists/blob/blobstrains/replicating_foam.dm b/code/modules/antagonists/blob/blobstrains/replicating_foam.dm index a31426ca060..236d7dea737 100644 --- a/code/modules/antagonists/blob/blobstrains/replicating_foam.dm +++ b/code/modules/antagonists/blob/blobstrains/replicating_foam.dm @@ -30,6 +30,6 @@ taste_description = "duplication" color = "#7B5A57" -/datum/reagent/blob/replicating_foam/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/replicating_foam/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() - M.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND) + exposed_mob.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm b/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm index 85ae2fd5df1..95be6543526 100644 --- a/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm +++ b/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm @@ -31,6 +31,6 @@ name = "Shifting Fragments" color = "#C8963C" -/datum/reagent/blob/shifting_fragments/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/shifting_fragments/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() - M.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND) + exposed_mob.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm b/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm index f0645badf29..c39728ad1dc 100644 --- a/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm +++ b/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm @@ -29,11 +29,11 @@ taste_description = "toxic mold" color = "#65ADA2" -/datum/reagent/blob/synchronous_mesh/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) +/datum/reagent/blob/synchronous_mesh/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) reac_volume = ..() - M.apply_damage(0.2*reac_volume, BRUTE, wound_bonus=CANT_WOUND) - if(M && reac_volume) - for(var/obj/structure/blob/B in range(1, M)) //if the target is completely surrounded, this is 2.4*reac_volume bonus damage, total of 2.6*reac_volume - if(M) - B.blob_attack_animation(M) //show them they're getting a bad time - M.apply_damage(0.3*reac_volume, BRUTE, wound_bonus=CANT_WOUND) + exposed_mob.apply_damage(0.2*reac_volume, BRUTE, wound_bonus=CANT_WOUND) + if(exposed_mob && reac_volume) + for(var/obj/structure/blob/nearby_blob in range(1, exposed_mob)) //if the target is completely surrounded, this is 2.4*reac_volume bonus damage, total of 2.6*reac_volume + if(exposed_mob) + nearby_blob.blob_attack_animation(exposed_mob) //show them they're getting a bad time + exposed_mob.apply_damage(0.3*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 9206971bbd7..5ac84779aca 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -602,27 +602,27 @@ reagent_state = LIQUID color = "#FFEBEB" -/datum/reagent/flightpotion/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message = 1) - if(iscarbon(M) && M.stat != DEAD) - var/mob/living/carbon/C = M - var/holycheck = ishumanbasic(C) - if(reac_volume < 5 || !(holycheck || islizard(C) || (ismoth(C) && C.dna.features["moth_wings"] != "Burnt Off"))) // implying xenohumans are holy //as with all things, +/datum/reagent/flightpotion/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE) + . = ..() + if(iscarbon(exposed_mob) && exposed_mob.stat != DEAD) + var/mob/living/carbon/exposed_carbon = exposed_mob + var/holycheck = ishumanbasic(exposed_carbon) + if(reac_volume < 5 || !(holycheck || islizard(exposed_carbon) || (ismoth(exposed_carbon) && exposed_carbon.dna.features["moth_wings"] != "Burnt Off"))) // implying xenohumans are holy //as with all things, if((methods & INGEST) && show_message) - to_chat(C, "You feel nothing but a terrible aftertaste.") - return ..() - if(C.dna.species.has_innate_wings) - to_chat(C, "A terrible pain travels down your back as your wings change shape!") - C.dna.features["moth_wings"] = "None" + to_chat(exposed_carbon, "You feel nothing but a terrible aftertaste.") + return + if(exposed_carbon.dna.species.has_innate_wings) + to_chat(exposed_carbon, "A terrible pain travels down your back as your wings change shape!") + exposed_carbon.dna.features["moth_wings"] = "None" else - to_chat(C, "A terrible pain travels down your back as wings burst out!") - C.dna.species.GiveSpeciesFlight(C) + to_chat(exposed_carbon, "A terrible pain travels down your back as wings burst out!") + exposed_carbon.dna.species.GiveSpeciesFlight(exposed_carbon) if(holycheck) - to_chat(C, "You feel blessed!") - ADD_TRAIT(C, TRAIT_HOLY, SPECIES_TRAIT) - playsound(C.loc, 'sound/items/poster_ripped.ogg', 50, TRUE, -1) - C.adjustBruteLoss(20) - C.emote("scream") - ..() + to_chat(exposed_carbon, "You feel blessed!") + ADD_TRAIT(exposed_carbon, TRAIT_HOLY, SPECIES_TRAIT) + playsound(exposed_carbon.loc, 'sound/items/poster_ripped.ogg', 50, TRUE, -1) + exposed_carbon.adjustBruteLoss(20) + exposed_carbon.emote("scream") /obj/item/jacobs_ladder diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index 4b175560a2d..1b45653fa03 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -156,7 +156,7 @@ Doesn't work on other aliens/AI.*/ /obj/effect/proc_holder/alien/acid/proc/corrode(atom/target,mob/living/carbon/user = usr) if(target in oview(1,user)) - if(target.acid_act(200, 100)) + if(target.acid_act(200, 1000)) user.visible_message("[user] vomits globs of vile stuff all over [target]. It begins to sizzle and melt under the bubbling mess of acid!") return TRUE else diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index cdfb56181f8..5318df68098 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -948,7 +948,7 @@ /mob/living/carbon/extinguish_mob() for(var/X in get_equipped_items()) var/obj/item/I = X - I.acid_level = 0 //washes off the acid on our clothes + I.wash(CLEAN_TYPE_ACID) //washes off the acid on our clothes I.extinguish() //extinguishes our clothes ..() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 86ac018a071..5cbc75c2467 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -617,9 +617,9 @@ inventory_items_to_kill += held_items - for(var/obj/item/I in inventory_items_to_kill) - I.acid_act(acidpwr, acid_volume) - return 1 + for(var/obj/item/inventory_item in inventory_items_to_kill) + inventory_item.acid_act(acidpwr, acid_volume) + return TRUE ///Overrides the point value that the mob is worth /mob/living/carbon/human/singularity_act() diff --git a/code/modules/mob/living/carbon/monkey/monkey_defense.dm b/code/modules/mob/living/carbon/monkey/monkey_defense.dm index e9ca82318d1..eae689588f9 100644 --- a/code/modules/mob/living/carbon/monkey/monkey_defense.dm +++ b/code/modules/mob/living/carbon/monkey/monkey_defense.dm @@ -145,7 +145,7 @@ apply_damage(damage, BRUTE, affecting) /mob/living/carbon/monkey/acid_act(acidpwr, acid_volume, bodyzone_hit) - . = 1 + . = TRUE if(!bodyzone_hit || bodyzone_hit == BODY_ZONE_HEAD) if(wear_mask) if(!(wear_mask.resistance_flags & UNACIDABLE)) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 528ae40753e..d5df01524bf 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -316,7 +316,7 @@ /mob/living/acid_act(acidpwr, acid_volume) take_bodypart_damage(acidpwr * min(1, acid_volume * 0.1)) - return 1 + return TRUE ///As the name suggests, this should be called to apply electric shocks. /mob/living/proc/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE) diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 7f722b9eae1..0003b3cc12d 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -74,6 +74,8 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) var/datum/material/material ///A list of causes why this chem should skip being removed, if the length is 0 it will be removed from holder naturally, if this is >0 it will not be removed from the holder. var/list/reagent_removal_skip_list = list() + ///The set of exposure methods this penetrates skin with. + var/penetrates_skin = VAPOR /datum/reagent/New() SHOULD_CALL_PARENT(TRUE) @@ -90,28 +92,37 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) holder = null /// Applies this reagent to an [/atom] -/datum/reagent/proc/expose_atom(atom/A, volume) - return +/datum/reagent/proc/expose_atom(atom/exposed_atom, reac_volume) + SHOULD_CALL_PARENT(TRUE) + + SEND_SIGNAL(src, COMSIG_REAGENT_EXPOSE_ATOM, exposed_atom, reac_volume) + SEND_SIGNAL(exposed_atom, COMSIG_ATOM_EXPOSE_REAGENT, src, reac_volume) + return TRUE /// Applies this reagent to a [/mob/living] -/datum/reagent/proc/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message = 1, touch_protection = 0) - if(!istype(M)) - return FALSE - if(methods & VAPOR) //smoke, foam, spray - if(M.reagents) - var/modifier = clamp((1 - touch_protection), 0, 1) - var/amount = round(reac_volume*modifier, 0.1) - if(amount >= 0.5) - M.reagents.add_reagent(type, amount) +/datum/reagent/proc/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) + SHOULD_CALL_PARENT(TRUE) + + SEND_SIGNAL(src, COMSIG_REAGENT_EXPOSE_MOB, exposed_mob, methods, reac_volume, show_message, touch_protection) + if((methods & penetrates_skin) && exposed_mob.reagents) //smoke, foam, spray + var/amount = round(reac_volume*clamp((1 - touch_protection), 0, 1), 0.1) + if(amount >= 0.5) + exposed_mob.reagents.add_reagent(type, amount) return TRUE /// Applies this reagent to an [/obj] -/datum/reagent/proc/expose_obj(obj/O, volume) - return +/datum/reagent/proc/expose_obj(obj/exposed_obj, reac_volume) + SHOULD_CALL_PARENT(TRUE) + + SEND_SIGNAL(src, COMSIG_REAGENT_EXPOSE_OBJ, exposed_obj, reac_volume) + return TRUE /// Applies this reagent to a [/turf] -/datum/reagent/proc/expose_turf(turf/T, volume) - return +/datum/reagent/proc/expose_turf(turf/exposed_turf, reac_volume) + SHOULD_CALL_PARENT(TRUE) + + SEND_SIGNAL(src, COMSIG_REAGENT_EXPOSE_TURF, exposed_turf, reac_volume) + return TRUE /// Called from [/datum/reagents/proc/metabolize] /datum/reagent/proc/on_mob_life(mob/living/carbon/M) diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index e64b8145f77..855f7cc84d6 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -48,35 +48,36 @@ All effects don't start immediately, but rather get worse over time; the rate is L.applyOrganDamage(((max(sqrt(volume) * (boozepwr ** ALCOHOL_EXPONENT) * L.alcohol_tolerance, 0))/150)) return ..() -/datum/reagent/consumable/ethanol/expose_obj(obj/O, reac_volume) - if(istype(O, /obj/item/paper)) - var/obj/item/paper/paperaffected = O +/datum/reagent/consumable/ethanol/expose_obj(obj/exposed_obj, reac_volume) + if(istype(exposed_obj, /obj/item/paper)) + var/obj/item/paper/paperaffected = exposed_obj paperaffected.clearpaper() to_chat(usr, "[paperaffected]'s ink washes away.") - if(istype(O, /obj/item/book)) + if(istype(exposed_obj, /obj/item/book)) if(reac_volume >= 5) - var/obj/item/book/affectedbook = O + var/obj/item/book/affectedbook = exposed_obj affectedbook.dat = null - O.visible_message("[O]'s writing is washed away by [name]!") + exposed_obj.visible_message("[exposed_obj]'s writing is washed away by [name]!") else - O.visible_message("[O]'s ink is smeared by [name], but doesn't wash away!") - return + exposed_obj.visible_message("[exposed_obj]'s ink is smeared by [name], but doesn't wash away!") + return ..() -/datum/reagent/consumable/ethanol/expose_mob(mob/living/M, methods=TOUCH, reac_volume)//Splashing people with ethanol isn't quite as good as fuel. - if(!isliving(M)) +/datum/reagent/consumable/ethanol/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)//Splashing people with ethanol isn't quite as good as fuel. + . = ..() + if(!(methods & (TOUCH|VAPOR|PATCH))) return - if(methods & (TOUCH|VAPOR|PATCH)) - M.adjust_fire_stacks(reac_volume / 15) + exposed_mob.adjust_fire_stacks(reac_volume / 15) - if(iscarbon(M)) - var/mob/living/carbon/C = M - var/power_multiplier = boozepwr / 65 // Weak alcohol has less sterilizing power + if(!iscarbon(exposed_mob)) + return - for(var/s in C.surgeries) - var/datum/surgery/S = s - S.speed_modifier = max(0.1*power_multiplier, S.speed_modifier) - return ..() + var/mob/living/carbon/exposed_carbon = exposed_mob + var/power_multiplier = boozepwr / 65 // Weak alcohol has less sterilizing power + + for(var/s in exposed_carbon.surgeries) + var/datum/surgery/surgery = s + surgery.speed_modifier = max(0.1*power_multiplier, surgery.speed_modifier) /datum/reagent/consumable/ethanol/beer name = "Beer" diff --git a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm index 622bd73c77e..85a8754e771 100644 --- a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm @@ -189,16 +189,15 @@ ..() . = TRUE -/datum/reagent/medicine/c2/hercuri/expose_mob(mob/living/carbon/M, methods=VAPOR, reac_volume) +/datum/reagent/medicine/c2/hercuri/expose_mob(mob/living/carbon/exposed_mob, methods=VAPOR, reac_volume) + . = ..() if(!(methods & VAPOR)) return - M.adjust_bodytemperature(-reac_volume * TEMPERATURE_DAMAGE_COEFFICIENT, 50) - M.adjust_fire_stacks(-reac_volume / 2) + exposed_mob.adjust_bodytemperature(-reac_volume * TEMPERATURE_DAMAGE_COEFFICIENT, 50) + exposed_mob.adjust_fire_stacks(-reac_volume / 2) if(reac_volume >= metabolization_rate) - M.extinguish_mob() - - ..() + exposed_mob.extinguish_mob() /datum/reagent/medicine/c2/hercuri/overdose_process(mob/living/carbon/M) M.adjust_bodytemperature(-10*TEMPERATURE_DAMAGE_COEFFICIENT*REM,50) //chilly chilly @@ -412,25 +411,27 @@ reagent_state = LIQUID color = "#FFEBEB" -/datum/reagent/medicine/c2/synthflesh/expose_mob(mob/living/M, methods=TOUCH, reac_volume,show_message = 1) - if(iscarbon(M)) - var/mob/living/carbon/carbies = M - if (carbies.stat == DEAD) - show_message = 0 - if(methods & (PATCH|TOUCH|VAPOR)) - var/harmies = min(carbies.getBruteLoss(),carbies.adjustBruteLoss(-1.25 * reac_volume)*-1) - var/burnies = min(carbies.getFireLoss(),carbies.adjustFireLoss(-1.25 * reac_volume)*-1) - for(var/i in carbies.all_wounds) - var/datum/wound/iter_wound = i - iter_wound.on_synthflesh(reac_volume) - carbies.adjustToxLoss((harmies+burnies)*0.66) - if(show_message) - to_chat(carbies, "You feel your burns and bruises healing! It stings like hell!") - SEND_SIGNAL(carbies, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine) - if(HAS_TRAIT_FROM(M, TRAIT_HUSK, "burn") && carbies.getFireLoss() < THRESHOLD_UNHUSK && (carbies.reagents.get_reagent_amount(/datum/reagent/medicine/c2/synthflesh) + reac_volume >= 100)) - carbies.cure_husk("burn") - carbies.visible_message("A rubbery liquid coats [carbies]'s burns. [carbies] looks a lot healthier!") //we're avoiding using the phrases "burnt flesh" and "burnt skin" here because carbies could be a skeleton or a golem or something - ..() +/datum/reagent/medicine/c2/synthflesh/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE) + . = ..() + if(!iscarbon(exposed_mob)) + return TRUE + var/mob/living/carbon/carbies = exposed_mob + if(carbies.stat == DEAD) + show_message = 0 + if(!(methods & (PATCH|TOUCH|VAPOR))) + return TRUE + var/harmies = min(carbies.getBruteLoss(),carbies.adjustBruteLoss(-1.25 * reac_volume)*-1) + var/burnies = min(carbies.getFireLoss(),carbies.adjustFireLoss(-1.25 * reac_volume)*-1) + for(var/i in carbies.all_wounds) + var/datum/wound/iter_wound = i + iter_wound.on_synthflesh(reac_volume) + carbies.adjustToxLoss((harmies+burnies)*0.66) + if(show_message) + to_chat(carbies, "You feel your burns and bruises healing! It stings like hell!") + SEND_SIGNAL(carbies, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine) + if(HAS_TRAIT_FROM(exposed_mob, TRAIT_HUSK, "burn") && carbies.getFireLoss() < THRESHOLD_UNHUSK && (carbies.reagents.get_reagent_amount(/datum/reagent/medicine/c2/synthflesh) + reac_volume >= 100)) + carbies.cure_husk("burn") + carbies.visible_message("A rubbery liquid coats [carbies]'s burns. [carbies] looks a lot healthier!") //we're avoiding using the phrases "burnt flesh" and "burnt skin" here because carbies could be a skeleton or a golem or something return TRUE /******ORGAN HEALING******/ diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index cc4eeac235b..d5fd7418e85 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -515,11 +515,11 @@ glass_name = "glass of Pwr Game" glass_desc = "Goes well with a Vlad's salad." -/datum/reagent/consumable/pwr_game/expose_mob(mob/living/C, methods=TOUCH, reac_volume) - ..() - if(C?.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && (methods & INGEST) && !HAS_TRAIT(C, TRAIT_GAMERGOD)) - ADD_TRAIT(C, TRAIT_GAMERGOD, "pwr_game") - to_chat(C, "As you imbibe the Pwr Game, your gamer third eye opens... \ +/datum/reagent/consumable/pwr_game/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(exposed_mob?.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && (methods & INGEST) && !HAS_TRAIT(exposed_mob, TRAIT_GAMERGOD)) + ADD_TRAIT(exposed_mob, TRAIT_GAMERGOD, "pwr_game") + to_chat(exposed_mob, "As you imbibe the Pwr Game, your gamer third eye opens... \ You feel as though a great secret of the universe has been made known to you...") /datum/reagent/consumable/pwr_game/on_mob_life(mob/living/carbon/M) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 12f045771a0..07aa33cf5d8 100755 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -24,20 +24,21 @@ return holder.remove_reagent(type, metabolization_rate) -/datum/reagent/consumable/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if((methods & INGEST) && quality && !HAS_TRAIT(M, TRAIT_AGEUSIA)) - switch(quality) - if (DRINK_NICE) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_nice) - if (DRINK_GOOD) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_good) - if (DRINK_VERYGOOD) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_verygood) - if (DRINK_FANTASTIC) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_fantastic) - if (FOOD_AMAZING) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_food", /datum/mood_event/amazingtaste) - return ..() +/datum/reagent/consumable/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(!(methods & INGEST) || !quality || HAS_TRAIT(exposed_mob, TRAIT_AGEUSIA)) + return + switch(quality) + if (DRINK_NICE) + SEND_SIGNAL(exposed_mob, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_nice) + if (DRINK_GOOD) + SEND_SIGNAL(exposed_mob, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_good) + if (DRINK_VERYGOOD) + SEND_SIGNAL(exposed_mob, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_verygood) + if (DRINK_FANTASTIC) + SEND_SIGNAL(exposed_mob, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_fantastic) + if (FOOD_AMAZING) + SEND_SIGNAL(exposed_mob, COMSIG_ADD_MOOD_EVENT, "quality_food", /datum/mood_event/amazingtaste) /datum/reagent/consumable/nutriment name = "Nutriment" @@ -124,49 +125,49 @@ taste_description = "oil" nutriment_factor = 7 * REAGENTS_METABOLISM //Not very healthy on its own metabolization_rate = 10 * REAGENTS_METABOLISM + penetrates_skin = NONE var/fry_temperature = 450 //Around ~350 F (117 C) which deep fryers operate around in the real world -/datum/reagent/consumable/cooking_oil/expose_obj(obj/O, reac_volume) - if(holder && holder.chem_temp >= fry_temperature) - if(isitem(O) && !istype(O, /obj/item/food/deepfryholder)) - O.loc.visible_message("[O] rapidly fries as it's splashed with hot oil! Somehow.") - var/obj/item/food/deepfryholder/F = new(O.drop_location(), O) - F.fry(volume) - F.reagents.add_reagent(/datum/reagent/consumable/cooking_oil, reac_volume) - -/datum/reagent/consumable/cooking_oil/expose_mob(mob/living/M, methods = TOUCH, reac_volume, show_message = 1, touch_protection = 0) - if(!istype(M)) +/datum/reagent/consumable/cooking_oil/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + if(!holder || (holder.chem_temp <= fry_temperature)) return - var/boiling = FALSE - if(holder && holder.chem_temp >= fry_temperature) - boiling = TRUE - if(!(methods & (VAPOR|TOUCH))) //Directly coats the mob, and doesn't go into their bloodstream - return ..() - if(!boiling) - return TRUE + if(!isitem(exposed_obj) || istype(exposed_obj, /obj/item/food/deepfryholder)) + return + exposed_obj.loc.visible_message("[exposed_obj] rapidly fries as it's splashed with hot oil! Somehow.") + var/obj/item/food/deepfryholder/fry_target = new(exposed_obj.drop_location(), exposed_obj) + fry_target.fry(volume) + fry_target.reagents.add_reagent(/datum/reagent/consumable/cooking_oil, reac_volume) + +/datum/reagent/consumable/cooking_oil/expose_mob(mob/living/exposed_mob, methods = TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) + . = ..() + if(!(methods & (VAPOR|TOUCH)) || isnull(holder) || (holder.chem_temp < fry_temperature)) //Directly coats the mob, and doesn't go into their bloodstream + return + var/oil_damage = ((holder.chem_temp / fry_temperature) * 0.33) //Damage taken per unit if(methods & TOUCH) - oil_damage *= 1 - M.get_permeability_protection() + oil_damage *= max(1 - touch_protection, 0) var/FryLoss = round(min(38, oil_damage * reac_volume)) - if(!HAS_TRAIT(M, TRAIT_OIL_FRIED)) - M.visible_message("The boiling oil sizzles as it covers [M]!", \ + if(!HAS_TRAIT(exposed_mob, TRAIT_OIL_FRIED)) + exposed_mob.visible_message("The boiling oil sizzles as it covers [exposed_mob]!", \ "You're covered in boiling oil!") if(FryLoss) - M.emote("scream") - playsound(M, 'sound/machines/fryer/deep_fryer_emerge.ogg', 25, TRUE) - ADD_TRAIT(M, TRAIT_OIL_FRIED, "cooking_oil_react") - addtimer(CALLBACK(M, /mob/living/proc/unfry_mob), 3) + exposed_mob.emote("scream") + playsound(exposed_mob, 'sound/machines/fryer/deep_fryer_emerge.ogg', 25, TRUE) + ADD_TRAIT(exposed_mob, TRAIT_OIL_FRIED, "cooking_oil_react") + addtimer(CALLBACK(exposed_mob, /mob/living/proc/unfry_mob), 3) if(FryLoss) - M.adjustFireLoss(FryLoss) + exposed_mob.adjustFireLoss(FryLoss) return TRUE -/datum/reagent/consumable/cooking_oil/expose_turf(turf/open/T, reac_volume) - if(!istype(T) || isgroundlessturf(T)) +/datum/reagent/consumable/cooking_oil/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(!istype(exposed_turf) || isgroundlessturf(exposed_turf) || (reac_volume < 5)) return - if(reac_volume >= 5) - T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = reac_volume * 1.5 SECONDS) - T.name = "deep-fried [initial(T.name)]" - T.add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY) + + exposed_turf.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = reac_volume * 1.5 SECONDS) + exposed_turf.name = "deep-fried [initial(exposed_turf.name)]" + exposed_turf.add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY) /datum/reagent/consumable/sugar name = "Sugar" @@ -289,27 +290,32 @@ M.adjust_bodytemperature(cooling, 50) ..() -/datum/reagent/consumable/frostoil/expose_turf(turf/T, reac_volume) - if(reac_volume >= 5) - for(var/mob/living/simple_animal/slime/M in T) - M.adjustToxLoss(rand(15,30)) - if(reac_volume >= 1) // Make Freezy Foam and anti-fire grenades! - if(isopenturf(T)) - var/turf/open/OT = T - OT.MakeSlippery(wet_setting=TURF_WET_ICE, min_wet_time=100, wet_time_to_add=reac_volume SECONDS) // Is less effective in high pressure/high heat capacity environments. More effective in low pressure. - OT.air.temperature -= MOLES_CELLSTANDARD*100*reac_volume/OT.air.heat_capacity() // reduces environment temperature by 5K per unit. +/datum/reagent/consumable/frostoil/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if(reac_volume < 1) + return + if(isopenturf(exposed_turf)) + var/turf/open/exposed_open_turf = exposed_turf + exposed_open_turf.MakeSlippery(wet_setting=TURF_WET_ICE, min_wet_time=100, wet_time_to_add=reac_volume SECONDS) // Is less effective in high pressure/high heat capacity environments. More effective in low pressure. + exposed_open_turf.air.temperature -= (MOLES_CELLSTANDARD * 100 * reac_volume) / exposed_open_turf.air.heat_capacity() // reduces environment temperature by 5K per unit. + if(reac_volume < 5) + return + for(var/mob/living/simple_animal/slime/exposed_slime in exposed_turf) + exposed_slime.adjustToxLoss(rand(15,30)) /datum/reagent/consumable/condensedcapsaicin name = "Condensed Capsaicin" description = "A chemical agent used for self-defense and in police work." color = "#B31008" // rgb: 179, 16, 8 taste_description = "scorching agony" + penetrates_skin = NONE -/datum/reagent/consumable/condensedcapsaicin/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(!ishuman(M) && !ismonkey(M)) +/datum/reagent/consumable/condensedcapsaicin/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(!ishuman(exposed_mob) && !ismonkey(exposed_mob)) return - var/mob/living/carbon/victim = M + var/mob/living/carbon/victim = exposed_mob if(methods & (TOUCH|VAPOR)) var/pepper_proof = victim.is_pepper_proof() @@ -320,7 +326,7 @@ victim.emote("scream") victim.blur_eyes(5) // 10 seconds victim.blind_eyes(3) // 6 seconds - victim.set_confusion(max(M.get_confusion(), 5)) // 10 seconds + victim.set_confusion(max(exposed_mob.get_confusion(), 5)) // 10 seconds victim.Knockdown(3 SECONDS) victim.add_movespeed_modifier(/datum/movespeed_modifier/reagent/pepperspray) addtimer(CALLBACK(victim, /mob.proc/remove_movespeed_modifier, /datum/movespeed_modifier/reagent/pepperspray), 10 SECONDS) @@ -328,7 +334,7 @@ if(methods & INGEST) if(!holder.has_reagent(/datum/reagent/consumable/milk)) if(prob(15)) - to_chat(M, "[pick("Your head pounds.", "Your mouth feels like it's on fire.", "You feel dizzy.")]") + to_chat(exposed_mob, "[pick("Your head pounds.", "Your mouth feels like it's on fire.", "You feel dizzy.")]") if(prob(10)) victim.blur_eyes(1) if(prob(10)) @@ -348,19 +354,19 @@ reagent_state = SOLID color = "#FFFFFF" // rgb: 255,255,255 taste_description = "salt" + penetrates_skin = NONE -/datum/reagent/consumable/sodiumchloride/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(!istype(M)) - return - if(M.has_bane(BANE_SALT)) - M.mind.disrupt_spells(-200) +/datum/reagent/consumable/sodiumchloride/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=0) + . = ..() + if(exposed_mob.has_bane(BANE_SALT)) + exposed_mob.mind.disrupt_spells(-200) -/datum/reagent/consumable/sodiumchloride/expose_turf(turf/T, reac_volume) //Creates an umbra-blocking salt pile - if(!istype(T)) +/datum/reagent/consumable/sodiumchloride/expose_turf(turf/exposed_turf, reac_volume) //Creates an umbra-blocking salt pile + . = ..() + if(!istype(exposed_turf) || (reac_volume < 1)) return - if(reac_volume < 1) - return - new/obj/effect/decal/cleanable/food/salt(T) + + new/obj/effect/decal/cleanable/food/salt(exposed_turf) /datum/reagent/consumable/blackpepper name = "Black Pepper" @@ -447,16 +453,17 @@ color = "#302000" // rgb: 48, 32, 0 taste_description = "slime" -/datum/reagent/consumable/cornoil/expose_turf(turf/open/T, reac_volume) - if (!istype(T)) +/datum/reagent/consumable/cornoil/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(!istype(exposed_turf)) return - T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = reac_volume*2 SECONDS) - var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T) + exposed_turf.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = reac_volume*2 SECONDS) + var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in exposed_turf) if(hotspot) - var/datum/gas_mixture/lowertemp = T.remove_air(T.air.total_moles()) + var/datum/gas_mixture/lowertemp = exposed_turf.remove_air(exposed_turf.air.total_moles()) lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0) lowertemp.react(src) - T.assume_air(lowertemp) + exposed_turf.assume_air(lowertemp) qdel(hotspot) /datum/reagent/consumable/enzyme @@ -497,8 +504,8 @@ color = "#302000" // rgb: 48, 32, 0 taste_description = "wet and cheap noodles on fire" -/datum/reagent/consumable/hell_ramen/on_mob_life(mob/living/carbon/M) - M.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT) +/datum/reagent/consumable/hell_ramen/on_mob_life(mob/living/carbon/target_mob) + target_mob.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT) ..() /datum/reagent/consumable/flour @@ -508,12 +515,15 @@ color = "#FFFFFF" // rgb: 0, 0, 0 taste_description = "chalky wheat" -/datum/reagent/consumable/flour/expose_turf(turf/T, reac_volume) - if(!isspaceturf(T)) - var/obj/effect/decal/cleanable/food/flour/reagentdecal = new(T) - reagentdecal = locate() in T //Might have merged with flour already there. - if(reagentdecal) - reagentdecal.reagents.add_reagent(/datum/reagent/consumable/flour, reac_volume) +/datum/reagent/consumable/flour/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if(isspaceturf(exposed_turf)) + return + + var/obj/effect/decal/cleanable/food/flour/reagentdecal = new(exposed_turf) + reagentdecal = locate() in exposed_turf //Might have merged with flour already there. + if(reagentdecal) + reagentdecal.reagents.add_reagent(/datum/reagent/consumable/flour, reac_volume) /datum/reagent/consumable/cherryjelly name = "Cherry Jelly" @@ -594,13 +604,15 @@ M.adjustToxLoss(-1*REM, 0) ..() -/datum/reagent/consumable/honey/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(iscarbon(M) && (methods & (TOUCH|VAPOR|PATCH))) - var/mob/living/carbon/C = M - for(var/s in C.surgeries) - var/datum/surgery/S = s - S.speed_modifier = max(0.6, S.speed_modifier) - ..() +/datum/reagent/consumable/honey/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(!iscarbon(exposed_mob) || !(methods & (TOUCH|VAPOR|PATCH))) + return + + var/mob/living/carbon/exposed_carbon = exposed_mob + for(var/s in exposed_carbon.surgeries) + var/datum/surgery/surgery = s + surgery.speed_modifier = max(0.6, surgery.speed_modifier) /datum/reagent/consumable/mayonnaise name = "Mayonnaise" @@ -620,21 +632,18 @@ color = "#c0c9a0" taste_description = "bitterness" -/datum/reagent/consumable/tearjuice/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(!istype(M)) +/datum/reagent/consumable/tearjuice/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(!(methods & INGEST) || !((methods & (TOUCH|PATCH|VAPOR)) && (exposed_mob.is_mouth_covered() || exposed_mob.is_eyes_covered()))) return - var/unprotected = FALSE - if((methods & INGEST) || ((methods & (TOUCH|PATCH|VAPOR)) && !M.is_mouth_covered() && !M.is_eyes_covered())) - unprotected = TRUE - if(unprotected) - if(!M.getorganslot(ORGAN_SLOT_EYES)) //can't blind somebody with no eyes - to_chat(M, "Your eye sockets feel wet.") - else - if(!M.eye_blurry) - to_chat(M, "Tears well up in your eyes!") - M.blind_eyes(2) - M.blur_eyes(5) - ..() + + if(!exposed_mob.getorganslot(ORGAN_SLOT_EYES)) //can't blind somebody with no eyes + to_chat(exposed_mob, "Your eye sockets feel wet.") + else + if(!exposed_mob.eye_blurry) + to_chat(exposed_mob, "Tears well up in your eyes!") + exposed_mob.blind_eyes(2) + exposed_mob.blur_eyes(5) /datum/reagent/consumable/tearjuice/on_mob_life(mob/living/carbon/M) ..() @@ -688,8 +697,9 @@ //Lazy list of mobs affected by the luminosity of this reagent. var/list/mobs_affected -/datum/reagent/consumable/tinlux/expose_mob(mob/living/M) - add_reagent_light(M) +/datum/reagent/consumable/tinlux/expose_mob(mob/living/exposed_mob) + . = ..() + add_reagent_light(exposed_mob) /datum/reagent/consumable/tinlux/on_mob_end_metabolize(mob/living/M) remove_reagent_light(M) @@ -740,12 +750,15 @@ color = "#97ee63" taste_description = "pure electricity" -/datum/reagent/consumable/liquidelectricity/expose_mob(mob/living/M, methods=TOUCH, reac_volume) //can't be on life because of the way blood works. - if((methods & (INGEST|INJECT|PATCH)) && iscarbon(M)) - var/mob/living/carbon/C = M - var/obj/item/organ/stomach/ethereal/stomach = C.getorganslot(ORGAN_SLOT_STOMACH) - if(istype(stomach)) - stomach.adjust_charge(reac_volume * REM) +/datum/reagent/consumable/liquidelectricity/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) //can't be on life because of the way blood works. + . = ..() + if(!(methods & (INGEST|INJECT|PATCH)) || !iscarbon(exposed_mob)) + return + + var/mob/living/carbon/exposed_carbon = exposed_mob + var/obj/item/organ/stomach/ethereal/stomach = exposed_carbon.getorganslot(ORGAN_SLOT_STOMACH) + if(istype(stomach)) + stomach.adjust_charge(reac_volume * REM) /datum/reagent/consumable/liquidelectricity/on_mob_life(mob/living/carbon/M) if(prob(25) && !isethereal(M)) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 41b87975455..b7b28965f72 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -232,13 +232,15 @@ ..() . = 1 -/datum/reagent/medicine/rezadone/expose_mob(mob/living/M, methods=TOUCH, reac_volume) +/datum/reagent/medicine/rezadone/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) . = ..() - if(iscarbon(M)) - var/mob/living/carbon/patient = M - if(reac_volume >= 5 && HAS_TRAIT_FROM(patient, TRAIT_HUSK, "burn") && patient.getFireLoss() < THRESHOLD_UNHUSK) //One carp yields 12u rezadone. - patient.cure_husk("burn") - patient.visible_message("[patient]'s body rapidly absorbs moisture from the environment, taking on a more healthy appearance.") + if(!iscarbon(exposed_mob)) + return + + var/mob/living/carbon/patient = exposed_mob + if(reac_volume >= 5 && HAS_TRAIT_FROM(patient, TRAIT_HUSK, "burn") && patient.getFireLoss() < THRESHOLD_UNHUSK) //One carp yields 12u rezadone. + patient.cure_husk("burn") + patient.visible_message("[patient]'s body rapidly absorbs moisture from the environment, taking on a more healthy appearance.") /datum/reagent/medicine/spaceacillin name = "Spaceacillin" @@ -326,21 +328,24 @@ ..() return TRUE -/datum/reagent/medicine/mine_salve/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message = 1) - if(iscarbon(M) && M.stat != DEAD) - if(methods & (INGEST|VAPOR|INJECT)) - M.adjust_nutrition(-5) - if(show_message) - to_chat(M, "Your stomach feels empty and cramps!") - else - var/mob/living/carbon/C = M - for(var/s in C.surgeries) - var/datum/surgery/S = s - S.speed_modifier = max(0.1, S.speed_modifier) +/datum/reagent/medicine/mine_salve/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE) + . = ..() + if(!iscarbon(exposed_mob) || (exposed_mob.stat == DEAD)) + return - if(show_message) - to_chat(M, "You feel your injuries fade away to nothing!" ) - ..() + if(methods & (INGEST|VAPOR|INJECT)) + exposed_mob.adjust_nutrition(-5) + if(show_message) + to_chat(exposed_mob, "Your stomach feels empty and cramps!") + + if(methods & (PATCH|TOUCH)) + var/mob/living/carbon/exposed_carbon = exposed_mob + for(var/s in exposed_carbon.surgeries) + var/datum/surgery/surgery = s + surgery.speed_modifier = max(0.1, surgery.speed_modifier) + + if(show_message) + to_chat(exposed_carbon, "You feel your injuries fade away to nothing!" ) /datum/reagent/medicine/mine_salve/on_mob_end_metabolize(mob/living/M) if(iscarbon(M)) @@ -766,26 +771,26 @@ if(chems.has_reagent(type, 1)) mytray.spawnplant() -/datum/reagent/medicine/strange_reagent/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(M.stat != DEAD) +/datum/reagent/medicine/strange_reagent/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + if(exposed_mob.stat != DEAD) return ..() - if(M.suiciding || M.hellbound) //they are never coming back - M.visible_message("[M]'s body does not react...") + if(exposed_mob.suiciding || exposed_mob.hellbound) //they are never coming back + exposed_mob.visible_message("[exposed_mob]'s body does not react...") return - if(iscarbon(M) && !(methods & INGEST)) //simplemobs can still be splashed + if(iscarbon(exposed_mob) && !(methods & INGEST)) //simplemobs can still be splashed return ..() - var/amount_to_revive = round((M.getBruteLoss()+M.getFireLoss())/20) - if(M.getBruteLoss()+M.getFireLoss() >= 200 || HAS_TRAIT(M, TRAIT_HUSK) || reac_volume < amount_to_revive) //body will die from brute+burn on revive or you haven't provided enough to revive. - M.visible_message("[M]'s body convulses a bit, and then falls still once more.") - M.do_jitter_animation(10) + var/amount_to_revive = round((exposed_mob.getBruteLoss()+exposed_mob.getFireLoss())/20) + if(exposed_mob.getBruteLoss()+exposed_mob.getFireLoss() >= 200 || HAS_TRAIT(exposed_mob, TRAIT_HUSK) || reac_volume < amount_to_revive) //body will die from brute+burn on revive or you haven't provided enough to revive. + exposed_mob.visible_message("[exposed_mob]'s body convulses a bit, and then falls still once more.") + exposed_mob.do_jitter_animation(10) return - M.visible_message("[M]'s body starts convulsing!") - M.notify_ghost_cloning("Your body is being revived with Strange Reagent!") - M.do_jitter_animation(10) + exposed_mob.visible_message("[exposed_mob]'s body starts convulsing!") + exposed_mob.notify_ghost_cloning("Your body is being revived with Strange Reagent!") + exposed_mob.do_jitter_animation(10) var/excess_healing = 5*(reac_volume-amount_to_revive) //excess reagent will heal blood and organs across the board - addtimer(CALLBACK(M, /mob/living/carbon.proc/do_jitter_animation, 10), 40) //jitter immediately, then again after 4 and 8 seconds - addtimer(CALLBACK(M, /mob/living/carbon.proc/do_jitter_animation, 10), 80) - addtimer(CALLBACK(M, /mob/living.proc/revive, FALSE, FALSE, excess_healing), 79) + addtimer(CALLBACK(exposed_mob, /mob/living/carbon.proc/do_jitter_animation, 10), 40) //jitter immediately, then again after 4 and 8 seconds + addtimer(CALLBACK(exposed_mob, /mob/living/carbon.proc/do_jitter_animation, 10), 80) + addtimer(CALLBACK(exposed_mob, /mob/living.proc/revive, FALSE, FALSE, excess_healing), 79) ..() /datum/reagent/medicine/strange_reagent/on_mob_life(mob/living/carbon/M) @@ -926,12 +931,15 @@ color = "#CC23FF" taste_description = "jelly" -/datum/reagent/medicine/regen_jelly/expose_mob(mob/living/M, reac_volume) - if(M && ishuman(M) && reac_volume >= 0.5) - var/mob/living/carbon/human/H = M - H.hair_color = "C2F" - H.facial_hair_color = "C2F" - H.update_hair() +/datum/reagent/medicine/regen_jelly/expose_mob(mob/living/exposed_mob, reac_volume) + . = ..() + if(!ishuman(exposed_mob) || (reac_volume < 0.5)) + return + + var/mob/living/carbon/human/exposed_human = exposed_mob + exposed_human.hair_color = "C2F" + exposed_human.facial_hair_color = "C2F" + exposed_human.update_hair() /datum/reagent/medicine/regen_jelly/on_mob_life(mob/living/carbon/M) M.adjustBruteLoss(-1.5*REM, 0) @@ -1267,18 +1275,18 @@ taste_description = "numbing bitterness" /datum/reagent/medicine/polypyr/on_mob_life(mob/living/carbon/M) //I wanted a collection of small positive effects, this is as hard to obtain as coniine after all. + . = ..() M.adjustOrganLoss(ORGAN_SLOT_LUNGS, -0.25) M.adjustBruteLoss(-0.35, 0) - ..() - . = 1 + return TRUE -/datum/reagent/medicine/polypyr/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(methods & (TOUCH|VAPOR)) - if(M && ishuman(M) && reac_volume >= 0.5) - var/mob/living/carbon/human/H = M - H.hair_color = "92f" - H.facial_hair_color = "92f" - H.update_hair() +/datum/reagent/medicine/polypyr/expose_mob(mob/living/carbon/human/exposed_human, methods=TOUCH, reac_volume) + . = ..() + if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_human) || (reac_volume < 0.5)) + return + exposed_human.hair_color = "92f" + exposed_human.facial_hair_color = "92f" + exposed_human.update_hair() /datum/reagent/medicine/polypyr/overdose_process(mob/living/M) M.adjustOrganLoss(ORGAN_SLOT_LUNGS, 0.5) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index f0817aac95f..b5ac596877f 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -9,6 +9,7 @@ glass_name = "glass of tomato juice" glass_desc = "Are you sure this is tomato juice?" shot_glass_icon_state = "shotglassred" + penetrates_skin = NONE // FEED ME /datum/reagent/blood/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray) @@ -16,26 +17,27 @@ if(chems.has_reagent(src.type, 1)) mytray.adjustPests(rand(2,3)) -/datum/reagent/blood/expose_mob(mob/living/L, methods=TOUCH, reac_volume) +/datum/reagent/blood/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=0) + . = ..() if(data && data["viruses"]) for(var/thing in data["viruses"]) - var/datum/disease/D = thing + var/datum/disease/strain = thing - if((D.spread_flags & DISEASE_SPREAD_SPECIAL) || (D.spread_flags & DISEASE_SPREAD_NON_CONTAGIOUS)) + if((strain.spread_flags & DISEASE_SPREAD_SPECIAL) || (strain.spread_flags & DISEASE_SPREAD_NON_CONTAGIOUS)) continue - if((methods & (TOUCH|VAPOR)) && (D.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS)) - L.ContactContractDisease(D) + if((methods & (TOUCH|VAPOR)) && (strain.spread_flags & DISEASE_SPREAD_CONTACT_FLUIDS)) + exposed_mob.ContactContractDisease(strain) else //ingest, patch or inject - L.ForceContractDisease(D) + exposed_mob.ForceContractDisease(strain) - if(iscarbon(L)) - var/mob/living/carbon/C = L - if(C.get_blood_id() == /datum/reagent/blood && ((methods & INJECT) || ((methods & INGEST) && C.dna && C.dna.species && (DRINKSBLOOD in C.dna.species.species_traits)))) - if(!data || !(data["blood_type"] in get_safe_blood(C.dna.blood_type))) - C.reagents.add_reagent(/datum/reagent/toxin, reac_volume * 0.5) + if(iscarbon(exposed_mob)) + var/mob/living/carbon/exposed_carbon = exposed_mob + if(exposed_carbon.get_blood_id() == /datum/reagent/blood && ((methods & INJECT) || ((methods & INGEST) && exposed_carbon.dna && exposed_carbon.dna.species && (DRINKSBLOOD in exposed_carbon.dna.species.species_traits)))) + if(!data || !(data["blood_type"] in get_safe_blood(exposed_carbon.dna.blood_type))) + exposed_carbon.reagents.add_reagent(/datum/reagent/toxin, reac_volume * 0.5) else - C.blood_volume = min(C.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM) + exposed_carbon.blood_volume = min(exposed_carbon.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM) /datum/reagent/blood/on_new(list/data) @@ -75,17 +77,18 @@ var/datum/disease/D = thing . += D -/datum/reagent/blood/expose_turf(turf/T, reac_volume)//splash the blood all over the place - if(!istype(T)) +/datum/reagent/blood/expose_turf(turf/exposed_turf, reac_volume)//splash the blood all over the place + . = ..() + if(!istype(exposed_turf)) return if(reac_volume < 3) return - var/obj/effect/decal/cleanable/blood/B = locate() in T //find some blood here - if(!B) - B = new(T) + var/obj/effect/decal/cleanable/blood/bloodsplatter = locate() in exposed_turf //find some blood here + if(!bloodsplatter) + bloodsplatter = new(exposed_turf) if(data["blood_DNA"]) - B.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) + bloodsplatter.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) /datum/reagent/blood/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray) . = ..() @@ -104,14 +107,18 @@ name = "Vaccine" color = "#C81040" // rgb: 200, 16, 64 taste_description = "slime" + penetrates_skin = NONE -/datum/reagent/vaccine/expose_mob(mob/living/L, methods=TOUCH, reac_volume) - if(islist(data) && (methods & (INGEST|INJECT))) - for(var/thing in L.diseases) - var/datum/disease/D = thing - if(D.GetDiseaseID() in data) - D.cure() - LAZYOR(L.disease_resistances, data) +/datum/reagent/vaccine/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=0) + . = ..() + if(!islist(data) || !(methods & (INGEST|INJECT))) + return + + for(var/thing in exposed_mob.diseases) + var/datum/disease/infection = thing + if(infection.GetDiseaseID() in data) + infection.cure() + LAZYOR(exposed_mob.disease_resistances, data) /datum/reagent/vaccine/on_merge(list/data) if(istype(data)) @@ -144,48 +151,46 @@ * Water reaction to turf */ -/datum/reagent/water/expose_turf(turf/open/T, reac_volume) - if(!istype(T)) +/datum/reagent/water/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(!istype(exposed_turf)) return - var/CT = cooling_temperature + var/cool_temp = cooling_temperature if(reac_volume >= 5) - T.MakeSlippery(TURF_WET_WATER, 10 SECONDS, min(reac_volume*1.5 SECONDS, 60 SECONDS)) + exposed_turf.MakeSlippery(TURF_WET_WATER, 10 SECONDS, min(reac_volume*1.5 SECONDS, 60 SECONDS)) - for(var/mob/living/simple_animal/slime/M in T) - M.apply_water() + for(var/mob/living/simple_animal/slime/exposed_slime in exposed_turf) + exposed_slime.apply_water() - var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T) - if(hotspot && !isspaceturf(T)) - if(T.air) - var/datum/gas_mixture/G = T.air - G.temperature = max(min(G.temperature-(CT*1000),G.temperature/CT),TCMB) - G.react(src) + var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in exposed_turf) + if(hotspot && !isspaceturf(exposed_turf)) + if(exposed_turf.air) + var/datum/gas_mixture/air = exposed_turf.air + air.temperature = max(min(air.temperature-(cool_temp*1000), air.temperature/cool_temp),TCMB) + air.react(src) qdel(hotspot) - //fixed - var/obj/effect/acid/A = (locate(/obj/effect/acid) in T) - if(A) - A.acid_level = max(A.acid_level - reac_volume*50, 0) /* * Water reaction to an object */ -/datum/reagent/water/expose_obj(obj/O, reac_volume) - O.extinguish() - O.acid_level = 0 +/datum/reagent/water/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + exposed_obj.extinguish() + exposed_obj.wash(CLEAN_TYPE_ACID) // Monkey cube - if(istype(O, /obj/item/reagent_containers/food/snacks/monkeycube)) - var/obj/item/reagent_containers/food/snacks/monkeycube/cube = O + if(istype(exposed_obj, /obj/item/reagent_containers/food/snacks/monkeycube)) + var/obj/item/reagent_containers/food/snacks/monkeycube/cube = exposed_obj cube.Expand() // Dehydrated carp - else if(istype(O, /obj/item/toy/plush/carpplushie/dehy_carp)) - var/obj/item/toy/plush/carpplushie/dehy_carp/dehy = O + else if(istype(exposed_obj, /obj/item/toy/plush/carpplushie/dehy_carp)) + var/obj/item/toy/plush/carpplushie/dehy_carp/dehy = exposed_obj dehy.Swell() // Makes a carp - else if(istype(O, /obj/item/stack/sheet/hairlesshide)) - var/obj/item/stack/sheet/hairlesshide/HH = O + else if(istype(exposed_obj, /obj/item/stack/sheet/hairlesshide)) + var/obj/item/stack/sheet/hairlesshide/HH = exposed_obj new /obj/item/stack/sheet/wethide(get_turf(HH), HH.amount) qdel(HH) @@ -193,12 +198,10 @@ * Water reaction to a mob */ -/datum/reagent/water/expose_mob(mob/living/M, methods=TOUCH, reac_volume)//Splashing people with water can help put them out! - if(!istype(M)) - return +/datum/reagent/water/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)//Splashing people with water can help put them out! + . = ..() if(methods & TOUCH) - M.extinguish_mob() // extinguish removes all fire stacks - ..() + exposed_mob.extinguish_mob() // extinguish removes all fire stacks /datum/reagent/water/on_mob_life(mob/living/carbon/M) . = ..() @@ -237,10 +240,10 @@ REMOVE_TRAIT(L, TRAIT_HOLY, type) ..() -/datum/reagent/water/holywater/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(iscultist(M)) - to_chat(M, "A vile holiness begins to spread its shining tendrils through your mind, purging the Geometer of Blood's influence!") - ..() +/datum/reagent/water/holywater/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(iscultist(exposed_mob)) + to_chat(exposed_mob, "A vile holiness begins to spread its shining tendrils through your mind, purging the Geometer of Blood's influence!") /datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M) if(M.blood_volume) @@ -275,14 +278,14 @@ return holder.remove_reagent(type, 0.4) //fixed consumption to prevent balancing going out of whack -/datum/reagent/water/holywater/expose_turf(turf/T, reac_volume) - ..() - if(!istype(T)) +/datum/reagent/water/holywater/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if(!istype(exposed_turf)) return if(reac_volume>=10) - for(var/obj/effect/rune/R in T) + for(var/obj/effect/rune/R in exposed_turf) qdel(R) - T.Bless() + exposed_turf.Bless() /datum/reagent/water/holywater/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray) . = ..() @@ -312,33 +315,27 @@ * Water reaction to turf */ -/datum/reagent/hydrogen_peroxide/expose_turf(turf/open/T, reac_volume) - if(!istype(T)) +/datum/reagent/hydrogen_peroxide/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(!istype(exposed_turf)) return if(reac_volume >= 5) - T.MakeSlippery(TURF_WET_WATER, 10 SECONDS, min(reac_volume*1.5 SECONDS, 60 SECONDS)) + exposed_turf.MakeSlippery(TURF_WET_WATER, 10 SECONDS, min(reac_volume*1.5 SECONDS, 60 SECONDS)) /* * Water reaction to a mob */ -/datum/reagent/hydrogen_peroxide/expose_mob(mob/living/M, methods=TOUCH, reac_volume)//Splashing people with h2o2 can burn them ! - if(!istype(M)) - return +/datum/reagent/hydrogen_peroxide/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)//Splashing people with h2o2 can burn them ! + . = ..() if(methods & TOUCH) - M.adjustFireLoss(2, 0) // burns - ..() + exposed_mob.adjustFireLoss(2, 0) // burns /datum/reagent/fuel/unholywater //if you somehow managed to extract this from someone, dont splash it on yourself and have a smoke name = "Unholy Water" description = "Something that shouldn't exist on this plane of existence." taste_description = "suffering" metabolization_rate = 2.5 * REAGENTS_METABOLISM //1u/tick - -/datum/reagent/fuel/unholywater/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(methods & (TOUCH|VAPOR)) - M.reagents.add_reagent(type,reac_volume/4) - return - return ..() + penetrates_skin = TOUCH|VAPOR /datum/reagent/fuel/unholywater/on_mob_life(mob/living/carbon/M) if(iscultist(M)) @@ -385,11 +382,12 @@ taste_description = "cherry" // by popular demand var/lube_kind = TURF_WET_LUBE ///What kind of slipperiness gets added to turfs. -/datum/reagent/lube/expose_turf(turf/open/T, reac_volume) - if (!istype(T)) +/datum/reagent/lube/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(!istype(exposed_turf)) return if(reac_volume >= 1) - T.MakeSlippery(lube_kind, 15 SECONDS, min(reac_volume * 2 SECONDS, 120)) + exposed_turf.MakeSlippery(lube_kind, 15 SECONDS, min(reac_volume * 2 SECONDS, 120)) ///Stronger kind of lube. Applies TURF_WET_SUPERLUBE. /datum/reagent/lube/superlube @@ -405,38 +403,39 @@ overdose_threshold = 11 //Slightly more than one un-nozzled spraybottle. taste_description = "sour oranges" -/datum/reagent/spraytan/expose_mob(mob/living/M, methods=TOUCH, reac_volume, show_message = 1) - if(ishuman(M)) +/datum/reagent/spraytan/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE) + . = ..() + if(ishuman(exposed_mob)) if(methods & (PATCH|VAPOR)) - var/mob/living/carbon/human/N = M - if(N.dna.species.id == "human") - switch(N.skin_tone) + var/mob/living/carbon/human/exposed_human = exposed_mob + if(exposed_human.dna.species.id == "human") + switch(exposed_human.skin_tone) if("african1") - N.skin_tone = "african2" + exposed_human.skin_tone = "african2" if("indian") - N.skin_tone = "african1" + exposed_human.skin_tone = "african1" if("arab") - N.skin_tone = "indian" + exposed_human.skin_tone = "indian" if("asian2") - N.skin_tone = "arab" + exposed_human.skin_tone = "arab" if("asian1") - N.skin_tone = "asian2" + exposed_human.skin_tone = "asian2" if("mediterranean") - N.skin_tone = "african1" + exposed_human.skin_tone = "african1" if("latino") - N.skin_tone = "mediterranean" + exposed_human.skin_tone = "mediterranean" if("caucasian3") - N.skin_tone = "mediterranean" + exposed_human.skin_tone = "mediterranean" if("caucasian2") - N.skin_tone = pick("caucasian3", "latino") + exposed_human.skin_tone = pick("caucasian3", "latino") if("caucasian1") - N.skin_tone = "caucasian2" + exposed_human.skin_tone = "caucasian2" if ("albino") - N.skin_tone = "caucasian1" + exposed_human.skin_tone = "caucasian1" - if(MUTCOLORS in N.dna.species.species_traits) //take current alien color and darken it slightly + if(MUTCOLORS in exposed_human.dna.species.species_traits) //take current alien color and darken it slightly var/newcolor = "" - var/string = N.dna.features["mcolor"] + var/string = exposed_human.dna.features["mcolor"] var/len = length(string) var/char = "" var/ascii = 0 @@ -459,14 +458,11 @@ else break if(ReadHSV(newcolor)[3] >= ReadHSV("#7F7F7F")[3]) - N.dna.features["mcolor"] = newcolor - N.regenerate_icons() - - + exposed_human.dna.features["mcolor"] = newcolor + exposed_human.regenerate_icons() if((methods & INGEST) && show_message) - to_chat(M, "That tasted horrible.") - ..() + to_chat(exposed_mob, "That tasted horrible.") /datum/reagent/spraytan/overdose_process(mob/living/M) @@ -688,10 +684,12 @@ description = "An advanced corruptive toxin produced by slimes." color = "#13BC5E" // rgb: 19, 188, 94 taste_description = "slime" + penetrates_skin = NONE -/datum/reagent/aslimetoxin/expose_mob(mob/living/L, methods=TOUCH, reac_volume) +/datum/reagent/aslimetoxin/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=0) + . = ..() if(methods & ~TOUCH) - L.ForceContractDisease(new /datum/disease/transformation/slime(), FALSE, TRUE) + exposed_mob.ForceContractDisease(new /datum/disease/transformation/slime(), FALSE, TRUE) /datum/reagent/gluttonytoxin name = "Gluttony's Blessing" @@ -699,9 +697,11 @@ color = "#5EFF3B" //RGB: 94, 255, 59 can_synth = FALSE taste_description = "decay" + penetrates_skin = NONE -/datum/reagent/gluttonytoxin/expose_mob(mob/living/L, methods=TOUCH, reac_volume) - L.ForceContractDisease(new /datum/disease/transformation/morph(), FALSE, TRUE) +/datum/reagent/gluttonytoxin/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=0) + . = ..() + exposed_mob.ForceContractDisease(new /datum/disease/transformation/morph(), FALSE, TRUE) /datum/reagent/serotrotium name = "Serotrotium" @@ -723,17 +723,18 @@ color = "#808080" // rgb: 128, 128, 128 taste_mult = 0 // oderless and tasteless -/datum/reagent/oxygen/expose_obj(obj/O, reac_volume) - if((!O) || (!reac_volume)) +/datum/reagent/oxygen/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + if((!exposed_obj) || (!reac_volume)) return 0 var/temp = holder ? holder.chem_temp : T20C - O.atmos_spawn_air("o2=[reac_volume/2];TEMP=[temp]") + exposed_obj.atmos_spawn_air("o2=[reac_volume/2];TEMP=[temp]") -/datum/reagent/oxygen/expose_turf(turf/open/T, reac_volume) - if(istype(T)) +/datum/reagent/oxygen/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(istype(exposed_turf)) var/temp = holder ? holder.chem_temp : T20C - T.atmos_spawn_air("o2=[reac_volume/2];TEMP=[temp]") - return + exposed_turf.atmos_spawn_air("o2=[reac_volume/2];TEMP=[temp]") /datum/reagent/copper name = "Copper" @@ -742,12 +743,15 @@ color = "#6E3B08" // rgb: 110, 59, 8 taste_description = "metal" -/datum/reagent/copper/expose_obj(obj/O, reac_volume) - if(istype(O, /obj/item/stack/sheet/metal)) - var/obj/item/stack/sheet/metal/M = O - reac_volume = min(reac_volume, M.amount) - new/obj/item/stack/tile/bronze(get_turf(M), reac_volume) - M.use(reac_volume) +/datum/reagent/copper/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + if(!istype(exposed_obj, /obj/item/stack/sheet/metal)) + return + + var/obj/item/stack/sheet/metal/M = exposed_obj + reac_volume = min(reac_volume, M.amount) + new/obj/item/stack/tile/bronze(get_turf(M), reac_volume) + M.use(reac_volume) /datum/reagent/nitrogen name = "Nitrogen" @@ -756,16 +760,18 @@ color = "#808080" // rgb: 128, 128, 128 taste_mult = 0 -/datum/reagent/nitrogen/expose_obj(obj/O, reac_volume) - if((!O) || (!reac_volume)) +/datum/reagent/nitrogen/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + if((!exposed_obj) || (!reac_volume)) return 0 var/temp = holder ? holder.chem_temp : T20C - O.atmos_spawn_air("n2=[reac_volume/2];TEMP=[temp]") + exposed_obj.atmos_spawn_air("n2=[reac_volume/2];TEMP=[temp]") -/datum/reagent/nitrogen/expose_turf(turf/open/T, reac_volume) - if(istype(T)) +/datum/reagent/nitrogen/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(istype(exposed_turf)) var/temp = holder ? holder.chem_temp : T20C - T.atmos_spawn_air("n2=[reac_volume/2];TEMP=[temp]") + exposed_turf.atmos_spawn_air("n2=[reac_volume/2];TEMP=[temp]") return /datum/reagent/hydrogen @@ -810,11 +816,14 @@ color = "#1C1300" // rgb: 30, 20, 0 taste_description = "sour chalk" -/datum/reagent/carbon/expose_turf(turf/T, reac_volume) - if(!isspaceturf(T)) - var/obj/effect/decal/cleanable/dirt/D = locate() in T.contents - if(!D) - new /obj/effect/decal/cleanable/dirt(T) +/datum/reagent/carbon/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if(isspaceturf(exposed_turf)) + return + + var/obj/effect/decal/cleanable/dirt/dirt_decal = (locate() in exposed_turf.contents) + if(!dirt_decal) + dirt_decal = new(exposed_turf) /datum/reagent/chlorine name = "Chlorine" @@ -909,12 +918,14 @@ color = "#D0EFEE" // space cleaner but lighter taste_description = "bitterness" -/datum/reagent/space_cleaner/sterilizine/expose_mob(mob/living/carbon/C, methods=TOUCH, reac_volume) - if(methods & (TOUCH|VAPOR|PATCH)) - for(var/s in C.surgeries) - var/datum/surgery/S = s - S.speed_modifier = max(0.2, S.speed_modifier) - ..() +/datum/reagent/space_cleaner/sterilizine/expose_mob(mob/living/carbon/exposed_carbon, methods=TOUCH, reac_volume) + . = ..() + if(!(methods & (TOUCH|VAPOR|PATCH))) + return + + for(var/s in exposed_carbon.surgeries) + var/datum/surgery/surgery = s + surgery.speed_modifier = max(0.2, surgery.speed_modifier) /datum/reagent/iron name = "Iron" @@ -930,11 +941,14 @@ C.blood_volume += 0.5 ..() -/datum/reagent/iron/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(M.has_bane(BANE_IRON)) //If the target is weak to cold iron, then poison them. - if(holder && holder.chem_temp < 100) // COLD iron. - M.reagents.add_reagent(/datum/reagent/toxin, reac_volume) - ..() +/datum/reagent/iron/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(!exposed_mob.has_bane(BANE_IRON)) //If the target is weak to cold iron, then poison them. + return + if(!holder || (holder.chem_temp >= 100)) // COLD iron. + return + + exposed_mob.reagents.add_reagent(/datum/reagent/toxin, reac_volume) /datum/reagent/gold name = "Gold" @@ -952,10 +966,10 @@ taste_description = "expensive yet reasonable metal" material = /datum/material/silver -/datum/reagent/silver/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(M.has_bane(BANE_SILVER)) - M.reagents.add_reagent(/datum/reagent/toxin, reac_volume) - ..() +/datum/reagent/silver/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(exposed_mob.has_bane(BANE_SILVER)) + exposed_mob.reagents.add_reagent(/datum/reagent/toxin, reac_volume) /datum/reagent/uranium name ="Uranium" @@ -970,14 +984,16 @@ M.apply_effect(irradiation_level/M.metabolism_efficiency,EFFECT_IRRADIATE,0) ..() -/datum/reagent/uranium/expose_turf(turf/T, reac_volume) - if(reac_volume >= 3) - if(!isspaceturf(T)) - var/obj/effect/decal/cleanable/greenglow/GG = locate() in T.contents - if(!GG) - GG = new/obj/effect/decal/cleanable/greenglow(T) - if(!QDELETED(GG)) - GG.reagents.add_reagent(type, reac_volume) +/datum/reagent/uranium/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if((reac_volume < 3) || isspaceturf(exposed_turf)) + return + + var/obj/effect/decal/cleanable/greenglow/glow = locate() in exposed_turf.contents + if(!glow) + glow = new(exposed_turf) + if(!QDELETED(glow)) + glow.reagents.add_reagent(type, reac_volume) //Mutagenic chem side-effects. /datum/reagent/uranium/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray, mob/user) @@ -1010,10 +1026,10 @@ taste_description = "fizzling blue" material = /datum/material/bluespace -/datum/reagent/bluespace/expose_mob(mob/living/M, methods=TOUCH, reac_volume) +/datum/reagent/bluespace/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() if(methods & (TOUCH|VAPOR)) - do_teleport(M, get_turf(M), (reac_volume / 5), asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) //4 tiles per crystal - ..() + do_teleport(exposed_mob, get_turf(exposed_mob), (reac_volume / 5), asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) //4 tiles per crystal /datum/reagent/bluespace/on_mob_life(mob/living/carbon/M) if(current_cycle > 10 && prob(15)) @@ -1049,12 +1065,12 @@ glass_icon_state = "dr_gibb_glass" glass_name = "glass of welder fuel" glass_desc = "Unless you're an industrial tool, this is probably not safe for consumption." + penetrates_skin = NONE -/datum/reagent/fuel/expose_mob(mob/living/M, methods=TOUCH, reac_volume)//Splashing people with welding fuel to make them easy to ignite! +/datum/reagent/fuel/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)//Splashing people with welding fuel to make them easy to ignite! + . = ..() if(methods & (TOUCH|VAPOR)) - M.adjust_fire_stacks(reac_volume / 10) - return - ..() + exposed_mob.adjust_fire_stacks(reac_volume / 10) /datum/reagent/fuel/on_mob_life(mob/living/carbon/M) M.adjustToxLoss(1, 0) @@ -1067,32 +1083,39 @@ color = "#A5F0EE" // rgb: 165, 240, 238 taste_description = "sourness" reagent_weight = 0.6 //so it sprays further + penetrates_skin = NONE var/clean_types = CLEAN_WASH -/datum/reagent/space_cleaner/expose_obj(obj/O, reac_volume) - O?.wash(clean_types) +/datum/reagent/space_cleaner/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + exposed_obj?.wash(clean_types) -/datum/reagent/space_cleaner/expose_turf(turf/T, reac_volume) - if(reac_volume >= 1) - T.wash(clean_types) - for(var/am in T) - var/atom/movable/movable_content = am - if(ismopable(movable_content)) // Mopables will be cleaned anyways by the turf wash - continue - movable_content.wash(clean_types) +/datum/reagent/space_cleaner/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if(reac_volume < 1) + return - for(var/mob/living/simple_animal/slime/M in T) - M.adjustToxLoss(rand(5,10)) + exposed_turf.wash(clean_types) + for(var/am in exposed_turf) + var/atom/movable/movable_content = am + if(ismopable(movable_content)) // Mopables will be cleaned anyways by the turf wash + continue + movable_content.wash(clean_types) -/datum/reagent/space_cleaner/expose_mob(mob/living/M, methods=TOUCH, reac_volume) + for(var/mob/living/simple_animal/slime/exposed_slime in exposed_turf) + exposed_slime.adjustToxLoss(rand(5,10)) + +/datum/reagent/space_cleaner/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=0) + . = ..() if(methods & (TOUCH|VAPOR)) - M.wash(clean_types) + exposed_mob.wash(clean_types) /datum/reagent/space_cleaner/ez_clean name = "EZ Clean" description = "A powerful, acidic cleaner sold by Waffle Co. Affects organic matter while leaving other objects unaffected." metabolization_rate = 1.5 * REAGENTS_METABOLISM taste_description = "acid" + penetrates_skin = VAPOR /datum/reagent/space_cleaner/ez_clean/on_mob_life(mob/living/carbon/M) M.adjustBruteLoss(3.33) @@ -1100,11 +1123,11 @@ M.adjustToxLoss(3.33) ..() -/datum/reagent/space_cleaner/ez_clean/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - ..() - if((methods & (TOUCH|VAPOR)) && !issilicon(M)) - M.adjustBruteLoss(1.5) - M.adjustFireLoss(1.5) +/datum/reagent/space_cleaner/ez_clean/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if((methods & (TOUCH|VAPOR)) && !issilicon(exposed_mob)) + exposed_mob.adjustBruteLoss(1.5) + exposed_mob.adjustFireLoss(1.5) /datum/reagent/cryptobiolin name = "Cryptobiolin" @@ -1140,10 +1163,12 @@ color = "#535E66" // rgb: 83, 94, 102 can_synth = FALSE taste_description = "sludge" + penetrates_skin = NONE -/datum/reagent/nanomachines/expose_mob(mob/living/L, methods=TOUCH, reac_volume, show_message = 1, touch_protection = 0) +/datum/reagent/nanomachines/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) + . = ..() if((methods & (PATCH|INGEST|INJECT)) || ((methods & VAPOR) && prob(min(reac_volume,100)*(1 - touch_protection)))) - L.ForceContractDisease(new /datum/disease/transformation/robot(), FALSE, TRUE) + exposed_mob.ForceContractDisease(new /datum/disease/transformation/robot(), FALSE, TRUE) /datum/reagent/xenomicrobes name = "Xenomicrobes" @@ -1151,10 +1176,12 @@ color = "#535E66" // rgb: 83, 94, 102 can_synth = FALSE taste_description = "sludge" + penetrates_skin = NONE -/datum/reagent/xenomicrobes/expose_mob(mob/living/L, methods=TOUCH, reac_volume, show_message = 1, touch_protection = 0) +/datum/reagent/xenomicrobes/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) + . = ..() if((methods & (PATCH|INGEST|INJECT)) || ((methods & VAPOR) && prob(min(reac_volume,100)*(1 - touch_protection)))) - L.ForceContractDisease(new /datum/disease/transformation/xeno(), FALSE, TRUE) + exposed_mob.ForceContractDisease(new /datum/disease/transformation/xeno(), FALSE, TRUE) /datum/reagent/fungalspores name = "Tubercle bacillus Cosmosis microbes" @@ -1162,10 +1189,12 @@ color = "#92D17D" // rgb: 146, 209, 125 can_synth = FALSE taste_description = "slime" + penetrates_skin = NONE -/datum/reagent/fungalspores/expose_mob(mob/living/L, methods=TOUCH, reac_volume, show_message = 1, touch_protection = 0) +/datum/reagent/fungalspores/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) + . = ..() if((methods & (PATCH|INGEST|INJECT)) || ((methods & VAPOR) && prob(min(reac_volume,100)*(1 - touch_protection)))) - L.ForceContractDisease(new /datum/disease/tuberculosis(), FALSE, TRUE) + exposed_mob.ForceContractDisease(new /datum/disease/tuberculosis(), FALSE, TRUE) /datum/reagent/snail name = "Agent-S" @@ -1173,10 +1202,12 @@ color = "#003300" // rgb(0, 51, 0) taste_description = "goo" can_synth = FALSE //special orange man request + penetrates_skin = NONE -/datum/reagent/snail/expose_mob(mob/living/L, methods=TOUCH, reac_volume, show_message = 1, touch_protection = 0) +/datum/reagent/snail/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) + . = ..() if((methods & (PATCH|INGEST|INJECT)) || ((methods & VAPOR) && prob(min(reac_volume,100)*(1 - touch_protection)))) - L.ForceContractDisease(new /datum/disease/gastrolosis(), FALSE, TRUE) + exposed_mob.ForceContractDisease(new /datum/disease/gastrolosis(), FALSE, TRUE) /datum/reagent/fluorosurfactant//foam precursor name = "Fluorosurfactant" @@ -1237,17 +1268,18 @@ color = "#B0B0B0" // rgb : 192, 192, 192 taste_description = "something unknowable" -/datum/reagent/carbondioxide/expose_obj(obj/O, reac_volume) - if((!O) || (!reac_volume)) +/datum/reagent/carbondioxide/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + if((!exposed_obj) || (!reac_volume)) return 0 var/temp = holder ? holder.chem_temp : T20C - O.atmos_spawn_air("co2=[reac_volume/5];TEMP=[temp]") + exposed_obj.atmos_spawn_air("co2=[reac_volume/5];TEMP=[temp]") -/datum/reagent/carbondioxide/expose_turf(turf/open/T, reac_volume) - if(istype(T)) +/datum/reagent/carbondioxide/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(istype(exposed_turf)) var/temp = holder ? holder.chem_temp : T20C - T.atmos_spawn_air("co2=[reac_volume/5];TEMP=[temp]") - return + exposed_turf.atmos_spawn_air("co2=[reac_volume/5];TEMP=[temp]") /datum/reagent/nitrous_oxide name = "Nitrous Oxide" @@ -1257,20 +1289,23 @@ color = "#808080" taste_description = "sweetness" -/datum/reagent/nitrous_oxide/expose_obj(obj/O, reac_volume) - if((!O) || (!reac_volume)) +/datum/reagent/nitrous_oxide/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + if((!exposed_obj) || (!reac_volume)) return 0 var/temp = holder ? holder.chem_temp : T20C - O.atmos_spawn_air("n2o=[reac_volume/5];TEMP=[temp]") + exposed_obj.atmos_spawn_air("n2o=[reac_volume/5];TEMP=[temp]") -/datum/reagent/nitrous_oxide/expose_turf(turf/open/T, reac_volume) - if(istype(T)) +/datum/reagent/nitrous_oxide/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(istype(exposed_turf)) var/temp = holder ? holder.chem_temp : T20C - T.atmos_spawn_air("n2o=[reac_volume/5];TEMP=[temp]") + exposed_turf.atmos_spawn_air("n2o=[reac_volume/5];TEMP=[temp]") -/datum/reagent/nitrous_oxide/expose_mob(mob/living/M, methods=TOUCH, reac_volume) +/datum/reagent/nitrous_oxide/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() if(methods & VAPOR) - M.drowsyness += max(round(reac_volume, 1), 2) + exposed_mob.drowsyness += max(round(reac_volume, 1), 2) /datum/reagent/nitrous_oxide/on_mob_life(mob/living/carbon/M) M.drowsyness += 2 @@ -1581,10 +1616,10 @@ taste_description = "carpet" // Your tounge feels furry. var/carpet_type = /turf/open/floor/carpet -/datum/reagent/carpet/expose_turf(turf/T, reac_volume) - if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) - var/turf/open/floor/F = T - F.PlaceOnTop(carpet_type, flags = CHANGETURF_INHERIT_AIR) +/datum/reagent/carpet/expose_turf(turf/exposed_turf, reac_volume) + if(isplatingturf(exposed_turf) || istype(exposed_turf, /turf/open/floor/plasteel)) + var/turf/open/floor/target_floor = exposed_turf + target_floor.PlaceOnTop(carpet_type, flags = CHANGETURF_INHERIT_AIR) ..() /datum/reagent/carpet/black @@ -1697,13 +1732,11 @@ taste_description = "acid" -/datum/reagent/acetone_oxide/expose_mob(mob/living/M, methods=TOUCH, reac_volume)//Splashing people kills people! - if(!istype(M)) - return +/datum/reagent/acetone_oxide/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)//Splashing people kills people! + . = ..() if(methods & TOUCH) - M.adjustFireLoss(2, FALSE) // burns, - M.adjust_fire_stacks((reac_volume / 10)) - ..() + exposed_mob.adjustFireLoss(2, FALSE) // burns, + exposed_mob.adjust_fire_stacks((reac_volume / 10)) @@ -1757,10 +1790,10 @@ return ..() /// Colors anything it touches a random color. -/datum/reagent/colorful_reagent/expose_atom(mob/living/M, reac_volume) - if(can_colour_mobs) - M.add_atom_colour(pick(random_color_list), WASHABLE_COLOUR_PRIORITY) - ..() +/datum/reagent/colorful_reagent/expose_atom(atom/exposed_atom, reac_volume) + . = ..() + if(!isliving(exposed_atom) || can_colour_mobs) + exposed_atom.add_atom_colour(pick(random_color_list), WASHABLE_COLOUR_PRIORITY) /datum/reagent/hair_dye name = "Quantum Hair Dye" @@ -1769,6 +1802,7 @@ var/list/potential_colors = list("0ad","a0f","f73","d14","d14","0b5","0ad","f73","fc2","084","05e","d22","fa0") // fucking hair code color = "#C8A5DC" taste_description = "sourness" + penetrates_skin = NONE /datum/reagent/hair_dye/New() SSticker.OnRoundstart(CALLBACK(src,.proc/UpdateColor)) @@ -1777,13 +1811,15 @@ /datum/reagent/hair_dye/proc/UpdateColor() color = pick(potential_colors) -/datum/reagent/hair_dye/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(methods & (TOUCH|VAPOR)) - if(M && ishuman(M)) - var/mob/living/carbon/human/H = M - H.hair_color = pick(potential_colors) - H.facial_hair_color = pick(potential_colors) - H.update_hair() +/datum/reagent/hair_dye/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=FALSE) + . = ..() + if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob)) + return + + var/mob/living/carbon/human/exposed_human = exposed_mob + exposed_human.hair_color = pick(potential_colors) + exposed_human.facial_hair_color = pick(potential_colors) + exposed_human.update_hair() /datum/reagent/barbers_aid name = "Barber's Aid" @@ -1791,16 +1827,20 @@ reagent_state = LIQUID color = "#A86B45" //hair is brown taste_description = "sourness" + penetrates_skin = NONE -/datum/reagent/barbers_aid/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if((methods & (TOUCH|VAPOR)) && ishuman(M) && !HAS_TRAIT(M, TRAIT_BALD)) - var/mob/living/carbon/human/exposed_human = M - var/datum/sprite_accessory/hair/picked_hair = pick(GLOB.hairstyles_list) - var/datum/sprite_accessory/facial_hair/picked_beard = pick(GLOB.facial_hairstyles_list) - to_chat(exposed_human, "Hair starts sprouting from your scalp.") - exposed_human.hairstyle = picked_hair - exposed_human.facial_hairstyle = picked_beard - exposed_human.update_hair() +/datum/reagent/barbers_aid/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=FALSE) + . = ..() + if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob) || HAS_TRAIT(exposed_mob, TRAIT_BALD)) + return + + var/mob/living/carbon/human/exposed_human = exposed_mob + var/datum/sprite_accessory/hair/picked_hair = pick(GLOB.hairstyles_list) + var/datum/sprite_accessory/facial_hair/picked_beard = pick(GLOB.facial_hairstyles_list) + to_chat(exposed_human, "Hair starts sprouting from your scalp.") + exposed_human.hairstyle = picked_hair + exposed_human.facial_hairstyle = picked_beard + exposed_human.update_hair() /datum/reagent/concentrated_barbers_aid name = "Concentrated Barber's Aid" @@ -1808,15 +1848,18 @@ reagent_state = LIQUID color = "#7A4E33" //hair is dark browmn taste_description = "sourness" + penetrates_skin = NONE -/datum/reagent/concentrated_barbers_aid/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(methods & (TOUCH|VAPOR)) - if(M && ishuman(M) && !HAS_TRAIT(M, TRAIT_BALD)) - var/mob/living/carbon/human/H = M - to_chat(H, "Your hair starts growing at an incredible speed!") - H.hairstyle = "Very Long Hair" - H.facial_hairstyle = "Beard (Very Long)" - H.update_hair() +/datum/reagent/concentrated_barbers_aid/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=FALSE) + . = ..() + if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob) || HAS_TRAIT(exposed_mob, TRAIT_BALD)) + return + + var/mob/living/carbon/human/exposed_human = exposed_mob + to_chat(exposed_human, "Your hair starts growing at an incredible speed!") + exposed_human.hairstyle = "Very Long Hair" + exposed_human.facial_hairstyle = "Beard (Very Long)" + exposed_human.update_hair() /datum/reagent/baldium name = "Baldium" @@ -1824,14 +1867,18 @@ reagent_state = LIQUID color = "#ecb2cf" taste_description = "bitterness" + penetrates_skin = NONE -/datum/reagent/baldium/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if((methods & (TOUCH|VAPOR)) && ishuman(M)) - var/mob/living/carbon/human/exposed_human = M - to_chat(exposed_human, "Your hair is falling out in clumps!") - exposed_human.hairstyle = "Bald" - exposed_human.facial_hairstyle = "Shaved" - exposed_human.update_hair() +/datum/reagent/baldium/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=FALSE) + . = ..() + if(!(methods & (TOUCH|VAPOR)) || !ishuman(exposed_mob)) + return + + var/mob/living/carbon/human/exposed_human = exposed_mob + to_chat(exposed_human, "Your hair is falling out in clumps!") + exposed_human.hairstyle = "Bald" + exposed_human.facial_hairstyle = "Shaved" + exposed_human.update_hair() /datum/reagent/saltpetre name = "Saltpetre" @@ -1864,15 +1911,19 @@ color = "#A70FFF" taste_description = "dryness" -/datum/reagent/drying_agent/expose_turf(turf/open/T, reac_volume) - if(istype(T)) - T.MakeDry(ALL, TRUE, reac_volume * 5 SECONDS) //50 deciseconds per unit +/datum/reagent/drying_agent/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(!istype(exposed_turf)) + return + exposed_turf.MakeDry(ALL, TRUE, reac_volume * 5 SECONDS) //50 deciseconds per unit -/datum/reagent/drying_agent/expose_obj(obj/O, reac_volume) - if(O.type == /obj/item/clothing/shoes/galoshes) - var/t_loc = get_turf(O) - qdel(O) - new /obj/item/clothing/shoes/galoshes/dry(t_loc) +/datum/reagent/drying_agent/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + if(exposed_obj.type != /obj/item/clothing/shoes/galoshes) + return + var/t_loc = get_turf(exposed_obj) + qdel(exposed_obj) + new /obj/item/clothing/shoes/galoshes/dry(t_loc) // Virology virus food chems. @@ -1946,12 +1997,12 @@ can_synth = FALSE taste_description = "brains" -/datum/reagent/romerol/expose_mob(mob/living/carbon/human/H, methods=TOUCH, reac_volume) +/datum/reagent/romerol/expose_mob(mob/living/carbon/human/exposed_mob, methods=TOUCH, reac_volume) + . = ..() // Silently add the zombie infection organ to be activated upon death - if(!H.getorganslot(ORGAN_SLOT_ZOMBIE)) + if(!exposed_mob.getorganslot(ORGAN_SLOT_ZOMBIE)) var/obj/item/organ/zombie_infection/nodamage/ZI = new() - ZI.Insert(H) - ..() + ZI.Insert(exposed_mob) /datum/reagent/magillitis name = "Magillitis" @@ -2010,10 +2061,11 @@ reagent_state = SOLID var/glitter_type = /obj/effect/decal/cleanable/glitter -/datum/reagent/glitter/expose_turf(turf/T, reac_volume) - if(!istype(T)) +/datum/reagent/glitter/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if(!istype(exposed_turf)) return - new glitter_type(T) + new glitter_type(exposed_turf) /datum/reagent/glitter/pink name = "pink glitter" @@ -2114,10 +2166,12 @@ color = "#9A6750" //RGB: 154, 103, 80 taste_description = "inner peace" can_synth = FALSE + penetrates_skin = NONE -/datum/reagent/tranquility/expose_mob(mob/living/L, methods=TOUCH, reac_volume, show_message = 1, touch_protection = 0) +/datum/reagent/tranquility/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message = TRUE, touch_protection = 0) + . = ..() if((methods & (PATCH|INGEST|INJECT)) || ((methods & VAPOR) && prob(min(reac_volume,100)*(1 - touch_protection)))) - L.ForceContractDisease(new /datum/disease/transformation/gondola(), FALSE, TRUE) + exposed_mob.ForceContractDisease(new /datum/disease/transformation/gondola(), FALSE, TRUE) /datum/reagent/spider_extract @@ -2214,13 +2268,13 @@ var/applied_material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR var/minumum_material_amount = 100 -/datum/reagent/metalgen/expose_obj(obj/O, volume) - metal_morph(O) - return +/datum/reagent/metalgen/expose_obj(obj/exposed_obj, volume) + . = ..() + metal_morph(exposed_obj) -/datum/reagent/metalgen/expose_turf(turf/T, volume) - metal_morph(T) - return +/datum/reagent/metalgen/expose_turf(turf/exposed_turf, volume) + . = ..() + metal_morph(exposed_turf) ///turn an object into a special material /datum/reagent/metalgen/proc/metal_morph(atom/A) @@ -2249,10 +2303,10 @@ metabolization_rate = 0.1 * REAGENTS_METABOLISM //20 times as long, so it's actually viable to use var/time_multiplier = 1 MINUTES //1 minute per unit of gravitum on objects. Seems overpowered, but the whole thing is very niche -/datum/reagent/gravitum/expose_obj(obj/O, volume) - O.AddElement(/datum/element/forced_gravity, 0) - - addtimer(CALLBACK(O, .proc/_RemoveElement, list(/datum/element/forced_gravity, 0)), volume * time_multiplier) +/datum/reagent/gravitum/expose_obj(obj/exposed_obj, volume) + . = ..() + exposed_obj.AddElement(/datum/element/forced_gravity, 0) + addtimer(CALLBACK(exposed_obj, .proc/_RemoveElement, list(/datum/element/forced_gravity, 0)), volume * time_multiplier) /datum/reagent/gravitum/on_mob_add(mob/living/L) L.AddElement(/datum/element/forced_gravity, 0) //0 is the gravity, and in this case weightless diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm index f4125263d55..bb48951d06f 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm @@ -6,9 +6,10 @@ color = "#550000" taste_description = "sweet tasting metal" -/datum/reagent/thermite/expose_turf(turf/T, reac_volume) +/datum/reagent/thermite/expose_turf(turf/exposed_turf, reac_volume) + . = ..() if(reac_volume >= 1) - T.AddComponent(/datum/component/thermite, reac_volume) + exposed_turf.AddComponent(/datum/component/thermite, reac_volume) /datum/reagent/thermite/on_mob_life(mob/living/carbon/M) M.adjustFireLoss(1, 0) @@ -41,6 +42,7 @@ color = "#FFC8C8" metabolization_rate = 4 taste_description = "burning" + penetrates_skin = NONE /datum/reagent/clf3/on_mob_life(mob/living/carbon/M) M.adjust_fire_stacks(2) @@ -49,33 +51,33 @@ ..() return TRUE -/datum/reagent/clf3/expose_turf(turf/T, reac_volume) - if(isplatingturf(T)) - var/turf/open/floor/plating/F = T - if(prob(10 + F.burnt + 5*F.broken)) //broken or burnt plating is more susceptible to being destroyed - F.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) - if(isfloorturf(T)) - var/turf/open/floor/F = T +/datum/reagent/clf3/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if(isplatingturf(exposed_turf)) + var/turf/open/floor/plating/target_plating = exposed_turf + if(prob(10 + target_plating.burnt + 5*target_plating.broken)) //broken or burnt plating is more susceptible to being destroyed + target_plating.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) + if(isfloorturf(exposed_turf)) + var/turf/open/floor/target_floor = exposed_turf if(prob(reac_volume)) - F.make_plating() + target_floor.make_plating() else if(prob(reac_volume)) - F.burn_tile() - if(isfloorturf(F)) - for(var/turf/turf in range(1,F)) - if(!locate(/obj/effect/hotspot) in turf) - new /obj/effect/hotspot(F) - if(iswallturf(T)) - var/turf/closed/wall/W = T + target_floor.burn_tile() + if(isfloorturf(target_floor)) + for(var/turf/nearby_turf in range(1, target_floor)) + if(!locate(/obj/effect/hotspot) in nearby_turf) + new /obj/effect/hotspot(nearby_turf) + if(iswallturf(exposed_turf)) + var/turf/closed/wall/target_wall = exposed_turf if(prob(reac_volume)) - W.ScrapeAway() + target_wall.ScrapeAway() -/datum/reagent/clf3/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(istype(M)) - if(methods & (TOUCH|VAPOR|PATCH)) - M.adjust_fire_stacks(min(reac_volume/5, 10)) - M.IgniteMob() - if(!locate(/obj/effect/hotspot) in M.loc) - new /obj/effect/hotspot(M.loc) +/datum/reagent/clf3/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + exposed_mob.adjust_fire_stacks(min(reac_volume/5, 10)) + exposed_mob.IgniteMob() + if(!locate(/obj/effect/hotspot) in exposed_mob.loc) + new /obj/effect/hotspot(exposed_mob.loc) /datum/reagent/sorium name = "Sorium" @@ -158,17 +160,17 @@ taste_description = "burning" self_consuming = TRUE -/datum/reagent/phlogiston/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - M.adjust_fire_stacks(1) - var/burndmg = max(0.3*M.fire_stacks, 0.3) - M.adjustFireLoss(burndmg, 0) - M.IgniteMob() - ..() +/datum/reagent/phlogiston/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + exposed_mob.adjust_fire_stacks(1) + var/burndmg = max(0.3*exposed_mob.fire_stacks, 0.3) + exposed_mob.adjustFireLoss(burndmg, 0) + exposed_mob.IgniteMob() -/datum/reagent/phlogiston/on_mob_life(mob/living/carbon/M) - M.adjust_fire_stacks(1) - var/burndmg = max(0.3*M.fire_stacks, 0.3) - M.adjustFireLoss(burndmg, 0) +/datum/reagent/phlogiston/on_mob_life(mob/living/carbon/exposed_mob) + exposed_mob.adjust_fire_stacks(1) + var/burndmg = max(0.3*exposed_mob.fire_stacks, 0.3) + exposed_mob.adjustFireLoss(burndmg, 0) ..() return TRUE @@ -179,6 +181,7 @@ color = "#FA00AF" taste_description = "burning" self_consuming = TRUE + penetrates_skin = NONE // why, just why /datum/reagent/napalm/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray, mob/user) @@ -193,10 +196,10 @@ M.adjust_fire_stacks(1) ..() -/datum/reagent/napalm/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(istype(M)) - if(methods & (TOUCH|VAPOR|PATCH)) - M.adjust_fire_stacks(min(reac_volume/4, 20)) +/datum/reagent/napalm/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(istype(exposed_mob) && (methods & (TOUCH|VAPOR|PATCH))) + exposed_mob.adjust_fire_stacks(min(reac_volume/4, 20)) /datum/reagent/cryostylane name = "Cryostylane" @@ -213,10 +216,12 @@ M.adjust_bodytemperature(-15) ..() -/datum/reagent/cryostylane/expose_turf(turf/T, reac_volume) - if(reac_volume >= 5) - for(var/mob/living/simple_animal/slime/M in T) - M.adjustToxLoss(rand(15,30)) +/datum/reagent/cryostylane/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if(reac_volume < 5) + return + for(var/mob/living/simple_animal/slime/exposed_slime in exposed_turf) + exposed_slime.adjustToxLoss(rand(15,30)) /datum/reagent/pyrosium name = "Pyrosium" @@ -287,30 +292,31 @@ color = "#A6FAFF55" taste_description = "the inside of a fire extinguisher" -/datum/reagent/firefighting_foam/expose_turf(turf/open/T, reac_volume) - if (!istype(T)) +/datum/reagent/firefighting_foam/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if (!istype(exposed_turf)) return if(reac_volume >= 1) - var/obj/effect/particle_effect/foam/firefighting/F = (locate(/obj/effect/particle_effect/foam) in T) - if(!F) - F = new(T) - else if(istype(F)) - F.lifetime = initial(F.lifetime) //reduce object churn a little bit when using smoke by keeping existing foam alive a bit longer + var/obj/effect/particle_effect/foam/firefighting/foam = (locate(/obj/effect/particle_effect/foam) in exposed_turf) + if(!foam) + foam = new(exposed_turf) + else if(istype(foam)) + foam.lifetime = initial(foam.lifetime) //reduce object churn a little bit when using smoke by keeping existing foam alive a bit longer - var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T) - if(hotspot && !isspaceturf(T)) - if(T.air) - var/datum/gas_mixture/G = T.air - if(G.temperature > T20C) - G.temperature = max(G.temperature/2,T20C) - G.react(src) - qdel(hotspot) + var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in exposed_turf) + if(hotspot && !isspaceturf(exposed_turf) && exposed_turf.air) + var/datum/gas_mixture/air = exposed_turf.air + if(air.temperature > T20C) + air.temperature = max(air.temperature/2,T20C) + air.react(src) + qdel(hotspot) -/datum/reagent/firefighting_foam/expose_obj(obj/O, reac_volume) - O.extinguish() +/datum/reagent/firefighting_foam/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + exposed_obj.extinguish() -/datum/reagent/firefighting_foam/expose_mob(mob/living/M, methods=TOUCH, reac_volume) +/datum/reagent/firefighting_foam/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() if(methods & (TOUCH|VAPOR)) - M.extinguish_mob() //All stacks are removed - ..() + exposed_mob.extinguish_mob() //All stacks are removed diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 4da66edc3c0..32db835f22d 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -38,20 +38,18 @@ taste_description = "slime" taste_mult = 0.9 -/datum/reagent/toxin/mutagen/expose_mob(mob/living/carbon/M, methods=TOUCH, reac_volume) - if(!..()) - return - if(!M.has_dna() || HAS_TRAIT(M, TRAIT_GENELESS) || HAS_TRAIT(M, TRAIT_BADDNA)) +/datum/reagent/toxin/mutagen/expose_mob(mob/living/carbon/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(!. || !exposed_mob.has_dna() || HAS_TRAIT(exposed_mob, TRAIT_GENELESS) || HAS_TRAIT(exposed_mob, TRAIT_BADDNA)) return //No robots, AIs, aliens, Ians or other mobs should be affected by this. if(((methods & VAPOR) && prob(min(33, reac_volume))) || (methods & (INGEST|PATCH|INJECT))) - M.randmuti() + exposed_mob.randmuti() if(prob(98)) - M.easy_randmut(NEGATIVE+MINOR_NEGATIVE) + exposed_mob.easy_randmut(NEGATIVE+MINOR_NEGATIVE) else - M.easy_randmut(POSITIVE) - M.updateappearance() - M.domutcheck() - ..() + exposed_mob.easy_randmut(POSITIVE) + exposed_mob.updateappearance() + exposed_mob.domutcheck() /datum/reagent/toxin/mutagen/on_mob_life(mob/living/carbon/C) C.apply_effect(5,EFFECT_IRRADIATE,0) @@ -73,6 +71,7 @@ color = "#8228A0" toxpwr = 3 material = /datum/material/plasma + penetrates_skin = NONE /datum/reagent/toxin/plasma/on_mob_life(mob/living/carbon/C) if(holder.has_reagent(/datum/reagent/medicine/epinephrine)) @@ -88,25 +87,27 @@ A.atmos_spawn_air("plasma=[volume];TEMP=[holder.chem_temp]") holder.del_reagent(type) -/datum/reagent/toxin/plasma/expose_obj(obj/O, reac_volume) - if((!O) || (!reac_volume)) +/datum/reagent/toxin/plasma/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + if((!exposed_obj) || (!reac_volume)) return 0 var/temp = holder ? holder.chem_temp : T20C if(temp >= LIQUID_PLASMA_BP) - O.atmos_spawn_air("plasma=[reac_volume];TEMP=[temp]") + exposed_obj.atmos_spawn_air("plasma=[reac_volume];TEMP=[temp]") -/datum/reagent/toxin/plasma/expose_turf(turf/open/T, reac_volume) - if(!istype(T)) +/datum/reagent/toxin/plasma/expose_turf(turf/open/exposed_turf, reac_volume) + . = ..() + if(!istype(exposed_turf)) return var/temp = holder ? holder.chem_temp : T20C if(temp >= LIQUID_PLASMA_BP) - T.atmos_spawn_air("plasma=[reac_volume];TEMP=[temp]") + exposed_turf.atmos_spawn_air("plasma=[reac_volume];TEMP=[temp]") -/datum/reagent/toxin/plasma/expose_mob(mob/living/M, methods=TOUCH, reac_volume)//Splashing people with plasma is stronger than fuel! +/datum/reagent/toxin/plasma/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume)//Splashing people with plasma is stronger than fuel! + . = ..() if(methods & (TOUCH|VAPOR)) - M.adjust_fire_stacks(reac_volume / 5) + exposed_mob.adjust_fire_stacks(reac_volume / 5) return - ..() /datum/reagent/toxin/hot_ice name = "Hot Ice Slush" @@ -196,6 +197,7 @@ color = "#669900" // rgb: 102, 153, 0 toxpwr = 0.5 taste_description = "death" + penetrates_skin = NONE var/fakedeath_active = FALSE /datum/reagent/toxin/zombiepowder/on_mob_metabolize(mob/living/L) @@ -208,12 +210,13 @@ L.cure_fakedeath(type) ..() -/datum/reagent/toxin/zombiepowder/expose_mob(mob/living/L, methods=TOUCH, reac_volume) - L.adjustOxyLoss(0.5*REM, 0) +/datum/reagent/toxin/zombiepowder/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + exposed_mob.adjustOxyLoss(0.5*REM, 0) if(methods & INGEST) - var/datum/reagent/toxin/zombiepowder/Z = L.reagents.has_reagent(/datum/reagent/toxin/zombiepowder) - if(istype(Z)) - Z.fakedeath_active = TRUE + var/datum/reagent/toxin/zombiepowder/zombiepowder = exposed_mob.reagents.has_reagent(/datum/reagent/toxin/zombiepowder) + if(istype(zombiepowder)) + zombiepowder.fakedeath_active = TRUE /datum/reagent/toxin/zombiepowder/on_mob_life(mob/living/M) ..() @@ -268,6 +271,7 @@ color = "#49002E" // rgb: 73, 0, 46 toxpwr = 1 taste_mult = 1 + penetrates_skin = NONE // Plant-B-Gone is just as bad /datum/reagent/toxin/plantbgone/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray, mob/user) @@ -277,21 +281,24 @@ mytray.adjustToxic(round(chems.get_reagent_amount(type) * 6)) mytray.adjustWeeds(-rand(4,8)) -/datum/reagent/toxin/plantbgone/expose_obj(obj/O, reac_volume) - if(istype(O, /obj/structure/alien/weeds)) - var/obj/structure/alien/weeds/alien_weeds = O +/datum/reagent/toxin/plantbgone/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + if(istype(exposed_obj, /obj/structure/alien/weeds)) + var/obj/structure/alien/weeds/alien_weeds = exposed_obj alien_weeds.take_damage(rand(15,35), BRUTE, 0) // Kills alien weeds pretty fast - else if(istype(O, /obj/structure/glowshroom)) //even a small amount is enough to kill it - qdel(O) - else if(istype(O, /obj/structure/spacevine)) - var/obj/structure/spacevine/SV = O + else if(istype(exposed_obj, /obj/structure/glowshroom)) //even a small amount is enough to kill it + qdel(exposed_obj) + else if(istype(exposed_obj, /obj/structure/spacevine)) + var/obj/structure/spacevine/SV = exposed_obj SV.on_chem_effect(src) -/datum/reagent/toxin/plantbgone/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if((methods & VAPOR) && iscarbon(M)) - var/mob/living/carbon/exposed_carbon = M - if(!exposed_carbon.wear_mask) - exposed_carbon.adjustToxLoss(min(round(0.4 * reac_volume, 0.1), 10)) +/datum/reagent/toxin/plantbgone/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(!(methods & VAPOR) || !iscarbon(exposed_mob)) + return + var/mob/living/carbon/exposed_carbon = exposed_mob + if(!exposed_carbon.wear_mask) + exposed_carbon.adjustToxLoss(min(round(0.4 * reac_volume, 0.1), 10)) /datum/reagent/toxin/plantbgone/weedkiller name = "Weed Killer" @@ -320,11 +327,11 @@ mytray.adjustToxic(round(chems.get_reagent_amount(type) * 1)) mytray.adjustPests(-rand(1,2)) -/datum/reagent/toxin/pestkiller/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - ..() - if(M.mob_biotypes & MOB_BUG) +/datum/reagent/toxin/pestkiller/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume) + . = ..() + if(exposed_mob.mob_biotypes & MOB_BUG) var/damage = min(round(0.4*reac_volume, 0.1),10) - M.adjustToxLoss(damage) + exposed_mob.adjustToxLoss(damage) /datum/reagent/toxin/pestkiller/organic name = "Natural Pest Killer" @@ -580,10 +587,7 @@ color = "#C8C8C8" metabolization_rate = 0.4 * REAGENTS_METABOLISM toxpwr = 0 - -/datum/reagent/toxin/itching_powder/expose_mob(mob/living/M, methods=TOUCH, reac_volume) - if(methods & (TOUCH|VAPOR)) - M.reagents?.add_reagent(/datum/reagent/toxin/itching_powder, reac_volume) + penetrates_skin = TOUCH|VAPOR /datum/reagent/toxin/itching_powder/on_mob_life(mob/living/carbon/M) if(prob(15)) @@ -839,29 +843,32 @@ mytray.adjustToxic(round(chems.get_reagent_amount(type) * 1.5)) mytray.adjustWeeds(-rand(1,2)) -/datum/reagent/toxin/acid/expose_mob(mob/living/carbon/C, methods=TOUCH, reac_volume) - if(!istype(C)) +/datum/reagent/toxin/acid/expose_mob(mob/living/carbon/exposed_carbon, methods=TOUCH, reac_volume) + . = ..() + if(!istype(exposed_carbon)) return reac_volume = round(reac_volume,0.1) if(methods & INGEST) - C.adjustBruteLoss(min(6*toxpwr, reac_volume * toxpwr)) + exposed_carbon.adjustBruteLoss(min(6*toxpwr, reac_volume * toxpwr)) return if(methods & INJECT) - C.adjustBruteLoss(1.5 * min(6*toxpwr, reac_volume * toxpwr)) + exposed_carbon.adjustBruteLoss(1.5 * min(6*toxpwr, reac_volume * toxpwr)) return - C.acid_act(acidpwr, reac_volume) + exposed_carbon.acid_act(acidpwr, reac_volume) -/datum/reagent/toxin/acid/expose_obj(obj/O, reac_volume) - if(ismob(O.loc)) //handled in human acid_act() +/datum/reagent/toxin/acid/expose_obj(obj/exposed_obj, reac_volume) + . = ..() + if(ismob(exposed_obj.loc)) //handled in human acid_act() return reac_volume = round(reac_volume,0.1) - O.acid_act(acidpwr, reac_volume) + exposed_obj.acid_act(acidpwr, reac_volume) -/datum/reagent/toxin/acid/expose_turf(turf/T, reac_volume) - if (!istype(T)) +/datum/reagent/toxin/acid/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + if (!istype(exposed_turf)) return reac_volume = round(reac_volume,0.1) - T.acid_act(acidpwr, reac_volume) + exposed_turf.acid_act(acidpwr, reac_volume) /datum/reagent/toxin/acid/fluacid name = "Fluorosulfuric acid" diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index e7e1e04a414..711f68c6a23 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -597,7 +597,7 @@ var/obj/O = owner.get_active_held_item() if(O) O.extinguish() //All shamelessly copied from water's expose_obj, since I didn't seem to be able to get it here for some reason. - O.acid_level = 0 + O.wash(CLEAN_TYPE_ACID) // Monkey cube if(istype(O, /obj/item/reagent_containers/food/snacks/monkeycube)) to_chat(owner, "[linked_extract] kept your hands wet! It makes [O] expand!") diff --git a/icons/effects/acid.dmi b/icons/effects/acid.dmi new file mode 100644 index 00000000000..284df8e536f Binary files /dev/null and b/icons/effects/acid.dmi differ diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index f306db41934..706cad3f5c8 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 2cfb0f0c635..8f44e450acd 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -23,6 +23,7 @@ #include "code\__DEFINES\_tick.dm" #include "code\__DEFINES\access.dm" #include "code\__DEFINES\achievements.dm" +#include "code\__DEFINES\acid.dm" #include "code\__DEFINES\actionspeed_modification.dm" #include "code\__DEFINES\admin.dm" #include "code\__DEFINES\antagonists.dm" @@ -259,7 +260,6 @@ #include "code\controllers\configuration\entries\general.dm" #include "code\controllers\configuration\entries\resources.dm" #include "code\controllers\subsystem\achievements.dm" -#include "code\controllers\subsystem\acid.dm" #include "code\controllers\subsystem\adjacent_air.dm" #include "code\controllers\subsystem\air.dm" #include "code\controllers\subsystem\assets.dm" @@ -322,6 +322,7 @@ #include "code\controllers\subsystem\vis_overlays.dm" #include "code\controllers\subsystem\vote.dm" #include "code\controllers\subsystem\weather.dm" +#include "code\controllers\subsystem\processing\acid.dm" #include "code\controllers\subsystem\processing\fastprocess.dm" #include "code\controllers\subsystem\processing\fields.dm" #include "code\controllers\subsystem\processing\fluids.dm" @@ -399,6 +400,7 @@ #include "code\datums\brain_damage\special.dm" #include "code\datums\brain_damage\split_personality.dm" #include "code\datums\components\_component.dm" +#include "code\datums\components\acid.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\areabound.dm" #include "code\datums\components\armor_plate.dm" @@ -602,6 +604,7 @@ #include "code\datums\keybinding\movement.dm" #include "code\datums\keybinding\robot.dm" #include "code\datums\looping_sounds\_looping_sound.dm" +#include "code\datums\looping_sounds\acid.dm" #include "code\datums\looping_sounds\item_sounds.dm" #include "code\datums\looping_sounds\machinery_sounds.dm" #include "code\datums\looping_sounds\weather.dm" @@ -892,7 +895,6 @@ #include "code\game\objects\obj_defense.dm" #include "code\game\objects\objs.dm" #include "code\game\objects\structures.dm" -#include "code\game\objects\effects\alien_acid.dm" #include "code\game\objects\effects\anomalies.dm" #include "code\game\objects\effects\blessing.dm" #include "code\game\objects\effects\bump_teleporter.dm"