Skip to content

Commit

Permalink
https://github.com/tgstation/tgstation/pull/55172
Browse files Browse the repository at this point in the history
  • Loading branch information
Tsar-Salat committed Mar 26, 2024
1 parent d2106ee commit 26c9f28
Show file tree
Hide file tree
Showing 18 changed files with 70 additions and 72 deletions.
4 changes: 4 additions & 0 deletions code/__DEFINES/do_afters.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#define DOAFTER_SOURCE_SURGERY "doafter_surgery"
#define DOAFTER_SOURCE_MECHADRILL "doafter_mechadrill"
#define DOAFTER_SOURCE_SURVIVALPEN "doafter_survivalpen"
#define DOAFTER_SOURCE_GETTING_UP "doafter_gettingup"
6 changes: 5 additions & 1 deletion code/__DEFINES/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,11 @@
#define WABBAJACK (1<<6)

#define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return;
#define INTERACTING_WITH(X, Y) (Y in X.do_afters)

#define DOING_INTERACTION(user, interaction_key) (LAZYACCESS(user.do_afters, interaction_key))
#define DOING_INTERACTION_LIMIT(user, interaction_key, max_interaction_count) ((LAZYACCESS(user.do_afters, interaction_key) || 0) >= max_interaction_count)
#define DOING_INTERACTION_WITH_TARGET(user, target) (LAZYACCESS(user.do_afters, target))
#define DOING_INTERACTION_WITH_TARGET_LIMIT(user, target, max_interaction_count) ((LAZYACCESS(user.do_afters, target) || 0) >= max_interaction_count)

/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine()
#define EXAMINE_MORE_TIME 1 SECONDS
Expand Down
18 changes: 5 additions & 13 deletions code/__DEFINES/timed_action.dm
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
// timed_action_flags parameter for 'proc/do_after'
#define IGNORE_TARGET_IN_DOAFTERS (1<<0)

// The user can move freely without canceling the do_after
#define IGNORE_USER_LOC_CHANGE (1<<1)
#define IGNORE_USER_LOC_CHANGE (1<<0)
// The target can move freely without canceling the do_after
#define IGNORE_TARGET_LOC_CHANGE (1<<2)
#define IGNORE_TARGET_LOC_CHANGE (1<<1)
/// Can do the action even if the item is no longer being held
#define IGNORE_HELD_ITEM (1<<3)
#define IGNORE_HELD_ITEM (1<<2)
/// Can do the action even if the mob is incapacitated
#define IGNORE_INCAPACITATED (1<<4)
/// Must be adjacent
#define REQUIRE_ADJACENCY (1<<5)
/// Can do the action even if the mob is handcuffed
#define IGNORE_RESTRAINED (1<<6)

// Combined parameters for ease of use
#define UNINTERRUPTIBLE IGNORE_TARGET_IN_DOAFTERS|IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM|IGNORE_INCAPACITATED
#define UNINTERRUPTIBLE_CONSCIOUS IGNORE_TARGET_IN_DOAFTERS|IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM
#define IGNORE_INCAPACITATED (1<<3)
55 changes: 23 additions & 32 deletions code/__HELPERS/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -270,18 +270,25 @@ GLOBAL_LIST_EMPTY(species_list)
* * progress - if TRUE, a progress bar is displayed.
* * extra_checks - a callback that can be used to add extra checks to the do_after. Returning false in this callback will cancel the do_after.
*/
/proc/do_after(mob/user, delay = 3 SECONDS, atom/target, timed_action_flags = NONE, progress = TRUE, datum/callback/extra_checks)
/proc/do_after(mob/user, delay = 3 SECONDS, atom/target, timed_action_flags = NONE, progress = TRUE, datum/callback/extra_checks, interaction_key, max_interact_count = 1)
if(!user)
return FALSE
if(!isnum(delay))
CRASH("do_after was passed a non-number delay: [delay || "null"].")

/*
if(target && INTERACTING_WITH(user, target))
to_chat(user, "<span class='warning'>You're already interacting with [target]!</span>")
return
*/

if(target)
LAZYADD(user.do_afters, target)
LAZYADD(target.targeted_by, user)
if(!interaction_key && target)
interaction_key = target //Use the direct ref to the target
if(interaction_key) //Do we have a interaction_key now?
var/current_interaction_count = LAZYACCESS(user.do_afters, interaction_key) || 0
if(current_interaction_count >= max_interact_count) //We are at our peak
return
LAZYSET(user.do_afters, interaction_key, current_interaction_count + 1)

var/atom/user_loc = user.loc
var/atom/target_loc = target?.loc
Expand All @@ -296,21 +303,14 @@ GLOBAL_LIST_EMPTY(species_list)

