mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-23 03:57:13 +01:00
Adds support for multiple callback checks for the do_after and incapacitated procs (#13057)
* do_after refactor Update slime.dm fix a comment if you read this you get a cookie! * some little tweaks Changes a TRUE to FALSE in a comment, got confused there. Removes the code that checks for non-callbacks in the extra_checks list and removes them. It should be up to the dev to not add non-callbacks to this list. I'd rather have it runtime instead * check_for_true_callbacks * CRLF to LF Co-authored-by: SteelSlayer <SteelSlayer@users.noreply.github.com>
This commit is contained in:
co-authored by
SteelSlayer
parent
bdafa40b40
commit
63ea21b20e
+39
-14
@@ -355,24 +355,35 @@ This is always put in the attack log.
|
||||
if(progress)
|
||||
qdel(progbar)
|
||||
|
||||
/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1, datum/callback/extra_checks = null)
|
||||
/* Use this proc when you want to have code under it execute after a delay, and ensure certain conditions are met during that delay...
|
||||
* Such as the user not being interrupted via getting stunned or by moving off the tile they're currently on.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* if(do_after(user, 50, target = sometarget, extra_checks = list(callback_check1, callback_check2)))
|
||||
* do_stuff()
|
||||
*
|
||||
* This will create progress bar that lasts for 5 seconds. If the user doesn't move or otherwise do something that would cause the checks to fail in those 5 seconds, do_stuff() would execute.
|
||||
* The Proc returns TRUE upon success (the progress bar reached the end), or FALSE upon failure (the user moved or some other check failed)
|
||||
*/
|
||||
/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1, list/extra_checks = list(), use_default_checks = TRUE)
|
||||
if(!user)
|
||||
return 0
|
||||
return FALSE
|
||||
var/atom/Tloc = null
|
||||
if(target)
|
||||
Tloc = target.loc
|
||||
|
||||
var/atom/Uloc = user.loc
|
||||
|
||||
var/drifting = 0
|
||||
var/drifting = FALSE
|
||||
if(!user.Process_Spacemove(0) && user.inertia_dir)
|
||||
drifting = 1
|
||||
drifting = TRUE
|
||||
|
||||
var/holding = user.get_active_hand()
|
||||
|
||||
var/holdingnull = 1 //User's hand started out empty, check for an empty hand
|
||||
var/holdingnull = TRUE //User's hand started out empty, check for an empty hand
|
||||
if(holding)
|
||||
holdingnull = 0 //Users hand started holding something, check to see if it's still holding that
|
||||
holdingnull = FALSE //Users hand started holding something, check to see if it's still holding that
|
||||
|
||||
var/datum/progressbar/progbar
|
||||
if(progress)
|
||||
@@ -380,22 +391,29 @@ This is always put in the attack log.
|
||||
|
||||
var/endtime = world.time + delay
|
||||
var/starttime = world.time
|
||||
. = 1
|
||||
. = TRUE
|
||||
|
||||
// By default, checks for weakness and stunned get added to the extra_checks list.
|
||||
// Setting `use_default_checks` to FALSE means that you don't want the do_after to check for these statuses, or that you will be supplying your own checks.
|
||||
if(use_default_checks)
|
||||
extra_checks += CALLBACK(user, /mob.proc/IsWeakened)
|
||||
extra_checks += CALLBACK(user, /mob.proc/IsStunned)
|
||||
|
||||
while(world.time < endtime)
|
||||
sleep(1)
|
||||
if(progress)
|
||||
progbar.update(world.time - starttime)
|
||||
|
||||
if(drifting && !user.inertia_dir)
|
||||
drifting = 0
|
||||
drifting = FALSE
|
||||
Uloc = user.loc
|
||||
|
||||
if(!user || user.stat || user.IsWeakened() || user.stunned || (!drifting && user.loc != Uloc)|| (extra_checks && !extra_checks.Invoke()))
|
||||
. = 0
|
||||
if(!user || user.stat || (!drifting && user.loc != Uloc) || check_for_true_callbacks(extra_checks))
|
||||
. = FALSE
|
||||
break
|
||||
|
||||
if(Tloc && (!target || Tloc != target.loc))
|
||||
. = 0
|
||||
. = FALSE
|
||||
break
|
||||
|
||||
if(needhand)
|
||||
@@ -403,14 +421,21 @@ This is always put in the attack log.
|
||||
//i.e the hand is used to pull some item/tool out of the construction
|
||||
if(!holdingnull)
|
||||
if(!holding)
|
||||
. = 0
|
||||
. = FALSE
|
||||
break
|
||||
if(user.get_active_hand() != holding)
|
||||
. = 0
|
||||
. = FALSE
|
||||
break
|
||||
if(progress)
|
||||
qdel(progbar)
|
||||
|
||||
// Upon any of the callbacks in the list returning TRUE, the proc will return TRUE.
|
||||
/proc/check_for_true_callbacks(list/extra_checks)
|
||||
for(var/datum/callback/CB in extra_checks)
|
||||
if(CB.Invoke())
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
#define DOAFTERONCE_MAGIC "Magic~~"
|
||||
GLOBAL_LIST_INIT(do_after_once_tracker, list())
|
||||
/proc/do_after_once(mob/user, delay, needhand = 1, atom/target = null, progress = 1, attempt_cancel_message = "Attempt cancelled.")
|
||||
@@ -423,7 +448,7 @@ GLOBAL_LIST_INIT(do_after_once_tracker, list())
|
||||
to_chat(user, "<span class='warning'>[attempt_cancel_message]</span>")
|
||||
return FALSE
|
||||
GLOB.do_after_once_tracker[cache_key] = TRUE
|
||||
. = do_after(user, delay, needhand, target, progress, extra_checks = CALLBACK(GLOBAL_PROC, .proc/do_after_once_checks, cache_key))
|
||||
. = do_after(user, delay, needhand, target, progress, extra_checks = list(CALLBACK(GLOBAL_PROC, .proc/do_after_once_checks, cache_key)))
|
||||
GLOB.do_after_once_tracker[cache_key] = FALSE
|
||||
|
||||
/proc/do_after_once_checks(cache_key)
|
||||
|
||||
@@ -1003,7 +1003,7 @@ About the new airlock wires panel:
|
||||
"<span class='notice'>You begin [welded ? "unwelding":"welding"] the airlock...</span>", \
|
||||
"<span class='italics'>You hear welding.</span>")
|
||||
|
||||
if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/weld_checks, I, user)))
|
||||
if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/weld_checks, I, user))))
|
||||
if(!density && !welded)
|
||||
return
|
||||
welded = !welded
|
||||
@@ -1014,7 +1014,7 @@ About the new airlock wires panel:
|
||||
user.visible_message("[user] is welding the airlock.", \
|
||||
"<span class='notice'>You begin repairing the airlock...</span>", \
|
||||
"<span class='italics'>You hear welding.</span>")
|
||||
if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/weld_checks, I, user)))
|
||||
if(I.use_tool(src, user, 40, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/weld_checks, I, user))))
|
||||
obj_integrity = max_integrity
|
||||
stat &= ~BROKEN
|
||||
user.visible_message("[user.name] has repaired [src].", \
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
var/datum/callback/tool_check = CALLBACK(src, .proc/tool_check_callback, user, target, amount, extra_checks)
|
||||
|
||||
if(ismob(target))
|
||||
if(!do_mob(user, target, delay, extra_checks=tool_check))
|
||||
if(!do_mob(user, target, delay, extra_checks = list(tool_check)))
|
||||
return
|
||||
|
||||
else
|
||||
if(!do_after(user, delay, target=target, extra_checks=tool_check))
|
||||
if(!do_after(user, delay, target=target, extra_checks = list(tool_check)))
|
||||
return
|
||||
else
|
||||
// Invoke the extra checks once, just in case.
|
||||
|
||||
@@ -254,7 +254,7 @@ GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e",
|
||||
if(!can_be_reached(user))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You begin to lever the window [state == WINDOW_OUT_OF_FRAME ? "into":"out of"] the frame...</span>")
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
|
||||
return
|
||||
state = (state == WINDOW_OUT_OF_FRAME ? WINDOW_IN_FRAME : WINDOW_OUT_OF_FRAME)
|
||||
to_chat(user, "<span class='notice'>You pry the window [state == WINDOW_IN_FRAME ? "into":"out of"] the frame.</span>")
|
||||
@@ -268,20 +268,20 @@ GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e",
|
||||
if(reinf)
|
||||
if(state == WINDOW_SCREWED_TO_FRAME || state == WINDOW_IN_FRAME)
|
||||
to_chat(user, "<span class='notice'>You begin to [state == WINDOW_SCREWED_TO_FRAME ? "unscrew the window from":"screw the window to"] the frame...</span>")
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
|
||||
return
|
||||
state = (state == WINDOW_IN_FRAME ? WINDOW_SCREWED_TO_FRAME : WINDOW_IN_FRAME)
|
||||
to_chat(user, "<span class='notice'>You [state == WINDOW_IN_FRAME ? "unfasten the window from":"fasten the window to"] the frame.</span>")
|
||||
else if(state == WINDOW_OUT_OF_FRAME)
|
||||
to_chat(user, "<span class='notice'>You begin to [anchored ? "unscrew the frame from":"screw the frame to"] the floor...</span>")
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
|
||||
return
|
||||
anchored = !anchored
|
||||
update_nearby_icons()
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "fasten the frame to":"unfasten the frame from"] the floor.</span>")
|
||||
else //if we're not reinforced, we don't need to check or update state
|
||||
to_chat(user, "<span class='notice'>You begin to [anchored ? "unscrew the window from":"screw the window to"] the floor...</span>")
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_anchored, anchored)))
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_anchored, anchored))))
|
||||
return
|
||||
anchored = !anchored
|
||||
air_update_turf(TRUE)
|
||||
@@ -297,7 +297,7 @@ GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e",
|
||||
if(!can_be_reached(user))
|
||||
return
|
||||
TOOL_ATTEMPT_DISMANTLE_MESSAGE
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = CALLBACK(src, .proc/check_state_and_anchored, state, anchored)))
|
||||
if(!I.use_tool(src, user, decon_speed, volume = I.tool_volume, extra_checks = list(CALLBACK(src, .proc/check_state_and_anchored, state, anchored))))
|
||||
return
|
||||
var/obj/item/stack/sheet/G = new glass_type(user.loc, glass_amount)
|
||||
G.add_fingerprint(user)
|
||||
|
||||
@@ -146,11 +146,13 @@
|
||||
return
|
||||
|
||||
var/limb_select = input(H, "Choose a limb to regrow", "Limb Regrowth") as null|anything in missing_limbs
|
||||
if(!limb_select) // If the user hit cancel on the popup, return
|
||||
return
|
||||
var/chosen_limb = missing_limbs[limb_select]
|
||||
|
||||
H.visible_message("<span class='notice'>[H] begins to hold still and concentrate on [H.p_their()] missing [limb_select]...</span>", "<span class='notice'>You begin to focus on regrowing your missing [limb_select]... (This will take [round(SLIMEPERSON_REGROWTHDELAY/10)] seconds, and you must hold still.)</span>")
|
||||
if(do_after(H, SLIMEPERSON_REGROWTHDELAY, needhand = 0, target = H))
|
||||
if(H.incapacitated())
|
||||
if(do_after(H, SLIMEPERSON_REGROWTHDELAY, FALSE, H, extra_checks = list(CALLBACK(H, /mob.proc/IsStunned)), use_default_checks = FALSE)) // Override the check for weakness, only check for stunned
|
||||
if(H.incapacitated(ignore_lying = TRUE, extra_checks = list(CALLBACK(H, /mob.proc/IsStunned)), use_default_checks = FALSE)) // Override the check for weakness, only check for stunned
|
||||
to_chat(H, "<span class='warning'>You cannot regenerate missing limbs in your current state.</span>")
|
||||
return
|
||||
|
||||
@@ -196,4 +198,4 @@
|
||||
|
||||
#undef SLIMEPERSON_HUNGERCOST
|
||||
#undef SLIMEPERSON_MINHUNGER
|
||||
#undef SLIMEPERSON_REGROWTHDELAY
|
||||
#undef SLIMEPERSON_REGROWTHDELAY
|
||||
@@ -65,8 +65,14 @@
|
||||
return !(IsWeakened() || paralysis || stat || (status_flags & FAKEDEATH))
|
||||
|
||||
// Whether the mob is capable of actions or not
|
||||
/mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, ignore_lying = FALSE)
|
||||
if(stat || paralysis || stunned || IsWeakened() || (!ignore_restraints && restrained()) || (!ignore_lying && lying))
|
||||
/mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, ignore_lying = FALSE, list/extra_checks = list(), use_default_checks = TRUE)
|
||||
// By default, checks for weakness and stunned get added to the extra_checks list.
|
||||
// Setting `use_default_checks` to FALSE means that you don't want it checking for these statuses or you are supplying your own checks.
|
||||
if(use_default_checks)
|
||||
extra_checks += CALLBACK(src, /mob.proc/IsWeakened)
|
||||
extra_checks += CALLBACK(src, /mob.proc/IsStunned)
|
||||
|
||||
if(stat || paralysis || (!ignore_restraints && restrained()) || (!ignore_lying && lying) || check_for_true_callbacks(extra_checks))
|
||||
return TRUE
|
||||
|
||||
// wonderful proc names, I know - used to check whether the blur overlay
|
||||
|
||||
@@ -173,6 +173,9 @@
|
||||
/mob/proc/Stun()
|
||||
return
|
||||
|
||||
/mob/proc/IsStunned()
|
||||
return stunned
|
||||
|
||||
/mob/proc/SetStunned()
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user