[PORT] Adds TG "busy" cogbar animation for players (#27932)

* looks like it works

* move to PREFTOGGLE_3 and add sneaky do_after

* linter

* param doc and some cleanup

* autodoc and comment signal

* fix wrong type in link_processing

* fix wrong var in preferences

* cover do_mob and do_after_once

* fix toggles total

* replace indent with space

* offset and helpers procs

* fix conditional statement

* Apply suggestions from code review

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: Mira <42539014+MiraHell@users.noreply.github.com>

* Update code/__HELPERS/mob_helpers.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: Mira <42539014+MiraHell@users.noreply.github.com>

* use SECONDS

* Update code/game/objects/items/weapons/weaponry.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Signed-off-by: Mira <42539014+MiraHell@users.noreply.github.com>

---------

Signed-off-by: Mira <42539014+MiraHell@users.noreply.github.com>
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
This commit is contained in:
Mira
2025-03-06 16:04:51 +00:00
committed by GitHub
co-authored by Luc Burzah
parent c550db4e65
commit a6e8f69c55
40 changed files with 357 additions and 41 deletions
+1
View File
@@ -112,6 +112,7 @@
#define EMISSIVE_RENDER_TARGET "*EMISSIVE_PLANE"
#define POINT_PLANE 14
#define COGBAR_PLANE 14
#define LIGHTING_PLANE 15
#define LIGHTING_LAYER 15
+4 -4
View File
@@ -82,11 +82,11 @@
// toggles_3 variables. These MUST be prefixed with PREFTOGGLE_3
#define TOGGLES_3_TOTAL 1023 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
#define PREFTOGGLE_3_COGBAR_ANIMATIONS (1<<0) // 1
// When you add a toggle here, inform AA on merge so the column can be zeroed out. This needs to exist to avoid the compiler freaking out
// Also update the above value to the actual total
#define TOGGLES_3_DEFAULT (1)
#define TOGGLES_3_TOTAL 1 // If you add or remove a preference toggle above, make sure you update this define with the total value of the toggles combined.
#define TOGGLES_3_DEFAULT (PREFTOGGLE_3_COGBAR_ANIMATIONS)
// Sanity checks
// I should really convert these to a JSON list at some point hnnnnnng
+11 -9
View File
@@ -50,15 +50,16 @@
#define INIT_ORDER_PROFILER 101
#define INIT_ORDER_QUEUE 100 // Load this quickly so people cant queue skip
#define INIT_ORDER_TITLE 99 // Load this quickly so people dont see a blank lobby screen
#define INIT_ORDER_GARBAGE 24
#define INIT_ORDER_DBCORE 23
#define INIT_ORDER_REDIS 22 // Make sure we dont miss any events
#define INIT_ORDER_BLACKBOX 21
#define INIT_ORDER_CLEANUP 20
#define INIT_ORDER_INPUT 19
#define INIT_ORDER_SOUNDS 18
#define INIT_ORDER_INSTRUMENTS 17
#define INIT_ORDER_RESEARCH 16 // SoonTM
#define INIT_ORDER_GARBAGE 25
#define INIT_ORDER_DBCORE 24
#define INIT_ORDER_REDIS 23 // Make sure we dont miss any events
#define INIT_ORDER_BLACKBOX 22
#define INIT_ORDER_CLEANUP 21
#define INIT_ORDER_INPUT 20
#define INIT_ORDER_SOUNDS 19
#define INIT_ORDER_INSTRUMENTS 18
#define INIT_ORDER_RESEARCH 17 // SoonTM
#define INIT_ORDER_VIS 16
#define INIT_ORDER_STATION 15 //This is high priority because it manipulates a lot of the subsystems that will initialize after it.
#define INIT_ORDER_EVENTS 14
#define INIT_ORDER_JOBS 13
@@ -100,6 +101,7 @@
#define FIRE_PRIORITY_TICKETS 10
#define FIRE_PRIORITY_RESEARCH 10 // SoonTM
#define FIRE_PRIORITY_AMBIENCE 10
#define FIRE_PRIORITY_VIS 10
#define FIRE_PRIORITY_GARBAGE 15
#define FIRE_PRIORITY_AIR 20
#define FIRE_PRIORITY_NPC 20
+19
View File
@@ -529,6 +529,25 @@ GLOBAL_LIST_EMPTY(bicon_cache)
var/icon/I = getFlatIcon(thing)
return icon2asset(I, target)
/// Returns a list containing the width and height of an icon file
/proc/get_icon_dimensions(icon_path)
if(isnull(GLOB.icon_dimensions[icon_path]))
var/icon/my_icon = icon(icon_path)
GLOB.icon_dimensions[icon_path] = list("width" = my_icon.Width(), "height" = my_icon.Height())
return GLOB.icon_dimensions[icon_path]
/// Returns an x and y value require to reverse the transformations made to center an oversized icon
/atom/proc/get_oversized_icon_offsets()
if(pixel_x == 0 && pixel_y == 0)
return list("x" = 0, "y" = 0)
var/list/icon_dimensions = get_icon_dimensions(icon)
var/icon_width = icon_dimensions["width"]
var/icon_height = icon_dimensions["height"]
return list(
"x" = icon_width > world.icon_size && pixel_x != 0 ? (icon_width - world.icon_size) * 0.5 : 0,
"y" = icon_height > world.icon_size && pixel_y != 0 ? (icon_height - world.icon_size) * 0.5 : 0,
)
/// Slimifies an icon by painting a color onto the icon, then changing the alpha.
/icon/proc/slimify(color = "#FFFFFF", alpha = "FF")
GrayScale()
+15 -4
View File
@@ -330,7 +330,7 @@
msg_admin_attack("[key_name_admin(user)] vs [target_info]: [what_done]", loglevel)
/proc/do_mob(mob/user, mob/target, time = 30, progress = 1, list/extra_checks = list(), only_use_extra_checks = FALSE, requires_upright = TRUE)
/proc/do_mob(mob/user, mob/target, time = 30, progress = 1, list/extra_checks = list(), only_use_extra_checks = FALSE, requires_upright = TRUE, hidden = FALSE)
if(!user || !target)
return 0
var/user_loc = user.loc
@@ -343,9 +343,13 @@
var/holding = user.get_active_hand()
var/datum/progressbar/progbar
var/datum/cogbar/cog
if(progress)
progbar = new(user, time, target)
if(!hidden && time >= 1 SECONDS)
cog = new(user)
var/endtime = world.time+time
var/starttime = world.time
. = 1
@@ -376,6 +380,7 @@
break
if(progress)
qdel(progbar)
cog?.remove()
/* 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.
@@ -387,8 +392,9 @@
*
* 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)
* param {boolean} hidden - By default, any action 1 second or longer shows a cog over the user while it is in progress. If hidden is set to TRUE, the cog will not be shown.
*/
/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1, allow_moving = 0, must_be_held = 0, list/extra_checks = list(), use_default_checks = TRUE, allow_moving_target = FALSE)
/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1, allow_moving = 0, must_be_held = 0, list/extra_checks = list(), use_default_checks = TRUE, allow_moving_target = FALSE, hidden = FALSE)
if(!user)
return FALSE
var/atom/Tloc = null
@@ -408,9 +414,13 @@
holdingnull = FALSE //Users hand started holding something, check to see if it's still holding that
var/datum/progressbar/progbar
var/datum/cogbar/cog
if(progress)
progbar = new(user, delay, target)
if(!hidden && delay >= 1 SECONDS)
cog = new(user)
var/endtime = world.time + delay
var/starttime = world.time
. = TRUE
@@ -457,6 +467,7 @@
break
if(progress)
qdel(progbar)
cog?.remove()
// Upon any of the callbacks in the list returning TRUE, the proc will return TRUE.
/proc/check_for_true_callbacks(list/extra_checks)
@@ -467,7 +478,7 @@
#define DOAFTERONCE_MAGIC "Magic~~"
GLOBAL_LIST_EMPTY(do_after_once_tracker)
/proc/do_after_once(mob/user, delay, needhand = 1, atom/target = null, progress = 1, allow_moving, must_be_held, attempt_cancel_message = "Attempt cancelled.", special_identifier)
/proc/do_after_once(mob/user, delay, needhand = 1, atom/target = null, progress = 1, allow_moving, must_be_held, attempt_cancel_message = "Attempt cancelled.", special_identifier, hidden = FALSE)
if(!user || !target)
return
@@ -477,7 +488,7 @@ GLOBAL_LIST_EMPTY(do_after_once_tracker)
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, allow_moving, must_be_held, extra_checks = list(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(do_after_once_checks), cache_key)))
. = do_after(user, delay, needhand, target, progress, allow_moving, must_be_held, extra_checks = list(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(do_after_once_checks), cache_key, hidden)))
GLOB.do_after_once_tracker[cache_key] = FALSE
/proc/do_after_once_checks(cache_key)
+2
View File
@@ -0,0 +1,2 @@
/// Cache of the width and height of icon files, to avoid repeating the same expensive operation
GLOBAL_LIST_EMPTY(icon_dimensions)
+10
View File
@@ -61,6 +61,16 @@
if(istype(mymob) && mymob.client && mymob.client.prefs)
alpha = (mymob.client.prefs.toggles2 & PREFTOGGLE_2_THOUGHT_BUBBLE) ? 255 : 0
/atom/movable/screen/plane_master/cogbar
name = "cogbar plane master"
plane = COGBAR_PLANE
appearance_flags = PLANE_MASTER //should use client color
blend_mode = BLEND_OVERLAY
/atom/movable/screen/plane_master/cogbar/backdrop(mob/mymob)
if(istype(mymob) && mymob.client?.prefs)
alpha = (mymob.client.prefs.toggles3 & PREFTOGGLE_3_COGBAR_ANIMATIONS) ? 255 : 0
/**
* Things placed on this mask the lighting plane. Doesn't render directly.
*
@@ -0,0 +1,130 @@
/**
* # SSvis_overlays
*
* This subsystem handles visual overlays for objects in the game world.
*
* It manages the creation, caching, and removal of visual overlays, allowing for dynamic visual effects
* associated with various atoms. Overlays can be reused if they are not unique, and they are automatically
* cleaned up if they go unused for a specified duration.
*/
SUBSYSTEM_DEF(vis_overlays)
name = "Vis contents overlays"
wait = 1 MINUTES
priority = FIRE_PRIORITY_VIS
init_order = INIT_ORDER_VIS
/// Cache for visual overlays
var/list/vis_overlay_cache
/// List of currently processed overlays during a run
var/list/currentrun
/datum/controller/subsystem/vis_overlays/Initialize()
vis_overlay_cache = list()
/datum/controller/subsystem/vis_overlays/fire(resumed = FALSE)
if(!resumed)
currentrun = vis_overlay_cache.Copy()
var/list/current_run = currentrun
while(length(current_run))
var/key = current_run[current_run.len]
var/obj/effect/overlay/vis/overlay = current_run[key]
current_run.len--
if(!overlay.unused && !length(overlay.vis_locs))
overlay.unused = world.time
else if(overlay.unused && overlay.unused + overlay.cache_expiration < world.time)
vis_overlay_cache -= key
qdel(overlay)
if(MC_TICK_CHECK)
return
/**
* Adds a visual overlay to a given atom.
*
* This procedure creates and adds a visual overlay to the specified object. It can either create a unique
* overlay or reuse an existing one based on the provided parameters.
*
* Arguments:
* * thing - The atom to which the overlay will be added. The "thing" var can be anything with vis_contents which includes images
* * icon - The icon to display for the overlay.
* * iconstate - The state of the icon.
* * layer - The layer on which the overlay will be rendered.
* * plane - The plane for the overlay.
* * dir - The direction the overlay faces.
* * alpha - The transparency level of the overlay (default is 255).
* * add_appearance_flags - Additional flags for overlay appearance (default is NONE).
* * unique - A boolean indicating if the overlay should be unique (default is FALSE).
*
* Returns the overlay that was added.
*/
/datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha = 255, add_appearance_flags = NONE, unique = FALSE)
var/obj/effect/overlay/vis/overlay
if(!unique)
. = "[icon]|[iconstate]|[layer]|[plane]|[dir]|[alpha]|[add_appearance_flags]"
overlay = vis_overlay_cache[.]
if(!overlay)
overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags)
vis_overlay_cache[.] = overlay
else
overlay.unused = 0
else
overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags)
overlay.cache_expiration = -1
var/cache_id = "[text_ref(overlay)]@{[world.time]}"
vis_overlay_cache[cache_id] = overlay
. = overlay
thing.vis_contents += overlay
if(!isatom(thing)) // Automatic rotation is not supported on non atoms
return overlay
if(!thing.managed_vis_overlays)
thing.managed_vis_overlays = list(overlay)
else
thing.managed_vis_overlays += overlay
return overlay
/**
* Creates a new visual overlay with the specified parameters.
*
* This procedure initializes a new visual overlay object with the given attributes.
*
* Arguments:
* * icon - The icon to display for the overlay.
* * iconstate - The state of the icon.
* * layer - The layer on which the overlay will be rendered.
* * plane - The plane for the overlay.
* * dir - The direction the overlay faces.
* * alpha - The transparency level of the overlay.
* * add_appearance_flags - Additional flags for overlay appearance.
*
* Returns the newly created overlay.
*/
/datum/controller/subsystem/vis_overlays/proc/_create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags)
var/obj/effect/overlay/vis/overlay = new
overlay.icon = icon
overlay.icon_state = iconstate
overlay.layer = layer
overlay.plane = plane
overlay.dir = dir
overlay.alpha = alpha
overlay.appearance_flags |= add_appearance_flags
return overlay
/**
* Removes specified visual overlays from an atom.
*
* This procedure removes the given overlays from the atom's visual contents and also updates the
* managed overlays list if applicable.
*
* Arguments:
* * thing - The atom from which the overlays will be removed.
* * overlays - A list of overlays to remove.
*/
/datum/controller/subsystem/vis_overlays/proc/remove_vis_overlay(atom/movable/thing, list/overlays)
thing.vis_contents -= overlays
if(!isatom(thing))
return
thing.managed_vis_overlays -= overlays
if(!length(thing.managed_vis_overlays))
thing.managed_vis_overlays = null
+119
View File
@@ -0,0 +1,119 @@
#define COGBAR_ANIMATION_TIME (0.5 SECONDS)
/**
* # Cogbar
* Represents that the user is busy doing something.
*
* The cogbar is a visual representation in the game that indicates to other players
* that a user is currently busy with an action. This class handles the creation,
* display, and removal of the cog animation.
*/
/datum/cogbar
/// Who's doing the thing
var/mob/user
/// The user client
var/client/user_client
/// The visible element to other players
var/obj/effect/overlay/vis/cog
/// The blank image that overlaps the cog - hides it from the source user
var/image/blank
/// The offset of the icon
var/offset_y
// Class constructor
/**
* Initializes a new instance of the cogbar for the specified user.
*
* This constructor sets up the user and user client properties, adds the cog overlay
* to the user, and registers a signal to handle user deletion.
*
* @param user - The user for whom the cogbar is created.
*/
/datum/cogbar/New(mob/user)
src.user = user
src.user_client = user.client
var/list/icon_offsets = user.get_oversized_icon_offsets()
offset_y = icon_offsets["y"]
add_cog_to_user()
RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(on_user_delete))
// Destructor
/**
* Cleans up the cogbar instance, removing overlays and images associated with the user.
*
* This method ensures that all visual elements are properly removed when the cogbar instance is destroyed
*/
/datum/cogbar/Destroy()
if(user)
SSvis_overlays.remove_vis_overlay(user, user.managed_vis_overlays)
user_client?.images -= blank
user = null
user_client = null
cog = null
QDEL_NULL(blank)
return ..()
/// Adds the cog to the user, visible by other players
/**
* Adds the cog overlay to the user, making it visible to other players.
*
* This function creates the cog overlay with appropriate properties and
* initiates the animation to fade it in. Additionally, a blank image is
* added to the user's client to hide the cog from the user's own perspective.
*/
/datum/cogbar/proc/add_cog_to_user()
cog = SSvis_overlays.add_vis_overlay(user,
icon = 'icons/effects/progressbar.dmi',
iconstate = "cog",
plane = COGBAR_PLANE,
add_appearance_flags = APPEARANCE_UI_IGNORE_ALPHA,
unique = TRUE,
alpha = 0,
)
cog.pixel_y = world.icon_size + offset_y
animate(cog, alpha = 255, time = COGBAR_ANIMATION_TIME)
if(isnull(user_client))
return
blank = image('icons/blanks/32x32.dmi', cog, "nothing")
blank.plane = HUD_PLANE
blank.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
blank.override = TRUE
user_client.images += blank
/// Removes the cog from the user
/**
* Initiates the removal process for the cog overlay.
*
* This function fades out the cog overlay and schedules the cogbar instance
* for deletion after the animation completes.
*/
/datum/cogbar/proc/remove()
if(isnull(cog))
qdel(src)
return
animate(cog, alpha = 0, time = COGBAR_ANIMATION_TIME)
QDEL_IN(src, COGBAR_ANIMATION_TIME)
/// When the user is deleted, remove the cog
/**
* Handles the cleanup when the associated user is deleted.
*
* This function is triggered by a signal and ensures that the cogbar instance is properly destroyed
*/
/datum/cogbar/proc/on_user_delete(datum/source)
SIGNAL_HANDLER // COMSIG_PARENT_QDELETING
qdel(src)
#undef COGBAR_ANIMATION_TIME
+1 -1
View File
@@ -14,7 +14,7 @@
EXCEPTION("Invalid target given")
if(goal_number)
goal = goal_number
bar = image('icons/effects/progessbar.dmi', target, "prog_bar_0", ABOVE_HUD_LAYER)
bar = image('icons/effects/progressbar.dmi', target, "prog_bar_0", ABOVE_HUD_LAYER)
bar.alpha = 0
bar.plane = ABOVE_HUD_PLANE
bar.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
+3
View File
@@ -42,6 +42,9 @@
/// Value used to increment ex_act() if reactionary_explosions is on
var/explosion_block = 0
///vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays.
var/list/managed_vis_overlays
// Detective Work, used for the duplicate data points kept in the scanners
var/list/original_atom
/// List of fibers that this atom has
@@ -865,7 +865,7 @@
user.playsound_local(user, "sparks", 50, FALSE, use_reverb = FALSE)
adjust_uses(-1, user)
robot_target.audible_message("<span class='italics'>You hear a loud electrical buzzing sound coming from [robot_target]!</span>")
if(!do_mob(user, robot_target, 10 SECONDS))
if(!do_mob(user, robot_target, 10 SECONDS, hidden = TRUE))
is_active = FALSE
return
is_active = FALSE
@@ -229,7 +229,7 @@
if(!occupant)
return
to_chat(occupant, "<span class='warning'>You start trying to break free!</span>")
if(!do_after_once(occupant, 20 SECONDS, FALSE, src))
if(!do_after_once(occupant, 20 SECONDS, FALSE, src, hidden = TRUE))
return
var/list/possible_results = list(
CALLBACK(src, PROC_REF(electrocute_abductee)) = 1,
+9
View File
@@ -68,3 +68,12 @@
layer = FLOAT_LAYER
vis_flags = VIS_INHERIT_ID
appearance_flags = KEEP_TOGETHER | LONG_GLIDE | PIXEL_SCALE
/obj/effect/overlay/vis
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
anchored = TRUE
vis_flags = VIS_INHERIT_DIR
///When detected to be unused it gets set to world.time, after a while it gets removed
var/unused = 0
///overlays which go unused for this amount of time get cleaned up
var/cache_expiration = 2 MINUTES
@@ -392,7 +392,7 @@
to_chat(user, "<span class='danger'>The mind batterer has been burnt out!</span>")
times_used--
return
if(!do_after_once(user, 2 SECONDS, target = src, allow_moving = TRUE, attempt_cancel_message = "You think it's best to save this for later."))
if(!do_after_once(user, 2 SECONDS, target = src, allow_moving = TRUE, attempt_cancel_message = "You think it's best to save this for later.", hidden = TRUE))
times_used--
return
to_chat(user, "<span class='notice'>You trigger [src]. It has [max_uses-times_used] charges left.</span>")
+1 -1
View File
@@ -12,7 +12,7 @@
user.visible_message("<span class='warning'>[user] attempts to [break_cuffs ? "break" : "remove"] [src]!</span>", "<span class='notice'>You attempt to [break_cuffs ? "break" : "remove"] [src]...</span>")
to_chat(user, "<span class='notice'>(This will take around [DisplayTimeText(effective_breakout_time)] and you need to stand still.)</span>")
if(!do_after(user, effective_breakout_time, FALSE, user))
if(!do_after(user, effective_breakout_time, FALSE, user, hidden = TRUE))
user.remove_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
to_chat(user, "<span class='warning'>You fail to [break_cuffs ? "break" : "remove"] [src]!</span>")
return
+1 -1
View File
@@ -224,7 +224,7 @@
L.update_inv_l_hand()
spinning = TRUE
for(var/i in 1 to max_spins)
if(!do_mob(L, L, 1 SECONDS, only_use_extra_checks = TRUE, extra_checks = list(CALLBACK(src, PROC_REF(can_spin_check), L))))
if(!do_mob(L, L, 1 SECONDS, only_use_extra_checks = TRUE, extra_checks = list(CALLBACK(src, PROC_REF(can_spin_check), L)), hidden = TRUE))
reset_values(L)
break
throw_range += range_increment
+1 -1
View File
@@ -258,7 +258,7 @@
return ..()
to_chat(user, "<span class='warning'>You begin gathering strength...</span>")
playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1)
if(do_after(user, 90, target = user))
if(do_after(user, 9 SECONDS, target = user, hidden = TRUE))
to_chat(user, "<span class='userdanger'>You gather power! Time for a home run!</span>")
homerun_ready = 1
..()
@@ -154,7 +154,7 @@
"<span class='notice'>You struggle to break free from [src], exacerbating your wounds! (Stay still for two minutes.)</span>",\
"<span class='italics'>You hear a wet squishing noise..</span>")
M.adjustBruteLoss(30)
if(!do_after(M, 2 MINUTES, target = src))
if(!do_after(M, 2 MINUTES, target = src, hidden = TRUE))
if(M && M.buckled)
to_chat(M, "<span class='warning'>You fail to free yourself!</span>")
return
+1 -1
View File
@@ -101,7 +101,7 @@ GLOBAL_LIST_EMPTY(safes)
if(!drill_timer)
return
cut_overlay(progress_bar)
progress_bar = image('icons/effects/progessbar.dmi', src, "prog_bar_[round((((world.time - drill_start_time) / time_to_drill) * 100), 5)]", HUD_LAYER)
progress_bar = image('icons/effects/progressbar.dmi', src, "prog_bar_[round((((world.time - drill_start_time) / time_to_drill) * 100), 5)]", HUD_LAYER)
add_overlay(progress_bar)
if(prob(DRILL_SPARK_CHANCE))
drill.spark_system.start()
@@ -33,7 +33,7 @@
M.visible_message("<span class='warning'>[M.name] struggles to break free from the gelatinous resin!</span>",\
"<span class='notice'>You struggle to break free from the gelatinous resin... (Stay still for two minutes.)</span>",\
"<span class='italics'>You hear squelching...</span>")
if(!do_after(M, 120 SECONDS, target = src))
if(!do_after(M, 120 SECONDS, target = src, hidden = TRUE))
if(M && M.buckled)
to_chat(M, "<span class='warning'>You fail to escape \the [src]!</span>")
return
@@ -27,7 +27,7 @@
is_operating = FALSE
return FALSE
user.visible_message("<span class='danger'>[user] begins vomiting an arachnid!</span>")
if(do_after(user, 4 SECONDS, FALSE, target = user)) // Takes 4 seconds to spawn a spider
if(do_after(user, 4 SECONDS, FALSE, target = user, hidden = TRUE)) // Takes 4 seconds to spawn a spider
spider_counter++
user.visible_message("<span class='danger'>[user] vomits up an arachnid!</span>")
var/mob/living/simple_animal/hostile/poison/giant_spider/hunter/infestation_spider/S = new(user.loc)
@@ -134,7 +134,7 @@
"<span class='sinister'>We begin our harvest on [H].</span>",
"<span class='notice'>You hear the hum of electricity.</span>"
)
if(!do_mob(owner.current, H, time = 2 SECONDS))
if(!do_mob(owner.current, H, time = 2 SECONDS, hidden = TRUE))
send_swarm_message("Our connection was incomplete.")
harvesting = null
return
@@ -201,7 +201,7 @@
to_chat(user, "<span class='notice'>Your override attempt fails before it can even begin.</span>")
qdel(src)
return
if(!do_mob(user, borg, conversion_time))
if(!do_mob(user, borg, conversion_time, hidden = TRUE))
to_chat(user, "<span class='notice'>Your concentration breaks.</span>")
qdel(src)
return
@@ -253,7 +253,7 @@
M.visible_message("<span class='notice'>[M] starts entering a cryptic series of characters on [U].</span>",\
"<span class='notice'>You start entering an extraction signal to your handlers on [U]...</span>")
if(do_after(M, EXTRACTION_PHASE_PREPARE, target = M))
if(do_after(M, EXTRACTION_PHASE_PREPARE, target = M, hidden = TRUE))
if(!U.Adjacent(M) || extraction_deadline > world.time)
return
var/obj/effect/contractor_flare/F = new(get_turf(M))
@@ -113,7 +113,7 @@ RESTRICT_TYPE(/datum/antagonist/vampire)
H.LAssailant = null
else
H.LAssailant = owner
while(do_mob(owner.current, H, suck_rate))
while(do_mob(owner.current, H, suck_rate, hidden = TRUE))
owner.current.do_attack_animation(H, ATTACK_EFFECT_BITE)
if(unique_suck_id in drained_humans)
if(drained_humans[unique_suck_id] >= BLOOD_DRAIN_LIMIT)
@@ -28,7 +28,7 @@
var/mob/living/target = targets[1]
user.visible_message("<span class='warning'>[user] bites [target]'s neck!</span>", "<span class='warning'>You bite [target]'s neck and begin the flow of power.</span>")
to_chat(target, "<span class='warning'>You feel the tendrils of evil invade your mind.</span>")
if(do_mob(user, target, 15 SECONDS))
if(do_mob(user, target, 15 SECONDS, hidden = TRUE))
if(can_enthrall(user, target))
handle_enthrall(user, target)
var/datum/spell_handler/vampire/V = custom_handler
@@ -140,7 +140,7 @@
if(!making_anchor && !anchor) // first cast, setup the anchor
var/turf/anchor_turf = get_turf(user)
making_anchor = TRUE
if(do_mob(user, user, 5 SECONDS, only_use_extra_checks = TRUE)) // no checks, cant fail
if(do_mob(user, user, 5 SECONDS, only_use_extra_checks = TRUE, hidden = TRUE)) // no checks, cant fail
make_anchor(user, anchor_turf)
making_anchor = FALSE
return
@@ -1011,6 +1011,12 @@
var/atom/movable/screen/plane_master/point/PM = locate(/atom/movable/screen/plane_master/point) in parent.screen
PM.backdrop(parent.mob)
if("cogbar")
toggles3 ^= PREFTOGGLE_3_COGBAR_ANIMATIONS
if(length(parent?.screen))
var/atom/movable/screen/plane_master/cogbar/PM = locate(/atom/movable/screen/plane_master/cogbar) in parent.screen
PM.backdrop(parent.mob)
if("be_special")
var/r = href_list["role"]
if(r in GLOB.special_roles)
@@ -481,6 +481,7 @@ GLOBAL_LIST_INIT(special_role_times, list(
dat += "<b>Set screentip mode:</b> <a href='byond://?_src_=prefs;preference=screentip_mode'>[(screentip_mode == 0) ? "Disabled" : "[screentip_mode]px"]</a><br>"
dat += "<b>Screentip color:</b> <span style='border: 1px solid #161616; background-color: [screentip_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='byond://?_src_=prefs;preference=screentip_color'><b>Change</b></a><br>"
dat += "<b>Thought Bubble when pointing:</b> <a href='byond://?_src_=prefs;preference=thought_bubble'>[(toggles2 & PREFTOGGLE_2_THOUGHT_BUBBLE) ? "Yes" : "No"]</a><br>"
dat += "<b>Cogbar indicators:</b> <a href='byond://?_src_=prefs;preference=cogbar'>[(toggles3 & PREFTOGGLE_3_COGBAR_ANIMATIONS) ? "Yes" : "No"]</a><br>"
dat += "<b>Custom UI settings:</b><br>"
dat += " - <b>Alpha (transparency):</b> <a href='byond://?_src_=prefs;preference=UIalpha'><b>[UI_style_alpha]</b></a><br>"
dat += " - <b>Color:</b> <a href='byond://?_src_=prefs;preference=UIcolor'><b>[UI_style_color]</b></a> <span style='border: 1px solid #161616; background-color: [UI_style_color];'>&nbsp;&nbsp;&nbsp;</span><br>"
+1 -1
View File
@@ -882,7 +882,7 @@
user.visible_message("<span class='warning'>[user] attempts to [break_restraints ? "break" : "remove"] [src]!</span>", "<span class='notice'>You attempt to [break_restraints ? "break" : "remove"] [src]...</span>")
to_chat(user, "<span class='notice'>(This will take around [DisplayTimeText(effective_breakout_time)] and you need to stand still.)</span>")
if(!do_after(user, effective_breakout_time, FALSE, user))
if(!do_after(user, effective_breakout_time, FALSE, user, hidden = TRUE))
user.remove_status_effect(STATUS_EFFECT_REMOVE_CUFFS)
to_chat(user, "<span class='warning'>You fail to [break_restraints ? "break" : "remove"] [src]!</span>")
return
+1 -1
View File
@@ -68,7 +68,7 @@
add_attack_logs(A, D, "Put into a chokehold with martial-art [src]", ATKLOG_ALL)
chokehold_active = TRUE
var/damage_multiplier = 1 + D.getStaminaLoss() / 100 //The chokehold is more effective the more tired the target is.
while(do_mob(A, D, 2 SECONDS) && chokehold_active)
while(do_mob(A, D, 2 SECONDS, hidden = TRUE) && chokehold_active)
D.apply_damage(10 * damage_multiplier, OXY)
D.LoseBreath(3 SECONDS)
if(D.getOxyLoss() >= 50 || D.health <= 20)
@@ -865,7 +865,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
visible_message("<span class='warning'>[src] attempts to unbuckle [p_themselves()]!</span>",
"<span class='notice'>You attempt to unbuckle yourself... (This will take around [breakout_time / 10] seconds and you need to stay still.)</span>")
if(!do_after(src, breakout_time, FALSE, src, allow_moving = TRUE, extra_checks = list(CALLBACK(src, PROC_REF(buckle_check))), allow_moving_target = TRUE))
if(!do_after(src, breakout_time, FALSE, src, allow_moving = TRUE, extra_checks = list(CALLBACK(src, PROC_REF(buckle_check))), allow_moving_target = TRUE, hidden = TRUE))
if(src && buckled)
to_chat(src, "<span class='warning'>You fail to unbuckle yourself!</span>")
else
@@ -931,7 +931,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
apply_status_effect(STATUS_EFFECT_REMOVE_MUZZLE)
visible_message("<span class='warning'>[src] gnaws on [I], trying to remove it!</span>")
to_chat(src, "<span class='notice'>You attempt to remove [I]... (This will take around [time/10] seconds and you need to stand still.)</span>")
if(do_after(src, time, FALSE, src, extra_checks = list(CALLBACK(src, PROC_REF(muzzle_check)))))
if(do_after(src, time, FALSE, src, extra_checks = list(CALLBACK(src, PROC_REF(muzzle_check))), hidden = TRUE))
visible_message("<span class='warning'>[src] removes [I]!</span>")
to_chat(src, "<span class='notice'>You get rid of [I]!</span>")
if(I.security_lock)
@@ -91,7 +91,7 @@ STATUS EFFECTS
if(stat == DEAD && !work_when_dead)
return
if(!instant && !do_mob(src, src, 1 SECONDS, extra_checks = list(CALLBACK(src, TYPE_PROC_REF(/mob/living, cannot_stand))), only_use_extra_checks = TRUE))
if(!instant && !do_mob(src, src, 1 SECONDS, extra_checks = list(CALLBACK(src, TYPE_PROC_REF(/mob/living, cannot_stand))), only_use_extra_checks = TRUE, hidden = TRUE))
return
if(resting || body_position == STANDING_UP || HAS_TRAIT(src, TRAIT_FLOORED))
return
@@ -48,7 +48,7 @@
/mob/living/simple_animal/hostile/headslug/AltClickOn(mob/living/carbon/carbon_target)
if(egg_layed || !istype(carbon_target) || !Adjacent(carbon_target) || ismachineperson(carbon_target))
return ..()
if(carbon_target.stat != DEAD && !do_mob(src, carbon_target, 5 SECONDS))
if(carbon_target.stat != DEAD && !do_mob(src, carbon_target, 5 SECONDS, hidden = TRUE))
return
if(HAS_TRAIT(carbon_target, TRAIT_XENO_HOST))
to_chat(src, "<span class='userdanger'>A foreign presence repels us from this body. Perhaps we should try to infest another?</span>")
+1 -1
View File
@@ -524,7 +524,7 @@
else
to_chat(src, "<span class='notice'>You are now trying to get up.</span>")
if(!do_mob(src, src, 1 SECONDS, extra_checks = list(CALLBACK(src, TYPE_PROC_REF(/mob/living, cannot_stand))), only_use_extra_checks = TRUE))
if(!do_mob(src, src, 1 SECONDS, extra_checks = list(CALLBACK(src, TYPE_PROC_REF(/mob/living, cannot_stand))), only_use_extra_checks = TRUE, hidden = TRUE))
return
if(resting)
Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 559 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 B

+3
View File
@@ -227,6 +227,7 @@
#include "code\_globalvars\lists\dye_registry.dm"
#include "code\_globalvars\lists\flavor_misc.dm"
#include "code\_globalvars\lists\fortunes.dm"
#include "code\_globalvars\lists\icons.dm"
#include "code\_globalvars\lists\keybindings_lists.dm"
#include "code\_globalvars\lists\maint_loot_tables.dm"
#include "code\_globalvars\lists\misc_lists.dm"
@@ -352,6 +353,7 @@
#include "code\controllers\subsystem\SStime_track.dm"
#include "code\controllers\subsystem\SStimer.dm"
#include "code\controllers\subsystem\SSverb_manager.dm"
#include "code\controllers\subsystem\SSvis_overlays.dm"
#include "code\controllers\subsystem\SSvote.dm"
#include "code\controllers\subsystem\SSweather.dm"
#include "code\controllers\subsystem\movement\movement_types.dm"
@@ -398,6 +400,7 @@
#include "code\datums\chat_payload.dm"
#include "code\datums\chatmessage.dm"
#include "code\datums\click_intercept.dm"
#include "code\datums\cogbar.dm"
#include "code\datums\custom_user_item.dm"
#include "code\datums\datacore.dm"
#include "code\datums\datum.dm"