Skip to content

Commit

Permalink
Action buttons (TauCetiStation#11551)
Browse files Browse the repository at this point in the history
Co-authored-by: Alexander V. <[email protected]>
  • Loading branch information
Chip11-n and volas authored Aug 26, 2023
1 parent 9b9a8e5 commit 17037f1
Show file tree
Hide file tree
Showing 58 changed files with 550 additions and 233 deletions.
52 changes: 36 additions & 16 deletions code/_onclick/hud/action.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
var/action_type = AB_ITEM
var/atom/movable/target = null
var/check_flags = 0
var/restained_check = ARMS // for AB_CHECK_INCAPACITATED
var/restrained_check = ARMS // for AB_CHECK_INCAPACITATED
var/processing = 0
var/active = 0
var/atom/movable/screen/movable/action_button/button = null
Expand Down Expand Up @@ -62,9 +62,7 @@
return
switch(action_type)
if(AB_ITEM)
if(target)
var/obj/item/item = target
item.ui_action_click()
Activate()
if(AB_SPELL)
if(target)
var/obj/effect/proc_holder/spell = target
Expand All @@ -74,6 +72,13 @@
Activate()
else
Deactivate()
if(!owner)
return
if(button == null)
var/atom/movable/screen/movable/action_button/N = new(owner.hud_used)
N.owner = src.owner
button = N
button.UpdateIcon()
return

/datum/action/proc/Activate()
Expand All @@ -82,9 +87,6 @@
/datum/action/proc/Deactivate()
return

/datum/action/proc/Process()
return

/datum/action/proc/CheckRemoval(mob/user) // TRUE if action is no longer valid for this mob and should be removed
return FALSE

Expand All @@ -104,14 +106,15 @@
/atom/movable/screen/movable/action_button/MouseExited()
closeToolTip(usr)

/datum/action/proc/Checks()// returns 1 if all checks pass
/// returns 1 if all checks pass
/datum/action/proc/Checks()
if(!owner)
return FALSE
if(check_flags & AB_CHECK_INCAPACITATED)
if(owner.incapacitated(restained_check))
if(owner.incapacitated(restrained_check))
return FALSE
if(check_flags & AB_CHECK_LYING)
if(owner.lying && !owner.crawling)
if(owner.lying)
return FALSE
if(check_flags & AB_CHECK_ALIVE)
if(owner.stat != CONSCIOUS)
Expand Down Expand Up @@ -295,20 +298,38 @@

//Presets for item actions
/datum/action/item_action
check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_LYING|AB_CHECK_INSIDE
check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_INSIDE

/datum/action/item_action/Activate()
var/obj/item/I = target
I.attack_self(usr)

/datum/action/item_action/CheckRemoval(mob/living/user)
/datum/action/item_action/IsAvailable()
return TRUE

/datum/action/item_action/CheckRemoval(mob/user)
return !(target in user)

/datum/action/item_action/hands_free
check_flags = AB_CHECK_ALIVE|AB_CHECK_INSIDE
check_flags = AB_CHECK_INCAPACITATED|AB_CHECK_LYING|AB_CHECK_INSIDE|AB_CHECK_ALIVE


//Preset for spells
/datum/action/spell_action
action_type = AB_SPELL
check_flags = 0
background_icon_state = "bg_spell"

/datum/action/spell_action/Grant(mob/T)
. = ..()
if(istype(target, /obj/effect/proc_holder/spell))
var/obj/effect/proc_holder/spell/S = target
if(S.charge_max < 1)
START_PROCESSING(SSaction_buttons, src)

/datum/action/spell_action/process()
UpdateButtonIcon()

/datum/action/spell_action/UpdateName()
var/obj/effect/proc_holder/spell/spell = target
return spell.name
Expand All @@ -320,9 +341,8 @@

if(usr)
return spell.can_cast(usr)
else
if(owner)
return spell.can_cast(owner)
else if(owner)
return spell.can_cast(owner)
return TRUE

/datum/action/spell_action/CheckRemoval()
Expand Down
5 changes: 5 additions & 0 deletions code/controllers/subsystem/action_buttons.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// The subsystem used to tick action buttons.
PROCESSING_SUBSYSTEM_DEF(action_buttons)
name = "Action Buttons"
flags = SS_NO_INIT | SS_BACKGROUND
wait = 2 SECONDS
4 changes: 4 additions & 0 deletions code/datums/datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
A.filters += filter(arglist(arguments))
UNSETEMPTY(filter_data)

/obj/item/update_filters()
. = ..()
update_item_actions()

/datum/proc/transition_filter(name, time, list/new_params, easing, loop)
var/filter = get_filter(name)
if(!filter)
Expand Down
35 changes: 22 additions & 13 deletions code/game/gamemodes/modes_gameplays/abduction/abduction_gear.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@
item_state = "armor"
blood_overlay_type = "armor"
origin_tech = "materials=5;biotech=4;powerstorage=5"
action_button_name = "Activate"
action_button_is_hands_free = 1
item_action_types = list(/datum/action/item_action/hands_free/activate_vest)
var/combat_cooldown = 10
var/datum/icon_snapshot/disguise
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
Expand All @@ -23,7 +22,8 @@
heat_protection = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
armor = list(melee = 50, bullet = 50, laser = 50, energy = 50, bomb = 50, bio = 50, rad = 50)

action_button_name = "Toggle Vest"
/datum/action/item_action/hands_free/activate_vest
name = "Activate Vest"

/obj/item/clothing/suit/armor/abductor/vest/proc/SetDisguise(datum/icon_snapshot/entry)
disguise = entry
Expand Down Expand Up @@ -197,12 +197,13 @@
desc = "Returns you to the mothership."
icon = 'icons/obj/abductor.dmi'
icon_state = "implant"
// activated = 1
item_action_types = list(/datum/action/item_action/hands_free/activate_implant)
var/obj/machinery/abductor/pad/home
var/cooldown = 30 SECONDS

action_button_name = "Activate Implant"
action_button_is_hands_free = 1
/datum/action/item_action/hands_free/activate_implant
name = "Activate Implant"
check_flags = AB_CHECK_INSIDE

/obj/item/weapon/implant/abductor/attack_self()
var/turf/T = get_turf(src)
Expand All @@ -220,7 +221,8 @@
return

/obj/item/weapon/implant/abductor/proc/start_recharge(mob/user = usr)
var/atom/movable/screen/cooldown_overlay/cooldowne = start_cooldown(action.button, initial(cooldown))
var/datum/action/item_action/hands_free/activate_implant/A = locate(/datum/action/item_action/hands_free/activate_implant) in item_actions
var/atom/movable/screen/cooldown_overlay/cooldowne = start_cooldown(A.button, initial(cooldown))
while(cooldown < initial(cooldown))
sleep(1)
cooldown++
Expand All @@ -236,28 +238,30 @@
origin_tech = "materials=6;biotech=4;combat=5"
icon_state = "alienpistol"
item_state = "alienpistol"
ammo_type = list(/obj/item/ammo_casing/energy/declone/light)
item_action_types = null

/obj/item/weapon/gun/energy/decloner/alien/special_check(mob/living/carbon/human/M)
if(M.species.name != ABDUCTOR)
to_chat(M, "<span class='notice'>You can't figure how this works.</span>")
return FALSE
return TRUE

/obj/item/weapon/gun/energy/decloner/alien
ammo_type = list(/obj/item/ammo_casing/energy/declone/light)


//AGENT HELMET
/obj/item/clothing/head/helmet/abductor
name = "agent headgear"
desc = "Abduct with style - spiky style. Prevents digital tracking."
icon_state = "alienhelmet"
item_state = "alienhelmet"
origin_tech = "materials=5;biotech=5"
action_button_name = "Activate Helmet"

var/obj/machinery/camera/helm_cam

item_action_types = list(/datum/action/item_action/hands_free/activate_helmet)

/datum/action/item_action/hands_free/activate_helmet
name = "Activate Helmet"

/obj/item/clothing/head/helmet/abductor/attack_self(mob/living/carbon/human/user)
if(!isabductor(user))
to_chat(user, "<span class='notice'>You can't figure how this works.</span>")
Expand Down Expand Up @@ -286,6 +290,7 @@

helm_cam.hidden = 1
to_chat(user, "<span class='notice'>Abductor detected. Camera activated.</span>")
update_item_actions()
return

/obj/item/clothing/head/helmet/abductor/equipped(mob/living/user, slot)
Expand Down Expand Up @@ -321,8 +326,11 @@
slot_flags = SLOT_FLAGS_BELT
force = 7
w_class = SIZE_SMALL
action_button_name = "Toggle Mode"
var/obj/machinery/abductor/console/console
item_action_types = list(/datum/action/item_action/hands_free/toggle_mode)

/datum/action/item_action/hands_free/toggle_mode
name = "Toggle Mode"

/obj/item/weapon/abductor_baton/proc/toggle(mob/living/user=usr)
if(!isabductor(user))
Expand All @@ -348,6 +356,7 @@
to_chat(user, "<span class='notice'>You switch the baton to [txt] mode.</span>")
update_icon()
update_inv_mob()
update_item_actions()

/obj/item/weapon/abductor_baton/update_icon()
switch(mode)
Expand Down
4 changes: 4 additions & 0 deletions code/game/gamemodes/modes_gameplays/cult/eminence_actions.dm
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@
target = E.tome
button.UpdateIcon()

/datum/action/innate/eminence/tome/Activate()
var/obj/item/I = target
I.attack_self(usr)

//Forbids research to cultists
/datum/action/innate/eminence/forbid_research
name = "Запретить/разрешить исследования"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,15 @@
unacidable = 1
flags = ABSTRACT | DROPDEL
canremove = 0
action_button_name = "Toggle Vision"
icon = 'icons/mob/shadowling_hud.dmi'
icon_state = "ling_vision_off"
flash_protection = FLASHES_AMPLIFIER
flash_protection_slots = list(SLOT_GLASSES)

item_action_types = list(/datum/action/item_action/toggle_vision)

/datum/action/item_action/toggle_vision
name = "Toggle Vision"

/obj/item/clothing/glasses/night/shadowling/attack_self()
toggle()
Expand Down
42 changes: 32 additions & 10 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@
var/max_heat_protection_temperature //Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags
var/min_cold_protection_temperature //Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags

var/datum/action/item_action/action = null
var/action_button_name //It is also the text which gets displayed on the action button. If not set it defaults to 'Use [name]'. If it's not set, there'll be no button.
var/action_button_is_hands_free = 0 //If 1, bypass the restrained, lying, and stunned checks action buttons normally test for
///Actions that item spawns on atom_init(), paths
var/list/item_action_types = list()
///Spawned actions, datums
var/list/item_actions = list()
///Add actions on equip(), otherwise we have a special behavior
var/item_actions_special = FALSE

var/slot_equipped = 0 // Where this item currently equipped in player inventory (slot_id) (should not be manually edited ever).

Expand Down Expand Up @@ -115,6 +118,10 @@
if(item_state_world)
update_world_icon()

for(var/path in item_action_types)
var/datum/action/B = new path (src)
item_actions += B

return INITIALIZE_HINT_NORMAL

/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
Expand All @@ -127,7 +134,8 @@
icon = 'icons/obj/device.dmi'

/obj/item/Destroy()
QDEL_NULL(action)
for(var/datum/action/A in item_actions)
qdel(A)
flags &= ~DROPDEL // prevent recursive dels
if(ismob(loc))
var/mob/m = loc
Expand All @@ -147,6 +155,22 @@
/obj/item/blob_act()
return

///Updates all icons of action buttons associated with this item
/obj/item/proc/update_item_actions()
for(var/datum/action/A as anything in item_actions)
A.button.UpdateIcon()

///Adds action buttons to user associated with this item
/obj/item/proc/add_item_actions(mob/user)
for(var/datum/action/A in item_actions)
A.Grant(user)

///Removes all action buttons from user associated with this item
/obj/item/proc/remove_item_actions(mob/user)
for(var/datum/action/A in item_actions)
if(A.CheckRemoval(user))
A.Remove(user)

//user: The mob that is suiciding
//damagetype: The type of damage the item will inflict on the user
//BRUTELOSS = 1
Expand Down Expand Up @@ -357,6 +381,8 @@
qdel(src)
update_world_icon()
set_alt_apperances_layers()
if(!item_actions_special)
remove_item_actions(user)

// called just as an item is picked up (loc is not yet changed)
/obj/item/proc/pickup(mob/user)
Expand Down Expand Up @@ -396,6 +422,8 @@
SEND_SIGNAL(user, COMSIG_MOB_EQUIPPED, src, slot)
update_world_icon()
set_alt_apperances_layers()
if(!item_actions_special)
add_item_actions(user)

//the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't.
//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen.
Expand Down Expand Up @@ -771,12 +799,6 @@
/obj/item/proc/tool_check_callback(mob/living/user, amount, datum/callback/extra_checks, target)
return tool_use_check(user, amount, target) && (!extra_checks || extra_checks.Invoke())

//This proc is executed when someone clicks the on-screen UI button. To make the UI button show, set the 'icon_action_button' to the icon_state of the image of the button in screen1_action.dmi
//The default action is attack_self().
//Checks before we get to here are: mob is alive, mob is not restrained, paralyzed, asleep, resting, laying, item is on the mob.
/obj/item/proc/ui_action_click()
attack_self(usr)

/obj/item/proc/IsReflect(def_zone, hol_dir, hit_dir) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit
return FALSE

Expand Down
12 changes: 8 additions & 4 deletions code/game/objects/items/devices/PDA/PDA.dm
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,14 @@

var/obj/item/device/paicard/pai = null // A slot for a personal AI device

action_button_name = "Toggle light"
item_action_types = list(/datum/action/item_action/hands_free/toggle_pda_light)

/datum/action/item_action/hands_free/toggle_pda_light
name = "Toggle light"

/datum/action/item_action/hands_free/toggle_pda_light/Activate()
var/obj/item/device/pda/P = target
P.toggle_light()

/obj/item/device/pda/atom_init()
. = ..()
Expand Down Expand Up @@ -123,9 +130,6 @@

return ..()

/obj/item/device/pda/ui_action_click()
toggle_light()

/obj/item/device/pda/verb/toggle_light()
set name = "Toggle light"
set category = "Object"
Expand Down
Loading

0 comments on commit 17037f1

Please sign in to comment.