var/datum/progressbar/progbar
if(progress)
if(target) // the progress bar needs a target, so if we don't have one just pass it the user.
progbar = new(user, delay, target)
else
progbar = new(user, delay, user)
progbar = new(user, delay, target || user)

var/endtime = world.time + delay
var/starttime = world.time
. = TRUE
while (world.time < endtime)
stoplag(1)

if(QDELETED(user))
. = FALSE
break

if(!QDELETED(progbar))
progbar.update(world.time - starttime)

Expand All @@ -319,35 +319,26 @@ GLOBAL_LIST_EMPTY(species_list)
user_loc = user.loc

// Check flags
if(!(timed_action_flags & IGNORE_USER_LOC_CHANGE) && !drifting && user.loc != user_loc)
. = FALSE

if(!(timed_action_flags & IGNORE_HELD_ITEM) && user.get_active_held_item() != holding)
. = FALSE

if(!(timed_action_flags & IGNORE_INCAPACITATED) && user.incapacitated(ignore_restraints = (timed_action_flags & IGNORE_RESTRAINED)))
. = FALSE

if(extra_checks && !extra_checks.Invoke())
if(QDELETED(user) \
|| (!(timed_action_flags & IGNORE_USER_LOC_CHANGE) && !drifting && user.loc != user_loc) \
|| (!(timed_action_flags & IGNORE_HELD_ITEM) && user.get_active_held_item() != holding) \
|| (!(timed_action_flags & IGNORE_INCAPACITATED) && HAS_TRAIT(user, TRAIT_INCAPACITATED)) \
|| (extra_checks && !extra_checks.Invoke()))
. = FALSE
break

// If we have a target, we check for them moving here. We don't care about it if we're drifting or we ignore target loc change
if(!(timed_action_flags & IGNORE_TARGET_LOC_CHANGE) && !drifting)
if(target_loc && user != target && (QDELETED(target) || target_loc != target.loc))
. = FALSE

if(target && !(timed_action_flags & IGNORE_TARGET_IN_DOAFTERS) && !(target in user.do_afters))
if(target && (user != target) && \
(QDELETED(target) \
|| (!(timed_action_flags & IGNORE_TARGET_LOC_CHANGE) && target.loc != target_loc)))
. = FALSE

if(!.)
break

if(!QDELETED(progbar))
progbar.end_progress()

if(!QDELETED(target))
LAZYREMOVE(user.do_afters, target)
LAZYREMOVE(target.targeted_by, user)
if(interaction_key)
LAZYREMOVE(user.do_afters, interaction_key)

/mob/proc/do_after_coefficent() // This gets added to the delay on a do_after, default 1
. = 1
Expand Down
4 changes: 4 additions & 0 deletions code/datums/components/butchering.dm
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
Butcher(user, M)

/datum/component/butchering/proc/startNeckSlice(obj/item/source, mob/living/carbon/human/H, mob/living/user)
if(DOING_INTERACTION_WITH_TARGET(user, H))
to_chat(user, "<span class = 'warning'>You're already interacting with [H]!</span>")
return

user.visible_message("<span class='danger'>[user] is slitting [H]'s throat!</span>", \
"<span class='danger'>You start slicing [H]'s throat!</span>", \
"<span class='hear'>You hear a cutting noise!</span>", ignored_mobs = H)
Expand Down
8 changes: 0 additions & 8 deletions code/game/atoms.dm
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@

var/list/alternate_appearances

///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy()
var/list/targeted_by

/// Last appearance of the atom for demo saving purposes
var/image/demo_last_appearance

Expand Down Expand Up @@ -309,11 +306,6 @@
LAZYCLEARLIST(overlays)
LAZYCLEARLIST(managed_overlays)

for(var/i in targeted_by)
var/mob/M = i
LAZYREMOVE(M.do_afters, src)

targeted_by = null
QDEL_NULL(light)

if(smoothing_flags & SMOOTH_QUEUED)
Expand Down
4 changes: 2 additions & 2 deletions code/game/mecha/equipment/mecha_equipment.dm
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@
chassis.use_power(energy_drain)
addtimer(CALLBACK(src, PROC_REF(set_ready_state), 1), equip_cooldown)

/obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown(atom/target)
/obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown(atom/target, mob/user, interaction_key)
if(!chassis)
return
var/C = chassis.loc
set_ready_state(0)
chassis.use_power(energy_drain)
. = do_after(chassis.occupant, equip_cooldown, target=target)
. = do_after(user, equip_cooldown, target=target, interaction_key = interaction_key)
set_ready_state(1)
if(!chassis || chassis.loc != C || src != chassis.selected || !(get_dir(chassis, target)&chassis.dir))
return 0
Expand Down
5 changes: 2 additions & 3 deletions code/game/objects/items/stacks/sheets/sheet_types.dm
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,9 @@ GLOBAL_LIST_INIT(bamboo_recipes, list ( \
force = 0
throwforce = 0
merge_type = /obj/item/stack/sheet/cotton
var/pull_effort = 30
var/loom_result = /obj/item/stack/sheet/cotton/cloth
grind_results = list(/datum/reagent/cellulose = 20)
var/pull_effort = 10
var/loom_result = /obj/item/stack/sheet/cotton/cloth

GLOBAL_LIST_INIT(cloth_recipes, list ( \
new/datum/stack_recipe("white jumpskirt", /obj/item/clothing/under/color/jumpskirt/white, 3), /*Ladies first*/ \
Expand Down Expand Up @@ -447,7 +447,6 @@ GLOBAL_LIST_INIT(durathread_recipes, list ( \
singular_name = "raw durathread ball"
icon_state = "sheet-durathreadraw"
merge_type = /obj/item/stack/sheet/cotton/durathread
pull_effort = 70
loom_result = /obj/item/stack/sheet/durathread
grind_results = list()

Expand Down
8 changes: 3 additions & 5 deletions code/game/objects/structures/loom.dm
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@
user.show_message("<span class='notice'>You need at least [FABRIC_PER_SHEET] units of fabric before using this.</span>", MSG_VISUAL)
return FALSE
user.show_message("<span class='notice'>You start weaving \the [W.name] through the loom..</span>", MSG_VISUAL)
if(W.use_tool(src, user, W.pull_effort))
if(W.amount >= FABRIC_PER_SHEET)
new W.loom_result(drop_location())
W.use(FABRIC_PER_SHEET)
user.show_message("<span class='notice'>You weave \the [W.name] into a workable fabric.</span>", MSG_VISUAL)
while(W.use_tool(src, user, W.pull_effort) && W.use(FABRIC_PER_SHEET))
new W.loom_result(drop_location())
user.show_message("<span class='notice'>You weave \the [W.name] into a workable fabric.</span>", MSG_VISUAL)
return TRUE

#undef FABRIC_PER_SHEET
10 changes: 10 additions & 0 deletions code/modules/clothing/shoes/_shoes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@
return

if(user == loc && tied != SHOES_TIED) // if they're our own shoes, go tie-wards
if(DOING_INTERACTION_WITH_TARGET(user, our_guy))
to_chat(user, span_warning("You're already interacting with [src]!"))
return
user.visible_message("<span class='notice'>[user] begins [tied ? "unknotting" : "tying"] the laces of [user.p_their()] [src.name].</span>", "<span class='notice'>You begin [tied ? "unknotting" : "tying"] the laces of your [src.name]...</span>")

if(do_after(user, lace_time, target = our_guy, extra_checks = CALLBACK(src, PROC_REF(still_shoed), our_guy)))
Expand All @@ -149,6 +152,9 @@
if(tied == SHOES_KNOTTED)
to_chat(user, "<span class='warning'>The laces on [loc]'s [src.name] are already a hopelessly tangled mess!</span>")
return
if(DOING_INTERACTION_WITH_TARGET(user, our_guy))
to_chat(user, span_warning("You're already interacting with [src]!"))
return

var/mod_time = lace_time
to_chat(user, "<span class='notice'>You quietly set to work [tied ? "untying" : "knotting"] [loc]'s [src.name]...</span>")
Expand Down Expand Up @@ -230,6 +236,10 @@
/obj/item/clothing/shoes/attack_self(mob/user)
. = ..()

if(DOING_INTERACTION_WITH_TARGET(user, src))
to_chat(user, "<span class='warning'>You're already interacting with [src]!</span>")
return

to_chat(user, "<span class='notice'>You begin [tied ? "untying" : "tying"] the laces on [src]...</span>")

if(do_after(user, lace_time, target = src,extra_checks = CALLBACK(src, PROC_REF(still_shoed), user)))
Expand Down
4 changes: 2 additions & 2 deletions code/modules/mob/living/carbon/carbon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@
if(!cuff_break)
visible_message("<span class='warning'>[src] attempts to remove [I]!</span>")
to_chat(src, "<span class='notice'>You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)</span>")
if(do_after(src, breakouttime, target = src, timed_action_flags = IGNORE_HELD_ITEM|IGNORE_RESTRAINED))
if(do_after(src, breakouttime, target = src, timed_action_flags = IGNORE_HELD_ITEM))
. = clear_cuffs(I, cuff_break)
else
to_chat(src, "<span class='warning'>You fail to remove [I]!</span>")
Expand All @@ -315,7 +315,7 @@
breakouttime = 50
visible_message("<span class='warning'>[src] is trying to break [I]!</span>")
to_chat(src, "<span class='notice'>You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)</span>")
if(do_after(src, breakouttime, target = src, timed_action_flags = IGNORE_HELD_ITEM|IGNORE_RESTRAINED))
if(do_after(src, breakouttime, target = src, timed_action_flags = IGNORE_HELD_ITEM))
. = clear_cuffs(I, cuff_break)
else
to_chat(src, "<span class='warning'>You fail to break [I]!</span>")
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/carbon/human/human.dm
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@
do
CHECK_DNA_AND_SPECIES(target)

if (INTERACTING_WITH(src, target))
if (DOING_INTERACTION_WITH_TARGET(src,target))
return FALSE

if (target.stat == DEAD || HAS_TRAIT(target, TRAIT_FAKEDEATH))
Expand Down
4 changes: 2 additions & 2 deletions code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@

/mob/living/proc/get_up(instant = FALSE)
set waitfor = FALSE
if(!instant && !do_after(src, 1 SECONDS, src, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM), extra_checks = CALLBACK(src, TYPE_PROC_REF(/mob/living, rest_checks_callback))))
if(!instant && !do_after(src, 1 SECONDS, src, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM), extra_checks = CALLBACK(src, TYPE_PROC_REF(/mob/living, rest_checks_callback)), interaction_key = DOAFTER_SOURCE_GETTING_UP))
return
if(resting || body_position == STANDING_UP || HAS_TRAIT(src, TRAIT_FLOORED))
return
Expand Down Expand Up @@ -977,7 +977,7 @@
"<span class='userdanger'>[src] tries to remove your [what.name].</span>", null, null, src)
to_chat(src, "<span class='danger'>You try to remove [who]'s [what.name]...</span>")
what.add_fingerprint(src)
if(do_after(src, what.strip_delay, who))
if(do_after(src, what.strip_delay, who, interaction_key = what))
if(what && Adjacent(who))
if(islist(where))
var/list/L = where
Expand Down
3 changes: 3 additions & 0 deletions code/modules/mob/living/simple_animal/bot/medbot.dm
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,9 @@
return TRUE

/mob/living/simple_animal/bot/medbot/attack_hand(mob/living/carbon/human/H)
if(DOING_INTERACTION_WITH_TARGET(H, src))
to_chat(H, "<span class='warning'>You're already interacting with [src].</span>")
return

if(H.a_intent == INTENT_DISARM && mode != BOT_TIPPED)
H.visible_message("<span class='danger'>[H] begins tipping over [src].</span>", "<span class='warning'>You begin tipping over [src]...</span>")
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/mob.dm
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@
to_chat(src, "<span class='warning'>You don't have a free hand to examine this!</span>")
return FALSE
//can only queue up one examine on something at a time
if(examined_thing in do_afters)
if(DOING_INTERACTION_WITH_TARGET(src, examined_thing))
return FALSE

to_chat(src, "<span class='notice'>You start feeling around for something...</span>")
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/mob_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@
///List of progress bars this mob is currently seeing for actions
var/list/progressbars = null //for stacking do_after bars

///For storing what do_after's someone has, in case we want to restrict them to only one of a certain do_after at a time
///For storing what do_after's someone has, key = string, value = amount of interactions of that type happening.
var/list/do_afters

///Allows a datum to intercept all click calls this mob is the source of
Expand Down
2 changes: 1 addition & 1 deletion code/modules/spells/spell_types/lightning.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
halo = halo || mutable_appearance('icons/effects/effects.dmi', "electricity", EFFECTS_LAYER)
user.add_overlay(halo)
playsound(get_turf(user), Snd, 50, FALSE)
if(do_after(user, 10 SECONDS, user, timed_action_flags = UNINTERRUPTIBLE))
if(do_after(user, 10 SECONDS, user, timed_action_flags = (IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM)))
if(ready && cast_check(skipcharge=1))
choose_targets()
else
Expand Down
1 change: 1 addition & 0 deletions shiptest.dme
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include "code\__DEFINES\directional.dm"
#include "code\__DEFINES\diseases.dm"
#include "code\__DEFINES\DNA.dm"
#include "code\__DEFINES\do_afters.dm"
#include "code\__DEFINES\dye_keys.dm"
#include "code\__DEFINES\economy.dm"
#include "code\__DEFINES\events.dm"
Expand Down

0 comments on commit 26c9f28

Please sign in to comment.