diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm index 8ac15ebc53..0d06544a7e 100644 --- a/code/__defines/flags.dm +++ b/code/__defines/flags.dm @@ -34,6 +34,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define PHORONGUARD (1<<5) // Does not get contaminated by phoron. #define NOREACT (1<<6) // Reagents don't react inside this container. #define OVERLAY_QUEUED (1<<7)// Atom queued to SSoverlay for COMPILE_OVERLAYS +#define IS_BUSY (1<<8) // Atom has a TASK_TARGET_EXCLUSIVE do_after with it as the target. //Flags for items (equipment) - Used in /obj/item/var/item_flags #define THICKMATERIAL (1<<0) // Prevents syringes, parapens and hyposprays if equipped to slot_suit or slot_head. @@ -49,3 +50,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define PASSGRILLE (1<<2) #define PASSBLOB (1<<3) #define PASSMOB (1<<4) + +// Flags for do_after/do_mob exclusivity. +#define TASK_TARGET_EXCLUSIVE (1<<1) +#define TASK_USER_EXCLUSIVE (1<<2) +#define TASK_ALL_EXCLUSIVE TASK_TARGET_EXCLUSIVE | TASK_USER_EXCLUSIVE \ No newline at end of file diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index dc5c92f708..c9b37eae95 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -155,12 +155,15 @@ Proc for attack log creation, because really why not /proc/do_mob(mob/user , mob/target, time = 30, target_zone = 0, uninterruptible = FALSE, progress = TRUE, ignore_movement = FALSE, exclusive = FALSE) if(!user || !target) - return 0 + return FALSE if(!time) - return 1 //Done! + return TRUE //Done! if(user.status_flags & DOING_TASK) to_chat(user, "You're in the middle of doing something else already.") - return 0 //Performing an exclusive do_after or do_mob already + return FALSE //Performing an exclusive do_after or do_mob already + if(target?.flags & IS_BUSY) + to_chat(user, "Someone is already doing something with \the [target].") + return FALSE var/user_loc = user.loc var/target_loc = target.loc @@ -172,8 +175,10 @@ Proc for attack log creation, because really why not var/endtime = world.time+time var/starttime = world.time - if(exclusive) + if(exclusive & TASK_USER_EXCLUSIVE) user.status_flags |= DOING_TASK + if(target && exclusive & TASK_TARGET_EXCLUSIVE) + target.flags |= IS_BUSY . = TRUE while (world.time < endtime) @@ -206,20 +211,26 @@ Proc for attack log creation, because really why not . = FALSE break - if(exclusive) + if(exclusive & TASK_USER_EXCLUSIVE) user.status_flags &= ~DOING_TASK + if(exclusive & TASK_TARGET_EXCLUSIVE) + target?.status_flags &= ~IS_BUSY if (progbar) qdel(progbar) /proc/do_after(mob/user, delay, atom/target = null, needhand = TRUE, progress = TRUE, incapacitation_flags = INCAPACITATION_DEFAULT, ignore_movement = FALSE, max_distance = null, exclusive = FALSE) if(!user) - return 0 + return FALSE if(!delay) - return 1 //Okay. Done. + return TRUE //Okay. Done. if(user.status_flags & DOING_TASK) to_chat(user, "You're in the middle of doing something else already.") - return 0 //Performing an exclusive do_after or do_mob already + return FALSE //Performing an exclusive do_after or do_mob already + if(target?.flags & IS_BUSY) + to_chat(user, "Someone is already doing something with \the [target].") + return FALSE + var/atom/target_loc = null if(target) target_loc = target.loc @@ -241,10 +252,13 @@ Proc for attack log creation, because really why not var/endtime = world.time + delay var/starttime = world.time - if(exclusive) + if(exclusive & TASK_USER_EXCLUSIVE) user.status_flags |= DOING_TASK + + if(target && exclusive & TASK_TARGET_EXCLUSIVE) + target.flags |= IS_BUSY - . = 1 + . = TRUE while (world.time < endtime) stoplag(1) if(progress) @@ -280,8 +294,10 @@ Proc for attack log creation, because really why not . = FALSE break - if(exclusive) + if(exclusive & TASK_USER_EXCLUSIVE) user.status_flags &= ~DOING_TASK + if(target & exclusive & TASK_TARGET_EXCLUSIVE) + target.flags &= ~IS_BUSY if(progbar) qdel(progbar) diff --git a/code/game/objects/items/devices/denecrotizer_vr.dm b/code/game/objects/items/devices/denecrotizer_vr.dm index 7305a49e53..72a2022089 100644 --- a/code/game/objects/items/devices/denecrotizer_vr.dm +++ b/code/game/objects/items/devices/denecrotizer_vr.dm @@ -145,7 +145,7 @@ return FALSE if(!target.mind) user.visible_message("[user] gently presses [src] to [target]...", runemessage = "presses [src] to [target]") - if(do_after(user, revive_time, exclusive = 1, target = target)) + if(do_after(user, revive_time, exclusive = TASK_USER_EXCLUSIVE, target = target)) target.faction = user.faction target.revivedby = user.name target.ghostjoin = 1 @@ -166,7 +166,7 @@ /obj/item/device/denecrotizer/proc/ghostjoin_rez(mob/living/simple_mob/target, mob/living/user) user.visible_message("[user] gently presses [src] to [target]...", runemessage = "presses [src] to [target]") - if(do_after(user, revive_time, exclusive = 1, target = target)) + if(do_after(user, revive_time, exclusive = TASK_ALL_EXCLUSIVE, target = target)) target.faction = user.faction target.revivedby = user.name target.revive() @@ -189,7 +189,7 @@ /obj/item/device/denecrotizer/proc/basic_rez(mob/living/simple_mob/target, mob/living/user) //so medical can have a way to bring back people's pets or whatever, does not change any settings about the mob or offer it to ghosts. user.visible_message("[user] presses [src] to [target]...", runemessage = "presses [src] to [target]") - if(do_after(user, revive_time, exclusive = 1, target = target)) + if(do_after(user, revive_time, exclusive = TASK_ALL_EXCLUSIVE, target = target)) target.revive() target.sight = initial(target.sight) target.see_in_dark = initial(target.see_in_dark) diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 629a383433..f065ec3ea1 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -408,7 +408,7 @@ to_chat(user, "You can't apply a splint to the arm you're using!") return user.visible_message("[user] starts to apply \the [src] to their [limb].", "You start to apply \the [src] to your [limb].", "You hear something being wrapped.") - if(do_after(user, 50, M, exclusive = TRUE)) + if(do_after(user, 50, M, exclusive = TASK_USER_EXCLUSIVE)) if(affecting.splinted) to_chat(user, "[M]'s [limb] is already splinted!") return diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm index 10c85fa7e4..ba5db2b33b 100644 --- a/code/game/objects/items/stacks/nanopaste.dm +++ b/code/game/objects/items/stacks/nanopaste.dm @@ -16,7 +16,7 @@ if (istype(M,/mob/living/silicon/robot)) //Repairing cyborgs var/mob/living/silicon/robot/R = M if (R.getBruteLoss() || R.getFireLoss()) - if(do_after(user, 7 * toolspeed, exclusive = TRUE)) + if(do_after(user, 7 * toolspeed, R, exclusive = TASK_ALL_EXCLUSIVE)) R.adjustBruteLoss(-15) R.adjustFireLoss(-15) R.updatehealth() @@ -51,9 +51,9 @@ else if(can_use(1)) user.setClickCooldown(user.get_attack_speed(src)) if(S.open >= 2) - if(do_after(user, 5 * toolspeed, exclusive = TRUE)) + if(do_after(user, 5 * toolspeed, S, exclusive = TASK_ALL_EXCLUSIVE)) S.heal_damage(restoration_internal, restoration_internal, robo_repair = 1) - else if(do_after(user, 5 * toolspeed, exclusive = TRUE)) + else if(do_after(user, 5 * toolspeed, S, exclusive = TASK_ALL_EXCLUSIVE)) S.heal_damage(restoration_external,restoration_external, robo_repair =1) H.updatehealth() use(1) diff --git a/code/game/objects/items/weapons/storage/pouches.dm b/code/game/objects/items/weapons/storage/pouches.dm index 38d0660894..24a81f4112 100644 --- a/code/game/objects/items/weapons/storage/pouches.dm +++ b/code/game/objects/items/weapons/storage/pouches.dm @@ -23,7 +23,7 @@ if(user.get_active_hand() == src || user.get_inactive_hand() == src) return TRUE // Skip delay - if(insert_delay && !do_after(user, 2 SECONDS, src, needhand = TRUE, exclusive = TRUE)) + if(insert_delay && !do_after(user, 2 SECONDS, src, needhand = TRUE, exclusive = TASK_USER_EXCLUSIVE)) return FALSE // Moved or whatever if(W in src) @@ -36,7 +36,7 @@ if(user.get_active_hand() == src || user.get_inactive_hand() == src) return TRUE // Skip delay - if(remove_delay && !do_after(user, 2 SECONDS, src, needhand = TRUE, exclusive = TRUE)) + if(remove_delay && !do_after(user, 2 SECONDS, src, needhand = TRUE, exclusive = TASK_USER_EXCLUSIVE)) return FALSE // Moved or whatever if(W in src) diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 5a786cacd8..2b57235299 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -176,7 +176,7 @@ playsound(src, WT.usesound, 50, 1) if(istext(glass)) user.visible_message("[user] welds the [glass] plating off the airlock assembly.", "You start to weld the [glass] plating off the airlock assembly.") - if(do_after(user, 40 * WT.toolspeed)) + if(do_after(user, 4 SECONDS * WT.toolspeed, src, exclusive = TASK_ALL_EXCLUSIVE)) if(!src || !WT.isOn()) return to_chat(user, "You welded the [glass] plating off!") var/M = text2path("/obj/item/stack/material/[glass]") @@ -184,14 +184,14 @@ glass = 0 else if(glass == 1) user.visible_message("[user] welds the glass panel out of the airlock assembly.", "You start to weld the glass panel out of the airlock assembly.") - if(do_after(user, 40 * WT.toolspeed)) + if(do_after(user, 4 SECONDS * WT.toolspeed, src, exclusive = TASK_ALL_EXCLUSIVE)) if(!src || !WT.isOn()) return to_chat(user, "You welded the glass panel out!") new /obj/item/stack/material/glass/reinforced(src.loc) glass = 0 else if(!anchored) user.visible_message("[user] dissassembles the airlock assembly.", "You start to dissassemble the airlock assembly.") - if(do_after(user, 40 * WT.toolspeed)) + if(do_after(user, 4 SECONDS * WT.toolspeed, src, exclusive = TASK_ALL_EXCLUSIVE)) if(!src || !WT.isOn()) return to_chat(user, "You dissasembled the airlock assembly!") new /obj/item/stack/material/steel(src.loc, 4) @@ -207,7 +207,7 @@ else user.visible_message("[user] begins securing the airlock assembly to the floor.", "You starts securing the airlock assembly to the floor.") - if(do_after(user, 40 * W.toolspeed)) + if(do_after(user, 4 SECONDS * W.toolspeed, src, exclusive = TASK_ALL_EXCLUSIVE)) if(!src) return to_chat(user, "You [anchored? "un" : ""]secured the airlock assembly!") anchored = !anchored @@ -218,7 +218,7 @@ to_chat(user, "You need one length of coil to wire the airlock assembly.") return user.visible_message("[user] wires the airlock assembly.", "You start to wire the airlock assembly.") - if(do_after(user, 40) && state == 0 && anchored) + if(do_after(user, 4 SECONDS, src, exclusive = TASK_ALL_EXCLUSIVE) && state == 0 && anchored) if (C.use(1)) src.state = 1 to_chat(user, "You wire the airlock.") @@ -227,7 +227,7 @@ playsound(src, W.usesound, 100, 1) user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly.") - if(do_after(user, 40 * W.toolspeed)) + if(do_after(user, 4 SECONDS * W.toolspeed, src, exclusive = TASK_ALL_EXCLUSIVE)) if(!src) return to_chat(user, "You cut the airlock wires.!") new/obj/item/stack/cable_coil(src.loc, 1) @@ -237,7 +237,7 @@ playsound(src, W.usesound, 100, 1) user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly.") - if(do_after(user, 40)) + if(do_after(user, 4 SECONDS, src, exclusive = TASK_ALL_EXCLUSIVE)) if(!src) return user.drop_item() W.loc = src @@ -255,7 +255,7 @@ playsound(src, W.usesound, 100, 1) user.visible_message("\The [user] starts removing the electronics from the airlock assembly.", "You start removing the electronics from the airlock assembly.") - if(do_after(user, 40 * W.toolspeed)) + if(do_after(user, 4 SECONDS * W.toolspeed, src, exclusive = TASK_ALL_EXCLUSIVE)) if(!src) return to_chat(user, "You removed the airlock electronics!") src.state = 1 @@ -270,7 +270,7 @@ if(material_name == "rglass") playsound(src, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.") - if(do_after(user, 40) && !glass) + if(do_after(user, 4 SECONDS, src, exclusive = TASK_ALL_EXCLUSIVE) && !glass) if (S.use(1)) to_chat(user, "You installed reinforced glass windows into the airlock assembly.") glass = 1 @@ -282,7 +282,7 @@ if(S.get_amount() >= 2) playsound(src, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.") - if(do_after(user, 40) && !glass) + if(do_after(user, 4 SECONDS, src, exclusive = TASK_ALL_EXCLUSIVE) && !glass) if (S.use(2)) to_chat(user, "You installed [material_display_name(material_name)] plating into the airlock assembly.") glass = material_name @@ -291,7 +291,7 @@ playsound(src, W.usesound, 100, 1) to_chat(user, "Now finishing the airlock.") - if(do_after(user, 40 * W.toolspeed)) + if(do_after(user, 4 SECONDS * W.toolspeed, src, exclusive = TASK_ALL_EXCLUSIVE)) if(!src) return to_chat(user, "You finish the airlock!") var/path diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm index 9150ce1877..3f5bb51148 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm @@ -910,7 +910,7 @@ to_chat(src, "You can't weave here!") return - if(do_after(src, desired_result.time, exclusive = TRUE)) + if(do_after(src, desired_result.time, exclusive = TASK_USER_EXCLUSIVE)) if(desired_result.cost > species.silk_reserve) to_chat(src, "You don't have enough silk to weave that!") return @@ -969,7 +969,7 @@ to_chat(src, "You can't weave here!") return - if(do_after(src, desired_result.time, exclusive = TRUE)) + if(do_after(src, desired_result.time, exclusive = TASK_USER_EXCLUSIVE)) if(desired_result.cost > species.silk_reserve) to_chat(src, "You don't have enough silk to weave that!") return diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm b/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm index cc2cc62e5b..e6c9ff410b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/softdog.dm @@ -254,7 +254,7 @@ return ..() if(M.a_intent == I_HELP) M.visible_message("[M] pets [src].", runemessage = "pets [src]") - if(do_after(M, 30 SECONDS, exclusive = 1, target = src)) + if(do_after(M, 30 SECONDS, exclusive = TASK_USER_EXCLUSIVE, target = src)) faction = M.faction revive() sight = initial(sight) diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 503f76d566..30ba2bc199 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -546,7 +546,7 @@ prey.ai_holder?.react_to_attack(user) //Timer and progress bar - if(!do_after(user, swallow_time, prey, exclusive = TRUE)) + if(!do_after(user, swallow_time, prey, exclusive = TASK_USER_EXCLUSIVE)) return FALSE // Prey escpaed (or user disabled) before timer expired. // If we got this far, nom successful! Announce it! @@ -832,7 +832,7 @@ playsound(src, 'sound/items/eatfood.ogg', rand(10,50), 1) var/T = (istype(M) ? M.hardness/40 : 1) SECONDS //1.5 seconds to eat a sheet of metal. 2.5 for durasteel and diamond & 1 by default (applies to some ores like raw carbon, slag, etc. to_chat(src, "You start crunching on [I] with your powerful jaws, attempting to tear it apart...") - if(do_after(feeder, T, ignore_movement = TRUE, exclusive = TRUE)) //Eat on the move, but not multiple things at once. + if(do_after(feeder, T, ignore_movement = TRUE, exclusive = TASK_ALL_EXCLUSIVE)) //Eat on the move, but not multiple things at once. if(feeder != src) to_chat(feeder, "You feed [I] to [src].") log_admin("VORE: [feeder] fed [src] [I].")