From dc3fd79427afe3b8f8ca0b2c92c209eb7292e30e Mon Sep 17 00:00:00 2001 From: ShadowLarkens Date: Sat, 26 Oct 2024 04:20:54 -0700 Subject: [PATCH] The final action buttons PR (#16514) * Make action button target datum * Initial working action palette * Action related refactors * tgstation/tgstation/pull/71339 --- code/__defines/action.dm | 13 + code/__defines/dcs/signals.dm | 12 + code/__defines/flags.dm | 16 + .../hud/_defines.dm => __defines/hud.dm} | 11 + code/__defines/math.dm | 1 + code/_helpers/weakref.dm | 2 + code/_onclick/hud/_defines_vr.dm | 3 - code/_onclick/hud/action/action.dm | 488 ++++++++------ code/_onclick/hud/action/action_group.dm | 212 ++++++ .../hud/action/action_group_helpers.dm | 41 ++ .../hud/action/action_item_overlay.dm | 73 +++ .../hud/action/action_screen_objects.dm | 613 ++++++++++++------ code/_onclick/hud/action/innate_action.dm | 20 + code/_onclick/hud/action/item_action.dm | 37 ++ code/_onclick/hud/action/positioning.dm | 49 ++ code/_onclick/hud/action/types/item.dm | 1 - code/_onclick/hud/hud.dm | 47 +- code/_onclick/hud/movable_screen_objects.dm | 1 + .../technomancer/devices/shield_armor.dm | 2 +- .../technomancer/devices/tesla_armor.dm | 4 +- code/game/mecha/mecha_actions.dm | 29 +- code/game/objects/items.dm | 77 ++- code/game/objects/items/devices/flashlight.dm | 2 +- code/game/objects/items/weapons/shields_vr.dm | 2 +- .../objects/items/weapons/tanks/jetpack.dm | 2 +- code/modules/ai/ai_holder.dm | 3 +- code/modules/catalogue/cataloguer.dm | 2 +- code/modules/client/client procs.dm | 6 + code/modules/clothing/clothing.dm | 3 +- code/modules/clothing/glasses/glasses.dm | 8 +- code/modules/clothing/glasses/glasses_vr.dm | 2 +- code/modules/clothing/glasses/hud_vr.dm | 4 +- code/modules/clothing/head/helmet_vr.dm | 4 +- code/modules/clothing/head/misc_special.dm | 2 +- code/modules/clothing/masks/miscellaneous.dm | 4 +- code/modules/clothing/shoes/magboots.dm | 4 +- code/modules/mob/living/carbon/carbon.dm | 2 +- code/modules/mob/living/death.dm | 2 +- code/modules/mob/living/living.dm | 2 +- code/modules/mob/login.dm | 5 +- .../projectiles/guns/projectile/shotgun_vr.dm | 2 +- .../vore/fluffstuff/custom_clothes_vr.dm | 4 +- icons/hud/64x16_actions.dmi | Bin 0 -> 3920 bytes icons/hud/screen_gen.dmi | Bin 0 -> 112316 bytes icons/mob/actions/backgrounds.dmi | Bin 0 -> 12167 bytes vorestation.dme | 10 +- 46 files changed, 1374 insertions(+), 453 deletions(-) rename code/{_onclick/hud/_defines.dm => __defines/hud.dm} (94%) create mode 100644 code/_helpers/weakref.dm delete mode 100644 code/_onclick/hud/_defines_vr.dm create mode 100644 code/_onclick/hud/action/action_group.dm create mode 100644 code/_onclick/hud/action/action_group_helpers.dm create mode 100644 code/_onclick/hud/action/action_item_overlay.dm create mode 100644 code/_onclick/hud/action/innate_action.dm create mode 100644 code/_onclick/hud/action/item_action.dm create mode 100644 code/_onclick/hud/action/positioning.dm create mode 100644 icons/hud/64x16_actions.dmi create mode 100644 icons/hud/screen_gen.dmi create mode 100644 icons/mob/actions/backgrounds.dmi diff --git a/code/__defines/action.dm b/code/__defines/action.dm index 3f9b8a5e414..25babfe3906 100644 --- a/code/__defines/action.dm +++ b/code/__defines/action.dm @@ -2,3 +2,16 @@ #define AB_CHECK_STUNNED 2 #define AB_CHECK_LYING 4 #define AB_CHECK_CONSCIOUS 8 + +///Action button triggered with right click +#define TRIGGER_SECONDARY_ACTION (1<<0) +///Action triggered to ignore any availability checks +#define TRIGGER_FORCE_AVAILABLE (1<<1) + +#define ACTION_BUTTON_DEFAULT_BACKGROUND "_use_ui_default_background" + +#define UPDATE_BUTTON_NAME (1<<0) +#define UPDATE_BUTTON_ICON (1<<1) +#define UPDATE_BUTTON_BACKGROUND (1<<2) +#define UPDATE_BUTTON_OVERLAY (1<<3) +#define UPDATE_BUTTON_STATUS (1<<4) diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm index 2623cadaafb..5faf4792d7f 100644 --- a/code/__defines/dcs/signals.dm +++ b/code/__defines/dcs/signals.dm @@ -191,6 +191,8 @@ #define COMSIG_ENTER_AREA "enter_area" ///from base of area/Exited(): (/area) #define COMSIG_EXIT_AREA "exit_area" +///from base of client/Click(): (atom/target, atom/location, control, params, mob/user) +#define COMSIG_CLIENT_CLICK "atom_client_click" ///from base of atom/Click(): (location, control, params, mob/user) #define COMSIG_CLICK "atom_click" ///from base of atom/ShiftClick(): (/mob) @@ -714,6 +716,16 @@ ///from base of datum/action/proc/Trigger(): (datum/action) #define COMSIG_ACTION_TRIGGER "action_trigger" #define COMPONENT_ACTION_BLOCK_TRIGGER (1<<0) +/// From /datum/action/Grant(): (mob/grant_to) +#define COMSIG_ACTION_GRANTED "action_grant" +/// From /datum/action/Remove(): (mob/removed_from) +#define COMSIG_ACTION_REMOVED "action_removed" +/// From /datum/action/Grant(): (datum/action) +#define COMSIG_MOB_GRANTED_ACTION "mob_action_grant" +/// From /datum/action/Remove(): (datum/action) +#define COMSIG_MOB_REMOVED_ACTION "mob_action_removed" +/// From /datum/action/apply_button_overlay() +#define COMSIG_ACTION_OVERLAY_APPLY "action_overlay_applied" //Xenobio hotkeys diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm index 57f148b02b4..7864c08d18e 100644 --- a/code/__defines/flags.dm +++ b/code/__defines/flags.dm @@ -56,3 +56,19 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define TASK_TARGET_EXCLUSIVE (1<<1) #define TASK_USER_EXCLUSIVE (1<<2) #define TASK_ALL_EXCLUSIVE TASK_TARGET_EXCLUSIVE | TASK_USER_EXCLUSIVE + +// Update flags for [/atom/proc/update_appearance] +/// Update the atom's name +#define UPDATE_NAME (1<<0) +/// Update the atom's desc +#define UPDATE_DESC (1<<1) +/// Update the atom's icon state +#define UPDATE_ICON_STATE (1<<2) +/// Update the atom's overlays +#define UPDATE_OVERLAYS (1<<3) +/// Update the atom's greyscaling +#define UPDATE_GREYSCALE (1<<4) +/// Update the atom's smoothing. (More accurately, queue it for an update) +#define UPDATE_SMOOTHING (1<<5) +/// Update the atom's icon +#define UPDATE_ICON (UPDATE_ICON_STATE|UPDATE_OVERLAYS) diff --git a/code/_onclick/hud/_defines.dm b/code/__defines/hud.dm similarity index 94% rename from code/_onclick/hud/_defines.dm rename to code/__defines/hud.dm index b39c71a7d23..84f45706abe 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/__defines/hud.dm @@ -200,3 +200,14 @@ #define ui_mech_deco2_f "WEST+2:-7, SOUTH+9" #define ui_smallquad "EAST-4:22,SOUTH:5" + +//Upper left (action buttons) +#define ui_action_palette "WEST+0:23,NORTH-1:5" +#define ui_action_palette_offset(north_offset) ("WEST+0:23,NORTH-[1+north_offset]:5") + +#define ui_palette_scroll "WEST+1:8,NORTH-6:28" +#define ui_palette_scroll_offset(north_offset) ("WEST+1:8,NORTH-[6+north_offset]:28") + +#define ui_shadekin_display "EAST-1:28,CENTER-3:15" +#define ui_lleill_display "EAST-1:28,CENTER-3:15" +#define ui_xenochimera_danger_display "EAST-1:28,CENTER-3:15" diff --git a/code/__defines/math.dm b/code/__defines/math.dm index 7b5fcd8c7a5..f4539605f22 100644 --- a/code/__defines/math.dm +++ b/code/__defines/math.dm @@ -25,6 +25,7 @@ #define SIGN(x) ( (x)!=0 ? (x) / abs(x) : 0 ) +#define ROUND_UP(x) ( -round(-(x))) #define CEILING(x, y) ( -round(-(x) / (y)) * (y) ) // round() acts like floor(x, 1) by default but can't handle other values diff --git a/code/_helpers/weakref.dm b/code/_helpers/weakref.dm new file mode 100644 index 00000000000..25b65e63ecd --- /dev/null +++ b/code/_helpers/weakref.dm @@ -0,0 +1,2 @@ +/// Checks if potential_weakref is a weakref of thing. +#define IS_WEAKREF_OF(thing, potential_weakref) (isdatum(thing) && !isnull(potential_weakref) && thing.weak_reference == potential_weakref) diff --git a/code/_onclick/hud/_defines_vr.dm b/code/_onclick/hud/_defines_vr.dm deleted file mode 100644 index 82d0af8b028..00000000000 --- a/code/_onclick/hud/_defines_vr.dm +++ /dev/null @@ -1,3 +0,0 @@ -#define ui_shadekin_display "EAST-1:28,CENTER-3:15" -#define ui_lleill_display "EAST-1:28,CENTER-3:15" -#define ui_xenochimera_danger_display "EAST-1:28,CENTER-3:15" \ No newline at end of file diff --git a/code/_onclick/hud/action/action.dm b/code/_onclick/hud/action/action.dm index d1f4441c7db..a5a512be689 100644 --- a/code/_onclick/hud/action/action.dm +++ b/code/_onclick/hud/action/action.dm @@ -1,96 +1,130 @@ +/** + * # Action system + * + * A simple base for an modular behavior attached to atom or datum. + */ /datum/action + /// The name of the action var/name = "Generic Action" - var/desc = null - - var/atom/movable/target = null - + /// The description of what the action does, shown in button tooltips + var/desc + /// The target the action is attached to. If the target datum is deleted, the action is as well. + /// Set in New() via the proc link_to(). PLEASE set a target if you're making an action + var/datum/target + /// Where any buttons we create should be by default. Accepts screen_loc and location defines + var/default_button_position = SCRN_OBJ_IN_LIST + /// This is who currently owns the action, and most often, this is who is using the action if it is triggered + /// This can be the same as "target" but is not ALWAYS the same - this is set and unset with Grant() and Remove() + var/mob/owner + /// Flags that will determine of the owner / user of the action can... use the action var/check_flags = NONE - var/processing = FALSE - - var/obj/screen/movable/action_button/button = null - - var/button_icon = 'icons/mob/actions.dmi' - var/background_icon_state = "bg_default" - var/buttontooltipstyle = "" + /// Whether the button becomes transparent when it can't be used or just reddened var/transparent_when_unavailable = TRUE + /// List of all mobs that are viewing our action button -> A unique movable for them to view. + var/list/viewers = list() + /// If TRUE, this action button will be shown to observers / other mobs who view from this action's owner's eyes. + /// Used in [/mob/proc/show_other_mob_action_buttons] + /// (Not really, this behavior is unimplemented) + var/show_to_observers = TRUE - var/icon_icon = 'icons/mob/actions.dmi' + /// The style the button's tooltips appear to be + var/buttontooltipstyle = "" + + /// This is the file for the BACKGROUND underlay icon of the button + var/background_icon = 'icons/mob/actions/backgrounds.dmi' + /// This is the icon state state for the BACKGROUND underlay icon of the button + /// (If set to ACTION_BUTTON_DEFAULT_BACKGROUND, uses the hud's default background) + var/background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND + + /// This is the file for the icon that appears on the button + var/button_icon = 'icons/mob/actions.dmi' + /// This is the icon state for the icon that appears on the button var/button_icon_state = "default" - var/mob/owner + /// This is the file for any FOREGROUND overlay icons on the button (such as borders) + var/overlay_icon = 'icons/mob/actions/backgrounds.dmi' + /// This is the icon state for any FOREGROUND overlay icons on the button (such as borders) + var/overlay_icon_state /datum/action/New(Target) link_to(Target) - button = new - button.linked_action = src - button.name = name - button.actiontooltipstyle = buttontooltipstyle - if(desc) - button.desc = desc +/// Links the passed target to our action, registering any relevant signals /datum/action/proc/link_to(Target) target = Target - RegisterSignal(Target, COMSIG_ATOM_UPDATED_ICON, .proc/OnUpdatedIcon) + RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref), override = TRUE) + + if(isatom(target)) + RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, PROC_REF(on_target_icon_update)) + + // if(istype(target, /datum/mind)) + // RegisterSignal(target, COMSIG_MIND_TRANSFERRED, .proc/on_target_mind_swapped) /datum/action/Destroy() if(owner) Remove(owner) target = null - QDEL_NULL(button) + QDEL_LIST_ASSOC_VAL(viewers) return ..() -/datum/action/proc/Grant(mob/M) - if(M) - if(owner) - if(owner == M) - return - Remove(owner) - owner = M +/// Signal proc that clears any references based on the owner or target deleting +/// If the owner's deleted, we will simply remove from them, but if the target's deleted, we will self-delete +/datum/action/proc/clear_ref(datum/ref) + SIGNAL_HANDLER + if(ref == owner) + Remove(owner) + if(ref == target) + qdel(src) - // button id generation - var/counter = 0 - var/bitfield = 0 - for(var/datum/action/A as anything in M.actions) - if(A.name == name && A.button.id) - counter += 1 - bitfield |= A.button.id - bitfield = !bitfield - var/bitflag = 1 - for(var/i in 1 to (counter + 1)) - if(bitfield & bitflag) - button.id = bitflag - break - bitflag *= 2 - - LAZYADD(M.actions, src) - if(M.client) - M.client.screen += button - button.locked = /* M.client.prefs.buttons_locked || */ button.id ? LAZYACCESS(M.client.prefs.action_button_screen_locs, "[name]_[button.id]") : FALSE //even if its not defaultly locked we should remember we locked it before - button.moved = button.id ? LAZYACCESS(M.client.prefs.action_button_screen_locs, "[name]_[button.id]") : FALSE - M.update_action_buttons(TRUE) - else +/// Grants the action to the passed mob, making it the owner +/datum/action/proc/Grant(mob/grant_to) + if(!grant_to) + Remove(owner) + return + if(owner) + if(owner == grant_to) + return Remove(owner) -/datum/action/proc/Remove(mob/M) - if(M) - if(M.client) - M.client.screen -= button - button.moved = FALSE - LAZYREMOVE(M.actions, src) - M.update_action_buttons(TRUE) - owner = null - button.moved = FALSE //so the button appears in its normal position when given to another owner. - button.locked = FALSE - button.id = null + SEND_SIGNAL(src, COMSIG_ACTION_GRANTED, grant_to) + SEND_SIGNAL(grant_to, COMSIG_MOB_GRANTED_ACTION, src) + owner = grant_to + RegisterSignal(owner, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref), override = TRUE) -/datum/action/proc/Trigger() + GiveAction(grant_to) + +/// Remove the passed mob from being owner of our action +/datum/action/proc/Remove(mob/remove_from) + SHOULD_CALL_PARENT(TRUE) + + for(var/datum/hud/hud in viewers) + if(!hud.mymob) + continue + HideFrom(hud.mymob) + LAZYREMOVE(remove_from.actions, src) // We aren't always properly inserted into the viewers list, gotta make sure that action's cleared + viewers = list() + + if(owner) + SEND_SIGNAL(src, COMSIG_ACTION_REMOVED, owner) + SEND_SIGNAL(owner, COMSIG_MOB_REMOVED_ACTION, src) + + UnregisterSignal(owner, COMSIG_PARENT_QDELETING) + if(target == owner) + RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref)) + + owner = null + +/// Actually triggers the effects of the action. +/// Called when the on-screen button is clicked, for example. +/datum/action/proc/Trigger(trigger_flags) if(!IsAvailable()) return FALSE if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER) return FALSE return TRUE +/// Whether our action is currently available to use or not /datum/action/proc/IsAvailable() if(!owner) return FALSE @@ -108,147 +142,207 @@ return FALSE return TRUE -/datum/action/proc/UpdateButtonIcon(status_only = FALSE, force = FALSE) +/// Builds / updates all buttons we have shared or given out +/datum/action/proc/build_all_button_icons(update_flags = ALL, force) + for(var/datum/hud/hud as anything in viewers) + build_button_icon(viewers[hud], update_flags, force) + +/** + * Builds the icon of the button. + * + * Concept: + * - Underlay (Background icon) + * - Icon (button icon) + * - Maptext + * - Overlay (Background border) + * + * button - which button we are modifying the icon of + * force - whether we're forcing a full update + */ +/datum/action/proc/build_button_icon(obj/screen/movable/action_button/button, update_flags = ALL, force = FALSE) + if(!button) + return + + if(update_flags & UPDATE_BUTTON_NAME) + update_button_name(button, force) + + if(update_flags & UPDATE_BUTTON_BACKGROUND) + apply_button_background(button, force) + + if(update_flags & UPDATE_BUTTON_ICON) + apply_button_icon(button, force) + + if(update_flags & UPDATE_BUTTON_OVERLAY) + apply_button_overlay(button, force) + + if(update_flags & UPDATE_BUTTON_STATUS) + update_button_status(button, force) + +/** + * Updates the name and description of the button to match our action name and discription. + * + * current_button - what button are we editing? + * force - whether an update is forced regardless of existing status + */ +/datum/action/proc/update_button_name(obj/screen/movable/action_button/button, force = FALSE) + button.name = name + if(desc) + button.desc = desc + +/** + * Creates the background underlay for the button + * + * current_button - what button are we editing? + * force - whether an update is forced regardless of existing status + */ +/datum/action/proc/apply_button_background(obj/screen/movable/action_button/current_button, force = FALSE) + if(!background_icon || !background_icon_state || (current_button.active_underlay_icon_state == background_icon_state && !force)) + return + + // What icons we use for our background + var/list/icon_settings = list( + // The icon file + "bg_icon" = background_icon, + // The icon state, if is_action_active() returns FALSE + "bg_state" = background_icon_state, + // The icon state, if is_action_active() returns TRUE + "bg_state_active" = background_icon_state, + ) + + // If background_icon_state is ACTION_BUTTON_DEFAULT_BACKGROUND instead use our hud's action button scheme + if(background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND && owner?.hud_used) + icon_settings = owner.hud_used.get_action_buttons_icons() + + // Determine which icon to use + var/used_icon_key = is_action_active(current_button) ? "bg_state_active" : "bg_state" + + // Make the underlay + current_button.underlays.Cut() + current_button.underlays += image(icon = icon_settings["bg_icon"], icon_state = icon_settings[used_icon_key]) + current_button.active_underlay_icon_state = icon_settings[used_icon_key] + +/** + * Applies our button icon and icon state to the button + * + * current_button - what button are we editing? + * force - whether an update is forced regardless of existing status + */ +/datum/action/proc/apply_button_icon(obj/screen/movable/action_button/current_button, force = FALSE) + if(!button_icon || !button_icon_state || (current_button.icon_state == button_icon_state && !force)) + return + + current_button.icon = button_icon + current_button.icon_state = button_icon_state + +/** + * Applies any overlays to our button + * + * current_button - what button are we editing? + * force - whether an update is forced regardless of existing status + */ +/datum/action/proc/apply_button_overlay(obj/screen/movable/action_button/current_button, force = FALSE) + SEND_SIGNAL(src, COMSIG_ACTION_OVERLAY_APPLY, current_button, force) + + if(!overlay_icon || !overlay_icon_state || (current_button.active_overlay_icon_state == overlay_icon_state && !force)) + return + + current_button.cut_overlay(current_button.button_overlay) + current_button.button_overlay = mutable_appearance(icon = overlay_icon, icon_state = overlay_icon_state) + current_button.add_overlay(current_button.button_overlay) + current_button.active_overlay_icon_state = overlay_icon_state + +/** + * Any other miscellaneous "status" updates within the action button is handled here, + * such as redding out when unavailable or modifying maptext. + * + * current_button - what button are we editing? + * force - whether an update is forced regardless of existing status + */ +/datum/action/proc/update_button_status(obj/screen/movable/action_button/current_button, force = FALSE) + if(IsAvailable()) + current_button.color = rgb(255,255,255,255) + else + current_button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0) + +/// Gives our action to the passed viewer. +/// Puts our action in their actions list and shows them the button. +/datum/action/proc/GiveAction(mob/viewer) + var/datum/hud/our_hud = viewer.hud_used + if(viewers[our_hud]) // Already have a copy of us? go away + return + + LAZYOR(viewer.actions, src) // Move this in + ShowTo(viewer) + +/// Adds our action button to the screen of the passed viewer. +/datum/action/proc/ShowTo(mob/viewer) + var/datum/hud/our_hud = viewer.hud_used + if(!our_hud || viewers[our_hud]) // There's no point in this if you have no hud in the first place + return + + var/obj/screen/movable/action_button/button = create_button() + SetId(button, viewer) + + button.our_hud = our_hud + viewers[our_hud] = button + if(viewer.client) + viewer.client.screen += button + + button.load_position(viewer) + viewer.update_action_buttons() + +/// Removes our action from the passed viewer. +/datum/action/proc/HideFrom(mob/viewer) + var/datum/hud/our_hud = viewer.hud_used + var/obj/screen/movable/action_button/button = viewers[our_hud] + LAZYREMOVE(viewer.actions, src) if(button) - if(!status_only) - button.name = name - button.desc = desc + qdel(button) - // if(owner && owner.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND) - // var/list/settings = owner.hud_used.get_action_buttons_icons() - // if(button.icon != settings["bg_icon"]) - // button.icon = settings["bg_icon"] - // if(button.icon_state != settings["bg_state"]) - // button.icon_state = settings["bg_state"] - // else +/// Creates an action button movable for the passed mob, and returns it. +/datum/action/proc/create_button() + var/obj/screen/movable/action_button/button = new() + button.linked_action = src + build_button_icon(button, ALL, TRUE) + return button - if(button.icon != button_icon) - button.icon = button_icon - if(button.icon_state != background_icon_state) - button.icon_state = background_icon_state +/datum/action/proc/SetId(obj/screen/movable/action_button/our_button, mob/owner) + //button id generation + var/bitfield = 0 + for(var/datum/action/action in owner.actions) + if(action == src) // This could be us, which is dumb + continue + var/obj/screen/movable/action_button/button = action.viewers[owner.hud_used] + if(action.name == name && button.id) + bitfield |= button.id - ApplyIcon(button, force) + bitfield = ~bitfield // Flip our possible ids, so we can check if we've found a unique one + for(var/i in 0 to 23) // We get 24 possible bitflags in dm + var/bitflag = 1 << i // Shift us over one + if(bitfield & bitflag) + our_button.id = bitflag + return - if(!IsAvailable()) - button.color = transparent_when_unavailable ? rgb(128, 0, 0, 128) : rgb(128, 0, 0) - else - button.color = rgb(255, 255, 255, 255) - return TRUE - -/datum/action/proc/ApplyIcon(obj/screen/movable/action_button/current_button, force = FALSE) - if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force)) - current_button.cut_overlays(TRUE) - current_button.add_overlay(mutable_appearance(icon_icon, button_icon_state)) - current_button.button_icon_state = button_icon_state - -// Currently never triggered -/datum/action/proc/OnUpdatedIcon() +/// Updates our buttons if our target's icon was updated +/// Still never triggered lmao +/datum/action/proc/on_target_icon_update(datum/source, updates, updated) SIGNAL_HANDLER - UpdateButtonIcon() -//Presets for item actions -/datum/action/item_action - check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_CONSCIOUS - button_icon_state = null - // If you want to override the normal icon being the item - // then change this to an icon state + var/update_flag = NONE + var/forced = FALSE + if(updates & UPDATE_ICON_STATE) + update_flag |= UPDATE_BUTTON_ICON + forced = TRUE + if(updates & UPDATE_OVERLAYS) + update_flag |= UPDATE_BUTTON_OVERLAY + forced = TRUE + if(updates & (UPDATE_NAME|UPDATE_DESC)) + update_flag |= UPDATE_BUTTON_NAME + // Status is not relevant, and background is not relevant. Neither will change -/datum/action/item_action/New(Target) - . = ..() - var/obj/item/I = target - LAZYADD(I.actions, src) + // Force the update if an icon state or overlay change was done + build_all_button_icons(update_flag, forced) -/datum/action/item_action/Destroy() - var/obj/item/I = target - LAZYREMOVE(I.actions, src) - return ..() - -/datum/action/item_action/Trigger() - if(!..()) - return 0 - if(target) - var/obj/item/I = target - I.ui_action_click(owner, src.type) - return 1 - -/datum/action/item_action/ApplyIcon(obj/screen/movable/action_button/current_button, force) - if(button_icon && button_icon_state) - // If set, use the custom icon that we set instead - // of the item appearence - return ..() - else if(target && ((current_button.appearance_cache != target.appearance) || force)) - var/mutable_appearance/ma = new(target.appearance) - ma.plane = FLOAT_PLANE - ma.layer = FLOAT_LAYER - ma.pixel_x = 0 - ma.pixel_y = 0 - - current_button.cut_overlays() - current_button.add_overlay(ma) - current_button.appearance_cache = target.appearance - -/datum/action/item_action/hands_free - check_flags = AB_CHECK_CONSCIOUS - - -/datum/action/innate - check_flags = NONE - var/active = 0 - -/datum/action/innate/Trigger() - if(!..()) - return 0 - if(!active) - Activate() - else - Deactivate() - return 1 - -/datum/action/innate/proc/Activate() - return - -/datum/action/innate/proc/Deactivate() - return - -//Preset for an action with a cooldown -/datum/action/cooldown - check_flags = NONE - transparent_when_unavailable = FALSE - var/cooldown_time = 0 - var/next_use_time = 0 - -/datum/action/cooldown/New() - ..() - button.maptext = "" - button.maptext_x = 8 - button.maptext_y = 0 - button.maptext_width = 24 - button.maptext_height = 12 - -/datum/action/cooldown/IsAvailable() - return next_use_time <= world.time - -/datum/action/cooldown/proc/StartCooldown() - next_use_time = world.time + cooldown_time - button.maptext = span_maptext(span_bold("[round(cooldown_time/10, 0.1)]")) - UpdateButtonIcon() - START_PROCESSING(SSfastprocess, src) - -/datum/action/cooldown/process() - if(!owner) - button.maptext = "" - STOP_PROCESSING(SSfastprocess, src) - var/timeleft = max(next_use_time - world.time, 0) - if(timeleft == 0) - button.maptext = "" - UpdateButtonIcon() - STOP_PROCESSING(SSfastprocess, src) - else - button.maptext = span_maptext(span_bold("[round(timeleft/10, 0.1)]")) - -/datum/action/cooldown/Grant(mob/M) - ..() - if(owner) - UpdateButtonIcon() - if(next_use_time > world.time) - START_PROCESSING(SSfastprocess, src) +/// Checks if our action is actively selected. Used for selecting icons primarily. +/datum/action/proc/is_action_active(obj/screen/movable/action_button/current_button) + return FALSE diff --git a/code/_onclick/hud/action/action_group.dm b/code/_onclick/hud/action/action_group.dm new file mode 100644 index 00000000000..d0b2f8df114 --- /dev/null +++ b/code/_onclick/hud/action/action_group.dm @@ -0,0 +1,212 @@ +/datum/action_group + /// The hud we're owned by + var/datum/hud/owner + /// The actions we're managing + var/list/obj/screen/movable/action_button/actions + /// The initial vertical offset of our action buttons + var/north_offset = 0 + /// The pixel vertical offset of our action buttons + var/pixel_north_offset = 0 + /// Max amount of buttons we can have per row + /// Indexes at 1 + var/column_max = 0 + /// How far "ahead" of the first row we start. Lets us "scroll" our rows + /// Indexes at 1 + var/row_offset = 0 + /// How many rows of actions we can have at max before we just stop hiding + /// Indexes at 1 + var/max_rows = INFINITY + /// The screen location we go by + var/location + /// Our landing screen object + var/obj/screen/action_landing/landing + +/datum/action_group/New(datum/hud/owner) + ..() + actions = list() + src.owner = owner + +/datum/action_group/Destroy() + owner = null + QDEL_NULL(landing) + QDEL_LIST(actions) + return ..() + +/datum/action_group/proc/insert_action(obj/screen/action, index) + if(action in actions) + if(actions[index] == action) + return + actions -= action // Don't dupe, come on + if(!index) + index = length(actions) + 1 + index = min(length(actions) + 1, index) + actions.Insert(index, action) + refresh_actions() + +/datum/action_group/proc/remove_action(obj/screen/action) + actions -= action + if(!QDELING(src)) + refresh_actions() + +/datum/action_group/proc/refresh_actions() + // We don't use size() here because landings are not canon + var/total_rows = ROUND_UP(length(actions) / column_max) + total_rows -= max_rows // Lets get the amount of rows we're off from our max + row_offset = clamp(row_offset, 0, total_rows) // You're not allowed to offset so far that we have a row of blank space + + var/button_number = 0 + for(var/obj/screen/button as anything in actions) + var/postion = ButtonNumberToScreenCoords(button_number ) + button.screen_loc = postion + button_number++ + + if(landing) + var/postion = ButtonNumberToScreenCoords(button_number, landing = TRUE) // Need a good way to count buttons off screen, but allow this to display in the right place if it's being placed with no concern for dropdown + landing.screen_loc = postion + button_number++ + +/// Accepts a number represeting our position in the group, indexes at 0 to make the math nicer +/datum/action_group/proc/ButtonNumberToScreenCoords(number, landing = FALSE) + var/row = round(number / column_max) + row -= row_offset // If you're less then 0, you don't get to render, this lets us "scroll" rows ya feel? + if(row < 0) + return null + + // Could use >= here, but I think it's worth noting that the two start at different places, since row is based on number here + if(row > max_rows - 1) + if(!landing) // If you're not a landing, go away please. thx + return null + // We always want to render landings, even if their action button can't be displayed. + // So we set a row equal to the max amount of rows + 1. Willing to overrun that max slightly to properly display the landing spot + row = max_rows // Remembering that max_rows indexes at 1, and row indexes at 0 + + // We're going to need to set our column to match the first item in the last row, so let's set number properly now + number = row * column_max + + var/visual_row = row + north_offset + var/coord_row = visual_row ? "-[visual_row]" : "+0" + + var/visual_column = number % column_max + var/coord_col = "+[visual_column]" + var/coord_col_offset = 4 + 2 * (visual_column + 1) + return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:-[pixel_north_offset]" + +/datum/action_group/proc/check_against_view() + var/owner_view = owner?.mymob?.client?.view + if(!owner_view) + return + // Unlikey as it is, we may have been changed. Want to start from our target position and fail down + column_max = initial(column_max) + // Convert our viewer's view var into a workable offset + var/list/view_size = view_to_pixels(owner_view) + + // We're primarially concerned about width here, if someone makes us 1x2000 I wish them a swift and watery death + var/furthest_screen_loc = ButtonNumberToScreenCoords(column_max - 1) + var/list/offsets = screen_loc_to_offset(furthest_screen_loc, owner_view) + if(offsets[1] > world.icon_size && offsets[1] < view_size[1] && offsets[2] > world.icon_size && offsets[2] < view_size[2]) // We're all good + return + + for(column_max in column_max - 1 to 1 step -1) // Yes I could do this by unwrapping ButtonNumberToScreenCoords, but I don't feel like it + var/tested_screen_loc = ButtonNumberToScreenCoords(column_max) + offsets = screen_loc_to_offset(tested_screen_loc, owner_view) + // We've found a valid max length, pack it in + if(offsets[1] > world.icon_size && offsets[1] < view_size[1] && offsets[2] > world.icon_size && offsets[2] < view_size[2]) + break + // Use our newly resized column max + refresh_actions() + +/// Returns the amount of objects we're storing at the moment +/datum/action_group/proc/size() + var/amount = length(actions) + if(landing) + amount += 1 + return amount + +/datum/action_group/proc/index_of(obj/screen/get_location) + return actions.Find(get_location) + +/// Generates a landing object that can be dropped on to join this group +/datum/action_group/proc/generate_landing() + if(landing) + return + landing = new() + landing.set_owner(src) + refresh_actions() + +/// Clears any landing objects we may currently have +/datum/action_group/proc/clear_landing() + QDEL_NULL(landing) + +/datum/action_group/proc/update_landing() + if(!landing) + return + landing.refresh_owner() + +/datum/action_group/proc/scroll(amount) + row_offset += amount + refresh_actions() + +/datum/action_group/palette + north_offset = 2 + column_max = 3 + max_rows = 3 + location = SCRN_OBJ_IN_PALETTE + +/datum/action_group/palette/insert_action(obj/screen/action, index) + . = ..() + var/obj/screen/button_palette/palette = owner.toggle_palette + palette.play_item_added() + +/datum/action_group/palette/remove_action(obj/screen/action) + . = ..() + var/obj/screen/button_palette/palette = owner.toggle_palette + palette.play_item_removed() + if(!length(actions)) + palette.set_expanded(FALSE) + +/datum/action_group/palette/refresh_actions() + var/obj/screen/button_palette/palette = owner.toggle_palette + var/obj/screen/palette_scroll/scroll_down = owner.palette_down + var/obj/screen/palette_scroll/scroll_up = owner.palette_up + if(!palette || !scroll_down || !scroll_up) + return + + var/actions_above = round((owner.listed_actions.size() - 1) / owner.listed_actions.column_max) + north_offset = initial(north_offset) + actions_above + + palette.screen_loc = ui_action_palette_offset(actions_above) + var/action_count = length(owner?.mymob?.actions) + var/our_row_count = round((length(actions) - 1) / column_max) + if(!action_count) + palette.screen_loc = null + + if(palette.expanded && action_count && our_row_count >= max_rows) + scroll_down.screen_loc = ui_palette_scroll_offset(actions_above) + scroll_up.screen_loc = ui_palette_scroll_offset(actions_above) + else + scroll_down.screen_loc = null + scroll_up.screen_loc = null + + return ..() + +/datum/action_group/palette/ButtonNumberToScreenCoords(number, landing) + var/obj/screen/button_palette/palette = owner.toggle_palette + if(palette.expanded) + return ..() + + if(!landing) + return null + + // We only render the landing in this case, so we force it to be the second item displayed (Second rather then first since it looks nicer) + // Remember the number var indexes at 0 + return ..(1 + (row_offset * column_max), landing) + + +/datum/action_group/listed + pixel_north_offset = 6 + column_max = 10 + location = SCRN_OBJ_IN_LIST + +/datum/action_group/listed/refresh_actions() + . = ..() + owner?.palette_actions.refresh_actions() // We effect them, so we gotta refresh em diff --git a/code/_onclick/hud/action/action_group_helpers.dm b/code/_onclick/hud/action/action_group_helpers.dm new file mode 100644 index 00000000000..14ca7194333 --- /dev/null +++ b/code/_onclick/hud/action/action_group_helpers.dm @@ -0,0 +1,41 @@ +/// Generates visual landings for all groups that the button is not a memeber of +/datum/hud/proc/generate_landings(obj/screen/movable/action_button/button) + listed_actions.generate_landing() + palette_actions.generate_landing() + +/// Clears all currently visible landings +/datum/hud/proc/hide_landings() + listed_actions.clear_landing() + palette_actions.clear_landing() + +// Updates any existing "owned" visuals, ensures they continue to be visible +/datum/hud/proc/update_our_owner() + toggle_palette.refresh_owner() + palette_down.refresh_owner() + palette_up.refresh_owner() + listed_actions.update_landing() + palette_actions.update_landing() + +/// Ensures all of our buttons are properly within the bounds of our client's view, moves them if they're not +/datum/hud/proc/view_audit_buttons() + var/our_view = mymob?.client?.view + if(!our_view) + return + listed_actions.check_against_view() + palette_actions.check_against_view() + for(var/obj/screen/movable/action_button/floating_button as anything in floating_actions) + var/list/current_offsets = screen_loc_to_offset(floating_button.screen_loc) + // We set the view arg here, so the output will be properly hemm'd in by our new view + floating_button.screen_loc = offset_to_screen_loc(current_offsets[1], current_offsets[2], view = our_view) + +/// Generates and fills new action groups with our mob's current actions +/datum/hud/proc/build_action_groups() + listed_actions = new(src) + palette_actions = new(src) + floating_actions = list() + for(var/datum/action/action as anything in mymob.actions) + var/obj/screen/movable/action_button/button = action.viewers[src] + if(!button) + action.ShowTo(mymob) + button = action.viewers[src] + position_action(button, button.location) diff --git a/code/_onclick/hud/action/action_item_overlay.dm b/code/_onclick/hud/action/action_item_overlay.dm new file mode 100644 index 00000000000..7d1af7309ef --- /dev/null +++ b/code/_onclick/hud/action/action_item_overlay.dm @@ -0,0 +1,73 @@ +/** + * Apply to an action to allow it to take an item + * and apply it as an overlay of the action button + */ +/datum/component/action_item_overlay + /// Weakref to what item the component uses to apply as an overlay. + var/datum/weakref/item_ref + /// Callback that dictates what item the component uses to apply as an overlay. + var/datum/callback/item_callback + + /// The appearance of the item we've applied + var/mutable_appearance/item_appearance + +/datum/component/action_item_overlay/Initialize(atom/movable/item, datum/callback/item_callback) + if(!istype(parent, /datum/action)) + return COMPONENT_INCOMPATIBLE + + if(!item && !item_callback) + stack_trace("[type] created without a reference item or an item callback - one or the other is required.") + return COMPONENT_INCOMPATIBLE + + src.item_ref = WEAKREF(item) + src.item_callback = item_callback + +/datum/component/action_item_overlay/Destroy(force, silent) + item_ref = null + QDEL_NULL(item_callback) + item_appearance = null + return ..() + +/datum/component/action_item_overlay/RegisterWithParent() + RegisterSignal(parent, COMSIG_ACTION_OVERLAY_APPLY, PROC_REF(on_overlays_applied)) + + var/datum/action/parent_action = parent + parent_action.build_all_button_icons(UPDATE_BUTTON_OVERLAY) + +/datum/component/action_item_overlay/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_ACTION_OVERLAY_APPLY) + + // If we're being unregistered / deleted but our parent is sticking around, + // force an overlay update to get rid of our item appearance + if(!QDELING(parent)) + var/datum/action/parent_action = parent + parent_action.build_all_button_icons(UPDATE_BUTTON_OVERLAY) + +/// Signal proc for [COMSIG_ACTION_OVERLAY_APPLY], applies the item appearance if possible. +/datum/component/action_item_overlay/proc/on_overlays_applied(datum/action/source, obj/screen/movable/action_button/current_button, force) + SIGNAL_HANDLER + + // We're in the middle of being removed / deleted, remove our associated overlay + if(QDELING(src) && item_appearance) + current_button.cut_overlay(item_appearance) + item_appearance = null + return + + var/atom/movable/muse = item_callback?.Invoke() || item_ref?.resolve() + if(!istype(muse)) + return + + if(item_appearance) + // For caching purposes, we will try not to update if we don't need to + if(!force && item_appearance.icon == muse.icon && item_appearance.icon_state == muse.icon_state) + return + current_button.cut_overlay(item_appearance) + + var/mutable_appearance/muse_appearance = new(muse.appearance) + muse_appearance.plane = FLOAT_PLANE + muse_appearance.layer = FLOAT_LAYER + muse_appearance.pixel_x = 0 + muse_appearance.pixel_y = 0 + + current_button.add_overlay(muse_appearance) + item_appearance = muse_appearance diff --git a/code/_onclick/hud/action/action_screen_objects.dm b/code/_onclick/hud/action/action_screen_objects.dm index fd64a38d571..503274f86f7 100644 --- a/code/_onclick/hud/action/action_screen_objects.dm +++ b/code/_onclick/hud/action/action_screen_objects.dm @@ -1,39 +1,48 @@ - /obj/screen/movable/action_button var/datum/action/linked_action + var/datum/hud/our_hud var/actiontooltipstyle = "" screen_loc = null + icon = null // we don't use the base icon at all, just underlays and overlays - var/button_icon_state - var/appearance_cache + /// The icon state of our active overlay, used to prevent re-applying identical overlays + var/active_overlay_icon_state + /// The icon state of our active underlay, used to prevent re-applying identical underlays + var/active_underlay_icon_state + /// The overlay we have overtop our button + var/mutable_appearance/button_overlay + /// Where we are currently placed on the hud. SCRN_OBJ_DEFAULT asks the linked action what it thinks + var/location = SCRN_OBJ_DEFAULT + /// A unique bitflag, combined with the name of our linked action this lets us persistently remember any user changes to our position var/id + /// A weakref of the last thing we hovered over + /// God I hate how dragging works + var/datum/weakref/last_hovored_ref + +/obj/screen/movable/action_button/Destroy() + if(our_hud) + var/mob/viewer = our_hud.mymob + our_hud.hide_action(src) + viewer?.client?.screen -= src + linked_action.viewers -= our_hud + viewer.update_action_buttons() + our_hud = null + linked_action = null + return ..() /obj/screen/movable/action_button/proc/can_use(mob/user) - if(linked_action) - return linked_action.owner == user - else if(isobserver(user)) - // var/mob/dead/observer/O = user - // return !O.observetarget - return TRUE - else - return TRUE + // if(isobserver(user)) + // var/mob/dead/observer/dead_mob = user + // if(dead_mob.observetarget) // Observers can only click on action buttons if they're not observing something + // return FALSE -/obj/screen/movable/action_button/MouseDrop(over_object) - if(!can_use(usr)) - return - if((istype(over_object, /obj/screen/movable/action_button) && !istype(over_object, /obj/screen/movable/action_button/hide_toggle))) - if(locked) - to_chat(usr, span_warning("Action button \"[name]\" is locked, unlock it first.")) - return - var/obj/screen/movable/action_button/B = over_object - var/list/actions = usr.actions - actions.Swap(actions.Find(src.linked_action), actions.Find(B.linked_action)) - moved = FALSE - B.moved = FALSE - usr.update_action_buttons() - else - return ..() + if(linked_action) + if(linked_action.viewers[user.hud_used]) + return TRUE + return FALSE + + return TRUE /obj/screen/movable/action_button/Click(location,control,params) if(!can_use(usr)) @@ -41,108 +50,40 @@ var/list/modifiers = params2list(params) if(LAZYACCESS(modifiers, SHIFT_CLICK)) - if(locked) - to_chat(usr, span_warning("Action button \"[name]\" is locked, unlock it first.")) - return TRUE - moved = FALSE - usr.update_action_buttons() - return TRUE - if(LAZYACCESS(modifiers, CTRL_CLICK)) - locked = !locked - to_chat(usr, span_notice("Action button \"[name]\" [locked ? "" : "un"]locked.")) - if(id && usr?.client?.prefs) // try to (un)remember position - LAZYSET(usr.client.prefs.action_button_screen_locs, "[name]_[id]", locked ? moved : null) + var/datum/hud/our_hud = usr.hud_used + our_hud.position_action(src, SCRN_OBJ_DEFAULT) return TRUE if(!usr.checkClickCooldown()) return usr.setClickCooldown(1) - linked_action.Trigger() + var/trigger_flags + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + trigger_flags |= TRIGGER_SECONDARY_ACTION + linked_action.Trigger(trigger_flags = trigger_flags) return TRUE -//Hide/Show Action Buttons ... Button -/obj/screen/movable/action_button/hide_toggle - name = "Hide Buttons" - desc = "Shift-click any button to reset its position, and Control-click it to lock it in place. Alt-click this button reset all buttons to their default positions." - icon = 'icons/mob/actions.dmi' - icon_state = "bg_default" - var/hidden = FALSE - -// /obj/screen/movable/action_button/hide_toggle/Initialize() -// . = ..() -// var/static/list/icon_cache = list() - -// var/cache_key = "[hide_icon][hide_state]" -// hide_appearance = icon_cache[cache_key] -// if(!hide_appearance) -// hide_appearance = icon_cache[cache_key] = mutable_appearance(hide_icon, hide_state) -// cache_key = "[hide_icon][show_state]" -// show_appearance = icon_cache[cache_key] -// if(!show_appearance) -// show_appearance = icon_cache[cache_key] = mutable_appearance(hide_icon, show_state) - -/obj/screen/movable/action_button/hide_toggle/Click(location, control, params) +// Entered and Exited won't fire while you're dragging something, because you're still "holding" it +// Very much byond logic, but I want nice behavior, so we fake it with drag +/obj/screen/movable/action_button/MouseDrag(atom/over_object, src_location, over_location, src_control, over_control, params) + . = ..() if(!can_use(usr)) - return FALSE + return + if(IS_WEAKREF_OF(over_object, last_hovored_ref)) + return - var/list/modifiers = params2list(params) - if(LAZYACCESS(modifiers, SHIFT_CLICK)) - if(locked) - to_chat(usr, span_warning("Action button \"[name]\" is locked, unlock it first.")) - return TRUE - moved = FALSE - usr.update_action_buttons(TRUE) - return TRUE - if(LAZYACCESS(modifiers, CTRL_CLICK)) - locked = !locked - to_chat(usr, span_notice("Action button \"[name]\" [locked ? "" : "un"]locked.")) - if(id && usr?.client?.prefs) // try to (un)remember position - LAZYSET(usr.client.prefs.action_button_screen_locs, "[name]_[id]", locked ? moved : null) - return TRUE - if(LAZYACCESS(modifiers, ALT_CLICK)) - AltClick(usr) - return TRUE + var/atom/old_object + if(last_hovored_ref) + old_object = last_hovored_ref.resolve() + else // If there is no current ref, we assume it was us. We also treat this as our "first go" location. + old_object = src + var/datum/hud/our_hud = usr.hud_used + our_hud?.generate_landings(src) - usr.hud_used.action_buttons_hidden = !usr.hud_used.action_buttons_hidden + if(old_object) + old_object.MouseExited(over_location, over_control, params) - hidden = usr.hud_used.action_buttons_hidden - if(hidden) - name = "Show Buttons" - else - name = "Hide Buttons" - update_icon() - usr.update_action_buttons() - -/obj/screen/movable/action_button/hide_toggle/AltClick(mob/user) - for(var/datum/action/A as anything in user.actions) - var/obj/screen/movable/action_button/B = A.button - B.moved = FALSE - if(B.id && usr?.client?.prefs) - LAZYSET(usr.client.prefs.action_button_screen_locs, "[name]_[B.id]", null) - // B.locked = usr.client.prefs.buttons_locked - // locked = usr.client.prefs.buttons_locked - if(id && usr?.client?.prefs) - LAZYSET(usr.client.prefs.action_button_screen_locs, "[name]_[id]", null) - moved = FALSE - user.update_action_buttons(TRUE) - to_chat(user, span_notice("Action button positions have been reset.")) - -/obj/screen/movable/action_button/hide_toggle/proc/InitialiseIcon(mob/user) - // var/settings = owner_hud.get_action_buttons_icons() - // icon = settings["bg_icon"] - // icon_state = settings["bg_state"] - // hide_icon = settings["toggle_icon"] - // hide_state = settings["toggle_hide"] - // show_state = settings["toggle_show"] - if(isalien(user)) - icon_state = "bg_alien" - else - icon_state = "bg_default" - update_icon() - -/obj/screen/movable/action_button/hide_toggle/update_icon() - cut_overlays() - add_overlay(mutable_appearance(icon, hidden ? "show" : "hide")) - // add_overlay(mutable_appearance(hide_icon, hidden ? show_state : hide_state)) + last_hovored_ref = WEAKREF(over_object) + over_object?.MouseEntered(over_location, over_control, params) /obj/screen/movable/action_button/MouseEntered(location, control, params) . = ..() @@ -151,89 +92,391 @@ /obj/screen/movable/action_button/MouseExited(location, control, params) closeToolTip(usr) + return ..() -// /datum/hud/proc/get_action_buttons_icons() -// . = list() -// .["bg_icon"] = ui_style_icon -// .["bg_state"] = "template" +/obj/screen/movable/action_button/MouseDrop(over_object) + last_hovored_ref = null + if(!can_use(usr)) + return + var/datum/hud/our_hud = usr.hud_used + if(over_object == src) + our_hud.hide_landings() + return + if(istype(over_object, /obj/screen/action_landing)) + var/obj/screen/action_landing/reserve = over_object + reserve.hit_by(src) + our_hud.hide_landings() + save_position() + return -// //TODO : Make these fit theme -// .["toggle_icon"] = 'icons/mob/actions.dmi' -// .["toggle_hide"] = "hide" -// .["toggle_show"] = "show" + our_hud.hide_landings() + if(istype(over_object, /obj/screen/button_palette) || istype(over_object, /obj/screen/palette_scroll)) + our_hud.position_action(src, SCRN_OBJ_IN_PALETTE) + save_position() + return + if(istype(over_object, /obj/screen/movable/action_button)) + var/obj/screen/movable/action_button/button = over_object + our_hud.position_action_relative(src, button) + save_position() + return + . = ..() + our_hud.position_action(src, screen_loc) + save_position() -//used to update the buttons icon. -/mob/proc/update_action_buttons_icon(status_only = FALSE) - for(var/X in actions) - var/datum/action/A = X - A.UpdateButtonIcon(status_only) +/obj/screen/movable/action_button/proc/save_position() + var/mob/user = our_hud.mymob + if(!user?.client) + return + var/position_info = "" + switch(location) + if(SCRN_OBJ_FLOATING) + position_info = screen_loc + if(SCRN_OBJ_IN_LIST) + position_info = SCRN_OBJ_IN_LIST + if(SCRN_OBJ_IN_PALETTE) + position_info = SCRN_OBJ_IN_PALETTE -//This is the proc used to update all the action buttons. -/mob/proc/update_action_buttons(reload_screen) + LAZYSET(user.client.prefs.action_button_screen_locs, "[name]_[id]", position_info) + +/obj/screen/movable/action_button/proc/load_position() + var/mob/user = our_hud.mymob + if(!user) + return + var/position_info = LAZYACCESS(user.client?.prefs?.action_button_screen_locs, "[name]_[id]") || SCRN_OBJ_DEFAULT + user.hud_used.position_action(src, position_info) + +/obj/screen/movable/action_button/proc/dump_save() + var/mob/user = our_hud.mymob + if(!user?.client) + return + LAZYREMOVE(user.client.prefs.action_button_screen_locs, "[name]_[id]") + +/** + * This is a silly proc used in hud code code to determine what icon and icon state we should be using + * for hud elements (such as action buttons) that don't have their own icon and icon state set. + * + * It returns a list, which is pretty much just a struct of info + */ +/datum/hud/proc/get_action_buttons_icons() + . = list() + .["bg_icon"] = 'icons/mob/actions/backgrounds.dmi' // ui_style // TODO: Implement hud-specific icon stuff + .["bg_state"] = "bg_default" + .["bg_state_active"] = "bg_default_on" + + +/** + * Updates all action buttons this mob has. + * + * Arguments: + * * update_flags - Which flags of the action should we update + * * force - Force buttons update even if the given button icon state has not changed + */ +/mob/proc/update_mob_action_buttons(update_flags = ALL, force = FALSE) + for(var/datum/action/current_action as anything in actions) + current_action.build_all_button_icons(update_flags, force) + +/** + * This proc handles adding all of the mob's actions to their screen + * + * If you just need to update existing buttons, use [/mob/proc/update_mob_action_buttons]! + * + * Arguments: + * * update_flags - reload_screen - bool, if TRUE, this proc will add the button to the screen of the passed mob as well + */ +/mob/proc/update_action_buttons(reload_screen = FALSE) if(!hud_used || !client) return if(!hud_used.hud_shown) //Hud toggled to minimal return - var/button_number = 0 - - if(hud_used.action_buttons_hidden) - for(var/datum/action/A in actions) - A.button.screen_loc = null - if(reload_screen) - client.screen += A.button - else - for(var/datum/action/A in actions) - button_number++ - A.UpdateButtonIcon() - var/obj/screen/movable/action_button/B = A.button - if(!B.moved) - B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number) - else - B.screen_loc = B.moved - if(reload_screen) - client.screen += B - - if(!button_number) - hud_used.hide_actions_toggle?.screen_loc = null - return - - // not exactly sure how this happens but it does - if(hud_used.hide_actions_toggle) - if(!hud_used.hide_actions_toggle.moved) - hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1) - else - hud_used.hide_actions_toggle.screen_loc = hud_used.hide_actions_toggle.moved + for(var/datum/action/action as anything in actions) + var/obj/screen/movable/action_button/button = action.viewers[hud_used] + action.build_all_button_icons() if(reload_screen) - client.screen += hud_used.hide_actions_toggle + client.screen += button -#define AB_WEST_OFFSET 4 -#define AB_NORTH_OFFSET 26 -#define AB_MAX_COLUMNS 10 + if(reload_screen) + hud_used.update_our_owner() + // This holds the logic for the palette buttons + hud_used?.palette_actions?.refresh_actions() -/datum/hud/proc/ButtonNumberToScreenCoords(var/number) // TODO : Make this zero-indexed for readabilty - var/row = round((number-1)/AB_MAX_COLUMNS) - var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1 +/** + * Show (most) of the another mob's action buttons to this mob + * + * Used for observers viewing another mob's screen + */ +/mob/proc/show_other_mob_action_buttons(mob/take_from) + if(!hud_used || !client) + return - var/coord_col = "+[col-1]" - var/coord_col_offset = AB_WEST_OFFSET+2*col + for(var/datum/action/action as anything in take_from.actions) + if(!action.show_to_observers) + continue + action.GiveAction(src) + RegisterSignal(take_from, COMSIG_MOB_GRANTED_ACTION, PROC_REF(on_observing_action_granted)) + RegisterSignal(take_from, COMSIG_MOB_REMOVED_ACTION, PROC_REF(on_observing_action_removed)) - var/coord_row = "[-1 - row]" - var/coord_row_offset = AB_NORTH_OFFSET +/** + * Hide another mob's action buttons from this mob + * + * Used for observers viewing another mob's screen + */ +/mob/proc/hide_other_mob_action_buttons(mob/take_from) + for(var/datum/action/action as anything in take_from.actions) + action.HideFrom(src) + UnregisterSignal(take_from, list(COMSIG_MOB_GRANTED_ACTION, COMSIG_MOB_REMOVED_ACTION)) - return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:[coord_row_offset]" +/// Signal proc for [COMSIG_MOB_GRANTED_ACTION] - If we're viewing another mob's action buttons, +/// we need to update with any newly added buttons granted to the mob. +/mob/proc/on_observing_action_granted(mob/living/source, datum/action/action) + SIGNAL_HANDLER -/datum/hud/proc/SetButtonCoords(var/obj/screen/button,var/number) - var/row = round((number-1)/AB_MAX_COLUMNS) - var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1 - var/x_offset = 32*(col-1) + AB_WEST_OFFSET + 2*col - var/y_offset = -32*(row+1) + AB_NORTH_OFFSET + if(!action.show_to_observers) + return + action.GiveAction(src) - var/matrix/M = matrix() - M.Translate(x_offset,y_offset) - button.transform = M +/// Signal proc for [COMSIG_MOB_REMOVED_ACTION] - If we're viewing another mob's action buttons, +/// we need to update with any removed buttons from the mob. +/mob/proc/on_observing_action_removed(mob/living/source, datum/action/action) + SIGNAL_HANDLER -#undef AB_WEST_OFFSET -#undef AB_NORTH_OFFSET -#undef AB_MAX_COLUMNS + action.HideFrom(src) + +// Button Palette +// A new way to interact with actions + +/obj/screen/button_palette + desc = "Drag buttons to move them
Shift-click any button to reset it
Alt-click this to reset all buttons" + icon = 'icons/hud/64x16_actions.dmi' + icon_state = "screen_gen_palette" + screen_loc = ui_action_palette + var/datum/hud/our_hud + var/expanded = FALSE + /// Id of any currently running timers that set our color matrix + var/color_timer_id + +/obj/screen/button_palette/Destroy() + if(our_hud) + our_hud.mymob?.client?.screen -= src + our_hud.toggle_palette = null + our_hud = null + return ..() + +/obj/screen/button_palette/Initialize(mapload) + . = ..() + // update_appearance() + update_name() + +/obj/screen/button_palette/proc/set_hud(datum/hud/our_hud) + src.our_hud = our_hud + refresh_owner() + +// /obj/screen/button_palette/update_name(updates) +/obj/screen/button_palette/proc/update_name() + // . = ..() + if(expanded) + name = "Hide Buttons" + else + name = "Show Buttons" + +/obj/screen/button_palette/proc/refresh_owner() + var/mob/viewer = our_hud.mymob + if(viewer.client) + viewer.client.screen |= src + + // var/list/settings = our_hud.get_action_buttons_icons() + // var/ui_icon = "[settings["bg_icon"]]" + // var/list/ui_segments = splittext(ui_icon, ".") + // var/list/ui_paths = splittext(ui_segments[1], "/") + // var/ui_name = ui_paths[length(ui_paths)] + + // icon_state = "[ui_name]_palette" + +/obj/screen/button_palette/MouseEntered(location, control, params) + . = ..() + if(QDELETED(src)) + return + show_tooltip(params) + +/obj/screen/button_palette/MouseExited() + closeToolTip(usr) + return ..() + +/obj/screen/button_palette/proc/show_tooltip(params) + openToolTip(usr, src, params, title = name, content = desc) + +GLOBAL_LIST_INIT(palette_added_matrix, list(0.4,0.5,0.2,0, 0,1.4,0,0, 0,0.4,0.6,0, 0,0,0,1, 0,0,0,0)) +GLOBAL_LIST_INIT(palette_removed_matrix, list(1.4,0,0,0, 0.7,0.4,0,0, 0.4,0,0.6,0, 0,0,0,1, 0,0,0,0)) + +/obj/screen/button_palette/proc/play_item_added() + color_for_now(GLOB.palette_added_matrix) + +/obj/screen/button_palette/proc/play_item_removed() + color_for_now(GLOB.palette_removed_matrix) + +/obj/screen/button_palette/proc/color_for_now(list/color) + if(color_timer_id) + return + add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY) //We unfortunately cannot animate matrix colors. Curse you lummy it would be ~~non~~trivial to interpolate between the two valuessssssssss + color_timer_id = addtimer(CALLBACK(src, PROC_REF(remove_color), color), 2 SECONDS) + +/obj/screen/button_palette/proc/remove_color(list/to_remove) + color_timer_id = null + remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, to_remove) + +/obj/screen/button_palette/proc/can_use(mob/user) + if(isobserver(user)) + // var/mob/dead/observer/O = user + // return !O.observetarget + return TRUE + return TRUE + +/obj/screen/button_palette/Click(location, control, params) + if(!can_use(usr)) + return + + var/list/modifiers = params2list(params) + + if(LAZYACCESS(modifiers, ALT_CLICK)) + for(var/datum/action/action as anything in usr.actions) // Reset action positions to default + for(var/datum/hud/hud as anything in action.viewers) + var/obj/screen/movable/action_button/button = action.viewers[hud] + hud.position_action(button, SCRN_OBJ_DEFAULT) + to_chat(usr, span_notice("Action button positions have been reset.")) + return TRUE + + set_expanded(!expanded) + +/obj/screen/button_palette/proc/clicked_while_open(datum/source, atom/target, atom/location, control, params, mob/user) + if(istype(target, /obj/screen/movable/action_button) || istype(target, /obj/screen/palette_scroll) || target == src) // If you're clicking on an action button, or us, you can live + return + set_expanded(FALSE) + if(source) + UnregisterSignal(source, COMSIG_CLIENT_CLICK) + +/obj/screen/button_palette/proc/set_expanded(new_expanded) + var/datum/action_group/our_group = our_hud.palette_actions + if(!length(our_group.actions)) //Looks dumb, trust me lad + new_expanded = FALSE + if(expanded == new_expanded) + return + + expanded = new_expanded + our_group.refresh_actions() + // update_appearance() + update_name() + + if(!usr.client) + return + + if(expanded) + RegisterSignal(usr.client, COMSIG_CLIENT_CLICK, PROC_REF(clicked_while_open)) + else + UnregisterSignal(usr.client, COMSIG_CLIENT_CLICK) + + closeToolTip(usr) //Our tooltips are now invalid, can't seem to update them in one frame, so here, just close them + +/obj/screen/palette_scroll + icon = 'icons/hud/screen_gen.dmi' + screen_loc = ui_palette_scroll + /// How should we move the palette's actions? + /// Positive scrolls down the list, negative scrolls back + var/scroll_direction = 0 + var/datum/hud/our_hud + +/obj/screen/palette_scroll/proc/can_use(mob/user) + if(isobserver(user)) + // var/mob/dead/observer/O = user + // return !O.observetarget + return TRUE + return TRUE + +/obj/screen/palette_scroll/proc/set_hud(datum/hud/our_hud) + src.our_hud = our_hud + refresh_owner() + +/obj/screen/palette_scroll/proc/refresh_owner() + var/mob/viewer = our_hud.mymob + if(viewer.client) + viewer.client.screen |= src + + // var/list/settings = our_hud.get_action_buttons_icons() + // icon = settings["bg_icon"] + +/obj/screen/palette_scroll/Click(location, control, params) + if(!can_use(usr)) + return + our_hud.palette_actions.scroll(scroll_direction) + +/obj/screen/palette_scroll/MouseEntered(location, control, params) + . = ..() + if(QDELETED(src)) + return + openToolTip(usr, src, params, title = name, content = desc) + +/obj/screen/palette_scroll/MouseExited() + closeToolTip(usr) + return ..() + +/obj/screen/palette_scroll/down + name = "Scroll Down" + desc = "Click on this to scroll the actions above down" + icon_state = "scroll_down" + scroll_direction = 1 + +/obj/screen/palette_scroll/down/Destroy() + if(our_hud) + our_hud.mymob?.client?.screen -= src + our_hud.palette_down = null + our_hud = null + return ..() + +/obj/screen/palette_scroll/up + name = "Scroll Up" + desc = "Click on this to scroll the actions above up" + icon_state = "scroll_up" + scroll_direction = -1 + +/obj/screen/palette_scroll/up/Destroy() + if(our_hud) + our_hud.mymob?.client?.screen -= src + our_hud.palette_up = null + our_hud = null + return ..() + +/// Exists so you have a place to put your buttons when you move them around +/obj/screen/action_landing + name = "Button Space" + desc = "Drag and drop a button into this spot
to add it to the group" + icon = 'icons/hud/screen_gen.dmi' + icon_state = "reserved" + // We want our whole 32x32 space to be clickable, so dropping's forgiving + mouse_opacity = MOUSE_OPACITY_OPAQUE + var/datum/action_group/owner + +/obj/screen/action_landing/Destroy() + if(owner) + owner.landing = null + owner?.owner?.mymob?.client?.screen -= src + owner.refresh_actions() + owner = null + return ..() + +/obj/screen/action_landing/proc/set_owner(datum/action_group/owner) + src.owner = owner + refresh_owner() + +/obj/screen/action_landing/proc/refresh_owner() + var/datum/hud/our_hud = owner.owner + var/mob/viewer = our_hud.mymob + if(viewer.client) + viewer.client.screen |= src + + // var/list/settings = our_hud.get_action_buttons_icons() + // icon = settings["bg_icon"] + +/// Reacts to having a button dropped on it +/obj/screen/action_landing/proc/hit_by(obj/screen/movable/action_button/button) + var/datum/hud/our_hud = owner.owner + our_hud.position_action(button, owner.location) diff --git a/code/_onclick/hud/action/innate_action.dm b/code/_onclick/hud/action/innate_action.dm new file mode 100644 index 00000000000..cdfb169ddb3 --- /dev/null +++ b/code/_onclick/hud/action/innate_action.dm @@ -0,0 +1,20 @@ +//Preset for general and toggled actions +/datum/action/innate + check_flags = NONE + /// Whether we're active or not, if we're a innate - toggle action. + var/active = 0 + +/datum/action/innate/Trigger(trigger_flags) + if(!..()) + return 0 + if(!active) + Activate() + else + Deactivate() + return 1 + +/datum/action/innate/proc/Activate() + return + +/datum/action/innate/proc/Deactivate() + return diff --git a/code/_onclick/hud/action/item_action.dm b/code/_onclick/hud/action/item_action.dm new file mode 100644 index 00000000000..4644efbf836 --- /dev/null +++ b/code/_onclick/hud/action/item_action.dm @@ -0,0 +1,37 @@ + +//Presets for item actions +/datum/action/item_action + check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_CONSCIOUS + // If you want to override the normal icon being the item + // then change this to an icon state + button_icon_state = null + +/datum/action/item_action/New(Target) + . = ..() + + // If our button state is null, use the target's icon instead + if(target && isnull(button_icon_state)) + AddComponent(/datum/component/action_item_overlay, target) + +/datum/action/item_action/vv_edit_var(var_name, var_value) + . = ..() + if(!. || !target) + return + + if(var_name == NAMEOF(src, button_icon_state)) + // If someone vv's our icon either add or remove the component + if(isnull(var_name)) + AddComponent(/datum/component/action_item_overlay, target) + else + qdel(GetComponent(/datum/component/action_item_overlay)) + +/datum/action/item_action/Trigger(trigger_flags) + if(!..()) + return 0 + if(target) + var/obj/item/item_target = target + item_target.ui_action_click(owner, src.type) + return 1 + +/datum/action/item_action/hands_free + check_flags = AB_CHECK_CONSCIOUS diff --git a/code/_onclick/hud/action/positioning.dm b/code/_onclick/hud/action/positioning.dm new file mode 100644 index 00000000000..1ed18d87cdf --- /dev/null +++ b/code/_onclick/hud/action/positioning.dm @@ -0,0 +1,49 @@ +/datum/hud/proc/position_action(obj/screen/movable/action_button/button, position) + if(button.location != SCRN_OBJ_DEFAULT) + hide_action(button) + switch(position) + if(SCRN_OBJ_DEFAULT) // Reset to the default + button.dump_save() // Nuke any existing saves + position_action(button, button.linked_action.default_button_position) + return + if(SCRN_OBJ_IN_LIST) + listed_actions.insert_action(button) + if(SCRN_OBJ_IN_PALETTE) + palette_actions.insert_action(button) + else // If we don't have it as a define, this is a screen_loc, and we should be floating + floating_actions += button + button.screen_loc = position + position = SCRN_OBJ_FLOATING + + button.location = position + +/datum/hud/proc/position_action_relative(obj/screen/movable/action_button/button, obj/screen/movable/action_button/relative_to) + if(button.location != SCRN_OBJ_DEFAULT) + hide_action(button) + switch(relative_to.location) + if(SCRN_OBJ_IN_LIST) + listed_actions.insert_action(button, listed_actions.index_of(relative_to)) + if(SCRN_OBJ_IN_PALETTE) + palette_actions.insert_action(button, palette_actions.index_of(relative_to)) + if(SCRN_OBJ_FLOATING) // If we don't have it as a define, this is a screen_loc, and we should be floating + floating_actions += button + var/client/our_client = mymob.client + if(!our_client) + position_action(button, button.linked_action.default_button_position) + return + button.screen_loc = get_valid_screen_location(relative_to.screen_loc, world.icon_size, our_client.view) // Asks for a location adjacent to our button that won't overflow the map + + button.location = relative_to.location + +/// Removes the passed in action from its current position on the screen +/datum/hud/proc/hide_action(obj/screen/movable/action_button/button) + switch(button.location) + if(SCRN_OBJ_DEFAULT) // Invalid + CRASH("We just tried to hide an action buttion that somehow has the default position as its location, you done fucked up") + if(SCRN_OBJ_FLOATING) + floating_actions -= button + if(SCRN_OBJ_IN_LIST) + listed_actions.remove_action(button) + if(SCRN_OBJ_IN_PALETTE) + palette_actions.remove_action(button) + button.screen_loc = null diff --git a/code/_onclick/hud/action/types/item.dm b/code/_onclick/hud/action/types/item.dm index df2d770aec5..6adec05d61a 100644 --- a/code/_onclick/hud/action/types/item.dm +++ b/code/_onclick/hud/action/types/item.dm @@ -4,7 +4,6 @@ /datum/action/item_action/activate/New(Target, name) . = ..() src.name = name - button.name = name // Specific names /datum/action/item_action/toggle_grippers diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index c2b54a001bf..774acba147f 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -186,8 +186,15 @@ var/list/global_huds = list( var/list/miniobjs var/list/obj/screen/hotkeybuttons - var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle - var/action_buttons_hidden = 0 + var/obj/screen/button_palette/toggle_palette + var/obj/screen/palette_scroll/down/palette_down + var/obj/screen/palette_scroll/up/palette_up + + var/datum/action_group/palette/palette_actions + var/datum/action_group/listed/listed_actions + var/list/floating_actions + + var/list/slot_info var/icon/ui_style @@ -205,9 +212,19 @@ var/list/global_huds = list( ..() /datum/hud/Destroy() - . = ..() + if(mymob.hud_used == src) + mymob.hud_used = null + QDEL_NULL_LIST(minihuds) - QDEL_NULL(hide_actions_toggle) + + // Actions + QDEL_NULL(toggle_palette) + QDEL_NULL(palette_down) + QDEL_NULL(palette_up) + QDEL_NULL(palette_actions) + QDEL_NULL(listed_actions) + QDEL_LIST(floating_actions) + grab_intent = null hurt_intent = null disarm_intent = null @@ -232,6 +249,8 @@ var/list/global_huds = list( ammo_hud_list = null mymob = null + return ..() + /datum/hud/proc/hidden_inventory_update() if(!mymob) return if(ishuman(mymob)) @@ -323,10 +342,15 @@ var/list/global_huds = list( return 0 mymob.create_mob_hud(src) - hide_actions_toggle = new() - hide_actions_toggle.InitialiseIcon(mymob) - // if(mymob.client) - // hide_actions_toggle.locked = mymob.client.prefs.buttons_locked + + // Past this point, mymob.hud_used is set + + toggle_palette = new() + toggle_palette.set_hud(src) + palette_down = new() + palette_down.set_hud(src) + palette_up = new() + palette_up.set_hud(src) persistant_inventory_update() mymob.reload_fullscreen() // Reload any fullscreen overlays this mob has. @@ -340,6 +364,11 @@ var/list/global_huds = list( HUD.ui_style = ui_style2icon(client?.prefs?.UI_style) HUD.ui_color = client?.prefs?.UI_style_color HUD.ui_alpha = client?.prefs?.UI_style_alpha + set_hud_used(HUD) + +/mob/proc/set_hud_used(datum/hud/new_hud) + hud_used = new_hud + new_hud.build_action_groups() /datum/hud/proc/apply_minihud(var/datum/mini_hud/MH) if(MH in minihuds) @@ -409,7 +438,7 @@ var/list/global_huds = list( hud_used?.action_intent.screen_loc = ui_acti //Restore intent selection to the original position client.screen += zone_sel //This one is a special snowflake - client.screen += hud_used.hide_actions_toggle + client.screen += hud_used.toggle_palette hud_used.hidden_inventory_update() hud_used.persistant_inventory_update() diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index daa82352e4d..6179fd09c66 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -11,6 +11,7 @@ /obj/screen/movable mouse_drag_pointer = 'icons/effects/mouse_pointers/screen_drag.dmi' var/snap2grid = FALSE + // TODO: Check if these can safely be deleted var/moved = FALSE var/locked = FALSE var/x_off = -16 diff --git a/code/game/gamemodes/technomancer/devices/shield_armor.dm b/code/game/gamemodes/technomancer/devices/shield_armor.dm index c991f6e164b..20c42faa303 100644 --- a/code/game/gamemodes/technomancer/devices/shield_armor.dm +++ b/code/game/gamemodes/technomancer/devices/shield_armor.dm @@ -78,7 +78,7 @@ to_chat(user, span_notice("You [active ? "" : "de"]activate \the [src].")) update_icon() user.update_inv_wear_suit() - user.update_action_buttons_icon() + user.update_mob_action_buttons() /obj/item/clothing/suit/armor/shield/update_icon() icon_state = "shield_armor_[active]" diff --git a/code/game/gamemodes/technomancer/devices/tesla_armor.dm b/code/game/gamemodes/technomancer/devices/tesla_armor.dm index 01a65b5a669..c6e1ae3cc44 100644 --- a/code/game/gamemodes/technomancer/devices/tesla_armor.dm +++ b/code/game/gamemodes/technomancer/devices/tesla_armor.dm @@ -57,7 +57,7 @@ to_chat(user, span_notice("You [active ? "" : "de"]activate \the [src].")) update_icon() user.update_inv_wear_suit() - user.update_action_buttons_icon() + user.update_mob_action_buttons() /obj/item/clothing/suit/armor/tesla/update_icon() if(active && ready) @@ -72,7 +72,7 @@ if(ishuman(loc)) var/mob/living/carbon/human/H = loc H.update_inv_wear_suit(0) - H.update_action_buttons_icon() + H.update_mob_action_buttons() ..() /obj/item/clothing/suit/armor/tesla/proc/shoot_lightning(mob/target, power) diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm index 40568d4fd1c..d3d5b1bd728 100644 --- a/code/game/mecha/mecha_actions.dm +++ b/code/game/mecha/mecha_actions.dm @@ -63,8 +63,9 @@ /datum/action/innate/mecha check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUNNED | AB_CHECK_CONSCIOUS + background_icon = 'icons/effects/actions_mecha.dmi' button_icon = 'icons/effects/actions_mecha.dmi' - icon_icon = 'icons/effects/actions_mecha.dmi' + overlay_icon = 'icons/effects/actions_mecha.dmi' var/obj/mecha/chassis /datum/action/innate/mecha/Destroy() @@ -83,7 +84,7 @@ /datum/action/innate/mecha/mech_toggle_lights/Activate() button_icon_state = "mech_lights_[chassis.lights ? "off" : "on"]" - UpdateButtonIcon() + build_all_button_icons() chassis.lights() @@ -94,7 +95,7 @@ /datum/action/innate/mecha/mech_toggle_internals/Activate() button_icon_state = "mech_internals_[chassis.use_internal_tank ? "off" : "on"]" - UpdateButtonIcon() + build_all_button_icons() chassis.internal_tank() @@ -123,7 +124,7 @@ /datum/action/innate/mecha/strafe/Activate() button_icon_state = "mech_strafe_[chassis.strafing ? "off" : "on"]" - UpdateButtonIcon() + build_all_button_icons() chassis.strafing() @@ -134,7 +135,7 @@ /datum/action/innate/mecha/mech_defence_mode/Activate() button_icon_state = "mech_defense_mode_[chassis.defence_mode ? "off" : "on"]" - UpdateButtonIcon() + build_all_button_icons() chassis.defence_mode() @@ -145,7 +146,7 @@ /datum/action/innate/mecha/mech_overload_mode/Activate() button_icon_state = "mech_overload_[chassis.overload ? "off" : "on"]" - UpdateButtonIcon() + build_all_button_icons() chassis.overload() @@ -156,7 +157,7 @@ /datum/action/innate/mecha/mech_smoke/Activate() //button_icon_state = "mech_smoke_[chassis.smoke ? "off" : "on"]" - //UpdateButtonIcon() //Dual colors notneeded ATM + //build_all_button_icons() //Dual colors notneeded ATM chassis.smoke() @@ -167,7 +168,7 @@ /datum/action/innate/mecha/mech_zoom/Activate() button_icon_state = "mech_zoom_[chassis.zoom ? "off" : "on"]" - UpdateButtonIcon() + build_all_button_icons() chassis.zoom() @@ -178,7 +179,7 @@ /datum/action/innate/mecha/mech_toggle_thrusters/Activate() button_icon_state = "mech_thrusters_[chassis.thrusters ? "off" : "on"]" - UpdateButtonIcon() + build_all_button_icons() chassis.thrusters() @@ -203,7 +204,7 @@ chassis.occupant_message("You select [chassis.selected]") send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list()) button_icon_state = "mech_cycle_equip_on" - UpdateButtonIcon() + build_all_button_icons() return var/number = 0 for(var/A in available_equipment) @@ -218,7 +219,7 @@ chassis.occupant_message("You switch to [chassis.selected]") button_icon_state = "mech_cycle_equip_on" send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list()) - UpdateButtonIcon() + build_all_button_icons() return @@ -233,7 +234,7 @@ button_icon_state = "mech_damtype_[chassis.damtype]" playsound(src, 'sound/mecha/mechmove01.ogg', 50, 1) - UpdateButtonIcon() + build_all_button_icons() chassis.query_damtype() @@ -244,7 +245,7 @@ /datum/action/innate/mecha/mech_toggle_phasing/Activate() button_icon_state = "mech_phasing_[chassis.phasing ? "off" : "on"]" - UpdateButtonIcon() + build_all_button_icons() chassis.phasing() @@ -255,7 +256,7 @@ /datum/action/innate/mecha/mech_toggle_cloaking/Activate() button_icon_state = "mech_phasing_[chassis.cloaked ? "off" : "on"]" - UpdateButtonIcon() + build_all_button_icons() chassis.toggle_cloaking() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index d66bb898744..553d08c343d 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -115,8 +115,10 @@ /obj/item/New() ..() + for(var/path in actions_types) - new path(src) + add_item_action(path) + if(embed_chance < 0) if(sharp) embed_chance = max(5, round(force/w_class)) @@ -137,10 +139,55 @@ m.update_inv_r_hand() m.update_inv_l_hand() src.loc = null - for(var/X in actions) - qdel(X) + + // Handle celaning up our actions list + for(var/datum/action/action as anything in actions) + remove_item_action(action) + return ..() + +/// Called when an action associated with our item is deleted +/obj/item/proc/on_action_deleted(datum/source) + SIGNAL_HANDLER + + if(!(source in actions)) + CRASH("An action ([source.type]) was deleted that was associated with an item ([src]), but was not found in the item's actions list.") + + LAZYREMOVE(actions, source) + +/// Adds an item action to our list of item actions. +/// Item actions are actions linked to our item, that are granted to mobs who equip us. +/// This also ensures that the actions are properly tracked in the actions list and removed if they're deleted. +/// Can be be passed a typepath of an action or an instance of an action. +/obj/item/proc/add_item_action(action_or_action_type) + var/datum/action/action + if(ispath(action_or_action_type, /datum/action)) + action = new action_or_action_type(src) + else if(istype(action_or_action_type, /datum/action)) + action = action_or_action_type + else + CRASH("item add_item_action got a type or instance of something that wasn't an action.") + + LAZYADD(actions, action) + RegisterSignal(action, COMSIG_PARENT_QDELETING, PROC_REF(on_action_deleted)) + if(ismob(loc)) + // We're being held or are equipped by someone while adding an action? + // Then they should also probably be granted the action, given it's in a correct slot + var/mob/holder = loc + give_item_action(action, holder, holder.get_inventory_slot(src)) + + return action + +/// Removes an instance of an action from our list of item actions. +/obj/item/proc/remove_item_action(datum/action/action) + if(!action) + return + + UnregisterSignal(action, COMSIG_PARENT_QDELETING) + LAZYREMOVE(actions, action) + qdel(action) + // Check if target is reasonable for us to operate on. /obj/item/proc/check_allowed_items(atom/target, not_inside, target_self) if(((src in target) && !target_self) || ((!istype(target.loc, /turf)) && (!istype(target, /turf)) && (not_inside))) @@ -335,8 +382,9 @@ if(zoom) zoom() //binoculars, scope, etc appearance_flags &= ~NO_CLIENT_COLOR - for(var/datum/action/A as anything in actions) - A.Remove(user) + // Remove any item actions we temporary gave out. + for(var/datum/action/action_item_has as anything in actions) + action_item_has.Remove(user) // called just as an item is picked up (loc is not yet changed) /obj/item/proc/pickup(mob/user) @@ -362,10 +410,9 @@ // for items that can be placed in multiple slots // note this isn't called during the initial dressing of a player /obj/item/proc/equipped(var/mob/user, var/slot) - for(var/X in actions) - var/datum/action/A = X - if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot. - A.Grant(user) + // Give out actions our item has to people who equip it. + for(var/datum/action/action as anything in actions) + give_item_action(action, user, slot) hud_layerise() user.position_hud_item(src,slot) if(user.client) user.client.screen |= src @@ -379,6 +426,18 @@ playsound(src, pickup_sound, 20, preference = /datum/preference/toggle/pickup_sounds) return +/// Gives one of our item actions to a mob, when equipped to a certain slot +/obj/item/proc/give_item_action(datum/action/action, mob/to_who, slot) + // Some items only give their actions buttons when in a specific slot. + if(!item_action_slot_check(slot, to_who)) + // There is a chance we still have our item action currently, + // and are moving it from a "valid slot" to an "invalid slot". + // So call Remove() here regardless, even if excessive. + action.Remove(to_who) + return + + action.Grant(to_who) + //sometimes we only want to grant the item's action if it's equipped in a specific slot. /obj/item/proc/item_action_slot_check(slot, mob/user) if(slot == SLOT_BACK || slot == LEGS) //these aren't true slots, so avoid granting actions there diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 3f1505b6f3e..eb9db84acdb 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -102,7 +102,7 @@ STOP_PROCESSING(SSobj, src) playsound(src, 'sound/weapons/empty.ogg', 15, 1, -3) // VOREStation Edit update_brightness() - user.update_action_buttons_icon() + user.update_mob_action_buttons() return 1 /obj/item/flashlight/emp_act(severity) diff --git a/code/game/objects/items/weapons/shields_vr.dm b/code/game/objects/items/weapons/shields_vr.dm index 245196269a4..96afa59be6e 100644 --- a/code/game/objects/items/weapons/shields_vr.dm +++ b/code/game/objects/items/weapons/shields_vr.dm @@ -64,7 +64,7 @@ set_light(0) light_applied = 0 update_icon(user) - user.update_action_buttons_icon() + user.update_mob_action_buttons() playsound(src, 'sound/weapons/empty.ogg', 15, 1, -3) /obj/item/shield/riot/explorer/update_icon() diff --git a/code/game/objects/items/weapons/tanks/jetpack.dm b/code/game/objects/items/weapons/tanks/jetpack.dm index 42b67842e4b..7660cb8e675 100644 --- a/code/game/objects/items/weapons/tanks/jetpack.dm +++ b/code/game/objects/items/weapons/tanks/jetpack.dm @@ -55,7 +55,7 @@ if (ismob(usr)) var/mob/M = usr M.update_inv_back() - M.update_action_buttons_icon() + M.update_mob_action_buttons() to_chat(usr, "You toggle the thrusters [on? "on":"off"].") diff --git a/code/modules/ai/ai_holder.dm b/code/modules/ai/ai_holder.dm index 6a897ce5fef..7eef273d638 100644 --- a/code/modules/ai/ai_holder.dm +++ b/code/modules/ai/ai_holder.dm @@ -52,8 +52,7 @@ return if(istype(src, /mob/living/carbon/human)) var/mob/living/carbon/human/H = src - H.hud_used = new /datum/hud(H) - H.create_mob_hud(H.hud_used) + new /datum/hud(H) /datum/ai_holder var/mob/living/holder = null // The mob this datum is going to control. diff --git a/code/modules/catalogue/cataloguer.dm b/code/modules/catalogue/cataloguer.dm index 766fd2e9394..2ea1045dca7 100644 --- a/code/modules/catalogue/cataloguer.dm +++ b/code/modules/catalogue/cataloguer.dm @@ -368,7 +368,7 @@ GLOBAL_LIST_EMPTY(all_cataloguers) if (ismob(usr)) var/mob/M = usr - M.update_action_buttons_icon() + M.update_mob_action_buttons() /obj/item/cataloguer/compact/afterattack(atom/target, mob/user, proximity_flag) if(!deployed) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index ca4fb202481..d4eff6fd9a1 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -706,3 +706,9 @@ if("Set-Tab") stat_tab = payload["tab"] SSstatpanels.immediate_send_stat_data(src) + + +// Mouse stuff +/client/Click(atom/object, atom/location, control, params) + SEND_SIGNAL(src, COMSIG_CLIENT_CLICK, object, location, control, params, usr) + . = ..() diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 617396500db..f45481622aa 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -485,8 +485,7 @@ update_light() update_icon(user) - spawn(10) // FIXME: Remove when SSoverlays stops queueing overlay changes - user.update_action_buttons_icon() + user.update_mob_action_buttons() /obj/item/clothing/head/attack_ai(var/mob/user) if(!mob_wear_hat(user)) diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 5ed049694c8..572f45c0b5d 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -71,7 +71,7 @@ BLIND // can't see anything tint = initial(tint) enables_planes = away_planes away_planes = null - user.update_action_buttons_icon() + user.update_mob_action_buttons() user.recalculate_vis() /obj/item/clothing/glasses/attack_self(mob/user) @@ -408,7 +408,7 @@ BLIND // can't see anything tint = TINT_NONE to_chat(usr, "You push \the [src] up out of your face.") update_clothing_icon() - usr.update_action_buttons_icon() + usr.update_mob_action_buttons() /obj/item/clothing/glasses/welding/superior name = "superior welding goggles" @@ -503,7 +503,7 @@ BLIND // can't see anything user << activation_sound user.recalculate_vis() user.update_inv_glasses() - user.update_action_buttons_icon() + user.update_mob_action_buttons() /obj/item/clothing/glasses/sunglasses/sechud/aviator/update_icon() if(on) @@ -623,4 +623,4 @@ BLIND // can't see anything icon_state = "[initial(icon_state)]up" to_chat(usr, "You push \the [src] up from in front of your eyes.") update_clothing_icon() - usr.update_action_buttons_icon() + usr.update_mob_action_buttons() diff --git a/code/modules/clothing/glasses/glasses_vr.dm b/code/modules/clothing/glasses/glasses_vr.dm index 35399268f77..0101d517fc6 100644 --- a/code/modules/clothing/glasses/glasses_vr.dm +++ b/code/modules/clothing/glasses/glasses_vr.dm @@ -106,7 +106,7 @@ if(src && choice && !user.incapacitated() && in_range(user,src)) icon_state = options[choice] user.update_inv_glasses() - user.update_action_buttons_icon() + user.update_mob_action_buttons() to_chat(user, span_notice("Your [src] now displays [choice] .")) return 1 diff --git a/code/modules/clothing/glasses/hud_vr.dm b/code/modules/clothing/glasses/hud_vr.dm index 1e13f56d177..3693717a59c 100644 --- a/code/modules/clothing/glasses/hud_vr.dm +++ b/code/modules/clothing/glasses/hud_vr.dm @@ -141,7 +141,7 @@ away_planes = null to_chat(usr, span_notice("You enabled the Augmented Reality HUD of your [src.name].")) ar_toggled = !ar_toggled - usr.update_action_buttons_icon() + usr.update_mob_action_buttons() usr.recalculate_vis() @@ -249,7 +249,7 @@ item_state = initial(item_state) usr.update_inv_glasses() to_chat(usr, "You activate the retinal projector on the [src].") - usr.update_action_buttons_icon() + usr.update_mob_action_buttons() /obj/item/clothing/glasses/omnihud/all name = "\improper AR-B glasses" diff --git a/code/modules/clothing/head/helmet_vr.dm b/code/modules/clothing/head/helmet_vr.dm index b02024594c1..7b7890b4238 100644 --- a/code/modules/clothing/head/helmet_vr.dm +++ b/code/modules/clothing/head/helmet_vr.dm @@ -83,7 +83,7 @@ if (ismob(src.loc)) //should allow masks to update when it is opened/closed var/mob/M = src.loc M.update_inv_wear_mask() - usr.update_action_buttons_icon() + usr.update_mob_action_buttons() // Costume Versions Here /obj/item/clothing/head/helmet/combat/crusader_costume @@ -140,4 +140,4 @@ if (ismob(src.loc)) //should allow masks to update when it is opened/closed var/mob/M = src.loc M.update_inv_wear_mask() - usr.update_action_buttons_icon() + usr.update_mob_action_buttons() diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 76467e49726..937da8a743a 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -65,7 +65,7 @@ if (ismob(src.loc)) //should allow masks to update when it is opened/closed var/mob/M = src.loc M.update_inv_wear_mask() - usr.update_action_buttons_icon() + usr.update_mob_action_buttons() /obj/item/clothing/head/welding/demon name = "demonic welding helmet" diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index c821aeeca23..be5dad9f667 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -373,7 +373,7 @@ if(src && choice && !user.incapacitated() && in_range(user,src)) icon_state = options[choice] user.update_inv_wear_mask() - user.update_action_buttons_icon() + user.update_mob_action_buttons() to_chat(user, span_notice("Your paper mask now is now [choice].")) return 1 @@ -408,7 +408,7 @@ if(src && choice && !user.incapacitated() && in_range(user,src)) icon_state = options[choice] user.update_inv_wear_mask() - user.update_action_buttons_icon() + user.update_mob_action_buttons() to_chat(user, span_notice("Your [src] now displays a [choice] emotion.")) return 1 diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 9a1c384478e..756d7f4d3f9 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -41,7 +41,7 @@ playsound(src, 'sound/effects/magnetclamp.ogg', 20) to_chat(user, "You enable the mag-pulse traction system.") user.update_inv_shoes() //so our mob-overlays update - user.update_action_buttons_icon() + user.update_mob_action_buttons() /obj/item/clothing/shoes/magboots/mob_can_equip(mob/user, slot, disable_warning = FALSE) var/mob/living/carbon/human/H = user @@ -111,7 +111,7 @@ magpulse = 1 canremove = FALSE //kinda hard to take off magclaws when you are gripping them tightly. to_chat(user, "You dig your claws deeply into the flooring, bracing yourself.") - user.update_action_buttons_icon() + user.update_mob_action_buttons() //In case they somehow come off while enabled. /obj/item/clothing/shoes/magboots/vox/dropped(mob/user as mob) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 1caf251fcf5..fbf72f59bb5 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -455,7 +455,7 @@ throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = handcuffed) else clear_alert("handcuffed") - update_action_buttons_icon() //some of our action buttons might be unusable when we're handcuffed. + update_mob_action_buttons() //some of our action buttons might be unusable when we're handcuffed. update_inv_handcuffed() // Clears blood overlays diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 224cdfa1d6a..d5df6193332 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -1,6 +1,6 @@ /mob/living/death(gibbed) clear_fullscreens() - update_action_buttons_icon() + update_mob_action_buttons() if(ai_holder) ai_holder.go_sleep() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 3c3e5e790ab..256f8d3c030 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -973,7 +973,7 @@ if(lying != lying_prev) lying_prev = lying update_transform() - update_action_buttons_icon(status_only = TRUE) + update_mob_action_buttons() //VOREStation Add if(lying && LAZYLEN(buckled_mobs)) for(var/mob/living/L as anything in buckled_mobs) diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 72168f1631f..49b1a81ec27 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -32,8 +32,9 @@ client.images = null //remove the images such as AIs being unable to see runes client.screen = list() //remove hud items just in case - if(hud_used) qdel(hud_used) //remove the hud objects - hud_used = new /datum/hud(src) + if(hud_used) + qdel(hud_used) //remove the hud objects + new /datum/hud(src) if(client.prefs && client.prefs.client_fps) client.fps = client.prefs.client_fps diff --git a/code/modules/projectiles/guns/projectile/shotgun_vr.dm b/code/modules/projectiles/guns/projectile/shotgun_vr.dm index 8ee2e7d049d..f8cdfc8d3b6 100644 --- a/code/modules/projectiles/guns/projectile/shotgun_vr.dm +++ b/code/modules/projectiles/guns/projectile/shotgun_vr.dm @@ -69,7 +69,7 @@ H.update_inv_r_hand() playsound(src, 'sound/weapons/targeton.ogg', 50, 1) - user.update_action_buttons_icon() + user.update_mob_action_buttons() /obj/item/gun/projectile/shotgun/compact/verb/verb_toggle_stock(mob/user as mob) set category = "Object" diff --git a/code/modules/vore/fluffstuff/custom_clothes_vr.dm b/code/modules/vore/fluffstuff/custom_clothes_vr.dm index abad2a0a959..a4a102ce847 100644 --- a/code/modules/vore/fluffstuff/custom_clothes_vr.dm +++ b/code/modules/vore/fluffstuff/custom_clothes_vr.dm @@ -1129,7 +1129,7 @@ if (ismob(loc)) //should allow masks to update when it is opened/closed var/mob/M = loc M.update_inv_wear_mask() - usr.update_action_buttons_icon() + usr.update_mob_action_buttons() //Vorrarkul: Theodora Lindt /obj/item/clothing/suit/chococoat @@ -2635,7 +2635,7 @@ Departamental Swimsuits, for general use if (ismob(loc)) //should allow masks to update when it is opened/closed var/mob/M = loc M.update_inv_wear_mask() - usr.update_action_buttons_icon() + usr.update_mob_action_buttons() /obj/item/clothing/suit/storage/toggle/labcoat/fluff/zeracloak name = "Grand Purple Cloak" diff --git a/icons/hud/64x16_actions.dmi b/icons/hud/64x16_actions.dmi new file mode 100644 index 0000000000000000000000000000000000000000..812d888846ebd76191628e35628847cfb88f4158 GIT binary patch literal 3920 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 literal 0 HcmV?d00001 diff --git a/icons/hud/screen_gen.dmi b/icons/hud/screen_gen.dmi new file mode 100644 index 0000000000000000000000000000000000000000..86383abbef1e2adc2dc1e71f9e1676e8582089d4 GIT binary patch literal 112316 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 rMTG{!(K0o_q8?oX>a>TRZD$S literal 0 HcmV?d00001 diff --git a/vorestation.dme b/vorestation.dme index b11104cc702..1519ec9d122 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -65,6 +65,7 @@ #include "code\__defines\holder.dm" #include "code\__defines\holomap.dm" #include "code\__defines\hoses.dm" +#include "code\__defines\hud.dm" #include "code\__defines\implant.dm" #include "code\__defines\input.dm" #include "code\__defines\instruments.dm" @@ -207,6 +208,7 @@ #include "code\_helpers\verbs.dm" #include "code\_helpers\view.dm" #include "code\_helpers\visual_filters.dm" +#include "code\_helpers\weakref.dm" #include "code\_helpers\icons\flatten.dm" #include "code\_helpers\logging\debug.dm" #include "code\_helpers\logging\ui.dm" @@ -224,8 +226,6 @@ #include "code\_onclick\other_mobs.dm" #include "code\_onclick\rig.dm" #include "code\_onclick\telekinesis.dm" -#include "code\_onclick\hud\_defines.dm" -#include "code\_onclick\hud\_defines_vr.dm" #include "code\_onclick\hud\ability_screen_objects.dm" #include "code\_onclick\hud\ai.dm" #include "code\_onclick\hud\alert.dm" @@ -254,7 +254,13 @@ #include "code\_onclick\hud\soulcatcher_guest.dm" #include "code\_onclick\hud\spell_screen_objects.dm" #include "code\_onclick\hud\action\action.dm" +#include "code\_onclick\hud\action\action_group.dm" +#include "code\_onclick\hud\action\action_group_helpers.dm" +#include "code\_onclick\hud\action\action_item_overlay.dm" #include "code\_onclick\hud\action\action_screen_objects.dm" +#include "code\_onclick\hud\action\innate_action.dm" +#include "code\_onclick\hud\action\item_action.dm" +#include "code\_onclick\hud\action\positioning.dm" #include "code\_onclick\hud\action\types\item.dm" #include "code\ATMOSPHERICS\_atmos_setup.dm" #include "code\ATMOSPHERICS\_atmospherics_helpers.dm"