diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index 6d609299a05..94c8c461997 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -12,8 +12,13 @@ var/ordered = TRUE //If the button gets placed into the default bar /atom/movable/screen/movable/action_button/proc/can_use(mob/user) - if (linked_action) - return linked_action.owner == user + if(linked_action) + if(linked_action.owner == user) + return TRUE + for(var/datum/weakref/reference as anything in linked_action.sharers) + if(IS_WEAKREF_OF(user, reference)) + return TRUE + return FALSE else if (isobserver(user)) var/mob/dead/observer/O = user return !O.observetarget diff --git a/code/datums/action.dm b/code/datums/action.dm index 542f64efee9..ac9bdda9707 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -19,6 +19,8 @@ var/icon_icon = 'icons/hud/actions.dmi' //This is the file for the ACTION icon var/button_icon_state = "default" //And this is the state for the action icon var/mob/owner + ///All mobs that are sharing our action button. + var/list/sharers = list() /datum/action/New(Target) link_to(Target) @@ -78,6 +80,12 @@ Remove(owner) /datum/action/proc/Remove(mob/M) + for(var/datum/weakref/reference as anything in sharers) + var/mob/freeloader = reference.resolve() + if(!freeloader) + continue + Unshare(freeloader) + sharers = null if(M) if(M.client) M.client.screen -= button @@ -149,6 +157,25 @@ SIGNAL_HANDLER UpdateButtonIcon() +//Adds our action button to the screen of another player +/datum/action/proc/Share(mob/freeloader) + if(!freeloader.client) + return + sharers += WEAKREF(freeloader) + freeloader.client.screen += button + freeloader.update_action_buttons() + +//Removes our action button from the screen of another player +/datum/action/proc/Unshare(mob/freeloader) + if(!freeloader.client) + return + for(var/freeloader_reference in sharers) + if(IS_WEAKREF_OF(freeloader, freeloader_reference)) + sharers -= freeloader_reference + break + freeloader.client.screen -= button + freeloader.update_action_buttons() + //Presets for item actions /datum/action/item_action check_flags = AB_CHECK_HANDS_BLOCKED|AB_CHECK_CONSCIOUS @@ -672,6 +699,27 @@ if(next_use_time > world.time) START_PROCESSING(SSfastprocess, src) +///Like a cooldown action, but with an associated proc holder. +/datum/action/cooldown/spell_like + +/datum/action/cooldown/spell_like/New(Target) + ..() + var/obj/effect/proc_holder/our_proc_holder = target + our_proc_holder.action = src + name = our_proc_holder.name + desc = our_proc_holder.desc + icon_icon = our_proc_holder.action_icon + button_icon_state = our_proc_holder.action_icon_state + background_icon_state = our_proc_holder.action_background_icon_state + button.name = name + +/datum/action/cooldown/spell_like/Trigger() + if(!..()) + return FALSE + if(target) + var/obj/effect/proc_holder/our_proc_holder = target + our_proc_holder.Click() + return TRUE //Stickmemes /datum/action/item_action/stickmen diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index eb35cc9a7ec..a5ae08ce68c 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -5,6 +5,7 @@ var/can_be_driven = TRUE /// If TRUE, this creature's abilities can be triggered by the rider while mounted var/can_use_abilities = FALSE + var/list/shared_action_buttons = list() /datum/component/riding/creature/Initialize(mob/living/riding_mob, force = FALSE, ride_check_flags = NONE, potion_boost = FALSE) if(!isliving(parent)) @@ -129,24 +130,32 @@ force_dismount(yeet_mob, (!user.combat_mode)) // gentle on help, byeeee if not /// If the ridden creature has abilities, and some var yet to be made is set to TRUE, the rider will be able to control those abilities -/datum/component/riding/creature/proc/setup_abilities(mob/living/M) - var/mob/living/ridden_creature = parent - - for(var/i in ridden_creature.abilities) - var/obj/effect/proc_holder/proc_holder = i - M.AddAbility(proc_holder) - -/// Takes away the riding parent's abilities from the rider -/datum/component/riding/creature/proc/remove_abilities(mob/living/M) +/datum/component/riding/creature/proc/setup_abilities(mob/living/rider) if(!istype(parent, /mob/living)) return var/mob/living/ridden_creature = parent - for(var/i in ridden_creature.abilities) - var/obj/effect/proc_holder/proc_holder = i - M.RemoveAbility(proc_holder) + for(var/ability in ridden_creature.abilities) + var/obj/effect/proc_holder/proc_holder = ability + if(!proc_holder.action) + return + proc_holder.action.Share(rider) +/// Takes away the riding parent's abilities from the rider +/datum/component/riding/creature/proc/remove_abilities(mob/living/rider) + if(!istype(parent, /mob/living)) + return + + var/mob/living/ridden_creature = parent + + for(var/ability in ridden_creature.abilities) + var/obj/effect/proc_holder/proc_holder = ability + if(!proc_holder.action) + return + if(rider == proc_holder.ranged_ability_user) + proc_holder.remove_ranged_ability() + proc_holder.action.Unshare(rider) ///////Yes, I said humans. No, this won't end well...////////// /datum/component/riding/creature/human diff --git a/code/modules/mob/living/simple_animal/hostile/vatbeast.dm b/code/modules/mob/living/simple_animal/hostile/vatbeast.dm index b7a7773bbaa..79b3b9ed172 100644 --- a/code/modules/mob/living/simple_animal/hostile/vatbeast.dm +++ b/code/modules/mob/living/simple_animal/hostile/vatbeast.dm @@ -54,8 +54,16 @@ action_icon_state = "tentacle_slap" action_background_icon_state = "bg_revenant" ranged_mousepointer = 'icons/effects/mouse_pointers/supplypod_target.dmi' + base_action = /datum/action/cooldown/spell_like + ///How long cooldown before we can use the ability again var/cooldown = 12 SECONDS - var/current_cooldown = 0 + +/obj/effect/proc_holder/tentacle_slap/Initialize(mapload, mob/living/new_owner) + . = ..() + if(!action) + return + var/datum/action/cooldown/our_action = action + our_action.cooldown_time = cooldown /obj/effect/proc_holder/tentacle_slap/Click(location, control, params) . = ..() @@ -63,14 +71,11 @@ return TRUE fire(usr) -/obj/effect/proc_holder/tentacle_slap/fire(mob/living/carbon/user) - if(current_cooldown > world.time) - to_chat(user, span_notice("This ability is still on cooldown.")) - return +/obj/effect/proc_holder/tentacle_slap/fire(mob/living/user) if(active) remove_ranged_ability(span_notice("You stop preparing to tentacle slap.")) else - add_ranged_ability(user, span_notice("You prepare your pimp-tentacle. Left-click to slap a target!"), TRUE) + add_ranged_ability(user, span_notice("You prepare [(IS_WEAKREF_OF(user, owner)) ? "your" : "their"] pimp-tentacle. Left-click to slap a target!"), TRUE) /obj/effect/proc_holder/tentacle_slap/InterceptClickOn(mob/living/caller, params, atom/target) . = ..() @@ -86,7 +91,7 @@ remove_ranged_ability() return - if(!caller.Adjacent(target)) + if(!beast_owner.Adjacent(target)) return if(!isliving(target)) @@ -94,11 +99,20 @@ var/mob/living/living_target = target + if(!action.IsAvailable()) //extra check for safety since the ability is shared + remove_ranged_ability() + to_chat(caller, span_notice("This ability is still on cooldown.")) + return + beast_owner.visible_message("