Files
Aurora.3/code/_onclick/hud/ability_screen_objects.dm
Fluffy df014f9bc0 Mouse drop refactor (#20256)
Refactored mousedrag procs, added signals, some safeguards, did some
cleanups around, renamed them to make a little more sense. Mostly put in
line with TG's code.
Fast clicking and releasing with a drag, depending on the grace period
and how fast it is done, can be counted as clicks, to aid in combat
scenarios where you spamclick.
2024-12-26 14:26:32 +00:00

347 lines
12 KiB
Plaintext

/atom/movable/screen/movable/ability_master
name = "Abilities"
icon = 'icons/mob/screen_spells.dmi'
icon_state = "grey_spell_ready"
var/list/atom/movable/screen/ability/ability_objects = list()
var/showing = FALSE // If we're 'open' or not.
var/open_state = "master_open" // What the button looks like when it's 'open', showing the other buttons.
var/closed_state = "master_closed" // Button when it's 'closed', hiding everything else.
screen_loc = ui_spell_master // TODO: Rename
var/mob/my_mob // The mob that possesses this hud object.
/atom/movable/screen/movable/ability_master/Initialize(mapload, owner)
. = ..()
if(owner)
my_mob = owner
update_abilities(0, owner)
/atom/movable/screen/movable/ability_master/Destroy()
//Get rid of the ability objects.
remove_all_abilities()
ability_objects.Cut()
// After that, remove ourselves from the mob seeing us, so we can qdel cleanly.
if(my_mob)
my_mob.ability_master = null
if(my_mob.client && my_mob.client.screen)
my_mob.client.screen -= src
my_mob = null
. = ..()
/atom/movable/screen/movable/ability_master/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params)
if(showing)
return
return ..()
/atom/movable/screen/movable/ability_master/Click()
if(!ability_objects.len) // If we're empty for some reason.
return
toggle_open()
/atom/movable/screen/movable/ability_master/proc/toggle_open(var/forced_state = 0, var/mob/user = usr)
if(showing && (forced_state != 2)) // We are closing the ability master, hide the abilities.
for(var/atom/movable/screen/ability/O in ability_objects)
if(my_mob && my_mob.client)
my_mob.client.screen -= O
showing = FALSE
overlays.len = 0
overlays.Add(closed_state)
else if(forced_state != 1) // We're opening it, show the icons.
open_ability_master(user)
update_abilities(1)
showing = TRUE
overlays.len = 0
overlays.Add(open_state)
update_icon()
/atom/movable/screen/movable/ability_master/proc/open_ability_master(var/mob/user = usr)
var/list/screen_loc_xy = splittext(screen_loc,",")
//Create list of X offsets
var/list/screen_loc_X = splittext(screen_loc_xy[1],":")
var/x_position = decode_screen_X(screen_loc_X[1], user)
var/x_pix = screen_loc_X[2]
//Create list of Y offsets
var/list/screen_loc_Y = splittext(screen_loc_xy[2],":")
var/y_position = decode_screen_Y(screen_loc_Y[1], user)
var/y_pix = screen_loc_Y[2]
for(var/i = 1; i <= ability_objects.len; i++)
var/atom/movable/screen/ability/A = ability_objects[i]
var/xpos = x_position + (x_position < 8 ? 1 : -1)*(i%7)
var/ypos = y_position + (y_position < 8 ? round(i/7) : -round(i/7))
A.screen_loc = "[encode_screen_X(xpos, user)]:[x_pix],[encode_screen_Y(ypos, user)]:[y_pix]"
if(my_mob && my_mob.client)
my_mob.client.screen += A
/atom/movable/screen/movable/ability_master/proc/update_abilities(forced = 0, mob/user)
update_icon()
if(user && user.client)
if(!(src in user.client.screen))
user.client.screen += src
var/i = 1
for(var/atom/movable/screen/ability/ability in ability_objects)
ability.update_icon(forced)
ability.index = i
ability.maptext = "[ability.index]" // Slot number
i++
/atom/movable/screen/movable/ability_master/update_icon()
if(ability_objects.len)
set_invisibility(0)
else
set_invisibility(101)
/atom/movable/screen/movable/ability_master/proc/add_ability(var/name_given)
if(!name)
return
var/atom/movable/screen/ability/new_button = new /atom/movable/screen/ability
new_button.ability_master = src
new_button.name = name_given
new_button.ability_icon_state = name_given
new_button.update_icon(1)
ability_objects.Add(new_button)
if(my_mob.client)
toggle_open(2) //forces the icons to refresh on screen
/atom/movable/screen/movable/ability_master/proc/remove_ability(var/atom/movable/screen/ability/ability)
if(!ability)
return
ability_objects.Remove(ability)
qdel(ability)
if(ability_objects.len)
toggle_open(showing + 1)
update_icon()
/atom/movable/screen/movable/ability_master/proc/remove_all_abilities()
for(var/atom/movable/screen/ability/A in ability_objects)
remove_ability(A)
/atom/movable/screen/movable/ability_master/proc/remove_all_psionic_abilities()
for(var/atom/movable/screen/ability/obj_based/psionic/A in ability_objects)
remove_ability(A)
/atom/movable/screen/movable/ability_master/proc/get_ability_by_name(name_to_search)
for(var/atom/movable/screen/ability/A in ability_objects)
if(A.name == name_to_search)
return A
return
/atom/movable/screen/movable/ability_master/proc/get_ability_by_proc_ref(proc_ref)
for(var/atom/movable/screen/ability/verb_based/V in ability_objects)
if(V.verb_to_call == proc_ref)
return V
return
/atom/movable/screen/movable/ability_master/proc/get_ability_by_instance(var/obj/instance/)
for(var/atom/movable/screen/ability/obj_based/O in ability_objects)
if(O.object == instance)
return O
return
///////////ACTUAL ABILITIES////////////
//This is what you click to do things//
///////////////////////////////////////
/atom/movable/screen/ability
icon = 'icons/mob/screen_spells.dmi'
icon_state = "grey_spell_base"
maptext_x = 3
var/background_base_state = "grey"
var/ability_icon_state = null
var/index = 0
var/atom/movable/screen/movable/ability_master/ability_master
/atom/movable/screen/ability/Destroy()
if(ability_master)
ability_master.ability_objects -= src
if(ability_master.my_mob && ability_master.my_mob.client)
ability_master.my_mob.client.screen -= src
if(ability_master && !ability_master.ability_objects.len)
ability_master.update_icon()
ability_master = null
. = ..()
/atom/movable/screen/ability/update_icon()
overlays.Cut()
icon_state = "[background_base_state]_spell_base"
overlays += ability_icon_state
/atom/movable/screen/ability/Click(var/location, var/control, var/params)
if(!usr)
return
var/list/click_params = params2list(params)
if(click_params["shift"])
examine(usr)
return
activate()
/atom/movable/screen/ability/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params)
if(!over || over == src)
return
if(istype(over, /atom/movable/screen/ability))
var/atom/movable/screen/ability/ability = over
if(ability.ability_master && ability.ability_master == src.ability_master)
ability_master.ability_objects.Swap(src.index, ability.index)
ability_master.toggle_open(2) // To update the UI.
// Makes the ability be triggered. The subclasses of this are responsible for carrying it out in whatever way it needs to.
/atom/movable/screen/ability/proc/activate()
LOG_DEBUG("[src] had activate() called.")
// This checks if the ability can be used.
/atom/movable/screen/ability/proc/can_activate()
return TRUE
/client/verb/activate_ability(var/slot as num)
set name = ".activate_ability"
if(!mob)
return // Paranoid.
if(isnull(slot) || !isnum(slot))
to_chat(src, SPAN_WARNING(".activate_ability requires a number as input, corrisponding to the slot you wish to use."))
return // Bad input.
if(!mob.ability_master)
return // No abilities.
if(slot > mob.ability_master.ability_objects.len || slot <= 0)
return // Out of bounds.
var/atom/movable/screen/ability/A = mob.ability_master.ability_objects[slot]
A.activate()
//////////Verb Abilities//////////
//Buttons to trigger verbs/procs//
//////////////////////////////////
/atom/movable/screen/ability/verb_based
var/verb_to_call = null
var/object_used = null
var/arguments_to_use = list()
/atom/movable/screen/ability/verb_based/activate()
if(object_used && verb_to_call)
call(object_used,verb_to_call)(arguments_to_use)
/atom/movable/screen/movable/ability_master/proc/add_verb_ability(var/object_given, var/verb_given, var/name_given, var/ability_icon_given, var/arguments)
if(!object_given)
message_admins("ERROR: add_verb_ability() was not given an object in its arguments.")
if(!verb_given)
message_admins("ERROR: add_verb_ability() was not given a verb/proc in its arguments.")
if(get_ability_by_proc_ref(verb_given))
return // Duplicate
var/atom/movable/screen/ability/verb_based/A = new /atom/movable/screen/ability/verb_based()
A.ability_master = src
A.object_used = object_given
A.verb_to_call = verb_given
A.ability_icon_state = ability_icon_given
A.name = name_given
if(arguments)
A.arguments_to_use = arguments
ability_objects.Add(A)
if(my_mob.client)
toggle_open(2) //forces the icons to refresh on screen
//Changeling Abilities
/atom/movable/screen/ability/verb_based/changeling
icon_state = "ling_spell_base"
background_base_state = "ling"
/atom/movable/screen/movable/ability_master/proc/add_ling_ability(var/object_given, var/verb_given, var/name_given, var/ability_icon_given, var/arguments)
if(!object_given)
message_admins("ERROR: add_ling_ability() was not given an object in its arguments.")
if(!verb_given)
message_admins("ERROR: add_ling_ability() was not given a verb/proc in its arguments.")
if(get_ability_by_proc_ref(verb_given))
return // Duplicate
var/atom/movable/screen/ability/verb_based/changeling/A = new /atom/movable/screen/ability/verb_based/changeling()
A.ability_master = src
A.object_used = object_given
A.verb_to_call = verb_given
A.ability_icon_state = ability_icon_given
A.name = name_given
if(arguments)
A.arguments_to_use = arguments
ability_objects.Add(A)
if(my_mob.client)
toggle_open(2) //forces the icons to refresh on screen
/////////Obj Abilities////////
//Buttons to trigger objects//
//////////////////////////////
/atom/movable/screen/ability/obj_based
var/obj/object
/atom/movable/screen/ability/obj_based/activate()
if(object)
object.Click()
/// Psionics.
/atom/movable/screen/ability/obj_based/psionic
icon_state = "nano_spell_base"
background_base_state = "nano"
var/singleton/psionic_power/connected_power
/atom/movable/screen/ability/obj_based/psionic/Destroy()
connected_power = null
return ..()
/atom/movable/screen/movable/ability_master/proc/add_psionic_ability(var/obj/object_given, var/ability_icon_given, var/singleton/psionic_power/P, var/mob/user)
if(!object_given)
message_admins("ERROR: add_psionic_ability() was not given an object in its arguments.")
if(!P)
message_admins("Psionic ability added without connected psionic power singleton!")
if(get_ability_by_instance(object_given))
return // Duplicate
var/atom/movable/screen/ability/obj_based/psionic/A = new /atom/movable/screen/ability/obj_based/psionic()
A.ability_master = src
A.object = object_given
A.ability_icon_state = ability_icon_given
A.name = object_given.name
A.connected_power = P
ability_objects.Add(A)
if(my_mob.client)
toggle_open(2, user) //forces the icons to refresh on screen
/atom/movable/screen/ability/obj_based/psionic/get_examine_text(mob/user)
. = ..()
. += SPAN_NOTICE("<font size=4>This ability is <b>[connected_power.name]</b>.</font>")
. += SPAN_NOTICE("[connected_power.desc]")
/// Technomancer.
/atom/movable/screen/ability/obj_based/technomancer
icon_state = "wiz_spell_base"
background_base_state = "wiz"
/atom/movable/screen/ability/obj_based/technomancer/activate()
if(ability_master.my_mob.incapacitated())
return
. = ..()
/atom/movable/screen/movable/ability_master/proc/add_technomancer_ability(var/obj/object_given, var/ability_icon_given)
if(!object_given)
message_admins("ERROR: add_technomancer_ability() was not given an object in its arguments.")
if(get_ability_by_instance(object_given))
return // Duplicate
var/atom/movable/screen/ability/obj_based/technomancer/A = new /atom/movable/screen/ability/obj_based/technomancer()
A.ability_master = src
A.object = object_given
A.ability_icon_state = ability_icon_given
A.name = object_given.name
ability_objects.Add(A)
if(my_mob.client)
toggle_open(2) //forces the icons to refresh on screen