diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_mouse.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_mouse.dm index 261c13c6673..2f8ebc83665 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_mouse.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_mouse.dm @@ -1,8 +1,10 @@ -// Atom mouse signals. Format: +// mouse signals. Format: // When the signal is called: (signal arguments) // All signals send the source datum of the signal as the first argument -///from base of atom/Click(): (location, control, params, mob/user) +///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(): (atom/location, control, params, mob/user) #define COMSIG_CLICK "atom_click" ///from base of atom/ShiftClick(): (/mob) #define COMSIG_CLICK_SHIFT "shift_click" diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index 60b7c308be4..200c152630b 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -14,3 +14,202 @@ #define APPEARANCE_UI_IGNORE_ALPHA (RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|RESET_ALPHA|PIXEL_SCALE) /// Used for HUD objects #define APPEARANCE_UI (RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|PIXEL_SCALE) + +/* + These defines specificy screen locations. For more information, see the byond documentation on the screen_loc var. + + The short version: + + Everything is encoded as strings because apparently that's how Byond rolls. + + "1,1" is the bottom left square of the user's screen. This aligns perfectly with the turf grid. + "1:2,3:4" is the square (1,3) with pixel offsets (+2, +4); slightly right and slightly above the turf grid. + Pixel offsets are used so you don't perfectly hide the turf under them, that would be crappy. + + In addition, the keywords NORTH, SOUTH, EAST, WEST and CENTER can be used to represent their respective + screen borders. NORTH-1, for example, is the row just below the upper edge. Useful if you want your + UI to scale with screen size. + + The size of the user's screen is defined by client.view (indirectly by world.view), in our case "15x15". + Therefore, the top right corner (except during admin shenanigans) is at "15,15" +*/ + +/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5) + var/x_off = i % 2 ? 0 : -1 + var/y_off = round((i-1) / 2) + return"CENTER+[x_off]:16,SOUTH+[y_off]:5" + +/proc/ui_equip_position(mob/M) + var/y_off = round((M.held_items.len-1) / 2) //values based on old equip ui position (CENTER: +/-16,SOUTH+1:5) + return "CENTER:-16,SOUTH+[y_off+1]:5" + +/proc/ui_swaphand_position(mob/M, which = 1) //values based on old swaphand ui positions (CENTER: +/-16,SOUTH+1:5) + var/x_off = which == 1 ? -1 : 0 + var/y_off = round((M.held_items.len-1) / 2) + return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5" + +//Lower left, persistent menu +#define ui_inventory "WEST:6,SOUTH:5" + +//Middle left indicators +#define ui_lingchemdisplay "WEST,CENTER-1:15" +#define ui_lingstingdisplay "WEST:6,CENTER-3:11" + +//Lower center, persistent menu +#define ui_sstore1 "CENTER-5:10,SOUTH:5" +#define ui_id "CENTER-4:12,SOUTH:5" +#define ui_belt "CENTER-3:14,SOUTH:5" +#define ui_back "CENTER-2:14,SOUTH:5" +#define ui_storage1 "CENTER+1:18,SOUTH:5" +#define ui_storage2 "CENTER+2:20,SOUTH:5" +#define ui_combo "CENTER+4:24,SOUTH+1:7" //combo meter for martial arts + +//Lower right, persistent menu +#define ui_drop_throw "EAST-1:28,SOUTH+1:7" +#define ui_above_movement "EAST-2:26,SOUTH+1:7" +#define ui_above_intent "EAST-3:24, SOUTH+1:7" +#define ui_movi "EAST-2:26,SOUTH:5" +#define ui_acti "EAST-3:24,SOUTH:5" +#define ui_combat_toggle "EAST-3:24,SOUTH:5" +#define ui_zonesel "EAST-1:28,SOUTH:5" +#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12) +#define ui_crafting "EAST-4:22,SOUTH:5" +#define ui_building "EAST-4:22,SOUTH:21" +#define ui_language_menu "EAST-4:6,SOUTH:21" +#define ui_skill_menu "EAST-4:22,SOUTH:5" + +//Upper-middle right (alerts) +#define ui_alert1 "EAST-1:28,CENTER+5:27" +#define ui_alert2 "EAST-1:28,CENTER+4:25" +#define ui_alert3 "EAST-1:28,CENTER+3:23" +#define ui_alert4 "EAST-1:28,CENTER+2:21" +#define ui_alert5 "EAST-1:28,CENTER+1:19" + +//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") + +//Middle right (status indicators) +#define ui_healthdoll "EAST-1:28,CENTER-2:13" +#define ui_health "EAST-1:28,CENTER-1:15" +#define ui_internal "EAST-1:28,CENTER+1:17" +#define ui_mood "EAST-1:28,CENTER:17" +#define ui_spacesuit "EAST-1:28,CENTER-4:10" +#define ui_stamina "EAST-1:28,CENTER-3:10" + +//Pop-up inventory +#define ui_shoes "WEST+1:8,SOUTH:5" +#define ui_iclothing "WEST:6,SOUTH+1:7" +#define ui_oclothing "WEST+1:8,SOUTH+1:7" +#define ui_gloves "WEST+2:10,SOUTH+1:7" +#define ui_glasses "WEST:6,SOUTH+3:11" +#define ui_mask "WEST+1:8,SOUTH+2:9" +#define ui_ears "WEST+2:10,SOUTH+2:9" +#define ui_neck "WEST:6,SOUTH+2:9" +#define ui_head "WEST+1:8,SOUTH+3:11" + +//Generic living +#define ui_living_pull "EAST-1:28,CENTER-3:15" +#define ui_living_healthdoll "EAST-1:28,CENTER-1:15" + +//Monkeys +#define ui_monkey_head "CENTER-5:13,SOUTH:5" +#define ui_monkey_mask "CENTER-4:14,SOUTH:5" +#define ui_monkey_neck "CENTER-3:15,SOUTH:5" +#define ui_monkey_back "CENTER-2:16,SOUTH:5" + +//Drones +#define ui_drone_drop "CENTER+1:18,SOUTH:5" +#define ui_drone_pull "CENTER+2:2,SOUTH:5" +#define ui_drone_storage "CENTER-2:14,SOUTH:5" +#define ui_drone_head "CENTER-3:14,SOUTH:5" + +//Cyborgs +#define ui_borg_health "EAST-1:28,CENTER-1:15" +#define ui_borg_pull "EAST-2:26,SOUTH+1:7" +#define ui_borg_radio "EAST-1:28,SOUTH+1:7" +#define ui_borg_intents "EAST-2:26,SOUTH:5" +#define ui_borg_lamp "CENTER-3:16, SOUTH:5" +#define ui_borg_tablet "CENTER-4:16, SOUTH:5" +#define ui_inv1 "CENTER-2:16,SOUTH:5" +#define ui_inv2 "CENTER-1 :16,SOUTH:5" +#define ui_inv3 "CENTER :16,SOUTH:5" +#define ui_borg_module "CENTER+1:16,SOUTH:5" +#define ui_borg_store "CENTER+2:16,SOUTH:5" +#define ui_borg_camera "CENTER+3:21,SOUTH:5" +#define ui_borg_alerts "CENTER+4:21,SOUTH:5" +#define ui_borg_language_menu "CENTER+4:19,SOUTH+1:6" + +//Aliens +#define ui_alien_health "EAST,CENTER-1:15" +#define ui_alienplasmadisplay "EAST,CENTER-2:15" +#define ui_alien_queen_finder "EAST,CENTER-3:15" +#define ui_alien_storage_r "CENTER+1:18,SOUTH:5" +#define ui_alien_language_menu "EAST-4:20,SOUTH:5" + +//AI +#define ui_ai_core "SOUTH:6,WEST" +#define ui_ai_camera_list "SOUTH:6,WEST+1" +#define ui_ai_track_with_camera "SOUTH:6,WEST+2" +#define ui_ai_camera_light "SOUTH:6,WEST+3" +#define ui_ai_crew_monitor "SOUTH:6,WEST+4" +#define ui_ai_crew_manifest "SOUTH:6,WEST+5" +#define ui_ai_alerts "SOUTH:6,WEST+6" +#define ui_ai_announcement "SOUTH:6,WEST+7" +#define ui_ai_shuttle "SOUTH:6,WEST+8" +#define ui_ai_state_laws "SOUTH:6,WEST+9" +#define ui_ai_pda_send "SOUTH:6,WEST+10" +#define ui_ai_pda_log "SOUTH:6,WEST+11" +#define ui_ai_take_picture "SOUTH:6,WEST+12" +#define ui_ai_view_images "SOUTH:6,WEST+13" +#define ui_ai_sensor "SOUTH:6,WEST+14" +#define ui_ai_multicam "SOUTH+1:6,WEST+13" +#define ui_ai_add_multicam "SOUTH+1:6,WEST+14" +#define ui_ai_language_menu "SOUTH+1:8,WEST+11:30" + +//pAI +#define ui_pai_software "SOUTH:6,WEST" +#define ui_pai_shell "SOUTH:6,WEST+1" +#define ui_pai_chassis "SOUTH:6,WEST+2" +#define ui_pai_rest "SOUTH:6,WEST+3" +#define ui_pai_light "SOUTH:6,WEST+4" +#define ui_pai_newscaster "SOUTH:6,WEST+5" +#define ui_pai_host_monitor "SOUTH:6,WEST+6" +#define ui_pai_crew_manifest "SOUTH:6,WEST+7" +#define ui_pai_state_laws "SOUTH:6,WEST+8" +#define ui_pai_pda_send "SOUTH:6,WEST+9" +#define ui_pai_pda_log "SOUTH:6,WEST+10" +#define ui_pai_internal_gps "SOUTH:6,WEST+11" +#define ui_pai_take_picture "SOUTH:6,WEST+12" +#define ui_pai_view_images "SOUTH:6,WEST+13" +#define ui_pai_radio "SOUTH:6,WEST+14" +#define ui_pai_language_menu "SOUTH+1:8,WEST+13:31" + +//Ghosts +#define ui_ghost_spawners_menu "SOUTH:6,CENTER-3:24" +#define ui_ghost_orbit "SOUTH:6,CENTER-2:24" +#define ui_ghost_reenter_corpse "SOUTH:6,CENTER-1:24" +#define ui_ghost_teleport "SOUTH:6,CENTER:24" +#define ui_ghost_pai "SOUTH: 6, CENTER+1:24" +#define ui_ghost_minigames "SOUTH: 6, CENTER+2:24" +#define ui_ghost_language_menu "SOUTH: 22, CENTER+3:8" + +//Blobbernauts +#define ui_blobbernaut_overmind_health "EAST-1:28,CENTER+0:19" + +//Families +#define ui_wanted_lvl "NORTH,11" + +// Defines relating to action button positions + +/// Whatever the base action datum thinks is best +#define SCRN_OBJ_DEFAULT "default" +/// Floating somewhere on the hud, not in any predefined place +#define SCRN_OBJ_FLOATING "floating" +/// In the list of buttons stored at the top of the screen +#define SCRN_OBJ_IN_LIST "list" +/// In the collapseable palette +#define SCRN_OBJ_IN_PALETTE "palette" diff --git a/code/__DEFINES/~skyrat_defines/hud.dm b/code/__DEFINES/~skyrat_defines/hud.dm new file mode 100644 index 00000000000..abc82a6d8bc --- /dev/null +++ b/code/__DEFINES/~skyrat_defines/hud.dm @@ -0,0 +1,18 @@ +// ERP stuff +#define ui_vagina "WEST+1:8,SOUTH+4:14" +#define ui_vagina_down "WEST+1:8,SOUTH+1:8" +#define ui_anus "WEST+2:10,SOUTH+4:14" +#define ui_anus_down "WEST+2:10,SOUTH+1:8" +#define ui_nipples "WEST:6,SOUTH+5:17" +#define ui_nipples_down "WEST:6,SOUTH+2:11" +#define ui_penis "WEST+1:8,SOUTH+5:17" +#define ui_penis_down "WEST+1:8,SOUTH+2:11" +#define ui_erp_inventory "WEST:6,SOUTH+1:8" +#define ui_erp_inventory_up "WEST:6,SOUTH+4:14" + +// Cyborg PDA +#define ui_borg_pda_send "CENTER+5:21,SOUTH:5" // To the right of the alert panel +#define ui_borg_pda_log "CENTER+6:21,SOUTH:5" + +// Ammo counter +#define ui_ammocounter "EAST-1:28,CENTER-5:9" diff --git a/code/__HELPERS/screen_objs.dm b/code/__HELPERS/screen_objs.dm new file mode 100644 index 00000000000..aa86b6d5795 --- /dev/null +++ b/code/__HELPERS/screen_objs.dm @@ -0,0 +1,91 @@ +/// Takes a screen loc string in the format +/// "+-left-offset:+-pixel,+-bottom-offset:+-pixel" +/// Where the :pixel is optional, and returns +/// A list in the format (x_offset, y_offset) +/// We require context to get info out of screen locs that contain relative info, so NORTH, SOUTH, etc +/proc/screen_loc_to_offset(screen_loc, view) + if(!screen_loc) + return list(64, 64) + var/list/view_size = view_to_pixels(view) + var/x = 0 + var/y = 0 + // Time to parse for directional relative offsets + if(findtext(screen_loc, "EAST")) // If you're starting from the east, we start from the east too + x += view_size[1] + if(findtext(screen_loc, "WEST")) // HHHHHHHHHHHHHHHHHHHHHH WEST is technically a 1 tile offset from the start. Shoot me please + x += world.icon_size + if(findtext(screen_loc, "NORTH")) + y += view_size[2] + if(findtext(screen_loc, "SOUTH")) + y += world.icon_size + // Cut out everything we just parsed + screen_loc = cut_relative_direction(screen_loc) + + var/list/x_and_y = splittext(screen_loc, ",") + var/list/x_pack = splittext(x_and_y[1], ":") + var/list/y_pack = splittext(x_and_y[2], ":") + x += text2num(x_pack[1]) * world.icon_size + y += text2num(y_pack[1]) * world.icon_size + + if(length(x_pack) > 1) + x += text2num(x_pack[2]) + if(length(y_pack) > 1) + y += text2num(y_pack[2]) + return list(x, y) + +/// Takes a list in the form (x_offset, y_offset) +/// And converts it to a screen loc string +/// Accepts an optional view string/size to force the screen_loc around, so it can't go out of scope +/proc/offset_to_screen_loc(x_offset, y_offset, view = null) + if(view) + var/list/view_bounds = view_to_pixels(view) + x_offset = clamp(x_offset, world.icon_size, view_bounds[1]) + y_offset = clamp(y_offset, world.icon_size, view_bounds[2]) + + // Round with no argument is floor, so we get the non pixel offset here + var/x = round(x_offset / world.icon_size) + var/pixel_x = x_offset % world.icon_size + var/y = round(y_offset / world.icon_size) + var/pixel_y = y_offset % world.icon_size + + var/list/generated_loc = list() + generated_loc += "[x]" + if(pixel_x) + generated_loc += ":[pixel_x]" + generated_loc += ",[y]" + if(pixel_y) + generated_loc += ":[pixel_y]" + return jointext(generated_loc, "") + +/** + * Returns a valid location to place a screen object without overflowing the viewport + * + * * target: The target location as a purely number based screen_loc string "+-left-offset:+-pixel,+-bottom-offset:+-pixel" + * * target_offset: The amount we want to offset the target location by. We explictly don't care about direction here, we will try all 4 + * * view: The view variable of the client we're doing this for. We use this to get the size of the screen + * + * Returns a screen loc representing the valid location +**/ +/proc/get_valid_screen_location(target_loc, target_offset, view) + var/list/offsets = screen_loc_to_offset(target_loc) + var/base_x = offsets[1] + var/base_y = offsets[2] + + var/list/view_size = view_to_pixels(view) + + // Bias to the right, down, left, and then finally up + if(base_x + target_offset < view_size[1]) + return offset_to_screen_loc(base_x + target_offset, base_y, view) + if(base_y - target_offset > world.icon_size) + return offset_to_screen_loc(base_x, base_y - target_offset, view) + if(base_x - target_offset > world.icon_size) + return offset_to_screen_loc(base_x - target_offset, base_y, view) + if(base_y + target_offset < view_size[2]) + return offset_to_screen_loc(base_x, base_y + target_offset, view) + stack_trace("You passed in a scren location {[target_loc]} and offset {[target_offset]} that can't be fit in the viewport Width {[view_size[1]]}, Height {[view_size[2]]}. what did you do lad") + return null // The fuck did you do lad + +/// Takes a screen_loc string and cut out any directions like NORTH or SOUTH +/proc/cut_relative_direction(fragment) + var/static/regex/regex = regex(@"([A-Z])\w+", "g") + return regex.Replace(fragment, "") diff --git a/code/__HELPERS/view.dm b/code/__HELPERS/view.dm index 4a4587e1550..6a4210bc535 100644 --- a/code/__HELPERS/view.dm +++ b/code/__HELPERS/view.dm @@ -6,6 +6,15 @@ var/list/viewrangelist = splittext(view,"x") return list(text2num(viewrangelist[1]), text2num(viewrangelist[2])) +/// Takes a string or num view, and converts it to pixel width/height in a list(pixel_width, pixel_height) +/proc/view_to_pixels(view) + if(!view) + return list(0, 0) + var/list/view_info = getviewsize(view) + view_info[1] *= world.icon_size + view_info[2] *= world.icon_size + return view_info + /proc/in_view_range(mob/user, atom/A) var/list/view_range = getviewsize(user.client.view) var/turf/source = get_turf(user) diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm index d8000fb81c8..d0d280dc194 100644 --- a/code/_onclick/drag_drop.dm +++ b/code/_onclick/drag_drop.dm @@ -92,26 +92,26 @@ if (LAZYACCESS(modifiers, MIDDLE_CLICK)) if (src_object && src_location != over_location) middragtime = world.time - middragatom = src_object + middle_drag_atom_ref = WEAKREF(src_object) else middragtime = 0 - middragatom = null + middle_drag_atom_ref = null mouseParams = params - mouseLocation = over_location - mouseObject = over_object + mouse_location_ref = WEAKREF(over_location) + mouse_object_ref = WEAKREF(over_object) if(selected_target[1] && over_object?.IsAutoclickable()) selected_target[1] = over_object selected_target[2] = params if(active_mousedown_item) active_mousedown_item.onMouseDrag(src_object, over_object, src_location, over_location, params, mob) SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEDRAG, src_object, over_object, src_location, over_location, src_control, over_control, params) - + return ..() /obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob) return -/client/MouseDrop(src_object, over_object, src_location, over_location, src_control, over_control, params) - if (middragatom == src_object) +/client/MouseDrop(atom/src_object, atom/over_object, atom/src_location, atom/over_location, src_control, over_control, params) + if (IS_WEAKREF_OF(src_object, middle_drag_atom_ref)) middragtime = 0 - middragatom = null + middle_drag_atom_ref = null ..() diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm deleted file mode 100644 index 1f8302a9f7b..00000000000 --- a/code/_onclick/hud/_defines.dm +++ /dev/null @@ -1,199 +0,0 @@ -/* - These defines specificy screen locations. For more information, see the byond documentation on the screen_loc var. - - The short version: - - Everything is encoded as strings because apparently that's how Byond rolls. - - "1,1" is the bottom left square of the user's screen. This aligns perfectly with the turf grid. - "1:2,3:4" is the square (1,3) with pixel offsets (+2, +4); slightly right and slightly above the turf grid. - Pixel offsets are used so you don't perfectly hide the turf under them, that would be crappy. - - In addition, the keywords NORTH, SOUTH, EAST, WEST and CENTER can be used to represent their respective - screen borders. NORTH-1, for example, is the row just below the upper edge. Useful if you want your - UI to scale with screen size. - - The size of the user's screen is defined by client.view (indirectly by world.view), in our case "15x15". - Therefore, the top right corner (except during admin shenanigans) is at "15,15" -*/ - -/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5) - var/x_off = -(!(i % 2)) - var/y_off = round((i-1) / 2) - return"CENTER+[x_off]:16,SOUTH+[y_off]:5" - -/proc/ui_equip_position(mob/M) - var/y_off = round((M.held_items.len-1) / 2) //values based on old equip ui position (CENTER: +/-16,SOUTH+1:5) - return "CENTER:-16,SOUTH+[y_off+1]:5" - -/proc/ui_swaphand_position(mob/M, which = 1) //values based on old swaphand ui positions (CENTER: +/-16,SOUTH+1:5) - var/x_off = which == 1 ? -1 : 0 - var/y_off = round((M.held_items.len-1) / 2) - return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5" - -//Lower left, persistent menu -#define ui_inventory "WEST:6,SOUTH:5" - -//Middle left indicators -#define ui_lingchemdisplay "WEST,CENTER-1:15" -#define ui_lingstingdisplay "WEST:6,CENTER-3:11" - -//Lower center, persistent menu -#define ui_sstore1 "CENTER-5:10,SOUTH:5" -#define ui_id "CENTER-4:12,SOUTH:5" -#define ui_belt "CENTER-3:14,SOUTH:5" -#define ui_back "CENTER-2:14,SOUTH:5" -#define ui_storage1 "CENTER+1:18,SOUTH:5" -#define ui_storage2 "CENTER+2:20,SOUTH:5" -#define ui_combo "CENTER+4:24,SOUTH+1:7" //combo meter for martial arts -//SKYRAT EDIT ADDITION BEGIN - ERP_SLOT_SYSTEM -#define ui_vagina "WEST+1:8,SOUTH+4:14" -#define ui_vagina_down "WEST+1:8,SOUTH+1:8" -#define ui_anus "WEST+2:10,SOUTH+4:14" -#define ui_anus_down "WEST+2:10,SOUTH+1:8" -#define ui_nipples "WEST:6,SOUTH+5:17" -#define ui_nipples_down "WEST:6,SOUTH+2:11" -#define ui_penis "WEST+1:8,SOUTH+5:17" -#define ui_penis_down "WEST+1:8,SOUTH+2:11" -#define ui_erp_inventory "WEST:6,SOUTH+1:8" -#define ui_erp_inventory_up "WEST:6,SOUTH+4:14" -//SKYRAT EDI ADDITION END - -//Lower right, persistent menu -#define ui_drop_throw "EAST-1:28,SOUTH+1:7" -#define ui_above_movement "EAST-2:26,SOUTH+1:7" -#define ui_above_intent "EAST-3:24, SOUTH+1:7" -#define ui_movi "EAST-2:26,SOUTH:5" -#define ui_acti "EAST-3:24,SOUTH:5" -#define ui_combat_toggle "EAST-3:24,SOUTH:5" -#define ui_zonesel "EAST-1:28,SOUTH:5" -#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12) -#define ui_crafting "EAST-4:22,SOUTH:5" -#define ui_building "EAST-4:22,SOUTH:21" -#define ui_language_menu "EAST-4:6,SOUTH:21" -#define ui_skill_menu "EAST-4:22,SOUTH:5" - -//Upper-middle right (alerts) -#define ui_alert1 "EAST-1:28,CENTER+5:27" -#define ui_alert2 "EAST-1:28,CENTER+4:25" -#define ui_alert3 "EAST-1:28,CENTER+3:23" -#define ui_alert4 "EAST-1:28,CENTER+2:21" -#define ui_alert5 "EAST-1:28,CENTER+1:19" - -//Middle right (status indicators) -#define ui_healthdoll "EAST-1:28,CENTER-2:13" -#define ui_health "EAST-1:28,CENTER-1:15" -#define ui_internal "EAST-1:28,CENTER+1:17" -#define ui_mood "EAST-1:28,CENTER:17" -#define ui_spacesuit "EAST-1:28,CENTER-4:10" -#define ui_stamina "EAST-1:28,CENTER-3:10" - -//Pop-up inventory -#define ui_shoes "WEST+1:8,SOUTH:5" -#define ui_iclothing "WEST:6,SOUTH+1:7" -#define ui_oclothing "WEST+1:8,SOUTH+1:7" -#define ui_gloves "WEST+2:10,SOUTH+1:7" -#define ui_glasses "WEST:6,SOUTH+3:11" -#define ui_mask "WEST+1:8,SOUTH+2:9" -#define ui_ears "WEST+2:10,SOUTH+2:9" -#define ui_neck "WEST:6,SOUTH+2:9" -#define ui_head "WEST+1:8,SOUTH+3:11" - -//Generic living -#define ui_living_pull "EAST-1:28,CENTER-3:15" -#define ui_living_healthdoll "EAST-1:28,CENTER-1:15" - -//Monkeys -#define ui_monkey_head "CENTER-5:13,SOUTH:5" -#define ui_monkey_mask "CENTER-4:14,SOUTH:5" -#define ui_monkey_neck "CENTER-3:15,SOUTH:5" -#define ui_monkey_back "CENTER-2:16,SOUTH:5" - -//Drones -#define ui_drone_drop "CENTER+1:18,SOUTH:5" -#define ui_drone_pull "CENTER+2:2,SOUTH:5" -#define ui_drone_storage "CENTER-2:14,SOUTH:5" -#define ui_drone_head "CENTER-3:14,SOUTH:5" - -//Cyborgs -#define ui_borg_health "EAST-1:28,CENTER-1:15" -#define ui_borg_pull "EAST-2:26,SOUTH+1:7" -#define ui_borg_radio "EAST-1:28,SOUTH+1:7" -#define ui_borg_intents "EAST-2:26,SOUTH:5" -#define ui_borg_lamp "CENTER-3:16, SOUTH:5" -#define ui_borg_tablet "CENTER-4:16, SOUTH:5" -#define ui_inv1 "CENTER-2:16,SOUTH:5" -#define ui_inv2 "CENTER-1 :16,SOUTH:5" -#define ui_inv3 "CENTER :16,SOUTH:5" -#define ui_borg_module "CENTER+1:16,SOUTH:5" -#define ui_borg_store "CENTER+2:16,SOUTH:5" -#define ui_borg_camera "CENTER+3:21,SOUTH:5" -#define ui_borg_alerts "CENTER+4:21,SOUTH:5" -#define ui_borg_language_menu "CENTER+4:19,SOUTH+1:6" -// SKYRAT EDIT ADDITION BEGIN - Cyborg PDA -#define ui_borg_pda_send "CENTER+5:21,SOUTH:5" // To the right of the alert panel -#define ui_borg_pda_log "CENTER+6:21,SOUTH:5" -// SKYRAT EDIT ADDITION END - -//Aliens -#define ui_alien_health "EAST,CENTER-1:15" -#define ui_alienplasmadisplay "EAST,CENTER-2:15" -#define ui_alien_queen_finder "EAST,CENTER-3:15" -#define ui_alien_storage_r "CENTER+1:18,SOUTH:5" -#define ui_alien_language_menu "EAST-4:20,SOUTH:5" - -//AI -#define ui_ai_core "SOUTH:6,WEST" -#define ui_ai_camera_list "SOUTH:6,WEST+1" -#define ui_ai_track_with_camera "SOUTH:6,WEST+2" -#define ui_ai_camera_light "SOUTH:6,WEST+3" -#define ui_ai_crew_monitor "SOUTH:6,WEST+4" -#define ui_ai_crew_manifest "SOUTH:6,WEST+5" -#define ui_ai_alerts "SOUTH:6,WEST+6" -#define ui_ai_announcement "SOUTH:6,WEST+7" -#define ui_ai_shuttle "SOUTH:6,WEST+8" -#define ui_ai_state_laws "SOUTH:6,WEST+9" -#define ui_ai_pda_send "SOUTH:6,WEST+10" -#define ui_ai_pda_log "SOUTH:6,WEST+11" -#define ui_ai_take_picture "SOUTH:6,WEST+12" -#define ui_ai_view_images "SOUTH:6,WEST+13" -#define ui_ai_sensor "SOUTH:6,WEST+14" -#define ui_ai_multicam "SOUTH+1:6,WEST+13" -#define ui_ai_add_multicam "SOUTH+1:6,WEST+14" -#define ui_ai_language_menu "SOUTH+1:8,WEST+11:30" - -//pAI -#define ui_pai_software "SOUTH:6,WEST" -#define ui_pai_shell "SOUTH:6,WEST+1" -#define ui_pai_chassis "SOUTH:6,WEST+2" -#define ui_pai_rest "SOUTH:6,WEST+3" -#define ui_pai_light "SOUTH:6,WEST+4" -#define ui_pai_newscaster "SOUTH:6,WEST+5" -#define ui_pai_host_monitor "SOUTH:6,WEST+6" -#define ui_pai_crew_manifest "SOUTH:6,WEST+7" -#define ui_pai_state_laws "SOUTH:6,WEST+8" -#define ui_pai_pda_send "SOUTH:6,WEST+9" -#define ui_pai_pda_log "SOUTH:6,WEST+10" -#define ui_pai_internal_gps "SOUTH:6,WEST+11" -#define ui_pai_take_picture "SOUTH:6,WEST+12" -#define ui_pai_view_images "SOUTH:6,WEST+13" -#define ui_pai_radio "SOUTH:6,WEST+14" -#define ui_pai_language_menu "SOUTH+1:8,WEST+13:31" - -//Ghosts -#define ui_ghost_spawners_menu "SOUTH:6,CENTER-3:24" -#define ui_ghost_orbit "SOUTH:6,CENTER-2:24" -#define ui_ghost_reenter_corpse "SOUTH:6,CENTER-1:24" -#define ui_ghost_teleport "SOUTH:6,CENTER:24" -#define ui_ghost_pai "SOUTH: 6, CENTER+1:24" -#define ui_ghost_minigames "SOUTH: 6, CENTER+2:24" -#define ui_ghost_language_menu "SOUTH: 22, CENTER+3:8" - -//Blobbernauts -#define ui_blobbernaut_overmind_health "EAST-1:28,CENTER+0:19" - -//Families -#define ui_wanted_lvl "NORTH,11" - -//SKYRAT HUD DEFINES BELOW -#define ui_ammocounter "EAST-1:28,CENTER-5:9" diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index ffd1a480b12..29b10891574 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -2,22 +2,36 @@ /atom/movable/screen/movable/action_button var/datum/action/linked_action + var/datum/hud/our_hud var/actiontooltipstyle = "" screen_loc = null var/button_icon_state var/appearance_cache + /// 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 - var/ordered = TRUE //If the button gets placed into the default bar + /// A weakref of the last thing we hovered over + /// God I hate how dragging works + var/datum/weakref/last_hovored_ref + +/atom/movable/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 ..() /atom/movable/screen/movable/action_button/proc/can_use(mob/user) if(linked_action) - if(linked_action.owner == user) + if(linked_action.viewers[user.hud_used]) return TRUE - for(var/datum/weakref/reference as anything in linked_action.sharers) - if(IS_WEAKREF_OF(user, reference)) - return TRUE return FALSE else if (isobserver(user)) var/mob/dead/observer/O = user @@ -25,41 +39,14 @@ else return TRUE -/atom/movable/screen/movable/action_button/MouseDrop(over_object) - if(!can_use(usr)) - return - if((istype(over_object, /atom/movable/screen/movable/action_button) && !istype(over_object, /atom/movable/screen/movable/action_button/hide_toggle))) - if(locked) - to_chat(usr, span_warning("Action button \"[name]\" is locked, unlock it first.")) - return - var/atom/movable/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 - ordered = TRUE - B.moved = FALSE - B.ordered = TRUE - usr.update_action_buttons() - else - return ..() - /atom/movable/screen/movable/action_button/Click(location,control,params) if (!can_use(usr)) return FALSE 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 = 0 - usr.update_action_buttons() //redraw buttons that are no longer considered "moved" - return TRUE - if(LAZYACCESS(modifiers, CTRL_CLICK)) - locked = !locked - to_chat(usr, span_notice("Action button \"[name]\" [locked ? "" : "un"]locked.")) - if(id && usr.client) //try to (un)remember position - usr.client.prefs.action_buttons_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.next_click > world.time) return @@ -70,127 +57,105 @@ linked_action.Trigger(trigger_flags = trigger_flags) return TRUE -//Hide/Show Action Buttons ... Button -/atom/movable/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 to reset all buttons to their default positions." - icon = 'icons/hud/actions.dmi' - icon_state = "bg_default" - var/hidden = FALSE - var/hide_icon = 'icons/hud/actions.dmi' - var/hide_state = "hide" - var/show_state = "show" - var/mutable_appearance/hide_appearance - var/mutable_appearance/show_appearance - -/atom/movable/screen/movable/action_button/hide_toggle/Initialize(mapload) +// 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 +/atom/movable/screen/movable/action_button/MouseDrag(atom/over_object, src_location, over_location, src_control, over_control, params) . = ..() - 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) - - -/atom/movable/screen/movable/action_button/hide_toggle/Click(location,control,params) - if (!can_use(usr)) + if(!can_use(usr)) return + if(IS_WEAKREF_OF(over_object, last_hovored_ref)) + return + var/atom/old_object + if(last_hovored_ref) + old_object = last_hovored_ref?.resolve() + else // If there's 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) - 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) //try to (un)remember position - usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = locked ? moved : null - return TRUE - if(LAZYACCESS(modifiers, ALT_CLICK)) - var/buttons_locked = usr.client.prefs.read_preference(/datum/preference/toggle/buttons_locked) - for(var/V in usr.actions) - var/datum/action/A = V - var/atom/movable/screen/movable/action_button/B = A.button - B.moved = FALSE - if(B.id && usr.client) - usr.client.prefs.action_buttons_screen_locs["[B.name]_[B.id]"] = null - B.locked = buttons_locked - locked = buttons_locked - moved = FALSE - if(id && usr.client) - usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = null - usr.update_action_buttons(TRUE) - to_chat(usr, span_notice("Action button positions have been reset.")) - return TRUE - 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_appearance() - usr.update_action_buttons() + last_hovored_ref = WEAKREF(over_object) + over_object.MouseEntered(over_location, over_control, params) -/atom/movable/screen/movable/action_button/hide_toggle/AltClick(mob/user) - for(var/V in user.actions) - var/datum/action/A = V - var/atom/movable/screen/movable/action_button/B = A.button - B.moved = FALSE - if(moved) - moved = FALSE - user.update_action_buttons(TRUE) - to_chat(user, span_notice("Action button positions have been reset.")) - - -/atom/movable/screen/movable/action_button/hide_toggle/proc/InitialiseIcon(datum/hud/owner_hud) - 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"] - update_appearance() - -/atom/movable/screen/movable/action_button/hide_toggle/update_overlays() - . = ..() - . += hidden ? show_appearance : hide_appearance - -/atom/movable/screen/movable/action_button/MouseEntered(location,control,params) +/atom/movable/screen/movable/action_button/MouseEntered(location, control, params) . = ..() if(!QDELETED(src)) - openToolTip(usr,src,params,title = name,content = desc,theme = actiontooltipstyle) + openToolTip(usr, src, params, title = name, content = desc, theme = actiontooltipstyle) - -/atom/movable/screen/movable/action_button/MouseExited() +/atom/movable/screen/movable/action_button/MouseExited(location, control, params) closeToolTip(usr) + return ..() + +/atom/movable/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, /atom/movable/screen/action_landing)) + var/atom/movable/screen/action_landing/reserve = over_object + reserve.hit_by(src) + our_hud.hide_landings() + save_position() + return + + our_hud.hide_landings() + if(istype(over_object, /atom/movable/screen/button_palette) || istype(over_object, /atom/movable/screen/palette_scroll)) + our_hud.position_action(src, SCRN_OBJ_IN_PALETTE) + save_position() + return + if(istype(over_object, /atom/movable/screen/movable/action_button)) + var/atom/movable/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() + +/atom/movable/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 + + user.client.prefs.action_buttons_screen_locs["[name]_[id]"] = position_info + +/atom/movable/screen/movable/action_button/proc/load_position() + var/mob/user = our_hud.mymob + if(!user) + return + var/position_info = user.client?.prefs?.action_buttons_screen_locs["[name]_[id]"] || SCRN_OBJ_DEFAULT + user.hud_used.position_action(src, position_info) + +/atom/movable/screen/movable/action_button/proc/dump_save() + var/mob/user = our_hud.mymob + if(!user?.client) + return + user.client.prefs.action_buttons_screen_locs -= "[name]_[id]" /datum/hud/proc/get_action_buttons_icons() . = list() .["bg_icon"] = ui_style .["bg_state"] = "template" - //TODO : Make these fit theme - .["toggle_icon"] = 'icons/hud/actions.dmi' - .["toggle_hide"] = "hide" - .["toggle_show"] = "show" - //see human and alien hud for specific implementations. /mob/proc/update_action_buttons_icon(status_only = FALSE) for(var/X in actions) var/datum/action/A = X - A.UpdateButtonIcon(status_only) + A.UpdateButtons(status_only) //This is the proc used to update all the action buttons. /mob/proc/update_action_buttons(reload_screen) @@ -200,58 +165,243 @@ if(hud_used.hud_shown != HUD_STYLE_STANDARD) return - var/button_number = 0 + for(var/datum/action/action as anything in actions) + var/atom/movable/screen/movable/action_button/button = action.viewers[hud_used] + action.UpdateButtons() + if(reload_screen) + client.screen += button - 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) - A.UpdateButtonIcon() - var/atom/movable/screen/movable/action_button/B = A.button - if(B.ordered) - button_number++ - if(B.moved) - B.screen_loc = B.moved - else - B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number) - if(reload_screen) - client.screen += B - - if(!button_number) - hud_used.hide_actions_toggle.screen_loc = null - return - - 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 if(reload_screen) - client.screen += hud_used.hide_actions_toggle + hud_used.update_our_owner() + // This holds the logic for the palette buttons + hud_used.palette_actions.refresh_actions() +/atom/movable/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 +/atom/movable/screen/button_palette/Destroy() + if(our_hud) + our_hud.mymob?.client?.screen -= src + our_hud.toggle_palette = null + our_hud = null + return ..() -#define AB_MAX_COLUMNS 10 +/atom/movable/screen/button_palette/Initialize(mapload) + . = ..() + update_appearance() -/datum/hud/proc/ButtonNumberToScreenCoords(number) // TODO : Make this zero-indexed for readabilty - var/row = round((number - 1)/AB_MAX_COLUMNS) - var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1 +/atom/movable/screen/button_palette/proc/set_hud(datum/hud/our_hud) + src.our_hud = our_hud + refresh_owner() - var/coord_col = "+[col-1]" - var/coord_col_offset = 4 + 2 * col +/atom/movable/screen/button_palette/update_name(updates) + . = ..() + if(expanded) + name = "Hide Buttons" + else + name = "Show Buttons" - var/coord_row = "[row ? -row : "+0"]" +/atom/movable/screen/button_palette/proc/refresh_owner() + var/mob/viewer = our_hud.mymob + if(viewer.client) + viewer.client.screen |= src - return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:-6" + 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)] -/datum/hud/proc/SetButtonCoords(atom/movable/screen/button,number) - var/row = round((number-1)/AB_MAX_COLUMNS) - var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1 - var/x_offset = 32*(col-1) + 4 + 2*col - var/y_offset = -32*(row+1) + 26 + icon_state = "[ui_name]_palette" - var/matrix/M = matrix() - M.Translate(x_offset,y_offset) - button.transform = M +/atom/movable/screen/button_palette/MouseEntered(location, control, params) + . = ..() + if(QDELETED(src)) + return + show_tooltip(params) + +/atom/movable/screen/button_palette/MouseExited() + closeToolTip(usr) + return ..() + +/atom/movable/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)) + +/atom/movable/screen/button_palette/proc/play_item_added() + color_for_now(GLOB.palette_added_matrix) + +/atom/movable/screen/button_palette/proc/play_item_removed() + color_for_now(GLOB.palette_removed_matrix) + +/atom/movable/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/remove_color, color), 2 SECONDS) + +/atom/movable/screen/button_palette/proc/remove_color(list/to_remove) + color_timer_id = null + remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, to_remove) + +/atom/movable/screen/button_palette/proc/can_use(mob/user) + if (isobserver(user)) + var/mob/dead/observer/O = user + return !O.observetarget + return TRUE + +/atom/movable/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/atom/movable/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) + +/atom/movable/screen/button_palette/proc/clicked_while_open(datum/source, atom/target, atom/location, control, params, mob/user) + if(istype(target, /atom/movable/screen/movable/action_button) || istype(target, /atom/movable/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) + +/atom/movable/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() + + if(!usr.client) + return + + if(expanded) + RegisterSignal(usr.client, COMSIG_CLIENT_CLICK, .proc/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 + +/atom/movable/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 + +/atom/movable/screen/palette_scroll/proc/can_use(mob/user) + if (isobserver(user)) + var/mob/dead/observer/O = user + return !O.observetarget + return TRUE + +/atom/movable/screen/palette_scroll/proc/set_hud(datum/hud/our_hud) + src.our_hud = our_hud + refresh_owner() + +/atom/movable/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"] + +/atom/movable/screen/palette_scroll/Click(location, control, params) + if(!can_use(usr)) + return + our_hud.palette_actions.scroll(scroll_direction) + +/atom/movable/screen/palette_scroll/MouseEntered(location, control, params) + . = ..() + if(QDELETED(src)) + return + openToolTip(usr, src, params, title = name, content = desc) + +/atom/movable/screen/palette_scroll/MouseExited() + closeToolTip(usr) + return ..() + +/atom/movable/screen/palette_scroll/down + name = "Scroll Down" + desc = "Click on this to scroll the actions above down" + icon_state = "scroll_down" + scroll_direction = 1 + +/atom/movable/screen/palette_scroll/down/Destroy() + if(our_hud) + our_hud.mymob?.client?.screen -= src + our_hud.palette_down = null + our_hud = null + return ..() + +/atom/movable/screen/palette_scroll/up + name = "Scroll Up" + desc = "Click on this to scroll the actions above up" + icon_state = "scroll_up" + scroll_direction = -1 + +/atom/movable/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 +/atom/movable/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 + +/atom/movable/screen/action_landing/Destroy() + if(owner) + owner.landing = null + owner?.owner?.mymob?.client?.screen -= src + owner.refresh_actions() + owner = null + return ..() + +/atom/movable/screen/action_landing/proc/set_owner(datum/action_group/owner) + src.owner = owner + refresh_owner() + +/atom/movable/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 +/atom/movable/screen/action_landing/proc/hit_by(atom/movable/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/hud.dm b/code/_onclick/hud/hud.dm index b18b7ee12f6..8a323820aac 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -93,8 +93,13 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( /// game (MouseEntered). var/screentip_color - var/atom/movable/screen/movable/action_button/hide_toggle/hide_actions_toggle - var/action_buttons_hidden = FALSE + var/atom/movable/screen/button_palette/toggle_palette + var/atom/movable/screen/palette_scroll/down/palette_down + var/atom/movable/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/atom/movable/screen/healths var/atom/movable/screen/stamina @@ -114,10 +119,12 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( ui_style = ui_style2icon(owner.client?.prefs?.read_preference(/datum/preference/choiced/ui_style)) erp_ui_style = erp_ui_style2icon(owner.client?.prefs?.read_preference(/datum/preference/choiced/ui_style)) //SKYRAT EDIT - ADDITION - ERP ICONS FIX - hide_actions_toggle = new - hide_actions_toggle.InitialiseIcon(src) - if(mymob.client?.prefs) - hide_actions_toggle.locked = mymob.client.prefs.read_preference(/datum/preference/toggle/buttons_locked) + toggle_palette = new() + toggle_palette.set_hud(src) + palette_down = new() + palette_down.set_hud(src) + palette_up = new() + palette_up.set_hud(src) hand_slots = list() @@ -142,7 +149,13 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( if(mymob.hud_used == src) mymob.hud_used = null - QDEL_NULL(hide_actions_toggle) + QDEL_NULL(toggle_palette) + QDEL_NULL(palette_down) + QDEL_NULL(palette_up) + QDEL_NULL(palette_actions) + QDEL_NULL(listed_actions) + QDEL_LIST(floating_actions) + QDEL_NULL(module_store_icon) QDEL_LIST(static_inventory) @@ -184,10 +197,14 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( /mob/proc/create_mob_hud() if(!client || hud_used) return - hud_used = new hud_type(src) + set_hud_used(new hud_type(src)) update_sight() SEND_SIGNAL(src, COMSIG_MOB_HUD_CREATED) +/mob/proc/set_hud_used(datum/hud/new_hud) + hud_used = new_hud + new_hud.build_action_groups() + //Version denotes which style should be displayed. blank or 0 means "next version" /datum/hud/proc/show_hud(version = 0, mob/viewmob) if(!ismob(mymob)) @@ -196,6 +213,8 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( if(!screenmob.client) return FALSE + // This code is the absolute fucking worst, I want it to go die in a fire + // Seriously, why screenmob.client.screen = list() screenmob.client.apply_clickcatcher() @@ -221,7 +240,7 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( if(infodisplay.len) screenmob.client.screen += infodisplay - screenmob.client.screen += hide_actions_toggle + screenmob.client.screen += toggle_palette if(action_intent) action_intent.screen_loc = initial(action_intent.screen_loc) //Restore intent selection to the original position @@ -320,7 +339,6 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( ui_style = new_ui_style build_hand_slots() - hide_actions_toggle.InitialiseIcon(src) //SKYRAT EDIT - ADDITION - ERP ICONS FIX @@ -334,7 +352,6 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( item.icon = new_erp_ui_style erp_ui_style = new_erp_ui_style - hide_actions_toggle.InitialiseIcon(src) //SKYRAT EDIT - ADDITION - ERP ICONS FIX - END @@ -384,3 +401,306 @@ GLOBAL_LIST_INIT(available_erp_ui_styles, list( /datum/hud/proc/update_locked_slots() return + +/datum/hud/proc/position_action(atom/movable/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(atom/movable/screen/movable/action_button/button, atom/movable/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_size.getView()) // 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(atom/movable/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 + +/// Generates visual landings for all groups that the button is not a memeber of +/datum/hud/proc/generate_landings(atom/movable/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/atom/movable/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/atom/movable/screen/movable/action_button/button = action.viewers[src] + if(!button) + action.ShowTo(mymob) + button = action.viewers[src] + position_action(button, button.location) + +/datum/action_group + /// The hud we're owned by + var/datum/hud/owner + /// The actions we're managing + var/list/atom/movable/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/atom/movable/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(atom/movable/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(atom/movable/screen/action) + actions -= action + 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/atom/movable/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(atom/movable/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(atom/movable/screen/action, index) + . = ..() + var/atom/movable/screen/button_palette/palette = owner.toggle_palette + palette.play_item_added() + +/datum/action_group/palette/remove_action(atom/movable/screen/action) + . = ..() + var/atom/movable/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/atom/movable/screen/button_palette/palette = owner.toggle_palette + var/atom/movable/screen/palette_scroll/scroll_down = owner.palette_down + var/atom/movable/screen/palette_scroll/scroll_up = owner.palette_up + + 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/atom/movable/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/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm index c3372d338f3..b1f40f76294 100644 --- a/code/_onclick/hud/movable_screen_objects.dm +++ b/code/_onclick/hud/movable_screen_objects.dm @@ -9,9 +9,8 @@ //Not tied to the grid, places it's center where the cursor is /atom/movable/screen/movable + mouse_drag_pointer = 'icons/effects/mouse_pointers/screen_drag.dmi' var/snap2grid = FALSE - var/moved = FALSE - var/locked = FALSE var/x_off = -16 var/y_off = -16 @@ -21,35 +20,29 @@ /atom/movable/screen/movable/snap snap2grid = TRUE - /atom/movable/screen/movable/MouseDrop(over_object, src_location, over_location, src_control, over_control, params) - if(locked) //no! I am locked! begone! + var/position = mouse_params_to_position(params) + if(!position) return + + screen_loc = position + +/// Takes mouse parmas as input, returns a string representing the appropriate mouse position +/atom/movable/screen/movable/proc/mouse_params_to_position(params) var/list/modifiers = params2list(params) //No screen-loc information? abort. if(!LAZYACCESS(modifiers, SCREEN_LOC)) return - - //Split screen-loc up into X+Pixel_X and Y+Pixel_Y - var/list/screen_loc_params = splittext(LAZYACCESS(modifiers, SCREEN_LOC), ",") - - //Split X+Pixel_X up into list(X, Pixel_X) - var/list/screen_loc_X = splittext(screen_loc_params[1],":") - - //Split Y+Pixel_Y up into list(Y, Pixel_Y) - var/list/screen_loc_Y = splittext(screen_loc_params[2],":") - + var/client/our_client = usr.client + var/list/offset = screen_loc_to_offset(LAZYACCESS(modifiers, SCREEN_LOC)) if(snap2grid) //Discard Pixel Values - screen_loc = "[screen_loc_X[1]],[screen_loc_Y[1]]" - + offset[1] = FLOOR(offset[1], world.icon_size) // drops any pixel offset + offset[2] = FLOOR(offset[2], world.icon_size) // drops any pixel offset else //Normalise Pixel Values (So the object drops at the center of the mouse, not 16 pixels off) - var/pix_X = text2num(screen_loc_X[2]) + x_off - var/pix_Y = text2num(screen_loc_Y[2]) + y_off - screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]" - - moved = screen_loc - + offset[1] += x_off + offset[2] += y_off + return offset_to_screen_loc(offset[1], offset[2], our_client?.view) //Debug procs /client/proc/test_movable_UI() diff --git a/code/_onclick/hud/screentip.dm b/code/_onclick/hud/screentip.dm index 36159ec0086..198e70326ab 100644 --- a/code/_onclick/hud/screentip.dm +++ b/code/_onclick/hud/screentip.dm @@ -16,6 +16,6 @@ SIGNAL_HANDLER if(!hud || !hud.mymob.client.view_size) //Might not have been initialized by now return - maptext_width = getviewsize(hud.mymob.client.view_size.getView())[1] * world.icon_size + maptext_width = view_to_pixels(hud.mymob.client.view_size.getView())[1] diff --git a/code/controllers/subsystem/augury.dm b/code/controllers/subsystem/augury.dm index 922e65e0e74..cb8f62df461 100644 --- a/code/controllers/subsystem/augury.dm +++ b/code/controllers/subsystem/augury.dm @@ -72,15 +72,15 @@ SUBSYSTEM_DEF(augury) SSaugury.watchers += owner to_chat(owner, span_notice("You are now auto-following debris.")) active = TRUE - UpdateButtonIcon() + UpdateButtons() /datum/action/innate/augury/Deactivate() SSaugury.watchers -= owner to_chat(owner, span_notice("You are no longer auto-following debris.")) active = FALSE - UpdateButtonIcon() + UpdateButtons() -/datum/action/innate/augury/UpdateButtonIcon(status_only = FALSE, force) +/datum/action/innate/augury/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force) ..() if(active) button.icon_state = "template_active" diff --git a/code/datums/action.dm b/code/datums/action.dm index 7e152b1131e..4366534e734 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -4,9 +4,10 @@ var/datum/target var/check_flags = NONE var/processing = FALSE - var/atom/movable/screen/movable/action_button/button = null var/buttontooltipstyle = "" var/transparent_when_unavailable = TRUE + /// Where any buttons we create should be by default. Accepts screen_loc and location defines + var/default_button_position = SCRN_OBJ_IN_LIST var/button_icon = 'icons/mob/actions/backgrounds.dmi' //This is the file for the BACKGROUND icon var/background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND //And this is the state for the background icon @@ -14,17 +15,11 @@ var/icon_icon = 'icons/hud/actions.dmi' //This is the file for the ACTION icon var/button_icon_state = "default" //And this is the state for the action icon var/mob/owner - ///All mobs that are sharing our action button. - var/list/sharers = list() + ///List of all mobs that are viewing our action button -> A unique movable for them to view. + var/list/viewers = list() /datum/action/New(Target) link_to(Target) - button = new - button.linked_action = src - button.name = name - button.actiontooltipstyle = buttontooltipstyle - if(desc) - button.desc = desc /datum/action/proc/link_to(Target) target = Target @@ -35,41 +30,21 @@ if(owner) Remove(owner) target = null - QDEL_NULL(button) + QDEL_LIST_ASSOC_VAL(viewers) // Qdel the buttons in the viewers list **NOT THE HUDS** return ..() /datum/action/proc/Grant(mob/M) - if(M) - if(owner) - if(owner == M) - return - Remove(owner) - owner = M - RegisterSignal(owner, COMSIG_PARENT_QDELETING, .proc/clear_ref, override = TRUE) - - //button id generation - var/counter = 0 - var/bitfield = 0 - for(var/datum/action/A 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.read_preference(/datum/preference/toggle/buttons_locked) || button.id ? M.client.prefs.action_buttons_screen_locs["[name]_[button.id]"] : FALSE //even if it's not defaultly locked we should remember we locked it before - button.moved = button.id ? M.client.prefs.action_buttons_screen_locs["[name]_[button.id]"] : FALSE - M.update_action_buttons() - else + if(!M) Remove(owner) + return + if(owner) + if(owner == M) + return + Remove(owner) + owner = M + RegisterSignal(owner, COMSIG_PARENT_QDELETING, .proc/clear_ref, override = TRUE) + + GiveAction(M) /datum/action/proc/clear_ref(datum/ref) SIGNAL_HANDLER @@ -79,26 +54,18 @@ qdel(src) /datum/action/proc/Remove(mob/M) - for(var/datum/weakref/reference as anything in sharers) - var/mob/freeloader = reference.resolve() - if(!freeloader) + for(var/datum/hud/hud in viewers) + if(!hud.mymob) continue - Unshare(freeloader) - sharers = null - if(M) - if(M.client) - M.client.screen -= button - LAZYREMOVE(M.actions, src) - M.update_action_buttons() + HideFrom(hud.mymob) + LAZYREMOVE(M.actions, src) // We aren't always properly inserted into the viewers list, gotta make sure that action's cleared + viewers = list() + if(owner) UnregisterSignal(owner, COMSIG_PARENT_QDELETING) if(target == owner) RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/clear_ref) owner = null - if(button) - button.moved = FALSE //so the button appears in its normal position when given to another owner. - button.locked = FALSE - button.id = null /datum/action/proc/Trigger(trigger_flags) if(!IsAvailable()) @@ -123,31 +90,36 @@ return FALSE return TRUE +/datum/action/proc/UpdateButtons(status_only, force) + for(var/datum/hud/hud in viewers) + var/atom/movable/screen/movable/button = viewers[hud] + UpdateButton(button, status_only, force) -/datum/action/proc/UpdateButtonIcon(status_only = FALSE, force = FALSE) - if(button) - if(!status_only) - button.name = name - button.desc = desc - if(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 - if(button.icon != button_icon) - button.icon = button_icon - if(button.icon_state != background_icon_state) - button.icon_state = background_icon_state - - ApplyIcon(button, force) - - if(!IsAvailable()) - button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0) +/datum/action/proc/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE) + if(!button) + return + if(!status_only) + button.name = name + button.desc = desc + if(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 - button.color = rgb(255,255,255,255) - return TRUE + if(button.icon != button_icon) + button.icon = button_icon + if(button.icon_state != background_icon_state) + button.icon_state = background_icon_state + + ApplyIcon(button, force) + + 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(atom/movable/screen/movable/action_button/current_button, force = FALSE) if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force)) @@ -157,28 +129,67 @@ /datum/action/proc/OnUpdatedIcon() SIGNAL_HANDLER - UpdateButtonIcon() + UpdateButtons() -//Adds our action button to the screen of another player -/datum/action/proc/Share(mob/freeloader) - if(!freeloader.client) +//Give our action button to the player +/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 - sharers += WEAKREF(freeloader) - freeloader.client.screen += button - freeloader.actions += src - freeloader.update_action_buttons() -//Removes our action button from the screen of another player -/datum/action/proc/Unshare(mob/freeloader) - if(!freeloader.client) + LAZYOR(viewer.actions, src) // Move this in + ShowTo(viewer) + +//Adds our action button to the screen of a player +/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 - for(var/freeloader_reference in sharers) - if(IS_WEAKREF_OF(freeloader, freeloader_reference)) - sharers -= freeloader_reference - break - freeloader.client.screen -= button - freeloader.actions -= src - freeloader.update_action_buttons() + + var/atom/movable/screen/movable/action_button/button = CreateButton() + 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 button from the screen of a player +/datum/action/proc/HideFrom(mob/viewer) + var/datum/hud/our_hud = viewer.hud_used + var/atom/movable/screen/movable/action_button/button = viewers[our_hud] + LAZYREMOVE(viewer.actions, src) + if(button) + qdel(button) + +/datum/action/proc/CreateButton() + var/atom/movable/screen/movable/action_button/button = new() + button.linked_action = src + button.name = name + button.actiontooltipstyle = buttontooltipstyle + if(desc) + button.desc = desc + return button + +/datum/action/proc/SetId(atom/movable/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/atom/movable/screen/movable/action_button/button = action.viewers[owner.hud_used] + if(action.name == name && button.id) + bitfield |= button.id + + 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 //Presets for item actions /datum/action/item_action @@ -274,12 +285,14 @@ /datum/action/item_action/set_internals name = "Set Internals" -/datum/action/item_action/set_internals/UpdateButtonIcon(status_only = FALSE, force) - if(..()) //button available - if(iscarbon(owner)) - var/mob/living/carbon/C = owner - if(target == C.internal) - button.icon_state = "template_active" +/datum/action/item_action/set_internals/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force) + if(!..()) // no button available + return + if(!iscarbon(owner)) + return + var/mob/living/carbon/C = owner + if(target == C.internal) + button.icon_state = "template_active" /datum/action/item_action/pick_color name = "Choose A Color" @@ -333,7 +346,7 @@ SIGNAL_HANDLER button_icon_state = "thermal_[suit.thermal_on ? "on" : "off"]" - UpdateButtonIcon() + UpdateButtons() /datum/action/item_action/vortex_recall name = "Vortex Recall" @@ -387,7 +400,6 @@ ..() var/obj/item/item_target = target name = "Toggle [item_target.name]" - button.name = name /datum/action/item_action/halt name = "HALT!" @@ -413,7 +425,6 @@ ..() var/obj/item/item_target = target name = "Adjust [item_target.name]" - button.name = name /datum/action/item_action/switch_hud name = "Switch HUD" @@ -499,13 +510,11 @@ ..() var/obj/item/organ/organ_target = target name = "Toggle [organ_target.name]" - button.name = name /datum/action/item_action/organ_action/use/New(Target) ..() var/obj/item/organ/organ_target = target name = "Use [organ_target.name]" - button.name = name /datum/action/item_action/cult_dagger name = "Draw Blood Rune" @@ -514,15 +523,13 @@ button_icon_state = "draw" buttontooltipstyle = "cult" background_icon_state = "bg_demon" + default_button_position = "6:157,4:-2" /datum/action/item_action/cult_dagger/Grant(mob/M) if(!IS_CULTIST(M)) Remove(owner) return - - . = ..() - button.screen_loc = "6:157,4:-2" - button.moved = "6:157,4:-2" + return ..() /datum/action/item_action/cult_dagger/Trigger(trigger_flags) for(var/obj/item/held_item as anything in owner.held_items) // In case we were already holding a dagger @@ -617,7 +624,6 @@ icon_icon = S.action_icon button_icon_state = S.action_icon_state background_icon_state = S.action_background_icon_state - button.name = name /datum/action/spell_action/Destroy() var/obj/effect/proc_holder/S = target @@ -695,13 +701,14 @@ // Shares cooldowns with other cooldown abilities of the same value, not active if null var/shared_cooldown -/datum/action/cooldown/New(Target) - ..() +/datum/action/cooldown/CreateButton() + var/atom/movable/screen/movable/action_button/button = ..() button.maptext = "" button.maptext_x = 8 button.maptext_y = 0 button.maptext_width = 24 button.maptext_height = 12 + return button /datum/action/cooldown/IsAvailable() return ..() && (next_use_time <= world.time) @@ -723,7 +730,7 @@ next_use_time = world.time + override_cooldown_time else next_use_time = world.time + cooldown_time - UpdateButtonIcon() + UpdateButtons() START_PROCESSING(SSfastprocess, src) /datum/action/cooldown/Trigger(trigger_flags, atom/target) @@ -741,7 +748,7 @@ else owner.click_intercept = src for(var/datum/action/cooldown/ability in owner.actions) - ability.UpdateButtonIcon() + ability.UpdateButtons() return TRUE return PreActivate(owner) @@ -766,12 +773,13 @@ /datum/action/cooldown/proc/Activate(atom/target) return -/datum/action/cooldown/UpdateButtonIcon(status_only = FALSE, force = FALSE) +/datum/action/cooldown/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE) . = ..() + if(!button) + return var/time_left = max(next_use_time - world.time, 0) - if(button) - if(text_cooldown) - button.maptext = MAPTEXT("[round(time_left/10, 0.1)]") + if(text_cooldown) + button.maptext = MAPTEXT("[round(time_left/10, 0.1)]") if(!owner || time_left == 0) button.maptext = "" if(IsAvailable() && owner.click_intercept == src) @@ -781,28 +789,28 @@ var/time_left = max(next_use_time - world.time, 0) if(!owner || time_left == 0) STOP_PROCESSING(SSfastprocess, src) - UpdateButtonIcon() + UpdateButtons() /datum/action/cooldown/Grant(mob/M) ..() - if(owner) - UpdateButtonIcon() - if(next_use_time > world.time) - START_PROCESSING(SSfastprocess, src) + if(!owner) + return + UpdateButtons() + if(next_use_time > world.time) + START_PROCESSING(SSfastprocess, src) ///Like a cooldown action, but with an associated proc holder. /datum/action/cooldown/spell_like /datum/action/cooldown/spell_like/New(Target) ..() - var/obj/effect/proc_holder/our_proc_holder = target + var/obj/effect/proc_holder/our_proc_holder = Target our_proc_holder.action = src name = our_proc_holder.name desc = our_proc_holder.desc icon_icon = our_proc_holder.action_icon button_icon_state = our_proc_holder.action_icon_state background_icon_state = our_proc_holder.action_background_icon_state - button.name = name /datum/action/cooldown/spell_like/Activate(atom/activate_target) if(!target) diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index a5c7710b067..7b5d6760ec8 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -275,7 +275,7 @@ name = "Hide" desc = "Hide yourself from your owner's sight." button_icon_state = "hide" - UpdateButtonIcon() + UpdateButtons() /datum/action/innate/imaginary_hide/Activate() var/mob/camera/imaginary_friend/I = owner diff --git a/code/datums/components/admin_popup.dm b/code/datums/components/admin_popup.dm index 0fff57863e3..c552c596c80 100644 --- a/code/datums/components/admin_popup.dm +++ b/code/datums/components/admin_popup.dm @@ -49,7 +49,7 @@ admin_popup = new var/client/parent_client = parent - admin_popup.maptext_width = getviewsize(parent_client.view_size.getView())[1] * world.icon_size + admin_popup.maptext_width = view_to_pixels(parent_client.view_size.getView())[1] parent_client.screen += admin_popup /datum/component/admin_popup/proc/delete_self() diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index 9de207a6423..85d144ea857 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -141,7 +141,7 @@ var/obj/effect/proc_holder/proc_holder = ability if(!proc_holder.action) return - proc_holder.action.Share(rider) + proc_holder.action.GiveAction(rider) /// Takes away the riding parent's abilities from the rider /datum/component/riding/creature/proc/remove_abilities(mob/living/rider) @@ -156,7 +156,7 @@ return if(rider == proc_holder.ranged_ability_user) proc_holder.remove_ranged_ability() - proc_holder.action.Unshare(rider) + proc_holder.action.HideFrom(rider) /datum/component/riding/creature/riding_can_z_move(atom/movable/movable_parent, direction, turf/start, turf/destination, z_move_flags, mob/living/rider) if(!(z_move_flags & ZMOVE_CAN_FLY_CHECKS)) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 7f7467f0e0c..e75cfb5d479 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -841,7 +841,7 @@ if(istype(S, type)) continue S.charge_counter = delay - S.updateButtonIcon() + S.updateButtons() INVOKE_ASYNC(S, /obj/effect/proc_holder/spell.proc/start_recharge) /datum/mind/proc/get_ghost(even_if_they_cant_reenter, ghosts_with_clients) diff --git a/code/datums/view.dm b/code/datums/view.dm index dffbc90a4f2..e8b6c1cfe82 100644 --- a/code/datums/view.dm +++ b/code/datums/view.dm @@ -33,11 +33,13 @@ default = string apply() -/datum/view_data/proc/safeApplyFormat() +/datum/view_data/proc/afterViewChange() if(isZooming()) assertFormat() - return - resetFormat() + else + resetFormat() + var/datum/hud/our_hud = chief?.mob?.hud_used + our_hud.view_audit_buttons() // Make sure our hud's buttons are in our new size /datum/view_data/proc/assertFormat()//T-Pose winset(chief, "mapwindow.map", "zoom=0") @@ -99,7 +101,7 @@ /datum/view_data/proc/apply() chief?.change_view(getView()) - safeApplyFormat() + afterViewChange() /datum/view_data/proc/supress() is_suppressed = TRUE diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 2131fb4f671..b4aea6d7c81 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1285,7 +1285,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e */ /obj/item/proc/update_action_buttons(status_only = FALSE, force = FALSE) for(var/datum/action/current_action as anything in actions) - current_action.UpdateButtonIcon(status_only, force) + current_action.UpdateButtons(status_only, force) // Update icons if this is being carried by a mob /obj/item/wash(clean_types) diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm index a9b9b78015d..e6d4293a25d 100644 --- a/code/game/objects/items/granters.dm +++ b/code/game/objects/items/granters.dm @@ -105,13 +105,13 @@ to_chat(owner, span_notice("You will now fold origami planes.")) button_icon_state = "origami_on" active = TRUE - UpdateButtonIcon() + UpdateButtons() /datum/action/innate/origami/Deactivate() to_chat(owner, span_notice("You will no longer fold origami planes.")) button_icon_state = "origami_off" active = FALSE - UpdateButtonIcon() + UpdateButtons() ///SPELLS/// diff --git a/code/game/objects/structures/deployable_turret.dm b/code/game/objects/structures/deployable_turret.dm index 92fdc82f23d..4a265d882be 100644 --- a/code/game/objects/structures/deployable_turret.dm +++ b/code/game/objects/structures/deployable_turret.dm @@ -114,7 +114,7 @@ var/client/controlling_client = controller.client if(controlling_client) var/modifiers = params2list(controlling_client.mouseParams) - var/atom/target_atom = controlling_client.mouseObject + var/atom/target_atom = controlling_client.mouse_object_ref?.resolve() var/turf/target_turf = get_turf(target_atom) if(istype(target_turf)) //They're hovering over something in the map. direction_track(controller, target_turf) diff --git a/code/modules/admin/verbs/SDQL2/SDQL_spells/spell_edit_menu.dm b/code/modules/admin/verbs/SDQL2/SDQL_spells/spell_edit_menu.dm index 3bffae75958..7c74c38ca70 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_spells/spell_edit_menu.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_spells/spell_edit_menu.dm @@ -404,7 +404,7 @@ GLOBAL_LIST_INIT_TYPED(sdql_spells, /obj/effect/proc_holder/spell, list()) if("confirm") if(target_spell) reassign_vars(target_spell) - target_spell.action.UpdateButtonIcon() + target_spell.action.UpdateButtons() log_admin("[key_name(user)] edited the SDQL spell \"[target_spell]\" owned by [key_name(target_mob)].") else var/new_spell = give_spell() @@ -895,7 +895,7 @@ GLOBAL_LIST_INIT_TYPED(sdql_spells, /obj/effect/proc_holder/spell, list()) var/obj/effect/proc_holder/spell/new_spell = new path(null, target_mob, user.ckey) GLOB.sdql_spells += new_spell reassign_vars(new_spell) - new_spell.action.UpdateButtonIcon() + new_spell.action.UpdateButtons() if(target_mob.mind) target_mob.mind.AddSpell(new_spell) else diff --git a/code/modules/antagonists/changeling/cellular_emporium.dm b/code/modules/antagonists/changeling/cellular_emporium.dm index 0e1e86baa8f..84aae218a10 100644 --- a/code/modules/antagonists/changeling/cellular_emporium.dm +++ b/code/modules/antagonists/changeling/cellular_emporium.dm @@ -95,7 +95,6 @@ /datum/action/innate/cellular_emporium/New(our_target) . = ..() - button.name = name if(istype(our_target, /datum/cellular_emporium)) cellular_emporium = our_target else diff --git a/code/modules/antagonists/changeling/powers/fakedeath.dm b/code/modules/antagonists/changeling/powers/fakedeath.dm index 32c29c05105..835e13cfb36 100644 --- a/code/modules/antagonists/changeling/powers/fakedeath.dm +++ b/code/modules/antagonists/changeling/powers/fakedeath.dm @@ -18,7 +18,7 @@ name = "Reviving Stasis" desc = "We fall into a stasis, allowing us to regenerate and trick our enemies." button_icon_state = "fake_death" - UpdateButtonIcon() + UpdateButtons() chemical_cost = 15 to_chat(user, span_notice("We have revived ourselves.")) else @@ -58,7 +58,7 @@ name = "Revive" desc = "We arise once more." button_icon_state = "revive" - UpdateButtonIcon() + UpdateButtons() chemical_cost = 0 revive_ready = TRUE diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 87546b499f3..fd334ab9d7b 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -2,15 +2,10 @@ name = "Prepare Blood Magic" button_icon_state = "carve" desc = "Prepare blood magic by carving runes into your flesh. This is easier with an empowering rune." + default_button_position = DEFAULT_BLOODSPELLS var/list/spells = list() var/channeling = FALSE -/datum/action/innate/cult/blood_magic/Grant() - ..() - button.screen_loc = DEFAULT_BLOODSPELLS - button.moved = DEFAULT_BLOODSPELLS - button.ordered = FALSE - /datum/action/innate/cult/blood_magic/Remove() for(var/X in spells) qdel(X) @@ -22,15 +17,21 @@ return ..() /datum/action/innate/cult/blood_magic/proc/Positioning() - var/list/screen_loc_split = splittext(button.screen_loc,",") - var/list/screen_loc_X = splittext(screen_loc_split[1],":") - var/list/screen_loc_Y = splittext(screen_loc_split[2],":") - var/pix_X = text2num(screen_loc_X[2]) - for(var/datum/action/innate/cult/blood_spell/B in spells) - if(B.button.locked) - var/order = pix_X+spells.Find(B)*31 - B.button.screen_loc = "[screen_loc_X[1]]:[order],[screen_loc_Y[1]]:[screen_loc_Y[2]]" - B.button.moved = B.button.screen_loc + for(var/datum/hud/hud as anything in viewers) + var/our_view = hud.mymob?.client?.view || "15x15" + var/atom/movable/screen/movable/action_button/button = viewers[hud] + var/position = screen_loc_to_offset(button.screen_loc) + var/spells_iterated = 0 + for(var/datum/action/innate/cult/blood_spell/blood_spell in spells) + spells_iterated += 1 + if(blood_spell.positioned) + continue + var/atom/movable/screen/movable/action_button/moving_button = blood_spell.viewers[hud] + if(!moving_button) + continue + var/our_x = position[1] + spells_iterated * world.icon_size // Offset any new buttons into our list + hud.position_action(moving_button, offset_to_screen_loc(our_x, position[2], our_view)) + blood_spell.positioned = TRUE /datum/action/innate/cult/blood_magic/Activate() var/rune = FALSE @@ -97,6 +98,8 @@ var/base_desc //To allow for updating tooltips var/invocation var/health_cost = 0 + /// Have we already been positioned into our starting location? + var/positioned = FALSE /datum/action/innate/cult/blood_spell/Grant(mob/living/owner, datum/action/innate/cult/blood_magic/BM) if(health_cost) @@ -104,9 +107,7 @@ base_desc = desc desc += "
Has [charges] use\s remaining." all_magic = BM - ..() - button.locked = TRUE - button.ordered = FALSE + return ..() /datum/action/innate/cult/blood_spell/Remove() if(all_magic) @@ -275,7 +276,7 @@ attached_action.charges-- attached_action.desc = attached_action.base_desc attached_action.desc += "
Has [attached_action.charges] use\s remaining." - attached_action.UpdateButtonIcon() + attached_action.UpdateButtons() if(attached_action.charges <= 0) remove_ranged_ability(span_cult("You have exhausted the spell's power!")) qdel(src) @@ -331,7 +332,7 @@ qdel(src) desc = base_desc desc += "
Has [charges] use\s remaining." - UpdateButtonIcon() + UpdateButtons() /datum/action/innate/cult/blood_spell/manipulation name = "Blood Rites" @@ -380,7 +381,7 @@ source.charges = uses source.desc = source.base_desc source.desc += "
Has [uses] use\s remaining." - source.UpdateButtonIcon() + source.UpdateButtons() return ..() /obj/item/melee/blood_magic/attack_self(mob/living/user) @@ -409,7 +410,7 @@ else if(source) source.desc = source.base_desc source.desc += "
Has [uses] use\s remaining." - source.UpdateButtonIcon() + source.UpdateButtons() //Stun /obj/item/melee/blood_magic/stun diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 3d54936f0fd..c4f7758c0c6 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -805,14 +805,13 @@ Striking a noncultist, however, will tear their flesh."} desc = "Call the bloody halberd back to your hand!" background_icon_state = "bg_demon" button_icon_state = "bloodspear" + default_button_position = "6:157,4:-2" var/obj/item/melee/cultblade/halberd/halberd var/cooldown = 0 /datum/action/innate/cult/halberd/Grant(mob/user, obj/blood_halberd) . = ..() halberd = blood_halberd - button.screen_loc = "6:157,4:-2" - button.moved = "6:157,4:-2" /datum/action/innate/cult/halberd/Activate() if(owner == halberd.loc || cooldown > world.time) diff --git a/code/modules/antagonists/heretic/heretic_living_heart.dm b/code/modules/antagonists/heretic/heretic_living_heart.dm index a619e242376..8609a0d96de 100644 --- a/code/modules/antagonists/heretic/heretic_living_heart.dm +++ b/code/modules/antagonists/heretic/heretic_living_heart.dm @@ -43,7 +43,7 @@ organ_parent.icon = 'icons/obj/eldritch.dmi' organ_parent.icon_state = "living_heart" - action.UpdateButtonIcon() + action.UpdateButtons() /datum/component/living_heart/Destroy(force, silent) QDEL_NULL(action) diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm index 24bc2fcfa56..36dd5c7c52e 100644 --- a/code/modules/antagonists/revenant/revenant_abilities.dm +++ b/code/modules/antagonists/revenant/revenant_abilities.dm @@ -189,7 +189,7 @@ user.reveal(reveal) user.stun(stun) if(action) - action.UpdateButtonIcon() + action.UpdateButtons() return TRUE //Overload Light: Breaks a light that's online and sends out lightning bolts to all nearby people. diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm index c17da72e1d3..2acb79cb7d2 100644 --- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm +++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm @@ -430,7 +430,6 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) /datum/action/innate/ai/ranged/override_machine/New() ..() desc = "[desc] It has [uses] use\s remaining." - button.desc = desc /datum/action/innate/ai/ranged/override_machine/proc/animate_machine(obj/machinery/M) if(M && !QDELETED(M)) @@ -458,7 +457,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) attached_action.adjust_uses(-1) if(attached_action?.uses) attached_action.desc = "[initial(attached_action.desc)] It has [attached_action.uses] use\s remaining." - attached_action.UpdateButtonIcon() + attached_action.UpdateButtons() target.audible_message(span_userdanger("You hear a loud electrical buzzing sound coming from [target]!")) addtimer(CALLBACK(attached_action, /datum/action/innate/ai/ranged/override_machine.proc/animate_machine, target), 50) //kabeep! remove_ranged_ability(span_danger("Sending override signal...")) @@ -508,7 +507,6 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) /datum/action/innate/ai/ranged/overload_machine/New() ..() desc = "[desc] It has [uses] use\s remaining." - button.desc = desc /datum/action/innate/ai/ranged/overload_machine/proc/detonate_machine(obj/machinery/M) if(M && !QDELETED(M)) @@ -541,7 +539,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) attached_action.adjust_uses(-1) if(attached_action?.uses) attached_action.desc = "[initial(attached_action.desc)] It has [attached_action.uses] use\s remaining." - attached_action.UpdateButtonIcon() + attached_action.UpdateButtons() target.audible_message(span_userdanger("You hear a loud electrical buzzing sound coming from [target]!")) addtimer(CALLBACK(attached_action, /datum/action/innate/ai/ranged/overload_machine.proc/detonate_machine, target), 50) //kaboom! remove_ranged_ability(span_danger("Overcharging machine...")) @@ -566,7 +564,6 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) /datum/action/innate/ai/blackout/New() ..() desc = "[desc] It has [uses] use\s remaining." - button.desc = desc /datum/action/innate/ai/blackout/Activate() for(var/obj/machinery/power/apc/apc in GLOB.apcs_list) @@ -577,9 +574,10 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) to_chat(owner, span_notice("Overcurrent applied to the powernet.")) owner.playsound_local(owner, SFX_SPARKS, 50, 0) adjust_uses(-1) - if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe - desc = "[initial(desc)] It has [uses] use\s remaining." - UpdateButtonIcon() + if(QDELETED(src) || uses) //Not sure if not having src here would cause a runtime, so it's here to be safe + return + desc = "[initial(desc)] It has [uses] use\s remaining." + UpdateButtons() /// HIGH IMPACT HONKING /datum/ai_module/destructive/megahonk @@ -785,7 +783,6 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) /datum/action/innate/ai/reactivate_cameras/New() ..() desc = "[desc] It has [uses] use\s remaining." - button.desc = desc /datum/action/innate/ai/reactivate_cameras/Activate() var/fixed_cameras = 0 @@ -801,9 +798,10 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) to_chat(owner, span_notice("Diagnostic complete! Cameras reactivated: [fixed_cameras]. Reactivations remaining: [uses].")) owner.playsound_local(owner, 'sound/items/wirecutter.ogg', 50, 0) adjust_uses(0, TRUE) //Checks the uses remaining - if(src && uses) //Not sure if not having src here would cause a runtime, so it's here to be safe - desc = "[initial(desc)] It has [uses] use\s remaining." - UpdateButtonIcon() + if(QDELETED(src) || !uses) //Not sure if not having src here would cause a runtime, so it's here to be safe + return + desc = "[initial(desc)] It has [uses] use\s remaining." + UpdateButtons() /// Upgrade Camera Network: EMP-proofs all cameras, in addition to giving them X-ray vision. /datum/ai_module/upgrade/upgrade_cameras diff --git a/code/modules/antagonists/traitor/equipment/module_picker.dm b/code/modules/antagonists/traitor/equipment/module_picker.dm index c11ace042d3..001f4434652 100644 --- a/code/modules/antagonists/traitor/equipment/module_picker.dm +++ b/code/modules/antagonists/traitor/equipment/module_picker.dm @@ -120,6 +120,6 @@ else //Adding uses to an existing module action.uses += initial(action.uses) action.desc = "[initial(action.desc)] It has [action.uses] use\s remaining." - action.UpdateButtonIcon() + action.UpdateButtons() processing_time -= AM.cost SSblackbox.record_feedback("nested tally", "malfunction_modules_bought", 1, list("[initial(AM.name)]", "[AM.cost]")) diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index fe324b6d665..2d32aa99586 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -166,14 +166,15 @@ var/obj/item/active_mousedown_item = null ///Used in MouseDrag to preserve the original mouse click parameters var/mouseParams = "" - ///Used in MouseDrag to preserve the last mouse-entered location. - var/mouseLocation = null - ///Used in MouseDrag to preserve the last mouse-entered object. - var/mouseObject = null + ///Used in MouseDrag to preserve the last mouse-entered location. Weakref + var/datum/weakref/mouse_location_ref = null + ///Used in MouseDrag to preserve the last mouse-entered object. Weakref + var/datum/weakref/mouse_object_ref //Middle-mouse-button click dragtime control for aimbot exploit detection. var/middragtime = 0 - //Middle-mouse-button clicked object control for aimbot exploit detection. - var/atom/middragatom + //Middle-mouse-button clicked object control for aimbot exploit detection. Weakref + var/datum/weakref/middle_drag_atom_ref + /// Messages currently seen by this client var/list/seen_messages diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index b3af514063d..161e8420b0d 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -911,7 +911,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if(dragged && !LAZYACCESS(modifiers, dragged)) //I don't know what's going on here, but I don't trust it return - if (object && object == middragatom && LAZYACCESS(modifiers, LEFT_CLICK)) + if (object && IS_WEAKREF_OF(object, middle_drag_atom_ref) && LAZYACCESS(modifiers, LEFT_CLICK)) ab = max(0, 5 SECONDS-(world.time-middragtime)*0.1) var/mcl = CONFIG_GET(number/minute_click_limit) @@ -960,6 +960,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( else winset(src, null, "input.focus=true input.background-color=[COLOR_INPUT_ENABLED]") + SEND_SIGNAL(src, COMSIG_CLIENT_CLICK, object, location, control, params, usr) + ..() /client/proc/add_verbs_from_config() diff --git a/code/modules/client/preferences/buttons_locked.dm b/code/modules/client/preferences/buttons_locked.dm deleted file mode 100644 index b4f54ff10f8..00000000000 --- a/code/modules/client/preferences/buttons_locked.dm +++ /dev/null @@ -1,5 +0,0 @@ -/datum/preference/toggle/buttons_locked - category = PREFERENCE_CATEGORY_GAME_PREFERENCES - savefile_key = "buttons_locked" - savefile_identifier = PREFERENCE_PLAYER - default_value = FALSE diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index 316d01015fc..54131e3928b 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -164,8 +164,8 @@ ..() /datum/action/item_action/chameleon/change/proc/initialize_disguises() - if(button) - button.name = "Change [chameleon_name] Appearance" + name = "Change [chameleon_name] Appearance" + UpdateButtons() chameleon_blacklist |= typecacheof(target.type) for(var/V in typesof(chameleon_type)) @@ -210,7 +210,7 @@ update_item(picked_item) var/obj/item/thing = target thing.update_slot_icon() - UpdateButtonIcon() + UpdateButtons() /datum/action/item_action/chameleon/change/proc/update_item(obj/item/picked_item) var/atom/atom_target = target @@ -326,8 +326,8 @@ agent_card.update_icon() /datum/action/item_action/chameleon/change/id_trim/initialize_disguises() - if(button) - button.name = "Change [chameleon_name] Appearance" + name = "Change [chameleon_name] Appearance" + UpdateButtons() chameleon_blacklist |= typecacheof(target.type) for(var/trim_path in typesof(chameleon_type)) @@ -535,9 +535,9 @@ ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) chameleon_action.random_look() var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = new(src) - togglehatmask_action.UpdateButtonIcon() + togglehatmask_action.UpdateButtons() var/datum/action/item_action/chameleon/drone/randomise/randomise_action = new(src) - randomise_action.UpdateButtonIcon() + randomise_action.UpdateButtons() /obj/item/clothing/mask/chameleon name = "gas mask" @@ -592,9 +592,9 @@ ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) chameleon_action.random_look() var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = new(src) - togglehatmask_action.UpdateButtonIcon() + togglehatmask_action.UpdateButtons() var/datum/action/item_action/chameleon/drone/randomise/randomise_action = new(src) - randomise_action.UpdateButtonIcon() + randomise_action.UpdateButtons() /obj/item/clothing/mask/chameleon/drone/attack_self(mob/user) to_chat(user, span_notice("[src] does not have a voice changer.")) diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index 5b484f3522a..4592dec8e1f 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -210,7 +210,7 @@ Doesn't work on other aliens/AI.*/ /obj/effect/proc_holder/alien/neurotoxin/update_icon() action.button_icon_state = "alien_neurotoxin_[active]" - action.UpdateButtonIcon() + action.UpdateButtons() return ..() /obj/effect/proc_holder/alien/neurotoxin/InterceptClickOn(mob/living/caller, params, atom/target) @@ -332,7 +332,7 @@ Doesn't work on other aliens/AI.*/ for(var/X in abilities) var/obj/effect/proc_holder/alien/APH = X if(APH.has_action) - APH.action.UpdateButtonIcon() + APH.action.UpdateButtons() return TRUE /mob/living/carbon/alien/adjustPlasma(amount) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 0716b39bcb2..0f4d4629cb5 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -569,9 +569,9 @@ spark_system.start() do_teleport(H, get_turf(H), 12, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) last_teleport = world.time - UpdateButtonIcon() //action icon looks unavailable + UpdateButtons() //action icon looks unavailable //action icon looks available again - addtimer(CALLBACK(src, .proc/UpdateButtonIcon), cooldown + 5) + addtimer(CALLBACK(src, .proc/UpdateButtons), cooldown + 5) //honk diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 9dc4dbecea4..c178c10e849 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -69,7 +69,7 @@ Cannibalize_Body(H) if(regenerate_limbs) - regenerate_limbs.UpdateButtonIcon() + regenerate_limbs.UpdateButtons() /datum/species/jelly/proc/Cannibalize_Body(mob/living/carbon/human/H) var/list/limbs_to_consume = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - H.get_missing_limbs() @@ -475,9 +475,9 @@ /datum/species/jelly/luminescent/proc/update_slime_actions() integrate_extract.update_name() - integrate_extract.UpdateButtonIcon() - extract_minor.UpdateButtonIcon() - extract_major.UpdateButtonIcon() + integrate_extract.UpdateButtons() + extract_minor.UpdateButtons() + extract_major.UpdateButtons() /datum/species/jelly/luminescent/proc/update_glow(mob/living/carbon/C, intensity) if(intensity) @@ -516,7 +516,7 @@ name = "Eject Extract" desc = "Eject your current slime extract." -/datum/action/innate/integrate_extract/UpdateButtonIcon(status_only, force) +/datum/action/innate/integrate_extract/UpdateButtons(status_only, force) var/datum/species/jelly/luminescent/species = target if(!species || !species.current_extract) button_icon_state = "slimeconsume" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 594297d7dc0..3edba64ba94 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -797,7 +797,7 @@ if(mind) for(var/S in mind.spell_list) var/obj/effect/proc_holder/spell/spell = S - spell.updateButtonIcon() + spell.updateButtons() if(excess_healing) INVOKE_ASYNC(src, .proc/emote, "gasp") log_combat(src, src, "revived") diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm index 3a80ecdf5c6..d77dffa053f 100644 --- a/code/modules/mob/living/silicon/robot/robot_model.dm +++ b/code/modules/mob/living/silicon/robot/robot_model.dm @@ -500,7 +500,7 @@ if(!wash_audio.is_active()) wash_audio.start() clean() - UpdateButtonIcon() + UpdateButtons() /// Start the process of disabling the buffer. Plays some effects, waits a bit, then finishes /datum/action/toggle_buffer/proc/deactivate_wash() @@ -530,7 +530,7 @@ var/mob/living/silicon/robot/robot_owner = owner buffer_on = FALSE robot_owner.remove_movespeed_modifier(/datum/movespeed_modifier/auto_wash) - UpdateButtonIcon() + UpdateButtons() /// Should we keep trying to activate our buffer, or did you fuck it up somehow /datum/action/toggle_buffer/proc/allow_buffer_activate() @@ -567,7 +567,7 @@ // We use more water doing this then mopping reagents.remove_any(2) //reaction() doesn't use up the reagents -/datum/action/toggle_buffer/UpdateButtonIcon(status_only = FALSE, force = FALSE) +/datum/action/toggle_buffer/UpdateButtons(status_only = FALSE, force = FALSE) if(buffer_on) name = "De-Activate Auto-Wash" button_icon_state = "deactivate_wash" diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 851cbffc910..fbe6f871d12 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -54,21 +54,18 @@ ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) var/spellnum = 1 for(var/spell in construct_spells) - var/the_spell = new spell(null) - AddSpell(the_spell) - var/obj/effect/proc_holder/spell/S = mob_spell_list[spellnum] var/pos = 2+spellnum*31 if(construct_spells.len >= 4) pos -= 31*(construct_spells.len - 4) - S.action.button.screen_loc = "6:[pos],4:-2" - S.action.button.moved = "6:[pos],4:-2" + var/obj/effect/proc_holder/spell/the_spell = new spell(null) + the_spell?.action.default_button_position ="6:[pos],4:-2" + AddSpell(the_spell) spellnum++ if(runetype) - our_rune = new runetype(src) - our_rune.Grant(src) var/pos = 2+spellnum*31 - our_rune.button.screen_loc = "6:[pos],4:-2" - our_rune.button.moved = "6:[pos],4:-2" + our_rune = new runetype(src) + our_rune.default_button_position = "6:[pos],4:-2" // Set the default position to this random position + our_rune.Grant(src) if(icon_state) add_overlay("glow_[icon_state]_[theme]") diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 883148c4b20..facffb201ce 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -337,7 +337,7 @@ if(ishuman(living_target) && (living_target.stat != DEAD || !consumed_mobs[living_target.tag])) //if they're not dead, you can consume them anyway consumed_mobs[living_target.tag] = TRUE fed++ - lay_eggs_enriched.UpdateButtonIcon(TRUE) + lay_eggs_enriched.UpdateButtons(TRUE) visible_message(span_danger("[src] sticks a proboscis into [living_target] and sucks a viscous substance out."),span_notice("You suck the nutriment out of [living_target], feeding you enough to lay a cluster of eggs.")) living_target.death() //you just ate them, they're dead. else @@ -403,7 +403,7 @@ /obj/effect/proc_holder/wrap/update_icon() action.button_icon_state = "wrap_[active]" - action.UpdateButtonIcon() + action.UpdateButtons() return ..() /obj/effect/proc_holder/wrap/Click() @@ -486,7 +486,7 @@ new_eggs.faction = spider.faction if(enriched) spider.fed-- - UpdateButtonIcon(TRUE) + UpdateButtons(TRUE) spider.is_busy = FALSE spider.stop_automated_movement = FALSE diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index c8f26feeb26..b29de2f72bc 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -77,24 +77,32 @@ While using this makes the system rely on OnFire, it still gives options for tim ///The internal attack ID for the elite's OpenFire() proc to use var/chosen_attack_num = 0 -/datum/action/innate/elite_attack/New() - ..() +/datum/action/innate/elite_attack/CreateButton() + var/atom/movable/screen/movable/action_button/button = ..() button.maptext = "" button.maptext_x = 8 button.maptext_y = 0 button.maptext_width = 24 button.maptext_height = 12 + return button /datum/action/innate/elite_attack/process() if(owner == null) STOP_PROCESSING(SSfastprocess, src) qdel(src) return + UpdateButtons() + +/datum/action/innate/elite_attack/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE) + . = ..() + if(!.) + return + if(status_only) + return var/mob/living/simple_animal/hostile/asteroid/elite/elite_owner = owner var/timeleft = max(elite_owner.ranged_cooldown - world.time, 0) if(timeleft == 0) button.maptext = "" - UpdateButtonIcon() else button.maptext = "[round(timeleft/10, 0.1)]" diff --git a/code/modules/mod/mod_actions.dm b/code/modules/mod/mod_actions.dm index c49f43d85d7..b8634f35640 100644 --- a/code/modules/mod/mod_actions.dm +++ b/code/modules/mod/mod_actions.dm @@ -72,7 +72,7 @@ button_icon_state = "activate-ready" if(!ai_action) background_icon_state = "bg_tech" - UpdateButtonIcon() + UpdateButtons() addtimer(CALLBACK(src, .proc/reset_ready), 3 SECONDS) return var/obj/item/mod/control/mod = target @@ -85,7 +85,7 @@ button_icon_state = initial(button_icon_state) if(!ai_action) background_icon_state = initial(background_icon_state) - UpdateButtonIcon() + UpdateButtons() /datum/action/item_action/mod/activate/ai ai_action = TRUE @@ -180,14 +180,14 @@ /datum/action/item_action/mod/pinned_module/proc/on_module_activate(datum/source) SIGNAL_HANDLER - UpdateButtonIcon() + UpdateButtons() /datum/action/item_action/mod/pinned_module/proc/on_module_deactivate(datum/source) SIGNAL_HANDLER - UpdateButtonIcon() + UpdateButtons() /datum/action/item_action/mod/pinned_module/proc/on_module_use(datum/source) SIGNAL_HANDLER - UpdateButtonIcon() + UpdateButtons() diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index bb7d74b8f54..2b405ec95f7 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -460,7 +460,7 @@ for(var/obj/item/item in buckled_mob.held_items) if(istype(item, /obj/item/turret_control)) qdel(item) - UpdateButtonIcon() + UpdateButtons() return playsound(proto_emitter,'sound/mecha/mechmove01.ogg', 50, TRUE) name = "Switch to Automatic Firing" @@ -477,7 +477,7 @@ else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand var/obj/item/turret_control/turret_control = new /obj/item/turret_control() buckled_mob.put_in_hands(turret_control) - UpdateButtonIcon() + UpdateButtons() /obj/item/turret_control diff --git a/code/modules/projectiles/guns/energy/beam_rifle.dm b/code/modules/projectiles/guns/energy/beam_rifle.dm index 1942417a1f2..01a2e87700d 100644 --- a/code/modules/projectiles/guns/energy/beam_rifle.dm +++ b/code/modules/projectiles/guns/energy/beam_rifle.dm @@ -196,7 +196,9 @@ else P.color = rgb(0, 255, 0) var/turf/curloc = get_turf(src) - var/turf/targloc = get_turf(current_user.client.mouseObject) + + var/atom/target_atom = current_user.client.mouse_object_ref?.resolve() + var/turf/targloc = get_turf(target_atom) if(!istype(targloc)) if(!istype(curloc)) return @@ -293,7 +295,9 @@ process_aim() if(aiming_time_left <= aiming_time_fire_threshold && check_user()) sync_ammo() - afterattack(M.client.mouseObject, M, FALSE, M.client.mouseParams, passthrough = TRUE) + var/atom/target = M.client.mouse_object_ref?.resolve() + if(target) + afterattack(target, M, FALSE, M.client.mouseParams, passthrough = TRUE) stop_aiming() QDEL_LIST(current_tracers) return ..() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index c2a5f2c13e9..af587e41b02 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -949,12 +949,10 @@ var/ty = (text2num(screen_loc_Y[1]) - 1) * world.icon_size + text2num(screen_loc_Y[2]) //Calculate the "resolution" of screen based on client's view and world's icon size. This will work if the user can view more tiles than average. - var/list/screenview = getviewsize(user.client.view) - var/screenviewX = screenview[1] * world.icon_size - var/screenviewY = screenview[2] * world.icon_size + var/list/screenview = view_to_pixels(user.client.view) - var/ox = round(screenviewX/2) - user.client.pixel_x //"origin" x - var/oy = round(screenviewY/2) - user.client.pixel_y //"origin" y + var/ox = round(screenview[1] / 2) - user.client.pixel_x //"origin" x + var/oy = round(screenview[2] / 2) - user.client.pixel_y //"origin" y angle = ATAN2(tx - oy, ty - ox) return list(angle, p_x, p_y) diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index de944eb4ca6..5501eb73d2c 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -231,7 +231,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th if("holdervar") adjust_var(user, holder_var_type, holder_var_amount) if(action) - action.UpdateButtonIcon() + action.UpdateButtons() return TRUE /obj/effect/proc_holder/spell/proc/charge_check(mob/user, silent = FALSE) @@ -304,7 +304,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th if(recharging && charge_type == "recharge" && (charge_counter < charge_max)) charge_counter += delta_time * 10 if(charge_counter >= charge_max) - action.UpdateButtonIcon() + action.UpdateButtons() charge_counter = charge_max recharging = FALSE @@ -321,7 +321,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th cast(targets,user=user) after_cast(targets) if(action) - action.UpdateButtonIcon() + action.UpdateButtons() /obj/effect/proc_holder/spell/proc/before_cast(list/targets) if(overlay) @@ -382,7 +382,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th if("holdervar") adjust_var(user, holder_var_type, -holder_var_amount) if(action) - action.UpdateButtonIcon() + action.UpdateButtons() /obj/effect/proc_holder/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types if (!istype(target)) @@ -507,8 +507,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th perform(targets,user=user) -/obj/effect/proc_holder/spell/proc/updateButtonIcon(status_only, force) - action.UpdateButtonIcon(status_only, force) +/obj/effect/proc_holder/spell/proc/updateButtons(status_only, force) + action.UpdateButtons(status_only, force) /obj/effect/proc_holder/spell/proc/can_be_cast_by(mob/caster) if((human_req || clothes_req) && !ishuman(caster)) diff --git a/code/modules/spells/spell_types/aimed.dm b/code/modules/spells/spell_types/aimed.dm index 8e35be95735..c8432f4bb1d 100644 --- a/code/modules/spells/spell_types/aimed.dm +++ b/code/modules/spells/spell_types/aimed.dm @@ -46,7 +46,7 @@ . = ..() action.button_icon_state = "[base_icon_state][active]" - action.UpdateButtonIcon() + action.UpdateButtons() /obj/effect/proc_holder/spell/aimed/InterceptClickOn(mob/living/caller, params, atom/target) if(..()) diff --git a/code/modules/spells/spell_types/pointed/pointed.dm b/code/modules/spells/spell_types/pointed/pointed.dm index bf5d818f2ce..94676ba64ac 100644 --- a/code/modules/spells/spell_types/pointed/pointed.dm +++ b/code/modules/spells/spell_types/pointed/pointed.dm @@ -62,7 +62,7 @@ . = ..() action.button_icon_state = "[action_icon_state][active ? 1 : null]" - action.UpdateButtonIcon() + action.UpdateButtons() /obj/effect/proc_holder/spell/pointed/InterceptClickOn(mob/living/caller, params, atom/target) if(..()) diff --git a/code/modules/spells/spell_types/touch_attacks.dm b/code/modules/spells/spell_types/touch_attacks.dm index d492d0d792b..6267706074f 100644 --- a/code/modules/spells/spell_types/touch_attacks.dm +++ b/code/modules/spells/spell_types/touch_attacks.dm @@ -25,7 +25,7 @@ //Start recharging. attached_hand = null recharging = TRUE - action.UpdateButtonIcon() + action.UpdateButtons() /obj/effect/proc_holder/spell/targeted/touch/cast(list/targets,mob/user = usr) if(!QDELETED(attached_hand)) diff --git a/code/modules/surgery/dental_implant.dm b/code/modules/surgery/dental_implant.dm index 1fef114b341..ece7c70b8ed 100644 --- a/code/modules/surgery/dental_implant.dm +++ b/code/modules/surgery/dental_implant.dm @@ -23,7 +23,8 @@ user.transferItemToLoc(tool, target, TRUE) var/datum/action/item_action/hands_free/activate_pill/pill_action = new(tool) - pill_action.button.name = "Activate [tool.name]" + pill_action.name = "Activate [tool.name]" + pill_action.UpdateButtons() pill_action.target = tool pill_action.Grant(target) //The pill never actually goes in an inventory slot, so the owner doesn't inherit actions from it diff --git a/code/modules/tooltip/tooltip.dm b/code/modules/tooltip/tooltip.dm index 11ab9bb803b..83bbe5f2995 100644 --- a/code/modules/tooltip/tooltip.dm +++ b/code/modules/tooltip/tooltip.dm @@ -87,13 +87,13 @@ Notes: /datum/tooltip/proc/hide() + queueHide = showing ? TRUE : FALSE + if (queueHide) addtimer(CALLBACK(src, .proc/do_hide), 1) else do_hide() - queueHide = showing ? TRUE : FALSE - return TRUE /datum/tooltip/proc/do_hide() diff --git a/code/modules/tooltip/tooltip.html b/code/modules/tooltip/tooltip.html index b4d858da51b..5be29994cf1 100644 --- a/code/modules/tooltip/tooltip.html +++ b/code/modules/tooltip/tooltip.html @@ -130,21 +130,29 @@ //alert(realIconSize + ' | ' +tooltip.tileSize + ' | ' + resizeRatio); //DEBUG - //Parse out the tile and cursor locations from params (e.g. "icon-x=32;icon-y=29;screen-loc=3:10,15:29") + const parameters = new Object(); + + //Parse out the contents of params (e.g. "icon-x=32;icon-y=29;screen-loc=3:10,15:29") + //It is worth noting that params is not always ordered in the same way. We therefore need to write the code + //To load their values in independantly of their order var paramsA = tooltip.params.cursor.split(';'); - if (paramsA.length < 3) {return false;} //Sometimes screen-loc is never sent ahaha fuck you byond + for (var i = 0; i < paramsA.length; i++) { + var entry = paramsA[i]; + var nameAndValue = entry.split("="); + parameters[nameAndValue[0]] = nameAndValue[1]; + } + + //Sometimes screen-loc is never sent ahaha fuck you byond + if (!parameters["icon-x"] || !parameters["icon-y"] || !parameters["screen-loc"]) { + return false; + } //icon-x - var iconX = paramsA[0]; - iconX = iconX.split('='); - iconX = parseInt(iconX[1]); + var iconX = parseInt(parameters["icon-x"]); //icon-y - var iconY = paramsA[1]; - iconY = iconY.split('='); - iconY = parseInt(iconY[1]); + var iconY = parseInt(parameters["icon-y"]); //screen-loc - var screenLoc = paramsA[2]; - screenLoc = screenLoc.split('='); - screenLoc = screenLoc[1].split(','); + var screenLoc = parameters["screen-loc"]; + screenLoc = screenLoc.split(','); if (screenLoc.length < 2) {return false;} var left = screenLoc[0]; var top = screenLoc[1]; diff --git a/code/modules/vehicles/mecha/combat/durand.dm b/code/modules/vehicles/mecha/combat/durand.dm index 862f4fcdb8c..fc8f624e320 100644 --- a/code/modules/vehicles/mecha/combat/durand.dm +++ b/code/modules/vehicles/mecha/combat/durand.dm @@ -212,7 +212,7 @@ own integrity back to max. Shield is automatically dropped if we run out of powe for(var/occupant in chassis.occupants) var/datum/action/button = chassis.occupant_actions[occupant][/datum/action/vehicle/sealed/mecha/mech_defense_mode] button.button_icon_state = "mech_defense_mode_[chassis.defense_mode ? "on" : "off"]" - button.UpdateButtonIcon() + button.UpdateButtons() set_light_on(chassis.defense_mode) diff --git a/code/modules/vehicles/mecha/combat/gygax.dm b/code/modules/vehicles/mecha/combat/gygax.dm index 43824350ee0..5f23d21b82f 100644 --- a/code/modules/vehicles/mecha/combat/gygax.dm +++ b/code/modules/vehicles/mecha/combat/gygax.dm @@ -44,7 +44,7 @@ chassis.movedelay = initial(chassis.movedelay) chassis.step_energy_drain = chassis.normal_step_energy_drain chassis.balloon_alert(owner, "you disable the overload") - UpdateButtonIcon() + UpdateButtons() /obj/vehicle/sealed/mecha/combat/gygax/dark desc = "A lightweight exosuit, painted in a dark scheme. This model appears to have some modifications." diff --git a/code/modules/vehicles/mecha/combat/marauder.dm b/code/modules/vehicles/mecha/combat/marauder.dm index b0cfd022e0c..9e67af31838 100644 --- a/code/modules/vehicles/mecha/combat/marauder.dm +++ b/code/modules/vehicles/mecha/combat/marauder.dm @@ -69,7 +69,7 @@ SEND_SOUND(owner, sound('sound/mecha/imag_enh.ogg', volume=50)) else owner.client.view_size.resetToDefault() - UpdateButtonIcon() + UpdateButtons() /obj/vehicle/sealed/mecha/combat/marauder/seraph desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel." diff --git a/code/modules/vehicles/mecha/combat/phazon.dm b/code/modules/vehicles/mecha/combat/phazon.dm index 16dc0ce3555..643caf402b0 100644 --- a/code/modules/vehicles/mecha/combat/phazon.dm +++ b/code/modules/vehicles/mecha/combat/phazon.dm @@ -44,7 +44,7 @@ chassis.damtype = new_damtype button_icon_state = "mech_damtype_[new_damtype]" playsound(chassis, 'sound/mecha/mechmove01.ogg', 50, TRUE) - UpdateButtonIcon() + UpdateButtons() /datum/action/vehicle/sealed/mecha/mech_toggle_phasing name = "Toggle Phasing" @@ -56,4 +56,4 @@ chassis.phasing = chassis.phasing ? "" : "phasing" button_icon_state = "mech_phasing_[chassis.phasing ? "on" : "off"]" chassis.balloon_alert(owner, "[chassis.phasing ? "enabled" : "disabled"] phasing") - UpdateButtonIcon() + UpdateButtons() diff --git a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm index c50314d7a60..3b28c661952 100644 --- a/code/modules/vehicles/mecha/combat/savannah_ivanov.dm +++ b/code/modules/vehicles/mecha/combat/savannah_ivanov.dm @@ -117,8 +117,8 @@ return S_TIMER_COOLDOWN_START(chassis, COOLDOWN_MECHA_SKYFALL, skyfall_cooldown_time) button_icon_state = "mech_savannah_cooldown" - UpdateButtonIcon() - addtimer(CALLBACK(src, /datum/action/vehicle/sealed/mecha/skyfall.proc/reset_button_icon), skyfall_cooldown_time) + UpdateButtons() + addtimer(CALLBACK(src, .proc/reset_button_icon), skyfall_cooldown_time) for(var/mob/living/shaken in range(7, chassis)) shake_camera(shaken, 3, 3) @@ -219,7 +219,7 @@ */ /datum/action/vehicle/sealed/mecha/skyfall/proc/reset_button_icon() button_icon_state = "mech_savannah" - UpdateButtonIcon() + UpdateButtons() /datum/action/vehicle/sealed/mecha/ivanov_strike name = "Ivanov Strike" @@ -254,7 +254,7 @@ */ /datum/action/vehicle/sealed/mecha/ivanov_strike/proc/reset_button_icon() button_icon_state = "mech_ivanov" - UpdateButtonIcon() + UpdateButtons() /** * ## start_missile_targeting @@ -322,7 +322,7 @@ "explosionSize" = list(0,0,1,2) )) button_icon_state = "mech_ivanov_cooldown" - UpdateButtonIcon() + UpdateButtons() addtimer(CALLBACK(src, /datum/action/vehicle/sealed/mecha/ivanov_strike.proc/reset_button_icon), strike_cooldown_time) //misc effects diff --git a/code/modules/vehicles/mecha/mecha_actions.dm b/code/modules/vehicles/mecha/mecha_actions.dm index 266a84a51f9..5cbd0c8c57a 100644 --- a/code/modules/vehicles/mecha/mecha_actions.dm +++ b/code/modules/vehicles/mecha/mecha_actions.dm @@ -38,7 +38,7 @@ button_icon_state = "mech_internals_[chassis.use_internal_tank ? "on" : "off"]" chassis.balloon_alert(owner, "taking air from [chassis.use_internal_tank ? "internal airtank" : "environment"]") chassis.log_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].", LOG_MECHA) - UpdateButtonIcon() + UpdateButtons() /datum/action/vehicle/sealed/mecha/mech_toggle_lights name = "Toggle Lights" @@ -60,7 +60,7 @@ chassis.balloon_alert(owner, "toggled lights [chassis.mecha_flags & LIGHTS_ON ? "on":"off"]") playsound(chassis,'sound/machines/clockcult/brass_skewer.ogg', 40, TRUE) chassis.log_message("Toggled lights [(chassis.mecha_flags & LIGHTS_ON)?"on":"off"].", LOG_MECHA) - UpdateButtonIcon() + UpdateButtons() /datum/action/vehicle/sealed/mecha/mech_view_stats name = "View Stats" @@ -104,7 +104,7 @@ for(var/occupant in occupants) var/datum/action/action = LAZYACCESSASSOC(occupant_actions, occupant, /datum/action/vehicle/sealed/mecha/strafe) - action?.UpdateButtonIcon() + action?.UpdateButtons() ///swap seats, for two person mecha /datum/action/vehicle/sealed/mecha/swap_seat diff --git a/code/modules/vehicles/mecha/working/clarke.dm b/code/modules/vehicles/mecha/working/clarke.dm index 49454ce7402..7f55038ab17 100644 --- a/code/modules/vehicles/mecha/working/clarke.dm +++ b/code/modules/vehicles/mecha/working/clarke.dm @@ -86,10 +86,10 @@ return var/mob/living/living_owner = owner button_icon_state = "mech_search_ruins_cooldown" - UpdateButtonIcon() + UpdateButtons() COOLDOWN_START(src, search_cooldown, SEARCH_COOLDOWN) addtimer(VARSET_CALLBACK(src, button_icon_state, "mech_search_ruins"), SEARCH_COOLDOWN) - addtimer(CALLBACK(src, .proc/UpdateButtonIcon), SEARCH_COOLDOWN) + addtimer(CALLBACK(src, .proc/UpdateButtons), SEARCH_COOLDOWN) var/obj/pinpointed_ruin for(var/obj/effect/landmark/ruin/ruin_landmark as anything in GLOB.ruin_landmarks) if(ruin_landmark.z != chassis.z) diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm index e0244f5b017..2990ebe568e 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -226,12 +226,16 @@ src.circuit_component = circuit_component - button.maptext_x = 2 - button.maptext_y = 0 - update_maptext() + UpdateButtons() START_PROCESSING(SSobj, src) +/datum/action/innate/bci_charge_action/CreateButton() + var/atom/movable/screen/movable/action_button/button = ..() + button.maptext_x = 2 + button.maptext_y = 0 + return button + /datum/action/innate/bci_charge_action/Destroy() circuit_component.charge_action = null circuit_component = null @@ -250,9 +254,14 @@ to_chat(owner, span_info("You can recharge it by using a cyborg recharging station.")) /datum/action/innate/bci_charge_action/process(delta_time) - update_maptext() + UpdateButtons() -/datum/action/innate/bci_charge_action/proc/update_maptext() +/datum/action/innate/bci_charge_action/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE) + . = ..() + if(!.) + return + if(status_only) + return var/obj/item/stock_parts/cell/cell = circuit_component.parent.cell button.maptext = cell ? MAPTEXT("[cell.percent()]%") : "" diff --git a/icons/effects/mouse_pointers/screen_drag.dmi b/icons/effects/mouse_pointers/screen_drag.dmi new file mode 100644 index 00000000000..48e4fce85f7 Binary files /dev/null and b/icons/effects/mouse_pointers/screen_drag.dmi differ diff --git a/icons/hud/64x16_actions.dmi b/icons/hud/64x16_actions.dmi new file mode 100644 index 00000000000..ae81ace4d55 Binary files /dev/null and b/icons/hud/64x16_actions.dmi differ diff --git a/icons/hud/actions.dmi b/icons/hud/actions.dmi index 6e242104110..f4026594247 100644 Binary files a/icons/hud/actions.dmi and b/icons/hud/actions.dmi differ diff --git a/icons/hud/screen_ai.dmi b/icons/hud/screen_ai.dmi index 8388ea3f806..8f8d30c6d8b 100644 Binary files a/icons/hud/screen_ai.dmi and b/icons/hud/screen_ai.dmi differ diff --git a/icons/hud/screen_alien.dmi b/icons/hud/screen_alien.dmi index 307c41075ef..88791da700b 100644 Binary files a/icons/hud/screen_alien.dmi and b/icons/hud/screen_alien.dmi differ diff --git a/icons/hud/screen_clockwork.dmi b/icons/hud/screen_clockwork.dmi index 896bf43b662..a0aa0af594e 100644 Binary files a/icons/hud/screen_clockwork.dmi and b/icons/hud/screen_clockwork.dmi differ diff --git a/icons/hud/screen_cyborg.dmi b/icons/hud/screen_cyborg.dmi index dd288e6950a..0b17f099607 100644 Binary files a/icons/hud/screen_cyborg.dmi and b/icons/hud/screen_cyborg.dmi differ diff --git a/icons/hud/screen_gen.dmi b/icons/hud/screen_gen.dmi index a9281c36698..725b3074b6d 100644 Binary files a/icons/hud/screen_gen.dmi and b/icons/hud/screen_gen.dmi differ diff --git a/icons/hud/screen_glass.dmi b/icons/hud/screen_glass.dmi index 2012716ba89..4cbdd189da2 100644 Binary files a/icons/hud/screen_glass.dmi and b/icons/hud/screen_glass.dmi differ diff --git a/icons/hud/screen_midnight.dmi b/icons/hud/screen_midnight.dmi index 605b845efc2..e8e92921f92 100644 Binary files a/icons/hud/screen_midnight.dmi and b/icons/hud/screen_midnight.dmi differ diff --git a/icons/hud/screen_operative.dmi b/icons/hud/screen_operative.dmi index 88fcb5b98ea..2dd30571372 100644 Binary files a/icons/hud/screen_operative.dmi and b/icons/hud/screen_operative.dmi differ diff --git a/icons/hud/screen_pai.dmi b/icons/hud/screen_pai.dmi index a8856712fad..3af44930e0a 100644 Binary files a/icons/hud/screen_pai.dmi and b/icons/hud/screen_pai.dmi differ diff --git a/icons/hud/screen_plasmafire.dmi b/icons/hud/screen_plasmafire.dmi index 61a99bab974..2605c71431b 100644 Binary files a/icons/hud/screen_plasmafire.dmi and b/icons/hud/screen_plasmafire.dmi differ diff --git a/icons/hud/screen_retro.dmi b/icons/hud/screen_retro.dmi index d3574b8824f..8c974e304b0 100644 Binary files a/icons/hud/screen_retro.dmi and b/icons/hud/screen_retro.dmi differ diff --git a/icons/hud/screen_slimecore.dmi b/icons/hud/screen_slimecore.dmi index 96185ed3cf6..d5021ed3586 100644 Binary files a/icons/hud/screen_slimecore.dmi and b/icons/hud/screen_slimecore.dmi differ diff --git a/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm b/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm index aa61e7df40c..b33416952ce 100644 --- a/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm +++ b/modular_skyrat/master_files/code/modules/projectiles/guns/gun.dm @@ -135,7 +135,7 @@ if(fire_select_modes.len > 1) firemode_action = new(src) firemode_action.button_icon_state = "fireselect_[fire_select]" - firemode_action.UpdateButtonIcon() + firemode_action.UpdateButtons() /obj/item/gun/ComponentInitialize() . = ..() @@ -244,7 +244,7 @@ playsound(user, 'sound/weapons/empty.ogg', 100, TRUE) update_appearance() firemode_action.button_icon_state = "fireselect_[fire_select]" - firemode_action.UpdateButtonIcon() + firemode_action.UpdateButtons() SEND_SIGNAL(src, COMSIG_UPDATE_AMMO_HUD) return TRUE @@ -397,7 +397,7 @@ else safety = !safety tsafety.button_icon_state = "safety_[safety ? "on" : "off"]" - tsafety.UpdateButtonIcon() + tsafety.UpdateButtons() playsound(src, 'sound/weapons/empty.ogg', 100, TRUE) user.visible_message(span_notice("[user] toggles [src]'s safety [safety ? "ON" : "OFF"]."), span_notice("You toggle [src]'s safety [safety ? "ON" : "OFF"].")) diff --git a/modular_skyrat/modules/hev_suit/code/hev_suit.dm b/modular_skyrat/modules/hev_suit/code/hev_suit.dm index 7c826ffc7ef..a9dcb502b84 100644 --- a/modular_skyrat/modules/hev_suit/code/hev_suit.dm +++ b/modular_skyrat/modules/hev_suit/code/hev_suit.dm @@ -231,7 +231,7 @@ playsound(my_suit, 'modular_skyrat/master_files/sound/blackmesa/hev/blip.ogg', 50) - UpdateButtonIcon() + UpdateButtons() /datum/action/item_action/hev_toggle/Trigger(trigger_flags) var/obj/item/clothing/suit/space/hev_suit/my_suit = target @@ -249,7 +249,7 @@ playsound(my_suit, 'modular_skyrat/master_files/sound/blackmesa/hev/blip.ogg', 50) - UpdateButtonIcon() + UpdateButtons() /obj/item/clothing/suit/space/hev_suit/proc/send_message(message, color = HEV_COLOR_ORANGE) if(send_notifications != HEV_NOTIFICATION_TEXT_AND_VOICE && send_notifications != HEV_NOTIFICATION_TEXT) diff --git a/tgstation.dme b/tgstation.dme index 2d0a9a629ab..aad53e2413b 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -282,6 +282,7 @@ #include "code\__DEFINES\~skyrat_defines\flavor_defines.dm" #include "code\__DEFINES\~skyrat_defines\game_options.dm" #include "code\__DEFINES\~skyrat_defines\gun.dm" +#include "code\__DEFINES\~skyrat_defines\hud.dm" #include "code\__DEFINES\~skyrat_defines\integrated_electronics.dm" #include "code\__DEFINES\~skyrat_defines\interactions.dm" #include "code\__DEFINES\~skyrat_defines\inventory.dm" @@ -367,6 +368,7 @@ #include "code\__HELPERS\ref.dm" #include "code\__HELPERS\roundend.dm" #include "code\__HELPERS\sanitize_values.dm" +#include "code\__HELPERS\screen_objs.dm" #include "code\__HELPERS\shell.dm" #include "code\__HELPERS\spatial_info.dm" #include "code\__HELPERS\spawns.dm" @@ -435,7 +437,6 @@ #include "code\_onclick\overmind.dm" #include "code\_onclick\pai.dm" #include "code\_onclick\telekinesis.dm" -#include "code\_onclick\hud\_defines.dm" #include "code\_onclick\hud\action_button.dm" #include "code\_onclick\hud\ai.dm" #include "code\_onclick\hud\alert.dm" @@ -2490,7 +2491,6 @@ #include "code\modules\client\preferences\auto_fit_viewport.dm" #include "code\modules\client\preferences\body_type.dm" #include "code\modules\client\preferences\broadcast_login_logout.dm" -#include "code\modules\client\preferences\buttons_locked.dm" #include "code\modules\client\preferences\clothing.dm" #include "code\modules\client\preferences\darkened_flash.dm" #include "code\modules\client\preferences\fov_darkness.dm"