From 140c12b580757e62fada547a486f06bfdb20c30e Mon Sep 17 00:00:00 2001 From: Jacquerel Date: Sun, 6 Nov 2022 03:09:17 +0000 Subject: [PATCH] Giant Spider action fixes & Action feedback (#70848) I went into this just planning on fixing some weird behaviour with spider buttons and ended up touching a lot of files. Specifically this is because some of the actions used by Giant Spiders would print feedback messages in IsAvailable, which was bad because this is called every time the button updates and so would (for example) print a bunch of messages about eggs existing when you spawned as a broodmother because the lay eggs button would be checking for that when it was granted to you. The feedback _is_ useful though so I've implemented a pattern used in Spell where we just pass a flag describing whether we want to print it or not, which is generally set to true in Trigger() or if the player physically pressed the button. A side effect of this is that any action with usability flags (such as "not when handcuffed") will now tell you why it is failing if you click it while it is unusable, which is nice. The spider changes are largely to make sure that their buttons are tinted at the correct time, they were previously tinted red as if inactive at almost all times due to the icon not being updated when relevant conditions changed. This necessitated adding a new signal (two actually) sent when a do_after begins and when it ends (for any reason, including premature interruption). I also fixed a quirk where the Wrap ability had a permanent 'active' outline after using it once (the icon states were inverted). I also fixed a bug where you could just lay infinite enriched eggs after eating one guy, which is not how the game describes it as working. I looked up the PR adding it (https://github.com/tgstation/tgstation/pull/54451) and one egg per kill seems to be how it is supposed to work. And finally I changed a few nurse spider to_chats into balloon_messages, on the principle that they're not information which needs to stick around for more than a few seconds. --- .../signals/signals_mob/signals_mob_main.dm | 4 + code/__DEFINES/traits.dm | 2 +- code/__HELPERS/mobs.dm | 4 +- code/__HELPERS/roundend.dm | 4 +- code/controllers/subsystem/vote.dm | 2 +- code/datums/actions/action.dm | 21 ++- code/datums/actions/cooldown_action.dm | 4 +- code/datums/actions/innate_action.dm | 2 +- code/datums/actions/items/organ_action.dm | 2 +- code/datums/actions/items/toggles.dm | 2 +- code/datums/actions/items/vortex_recall.dm | 2 +- code/datums/components/mind_linker.dm | 2 +- code/datums/dash_weapon.dm | 14 +- .../antagonists/_common/antag_datum.dm | 2 +- code/modules/antagonists/cult/blood_magic.dm | 4 +- code/modules/antagonists/cult/cult_comms.dm | 18 +- code/modules/antagonists/cult/cult_items.dm | 2 +- .../antagonists/cult/rune_spawn_action.dm | 2 +- .../heretic/heretic_living_heart.dm | 2 +- .../antagonists/heretic/magic/expand_sight.dm | 2 +- .../heretic/structures/carving_knife.dm | 2 +- .../traitor/equipment/Malf_Modules.dm | 2 +- code/modules/clothing/chameleon.dm | 10 +- code/modules/mining/lavaland/tendril_loot.dm | 2 +- .../living/carbon/alien/adult/alien_powers.dm | 12 +- .../living/carbon/alien/adult/caste/drone.dm | 2 +- .../carbon/alien/adult/caste/praetorian.dm | 2 +- .../mob/living/carbon/alien/adult/queen.dm | 2 +- .../mob/living/carbon/alien/larva/powers.dm | 4 +- .../carbon/human/species_types/golems.dm | 2 +- .../carbon/human/species_types/jellypeople.dm | 8 +- .../mob/living/silicon/robot/robot_model.dm | 2 +- .../mob/living/simple_animal/bot/vibebot.dm | 2 +- .../hostile/bosses/paperwizard.dm | 2 +- .../simple_animal/hostile/giant_spider.dm | 175 +++++++++++------- .../hostile/megafauna/colossus.dm | 2 +- .../mob/living/simple_animal/hostile/ooze.dm | 4 +- .../simple_animal/hostile/retaliate/clown.dm | 2 +- .../mob/living/simple_animal/slime/powers.dm | 2 +- code/modules/mod/mod_actions.dm | 2 +- .../xenobiology/crossbreeding/_clothing.dm | 4 +- code/modules/spells/spell.dm | 15 +- .../spells/spell_types/pointed/swap.dm | 2 +- .../spells/spell_types/teleport/teleport.dm | 2 +- code/modules/surgery/organs/vocal_cords.dm | 18 +- 45 files changed, 221 insertions(+), 158 deletions(-) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index f4cda43da86..7779528a974 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -49,6 +49,10 @@ /// from base of /datum/view_data/proc/afterViewChange() : (view) #define COMSIG_VIEWDATA_UPDATE "viewdata_update" +/// Sent from /proc/do_after if someone starts a do_after action bar. +#define COMSIG_DO_AFTER_BEGAN "mob_do_after_began" +/// Sent from /proc/do_after once a do_after action completes, whether via the bar filling or via interruption. +#define COMSIG_DO_AFTER_ENDED "mob_do_after_ended" ///from mind/transfer_to. Sent to the receiving mob. #define COMSIG_MOB_MIND_TRANSFERRED_INTO "mob_mind_transferred_into" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index defcbb25fbd..f6452fb3074 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -422,7 +422,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Whether or not orbiting is blocked or not #define TRAIT_ORBITING_FORBIDDEN "orbiting_forbidden" -/// Whether a spider's consumed this mob +/// Trait applied to mob/living to mark that spiders should not gain further enriched eggs from eating their corpse. #define TRAIT_SPIDER_CONSUMED "spider_consumed" /// Whether we're sneaking, from the alien sneak ability. /// Maybe worth generalizing into a general "is sneaky" / "is stealth" trait in the future. diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 9ebf62be3d4..b2d60995ce7 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -342,6 +342,8 @@ GLOBAL_LIST_EMPTY(species_list) if(progress) progbar = new(user, delay, target || user) + SEND_SIGNAL(user, COMSIG_DO_AFTER_BEGAN) + var/endtime = world.time + delay var/starttime = world.time . = TRUE @@ -380,7 +382,7 @@ GLOBAL_LIST_EMPTY(species_list) if(interaction_key) LAZYREMOVE(user.do_afters, interaction_key) - + SEND_SIGNAL(user, COMSIG_DO_AFTER_ENDED) ///Timed action involving at least one mob user and a list of targets. interaction_key is the assoc key under which the do_after is capped under, and the max interaction count is how many of this interaction you can do at once. /proc/do_after_mob(mob/user, list/targets, time = 3 SECONDS, timed_action_flags = NONE, progress = TRUE, datum/callback/extra_checks, interaction_key, max_interact_count = 1) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index e2997205b48..5182ceee7d5 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -656,8 +656,8 @@ if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED) SSticker.show_roundend_report(owner.client) -/datum/action/report/IsAvailable() - return 1 +/datum/action/report/IsAvailable(feedback = FALSE) + return TRUE /datum/action/report/Topic(href,href_list) if(usr != owner) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 194e4e3e1eb..d3d639f6b29 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -311,7 +311,7 @@ SUBSYSTEM_DEF(vote) name = "Vote!" button_icon_state = "vote" -/datum/action/vote/IsAvailable() +/datum/action/vote/IsAvailable(feedback = FALSE) return TRUE // Democracy is always available to the free people /datum/action/vote/Trigger(trigger_flags) diff --git a/code/datums/actions/action.dm b/code/datums/actions/action.dm index a6b51e17970..e8974d303a3 100644 --- a/code/datums/actions/action.dm +++ b/code/datums/actions/action.dm @@ -123,25 +123,36 @@ /// Actually triggers the effects of the action. /// Called when the on-screen button is clicked, for example. /datum/action/proc/Trigger(trigger_flags) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return FALSE if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER) return FALSE return TRUE -/// Whether our action is currently available to use or not -/datum/action/proc/IsAvailable() +/** + * Whether our action is currently available to use or not + * * feedback - If true this is being called to check if we have any messages to show to the owner + */ +/datum/action/proc/IsAvailable(feedback = FALSE) if(!owner) return FALSE if((check_flags & AB_CHECK_HANDS_BLOCKED) && HAS_TRAIT(owner, TRAIT_HANDS_BLOCKED)) + if (feedback) + owner.balloon_alert(owner, "hands blocked!") return FALSE if((check_flags & AB_CHECK_IMMOBILE) && HAS_TRAIT(owner, TRAIT_IMMOBILIZED)) + if (feedback) + owner.balloon_alert(owner, "can't move!") return FALSE if((check_flags & AB_CHECK_LYING) && isliving(owner)) - var/mob/living/action_user = owner - if(action_user.body_position == LYING_DOWN) + var/mob/living/action_owner = owner + if(action_owner.body_position == LYING_DOWN) + if (feedback) + owner.balloon_alert(owner, "must stand up!") return FALSE if((check_flags & AB_CHECK_CONSCIOUS) && owner.stat != CONSCIOUS) + if (feedback) + owner.balloon_alert(owner, "unconscious!") return FALSE return TRUE diff --git a/code/datums/actions/cooldown_action.dm b/code/datums/actions/cooldown_action.dm index 1005cc4def6..1126ee6e6d0 100644 --- a/code/datums/actions/cooldown_action.dm +++ b/code/datums/actions/cooldown_action.dm @@ -71,7 +71,7 @@ ability.Remove(removed_from) return ..() -/datum/action/cooldown/IsAvailable() +/datum/action/cooldown/IsAvailable(feedback = FALSE) return ..() && (next_use_time <= world.time) /// Initializes any sequence actions @@ -160,7 +160,7 @@ /// Intercepts client owner clicks to activate the ability /datum/action/cooldown/proc/InterceptClickOn(mob/living/caller, params, atom/target) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return FALSE if(!target) return FALSE diff --git a/code/datums/actions/innate_action.dm b/code/datums/actions/innate_action.dm index 422ec8ad56f..08e67678857 100644 --- a/code/datums/actions/innate_action.dm +++ b/code/datums/actions/innate_action.dm @@ -66,7 +66,7 @@ /// Handles whenever a mob clicks on something /datum/action/innate/proc/InterceptClickOn(mob/living/caller, params, atom/clicked_on) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) unset_ranged_ability(caller) return FALSE if(!clicked_on) diff --git a/code/datums/actions/items/organ_action.dm b/code/datums/actions/items/organ_action.dm index 19a8f700373..367c00d656a 100644 --- a/code/datums/actions/items/organ_action.dm +++ b/code/datums/actions/items/organ_action.dm @@ -2,7 +2,7 @@ name = "Organ Action" check_flags = AB_CHECK_CONSCIOUS -/datum/action/item_action/organ_action/IsAvailable() +/datum/action/item_action/organ_action/IsAvailable(feedback = FALSE) var/obj/item/organ/attached_organ = target if(!attached_organ.owner) return FALSE diff --git a/code/datums/actions/items/toggles.dm b/code/datums/actions/items/toggles.dm index 1af240a6b02..92804adedf6 100644 --- a/code/datums/actions/items/toggles.dm +++ b/code/datums/actions/items/toggles.dm @@ -74,7 +74,7 @@ /datum/action/item_action/jetpack_stabilization name = "Toggle Jetpack Stabilization" -/datum/action/item_action/jetpack_stabilization/IsAvailable() +/datum/action/item_action/jetpack_stabilization/IsAvailable(feedback = FALSE) var/obj/item/tank/jetpack/linked_jetpack = target if(!istype(linked_jetpack) || !linked_jetpack.on) return FALSE diff --git a/code/datums/actions/items/vortex_recall.dm b/code/datums/actions/items/vortex_recall.dm index 943da403e7a..625c04a4199 100644 --- a/code/datums/actions/items/vortex_recall.dm +++ b/code/datums/actions/items/vortex_recall.dm @@ -4,7 +4,7 @@ icon_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "vortex_recall" -/datum/action/item_action/vortex_recall/IsAvailable() +/datum/action/item_action/vortex_recall/IsAvailable(feedback = FALSE) var/area/current_area = get_area(target) if(!current_area || current_area.area_flags & NOTELEPORT) return FALSE diff --git a/code/datums/components/mind_linker.dm b/code/datums/components/mind_linker.dm index 6e852f6507a..7e35b73893e 100644 --- a/code/datums/components/mind_linker.dm +++ b/code/datums/components/mind_linker.dm @@ -185,7 +185,7 @@ button_icon_state = linker.speech_action_icon_state background_icon_state = linker.speech_action_background_icon_state -/datum/action/innate/linked_speech/IsAvailable() +/datum/action/innate/linked_speech/IsAvailable(feedback = FALSE) return ..() && (owner.stat != DEAD) /datum/action/innate/linked_speech/Activate() diff --git a/code/datums/dash_weapon.dm b/code/datums/dash_weapon.dm index 71f77908b2e..a156efc17e8 100644 --- a/code/datums/dash_weapon.dm +++ b/code/datums/dash_weapon.dm @@ -23,8 +23,15 @@ /// What effect should we play when we phase out (at the source turf) var/phaseout = /obj/effect/temp_visual/dir_setting/ninja/phase/out -/datum/action/innate/dash/IsAvailable() - return ..() && (current_charges > 0) +/datum/action/innate/dash/IsAvailable(feedback = FALSE) + . = ..() + if (!.) + return FALSE + if (current_charges <= 0) + if (feedback) + owner.balloon_alert(owner, "no charges!") + return FALSE + return TRUE /datum/action/innate/dash/Activate() var/obj/item/dashing_item = target @@ -35,8 +42,7 @@ /// Teleports user to target using do_teleport. Returns TRUE if teleport successful, FALSE otherwise. /datum/action/innate/dash/proc/teleport(mob/user, atom/target) - if(!IsAvailable()) - user.balloon_alert(user, "no charges!") + if(!IsAvailable(feedback = TRUE)) return FALSE var/turf/current_turf = get_turf(user) diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index c2c7f09c322..e692d154e62 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -494,7 +494,7 @@ GLOBAL_LIST_EMPTY(antagonists) target.ui_interact(owner) -/datum/action/antag_info/IsAvailable() +/datum/action/antag_info/IsAvailable(feedback = FALSE) if(!target) stack_trace("[type] was used without a target antag datum!") return FALSE diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 309b70be59f..859f4c9f346 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -11,7 +11,7 @@ qdel(X) ..() -/datum/action/innate/cult/blood_magic/IsAvailable() +/datum/action/innate/cult/blood_magic/IsAvailable(feedback = FALSE) if(!IS_CULTIST(owner)) return FALSE return ..() @@ -117,7 +117,7 @@ hand_magic = null ..() -/datum/action/innate/cult/blood_spell/IsAvailable() +/datum/action/innate/cult/blood_spell/IsAvailable(feedback = FALSE) if(!IS_CULTIST(owner) || owner.incapacitated() || !charges) return FALSE return ..() diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm index 7cc77a0520b..1f9d77a512c 100644 --- a/code/modules/antagonists/cult/cult_comms.dm +++ b/code/modules/antagonists/cult/cult_comms.dm @@ -7,7 +7,7 @@ check_flags = AB_CHECK_HANDS_BLOCKED|AB_CHECK_IMMOBILE|AB_CHECK_CONSCIOUS ranged_mousepointer = 'icons/effects/mouse_pointers/cult_target.dmi' -/datum/action/innate/cult/IsAvailable() +/datum/action/innate/cult/IsAvailable(feedback = FALSE) if(!IS_CULTIST(owner)) return FALSE return ..() @@ -17,14 +17,14 @@ desc = "Whispered words that all cultists can hear.
Warning:Nearby non-cultists can still hear you." button_icon_state = "cult_comms" -/datum/action/innate/cult/comm/IsAvailable() +/datum/action/innate/cult/comm/IsAvailable(feedback = FALSE) if(isshade(owner) && IS_CULTIST(owner)) return TRUE return ..() /datum/action/innate/cult/comm/Activate() var/input = tgui_input_text(usr, "Message to tell to the other acolytes", "Voice of Blood") - if(!input || !IsAvailable()) + if(!input || !IsAvailable(feedback = TRUE)) return var/list/filter_result = CAN_BYPASS_FILTER(usr) ? null : is_ic_filtered(input) @@ -68,7 +68,7 @@ name = "Spiritual Communion" desc = "Conveys a message from the spirit realm that all cultists can hear." -/datum/action/innate/cult/comm/spirit/IsAvailable() +/datum/action/innate/cult/comm/spirit/IsAvailable(feedback = FALSE) if(IS_CULTIST(owner.mind.current)) return TRUE return ..() @@ -89,7 +89,7 @@ name = "Assert Leadership" button_icon_state = "cultvote" -/datum/action/innate/cult/mastervote/IsAvailable() +/datum/action/innate/cult/mastervote/IsAvailable(feedback = FALSE) var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) if(!C || C.cult_team.cult_vote_called || !ishuman(owner)) return FALSE @@ -157,7 +157,7 @@ to_chat(B.current,span_cultlarge("[Nominee] has won the cult's support and is now their master. Follow [Nominee.p_their()] orders to the best of your ability!")) return TRUE -/datum/action/innate/cult/master/IsAvailable() +/datum/action/innate/cult/master/IsAvailable(feedback = FALSE) if(!owner.mind || !owner.mind.has_antag_datum(/datum/antagonist/cult/master) || GLOB.cult_narsie) return FALSE return ..() @@ -246,7 +246,7 @@ /// The actual cooldown tracked of the action COOLDOWN_DECLARE(cult_mark_cooldown) -/datum/action/innate/cult/master/cultmark/IsAvailable() +/datum/action/innate/cult/master/cultmark/IsAvailable(feedback = FALSE) return ..() && COOLDOWN_FINISHED(src, cult_mark_cooldown) /datum/action/innate/cult/master/cultmark/InterceptClickOn(mob/caller, params, atom/clicked_on) @@ -293,7 +293,7 @@ /// The actual cooldown tracked of the action COOLDOWN_DECLARE(cult_mark_cooldown) -/datum/action/innate/cult/ghostmark/IsAvailable() +/datum/action/innate/cult/ghostmark/IsAvailable(feedback = FALSE) return ..() && isobserver(owner) /datum/action/innate/cult/ghostmark/Activate() @@ -372,7 +372,7 @@ /// The actual cooldown tracked of the action COOLDOWN_DECLARE(pulse_cooldown) -/datum/action/innate/cult/master/pulse/IsAvailable() +/datum/action/innate/cult/master/pulse/IsAvailable(feedback = FALSE) return ..() && COOLDOWN_FINISHED(src, pulse_cooldown) /datum/action/innate/cult/master/pulse/InterceptClickOn(mob/living/caller, params, atom/clicked_on) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 1f463daa1ee..0bc37ba5369 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -133,7 +133,7 @@ Striking a noncultist, however, will tear their flesh."} phasein = /obj/effect/temp_visual/dir_setting/cult/phase phaseout = /obj/effect/temp_visual/dir_setting/cult/phase/out -/datum/action/innate/dash/cult/IsAvailable() +/datum/action/innate/dash/cult/IsAvailable(feedback = FALSE) if(IS_CULTIST(owner) && current_charges) return TRUE else diff --git a/code/modules/antagonists/cult/rune_spawn_action.dm b/code/modules/antagonists/cult/rune_spawn_action.dm index fe10b3a8193..de9cdda3570 100644 --- a/code/modules/antagonists/cult/rune_spawn_action.dm +++ b/code/modules/antagonists/cult/rune_spawn_action.dm @@ -14,7 +14,7 @@ var/obj/effect/temp_visual/cult/rune_spawn/rune_center_type var/rune_color -/datum/action/innate/cult/create_rune/IsAvailable() +/datum/action/innate/cult/create_rune/IsAvailable(feedback = FALSE) if(!rune_type || cooldown > world.time) return FALSE return ..() diff --git a/code/modules/antagonists/heretic/heretic_living_heart.dm b/code/modules/antagonists/heretic/heretic_living_heart.dm index df726afa79b..3fa3a40c250 100644 --- a/code/modules/antagonists/heretic/heretic_living_heart.dm +++ b/code/modules/antagonists/heretic/heretic_living_heart.dm @@ -87,7 +87,7 @@ return ..() -/datum/action/cooldown/track_target/IsAvailable() +/datum/action/cooldown/track_target/IsAvailable(feedback = FALSE) . = ..() if(!.) return diff --git a/code/modules/antagonists/heretic/magic/expand_sight.dm b/code/modules/antagonists/heretic/magic/expand_sight.dm index be93270c740..6c2782be276 100644 --- a/code/modules/antagonists/heretic/magic/expand_sight.dm +++ b/code/modules/antagonists/heretic/magic/expand_sight.dm @@ -10,7 +10,7 @@ /// A cooldown for the last time we toggled it, to prevent spam. COOLDOWN_DECLARE(last_toggle) -/datum/action/innate/expand_sight/IsAvailable() +/datum/action/innate/expand_sight/IsAvailable(feedback = FALSE) return ..() && COOLDOWN_FINISHED(src, last_toggle) /datum/action/innate/expand_sight/Activate() diff --git a/code/modules/antagonists/heretic/structures/carving_knife.dm b/code/modules/antagonists/heretic/structures/carving_knife.dm index 2e6a1772314..6c642a97132 100644 --- a/code/modules/antagonists/heretic/structures/carving_knife.dm +++ b/code/modules/antagonists/heretic/structures/carving_knife.dm @@ -142,7 +142,7 @@ return ..() -/datum/action/item_action/rune_shatter/IsAvailable() +/datum/action/item_action/rune_shatter/IsAvailable(feedback = FALSE) . = ..() if(!.) return diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm index 4cac9564a67..e4885c2a57e 100644 --- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm +++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm @@ -65,7 +65,7 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module)) else owner_AI = owner -/datum/action/innate/ai/IsAvailable() +/datum/action/innate/ai/IsAvailable(feedback = FALSE) . = ..() if(owner_AI && owner_AI.malf_cooldown > world.time) return diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index 923513e5550..3447d6be48b 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -6,7 +6,7 @@ button_icon_state = "random" /datum/action/item_action/chameleon/drone/randomise/Trigger(trigger_flags) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return // Damn our lack of abstract interfeces @@ -33,7 +33,7 @@ button_icon_state = "drone_camogear_mask" /datum/action/item_action/chameleon/drone/togglehatmask/Trigger(trigger_flags) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return // No point making the code more complicated if no non-drone @@ -91,12 +91,12 @@ return select_outfit(owner) /datum/action/chameleon_outfit/proc/select_outfit(mob/user) - if(!user || !IsAvailable()) + if(!user || !IsAvailable(feedback = TRUE)) return FALSE var/selected = tgui_input_list(user, "Select outfit to change into", "Chameleon Outfit", outfit_options) if(isnull(selected)) return FALSE - if(!IsAvailable() || QDELETED(src) || QDELETED(user)) + if(!IsAvailable(feedback = TRUE) || QDELETED(src) || QDELETED(user)) return FALSE if(isnull(outfit_options[selected])) return FALSE @@ -244,7 +244,7 @@ atom_target.icon = initial(picked_item.icon) /datum/action/item_action/chameleon/change/Trigger(trigger_flags) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return select_look(owner) diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index 1e444161a72..2fd23748013 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -796,7 +796,7 @@ cooldown_time = 45 SECONDS ranged_mousepointer = 'icons/effects/mouse_pointers/scan_target.dmi' -/datum/action/cooldown/scan/IsAvailable() +/datum/action/cooldown/scan/IsAvailable(feedback = FALSE) return ..() && isliving(owner) /datum/action/cooldown/scan/Activate(atom/scanned) diff --git a/code/modules/mob/living/carbon/alien/adult/alien_powers.dm b/code/modules/mob/living/carbon/alien/adult/alien_powers.dm index eecae4638a9..4f1e711adba 100644 --- a/code/modules/mob/living/carbon/alien/adult/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/adult/alien_powers.dm @@ -18,7 +18,7 @@ Doesn't work on other aliens/AI.*/ /// How much plasma this action uses. var/plasma_cost = 0 -/datum/action/cooldown/alien/IsAvailable() +/datum/action/cooldown/alien/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE @@ -61,7 +61,7 @@ Doesn't work on other aliens/AI.*/ /// The type of structure the action makes on use var/obj/structure/made_structure_type -/datum/action/cooldown/alien/make_structure/IsAvailable() +/datum/action/cooldown/alien/make_structure/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE @@ -135,7 +135,7 @@ Doesn't work on other aliens/AI.*/ return FALSE var/to_whisper = tgui_input_text(owner, title = "Alien Whisper") - if(QDELETED(chosen_recipient) || QDELETED(src) || QDELETED(owner) || !IsAvailable() || !to_whisper) + if(QDELETED(chosen_recipient) || QDELETED(src) || QDELETED(owner) || !IsAvailable(feedback = TRUE) || !to_whisper) return FALSE if(chosen_recipient.can_block_magic(MAGIC_RESISTANCE_MIND, charge_cost = 0)) to_chat(owner, span_warning("As you reach into [chosen_recipient]'s mind, you are stopped by a mental blockage. It seems you've been foiled.")) @@ -176,7 +176,7 @@ Doesn't work on other aliens/AI.*/ return FALSE var/amount = tgui_input_number(owner, "Amount", "Transfer Plasma to [donation_target]", max_value = carbon_owner.getPlasma()) - if(QDELETED(donation_target) || QDELETED(src) || QDELETED(owner) || !IsAvailable() || isnull(amount) || amount <= 0) + if(QDELETED(donation_target) || QDELETED(src) || QDELETED(owner) || !IsAvailable(feedback = TRUE) || isnull(amount) || amount <= 0) return FALSE if(get_dist(owner, donation_target) > 1) @@ -243,7 +243,7 @@ Doesn't work on other aliens/AI.*/ button_icon_state = "alien_neurotoxin_0" plasma_cost = 50 -/datum/action/cooldown/alien/acid/neurotoxin/IsAvailable() +/datum/action/cooldown/alien/acid/neurotoxin/IsAvailable(feedback = FALSE) if(owner.is_muzzled()) return FALSE if(!isturf(owner.loc)) @@ -327,7 +327,7 @@ Doesn't work on other aliens/AI.*/ /datum/action/cooldown/alien/make_structure/resin/Activate(atom/target) var/choice = tgui_input_list(owner, "Select a shape to build", "Resin building", structures) - if(isnull(choice) || QDELETED(src) || QDELETED(owner) || !check_for_duplicate() || !IsAvailable()) + if(isnull(choice) || QDELETED(src) || QDELETED(owner) || !check_for_duplicate() || !IsAvailable(feedback = TRUE)) return FALSE var/obj/structure/choice_path = structures[choice] diff --git a/code/modules/mob/living/carbon/alien/adult/caste/drone.dm b/code/modules/mob/living/carbon/alien/adult/caste/drone.dm index 3d00692b869..1d9404fed4b 100644 --- a/code/modules/mob/living/carbon/alien/adult/caste/drone.dm +++ b/code/modules/mob/living/carbon/alien/adult/caste/drone.dm @@ -22,7 +22,7 @@ button_icon_state = "alien_evolve_drone" plasma_cost = 500 -/datum/action/cooldown/alien/evolve_to_praetorian/IsAvailable() +/datum/action/cooldown/alien/evolve_to_praetorian/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE diff --git a/code/modules/mob/living/carbon/alien/adult/caste/praetorian.dm b/code/modules/mob/living/carbon/alien/adult/caste/praetorian.dm index d8fa91cc61d..df3c9da6618 100644 --- a/code/modules/mob/living/carbon/alien/adult/caste/praetorian.dm +++ b/code/modules/mob/living/carbon/alien/adult/caste/praetorian.dm @@ -29,7 +29,7 @@ button_icon_state = "alien_evolve_praetorian" plasma_cost = 500 -/datum/action/cooldown/alien/evolve_to_queen/IsAvailable() +/datum/action/cooldown/alien/evolve_to_queen/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE diff --git a/code/modules/mob/living/carbon/alien/adult/queen.dm b/code/modules/mob/living/carbon/alien/adult/queen.dm index 8d3cc37eaee..c6fe38ac2a9 100644 --- a/code/modules/mob/living/carbon/alien/adult/queen.dm +++ b/code/modules/mob/living/carbon/alien/adult/queen.dm @@ -97,7 +97,7 @@ .[PANEL_DISPLAY_STATUS] = "PLASMA - [promotion_plasma_cost]" -/datum/action/cooldown/alien/promote/IsAvailable() +/datum/action/cooldown/alien/promote/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE diff --git a/code/modules/mob/living/carbon/alien/larva/powers.dm b/code/modules/mob/living/carbon/alien/larva/powers.dm index 246c47a2bb1..e8b3c0b2e8a 100644 --- a/code/modules/mob/living/carbon/alien/larva/powers.dm +++ b/code/modules/mob/living/carbon/alien/larva/powers.dm @@ -29,7 +29,7 @@ button_icon_state = "alien_evolve_larva" plasma_cost = 0 -/datum/action/cooldown/alien/larva_evolve/IsAvailable() +/datum/action/cooldown/alien/larva_evolve/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE @@ -83,7 +83,7 @@ caste_options["Drone"] = drone var/alien_caste = show_radial_menu(owner, owner, caste_options, radius = 38, require_near = TRUE, tooltips = TRUE) - if(QDELETED(src) || QDELETED(owner) || !IsAvailable() || isnull(alien_caste)) + if(QDELETED(src) || QDELETED(owner) || !IsAvailable(feedback = TRUE) || isnull(alien_caste)) return var/mob/living/carbon/alien/adult/new_xeno diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index ce27d5e11af..b22ecf0799b 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -540,7 +540,7 @@ ///Set to true upon action activation to prevent spamming teleport callbacks while the first is still occurring. var/is_charging = FALSE -/datum/action/innate/unstable_teleport/IsAvailable() +/datum/action/innate/unstable_teleport/IsAvailable(feedback = FALSE) . = ..() if(!.) return diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 0d027704091..1a5d3ed7ef2 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -105,7 +105,7 @@ icon_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" -/datum/action/innate/regenerate_limbs/IsAvailable() +/datum/action/innate/regenerate_limbs/IsAvailable(feedback = FALSE) . = ..() if(!.) return @@ -224,7 +224,7 @@ icon_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" -/datum/action/innate/split_body/IsAvailable() +/datum/action/innate/split_body/IsAvailable(feedback = FALSE) . = ..() if(!.) return @@ -585,7 +585,7 @@ background_icon_state = "bg_alien" var/activation_type = SLIME_ACTIVATE_MINOR -/datum/action/innate/use_extract/IsAvailable() +/datum/action/innate/use_extract/IsAvailable(feedback = FALSE) if(..()) var/datum/species/jelly/luminescent/species = target if(species && species.current_extract && (world.time > species.extract_cooldown)) @@ -712,7 +712,7 @@ stack_trace("[name] ([type]) was instantiated on a non-mind_linker target, this doesn't work.") qdel(src) -/datum/action/innate/link_minds/IsAvailable() +/datum/action/innate/link_minds/IsAvailable(feedback = FALSE) . = ..() if(!.) return diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm index aa37fa950c6..6162d8bbba2 100644 --- a/code/modules/mob/living/silicon/robot/robot_model.dm +++ b/code/modules/mob/living/silicon/robot/robot_model.dm @@ -409,7 +409,7 @@ . = ..() wash_audio = new(owner) -/datum/action/toggle_buffer/IsAvailable() +/datum/action/toggle_buffer/IsAvailable(feedback = FALSE) if(!iscyborg(owner)) return FALSE return ..() diff --git a/code/modules/mob/living/simple_animal/bot/vibebot.dm b/code/modules/mob/living/simple_animal/bot/vibebot.dm index f1769cd9883..59b01b1399a 100644 --- a/code/modules/mob/living/simple_animal/bot/vibebot.dm +++ b/code/modules/mob/living/simple_animal/bot/vibebot.dm @@ -64,7 +64,7 @@ icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "funk" -/datum/action/innate/vibe/IsAvailable() +/datum/action/innate/vibe/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm index c746625110a..75fa33ec49f 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm @@ -47,7 +47,7 @@ ///How many minions we should spawn var/minions_to_summon = 3 -/datum/action/boss/wizard_summon_minions/IsAvailable() +/datum/action/boss/wizard_summon_minions/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index a0738b1deca..1552bf6a318 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -155,13 +155,13 @@ return ..() var/mob/living/simple_animal/hostile/giant_spider/hurt_spider = target if(hurt_spider == src) - to_chat(src, span_warning("You don't have the dexerity to wrap your own wounds.")) + balloon_alert(src, "can't heal yourself!") return if(hurt_spider.health >= hurt_spider.maxHealth) - to_chat(src, span_warning("You can't find any wounds to wrap up.")) + balloon_alert(src, "not hurt!") return if(hurt_spider.stat == DEAD) - to_chat(src, span_warning("You're a nurse, not a miracle worker.")) + balloon_alert(src, "they're dead!") return visible_message( span_notice("[src] begins wrapping the wounds of [hurt_spider]."), @@ -310,25 +310,32 @@ check_flags = AB_CHECK_CONSCIOUS button_icon_state = "lay_web" -/datum/action/innate/spider/lay_web/IsAvailable() +/datum/action/innate/spider/lay_web/Grant(mob/grant_to) + . = ..() + if (!owner) + return + RegisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED), .proc/update_icon_on_signal) + +/datum/action/innate/spider/lay_web/Remove(mob/removed_from) + . = ..() + UnregisterSignal(removed_from, list(COMSIG_MOVABLE_MOVED, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED)) + +/datum/action/innate/spider/lay_web/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE - - if(DOING_INTERACTION(owner, INTERACTION_SPIDER_KEY)) - return FALSE if(!isspider(owner)) return FALSE - + if(DOING_INTERACTION(owner, INTERACTION_SPIDER_KEY)) + return FALSE + if(!isturf(owner.loc)) + return FALSE var/mob/living/simple_animal/hostile/giant_spider/spider = owner var/obj/structure/spider/stickyweb/web = locate() in get_turf(spider) if(web && (!spider.web_sealer || istype(web, /obj/structure/spider/stickyweb/sealed))) - to_chat(owner, span_warning("There's already a web here!")) + if (feedback) + owner.balloon_alert(owner, "already webbed!") return FALSE - - if(!isturf(spider.loc)) - return FALSE - return TRUE /datum/action/innate/spider/lay_web/Activate() @@ -348,19 +355,21 @@ spider.stop_automated_movement = TRUE - if(do_after(spider, 4 SECONDS * spider.web_speed, target = spider_turf)) + if(do_after(spider, 4 SECONDS * spider.web_speed, target = spider_turf, interaction_key = INTERACTION_SPIDER_KEY)) if(spider.loc == spider_turf) if(web) qdel(web) new /obj/structure/spider/stickyweb/sealed(spider_turf) new /obj/structure/spider/stickyweb(spider_turf) + UpdateButtons() spider.stop_automated_movement = FALSE /datum/action/cooldown/wrap name = "Wrap" desc = "Wrap something or someone in a cocoon. If it's a human or similar species, \ - you'll also consume them, allowing you to lay enriched eggs." + you'll also consume them, allowing you to lay enriched eggs. \ + Activate this ability and then click on an adjacent target to begin wrapping them." background_icon_state = "bg_alien" icon_icon = 'icons/mob/actions/actions_animal.dmi' button_icon_state = "wrap_0" @@ -370,7 +379,17 @@ /// The time it takes to wrap something. var/wrap_time = 5 SECONDS -/datum/action/cooldown/wrap/IsAvailable() +/datum/action/cooldown/wrap/Grant(mob/grant_to) + . = ..() + if (!owner) + return + RegisterSignal(owner, list(COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED), .proc/update_icon_on_signal) + +/datum/action/cooldown/wrap/Remove(mob/removed_from) + . = ..() + UnregisterSignal(removed_from, list(COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED)) + +/datum/action/cooldown/wrap/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE @@ -385,8 +404,8 @@ if(!.) return - to_chat(on_who, span_notice("You prepare to wrap something in a cocoon. Left-click your target to start wrapping!")) - button_icon_state = "wrap_0" + on_who.balloon_alert(on_who, "prepared to wrap") + button_icon_state = "wrap_1" UpdateButtons() /datum/action/cooldown/wrap/unset_click_ability(mob/on_who, refund_cooldown = TRUE) @@ -394,9 +413,9 @@ if(!.) return - if(refund_cooldown) - to_chat(on_who, span_notice("You no longer prepare to wrap something in a cocoon.")) - button_icon_state = "wrap_1" + if (refund_cooldown) + on_who.balloon_alert(on_who, "wrap cancelled") + button_icon_state = "wrap_0" UpdateButtons() /datum/action/cooldown/wrap/Activate(atom/to_wrap) @@ -433,30 +452,34 @@ animal_owner.stop_automated_movement = TRUE if(do_after(owner, wrap_time, target = to_wrap, interaction_key = INTERACTION_SPIDER_KEY)) - var/obj/structure/spider/cocoon/casing = new(to_wrap.loc) - if(isliving(to_wrap)) - var/mob/living/living_wrapped = to_wrap - // if they're not dead, you can consume them anyway - if(ishuman(living_wrapped) && (living_wrapped.stat != DEAD || !HAS_TRAIT(living_wrapped, TRAIT_SPIDER_CONSUMED))) - var/datum/action/innate/spider/lay_eggs/enriched/egg_power = locate() in owner.actions - if(egg_power) - egg_power.charges++ - egg_power.UpdateButtons() - owner.visible_message( - span_danger("[owner] sticks a proboscis into [living_wrapped] and sucks a viscous substance out."), - span_notice("You suck the nutriment out of [living_wrapped], feeding you enough to lay a cluster of enriched eggs."), - ) - - living_wrapped.death() //you just ate them, they're dead. - else - to_chat(owner, span_warning("[living_wrapped] cannot sate your hunger!")) - - to_wrap.forceMove(casing) - if(to_wrap.density || ismob(to_wrap)) - casing.icon_state = pick("cocoon_large1", "cocoon_large2", "cocoon_large3") - + wrap_target(to_wrap) if(istype(animal_owner)) - animal_owner.stop_automated_movement = TRUE + animal_owner.stop_automated_movement = FALSE + +/datum/action/cooldown/wrap/proc/wrap_target(atom/movable/to_wrap) + var/obj/structure/spider/cocoon/casing = new(to_wrap.loc) + if(isliving(to_wrap)) + var/mob/living/living_wrapped = to_wrap + // You get a point every time you consume a living player, even if they've been consumed before. + // You only get a point for any individual corpse once, so you can't keep breaking it out and eating it again. + if(ishuman(living_wrapped) && (living_wrapped.stat != DEAD || !HAS_TRAIT(living_wrapped, TRAIT_SPIDER_CONSUMED))) + var/datum/action/innate/spider/lay_eggs/enriched/egg_power = locate() in owner.actions + if(egg_power) + egg_power.charges++ + egg_power.UpdateButtons() + owner.visible_message( + span_danger("[owner] sticks a proboscis into [living_wrapped] and sucks a viscous substance out."), + span_notice("You suck the nutriment out of [living_wrapped], feeding you enough to lay a cluster of enriched eggs."), + ) + ADD_TRAIT(living_wrapped, TRAIT_SPIDER_CONSUMED, TRAIT_GENERIC) + living_wrapped.death() //you just ate them, they're dead. + log_combat(owner, living_wrapped, "spider cocooned") + else + to_chat(owner, span_warning("[living_wrapped] is not edible!")) + + to_wrap.forceMove(casing) + if(to_wrap.density || ismob(to_wrap)) + casing.icon_state = pick("cocoon_large1", "cocoon_large2", "cocoon_large3") /datum/action/innate/spider/lay_eggs name = "Lay Eggs" @@ -468,24 +491,32 @@ ///The type of egg we create var/egg_type = /obj/effect/mob_spawn/ghost_role/spider -/datum/action/innate/spider/lay_eggs/IsAvailable() +/datum/action/innate/spider/lay_eggs/Grant(mob/grant_to) + . = ..() + if (!owner) + return + RegisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED), .proc/update_icon_on_signal) + +/datum/action/innate/spider/lay_eggs/Remove(mob/removed_from) + . = ..() + UnregisterSignal(removed_from, list(COMSIG_MOVABLE_MOVED, COMSIG_DO_AFTER_BEGAN, COMSIG_DO_AFTER_ENDED)) + +/datum/action/innate/spider/lay_eggs/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE - if(!isspider(owner)) return FALSE - var/obj/structure/spider/eggcluster/eggs = locate() in get_turf(owner) - if(eggs) - to_chat(owner, span_warning("There is already a cluster of eggs here!")) - return FALSE if(DOING_INTERACTION(owner, INTERACTION_SPIDER_KEY)) return FALSE - + var/obj/structure/spider/eggcluster/eggs = locate() in get_turf(owner) + if(eggs) + if (feedback) + owner.balloon_alert(owner, "already eggs here!") + return FALSE return TRUE /datum/action/innate/spider/lay_eggs/Activate() - owner.visible_message( span_notice("[owner] begins to lay a cluster of eggs."), span_notice("You begin to lay a cluster of eggs."), @@ -496,14 +527,19 @@ if(do_after(owner, egg_lay_time, target = get_turf(owner), interaction_key = INTERACTION_SPIDER_KEY)) var/obj/structure/spider/eggcluster/eggs = locate() in get_turf(owner) - if(!eggs || !isturf(spider.loc)) - var/obj/effect/mob_spawn/ghost_role/spider/new_eggs = new egg_type(get_turf(spider)) - new_eggs.directive = spider.directive - new_eggs.faction = spider.faction - UpdateButtons(TRUE) - + if(eggs) + owner.balloon_alert(owner, "already eggs here!") + else + lay_egg() + UpdateButtons(TRUE) spider.stop_automated_movement = FALSE +/datum/action/innate/spider/lay_eggs/proc/lay_egg() + var/mob/living/simple_animal/hostile/giant_spider/spider = owner + var/obj/effect/mob_spawn/ghost_role/spider/new_eggs = new egg_type(get_turf(owner)) + new_eggs.directive = spider.directive + new_eggs.faction = spider.faction + /datum/action/innate/spider/lay_eggs/enriched name = "Lay Enriched Eggs" desc = "Lay a cluster of eggs, which will soon grow into a greater spider. Requires you drain a human per cluster of these eggs." @@ -512,8 +548,19 @@ /// How many charges we have to make eggs var/charges = 0 -/datum/action/innate/spider/lay_eggs/enriched/IsAvailable() - return ..() && (charges > 0) +/datum/action/innate/spider/lay_eggs/enriched/IsAvailable(feedback = FALSE) + . = ..() + if (!.) + return FALSE + if (charges <= 0) + if (feedback) + owner.balloon_alert(owner, "must feed first!") + return FALSE + return TRUE + +/datum/action/innate/spider/lay_eggs/enriched/lay_egg() + charges-- + return ..() /datum/action/innate/spider/set_directive name = "Set Directive" @@ -521,14 +568,14 @@ check_flags = AB_CHECK_CONSCIOUS button_icon_state = "directive" -/datum/action/innate/spider/set_directive/IsAvailable() +/datum/action/innate/spider/set_directive/IsAvailable(feedback = FALSE) return ..() && isspider(owner) /datum/action/innate/spider/set_directive/Activate() var/mob/living/simple_animal/hostile/giant_spider/spider = owner spider.directive = tgui_input_text(spider, "Enter the new directive", "Create directive", "[spider.directive]") - if(isnull(spider.directive) || QDELETED(src) || QDELETED(owner) || !IsAvailable()) + if(isnull(spider.directive) || QDELETED(src) || QDELETED(owner) || !IsAvailable(feedback = TRUE)) return FALSE message_admins("[ADMIN_LOOKUPFLW(owner)] set its directive to: '[spider.directive]'.") @@ -541,12 +588,12 @@ check_flags = AB_CHECK_CONSCIOUS button_icon_state = "command" -/datum/action/innate/spider/comm/IsAvailable() +/datum/action/innate/spider/comm/IsAvailable(feedback = FALSE) return ..() && istype(owner, /mob/living/simple_animal/hostile/giant_spider/midwife) /datum/action/innate/spider/comm/Trigger(trigger_flags) var/input = tgui_input_text(owner, "Input a command for your legions to follow.", "Command") - if(!input || QDELETED(src) || QDELETED(owner) || !IsAvailable()) + if(!input || QDELETED(src) || QDELETED(owner) || !IsAvailable(feedback = TRUE)) return FALSE spider_command(owner, input) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 01a58badbc2..fbf51441f16 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -616,7 +616,7 @@ icon_icon = 'icons/mob/actions/actions_spells.dmi' button_icon_state = "exit_possession" -/datum/action/exit_possession/IsAvailable() +/datum/action/exit_possession/IsAvailable(feedback = FALSE) return ..() && isfloorturf(owner.loc) /datum/action/exit_possession/Trigger(trigger_flags) diff --git a/code/modules/mob/living/simple_animal/hostile/ooze.dm b/code/modules/mob/living/simple_animal/hostile/ooze.dm index fdc5caf11c5..d0c139e2332 100644 --- a/code/modules/mob/living/simple_animal/hostile/ooze.dm +++ b/code/modules/mob/living/simple_animal/hostile/ooze.dm @@ -145,7 +145,7 @@ ///Mob needs to have enough nutrition -/datum/action/cooldown/metabolicboost/IsAvailable() +/datum/action/cooldown/metabolicboost/IsAvailable(feedback = FALSE) . = ..() var/mob/living/simple_animal/hostile/ooze/ooze = owner if(!.) @@ -435,7 +435,7 @@ ooze.adjust_ooze_nutrition(-30) ///Mob needs to have enough nutrition -/datum/action/cooldown/gel_cocoon/IsAvailable() +/datum/action/cooldown/gel_cocoon/IsAvailable(feedback = FALSE) . = ..() if(!.) return diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm index 336f052d7ce..35dfdc169c7 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm @@ -500,7 +500,7 @@ on_who.icon_state = initial(on_who.icon_state) on_who.update_appearance(UPDATE_ICON) -/datum/action/cooldown/regurgitate/IsAvailable() +/datum/action/cooldown/regurgitate/IsAvailable(feedback = FALSE) . = ..() if(!.) return FALSE diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm index 7c509530e2b..cbf17702b43 100644 --- a/code/modules/mob/living/simple_animal/slime/powers.dm +++ b/code/modules/mob/living/simple_animal/slime/powers.dm @@ -11,7 +11,7 @@ background_icon_state = "bg_alien" var/needs_growth = NO_GROWTH_NEEDED -/datum/action/innate/slime/IsAvailable() +/datum/action/innate/slime/IsAvailable(feedback = FALSE) . = ..() if(!.) return diff --git a/code/modules/mod/mod_actions.dm b/code/modules/mod/mod_actions.dm index a0890ffafe1..01ab9d56e25 100644 --- a/code/modules/mod/mod_actions.dm +++ b/code/modules/mod/mod_actions.dm @@ -30,7 +30,7 @@ return ..() /datum/action/item_action/mod/Trigger(trigger_flags) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return FALSE var/obj/item/mod/control/mod = target if(mod.malfunctioning && prob(75)) diff --git a/code/modules/research/xenobiology/crossbreeding/_clothing.dm b/code/modules/research/xenobiology/crossbreeding/_clothing.dm index 69c9097b3b4..76fca921f12 100644 --- a/code/modules/research/xenobiology/crossbreeding/_clothing.dm +++ b/code/modules/research/xenobiology/crossbreeding/_clothing.dm @@ -65,7 +65,7 @@ Slimecrossing Armor button_icon_state = "prismcolor" /datum/action/item_action/change_prism_colour/Trigger(trigger_flags) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return var/obj/item/clothing/glasses/prism_glasses/glasses = target var/new_color = input(owner, "Choose the lens color:", "Color change",glasses.glasses_color) as color|null @@ -79,7 +79,7 @@ Slimecrossing Armor button_icon_state = "lightprism" /datum/action/item_action/place_light_prism/Trigger(trigger_flags) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return var/obj/item/clothing/glasses/prism_glasses/glasses = target if(locate(/obj/structure/light_prism) in get_turf(owner)) diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index eea91cb3e63..b3f18fc1313 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -123,19 +123,8 @@ return ..() -/datum/action/cooldown/spell/IsAvailable() - return ..() && can_cast_spell(feedback = FALSE) - -/datum/action/cooldown/spell/Trigger(trigger_flags, atom/target) - // We implement this can_cast_spell check before the parent call of Trigger() - // to allow people to click unavailable abilities to get a feedback chat message - // about why the ability is unavailable. - // It is otherwise redundant, however, as IsAvailable() checks can_cast_spell as well. - if(!can_cast_spell()) - UpdateButtons(TRUE) - return FALSE - - return ..() +/datum/action/cooldown/spell/IsAvailable(feedback = FALSE) + return ..() && can_cast_spell(feedback) /datum/action/cooldown/spell/set_click_ability(mob/on_who) if(SEND_SIGNAL(on_who, COMSIG_MOB_SPELL_ACTIVATED, src) & SPELL_CANCEL_CAST) diff --git a/code/modules/spells/spell_types/pointed/swap.dm b/code/modules/spells/spell_types/pointed/swap.dm index 8d9c7fb058d..65344df99a6 100644 --- a/code/modules/spells/spell_types/pointed/swap.dm +++ b/code/modules/spells/spell_types/pointed/swap.dm @@ -31,7 +31,7 @@ /datum/action/cooldown/spell/pointed/swap/InterceptClickOn(mob/living/caller, params, atom/click_target) if(LAZYACCESS(params2list(params), RIGHT_CLICK)) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return FALSE if(!target) return FALSE diff --git a/code/modules/spells/spell_types/teleport/teleport.dm b/code/modules/spells/spell_types/teleport/teleport.dm index a6ce6d1b9a5..1dfcf6f2608 100644 --- a/code/modules/spells/spell_types/teleport/teleport.dm +++ b/code/modules/spells/spell_types/teleport/teleport.dm @@ -38,7 +38,7 @@ invocation_says_area = FALSE -/datum/action/cooldown/spell/teleport/area_teleport/wizard/scroll/IsAvailable() +/datum/action/cooldown/spell/teleport/area_teleport/wizard/scroll/IsAvailable(feedback = FALSE) return ..() && owner.is_holding(target) /datum/action/cooldown/spell/teleport/area_teleport/wizard/scroll/before_cast(atom/cast_on) diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index ffef66ef99c..58b32075c14 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -33,7 +33,7 @@ icon_state = "adamantine_cords" /datum/action/item_action/organ_action/use/adamantine_vocal_cords/Trigger(trigger_flags) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return var/message = tgui_input_text(owner, "Resonate a message to all nearby golems", "Resonate") if(!message) @@ -72,25 +72,29 @@ ..() cords = target -/datum/action/item_action/organ_action/colossus/IsAvailable() - if(world.time < cords.next_command) - return FALSE +/datum/action/item_action/organ_action/colossus/IsAvailable(feedback = FALSE) if(!owner) return FALSE + if(world.time < cords.next_command) + if (feedback) + owner.balloon_alert(owner, "wait [DisplayTimeText(cords.next_command - world.time)]!") + return FALSE if(isliving(owner)) var/mob/living/living = owner if(!living.can_speak()) + if (feedback) + owner.balloon_alert(owner, "can't speak!") return FALSE if(check_flags & AB_CHECK_CONSCIOUS) if(owner.stat) + if (feedback) + owner.balloon_alert(owner, "unconscious!") return FALSE return TRUE /datum/action/item_action/organ_action/colossus/Trigger(trigger_flags) . = ..() - if(!IsAvailable()) - if(world.time < cords.next_command) - to_chat(owner, span_notice("You must wait [DisplayTimeText(cords.next_command - world.time)] before Speaking again.")) + if(!.) return var/command = tgui_input_text(owner, "Speak with the Voice of God", "Command") if(!command)