d k daunkey kaung
This commit is contained in:
2
code/__DEFINES/_click.dm
Normal file
2
code/__DEFINES/_click.dm
Normal file
@@ -0,0 +1,2 @@
|
||||
//The button used for dragging (only sent for unrelated mouse up/down messages during a drag)
|
||||
#define DRAG "drag"
|
||||
@@ -196,18 +196,6 @@
|
||||
#define COMSIG_ENTER_AREA "enter_area" //from base of area/Entered(): (/area)
|
||||
#define COMSIG_EXIT_AREA "exit_area" //from base of area/Exited(): (/area)
|
||||
|
||||
#define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params, mob/user)
|
||||
#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob), return flags also used by other signals.
|
||||
#define COMPONENT_ALLOW_EXAMINATE 1
|
||||
#define COMPONENT_DENY_EXAMINATE 2 //Higher priority compared to the above one
|
||||
|
||||
#define COMSIG_CLICK_CTRL "ctrl_click" //from base of atom/CtrlClickOn(): (/mob)
|
||||
#define COMSIG_CLICK_ALT "alt_click" //from base of atom/AltClick(): (/mob)
|
||||
#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click" //from base of atom/CtrlShiftClick(/mob)
|
||||
#define COMSIG_MOUSEDROP_ONTO "mousedrop_onto" //from base of atom/MouseDrop(): (/atom/over, /mob/user)
|
||||
#define COMPONENT_NO_MOUSEDROP 1
|
||||
#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto" //from base of atom/MouseDrop_T: (/atom/from, /mob/user)
|
||||
|
||||
// /area signals
|
||||
#define COMSIG_AREA_ENTERED "area_entered" //from base of area/Entered(): (atom/movable/M)
|
||||
#define COMSIG_AREA_EXITED "area_exited" //from base of area/Exited(): (atom/movable/M)
|
||||
|
||||
6
code/__DEFINES/dcs/signals/signals_action.dm
Normal file
6
code/__DEFINES/dcs/signals/signals_action.dm
Normal file
@@ -0,0 +1,6 @@
|
||||
/// From base of /datum/action/cooldown/proc/PreActivate(), sent to the action owner: (datum/action/cooldown/activated)
|
||||
#define COMSIG_MOB_ABILITY_STARTED "mob_ability_base_started"
|
||||
/// Return to block the ability from starting / activating
|
||||
#define COMPONENT_BLOCK_ABILITY_START (1<<0)
|
||||
/// From base of /datum/action/cooldown/proc/PreActivate(), sent to the action owner: (datum/action/cooldown/finished)
|
||||
#define COMSIG_MOB_ABILITY_FINISHED "mob_ability_base_finished"
|
||||
@@ -0,0 +1,25 @@
|
||||
// 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 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"
|
||||
/// Allows the user to examinate regardless of client.eye.
|
||||
#define COMPONENT_ALLOW_EXAMINATE (1<<0)
|
||||
/// Higher priority compared to the above one
|
||||
#define COMPONENT_DENY_EXAMINATE (1<<1)
|
||||
///from base of atom/CtrlClickOn(): (/mob)
|
||||
#define COMSIG_CLICK_CTRL "ctrl_click"
|
||||
///from base of atom/AltClick(): (/mob)
|
||||
#define COMSIG_CLICK_ALT "alt_click"
|
||||
///from base of atom/CtrlShiftClick(/mob)
|
||||
#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click"
|
||||
///from base of atom/MouseDrop(): (/atom/over, /mob/user)
|
||||
#define COMSIG_MOUSEDROP_ONTO "mousedrop_onto"
|
||||
#define COMPONENT_NO_MOUSEDROP (1<<0)
|
||||
///from base of atom/MouseDrop_T: (/atom/from, /mob/user)
|
||||
#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto" //from base of atom/MouseDrop_T: (/atom/from, /mob/user)
|
||||
@@ -1,9 +1,232 @@
|
||||
//HUD styles. Index order defines how they are cycled in F12.
|
||||
#define HUD_STYLE_STANDARD 1 //Standard hud
|
||||
#define HUD_STYLE_REDUCED 2 //Reduced hud (just hands and intent switcher)
|
||||
#define HUD_STYLE_NOHUD 3 //No hud (for screenshots)
|
||||
/// Standard hud
|
||||
#define HUD_STYLE_STANDARD 1
|
||||
/// Reduced hud (just hands and intent switcher)
|
||||
#define HUD_STYLE_REDUCED 2
|
||||
/// No hud (for screenshots)
|
||||
#define HUD_STYLE_NOHUD 3
|
||||
|
||||
#define HUD_VERSIONS 3 //Used in show_hud(); Please ensure this is the same as the maximum index.
|
||||
/// Used in show_hud(); Please ensure this is the same as the maximum index.
|
||||
#define HUD_VERSIONS 3
|
||||
|
||||
// Consider these images/atoms as part of the UI/HUD (apart of the appearance_flags)
|
||||
/// Used for progress bars and chat messages
|
||||
#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))
|
||||
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"
|
||||
|
||||
#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
|
||||
|
||||
//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_pull_resist "EAST-2:26,SOUTH+1:7"
|
||||
#define ui_movi "EAST-2:26,SOUTH:5"
|
||||
#define ui_sprintbufferloc "EAST-2:26,SOUTH:18"
|
||||
#define ui_acti "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-5:20,SOUTH:5"//CIT CHANGE - moves this over one tile to accommodate for combat mode toggle
|
||||
#define ui_building "EAST-5:20,SOUTH:21"//CIT CHANGE - ditto
|
||||
#define ui_language_menu "EAST-5:4,SOUTH:21"//CIT CHANGE - ditto
|
||||
#define ui_voremode "EAST-5:20,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:19"//CIT CHANGE - moves internal icon up a little bit to accommodate for the stamina meter
|
||||
#define ui_mood "EAST-1:28,CENTER-3:10"
|
||||
// #define ui_spacesuit "EAST-1:28,CENTER-4: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-2:15"
|
||||
#define ui_living_health "EAST-1:28,CENTER: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:21,SOUTH+1:5"
|
||||
#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"
|
||||
#define ui_borg_sensor "CENTER-6:16, SOUTH:5" //LEGACY
|
||||
#define ui_borg_thrusters "CENTER-5:16, SOUTH:5" //LEGACY
|
||||
|
||||
//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-3:26,SOUTH:5"
|
||||
|
||||
//Constructs
|
||||
#define ui_construct_pull "EAST,CENTER-2:15"
|
||||
#define ui_construct_health "EAST,CENTER:15"
|
||||
|
||||
//AI
|
||||
#define ui_ai_core "BOTTOM:6,RIGHT-4"
|
||||
#define ui_ai_shuttle "BOTTOM:6,RIGHT-3"
|
||||
#define ui_ai_announcement "BOTTOM:6,RIGHT-2"
|
||||
#define ui_ai_state_laws "BOTTOM:6,RIGHT-1"
|
||||
#define ui_ai_pda_log "BOTTOM:6,RIGHT"
|
||||
#define ui_ai_pda_send "BOTTOM+1:6,RIGHT"
|
||||
#define ui_ai_language_menu "BOTTOM+1:8,RIGHT-2:30"
|
||||
|
||||
#define ui_ai_crew_monitor "BOTTOM:6,CENTER-1"
|
||||
#define ui_ai_crew_manifest "BOTTOM:6,CENTER"
|
||||
#define ui_ai_alerts "BOTTOM:6,CENTER+1"
|
||||
|
||||
#define ui_ai_view_images "BOTTOM:6,LEFT+4"
|
||||
#define ui_ai_camera_list "BOTTOM:6,LEFT+3"
|
||||
#define ui_ai_track_with_camera "BOTTOM:6,LEFT+2"
|
||||
#define ui_ai_camera_light "BOTTOM:6,LEFT+1"
|
||||
#define ui_ai_sensor "BOTTOM:6,LEFT"
|
||||
#define ui_ai_multicam "BOTTOM+1:6,LEFT+1"
|
||||
#define ui_ai_add_multicam "BOTTOM+1:6,LEFT"
|
||||
#define ui_ai_take_picture "BOTTOM+2:6,LEFT"
|
||||
|
||||
|
||||
// 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_take_picture "SOUTH:6,WEST+12"
|
||||
// #define ui_pai_view_images "SOUTH:6,WEST+13"
|
||||
|
||||
//Ghosts
|
||||
#define ui_ghost_jumptomob "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_mafia "SOUTH: 6, CENTER+2:24"
|
||||
#define ui_ghost_spawners "SOUTH: 6, CENTER+1:24" // LEGACY. SAME LOC AS PAI
|
||||
|
||||
//UI position overrides for 1:1 screen layout. (default is 7:5)
|
||||
#define ui_stamina "EAST-1:28,CENTER:17" // replacing internals button
|
||||
#define ui_overridden_resist "EAST-3:24,SOUTH+1:7"
|
||||
#define ui_clickdelay "CENTER,SOUTH+1:-31"
|
||||
#define ui_resistdelay "EAST-3:24,SOUTH+1:4"
|
||||
#define ui_combat_toggle "EAST-4:22,SOUTH:5"
|
||||
|
||||
#define ui_boxcraft "EAST-4:22,SOUTH+1:6"
|
||||
#define ui_boxarea "EAST-4:6,SOUTH+1:6"
|
||||
#define ui_boxlang "EAST-5:22,SOUTH+1:6"
|
||||
#define ui_boxvore "EAST-5:22,SOUTH+1:6"
|
||||
|
||||
#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"
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
#define CEILING(x, y) ( -round(-(x) / (y)) * (y) )
|
||||
|
||||
#define ROUND_UP(x) ( -round(-(x)))
|
||||
|
||||
// round() acts like floor(x, 1) by default but can't handle other values
|
||||
#define FLOOR(x, y) ( round((x) / (y)) * (y) )
|
||||
|
||||
|
||||
@@ -304,10 +304,6 @@ GLOBAL_LIST_INIT(pda_reskins, list(
|
||||
|
||||
*/
|
||||
|
||||
// Consider these images/atoms as part of the UI/HUD
|
||||
#define APPEARANCE_UI_IGNORE_ALPHA (RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|RESET_ALPHA|PIXEL_SCALE)
|
||||
#define APPEARANCE_UI (RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|PIXEL_SCALE)
|
||||
|
||||
//Just space
|
||||
#define SPACE_ICON_STATE "[((x + y) ^ ~(x * y) + z) % 25]"
|
||||
|
||||
|
||||
91
code/__HELPERS/screen_objs.dm
Normal file
91
code/__HELPERS/screen_objs.dm
Normal file
@@ -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, "")
|
||||
@@ -1,15 +1,19 @@
|
||||
/proc/getviewsize(view)
|
||||
var/viewX
|
||||
var/viewY
|
||||
if(isnum(view))
|
||||
var/totalviewrange = (view < 0 ? -1 : 1) + 2 * view
|
||||
viewX = totalviewrange
|
||||
viewY = totalviewrange
|
||||
return list(totalviewrange, totalviewrange)
|
||||
else
|
||||
var/list/viewrangelist = splittext(view,"x")
|
||||
viewX = text2num(viewrangelist[1])
|
||||
viewY = text2num(viewrangelist[2])
|
||||
return list(viewX, viewY)
|
||||
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)
|
||||
|
||||
@@ -91,31 +91,31 @@
|
||||
/atom/movable/screen/click_catcher/IsAutoclickable()
|
||||
. = 1
|
||||
|
||||
//Please don't roast me too hard
|
||||
/client/MouseMove(object,location,control,params)
|
||||
mouseParams = params
|
||||
mouseLocation = location
|
||||
mouseObject = object
|
||||
mouseControlObject = control
|
||||
if(mob)
|
||||
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOUSEMOVE, object, location, control, params)
|
||||
// god forgive me for i have sinned - used for autoparry. currently at 5 objects.
|
||||
moused_over_objects[object] = world.time
|
||||
if(moused_over_objects.len > 7)
|
||||
moused_over_objects.Cut(1, 2)
|
||||
..()
|
||||
|
||||
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
|
||||
var/list/modifiers = params2list(params)
|
||||
if (LAZYACCESS(modifiers, MIDDLE_CLICK))
|
||||
if (src_object && src_location != over_location)
|
||||
middragtime = world.time
|
||||
middle_drag_atom_ref = WEAKREF(src_object)
|
||||
else
|
||||
middragtime = 0
|
||||
middle_drag_atom_ref = null
|
||||
mouseParams = params
|
||||
mouseLocation = over_location
|
||||
mouseObject = over_object
|
||||
mouseControlObject = over_control
|
||||
if(selected_target[1] && over_object && over_object.IsAutoclickable())
|
||||
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(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
|
||||
middle_drag_atom_ref = null
|
||||
..()
|
||||
|
||||
@@ -1,195 +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"
|
||||
|
||||
#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
|
||||
|
||||
//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_pull_resist "EAST-2:26,SOUTH+1:7"
|
||||
#define ui_movi "EAST-2:26,SOUTH:5"
|
||||
#define ui_sprintbufferloc "EAST-2:26,SOUTH:18"
|
||||
#define ui_acti "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-5:20,SOUTH:5"//CIT CHANGE - moves this over one tile to accommodate for combat mode toggle
|
||||
#define ui_building "EAST-5:20,SOUTH:21"//CIT CHANGE - ditto
|
||||
#define ui_language_menu "EAST-5:4,SOUTH:21"//CIT CHANGE - ditto
|
||||
#define ui_voremode "EAST-5:20,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:19"//CIT CHANGE - moves internal icon up a little bit to accommodate for the stamina meter
|
||||
#define ui_mood "EAST-1:28,CENTER-3:10"
|
||||
// #define ui_spacesuit "EAST-1:28,CENTER-4: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-2:15"
|
||||
#define ui_living_health "EAST-1:28,CENTER: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:21,SOUTH+1:5"
|
||||
#define ui_borg_sensor "CENTER-6:16, SOUTH:5" //LEGACY
|
||||
#define ui_borg_thrusters "CENTER-5:16, SOUTH:5" //LEGACY
|
||||
|
||||
//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-3:26,SOUTH:5"
|
||||
|
||||
//Constructs
|
||||
#define ui_construct_pull "EAST,CENTER-2:15"
|
||||
#define ui_construct_health "EAST,CENTER:15"
|
||||
|
||||
//AI
|
||||
#define ui_ai_core "BOTTOM:6,RIGHT-4"
|
||||
#define ui_ai_shuttle "BOTTOM:6,RIGHT-3"
|
||||
#define ui_ai_announcement "BOTTOM:6,RIGHT-2"
|
||||
#define ui_ai_state_laws "BOTTOM:6,RIGHT-1"
|
||||
#define ui_ai_pda_log "BOTTOM:6,RIGHT"
|
||||
#define ui_ai_pda_send "BOTTOM+1:6,RIGHT"
|
||||
#define ui_ai_language_menu "BOTTOM+1:8,RIGHT-2:30"
|
||||
|
||||
#define ui_ai_crew_monitor "BOTTOM:6,CENTER-1"
|
||||
#define ui_ai_crew_manifest "BOTTOM:6,CENTER"
|
||||
#define ui_ai_alerts "BOTTOM:6,CENTER+1"
|
||||
|
||||
#define ui_ai_view_images "BOTTOM:6,LEFT+4"
|
||||
#define ui_ai_camera_list "BOTTOM:6,LEFT+3"
|
||||
#define ui_ai_track_with_camera "BOTTOM:6,LEFT+2"
|
||||
#define ui_ai_camera_light "BOTTOM:6,LEFT+1"
|
||||
#define ui_ai_sensor "BOTTOM:6,LEFT"
|
||||
#define ui_ai_multicam "BOTTOM+1:6,LEFT+1"
|
||||
#define ui_ai_add_multicam "BOTTOM+1:6,LEFT"
|
||||
#define ui_ai_take_picture "BOTTOM+2:6,LEFT"
|
||||
|
||||
|
||||
// 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_take_picture "SOUTH:6,WEST+12"
|
||||
// #define ui_pai_view_images "SOUTH:6,WEST+13"
|
||||
|
||||
//Ghosts
|
||||
#define ui_ghost_jumptomob "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_mafia "SOUTH: 6, CENTER+2:24"
|
||||
#define ui_ghost_spawners "SOUTH: 6, CENTER+1:24" // LEGACY. SAME LOC AS PAI
|
||||
|
||||
//UI position overrides for 1:1 screen layout. (default is 7:5)
|
||||
#define ui_stamina "EAST-1:28,CENTER:17" // replacing internals button
|
||||
#define ui_overridden_resist "EAST-3:24,SOUTH+1:7"
|
||||
#define ui_clickdelay "CENTER,SOUTH+1:-31"
|
||||
#define ui_resistdelay "EAST-3:24,SOUTH+1:4"
|
||||
#define ui_combat_toggle "EAST-4:22,SOUTH:5"
|
||||
|
||||
#define ui_boxcraft "EAST-4:22,SOUTH+1:6"
|
||||
#define ui_boxarea "EAST-4:6,SOUTH+1:6"
|
||||
#define ui_boxlang "EAST-5:22,SOUTH+1:6"
|
||||
#define ui_boxvore "EAST-5:22,SOUTH+1:6"
|
||||
|
||||
#define ui_wanted_lvl "NORTH,11"
|
||||
@@ -2,186 +2,154 @@
|
||||
|
||||
/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)
|
||||
return linked_action.owner == user
|
||||
if(linked_action.viewers[user.hud_used])
|
||||
return TRUE
|
||||
return FALSE
|
||||
else if (isobserver(user))
|
||||
var/mob/dead/observer/O = user
|
||||
return !O.observetarget
|
||||
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 class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
|
||||
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
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"])
|
||||
if(locked)
|
||||
to_chat(usr, "<span class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
|
||||
return TRUE
|
||||
moved = 0
|
||||
usr.update_action_buttons() //redraw buttons that are no longer considered "moved"
|
||||
return TRUE
|
||||
if(modifiers["ctrl"])
|
||||
locked = !locked
|
||||
to_chat(usr, "<span class='notice'>Action button \"[name]\" [locked ? "" : "un"]locked.</span>")
|
||||
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
|
||||
linked_action.Trigger()
|
||||
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/mob/actions.dmi'
|
||||
icon_state = "bg_default"
|
||||
var/hidden = 0
|
||||
var/hide_icon = 'icons/mob/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()
|
||||
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/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)
|
||||
if(old_object)
|
||||
old_object.MouseExited(over_location, over_control, params)
|
||||
|
||||
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)
|
||||
last_hovored_ref = WEAKREF(over_object)
|
||||
over_object.MouseEntered(over_location, over_control, params)
|
||||
|
||||
/atom/movable/screen/movable/action_button/hide_toggle/Click(location,control,params)
|
||||
if (!can_use(usr))
|
||||
/atom/movable/screen/movable/action_button/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
if(!QDELETED(src))
|
||||
openToolTip(usr, src, params, title = name, content = desc, theme = actiontooltipstyle)
|
||||
|
||||
/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
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"])
|
||||
if(locked)
|
||||
to_chat(usr, "<span class='warning'>Action button \"[name]\" is locked, unlock it first.</span>")
|
||||
return TRUE
|
||||
moved = FALSE
|
||||
usr.update_action_buttons(TRUE)
|
||||
return TRUE
|
||||
if(modifiers["ctrl"])
|
||||
locked = !locked
|
||||
to_chat(usr, "<span class='notice'>Action button \"[name]\" [locked ? "" : "un"]locked.</span>")
|
||||
if(id && usr.client) //try to (un)remember position
|
||||
usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = locked ? moved : null
|
||||
return TRUE
|
||||
if(modifiers["alt"])
|
||||
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 = usr.client.prefs.buttons_locked
|
||||
locked = usr.client.prefs.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 class='notice'>Action button positions have been reset.</span>")
|
||||
return TRUE
|
||||
usr.hud_used.action_buttons_hidden = !usr.hud_used.action_buttons_hidden
|
||||
|
||||
hidden = usr.hud_used.action_buttons_hidden
|
||||
if(hidden)
|
||||
name = "Show Buttons"
|
||||
else
|
||||
name = "Hide Buttons"
|
||||
update_icon()
|
||||
usr.update_action_buttons()
|
||||
|
||||
/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 class='notice'>Action button positions have been reset.</span>")
|
||||
return TRUE
|
||||
|
||||
|
||||
/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_icon()
|
||||
|
||||
/atom/movable/screen/movable/action_button/hide_toggle/update_overlays()
|
||||
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
|
||||
. = ..()
|
||||
if(hidden)
|
||||
. += show_appearance
|
||||
else
|
||||
. += hide_appearance
|
||||
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
|
||||
|
||||
/atom/movable/screen/movable/action_button/MouseEntered(location,control,params)
|
||||
if(!QDELETED(src))
|
||||
openToolTip(usr,src,params,title = name,content = desc,theme = actiontooltipstyle)
|
||||
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/MouseExited()
|
||||
closeToolTip(usr)
|
||||
/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/mob/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)
|
||||
@@ -191,56 +159,243 @@
|
||||
if(hud_used.hud_shown != HUD_STYLE_STANDARD)
|
||||
return
|
||||
|
||||
var/button_number = 0
|
||||
var/list/cview = getviewsize(client.view)
|
||||
var/supportedcolumns = cview[1]-2
|
||||
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, supportedcolumns)
|
||||
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, supportedcolumns)
|
||||
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()
|
||||
|
||||
/datum/hud/proc/ButtonNumberToScreenCoords(number, supportedcolumns) // TODO : Make this zero-indexed for readabilty
|
||||
var/row = round((number - 1)/supportedcolumns)
|
||||
var/col = ((number - 1)%(supportedcolumns)) + 1
|
||||
/atom/movable/screen/button_palette
|
||||
desc = "<b>Drag</b> buttons to move them<br><b>Shift-click</b> any button to reset it<br><b>Alt-click</b> 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
|
||||
|
||||
var/coord_col = "+[col-1]"
|
||||
var/coord_col_offset = 2 + 2 * col
|
||||
/atom/movable/screen/button_palette/Destroy()
|
||||
if(our_hud)
|
||||
our_hud.mymob?.client?.screen -= src
|
||||
our_hud.toggle_palette = null
|
||||
our_hud = null
|
||||
return ..()
|
||||
|
||||
var/coord_row = "[row ? -row : "+0"]"
|
||||
/atom/movable/screen/button_palette/Initialize(mapload)
|
||||
. = ..()
|
||||
update_appearance()
|
||||
|
||||
return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:-6"
|
||||
/atom/movable/screen/button_palette/proc/set_hud(datum/hud/our_hud)
|
||||
src.our_hud = our_hud
|
||||
refresh_owner()
|
||||
|
||||
/datum/hud/proc/SetButtonCoords(atom/movable/screen/button,number, supportedcolumns)
|
||||
var/row = round((number-1)/supportedcolumns)
|
||||
var/col = ((number - 1)%(supportedcolumns)) + 1
|
||||
var/x_offset = 32*(col-1) + 4 + 2*col
|
||||
var/y_offset = -32*(row+1) + 26
|
||||
/atom/movable/screen/button_palette/update_name(updates)
|
||||
. = ..()
|
||||
if(expanded)
|
||||
name = "Hide Buttons"
|
||||
else
|
||||
name = "Show Buttons"
|
||||
|
||||
var/matrix/M = matrix()
|
||||
M.Translate(x_offset,y_offset)
|
||||
button.transform = M
|
||||
/atom/movable/screen/button_palette/proc/refresh_owner()
|
||||
var/mob/viewer = our_hud.mymob
|
||||
if(viewer.client)
|
||||
viewer.client.screen |= src
|
||||
|
||||
var/list/settings = our_hud.get_action_buttons_icons()
|
||||
var/ui_icon = "[settings["bg_icon"]]"
|
||||
var/list/ui_segments = splittext(ui_icon, ".")
|
||||
var/list/ui_paths = splittext(ui_segments[1], "/")
|
||||
var/ui_name = ui_paths[length(ui_paths)]
|
||||
|
||||
icon_state = "[ui_name]_palette"
|
||||
|
||||
/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/mob/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 = "<b>Click</b> 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 = "<b>Click</b> 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 = "<b>Drag and drop</b> a button into this spot<br>to add it to the group"
|
||||
icon = 'icons/mob/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)
|
||||
|
||||
@@ -73,8 +73,13 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
|
||||
// We don't actually do proccalls really yet, so let's grab at prefs
|
||||
|
||||
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/healthdoll
|
||||
@@ -91,10 +96,12 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
// will fall back to the default if any of these are null
|
||||
ui_style = ui_style2icon(owner.client && owner.client.prefs && owner.client.prefs.UI_style)
|
||||
|
||||
hide_actions_toggle = new
|
||||
hide_actions_toggle.InitialiseIcon(src)
|
||||
if(mymob.client)
|
||||
hide_actions_toggle.locked = mymob.client.prefs.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()
|
||||
|
||||
@@ -110,7 +117,13 @@ GLOBAL_LIST_INIT(available_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)
|
||||
|
||||
@@ -148,10 +161,14 @@ GLOBAL_LIST_INIT(available_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))
|
||||
@@ -160,6 +177,8 @@ GLOBAL_LIST_INIT(available_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.update_clickcatcher()
|
||||
|
||||
@@ -181,7 +200,7 @@ GLOBAL_LIST_INIT(available_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
|
||||
@@ -272,7 +291,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
||||
|
||||
ui_style = new_ui_style
|
||||
build_hand_slots()
|
||||
hide_actions_toggle.InitialiseIcon(src)
|
||||
|
||||
//Triggered when F12 is pressed (Unless someone changed something in the DMF)
|
||||
/mob/verb/button_pressed_F12()
|
||||
@@ -320,3 +338,306 @@ GLOBAL_LIST_INIT(available_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
|
||||
|
||||
@@ -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
|
||||
var/list/PM = params2list(params)
|
||||
|
||||
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(!PM || !PM["screen-loc"])
|
||||
if(!LAZYACCESS(modifiers, SCREEN_LOC))
|
||||
return
|
||||
|
||||
//Split screen-loc up into X+Pixel_X and Y+Pixel_Y
|
||||
var/list/screen_loc_params = splittext(PM["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()
|
||||
|
||||
@@ -17,4 +17,4 @@
|
||||
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]
|
||||
|
||||
@@ -69,15 +69,15 @@ SUBSYSTEM_DEF(augury)
|
||||
SSaugury.watchers += owner
|
||||
to_chat(owner, "<span class='notice'>You are now auto-following debris.</span>")
|
||||
active = TRUE
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/innate/augury/Deactivate()
|
||||
SSaugury.watchers -= owner
|
||||
to_chat(owner, "<span class='notice'>You are no longer auto-following debris.</span>")
|
||||
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"
|
||||
|
||||
@@ -11,9 +11,11 @@
|
||||
var/check_flags = 0
|
||||
var/required_mobility_flags = MOBILITY_USE
|
||||
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/use_target_appearance = FALSE
|
||||
var/list/target_appearance_matrix //if set, will be used to transform the target button appearance as an arglist.
|
||||
|
||||
@@ -28,12 +30,6 @@
|
||||
|
||||
/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
|
||||
@@ -43,51 +39,42 @@
|
||||
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
|
||||
|
||||
//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
|
||||
|
||||
M.actions += src
|
||||
if(M.client)
|
||||
M.client.screen += button
|
||||
button.locked = M.client.prefs.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
|
||||
if(ref == owner)
|
||||
Remove(owner)
|
||||
if(ref == target)
|
||||
qdel(src)
|
||||
|
||||
/datum/action/proc/Remove(mob/M)
|
||||
if(M)
|
||||
if(M.client)
|
||||
M.client.screen -= button
|
||||
M.actions -= src
|
||||
M.update_action_buttons()
|
||||
owner = null
|
||||
button.moved = FALSE //so the button appears in its normal position when given to another owner.
|
||||
button.locked = FALSE
|
||||
button.id = null
|
||||
for(var/datum/hud/hud in viewers)
|
||||
if(!hud.mymob)
|
||||
continue
|
||||
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
|
||||
|
||||
/datum/action/proc/Trigger()
|
||||
if(!IsAvailable())
|
||||
@@ -125,15 +112,15 @@
|
||||
/datum/action/proc/UpdateButtons(status_only, force)
|
||||
for(var/datum/hud/hud in viewers)
|
||||
var/atom/movable/screen/movable/button = viewers[hud]
|
||||
UpdateButtonIcon(button, status_only, force)
|
||||
UpdateButton(button, status_only, force)
|
||||
|
||||
/datum/action/proc/UpdateButtonIcon(status_only = FALSE, force = FALSE)
|
||||
/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 && owner.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND)
|
||||
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"]
|
||||
@@ -145,25 +132,13 @@
|
||||
if(button.icon_state != background_icon_state)
|
||||
button.icon_state = background_icon_state
|
||||
|
||||
if(!use_target_appearance)
|
||||
ApplyIcon(button, force)
|
||||
ApplyIcon(button, force)
|
||||
|
||||
else if(target && button.appearance_cache != target.appearance) //replace with /ref comparison if this is not valid.
|
||||
var/mutable_appearance/M = new(target)
|
||||
M.layer = FLOAT_LAYER
|
||||
M.plane = FLOAT_PLANE
|
||||
if(target_appearance_matrix)
|
||||
var/list/L = target_appearance_matrix
|
||||
M.transform = matrix(L[1], L[2], L[3], L[4], L[5], L[6])
|
||||
button.cut_overlays()
|
||||
button.add_overlay(M)
|
||||
button.appearance_cache = target.appearance
|
||||
|
||||
if(!IsAvailable(TRUE))
|
||||
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 1
|
||||
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))
|
||||
@@ -184,7 +159,67 @@
|
||||
M.ghostize(can_reenter_corpse = TRUE, voluntary = TRUE)
|
||||
|
||||
/datum/action/proc/OnUpdatedIcon()
|
||||
addtimer(CALLBACK(src, .proc/UpdateButtonIcon), 1) //Hopefully runs after new icon overlays have been compiled.
|
||||
SIGNAL_HANDLER
|
||||
UpdateButtons()
|
||||
|
||||
//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
|
||||
|
||||
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
|
||||
|
||||
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.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
|
||||
@@ -258,12 +293,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"
|
||||
@@ -309,9 +346,9 @@
|
||||
|
||||
/datum/action/item_action/toggle_unfriendly_fire/Trigger()
|
||||
if(..())
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/item_action/toggle_unfriendly_fire/UpdateButtonIcon(status_only = FALSE, force)
|
||||
/datum/action/item_action/toggle_unfriendly_fire/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force)
|
||||
if(istype(target, /obj/item/hierophant_club))
|
||||
var/obj/item/hierophant_club/H = target
|
||||
if(H.friendly_fire_check)
|
||||
@@ -380,7 +417,6 @@
|
||||
/datum/action/item_action/toggle/New(Target)
|
||||
..()
|
||||
name = "Toggle [target.name]"
|
||||
button.name = name
|
||||
|
||||
/datum/action/item_action/halt
|
||||
name = "HALT!"
|
||||
@@ -409,7 +445,6 @@
|
||||
/datum/action/item_action/adjust/New(Target)
|
||||
..()
|
||||
name = "Adjust [target.name]"
|
||||
button.name = name
|
||||
|
||||
/datum/action/item_action/switch_hud
|
||||
name = "Switch HUD"
|
||||
@@ -495,12 +530,10 @@
|
||||
/datum/action/item_action/organ_action/toggle/New(Target)
|
||||
..()
|
||||
name = "Toggle [target.name]"
|
||||
button.name = name
|
||||
|
||||
/datum/action/item_action/organ_action/use/New(Target)
|
||||
..()
|
||||
name = "Use [target.name]"
|
||||
button.name = name
|
||||
|
||||
/datum/action/item_action/cult_dagger
|
||||
name = "Draw Blood Rune"
|
||||
@@ -509,14 +542,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(iscultist(M))
|
||||
..()
|
||||
button.screen_loc = "6:157,4:-2"
|
||||
button.moved = "6:157,4:-2"
|
||||
else
|
||||
if(!iscultist(M))
|
||||
Remove(owner)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/cult_dagger/Trigger()
|
||||
for(var/obj/item/H in owner.held_items) //In case we were already holding another dagger
|
||||
@@ -643,7 +675,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
|
||||
@@ -711,44 +742,114 @@
|
||||
/datum/action/cooldown
|
||||
check_flags = 0
|
||||
transparent_when_unavailable = FALSE
|
||||
// The default cooldown applied when StartCooldown() is called
|
||||
var/cooldown_time = 0
|
||||
// The actual next time this ability can be used
|
||||
var/next_use_time = 0
|
||||
// Whether or not you want the cooldown for the ability to display in text form
|
||||
var/text_cooldown = TRUE
|
||||
// Setting for intercepting clicks before activating the ability
|
||||
var/click_to_activate = FALSE
|
||||
// Shares cooldowns with other cooldown abilities of the same value, not active if null
|
||||
var/shared_cooldown
|
||||
|
||||
/datum/action/cooldown/New()
|
||||
..()
|
||||
/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(silent = FALSE)
|
||||
return next_use_time <= world.time
|
||||
/datum/action/cooldown/IsAvailable()
|
||||
return ..() && (next_use_time <= world.time)
|
||||
|
||||
/datum/action/cooldown/proc/StartCooldown()
|
||||
next_use_time = world.time + cooldown_time
|
||||
button.maptext = MAPTEXT_TINY_UNICODE("[round(cooldown_time/10, 0.1)]")
|
||||
UpdateButtonIcon()
|
||||
/// Starts a cooldown time to be shared with similar abilities, will use default cooldown time if an override is not specified
|
||||
/datum/action/cooldown/proc/StartCooldown(override_cooldown_time)
|
||||
if(shared_cooldown)
|
||||
for(var/datum/action/cooldown/shared_ability in owner.actions - src)
|
||||
if(shared_cooldown == shared_ability.shared_cooldown)
|
||||
if(isnum(override_cooldown_time))
|
||||
shared_ability.StartCooldownSelf(override_cooldown_time)
|
||||
else
|
||||
shared_ability.StartCooldownSelf(cooldown_time)
|
||||
StartCooldownSelf(override_cooldown_time)
|
||||
|
||||
/// Starts a cooldown time for this ability only, will use default cooldown time if an override is not specified
|
||||
/datum/action/cooldown/proc/StartCooldownSelf(override_cooldown_time)
|
||||
if(isnum(override_cooldown_time))
|
||||
next_use_time = world.time + override_cooldown_time
|
||||
else
|
||||
next_use_time = world.time + cooldown_time
|
||||
UpdateButtons()
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/datum/action/cooldown/process()
|
||||
/datum/action/cooldown/Trigger(trigger_flags, atom/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!owner)
|
||||
return FALSE
|
||||
if(click_to_activate)
|
||||
if(target)
|
||||
// For automatic / mob handling
|
||||
return InterceptClickOn(owner, null, target)
|
||||
if(owner.click_intercept == src)
|
||||
owner.click_intercept = null
|
||||
else
|
||||
owner.click_intercept = src
|
||||
for(var/datum/action/cooldown/ability in owner.actions)
|
||||
ability.UpdateButtons()
|
||||
return TRUE
|
||||
return PreActivate(owner)
|
||||
|
||||
/// Intercepts client owner clicks to activate the ability
|
||||
/datum/action/cooldown/proc/InterceptClickOn(mob/living/caller, params, atom/target)
|
||||
if(!IsAvailable())
|
||||
return FALSE
|
||||
if(!target)
|
||||
return FALSE
|
||||
PreActivate(target)
|
||||
caller.click_intercept = null
|
||||
return TRUE
|
||||
|
||||
/// For signal calling
|
||||
/datum/action/cooldown/proc/PreActivate(atom/target)
|
||||
if(SEND_SIGNAL(owner, COMSIG_MOB_ABILITY_STARTED, src) & COMPONENT_BLOCK_ABILITY_START)
|
||||
return
|
||||
. = Activate(target)
|
||||
SEND_SIGNAL(owner, COMSIG_MOB_ABILITY_FINISHED, src)
|
||||
|
||||
/// To be implemented by subtypes
|
||||
/datum/action/cooldown/proc/Activate(atom/target)
|
||||
return
|
||||
|
||||
/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(text_cooldown)
|
||||
button.maptext = MAPTEXT("<b>[round(time_left/10, 0.1)]</b>")
|
||||
if(!owner || time_left == 0)
|
||||
button.maptext = ""
|
||||
if(IsAvailable() && owner.click_intercept == src)
|
||||
button.color = COLOR_GREEN
|
||||
|
||||
/datum/action/cooldown/process()
|
||||
var/time_left = max(next_use_time - world.time, 0)
|
||||
if(!owner || time_left == 0)
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
var/timeleft = max(next_use_time - world.time, 0)
|
||||
if(timeleft == 0)
|
||||
button.maptext = ""
|
||||
UpdateButtonIcon()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
else
|
||||
button.maptext = MAPTEXT_TINY_UNICODE("[round(cooldown_time/10, 0.1)]")
|
||||
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)
|
||||
|
||||
//surf_ss13
|
||||
/datum/action/item_action/bhop
|
||||
|
||||
@@ -225,7 +225,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
|
||||
|
||||
@@ -1661,7 +1661,7 @@ GLOBAL_LIST(objective_choices)
|
||||
if(istype(S, type))
|
||||
continue
|
||||
S.charge_counter = delay
|
||||
S.updateButtonIcon()
|
||||
S.UpdateButton()
|
||||
INVOKE_ASYNC(S, /obj/effect/proc_holder/spell.proc/start_recharge)
|
||||
|
||||
/datum/mind/proc/get_ghost(even_if_they_cant_reenter)
|
||||
|
||||
@@ -1,108 +1,110 @@
|
||||
//This is intended to be a full wrapper. DO NOT directly modify its values
|
||||
///Container for client viewsize
|
||||
/datum/viewData
|
||||
/datum/view_data
|
||||
var/width = 0
|
||||
var/height = 0
|
||||
var/default = ""
|
||||
var/is_suppressed = FALSE
|
||||
var/client/chief = null
|
||||
|
||||
/datum/viewData/New(client/owner, view_string)
|
||||
/datum/view_data/New(client/owner, view_string)
|
||||
default = view_string
|
||||
chief = owner
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/setDefault(string)
|
||||
/datum/view_data/proc/setDefault(string)
|
||||
default = string
|
||||
apply()
|
||||
|
||||
/datum/viewData/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/viewData/proc/assertFormat()//T-Pose
|
||||
/datum/view_data/proc/assertFormat()//T-Pose
|
||||
// winset(chief, "mapwindow.map", "zoom=0")
|
||||
// Citadel Edit - We're using icon dropdown instead
|
||||
|
||||
/datum/viewData/proc/resetFormat()//Cuck
|
||||
/datum/view_data/proc/resetFormat()//Cuck
|
||||
// winset(chief, "mapwindow.map", "zoom=[chief.prefs.pixel_size]")
|
||||
// Citadel Edit - We're using icon dropdown instead
|
||||
|
||||
/datum/viewData/proc/setZoomMode()
|
||||
/datum/view_data/proc/setZoomMode()
|
||||
// winset(chief, "mapwindow.map", "zoom-mode=[chief.prefs.scaling_method]")
|
||||
// Citadel Edit - We're using icon dropdown instead
|
||||
|
||||
/datum/viewData/proc/isZooming()
|
||||
/datum/view_data/proc/isZooming()
|
||||
return (width || height)
|
||||
|
||||
/datum/viewData/proc/resetToDefault()
|
||||
/datum/view_data/proc/resetToDefault()
|
||||
width = 0
|
||||
height = 0
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/add(toAdd)
|
||||
/datum/view_data/proc/add(toAdd)
|
||||
width += toAdd
|
||||
height += toAdd
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/addTo(toAdd)
|
||||
/datum/view_data/proc/addTo(toAdd)
|
||||
var/list/shitcode = getviewsize(toAdd)
|
||||
width += shitcode[1]
|
||||
height += shitcode[2]
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/setTo(toAdd)
|
||||
/datum/view_data/proc/setTo(toAdd)
|
||||
var/list/shitcode = getviewsize(toAdd) //Backward compatability to account
|
||||
width = shitcode[1] //for a change in how sizes get calculated. we used to include world.view in
|
||||
height = shitcode[2] //this, but it was jank, so I had to move it
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/setBoth(wid, hei)
|
||||
/datum/view_data/proc/setBoth(wid, hei)
|
||||
width = wid
|
||||
height = hei
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/setWidth(wid)
|
||||
/datum/view_data/proc/setWidth(wid)
|
||||
width = wid
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/setHeight(hei)
|
||||
/datum/view_data/proc/setHeight(hei)
|
||||
width = hei
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/addToWidth(toAdd)
|
||||
/datum/view_data/proc/addToWidth(toAdd)
|
||||
width += toAdd
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/addToHeight(screen, toAdd)
|
||||
/datum/view_data/proc/addToHeight(screen, toAdd)
|
||||
height += toAdd
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/apply()
|
||||
/datum/view_data/proc/apply()
|
||||
chief.change_view(getView())
|
||||
safeApplyFormat()
|
||||
afterViewChange()
|
||||
|
||||
/datum/viewData/proc/supress()
|
||||
/datum/view_data/proc/supress()
|
||||
is_suppressed = TRUE
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/unsupress()
|
||||
/datum/view_data/proc/unsupress()
|
||||
is_suppressed = FALSE
|
||||
apply()
|
||||
|
||||
/datum/viewData/proc/getView()
|
||||
/datum/view_data/proc/getView()
|
||||
var/list/temp = getviewsize(default)
|
||||
if(is_suppressed)
|
||||
return "[temp[1]]x[temp[2]]"
|
||||
return "[width + temp[1]]x[height + temp[2]]"
|
||||
|
||||
/datum/viewData/proc/zoomIn()
|
||||
/datum/view_data/proc/zoomIn()
|
||||
resetToDefault()
|
||||
animate(chief, pixel_x = 0, pixel_y = 0, 0, FALSE, LINEAR_EASING, ANIMATION_END_NOW)
|
||||
|
||||
/datum/viewData/proc/zoomOut(radius = 0, offset = 0, direction = FALSE)
|
||||
/datum/view_data/proc/zoomOut(radius = 0, offset = 0, direction = FALSE)
|
||||
if(direction)
|
||||
var/_x = 0
|
||||
var/_y = 0
|
||||
|
||||
@@ -1283,7 +1283,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
*/
|
||||
/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)
|
||||
|
||||
/// Special stuff you want to do when an outfit equips this item.
|
||||
/obj/item/proc/on_outfit_equip(mob/living/carbon/human/outfit_wearer, visuals_only, item_slot)
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
update_power()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
|
||||
/obj/item/defibrillator/proc/make_paddles()
|
||||
if(!combat)
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
playsound(src, on ? 'sound/weapons/magin.ogg' : 'sound/weapons/magout.ogg', 40, TRUE)
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
return TRUE
|
||||
|
||||
/obj/item/flashlight/DoRevenantThrowEffects(atom/target)
|
||||
|
||||
@@ -129,12 +129,12 @@
|
||||
/datum/action/innate/drink_fling/Activate()
|
||||
button_icon_state = "drinkfling_on"
|
||||
active = TRUE
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/innate/drink_fling/Deactivate()
|
||||
button_icon_state = "drinkfling_off"
|
||||
active = FALSE
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
/obj/item/book/granter/action/origami
|
||||
granted_action = /datum/action/innate/origami
|
||||
@@ -155,13 +155,13 @@
|
||||
to_chat(owner, "<span class='notice'>You will now fold origami planes.</span>")
|
||||
button_icon_state = "origami_on"
|
||||
active = TRUE
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/innate/origami/Deactivate()
|
||||
to_chat(owner, "<span class='notice'>You will no longer fold origami planes.</span>")
|
||||
button_icon_state = "origami_off"
|
||||
active = FALSE
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
///SPELLS///
|
||||
|
||||
|
||||
@@ -719,6 +719,6 @@
|
||||
user.vtec = initial(user.vtec) - maxReduction * 1
|
||||
|
||||
action.button_icon_state = "Chevron_State_[currentState]"
|
||||
action.UpdateButtonIcon()
|
||||
action.UpdateButtons()
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
to_chat(user, "<span class='notice'>You turn the jetpack off.</span>")
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
|
||||
/obj/item/tank/jetpack/proc/turn_on(mob/user)
|
||||
on = TRUE
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
return FALSE
|
||||
var/client/C = controller.client
|
||||
if(C)
|
||||
var/atom/A = C.mouseObject
|
||||
var/atom/A = WEAKREF(C.mouse_object_ref)
|
||||
var/turf/T = get_turf(A)
|
||||
if(istype(T)) //They're hovering over something in the map.
|
||||
direction_track(controller, T)
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
H.update_inv_wear_suit()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
|
||||
/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user, datum/action/A)
|
||||
if(slot == ITEM_SLOT_OCLOTHING) //we only give the mob the ability to activate the vest if he's actually wearing it.
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
return
|
||||
// Disable Powers: Masquerade * NOTE * This should happen as a FLAW!
|
||||
//if (stat >= UNCONSCIOUS)
|
||||
// for (var/datum/action/bloodsucker/masquerade/P in powers)
|
||||
// for (var/datum/action/cooldown/bloodsucker/masquerade/P in powers)
|
||||
// P.Deactivate()
|
||||
// TEMP DEATH
|
||||
var/total_brute = owner.current.getBruteLoss_nonProsthetic()
|
||||
@@ -252,7 +252,7 @@
|
||||
owner.current.update_sight()
|
||||
owner.current.reload_fullscreen()
|
||||
// Disable ALL Powers
|
||||
for(var/datum/action/bloodsucker/power in powers)
|
||||
for(var/datum/action/cooldown/bloodsucker/power in powers)
|
||||
if(power.active && !power.can_use_in_torpor)
|
||||
power.DeactivatePower()
|
||||
if(owner.current.suiciding)
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
/datum/action/bloodsucker
|
||||
/datum/action/cooldown/bloodsucker
|
||||
name = "Vampiric Gift"
|
||||
desc = "A vampiric gift."
|
||||
button_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the BACKGROUND icon
|
||||
background_icon_state = "vamp_power_off" //And this is the state for the background icon
|
||||
var/background_icon_state_on = "vamp_power_on" // FULP: Our "ON" icon alternative.
|
||||
var/background_icon_state_off = "vamp_power_off" // FULP: Our "OFF" icon alternative.
|
||||
icon_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the ACTION icon
|
||||
button_icon_state = "power_feed" //And this is the state for the action icon
|
||||
buttontooltipstyle = "cult"
|
||||
transparent_when_unavailable = TRUE
|
||||
|
||||
/// Cooldown you'll have to wait between each use, decreases depending on level.
|
||||
cooldown_time = 2 SECONDS
|
||||
|
||||
///Background icon when the Power is active.
|
||||
var/background_icon_state_on = "vamp_power_on"
|
||||
///Background icon when the Power is NOT active.
|
||||
var/background_icon_state_off = "vamp_power_off"
|
||||
|
||||
// Action-Related
|
||||
//var/amPassive = FALSE // REMOVED: Just made it its own kind. // Am I just "on" at all times? (aka NO ICON)
|
||||
var/amTargetted = FALSE // Am I asked to choose a target when enabled? (Shows as toggled ON when armed)
|
||||
var/amToggle = FALSE // Can I be actively turned on and off?
|
||||
var/amSingleUse = FALSE // Am I removed after a single use?
|
||||
var/active = FALSE
|
||||
var/cooldown = 20 // 10 ticks, 1 second.
|
||||
var/cooldownUntil = 0 // From action.dm: next_use_time = world.time + cooldown_time
|
||||
// Power-Related
|
||||
var/level_current = 0 // Can increase to yield new abilities. Each power goes up in strength each Rank.
|
||||
//var/level_max = 1 //
|
||||
@@ -32,7 +36,7 @@
|
||||
//var/not_bloodsucker = FALSE // This goes to Vassals or Hunters, but NOT bloodsuckers.
|
||||
var/must_be_concious = TRUE //Can't use this ability while unconcious.
|
||||
|
||||
/datum/action/bloodsucker/New()
|
||||
/datum/action/cooldown/bloodsucker/New()
|
||||
if(bloodcost > 0)
|
||||
desc += "<br><br><b>COST:</b> [bloodcost] Blood" // Modify description to add cost.
|
||||
if(warn_constant_cost)
|
||||
@@ -46,7 +50,7 @@
|
||||
// click.dm <--- Where we can take over mouse clicks
|
||||
// spells.dm /add_ranged_ability() <--- How we take over the mouse click to use a power on a target.
|
||||
|
||||
/datum/action/bloodsucker/Trigger()
|
||||
/datum/action/cooldown/bloodsucker/Trigger()
|
||||
// Active? DEACTIVATE AND END!
|
||||
if(active && CheckCanDeactivate(TRUE))
|
||||
DeactivatePower()
|
||||
@@ -56,7 +60,7 @@
|
||||
PayCost()
|
||||
if(amToggle)
|
||||
active = !active
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
if(!amToggle || !active)
|
||||
StartCooldown() // Must come AFTER UpdateButton(), otherwise icon will revert.
|
||||
ActivatePower() // NOTE: ActivatePower() freezes this power in place until it ends.
|
||||
@@ -65,13 +69,13 @@
|
||||
if(amSingleUse)
|
||||
RemoveAfterUse()
|
||||
|
||||
/datum/action/bloodsucker/proc/CheckCanPayCost(display_error)
|
||||
/datum/action/cooldown/bloodsucker/proc/CheckCanPayCost(display_error)
|
||||
if(!owner || !owner.mind)
|
||||
return FALSE
|
||||
// Cooldown?
|
||||
if(cooldownUntil > world.time)
|
||||
if(next_use_time > world.time)
|
||||
if(display_error)
|
||||
to_chat(owner, "[src] is unavailable. Wait [(cooldownUntil - world.time) / 10] seconds.")
|
||||
to_chat(owner, "[src] is unavailable. Wait [(next_use_time - world.time) / 10] seconds.")
|
||||
return FALSE
|
||||
// Have enough blood?
|
||||
var/mob/living/L = owner
|
||||
@@ -81,7 +85,7 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/proc/CheckCanUse(display_error) // These checks can be scanned every frame while a ranged power is on.
|
||||
/datum/action/cooldown/bloodsucker/proc/CheckCanUse(display_error) // These checks can be scanned every frame while a ranged power is on.
|
||||
if(!owner || !owner.mind)
|
||||
return FALSE
|
||||
// Torpor?
|
||||
@@ -123,79 +127,43 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/proc/StartCooldown()
|
||||
set waitfor = FALSE
|
||||
// Alpha Out
|
||||
button.color = rgb(128,0,0,128)
|
||||
button.alpha = 100
|
||||
// Calculate Cooldown (by power's level)
|
||||
var/this_cooldown = (cooldown_static || amSingleUse) ? cooldown : max(cooldown / 2, cooldown - (cooldown / 16 * (level_current-1)))
|
||||
// NOTE: With this formula, you'll hit half cooldown at level 8 for that power.
|
||||
|
||||
// Wait for cooldown
|
||||
cooldownUntil = world.time + this_cooldown
|
||||
spawn(this_cooldown)
|
||||
// Alpha In
|
||||
button.color = rgb(255,255,255,255)
|
||||
button.alpha = 255
|
||||
|
||||
/datum/action/bloodsucker/proc/CheckCanDeactivate(display_error)
|
||||
/datum/action/cooldown/bloodsucker/proc/CheckCanDeactivate(display_error)
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/UpdateButtonIcon(force = FALSE)
|
||||
/datum/action/cooldown/bloodsucker/UpdateButton(atom/movable/screen/movable/action_button/button, force = FALSE)
|
||||
background_icon_state = active? background_icon_state_on : background_icon_state_off
|
||||
..()//UpdateButtonIcon()
|
||||
..()//UpdateButton()
|
||||
|
||||
|
||||
/datum/action/bloodsucker/proc/PayCost()
|
||||
/datum/action/cooldown/bloodsucker/proc/PayCost()
|
||||
// owner for actions is the mob, not mind.
|
||||
var/mob/living/L = owner
|
||||
L.blood_volume -= bloodcost
|
||||
|
||||
|
||||
/datum/action/bloodsucker/proc/ActivatePower()
|
||||
/datum/action/cooldown/bloodsucker/proc/ActivatePower()
|
||||
|
||||
|
||||
/datum/action/bloodsucker/proc/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/proc/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
active = FALSE
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
StartCooldown()
|
||||
|
||||
/datum/action/bloodsucker/proc/ContinueActive(mob/living/user, mob/living/target) // Used by loops to make sure this power can stay active.
|
||||
/datum/action/cooldown/bloodsucker/proc/ContinueActive(mob/living/user, mob/living/target) // Used by loops to make sure this power can stay active.
|
||||
return active && user && (!warn_constant_cost || user.blood_volume > 0)
|
||||
|
||||
/datum/action/bloodsucker/proc/RemoveAfterUse()
|
||||
/datum/action/cooldown/bloodsucker/proc/RemoveAfterUse()
|
||||
// Un-Learn Me! (GO HOME
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
if (istype(bloodsuckerdatum))
|
||||
bloodsuckerdatum.powers -= src
|
||||
Remove(owner)
|
||||
|
||||
/datum/action/bloodsucker/proc/Upgrade()
|
||||
/datum/action/cooldown/bloodsucker/proc/Upgrade()
|
||||
level_current ++
|
||||
|
||||
/////////////////////////////////// PASSIVE POWERS ///////////////////////////////////
|
||||
|
||||
// New Type: Passive (Always on, no button)
|
||||
/datum/action/bloodsucker/passive
|
||||
|
||||
/datum/action/bloodsucker/passive/New()
|
||||
// REMOVED: DO NOTHBING!
|
||||
..()
|
||||
// Don't Display Button! (it doesn't do anything anyhow)
|
||||
button.screen_loc = DEFAULT_BLOODSPELLS
|
||||
button.moved = DEFAULT_BLOODSPELLS
|
||||
button.ordered = FALSE
|
||||
|
||||
/datum/action/bloodsucker/passive/Destroy()
|
||||
if(owner)
|
||||
Remove(owner)
|
||||
target = null
|
||||
return ..()
|
||||
|
||||
/////////////////////////////////// TARGETTED POWERS ///////////////////////////////////
|
||||
|
||||
/datum/action/bloodsucker/targeted
|
||||
/datum/action/cooldown/bloodsucker/targeted
|
||||
// NOTE: All Targeted spells are Toggles! We just don't bother checking here.
|
||||
var/target_range = 99
|
||||
var/message_Trigger = "Select a target."
|
||||
@@ -204,7 +172,7 @@
|
||||
|
||||
var/power_in_use = FALSE // Is this power LOCKED due to being used?
|
||||
|
||||
/datum/action/bloodsucker/targeted/New(Target)
|
||||
/datum/action/cooldown/bloodsucker/targeted/New(Target)
|
||||
desc += "<br>\[<i>Targeted Power</i>\]" // Modify description to add notice that this is aimed.
|
||||
..()
|
||||
// Create Proc Holder for intercepting clicks
|
||||
@@ -212,7 +180,7 @@
|
||||
bs_proc_holder.linked_power = src
|
||||
|
||||
// Click power: Begin Aim
|
||||
/datum/action/bloodsucker/targeted/Trigger()
|
||||
/datum/action/cooldown/bloodsucker/targeted/Trigger()
|
||||
if(active && CheckCanDeactivate(TRUE))
|
||||
DeactivateRangedAbility()
|
||||
DeactivatePower()
|
||||
@@ -220,7 +188,7 @@
|
||||
if(!CheckCanPayCost(TRUE) || !CheckCanUse(TRUE))
|
||||
return
|
||||
active = !active
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
// Create & Link Targeting Proc
|
||||
var/mob/living/L = owner
|
||||
if(L.ranged_ability)
|
||||
@@ -230,7 +198,7 @@
|
||||
if(message_Trigger != "")
|
||||
to_chat(owner, "<span class='announce'>[message_Trigger]</span>")
|
||||
|
||||
/datum/action/bloodsucker/targeted/CheckCanUse(display_error)
|
||||
/datum/action/cooldown/bloodsucker/targeted/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -238,21 +206,21 @@
|
||||
return FALSE // doesn't let you remove powers if you're not there. So, let's just cancel the power entirely.
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/targeted/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/targeted/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
// Don't run ..(), we don't want to engage the cooldown until we USE this power!
|
||||
active = FALSE
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/bloodsucker/targeted/proc/DeactivateRangedAbility()
|
||||
/datum/action/cooldown/bloodsucker/targeted/proc/DeactivateRangedAbility()
|
||||
// Only Turned off when CLICK is disabled...aka, when you successfully clicked (or
|
||||
bs_proc_holder.remove_ranged_ability()
|
||||
|
||||
// Check if target is VALID (wall, turf, or character?)
|
||||
/datum/action/bloodsucker/targeted/proc/CheckValidTarget(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/proc/CheckValidTarget(atom/A)
|
||||
return FALSE // FALSE targets nothing.
|
||||
|
||||
// Check if valid target meets conditions
|
||||
/datum/action/bloodsucker/targeted/proc/CheckCanTarget(atom/A, display_error)
|
||||
/datum/action/cooldown/bloodsucker/targeted/proc/CheckCanTarget(atom/A, display_error)
|
||||
// Out of Range
|
||||
if(!(A in view(target_range, owner)))
|
||||
if(display_error && target_range > 1) // Only warn for range if it's greater than 1. Brawn doesn't need to announce itself.
|
||||
@@ -261,7 +229,7 @@
|
||||
return istype(A)
|
||||
|
||||
// Click Target
|
||||
/datum/action/bloodsucker/targeted/proc/ClickWithPower(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/proc/ClickWithPower(atom/A)
|
||||
// CANCEL RANGED TARGET check
|
||||
if(power_in_use || !CheckValidTarget(A))
|
||||
return FALSE
|
||||
@@ -276,21 +244,21 @@
|
||||
power_in_use = FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/targeted/proc/FireTargetedPower(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/proc/FireTargetedPower(atom/A)
|
||||
// Like ActivatePower, but specific to Targeted (and takes an atom input). We don't use ActivatePower for targeted.
|
||||
|
||||
/datum/action/bloodsucker/targeted/proc/PowerActivatedSuccessfully()
|
||||
/datum/action/cooldown/bloodsucker/targeted/proc/PowerActivatedSuccessfully()
|
||||
// The power went off! We now pay the cost of the power.
|
||||
PayCost()
|
||||
DeactivateRangedAbility()
|
||||
DeactivatePower()
|
||||
StartCooldown() // Do AFTER UpdateIcon() inside of DeactivatePower. Otherwise icon just gets wiped.
|
||||
|
||||
/datum/action/bloodsucker/targeted/ContinueActive(mob/living/user, mob/living/target) // Used by loops to make sure this power can stay active.
|
||||
/datum/action/cooldown/bloodsucker/targeted/ContinueActive(mob/living/user, mob/living/target) // Used by loops to make sure this power can stay active.
|
||||
return ..()
|
||||
// Target Proc Holder
|
||||
/obj/effect/proc_holder/bloodsucker
|
||||
var/datum/action/bloodsucker/targeted/linked_power
|
||||
var/datum/action/cooldown/bloodsucker/targeted/linked_power
|
||||
|
||||
/obj/effect/proc_holder/bloodsucker/remove_ranged_ability(msg)
|
||||
..()
|
||||
|
||||
@@ -55,8 +55,8 @@
|
||||
bloodsuckerdatum.warn_sun_locker = FALSE
|
||||
bloodsuckerdatum.warn_sun_burn = FALSE
|
||||
// Remove Dawn Powers
|
||||
for(var/datum/action/bloodsucker/P in bloodsuckerdatum.powers)
|
||||
if(istype(P, /datum/action/bloodsucker/gohome))
|
||||
for(var/datum/action/cooldown/bloodsucker/P in bloodsuckerdatum.powers)
|
||||
if(istype(P, /datum/action/cooldown/bloodsucker/gohome))
|
||||
bloodsuckerdatum.powers -= P
|
||||
P.Remove(M.current)
|
||||
nighttime_duration += 100 //Each day makes the night a minute longer.
|
||||
@@ -149,5 +149,5 @@
|
||||
if(!istype(M) || !istype(M.current))
|
||||
continue
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = M.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
if(istype(bloodsuckerdatum) && bloodsuckerdatum.lair && !(locate(/datum/action/bloodsucker/gohome) in bloodsuckerdatum.powers))
|
||||
bloodsuckerdatum.BuyPower(new /datum/action/bloodsucker/gohome)
|
||||
if(istype(bloodsuckerdatum) && bloodsuckerdatum.lair && !(locate(/datum/action/cooldown/bloodsucker/gohome) in bloodsuckerdatum.powers))
|
||||
bloodsuckerdatum.BuyPower(new /datum/action/cooldown/bloodsucker/gohome)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
dat += "<HR>"
|
||||
|
||||
// Step One: Decide powers you CAN buy.
|
||||
for(var/pickedpower in typesof(/datum/action/bloodsucker))
|
||||
for(var/pickedpower in typesof(/datum/action/cooldown/bloodsucker))
|
||||
var/obj/effect/proc_holder/spell/bloodsucker/power = pickedpower
|
||||
// NAME
|
||||
dat += "<A href='byond://?src=[REF(src)];[module.mod_pick_name]=1'>[power.name]</A>"
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
return fullname
|
||||
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/BuyPower(datum/action/bloodsucker/power)//(obj/effect/proc_holder/spell/power)
|
||||
/datum/antagonist/bloodsucker/proc/BuyPower(datum/action/cooldown/bloodsucker/power)//(obj/effect/proc_holder/spell/power)
|
||||
powers += power
|
||||
power.Grant(owner.current)// owner.AddSpell(power)
|
||||
|
||||
@@ -177,9 +177,9 @@
|
||||
add_hud()
|
||||
update_hud(TRUE) // Set blood value, current rank
|
||||
// Powers
|
||||
BuyPower(new /datum/action/bloodsucker/feed)
|
||||
BuyPower(new /datum/action/bloodsucker/masquerade)
|
||||
BuyPower(new /datum/action/bloodsucker/veil)
|
||||
BuyPower(new /datum/action/cooldown/bloodsucker/feed)
|
||||
BuyPower(new /datum/action/cooldown/bloodsucker/masquerade)
|
||||
BuyPower(new /datum/action/cooldown/bloodsucker/veil)
|
||||
// Traits
|
||||
for(var/T in defaultTraits)
|
||||
ADD_TRAIT(owner.current, T, BLOODSUCKER_TRAIT)
|
||||
@@ -221,7 +221,7 @@
|
||||
remove_hud()
|
||||
// Powers
|
||||
while(powers.len)
|
||||
var/datum/action/bloodsucker/power = pick(powers)
|
||||
var/datum/action/cooldown/bloodsucker/power = pick(powers)
|
||||
powers -= power
|
||||
power.Remove(owner.current)
|
||||
// owner.RemoveSpell(power)
|
||||
@@ -267,7 +267,7 @@
|
||||
to_chat(owner, "<span class='announce'>Bloodsucker Tip: If you cannot find or steal a coffin to use, you can build one from wooden planks.</span><br>")
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/LevelUpPowers()
|
||||
for(var/datum/action/bloodsucker/power in powers)
|
||||
for(var/datum/action/cooldown/bloodsucker/power in powers)
|
||||
power.level_current ++
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/SpendRank()
|
||||
@@ -281,8 +281,8 @@
|
||||
//TODO: Make this into a radial, or perhaps a tgui next UI
|
||||
// Purchase Power Prompt
|
||||
var/list/options = list()
|
||||
for(var/pickedpower in typesof(/datum/action/bloodsucker))
|
||||
var/datum/action/bloodsucker/power = pickedpower
|
||||
for(var/pickedpower in typesof(/datum/action/cooldown/bloodsucker))
|
||||
var/datum/action/cooldown/bloodsucker/power = pickedpower
|
||||
// If I don't own it, and I'm allowed to buy it.
|
||||
if(!(locate(power) in powers) && initial(power.bloodsucker_can_buy))
|
||||
options[initial(power.name)] = power // TESTING: After working with TGUI, it seems you can use initial() to view the variables inside a path?
|
||||
@@ -303,7 +303,7 @@
|
||||
to_chat(owner.current, "<span class='warning'>You dont have enough blood to thicken your blood, you need [level_bloodcost - L.blood_volume] units more!</span>")
|
||||
return
|
||||
// Buy New Powers
|
||||
var/datum/action/bloodsucker/P = options[choice]
|
||||
var/datum/action/cooldown/bloodsucker/P = options[choice]
|
||||
AddBloodVolume(-level_bloodcost)
|
||||
BuyPower(new P)
|
||||
to_chat(owner.current, "<span class='notice'>You have used [level_bloodcost] units of blood and learned [initial(P.name)]!</span>")
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
//owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer/hunter_edition)
|
||||
|
||||
// Give Hunter Power
|
||||
var/datum/action/P = new /datum/action/bloodsucker/trackvamp
|
||||
var/datum/action/P = new /datum/action/cooldown/bloodsucker/trackvamp
|
||||
P.Grant(owner.current)
|
||||
|
||||
// Give Hunter Martial Arts
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
// Take Hunter Power
|
||||
if (owner.current)
|
||||
for (var/datum/action/bloodsucker/P in owner.current.actions)
|
||||
for (var/datum/action/cooldown/bloodsucker/P in owner.current.actions)
|
||||
P.Remove(owner.current)
|
||||
|
||||
// Take Hunter Martial Arts
|
||||
@@ -166,7 +166,7 @@
|
||||
/*
|
||||
|
||||
|
||||
/datum/action/bloodsucker/trackvamp/
|
||||
/datum/action/cooldown/bloodsucker/trackvamp/
|
||||
name = "Track Monster"//"Cellular Emporium"
|
||||
desc = "Take a moment to look for clues of any nearby monsters.<br>These creatures are slippery, and often look like the crew."
|
||||
button_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the BACKGROUND icon
|
||||
@@ -177,7 +177,7 @@
|
||||
cooldown = 300 // 10 ticks, 1 second.
|
||||
bloodcost = 0
|
||||
|
||||
/datum/action/bloodsucker/trackvamp/ActivatePower()
|
||||
/datum/action/cooldown/bloodsucker/trackvamp/ActivatePower()
|
||||
|
||||
var/mob/living/user = owner
|
||||
to_chat(user, "<span class='notice'>You look around, scanning your environment and discerning signs of any filthy, wretched affronts to the natural order.</span>")
|
||||
@@ -192,7 +192,7 @@
|
||||
// NOTE: DON'T DEACTIVATE!
|
||||
//DeactivatePower()
|
||||
|
||||
/datum/action/bloodsucker/trackvamp/proc/display_proximity()
|
||||
/datum/action/cooldown/bloodsucker/trackvamp/proc/display_proximity()
|
||||
// Pick target
|
||||
var/turf/my_loc = get_turf(owner)
|
||||
//var/list/mob/living/carbon/vamps = list()
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
// Master Pinpointer
|
||||
owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer/vassal_edition)
|
||||
// Powers
|
||||
var/datum/action/bloodsucker/vassal/recuperate/new_Recuperate = new ()
|
||||
var/datum/action/cooldown/bloodsucker/vassal/recuperate/new_Recuperate = new ()
|
||||
new_Recuperate.Grant(owner.current)
|
||||
powers += new_Recuperate
|
||||
// Give Vassal Objective
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
|
||||
|
||||
/datum/action/bloodsucker/targeted/brawn
|
||||
/datum/action/cooldown/bloodsucker/targeted/brawn
|
||||
name = "Brawn"
|
||||
desc = "Snap restraints with ease, or deal terrible damage with your bare hands."
|
||||
button_icon_state = "power_strength"
|
||||
bloodcost = 10
|
||||
cooldown = 90
|
||||
cooldown_time = 90
|
||||
target_range = 1
|
||||
power_activates_immediately = TRUE
|
||||
message_Trigger = ""//"Whom will you subvert to your will?"
|
||||
@@ -16,7 +16,7 @@
|
||||
var/upgrade_canLocker = FALSE
|
||||
var/upgrade_canDoor = FALSE
|
||||
|
||||
/datum/action/bloodsucker/targeted/brawn/CheckCanUse(display_error)
|
||||
/datum/action/cooldown/bloodsucker/targeted/brawn/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -38,10 +38,10 @@
|
||||
|
||||
// NOTE: We use . = FALSE so that we can break cuffs AND throw off our attacker in one use!
|
||||
//return TRUE
|
||||
/datum/action/bloodsucker/targeted/brawn/CheckValidTarget(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/brawn/CheckValidTarget(atom/A)
|
||||
return isliving(A) || istype(A, /obj/machinery/door)
|
||||
|
||||
/datum/action/bloodsucker/targeted/brawn/CheckCanTarget(atom/A, display_error)
|
||||
/datum/action/cooldown/bloodsucker/targeted/brawn/CheckCanTarget(atom/A, display_error)
|
||||
// DEFAULT CHECKS (Distance)
|
||||
if(!..()) // Disable range notice for Brawn.
|
||||
return FALSE
|
||||
@@ -59,7 +59,7 @@
|
||||
return TRUE
|
||||
return ..() // yes, FALSE! You failed if you got here! BAD TARGET
|
||||
|
||||
/datum/action/bloodsucker/targeted/brawn/FireTargetedPower(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/brawn/FireTargetedPower(atom/A)
|
||||
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done.
|
||||
var/mob/living/carbon/target = A
|
||||
var/mob/living/user = owner
|
||||
@@ -97,7 +97,7 @@
|
||||
D.open(2) // open(2) is like a crowbar or jaws of life.
|
||||
// Target Type: Closet
|
||||
|
||||
/datum/action/bloodsucker/targeted/brawn/proc/CheckBreakRestraints()
|
||||
/datum/action/cooldown/bloodsucker/targeted/brawn/proc/CheckBreakRestraints()
|
||||
if(!iscarbon(owner)) // || !owner.restrained()
|
||||
return FALSE
|
||||
// (NOTE: Just like biodegrade.dm, we only remove one thing per use //
|
||||
@@ -131,7 +131,7 @@
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/action/bloodsucker/targeted/brawn/proc/CheckEscapePuller()
|
||||
/datum/action/cooldown/bloodsucker/targeted/brawn/proc/CheckEscapePuller()
|
||||
if(!owner.pulledby)// || owner.pulledby.grab_state <= GRAB_PASSIVE)
|
||||
return FALSE
|
||||
var/mob/M = owner.pulledby
|
||||
@@ -153,7 +153,7 @@
|
||||
owner.pulledby = null // It's already done, but JUST IN CASE.
|
||||
return TRUE
|
||||
/* Doesnt work
|
||||
/datum/action/bloodsucker/targeted/brawn/proc/CheckBreakLocker()
|
||||
/datum/action/cooldown/bloodsucker/targeted/brawn/proc/CheckBreakLocker()
|
||||
if(!istype(owner.loc, /obj/structure/closet))
|
||||
return FALSE
|
||||
playsound(get_turf(owner), 'sound/machines/airlock_alien_prying.ogg', 40, 1, -1)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
|
||||
|
||||
/datum/action/bloodsucker/cloak
|
||||
/datum/action/cooldown/bloodsucker/cloak
|
||||
name = "Cloak of Darkness"
|
||||
desc = "Blend into the shadows and become invisible to the untrained eye. Movement is slowed in brightly lit areas, and you cannot dissapear while mortals watch you."
|
||||
button_icon_state = "power_cloak"
|
||||
bloodcost = 5
|
||||
cooldown = 50
|
||||
cooldown_time = 50
|
||||
bloodsucker_can_buy = TRUE
|
||||
amToggle = TRUE
|
||||
warn_constant_cost = TRUE
|
||||
@@ -14,7 +14,7 @@
|
||||
var/walk_threshold = 0.4 // arbitrary number, to be changed. edit in last commit: this is fine after testing on box station for a bit
|
||||
var/lum
|
||||
|
||||
/datum/action/bloodsucker/cloak/CheckCanUse(display_error)
|
||||
/datum/action/cooldown/bloodsucker/cloak/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -24,7 +24,7 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/cloak/ActivatePower()
|
||||
/datum/action/cooldown/bloodsucker/cloak/ActivatePower()
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
var/mob/living/user = owner
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
sleep(5) // Check every few ticks
|
||||
|
||||
/datum/action/bloodsucker/cloak/ContinueActive(mob/living/user, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/cloak/ContinueActive(mob/living/user, mob/living/target)
|
||||
if (!..())
|
||||
return FALSE
|
||||
if(user.stat == !CONSCIOUS) // Must be CONSCIOUS
|
||||
@@ -60,7 +60,7 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/cloak/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/cloak/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
..()
|
||||
REMOVE_TRAIT(user, TRAIT_NORUNNING, "cloak of darkness")
|
||||
user.alpha = 255
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
|
||||
/datum/action/bloodsucker/feed
|
||||
/datum/action/cooldown/bloodsucker/feed
|
||||
name = "Feed"
|
||||
desc = "Draw the heartsblood of living victims in your grasp.<br><b>None/Passive:</b> Feed silently and unnoticed by your victim.<br><b>Aggressive: </b>Subdue your target quickly."
|
||||
button_icon_state = "power_feed"
|
||||
|
||||
bloodcost = 0
|
||||
cooldown = 30
|
||||
cooldown_time = 30
|
||||
amToggle = TRUE
|
||||
bloodsucker_can_buy = TRUE
|
||||
can_be_staked = TRUE
|
||||
@@ -16,7 +16,7 @@
|
||||
var/mob/living/feed_target // So we can validate more than just the guy we're grappling.
|
||||
var/target_grappled = FALSE // If you started grappled, then ending it will end your Feed.
|
||||
|
||||
/datum/action/bloodsucker/feed/CheckCanUse(display_error)
|
||||
/datum/action/cooldown/bloodsucker/feed/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -33,7 +33,7 @@
|
||||
// DONE!
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/feed/proc/ValidateTarget(mob/living/target, display_error) // Called twice: validating a subtle victim, or validating your grapple victim.
|
||||
/datum/action/cooldown/bloodsucker/feed/proc/ValidateTarget(mob/living/target, display_error) // Called twice: validating a subtle victim, or validating your grapple victim.
|
||||
// Bloodsuckers + Animals MUST be grabbed aggressively!
|
||||
if(!owner.pulling || target == owner.pulling && owner.grab_state < GRAB_AGGRESSIVE)
|
||||
// NOTE: It's OKAY that we are checking if(!target) below, AFTER animals here. We want passive check vs animal to warn you first, THEN the standard warning.
|
||||
@@ -76,7 +76,7 @@
|
||||
return TRUE
|
||||
|
||||
// If I'm not grabbing someone, find me someone nearby.
|
||||
/datum/action/bloodsucker/feed/proc/FindMyTarget(display_error)
|
||||
/datum/action/cooldown/bloodsucker/feed/proc/FindMyTarget(display_error)
|
||||
// Default
|
||||
feed_target = null
|
||||
target_grappled = FALSE
|
||||
@@ -132,7 +132,7 @@
|
||||
feed_target = pick(targets_valid)//targets[1]
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/feed/ActivatePower()
|
||||
/datum/action/cooldown/bloodsucker/feed/ActivatePower()
|
||||
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up Activate(), so Deactivate() can happen after.
|
||||
var/mob/living/target = feed_target // Stored during CheckCanUse(). Can be a grabbed OR adjecent character.
|
||||
var/mob/living/user = owner
|
||||
@@ -302,16 +302,16 @@
|
||||
CheckKilledTarget(user,target)
|
||||
|
||||
|
||||
/datum/action/bloodsucker/feed/proc/CheckKilledTarget(mob/living/user, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/feed/proc/CheckKilledTarget(mob/living/user, mob/living/target)
|
||||
// Bad Bloodsucker. You shouldn't do that.
|
||||
if(target && target.stat >= DEAD && ishuman(target))
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankkilled", /datum/mood_event/drankkilled) // BAD // in bloodsucker_life.dm
|
||||
|
||||
/datum/action/bloodsucker/feed/ContinueActive(mob/living/user, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/feed/ContinueActive(mob/living/user, mob/living/target)
|
||||
return ..() && target && (!target_grappled || user.pulling == target) && blood_sucking_checks(target, TRUE, TRUE) // Active, and still antag,
|
||||
// NOTE: We only care about pulling if target started off that way. Mostly only important for Aggressive feed.
|
||||
|
||||
/datum/action/bloodsucker/feed/proc/ApplyVictimEffects(mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/feed/proc/ApplyVictimEffects(mob/living/target)
|
||||
// Bloodsuckers not affected by "the Kiss" of another vampire
|
||||
if(!target.mind || !target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
target.Unconscious(50,0)
|
||||
@@ -320,7 +320,7 @@
|
||||
if(ishuman(target))
|
||||
target.adjustStaminaLoss(5, forced = TRUE)// Base Stamina Damage
|
||||
|
||||
/datum/action/bloodsucker/feed/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/feed/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
..() // activate = FALSE
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
// No longer Feeding
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
|
||||
|
||||
/datum/action/bloodsucker/fortitude
|
||||
/datum/action/cooldown/bloodsucker/fortitude
|
||||
name = "Fortitude"
|
||||
desc = "Withstand egregious physical wounds and walk away from attacks that would stun, pierce, and dismember lesser beings. You cannot run while active."
|
||||
button_icon_state = "power_fortitude"
|
||||
bloodcost = 30
|
||||
cooldown = 80
|
||||
cooldown_time = 80
|
||||
bloodsucker_can_buy = TRUE
|
||||
amToggle = TRUE
|
||||
warn_constant_cost = TRUE
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
var/fortitude_resist // So we can raise and lower your brute resist based on what your level_current WAS.
|
||||
|
||||
/datum/action/bloodsucker/fortitude/ActivatePower()
|
||||
/datum/action/cooldown/bloodsucker/fortitude/ActivatePower()
|
||||
var/datum/antagonist/bloodsucker/B = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
var/mob/living/user = owner
|
||||
to_chat(user, "<span class='notice'>Your flesh, skin, and muscles become as steel.</span>")
|
||||
@@ -47,8 +47,8 @@
|
||||
B.AddBloodVolume(-0.5)
|
||||
sleep(20) // Check every few ticks that we haven't disabled this power
|
||||
// Return to Running (if you were before)
|
||||
|
||||
/datum/action/bloodsucker/fortitude/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
|
||||
/datum/action/cooldown/bloodsucker/fortitude/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
..()
|
||||
// Restore Traits & Effects
|
||||
REMOVE_TRAIT(user, TRAIT_PIERCEIMMUNE, "fortitude")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
/datum/action/bloodsucker/gohome
|
||||
/datum/action/cooldown/bloodsucker/gohome
|
||||
name = "Vanishing Act"
|
||||
desc = "As dawn aproaches, disperse into mist and return directly to your Lair.<br><b>WARNING:</b> You will drop <b>ALL</b> of your possessions if observed by mortals."
|
||||
button_icon_state = "power_gohome"
|
||||
@@ -8,7 +8,7 @@
|
||||
background_icon_state_off = "vamp_power_off_oneshot"
|
||||
|
||||
bloodcost = 100
|
||||
cooldown = 99999 // It'll never come back.
|
||||
cooldown_time = 99999 // It'll never come back.
|
||||
amToggle = FALSE
|
||||
amSingleUse = TRUE
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
can_be_immobilized = TRUE
|
||||
must_be_concious = FALSE
|
||||
|
||||
/datum/action/bloodsucker/gohome/CheckCanUse(display_error)
|
||||
/datum/action/cooldown/bloodsucker/gohome/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -30,12 +30,12 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/gohome/proc/flicker_lights(var/flicker_range, var/beat_volume)
|
||||
/datum/action/cooldown/bloodsucker/gohome/proc/flicker_lights(var/flicker_range, var/beat_volume)
|
||||
for(var/obj/machinery/light/L in view(flicker_range, get_turf(owner)))
|
||||
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', beat_volume, 1)
|
||||
|
||||
|
||||
/datum/action/bloodsucker/gohome/ActivatePower()
|
||||
/datum/action/cooldown/bloodsucker/gohome/ActivatePower()
|
||||
var/mob/living/carbon/user = owner
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
// IMPORTANT: Check for lair at every step! It might get destroyed.
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
// Level 2: Dodge Bullets
|
||||
// Level 3: Stun People Passed
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste
|
||||
/datum/action/cooldown/bloodsucker/targeted/haste
|
||||
name = "Immortal Haste"
|
||||
desc = "Dash somewhere with supernatural speed. Those nearby may be knocked away, stunned, or left empty-handed."
|
||||
button_icon_state = "power_speed"
|
||||
bloodcost = 6
|
||||
cooldown = 120
|
||||
cooldown_time = 120
|
||||
target_range = 15
|
||||
power_activates_immediately = TRUE
|
||||
message_Trigger = ""//"Whom will you subvert to your will?"
|
||||
@@ -18,7 +18,7 @@
|
||||
/// If set, uses this speed in deciseconds instead of world.tick_lag
|
||||
var/speed_override
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/CheckCanUse(display_error)
|
||||
/datum/action/cooldown/bloodsucker/targeted/haste/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -33,10 +33,10 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/CheckValidTarget(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/haste/CheckValidTarget(atom/A)
|
||||
return isturf(A) || A.loc != owner.loc // Anything will do, if it's not me or my square
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/CheckCanTarget(atom/A, display_error)
|
||||
/datum/action/cooldown/bloodsucker/targeted/haste/CheckCanTarget(atom/A, display_error)
|
||||
// DEFAULT CHECKS (Distance)
|
||||
if (!..())
|
||||
return FALSE
|
||||
@@ -45,7 +45,7 @@
|
||||
// return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/FireTargetedPower(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/haste/FireTargetedPower(atom/A)
|
||||
// This is a non-async proc to make sure the power is "locked" until this finishes.
|
||||
hit = list()
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/on_move)
|
||||
@@ -78,11 +78,11 @@
|
||||
hit = null
|
||||
user.update_mobility()
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/targeted/haste/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
..() // activate = FALSE
|
||||
user.update_mobility()
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/proc/on_move()
|
||||
/datum/action/cooldown/bloodsucker/targeted/haste/proc/on_move()
|
||||
for(var/mob/living/L in dview(1, get_turf(owner)))
|
||||
if(!hit[L] && (L != owner))
|
||||
hit[L] = TRUE
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
|
||||
|
||||
/datum/action/bloodsucker/lunge
|
||||
/datum/action/cooldown/bloodsucker/lunge
|
||||
name = "Predatory Lunge"
|
||||
desc = "Prepare the strenght to grapple your prey."
|
||||
button_icon_state = "power_lunge"
|
||||
bloodcost = 10
|
||||
cooldown = 30
|
||||
cooldown_time = 30
|
||||
bloodsucker_can_buy = TRUE
|
||||
warn_constant_cost = TRUE
|
||||
amToggle = TRUE
|
||||
var/leap_skill_mod = 5
|
||||
|
||||
/datum/action/bloodsucker/lunge/New()
|
||||
/datum/action/cooldown/bloodsucker/lunge/New()
|
||||
. = ..()
|
||||
|
||||
|
||||
/datum/action/bloodsucker/lunge/Destroy()
|
||||
|
||||
/datum/action/cooldown/bloodsucker/lunge/Destroy()
|
||||
. = ..()
|
||||
UnregisterSignal(owner, COMSIG_CARBON_TACKLED)
|
||||
|
||||
/datum/action/bloodsucker/lunge/ActivatePower()
|
||||
/datum/action/cooldown/bloodsucker/lunge/ActivatePower()
|
||||
var/mob/living/carbon/user = owner
|
||||
var/datum/antagonist/bloodsucker/B = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
var/datum/component/tackler/T = user.LoadComponent(/datum/component/tackler)
|
||||
@@ -37,10 +37,10 @@
|
||||
sleep(5)
|
||||
|
||||
//Without this, the leap component would get removed too early, causing the normal crash into effects.
|
||||
/datum/action/bloodsucker/lunge/proc/DelayedDeactivatePower()
|
||||
/datum/action/cooldown/bloodsucker/lunge/proc/DelayedDeactivatePower()
|
||||
addtimer(CALLBACK(src, .proc/DeactivatePower), 1 SECONDS, TIMER_UNIQUE)
|
||||
|
||||
/datum/action/bloodsucker/lunge/DeactivatePower(mob/living/user = owner)
|
||||
/datum/action/cooldown/bloodsucker/lunge/DeactivatePower(mob/living/user = owner)
|
||||
. = ..()
|
||||
qdel(user.GetComponent(/datum/component/tackler))
|
||||
UnregisterSignal(user, COMSIG_CARBON_TACKLED)
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
// -
|
||||
|
||||
|
||||
/datum/action/bloodsucker/masquerade
|
||||
/datum/action/cooldown/bloodsucker/masquerade
|
||||
name = "Masquerade"
|
||||
desc = "Feign the vital signs of a mortal, and escape both casual and medical notice as the monster you truly are."
|
||||
button_icon_state = "power_human"
|
||||
bloodcost = 10
|
||||
cooldown = 50
|
||||
cooldown_time = 50
|
||||
amToggle = TRUE
|
||||
bloodsucker_can_buy = TRUE
|
||||
warn_constant_cost = TRUE
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
// NOTE: Firing off vulgar powers disables your Masquerade!
|
||||
|
||||
/*/datum/action/bloodsucker/masquerade/CheckCanUse(display_error)
|
||||
/*/datum/action/cooldown/bloodsucker/masquerade/CheckCanUse(display_error)
|
||||
if(!..(display_error))// DEFAULT CHECKS
|
||||
return FALSE
|
||||
// DONE!
|
||||
@@ -39,7 +39,7 @@
|
||||
*/
|
||||
|
||||
|
||||
/datum/action/bloodsucker/masquerade/ActivatePower()
|
||||
/datum/action/cooldown/bloodsucker/masquerade/ActivatePower()
|
||||
|
||||
var/mob/living/user = owner
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
@@ -78,14 +78,14 @@
|
||||
sleep(20) // Check every few ticks that we haven't disabled this power
|
||||
|
||||
|
||||
/datum/action/bloodsucker/masquerade/ContinueActive(mob/living/user)
|
||||
/datum/action/cooldown/bloodsucker/masquerade/ContinueActive(mob/living/user)
|
||||
// Disable if unable to use power anymore.
|
||||
//if (user.stat == DEAD || user.blood_volume <= 0) // not conscious or soft critor uncon, just dead
|
||||
// return FALSE
|
||||
return ..() // Active, and still Antag
|
||||
|
||||
|
||||
/datum/action/bloodsucker/masquerade/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/masquerade/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
..() // activate = FALSE
|
||||
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
// FOLLOW: Target follows you, spouting random phrases from their history (or maybe Polly's or NPC's vocab?)
|
||||
// ATTACK: Target finds a nearby non-Bloodsucker victim to attack.
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize
|
||||
/datum/action/cooldown/bloodsucker/targeted/mesmerize
|
||||
name = "Mesmerize"
|
||||
desc = "Dominate the mind of a mortal who can see your eyes."
|
||||
button_icon_state = "power_mez"
|
||||
bloodcost = 30
|
||||
cooldown = 300
|
||||
cooldown_time = 300
|
||||
target_range = 2
|
||||
power_activates_immediately = TRUE
|
||||
message_Trigger = "Whom will you subvert to your will?"
|
||||
@@ -18,7 +18,7 @@
|
||||
bloodsucker_can_buy = TRUE
|
||||
var/success
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize/CheckCanUse(display_error)
|
||||
/datum/action/cooldown/bloodsucker/targeted/mesmerize/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -34,10 +34,10 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize/CheckValidTarget(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/mesmerize/CheckValidTarget(atom/A)
|
||||
return iscarbon(A)
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize/CheckCanTarget(atom/A,display_error)
|
||||
/datum/action/cooldown/bloodsucker/targeted/mesmerize/CheckCanTarget(atom/A,display_error)
|
||||
// Check: Self
|
||||
if(A == owner)
|
||||
return FALSE
|
||||
@@ -88,7 +88,7 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize/proc/ContinueTarget(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/mesmerize/proc/ContinueTarget(atom/A)
|
||||
var/mob/living/carbon/target = A
|
||||
var/mob/living/L = owner
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
to_chat(L, "<span class='warning'>[target] has escaped your gaze!</span>")
|
||||
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize/FireTargetedPower(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/mesmerize/FireTargetedPower(atom/A)
|
||||
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done.
|
||||
var/mob/living/carbon/target = A
|
||||
var/mob/living/L = owner
|
||||
@@ -118,7 +118,7 @@
|
||||
// 5 second windup
|
||||
addtimer(CALLBACK(src, .proc/apply_effects, L, target, power_time), 6 SECONDS)
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize/proc/apply_effects(aggressor, victim, power_time)
|
||||
/datum/action/cooldown/bloodsucker/targeted/mesmerize/proc/apply_effects(aggressor, victim, power_time)
|
||||
var/mob/living/carbon/target = victim
|
||||
var/mob/living/L = aggressor
|
||||
if(!success)
|
||||
@@ -135,5 +135,5 @@
|
||||
to_chat(L, "<span class='warning'>[target] has snapped out of their trance.</span>")
|
||||
|
||||
|
||||
/datum/action/bloodsucker/targeted/mesmerize/ContinueActive(mob/living/user, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/targeted/mesmerize/ContinueActive(mob/living/user, mob/living/target)
|
||||
return ..() && CheckCanUse() && CheckCanTarget(target)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/datum/action/bloodsucker/vassal/recuperate
|
||||
/datum/action/cooldown/bloodsucker/vassal/recuperate
|
||||
name = "Sanguine Recuperation"
|
||||
desc = "Slowly heal brute damage while active. This process is exhausting, and requires some of your tainted blood."
|
||||
button_icon_state = "power_recup"
|
||||
amToggle = TRUE
|
||||
bloodcost = 5
|
||||
cooldown = 100
|
||||
cooldown_time = 100
|
||||
|
||||
/datum/action/bloodsucker/vassal/recuperate/CheckCanUse(display_error)
|
||||
/datum/action/cooldown/bloodsucker/vassal/recuperate/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -14,7 +14,7 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/vassal/recuperate/ActivatePower()
|
||||
/datum/action/cooldown/bloodsucker/vassal/recuperate/ActivatePower()
|
||||
to_chat(owner, "<span class='notice'>Your muscles clench and your skin crawls as your master's immortal blood knits your wounds and gives you stamina.</span>")
|
||||
var/mob/living/carbon/C = owner
|
||||
var/mob/living/carbon/human/H
|
||||
@@ -35,5 +35,5 @@
|
||||
// DONE!
|
||||
//DeactivatePower(owner)
|
||||
|
||||
/datum/action/bloodsucker/vassal/recuperate/ContinueActive(mob/living/user, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/vassal/recuperate/ContinueActive(mob/living/user, mob/living/target)
|
||||
return ..() && user.stat <= DEAD && user.blood_volume > 500
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
|
||||
/datum/action/bloodsucker/targeted/trespass
|
||||
/datum/action/cooldown/bloodsucker/targeted/trespass
|
||||
name = "Trespass"
|
||||
desc = "Become mist and advance two tiles in one direction, ignoring all obstacles except for walls. Useful for skipping past doors and barricades."
|
||||
button_icon_state = "power_tres"
|
||||
|
||||
bloodcost = 10
|
||||
cooldown = 80
|
||||
cooldown_time = 80
|
||||
amToggle = FALSE
|
||||
//target_range = 2
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
var/turf/target_turf // We need to decide where we're going based on where we clicked. It's not actually the tile we clicked.
|
||||
|
||||
/datum/action/bloodsucker/targeted/trespass/CheckCanUse(display_error)
|
||||
/datum/action/cooldown/bloodsucker/targeted/trespass/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -26,7 +26,7 @@
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/action/bloodsucker/targeted/trespass/CheckValidTarget(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/trespass/CheckValidTarget(atom/A)
|
||||
// Can't target my tile
|
||||
if(A == get_turf(owner) || get_turf(A) == get_turf(owner))
|
||||
return FALSE
|
||||
@@ -34,7 +34,7 @@
|
||||
return TRUE // All we care about is destination. Anything you click is fine.
|
||||
|
||||
|
||||
/datum/action/bloodsucker/targeted/trespass/CheckCanTarget(atom/A, display_error)
|
||||
/datum/action/cooldown/bloodsucker/targeted/trespass/CheckCanTarget(atom/A, display_error)
|
||||
// NOTE: Do NOT use ..()! We don't want to check distance or anything.
|
||||
|
||||
// Get clicked tile
|
||||
@@ -60,7 +60,7 @@
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/action/bloodsucker/targeted/trespass/FireTargetedPower(atom/A)
|
||||
/datum/action/cooldown/bloodsucker/targeted/trespass/FireTargetedPower(atom/A)
|
||||
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done.
|
||||
|
||||
// Find target turf, at or below Atom
|
||||
@@ -87,7 +87,7 @@
|
||||
user.invisibility = INVISIBILITY_MAXIMUM
|
||||
|
||||
// LOSE CUFFS
|
||||
|
||||
|
||||
// Wait...
|
||||
sleep(mist_delay / 2)
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
/datum/action/bloodsucker/veil
|
||||
/datum/action/cooldown/bloodsucker/veil
|
||||
name = "Veil of Many Faces"
|
||||
desc = "Disguise yourself in the illusion of another identity."
|
||||
button_icon_state = "power_veil"
|
||||
bloodcost = 15
|
||||
cooldown = 100
|
||||
cooldown_time = 100
|
||||
amToggle = TRUE
|
||||
bloodsucker_can_buy = TRUE
|
||||
warn_constant_cost = TRUE
|
||||
@@ -29,7 +29,7 @@
|
||||
var/list/prev_features // For lizards and such
|
||||
|
||||
|
||||
/datum/action/bloodsucker/veil/CheckCanUse(display_error)
|
||||
/datum/action/cooldown/bloodsucker/veil/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
@@ -37,7 +37,7 @@
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/action/bloodsucker/veil/ActivatePower()
|
||||
/datum/action/cooldown/bloodsucker/veil/ActivatePower()
|
||||
|
||||
cast_effect() // POOF
|
||||
|
||||
@@ -47,14 +47,14 @@
|
||||
Disguise_FaceName()
|
||||
|
||||
|
||||
/datum/action/bloodsucker/veil/proc/Disguise_Outfit()
|
||||
/datum/action/cooldown/bloodsucker/veil/proc/Disguise_Outfit()
|
||||
|
||||
// Step One: Back up original items
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/action/bloodsucker/veil/proc/Disguise_FaceName()
|
||||
/datum/action/cooldown/bloodsucker/veil/proc/Disguise_FaceName()
|
||||
|
||||
// Change Name/Voice
|
||||
var/mob/living/carbon/human/H = owner
|
||||
@@ -112,7 +112,7 @@
|
||||
sleep(50)
|
||||
|
||||
|
||||
/datum/action/bloodsucker/veil/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
/datum/action/cooldown/bloodsucker/veil/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
..()
|
||||
if (ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
@@ -149,7 +149,7 @@
|
||||
cast_effect() // POOF
|
||||
|
||||
// CAST EFFECT // // General effect (poof, splat, etc) when you cast. Doesn't happen automatically!
|
||||
/datum/action/bloodsucker/veil/proc/cast_effect()
|
||||
/datum/action/cooldown/bloodsucker/veil/proc/cast_effect()
|
||||
// Effect
|
||||
playsound(get_turf(owner), 'sound/magic/smoke.ogg', 20, 1)
|
||||
var/datum/effect_system/steam_spread/puff = new /datum/effect_system/steam_spread/()
|
||||
|
||||
@@ -80,7 +80,6 @@
|
||||
|
||||
/datum/action/innate/cellular_emporium/New(our_target)
|
||||
. = ..()
|
||||
button.name = name
|
||||
if(istype(our_target, /datum/cellular_emporium))
|
||||
cellular_emporium = our_target
|
||||
else
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
name = "Reviving Stasis"
|
||||
desc = "We fall into a stasis, allowing us to regenerate and trick our enemies. Costs 15 chemicals."
|
||||
button_icon_state = "fake_death"
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
chemical_cost = 15
|
||||
to_chat(user, "<span class='notice'>We have revived ourselves.</span>")
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
name = "Revive"
|
||||
desc = "We arise once more."
|
||||
button_icon_state = "revive"
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
chemical_cost = 0
|
||||
revive_ready = TRUE
|
||||
|
||||
|
||||
@@ -411,6 +411,6 @@
|
||||
Q.name = "[quickbind_slot.name] ([Q.scripture_index])"
|
||||
Q.desc = quickbind_slot.quickbind_desc
|
||||
Q.button_icon_state = quickbind_slot.name
|
||||
Q.UpdateButtonIcon()
|
||||
Q.UpdateButtons()
|
||||
if(isliving(loc))
|
||||
Q.Grant(loc)
|
||||
|
||||
@@ -2,16 +2,11 @@
|
||||
name = "Prepare Blood Magic"
|
||||
button_icon_state = "carve"
|
||||
desc = "Prepare blood magic by carving runes into your flesh. This rite is most effective with an <b>empowering rune</b>"
|
||||
default_button_position = DEFAULT_BLOODSPELLS
|
||||
var/list/spells = list()
|
||||
var/channeling = FALSE
|
||||
var/holy_dispel = 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)
|
||||
@@ -23,15 +18,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()
|
||||
if(holy_dispel)
|
||||
@@ -99,6 +100,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)
|
||||
@@ -106,9 +109,7 @@
|
||||
base_desc = desc
|
||||
desc += "<br><b><u>Has [charges] use\s remaining</u></b>."
|
||||
all_magic = BM
|
||||
..()
|
||||
button.locked = TRUE
|
||||
button.ordered = FALSE
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/cult/blood_spell/Remove()
|
||||
if(all_magic)
|
||||
@@ -273,7 +274,7 @@
|
||||
attached_action.charges--
|
||||
attached_action.desc = attached_action.base_desc
|
||||
attached_action.desc += "<br><b><u>Has [attached_action.charges] use\s remaining</u></b>."
|
||||
attached_action.UpdateButtonIcon()
|
||||
attached_action.UpdateButtons()
|
||||
if(attached_action.charges <= 0)
|
||||
remove_ranged_ability("<span class='cult'>You have exhausted the spell's power!</span>")
|
||||
qdel(src)
|
||||
@@ -325,7 +326,7 @@
|
||||
qdel(src)
|
||||
desc = base_desc
|
||||
desc += "<br><b><u>Has [charges] use\s remaining</u></b>."
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/innate/cult/blood_spell/manipulation
|
||||
name = "Blood Rites"
|
||||
@@ -373,7 +374,7 @@
|
||||
source.charges = uses
|
||||
source.desc = source.base_desc
|
||||
source.desc += "<br><b><u>Has [uses] use\s remaining</u></b>."
|
||||
source.UpdateButtonIcon()
|
||||
source.UpdateButtons()
|
||||
..()
|
||||
|
||||
/obj/item/melee/blood_magic/attack_self(mob/living/user)
|
||||
@@ -400,7 +401,7 @@
|
||||
else if(source)
|
||||
source.desc = source.base_desc
|
||||
source.desc += "<br><b><u>Has [uses] use\s remaining</u></b>."
|
||||
source.UpdateButtonIcon()
|
||||
source.UpdateButtons()
|
||||
|
||||
//Stun
|
||||
/obj/item/melee/blood_magic/stun
|
||||
|
||||
@@ -795,14 +795,13 @@
|
||||
desc = "Call the blood spear back to your hand!"
|
||||
background_icon_state = "bg_demon"
|
||||
button_icon_state = "bloodspear"
|
||||
default_button_position = "6:157,4:-2"
|
||||
var/obj/item/cult_spear/spear
|
||||
var/cooldown = 0
|
||||
|
||||
/datum/action/innate/cult/spear/Grant(mob/user, obj/blood_spear)
|
||||
. = ..()
|
||||
spear = blood_spear
|
||||
button.screen_loc = "6:157,4:-2"
|
||||
button.moved = "6:157,4:-2"
|
||||
|
||||
/datum/action/innate/cult/spear/Activate()
|
||||
if(owner == spear.loc || cooldown > world.time)
|
||||
|
||||
@@ -176,7 +176,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.
|
||||
|
||||
@@ -33,9 +33,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
|
||||
/datum/action/innate/ai/New()
|
||||
..()
|
||||
if(uses > 1)
|
||||
desc = "[desc] It has [uses] use\s remaining."
|
||||
button.desc = desc
|
||||
desc = "[desc] It has [uses] use\s remaining."
|
||||
|
||||
/datum/action/innate/ai/Grant(mob/living/L)
|
||||
. = ..()
|
||||
@@ -63,7 +61,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
if(!silent)
|
||||
to_chat(owner, "<span class='notice'>[name] now has <b>[uses]</b> use[uses > 1 ? "s" : ""] remaining.</span>")
|
||||
desc = "[initial(desc)] It has [uses] use\s remaining."
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
return
|
||||
if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
|
||||
to_chat(owner, "<span class='warning'>[name] has run out of uses!</span>")
|
||||
@@ -92,7 +90,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
if(!silent)
|
||||
to_chat(owner, "<span class='notice'>[name] now has <b>[uses]</b> use[uses > 1 ? "s" : ""] remaining.</span>")
|
||||
desc = "[initial(desc)] It has [uses] use\s remaining."
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
return
|
||||
if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
|
||||
to_chat(owner, "<span class='warning'>[name] has run out of uses!</span>")
|
||||
@@ -203,7 +201,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
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()
|
||||
temp = "Additional use[action.uses > 1 ? "s" : ""] added to [action.name]!"
|
||||
processing_time -= AM.cost
|
||||
|
||||
@@ -759,6 +757,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
uses = 3
|
||||
auto_use_uses = FALSE
|
||||
|
||||
/datum/action/innate/ai/blackout/New()
|
||||
..()
|
||||
desc = "[desc] It has [uses] use\s remaining."
|
||||
|
||||
/datum/action/innate/ai/blackout/Activate()
|
||||
for(var/obj/machinery/power/apc/apc in GLOB.apcs_list)
|
||||
if(prob(30 * apc.overload))
|
||||
@@ -768,7 +770,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
to_chat(owner, "<span class='notice'>Overcurrent applied to the powernet.</span>")
|
||||
owner.playsound_local(owner, "sparks", 50, 0)
|
||||
adjust_uses(-1)
|
||||
|
||||
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()
|
||||
|
||||
//Disable Emergency Lights
|
||||
/datum/AI_Module/small/emergency_lights
|
||||
@@ -816,6 +821,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
auto_use_uses = FALSE
|
||||
cooldown_period = 30
|
||||
|
||||
/datum/action/innate/ai/reactivate_cameras/New()
|
||||
..()
|
||||
desc = "[desc] It has [uses] use\s remaining."
|
||||
|
||||
/datum/action/innate/ai/reactivate_cameras/Activate()
|
||||
var/fixed_cameras = 0
|
||||
for(var/V in GLOB.cameranet.cameras)
|
||||
@@ -830,7 +839,10 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
to_chat(owner, "<span class='notice'>Diagnostic complete! Cameras reactivated: <b>[fixed_cameras]</b>. Reactivations remaining: <b>[uses]</b>.</span>")
|
||||
owner.playsound_local(owner, 'sound/items/wirecutter.ogg', 50, 0)
|
||||
adjust_uses(0, TRUE) //Checks the uses remaining
|
||||
|
||||
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/large/upgrade_cameras
|
||||
|
||||
@@ -134,16 +134,19 @@
|
||||
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
|
||||
var/mouseControlObject = 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. Weakref
|
||||
var/datum/weakref/middle_drag_atom_ref
|
||||
|
||||
/// Messages currently seen by this client
|
||||
var/list/seen_messages
|
||||
/// viewsize datum for holding our view size
|
||||
var/datum/viewData/view_size
|
||||
var/datum/view_data/view_size
|
||||
|
||||
/// our current tab
|
||||
var/stat_tab
|
||||
|
||||
@@ -881,11 +881,16 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
click_intercept_time = 0 //Reset and return. Next click should work, but not this one.
|
||||
return
|
||||
click_intercept_time = 0 //Just reset. Let's not keep re-checking forever.
|
||||
var/list/L = params2list(params)
|
||||
var/ab = FALSE
|
||||
var/list/modifiers = params2list(params)
|
||||
|
||||
if(L["drag"])
|
||||
var/dragged = LAZYACCESS(modifiers, DRAG)
|
||||
if(dragged && !LAZYACCESS(modifiers, dragged)) //I don't know what's going on here, but I don't trust it
|
||||
return
|
||||
|
||||
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)
|
||||
if (!holder && !ignore_spam && mcl)
|
||||
var/minute = round(world.time, 600)
|
||||
@@ -901,6 +906,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
clicklimiter[ADMINSWARNED_AT] = minute
|
||||
|
||||
msg += " Administrators have been informed."
|
||||
if (ab)
|
||||
log_game("[key_name(src)] is using the middle click aimbot exploit")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] [ADMIN_KICK(usr)] is using the middle click aimbot exploit</span>")
|
||||
log_click(object, location, control, params, src, "lockout (spam - minute)", TRUE)
|
||||
log_game("[key_name(src)] Has hit the per-minute click limit of [mcl] clicks in a given game minute")
|
||||
message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] Has hit the per-minute click limit of [mcl] clicks in a given game minute")
|
||||
@@ -929,6 +937,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
// so that the visual focus indicator matches reality.
|
||||
winset(src, null, "input.background-color=[COLOR_INPUT_DISABLED]")
|
||||
|
||||
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()
|
||||
|
||||
@@ -65,7 +65,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/screentip_pref = SCREENTIP_PREFERENCE_ENABLED
|
||||
var/screentip_color = "#ffd391"
|
||||
var/screentip_images = TRUE
|
||||
var/buttons_locked = FALSE
|
||||
var/hotkeys = FALSE
|
||||
|
||||
///Runechat preference. If true, certain messages will be displayed on the map, not ust on the chat area. Boolean.
|
||||
@@ -1070,8 +1069,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Runechat message char limit:</b> <a href='?_src_=prefs;preference=max_chat_length;task=input'>[max_chat_length]</a><br>"
|
||||
dat += "<b>See Runechat for non-mobs:</b> <a href='?_src_=prefs;preference=see_chat_non_mob'>[see_chat_non_mob ? "Enabled" : "Disabled"]</a><br>"
|
||||
dat += "<br>"
|
||||
dat += "<b>Action Buttons:</b> <a href='?_src_=prefs;preference=action_buttons'>[(buttons_locked) ? "Locked In Place" : "Unlocked"]</a><br>"
|
||||
dat += "<br>"
|
||||
dat += "<b>PDA Color:</b> <span style='border:1px solid #161616; background-color: [pda_color];'><font color='[color_hex2num(pda_color) < 200 ? "FFFFFF" : "000000"]'>[pda_color]</font></span> <a href='?_src_=prefs;preference=pda_color;task=input'>Change</a><BR>"
|
||||
dat += "<b>PDA Style:</b> <a href='?_src_=prefs;task=input;preference=pda_style'>[pda_style]</a><br>"
|
||||
dat += "<b>PDA Reskin:</b> <a href='?_src_=prefs;task=input;preference=pda_skin'>[pda_skin]</a><br>"
|
||||
@@ -3001,8 +2998,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
chat_on_map = !chat_on_map
|
||||
if("see_chat_non_mob")
|
||||
see_chat_non_mob = !see_chat_non_mob
|
||||
if("action_buttons")
|
||||
buttons_locked = !buttons_locked
|
||||
if("tgui_fancy")
|
||||
tgui_fancy = !tgui_fancy
|
||||
if("outline_enabled")
|
||||
|
||||
@@ -435,7 +435,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["see_chat_non_mob"] >> see_chat_non_mob
|
||||
S["tgui_fancy"] >> tgui_fancy
|
||||
S["tgui_lock"] >> tgui_lock
|
||||
S["buttons_locked"] >> buttons_locked
|
||||
S["windowflash"] >> windowflashing
|
||||
S["be_special"] >> be_special
|
||||
|
||||
@@ -513,7 +512,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
see_chat_non_mob = sanitize_integer(see_chat_non_mob, 0, 1, initial(see_chat_non_mob))
|
||||
tgui_fancy = sanitize_integer(tgui_fancy, 0, 1, initial(tgui_fancy))
|
||||
tgui_lock = sanitize_integer(tgui_lock, 0, 1, initial(tgui_lock))
|
||||
buttons_locked = sanitize_integer(buttons_locked, 0, 1, initial(buttons_locked))
|
||||
windowflashing = sanitize_integer(windowflashing, 0, 1, initial(windowflashing))
|
||||
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
|
||||
toggles = sanitize_integer(toggles, 0, 16777215, initial(toggles))
|
||||
@@ -626,7 +624,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["see_chat_non_mob"], see_chat_non_mob)
|
||||
WRITE_FILE(S["tgui_fancy"], tgui_fancy)
|
||||
WRITE_FILE(S["tgui_lock"], tgui_lock)
|
||||
WRITE_FILE(S["buttons_locked"], buttons_locked)
|
||||
WRITE_FILE(S["windowflash"], windowflashing)
|
||||
WRITE_FILE(S["be_special"], be_special)
|
||||
WRITE_FILE(S["default_slot"], default_slot)
|
||||
|
||||
@@ -162,8 +162,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))
|
||||
@@ -209,7 +209,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)
|
||||
target.name = initial(picked_item.name)
|
||||
@@ -435,9 +435,9 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/head/chameleon)
|
||||
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()
|
||||
|
||||
CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/mask/chameleon)
|
||||
name = "gas mask"
|
||||
@@ -489,9 +489,9 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/mask/chameleon)
|
||||
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 class='notice'>[src] does not have a voice changer.</span>")
|
||||
|
||||
@@ -402,7 +402,7 @@ BLIND // can't see anything
|
||||
C.head_update(src, forced = 1)
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/proc/visor_toggling() //handles all the actual toggling of flags
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
update_icon()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/attack_self(mob/user)
|
||||
toggle_mode(user, TRUE)
|
||||
|
||||
@@ -389,7 +389,7 @@
|
||||
set_light(0)
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
|
||||
/obj/item/clothing/head/helmet/durathread
|
||||
name = "makeshift helmet"
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
user.update_inv_wear_mask()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
to_chat(user, "<span class='notice'>Your Clown Mask has now morphed into [choice], all praise the Honkmother!</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
user.update_inv_wear_mask()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
to_chat(user, "<span class='notice'>Your Mime Mask has now morphed into [choice]!</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
user.update_inv_wear_mask()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
to_chat(M, "The Tiki Mask has now changed into the [choice] Mask!")
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
user.update_inv_wear_mask()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
to_chat(user, "<span class='notice'>Your Joy mask now has a [choice] Emotion!</span>")
|
||||
return 1
|
||||
|
||||
@@ -475,6 +475,6 @@
|
||||
user.update_inv_wear_mask()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
to_chat(user, "<span class='notice'>Your paper mask now has a [choice] symbol!</span>")
|
||||
return 1
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
user.update_gravity(user.has_gravity())
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
|
||||
/obj/item/clothing/shoes/magboots/negates_gravity()
|
||||
return clothing_flags & NOSLIP
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
if(camera)
|
||||
camera.remove_target_ui()
|
||||
camera.forceMove(user)
|
||||
teleport_now.UpdateButtonIcon()
|
||||
teleport_now.UpdateButtons()
|
||||
|
||||
/obj/item/clothing/suit/space/chronos/proc/chronowalk(atom/location)
|
||||
var/mob/living/carbon/human/user = src.loc
|
||||
@@ -105,7 +105,7 @@
|
||||
if(camera)
|
||||
camera.remove_target_ui()
|
||||
|
||||
teleport_now.UpdateButtonIcon()
|
||||
teleport_now.UpdateButtons()
|
||||
|
||||
var/list/nonsafe_slots = list(ITEM_SLOT_BELT, ITEM_SLOT_BACK)
|
||||
var/list/exposed = list()
|
||||
|
||||
@@ -345,7 +345,7 @@
|
||||
C.head_update(src, forced = 1)
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/syndi/proc/toggle_hardsuit_mode(mob/user) //Helmet Toggles Suit Mode
|
||||
if(linkedsuit)
|
||||
@@ -937,7 +937,7 @@
|
||||
set_light(0)
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/lavaknight/update_overlays()
|
||||
. = ..()
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
usr.update_inv_wear_suit()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
|
||||
/obj/item/clothing/suit/toggle/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -85,6 +85,6 @@
|
||||
description = "Immediately examine anything you're hovering your mouse over."
|
||||
|
||||
/datum/keybinding/mob/examine_immediate/down(client/user)
|
||||
var/atom/A = user.mouseObject
|
||||
var/atom/A = WEAKREF(user.mouse_object_ref)
|
||||
if(A)
|
||||
A.attempt_examinate(user.mob)
|
||||
|
||||
@@ -200,7 +200,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()
|
||||
|
||||
/obj/effect/proc_holder/alien/neurotoxin/InterceptClickOn(mob/living/caller, params, atom/target)
|
||||
if(..())
|
||||
@@ -333,7 +333,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 1
|
||||
|
||||
/mob/living/carbon/alien/adjustPlasma(amount)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
to_chat(owner, "There's something stuck to your hand, stopping you from transforming!")
|
||||
return
|
||||
if(IsAvailable())
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
var/mutcolor = owner.get_ability_property(INNATE_ABILITY_SLIME_BLOBFORM, PROPERTY_BLOBFORM_COLOR) || ("#" + H.dna.features["mcolor"])
|
||||
if(!is_puddle)
|
||||
if(CHECK_MOBILITY(H, MOBILITY_USE)) //if we can use items, we can turn into a puddle
|
||||
@@ -78,7 +78,7 @@
|
||||
owner.update_antag_overlays()
|
||||
|
||||
transforming = FALSE
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
else
|
||||
detransform()
|
||||
else
|
||||
@@ -109,4 +109,4 @@
|
||||
squeak.RemoveComponent()
|
||||
H.regenerate_icons()
|
||||
transforming = FALSE
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
@@ -480,9 +480,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
|
||||
sleep(cooldown + 5)
|
||||
UpdateButtonIcon() //action icon looks available again
|
||||
UpdateButtons() //action icon looks unavailable
|
||||
//action icon looks available again
|
||||
addtimer(CALLBACK(src, .proc/UpdateButtons), cooldown + 5)
|
||||
|
||||
|
||||
//honk
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
|
||||
var/datum/action/innate/ability/regrowth = H.ability_actions[INNATE_ABILITY_LIMB_REGROWTH]
|
||||
if(regrowth)
|
||||
regrowth.UpdateButtonIcon()
|
||||
regrowth.UpdateButtons()
|
||||
|
||||
return FALSE // to let living/handle_blood know that the species is handling blood instead
|
||||
|
||||
@@ -472,9 +472,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)
|
||||
@@ -514,7 +514,7 @@
|
||||
name = "Eject Extract"
|
||||
desc = "Eject your current slime extract."
|
||||
|
||||
/datum/action/innate/integrate_extract/UpdateButtonIcon(status_only, force)
|
||||
/datum/action/innate/integrate_extract/UpdateButton(atom/movable/screen/movable/action_button/button, status_only, force)
|
||||
if(!species || !species.current_extract)
|
||||
button_icon_state = "slimeconsume"
|
||||
else
|
||||
|
||||
@@ -636,7 +636,7 @@
|
||||
if(mind)
|
||||
for(var/S in mind.spell_list)
|
||||
var/obj/effect/proc_holder/spell/spell = S
|
||||
spell.updateButtonIcon()
|
||||
spell.UpdateButton()
|
||||
|
||||
//proc used to remove all immobilisation effects + reset stamina
|
||||
/mob/living/proc/remove_CC(should_update_mobility = TRUE)
|
||||
|
||||
@@ -241,7 +241,7 @@
|
||||
// before doing anything, check if the user moused over them properly
|
||||
if(!client)
|
||||
return BLOCK_NONE
|
||||
var/found = attacker == client.mouseObject
|
||||
var/found = attacker == WEAKREF(client.mouse_object_ref)
|
||||
if(!found)
|
||||
for(var/i in client.moused_over_objects)
|
||||
if(i == object)
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
var/can_repair_constructs = FALSE
|
||||
var/can_repair_self = FALSE
|
||||
var/runetype
|
||||
var/datum/action/innate/cult/create_rune/our_rune
|
||||
/// Theme controls color. THEME_CULT is red THEME_WIZARD is purple and THEME_HOLY is blue
|
||||
var/theme = "cult"
|
||||
var/datum/mind/original_mind
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/Initialize(mapload)
|
||||
@@ -51,24 +54,24 @@
|
||||
update_health_hud()
|
||||
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)
|
||||
var/datum/action/innate/cult/create_rune/CR = new runetype(src)
|
||||
CR.Grant(src)
|
||||
var/pos = 2+spellnum*31
|
||||
CR.button.screen_loc = "6:[pos],4:-2"
|
||||
CR.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]")
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/Destroy()
|
||||
original_mind = null
|
||||
QDEL_NULL(our_rune)
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/death()
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
var/datum/action/boss/AB = ab
|
||||
if(!boss.client && (!AB.req_statuses || (boss.AIStatus in AB.req_statuses)) && prob(AB.usage_probability) && AB.Trigger())
|
||||
break
|
||||
AB.UpdateButtonIcon(TRUE)
|
||||
AB.UpdateButtons(TRUE)
|
||||
|
||||
|
||||
/datum/boss_active_timed_battle/Destroy()
|
||||
|
||||
@@ -336,7 +336,7 @@
|
||||
if(L.blood_volume && (L.stat != DEAD || !consumed_mobs[L.tag])) //if they're not dead, you can consume them anyway
|
||||
consumed_mobs[L.tag] = TRUE
|
||||
fed++
|
||||
lay_eggs.UpdateButtonIcon(TRUE)
|
||||
lay_eggs.UpdateButtons(TRUE)
|
||||
visible_message("<span class='danger'>[src] sticks a proboscis into [L] and sucks a viscous substance out.</span>","<span class='notice'>You suck the nutriment out of [L], feeding you enough to lay a cluster of eggs.</span>")
|
||||
L.death() //you just ate them, they're dead.
|
||||
else
|
||||
@@ -402,7 +402,7 @@
|
||||
|
||||
/obj/effect/proc_holder/wrap/update_icon()
|
||||
action.button_icon_state = "wrap_[active]"
|
||||
action.UpdateButtonIcon()
|
||||
action.UpdateButtons()
|
||||
|
||||
/obj/effect/proc_holder/wrap/Trigger(mob/living/simple_animal/hostile/poison/giant_spider/nurse/user)
|
||||
if(!istype(user))
|
||||
@@ -482,7 +482,7 @@
|
||||
C.poison_per_bite = S.poison_per_bite
|
||||
C.faction = S.faction.Copy()
|
||||
S.fed--
|
||||
UpdateButtonIcon(TRUE)
|
||||
UpdateButtons(TRUE)
|
||||
S.busy = SPIDER_IDLE
|
||||
S.stop_automated_movement = FALSE
|
||||
|
||||
|
||||
@@ -72,19 +72,48 @@ While using this makes the system rely on OnFire, it still gives options for tim
|
||||
icon_icon = 'icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = ""
|
||||
background_icon_state = "bg_default"
|
||||
var/mob/living/simple_animal/hostile/asteroid/elite/M
|
||||
var/chosen_message
|
||||
var/chosen_attack_num = 0
|
||||
|
||||
/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 = ""
|
||||
else
|
||||
button.maptext = "<b class='maptext'>[round(timeleft/10, 0.1)]</b>"
|
||||
|
||||
/datum/action/innate/elite_attack/Grant(mob/living/L)
|
||||
if(istype(L, /mob/living/simple_animal/hostile/asteroid/elite))
|
||||
M = L
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
return ..()
|
||||
return FALSE
|
||||
|
||||
/datum/action/innate/elite_attack/Activate()
|
||||
M.chosen_attack = chosen_attack_num
|
||||
to_chat(M, chosen_message)
|
||||
var/mob/living/simple_animal/hostile/asteroid/elite/elite_owner = owner
|
||||
elite_owner.chosen_attack = chosen_attack_num
|
||||
to_chat(elite_owner, chosen_message)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/updatehealth()
|
||||
. = ..()
|
||||
|
||||
@@ -426,7 +426,7 @@
|
||||
for(var/obj/item/I in U.held_items)
|
||||
if(istype(I, /obj/item/turret_control))
|
||||
qdel(I)
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
return
|
||||
else
|
||||
playsound(PE,'sound/mecha/mechmove01.ogg', 50, TRUE)
|
||||
@@ -443,7 +443,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/TC = new /obj/item/turret_control()
|
||||
U.put_in_hands(TC)
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
|
||||
/obj/item/turret_control
|
||||
|
||||
@@ -142,7 +142,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()
|
||||
. = ..()
|
||||
@@ -219,7 +219,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()
|
||||
return TRUE
|
||||
|
||||
/obj/item/gun/equipped(mob/living/user, slot)
|
||||
@@ -670,7 +670,7 @@
|
||||
update_icon()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
A.UpdateButtons()
|
||||
|
||||
/obj/item/gun/update_overlays()
|
||||
. = ..()
|
||||
|
||||
@@ -200,7 +200,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(fire_check() && can_trigger_gun(M))
|
||||
sync_ammo()
|
||||
do_fire(M.client.mouseObject, M, FALSE, M.client.mouseParams, M.zone_selected)
|
||||
var/atom/target = M.client.mouse_object_ref?.resolve()
|
||||
if(target)
|
||||
afterattack(target, M, FALSE, M.client.mouseParams)
|
||||
stop_aiming()
|
||||
QDEL_LIST(current_tracers)
|
||||
return ..()
|
||||
|
||||
@@ -939,12 +939,10 @@
|
||||
var/y = text2num(screen_loc_Y[1]) * 32 + text2num(screen_loc_Y[2]) - 32
|
||||
|
||||
//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 = arctan(y - oy, x - ox)
|
||||
return list(angle, p_x, p_y)
|
||||
|
||||
|
||||
@@ -165,7 +165,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)
|
||||
@@ -243,7 +243,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 += 2 //processes 5 times per second instead of 10.
|
||||
if(charge_counter >= charge_max)
|
||||
action.UpdateButtonIcon()
|
||||
action.UpdateButtons()
|
||||
charge_counter = charge_max
|
||||
recharging = FALSE
|
||||
|
||||
@@ -259,7 +259,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)
|
||||
@@ -321,7 +321,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))
|
||||
@@ -438,8 +438,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/UpdateButton(atom/movable/screen/movable/action_button/button, status_only, force)
|
||||
action.UpdateButtons(status_only, force)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/proc/los_check(mob/A,mob/B)
|
||||
//Checks for obstacles from A to B
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
if(!action)
|
||||
return
|
||||
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(..())
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
action.button_icon_state = "[action_icon_state]1"
|
||||
else
|
||||
action.button_icon_state = "[action_icon_state]"
|
||||
action.UpdateButtonIcon()
|
||||
action.UpdateButtons()
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/InterceptClickOn(mob/living/caller, params, atom/target)
|
||||
if(..())
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
else
|
||||
action.button_icon_state = action_icon_state
|
||||
|
||||
action.UpdateButtonIcon()
|
||||
action.UpdateButtons()
|
||||
return
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -18,7 +18,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))
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
|
||||
user.transferItemToLoc(tool, target, TRUE)
|
||||
|
||||
var/datum/action/item_action/hands_free/activate_pill/P = new(tool)
|
||||
P.button.name = "Activate [tool.name]"
|
||||
P.target = tool
|
||||
P.Grant(target) //The pill never actually goes in an inventory slot, so the owner doesn't inherit actions from it
|
||||
var/datum/action/item_action/hands_free/activate_pill/pill_action = new(tool)
|
||||
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
|
||||
|
||||
user.visible_message("[user] wedges \the [tool] into [target]'s [parse_zone(target_zone)]!", "<span class='notice'>You wedge [tool] into [target]'s [parse_zone(target_zone)].</span>")
|
||||
return 1
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -136,21 +136,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];
|
||||
|
||||
@@ -194,7 +194,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(light_range, light_power, light_color)
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
button_icon_state = "mech_internals_[chassis.use_internal_tank ? "on" : "off"]"
|
||||
to_chat(chassis.occupants, "[icon2html(chassis, owner)]<span class='notice'>Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].</span>")
|
||||
chassis.log_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].", LOG_MECHA)
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/mech_cycle_equip
|
||||
name = "Cycle Equipment"
|
||||
@@ -61,7 +61,7 @@
|
||||
to_chat(owner, "[icon2html(chassis, owner)]<span class='notice'>You select [chassis.selected].</span>")
|
||||
send_byjax(chassis.occupants,"exosuit.browser","eq_list",chassis.get_equipment_list())
|
||||
button_icon_state = "mech_cycle_equip_on"
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
return
|
||||
var/number = 0
|
||||
for(var/equipment in available_equipment)
|
||||
@@ -77,7 +77,7 @@
|
||||
to_chat(owner, "[icon2html(chassis, owner)]<span class='notice'>You switch to [chassis.selected].</span>")
|
||||
button_icon_state = "mech_cycle_equip_on"
|
||||
send_byjax(chassis.occupants,"exosuit.browser","eq_list",chassis.get_equipment_list())
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
return
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
chassis.set_light(0)
|
||||
to_chat(owner, "[icon2html(chassis, owner)]<span class='notice'>Toggled lights [(chassis.mecha_flags & LIGHTS_ON)?"on":"off"].</span>")
|
||||
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"
|
||||
@@ -140,7 +140,7 @@
|
||||
|
||||
for(var/occupant in occupants)
|
||||
var/datum/action/action = LAZYACCESSASSOC(occupant_actions, occupant, /datum/action/vehicle/sealed/mecha/strafe)
|
||||
action?.UpdateButtonIcon()
|
||||
action?.UpdateButtons()
|
||||
|
||||
//////////////////////////////////////// Specific Ability Actions ///////////////////////////////////////////////
|
||||
//Need to be granted by the mech type, Not default abilities.
|
||||
@@ -176,7 +176,7 @@
|
||||
chassis.movedelay = initial(chassis.movedelay)
|
||||
chassis.step_energy_drain = chassis.normal_step_energy_drain
|
||||
to_chat(owner, "[icon2html(chassis, owner)]<span class='notice'>You disable leg actuators overload.</span>")
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/mech_smoke
|
||||
name = "Smoke"
|
||||
@@ -208,7 +208,7 @@
|
||||
SEND_SOUND(owner, sound('sound/mecha/imag_enh.ogg',volume=50))
|
||||
else
|
||||
owner.client.view_size.resetToDefault() //Let's not let this stack shall we?
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
/datum/action/vehicle/sealed/mecha/mech_switch_damtype
|
||||
name = "Reconfigure arm microtool arrays"
|
||||
@@ -231,7 +231,7 @@
|
||||
chassis.damtype = new_damtype
|
||||
button_icon_state = "mech_damtype_[new_damtype]"
|
||||
playsound(chassis, 'sound/mecha/mechmove01.ogg', 50, TRUE)
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
///swap seats, for two person mecha
|
||||
/datum/action/vehicle/sealed/mecha/swap_seat
|
||||
@@ -272,4 +272,4 @@
|
||||
chassis.phasing = !chassis.phasing
|
||||
button_icon_state = "mech_phasing_[chassis.phasing ? "on" : "off"]"
|
||||
to_chat(owner, "[icon2html(chassis, owner)]<font color=\"[chassis.phasing?"#00f\">En":"#f00\">Dis"]abled phasing.</font>")
|
||||
UpdateButtonIcon()
|
||||
UpdateButtons()
|
||||
|
||||
Reference in New Issue
Block a user