[MISSED MIRROR] Giant Spider action fixes & Action feedback (#17439)

* missed mirror 70848

* SR modular
This commit is contained in:
Tastyfish
2022-11-11 09:42:28 -05:00
committed by GitHub
parent 69a3ed3d7f
commit 69df5a8320
51 changed files with 237 additions and 175 deletions

View File

@@ -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"

View File

@@ -424,7 +424,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.

View File

@@ -339,6 +339,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
@@ -377,7 +379,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)

View File

@@ -673,8 +673,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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -76,7 +76,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

View File

@@ -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

View File

@@ -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()

View File

@@ -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)

View File

@@ -498,7 +498,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

View File

@@ -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 ..()

View File

@@ -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.<br><b>Warning:</b>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)

View File

@@ -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

View File

@@ -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 ..()

View File

@@ -87,7 +87,7 @@
return ..()
/datum/action/cooldown/track_target/IsAvailable()
/datum/action/cooldown/track_target/IsAvailable(feedback = FALSE)
. = ..()
if(!.)
return

View File

@@ -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()

View File

@@ -142,7 +142,7 @@
return ..()
/datum/action/item_action/rune_shatter/IsAvailable()
/datum/action/item_action/rune_shatter/IsAvailable(feedback = FALSE)
. = ..()
if(!.)
return

View File

@@ -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

View File

@@ -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)

View File

@@ -800,7 +800,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)

View File

@@ -17,7 +17,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
@@ -60,7 +60,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
@@ -134,7 +134,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."))
@@ -175,7 +175,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)
@@ -242,7 +242,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))
@@ -326,7 +326,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]

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
@@ -85,7 +85,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

View File

@@ -549,7 +549,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

View File

@@ -114,7 +114,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
@@ -233,7 +233,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
@@ -594,7 +594,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))
@@ -721,7 +721,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

View File

@@ -430,7 +430,7 @@
. = ..()
wash_audio = new(owner)
/datum/action/toggle_buffer/IsAvailable()
/datum/action/toggle_buffer/IsAvailable(feedback = FALSE)
if(!iscyborg(owner))
return FALSE
return ..()

View File

@@ -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

View File

@@ -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

View File

@@ -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. <B>Left-click your target to start wrapping!</B>"))
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)

View File

@@ -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)

View File

@@ -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(!.)
@@ -437,7 +437,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

View File

@@ -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

View File

@@ -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

View File

@@ -32,7 +32,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))

View File

@@ -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))

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -551,7 +551,7 @@
if(owner)
owner.event_vote()
/datum/action/vote_event/IsAvailable()
/datum/action/vote_event/IsAvailable(feedback = FALSE)
return TRUE
/datum/action/vote_event/proc/remove_from_client()

View File

@@ -896,13 +896,10 @@
return
owner.opposing_force()
/datum/action/opfor/IsAvailable()
/datum/action/opfor/IsAvailable(feedback = FALSE)
if(!target)
return FALSE
. = ..()
if(!.)
return
return TRUE
return ..()
/obj/effect/statclick/opfor_specific
var/datum/opposing_force/opfor

View File

@@ -75,14 +75,17 @@
/// Some xeno abilities block other abilities from being used, this allows them to get around that in cases where it is needed
var/can_be_used_always = FALSE
/datum/action/cooldown/alien/skyrat/IsAvailable()
/datum/action/cooldown/alien/skyrat/IsAvailable(feedback = FALSE)
. = ..()
if(!isalien(owner))
if(!.)
return FALSE
if(can_be_used_always)
return TRUE
var/mob/living/carbon/alien/adult/skyrat/owner_alien = owner
if(!can_be_used_always)
if(owner_alien.unable_to_use_abilities)
return FALSE
if(!istype(owner_alien) || owner_alien.unable_to_use_abilities)
return FALSE
/datum/action/small_sprite/skyrat_xeno
small_icon = 'icons/obj/toys/plushes.dmi'

View File

@@ -45,7 +45,7 @@
)
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
spawn_new_xeno(alien_caste)

View File

@@ -62,14 +62,13 @@
/// What type of damage should the tail sweep do
var/impact_damage_type = BRUTE
/datum/action/cooldown/spell/aoe/repulse/xeno/skyrat_tailsweep/IsAvailable()
/datum/action/cooldown/spell/aoe/repulse/xeno/skyrat_tailsweep/IsAvailable(feedback = FALSE)
. = ..()
if(!isalien(owner))
if(!.)
return FALSE
var/mob/living/carbon/alien/adult/skyrat/owner_alien = owner
if(owner_alien.unable_to_use_abilities)
if(!istype(owner_alien) || owner_alien.unable_to_use_abilities)
return FALSE
/datum/action/cooldown/spell/aoe/repulse/xeno/skyrat_tailsweep/cast_on_thing_in_aoe(atom/movable/victim, atom/caster)

View File

@@ -40,7 +40,7 @@
shared_cooldown = MOB_SHARED_COOLDOWN_3
cooldown_time = 5 SECONDS
/datum/action/cooldown/alien/acid/skyrat/IsAvailable()
/datum/action/cooldown/alien/acid/skyrat/IsAvailable(feedback = FALSE)
return ..() && isturf(owner.loc)
/datum/action/cooldown/alien/acid/skyrat/set_click_ability(mob/on_who)