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)