diff --git a/code/__DEFINES/actions.dm b/code/__DEFINES/actions.dm new file mode 100644 index 000000000000..7818244e5257 --- /dev/null +++ b/code/__DEFINES/actions.dm @@ -0,0 +1,36 @@ +///Action button checks if user is restrained +#define AB_CHECK_RESTRAINED (1<<0) +///Action button checks if user is stunned +#define AB_CHECK_STUN (1<<1) +///Action button checks if user is resting +#define AB_CHECK_LYING (1<<2) +///Action button checks if user is conscious +#define AB_CHECK_CONSCIOUS (1<<3) + +/* +DEFINE_BITFIELD(check_flags, list( + "CHECK IF RESTRAINED" = AB_CHECK_RESTRAINED, + "CHECK IF STUNNED" = AB_CHECK_STUN, + "CHECK IF LYING DOWN" = AB_CHECK_LYING, + "CHECK IF CONSCIOUS" = AB_CHECK_CONSCIOUS, +)) */ + +///Action button triggered with right click +#define TRIGGER_SECONDARY_ACTION (1<<0) +///Action triggered to ignore any availability checks +#define TRIGGER_FORCE_AVAILABLE (1<<1) + +#define ACTION_BUTTON_DEFAULT_BACKGROUND "_use_ui_default_background" + +#define UPDATE_BUTTON_NAME (1<<0) +#define UPDATE_BUTTON_ICON (1<<1) +#define UPDATE_BUTTON_BACKGROUND (1<<2) +#define UPDATE_BUTTON_OVERLAY (1<<3) +#define UPDATE_BUTTON_STATUS (1<<4) + +/// Takes in a typepath of a `/datum/action` and adds it to `src`. +/// Only useful if you want to add the action and never desire to reference it again ever. +#define GRANT_ACTION(typepath) do {\ + var/datum/action/_ability = new typepath(src);\ + _ability.Grant(src);\ +} while (FALSE) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index f216a416c5cc..4f55d7dfb80a 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -459,97 +459,6 @@ /// from /obj/machinery/power/supermatter_crystal/process_atmos(); when the SM sounds an audible alarm #define COMSIG_SUPERMATTER_DELAM_ALARM "sm_delam_alarm" -// /obj/item signals -#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user) -#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob) - #define COMPONENT_NO_INTERACT 1 -#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob) - #define COMPONENT_NO_ATTACK_OBJ 1 -#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack" //from base of obj/item/pre_attack(): (atom/target, mob/user, params) - #define COMPONENT_NO_ATTACK 1 -#define COMSIG_ITEM_AFTERATTACK "item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, params) -#define COMSIG_ITEM_ALT_AFTERATTACK "item_alt_afterattack" //from base of obj/item/altafterattack(): (atom/target, mob/user, proximity, params) -#define COMSIG_ITEM_EQUIPPED "item_equip" //from base of obj/item/equipped(): (/mob/equipper, slot) -/// A mob has just unequipped an item. -#define COMSIG_MOB_UNEQUIPPED_ITEM "mob_unequipped_item" - // Do not grant actions on equip. - #define COMPONENT_NO_GRANT_ACTIONS 1 -#define COMSIG_ITEM_DROPPED "item_drop" //from base of obj/item/dropped(): (mob/user) - // relocated, tell inventory procs if those called this that the item isn't available anymore. - #define COMPONENT_DROPPED_RELOCATION 1 -#define COMSIG_ITEM_PICKUP "item_pickup" //from base of obj/item/pickup(): (/mob/taker) -#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" //from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone) -#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user) -#define COMSIG_ITEM_HIT_REACT "item_hit_react" //from base of obj/item/hit_reaction(): (list/args) -#define COMSIG_ITEM_WEARERCROSSED "wearer_crossed" //called on item when crossed by something (): (/atom/movable) -#define COMSIG_ITEM_SHARPEN_ACT "sharpen_act" //from base of item/sharpener/attackby(): (amount, max) - #define COMPONENT_BLOCK_SHARPEN_APPLIED 1 - #define COMPONENT_BLOCK_SHARPEN_BLOCKED 2 - #define COMPONENT_BLOCK_SHARPEN_ALREADY 4 - #define COMPONENT_BLOCK_SHARPEN_MAXED 8 -#define COMSIG_ITEM_MICROWAVE_ACT "microwave_act" //called on item when microwaved (): (obj/machinery/microwave/M) - -// /obj/item signals for economy -#define COMSIG_ITEM_SOLD "item_sold" //called when an item is sold by the exports subsystem -#define COMSIG_STRUCTURE_UNWRAPPED "structure_unwrapped" //called when a wrapped up structure is opened by hand -#define COMSIG_ITEM_UNWRAPPED "item_unwrapped" //called when a wrapped up item is opened by hand - #define COMSIG_ITEM_SPLIT_VALUE 1 -#define COMSIG_ITEM_SPLIT_PROFIT "item_split_profits" //Called when getting the item's exact ratio for cargo's profit. - -#define COMSIG_ITEM_WORN_OVERLAYS "item_worn_overlays" //from base of obj/item/worn_overlays(): (isinhands, icon_file, used_state, style_flags, list/overlays) -#define COMSIG_ARMOR_PLATED "armor_plated" //called when an armor plate is successfully applied to an object -// THE FOLLOWING TWO BLOCKS SHOULD RETURN BLOCK FLAGS AS DEFINED IN __DEFINES/combat.dm! -#define COMSIG_ITEM_CHECK_BLOCK "check_block" //from base of obj/item/check_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) -#define COMSIG_ITEM_RUN_BLOCK "run_block" //from base of obj/item/run_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) -// Item mouse siganls -#define COMSIG_ITEM_MOUSE_EXIT "item_mouse_exit" //from base of obj/item/MouseExited(): (location, control, params) -#define COMSIG_ITEM_MOUSE_ENTER "item_mouse_enter" //from base of obj/item/MouseEntered(): (location, control, params) -#define COMSIG_ITEM_DECONSTRUCTOR_DEEPSCAN "deconstructor_deepscan" //Called by deconstructive analyzers deepscanning an item: (obj/machinery/rnd/destructive_analyzer/analyzer_machine, mob/user, list/information_list) -#define COMSIG_ITEM_DISABLE_EMBED "item_disable_embed" ///from [/obj/item/proc/disableEmbedding]: -#define COMSIG_MINE_TRIGGERED "minegoboom" ///from [/obj/effect/mine/proc/triggermine]: - // Uncovered information - #define COMPONENT_DEEPSCAN_UNCOVERED_INFORMATION 1 -///Called when an item is being offered, from [/obj/item/proc/on_offered(mob/living/carbon/offerer)] -#define COMSIG_ITEM_OFFERING "item_offering" - ///Interrupts the offer proc - #define COMPONENT_OFFER_INTERRUPT (1<<0) -///Called when an someone tries accepting an offered item, from [/obj/item/proc/on_offer_taken(mob/living/carbon/offer, mob/living/carbon/taker)] -#define COMSIG_ITEM_OFFER_TAKEN "item_offer_taken" - ///Interrupts the offer acceptance - #define COMPONENT_OFFER_TAKE_INTERRUPT (1<<0) -///from [/obj/structure/closet/supplypod/proc/endlaunch]: -#define COMSIG_SUPPLYPOD_LANDED "supplypodgoboom" - -// /obj/item/grenade signals -#define COMSIG_GRENADE_PRIME "grenade_prime" //called in /obj/item/gun/process_fire (user, target, params, zone_override) -#define COMSIG_GRENADE_ARMED "grenade_armed" //called in /obj/item/gun/process_fire (user, target, params, zone_override) - -// /obj/item/clothing signals -#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): () -#define COMSIG_SUIT_MADE_HELMET "suit_made_helmet" //from base of obj/item/clothing/suit/MakeHelmet(): (helmet) - -// /obj/item/implant signals -#define COMSIG_IMPLANT_ACTIVATED "implant_activated" //from base of /obj/item/implant/proc/activate(): () -#define COMSIG_IMPLANT_IMPLANTING "implant_implanting" //from base of /obj/item/implant/proc/implant(): (list/args) - #define COMPONENT_STOP_IMPLANTING 1 -#define COMSIG_IMPLANT_OTHER "implant_other" //called on already installed implants when a new one is being added in /obj/item/implant/proc/implant(): (list/args, obj/item/implant/new_implant) - //#define COMPONENT_STOP_IMPLANTING 1 //The name makes sense for both - #define COMPONENT_DELETE_NEW_IMPLANT 2 - #define COMPONENT_DELETE_OLD_IMPLANT 4 -#define COMSIG_IMPLANT_EXISTING_UPLINK "implant_uplink_exists" //called on implants being implanted into someone with an uplink implant: (datum/component/uplink) - //This uses all return values of COMSIG_IMPLANT_OTHER -#define COMSIG_IMPLANT_REMOVING "implant_removing" //from base of /obj/item/implant/proc/removed() (list/args) - -// /obj/item/pda signals -#define COMSIG_PDA_CHANGE_RINGTONE "pda_change_ringtone" //called on pda when the user changes the ringtone: (mob/living/user, new_ringtone) - #define COMPONENT_STOP_RINGTONE_CHANGE 1 - -// /obj/item/radio signals -#define COMSIG_RADIO_NEW_FREQUENCY "radio_new_frequency" //called from base of /obj/item/radio/proc/set_frequency(): (list/args) - -// /obj/item/pen signals -#define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user) - // /obj/item/projectile signals (sent to the firer) #define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" ///from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle, hit_limb) #define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" ///from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle, hit_limb) @@ -680,10 +589,6 @@ // /datum/component/squeak signals #define COMSIG_CROSS_SQUEAKED "cross_squeaked" // sent when a squeak component squeaks from crossing something, to delay anything else crossing that might squeak to prevent ear hurt. -// /datum/action signals -#define COMSIG_ACTION_TRIGGER "action_trigger" //from base of datum/action/proc/Trigger(): (datum/action) - #define COMPONENT_ACTION_BLOCK_TRIGGER 1 - //Xenobio hotkeys #define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl" //from slime CtrlClickOn(): (/mob) #define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt" //from slime AltClickOn(): (/mob) diff --git a/code/__DEFINES/dcs/signals/signals_action.dm b/code/__DEFINES/dcs/signals/signals_action.dm index 62eccf282397..c6e042a0581d 100644 --- a/code/__DEFINES/dcs/signals/signals_action.dm +++ b/code/__DEFINES/dcs/signals/signals_action.dm @@ -1,6 +1,53 @@ +// Action signals + +///from base of datum/action/proc/Trigger(): (datum/action) +#define COMSIG_ACTION_TRIGGER "action_trigger" + // Return to block the trigger from occurring + #define COMPONENT_ACTION_BLOCK_TRIGGER (1<<0) +/// From /datum/action/Grant(): (mob/grant_to) +#define COMSIG_ACTION_GRANTED "action_grant" +/// From /datum/action/Grant(): (datum/action) +#define COMSIG_MOB_GRANTED_ACTION "mob_action_grant" +/// From /datum/action/Remove(): (mob/removed_from) +#define COMSIG_ACTION_REMOVED "action_removed" +/// From /datum/action/Remove(): (datum/action) +#define COMSIG_MOB_REMOVED_ACTION "mob_action_removed" +/// From /datum/action/apply_button_overlay() +#define COMSIG_ACTION_OVERLAY_APPLY "action_overlay_applied" + +// Cooldown action signals + /// From base of /datum/action/cooldown/proc/PreActivate(), sent to the action owner: (datum/action/cooldown/activated) #define COMSIG_MOB_ABILITY_STARTED "mob_ability_base_started" /// Return to block the ability from starting / activating #define COMPONENT_BLOCK_ABILITY_START (1<<0) /// From base of /datum/action/cooldown/proc/PreActivate(), sent to the action owner: (datum/action/cooldown/finished) #define COMSIG_MOB_ABILITY_FINISHED "mob_ability_base_finished" + +/// From base of /datum/action/cooldown/proc/set_statpanel_format(): (list/stat_panel_data) +#define COMSIG_ACTION_SET_STATPANEL "ability_set_statpanel" + +// Specific cooldown action signals + +/// From base of /datum/action/cooldown/mob_cooldown/blood_warp/proc/blood_warp(): () +#define COMSIG_BLOOD_WARP "mob_ability_blood_warp" +/// From base of /datum/action/cooldown/mob_cooldown/charge/proc/do_charge(): () +#define COMSIG_STARTED_CHARGE "mob_ability_charge_started" +/// From base of /datum/action/cooldown/mob_cooldown/charge/proc/do_charge(): () +#define COMSIG_FINISHED_CHARGE "mob_ability_charge_finished" +/// From base of /datum/action/cooldown/mob_cooldown/lava_swoop/proc/swoop_attack(): () +#define COMSIG_SWOOP_INVULNERABILITY_STARTED "mob_swoop_invulnerability_started" +/// From base of /datum/action/cooldown/mob_cooldown/lava_swoop/proc/swoop_attack(): () +#define COMSIG_LAVA_ARENA_FAILED "mob_lava_arena_failed" + +/// From /datum/action/vehicle/sealed/mecha/mech_toggle_safeties/proc/update_action_icon(): () +#define COMSIG_MECH_SAFETIES_TOGGLE "mech_safeties_toggle" + +/// From /datum/action/cooldown/mob_cooldown/assume_form/proc/assume_appearances(), sent to the action owner: (atom/movable/target) +#define COMSIG_ACTION_DISGUISED_APPEARANCE "mob_ability_disguise_appearance" + +/// From /datum/action/cooldown/manual_heart/Activate(): () +#define COMSIG_HEART_MANUAL_PULSE "heart_manual_pulse" + +/// From /datum/action/cooldown/mob_cooldown/capture_photo/Activate(): +#define COMSIG_ACTION_PHOTO_CAPTURED "action_photo_captured" diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm new file mode 100644 index 000000000000..ce0436eebfd9 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -0,0 +1,96 @@ +// /obj/item signals +#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user) +#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob) + #define COMPONENT_NO_INTERACT 1 +#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob) + #define COMPONENT_NO_ATTACK_OBJ 1 +#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack" //from base of obj/item/pre_attack(): (atom/target, mob/user, params) + #define COMPONENT_NO_ATTACK 1 +#define COMSIG_ITEM_AFTERATTACK "item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, params) +#define COMSIG_ITEM_ALT_AFTERATTACK "item_alt_afterattack" //from base of obj/item/altafterattack(): (atom/target, mob/user, proximity, params) +#define COMSIG_ITEM_EQUIPPED "item_equip" //from base of obj/item/equipped(): (/mob/equipper, slot) +/// A mob has just unequipped an item. +#define COMSIG_MOB_UNEQUIPPED_ITEM "mob_unequipped_item" + // Do not grant actions on equip. + #define COMPONENT_NO_GRANT_ACTIONS 1 +#define COMSIG_ITEM_DROPPED "item_drop" //from base of obj/item/dropped(): (mob/user) + // relocated, tell inventory procs if those called this that the item isn't available anymore. + #define COMPONENT_DROPPED_RELOCATION 1 +#define COMSIG_ITEM_PICKUP "item_pickup" //from base of obj/item/pickup(): (/mob/taker) + +/// Sent from obj/item/item_action_slot_check(): (mob/user, datum/action, slot) +#define COMSIG_ITEM_UI_ACTION_SLOT_CHECKED "item_action_slot_checked" + /// Return to prevent the default behavior (attack_selfing) from occurring. + #define COMPONENT_ITEM_ACTION_SLOT_INVALID (1<<0) + +#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" //from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone) +#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user) +#define COMSIG_ITEM_HIT_REACT "item_hit_react" //from base of obj/item/hit_reaction(): (list/args) +#define COMSIG_ITEM_WEARERCROSSED "wearer_crossed" //called on item when crossed by something (): (/atom/movable) +#define COMSIG_ITEM_SHARPEN_ACT "sharpen_act" //from base of item/sharpener/attackby(): (amount, max) + #define COMPONENT_BLOCK_SHARPEN_APPLIED 1 + #define COMPONENT_BLOCK_SHARPEN_BLOCKED 2 + #define COMPONENT_BLOCK_SHARPEN_ALREADY 4 + #define COMPONENT_BLOCK_SHARPEN_MAXED 8 +#define COMSIG_ITEM_MICROWAVE_ACT "microwave_act" //called on item when microwaved (): (obj/machinery/microwave/M) + +// /obj/item signals for economy +#define COMSIG_ITEM_SOLD "item_sold" //called when an item is sold by the exports subsystem +#define COMSIG_STRUCTURE_UNWRAPPED "structure_unwrapped" //called when a wrapped up structure is opened by hand +#define COMSIG_ITEM_UNWRAPPED "item_unwrapped" //called when a wrapped up item is opened by hand + #define COMSIG_ITEM_SPLIT_VALUE 1 +#define COMSIG_ITEM_SPLIT_PROFIT "item_split_profits" //Called when getting the item's exact ratio for cargo's profit. + +#define COMSIG_ITEM_WORN_OVERLAYS "item_worn_overlays" //from base of obj/item/worn_overlays(): (isinhands, icon_file, used_state, style_flags, list/overlays) +#define COMSIG_ARMOR_PLATED "armor_plated" //called when an armor plate is successfully applied to an object +// THE FOLLOWING TWO BLOCKS SHOULD RETURN BLOCK FLAGS AS DEFINED IN __DEFINES/combat.dm! +#define COMSIG_ITEM_CHECK_BLOCK "check_block" //from base of obj/item/check_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) +#define COMSIG_ITEM_RUN_BLOCK "run_block" //from base of obj/item/run_block(): (mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) +// Item mouse siganls +#define COMSIG_ITEM_MOUSE_EXIT "item_mouse_exit" //from base of obj/item/MouseExited(): (location, control, params) +#define COMSIG_ITEM_MOUSE_ENTER "item_mouse_enter" //from base of obj/item/MouseEntered(): (location, control, params) +#define COMSIG_ITEM_DECONSTRUCTOR_DEEPSCAN "deconstructor_deepscan" //Called by deconstructive analyzers deepscanning an item: (obj/machinery/rnd/destructive_analyzer/analyzer_machine, mob/user, list/information_list) +#define COMSIG_ITEM_DISABLE_EMBED "item_disable_embed" ///from [/obj/item/proc/disableEmbedding]: +#define COMSIG_MINE_TRIGGERED "minegoboom" ///from [/obj/effect/mine/proc/triggermine]: + // Uncovered information + #define COMPONENT_DEEPSCAN_UNCOVERED_INFORMATION 1 +///Called when an item is being offered, from [/obj/item/proc/on_offered(mob/living/carbon/offerer)] +#define COMSIG_ITEM_OFFERING "item_offering" + ///Interrupts the offer proc + #define COMPONENT_OFFER_INTERRUPT (1<<0) +///Called when an someone tries accepting an offered item, from [/obj/item/proc/on_offer_taken(mob/living/carbon/offer, mob/living/carbon/taker)] +#define COMSIG_ITEM_OFFER_TAKEN "item_offer_taken" + ///Interrupts the offer acceptance + #define COMPONENT_OFFER_TAKE_INTERRUPT (1<<0) +///from [/obj/structure/closet/supplypod/proc/endlaunch]: +#define COMSIG_SUPPLYPOD_LANDED "supplypodgoboom" + +// /obj/item/grenade signals +#define COMSIG_GRENADE_PRIME "grenade_prime" //called in /obj/item/gun/process_fire (user, target, params, zone_override) +#define COMSIG_GRENADE_ARMED "grenade_armed" //called in /obj/item/gun/process_fire (user, target, params, zone_override) + +// /obj/item/clothing signals +#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): () +#define COMSIG_SUIT_MADE_HELMET "suit_made_helmet" //from base of obj/item/clothing/suit/MakeHelmet(): (helmet) + +// /obj/item/implant signals +#define COMSIG_IMPLANT_ACTIVATED "implant_activated" //from base of /obj/item/implant/proc/activate(): () +#define COMSIG_IMPLANT_IMPLANTING "implant_implanting" //from base of /obj/item/implant/proc/implant(): (list/args) + #define COMPONENT_STOP_IMPLANTING 1 +#define COMSIG_IMPLANT_OTHER "implant_other" //called on already installed implants when a new one is being added in /obj/item/implant/proc/implant(): (list/args, obj/item/implant/new_implant) + //#define COMPONENT_STOP_IMPLANTING 1 //The name makes sense for both + #define COMPONENT_DELETE_NEW_IMPLANT 2 + #define COMPONENT_DELETE_OLD_IMPLANT 4 +#define COMSIG_IMPLANT_EXISTING_UPLINK "implant_uplink_exists" //called on implants being implanted into someone with an uplink implant: (datum/component/uplink) + //This uses all return values of COMSIG_IMPLANT_OTHER +#define COMSIG_IMPLANT_REMOVING "implant_removing" //from base of /obj/item/implant/proc/removed() (list/args) + +// /obj/item/pda signals +#define COMSIG_PDA_CHANGE_RINGTONE "pda_change_ringtone" //called on pda when the user changes the ringtone: (mob/living/user, new_ringtone) + #define COMPONENT_STOP_RINGTONE_CHANGE 1 + +// /obj/item/radio signals +#define COMSIG_RADIO_NEW_FREQUENCY "radio_new_frequency" //called from base of /obj/item/radio/proc/set_frequency(): (list/args) + +// /obj/item/pen signals +#define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user) diff --git a/code/__DEFINES/sight.dm b/code/__DEFINES/sight.dm index 5cac2900823b..875625f9935e 100644 --- a/code/__DEFINES/sight.dm +++ b/code/__DEFINES/sight.dm @@ -1,3 +1,5 @@ +#define INVISIBILITY_NONE 0 + #define SEE_INVISIBLE_MINIMUM 5 #define INVISIBILITY_LIGHTING 20 diff --git a/code/__DEFINES/spans.dm b/code/__DEFINES/spans.dm index b6b633d91a5d..33a64697fee8 100644 --- a/code/__DEFINES/spans.dm +++ b/code/__DEFINES/spans.dm @@ -56,8 +56,10 @@ #define span_icon(str) ("" + str + "") #define span_info(str) ("" + str + "") #define span_interface(str) ("" + str + "") +#define span_italics(str) ("" + str + "") #define span_looc(str) ("" + str + "") +#define span_love(str) ("" + str + "") #define span_medal(str) ("" + str + "") #define span_medradio(str) ("" + str + "") #define span_memo(str) ("" + str + "") diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 95e36ba1a5ad..044ff7512e5b 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -662,12 +662,18 @@ /datum/action/report name = "Show roundend report" button_icon_state = "round_end" + check_flags = NONE + required_mobility_flags = NONE -/datum/action/report/Trigger() +/datum/action/report/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED) SSticker.show_roundend_report(owner.client) + return TRUE -/datum/action/report/IsAvailable() +/datum/action/report/IsAvailable(feedback) return TRUE /datum/action/report/Topic(href,href_list) diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index cb88f56dcb1a..1fd89899a655 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -1,5 +1,3 @@ -#define ACTION_BUTTON_DEFAULT_BACKGROUND "default" - /atom/movable/screen/movable/action_button var/datum/action/linked_action var/datum/hud/our_hud @@ -7,9 +5,13 @@ screen_loc = null mouse_over_pointer = MOUSE_HAND_POINTER - var/button_icon_state - var/appearance_cache + /// The icon state of our active overlay, used to prevent re-applying identical overlays + var/active_overlay_icon_state + /// The icon state of our active underlay, used to prevent re-applying identical underlays + var/active_underlay_icon_state + /// The overlay we have overtop our button var/mutable_appearance/button_overlay + /// Where we are currently placed on the hud. SCRN_OBJ_DEFAULT asks the linked action what it thinks var/location = SCRN_OBJ_DEFAULT /// A unique bitflag, combined with the name of our linked action this lets us persistently remember any user changes to our position @@ -17,6 +19,8 @@ /// A weakref of the last thing we hovered over /// God I hate how dragging works var/datum/weakref/last_hovored_ref + /// overlay for keybind maptext + var/mutable_appearance/keybind_maptext /atom/movable/screen/movable/action_button/Destroy() if(our_hud) @@ -44,20 +48,33 @@ /atom/movable/screen/movable/action_button/Click(location,control,params) if (!can_use(usr)) - return + return FALSE var/list/modifiers = params2list(params) + /* if(LAZYACCESS(modifiers, ALT_CLICK)) + begin_creating_bind(usr) + return TRUE */ if(LAZYACCESS(modifiers, SHIFT_CLICK)) var/datum/hud/our_hud = usr.hud_used our_hud.position_action(src, SCRN_OBJ_DEFAULT) return TRUE - var/mob/clicker = usr - if(!clicker.CheckActionCooldown()) + if(!usr.CheckActionCooldown()) return - clicker.DelayNextAction(1) - linked_action.Trigger() + usr.DelayNextAction(1) + var/trigger_flags + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + trigger_flags |= TRIGGER_SECONDARY_ACTION + linked_action.Trigger(trigger_flags = trigger_flags) return TRUE +/* /atom/movable/screen/movable/action_button/proc/begin_creating_bind(mob/user) + if(!isnull(linked_action.full_key)) + linked_action.full_key = null + linked_action.update_button_status(src) + return + linked_action.full_key = tgui_input_keycombo(user, "Please bind a key for this action.") + linked_action.update_button_status(src) */ + // Entered and Exited won't fire while you're dragging something, because you're still "holding" it // Very much byond logic, but I want nice behavior, so we fake it with drag /atom/movable/screen/movable/action_button/MouseDrag(atom/over_object, atom/src_location, atom/over_location, src_control, over_control, params) @@ -77,11 +94,8 @@ if(old_object) old_object.MouseExited(over_location, over_control, params) - if(QDELETED(over_location)) - last_hovored_ref = null - return last_hovored_ref = WEAKREF(over_object) - over_object.MouseEntered(over_location, over_control, params) + over_object?.MouseEntered(over_location, over_control, params) /atom/movable/screen/movable/action_button/MouseEntered(location, control, params) . = ..() @@ -96,30 +110,37 @@ last_hovored_ref = null if(!can_use(usr)) return + var/datum/hud/our_hud = usr.hud_used if(over_object == src) our_hud.hide_landings() return + if(istype(over_object, /atom/movable/screen/action_landing)) var/atom/movable/screen/action_landing/reserve = over_object reserve.hit_by(src) - our_hud.hide_landings() save_position() + our_hud.hide_landings() return - our_hud.hide_landings() if(istype(over_object, /atom/movable/screen/button_palette) || istype(over_object, /atom/movable/screen/palette_scroll)) our_hud.position_action(src, SCRN_OBJ_IN_PALETTE) save_position() + our_hud.hide_landings() return + if(istype(over_object, /atom/movable/screen/movable/action_button)) var/atom/movable/screen/movable/action_button/button = over_object our_hud.position_action_relative(src, button) save_position() + our_hud.hide_landings() return + . = ..() + our_hud.position_action(src, screen_loc) save_position() + our_hud.hide_landings() /atom/movable/screen/movable/action_button/proc/save_position() var/mob/user = our_hud.mymob @@ -151,6 +172,15 @@ user.client.prefs.action_buttons_screen_locs -= "[name]_[id]" user.client.prefs.queue_save_pref(1 SECONDS, TRUE) +/atom/movable/screen/movable/action_button/proc/update_keybind_maptext(key) + cut_overlay(keybind_maptext) + if(!key) + return + keybind_maptext = new + keybind_maptext.maptext = MAPTEXT("[key]") + keybind_maptext.transform = keybind_maptext.transform.Translate(-4, length(key) > 1 ? -6 : 2) //with modifiers, its placed lower so cooldown is visible + add_overlay(keybind_maptext) + /** * This is a silly proc used in hud code code to determine what icon and icon state we should be using * for hud elements (such as action buttons) that don't have their own icon and icon state set. @@ -161,13 +191,18 @@ . = list() .["bg_icon"] = ui_style .["bg_state"] = "template" + .["bg_state_active"] = "template_active" -//see human and alien hud for specific implementations. - -/mob/proc/update_action_buttons_icon(status_only = FALSE) - for(var/X in actions) - var/datum/action/A = X - A.UpdateButtons(status_only) +/** + * Updates all action buttons this mob has. + * + * Arguments: + * * update_flags - Which flags of the action should we update + * * force - Force buttons update even if the given button icon state has not changed + */ +/mob/proc/update_mob_action_buttons(update_flags = ALL, force = FALSE) + for(var/datum/action/current_action as anything in actions) + current_action.build_all_button_icons(update_flags, force) /** * This proc handles adding all of the mob's actions to their screen @@ -186,7 +221,7 @@ for(var/datum/action/action as anything in actions) var/atom/movable/screen/movable/action_button/button = action.viewers[hud_used] - action.UpdateButtons() + action.build_all_button_icons() if(reload_screen) client.screen += button @@ -195,6 +230,48 @@ // This holds the logic for the palette buttons hud_used.palette_actions.refresh_actions() +/** + * Show (most) of the another mob's action buttons to this mob + * + * Used for observers viewing another mob's screen + */ +/mob/proc/show_other_mob_action_buttons(mob/take_from) + if(!hud_used || !client) + return + + for(var/datum/action/action as anything in take_from.actions) + if(!action.show_to_observers || !action.owner_has_control) + continue + action.GiveAction(src) + RegisterSignal(take_from, COMSIG_MOB_GRANTED_ACTION, PROC_REF(on_observing_action_granted)) + RegisterSignal(take_from, COMSIG_MOB_REMOVED_ACTION, PROC_REF(on_observing_action_removed)) + +/** + * Hide another mob's action buttons from this mob + * + * Used for observers viewing another mob's screen + */ +/mob/proc/hide_other_mob_action_buttons(mob/take_from) + for(var/datum/action/action as anything in take_from.actions) + action.HideFrom(src) + UnregisterSignal(take_from, list(COMSIG_MOB_GRANTED_ACTION, COMSIG_MOB_REMOVED_ACTION)) + +/// Signal proc for [COMSIG_MOB_GRANTED_ACTION] - If we're viewing another mob's action buttons, +/// we need to update with any newly added buttons granted to the mob. +/mob/proc/on_observing_action_granted(mob/living/source, datum/action/action) + SIGNAL_HANDLER + + if(!action.show_to_observers || !action.owner_has_control) + return + action.GiveAction(src) + +/// Signal proc for [COMSIG_MOB_REMOVED_ACTION] - If we're viewing another mob's action buttons, +/// we need to update with any removed buttons from the mob. +/mob/proc/on_observing_action_removed(mob/living/source, datum/action/action) + SIGNAL_HANDLER + + action.HideFrom(src) + /atom/movable/screen/button_palette desc = "Drag buttons to move them
Shift-click any button to reset it
Alt-click this to reset all buttons" icon = 'icons/hud/64x16_actions.dmi' @@ -220,6 +297,7 @@ /atom/movable/screen/button_palette/proc/set_hud(datum/hud/our_hud) src.our_hud = our_hud refresh_owner() + disable_landing() // If our hud already has elements, don't force hide us /atom/movable/screen/button_palette/update_name(updates) . = ..() @@ -241,6 +319,21 @@ icon_state = "[ui_name]_palette" +/atom/movable/screen/button_palette/proc/activate_landing() + // Reveal ourselves to the user + invisibility = INVISIBILITY_NONE + +/atom/movable/screen/button_palette/proc/disable_landing() + // If we have no elements in the palette, hide your ugly self please + if (!length(our_hud.palette_actions?.actions) && !length(our_hud.floating_actions)) + invisibility = INVISIBILITY_ABSTRACT + +/atom/movable/screen/button_palette/proc/update_state() + if (length(our_hud.floating_actions)) + activate_landing() + else + disable_landing() + /atom/movable/screen/button_palette/MouseEntered(location, control, params) . = ..() if(QDELETED(src)) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index bda691dcc9d3..95a305f25e9a 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -134,10 +134,13 @@ GLOBAL_LIST_INIT(available_ui_styles, list( QDEL_NULL(module_store_icon) QDEL_LIST(static_inventory) + // all already deleted by static inventory clear inv_slots.Cut() action_intent = null zone_select = null pull_icon = null + rest_icon = null + hand_slots.Cut() QDEL_LIST(toggleable_inventory) QDEL_LIST(hotkeybuttons) @@ -255,6 +258,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( show_hud(hud_version, M) else if (viewmob.hud_used) viewmob.hud_used.plane_masters_update() + viewmob.show_other_mob_action_buttons(mymob) screenmob.reload_rendering() @@ -369,6 +373,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( floating_actions += button button.screen_loc = position position = SCRN_OBJ_FLOATING + toggle_palette.update_state() button.location = position @@ -387,6 +392,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( position_action(button, button.linked_action.default_button_position) return button.screen_loc = get_valid_screen_location(relative_to.screen_loc, world.icon_size, our_client.view_size.getView()) // Asks for a location adjacent to our button that won't overflow the map + toggle_palette.update_state() button.location = relative_to.location @@ -396,6 +402,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( if(SCRN_OBJ_DEFAULT) // Invalid CRASH("We just tried to hide an action buttion that somehow has the default position as its location, you done fucked up") if(SCRN_OBJ_FLOATING) + toggle_palette.update_state() floating_actions -= button if(SCRN_OBJ_IN_LIST) listed_actions.remove_action(button) @@ -407,11 +414,13 @@ GLOBAL_LIST_INIT(available_ui_styles, list( /datum/hud/proc/generate_landings(atom/movable/screen/movable/action_button/button) listed_actions.generate_landing() palette_actions.generate_landing() + toggle_palette.activate_landing() /// Clears all currently visible landings /datum/hud/proc/hide_landings() listed_actions.clear_landing() palette_actions.clear_landing() + toggle_palette.disable_landing() // Updates any existing "owned" visuals, ensures they continue to be visible /datum/hud/proc/update_our_owner() @@ -429,7 +438,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( listed_actions.check_against_view() palette_actions.check_against_view() for(var/atom/movable/screen/movable/action_button/floating_button as anything in floating_actions) - var/list/current_offsets = screen_loc_to_offset(floating_button.screen_loc) + var/list/current_offsets = screen_loc_to_offset(floating_button.screen_loc, our_view) // We set the view arg here, so the output will be properly hemm'd in by our new view floating_button.screen_loc = offset_to_screen_loc(current_offsets[1], current_offsets[2], view = our_view) @@ -442,7 +451,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list( var/atom/movable/screen/movable/action_button/button = action.viewers[src] if(!button) action.ShowTo(mymob) - button = action.viewers[src] else position_action(button, button.location) @@ -655,4 +663,4 @@ GLOBAL_LIST_INIT(available_ui_styles, list( /datum/action_group/listed/refresh_actions() . = ..() - owner?.palette_actions.refresh_actions() // We effect them, so we gotta refresh em + owner.palette_actions.refresh_actions() // We effect them, so we gotta refresh em diff --git a/code/_onclick/hud/new_player.dm b/code/_onclick/hud/new_player.dm index f1e12bccdd72..533953c2cbd7 100644 --- a/code/_onclick/hud/new_player.dm +++ b/code/_onclick/hud/new_player.dm @@ -620,6 +620,8 @@ return SEND_SOUND(hud.mymob, sound('sound/effects/splat.ogg', volume = 50)) SSticker.start_immediately = TRUE + if(SSticker.current_state == GAME_STATE_STARTUP) + to_chat(usr, span_admin("The server is still setting up, but the round will be started as soon as possible.")) #undef SHUTTER_MOVEMENT_DURATION #undef SHUTTER_WAIT_DURATION diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index ace6303c031e..32fc116306dd 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -218,7 +218,7 @@ var/image/item_overlay = image(holding) item_overlay.alpha = 92 - if(!holding.mob_can_equip(user, slot_id, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) + if(!holding.mob_can_equip(user, user, slot_id, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) item_overlay.color = "#FF0000" else item_overlay.color = "#00ff00" @@ -596,7 +596,7 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT /atom/movable/screen/healths/clock - icon = 'icons/mob/actions.dmi' + icon = 'icons/hud/actions.dmi' icon_state = "bg_clock" screen_loc = ui_health mouse_opacity = MOUSE_OPACITY_TRANSPARENT @@ -608,7 +608,7 @@ /atom/movable/screen/healths/revenant name = "essence" - icon = 'icons/mob/actions.dmi' + icon = 'icons/hud/actions.dmi' icon_state = "bg_revenant" screen_loc = ui_health mouse_opacity = MOUSE_OPACITY_TRANSPARENT diff --git a/code/controllers/subsystem/augury.dm b/code/controllers/subsystem/augury.dm index f7a7c667184e..1de0cf67ca52 100644 --- a/code/controllers/subsystem/augury.dm +++ b/code/controllers/subsystem/augury.dm @@ -56,9 +56,8 @@ SUBSYSTEM_DEF(augury) /datum/action/innate/augury name = "Auto Follow Debris" - icon_icon = 'icons/obj/meteor.dmi' + button_icon = 'icons/obj/meteor.dmi' button_icon_state = "flaming" - background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND /datum/action/innate/augury/Destroy() if(owner) @@ -67,19 +66,10 @@ SUBSYSTEM_DEF(augury) /datum/action/innate/augury/Activate() SSaugury.watchers += owner - to_chat(owner, "You are now auto-following debris.") + to_chat(owner, span_notice("You are now auto-following debris.")) active = TRUE - UpdateButtons() /datum/action/innate/augury/Deactivate() SSaugury.watchers -= owner - to_chat(owner, "You are no longer auto-following debris.") + to_chat(owner, span_notice("You are no longer auto-following debris.")) active = FALSE - UpdateButtons() - -/datum/action/innate/augury/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force) - ..() - if(active) - button.icon_state = "template_active" - else - button.icon_state = "template" diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index abcc7319aa5a..149d66008b86 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -728,14 +728,21 @@ SUBSYSTEM_DEF(vote) /datum/action/vote name = "Vote!" button_icon_state = "vote" + check_flags = NONE + required_mobility_flags = NONE -/datum/action/vote/Trigger() - if(owner) - owner.vote() - remove_from_client() - Remove(owner) +/datum/action/vote/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + if(!owner) + return FALSE + owner.vote() + remove_from_client() + Remove(owner) + return TRUE -/datum/action/vote/IsAvailable(silent = FALSE) +/datum/action/vote/IsAvailable(feedback = TRUE) return TRUE /datum/action/vote/proc/remove_from_client() diff --git a/code/datums/action.dm b/code/datums/action.dm index a4bd371c1e53..d01dad3f8222 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -1,9 +1,8 @@ -#define AB_CHECK_RESTRAINED 1 -#define AB_CHECK_STUN 2 -#define AB_CHECK_LYING 4 -#define AB_CHECK_CONSCIOUS 8 -#define AB_CHECK_ALIVE 16 - +/** + * # Action system + * + * A simple base for an modular behavior attached to atom or datum. + */ /datum/action /// The name of the action var/name = "Generic Action" @@ -17,6 +16,8 @@ /// This is who currently owns the action, and most often, this is who is using the action if it is triggered /// This can be the same as "target" but is not ALWAYS the same - this is set and unset with Grant() and Remove() var/mob/owner + /// If False, the owner of this action does not get a hud and cannot activate it on their own + var/owner_has_control = TRUE /// Flags that will determine of the owner / user of the action can... use the action var/check_flags = NONE var/required_mobility_flags = MOBILITY_USE @@ -25,21 +26,36 @@ var/transparent_when_unavailable = TRUE ///List of all mobs that are viewing our action button -> A unique movable for them to view. var/list/viewers = list() + /// If TRUE, this action button will be shown to observers / other mobs who view from this action's owner's eyes. + /// Used in [/mob/proc/show_other_mob_action_buttons] + var/show_to_observers = TRUE /// The style the button's tooltips appear to be var/buttontooltipstyle = "" /// This is the file for the BACKGROUND underlay icon of the button - var/button_icon = 'icons/mob/actions/backgrounds.dmi' + var/background_icon = 'icons/mob/actions/backgrounds.dmi' /// This is the icon state state for the BACKGROUND underlay icon of the button /// (If set to ACTION_BUTTON_DEFAULT_BACKGROUND, uses the hud's default background) var/background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND /// This is the file for the icon that appears on the button - var/icon_icon = 'icons/mob/actions.dmi' + var/button_icon = 'icons/hud/actions.dmi' /// This is the icon state for the icon that appears on the button var/button_icon_state = "default" - var/button_overlay_state + + /// This is the file for any FOREGROUND overlay icons on the button (such as borders) + var/overlay_icon = 'icons/mob/actions/backgrounds.dmi' + /// This is the icon state for any FOREGROUND overlay icons on the button (such as borders) + var/overlay_icon_state + + /// full key we are bound to + var/full_key + + /// Toggles whether this action is usable or not + var/action_disabled = FALSE + /// Can this action be shared with our rider? + var/can_be_shared = TRUE /datum/action/New(Target) link_to(Target) @@ -77,12 +93,16 @@ owner = grant_to if(!isnull(previous_owner)) Remove(previous_owner) + SEND_SIGNAL(src, COMSIG_ACTION_GRANTED, owner) + SEND_SIGNAL(owner, COMSIG_MOB_GRANTED_ACTION, src) RegisterSignal(owner, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref), override = TRUE) // Register some signals based on our check_flags // so that our button icon updates when relevant if(check_flags & AB_CHECK_CONSCIOUS) RegisterSignal(owner, COMSIG_MOB_STATCHANGE, PROC_REF(update_status_on_signal)) + if(check_flags & AB_CHECK_LYING) + RegisterSignal(owner, COMSIG_LIVING_RESTING, PROC_REF(update_status_on_signal)) GiveAction(grant_to) @@ -102,7 +122,8 @@ // Clean up our check_flag signals UnregisterSignal(owner, list( - COMSIG_MOB_STATCHANGE + COMSIG_LIVING_RESTING, + COMSIG_MOB_STATCHANGE, )) if(target == owner) @@ -112,8 +133,8 @@ /// Actually triggers the effects of the action. /// Called when the on-screen button is clicked, for example. -/datum/action/proc/Trigger() - if(!IsAvailable()) +/datum/action/proc/Trigger(trigger_flags) + if(!(trigger_flags & TRIGGER_FORCE_AVAILABLE) && !IsAvailable(feedback = TRUE)) return FALSE if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, target) & COMPONENT_ACTION_BLOCK_TRIGGER) return FALSE @@ -124,92 +145,180 @@ /** * Whether our action is currently available to use or not - * * silent - If false this is being called to check if we have any messages to show to the owner + * * feedback - If true this is being called to check if we have any messages to show to the owner */ -/datum/action/proc/IsAvailable(silent = FALSE) +/datum/action/proc/IsAvailable(feedback = FALSE) if(!owner) return FALSE + if(action_disabled) + return FALSE var/mob/living/L = owner if(istype(L) && !CHECK_ALL_MOBILITY(L, required_mobility_flags)) return FALSE - if(check_flags & AB_CHECK_RESTRAINED) - if(owner.restrained()) - return FALSE + if(check_flags & AB_CHECK_RESTRAINED && owner.restrained()) + if (feedback) + owner.balloon_alert(owner, "restrained!") + return FALSE if(check_flags & AB_CHECK_STUN) if(istype(L) && !CHECK_MOBILITY(L, MOBILITY_USE)) return FALSE if(check_flags & AB_CHECK_LYING) if(istype(L) && !CHECK_MOBILITY(L, MOBILITY_STAND)) - if (!silent) + if (feedback) owner.balloon_alert(owner, "must stand up!") return FALSE - if(check_flags & AB_CHECK_CONSCIOUS) - if(owner.stat) - if (!silent) - owner.balloon_alert(owner, "unconscious!") - return FALSE - if(check_flags & AB_CHECK_ALIVE) - if(owner.stat == DEAD) - return FALSE + if(check_flags & AB_CHECK_CONSCIOUS && owner.stat != CONSCIOUS) + if (feedback) + switch(owner.stat) + if(SOFT_CRIT) + owner.balloon_alert(owner, "soft crit!") + if(UNCONSCIOUS) + owner.balloon_alert(owner, "unconscious!") + if(DEAD) + owner.balloon_alert(owner, "dead!") + return FALSE return TRUE -/datum/action/proc/UpdateButtons(status_only, force) - for(var/datum/hud/hud in viewers) - var/atom/movable/screen/movable/button = viewers[hud] - UpdateButton(button, status_only, force) +/// Builds / updates all buttons we have shared or given out +/datum/action/proc/build_all_button_icons(update_flags = ALL, force) + for(var/datum/hud/hud as anything in viewers) + build_button_icon(viewers[hud], update_flags, force) -/datum/action/proc/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE) +/** + * Builds the icon of the button. + * + * Concept: + * - Underlay (Background icon) + * - Icon (button icon) + * - Maptext + * - Overlay (Background border) + * + * button - which button we are modifying the icon of + * force - whether we're forcing a full update + */ +/datum/action/proc/build_button_icon(atom/movable/screen/movable/action_button/button, update_flags = ALL, force = FALSE) if(!button) return - if(!status_only) - button.name = name + + if(update_flags & UPDATE_BUTTON_NAME) + update_button_name(button, force) + + if(update_flags & UPDATE_BUTTON_BACKGROUND) + apply_button_background(button, force) + + if(update_flags & UPDATE_BUTTON_ICON) + apply_button_icon(button, force) + + if(update_flags & UPDATE_BUTTON_OVERLAY) + apply_button_overlay(button, force) + + if(update_flags & UPDATE_BUTTON_STATUS) + update_button_status(button, force) + +/** + * Updates the name and description of the button to match our action name and discription. + * + * current_button - what button are we editing? + * force - whether an update is forced regardless of existing status + */ +/datum/action/proc/update_button_name(atom/movable/screen/movable/action_button/button, force = FALSE) + button.name = name + if(desc) button.desc = desc - if(owner?.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND) - var/list/settings = owner.hud_used.get_action_buttons_icons() - if(button.icon != settings["bg_icon"]) - button.icon = settings["bg_icon"] - if(button.icon_state != settings["bg_state"]) - button.icon_state = settings["bg_state"] - else - if(button.icon != button_icon) - button.icon = button_icon - if(button.icon_state != background_icon_state) - button.icon_state = background_icon_state - ApplyIcon(button, force) +/** + * Creates the background underlay for the button + * + * current_button - what button are we editing? + * force - whether an update is forced regardless of existing status + */ +/datum/action/proc/apply_button_background(atom/movable/screen/movable/action_button/current_button, force = FALSE) + if(!background_icon || !background_icon_state || (current_button.active_underlay_icon_state == background_icon_state && !force)) + return - if(button_overlay_state) - button.cut_overlay(button.button_overlay) - button.button_overlay = mutable_appearance(icon = 'icons/mob/actions.dmi', icon_state = button_overlay_state) - button.add_overlay(button.button_overlay) + // What icons we use for our background + var/list/icon_settings = list( + // The icon file + "bg_icon" = background_icon, + // The icon state, if is_action_active() returns FALSE + "bg_state" = background_icon_state, + // The icon state, if is_action_active() returns TRUE + "bg_state_active" = background_icon_state, + ) - if(!IsAvailable(TRUE)) - button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0) - else - button.color = rgb(255,255,255,255) - return TRUE + // If background_icon_state is ACTION_BUTTON_DEFAULT_BACKGROUND instead use our hud's action button scheme + if(background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND && owner?.hud_used) + icon_settings = owner.hud_used.get_action_buttons_icons() + + // Determine which icon to use + var/used_icon_key = is_action_active(current_button) ? "bg_state_active" : "bg_state" -/datum/action/proc/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force = FALSE) - if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force)) - current_button.cut_overlays() - current_button.add_overlay(mutable_appearance(icon_icon, button_icon_state)) - current_button.button_icon_state = button_icon_state + // Make the underlay + current_button.underlays.Cut() + current_button.underlays += image(icon = icon_settings["bg_icon"], icon_state = icon_settings[used_icon_key]) + current_button.active_underlay_icon_state = icon_settings[used_icon_key] + +/** + * Applies our button icon and icon state to the button + * + * current_button - what button are we editing? + * force - whether an update is forced regardless of existing status + */ +/datum/action/proc/apply_button_icon(atom/movable/screen/movable/action_button/current_button, force = FALSE) + if(!button_icon || !button_icon_state || (current_button.icon_state == button_icon_state && !force)) + return + + current_button.icon = button_icon + current_button.icon_state = button_icon_state + +/** + * Applies any overlays to our button + * + * current_button - what button are we editing? + * force - whether an update is forced regardless of existing status + */ +/datum/action/proc/apply_button_overlay(atom/movable/screen/movable/action_button/current_button, force = FALSE) + + SEND_SIGNAL(src, COMSIG_ACTION_OVERLAY_APPLY, current_button, force) + + if(!overlay_icon || !overlay_icon_state || (current_button.active_overlay_icon_state == overlay_icon_state && !force)) + return + + current_button.cut_overlay(current_button.button_overlay) + current_button.button_overlay = mutable_appearance(icon = overlay_icon, icon_state = overlay_icon_state) + current_button.add_overlay(current_button.button_overlay) + current_button.active_overlay_icon_state = overlay_icon_state + +/** + * Any other miscellaneous "status" updates within the action button is handled here, + * such as redding out when unavailable or modifying maptext. + * + * current_button - what button are we editing? + * force - whether an update is forced regardless of existing status + */ +/datum/action/proc/update_button_status(atom/movable/screen/movable/action_button/current_button, force = FALSE) + current_button.update_keybind_maptext(full_key) + if(IsAvailable()) + current_button.color = rgb(255,255,255,255) + else + current_button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0) /datum/action/ghost - icon_icon = 'icons/mob/mob.dmi' + button_icon = 'icons/mob/mob.dmi' button_icon_state = "ghost" name = "Ghostize" desc = "Turn into a ghost and freely come back to your body." -/datum/action/ghost/Trigger() +/datum/action/ghost/Trigger(trigger_flags) if(!..()) return FALSE var/mob/M = target M.ghostize(can_reenter_corpse = TRUE, voluntary = TRUE) + return TRUE /datum/action/proc/OnUpdatedIcon() SIGNAL_HANDLER - UpdateButtons(force = TRUE) + build_all_button_icons(force = TRUE) /// Gives our action to the passed viewer. /// Puts our action in their actions list and shows them the button. @@ -227,7 +336,7 @@ if(!our_hud || viewers[our_hud]) // There's no point in this if you have no hud in the first place return - var/atom/movable/screen/movable/action_button/button = CreateButton() + var/atom/movable/screen/movable/action_button/button = create_button() SetId(button, viewer) button.our_hud = our_hud @@ -246,12 +355,10 @@ if(button) qdel(button) -/datum/action/proc/CreateButton() +/datum/action/proc/create_button() var/atom/movable/screen/movable/action_button/button = new() button.linked_action = src - button.actiontooltipstyle = buttontooltipstyle - if(desc) - button.desc = desc + build_button_icon(button, ALL, TRUE) return button /datum/action/proc/SetId(atom/movable/screen/movable/action_button/our_button, mob/owner) @@ -271,81 +378,78 @@ our_button.id = bitflag return +/// Updates our buttons if our target's icon was updated +/datum/action/proc/on_target_icon_update(datum/source, updates, updated) + SIGNAL_HANDLER + + var/update_flag = NONE + var/forced = FALSE + if(updates & UPDATE_ICON_STATE) + update_flag |= UPDATE_BUTTON_ICON + forced = TRUE + if(updates & UPDATE_OVERLAYS) + update_flag |= UPDATE_BUTTON_OVERLAY + forced = TRUE + if(updates & (UPDATE_NAME|UPDATE_DESC)) + update_flag |= UPDATE_BUTTON_NAME + // Status is not relevant, and background is not relevant. Neither will change + + // Force the update if an icon state or overlay change was done + build_all_button_icons(update_flag, forced) + /// A general use signal proc that reacts to an event and updates JUST our button's status /datum/action/proc/update_status_on_signal(datum/source, new_stat, old_stat) SIGNAL_HANDLER - UpdateButton(status_only = TRUE) -//Presets for item actions -/datum/action/item_action - check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_LYING|AB_CHECK_CONSCIOUS - button_icon_state = null - // If you want to override the normal icon being the item - // then change this to an icon state + build_all_button_icons(UPDATE_BUTTON_STATUS) -/datum/action/item_action/New(Target) - ..() - var/obj/item/I = target - LAZYINITLIST(I.actions) - I.actions += src - -/datum/action/item_action/Destroy() - var/obj/item/I = target - I.actions -= src - UNSETEMPTY(I.actions) - return ..() +/// Signal proc for COMSIG_MIND_TRANSFERRED - for minds, transfers our action to our new mob on mind transfer +/datum/action/proc/on_target_mind_swapped(datum/mind/source, mob/old_current) + SIGNAL_HANDLER -/datum/action/item_action/Trigger(trigger_flags) - . = ..() - if(!.) - return FALSE - if(target) - var/obj/item/I = target - I.ui_action_click(owner, src) - return TRUE + // Grant() calls Remove() from the existing owner so we're covered on that + Grant(source.current) -/datum/action/item_action/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force) - var/obj/item/item_target = target - if(button_icon && button_icon_state) - // If set, use the custom icon that we set instead - // of the item appearence - ..() - else if((target && current_button.appearance_cache != item_target.appearance) || force) //replace with /ref comparison if this is not valid. - var/old_layer = item_target.layer - var/old_plane = item_target.plane - item_target.layer = FLOAT_LAYER //AAAH - item_target.plane = FLOAT_PLANE //^ what that guy said - current_button.filters = null - current_button.cut_overlays() - current_button.add_overlay(item_target) - item_target.layer = old_layer - item_target.plane = old_plane - current_button.appearance_cache = item_target.appearance +/// Checks if our action is actively selected. Used for selecting icons primarily. +/datum/action/proc/is_action_active(atom/movable/screen/movable/action_button/current_button) + return FALSE + +/datum/action/proc/keydown(mob/source, key, client/client, full_key) + SIGNAL_HANDLER + if(isnull(full_key) || full_key != src.full_key) + return + if(istype(source)) + if(!source.CheckActionCooldown()) + return + else + source.DelayNextAction(1) + INVOKE_ASYNC(src, PROC_REF(Trigger)) /datum/action/item_action/toggle_light name = "Toggle Light" -/datum/action/item_action/toggle_light/pda/Trigger(trigger_flags) - if(istype(target, /obj/item/pda)) - var/obj/item/pda/P = target - return P.toggle_light(owner) +/datum/action/item_action/toggle_light/pda/do_effect(trigger_flags) + var/obj/item/pda/P = target + if(!istype(P)) + return FALSE + return P.toggle_light(owner) /datum/action/item_action/toggle_hood name = "Toggle Hood" /datum/action/item_action/toggle_firemode - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "fireselect_no" name = "Toggle Firemode" /datum/action/item_action/rcl_col name = "Change Cable Color" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "rcl_rainbow" /datum/action/item_action/rcl_gui name = "Toggle Fast Wiring Gui" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "rcl_gui" /datum/action/item_action/startchainsaw @@ -369,16 +473,11 @@ /datum/action/item_action/set_internals name = "Set Internals" default_button_position = SCRN_OBJ_INSERT_FIRST - button_overlay_state = "ab_goldborder" + overlay_icon_state = "ab_goldborder" -/datum/action/item_action/set_internals/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force) - if(!..()) // no button available - return - if(!iscarbon(owner)) - return - var/mob/living/carbon/C = owner - if(target == C.internal) - button.icon_state = "template_active" +/datum/action/item_action/set_internals/is_action_active(atom/movable/screen/movable/action_button/current_button) + var/mob/living/carbon/carbon_owner = owner + return istype(carbon_owner) && target == carbon_owner.internal /datum/action/item_action/pick_color name = "Choose A Color" @@ -395,67 +494,69 @@ /datum/action/item_action/toggle_welding_screen name = "Toggle Welding Screen" -/datum/action/item_action/toggle_welding_screen/Trigger() +/datum/action/item_action/toggle_welding_screen/do_effect(trigger_flags) var/obj/item/clothing/head/hardhat/weldhat/H = target - if(istype(H)) - H.toggle_welding_screen(owner) + if(!istype(H)) + return FALSE + H.toggle_welding_screen(owner) + return TRUE /datum/action/item_action/toggle_welding_screen/plasmaman -/datum/action/item_action/toggle_welding_screen/plasmaman/Trigger() +/datum/action/item_action/toggle_welding_screen/plasmaman/do_effect(trigger_flags) var/obj/item/clothing/head/helmet/space/plasmaman/H = target - if(istype(H)) - H.toggle_welding_screen(owner) + if(!istype(H)) + return FALSE + H.toggle_welding_screen(owner) + return TRUE /datum/action/item_action/toggle_headphones name = "Toggle Headphones" desc = "UNTZ UNTZ UNTZ" -/datum/action/item_action/toggle_headphones/Trigger() +/datum/action/item_action/toggle_headphones/do_effect(trigger_flags) var/obj/item/clothing/ears/headphones/H = target - if(istype(H)) - H.toggle(owner) + if(!istype(H)) + return FALSE + H.toggle(owner) + return TRUE /datum/action/item_action/toggle_unfriendly_fire name = "Toggle Friendly Fire \[ON\]" desc = "Toggles if the club's blasts cause friendly fire." - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "vortex_ff_on" -/datum/action/item_action/toggle_unfriendly_fire/Trigger() - if(..()) - UpdateButtons() +/datum/action/item_action/toggle_unfriendly_fire/update_button_name(atom/movable/screen/movable/action_button/button, force) + var/obj/item/hierophant_club/club = target + name = "Toggle Friendly Fire [club.friendly_fire_check ? "\[OFF\]" : "\[ON\]"]" + return ..() -/datum/action/item_action/toggle_unfriendly_fire/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force) - if(istype(target, /obj/item/hierophant_club)) - var/obj/item/hierophant_club/H = target - if(H.friendly_fire_check) - button_icon_state = "vortex_ff_off" - name = "Toggle Friendly Fire \[OFF\]" - else - button_icon_state = "vortex_ff_on" - name = "Toggle Friendly Fire \[ON\]" - ..() +/datum/action/item_action/toggle_unfriendly_fire/apply_button_icon(atom/movable/screen/movable/action_button/current_button, force) + var/obj/item/hierophant_club/club = target + button_icon_state = club.friendly_fire_check ? "vortex_ff_off" : "vortex_ff_on" + return ..() /datum/action/item_action/vortex_recall name = "Vortex Recall" desc = "Recall yourself, and anyone nearby, to an attuned hierophant beacon at any time.
If the beacon is still attached, will detach it." - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "vortex_recall" -/datum/action/item_action/vortex_recall/IsAvailable(silent = FALSE) - if(istype(target, /obj/item/hierophant_club)) - var/obj/item/hierophant_club/H = target - if(H.teleporting) - return FALSE +/datum/action/item_action/vortex_recall/IsAvailable(feedback = TRUE) + if(!istype(target, /obj/item/hierophant_club)) + return FALSE + var/obj/item/hierophant_club/teleport_stick = target + if(teleport_stick.teleporting) + return FALSE return ..() /datum/action/item_action/clock - icon_icon = 'icons/mob/actions/actions_clockcult.dmi' + button_icon = 'icons/mob/actions/actions_clockcult.dmi' background_icon_state = "bg_clock" buttontooltipstyle = "clockcult" -/datum/action/item_action/clock/IsAvailable(silent = FALSE) +/datum/action/item_action/clock/IsAvailable(feedback = TRUE) if(!is_servant_of_ratvar(owner)) return FALSE return ..() @@ -464,13 +565,14 @@ name = "Create Judicial Marker" desc = "Allows you to create a stunning Judicial Marker at any location in view. Click again to disable." -/datum/action/item_action/clock/toggle_visor/IsAvailable(silent = FALSE) +/datum/action/item_action/clock/toggle_visor/IsAvailable(feedback = TRUE) if(!is_servant_of_ratvar(owner)) return FALSE - if(istype(target, /obj/item/clothing/glasses/judicial_visor)) - var/obj/item/clothing/glasses/judicial_visor/V = target - if(V.recharging) - return FALSE + if(!istype(target, /obj/item/clothing/glasses/judicial_visor)) + return FALSE + var/obj/item/clothing/glasses/judicial_visor/goggles = target + if(goggles.recharging) + return FALSE return ..() /datum/action/item_action/clock/hierophant @@ -507,16 +609,13 @@ /datum/action/item_action/nano_picket_sign name = "Retext Nano Picket Sign" - var/obj/item/picket_sign/S - -/datum/action/item_action/nano_picket_sign/New(Target) - ..() - if(istype(Target, /obj/item/picket_sign)) - S = Target -/datum/action/item_action/nano_picket_sign/Trigger() - if(istype(S)) - S.retext(owner) +/datum/action/item_action/nano_picket_sign/do_effect(trigger_flags) + if(!istype(target, /obj/item/picket_sign)) + return FALSE + var/obj/item/picket_sign/sign = target + sign.retext(owner) + return TRUE /datum/action/item_action/adjust @@ -544,7 +643,7 @@ /datum/action/item_action/jetpack_stabilization name = "Toggle Jetpack Stabilization" -/datum/action/item_action/jetpack_stabilization/IsAvailable(silent = FALSE) +/datum/action/item_action/jetpack_stabilization/IsAvailable(feedback = TRUE) var/obj/item/tank/jetpack/J = target if(!istype(J) || !J.on) return FALSE @@ -567,19 +666,20 @@ /datum/action/item_action/toggle_research_scanner name = "Toggle Research Scanner" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "scan_mode" var/active = FALSE -/datum/action/item_action/toggle_research_scanner/Trigger() - if(IsAvailable()) - active = !active - if(active) - owner.research_scanner++ - else - owner.research_scanner-- - to_chat(owner, "[target] research scanner has been [active ? "activated" : "deactivated"].") - return TRUE +/datum/action/item_action/toggle_research_scanner/do_effect(trigger_flags) + if(!IsAvailable(feedback = TRUE)) + return FALSE + active = !active + if(active) + owner.research_scanner++ + else + owner.research_scanner-- + to_chat(owner, span_notice("[target] research scanner has been [active ? "activated" : "deactivated"].")) + return TRUE /datum/action/item_action/toggle_research_scanner/Remove(mob/M) if(owner && active) @@ -591,18 +691,18 @@ name = "Use Instrument" desc = "Use the instrument specified" -/datum/action/item_action/instrument/Trigger() - if(istype(target, /obj/item/instrument)) - var/obj/item/instrument/I = target - I.interact(usr) - return - return ..() +/datum/action/item_action/instrument/do_effect(trigger_flags) + if(!istype(target, /obj/item/instrument)) + return FALSE + var/obj/item/instrument/instrument = target + instrument.interact(usr) + return TRUE /datum/action/item_action/organ_action name = "Organ Action" check_flags = AB_CHECK_CONSCIOUS -/datum/action/item_action/organ_action/IsAvailable(silent = FALSE) +/datum/action/item_action/organ_action/IsAvailable(feedback) var/obj/item/organ/attached_organ = target if(!attached_organ.owner) return FALSE @@ -628,30 +728,41 @@ /datum/action/item_action/cult_dagger name = "Draw Blood Rune" desc = "Use the ritual dagger to create a powerful blood rune" - icon_icon = 'icons/mob/actions/actions_cult.dmi' + button_icon = 'icons/mob/actions/actions_cult.dmi' button_icon_state = "draw" buttontooltipstyle = "cult" background_icon_state = "bg_demon" default_button_position = "6:157,4:-2" -/datum/action/item_action/cult_dagger/Grant(mob/M) - if(!iscultist(M)) - Remove(owner) +/datum/action/item_action/cult_dagger/Grant(mob/grant_to) + if(!grant_to?.mind.has_antag_datum(grant_to, /datum/antagonist/cult)) return + return ..() -/datum/action/item_action/cult_dagger/Trigger() - for(var/obj/item/H in owner.held_items) //In case we were already holding another dagger - if(istype(H, /obj/item/melee/cultblade/dagger)) - H.attack_self(owner) - return - var/obj/item/I = target - if(owner.can_equip(I, ITEM_SLOT_HANDS)) - owner.temporarilyRemoveItemFromInventory(I) - owner.put_in_hands(I) - I.attack_self(owner) +/datum/action/item_action/cult_dagger/do_effect(trigger_flags) + if(!isliving(owner)) + to_chat(owner, span_warning("You lack the necessary living force for this action.")) + return FALSE + + var/obj/item/target_item = target + var/mob/living/living_owner = owner + if(target in owner.held_items) + target_item.attack_self(owner) + return TRUE + + if(owner.can_equip(target_item, ITEM_SLOT_HANDS)) + owner.temporarilyRemoveItemFromInventory(target_item) + owner.put_in_hands(target_item) + target_item.attack_self(owner) + return TRUE + + if (living_owner.get_num_arms()) + to_chat(living_owner, span_warning("You don't have any usable hands!")) else - to_chat(owner, "Your hands are full!") + to_chat(living_owner, span_warning("Your hands are full!")) + return FALSE + //MGS Box /datum/action/item_action/agent_box @@ -659,85 +770,88 @@ desc = "Find inner peace, here, in the box." check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS background_icon_state = "bg_agent" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "deploy_box" - var/cooldown = 0 var/boxtype = /obj/structure/closet/cardboard/agent + COOLDOWN_DECLARE(box_cooldown) //Handles open and closing the box -/datum/action/item_action/agent_box/Trigger() +/datum/action/item_action/agent_box/do_effect(trigger_flags) . = ..() if(!.) return FALSE if(istype(owner.loc, /obj/structure/closet/cardboard/agent)) var/obj/structure/closet/cardboard/agent/box = owner.loc - owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) - box.open() - return + if(box.open()) + owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) + return FALSE //Box closing from here on out. if(!isturf(owner.loc)) //Don't let the player use this to escape mechs/welded closets. - to_chat(owner, "You need more space to activate this implant.") - return - if(cooldown < world.time - 100) - var/box = new boxtype(owner.drop_location()) - owner.forceMove(box) - cooldown = world.time - owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) + to_chat(owner, span_warning("You need more space to activate this implant.")) + return FALSE + if(!COOLDOWN_FINISHED(src, box_cooldown)) + return FALSE + COOLDOWN_START(src, box_cooldown, 10 SECONDS) + var/box = new boxtype(owner.drop_location()) + owner.forceMove(box) + owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) /datum/action/item_action/removeAPCs name = "Relinquish APC" desc = "Let go of an APC, relinquish control back to the station." - icon_icon = 'icons/obj/implants.dmi' + button_icon = 'icons/obj/implants.dmi' button_icon_state = "hijackx" -/datum/action/item_action/removeAPCs/Trigger() +/datum/action/item_action/removeAPCs/do_effect(trigger_flags) var/list/areas = list() for (var/area/a in owner.siliconaccessareas) areas[a.name] = a var/removeAPC = input("Select an APC to remove:","Remove APC Control",1) as null|anything in areas if (!removeAPC) - return + return FALSE var/area/area = areas[removeAPC] var/obj/machinery/power/apc/apc = area.get_apc() if (!apc || !(area in owner.siliconaccessareas)) - return + return FALSE apc.hijacker = null apc.update_icon() apc.set_hijacked_lighting() owner.toggleSiliconAccessArea(area) + return TRUE /datum/action/item_action/accessAPCs name = "Access APC Interface" desc = "Open the APC's interface." - icon_icon = 'icons/obj/implants.dmi' + button_icon = 'icons/obj/implants.dmi' button_icon_state = "hijacky" -/datum/action/item_action/accessAPCs/Trigger() +/datum/action/item_action/accessAPCs/do_effect(trigger_flags) var/list/areas = list() for (var/area/a in owner.siliconaccessareas) areas[a.name] = a var/accessAPC = input("Select an APC to access:","Access APC Interface",1) as null|anything in areas if (!accessAPC) - return + return FALSE var/area/area = areas[accessAPC] var/obj/machinery/power/apc/apc = area.get_apc() if (!apc || !(area in owner.siliconaccessareas)) - return + return FALSE apc.ui_interact(owner) + return TRUE /datum/action/item_action/stealthmodetoggle name = "Toggle Stealth Mode" desc = "Toggles the stealth mode on the hijack implant." - icon_icon = 'icons/obj/implants.dmi' + button_icon = 'icons/obj/implants.dmi' button_icon_state = "hijackz" -/datum/action/item_action/stealthmodetoggle/Trigger() +/datum/action/item_action/stealthmodetoggle/do_effect(trigger_flags) var/obj/item/implant/hijack/H = target if (!istype(H)) - return + return FALSE if (H.stealthcooldown > world.time) - to_chat(owner,"The hijack implant's stealth mode toggle is still rebooting!") - return + to_chat(owner, span_warning("The hijack implant's stealth mode toggle is still rebooting!")) + return FALSE H.stealthmode = !H.stealthmode for (var/area/area in H.imp_in.siliconaccessareas) var/obj/machinery/power/apc/apc = area.get_apc() @@ -746,7 +860,8 @@ apc.update_icon() H.stealthcooldown = world.time + 15 SECONDS H.toggle_eyes() - to_chat(owner,"You toggle the hijack implant's stealthmode [H.stealthmode ? "on" : "off"].") + to_chat(owner, span_notice("You toggle the hijack implant's stealthmode [H.stealthmode ? "on" : "off"].")) + return TRUE /datum/action/item_action/flash name = "Flash" @@ -762,7 +877,7 @@ S.action = src name = S.name desc = S.desc - icon_icon = S.action_icon + button_icon = S.action_icon button_icon_state = S.action_icon_state background_icon_state = S.action_background_icon_state @@ -771,193 +886,57 @@ S.action = null return ..() -/datum/action/spell_action/Trigger() - if(!..()) +/datum/action/spell_action/Trigger(trigger_flags) + . = ..() + if(!.) return FALSE - if(target) - var/obj/effect/proc_holder/S = target - S.Trigger(usr) - return TRUE + if(!target) + return FALSE + var/obj/effect/proc_holder/S = target + return S.Trigger(usr) -/datum/action/spell_action/IsAvailable(silent = FALSE) +/datum/action/spell_action/IsAvailable(feedback = TRUE) if(!target) return FALSE return TRUE /datum/action/spell_action/spell -/datum/action/spell_action/spell/IsAvailable(silent = FALSE) +/datum/action/spell_action/spell/IsAvailable(feedback = TRUE) if(!target) return FALSE var/obj/effect/proc_holder/spell/S = target if(owner) - return S.can_cast(owner, FALSE, silent) + return S.can_cast(owner, FALSE, feedback) return FALSE /datum/action/spell_action/alien -/datum/action/spell_action/alien/IsAvailable(silent = FALSE) +/datum/action/spell_action/alien/IsAvailable(feedback = TRUE) if(!target) return FALSE var/obj/effect/proc_holder/alien/ab = target if(owner) - return ab.cost_check(ab.check_turf,owner,silent) + return ab.cost_check(ab.check_turf,owner, feedback) return FALSE - - -//Preset for general and toggled actions -/datum/action/innate - check_flags = NONE - required_mobility_flags = NONE - var/active = 0 - -/datum/action/innate/Trigger() - if(!..()) - return FALSE - if(!active) - Activate() - else - Deactivate() - return TRUE - -/datum/action/innate/proc/Activate() - return - -/datum/action/innate/proc/Deactivate() - return - -//Preset for an action with a cooldown - -/datum/action/cooldown - check_flags = 0 - transparent_when_unavailable = FALSE - // The default cooldown applied when StartCooldown() is called - var/cooldown_time = 0 - // The actual next time this ability can be used - var/next_use_time = 0 - // Whether or not you want the cooldown for the ability to display in text form - var/text_cooldown = TRUE - // Setting for intercepting clicks before activating the ability - var/click_to_activate = FALSE - // Shares cooldowns with other cooldown abilities of the same value, not active if null - var/shared_cooldown - -/datum/action/cooldown/CreateButton() - var/atom/movable/screen/movable/action_button/button = ..() - button.maptext = "" - button.maptext_x = 8 - button.maptext_y = 0 - button.maptext_width = 24 - button.maptext_height = 12 - return button - -/datum/action/cooldown/IsAvailable() - return ..() && (next_use_time <= world.time) - -/// Starts a cooldown time to be shared with similar abilities, will use default cooldown time if an override is not specified -/datum/action/cooldown/proc/StartCooldown(override_cooldown_time) - if(shared_cooldown) - for(var/datum/action/cooldown/shared_ability in owner.actions - src) - if(shared_cooldown == shared_ability.shared_cooldown) - if(isnum(override_cooldown_time)) - shared_ability.StartCooldownSelf(override_cooldown_time) - else - shared_ability.StartCooldownSelf(cooldown_time) - StartCooldownSelf(override_cooldown_time) - -/// Starts a cooldown time for this ability only, will use default cooldown time if an override is not specified -/datum/action/cooldown/proc/StartCooldownSelf(override_cooldown_time) - if(isnum(override_cooldown_time)) - next_use_time = world.time + override_cooldown_time - else - next_use_time = world.time + cooldown_time - UpdateButtons() - START_PROCESSING(SSfastprocess, src) - -/datum/action/cooldown/Trigger(trigger_flags, atom/target) - . = ..() - if(!.) - return - if(!owner) - return FALSE - if(click_to_activate) - if(target) - // For automatic / mob handling - return InterceptClickOn(owner, null, target) - if(owner.click_intercept == src) - owner.click_intercept = null - else - owner.click_intercept = src - for(var/datum/action/cooldown/ability in owner.actions) - ability.UpdateButtons() - return TRUE - return PreActivate(owner) - -/// Intercepts client owner clicks to activate the ability -/datum/action/cooldown/proc/InterceptClickOn(mob/living/caller, params, atom/target) - if(!IsAvailable()) - return FALSE - if(!target) - return FALSE - PreActivate(target) - caller.click_intercept = null - return TRUE - -/// For signal calling -/datum/action/cooldown/proc/PreActivate(atom/target) - if(SEND_SIGNAL(owner, COMSIG_MOB_ABILITY_STARTED, src) & COMPONENT_BLOCK_ABILITY_START) - return - . = Activate(target) - SEND_SIGNAL(owner, COMSIG_MOB_ABILITY_FINISHED, src) - -/// To be implemented by subtypes -/datum/action/cooldown/proc/Activate(atom/target) - return - -/datum/action/cooldown/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE) - . = ..() - if(!button) - return - var/time_left = max(next_use_time - world.time, 0) - if(text_cooldown) - button.maptext = MAPTEXT("[round(time_left/10, 0.1)]") - if(!owner || time_left == 0) - button.maptext = "" - if(IsAvailable() && owner.click_intercept == src) - button.color = COLOR_GREEN - -/datum/action/cooldown/process() - var/time_left = max(next_use_time - world.time, 0) - if(!owner || time_left == 0) - STOP_PROCESSING(SSfastprocess, src) - UpdateButtons() - -/datum/action/cooldown/Grant(mob/M) - ..() - if(!owner) - return - UpdateButtons() - if(next_use_time > world.time) - START_PROCESSING(SSfastprocess, src) - //surf_ss13 /datum/action/item_action/bhop name = "Activate Jump Boots" desc = "Activates the jump boot's internal propulsion system, allowing the user to dash over 4-wide gaps." - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "jetboot" /datum/action/item_action/wheelys name = "Toggle Wheely-Heel's Wheels" desc = "Pops out or in your wheely-heel's wheels." - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "wheelys" /datum/action/item_action/kindleKicks name = "Activate Kindle Kicks" desc = "Kick you feet together, activating the lights in your Kindle Kicks." - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "kindleKicks" //Small sprites @@ -987,8 +966,10 @@ /datum/action/small_sprite/megafauna/legion small_icon_state = "mega_legion" -/datum/action/small_sprite/Trigger() - ..() +/datum/action/small_sprite/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!small) var/image/I = image(icon = small_icon, icon_state = small_icon_state, loc = owner) I.override = TRUE @@ -999,11 +980,12 @@ else owner.remove_alt_appearance("smallsprite") small = FALSE + return TRUE /datum/action/item_action/storage_gather_mode name = "Switch gathering mode" desc = "Switches the gathering mode of a storage object." - button_icon = 'icons/mob/actions/actions_items.dmi' + background_icon = 'icons/mob/actions/actions_items.dmi' background_icon_state = "storage_gather_switch" /proc/get_action_of_type(mob/M, action_type) diff --git a/code/datums/actions/beam_rifle.dm b/code/datums/actions/beam_rifle.dm index 3af5d13690d0..23e19d5832d7 100644 --- a/code/datums/actions/beam_rifle.dm +++ b/code/datums/actions/beam_rifle.dm @@ -1,12 +1,12 @@ /datum/action/item_action/zoom_speed_action name = "Toggle Zooming Speed" - icon_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon = 'icons/mob/actions/actions_spells.dmi' button_icon_state = "projectile" background_icon_state = "bg_tech" /datum/action/item_action/zoom_lock_action name = "Switch Zoom Mode" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "zoom_mode" background_icon_state = "bg_tech" diff --git a/code/datums/actions/cooldown_action.dm b/code/datums/actions/cooldown_action.dm new file mode 100644 index 000000000000..d590fa3bc035 --- /dev/null +++ b/code/datums/actions/cooldown_action.dm @@ -0,0 +1,153 @@ +#define COOLDOWN_NO_DISPLAY_TIME (180 SECONDS) + +/// Preset for an action with a cooldown +/datum/action/cooldown + check_flags = 0 + transparent_when_unavailable = FALSE + /// The default cooldown applied when StartCooldown() is called + var/cooldown_time = 0 + /// The actual next time this ability can be used + var/next_use_time = 0 + /// Whether or not you want the cooldown for the ability to display in text form + var/text_cooldown = TRUE + /// Significant figures to round cooldown to + var/cooldown_rounding = 0.1 + /// Setting for intercepting clicks before activating the ability + var/click_to_activate = FALSE + /// Shares cooldowns with other cooldown abilities of the same value, not active if null + var/shared_cooldown + /// The base icon_state of this action's background + var/base_background_icon_state + /// The icon state the background uses when active + var/active_background_icon_state + /// The base icon_state of the overlay we apply + var/base_overlay_icon_state + /// The active icon_state of the overlay we apply + var/active_overlay_icon_state + /// The base icon state of the spell's button icon, used for editing the icon "off" + var/base_icon_state + /// The active icon state of the spell's button icon, used for editing the icon "on" + var/active_icon_state + +/datum/action/cooldown/create_button() + var/atom/movable/screen/movable/action_button/button = ..() + button.maptext = "" + button.maptext_x = 8 + button.maptext_y = 0 + button.maptext_width = 24 + button.maptext_height = 12 + return button + +/datum/action/cooldown/update_button_status(atom/movable/screen/movable/action_button/button, force = FALSE) + . = ..() + var/time_left = max(next_use_time - world.time, 0) + if(!text_cooldown || !owner || time_left == 0 || time_left >= COOLDOWN_NO_DISPLAY_TIME) + button.maptext = "" + else + if (cooldown_rounding > 0) + button.maptext = MAPTEXT_TINY_UNICODE("[round(time_left/10, cooldown_rounding)]") + else + button.maptext = MAPTEXT_TINY_UNICODE("[round(time_left/10)]") + + if(!IsAvailable() || !is_action_active(button)) + return + // If we don't change the icon state, or don't apply a special overlay, + if(active_background_icon_state || active_icon_state || active_overlay_icon_state) + return + // ...we need to show it's active somehow. So, make it greeeen + button.color = COLOR_GREEN + +/datum/action/cooldown/apply_button_background(atom/movable/screen/movable/action_button/current_button, force) + if(active_background_icon_state) + background_icon_state = is_action_active(current_button) ? active_background_icon_state : base_background_icon_state + return ..() + +/datum/action/cooldown/apply_button_icon(atom/movable/screen/movable/action_button/current_button, force) + if(active_icon_state) + button_icon_state = is_action_active(current_button) ? active_icon_state : base_icon_state + return ..() + +/datum/action/cooldown/apply_button_overlay(atom/movable/screen/movable/action_button/current_button, force) + if(active_overlay_icon_state) + overlay_icon_state = is_action_active(current_button) ? active_overlay_icon_state : base_overlay_icon_state + return ..() + +/datum/action/cooldown/is_action_active(atom/movable/screen/movable/action_button/current_button) + return click_to_activate && current_button.our_hud?.mymob?.click_intercept == src + +/datum/action/cooldown/IsAvailable(feedback = FALSE) + return ..() && (next_use_time <= world.time) + +/// Starts a cooldown time to be shared with similar abilities, will use default cooldown time if an override is not specified +/datum/action/cooldown/proc/StartCooldown(override_cooldown_time) + if(shared_cooldown) + for(var/datum/action/cooldown/shared_ability in owner.actions - src) + if(shared_cooldown == shared_ability.shared_cooldown) + if(isnum(override_cooldown_time)) + shared_ability.StartCooldownSelf(override_cooldown_time) + else + shared_ability.StartCooldownSelf(cooldown_time) + StartCooldownSelf(override_cooldown_time) + +/// Starts a cooldown time for this ability only, will use default cooldown time if an override is not specified +/datum/action/cooldown/proc/StartCooldownSelf(override_cooldown_time) + if(isnum(override_cooldown_time)) + next_use_time = world.time + override_cooldown_time + else + next_use_time = world.time + cooldown_time + build_all_button_icons() + START_PROCESSING(SSfastprocess, src) + +/datum/action/cooldown/Trigger(trigger_flags, atom/target) + . = ..() + if(!.) + return + if(!owner) + return FALSE + if(click_to_activate) + if(target) + // For automatic / mob handling + return InterceptClickOn(owner, null, target) + if(owner.click_intercept == src) + owner.click_intercept = null + else + owner.click_intercept = src + for(var/datum/action/cooldown/ability in owner.actions) + ability.build_all_button_icons() + return TRUE + return PreActivate(owner) + +/// Intercepts client owner clicks to activate the ability +/datum/action/cooldown/proc/InterceptClickOn(mob/living/caller, params, atom/target) + if(!IsAvailable(feedback = TRUE)) + return FALSE + if(!target) + return FALSE + PreActivate(target) + caller.click_intercept = null + return TRUE + +/// For signal calling +/datum/action/cooldown/proc/PreActivate(atom/target) + if(SEND_SIGNAL(owner, COMSIG_MOB_ABILITY_STARTED, src) & COMPONENT_BLOCK_ABILITY_START) + return + . = Activate(target) + SEND_SIGNAL(owner, COMSIG_MOB_ABILITY_FINISHED, src) + +/// To be implemented by subtypes +/datum/action/cooldown/proc/Activate(atom/target) + return + +/datum/action/cooldown/process() + var/time_left = max(next_use_time - world.time, 0) + if(!owner || time_left == 0) + STOP_PROCESSING(SSfastprocess, src) + build_all_button_icons() + +/datum/action/cooldown/Grant(mob/M) + ..() + if(!owner) + return + build_all_button_icons() + if(next_use_time > world.time) + START_PROCESSING(SSfastprocess, src) diff --git a/code/datums/actions/flightsuit.dm b/code/datums/actions/flightsuit.dm index 205b72cfae23..b5c67a105958 100644 --- a/code/datums/actions/flightsuit.dm +++ b/code/datums/actions/flightsuit.dm @@ -1,117 +1,126 @@ /datum/action/item_action/flightsuit - icon_icon = 'icons/mob/actions/actions_flightsuit.dmi' + button_icon = 'icons/mob/actions/actions_flightsuit.dmi' /datum/action/item_action/flightsuit/toggle_boots name = "Toggle Boots" button_icon_state = "flightsuit_shoes" background_icon_state = "bg_tech" -/datum/action/item_action/flightsuit/toggle_boots/Trigger() +/datum/action/item_action/flightsuit/toggle_boots/do_effect(trigger_flags) var/obj/item/clothing/suit/space/hardsuit/flightsuit/FS = target - if(istype(FS)) - FS.deployedshoes? FS.retract_flightshoes() : FS.extend_flightshoes() - return ..() + if(!istype(FS)) + return FALSE + FS.deployedshoes? FS.retract_flightshoes() : FS.extend_flightshoes() + return TRUE /datum/action/item_action/flightsuit/toggle_helmet name = "Toggle Helmet" button_icon_state = "flightsuit_helmet" background_icon_state = "bg_tech" -/datum/action/item_action/flightsuit/toggle_helmet/Trigger() +/datum/action/item_action/flightsuit/toggle_helmet/do_effect(trigger_flags) var/obj/item/clothing/suit/space/hardsuit/flightsuit/FS = target - if(istype(FS)) - FS.ToggleHelmet() - return ..() + if(!istype(FS)) + return FALSE + FS.ToggleHelmet() /datum/action/item_action/flightsuit/toggle_flightpack name = "Toggle Flightpack" button_icon_state = "flightsuit_pack" background_icon_state = "bg_tech" -/datum/action/item_action/flightsuit/toggle_flightpack/Trigger() +/datum/action/item_action/flightsuit/toggle_flightpack/do_effect(trigger_flags) var/obj/item/clothing/suit/space/hardsuit/flightsuit/FS = target - if(istype(FS)) - FS.deployedpack? FS.retract_flightpack() : FS.extend_flightpack() - return ..() + if(!istype(FS)) + return FALSE + FS.deployedpack? FS.retract_flightpack() : FS.extend_flightpack() + return TRUE /datum/action/item_action/flightsuit/lock_suit name = "Lock Suit" button_icon_state = "flightsuit_lock" background_icon_state = "bg_tech" -/datum/action/item_action/flightsuit/lock_suit/Trigger() +/datum/action/item_action/flightsuit/lock_suit/do_effect(trigger_flags) var/obj/item/clothing/suit/space/hardsuit/flightsuit/FS = target - if(istype(FS)) - FS.locked? FS.unlock_suit(owner) : FS.lock_suit(owner) - return ..() + if(!istype(FS)) + return FALSE + FS.locked? FS.unlock_suit(owner) : FS.lock_suit(owner) + return TRUE /datum/action/item_action/flightpack - icon_icon = 'icons/mob/actions/actions_flightsuit.dmi' + button_icon = 'icons/mob/actions/actions_flightsuit.dmi' /datum/action/item_action/flightpack/toggle_flight name = "Toggle Flight" button_icon_state = "flightpack_fly" background_icon_state = "bg_tech_blue" -/datum/action/item_action/flightpack/toggle_flight/Trigger() +/datum/action/item_action/flightpack/toggle_flight/do_effect(trigger_flags) var/obj/item/flightpack/F = target - if(istype(F)) - F.flight? F.disable_flight() : F.enable_flight() - return ..() + if(!istype(F)) + return FALSE + F.flight? F.disable_flight() : F.enable_flight() + return TRUE /datum/action/item_action/flightpack/engage_boosters name = "Toggle Boosters" button_icon_state = "flightpack_boost" background_icon_state = "bg_tech_blue" -/datum/action/item_action/flightpack/engage_boosters/Trigger() +/datum/action/item_action/flightpack/engage_boosters/do_effect(trigger_flags) var/obj/item/flightpack/F = target - if(istype(F)) - F.boost? F.deactivate_booster() : F.activate_booster() - return ..() + if(!istype(F)) + return FALSE + F.boost? F.deactivate_booster() : F.activate_booster() + return TRUE /datum/action/item_action/flightpack/toggle_stabilizers name = "Toggle Stabilizers" button_icon_state = "flightpack_stabilizer" background_icon_state = "bg_tech_blue" -/datum/action/item_action/flightpack/toggle_stabilizers/Trigger() +/datum/action/item_action/flightpack/toggle_stabilizers/do_effect(trigger_flags) var/obj/item/flightpack/F = target - if(istype(F)) - F.stabilizer? F.disable_stabilizers() : F.enable_stabilizers() - return ..() + if(!istype(F)) + return FALSE + F.stabilizer? F.disable_stabilizers() : F.enable_stabilizers() + return TRUE /datum/action/item_action/flightpack/change_power name = "Flight Power Setting" button_icon_state = "flightpack_power" background_icon_state = "bg_tech_blue" -/datum/action/item_action/flightpack/change_power/Trigger() +/datum/action/item_action/flightpack/change_power/do_effect(trigger_flags) var/obj/item/flightpack/F = target - if(istype(F)) - F.cycle_power() - return ..() + if(!istype(F)) + return FALSE + F.cycle_power() + return TRUE /datum/action/item_action/flightpack/toggle_airbrake name = "Toggle Airbrake" button_icon_state = "flightpack_airbrake" background_icon_state = "bg_tech_blue" -/datum/action/item_action/flightpack/toggle_airbrake/Trigger() +/datum/action/item_action/flightpack/toggle_airbrake/do_effect(trigger_flags) var/obj/item/flightpack/F = target - if(istype(F)) - F.brake? F.disable_airbrake() : F.enable_airbrake() - return ..() + if(!istype(F)) + return FALSE + F.brake? F.disable_airbrake() : F.enable_airbrake() + return TRUE /datum/action/item_action/flightpack/zoom name = "Helmet Smart Zoom" - icon_icon = 'icons/mob/actions.dmi' + button_icon = 'icons/mob/actions.dmi' background_icon_state = "bg_tech_blue" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "sniper_zoom" -/datum/action/item_action/flightpack/zoom/Trigger() +/datum/action/item_action/flightpack/zoom/do_effect(trigger_flags) var/obj/item/clothing/head/helmet/space/hardsuit/flightsuit/FH = target - if(istype(FH)) + if(!istype(FH)) + return FALSE FH.toggle_zoom(owner) - return ..() + return TRUE diff --git a/code/datums/actions/innate_action.dm b/code/datums/actions/innate_action.dm new file mode 100644 index 000000000000..c7ff4830a434 --- /dev/null +++ b/code/datums/actions/innate_action.dm @@ -0,0 +1,28 @@ +//Preset for general and toggled actions +/datum/action/innate + check_flags = NONE + required_mobility_flags = NONE + /// Whether we're active or not, if we're a innate - toggle action. + var/active = FALSE + +/datum/action/innate/Trigger(trigger_flags) + if(!..()) + return FALSE + var/active_status = active + if(active_status) + Deactivate() + else + Activate() + + if(active != active_status) + build_all_button_icons(UPDATE_BUTTON_STATUS) + return TRUE + +/datum/action/innate/is_action_active(atom/movable/screen/movable/action_button/current_button) + return active + +/datum/action/innate/proc/Activate() + return + +/datum/action/innate/proc/Deactivate() + return diff --git a/code/datums/actions/item_action.dm b/code/datums/actions/item_action.dm new file mode 100644 index 000000000000..5ba78f1da81c --- /dev/null +++ b/code/datums/actions/item_action.dm @@ -0,0 +1,37 @@ +//Presets for item actions +/datum/action/item_action + name = "Item Action" + check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS + button_icon_state = null + +/datum/action/item_action/New(Target) + . = ..() + + // If our button state is null, use the target's icon instead + if(target && isnull(button_icon_state)) + AddComponent(/datum/component/action_item_overlay, target) + +/datum/action/item_action/vv_edit_var(var_name, var_value) + . = ..() + if(!. || !target) + return + + if(var_name == NAMEOF(src, button_icon_state)) + // If someone vv's our icon either add or remove the component + if(isnull(var_name)) + AddComponent(/datum/component/action_item_overlay, target) + else + qdel(GetComponent(/datum/component/action_item_overlay)) + +/datum/action/item_action/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + return do_effect(trigger_flags) + +/datum/action/item_action/proc/do_effect(trigger_flags) + if(!target) + return FALSE + var/obj/item/item_target = target + item_target.ui_action_click(owner, src) + return TRUE diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index 38e187845198..7197211c22bb 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -200,7 +200,7 @@ /datum/action/innate/imaginary_join name = "Join" desc = "Join your owner, following them from inside their mind." - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' background_icon_state = "bg_revenant" button_icon_state = "join" @@ -211,7 +211,7 @@ /datum/action/innate/imaginary_hide name = "Hide" desc = "Hide yourself from your owner's sight." - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' background_icon_state = "bg_revenant" button_icon_state = "hide" @@ -225,7 +225,7 @@ name = "Hide" desc = "Hide yourself from your owner's sight." button_icon_state = "hide" - UpdateButtons() + build_all_button_icons() /datum/action/innate/imaginary_hide/Activate() var/mob/camera/imaginary_friend/I = owner diff --git a/code/datums/components/action_item_overlay.dm b/code/datums/components/action_item_overlay.dm new file mode 100644 index 000000000000..80478aa9ca42 --- /dev/null +++ b/code/datums/components/action_item_overlay.dm @@ -0,0 +1,79 @@ +/** + * Apply to an action to allow it to take an item + * and apply it as an overlay of the action button + */ +/datum/component/action_item_overlay + /// Weakref to what item the component uses to apply as an overlay. + var/datum/weakref/item_ref + /// Callback that dictates what item the component uses to apply as an overlay. + var/datum/callback/item_callback + + /// The appearance of the item we've applied + var/mutable_appearance/item_appearance + +/datum/component/action_item_overlay/Initialize(atom/movable/item, datum/callback/item_callback) + if(!istype(parent, /datum/action)) + return COMPONENT_INCOMPATIBLE + + ASSERT(isnull(item) || istype(item)) + + if(!item && !item_callback) + stack_trace("[type] created without a reference item or an item callback - one or the other is required.") + return COMPONENT_INCOMPATIBLE + + src.item_ref = WEAKREF(item) + src.item_callback = item_callback + +/datum/component/action_item_overlay/Destroy(force) + item_ref = null + item_callback = null + item_appearance = null + return ..() + +/datum/component/action_item_overlay/RegisterWithParent() + RegisterSignal(parent, COMSIG_ACTION_OVERLAY_APPLY, PROC_REF(on_overlays_applied)) + + var/datum/action/parent_action = parent + parent_action.build_all_button_icons(UPDATE_BUTTON_OVERLAY) + +/datum/component/action_item_overlay/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_ACTION_OVERLAY_APPLY) + + // If we're being unregistered / deleted but our parent is sticking around, + // force an overlay update to get rid of our item appearance + if(!QDELING(parent)) + var/datum/action/parent_action = parent + parent_action.build_all_button_icons(UPDATE_BUTTON_OVERLAY) + +/// Signal proc for [COMSIG_ACTION_OVERLAY_APPLY], applies the item appearance if possible. +/datum/component/action_item_overlay/proc/on_overlays_applied(datum/action/source, atom/movable/screen/movable/action_button/current_button, force) + SIGNAL_HANDLER + + // We're in the middle of being removed / deleted, remove our associated overlay + if(QDELING(src)) + if(item_appearance) + current_button.cut_overlay(item_appearance) + item_appearance = null + return + + var/atom/movable/muse = item_callback?.Invoke() || item_ref?.resolve() + if(!istype(muse)) + if(item_appearance) // New item does not exist but we have an old appearance + current_button.cut_overlay(item_appearance) + item_appearance = null + return + + if(item_appearance) + // For caching purposes, we will try not to update if we don't need to + if(!force && item_appearance.icon == muse.icon && item_appearance.icon_state == muse.icon_state) + return + current_button.cut_overlay(item_appearance) + + var/mutable_appearance/muse_appearance = new(muse.appearance) + muse_appearance.plane = FLOAT_PLANE + muse_appearance.layer = FLOAT_LAYER + muse_appearance.pixel_x = 0 + muse_appearance.pixel_y = 0 + + current_button.add_overlay(muse_appearance) + item_appearance = muse_appearance diff --git a/code/datums/components/dullahan.dm b/code/datums/components/dullahan.dm index 0d1b8fe21957..596e9af3cba6 100644 --- a/code/datums/components/dullahan.dm +++ b/code/datums/components/dullahan.dm @@ -151,8 +151,10 @@ name = "Toggle Perspective" desc = "Switch between seeing normally from your head, or blindly from your body." -/datum/action/item_action/organ_action/dullahan/Trigger() +/datum/action/item_action/organ_action/dullahan/do_effect(trigger_flags) . = ..() + if(!.) + return var/mob/living/carbon/human/H = owner var/obj/item/organ/eyes/E = owner.getorganslot(ORGAN_SLOT_EYES) if(E) @@ -162,13 +164,14 @@ E.tint = INFINITY var/datum/component/dullahan/D = H.GetComponent(/datum/component/dullahan) - if(D) - D.update_vision_perspective() + if(!D) + return FALSE + return D.update_vision_perspective() /datum/component/dullahan/proc/update_vision_perspective() var/mob/living/carbon/human/H = parent if(!H) - return . + return FALSE var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES) if(eyes) H.update_tint() @@ -176,6 +179,7 @@ H.reset_perspective(H) else H.reset_perspective(dullahan_head) + return TRUE /datum/component/dullahan/Destroy() UnregisterSignal(parent, COMSIG_LIVING_REGENERATE_LIMBS) diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index cde8a09e8a6e..91b252a68b6b 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -133,7 +133,7 @@ if(!isitem(parent) || !allow_quick_gather) return var/obj/item/I = parent - modeswitch_action = new(I) + modeswitch_action = I.add_item_action(/datum/action/item_action/storage_gather_mode) RegisterSignal(modeswitch_action, COMSIG_ACTION_TRIGGER, PROC_REF(action_trigger)) if(I.obj_flags & IN_INVENTORY) var/mob/M = I.loc diff --git a/code/datums/dash_weapon.dm b/code/datums/dash_weapon.dm index adf7b72c1129..cd37ac5dc191 100644 --- a/code/datums/dash_weapon.dm +++ b/code/datums/dash_weapon.dm @@ -1,7 +1,7 @@ /datum/action/innate/dash name = "Dash" desc = "Teleport to the targeted location." - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "jetboot" var/current_charges = 1 var/max_charges = 1 @@ -17,7 +17,7 @@ . = ..() dashing_item = dasher -/datum/action/innate/dash/IsAvailable(silent = FALSE) +/datum/action/innate/dash/IsAvailable(feedback = TRUE) if(current_charges > 0) return TRUE else @@ -27,7 +27,7 @@ dashing_item.attack_self(owner) //Used to toggle dash behavior in the dashing item /datum/action/innate/dash/proc/Teleport(mob/user, atom/target) - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return var/turf/T = get_turf(target) if(target in view(user.client.view, user)) @@ -36,12 +36,12 @@ var/obj/spot2 = new phasein(get_turf(user), user.dir) spot1.Beam(spot2,beam_effect,time=20) current_charges-- - owner.update_action_buttons_icon() + owner.update_mob_action_buttons() addtimer(CALLBACK(src, PROC_REF(charge)), charge_rate) /datum/action/innate/dash/proc/charge() current_charges = clamp(current_charges + 1, 0, max_charges) - owner.update_action_buttons_icon() + owner.update_mob_action_buttons() if(recharge_sound) playsound(dashing_item, recharge_sound, 50, 1) to_chat(owner, "[src] now has [current_charges]/[max_charges] charges.") diff --git a/code/datums/elements/polychromic.dm b/code/datums/elements/polychromic.dm index bc6a6dd1da33..18cfac99f887 100644 --- a/code/datums/elements/polychromic.dm +++ b/code/datums/elements/polychromic.dm @@ -41,8 +41,9 @@ RegisterSignal(A, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(apply_overlays)) if(_flags & POLYCHROMIC_ALTCLICK) - RegisterSignal(A, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(A, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_requesting_context_from_item)) RegisterSignal(A, COMSIG_CLICK_ALT, PROC_REF(set_color)) + RegisterSignal(A, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine)) if(!overlays_names && names) //generate overlays_names = names @@ -77,7 +78,7 @@ if(P) actions_by_atom -= A qdel(P) - UnregisterSignal(A, list(COMSIG_PARENT_EXAMINE, COMSIG_CLICK_ALT, COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_ITEM_WORN_OVERLAYS, COMSIG_SUIT_MADE_HELMET)) + UnregisterSignal(A, list(COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, COMSIG_ATOM_UPDATE_OVERLAYS, COMSIG_CLICK_ALT, COMSIG_PARENT_EXAMINE, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_ITEM_WORN_OVERLAYS, COMSIG_SUIT_MADE_HELMET)) if(isitem(A)) var/obj/item/clothing/head/H = helmet_by_suit[A] if(H) @@ -161,9 +162,21 @@ /datum/element/polychromic/proc/activate_action(datum/action/source, atom/target) set_color(target, source.owner) + return COMPONENT_ACTION_BLOCK_TRIGGER /datum/element/polychromic/proc/on_examine(atom/source, mob/user, list/examine_list) - examine_list += "Alt-click to recolor it." + examine_list += span_notice("Alt-click to recolor it.") + +/datum/element/polychromic/proc/on_requesting_context_from_item( + obj/source, + list/context, + obj/item/held_item, + mob/living/user, +) + SIGNAL_HANDLER + + LAZYSET(context[SCREENTIP_CONTEXT_ALT_LMB], INTENT_ANY, "Modify [source]'\s Colors") + return CONTEXTUAL_SCREENTIP_SET /datum/element/polychromic/proc/connect_helmet(atom/I, var/applycolor) if(isitem(I)) @@ -203,7 +216,7 @@ button_icon_state = null check_flags = NONE -/datum/action/item_action/polychromic/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force) +/datum/action/item_action/polychromic/apply_button_icon(atom/movable/screen/movable/action_button/current_button, force = FALSE) var/atom/polychromic_thing = target var/matrix/save_matrix = polychromic_thing.transform diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index bb033c10c9f2..ac627bc3f341 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -198,7 +198,7 @@ /datum/action/innate/end_holocall name = "End Holocall" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "camera_off" var/datum/holocall/hcall diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index d91e802a8aa6..dac11a0e86b3 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -8,63 +8,90 @@ /datum/action/neck_chop name = "Neck Chop - Injures the neck, stopping the victim from speaking for a while." - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "neckchop" -/datum/action/neck_chop/Trigger() - if(owner.incapacitated()) - to_chat(owner, "You can't use [name] while you're incapacitated.") - return +/datum/action/neck_chop/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE var/mob/living/carbon/human/H = owner if (H.mind.martial_art.streak == "neck_chop") owner.visible_message("[owner] assumes a neutral stance.", "Your next attack is cleared.") H.mind.martial_art.streak = "" else - if(HAS_TRAIT(H, TRAIT_PACIFISM)) - to_chat(H, "You don't want to harm other people!") - return owner.visible_message("[owner] assumes the Neck Chop stance!", "Your next attack will be a Neck Chop.") H.mind.martial_art.streak = "neck_chop" + return TRUE + +/datum/action/neck_chop/IsAvailable(feedback) + if(owner.incapacitated()) + if(feedback) + to_chat(owner, "You can't use [name] while you're incapacitated.") + return FALSE + if(HAS_TRAIT(owner, TRAIT_PACIFISM)) + if(feedback) + to_chat(owner, "You don't want to harm other people!") + return FALSE + return ..() /datum/action/leg_sweep name = "Leg Sweep - Trips the victim, knocking them down for a brief moment." - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "legsweep" -/datum/action/leg_sweep/Trigger() - if(owner.incapacitated()) - to_chat(owner, "You can't use [name] while you're incapacitated.") - return +/datum/action/leg_sweep/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE var/mob/living/carbon/human/H = owner if (H.mind.martial_art.streak == "leg_sweep") owner.visible_message("[owner] assumes a neutral stance.", "Your next attack is cleared.") H.mind.martial_art.streak = "" else - if(HAS_TRAIT(H, TRAIT_PACIFISM)) - to_chat(H, "You don't want to harm other people!") - return owner.visible_message("[owner] assumes the Leg Sweep stance!", "Your next attack will be a Leg Sweep.") H.mind.martial_art.streak = "leg_sweep" + return TRUE + +/datum/action/leg_sweep/IsAvailable(feedback) + if(owner.incapacitated()) + if(feedback) + to_chat(owner, "You can't use [name] while you're incapacitated.") + return FALSE + if(HAS_TRAIT(owner, TRAIT_PACIFISM)) + if(feedback) + to_chat(owner, "You don't want to harm other people!") + return FALSE + return ..() /datum/action/lung_punch//referred to internally as 'quick choke' name = "Lung Punch - Delivers a strong punch just above the victim's abdomen, constraining the lungs. The victim will be unable to breathe for a short time." - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "lungpunch" -/datum/action/lung_punch/Trigger() - if(owner.incapacitated()) - to_chat(owner, "You can't use [name] while you're incapacitated.") - return +/datum/action/lung_punch/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE var/mob/living/carbon/human/H = owner if (H.mind.martial_art.streak == "quick_choke") owner.visible_message("[owner] assumes a neutral stance.", "Your next attack is cleared.") H.mind.martial_art.streak = "" else - if(HAS_TRAIT(H, TRAIT_PACIFISM)) - to_chat(H, "You don't want to harm other people!") - return owner.visible_message("[owner] assumes the Lung Punch stance!", "Your next attack will be a Lung Punch.") H.mind.martial_art.streak = "quick_choke"//internal name for lung punch + return TRUE + +/datum/action/lung_punch/IsAvailable(feedback) + if(owner.incapacitated()) + if(feedback) + to_chat(owner, "You can't use [name] while you're incapacitated.") + return FALSE + if(HAS_TRAIT(owner, TRAIT_PACIFISM)) + if(feedback) + to_chat(owner, "You don't want to harm other people!") + return FALSE + return ..() /datum/martial_art/krav_maga/teach(mob/living/carbon/human/H,make_temporary=0) if(..()) diff --git a/code/datums/martial/rising_bass.dm b/code/datums/martial/rising_bass.dm index 87c0d42a2975..d36cead055f4 100644 --- a/code/datums/martial/rising_bass.dm +++ b/code/datums/martial/rising_bass.dm @@ -41,24 +41,33 @@ /datum/action/risingbassmove name = "" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "" var/movestreak = "" -/datum/action/risingbassmove/Trigger() - if(owner.incapacitated()) - to_chat(owner, "You can't use [name] while you're incapacitated.") - return +/datum/action/risingbassmove/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE var/mob/living/carbon/human/H = owner if (H.mind.martial_art.streak == "[movestreak]") H.mind.martial_art.streak = "" to_chat(H,"You relax your muscles and return to a neutral position.") else - if(HAS_TRAIT(H, TRAIT_PACIFISM)) - to_chat(H, "You don't want to harm other people!") - return to_chat(H,"You get ready to use the [name] maneuver!") H.mind.martial_art.streak = "[movestreak]" + return TRUE + +/datum/action/risingbassmove/IsAvailable(feedback) + if(owner.incapacitated()) + if(feedback) + to_chat(owner, "You can't use [name] while you're incapacitated.") + return FALSE + if(HAS_TRAIT(owner, TRAIT_PACIFISM)) + if(feedback) + to_chat(owner, "You don't want to harm other people!") + return FALSE + return ..() /datum/action/risingbassmove/sidekick name = "Side Kick" diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm index b56c891820e6..8a175707f497 100644 --- a/code/datums/martial/wrestling.dm +++ b/code/datums/martial/wrestling.dm @@ -47,77 +47,121 @@ name = "Slam (Cinch) - Slam a grappled opponent into the floor." button_icon_state = "wrassle_slam" -/datum/action/slam/Trigger() - if(owner.incapacitated()) - to_chat(owner, "You can't WRESTLE while you're OUT FOR THE COUNT.") - return - if(HAS_TRAIT(owner, TRAIT_PACIFISM)) - to_chat(owner, "You are too HIPPIE to WRESTLE other living beings!") - return - owner.visible_message("[owner] prepares to BODY SLAM!", "Your next attack will be a BODY SLAM.") +/datum/action/slam/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + owner.visible_message(span_danger("[owner] prepares to BODY SLAM!"), "Your next attack will be a BODY SLAM.") var/mob/living/carbon/human/H = owner H.mind.martial_art.streak = "slam" + return TRUE + +/datum/action/slam/IsAvailable(feedback) + if(owner.incapacitated()) + if(feedback) + to_chat(owner, span_warning("You can't WRESTLE while you're OUT FOR THE COUNT.")) + return FALSE + if(HAS_TRAIT(owner, TRAIT_PACIFISM)) + if(feedback) + to_chat(owner, span_warning("You are too HIPPIE to WRESTLE other living beings!")) + return FALSE + return ..() /datum/action/throw_wrassle name = "Throw (Cinch) - Spin a cinched opponent around and throw them." button_icon_state = "wrassle_throw" -/datum/action/throw_wrassle/Trigger() - if(owner.incapacitated()) - to_chat(owner, "You can't WRESTLE while you're OUT FOR THE COUNT.") - return - if(HAS_TRAIT(owner, TRAIT_PACIFISM)) - to_chat(owner, "You are too HIPPIE to WRESTLE other living beings!") - return - owner.visible_message("[owner] prepares to THROW!", "Your next attack will be a THROW.") +/datum/action/throw_wrassle/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + owner.visible_message(span_danger("[owner] prepares to THROW!"), "Your next attack will be a THROW.") var/mob/living/carbon/human/H = owner H.mind.martial_art.streak = "throw" + return TRUE + +/datum/action/throw_wrassle/IsAvailable(feedback) + if(owner.incapacitated()) + if(feedback) + to_chat(owner, span_warning("You can't WRESTLE while you're OUT FOR THE COUNT.")) + return FALSE + if(HAS_TRAIT(owner, TRAIT_PACIFISM)) + if(feedback) + to_chat(owner, span_warning("You are too HIPPIE to WRESTLE other living beings!")) + return FALSE + return ..() /datum/action/kick name = "Kick - A powerful kick, sends people flying away from you. Also useful for escaping from bad situations." button_icon_state = "wrassle_kick" -/datum/action/kick/Trigger() - if(owner.incapacitated()) - to_chat(owner, "You can't WRESTLE while you're OUT FOR THE COUNT.") - return - if(HAS_TRAIT(owner, TRAIT_PACIFISM)) - to_chat(owner, "You are too HIPPIE to WRESTLE other living beings!") - return - owner.visible_message("[owner] prepares to KICK!", "Your next attack will be a KICK.") +/datum/action/kick/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + owner.visible_message(span_danger("[owner] prepares to KICK!"), "Your next attack will be a KICK.") var/mob/living/carbon/human/H = owner H.mind.martial_art.streak = "kick" + return TRUE + +/datum/action/kick/IsAvailable(feedback) + if(owner.incapacitated()) + if(feedback) + to_chat(owner, span_warning("You can't WRESTLE while you're OUT FOR THE COUNT.")) + return FALSE + if(HAS_TRAIT(owner, TRAIT_PACIFISM)) + if(feedback) + to_chat(owner, span_warning("You are too HIPPIE to WRESTLE other living beings!")) + return FALSE + return ..() /datum/action/strike name = "Strike - Hit a neaby opponent with a quick attack." button_icon_state = "wrassle_strike" -/datum/action/strike/Trigger() - if(owner.incapacitated()) - to_chat(owner, "You can't WRESTLE while you're OUT FOR THE COUNT.") - return - if(HAS_TRAIT(owner, TRAIT_PACIFISM)) - to_chat(owner, "You are too HIPPIE to WRESTLE other living beings!") - return - owner.visible_message("[owner] prepares to STRIKE!", "Your next attack will be a STRIKE.") +/datum/action/strike/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + owner.visible_message(span_danger("[owner] prepares to STRIKE!"), "Your next attack will be a STRIKE.") var/mob/living/carbon/human/H = owner H.mind.martial_art.streak = "strike" + return TRUE + +/datum/action/strike/IsAvailable(feedback) + if(owner.incapacitated()) + if(feedback) + to_chat(owner, span_warning("You can't WRESTLE while you're OUT FOR THE COUNT.")) + return FALSE + if(HAS_TRAIT(owner, TRAIT_PACIFISM)) + if(feedback) + to_chat(owner, span_warning("You are too HIPPIE to WRESTLE other living beings!")) + return FALSE + return ..() /datum/action/drop name = "Drop - Smash down onto an opponent." button_icon_state = "wrassle_drop" -/datum/action/drop/Trigger() - if(owner.incapacitated()) - to_chat(owner, "You can't WRESTLE while you're OUT FOR THE COUNT.") - return - if(HAS_TRAIT(owner, TRAIT_PACIFISM)) - to_chat(owner, "You are too HIPPIE to WRESTLE other living beings!") - return - owner.visible_message("[owner] prepares to LEG DROP!", "Your next attack will be a LEG DROP.") +/datum/action/drop/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + owner.visible_message(span_danger("[owner] prepares to LEG DROP!"), "Your next attack will be a LEG DROP.") var/mob/living/carbon/human/H = owner H.mind.martial_art.streak = "drop" +/datum/action/drop/IsAvailable(feedback) + if(owner.incapacitated()) + if(feedback) + to_chat(owner, span_warning("You can't WRESTLE while you're OUT FOR THE COUNT.")) + return FALSE + if(HAS_TRAIT(owner, TRAIT_PACIFISM)) + if(feedback) + to_chat(owner, span_warning("You are too HIPPIE to WRESTLE other living beings!")) + return FALSE + return ..() + /datum/martial_art/wrestling/teach(mob/living/carbon/human/H,make_temporary=0) if(..()) to_chat(H, "SNAP INTO A THIN TIM!") @@ -473,8 +517,8 @@ if(A.pulling == D || A == D) // don't stun grab yoursel return FALSE A.start_pulling(D) - D.visible_message("[A] gets [D] in a cinch!", \ - "[A] gets [D] in a cinch!") + D.visible_message(span_danger("[A] gets [D] in a cinch!"), \ + span_userdanger("[A] gets [D] in a cinch!")) D.Stun(rand(60,100)) log_combat(A, D, "cinched") return TRUE diff --git a/code/datums/mutations/actions.dm b/code/datums/mutations/actions.dm index 37da0c80bf49..4c0f31f04ef2 100644 --- a/code/datums/mutations/actions.dm +++ b/code/datums/mutations/actions.dm @@ -492,7 +492,7 @@ ..() /datum/action/innate/send_chems - icon_icon = 'icons/mob/actions/actions_genetic.dmi' + button_icon = 'icons/mob/actions/actions_genetic.dmi' background_icon_state = "bg_spell" check_flags = AB_CHECK_CONSCIOUS button_icon_state = "spikechemswap" diff --git a/code/datums/outfit.dm b/code/datums/outfit.dm index 4c17874f97c6..03e63425a3bb 100755 --- a/code/datums/outfit.dm +++ b/code/datums/outfit.dm @@ -223,7 +223,7 @@ apply_fingerprints(H) if(internals_slot) H.internal = H.get_item_by_slot(internals_slot) - H.update_action_buttons_icon() + H.update_mob_action_buttons() if(implants) for(var/implant_type in implants) var/obj/item/implant/I = new implant_type(H) diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm index 2a64f690380c..5f0c601f757d 100644 --- a/code/game/gamemodes/objective_items.dm +++ b/code/game/gamemodes/objective_items.dm @@ -168,7 +168,7 @@ excludefromjob = list("Research Director","Scientist", "Roboticist") /datum/objective_item/steal/slime/check_special_completion(obj/item/slime_extract/E) - if(E.Uses > 0) + if(E.extract_uses > 0) return TRUE return FALSE diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 5395dd6feeac..683c018de2a2 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -234,7 +234,7 @@ /datum/action/innate/camera_off name = "End Camera View" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "camera_off" /datum/action/innate/camera_off/Activate() @@ -246,7 +246,7 @@ /datum/action/innate/camera_jump name = "Jump To Camera" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "camera_jump" /datum/action/innate/camera_jump/Activate() diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index d113aa0fadbc..6a313c203b75 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -39,7 +39,7 @@ MA.plane = 0 holder.appearance = MA update_indicator() - + /obj/machinery/launchpad/Destroy() qdel(hud_list[DIAG_LAUNCHPAD_HUD]) return ..() diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 2536c9078f31..fa0ae181673b 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -673,25 +673,33 @@ DEFINE_BITFIELD(turret_flags, list( /datum/action/turret_toggle name = "Toggle Mode" - icon_icon = 'icons/mob/actions/actions_mecha.dmi' + button_icon = 'icons/mob/actions/actions_mecha.dmi' button_icon_state = "mech_cycle_equip_off" -/datum/action/turret_toggle/Trigger() +/datum/action/turret_toggle/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE var/obj/machinery/porta_turret/P = target if(!istype(P)) - return + return FALSE P.setState(P.on,!P.mode) + return TRUE /datum/action/turret_quit name = "Release Control" - icon_icon = 'icons/mob/actions/actions_mecha.dmi' + button_icon = 'icons/mob/actions/actions_mecha.dmi' button_icon_state = "mech_eject" -/datum/action/turret_quit/Trigger() +/datum/action/turret_quit/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE var/obj/machinery/porta_turret/P = target if(!istype(P)) - return + return FALSE P.remove_control(FALSE) + return TRUE /obj/machinery/porta_turret/proc/give_control(mob/A) if(manual_control || !can_interact(A)) diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index d9b110e8c4f7..1091a289bfa4 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -415,7 +415,7 @@ reactants += G.reagents for(var/obj/item/slime_extract/S in beakers) - if(S.Uses) + if(S.extract_uses) for(var/obj/item/reagent_containers/glass/G in beakers) G.reagents.trans_to(S, G.reagents.total_volume) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 0a11ae69da8f..d4ca6a18b1f3 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -86,8 +86,12 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb var/max_heat_protection_temperature //Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags var/min_cold_protection_temperature //Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags - var/list/actions //list of /datum/action's that this item has. - var/list/actions_types //list of paths of action datums to give to the item on New(). + ///list of /datum/action's that this item has. + var/list/datum/action/actions + ///list of paths of action datums to give to the item on New(). + var/list/actions_types + ///Slot flags in which this item grants actions. If null, defaults to the item's slot flags (so actions are granted when worn) + var/action_slots = null //Since any item can now be a piece of clothing, this has to be put here so all items share it. var/flags_inv //This flag is used to determine when items in someone's inventory cover others. IE helmets making it so you can't see glasses, etc. @@ -185,7 +189,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb . = ..() for(var/path in actions_types) - new path(src) + add_item_action(path) actions_types = null if(force_string) @@ -213,8 +217,11 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb if(ismob(loc)) var/mob/m = loc m.temporarilyRemoveItemFromInventory(src, TRUE) - for(var/X in actions) - qdel(X) + + // Handle cleaning up our actions list + for(var/datum/action/action as anything in actions) + remove_item_action(action) + return ..() /obj/item/ComponentInitialize() @@ -237,6 +244,50 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb if(sharpness && force > 5) //give sharp objects butchering functionality, for consistency AddComponent(/datum/component/butchering, 80 * toolspeed) +/// Called when an action associated with our item is deleted +/obj/item/proc/on_action_deleted(datum/source) + SIGNAL_HANDLER + + if(!(source in actions)) + CRASH("An action ([source.type]) was deleted that was associated with an item ([src]), but was not found in the item's actions list.") + + LAZYREMOVE(actions, source) + +/// Adds an item action to our list of item actions. +/// Item actions are actions linked to our item, that are granted to mobs who equip us. +/// This also ensures that the actions are properly tracked in the actions list and removed if they're deleted. +/// Can be be passed a typepath of an action or an instance of an action. +/obj/item/proc/add_item_action(action_or_action_type) + + var/datum/action/action + if(ispath(action_or_action_type, /datum/action)) + action = new action_or_action_type(src) + else if(istype(action_or_action_type, /datum/action)) + action = action_or_action_type + else + CRASH("item add_item_action got a type or instance of something that wasn't an action.") + + LAZYADD(actions, action) + RegisterSignal(action, COMSIG_PARENT_QDELETING, PROC_REF(on_action_deleted)) + grant_action_to_bearer(action) + return action + +/// Grant the action to anyone who has this item equipped to an appropriate slot +/obj/item/proc/grant_action_to_bearer(datum/action/action) + if(!ismob(loc)) + return + var/mob/holder = loc + give_item_action(action, holder, holder.get_slot_by_item(src)) + +/// Removes an instance of an action from our list of item actions. +/obj/item/proc/remove_item_action(datum/action/action) + if(!action) + return + + UnregisterSignal(action, COMSIG_PARENT_QDELETING) + LAZYREMOVE(actions, action) + qdel(action) + /obj/item/proc/check_allowed_items(atom/target, not_inside, target_self) if(((src in target) && !target_self) || (!isturf(target.loc) && !isturf(target) && not_inside)) return FALSE @@ -567,10 +618,26 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb . = list() SEND_SIGNAL(src, COMSIG_ITEM_WORN_OVERLAYS, isinhands, icon_file, used_state, style_flags, .) -//sometimes we only want to grant the item's action if it's equipped in a specific slot. -/obj/item/proc/item_action_slot_check(slot, mob/user, datum/action/A) - if(slot == ITEM_SLOT_BACKPACK || slot == ITEM_SLOT_LEGCUFFED) //these aren't true slots, so avoid granting actions there +/// Gives one of our item actions to a mob, when equipped to a certain slot +/obj/item/proc/give_item_action(datum/action/action, mob/to_who, slot) + // Some items only give their actions buttons when in a specific slot. + if(!item_action_slot_check(slot, to_who, action) || SEND_SIGNAL(src, COMSIG_ITEM_UI_ACTION_SLOT_CHECKED, to_who, action, slot) & COMPONENT_ITEM_ACTION_SLOT_INVALID) + // There is a chance we still have our item action currently, + // and are moving it from a "valid slot" to an "invalid slot". + // So call Remove() here regardless, even if excessive. + action.Remove(to_who) + return + + action.Grant(to_who) + +/// Sometimes we only want to grant the item's action if it's equipped in a specific slot. +/obj/item/proc/item_action_slot_check(slot, mob/user, datum/action/action) + if(slot & (ITEM_SLOT_BACKPACK|ITEM_SLOT_LEGCUFFED)) //these aren't true slots, so avoid granting actions there return FALSE + if(!isnull(action_slots)) + return (slot & action_slots) + else if (slot_flags) + return (slot & slot_flags) return TRUE //the mob M is attempting to equip this item into the slot passed through as 'slot'. return TRUE if it can do this and 0 if it can't. @@ -1284,7 +1351,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb */ /obj/item/proc/update_action_buttons(status_only = FALSE, force = FALSE) for(var/datum/action/current_action as anything in actions) - current_action.UpdateButtons(status_only, force) + current_action.build_all_button_icons(status_only, force) /// Special stuff you want to do when an outfit equips this item. /obj/item/proc/on_outfit_equip(mob/living/carbon/human/outfit_wearer, visuals_only, item_slot) diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index fac44ddf5447..a88775da9abe 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -450,12 +450,13 @@ /obj/item/card/id/syndicate name = "agent card" access = list(ACCESS_MAINT_TUNNELS, ACCESS_SYNDICATE) + action_slots = ALL var/anyone = FALSE //Can anyone forge the ID or just syndicate? var/forged = FALSE //have we set a custom name and job assignment, or will we use what we're given when we chameleon change? /obj/item/card/id/syndicate/Initialize(mapload) . = ..() - var/datum/action/item_action/chameleon/change/chameleon_action = new(src) + var/datum/action/item_action/chameleon/change/chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/card/id chameleon_action.chameleon_name = "ID Card" chameleon_action.initialize_disguises() diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index a154b8a638ca..8c9498a035a1 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -191,7 +191,7 @@ update_power() for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() /obj/item/defibrillator/proc/make_paddles() if(!combat) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 5cd8d8dc3f88..fde9eaf7031f 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -30,6 +30,7 @@ GLOBAL_LIST_EMPTY(PDAs) w_class = WEIGHT_CLASS_TINY slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT actions_types = list(/datum/action/item_action/toggle_light/pda) + action_slots = ALL armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100) resistance_flags = FIRE_PROOF | ACID_PROOF diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 5db6aead987f..d64e8ac769c8 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -12,6 +12,7 @@ slot_flags = ITEM_SLOT_BELT custom_materials = list(/datum/material/iron=50, /datum/material/glass=20) actions_types = list(/datum/action/item_action/toggle_light) + action_slots = ALL var/on = FALSE var/brightness_on = 4 //range of light when on var/flashlight_power = 0.8 //strength of the light when on @@ -40,7 +41,7 @@ playsound(src, on ? 'sound/weapons/magin.ogg' : 'sound/weapons/magout.ogg', 40, TRUE) for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() return TRUE /obj/item/flashlight/DoRevenantThrowEffects(atom/target) @@ -514,6 +515,10 @@ /obj/item/flashlight/glowstick/proc/activate() if(!on) on = TRUE + var/datum/action/toggle = locate(/datum/action/item_action/toggle_light) in actions + // No sense having a toggle light action that we don't use eh? + if(toggle) + remove_item_action(toggle) START_PROCESSING(SSobj, src) /obj/item/flashlight/glowstick/red diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index 577ec39486c5..af4bb94a2177 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -136,7 +136,7 @@ . = ..() START_PROCESSING(SSobj, src) eye = new /mob/camera/aiEye/remote/ai_detector() - toggle_action = new /datum/action/item_action/toggle_multitool(src) + toggle_action = add_item_action(/datum/action/item_action/toggle_multitool) /obj/item/multitool/ai_detect/Destroy() STOP_PROCESSING(SSobj, src) @@ -236,12 +236,14 @@ name = "Toggle AI detector HUD" check_flags = NONE -/datum/action/item_action/toggle_multitool/Trigger() - if(!..()) +/datum/action/item_action/toggle_multitool/do_effect(trigger_flags) + . = ..() + if(!.) + return + if(!istype(target, /obj/item/multitool/ai_detect)) return FALSE - if(target) - var/obj/item/multitool/ai_detect/M = target - M.toggle_hud(owner) + var/obj/item/multitool/ai_detect/M = target + M.toggle_hud(owner) return TRUE /obj/item/multitool/cyborg diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm index 801befc9c608..cd554b70dc18 100644 --- a/code/game/objects/items/granters.dm +++ b/code/game/objects/items/granters.dm @@ -129,12 +129,12 @@ /datum/action/innate/drink_fling/Activate() button_icon_state = "drinkfling_on" active = TRUE - UpdateButtons() + build_all_button_icons() /datum/action/innate/drink_fling/Deactivate() button_icon_state = "drinkfling_off" active = FALSE - UpdateButtons() + build_all_button_icons() /obj/item/book/granter/action/origami granted_action = /datum/action/innate/origami @@ -155,13 +155,13 @@ to_chat(owner, "You will now fold origami planes.") button_icon_state = "origami_on" active = TRUE - UpdateButtons() + build_all_button_icons() /datum/action/innate/origami/Deactivate() to_chat(owner, "You will no longer fold origami planes.") button_icon_state = "origami_off" active = FALSE - UpdateButtons() + build_all_button_icons() ///SPELLS/// diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index 7a834122b658..69b75c39fe60 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -220,7 +220,7 @@ return FALSE for(var/obj/item/slime_extract/S in beakers) - if(S.Uses) + if(S.extract_uses) for(var/obj/item/reagent_containers/glass/G in beakers) G.reagents.trans_to(S, G.reagents.total_volume) diff --git a/code/game/objects/items/grenades/grenade.dm b/code/game/objects/items/grenades/grenade.dm index a7d55fa2e456..ebd0f371e791 100644 --- a/code/game/objects/items/grenades/grenade.dm +++ b/code/game/objects/items/grenades/grenade.dm @@ -11,6 +11,7 @@ throw_range = 7 flags_1 = CONDUCT_1 slot_flags = ITEM_SLOT_BELT + action_slots = ALL resistance_flags = FLAMMABLE max_integrity = 40 var/active = 0 diff --git a/code/game/objects/items/implants/implant_mindshield.dm b/code/game/objects/items/implants/implant_mindshield.dm index 14a49c1a00f3..0b2f9ae77f19 100644 --- a/code/game/objects/items/implants/implant_mindshield.dm +++ b/code/game/objects/items/implants/implant_mindshield.dm @@ -1,6 +1,7 @@ /obj/item/implant/mindshield name = "mindshield implant" desc = "Protects against brainwashing." + actions_types = null activated = 0 /obj/item/implant/mindshield/get_data() diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 5d57c9ee69c0..375ced916f7d 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -16,6 +16,7 @@ righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' flags_1 = CONDUCT_1 slot_flags = ITEM_SLOT_BELT + action_slots = ALL force = 14 throwforce = 10 wound_bonus = 15 diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index b4917c2500c2..b3b7b373f546 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -355,7 +355,7 @@ return FALSE icon_state = "selfrepair_off" - toggle_action = new /datum/action/item_action/toggle(src) + toggle_action = add_item_action(/datum/action/item_action/toggle) toggle_action.Grant(R) /obj/item/borg/upgrade/selfrepair/deactivate(mob/living/silicon/robot/R, user = usr) @@ -705,7 +705,7 @@ /obj/effect/proc_holder/silicon/cyborg/vtecControl name = "vTec Control" desc = "Allows finer-grained control of the vTec speed boost." - action_icon = 'icons/mob/actions.dmi' + action_icon = 'icons/hud/actions.dmi' action_icon_state = "Chevron_State_0" var/currentState = 0 @@ -725,6 +725,6 @@ user.vtec = initial(user.vtec) - maxReduction * 1 action.button_icon_state = "Chevron_State_[currentState]" - action.UpdateButtons() + action.build_all_button_icons() return TRUE diff --git a/code/game/objects/items/storage/_storage.dm b/code/game/objects/items/storage/_storage.dm index cbaa1775eb0d..145983e0ad1a 100644 --- a/code/game/objects/items/storage/_storage.dm +++ b/code/game/objects/items/storage/_storage.dm @@ -3,6 +3,7 @@ name = "storage" icon = 'icons/obj/storage.dmi' w_class = WEIGHT_CLASS_NORMAL + action_slots = ALL var/component_type = /datum/component/storage/concrete /obj/item/storage/get_dumping_location(obj/item/storage/source,mob/user) diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm index a091993ff1aa..a8979729bcc4 100644 --- a/code/game/objects/items/tanks/jetpack.dm +++ b/code/game/objects/items/tanks/jetpack.dm @@ -50,7 +50,7 @@ to_chat(user, "You turn the jetpack off.") for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() /obj/item/tank/jetpack/proc/turn_on(mob/user) on = TRUE diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index 0380c2d5acf1..4f6dce99705f 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -15,6 +15,7 @@ throw_range = 4 custom_materials = list(/datum/material/iron = 500) actions_types = list(/datum/action/item_action/set_internals) + action_slots = ALL armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 10, BIO = 0, RAD = 0, FIRE = 80, ACID = 30) var/datum/gas_mixture/air_contents = null var/distribute_pressure = ONE_ATMOSPHERE @@ -59,7 +60,7 @@ else to_chat(H, "You open [src] valve.") H.internal = src - H.update_action_buttons_icon() + H.update_mob_action_buttons() /obj/item/tank/Initialize(mapload) diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 2c3b0545f81b..52e3bb8bc9f5 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -467,7 +467,7 @@ GLOBAL_LIST_INIT(double_bedsheets, list(/obj/item/bedsheet/double, /obj/item/bedsheet/chameleon/New() ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/bedsheet chameleon_action.chameleon_name = "Bedsheet" chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/bedsheet/chameleon, /obj/item/bedsheet/random, /obj/item/bedsheet/unlockable), only_root_path = FALSE) diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index c8fea2de4a66..2d8a8eb3b131 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -113,7 +113,7 @@ to_chat(new_spawn, "You can expand the weather proof area provided by your shelters by using the 'New Area' key near the bottom right of your HUD.") to_chat(new_spawn, "Dragging injured ashwalkers to the tentacle or using the sleep verb next to it youself causes the body to remade whole after a short delay!") else - to_chat(new_spawn, "You have been born outside of your natural home! Whether you decide to return home, or make due with your new home is your own decision.") + to_chat(new_spawn, span_userdanger("You have been born outside of your natural home! Whether you decide to return home, or make due with your new home is your own decision.")) //Ash walkers on birth understand how to make bone bows, bone arrows and ashen arrows @@ -247,7 +247,7 @@ if(transfer_choice != "Yes" || QDELETED(src) || uses <= 0 || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERY, NO_TK)) return log_game("[key_name(user)] golem-swapped into [src]") - user.visible_message("A faint light leaves [user], moving to [src] and animating it!","You leave your old body behind, and transfer into [src]!") + user.visible_message(span_notice("A faint light leaves [user], moving to [src] and animating it!"),span_notice("You leave your old body behind, and transfer into [src]!")) show_flavour = FALSE create(ckey = user.ckey,name = user.real_name) user.death() @@ -477,7 +477,7 @@ id.registered_name = L.real_name id.update_label() else - to_chat(L, "Your owner is already dead! You will soon perish.") + to_chat(L, span_userdanger("Your owner is already dead! You will soon perish.")) addtimer(CALLBACK(L, TYPE_PROC_REF(/mob, dust), 150)) //Give em a few seconds as a mercy. /datum/outfit/demonic_friend @@ -666,24 +666,24 @@ if(.) return if(user.mind.has_antag_datum(/datum/antagonist/pirate)) - to_chat(user, "Your shipmate sails within their dreams for now. Perhaps they may wake up eventually.") + to_chat(user, span_notice("Your shipmate sails within their dreams for now. Perhaps they may wake up eventually.")) else - to_chat(user, "If you want to kill the pirate off, something to pry open the sleeper might be the best way to do it.") + to_chat(user, span_notice("If you want to kill the pirate off, something to pry open the sleeper might be the best way to do it.")) /obj/effect/mob_spawn/human/pirate/attackby(obj/item/W, mob/user, params) if(W.tool_behaviour == TOOL_CROWBAR && user.a_intent != INTENT_HARM) if(user.mind.has_antag_datum(/datum/antagonist/pirate)) - to_chat(user,"Why would you want to do that to your shipmate? That'd kill them.") + to_chat(user,span_warning("Why would you want to do that to your shipmate? That'd kill them.")) return - user.visible_message("[user] start to pry open [src]...", - "You start to pry open [src]...", - "You hear prying...") + user.visible_message(span_warning("[user] start to pry open [src]..."), + span_notice("You start to pry open [src]..."), + span_italics("You hear prying...")) W.play_tool_sound(src) if(do_after(user, 100*W.toolspeed, target = src)) - user.visible_message("[user] pries open [src], disrupting the sleep of the pirate within and killing them.", - "You pry open [src], disrupting the sleep of the pirate within and killing them.", - "You hear prying, followed by the death rattling of bones.") + user.visible_message(span_warning("[user] pries open [src], disrupting the sleep of the pirate within and killing them."), + span_notice("You pry open [src], disrupting the sleep of the pirate within and killing them."), + span_italics("You hear prying, followed by the death rattling of bones.")) log_game("[key_name(user)] has successfully pried open [src] and disabled a space pirate spawner.") W.play_tool_sound(src) playsound(src.loc, 'modular_citadel/sound/voice/scream_skeleton.ogg', 50, 1, 4, 1.2) @@ -746,27 +746,28 @@ banType = ROLE_GHOSTCAFE /datum/action/toggle_dead_chat_mob - icon_icon = 'icons/mob/mob.dmi' + button_icon = 'icons/mob/mob.dmi' button_icon_state = "ghost" name = "Toggle deadchat" desc = "Turn off or on your ability to hear ghosts." -/datum/action/toggle_dead_chat_mob/Trigger() - if(!..()) +/datum/action/toggle_dead_chat_mob/Trigger(trigger_flags) + . = ..() + if(!.) return FALSE var/mob/M = target if(HAS_TRAIT_FROM(M,TRAIT_SIXTHSENSE,GHOSTROLE_TRAIT)) REMOVE_TRAIT(M,TRAIT_SIXTHSENSE,GHOSTROLE_TRAIT) - to_chat(M,"You're no longer hearing deadchat.") + to_chat(M,span_notice("You're no longer hearing deadchat.")) else ADD_TRAIT(M,TRAIT_SIXTHSENSE,GHOSTROLE_TRAIT) - to_chat(M,"You're once again longer hearing deadchat.") - + to_chat(M,span_notice("You're once again longer hearing deadchat.")) + return TRUE /datum/action/disguise name = "Disguise" button_icon_state = "ling_transform" - icon_icon = 'icons/mob/actions/actions_changeling.dmi' + button_icon = 'icons/mob/actions/actions_changeling.dmi' background_icon_state = "bg_mime" var/currently_disguised = FALSE var/static/list/mob_blacklist = typecacheof(list( @@ -798,36 +799,44 @@ )) -/datum/action/disguise/Trigger() +/datum/action/disguise/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE var/mob/living/carbon/human/H = owner - if(!currently_disguised) - var/user_object_type = input(H, "Disguising as OBJECT or MOB?") as null|anything in list("OBJECT", "MOB") - if(user_object_type) - var/search_term = stripped_input(H, "Enter the search term") - if(search_term) - var/list_to_search - if(user_object_type == "MOB") - list_to_search = subtypesof(/mob) - mob_blacklist - else - list_to_search = subtypesof(/obj) - var/list/filtered_results = list() - for(var/some_search_item in list_to_search) - if(findtext("[some_search_item]", search_term)) - filtered_results += some_search_item - if(!length(filtered_results)) - to_chat(H, "Nothing matched your search query!") - else - var/disguise_selection = input("Select item to disguise as") as null|anything in filtered_results - if(disguise_selection) - var/atom/disguise_item = disguise_selection - var/image/I = image(icon = initial(disguise_item.icon), icon_state = initial(disguise_item.icon_state), loc = H) - I.override = TRUE - I.layer = ABOVE_MOB_LAYER - H.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "ghost_cafe_disguise", I) - currently_disguised = TRUE - else + if(currently_disguised) H.remove_alt_appearance("ghost_cafe_disguise") currently_disguised = FALSE + return TRUE + else + var/user_object_type = input(H, "Disguising as OBJECT or MOB?") as null|anything in list("OBJECT", "MOB") + if(!user_object_type) + return FALSE + var/search_term = stripped_input(H, "Enter the search term") + if(!search_term) + return FALSE + var/list_to_search + if(user_object_type == "MOB") + list_to_search = subtypesof(/mob) - mob_blacklist + else + list_to_search = subtypesof(/obj) + var/list/filtered_results = list() + for(var/some_search_item in list_to_search) + if(findtext("[some_search_item]", search_term)) + filtered_results += some_search_item + if(!length(filtered_results)) + to_chat(H, "Nothing matched your search query!") + return FALSE + var/disguise_selection = input("Select item to disguise as") as null|anything in filtered_results + if(!disguise_selection) + return FALSE + var/atom/disguise_item = disguise_selection + var/image/I = image(icon = initial(disguise_item.icon), icon_state = initial(disguise_item.icon_state), loc = H) + I.override = TRUE + I.layer = ABOVE_MOB_LAYER + H.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "ghost_cafe_disguise", I) + currently_disguised = TRUE + return TRUE /obj/effect/mob_spawn/human/ghostcafe/special(mob/living/carbon/human/new_spawn) if(new_spawn.client) @@ -844,7 +853,7 @@ ADD_TRAIT(new_spawn, TRAIT_SIXTHSENSE, GHOSTROLE_TRAIT) ADD_TRAIT(new_spawn, TRAIT_EXEMPT_HEALTH_EVENTS, GHOSTROLE_TRAIT) ADD_TRAIT(new_spawn, TRAIT_NO_MIDROUND_ANTAG, GHOSTROLE_TRAIT) //The mob can't be made into a random antag, they are still eligible for ghost roles popups. - to_chat(new_spawn,"Ghosting is free!") + to_chat(new_spawn,span_boldwarning("Ghosting is free!")) var/datum/action/toggle_dead_chat_mob/D = new(new_spawn) D.Grant(new_spawn) var/datum/action/disguise/disguise_action = new(new_spawn) diff --git a/code/modules/VR/vr_mob.dm b/code/modules/VR/vr_mob.dm index 5f2caffc76da..97e3c8fed7df 100644 --- a/code/modules/VR/vr_mob.dm +++ b/code/modules/VR/vr_mob.dm @@ -35,10 +35,10 @@ /datum/action/quit_vr name = "Quit Virtual Reality" - icon_icon = 'icons/mob/actions/actions_vr.dmi' + button_icon = 'icons/mob/actions/actions_vr.dmi' button_icon_state = "logout" -/datum/action/quit_vr/Trigger() //this merely a trigger for /datum/component/virtual_reality +/datum/action/quit_vr/Trigger(trigger_flags) //this merely a trigger for /datum/component/virtual_reality . = ..() if(.) //The component was not there to block the trigger. Remove(owner) diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index 9f3556dbb6f0..7b2c08043964 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -523,11 +523,16 @@ GLOBAL_LIST_EMPTY(antagonists) src.antag_datum = antag_datum name += " [antag_datum.name]" -/datum/action/antag_info/Trigger() - if(antag_datum) - antag_datum.ui_interact(owner) +/datum/action/antag_info/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + if(!antag_datum) + return FALSE + antag_datum.ui_interact(owner) + return TRUE -/datum/action/antag_info/IsAvailable() +/datum/action/antag_info/IsAvailable(feedback) return TRUE ///Clears change requests from deleted objectives to avoid broken references. diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm index 7506ae897504..e00042bedd69 100644 --- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm +++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm @@ -59,7 +59,7 @@ H.update_inv_wear_suit() for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() /obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user, datum/action/A) if(slot == ITEM_SLOT_OCLOTHING) //we only give the mob the ability to activate the vest if he's actually wearing it. @@ -441,6 +441,7 @@ force = 7 w_class = WEIGHT_CLASS_NORMAL actions_types = list(/datum/action/item_action/toggle_mode) + action_slots = ALL /obj/item/abductor/baton/ComponentInitialize() . = ..() diff --git a/code/modules/antagonists/abductor/machinery/camera.dm b/code/modules/antagonists/abductor/machinery/camera.dm index 4fb6bf56459c..6f7a10664a06 100644 --- a/code/modules/antagonists/abductor/machinery/camera.dm +++ b/code/modules/antagonists/abductor/machinery/camera.dm @@ -24,7 +24,7 @@ /obj/machinery/computer/camera_advanced/abductor/Initialize(mapload) . = ..() - + if(tele_in_action) actions += new tele_in_action(src) if(tele_out_action) @@ -43,7 +43,7 @@ /datum/action/innate/teleport_in name = "Send To" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "beam_down" /datum/action/innate/teleport_in/Activate() @@ -57,7 +57,7 @@ /datum/action/innate/teleport_out name = "Retrieve" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "beam_up" /datum/action/innate/teleport_out/Activate() @@ -69,7 +69,7 @@ /datum/action/innate/teleport_self name = "Send Self" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "beam_down" /datum/action/innate/teleport_self/Activate() @@ -83,7 +83,7 @@ /datum/action/innate/vest_mode_swap name = "Switch Vest Mode" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "vest_mode" /datum/action/innate/vest_mode_swap/Activate() @@ -95,7 +95,7 @@ /datum/action/innate/vest_disguise_swap name = "Switch Vest Disguise" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "vest_disguise" /datum/action/innate/vest_disguise_swap/Activate() @@ -106,7 +106,7 @@ /datum/action/innate/set_droppoint name = "Set Experiment Release Point" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "set_drop" /datum/action/innate/set_droppoint/Activate() diff --git a/code/modules/antagonists/blob/blob.dm b/code/modules/antagonists/blob/blob.dm index c449bd301220..c5e659dfbca5 100644 --- a/code/modules/antagonists/blob/blob.dm +++ b/code/modules/antagonists/blob/blob.dm @@ -51,7 +51,7 @@ /datum/action/innate/blobpop name = "Pop" desc = "Unleash the blob" - icon_icon = 'icons/mob/blob.dmi' + button_icon = 'icons/mob/blob.dmi' button_icon_state = "blob" /datum/action/innate/blobpop/Activate() diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm b/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm index dc16ecef1e23..9cb68f70669b 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_powers.dm @@ -3,7 +3,7 @@ desc = "A vampiric gift." button_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the BACKGROUND icon background_icon_state = "vamp_power_off" //And this is the state for the background icon - icon_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the ACTION icon + button_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the ACTION icon button_icon_state = "power_feed" //And this is the state for the action icon buttontooltipstyle = "cult" transparent_when_unavailable = TRUE @@ -51,17 +51,17 @@ // spells.dm /add_ranged_ability() <--- How we take over the mouse click to use a power on a target. // TODO: Refactor this to use /Activate(). -/datum/action/cooldown/bloodsucker/Trigger() +/datum/action/cooldown/bloodsucker/Trigger(trigger_flags) // Active? DEACTIVATE AND END! if(active && CheckCanDeactivate(TRUE)) DeactivatePower() - return + return FALSE if(!CheckCanPayCost(TRUE) || !CheckCanUse(TRUE)) - return + return FALSE PayCost() if(amToggle) active = !active - UpdateButtons() + build_all_button_icons() if(!amToggle || !active) StartCooldown() // Must come AFTER UpdateButton(), otherwise icon will revert. ActivatePower() // NOTE: ActivatePower() freezes this power in place until it ends. @@ -69,6 +69,7 @@ DeactivatePower() if(amSingleUse) RemoveAfterUse() + return TRUE /datum/action/cooldown/bloodsucker/proc/CheckCanPayCost(display_error) if(!owner || !owner.mind) @@ -82,7 +83,7 @@ var/mob/living/L = owner if(L.blood_volume < bloodcost) if(display_error) - to_chat(owner, "You need at least [bloodcost] blood to activate [name]") + to_chat(owner, span_warning("You need at least [bloodcost] blood to activate [name]")) return FALSE return TRUE @@ -92,12 +93,12 @@ // Torpor? if(!can_use_in_torpor && HAS_TRAIT(owner, TRAIT_DEATHCOMA)) if(display_error) - to_chat(owner, "Not while you're in Torpor.") + to_chat(owner, span_warning("Not while you're in Torpor.")) return FALSE // Stake? if(!can_be_staked && owner.AmStaked()) if(display_error) - to_chat(owner, "You have a stake in your chest! Your powers are useless.") + to_chat(owner, span_warning("You have a stake in your chest! Your powers are useless.")) return FALSE if(istype(owner.get_item_by_slot(ITEM_SLOT_NECK), /obj/item/clothing/neck/garlic_necklace)) if(display_error) @@ -105,35 +106,36 @@ return FALSE if(owner.reagents?.has_reagent(/datum/reagent/consumable/garlic)) if(display_error) - to_chat(owner, "Garlic in your blood is interfering with your powers!") + to_chat(owner, span_warning("Garlic in your blood is interfering with your powers!")) return FALSE if(must_be_concious) if(owner.stat != CONSCIOUS) if(display_error) - to_chat(owner, "You can't do this while you are unconcious!") + to_chat(owner, span_warning("You can't do this while you are unconcious!")) return FALSE // Incap? if(must_be_capacitated) var/mob/living/L = owner if (L.incapacitated(TRUE, TRUE) || !CHECK_MOBILITY(L, MOBILITY_STAND) && !can_be_immobilized) if(display_error) - to_chat(owner, "Not while you're incapacitated!") + to_chat(owner, span_warning("Not while you're incapacitated!")) return FALSE // Constant Cost (out of blood) if(warn_constant_cost) var/mob/living/L = owner if(L.blood_volume <= 0) if(display_error) - to_chat(owner, "You don't have the blood to upkeep [src].") + to_chat(owner, span_warning("You don't have the blood to upkeep [src].")) return FALSE return TRUE /datum/action/cooldown/bloodsucker/proc/CheckCanDeactivate(display_error) return TRUE -/datum/action/cooldown/bloodsucker/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE) - background_icon_state = active? background_icon_state_on : background_icon_state_off - ..()//UpdateButton() +/datum/action/cooldown/bloodsucker/apply_button_background(atom/movable/screen/movable/action_button/current_button, force) + if(active_background_icon_state) + background_icon_state = is_action_active(current_button) ? active_background_icon_state : base_background_icon_state + return ..() /datum/action/cooldown/bloodsucker/proc/PayCost() // owner for actions is the mob, not mind. @@ -146,7 +148,7 @@ /datum/action/cooldown/bloodsucker/proc/DeactivatePower(mob/living/user = owner, mob/living/target) active = FALSE - UpdateButtons() + build_all_button_icons() StartCooldown() /datum/action/cooldown/bloodsucker/proc/ContinueActive(mob/living/user, mob/living/target) // Used by loops to make sure this power can stay active. @@ -182,15 +184,15 @@ // TODO: Refactor this to use /Activate() and click_to_activate = TRUE. // Click power: Begin Aim -/datum/action/cooldown/bloodsucker/targeted/Trigger() +/datum/action/cooldown/bloodsucker/targeted/Trigger(trigger_flags) if(active && CheckCanDeactivate(TRUE)) DeactivateRangedAbility() DeactivatePower() - return + return FALSE if(!CheckCanPayCost(TRUE) || !CheckCanUse(TRUE)) - return + return FALSE active = !active - UpdateButtons() + build_all_button_icons() // Create & Link Targeting Proc var/mob/living/L = owner if(L.ranged_ability) @@ -198,7 +200,8 @@ bs_proc_holder.add_ranged_ability(L) if(message_Trigger != "") - to_chat(owner, "[message_Trigger]") + to_chat(owner, span_announce("[message_Trigger]")) + return TRUE /datum/action/cooldown/bloodsucker/targeted/CheckCanUse(display_error) . = ..() @@ -211,7 +214,7 @@ /datum/action/cooldown/bloodsucker/targeted/DeactivatePower(mob/living/user = owner, mob/living/target) // Don't run ..(), we don't want to engage the cooldown until we USE this power! active = FALSE - UpdateButtons() + build_all_button_icons() /datum/action/cooldown/bloodsucker/targeted/proc/DeactivateRangedAbility() // Only Turned off when CLICK is disabled...aka, when you successfully clicked (or @@ -226,7 +229,7 @@ // Out of Range if(!(A in view(target_range, owner))) if(display_error && target_range > 1) // Only warn for range if it's greater than 1. Brawn doesn't need to announce itself. - to_chat(owner, "Your target is out of range.") + to_chat(owner, span_warning("Your target is out of range.")) return FALSE return istype(A) diff --git a/code/modules/antagonists/bloodsucker/datum_hunter.dm b/code/modules/antagonists/bloodsucker/datum_hunter.dm index 9c862fe42a3d..bb3505233d1f 100644 --- a/code/modules/antagonists/bloodsucker/datum_hunter.dm +++ b/code/modules/antagonists/bloodsucker/datum_hunter.dm @@ -171,7 +171,7 @@ desc = "Take a moment to look for clues of any nearby monsters.
These creatures are slippery, and often look like the crew." button_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the BACKGROUND icon background_icon_state = "vamp_power_off" //And this is the state for the background icon - icon_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the ACTION icon + button_icon = 'icons/mob/actions/bloodsucker.dmi' //This is the file for the ACTION icon button_icon_state = "power_hunter" //And this is the state for the action icon amToggle = FALSE // Action-Related cooldown = 300 // 10 ticks, 1 second. diff --git a/code/modules/antagonists/changeling/cellular_emporium.dm b/code/modules/antagonists/changeling/cellular_emporium.dm index 3e48fca317d9..e50fa0cf449e 100644 --- a/code/modules/antagonists/changeling/cellular_emporium.dm +++ b/code/modules/antagonists/changeling/cellular_emporium.dm @@ -73,7 +73,7 @@ /datum/action/innate/cellular_emporium name = "Cellular Emporium" - icon_icon = 'icons/obj/drinks.dmi' + button_icon = 'icons/obj/drinks.dmi' button_icon_state = "changelingsting" background_icon_state = "bg_changeling" var/datum/cellular_emporium/cellular_emporium diff --git a/code/modules/antagonists/changeling/changeling_power.dm b/code/modules/antagonists/changeling/changeling_power.dm index 8f481285620e..3a7165c020f9 100644 --- a/code/modules/antagonists/changeling/changeling_power.dm +++ b/code/modules/antagonists/changeling/changeling_power.dm @@ -5,7 +5,7 @@ /datum/action/changeling name = "Prototype Sting - Debug button, ahelp this" background_icon_state = "bg_changeling" - icon_icon = 'icons/mob/actions/actions_changeling.dmi' + button_icon = 'icons/mob/actions/actions_changeling.dmi' var/needs_button = TRUE//for passive abilities like hivemind that dont need a button var/helptext = "" // Details var/chemical_cost = 0 // negative chemical cost is for passive abilities (chemical glands) @@ -30,11 +30,12 @@ the same goes for Remove(). if you override Remove(), call parent or else your p if(needs_button) Grant(user)//how powers are added rather than the checks in mob.dm -/datum/action/changeling/Trigger() +/datum/action/changeling/Trigger(trigger_flags) var/mob/user = owner if(!user || !user.mind || !user.mind.has_antag_datum(/datum/antagonist/changeling)) - return + return FALSE try_to_sting(user) + return TRUE /datum/action/changeling/proc/try_to_sting(mob/user, mob/target) if(!can_sting(user, target)) diff --git a/code/modules/antagonists/changeling/powers/fakedeath.dm b/code/modules/antagonists/changeling/powers/fakedeath.dm index 8bbbc423a11a..d2cc99b1a869 100644 --- a/code/modules/antagonists/changeling/powers/fakedeath.dm +++ b/code/modules/antagonists/changeling/powers/fakedeath.dm @@ -44,7 +44,7 @@ name = "Reviving Stasis" desc = "We fall into a stasis, allowing us to regenerate and trick our enemies. Costs 15 chemicals." button_icon_state = "fake_death" - UpdateButtons() + build_all_button_icons() chemical_cost = 15 to_chat(user, "We have revived ourselves.") @@ -56,7 +56,7 @@ name = "Revive" desc = "We arise once more." button_icon_state = "revive" - UpdateButtons() + build_all_button_icons() chemical_cost = 0 revive_ready = TRUE diff --git a/code/modules/antagonists/changeling/powers/pheromone_receptors.dm b/code/modules/antagonists/changeling/powers/pheromone_receptors.dm index 9d7eb8744d76..57e3a6b716da 100644 --- a/code/modules/antagonists/changeling/powers/pheromone_receptors.dm +++ b/code/modules/antagonists/changeling/powers/pheromone_receptors.dm @@ -7,7 +7,7 @@ name = "Pheromone Receptors" desc = "We attune our senses to track other changelings by scent. The closer they are, the easier we can find them." helptext = "We will know the general direction of nearby changelings, with closer scents being stronger. Our chemical generation is slowed while this is active." - icon_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon = 'icons/mob/actions/actions_spells.dmi' button_icon_state = "nose" chemical_cost = 0 //Reduces regain rate while active. dna_cost = 2 diff --git a/code/modules/antagonists/changeling/powers/tiny_prick.dm b/code/modules/antagonists/changeling/powers/tiny_prick.dm index 514d6ed6f680..489d7616affc 100644 --- a/code/modules/antagonists/changeling/powers/tiny_prick.dm +++ b/code/modules/antagonists/changeling/powers/tiny_prick.dm @@ -3,21 +3,21 @@ desc = "Stabby stabby" var/sting_icon = null -/datum/action/changeling/sting/Trigger() +/datum/action/changeling/sting/Trigger(trigger_flags) var/mob/user = owner if(!user || !user.mind) - return + return FALSE var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) if(!changeling) - return + return FALSE if(!changeling.chosen_sting) set_sting(user) else unset_sting(user) - return + return TRUE /datum/action/changeling/sting/proc/set_sting(mob/user) - to_chat(user, "We prepare our sting, use Alt+click or click the middle mouse button on a target to sting them.") + to_chat(user, span_notice("We prepare our sting, use Alt+click or click the middle mouse button on a target to sting them.")) var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) changeling.chosen_sting = src @@ -25,7 +25,7 @@ user.hud_used.lingstingdisplay.invisibility = 0 /datum/action/changeling/sting/proc/unset_sting(mob/user) - to_chat(user, "We retract our sting, we can't sting anyone for now.") + to_chat(user, span_warning("We retract our sting, we can't sting anyone for now.")) var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) changeling.chosen_sting = null @@ -58,9 +58,9 @@ /datum/action/changeling/sting/sting_feedback(mob/user, mob/target) if(!target) return - to_chat(user, "We stealthily sting [target.name].") + to_chat(user, span_notice("We stealthily sting [target.name].")) if(target.mind && target.mind.has_antag_datum(/datum/antagonist/changeling)) - to_chat(target, "You feel a tiny prick.") + to_chat(target, span_warning("You feel a tiny prick.")) return TRUE @@ -75,31 +75,31 @@ loudness = 1 var/datum/changelingprofile/selected_dna = null -/datum/action/changeling/sting/transformation/Trigger() +/datum/action/changeling/sting/transformation/Trigger(trigger_flags) var/mob/user = owner var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) if(changeling.chosen_sting) unset_sting(user) - return + return FALSE selected_dna = changeling.select_dna() if(!selected_dna) - return + return FALSE if(NOTRANSSTING in selected_dna.dna.species.species_traits) - to_chat(user, "That DNA is not compatible with changeling retrovirus!") - return - ..() + to_chat(user, span_notice("That DNA is not compatible with changeling retrovirus!")) + return FALSE + return ..() /datum/action/changeling/sting/transformation/can_sting(mob/user, mob/living/carbon/target) if(!..()) return if((HAS_TRAIT(target, TRAIT_HUSK)) || !iscarbon(target) || (NOTRANSSTING in target.dna.species.species_traits)) - to_chat(user, "Our sting appears ineffective against its DNA.") + to_chat(user, span_warning("Our sting appears ineffective against its DNA.")) return FALSE return TRUE /datum/action/changeling/sting/transformation/sting_action(mob/user, mob/target) if(ismonkey(target)) - to_chat(user, "Our genes cry out as we sting [target.name]!") + to_chat(user, span_notice("Our genes cry out as we sting [target.name]!")) var/mob/living/carbon/C = target . = TRUE @@ -132,7 +132,7 @@ if(isliving(target)) var/mob/living/L = target if((HAS_TRAIT(L, TRAIT_HUSK)) || !L.has_dna()) - to_chat(user, "Our sting appears ineffective against its DNA.") + to_chat(user, span_warning("Our sting appears ineffective against its DNA.")) return FALSE return TRUE @@ -141,15 +141,15 @@ var/obj/item/held = target.get_active_held_item() if(held && !target.dropItemToGround(held)) - to_chat(user, "[held] is stuck to [target.p_their()] hand, you cannot grow a false armblade over it!") + to_chat(user, span_warning("[held] is stuck to [target.p_their()] hand, you cannot grow a false armblade over it!")) return if(ismonkey(target)) - to_chat(user, "Our genes cry out as we sting [target.name]!") + to_chat(user, span_notice("Our genes cry out as we sting [target.name]!")) var/obj/item/melee/arm_blade/false/blade = new(target,1) target.put_in_hands(blade) - target.visible_message("A grotesque blade forms around [target.name]\'s arm!", "Your arm twists and mutates, transforming into a horrific monstrosity!", "You hear organic matter ripping and tearing!") + target.visible_message(span_warning("A grotesque blade forms around [target.name]\'s arm!"), span_userdanger("Your arm twists and mutates, transforming into a horrific monstrosity!"), span_italics("You hear organic matter ripping and tearing!")) playsound(target, 'sound/effects/blobattack.ogg', 30, 1) addtimer(CALLBACK(src, PROC_REF(remove_fake), target, blade), 600) @@ -157,9 +157,9 @@ /datum/action/changeling/sting/false_armblade/proc/remove_fake(mob/target, obj/item/melee/arm_blade/false/blade) playsound(target, 'sound/effects/blobattack.ogg', 30, 1) - target.visible_message("With a sickening crunch, \ - [target] reforms [target.p_their()] [blade.name] into an arm!", - "[blade] reforms back to normal.", + target.visible_message(span_warning("With a sickening crunch, \ + [target] reforms [target.p_their()] [blade.name] into an arm!"), + span_warning("[blade] reforms back to normal."), "Your eyes burn horrifically!") + to_chat(target, span_danger("Your eyes burn horrifically!")) target.become_nearsighted(EYE_DAMAGE) target.blind_eyes(20) target.blur_eyes(40) diff --git a/code/modules/antagonists/clockcult/clock_helpers/hierophant_network.dm b/code/modules/antagonists/clockcult/clock_helpers/hierophant_network.dm index 0c01dc0963a9..e59ebe40e4b0 100644 --- a/code/modules/antagonists/clockcult/clock_helpers/hierophant_network.dm +++ b/code/modules/antagonists/clockcult/clock_helpers/hierophant_network.dm @@ -26,7 +26,7 @@ /datum/action/innate/hierophant name = "Hierophant Network" desc = "Allows you to communicate with other Servants." - icon_icon = 'icons/mob/actions/actions_clockcult.dmi' + button_icon = 'icons/mob/actions/actions_clockcult.dmi' button_icon_state = "hierophant" background_icon_state = "bg_clock" check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS @@ -35,14 +35,14 @@ var/span_for_name = "heavy_brass" var/span_for_message = "brass" -/datum/action/innate/hierophant/IsAvailable(silent = FALSE) +/datum/action/innate/hierophant/IsAvailable(feedback = TRUE) if(!is_servant_of_ratvar(owner)) return FALSE return ..() /datum/action/innate/hierophant/Activate() var/input = stripped_input(usr, "Please enter a message to send to other servants.", "Hierophant Network", "") - if(!input || !IsAvailable()) + if(!input || !IsAvailable(feedback = TRUE)) return if(ishuman(owner)) clockwork_say(owner, "[text2ratvar("Servants, hear my words: [input]")]", TRUE) diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm index 04d8dc951844..0db98281b710 100644 --- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm @@ -3,7 +3,7 @@ /datum/action/innate/call_weapon name = "Call Weapon" desc = "This definitely shouldn't exist." - icon_icon = 'icons/mob/actions/actions_clockcult.dmi' + button_icon = 'icons/mob/actions/actions_clockcult.dmi' button_icon_state = "ratvarian_spear" background_icon_state = "bg_clock" check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS @@ -12,7 +12,7 @@ var/obj/item/clockwork/weapon/weapon_type //The type of weapon to create var/obj/item/clockwork/weapon/weapon -/datum/action/innate/call_weapon/IsAvailable(silent = FALSE) +/datum/action/innate/call_weapon/IsAvailable(feedback = TRUE) if(!is_servant_of_ratvar(owner)) qdel(src) return @@ -39,11 +39,11 @@ owner.visible_message("A [weapon.name] materializes in [owner]'s hands!", "You call forth your [weapon.name]!") weapon.forceMove(get_turf(owner)) owner.put_in_hands(weapon) - owner.update_action_buttons_icon() + owner.update_mob_action_buttons() return TRUE /datum/action/innate/call_weapon/proc/weapon_reset(cooldown_time) cooldown = world.time + cooldown_time - addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob, update_action_buttons_icon)), cooldown_time) - owner.update_action_buttons_icon() + addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob, update_mob_action_buttons)), cooldown_time) + owner.update_mob_action_buttons() QDEL_NULL(weapon) diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm index 96380d7882e0..1d5cc29775fa 100644 --- a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm +++ b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm @@ -405,12 +405,12 @@ for(var/i in 1 to quickbound.len) if(!quickbound[i]) continue - var/datum/action/item_action/clock/quickbind/Q = new /datum/action/item_action/clock/quickbind(src) + var/datum/action/item_action/clock/quickbind/Q = add_item_action(/datum/action/item_action/clock/quickbind) Q.scripture_index = i var/datum/clockwork_scripture/quickbind_slot = GLOB.all_scripture[quickbound[i]] Q.name = "[quickbind_slot.name] ([Q.scripture_index])" Q.desc = quickbind_slot.quickbind_desc Q.button_icon_state = quickbind_slot.name - Q.UpdateButtons() + Q.build_all_button_icons() if(isliving(loc)) Q.Grant(loc) diff --git a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm index 542361bdf664..6a2cb6194d1a 100644 --- a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm +++ b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm @@ -73,7 +73,7 @@ var/mob/living/L = loc active = change_to icon_state = "judicial_visor_[active]" - L.update_action_buttons_icon() + L.update_mob_action_buttons() L.update_inv_glasses() if(!is_servant_of_ratvar(L) || L.stat) return FALSE @@ -95,7 +95,7 @@ active = FALSE icon_state = "judicial_visor_[active]" if(user) - user.update_action_buttons_icon() + user.update_mob_action_buttons() user.update_inv_glasses() /obj/effect/proc_holder/judicial_visor @@ -137,7 +137,7 @@ var/turf/targetturf = get_turf(target) new/obj/effect/clockwork/judicial_marker(targetturf, ranged_ability_user) log_combat(ranged_ability_user, targetturf, "created a judicial marker") - ranged_ability_user.update_action_buttons_icon() + ranged_ability_user.update_mob_action_buttons() ranged_ability_user.update_inv_glasses() addtimer(CALLBACK(visor, TYPE_PROC_REF(/obj/item/clothing/glasses/judicial_visor, recharge_visor), ranged_ability_user), GLOB.ratvar_awakens ? visor.recharge_cooldown*0.1 : visor.recharge_cooldown)//Cooldown is reduced by 10x if Ratvar is up remove_ranged_ability() diff --git a/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm b/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm index 9a626f4f797b..1bc27973512d 100644 --- a/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm +++ b/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm @@ -231,11 +231,11 @@ /datum/action/innate/eminence name = "Eminence Action" desc = "You shouldn't see this. File a bug report!" - icon_icon = 'icons/mob/actions/actions_clockcult.dmi' + button_icon = 'icons/mob/actions/actions_clockcult.dmi' background_icon_state = "bg_clock" buttontooltipstyle = "clockcult" -/datum/action/innate/eminence/IsAvailable(silent = FALSE) +/datum/action/innate/eminence/IsAvailable(feedback = TRUE) if(!iseminence(owner)) qdel(src) return @@ -323,7 +323,7 @@ desc = "Initiates a mass recall, warping all servants to the Ark after a short delay. This can only be used once." button_icon_state = "Spatial Gateway" -/datum/action/innate/eminence/mass_recall/IsAvailable(silent = FALSE) +/datum/action/innate/eminence/mass_recall/IsAvailable(feedback = TRUE) . = ..() if(.) var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar diff --git a/code/modules/antagonists/clockcult/clock_mobs/clockwork_guardian.dm b/code/modules/antagonists/clockcult/clock_mobs/clockwork_guardian.dm index 44139c6ab9c3..c6be20288a25 100644 --- a/code/modules/antagonists/clockcult/clock_mobs/clockwork_guardian.dm +++ b/code/modules/antagonists/clockcult/clock_mobs/clockwork_guardian.dm @@ -381,12 +381,14 @@ var/list/defend_phrases = list("Defend me", "Come forth", "Assist me", "Protect me", "Give aid", "Help me") var/list/return_phrases = list("Return", "Return to me", "Your job is done", "You have served", "Come back", "Retreat") -/datum/action/innate/summon_guardian/IsAvailable() +/datum/action/innate/summon_guardian/IsAvailable(feedback) if(!linked_guardian) return FALSE if(isliving(owner)) var/mob/living/L = owner if(!L.can_speak_vocal() || L.stat) + if(feedback) + L.balloon_alert(L, "can't speak!") return FALSE return ..() @@ -409,7 +411,7 @@ buttontooltipstyle = "clockcult" var/mob/living/simple_animal/hostile/clockwork/guardian/linked_guardian -/datum/action/innate/linked_minds/IsAvailable() +/datum/action/innate/linked_minds/IsAvailable(feedback) if(!linked_guardian) return FALSE return ..() diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm index 5d5aa95e47a0..8780f86e3c2b 100644 --- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm @@ -174,7 +174,7 @@ /datum/action/innate/clockwork_armaments name = "Clockwork Armaments" desc = "Outfits you in a full set of Ratvarian armor." - icon_icon = 'icons/mob/actions/actions_clockcult.dmi' + button_icon = 'icons/mob/actions/actions_clockcult.dmi' button_icon_state = "clockwork_armor" background_icon_state = "bg_clock" check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS @@ -190,7 +190,7 @@ /obj/item/clothing/head/helmet/space, /obj/item/clothing/shoes/magboots)) //replace this only if ratvar is up -/datum/action/innate/clockwork_armaments/IsAvailable(silent = FALSE) +/datum/action/innate/clockwork_armaments/IsAvailable(feedback = TRUE) if(!is_servant_of_ratvar(owner)) qdel(src) return @@ -216,8 +216,8 @@ owner.visible_message("Strange armor appears on [owner]!", "A bright shimmer runs down your body, equipping you with Ratvarian armor.") playsound(owner, 'sound/magic/clockwork/fellowship_armory.ogg', 15 * do_message, TRUE) //get sound loudness based on how much we equipped cooldown = CLOCKWORK_ARMOR_COOLDOWN + world.time - owner.update_action_buttons_icon() - addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob, update_action_buttons_icon)), CLOCKWORK_ARMOR_COOLDOWN) + owner.update_mob_action_buttons() + addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob, update_mob_action_buttons)), CLOCKWORK_ARMOR_COOLDOWN) return TRUE /datum/action/innate/clockwork_armaments/proc/remove_item_if_better(obj/item/I, mob/user) diff --git a/code/modules/antagonists/clockcult/clockcult.dm b/code/modules/antagonists/clockcult/clockcult.dm index f052afc4b49b..3e77da250195 100644 --- a/code/modules/antagonists/clockcult/clockcult.dm +++ b/code/modules/antagonists/clockcult/clockcult.dm @@ -97,7 +97,7 @@ GLOB.all_clockwork_mobs += current current.faction |= "ratvar" current.grant_language(/datum/language/ratvar, source = LANGUAGE_CLOCKIE) - current.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them for whatever reason, we need to update buttons + current.update_mob_action_buttons() //because a few clockcult things are action buttons and we may be wearing/holding them for whatever reason, we need to update buttons if(issilicon(current)) var/mob/living/silicon/S = current if(iscyborg(S)) @@ -171,7 +171,7 @@ var/mob/living/silicon/robot/R = temp_owner R.module.rebuild_modules() if(temp_owner) - temp_owner.update_action_buttons_icon() //because a few clockcult things are action buttons and we may be wearing/holding them, we need to update buttons + temp_owner.update_mob_action_buttons() //because a few clockcult things are action buttons and we may be wearing/holding them, we need to update buttons temp_owner.cut_overlays() temp_owner.regenerate_icons() diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index d4ff89084c5f..5ac256c2fb12 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -12,7 +12,7 @@ qdel(X) ..() -/datum/action/innate/cult/blood_magic/IsAvailable(silent = FALSE) +/datum/action/innate/cult/blood_magic/IsAvailable(feedback = TRUE) if(!iscultist(owner)) return FALSE return ..() @@ -119,7 +119,7 @@ hand_magic = null ..() -/datum/action/innate/cult/blood_spell/IsAvailable(silent = FALSE) +/datum/action/innate/cult/blood_spell/IsAvailable(feedback = TRUE) if(!iscultist(owner) || owner.incapacitated() || !charges) return FALSE return ..() @@ -274,7 +274,7 @@ attached_action.charges-- attached_action.desc = attached_action.base_desc attached_action.desc += "
Has [attached_action.charges] use\s remaining." - attached_action.UpdateButtons() + attached_action.build_all_button_icons() if(attached_action.charges <= 0) remove_ranged_ability("You have exhausted the spell's power!") qdel(src) @@ -326,7 +326,7 @@ qdel(src) desc = base_desc desc += "
Has [charges] use\s remaining." - UpdateButtons() + build_all_button_icons() /datum/action/innate/cult/blood_spell/manipulation name = "Blood Rites" @@ -374,7 +374,7 @@ source.charges = uses source.desc = source.base_desc source.desc += "
Has [uses] use\s remaining." - source.UpdateButtons() + source.build_all_button_icons() ..() /obj/item/melee/blood_magic/attack_self(mob/living/user) @@ -401,7 +401,7 @@ else if(source) source.desc = source.base_desc source.desc += "
Has [uses] use\s remaining." - source.UpdateButtons() + source.build_all_button_icons() //Stun /obj/item/melee/blood_magic/stun diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index fe9f8cbe040a..6ea222811d5d 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -223,7 +223,7 @@ reckoning.Grant(current) bloodmark.Grant(current) throwing.Grant(current) - current.update_action_buttons_icon() + current.update_mob_action_buttons() current.apply_status_effect(/datum/status_effect/cult_master) if(cult_team?.cult_risen) cult_team.rise(current) @@ -238,7 +238,7 @@ reckoning.Remove(current) bloodmark.Remove(current) throwing.Remove(current) - current.update_action_buttons_icon() + current.update_mob_action_buttons() current.remove_status_effect(/datum/status_effect/cult_master) if(ishuman(current)) diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm index cd348485f10a..6da75fe053cf 100644 --- a/code/modules/antagonists/cult/cult_comms.dm +++ b/code/modules/antagonists/cult/cult_comms.dm @@ -1,12 +1,12 @@ // Contains cult communion, guide, and cult master abilities /datum/action/innate/cult - icon_icon = 'icons/mob/actions/actions_cult.dmi' + button_icon = 'icons/mob/actions/actions_cult.dmi' background_icon_state = "bg_demon" buttontooltipstyle = "cult" check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS -/datum/action/innate/cult/IsAvailable(silent = FALSE) +/datum/action/innate/cult/IsAvailable(feedback = TRUE) if(!iscultist(owner)) return FALSE return ..() @@ -18,7 +18,7 @@ /datum/action/innate/cult/comm/Activate() var/input = stripped_input(usr, "Please choose a message to tell to the other acolytes.", "Voice of Blood", "") - if(!input || !IsAvailable()) + if(!input || !IsAvailable(feedback = TRUE)) return cultist_commune(usr, input) @@ -51,7 +51,7 @@ name = "Spiritual Communion" desc = "Conveys a message from the spirit realm that all cultists can hear." -/datum/action/innate/cult/comm/spirit/IsAvailable(silent = FALSE) +/datum/action/innate/cult/comm/spirit/IsAvailable(feedback = TRUE) if(iscultist(owner.mind.current)) return TRUE @@ -72,7 +72,7 @@ name = "Assert Leadership" button_icon_state = "cultvote" -/datum/action/innate/cult/mastervote/IsAvailable(silent = FALSE) +/datum/action/innate/cult/mastervote/IsAvailable(feedback = TRUE) var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) if(!C?.cult_team || C.cult_team.cult_vote_called || !ishuman(owner)) return FALSE @@ -80,10 +80,10 @@ /datum/action/innate/cult/mastervote/Activate() var/choice = alert(owner, "The mantle of leadership is heavy. Success in this role requires an expert level of communication and experience. Are you sure?",, "Yes", "No") - if(choice == "Yes" && IsAvailable()) + if(choice == "Yes" && IsAvailable(feedback = TRUE)) var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) if(!C.cult_team) - to_chat(owner, "Do you not already lead yourself?") + to_chat(owner, span_cultbold("Do you not already lead yourself?")) return pollCultists(owner,C.cult_team) @@ -94,7 +94,7 @@ team.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try for(var/datum/mind/B in team.members) if(B.current) - B.current.update_action_buttons_icon() + B.current.update_mob_action_buttons() if(!B.current.incapacitated()) SEND_SOUND(B.current, 'sound/hallucinations/im_here1.ogg') to_chat(B.current, "Acolyte [Nominee] has asserted that [Nominee.p_theyre()] worthy of leading the cult. A vote will be called shortly.") @@ -109,7 +109,7 @@ team.cult_vote_called = FALSE for(var/datum/mind/B in team.members) if(B.current) - B.current.update_action_buttons_icon() + B.current.update_mob_action_buttons() if(!B.current.incapacitated()) to_chat(B.current,"[Nominee] has died in the process of attempting to win the cult's support!") return FALSE @@ -117,7 +117,7 @@ team.cult_vote_called = FALSE for(var/datum/mind/B in team.members) if(B.current) - B.current.update_action_buttons_icon() + B.current.update_mob_action_buttons() if(!B.current.incapacitated()) to_chat(B.current,"[Nominee] has gone catatonic in the process of attempting to win the cult's support!") return FALSE @@ -125,7 +125,7 @@ team.cult_vote_called = FALSE for(var/datum/mind/B in team.members) if(B.current) - B.current.update_action_buttons_icon() + B.current.update_mob_action_buttons() if(!B.current.incapacitated()) to_chat(B.current, "[Nominee] could not win the cult's support and shall continue to serve as an acolyte.") return FALSE @@ -140,7 +140,7 @@ to_chat(B.current,"[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(silent = FALSE) +/datum/action/innate/cult/master/IsAvailable(feedback = TRUE) if(!owner.mind || !owner.mind.has_antag_datum(/datum/antagonist/cult/master) || GLOB.cult_narsie) return FALSE return ..() @@ -226,9 +226,9 @@ CM.attached_action = src ..() -/datum/action/innate/cult/master/cultmark/IsAvailable(silent = FALSE) +/datum/action/innate/cult/master/cultmark/IsAvailable(feedback = TRUE) if(cooldown > world.time) - if(!CM.active && !silent) + if(!CM.active && feedback) to_chat(owner, "You need to wait [DisplayTimeText(cooldown - world.time)] before you can mark another target!") return FALSE return ..() @@ -278,7 +278,7 @@ C.cult_team.blood_target = target var/area/A = get_area(target) attached_action.cooldown = world.time + attached_action.base_cooldown - addtimer(CALLBACK(attached_action.owner, TYPE_PROC_REF(/mob, update_action_buttons_icon)), attached_action.base_cooldown) + addtimer(CALLBACK(attached_action.owner, TYPE_PROC_REF(/mob, update_mob_action_buttons)), attached_action.base_cooldown) C.cult_team.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) C.cult_team.blood_target_image.appearance_flags = RESET_COLOR C.cult_team.blood_target_image.pixel_x = -target.pixel_x @@ -288,7 +288,7 @@ to_chat(B.current, "[ranged_ability_user] has marked [C.cult_team.blood_target] in the [A.name] as the cult's top priority, get there immediately!") SEND_SOUND(B.current, sound(pick('sound/hallucinations/over_here2.ogg','sound/hallucinations/over_here3.ogg'),0,1,75)) B.current.client.images += C.cult_team.blood_target_image - attached_action.owner.update_action_buttons_icon() + attached_action.owner.update_mob_action_buttons() remove_ranged_ability("The marking rite is complete! It will last for 90 seconds.") C.cult_team.blood_target_reset_timer = addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(reset_blood_target),C.cult_team), 900, TIMER_STOPPABLE) return TRUE @@ -308,7 +308,7 @@ name = "Mark a Blood Target for the Cult" desc = "Marks a target for the entire cult to track." -/datum/action/innate/cult/master/cultmark/ghost/IsAvailable(silent = FALSE) +/datum/action/innate/cult/master/cultmark/ghost/IsAvailable(feedback = TRUE) if(istype(owner, /mob/dead/observer) && iscultist(owner.mind.current)) return TRUE else @@ -322,7 +322,7 @@ var/cooldown = 0 var/base_cooldown = 600 -/datum/action/innate/cult/ghostmark/IsAvailable(silent = FALSE) +/datum/action/innate/cult/ghostmark/IsAvailable(feedback = TRUE) if(istype(owner, /mob/dead/observer) && iscultist(owner.mind.current)) return TRUE else @@ -333,7 +333,7 @@ name = "Blood Mark your Target" desc = "Marks whatever you are orbitting - for the entire cult to track." button_icon_state = "cult_mark" - owner.update_action_buttons_icon() + owner.update_mob_action_buttons() SEND_SOUND(owner, 'sound/magic/enter_blood.ogg') to_chat(owner,"Your previous mark is gone - you are now ready to create a new blood mark.") @@ -360,7 +360,7 @@ C.cult_team.blood_target = target var/area/A = get_area(target) cooldown = world.time + base_cooldown - addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob, update_action_buttons_icon)), base_cooldown) + addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob, update_mob_action_buttons)), base_cooldown) C.cult_team.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) C.cult_team.blood_target_image.appearance_flags = RESET_COLOR C.cult_team.blood_target_image.pixel_x = -C.cult_team.blood_target.pixel_x @@ -376,7 +376,7 @@ name = "Clear the Blood Mark" desc = "Remove the Blood Mark you previously set." button_icon_state = "emp" - owner.update_action_buttons_icon() + owner.update_mob_action_buttons() C.cult_team.blood_target_reset_timer = addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(reset_blood_target),C.cult_team), base_cooldown, TIMER_STOPPABLE) addtimer(CALLBACK(src, PROC_REF(reset_button)), base_cooldown) @@ -388,7 +388,7 @@ /datum/action/innate/cult/master/pulse name = "Eldritch Pulse" desc = "Seize upon a fellow cultist or cult structure and teleport it to a nearby location." - icon_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon = 'icons/mob/actions/actions_spells.dmi' button_icon_state = "arcane_barrage" var/obj/effect/proc_holder/pulse/PM var/cooldown = 0 @@ -401,11 +401,11 @@ PM.attached_action = src ..() -/datum/action/innate/cult/master/pulse/IsAvailable(silent = FALSE) +/datum/action/innate/cult/master/pulse/IsAvailable(feedback = TRUE) if(!owner.mind || !owner.mind.has_antag_datum(/datum/antagonist/cult/master)) return FALSE if(cooldown > world.time) - if(!PM.active && !silent) + if(!PM.active && feedback) to_chat(owner, "You need to wait [DisplayTimeText(cooldown - world.time)] before you can pulse again!") return FALSE return ..() @@ -467,5 +467,5 @@ attached_action.throwing = FALSE attached_action.cooldown = world.time + attached_action.base_cooldown remove_ranged_ability("A pulse of blood magic surges through you as you shift [attached_action.throwee] through time and space.") - caller.update_action_buttons_icon() - addtimer(CALLBACK(caller, TYPE_PROC_REF(/mob, update_action_buttons_icon)), attached_action.base_cooldown) + caller.update_mob_action_buttons() + addtimer(CALLBACK(caller, TYPE_PROC_REF(/mob, update_mob_action_buttons)), attached_action.base_cooldown) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 878fe4a443f6..0b71a28093b5 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -222,7 +222,7 @@ /datum/action/innate/dash/cult name = "Rend the Veil" desc = "Use the sword to shear open the flimsy fabric of this reality and teleport to your target." - icon_icon = 'icons/mob/actions/actions_cult.dmi' + button_icon = 'icons/mob/actions/actions_cult.dmi' button_icon_state = "phaseshift" dash_sound = 'sound/magic/enter_blood.ogg' recharge_sound = 'sound/magic/exit_blood.ogg' @@ -230,7 +230,7 @@ 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(silent = FALSE) +/datum/action/innate/dash/cult/IsAvailable(feedback = TRUE) if(iscultist(owner) && current_charges) return TRUE else @@ -250,7 +250,7 @@ sword = bastard holder = user -/datum/action/innate/cult/spin2win/IsAvailable(silent = FALSE) +/datum/action/innate/cult/spin2win/IsAvailable(feedback = TRUE) if(iscultist(holder) && cooldown <= world.time) return TRUE else @@ -264,14 +264,14 @@ sword.block_chance = 100 sword.slowdown += 1.5 addtimer(CALLBACK(src, PROC_REF(stop_spinning)), 50) - holder.update_action_buttons_icon() + holder.update_mob_action_buttons() /datum/action/innate/cult/spin2win/proc/stop_spinning() sword.spinning = FALSE sword.block_chance = 50 sword.slowdown -= 1.5 sleep(sword.spin_cooldown) - holder.update_action_buttons_icon() + holder.update_mob_action_buttons() /obj/item/restraints/legcuffs/bola/cult name = "\improper Nar'Sien bola" diff --git a/code/modules/antagonists/cult/rune_spawn_action.dm b/code/modules/antagonists/cult/rune_spawn_action.dm index fd3c704849b1..47498c9f9f53 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(silent = FALSE) +/datum/action/innate/cult/create_rune/IsAvailable(feedback = TRUE) if(!rune_type || cooldown > world.time) return FALSE return ..() @@ -56,8 +56,8 @@ R4 = new rune_center_type(T, scribe_time, rune_color) cooldown = base_cooldown + world.time - owner.update_action_buttons_icon() - addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob, update_action_buttons_icon)), base_cooldown) + owner.update_mob_action_buttons() + addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob, update_mob_action_buttons)), base_cooldown) var/list/health if(damage_interrupt && isliving(owner)) var/mob/living/L = owner @@ -78,7 +78,7 @@ if(R4) qdel(R4) cooldown = 0 - owner.update_action_buttons_icon() + owner.update_mob_action_buttons() //teleport rune /datum/action/innate/cult/create_rune/tele diff --git a/code/modules/antagonists/disease/disease_abilities.dm b/code/modules/antagonists/disease/disease_abilities.dm index 0b5258dd5049..7a50c5fea4fd 100644 --- a/code/modules/antagonists/disease/disease_abilities.dm +++ b/code/modules/antagonists/disease/disease_abilities.dm @@ -164,7 +164,7 @@ new /datum/disease_ability/symptom/powerful/youth /datum/action/cooldown/disease_cough name = "Cough" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "cough" desc = "Force the host you are following to cough with extra force, spreading your infection to those within two meters of your host even if your transmissibility is low.
Cooldown: 10 seconds" cooldown_time = 100 @@ -194,7 +194,7 @@ new /datum/disease_ability/symptom/powerful/youth /datum/action/cooldown/disease_sneeze name = "Sneeze" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "sneeze" desc = "Force the host you are following to sneeze with extra force, spreading your infection to any victims in a 4 meter cone in front of your host even if your transmissibility is low.
Cooldown: 20 seconds" cooldown_time = 200 @@ -228,7 +228,7 @@ new /datum/disease_ability/symptom/powerful/youth /datum/action/cooldown/disease_infect name = "Secrete Infection" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "infect" desc = "Cause the host you are following to excrete an infective substance from their pores, causing all objects touching their skin to transmit your infection to anyone who touches them for the next 30 seconds.
Cooldown: 40 seconds" cooldown_time = 400 diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm index ea538c93ba52..5337fc20fac5 100644 --- a/code/modules/antagonists/disease/disease_mob.dm +++ b/code/modules/antagonists/disease/disease_mob.dm @@ -403,7 +403,7 @@ the new instance inside the host to be updated to the template's stats. /datum/action/innate/disease_adapt name = "Adaptation Menu" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "disease_menu" /datum/action/innate/disease_adapt/Activate() diff --git a/code/modules/antagonists/eldritch_cult/eldritch_items.dm b/code/modules/antagonists/eldritch_cult/eldritch_items.dm index 58e0193de583..a34b786d3c16 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_items.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_items.dm @@ -371,7 +371,7 @@ desc = "Destroys all runes that were drawn by this blade." background_icon_state = "bg_ecult" button_icon_state = "rune_break" - icon_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon = 'icons/mob/actions/actions_ecult.dmi' check_flags = AB_CHECK_CONSCIOUS ///Reference to the rune knife it is inside of var/obj/item/melee/rune_knife/sword diff --git a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm index 9dc1d3f995c6..ce47257611e3 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm @@ -608,7 +608,7 @@ name = "Mansus Link" desc = "Send a psychic message to everyone connected to your Mansus Net." button_icon_state = "link_speech" - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_ecult" var/mob/living/simple_animal/hostile/eldritch/raw_prophet/originator diff --git a/code/modules/antagonists/gang/gang.dm b/code/modules/antagonists/gang/gang.dm index 058379d96c6f..af9ec4259332 100644 --- a/code/modules/antagonists/gang/gang.dm +++ b/code/modules/antagonists/gang/gang.dm @@ -220,7 +220,7 @@ desc = "Teach new recruits the Secret Handshake to join." check_flags = AB_CHECK_CONSCIOUS button_icon_state = "recruit" - icon_icon = 'icons/obj/gang/actions.dmi' + button_icon = 'icons/obj/gang/actions.dmi' cooldown_time = 300 /// The family antagonist datum of the "owner" of this action. var/datum/antagonist/gang/my_gang_datum diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm index e81d7f236909..c461fc5f6d8a 100644 --- a/code/modules/antagonists/revenant/revenant.dm +++ b/code/modules/antagonists/revenant/revenant.dm @@ -132,7 +132,7 @@ to_chat(src, "You can move again!") if(essence_regenerating && !inhibited && essence < essence_regen_cap) //While inhibited, essence will not regenerate essence = min(essence_regen_cap, essence+essence_regen_amount) - update_action_buttons_icon() //because we update something required by our spells in life, we need to update our buttons + update_mob_action_buttons() //because we update something required by our spells in life, we need to update our buttons update_spooky_icon() update_health_hud() @@ -200,12 +200,12 @@ "As \the [W] passes through you, you feel your essence draining away!") adjustBruteLoss(25) //hella effective inhibited = TRUE - update_action_buttons_icon() + update_mob_action_buttons() addtimer(CALLBACK(src, PROC_REF(reset_inhibit)), 30) /mob/living/simple_animal/revenant/proc/reset_inhibit() inhibited = FALSE - update_action_buttons_icon() + update_mob_action_buttons() /mob/living/simple_animal/revenant/adjustHealth(amount, updating_health = TRUE, forced = FALSE) if(!forced && !revealed) @@ -314,7 +314,7 @@ if(essence_excess < essence_cost) return FALSE essence_excess -= essence_cost - update_action_buttons_icon() + update_mob_action_buttons() return TRUE /mob/living/simple_animal/revenant/proc/change_essence_amount(essence_amt, silent = FALSE, source = null) @@ -327,7 +327,7 @@ if(essence_amt > 0) essence_accumulated = max(0, essence_accumulated+essence_amt) essence_excess = max(0, essence_excess+essence_amt) - update_action_buttons_icon() + update_mob_action_buttons() if(!silent) if(essence_amt > 0) to_chat(src, "Gained [essence_amt]E[source ? " from [source]":""].") diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm index 3eea2d9ad845..e22bc768fdf6 100644 --- a/code/modules/antagonists/revenant/revenant_abilities.dm +++ b/code/modules/antagonists/revenant/revenant_abilities.dm @@ -138,7 +138,7 @@ else name = "[initial(name)] ([cast_amount]E)" -/obj/effect/proc_holder/spell/aoe_turf/revenant/can_cast(mob/living/simple_animal/revenant/user = usr, skipcharge = FALSE, silent = FALSE) +/obj/effect/proc_holder/spell/aoe_turf/revenant/can_cast(mob/living/simple_animal/revenant/user = usr, skipcharge = FALSE, feedback = TRUE) if(charge_counter < charge_max) return FALSE if(!istype(user)) //Badmins, no. Badmins, don't do it. @@ -176,7 +176,7 @@ user.reveal(reveal) user.stun(stun) if(action) - action.UpdateButtons() + action.build_all_button_icons() return TRUE //Overload Light: Breaks a light that's online and sends out lightning bolts to all nearby people. diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm index 802d9eb5eab7..39316f134465 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -82,7 +82,7 @@ /datum/action/cooldown/slam name = "Slaughter Slam" desc = "Launch enemies and break bones in one strike." - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' background_icon_state = "bg_demon" button_icon_state = "slam" cooldown_time = 45 SECONDS diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm index 44e70ebb3405..4c68d7fde1c0 100644 --- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm +++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm @@ -23,7 +23,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( name = "AI Action" desc = "You aren't entirely sure what this does, but it's very beepy and boopy." background_icon_state = "bg_tech_blue" - icon_icon = 'icons/mob/actions/actions_AI.dmi' + button_icon = 'icons/mob/actions/actions_AI.dmi' check_flags = AB_CHECK_CONSCIOUS //can't doomsday if dead. var/mob/living/silicon/ai/owner_AI //The owner AI, so we don't have to typecast every time var/uses //If we have multiple uses of the same power @@ -43,28 +43,29 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( else owner_AI = owner -/datum/action/innate/ai/IsAvailable(silent = FALSE) +/datum/action/innate/ai/IsAvailable(feedback = TRUE) . = ..() if(owner_AI && owner_AI.malf_cooldown > world.time) return FALSE -/datum/action/innate/ai/Trigger() +/datum/action/innate/ai/Trigger(trigger_flags) . = ..() if(auto_use_uses) adjust_uses(-1) if(cooldown_period) owner_AI.malf_cooldown = world.time + cooldown_period + return TRUE /datum/action/innate/ai/proc/adjust_uses(amt, silent) uses += amt if(uses) if(!silent) - to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.") + to_chat(owner, span_notice("[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.")) desc = "[initial(desc)] It has [uses] use\s remaining." - UpdateButtons() + build_all_button_icons() return if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway! - to_chat(owner, "[name] has run out of uses!") + to_chat(owner, span_warning("[name] has run out of uses!")) qdel(src) @@ -88,12 +89,12 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( uses += amt if(uses) if(!silent) - to_chat(owner, "[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.") + to_chat(owner, span_notice("[name] now has [uses] use[uses > 1 ? "s" : ""] remaining.")) desc = "[initial(desc)] It has [uses] use\s remaining." - UpdateButtons() + build_all_button_icons() return if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway! - to_chat(owner, "[name] has run out of uses!") + to_chat(owner, span_warning("[name] has run out of uses!")) Remove(owner) QDEL_IN(src, 100) //let any active timers on us finish up @@ -107,8 +108,8 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( //The actual ranged proc holder. /obj/effect/proc_holder/ranged_ai - var/enable_text = "Hello World!" //Appears when the user activates the ability - var/disable_text = "Goodbye Cruel World!" //Context clues! + var/enable_text = span_notice("Hello World!") //Appears when the user activates the ability + var/disable_text = span_danger("Goodbye Cruel World!") //Context clues! var/datum/action/innate/ai/ranged/attached_action /obj/effect/proc_holder/ranged_ai/Destroy() @@ -166,7 +167,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( var/mob/living/silicon/ai/A = usr if(A.stat == DEAD) - to_chat(A, "You are already dead!") + to_chat(A, span_warning("You are already dead!")) return for(var/datum/AI_Module/AM in possible_modules) @@ -201,7 +202,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( else //Adding uses to an existing module action.uses += initial(action.uses) action.desc = "[initial(action.desc)] It has [action.uses] use\s remaining." - action.UpdateButtons() + action.build_all_button_icons() temp = "Additional use[action.uses > 1 ? "s" : ""] added to [action.name]!" processing_time -= AM.cost @@ -222,7 +223,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( var/power_type = /datum/action/innate/ai //If the module gives an active ability, use this. Mutually exclusive with upgrade. var/upgrade //If the module gives a passive upgrade, use this. Mutually exclusive with power_type. - var/unlock_text = "Hello World!" //Text shown when an ability is unlocked + var/unlock_text = span_notice("Hello World!") //Text shown when an ability is unlocked var/unlock_sound //Sound played when an ability is unlocked /datum/AI_Module/proc/upgrade(mob/living/silicon/ai/AI) //Apply upgrades! @@ -240,7 +241,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( cost = 130 one_purchase = TRUE power_type = /datum/action/innate/ai/nuke_station - unlock_text = "You slowly, carefully, establish a connection with the on-station self-destruct. You can now activate it at any time." + unlock_text = span_notice("You slowly, carefully, establish a connection with the on-station self-destruct. You can now activate it at any time.") /datum/action/innate/ai/nuke_station name = "Doomsday Device" @@ -251,7 +252,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( /datum/action/innate/ai/nuke_station/Activate() var/turf/T = get_turf(owner) if(!istype(T) || !is_station_level(T.z)) - to_chat(owner, "You cannot activate the doomsday device while off-station!") + to_chat(owner, span_warning("You cannot activate the doomsday device while off-station!")) return if(alert(owner, "Send arming signal? (true = arm, false = cancel)", "purge_all_life()", "confirm = TRUE;", "confirm = FALSE;") != "confirm = TRUE;") return @@ -275,13 +276,13 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( if(QDELETED(owner) || owner.stat == DEAD) return owner.playsound_local(owner, 'sound/misc/bloblarm.ogg', 50, 0) - to_chat(owner, "!!! UNAUTHORIZED SELF-DESTRUCT ACCESS !!!") - to_chat(owner, "This is a class-3 security violation. This incident will be reported to Central Command.") + to_chat(owner, span_userdanger("!!! UNAUTHORIZED SELF-DESTRUCT ACCESS !!!")) + to_chat(owner, span_boldannounce("This is a class-3 security violation. This incident will be reported to Central Command.")) for(var/i in 1 to 3) sleep(20) if(QDELETED(owner) || owner.stat == DEAD) return - to_chat(owner, "Sending security report to Central Command.....[rand(0, 9) + (rand(20, 30) * i)]%") + to_chat(owner, span_boldannounce("Sending security report to Central Command.....[rand(0, 9) + (rand(20, 30) * i)]%")) sleep(3) if(QDELETED(owner) || owner.stat == DEAD) return @@ -290,12 +291,12 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( sleep(30) if(QDELETED(owner) || owner.stat == DEAD) return - to_chat(owner, "Credentials accepted. Welcome, akjv9c88asdf12nb.") + to_chat(owner, span_boldnotice("Credentials accepted. Welcome, akjv9c88asdf12nb.")) owner.playsound_local(owner, 'sound/misc/server-ready.ogg', 50, 0) sleep(5) if(QDELETED(owner) || owner.stat == DEAD) return - to_chat(owner, "Arm self-destruct device? (Y/N)") + to_chat(owner, span_boldnotice("Arm self-destruct device? (Y/N)")) owner.playsound_local(owner, 'sound/misc/compiler-stage1.ogg', 50, 0) sleep(20) if(QDELETED(owner) || owner.stat == DEAD) @@ -304,7 +305,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( sleep(15) if(QDELETED(owner) || owner.stat == DEAD) return - to_chat(owner, "Confirm arming of self-destruct device? (Y/N)") + to_chat(owner, span_boldnotice("Confirm arming of self-destruct device? (Y/N)")) owner.playsound_local(owner, 'sound/misc/compiler-stage2.ogg', 50, 0) sleep(10) if(QDELETED(owner) || owner.stat == DEAD) @@ -313,7 +314,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( sleep(rand(15, 25)) if(QDELETED(owner) || owner.stat == DEAD) return - to_chat(owner, "Please repeat password to confirm.") + to_chat(owner, span_boldnotice("Please repeat password to confirm.")) owner.playsound_local(owner, 'sound/misc/compiler-stage2.ogg', 50, 0) sleep(14) if(QDELETED(owner) || owner.stat == DEAD) @@ -322,14 +323,14 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( sleep(40) if(QDELETED(owner) || owner.stat == DEAD) return - to_chat(owner, "Credentials accepted. Transmitting arming signal...") + to_chat(owner, span_boldnotice("Credentials accepted. Transmitting arming signal...")) owner.playsound_local(owner, 'sound/misc/server-ready.ogg', 50, 0) sleep(30) if(QDELETED(owner) || owner.stat == DEAD) return if(istype(owner.loc, /obj/item/aicard)) - to_chat(owner, "Error: Signal transmission failed. Reason: Lost connection to network.") - to_chat(owner, "You can't activate the doomsday device while inside an intelliCard!") + to_chat(owner, span_boldnotice("Error: Signal transmission failed. Reason: Lost connection to network.")) + to_chat(owner, span_warning("You can't activate the doomsday device while inside an intelliCard!")) return priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", "aimalf") set_security_level("delta") @@ -409,7 +410,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( continue if(issilicon(L)) continue - to_chat(L, "The blast wave from [src] tears you atom from atom!") + to_chat(L, span_userdanger("The blast wave from [src] tears you atom from atom!")) L.dust() to_chat(world, "The AI cleansed the station of life with the doomsday device!") SSticker.force_ending = 1 @@ -422,7 +423,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( description = "Improves the power and health of all AI turrets. This effect is permanent." cost = 30 upgrade = TRUE - unlock_text = "You establish a power diversion to your turrets, upgrading their health and damage." + unlock_text = span_notice("You establish a power diversion to your turrets, upgrading their health and damage.") unlock_sound = 'sound/items/rped.ogg' /datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/ai/AI) @@ -441,7 +442,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( cost = 30 one_purchase = TRUE power_type = /datum/action/innate/ai/lockdown - unlock_text = "You upload a sleeper trojan into the door control systems. You can send a signal to set it off at any time." + unlock_text = span_notice("You upload a sleeper trojan into the door control systems. You can send a signal to set it off at any time.") unlock_sound = 'sound/machines/boltsdown.ogg' /datum/action/innate/ai/lockdown @@ -462,7 +463,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( C.post_status("alert", "lockdown") minor_announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.","Network Alert:", TRUE) - to_chat(owner, "Lockdown initiated. Network reset in 90 seconds.") + to_chat(owner, span_danger("Lockdown initiated. Network reset in 90 seconds.")) addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(minor_announce), "Automatic system reboot complete. Have a secure day.", "Network reset:"), 900) @@ -476,7 +477,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( cost = 25 one_purchase = TRUE power_type = /datum/action/innate/ai/destroy_rcds - unlock_text = "After some improvisation, you rig your onboard radio to be able to send a signal to detonate all RCDs." + unlock_text = span_notice("After some improvisation, you rig your onboard radio to be able to send a signal to detonate all RCDs.") unlock_sound = 'sound/items/timer.ogg' /datum/action/innate/ai/destroy_rcds @@ -491,7 +492,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( if(!istype(I, /obj/item/construction/rcd/borg)) //Ensures that cyborg RCDs are spared. var/obj/item/construction/rcd/RCD = I RCD.detonate_pulse() - to_chat(owner, "RCD detonation pulse emitted.") + to_chat(owner, span_danger("RCD detonation pulse emitted.")) owner.playsound_local(owner, 'sound/machines/twobeep.ogg', 50, 0) @@ -503,7 +504,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( Do not allow the mech to leave the station's vicinity or allow it to be destroyed." cost = 30 upgrade = TRUE - unlock_text = "Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout." + unlock_text = span_notice("Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout.") unlock_sound = 'sound/mecha/nominal.ogg' /datum/AI_Module/large/mecha_domination/upgrade(mob/living/silicon/ai/AI) @@ -519,7 +520,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( one_purchase = TRUE cost = 25 power_type = /datum/action/innate/ai/break_fire_alarms - unlock_text = "You replace the thermal sensing capabilities of all fire alarms with a manual override, allowing you to turn them off at will." + unlock_text = span_notice("You replace the thermal sensing capabilities of all fire alarms with a manual override, allowing you to turn them off at will.") unlock_sound = 'goon/sound/machinery/firealarm.ogg' /datum/action/innate/ai/break_fire_alarms @@ -534,7 +535,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( continue F.obj_flags |= EMAGGED F.update_icon() - to_chat(owner, "All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.") + to_chat(owner, span_notice("All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.")) owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0) @@ -547,7 +548,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( one_purchase = TRUE cost = 50 power_type = /datum/action/innate/ai/break_air_alarms - unlock_text = "You remove the safety overrides on all air alarms, but you leave the confirm prompts open. You can hit 'Yes' at any time... you bastard." + unlock_text = span_notice("You remove the safety overrides on all air alarms, but you leave the confirm prompts open. You can hit 'Yes' at any time... you bastard.") unlock_sound = 'sound/effects/space_wind.ogg' /datum/action/innate/ai/break_air_alarms @@ -561,7 +562,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( if(!is_station_level(AA.z)) continue AA.obj_flags |= EMAGGED - to_chat(owner, "All air alarm safeties on the station have been overridden. Air alarms may now use the Flood environmental mode.") + to_chat(owner, span_notice("All air alarm safeties on the station have been overridden. Air alarms may now use the Flood environmental mode.")) owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0) @@ -572,7 +573,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( description = "Overheats an electrical machine, causing a small explosion and destroying it. Two uses per purchase." cost = 20 power_type = /datum/action/innate/ai/ranged/overload_machine - unlock_text = "You enable the ability for the station's APCs to direct intense energy into machinery." + unlock_text = span_notice("You enable the ability for the station's APCs to direct intense energy into machinery.") unlock_sound = 'sound/effects/comfyfire.ogg' //definitely not comfy, but it's the closest sound to "roaring fire" we have /datum/action/innate/ai/ranged/overload_machine @@ -594,8 +595,8 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( /obj/effect/proc_holder/ranged_ai/overload_machine active = FALSE ranged_mousepointer = 'icons/effects/overload_machine_target.dmi' - enable_text = "You tap into the station's powernet. Click on a machine to detonate it, or use the ability again to cancel." - disable_text = "You release your hold on the powernet." + enable_text = span_notice("You tap into the station's powernet. Click on a machine to detonate it, or use the ability again to cancel.") + disable_text = span_notice("You release your hold on the powernet.") /obj/effect/proc_holder/ranged_ai/overload_machine/InterceptClickOn(mob/living/caller, params, obj/machinery/target) if(..()) @@ -604,16 +605,16 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( remove_ranged_ability() return if(!istype(target)) - to_chat(ranged_ability_user, "You can only overload machines!") + to_chat(ranged_ability_user, span_warning("You can only overload machines!")) return if(is_type_in_typecache(target, GLOB.blacklisted_malf_machines)) - to_chat(ranged_ability_user, "You cannot overload that device!") + to_chat(ranged_ability_user, span_warning("You cannot overload that device!")) return ranged_ability_user.playsound_local(ranged_ability_user, "sparks", 50, 0) attached_action.adjust_uses(-1) - target.audible_message("You hear a loud electrical buzzing sound coming from [target]!") + target.audible_message(span_userdanger("You hear a loud electrical buzzing sound coming from [target]!")) addtimer(CALLBACK(attached_action, TYPE_PROC_REF(/datum/action/innate/ai/ranged/overload_machine, detonate_machine), target), 50) //kaboom! - remove_ranged_ability("Overcharging machine...") + remove_ranged_ability(span_danger("Overcharging machine...")) return TRUE @@ -624,7 +625,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. Four uses." cost = 30 power_type = /datum/action/innate/ai/ranged/override_machine - unlock_text = "You procure a virus from the Space Dark Web and distribute it to the station's machines." + unlock_text = span_notice("You procure a virus from the Space Dark Web and distribute it to the station's machines.") unlock_sound = 'sound/machines/airlock_alien_prying.ogg' /datum/action/innate/ai/ranged/override_machine @@ -641,8 +642,8 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( /obj/effect/proc_holder/ranged_ai/override_machine active = FALSE ranged_mousepointer = 'icons/effects/override_machine_target.dmi' - enable_text = "You tap into the station's powernet. Click on a machine to animate it, or use the ability again to cancel." - disable_text = "You release your hold on the powernet." + enable_text = span_notice("You tap into the station's powernet. Click on a machine to animate it, or use the ability again to cancel.") + disable_text = span_notice("You release your hold on the powernet.") /obj/effect/proc_holder/ranged_ai/override_machine/InterceptClickOn(mob/living/caller, params, obj/machinery/target) if(..()) @@ -651,16 +652,16 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( remove_ranged_ability() return if(!istype(target)) - to_chat(ranged_ability_user, "You can only animate machines!") + to_chat(ranged_ability_user, span_warning("You can only animate machines!")) return if(!target.can_be_overridden() || is_type_in_typecache(target, GLOB.blacklisted_malf_machines)) - to_chat(ranged_ability_user, "That machine can't be overridden!") + to_chat(ranged_ability_user, span_warning("That machine can't be overridden!")) return ranged_ability_user.playsound_local(ranged_ability_user, 'sound/misc/interference.ogg', 50, 0) attached_action.adjust_uses(-1) - target.audible_message("You hear a loud electrical buzzing sound coming from [target]!") + target.audible_message(span_userdanger("You hear a loud electrical buzzing sound coming from [target]!")) addtimer(CALLBACK(attached_action, TYPE_PROC_REF(/datum/action/innate/ai/ranged/override_machine, animate_machine), target), 50) //kabeep! - remove_ranged_ability("Sending override signal...") + remove_ranged_ability(span_danger("Sending override signal...")) return TRUE @@ -672,7 +673,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( cost = 100 one_purchase = TRUE power_type = /datum/action/innate/ai/place_transformer - unlock_text = "You make contact with Space Amazon and request a robotics factory for delivery." + unlock_text = span_notice("You make contact with Space Amazon and request a robotics factory for delivery.") unlock_sound = 'sound/machines/ping.ogg' /datum/action/innate/ai/place_transformer @@ -704,7 +705,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( conveyor.masterAI = owner playsound(T, 'sound/effects/phasein.ogg', 100, 1) owner_AI.can_shunt = FALSE - to_chat(owner, "You are no longer able to shunt your core to APCs.") + to_chat(owner, span_warning("You are no longer able to shunt your core to APCs.")) adjust_uses(-1) /mob/living/silicon/ai/proc/remove_transformer_image(client/C, image/I, turf/T) @@ -736,7 +737,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( I.icon_state = "[success ? "green" : "red"]Overlay" //greenOverlay and redOverlay for success and failure respectively addtimer(CALLBACK(src, PROC_REF(remove_transformer_image), client, I, T), 30) if(!success) - to_chat(src, "[alert_msg]") + to_chat(src, span_warning("[alert_msg]")) return success @@ -747,7 +748,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. Three uses." cost = 15 power_type = /datum/action/innate/ai/blackout - unlock_text = "You hook into the powernet and route bonus power towards the station's lighting." + unlock_text = span_notice("You hook into the powernet and route bonus power towards the station's lighting.") unlock_sound = "sparks" /datum/action/innate/ai/blackout @@ -767,13 +768,13 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( apc.overload_lighting() else apc.overload++ - to_chat(owner, "Overcurrent applied to the powernet.") + to_chat(owner, span_notice("Overcurrent applied to the powernet.")) owner.playsound_local(owner, "sparks", 50, 0) adjust_uses(-1) if(QDELETED(src) || uses) //Not sure if not having src here would cause a runtime, so it's here to be safe return desc = "[initial(desc)] It has [uses] use\s remaining." - UpdateButtons() + build_all_button_icons() //Disable Emergency Lights /datum/AI_Module/small/emergency_lights @@ -783,7 +784,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( cost = 10 one_purchase = TRUE power_type = /datum/action/innate/ai/emergency_lights - unlock_text = "You hook into the powernet and locate the connections between light fixtures and their fallbacks." + unlock_text = span_notice("You hook into the powernet and locate the connections between light fixtures and their fallbacks.") unlock_sound = "sparks" /datum/action/innate/ai/emergency_lights @@ -798,7 +799,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( L.no_emergency = TRUE INVOKE_ASYNC(L, TYPE_PROC_REF(/obj/machinery/light, update), FALSE) CHECK_TICK - to_chat(owner, "Emergency light connections severed.") + to_chat(owner, span_notice("Emergency light connections severed.")) owner.playsound_local(owner, 'sound/effects/light_flicker.ogg', 50, FALSE) @@ -810,7 +811,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( cost = 10 one_purchase = TRUE power_type = /datum/action/innate/ai/reactivate_cameras - unlock_text = "You deploy nanomachines to the cameranet." + unlock_text = span_notice("You deploy nanomachines to the cameranet.") unlock_sound = 'sound/items/wirecutter.ogg' /datum/action/innate/ai/reactivate_cameras @@ -836,13 +837,13 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( C.view_range = initial(C.view_range) fixed_cameras++ uses-- //Not adjust_uses() so it doesn't automatically delete or show a message - to_chat(owner, "Diagnostic complete! Cameras reactivated: [fixed_cameras]. Reactivations remaining: [uses].") + to_chat(owner, span_notice("Diagnostic complete! Cameras reactivated: [fixed_cameras]. Reactivations remaining: [uses].")) owner.playsound_local(owner, 'sound/items/wirecutter.ogg', 50, 0) adjust_uses(0, TRUE) //Checks the uses remaining if(QDELETED(src) || !uses) //Not sure if not having src here would cause a runtime, so it's here to be safe return desc = "[initial(desc)] It has [uses] use\s remaining." - UpdateButtons() + build_all_button_icons() //Upgrade Camera Network: EMP-proofs all cameras, in addition to giving them X-ray vision. /datum/AI_Module/large/upgrade_cameras @@ -853,7 +854,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( one_purchase = TRUE cost = 35 //Decent price for omniscience! upgrade = TRUE - unlock_text = "OTA firmware distribution complete! Cameras upgraded: CAMSUPGRADED. Light amplification system online." + unlock_text = span_notice("OTA firmware distribution complete! Cameras upgraded: CAMSUPGRADED. Light amplification system online.") unlock_sound = 'sound/items/rped.ogg' /datum/AI_Module/large/upgrade_cameras/upgrade(mob/living/silicon/ai/AI) @@ -888,7 +889,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( cost = 30 one_purchase = TRUE upgrade = TRUE - unlock_text = "OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online." + unlock_text = span_notice("OTA firmware distribution complete! Cameras upgraded: Enhanced surveillance package online.") unlock_sound = 'sound/items/rped.ogg' /datum/AI_Module/large/eavesdrop/upgrade(mob/living/silicon/ai/AI) diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index b3030b67ecba..1bd0b759b162 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -2,13 +2,13 @@ /datum/action/item_action/chameleon/drone/randomise name = "Randomise Headgear" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "random" -/datum/action/item_action/chameleon/drone/randomise/Trigger() - if(!IsAvailable()) +/datum/action/item_action/chameleon/drone/randomise/do_effect(trigger_flags) + . = ..() + if(!.) return - // Damn our lack of abstract interfeces if (istype(target, /obj/item/clothing/head/chameleon/drone)) var/obj/item/clothing/head/chameleon/drone/X = target @@ -22,7 +22,7 @@ /datum/action/item_action/chameleon/drone/togglehatmask name = "Toggle Headgear Mode" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' /datum/action/item_action/chameleon/drone/togglehatmask/New() ..() @@ -32,19 +32,17 @@ if (istype(target, /obj/item/clothing/mask/chameleon/drone)) button_icon_state = "drone_camogear_mask" -/datum/action/item_action/chameleon/drone/togglehatmask/Trigger() - if(!IsAvailable()) +/datum/action/item_action/chameleon/drone/togglehatmask/do_effect(trigger_flags) + . = ..() + if(!.) return - // No point making the code more complicated if no non-drone // is ever going to use one of these - var/mob/living/simple_animal/drone/D + var/mob/living/simple_animal/drone/D = owner - if(istype(owner, /mob/living/simple_animal/drone)) - D = owner - else - return + if(!istype(owner, /mob/living/simple_animal/drone)) + return FALSE // The drone unEquip() proc sets head to null after dropping // an item, so we need to keep a reference to our old headgear @@ -58,13 +56,13 @@ new_headgear = new /obj/item/clothing/head/chameleon/drone() else to_chat(owner, "You shouldn't be able to toggle a camogear helmetmask if you're not wearing it") - if(new_headgear) - // Force drop the item in the headslot, even though - // it's TRAIT_NODROP - D.dropItemToGround(target, TRUE) - qdel(old_headgear) - // where is `ITEM_SLOT_HEAD` defined? WHO KNOWS - D.equip_to_slot(new_headgear, ITEM_SLOT_HEAD) + return FALSE + // Force drop the item in the headslot, even though + // it's TRAIT_NODROP + D.dropItemToGround(target, TRUE) + qdel(old_headgear) + // where is `ITEM_SLOT_HEAD` defined? WHO KNOWS + D.equip_to_slot(new_headgear, ITEM_SLOT_HEAD) return TRUE @@ -87,14 +85,17 @@ sortTim(standard_outfit_options, GLOBAL_PROC_REF(cmp_text_asc)) outfit_options = standard_outfit_options -/datum/action/chameleon_outfit/Trigger() +/datum/action/chameleon_outfit/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE 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 = input("Select outfit to change into", "Chameleon Outfit") as null|anything in outfit_options - if(!IsAvailable() || QDELETED(src) || QDELETED(user)) + if(!IsAvailable(feedback = TRUE) || QDELETED(src) || QDELETED(user)) return FALSE var/outfit_type = outfit_options[selected] if(!outfit_type) @@ -163,7 +164,7 @@ /datum/action/item_action/chameleon/change/proc/initialize_disguises() name = "Change [chameleon_name] Appearance" - UpdateButtons() + build_all_button_icons() chameleon_blacklist |= typecacheof(target.type) for(var/V in typesof(chameleon_type)) @@ -180,11 +181,11 @@ var/picked_name picked_name = input("Select [chameleon_name] to change into", "Chameleon [chameleon_name]", picked_name) as null|anything in chameleon_list if(!picked_name) - return + return FALSE picked_item = chameleon_list[picked_name] if(!picked_item) - return - update_look(user, picked_item) + return FALSE + return update_look(user, picked_item) /datum/action/item_action/chameleon/change/proc/random_look(mob/user) var/picked_name = pick(chameleon_list) @@ -201,15 +202,17 @@ update_item(chameleon_list[picked_name]) /datum/action/item_action/chameleon/change/proc/update_look(mob/user, obj/item/picked_item) - if(isliving(user)) - var/mob/living/C = user - if(C.stat != CONSCIOUS) - return + if(!isliving(user)) + return FALSE + var/mob/living/C = user + if(C.stat != CONSCIOUS) + return FALSE - update_item(picked_item) - var/obj/item/thing = target - thing.update_slot_icon() - UpdateButtons() + update_item(picked_item) + var/obj/item/thing = target + thing.update_slot_icon() + build_all_button_icons() + return TRUE /datum/action/item_action/chameleon/change/proc/update_item(obj/item/picked_item) var/obj/item/chameleon_item = target @@ -231,8 +234,11 @@ chameleon_item.icon = initial(picked_item.icon) /datum/action/item_action/chameleon/change/pda/update_item(obj/item/pda/picked_item) + . = ..() + if(!.) + return if(!istype(target, /obj/item/pda)) - return ..() + return var/obj/item/pda/P = target P.name = initial(picked_item.name) P.desc = initial(picked_item.desc) @@ -242,10 +248,7 @@ P.set_new_overlays() P.update_icon() -/datum/action/item_action/chameleon/change/Trigger() - if(!IsAvailable()) - return - +/datum/action/item_action/chameleon/change/do_effect(trigger_flags) select_look(owner) return TRUE @@ -293,7 +296,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/under/chameleon) /obj/item/clothing/under/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/clothing/under chameleon_action.chameleon_name = "Jumpsuit" chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/under, /obj/item/clothing/under/color, /obj/item/clothing/under/rank, /obj/item/clothing/under/changeling), only_root_path = TRUE) @@ -322,7 +325,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/suit/chameleon) /obj/item/clothing/suit/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/clothing/suit chameleon_action.chameleon_name = "Suit" chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/suit/armor/abductor, /obj/item/clothing/suit/changeling), only_root_path = TRUE) @@ -350,7 +353,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/glasses/chameleon) /obj/item/clothing/glasses/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/clothing/glasses chameleon_action.chameleon_name = "Glasses" chameleon_action.chameleon_blacklist = typecacheof(/obj/item/clothing/glasses/changeling, only_root_path = TRUE) @@ -382,7 +385,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/gloves/chameleon/insulated) /obj/item/clothing/gloves/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/clothing/gloves chameleon_action.chameleon_name = "Gloves" chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/gloves, /obj/item/clothing/gloves/color, /obj/item/clothing/gloves/changeling), only_root_path = TRUE) @@ -410,7 +413,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/head/chameleon) /obj/item/clothing/head/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/clothing/head chameleon_action.chameleon_name = "Hat" chameleon_action.chameleon_blacklist = typecacheof(/obj/item/clothing/head/changeling, only_root_path = TRUE) @@ -436,10 +439,10 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/head/chameleon) . = ..() ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) chameleon_action.random_look() - var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = new(src) - togglehatmask_action.UpdateButtons() - var/datum/action/item_action/chameleon/drone/randomise/randomise_action = new(src) - randomise_action.UpdateButtons() + var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = add_item_action(/datum/action/item_action/chameleon/drone/togglehatmask) + togglehatmask_action.build_all_button_icons() + var/datum/action/item_action/chameleon/drone/randomise/randomise_action = add_item_action(/datum/action/item_action/chameleon/drone/randomise) + randomise_action.build_all_button_icons() CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/mask/chameleon) name = "gas mask" @@ -460,7 +463,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/mask/chameleon) /obj/item/clothing/mask/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/clothing/mask chameleon_action.chameleon_name = "Mask" chameleon_action.chameleon_blacklist = typecacheof(/obj/item/clothing/mask/changeling, only_root_path = TRUE) @@ -490,10 +493,10 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/mask/chameleon) . = ..() ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) chameleon_action.random_look() - var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = new(src) - togglehatmask_action.UpdateButtons() - var/datum/action/item_action/chameleon/drone/randomise/randomise_action = new(src) - randomise_action.UpdateButtons() + var/datum/action/item_action/chameleon/drone/togglehatmask/togglehatmask_action = add_item_action(/datum/action/item_action/chameleon/drone/togglehatmask) + togglehatmask_action.build_all_button_icons() + var/datum/action/item_action/chameleon/drone/randomise/randomise_action = add_item_action(/datum/action/item_action/chameleon/drone/randomise) + randomise_action.build_all_button_icons() /obj/item/clothing/mask/chameleon/drone/attack_self(mob/user) to_chat(user, "[src] does not have a voice changer.") @@ -511,7 +514,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/shoes/chameleon) /obj/item/clothing/shoes/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/clothing/shoes chameleon_action.chameleon_name = "Shoes" chameleon_action.chameleon_blacklist = typecacheof(/obj/item/clothing/shoes/changeling, only_root_path = TRUE) @@ -539,7 +542,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/storage/backpack/chameleon) /obj/item/storage/backpack/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/storage/backpack chameleon_action.chameleon_name = "Backpack" chameleon_action.initialize_disguises() @@ -562,7 +565,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/storage/belt/chameleon) /obj/item/storage/belt/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/storage/belt chameleon_action.chameleon_name = "Belt" chameleon_action.initialize_disguises() @@ -588,7 +591,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/radio/headset/chameleon) /obj/item/radio/headset/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/radio/headset chameleon_action.chameleon_name = "Headset" chameleon_action.initialize_disguises() @@ -609,7 +612,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/pda/chameleon) /obj/item/pda/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/pda chameleon_action.chameleon_name = "PDA" chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/pda/heads, /obj/item/pda/ai, /obj/item/pda/ai/pai), only_root_path = TRUE) @@ -630,7 +633,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/stamp/chameleon) /obj/item/stamp/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/stamp chameleon_action.chameleon_name = "Stamp" chameleon_action.initialize_disguises() @@ -652,7 +655,7 @@ CHAMELEON_CLOTHING_DEFINE(/obj/item/clothing/neck/cloak/chameleon) /obj/item/clothing/neck/cloak/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/clothing/neck chameleon_action.chameleon_name = "Cloak" chameleon_action.initialize_disguises() diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index e3f4e5213e22..6e34b8af1a40 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -402,7 +402,7 @@ BLIND // can't see anything C.head_update(src, forced = 1) for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() return TRUE /obj/item/clothing/proc/visor_toggling() //handles all the actual toggling of flags diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 11e22ed5a88d..c99a2fb317e4 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -432,7 +432,7 @@ /obj/item/clothing/glasses/thermal/syndi/New() ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/clothing/glasses chameleon_action.chameleon_name = "Glasses" chameleon_action.chameleon_blacklist = typecacheof(/obj/item/clothing/glasses/changeling, only_root_path = TRUE) diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm index 395eeaeaa666..42e5d0cef83f 100644 --- a/code/modules/clothing/glasses/engine_goggles.dm +++ b/code/modules/clothing/glasses/engine_goggles.dm @@ -62,7 +62,7 @@ update_icon() for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() /obj/item/clothing/glasses/meson/engine/attack_self(mob/user) toggle_mode(user, TRUE) diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index 733fc0195cb1..6c1bbf0952ac 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -163,7 +163,7 @@ /obj/item/clothing/glasses/hud/security/chameleon/New() ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change) chameleon_action.chameleon_type = /obj/item/clothing/glasses chameleon_action.chameleon_name = "Glasses" chameleon_action.chameleon_blacklist = typecacheof(/obj/item/clothing/glasses/changeling, only_root_path = TRUE) diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 4f370866b371..c75a5e74a1fe 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -23,7 +23,7 @@ /obj/item/clothing/head/helmet/Initialize(mapload) . = ..() if(attached_light) - alight = new(src) + alight = add_item_action(/datum/action/item_action/toggle_helmet_flashlight) /obj/item/clothing/head/helmet/ComponentInitialize() . = ..() @@ -389,7 +389,7 @@ set_light(0) for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() /obj/item/clothing/head/helmet/durathread name = "makeshift helmet" diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index bc4fc4fe2375..2deb76da770a 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -75,7 +75,7 @@ if(!just_flavor) to_chat(user, "You push \the [src] [mask_adjusted ? "out of the way" : "back into place"].") user.wear_mask_update(src, toggle_off = mask_adjusted) - user.update_action_buttons_icon() //when mask is adjusted out, we update all buttons icon so the user's potential internal tank correctly shows as off. + user.update_mob_action_buttons() //when mask is adjusted out, we update all buttons icon so the user's potential internal tank correctly shows as off. else to_chat(usr, "You adjust [src], it will now [mask_adjusted ? "not" : ""] obscure your identity while worn.") return TRUE diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 1c9b15b39889..d6b44eea671c 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -115,7 +115,7 @@ user.update_inv_wear_mask() for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() to_chat(user, "Your Clown Mask has now morphed into [choice], all praise the Honkmother!") return TRUE @@ -181,7 +181,7 @@ user.update_inv_wear_mask() for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() to_chat(user, "Your Mime Mask has now morphed into [choice]!") return TRUE @@ -274,7 +274,7 @@ user.update_inv_wear_mask() for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() to_chat(M, "The Tiki Mask has now changed into the [choice] Mask!") return TRUE diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm index 9f837654a022..8c1a8ad9f54c 100644 --- a/code/modules/clothing/masks/miscellaneous.dm +++ b/code/modules/clothing/masks/miscellaneous.dm @@ -109,7 +109,7 @@ user.update_inv_wear_mask() for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() to_chat(user, "Your Joy mask now has a [choice] Emotion!") return TRUE @@ -475,6 +475,6 @@ user.update_inv_wear_mask() for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() to_chat(user, "Your paper mask now has a [choice] symbol!") return TRUE diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 304a4a3545f6..9cedf6983102 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -36,7 +36,7 @@ user.update_gravity(user.has_gravity()) for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() /obj/item/clothing/shoes/magboots/negates_gravity() return clothing_flags & NOSLIP diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index 9e387dab3f68..df420feefe9f 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -91,7 +91,7 @@ if(camera) camera.remove_target_ui() camera.forceMove(user) - teleport_now.UpdateButtons() + teleport_now.build_all_button_icons() /obj/item/clothing/suit/space/chronos/proc/chronowalk(atom/location) var/mob/living/carbon/human/user = src.loc @@ -105,7 +105,7 @@ if(camera) camera.remove_target_ui() - teleport_now.UpdateButtons() + teleport_now.build_all_button_icons() var/list/nonsafe_slots = list(ITEM_SLOT_BELT, ITEM_SLOT_BACK) var/list/exposed = list() @@ -312,16 +312,16 @@ /datum/action/innate/chrono_teleport name = "Teleport Now" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "chrono_phase" check_flags = AB_CHECK_CONSCIOUS //|AB_CHECK_INSIDE var/obj/item/clothing/suit/space/chronos/chronosuit = null -/datum/action/innate/chrono_teleport/IsAvailable(silent = FALSE) +/datum/action/innate/chrono_teleport/IsAvailable(feedback = TRUE) return (chronosuit && chronosuit.activated && chronosuit.camera && !chronosuit.teleporting) /datum/action/innate/chrono_teleport/Activate() - if(!IsAvailable()) + if(!IsAvailable(feedback = TRUE)) return if(chronosuit.camera) chronosuit.chronowalk(chronosuit.camera) diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index e6ed9c3d5115..c6c7b7036152 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -345,7 +345,7 @@ C.head_update(src, forced = 1) for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() /obj/item/clothing/head/helmet/space/hardsuit/syndi/proc/toggle_hardsuit_mode(mob/user) //Helmet Toggles Suit Mode if(linkedsuit) @@ -937,7 +937,7 @@ set_light(0) for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() /obj/item/clothing/head/helmet/space/hardsuit/lavaknight/update_overlays() . = ..() diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm index 9fc51b82871c..217b79d1475f 100644 --- a/code/modules/clothing/suits/toggles.dm +++ b/code/modules/clothing/suits/toggles.dm @@ -139,7 +139,7 @@ usr.update_inv_wear_suit() for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() /obj/item/clothing/suit/toggle/examine(mob/user) . = ..() diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index ebc590185cce..553d7ad6d252 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -175,7 +175,7 @@ /datum/action/item_action/stickmen name = "Summon Stick Minions" desc = "Allows you to summon faithful stickmen allies to aide you in battle." - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "art_summon" var/ready = TRUE var/list/summoned_stickmen = list() @@ -222,7 +222,7 @@ . = ..() UnregisterSignal(M, COMSIG_MOB_POINTED) -/datum/action/item_action/stickmen/Trigger() +/datum/action/item_action/stickmen/do_effect(trigger_flags) . = ..() if(!.) return @@ -249,6 +249,7 @@ RegisterSignal(S, COMSIG_PARENT_QDELETING, PROC_REF(remove_from_list)) ready = FALSE addtimer(CALLBACK(src, PROC_REF(ready_again)), cooldown) + return TRUE /datum/action/item_action/stickmen/proc/remove_from_list(datum/source, forced) summoned_stickmen -= source diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index 8d09b73f864d..ed23d3620c2d 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -24,10 +24,15 @@ /datum/action/item_action/displayDetectiveScanResults name = "Display Forensic Scanner Results" -/datum/action/item_action/displayDetectiveScanResults/Trigger() +/datum/action/item_action/displayDetectiveScanResults/do_effect(trigger_flags) + . = ..() + if(!.) + return var/obj/item/detective_scanner/scanner = target - if(istype(scanner)) - scanner.displayDetectiveScanResults(usr) + if(!istype(scanner)) + return FALSE + scanner.displayDetectiveScanResults(usr) + return TRUE /obj/item/detective_scanner/attack_self(mob/user) if(log.len && !scanning) diff --git a/code/modules/instruments/instruments/item.dm b/code/modules/instruments/instruments/item.dm index 4c496212c84e..752ae4020134 100644 --- a/code/modules/instruments/instruments/item.dm +++ b/code/modules/instruments/instruments/item.dm @@ -227,6 +227,7 @@ force = 5 w_class = WEIGHT_CLASS_SMALL actions_types = list(/datum/action/item_action/instrument) + action_slots = ALL /obj/item/instrument/harmonica/proc/handle_speech(datum/source, list/speech_args) if(song.playing && ismob(loc)) diff --git a/code/modules/mafia/controller.dm b/code/modules/mafia/controller.dm index 0b94af15a784..ace7bcc2db18 100644 --- a/code/modules/mafia/controller.dm +++ b/code/modules/mafia/controller.dm @@ -1001,7 +1001,7 @@ /datum/action/innate/mafia_panel name = "Mafia Panel" desc = "Use this to play." - icon_icon = 'icons/obj/mafia.dmi' + button_icon = 'icons/obj/mafia.dmi' button_icon_state = "board" var/datum/mafia_controller/parent diff --git a/code/modules/mining/aux_base_camera.dm b/code/modules/mining/aux_base_camera.dm index f4f91fe139f9..aabd6c1aac71 100644 --- a/code/modules/mining/aux_base_camera.dm +++ b/code/modules/mining/aux_base_camera.dm @@ -119,7 +119,7 @@ return ..() /datum/action/innate/aux_base //Parent aux base action - icon_icon = 'icons/mob/actions/actions_construction.dmi' + button_icon = 'icons/mob/actions/actions_construction.dmi' var/mob/camera/aiEye/remote/base_construction/remote_eye //Console's eye mob var/obj/machinery/computer/camera_advanced/base_construction/B //Console itself diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 6da752f17dcb..d01492783757 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -19,6 +19,7 @@ attack_verb = list("smashed", "crushed", "cleaved", "chopped", "pulped") sharpness = SHARP_EDGED actions_types = list(/datum/action/item_action/toggle_light) + action_slots = ALL obj_flags = UNIQUE_RENAME var/list/trophies = list() var/charged = TRUE diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 0475b7075ae9..05d8a51bd430 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -321,22 +321,24 @@ return ..() /obj/item/clothing/neck/necklace/memento_mori/proc/memento(mob/living/carbon/human/user) - to_chat(user, "You feel your life being drained by the pendant...") - if(do_after(user, 40, target = user)) - to_chat(user, "Your lifeforce is now linked to the pendant! You feel like removing it would kill you, and yet you instinctively know that until then, you won't die.") - ADD_TRAIT(user, TRAIT_NODEATH, "memento_mori") - ADD_TRAIT(user, TRAIT_NOHARDCRIT, "memento_mori") - ADD_TRAIT(user, TRAIT_NOCRITDAMAGE, "memento_mori") - icon_state = "memento_mori_active" - active_owner = user + to_chat(user, span_warning("You feel your life being drained by the pendant...")) + if(!do_after(user, 40, target = user)) + return FALSE + to_chat(user, span_notice("Your lifeforce is now linked to the pendant! You feel like removing it would kill you, and yet you instinctively know that until then, you won't die.")) + ADD_TRAIT(user, TRAIT_NODEATH, "memento_mori") + ADD_TRAIT(user, TRAIT_NOHARDCRIT, "memento_mori") + ADD_TRAIT(user, TRAIT_NOCRITDAMAGE, "memento_mori") + icon_state = "memento_mori_active" + active_owner = user + return TRUE /obj/item/clothing/neck/necklace/memento_mori/proc/mori() icon_state = "memento_mori" if(!active_owner) - return + return FALSE var/mob/living/carbon/human/H = active_owner //to avoid infinite looping when dust unequips the pendant active_owner = null - to_chat(H, "You feel your life rapidly slipping away from you!") + to_chat(H, span_userdanger("You feel your life rapidly slipping away from you!")) H.dust(TRUE, TRUE) /datum/action/item_action/hands_free/memento_mori @@ -344,15 +346,23 @@ name = "Memento Mori" desc = "Bind your life to the pendant." -/datum/action/item_action/hands_free/memento_mori/Trigger() +/datum/action/item_action/hands_free/memento_mori/do_effect(trigger_flags) + . = ..() + if(!.) + return var/obj/item/clothing/neck/necklace/memento_mori/MM = target + if(!istype(MM)) + return FALSE + if(!MM.active_owner) - if(ishuman(owner)) - MM.memento(owner) + if(!ishuman(owner)) + return FALSE + . = MM.memento(owner) else - to_chat(owner, "You try to free your lifeforce from the pendant...") - if(do_after(owner, 40, target = owner)) - MM.mori() + to_chat(owner, span_warning("You try to free your lifeforce from the pendant...")) + if(!do_after(owner, 40, target = owner)) + return FALSE + . = MM.mori() //Wisp Lantern /obj/item/wisp_lantern @@ -1272,6 +1282,7 @@ attack_verb = list("clubbed", "beat", "pummeled") hitsound = 'sound/weapons/sonic_jackhammer.ogg' actions_types = list(/datum/action/item_action/vortex_recall, /datum/action/item_action/toggle_unfriendly_fire) + action_slots = ALL var/cooldown_time = 20 //how long the cooldown between non-melee ranged attacks is var/chaser_cooldown = 81 //how long the cooldown between firing chasers at mobs is var/chaser_timer = 0 //what our current chaser cooldown is @@ -1377,7 +1388,7 @@ playsound(T,'sound/magic/blind.ogg', 200, 1, -4) new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, user) beacon = new/obj/effect/hierophant(T) - user.update_action_buttons_icon() + user.update_mob_action_buttons() user.visible_message("[user] places a strange machine beneath [user.p_their()] feet!", \ "You detach the hierophant beacon, allowing you to teleport yourself and any allies to it at any time!\n\ You can remove the beacon to place it again by striking it with the club.") @@ -1397,7 +1408,7 @@ to_chat(user, "You don't have enough space to teleport from here!") return teleporting = TRUE //start channel - user.update_action_buttons_icon() + user.update_mob_action_buttons() user.visible_message("[user] starts to glow faintly...") timer = world.time + 50 INVOKE_ASYNC(src, PROC_REF(prepare_icon_update)) @@ -1410,7 +1421,7 @@ if(is_blocked_turf(T, TRUE)) teleporting = FALSE to_chat(user, "The beacon is blocked by something, preventing teleportation!") - user.update_action_buttons_icon() + user.update_mob_action_buttons() timer = world.time INVOKE_ASYNC(src, PROC_REF(prepare_icon_update)) beacon.icon_state = "hierophant_tele_off" @@ -1422,7 +1433,7 @@ if(!do_after(user, 3, target = user) || !user || !beacon || QDELETED(beacon)) //no walking away shitlord teleporting = FALSE if(user) - user.update_action_buttons_icon() + user.update_mob_action_buttons() timer = world.time INVOKE_ASYNC(src, PROC_REF(prepare_icon_update)) if(beacon) @@ -1431,7 +1442,7 @@ if(is_blocked_turf(T, TRUE)) teleporting = FALSE to_chat(user, "The beacon is blocked by something, preventing teleportation!") - user.update_action_buttons_icon() + user.update_mob_action_buttons() timer = world.time INVOKE_ASYNC(src, PROC_REF(prepare_icon_update)) beacon.icon_state = "hierophant_tele_off" @@ -1459,7 +1470,7 @@ beacon.icon_state = "hierophant_tele_off" teleporting = FALSE if(user) - user.update_action_buttons_icon() + user.update_mob_action_buttons() /obj/item/hierophant_club/proc/teleport_mob(turf/source, mob/M, turf/target, mob/user) var/turf/turf_to_teleport_to = get_step(target, get_dir(source, M)) //get position relative to caster diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 75b647809a4f..fbc95ad4a823 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -224,7 +224,7 @@ /datum/action/innate/minedrone check_flags = AB_CHECK_CONSCIOUS - icon_icon = 'icons/mob/actions/actions_mecha.dmi' + button_icon = 'icons/mob/actions/actions_mecha.dmi' background_icon_state = "bg_default" /datum/action/innate/minedrone/toggle_light diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 3899e788df5b..9d04f7043c61 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -860,16 +860,23 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/reset_perspective(atom/A) if(client) if(ismob(client.eye) && (client.eye != src)) - var/mob/target = client.eye - observetarget = null - if(target.observers) - target.observers -= src - UNSETEMPTY(target.observers) + cleanup_observe() if(..()) if(hud_used) client.screen = list() hud_used.show_hud(hud_used.hud_version) +/mob/dead/observer/proc/cleanup_observe() + if(isnull(observetarget)) + return + var/mob/target = observetarget + observetarget = null + client?.perspective = initial(client.perspective) + sight = initial(sight) + if(target) + hide_other_mob_action_buttons(target) + LAZYREMOVE(target.observers, src) + /mob/dead/observer/verb/observe() set name = "Observe" set category = "OOC" diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index bcb6c9b2969f..b4c78f9a4259 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -39,18 +39,18 @@ Doesn't work on other aliens/AI.*/ if(plasma_cost > 0) return "[plasma_cost]" -/obj/effect/proc_holder/alien/proc/cost_check(check_turf = FALSE, mob/living/carbon/user, silent = FALSE) +/obj/effect/proc_holder/alien/proc/cost_check(check_turf = FALSE, mob/living/carbon/user, feedback = TRUE) if(user.stat) - if(!silent) - to_chat(user, "You must be conscious to do this.") + if(feedback) + to_chat(user, span_noticealien("You must be conscious to do this.")) return FALSE if(user.getPlasma() < plasma_cost) - if(!silent) - to_chat(user, "Not enough plasma stored.") + if(feedback) + to_chat(user, span_noticealien("Not enough plasma stored.")) return FALSE if(check_turf && (!isturf(user.loc) || isspaceturf(user.loc))) - if(!silent) - to_chat(user, "Bad place for a garden!") + if(feedback) + to_chat(user, span_noticealien("Bad place for a garden!")) return FALSE return TRUE @@ -73,7 +73,7 @@ Doesn't work on other aliens/AI.*/ if(locate(/obj/structure/alien/weeds/node) in get_turf(user)) to_chat(user, "There's already a weed node here.") return FALSE - user.visible_message("[user] has planted some alien weeds!") + user.visible_message(span_noticealien("[user] has planted some alien weeds!")) new/obj/structure/alien/weeds/node(user.loc) return TRUE @@ -201,7 +201,7 @@ Doesn't work on other aliens/AI.*/ /obj/effect/proc_holder/alien/neurotoxin/update_icon() . = ..() action.button_icon_state = "alien_neurotoxin_[active]" - action.UpdateButtons() + action.build_all_button_icons() /obj/effect/proc_holder/alien/neurotoxin/InterceptClickOn(mob/living/caller, params, atom/target) if(..()) @@ -334,7 +334,7 @@ Doesn't work on other aliens/AI.*/ for(var/X in abilities) var/obj/effect/proc_holder/alien/APH = X if(APH.has_action) - APH.action.UpdateButtons() + APH.action.build_all_button_icons() return TRUE /mob/living/carbon/alien/adjustPlasma(amount) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 47c9c61e343e..4b2f0cfa9f1d 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -831,7 +831,7 @@ else clear_alert("handcuffed") SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "handcuffed") - update_action_buttons_icon() //some of our action buttons might be unusable when we're handcuffed. + update_mob_action_buttons() //some of our action buttons might be unusable when we're handcuffed. update_inv_handcuffed() update_hud_handcuffed() diff --git a/code/modules/mob/living/carbon/human/innate_abilities/blobform.dm b/code/modules/mob/living/carbon/human/innate_abilities/blobform.dm index 177444503b9e..a0ed1600f600 100644 --- a/code/modules/mob/living/carbon/human/innate_abilities/blobform.dm +++ b/code/modules/mob/living/carbon/human/innate_abilities/blobform.dm @@ -3,7 +3,7 @@ name = "Puddle Transformation" check_flags = AB_CHECK_CONSCIOUS button_icon_state = "slimepuddle" - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" required_mobility_flags = MOBILITY_STAND var/is_puddle = FALSE @@ -18,10 +18,12 @@ var/transforming = FALSE var/last_use -/datum/action/innate/ability/slime_blobform/IsAvailable() +/datum/action/innate/ability/slime_blobform/IsAvailable(feedback) if(!transforming) return ..() else + if(feedback) + owner.balloon_alert(owner, "busy!") return FALSE /datum/action/innate/ability/slime_blobform/Remove(mob/M) @@ -36,8 +38,8 @@ if(HAS_TRAIT(I, TRAIT_NODROP)) to_chat(owner, "There's something stuck to your hand, stopping you from transforming!") return - if(IsAvailable()) - UpdateButtons() + if(IsAvailable(TRUE)) + build_all_button_icons() var/mutcolor = owner.get_ability_property(INNATE_ABILITY_SLIME_BLOBFORM, PROPERTY_BLOBFORM_COLOR) || ("#" + H.dna.features["mcolor"]) if(!is_puddle) if(CHECK_MOBILITY(H, MOBILITY_USE)) //if we can use items, we can turn into a puddle @@ -78,7 +80,7 @@ owner.update_antag_overlays() transforming = FALSE - UpdateButtons() + build_all_button_icons() else detransform() else @@ -109,4 +111,4 @@ squeak.RemoveComponent() H.regenerate_icons() transforming = FALSE - UpdateButtons() + build_all_button_icons() diff --git a/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm b/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm index 4df77a489b20..448f9e25df69 100644 --- a/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm +++ b/code/modules/mob/living/carbon/human/innate_abilities/coiling.dm @@ -3,7 +3,7 @@ name = "Coil Grabbed Mob" check_flags = AB_CHECK_CONSCIOUS button_icon_state = "coil_icon" - icon_icon = 'icons/mob/actions/actions_snake.dmi' + button_icon = 'icons/mob/actions/actions_snake.dmi' background_icon_state = "bg_alien" required_mobility_flags = MOBILITY_STAND var/currently_coiling = FALSE @@ -12,7 +12,7 @@ /datum/action/innate/ability/coiling/Activate() // make sure they meet the mobility/check flags - if(IsAvailable()) + if(IsAvailable(feedback = TRUE)) // check that the user has grabbed someone and they are not currently coiling someone if(ishuman(owner.pulling) && !currently_coiling) coil_mob(owner.pulling) diff --git a/code/modules/mob/living/carbon/human/innate_abilities/customization.dm b/code/modules/mob/living/carbon/human/innate_abilities/customization.dm index 621dc58650f2..45766f4613c5 100644 --- a/code/modules/mob/living/carbon/human/innate_abilities/customization.dm +++ b/code/modules/mob/living/carbon/human/innate_abilities/customization.dm @@ -2,7 +2,7 @@ name = "Alter Form" check_flags = AB_CHECK_CONSCIOUS button_icon_state = "alter_form" //placeholder - icon_icon = 'modular_citadel/icons/mob/actions/actions_slime.dmi' + button_icon = 'modular_citadel/icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" /datum/action/innate/ability/humanoid_customization/Activate() @@ -116,7 +116,7 @@ if(new_snout) H.dna.features["mam_snouts"] = new_snout H.update_body() - + else if (select_alteration == "Wings") var/new_color = input(owner, "Choose your wing color:", "Race change","#"+H.dna.features["wings_color"]) as color|null if(new_color) diff --git a/code/modules/mob/living/carbon/human/innate_abilities/limb_regeneration.dm b/code/modules/mob/living/carbon/human/innate_abilities/limb_regeneration.dm index 71b15bda2d5e..2519076d49e2 100644 --- a/code/modules/mob/living/carbon/human/innate_abilities/limb_regeneration.dm +++ b/code/modules/mob/living/carbon/human/innate_abilities/limb_regeneration.dm @@ -3,11 +3,11 @@ name = "Regenerate Limbs" check_flags = AB_CHECK_CONSCIOUS button_icon_state = "slimeheal" - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" required_mobility_flags = NONE -/datum/action/innate/ability/limb_regrowth/IsAvailable(silent = FALSE) +/datum/action/innate/ability/limb_regrowth/IsAvailable(feedback = TRUE) if(..()) var/mob/living/carbon/human/H = owner var/list/limbs_to_heal = H.get_missing_limbs() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 29866459d82d..73eafc4c4ea9 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -53,6 +53,49 @@ return s_store return null +/mob/living/carbon/human/get_slot_by_item(obj/item/looking_for) + if(looking_for == belt) + return ITEM_SLOT_BELT + + if(looking_for == wear_id) + return ITEM_SLOT_ID + + if(looking_for == ears) + return ITEM_SLOT_EARS + + if(looking_for == glasses) + return ITEM_SLOT_EYES + + if(looking_for == gloves) + return ITEM_SLOT_GLOVES + + if(looking_for == head) + return ITEM_SLOT_HEAD + + if(looking_for == shoes) + return ITEM_SLOT_FEET + + if(looking_for == wear_suit) + return ITEM_SLOT_OCLOTHING + + var/obj/item/clothing/under/look_at = w_uniform + if(look_at) + if(looking_for == look_at) + return ITEM_SLOT_ICLOTHING + if(istype(look_at) && looking_for == look_at.attached_accessory) + return ITEM_SLOT_ACCESSORY + + if(looking_for == r_store) + return ITEM_SLOT_RPOCKET + + if(looking_for == l_store) + return ITEM_SLOT_LPOCKET + + if(looking_for == s_store) + return ITEM_SLOT_SUITSTORE + + return ..() + /mob/living/carbon/human/proc/get_all_slots() . = get_head_slots() | get_body_slots() @@ -133,7 +176,7 @@ update_inv_w_uniform() if(wear_suit.breakouttime) //when equipping a straightjacket stop_pulling() //can't pull if restrained - update_action_buttons_icon() //certain action buttons will no longer be usable. + update_mob_action_buttons() //certain action buttons will no longer be usable. update_inv_wear_suit() if(ITEM_SLOT_ICLOTHING) w_uniform = I @@ -180,7 +223,7 @@ dropItemToGround(s_store, TRUE) //It makes no sense for your suit storage to stay on you if you drop your suit. if(wear_suit.breakouttime) //when unequipping a straightjacket drop_all_held_items() //suit is restraining - update_action_buttons_icon() //certain action buttons may be usable again. + update_mob_action_buttons() //certain action buttons may be usable again. wear_suit = null if(!QDELETED(src)) //no need to update we're getting deleted anyway if(I.flags_inv & HIDEJUMPSUIT) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index e50978e9c0b3..0fd8b3a67ca9 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -2650,7 +2650,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) /datum/action/innate/flight name = "Toggle Flight" check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_STUN - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "flight" /datum/action/innate/flight/Activate() diff --git a/code/modules/mob/living/carbon/human/species_types/arachnid.dm b/code/modules/mob/living/carbon/human/species_types/arachnid.dm index fabd9072c8db..11a522493728 100644 --- a/code/modules/mob/living/carbon/human/species_types/arachnid.dm +++ b/code/modules/mob/living/carbon/human/species_types/arachnid.dm @@ -62,13 +62,13 @@ /datum/action/innate/spin_web name = "Spin Web" check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS - icon_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon = 'icons/mob/actions/actions_animal.dmi' button_icon_state = "lay_web" /datum/action/innate/spin_cocoon name = "Spin Cocoon" check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS - icon_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon = 'icons/mob/actions/actions_animal.dmi' button_icon_state = "wrap_0" /datum/action/innate/spin_web/Activate() 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 5ca140cab48d..37adc57f194d 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -456,11 +456,11 @@ name = "Unstable Teleport" check_flags = AB_CHECK_CONSCIOUS button_icon_state = "jaunt" - icon_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon = 'icons/mob/actions/actions_spells.dmi' var/cooldown = 150 var/last_teleport = 0 -/datum/action/innate/unstable_teleport/IsAvailable(silent = FALSE) +/datum/action/innate/unstable_teleport/IsAvailable(feedback = TRUE) if(..()) if(world.time > last_teleport + cooldown) return TRUE @@ -480,9 +480,9 @@ spark_system.start() do_teleport(H, get_turf(H), 12, asoundin = 'sound/weapons/emitter2.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) last_teleport = world.time - UpdateButtons() //action icon looks unavailable + build_all_button_icons() //action icon looks unavailable //action icon looks available again - addtimer(CALLBACK(src, PROC_REF(UpdateButtons)), cooldown + 5) + addtimer(CALLBACK(src, PROC_REF(build_all_button_icons)), cooldown + 5) //honk @@ -991,7 +991,7 @@ name = "Bone Chill" desc = "Rattle your bones and strike fear into your enemies!" check_flags = AB_CHECK_CONSCIOUS - icon_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon = 'icons/mob/actions/actions_spells.dmi' button_icon_state = "bonechill" var/cooldown = 600 var/last_use diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm index f6749dde0617..5e3fae09eddc 100644 --- a/code/modules/mob/living/carbon/human/species_types/ipc.dm +++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm @@ -58,7 +58,7 @@ /datum/action/innate/monitor_change name = "Screen Change" check_flags = AB_CHECK_CONSCIOUS - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "drone_vision" /datum/action/innate/monitor_change/Activate() 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 550789a0666f..10651b357fc7 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -82,7 +82,7 @@ var/datum/action/innate/ability/regrowth = H.ability_actions[INNATE_ABILITY_LIMB_REGROWTH] if(regrowth) - regrowth.UpdateButtons() + regrowth.build_all_button_icons() return FALSE // to let living/handle_blood know that the species is handling blood instead @@ -176,10 +176,10 @@ name = "Split Body" check_flags = AB_CHECK_CONSCIOUS button_icon_state = "slimesplit" - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" -/datum/action/innate/split_body/IsAvailable(silent = FALSE) +/datum/action/innate/split_body/IsAvailable(feedback = TRUE) if(..()) var/mob/living/carbon/human/H = owner if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT) @@ -256,7 +256,7 @@ name = "Swap Body" check_flags = NONE button_icon_state = "slimeswap" - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" /datum/action/innate/swap_body/Activate() @@ -438,48 +438,55 @@ name = "Luminescent Slime Entity" id = SPECIES_SLIME_LUMI say_mod = "says" + /// How strong is our glow var/glow_intensity = LUMINESCENT_DEFAULT_GLOW + /// Internal dummy used to glow (very cool) var/obj/effect/dummy/luminescent_glow/glow + /// The slime extract we currently have integrated var/obj/item/slime_extract/current_extract - var/datum/action/innate/integrate_extract/integrate_extract - var/datum/action/innate/use_extract/extract_minor - var/datum/action/innate/use_extract/major/extract_major - var/extract_cooldown = 0 + /// A list of all luminescent related actions we have + var/list/luminescent_actions + /// The cooldown of us using exteracts + COOLDOWN_DECLARE(extract_cooldown) + +//Species datums don't normally implement destroy, but JELLIES SUCK ASS OUT OF A STEEL STRAW and have to i guess +/datum/species/jelly/luminescent/Destroy(force) + current_extract = null + QDEL_NULL(glow) + QDEL_LIST(luminescent_actions) + return ..() -/datum/species/jelly/luminescent/on_species_loss(mob/living/carbon/C) +/datum/species/jelly/luminescent/on_species_gain(mob/living/carbon/new_jellyperson, datum/species/old_species) ..() + glow = new(new_jellyperson) + update_glow(new_jellyperson) + + luminescent_actions = list() + + var/datum/action/innate/integrate_extract/integrate_extract = new(src) + integrate_extract.Grant(new_jellyperson) + luminescent_actions += integrate_extract + + var/datum/action/innate/use_extract/extract_minor = new(src) + extract_minor.Grant(new_jellyperson) + luminescent_actions += extract_minor + + var/datum/action/innate/use_extract/major/extract_major = new(src) + extract_major.Grant(new_jellyperson) + luminescent_actions += extract_major + +/datum/species/jelly/luminescent/on_species_loss(mob/living/carbon/C) + . = ..() if(current_extract) current_extract.forceMove(C.drop_location()) current_extract = null - qdel(glow) - if(integrate_extract) - integrate_extract.Remove(C) - if(extract_minor) - extract_minor.Remove(C) - if(extract_major) - extract_major.Remove(C) - -/datum/species/jelly/luminescent/on_species_gain(mob/living/carbon/C, datum/species/old_species) - ..() - glow = new(C) - update_glow(C) - integrate_extract = new(src) - integrate_extract.Grant(C) - extract_minor = new(src) - extract_minor.Grant(C) - extract_major = new(src) - extract_major.Grant(C) - -/datum/species/jelly/luminescent/proc/update_slime_actions() - integrate_extract.update_name() - integrate_extract.UpdateButtons() - extract_minor.UpdateButtons() - extract_major.UpdateButtons() - -/datum/species/jelly/luminescent/proc/update_glow(mob/living/carbon/C, intensity) + QDEL_NULL(glow) + QDEL_NULL_LIST(luminescent_actions) + +/datum/species/jelly/luminescent/proc/update_glow(mob/living/carbon/human/glowie, intensity) if(intensity) glow_intensity = intensity - glow.set_light(glow_intensity, glow_intensity, C.dna.features["mcolor"]) + glow.set_light(glow_intensity, glow_intensity, glowie.dna.features["mcolor"]) /obj/effect/dummy/luminescent_glow name = "luminescent glow" @@ -498,98 +505,110 @@ desc = "Eat a slime extract to use its properties." check_flags = AB_CHECK_CONSCIOUS button_icon_state = "slimeconsume" - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" - var/datum/species/jelly/luminescent/species -/datum/action/innate/integrate_extract/New(_species) - ..() - species = _species +/datum/action/innate/integrate_extract/New(Target) + . = ..() + AddComponent(/datum/component/action_item_overlay, item_callback = CALLBACK(src, PROC_REF(locate_extract))) -/datum/action/innate/integrate_extract/proc/update_name() - if(!species || !species.current_extract) +/// Callback for /datum/component/action_item_overlay to find the slime extract from within the species +/datum/action/innate/integrate_extract/proc/locate_extract() + var/datum/species/jelly/luminescent/species = target + if(!istype(species)) + return null + + return species.current_extract + +/datum/action/innate/integrate_extract/update_button_name(atom/movable/screen/movable/action_button/button, force = FALSE) + var/datum/species/jelly/luminescent/species = target + if(!istype(species) || !species.current_extract) name = "Integrate Extract" desc = "Eat a slime extract to use its properties." else name = "Eject Extract" desc = "Eject your current slime extract." -/datum/action/innate/integrate_extract/UpdateButton(atom/movable/screen/movable/action_button/button, status_only, force) - if(!species || !species.current_extract) + return ..() + +/datum/action/innate/integrate_extract/apply_button_icon(atom/movable/screen/movable/action_button/current_button, force) + var/datum/species/jelly/luminescent/species = target + if(!istype(species) || !species.current_extract) button_icon_state = "slimeconsume" else button_icon_state = "slimeeject" - ..() -/datum/action/innate/integrate_extract/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force) - ..(current_button, TRUE) - if(species && species.current_extract) - current_button.add_overlay(mutable_appearance(species.current_extract.icon, species.current_extract.icon_state)) + return ..() /datum/action/innate/integrate_extract/Activate() - var/mob/living/carbon/human/H = owner - if(!is_species(H, /datum/species/jelly/luminescent) || !species) + var/mob/living/carbon/human/human_owner = owner + var/datum/species/jelly/luminescent/species = target + if(!istype(species)) return - CHECK_DNA_AND_SPECIES(H) if(species.current_extract) - var/obj/item/slime_extract/S = species.current_extract - if(!H.put_in_active_hand(S)) - S.forceMove(H.drop_location()) + var/obj/item/slime_extract/to_remove = species.current_extract + if(!human_owner.put_in_active_hand(to_remove)) + to_remove.forceMove(human_owner.drop_location()) + species.current_extract = null - to_chat(H, "You eject [S].") - species.update_slime_actions() + human_owner.balloon_alert(human_owner, "[to_remove.name] ejected") + else - var/obj/item/I = H.get_active_held_item() - if(istype(I, /obj/item/slime_extract)) - var/obj/item/slime_extract/S = I - if(!S.Uses) - to_chat(H, "[I] is spent! You cannot integrate it.") - return - if(!H.temporarilyRemoveItemFromInventory(S)) - return - S.forceMove(H) - species.current_extract = S - to_chat(H, "You consume [I], and you feel it pulse within you...") - species.update_slime_actions() - else - to_chat(H, "You need to hold an unused slime extract in your active hand!") + var/obj/item/slime_extract/to_integrate = human_owner.get_active_held_item() + if(!istype(to_integrate) || to_integrate.extract_uses <= 0) + human_owner.balloon_alert(human_owner, "need an unused slime extract!") + return + if(!human_owner.temporarilyRemoveItemFromInventory(to_integrate)) + return + to_integrate.forceMove(human_owner) + species.current_extract = to_integrate + human_owner.balloon_alert(human_owner, "[to_integrate.name] consumed") + + for(var/datum/action/to_update as anything in species.luminescent_actions) + to_update.build_all_button_icons() /datum/action/innate/use_extract name = "Extract Minor Activation" desc = "Pulse the slime extract with energized jelly to activate it." check_flags = AB_CHECK_CONSCIOUS button_icon_state = "slimeuse1" - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" + overlay_icon_state = "bg_alien_border" var/activation_type = SLIME_ACTIVATE_MINOR - var/datum/species/jelly/luminescent/species -/datum/action/innate/use_extract/New(_species) - ..() - species = _species +/datum/action/innate/use_extract/New(Target) + . = ..() + AddComponent(/datum/component/action_item_overlay, item_callback = CALLBACK(src, PROC_REF(locate_extract))) -/datum/action/innate/use_extract/IsAvailable(silent = FALSE) - if(..()) - if(species && species.current_extract && (world.time > species.extract_cooldown)) - return TRUE - return FALSE +/// Callback for /datum/component/action_item_overlay to find the slime extract from within the species +/datum/action/innate/use_extract/proc/locate_extract() + var/datum/species/jelly/luminescent/species = target + if(!istype(species)) + return null + + return species.current_extract + +/datum/action/innate/use_extract/IsAvailable(feedback = FALSE) + . = ..() + if(!.) + return -/datum/action/innate/use_extract/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force) - ..(current_button, TRUE) - if(species && species.current_extract) - current_button.add_overlay(mutable_appearance(species.current_extract.icon, species.current_extract.icon_state)) + var/datum/species/jelly/luminescent/species = target + if(istype(species) && species.current_extract && (COOLDOWN_FINISHED(species, extract_cooldown))) + return TRUE + return FALSE /datum/action/innate/use_extract/Activate() - var/mob/living/carbon/human/H = owner - if(!is_species(H, /datum/species/jelly/luminescent) || !species) + var/mob/living/carbon/human/human_owner = owner + var/datum/species/jelly/luminescent/species = human_owner.dna?.species + if(!istype(species) || !species.current_extract) return - CHECK_DNA_AND_SPECIES(H) - if(species.current_extract) - species.extract_cooldown = world.time + 100 - var/cooldown = species.current_extract.activate(H, species, activation_type) - species.extract_cooldown = world.time + cooldown + COOLDOWN_START(species, extract_cooldown, 10 SECONDS) + var/after_use_cooldown = species.current_extract.activate(human_owner, species, activation_type) + COOLDOWN_START(species, extract_cooldown, after_use_cooldown) /datum/action/innate/use_extract/major name = "Extract Major Activation" @@ -664,7 +683,7 @@ name = "Slimelink" desc = "Send a psychic message to everyone connected to your slime link." button_icon_state = "link_speech" - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" var/datum/species/jelly/stargazer/species @@ -702,7 +721,7 @@ name = "Send Thought" desc = "Send a private psychic message to someone you can see." button_icon_state = "send_mind" - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" /datum/action/innate/project_thought/Activate() @@ -741,7 +760,7 @@ name = "Link Minds" desc = "Link someone's mind to your Slime Link, allowing them to communicate telepathically with other linked minds." button_icon_state = "mindlink" - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" var/datum/species/jelly/stargazer/species diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 3e54a4e63872..429ce5d2d34b 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -62,7 +62,7 @@ var/area/A = get_area(C) if(istype(A, /area/service/chapel) && C.mind?.assigned_role != "Chaplain") - to_chat(C, "You don't belong here!") + to_chat(C, span_danger("You don't belong here!")) C.adjustFireLoss(5) C.adjust_fire_stacks(6) C.IgniteMob() @@ -79,47 +79,51 @@ name = "Drain Victim" desc = "Leech blood from any carbon victim you are passively grabbing." -/datum/action/item_action/organ_action/vampire/Trigger() +/datum/action/item_action/organ_action/vampire/do_effect(trigger_flags) . = ..() - if(iscarbon(owner)) - var/mob/living/carbon/H = owner - var/obj/item/organ/tongue/vampire/V = target - if(V.drain_cooldown >= world.time) - to_chat(H, "You just drained blood, wait a few seconds.") - return - if(H.pulling && iscarbon(H.pulling)) - var/mob/living/carbon/victim = H.pulling - if(H.blood_volume >= BLOOD_VOLUME_MAXIMUM) - to_chat(H, "You're already full!") - return - //This checks whether or not they are wearing a garlic clove on their neck - if(!blood_sucking_checks(victim, TRUE, FALSE)) - return - if(victim.stat == DEAD) - to_chat(H, "You need a living victim!") - return - if(!victim.blood_volume || (victim.dna && ((NOBLOOD in victim.dna.species.species_traits) || victim.dna.species.exotic_blood))) - to_chat(H, "[victim] doesn't have blood!") - return - V.drain_cooldown = world.time + 30 - if(victim.anti_magic_check(FALSE, TRUE, FALSE, 0)) - to_chat(victim, "[H] tries to bite you, but stops before touching you!") - to_chat(H, "[victim] is blessed! You stop just in time to avoid catching fire.") - return - //Here we check now for both the garlic cloves on the neck and for blood in the victims bloodstream. - if(!blood_sucking_checks(victim, TRUE, TRUE)) - return - if(!do_after(H, 30, target = victim)) - return - var/blood_volume_difference = BLOOD_VOLUME_MAXIMUM - H.blood_volume //How much capacity we have left to absorb blood - var/drained_blood = min(victim.blood_volume, VAMP_DRAIN_AMOUNT, blood_volume_difference) - to_chat(victim, "[H] is draining your blood!") - to_chat(H, "You drain some blood!") - playsound(H, 'sound/items/drink.ogg', 30, 1, -2) - victim.blood_volume = clamp(victim.blood_volume - drained_blood, 0, BLOOD_VOLUME_MAXIMUM) - H.blood_volume = clamp(H.blood_volume + drained_blood, 0, BLOOD_VOLUME_MAXIMUM) - if(!victim.blood_volume) - to_chat(H, "You finish off [victim]'s blood supply!") + if(!.) + return + if(!iscarbon(owner)) + return FALSE + var/mob/living/carbon/H = owner + var/obj/item/organ/tongue/vampire/V = target + if(V.drain_cooldown >= world.time) + to_chat(H, span_notice("You just drained blood, wait a few seconds.")) + return FALSE + if(H.pulling && iscarbon(H.pulling)) + var/mob/living/carbon/victim = H.pulling + if(H.blood_volume >= BLOOD_VOLUME_MAXIMUM) + to_chat(H, span_notice("You're already full!")) + return FALSE + //This checks whether or not they are wearing a garlic clove on their neck + if(!blood_sucking_checks(victim, TRUE, FALSE)) + return FALSE + if(victim.stat == DEAD) + to_chat(H, span_notice("You need a living victim!")) + return FALSE + if(!victim.blood_volume || (victim.dna && ((NOBLOOD in victim.dna.species.species_traits) || victim.dna.species.exotic_blood))) + to_chat(H, span_notice("[victim] doesn't have blood!")) + return FALSE + V.drain_cooldown = world.time + 30 + if(victim.anti_magic_check(FALSE, TRUE, FALSE, 0)) + to_chat(victim, span_warning("[H] tries to bite you, but stops before touching you!")) + to_chat(H, span_warning("[victim] is blessed! You stop just in time to avoid catching fire.")) + return FALSE + //Here we check now for both the garlic cloves on the neck and for blood in the victims bloodstream. + if(!blood_sucking_checks(victim, TRUE, TRUE)) + return FALSE + if(!do_after(H, 30, target = victim)) + return FALSE + var/blood_volume_difference = BLOOD_VOLUME_MAXIMUM - H.blood_volume //How much capacity we have left to absorb blood + var/drained_blood = min(victim.blood_volume, VAMP_DRAIN_AMOUNT, blood_volume_difference) + to_chat(victim, span_danger("[H] is draining your blood!")) + to_chat(H, span_notice("You drain some blood!")) + playsound(H, 'sound/items/drink.ogg', 30, 1, -2) + victim.blood_volume = clamp(victim.blood_volume - drained_blood, 0, BLOOD_VOLUME_MAXIMUM) + H.blood_volume = clamp(H.blood_volume + drained_blood, 0, BLOOD_VOLUME_MAXIMUM) + if(!victim.blood_volume) + to_chat(H, span_warning("You finish off [victim]'s blood supply!")) + return TRUE #undef VAMP_DRAIN_AMOUNT @@ -140,11 +144,15 @@ name = "Check Blood Level" desc = "Check how much blood you have remaining." -/datum/action/item_action/organ_action/vampire_heart/Trigger() +/datum/action/item_action/organ_action/vampire_heart/do_effect(trigger_flags) . = ..() - if(iscarbon(owner)) - var/mob/living/carbon/H = owner - to_chat(H, "Current blood level: [H.blood_volume]/[BLOOD_VOLUME_MAXIMUM].") + if(!.) + return + if(!iscarbon(owner)) + return FALSE + var/mob/living/carbon/H = owner + to_chat(H, span_notice("Current blood level: [H.blood_volume]/[BLOOD_VOLUME_MAXIMUM].")) + return TRUE /obj/effect/proc_holder/spell/targeted/shapeshift/bat name = "Bat Form" @@ -159,11 +167,11 @@ /obj/effect/proc_holder/spell/targeted/shapeshift/bat/Shapeshift(mob/living/caster) //cit change var/obj/shapeshift_holder/H = locate() in caster if(H) - to_chat(caster, "You're already shapeshifted!") + to_chat(caster, span_warning("You're already shapeshifted!")) return if(!ishuman(caster)) - to_chat(caster, "You need to be humanoid to be able to do this!") + to_chat(caster, span_warning("You need to be humanoid to be able to do this!")) return var/mob/living/carbon/human/human_caster = caster @@ -184,11 +192,11 @@ /obj/effect/proc_holder/spell/targeted/shapeshift/bat/cast(list/targets, mob/user = usr) if(!(locate(/obj/shapeshift_holder) in targets[1])) if(!ishuman(user)) - to_chat(user, "You need to be humanoid to be able to do this!") + to_chat(user, span_warning("You need to be humanoid to be able to do this!")) return var/mob/living/carbon/human/human_user = user if(!(human_user.dna?.species?.id == SPECIES_VAMPIRE)) - to_chat(user, "You don't seem to be able to shapeshift..") + to_chat(user, span_warning("You don't seem to be able to shapeshift..")) return return ..() diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index 2422528d2113..4e4f71f96325 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -14,6 +14,30 @@ return legcuffed return null +/mob/living/carbon/get_slot_by_item(obj/item/looking_for) + if(looking_for == back) + return ITEM_SLOT_BACK + + if(back && (looking_for in back)) + return ITEM_SLOT_BACKPACK + + if(looking_for == wear_mask) + return ITEM_SLOT_MASK + + if(looking_for == wear_neck) + return ITEM_SLOT_NECK + + if(looking_for == head) + return ITEM_SLOT_HEAD + + if(looking_for == handcuffed) + return ITEM_SLOT_HANDCUFFED + + if(looking_for == legcuffed) + return ITEM_SLOT_LEGCUFFED + + return ..() + /mob/living/carbon/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1, critical = FALSE) for(var/slot in slots) if(equip_to_slot_if_possible(I, slots[slot], qdel_on_fail = 0, disable_warning = TRUE)) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index aaf9bf0a7a3a..dcc247bcdd82 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -78,7 +78,7 @@ blind_eyes(1) reset_perspective(null) reload_fullscreen() - update_action_buttons_icon() + update_mob_action_buttons() update_damage_hud() update_health_hud() update_mobility() diff --git a/code/modules/mob/living/living_mobility.dm b/code/modules/mob/living/living_mobility.dm index 155f1dbc892b..c1d6b4feea7e 100644 --- a/code/modules/mob/living/living_mobility.dm +++ b/code/modules/mob/living/living_mobility.dm @@ -9,8 +9,7 @@ resting = new_resting if(!silent) to_chat(src, "You are now [resting? "resting" : "getting up"].") - if(resting == 1) - SEND_SIGNAL(src, COMSIG_LIVING_RESTING) + SEND_SIGNAL(src, COMSIG_LIVING_RESTING, resting) update_resting(updating) /mob/living/proc/update_resting(update_mobility = TRUE) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index b4f9b4a8eef2..f8135ec29a29 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -132,8 +132,8 @@ target_ai.mind.transfer_to(src) if(mind.special_role) mind.store_memory("As an AI, you must obey your silicon laws above all else. Your objectives will consider you to be dead.") - to_chat(src, "You have been installed as an AI! ") - to_chat(src, "You must obey your silicon laws above all else. Your objectives will consider you to be dead.") + to_chat(src, span_userdanger("You have been installed as an AI! ")) + to_chat(src, span_danger("You must obey your silicon laws above all else. Your objectives will consider you to be dead.")) if(!mind.has_ever_been_ai) mind.has_ever_been_ai = TRUE @@ -285,7 +285,7 @@ /mob/living/silicon/ai/proc/ai_call_shuttle() if(control_disabled) - to_chat(usr, "Wireless control is disabled!") + to_chat(usr, span_warning("Wireless control is disabled!")) return var/reason = input(src, "What is the nature of your emergency? ([CALL_SHUTTLE_REASON_LENGTH] characters required.)", "Confirm Shuttle Call") as null|text @@ -398,7 +398,7 @@ /mob/living/silicon/ai/proc/ai_cancel_call() set category = "Malfunction" if(control_disabled) - to_chat(src, "Wireless control is disabled!") + to_chat(src, span_warning("Wireless control is disabled!")) return SSshuttle.cancelEvac(src) @@ -431,7 +431,7 @@ if(H) H.attack_ai(src) //may as well recycle else - to_chat(src, "Unable to locate the holopad.") + to_chat(src, span_notice("Unable to locate the holopad.")) if(href_list["track"]) var/string = href_list["track"] trackable_mobs() @@ -590,7 +590,7 @@ if(network in C.network) U.eyeobj.setLoc(get_turf(C)) break - to_chat(src, "Switched to the \"[uppertext(network)]\" camera network.") + to_chat(src, span_notice("Switched to the \"[uppertext(network)]\" camera network.")) //End of code by Mord_Sith @@ -711,7 +711,7 @@ var/obj/machinery/power/apc/apc = src.loc if(!istype(apc)) - to_chat(src, "You are already in your Main Core.") + to_chat(src, span_notice("You are already in your Main Core.")) return apc.malfvacate() @@ -783,11 +783,11 @@ return if(interaction == AI_TRANS_TO_CARD)//The only possible interaction. Upload AI mob to a card. if(!can_be_carded) - to_chat(user, "Transfer failed.") + to_chat(user, span_boldwarning("Transfer failed.")) return disconnect_shell() //If the AI is controlling a borg, force the player back to core! if(!mind) - to_chat(user, "No intelligence patterns detected." ) + to_chat(user, span_warning("No intelligence patterns detected.")) return ShutOffDoomsdayDevice() var/obj/structure/ai_core/new_core = new /obj/structure/ai_core/deactivated(loc, posibrain_inside)//Spawns a deactivated terminal at AI location. @@ -811,10 +811,10 @@ /mob/living/silicon/ai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE) if(control_disabled || incapacitated()) - to_chat(src, "You can't do that right now!") + to_chat(src, span_warning("You can't do that right now!")) return FALSE if(be_close && !in_range(M, src)) - to_chat(src, "You are too far away!") + to_chat(src, span_warning("You are too far away!")) return FALSE return can_see(M) //stop AIs from leaving windows open and using then after they lose vision @@ -915,10 +915,10 @@ clear_alert("hackingapc") if(!istype(apc) || QDELETED(apc) || apc.machine_stat & BROKEN) - to_chat(src, "Hack aborted. The designated APC no longer exists on the power network.") + to_chat(src, span_danger("Hack aborted. The designated APC no longer exists on the power network.")) playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, TRUE, ignore_walls = FALSE) else if(apc.aidisabled) - to_chat(src, "Hack aborted. \The [apc] is no longer responding to our systems.") + to_chat(src, span_danger("Hack aborted. \The [apc] is no longer responding to our systems.")) playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, TRUE, ignore_walls = FALSE) else malf_picker.processing_time += 10 @@ -939,7 +939,7 @@ if(incapacitated()) return if(control_disabled) - to_chat(src, "Wireless networking module is offline.") + to_chat(src, span_warning("Wireless networking module is offline.")) return var/list/possible = list() @@ -968,30 +968,38 @@ /datum/action/innate/deploy_shell name = "Deploy to AI Shell" desc = "Wirelessly control a specialized cyborg shell." - icon_icon = 'icons/mob/actions/actions_AI.dmi' + button_icon = 'icons/mob/actions/actions_AI.dmi' button_icon_state = "ai_shell" -/datum/action/innate/deploy_shell/Trigger() +/datum/action/innate/deploy_shell/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE var/mob/living/silicon/ai/AI = owner if(!AI) - return + return FALSE AI.deploy_to_shell() + return TRUE /datum/action/innate/deploy_last_shell name = "Reconnect to shell" desc = "Reconnect to the most recently used AI shell." - icon_icon = 'icons/mob/actions/actions_AI.dmi' + button_icon = 'icons/mob/actions/actions_AI.dmi' button_icon_state = "ai_last_shell" var/mob/living/silicon/robot/last_used_shell -/datum/action/innate/deploy_last_shell/Trigger() +/datum/action/innate/deploy_last_shell/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner) - return + return FALSE if(last_used_shell) var/mob/living/silicon/ai/AI = owner AI.deploy_to_shell(last_used_shell) else Remove(owner) //If the last shell is blown, destroy it. + return TRUE /datum/action/innate/deploy_last_shell/Destroy() last_used_shell = null @@ -999,7 +1007,7 @@ /mob/living/silicon/ai/proc/disconnect_shell() if(deployed_shell) //Forcibly call back AI in event of things such as damage, EMP or power loss. - to_chat(src, "Your remote connection has been reset!") + to_chat(src, span_danger("Your remote connection has been reset!")) deployed_shell.undeploy() diag_hud_set_deployed() diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 99c3eda3ebe0..66062c85e6cc 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -215,7 +215,7 @@ /mob/living/silicon/pai/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE) if(be_close && !in_range(M, src)) - to_chat(src, "You are too far away!") + to_chat(src, span_warning("You are too far away!")) return FALSE return TRUE @@ -230,62 +230,79 @@ /datum/action/innate/pai name = "PAI Action" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' var/mob/living/silicon/pai/P -/datum/action/innate/pai/Trigger() +/datum/action/innate/pai/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!ispAI(owner)) return FALSE P = owner + return TRUE /datum/action/innate/pai/software name = "Software Interface" button_icon_state = "pai" background_icon_state = "bg_tech" -/datum/action/innate/pai/software/Trigger() - ..() +/datum/action/innate/pai/software/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE P.paiInterface() + return TRUE /datum/action/innate/pai/shell name = "Toggle Holoform" button_icon_state = "pai_holoform" background_icon_state = "bg_tech" -/datum/action/innate/pai/shell/Trigger() - ..() +/datum/action/innate/pai/shell/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(P.holoform) - P.fold_in(FALSE) + . = P.fold_in(FALSE) else - P.fold_out() + . = P.fold_out() /datum/action/innate/pai/chassis name = "Holochassis Appearance Composite" button_icon_state = "pai_chassis" background_icon_state = "bg_tech" -/datum/action/innate/pai/chassis/Trigger() - ..() - P.choose_chassis() +/datum/action/innate/pai/chassis/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + return P.choose_chassis() /datum/action/innate/pai/rest name = "Rest" button_icon_state = "pai_rest" background_icon_state = "bg_tech" -/datum/action/innate/pai/rest/Trigger() - ..() +/datum/action/innate/pai/rest/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE P.lay_down() + return TRUE /datum/action/innate/pai/light name = "Toggle Integrated Lights" - icon_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon = 'icons/mob/actions/actions_spells.dmi' button_icon_state = "emp" background_icon_state = "bg_tech" -/datum/action/innate/pai/light/Trigger() - ..() +/datum/action/innate/pai/light/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE P.toggle_integrated_light() + return TRUE /mob/living/silicon/pai/Process_Spacemove(movement_dir = 0) . = ..() @@ -304,7 +321,7 @@ if(cable) if(get_dist(src, cable) > 1) var/turf/T = get_turf(src.loc) - T.visible_message("[src.cable] rapidly retracts back into its spool.", "You hear a click and the sound of wire spooling rapidly.") + T.visible_message(span_warning("[src.cable] rapidly retracts back into its spool."), span_italics("You hear a click and the sound of wire spooling rapidly.")) qdel(src.cable) cable = null @@ -335,17 +352,17 @@ /obj/item/paicard/attack_ghost(mob/dead/observer/user) if(pai) - to_chat(user, "This pAI is already in use!") + to_chat(user, span_warning("This pAI is already in use!")) return var/area/A = get_area(get_turf(src)) if(A.type in SSpai.restricted_areas) // set in subsystem/pai.dm on initialize of the subsystem - to_chat(user, "You can't download yourself into a restricted area!") + to_chat(user, span_warning("You can't download yourself into a restricted area!")) return var/pai_name = reject_bad_name(stripped_input(usr, "Enter a name for your pAI", "pAI Name", user.name, MAX_NAME_LEN), TRUE) if(!pai_name) - to_chat(user, "Entered name is not valid.") + to_chat(user, span_warning("Entered name is not valid.")) return var/mob/living/silicon/pai/new_pai = new(src) @@ -361,8 +378,8 @@ . = ..() if(!pai) return - to_chat(user, "You override [pai]'s directive system, clearing its master string and supplied directive.") - to_chat(pai, "Warning: System override detected, check directive sub-system for any changes.'") + to_chat(user, span_notice("You override [pai]'s directive system, clearing its master string and supplied directive.")) + to_chat(pai, span_danger("Warning: System override detected, check directive sub-system for any changes.'")) log_game("[key_name(user)] emagged [key_name(pai)], wiping their master DNA and supplemental directive.") pai.master = null pai.master_dna = null @@ -372,12 +389,12 @@ if(radio_short_timerid) deltimer(radio_short_timerid) radio_short = TRUE - to_chat(src, "Your radio shorts out!") + to_chat(src, span_danger("Your radio shorts out!")) radio_short_timerid = addtimer(CALLBACK(src, PROC_REF(unshort_radio)), radio_short_cooldown, flags = TIMER_STOPPABLE) /mob/living/silicon/pai/proc/unshort_radio() radio_short = FALSE - to_chat(src, "You feel your radio is operational once more.") + to_chat(src, span_danger("You feel your radio is operational once more.")) if(radio_short_timerid) deltimer(radio_short_timerid) diff --git a/code/modules/mob/living/silicon/pai/pai_shell.dm b/code/modules/mob/living/silicon/pai/pai_shell.dm index 63fb82082fad..499788433b2e 100644 --- a/code/modules/mob/living/silicon/pai/pai_shell.dm +++ b/code/modules/mob/living/silicon/pai/pai_shell.dm @@ -101,6 +101,7 @@ if(possible_chassis[chassis]) AddElement(/datum/element/mob_holder, chassis, 'icons/mob/pai_item_head.dmi', 'icons/mob/pai_item_rh.dmi', 'icons/mob/pai_item_lh.dmi', ITEM_SLOT_HEAD) to_chat(src, "You switch your holochassis projection composite to [chassis]") + return TRUE /mob/living/silicon/pai/lay_down() . = ..() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index a47cc1d18137..c6cefff9e63a 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -118,7 +118,7 @@ mind.transfer_to(mmi.brainmob) mmi.update_icon() else - to_chat(src, "Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug.") + to_chat(src, span_boldannounce("Oops! Something went very wrong, your MMI was unable to receive your mind. You have been ghosted. Please make a bug report so we can fix this bug.")) ghostize() stack_trace("Borg MMI lacked a brainmob") mmi = null @@ -153,11 +153,11 @@ return if(wires.is_cut(WIRE_RESET_MODULE)) - to_chat(src,"ERROR: Module installer reply timeout. Please check internal connections.") + to_chat(src,span_userdanger("ERROR: Module installer reply timeout. Please check internal connections.")) return if(!CONFIG_GET(flag/disable_secborg) && GLOB.security_level < CONFIG_GET(number/minimum_secborg_alert)) - to_chat(src, "NOTICE: Due to local station regulations, the security cyborg module and its variants are only available during [NUM2SECLEVEL(CONFIG_GET(number/minimum_secborg_alert))] alert and greater.") + to_chat(src, span_notice("NOTICE: Due to local station regulations, the security cyborg module and its variants are only available during [NUM2SECLEVEL(CONFIG_GET(number/minimum_secborg_alert))] alert and greater.")) var/list/modulelist = list("Standard" = /obj/item/robot_module/standard, \ "Engineering" = /obj/item/robot_module/engineering, \ @@ -204,7 +204,7 @@ set category = "Robot Commands" set name = "Show Alerts" if(usr.stat == DEAD) - to_chat(src, "Alert: You are dead.") + to_chat(src, span_userdanger("Alert: You are dead.")) return //won't work if dead alert_control.ui_interact(src) @@ -221,7 +221,7 @@ /mob/living/silicon/robot/proc/toggle_ionpulse() if(!ionpulse) - to_chat(src, "No thrusters are installed!") + to_chat(src, span_notice("No thrusters are installed!")) return if(!ion_trail) @@ -229,7 +229,7 @@ ion_trail.set_up(src) ionpulse_on = !ionpulse_on - to_chat(src, "You [ionpulse_on ? null :"de"]activate your ion thrusters.") + to_chat(src, span_notice("You [ionpulse_on ? null :"de"]activate your ion thrusters.")) if(ionpulse_on) ion_trail.start() else @@ -419,7 +419,7 @@ if(!LAZYLEN(S.contents)) continue if(!validbreakout) - visible_message("[user] wedges [I] into the crevice separating [S] from [src]'s chassis, and begins to pry...", "You wedge [I] into the crevice separating [S] from [src]'s chassis, and begin to pry...") + visible_message(span_notice("[user] wedges [I] into the crevice separating [S] from [src]'s chassis, and begins to pry..."), span_notice("You wedge [I] into the crevice separating [S] from [src]'s chassis, and begin to pry...")) validbreakout = TRUE S.go_out() if(validbreakout) @@ -437,7 +437,7 @@ if("Yes") locked = FALSE update_icons() - to_chat(usr, "You unlock your cover.") + to_chat(usr, span_notice("You unlock your cover.")) /mob/living/silicon/robot/proc/allowed(mob/M) //check if it doesn't require any access at all @@ -545,7 +545,7 @@ lamp_functional = FALSE playsound(src, 'sound/effects/glass_step.ogg', 50) toggle_headlamp(TRUE) - to_chat(src, "Your headlamp is broken! You'll need a human to help replace it.") + to_chat(src, span_danger("Your headlamp is broken! You'll need a human to help replace it.")) /mob/living/silicon/robot/verb/outputlaws() @@ -771,10 +771,10 @@ /mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE) if(stat || locked_down || low_power_mode) - to_chat(src, "You can't do that right now!") + to_chat(src, span_warning("You can't do that right now!")) return FALSE if(be_close && !in_range(M, src)) - to_chat(src, "You are too far away!") + to_chat(src, span_warning("You are too far away!")) return FALSE return TRUE @@ -1090,12 +1090,13 @@ /datum/action/innate/undeployment name = "Disconnect from shell" desc = "Stop controlling your shell and resume normal core operations." - icon_icon = 'icons/mob/actions/actions_AI.dmi' + button_icon = 'icons/mob/actions/actions_AI.dmi' button_icon_state = "ai_core" required_mobility_flags = NONE -/datum/action/innate/undeployment/Trigger() - if(!..()) +/datum/action/innate/undeployment/Trigger(trigger_flags) + . = ..() + if(!.) return FALSE var/mob/living/silicon/robot/R = owner @@ -1105,26 +1106,27 @@ /datum/action/innate/custom_holoform name = "Select Custom Holoform" desc = "Select one of your existing avatars to use as a holoform." - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "custom_holoform" required_mobility_flags = NONE -/datum/action/innate/custom_holoform/Trigger() +/datum/action/innate/custom_holoform/Trigger(trigger_flags) if(!..()) return FALSE var/mob/living/silicon/S = owner //if setting the holoform succeeds, attempt to set it as the current holoform for the pAI or AI - if(S.attempt_set_custom_holoform()) - if(istype(S, /mob/living/silicon/pai)) - var/mob/living/silicon/pai/P = S - P.chassis = "custom" - else if(istype(S, /mob/living/silicon/ai)) - var/mob/living/silicon/ai/A = S - if(A.client?.prefs?.custom_holoform_icon) - A.holo_icon = A.client.prefs.get_filtered_holoform(HOLOFORM_FILTER_AI) - else - A.holo_icon = getHologramIcon(icon('icons/mob/ai.dmi', "female")) + if(!S.attempt_set_custom_holoform()) + return FALSE + if(istype(S, /mob/living/silicon/pai)) + var/mob/living/silicon/pai/P = S + P.chassis = "custom" + else if(istype(S, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/A = S + if(A.client?.prefs?.custom_holoform_icon) + A.holo_icon = A.client.prefs.get_filtered_holoform(HOLOFORM_FILTER_AI) + else + A.holo_icon = getHologramIcon(icon('icons/mob/ai.dmi', "female")) return TRUE @@ -1167,7 +1169,7 @@ /mob/living/silicon/robot/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE) if(!is_type_in_typecache(M, can_ride_typecache)) - M.visible_message("[M] really can't seem to mount [src]...") + M.visible_message(span_warning("[M] really can't seem to mount [src]...")) return var/datum/component/riding/riding_datum = LoadComponent(/datum/component/riding/cyborg) @@ -1180,13 +1182,13 @@ if(stat || incapacitated()) return if(module && !module.allow_riding) - M.visible_message("Unfortunately, [M] just can't seem to hold onto [src]!") + M.visible_message(span_boldwarning("Unfortunately, [M] just can't seem to hold onto [src]!")) return if(iscarbon(M) && !M.incapacitated() && !riding_datum.equip_buckle_inhands(M, 1)) if(M.get_num_arms() <= 0) - M.visible_message("[M] can't climb onto [src] because [M.p_they()] don't have any usable arms!") + M.visible_message(span_boldwarning("[M] can't climb onto [src] because [M.p_they()] don't have any usable arms!")) else - M.visible_message("[M] can't climb onto [src] because [M.p_their()] hands are full!") + M.visible_message(span_boldwarning("[M] can't climb onto [src] because [M.p_their()] hands are full!")) return . = ..(M, force, check_loc) diff --git a/code/modules/mob/living/silicon/robot/robot_mobility.dm b/code/modules/mob/living/silicon/robot/robot_mobility.dm index c5863b523f0f..dc8dc42611a1 100644 --- a/code/modules/mob/living/silicon/robot/robot_mobility.dm +++ b/code/modules/mob/living/silicon/robot/robot_mobility.dm @@ -10,6 +10,6 @@ newflags |= MOBILITY_FLAGS_ANY_INTERACTION mobility_flags = newflags update_transform() - update_action_buttons_icon() + update_mob_action_buttons() update_icons() return mobility_flags diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 0a84d5afc892..ba92f018df2d 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -432,7 +432,7 @@ /datum/action/innate/seek_prey name = "Seek the Harvest" desc = "None can hide from Nar'Sie, activate to track a survivor attempting to flee the red harvest!" - icon_icon = 'icons/mob/actions/actions_cult.dmi' + button_icon = 'icons/mob/actions/actions_cult.dmi' background_icon_state = "bg_demon" buttontooltipstyle = "cult" button_icon_state = "cult_mark" diff --git a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm index c956e19a857a..aed1cc33f880 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm @@ -42,6 +42,12 @@ return internal_storage return ..() +/mob/living/simple_animal/drone/get_slot_by_item(obj/item/looking_for) + if(internal_storage == looking_for) + return ITEM_SLOT_DEX_STORAGE + if(head == looking_for) + return ITEM_SLOT_HEAD + return ..() /mob/living/simple_animal/drone/equip_to_slot(obj/item/I, slot) if(!slot) diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm index 88f25eb5cee0..500bc237ebc4 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm @@ -59,7 +59,7 @@ . = ..() boss = null -/datum/action/boss/IsAvailable(silent = FALSE) +/datum/action/boss/IsAvailable(feedback = TRUE) . = ..() if(!.) return @@ -72,14 +72,16 @@ if(!boss.client && needs_target && !boss.target) return FALSE -/datum/action/boss/Trigger() +/datum/action/boss/Trigger(trigger_flags) . = ..() if(!.) - return + return FALSE if(!boss.atb.spend(boss_cost)) return FALSE - if(say_when_triggered) - boss.say(say_when_triggered, forced = "boss action") + if(!say_when_triggered) + return FALSE + boss.say(say_when_triggered, forced = "boss action") + return TRUE //Example: /* @@ -143,7 +145,7 @@ var/datum/action/boss/AB = ab if(!boss.client && (!AB.req_statuses || (boss.AIStatus in AB.req_statuses)) && prob(AB.usage_probability) && AB.Trigger()) break - AB.UpdateButtons(TRUE) + AB.build_all_button_icons() /datum/boss_active_timed_battle/Destroy() 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 82a6b837e00f..ba2ca18a02a9 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm @@ -30,7 +30,7 @@ //Lets the wizard summon his art to fight for him /datum/action/boss/wizard_summon_minions name = "Summon Minions" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "art_summon" usage_probability = 20 boss_cost = 30 @@ -42,10 +42,10 @@ var/maximum_stickmen = 6 var/stickmen_to_summon = 3 -/datum/action/boss/wizard_summon_minions/Trigger() +/datum/action/boss/wizard_summon_minions/Trigger(trigger_flags) . =..() if(!.) - return + return FALSE var/to_summon = stickmen_to_summon var/current_len = length(summoned_minions) if(current_len > maximum_stickmen - stickmen_to_summon) @@ -71,6 +71,7 @@ S.faction = boss.faction RegisterSignal(S, COMSIG_PARENT_QDELETING, PROC_REF(remove_from_list)) summoned_minions += S + return TRUE /datum/action/boss/wizard_summon_minions/proc/remove_from_list(datum/source, forced) summoned_minions -= source @@ -81,7 +82,7 @@ //Hitting the wizard himself destroys all decoys /datum/action/boss/wizard_mimic name = "Craft Mimicry" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "mimic_summon" usage_probability = 30 boss_cost = 40 @@ -89,10 +90,10 @@ req_statuses = list(AI_ON) say_when_triggered = "" -/datum/action/boss/wizard_mimic/Trigger() +/datum/action/boss/wizard_mimic/Trigger(trigger_flags) . = ..() if(!.) - return + return FALSE var/mob/living/target if(!boss.client) //AI's target target = boss.target @@ -102,6 +103,7 @@ target = pick(threats) else to_chat(owner, "There is no potential foe of different faction around to attack") + return FALSE if(target) var/mob/living/simple_animal/hostile/boss/paper_wizard/wiz = boss var/directions = GLOB.cardinals.Copy() @@ -114,8 +116,10 @@ wiz.forceMove(get_step(target,pick_n_take(directions))) wiz.minimum_distance = 1 //so he doesn't run away and ruin everything wiz.retreat_distance = 0 + return TRUE else boss.atb.refund(boss_cost) + return FALSE /mob/living/simple_animal/hostile/boss/paper_wizard/copy desc = "'Tis a ruse!" 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 c4a389cd2c8f..e271a6922f69 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -77,8 +77,8 @@ /mob/living/simple_animal/hostile/poison/giant_spider/Login() ..() if(directive) - to_chat(src, "Your mother left you a directive! Follow it at all costs.") - to_chat(src, "[directive]") + to_chat(src, span_notice("Your mother left you a directive! Follow it at all costs.")) + to_chat(src, span_spider("[directive]")) /mob/living/simple_animal/hostile/poison/giant_spider/attack_ghost(mob/user) . = ..() @@ -97,7 +97,7 @@ if(spider_ask == "No" || !src || QDELETED(src)) return TRUE if(key) - to_chat(user, "Someone else already took this spider.") + to_chat(user, span_notice("Someone else already took this spider.")) return TRUE user.transfer_ckey(src, FALSE) return TRUE @@ -313,19 +313,19 @@ /mob/living/simple_animal/hostile/poison/giant_spider/nurse/proc/cocoon() if(stat != DEAD && cocoon_target && !cocoon_target.anchored) if(cocoon_target == src) - to_chat(src, "You can't wrap yourself!") + to_chat(src, span_warning("You can't wrap yourself!")) return if(istype(cocoon_target, /mob/living/simple_animal/hostile/poison/giant_spider)) - to_chat(src, "You can't wrap other spiders!") + to_chat(src, span_warning("You can't wrap other spiders!")) return if(!Adjacent(cocoon_target)) - to_chat(src, "You can't reach [cocoon_target]!") + to_chat(src, span_warning("You can't reach [cocoon_target]!")) return if(busy == SPINNING_COCOON) - to_chat(src, "You're already spinning a cocoon!") + to_chat(src, span_warning("You're already spinning a cocoon!")) return //we're already doing this, don't cancel out or anything busy = SPINNING_COCOON - visible_message("[src] begins to secrete a sticky substance around [cocoon_target].","You begin wrapping [cocoon_target] into a cocoon.") + visible_message(span_notice("[src] begins to secrete a sticky substance around [cocoon_target]."),span_notice("You begin wrapping [cocoon_target] into a cocoon.")) stop_automated_movement = TRUE walk(src,0) if(do_after(src, 50, target = cocoon_target)) @@ -336,11 +336,11 @@ if(L.blood_volume && (L.stat != DEAD || !consumed_mobs[L.tag])) //if they're not dead, you can consume them anyway consumed_mobs[L.tag] = TRUE fed++ - lay_eggs.UpdateButtons(TRUE) - visible_message("[src] sticks a proboscis into [L] and sucks a viscous substance out.","You suck the nutriment out of [L], feeding you enough to lay a cluster of eggs.") + lay_eggs.build_all_button_icons() + visible_message(span_danger("[src] sticks a proboscis into [L] and sucks a viscous substance out."),span_notice("You suck the nutriment out of [L], feeding you enough to lay a cluster of eggs.")) L.death() //you just ate them, they're dead. else - to_chat(src, "[L] cannot sate your hunger!") + to_chat(src, span_warning("[L] cannot sate your hunger!")) cocoon_target.forceMove(C) if(cocoon_target.density || ismob(cocoon_target)) @@ -350,7 +350,7 @@ stop_automated_movement = FALSE /datum/action/innate/spider - icon_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon = 'icons/mob/actions/actions_animal.dmi' background_icon_state = "bg_alien" /datum/action/innate/spider/lay_web @@ -371,12 +371,12 @@ var/obj/structure/spider/stickyweb/W = locate() in T var/obj/structure/arachnid/W2 = locate() in T if(W || W2) - to_chat(S, "There's already a web here!") + to_chat(S, span_warning("There's already a web here!")) return if(S.busy != SPINNING_WEB) S.busy = SPINNING_WEB - S.visible_message("[S] begins to secrete a sticky substance.","You begin to lay a web.") + S.visible_message(span_notice("[S] begins to secrete a sticky substance."),span_notice("You begin to lay a web.")) S.stop_automated_movement = TRUE if(do_after(S, 40, target = T)) if(S.busy == SPINNING_WEB && S.loc == T) @@ -384,7 +384,7 @@ S.busy = SPIDER_IDLE S.stop_automated_movement = FALSE else - to_chat(S, "You're already spinning a web!") + to_chat(S, span_warning("You're already spinning a web!")) /obj/effect/proc_holder/wrap name = "Wrap" @@ -403,7 +403,7 @@ /obj/effect/proc_holder/wrap/update_icon() . = ..() action.button_icon_state = "wrap_[active]" - action.UpdateButtons() + action.build_all_button_icons() /obj/effect/proc_holder/wrap/Trigger(mob/living/simple_animal/hostile/poison/giant_spider/nurse/user) if(!istype(user)) @@ -414,10 +414,10 @@ /obj/effect/proc_holder/wrap/proc/activate(mob/living/user) var/message if(active) - message = "You no longer prepare to wrap something in a cocoon." + message = span_notice("You no longer prepare to wrap something in a cocoon.") remove_ranged_ability(message) else - message = "You prepare to wrap something in a cocoon. Left-click your target to start wrapping!" + message = span_notice("You prepare to wrap something in a cocoon. Left-click your target to start wrapping!") add_ranged_ability(user, message, TRUE) return TRUE @@ -448,7 +448,7 @@ check_flags = AB_CHECK_CONSCIOUS button_icon_state = "lay_eggs" -/datum/action/innate/spider/lay_eggs/IsAvailable(silent = FALSE) +/datum/action/innate/spider/lay_eggs/IsAvailable(feedback = TRUE) if(..()) if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse)) return FALSE @@ -464,12 +464,12 @@ var/obj/structure/spider/eggcluster/E = locate() in get_turf(S) if(E) - to_chat(S, "There is already a cluster of eggs here!") + to_chat(S, span_warning("There is already a cluster of eggs here!")) else if(!S.fed) - to_chat(S, "You are too hungry to do this!") + to_chat(S, span_warning("You are too hungry to do this!")) else if(S.busy != LAYING_EGGS) S.busy = LAYING_EGGS - S.visible_message("[S] begins to lay a cluster of eggs.","You begin to lay a cluster of eggs.") + S.visible_message(span_notice("[S] begins to lay a cluster of eggs."),span_notice("You begin to lay a cluster of eggs.")) S.stop_automated_movement = TRUE if(do_after(S, 50, target = get_turf(S))) if(S.busy == LAYING_EGGS) @@ -483,7 +483,7 @@ C.poison_per_bite = S.poison_per_bite C.faction = S.faction.Copy() S.fed-- - UpdateButtons(TRUE) + build_all_button_icons() S.busy = SPIDER_IDLE S.stop_automated_movement = FALSE @@ -512,14 +512,17 @@ desc = "Send a command to all living spiders." button_icon_state = "command" -/datum/action/innate/spider/comm/IsAvailable(silent = FALSE) +/datum/action/innate/spider/comm/IsAvailable(feedback = TRUE) if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife)) return FALSE return TRUE -/datum/action/innate/spider/comm/Trigger() +/datum/action/innate/spider/comm/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE var/input = stripped_input(owner, "Input a command for your legions to follow.", "Command", "") - if(QDELETED(src) || !input || !IsAvailable()) + if(QDELETED(src) || !input || !IsAvailable(feedback = TRUE)) return FALSE spider_command(owner, input) return TRUE @@ -528,7 +531,7 @@ if(!message) return var/my_message - my_message = "Command from [user]: [message]" + my_message = span_spider("Command from [user]: [message]") for(var/mob/living/simple_animal/hostile/poison/giant_spider/M in GLOB.spidermobs) to_chat(M, my_message) for(var/M in GLOB.dead_mob_list) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm index 8b657fc72943..decbee69d3c0 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm @@ -64,21 +64,21 @@ Difficulty: Medium /datum/action/innate/megafauna_attack/dash name = "Dash To Target" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "sniper_zoom" chosen_message = "You are now dashing to your target." chosen_attack_num = 1 /datum/action/innate/megafauna_attack/kinetic_accelerator name = "Fire Kinetic Accelerator" - icon_icon = 'icons/obj/guns/energy.dmi' + button_icon = 'icons/obj/guns/energy.dmi' button_icon_state = "kineticgun" chosen_message = "You are now shooting your kinetic accelerator." chosen_attack_num = 2 /datum/action/innate/megafauna_attack/transform_weapon name = "Transform Weapon" - icon_icon = 'icons/obj/lavaland/artefacts.dmi' + button_icon = 'icons/obj/lavaland/artefacts.dmi' button_icon_state = "cleaving_saw" chosen_message = "You are now transforming your weapon." chosen_attack_num = 3 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm index f3ba99864616..e2247f6ee3dc 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm @@ -55,21 +55,21 @@ Difficulty: Extremely Hard /datum/action/innate/megafauna_attack/frost_orbs name = "Fire Frost Orbs" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "sniper_zoom" chosen_message = "You are now sending out frost orbs to track in on a target." chosen_attack_num = 1 /datum/action/innate/megafauna_attack/snowball_machine_gun name = "Fire Snowball Machine Gun" - icon_icon = 'icons/obj/guns/energy.dmi' + button_icon = 'icons/obj/guns/energy.dmi' button_icon_state = "kineticgun" chosen_message = "You are now firing a snowball machine gun at a target." chosen_attack_num = 2 /datum/action/innate/megafauna_attack/ice_shotgun name = "Fire Ice Shotgun" - icon_icon = 'icons/obj/guns/projectile.dmi' + button_icon = 'icons/obj/guns/projectile.dmi' button_icon_state = "shotgun" chosen_message = "You are now firing shotgun ice blasts." chosen_attack_num = 3 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 8111dbb36615..549a73b1df28 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -695,7 +695,7 @@ Difficulty: Normal new /obj/effect/temp_visual/hierophant/telegraph/teleport(get_turf(src), user) to_chat(user, "You collect [src], reattaching it to the club!") H.beacon = null - user.update_action_buttons_icon() + user.update_mob_action_buttons() qdel(src) else H.timer = world.time diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index 64566abb9d53..adb571f84176 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -179,7 +179,7 @@ /datum/action/innate/megafauna_attack name = "Megafauna Attack" - icon_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon = 'icons/mob/actions/actions_animal.dmi' button_icon_state = "" var/mob/living/simple_animal/hostile/megafauna/M var/chosen_message diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm index aada6229303b..3d121470c2dd 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm @@ -51,21 +51,21 @@ Difficulty: Hard /datum/action/innate/megafauna_attack/heavy_stomp name = "Heavy Stomp" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "sniper_zoom" chosen_message = "You are now stomping the ground around you." chosen_attack_num = 1 /datum/action/innate/megafauna_attack/teleport name = "Teleport" - icon_icon = 'icons/effects/bubblegum.dmi' + button_icon = 'icons/effects/bubblegum.dmi' button_icon_state = "smack ya one" chosen_message = "You are now teleporting at the target you click on." chosen_attack_num = 2 /datum/action/innate/megafauna_attack/disorienting_scream name = "Disorienting Scream" - icon_icon = 'icons/turf/walls/wall.dmi' + button_icon = 'icons/turf/walls/wall.dmi' button_icon_state = "wall" chosen_message = "You are now screeching, disorienting targets around you." chosen_attack_num = 3 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index bd9790733706..0183de23a213 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -73,13 +73,13 @@ While using this makes the system rely on OnFire, it still gives options for tim /datum/action/innate/elite_attack name = "Elite Attack" - icon_icon = 'icons/mob/actions/actions_elites.dmi' + button_icon = 'icons/mob/actions/actions_elites.dmi' button_icon_state = "" background_icon_state = "bg_default" var/chosen_message var/chosen_attack_num = 0 -/datum/action/innate/elite_attack/CreateButton() +/datum/action/innate/elite_attack/create_button() var/atom/movable/screen/movable/action_button/button = ..() button.maptext = "" button.maptext_x = 8 @@ -93,20 +93,19 @@ While using this makes the system rely on OnFire, it still gives options for tim STOP_PROCESSING(SSfastprocess, src) qdel(src) return - UpdateButtons() + build_all_button_icons(UPDATE_BUTTON_STATUS) -/datum/action/innate/elite_attack/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE) - . = ..() - if(!.) - return - if(status_only) - return +/datum/action/innate/elite_attack/update_button_status(atom/movable/screen/movable/action_button/button, force = FALSE) var/mob/living/simple_animal/hostile/asteroid/elite/elite_owner = owner + if(!istype(owner)) + button.maptext = "" + return + var/timeleft = max(elite_owner.ranged_cooldown - world.time, 0) if(timeleft == 0) button.maptext = "" else - button.maptext = "[round(timeleft/10, 0.1)]" + button.maptext = MAPTEXT("[round(timeleft/10, 0.1)]") /datum/action/innate/elite_attack/Grant(mob/living/L) if(istype(L, /mob/living/simple_animal/hostile/asteroid/elite)) diff --git a/code/modules/mob/living/simple_animal/hostile/plaguerat.dm b/code/modules/mob/living/simple_animal/hostile/plaguerat.dm index 88118d179b9f..2cd78f2fd040 100644 --- a/code/modules/mob/living/simple_animal/hostile/plaguerat.dm +++ b/code/modules/mob/living/simple_animal/hostile/plaguerat.dm @@ -162,7 +162,7 @@ GLOBAL_LIST_EMPTY(plague_rats) /datum/action/cooldown/scavenge name = "Scavenge" desc = "Spread the plague, scavenge for trash and fresh meat to reproduce." - icon_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon = 'icons/mob/actions/actions_animal.dmi' background_icon_state = "bg_clock" button_icon_state = "coffer" cooldown_time = 50 diff --git a/code/modules/mob/living/simple_animal/hostile/regalrat.dm b/code/modules/mob/living/simple_animal/hostile/regalrat.dm index 87c7d0519bb6..6efad3c0ec5d 100644 --- a/code/modules/mob/living/simple_animal/hostile/regalrat.dm +++ b/code/modules/mob/living/simple_animal/hostile/regalrat.dm @@ -83,7 +83,7 @@ /datum/action/cooldown/coffer name = "Fill Coffers" desc = "Your newly granted regality and poise let you scavenge for lost junk, but more importantly, cheese." - icon_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon = 'icons/mob/actions/actions_animal.dmi' background_icon_state = "bg_clock" button_icon_state = "coffer" cooldown_time = 50 @@ -125,7 +125,7 @@ /datum/action/cooldown/riot name = "Raise Army" desc = "Raise an army out of the hordes of mice and pests crawling around the maintenance shafts." - icon_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon = 'icons/mob/actions/actions_animal.dmi' button_icon_state = "riot" background_icon_state = "bg_clock" cooldown_time = 80 diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 2f0c42bf77f8..a4c96648961e 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -488,7 +488,7 @@ name = "Summon Rift" desc = "Summon a rift to bring forth a horde of space carp." background_icon_state = "bg_default" - icon_icon = 'icons/mob/actions/actions_space_dragon.dmi' + button_icon = 'icons/mob/actions/actions_space_dragon.dmi' button_icon_state = "carp_rift" /datum/action/innate/summon_rift/Activate() diff --git a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm index 62d989a31e26..118fb67ea71e 100644 --- a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm +++ b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm @@ -65,7 +65,7 @@ E.Activate() /datum/action/innate/fugu - icon_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon = 'icons/mob/actions/actions_animal.dmi' /datum/action/innate/fugu/expand name = "Inflate" diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index c7e753744c95..a616fd17c7ac 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -484,7 +484,7 @@ if(!CHECK_MOBILITY(src, MOBILITY_MOVE)) // !(mobility_flags & MOBILITY_MOVE) walk(src, 0) //stop mid walk update_transform() - update_action_buttons_icon() + update_mob_action_buttons() return mobility_flags /mob/living/simple_animal/update_transform(do_animate) diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index 8e66ae14e34a..b98f82a312f0 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -249,7 +249,7 @@ else if (nutrition >= get_grow_nutrition() && amount_grown < SLIME_EVOLUTION_THRESHOLD) adjust_nutrition(-20) amount_grown++ - update_action_buttons_icon() + update_mob_action_buttons() if(amount_grown >= SLIME_EVOLUTION_THRESHOLD && !buckled && !Target && !ckey) if(is_adult) diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm index 3624c00e6dbf..975bbe8ae370 100644 --- a/code/modules/mob/living/simple_animal/slime/powers.dm +++ b/code/modules/mob/living/simple_animal/slime/powers.dm @@ -7,11 +7,11 @@ /datum/action/innate/slime check_flags = AB_CHECK_CONSCIOUS - icon_icon = 'icons/mob/actions/actions_slime.dmi' + button_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" var/needs_growth = NO_GROWTH_NEEDED -/datum/action/innate/slime/IsAvailable(silent = FALSE) +/datum/action/innate/slime/IsAvailable(feedback = TRUE) if(..()) var/mob/living/simple_animal/slime/S = owner if(needs_growth == GROWTH_NEEDED) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index d700de554a83..1eed683a50f9 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -234,9 +234,19 @@ if(self_message) show_message(self_message, MSG_AUDIBLE, deaf_message, MSG_VISUAL) +///Get the item on the mob in the storage slot identified by the id passed in /mob/proc/get_item_by_slot(slot_id) return null +/// Gets what slot the item on the mob is held in. +/// Returns null if the item isn't in any slots on our mob. +/// Does not check if the passed item is null, which may result in unexpected outcoms. +/mob/proc/get_slot_by_item(obj/item/looking_for) + if(looking_for in held_items) + return ITEM_SLOT_HANDS + + return null + /mob/proc/restrained(ignore_grab) return diff --git a/code/modules/mod/mod_actions.dm b/code/modules/mod/mod_actions.dm index ee28771ef108..9cad31912bd0 100644 --- a/code/modules/mod/mod_actions.dm +++ b/code/modules/mod/mod_actions.dm @@ -1,8 +1,7 @@ /datum/action/item_action/mod background_icon_state = "bg_tech_blue" - icon_icon = 'icons/mob/actions/actions_mod.dmi' + button_icon = 'icons/mob/actions/actions_mod.dmi' check_flags = AB_CHECK_CONSCIOUS - var/obj/item/mod/control/mod /// Whether this action is intended for the AI. Stuff breaks a lot if this is done differently. var/ai_action = FALSE @@ -12,10 +11,10 @@ qdel(src) return if(ai_action) - background_icon_state = "bg_tech" + background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND /datum/action/item_action/mod/Grant(mob/user) - mod = target + var/obj/item/mod/control/mod = target if(ai_action && user != mod.ai) return else if(!ai_action && user == mod.ai) @@ -23,15 +22,15 @@ return ..() /datum/action/item_action/mod/Remove(mob/user) + var/obj/item/mod/control/mod = target if(ai_action && mod && user != mod.ai) return else if(!ai_action && mod && user == mod.ai) return return ..() -/datum/action/item_action/mod/Trigger(trigger_flags) - if(!IsAvailable()) - return FALSE +/datum/action/item_action/mod/do_effect(trigger_flags) + var/obj/item/mod/control/mod = target if(mod.malfunctioning && prob(75)) mod.balloon_alert(usr, "button malfunctions!") return FALSE @@ -42,11 +41,12 @@ desc = "Deploy/Conceal a part of the MODsuit." button_icon_state = "deploy" -/datum/action/item_action/mod/deploy/Trigger() - if(!IsAvailable()) - return FALSE +/datum/action/item_action/mod/deploy/do_effect(trigger_flags) + . = ..() + if(!.) + return + var/obj/item/mod/control/mod = target mod.choose_deploy(usr) - return TRUE /datum/action/item_action/mod/deploy/ai ai_action = TRUE @@ -56,11 +56,12 @@ desc = "Activate/Deactivate the MODsuit." button_icon_state = "activate" -/datum/action/item_action/mod/activate/Trigger() - if(!IsAvailable()) - return FALSE +/datum/action/item_action/mod/activate/do_effect(trigger_flags) + . = ..() + if(!.) + return + var/obj/item/mod/control/mod = target mod.toggle_activate(usr) - return TRUE /datum/action/item_action/mod/activate/ai ai_action = TRUE @@ -70,11 +71,12 @@ desc = "Toggle a MODsuit module." button_icon_state = "module" -/datum/action/item_action/mod/module/Trigger() - if(!IsAvailable()) - return FALSE +/datum/action/item_action/mod/module/do_effect(trigger_flags) + . = ..() + if(!.) + return + var/obj/item/mod/control/mod = target mod.quick_module(usr) - return TRUE /datum/action/item_action/mod/module/ai ai_action = TRUE @@ -84,11 +86,12 @@ desc = "Open the MODsuit's panel." button_icon_state = "panel" -/datum/action/item_action/mod/panel/Trigger() - if(!IsAvailable()) - return FALSE +/datum/action/item_action/mod/panel/do_effect(trigger_flags) + . = ..() + if(!.) + return + var/obj/item/mod/control/mod = target mod.ui_interact(usr) - return TRUE /datum/action/item_action/mod/panel/ai ai_action = TRUE diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index 40f7fa1a932c..4dc33aa222e7 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -431,7 +431,7 @@ /obj/item/mod/control/proc/quick_module(mob/user) if(!length(modules)) - return + return FALSE var/list/display_names = list() var/list/items = list() for(var/obj/item/mod/module/module as anything in modules) @@ -441,15 +441,16 @@ var/image/module_image = image(icon = module.icon, icon_state = module.icon_state) items += list(module.name = module_image) if(!length(items)) - return + return FALSE var/pick = show_radial_menu(user, src, items, custom_check = FALSE, require_near = TRUE) if(!pick) - return + return FALSE var/module_reference = display_names[pick] var/obj/item/mod/module/selected_module = locate(module_reference) in modules if(!istype(selected_module) || user.incapacitated()) - return + return FALSE selected_module.on_select() + return TRUE /obj/item/mod/control/proc/set_mod_color(new_color) var/list/all_parts = mod_parts + src diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_adrenaline.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_adrenaline.dm index 4dc9e738ecca..1202b4aec53c 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_adrenaline.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_adrenaline.dm @@ -6,7 +6,7 @@ name = "Adrenaline Boost" desc = "Inject a secret chemical that will counteract all movement-impairing effect." button_icon_state = "adrenal" - icon_icon = 'icons/obj/implants.dmi' + button_icon = 'icons/obj/implants.dmi' required_mobility_flags = NONE /** diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_empulse.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_empulse.dm index ea2341a13235..8e75dbcb89a9 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_empulse.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_empulse.dm @@ -4,7 +4,7 @@ name = "EM Burst (50E)" desc = "Disable any nearby technology with an electro-magnetic pulse." button_icon_state = "emp" - icon_icon = 'icons/mob/actions/actions_spells.dmi' + button_icon = 'icons/mob/actions/actions_spells.dmi' /** * Proc called to allow the ninja to EMP the nearby area. diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_glove_toggle.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_glove_toggle.dm index ec5bf078a550..0888a763fb17 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_glove_toggle.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_glove_toggle.dm @@ -2,7 +2,7 @@ name = "Toggle interaction" desc = "Switch between normal interaction and drain mode." button_icon_state = "s-ninjan" - icon_icon = 'icons/obj/clothing/gloves.dmi' + button_icon = 'icons/obj/clothing/gloves.dmi' /** * Proc called to toggle the ninja glove's special abilities. diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm index ab52f3e01809..6a74095f7fe5 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_net.dm @@ -2,7 +2,7 @@ name = "Energy Net (40E)" desc = "Captures a fallen opponent in a net of energy." button_icon_state = "energynet" - icon_icon = 'icons/effects/effects.dmi' + button_icon = 'icons/effects/effects.dmi' /** * Proc called to ensnare a person in a energy net. diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_stars.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_stars.dm index ef897d5bb9d0..f6ad28750504 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_stars.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_stars.dm @@ -2,7 +2,7 @@ name = "Create Throwing Stars (1E)" desc = "Creates a throwing star in your hand, if possible." button_icon_state = "throwingstar" - icon_icon = 'icons/obj/items_and_weapons.dmi' + button_icon = 'icons/obj/items_and_weapons.dmi' /** * Proc called to create a ninja star in the ninja's hands. diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_status_read.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_status_read.dm index 33e6b1ae26e2..1a18fce22d43 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_status_read.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_status_read.dm @@ -3,5 +3,5 @@ name = "Status Readout" desc = "Gives a detailed readout about your current status." button_icon_state = "health" - icon_icon = 'icons/obj/device.dmi' + button_icon = 'icons/obj/device.dmi' var/action_background_icon_state = "bg_default_on" diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_stealth.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_stealth.dm index 079f0c53e941..73e1e5c1e394 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_stealth.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_stealth.dm @@ -2,7 +2,7 @@ name = "Toggle Stealth" desc = "Toggles stealth mode on and off." button_icon_state = "ninja_cloak" - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' /** * Proc called to toggle ninja stealth. diff --git a/code/modules/ninja/suit/ninja_equipment_actions/ninja_sword_recall.dm b/code/modules/ninja/suit/ninja_equipment_actions/ninja_sword_recall.dm index dd6ca61f881f..37a8dc1e4843 100644 --- a/code/modules/ninja/suit/ninja_equipment_actions/ninja_sword_recall.dm +++ b/code/modules/ninja/suit/ninja_equipment_actions/ninja_sword_recall.dm @@ -2,7 +2,7 @@ name = "Recall Energy Katana (Variable Cost)" desc = "Teleports the Energy Katana linked to this suit to its wearer, cost based on distance." button_icon_state = "energy_katana" - icon_icon = 'icons/obj/items_and_weapons.dmi' + button_icon = 'icons/obj/items_and_weapons.dmi' /** * Proc called to recall the ninja's sword. diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 24b6cf71c128..151ddb6def24 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -426,7 +426,7 @@ for(var/obj/item/I in U.held_items) if(istype(I, /obj/item/turret_control)) qdel(I) - UpdateButtons() + build_all_button_icons() return else playsound(PE,'sound/mecha/mechmove01.ogg', 50, TRUE) @@ -443,7 +443,7 @@ else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand var/obj/item/turret_control/TC = new /obj/item/turret_control() U.put_in_hands(TC) - UpdateButtons() + build_all_button_icons() /obj/item/turret_control diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index f8f8182a2883..c0dc454dde3a 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -19,6 +19,8 @@ item_flags = NEEDS_PERMIT attack_verb = list("struck", "hit", "bashed") attack_speed = CLICK_CD_RANGE + action_slots = ALL + var/ranged_attack_speed = CLICK_CD_RANGE var/melee_attack_speed = CLICK_CD_MELEE @@ -142,7 +144,7 @@ if(fire_select_modes.len > 1) firemode_action = new(src) firemode_action.button_icon_state = "fireselect_[fire_select]" - firemode_action.UpdateButtons() + firemode_action.build_all_button_icons() /obj/item/gun/ComponentInitialize() . = ..() @@ -219,7 +221,7 @@ playsound(user, 'sound/weapons/empty.ogg', 100, TRUE) update_appearance() firemode_action.button_icon_state = "fireselect_[fire_select]" - firemode_action.UpdateButtons() + firemode_action.build_all_button_icons() return TRUE /obj/item/gun/equipped(mob/living/user, slot) @@ -670,7 +672,7 @@ update_icon() for(var/X in actions) var/datum/action/A = X - A.UpdateButtons() + A.build_all_button_icons() /obj/item/gun/update_overlays() . = ..() @@ -751,20 +753,24 @@ /datum/action/item_action/toggle_scope_zoom name = "Toggle Scope" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' button_icon_state = "sniper_zoom" -/datum/action/item_action/toggle_scope_zoom/IsAvailable(silent = FALSE) +/datum/action/item_action/toggle_scope_zoom/IsAvailable(feedback = TRUE) . = ..() if(!. && owner) var/obj/item/gun/G = target G.zoom(owner, owner.dir, FALSE) -/datum/action/item_action/toggle_scope_zoom/Trigger() +/datum/action/item_action/toggle_scope_zoom/do_effect(trigger_flags) . = ..() - if(.) - var/obj/item/gun/G = target - G.zoom(owner, owner.dir) + if(!.) + return + var/obj/item/gun/G = target + if(!istype(G)) + return FALSE + G.zoom(owner, owner.dir) + return TRUE /datum/action/item_action/toggle_scope_zoom/Remove(mob/living/L) var/obj/item/gun/G = target diff --git a/code/modules/projectiles/guns/magic/motivation.dm b/code/modules/projectiles/guns/magic/motivation.dm index db4c222619e4..774ff21dcdd1 100644 --- a/code/modules/projectiles/guns/magic/motivation.dm +++ b/code/modules/projectiles/guns/magic/motivation.dm @@ -34,14 +34,18 @@ //action button to toggle judgement cuts on/off /datum/action/judgement_cut name = "Judgement Cut - Allows Motivation to slash at a longer distance." - icon_icon = 'icons/obj/projectiles.dmi' + button_icon = 'icons/obj/projectiles.dmi' button_icon_state = "judgement_fire" var/judgement_toggled = TRUE //lets the user know that you toggled them on/off -/datum/action/judgement_cut/Trigger() +/datum/action/judgement_cut/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE judgement_toggled = !judgement_toggled to_chat(owner, "You [judgement_toggled ? "enable" : "disable"] Judgement Cuts with Motivation.") + return TRUE //Prevents "firing" the judgement cuts if toggled off and lets the user know /obj/item/gun/magic/staff/motivation/can_trigger_gun(mob/living/user) diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index 4548719a20b3..7f9dd7a89b6c 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -174,7 +174,7 @@ fire_delay = delay current_tracers = list() START_PROCESSING(SSfastprocess, src) - zoom_lock_action = new(src) + zoom_lock_action = add_item_action(/datum/action/item_action/zoom_lock_action) /obj/item/gun/energy/beam_rifle/Destroy() STOP_PROCESSING(SSfastprocess, src) diff --git a/code/modules/projectiles/guns/misc/chameleon.dm b/code/modules/projectiles/guns/misc/chameleon.dm index 428de747f768..f4791f88da1e 100644 --- a/code/modules/projectiles/guns/misc/chameleon.dm +++ b/code/modules/projectiles/guns/misc/chameleon.dm @@ -27,7 +27,7 @@ /obj/item/gun/energy/laser/chameleon/Initialize(mapload) . = ..() - chameleon_action = new(src) + chameleon_action = add_item_action(/datum/action/item_action/chameleon/change/gun) chameleon_action.chameleon_type = /obj/item/gun chameleon_action.chameleon_name = "Gun" chameleon_action.chameleon_blacklist = typecacheof(/obj/item/gun/magic, ignore_root_path = FALSE) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 312f3caace66..8fdb91c40522 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -515,7 +515,7 @@ else if(istype(cached_my_atom, /obj/item/slime_extract))//if the object is a slime_extract. var/obj/item/slime_extract/M = cached_my_atom - if(M.Uses > 0) // added a limit to slime cores -- Muskets requested this + if(M.extract_uses > 0) // added a limit to slime cores -- Muskets requested this matching_other = 1 else if(!C.required_container) @@ -608,8 +608,8 @@ if(istype(cached_my_atom, /obj/item/slime_extract))//if there's an extract and it's used up. var/obj/item/slime_extract/ME2 = my_atom - ME2.Uses-- - if(ME2.Uses <= 0) // give the notification that the slime core is dead + ME2.extract_uses-- + if(ME2.extract_uses <= 0) // give the notification that the slime core is dead for(var/mob/M in seen) to_chat(M, "[iconhtml] \The [my_atom]'s power is consumed in the reaction.") ME2.name = "used slime extract" diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index 45d0df55802e..4b0abd82044a 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -12,7 +12,7 @@ /datum/chemical_reaction/slime/proc/delete_extract(datum/reagents/holder) var/obj/item/slime_extract/M = holder.my_atom - if(M.Uses <= 0 && !results.len) //if the slime doesn't output chemicals + if(M.extract_uses <= 0 && !results.len) //if the slime doesn't output chemicals qdel(M) //Grey @@ -579,7 +579,7 @@ var/turf/T = get_turf(holder.my_atom) new /obj/effect/timestop(T, null, null, null) if(istype(extract)) - if(extract.Uses > 0) + if(extract.extract_uses > 0) var/mob/lastheld = get_mob_by_key(holder.my_atom.fingerprintslast) if(lastheld && !lastheld.equip_to_slot_if_possible(extract, ITEM_SLOT_HANDS, disable_warning = TRUE)) extract.forceMove(get_turf(lastheld)) diff --git a/code/modules/research/nanites/nanite_programs/utility.dm b/code/modules/research/nanites/nanite_programs/utility.dm index 5dc258fad45c..997977f7853e 100644 --- a/code/modules/research/nanites/nanite_programs/utility.dm +++ b/code/modules/research/nanites/nanite_programs/utility.dm @@ -337,7 +337,7 @@ /datum/action/innate/nanite_button name = "Button" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS button_icon_state = "nanite_power" var/datum/nanite_program/dermal_button/program diff --git a/code/modules/research/xenobiology/crossbreeding/_clothing.dm b/code/modules/research/xenobiology/crossbreeding/_clothing.dm index 640aa6d49057..a2d5154c2248 100644 --- a/code/modules/research/xenobiology/crossbreeding/_clothing.dm +++ b/code/modules/research/xenobiology/crossbreeding/_clothing.dm @@ -58,41 +58,48 @@ Slimecrossing Armor set_light(5) /obj/structure/light_prism/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) - to_chat(user, "You dispel [src]") + to_chat(user, span_notice("You dispel [src]")) qdel(src) /datum/action/item_action/change_prism_colour name = "Adjust Prismatic Lens" - icon_icon = 'icons/obj/slimecrossing.dmi' + button_icon = 'icons/obj/slimecrossing.dmi' button_icon_state = "prismcolor" -/datum/action/item_action/change_prism_colour/Trigger() - if(!IsAvailable()) +/datum/action/item_action/change_prism_colour/do_effect(trigger_flags) + . = ..() + if(!.) return var/obj/item/clothing/glasses/prism_glasses/glasses = target + if(!istype(glasses)) + return FALSE var/new_color = input(owner, "Choose the lens color:", "Color change",glasses.glasses_color) as color|null if(!new_color) - return + return FALSE glasses.glasses_color = new_color + return TRUE /datum/action/item_action/place_light_prism name = "Fabricate Light Prism" - icon_icon = 'icons/obj/slimecrossing.dmi' + button_icon = 'icons/obj/slimecrossing.dmi' button_icon_state = "lightprism" -/datum/action/item_action/place_light_prism/Trigger() - if(!IsAvailable()) +/datum/action/item_action/place_light_prism/do_effect(trigger_flags) + . = ..() + if(!.) return var/obj/item/clothing/glasses/prism_glasses/glasses = target if(locate(/obj/structure/light_prism) in get_turf(owner)) - to_chat(owner, "There isn't enough ambient energy to fabricate another light prism here.") - return - if(istype(glasses)) - if(!glasses.glasses_color) - to_chat(owner, "The lens is oddly opaque...") - return - to_chat(owner, "You channel nearby light into a glowing, ethereal prism.") - new /obj/structure/light_prism(get_turf(owner), glasses.glasses_color) + to_chat(owner, span_warning("There isn't enough ambient energy to fabricate another light prism here.")) + return FALSE + if(!istype(glasses)) + return FALSE + if(!glasses.glasses_color) + to_chat(owner, span_warning("The lens is oddly opaque...")) + return FALSE + to_chat(owner, span_notice("You channel nearby light into a glowing, ethereal prism.")) + new /obj/structure/light_prism(get_turf(owner), glasses.glasses_color) + return TRUE /obj/item/clothing/head/peaceflower name = "heroine bud" @@ -122,7 +129,7 @@ Slimecrossing Armor if(iscarbon(user)) var/mob/living/carbon/C = user if(src == C.head) - to_chat(user, "You feel at peace. Why would you want anything else?") + to_chat(user, span_warning("You feel at peace. Why would you want anything else?")) return return ..() diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm index cc2df99785d5..d4ae79a0f363 100644 --- a/code/modules/research/xenobiology/crossbreeding/burning.dm +++ b/code/modules/research/xenobiology/crossbreeding/burning.dm @@ -394,7 +394,7 @@ Burning extracts: return var/path = S.type var/obj/item/slime_extract/C = new path(get_turf(target)) - C.Uses = S.Uses + C.extract_uses = S.extract_uses to_chat(user, "You pour the potion onto [target], and the fluid solidifies into a copy of it!") qdel(src) return diff --git a/code/modules/research/xenobiology/crossbreeding/recurring.dm b/code/modules/research/xenobiology/crossbreeding/recurring.dm index 43898018823a..6625c5bda0d7 100644 --- a/code/modules/research/xenobiology/crossbreeding/recurring.dm +++ b/code/modules/research/xenobiology/crossbreeding/recurring.dm @@ -29,10 +29,10 @@ Recurring extracts: /obj/item/slimecross/recurring/process() if(cooldown > 0) cooldown-- - else if(extract.Uses < 10 && extract.Uses > 0) - extract.Uses++ + else if(extract.extract_uses < 10 && extract.extract_uses > 0) + extract.extract_uses++ cooldown = max_cooldown - else if(extract.Uses <= 0) + else if(extract.extract_uses <= 0) extract.visible_message("The light inside [extract] flickers and dies out.") extract.desc = "A tiny, inert core, bleeding dark, cerulean-colored goo." extract.icon_state = "prismatic" diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index ee8975600080..90da0f205ad9 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -162,7 +162,7 @@ /datum/action/innate/slime_place name = "Place Slimes" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "slime_down" /datum/action/innate/slime_place/Activate() @@ -181,7 +181,7 @@ /datum/action/innate/slime_pick_up name = "Pick up Slime" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "slime_up" /datum/action/innate/slime_pick_up/Activate() @@ -206,7 +206,7 @@ /datum/action/innate/feed_slime name = "Feed Slimes" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "monkey_down" /datum/action/innate/feed_slime/Activate() @@ -230,7 +230,7 @@ /datum/action/innate/monkey_recycle name = "Recycle Monkeys" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "monkey_up" /datum/action/innate/monkey_recycle/Activate() @@ -250,7 +250,7 @@ /datum/action/innate/slime_scan name = "Scan Slime" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "slime_scan" /datum/action/innate/slime_scan/Activate() @@ -266,7 +266,7 @@ /datum/action/innate/feed_potion name = "Apply Potion" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "slime_potion" /datum/action/innate/feed_potion/Activate() @@ -321,7 +321,7 @@ /datum/action/innate/hotkey_help name = "Hotkey Help" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon = 'icons/mob/actions/actions_silicon.dmi' button_icon_state = "hotkey_help" /datum/action/innate/hotkey_help/Activate() diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index e81b55db00fb..32c87a529e7b 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -11,7 +11,7 @@ throw_speed = 3 throw_range = 6 grind_results = list() - var/Uses = 1 // uses before it goes inert + var/extract_uses = 1 // uses before it goes inert var/qdel_timer = null // deletion timer, for delayed reactions var/effectmod var/list/activate_reagents = list() //Reagents required for activation @@ -19,20 +19,20 @@ /obj/item/slime_extract/examine(mob/user) . = ..() - if(Uses > 1) - . += "It has [Uses] uses remaining." + if(extract_uses > 1) + . += "It has [extract_uses] uses remaining." /obj/item/slime_extract/attackby(obj/item/O, mob/user) if(istype(O, /obj/item/slimepotion/enhancer)) - if(Uses >= 5 || recurring) + if(extract_uses >= 5 || recurring) to_chat(user, "You cannot enhance this extract further!") return ..() if(O.type == /obj/item/slimepotion/enhancer) //Seriously, why is this defined here...? to_chat(user, "You apply the enhancer to the slime extract. It may now be reused one more time.") - Uses++ + extract_uses++ if(O.type == /obj/item/slimepotion/enhancer/max) to_chat(user, "You dump the maximizer on the slime extract. It can now be used a total of 5 times!") - Uses = 5 + extract_uses = 5 qdel(O) ..() @@ -41,7 +41,7 @@ create_reagents(100, INJECTABLE | DRAWABLE) /obj/item/slime_extract/on_grind() - if(Uses) + if(extract_uses) grind_results[/datum/reagent/toxin/slimejelly] = 20 //Effect when activated by a Luminescent. Separated into a minor and major effect. Returns cooldown in deciseconds. diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm index 84ceb3ae01ca..cdd7444917f5 100644 --- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm @@ -317,12 +317,15 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) desc = "Stop looking through the bluespace peephole." button_icon_state = "cancel_peephole" -/datum/action/peepholeCancel/Trigger() +/datum/action/peepholeCancel/Trigger(trigger_flags) . = ..() + if(!.) + return FALSE to_chat(owner, "You move away from the peephole.") owner.reset_perspective() owner.clear_fullscreen("remote_view", 0) qdel(src) + return TRUE /area/hilbertshotel name = "Hilbert's Hotel Room" diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm index 6a290c3c844c..9335b24f0183 100644 --- a/code/modules/shuttle/navigation_computer.dm +++ b/code/modules/shuttle/navigation_computer.dm @@ -320,7 +320,7 @@ /datum/action/innate/shuttledocker_rotate name = "Rotate" - icon_icon = 'icons/mob/actions/actions_mecha.dmi' + button_icon = 'icons/mob/actions/actions_mecha.dmi' button_icon_state = "mech_cycle_equip_off" /datum/action/innate/shuttledocker_rotate/Activate() @@ -332,7 +332,7 @@ /datum/action/innate/shuttledocker_place name = "Place" - icon_icon = 'icons/mob/actions/actions_mecha.dmi' + button_icon = 'icons/mob/actions/actions_mecha.dmi' button_icon_state = "mech_zoom_off" /datum/action/innate/shuttledocker_place/Activate() diff --git a/code/modules/shuttle/shuttle_creation/shuttle_creator_actions.dm b/code/modules/shuttle/shuttle_creation/shuttle_creator_actions.dm index 486e45d25019..a1049c19244c 100644 --- a/code/modules/shuttle/shuttle_creation/shuttle_creator_actions.dm +++ b/code/modules/shuttle/shuttle_creation/shuttle_creator_actions.dm @@ -1,6 +1,6 @@ //============ Actions ============ /datum/action/innate/shuttle_creator - icon_icon = 'icons/mob/actions/actions_shuttle.dmi' + button_icon = 'icons/mob/actions/actions_shuttle.dmi' var/mob/camera/aiEye/remote/shuttle_creation/remote_eye var/obj/item/shuttle_creator/shuttle_creator diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index 28cb9ac36c8c..c90a471852a4 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -165,19 +165,19 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th if("holdervar") adjust_var(user, holder_var_type, holder_var_amount) if(action) - action.UpdateButtons() + action.build_all_button_icons() return TRUE -/obj/effect/proc_holder/spell/proc/charge_check(mob/user, silent = FALSE) +/obj/effect/proc_holder/spell/proc/charge_check(mob/user, feedback = TRUE) switch(charge_type) if("recharge") if(charge_counter < charge_max) - if(!silent) + if(feedback) to_chat(user, still_recharging_msg) return FALSE if("charges") if(!charge_counter) - if(!silent) + if(feedback) to_chat(user, "[name] has no charges left.") return FALSE return TRUE @@ -243,7 +243,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th if(recharging && charge_type == "recharge" && (charge_counter < charge_max)) charge_counter += 2 //processes 5 times per second instead of 10. if(charge_counter >= charge_max) - action.UpdateButtons() + action.build_all_button_icons() charge_counter = charge_max recharging = FALSE @@ -259,7 +259,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th cast(targets,user=user) after_cast(targets) if(action) - action.UpdateButtons() + action.build_all_button_icons() /obj/effect/proc_holder/spell/proc/before_cast(list/targets) if(overlay) @@ -321,7 +321,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th if("holdervar") adjust_var(user, holder_var_type, -holder_var_amount) if(action) - action.UpdateButtons() + action.build_all_button_icons() /obj/effect/proc_holder/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types if (!istype(target)) @@ -439,7 +439,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th perform(targets,user=user) /obj/effect/proc_holder/spell/proc/UpdateButton(atom/movable/screen/movable/action_button/button, status_only, force) - action.UpdateButtons(status_only, force) + action.build_all_button_icons(status_only, force) /obj/effect/proc_holder/spell/targeted/proc/los_check(mob/A,mob/B) //Checks for obstacles from A to B @@ -453,40 +453,40 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th qdel(dummy) return TRUE -/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr, skipcharge = FALSE, silent = FALSE) +/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr, skipcharge = FALSE, feedback = TRUE) var/magic_flags = SEND_SIGNAL(user, COMSIG_MOB_SPELL_CAN_CAST, src) if(magic_flags & SPELL_SKIP_ALL_REQS) return TRUE if(player_lock ? (!user.mind || !(src in user.mind.spell_list) && !(src in user.mob_spell_list)) : !(src in user.mob_spell_list)) - if(!silent) + if(feedback) to_chat(user, "You shouldn't have this spell! Something's wrong.") return FALSE if(!centcom_cancast && !(magic_flags & SPELL_SKIP_CENTCOM)) //Certain spells are not allowed on the centcom zlevel var/turf/T = get_turf(user) if(is_centcom_level(T.z)) - if(!silent) + if(feedback) to_chat(user, "You can't cast this spell here.") return FALSE - if(!skipcharge && !charge_check(user, silent)) + if(!skipcharge && !charge_check(user, feedback)) return FALSE if(user.stat && !stat_allowed && !(magic_flags & SPELL_SKIP_STAT)) - if(!silent) + if(feedback) to_chat(user, "Not when you're incapacitated.") return FALSE if(!phase_allowed && istype(user.loc, /obj/effect/dummy)) - if(!silent) + if(feedback) to_chat(user, "[name] cannot be cast unless you are completely manifested in the material plane.") return FALSE if(clothes_req && !(magic_flags & SPELL_SKIP_CLOTHES)) var/met_requirements = magic_flags & (clothes_req) if(met_requirements != clothes_req) - if(!silent) + if(feedback) var/the_many_hats = met_requirements & (clothes_req & (SPELL_WIZARD_HAT|SPELL_CULT_HELMET)) var/the_many_suits = met_requirements & (clothes_req & (SPELL_WIZARD_ROBE|SPELL_CULT_ARMOR)) var/without_hat_robe = the_many_suits ? "a proper headwear" : the_many_hats ? "a proper suit" : "proper garments" @@ -500,12 +500,12 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th if(!(magic_flags & SPELL_SKIP_VOCAL) && (invocation_type in list("whisper", "shout")) && isliving(user)) var/mob/living/L = user if(!L.can_speak_vocal()) - if(!silent) + if(feedback) to_chat(L, "You can't get the words out!") return FALSE if(!(magic_flags & SPELL_SKIP_MOBTYPE) && ((mobs_whitelist && !mobs_whitelist[user.type]) || (mobs_blacklist && mobs_blacklist[user.type]))) - if(!silent) + if(feedback) to_chat(user, "This spell can't be casted in this current form!") return FALSE return TRUE diff --git a/code/modules/spells/spell_types/aimed.dm b/code/modules/spells/spell_types/aimed.dm index 9e68862ff416..61d0ca043a93 100644 --- a/code/modules/spells/spell_types/aimed.dm +++ b/code/modules/spells/spell_types/aimed.dm @@ -44,7 +44,7 @@ if(!action) return action.button_icon_state = "[base_icon_state][active]" - action.UpdateButtons() + action.build_all_button_icons() /obj/effect/proc_holder/spell/aimed/InterceptClickOn(mob/living/caller, params, atom/target) if(..()) diff --git a/code/modules/spells/spell_types/cluwnecurse.dm b/code/modules/spells/spell_types/cluwnecurse.dm index 2da87b9e5055..86f2c3502723 100644 --- a/code/modules/spells/spell_types/cluwnecurse.dm +++ b/code/modules/spells/spell_types/cluwnecurse.dm @@ -33,4 +33,4 @@ /datum/action/spell_action/New(Target) ..() var/obj/effect/proc_holder/spell/S = Target - icon_icon = S.action_icon + button_icon = S.action_icon diff --git a/code/modules/spells/spell_types/pointed/pointed.dm b/code/modules/spells/spell_types/pointed/pointed.dm index f69cbfca7050..bc667b773ebe 100644 --- a/code/modules/spells/spell_types/pointed/pointed.dm +++ b/code/modules/spells/spell_types/pointed/pointed.dm @@ -64,7 +64,7 @@ action.button_icon_state = "[action_icon_state]1" else action.button_icon_state = "[action_icon_state]" - action.UpdateButtons() + action.build_all_button_icons() /obj/effect/proc_holder/spell/pointed/InterceptClickOn(mob/living/caller, params, atom/target) if(..()) diff --git a/code/modules/spells/spell_types/taeclowndo.dm b/code/modules/spells/spell_types/taeclowndo.dm index 701392775591..318920ca5530 100644 --- a/code/modules/spells/spell_types/taeclowndo.dm +++ b/code/modules/spells/spell_types/taeclowndo.dm @@ -55,7 +55,7 @@ else action.button_icon_state = action_icon_state - action.UpdateButtons() + action.build_all_button_icons() ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /obj/effect/proc_holder/spell/targeted/touch/megahonk diff --git a/code/modules/spells/spell_types/touch_attacks.dm b/code/modules/spells/spell_types/touch_attacks.dm index 4f0ac2964f70..84091f26da40 100644 --- a/code/modules/spells/spell_types/touch_attacks.dm +++ b/code/modules/spells/spell_types/touch_attacks.dm @@ -18,7 +18,7 @@ //Start recharging. attached_hand = null recharging = TRUE - action.UpdateButtons() + action.build_all_button_icons() /obj/effect/proc_holder/spell/targeted/touch/cast(list/targets,mob/user = usr) if(!QDELETED(attached_hand)) diff --git a/code/modules/spells/spell_types/voice_of_god.dm b/code/modules/spells/spell_types/voice_of_god.dm index fa41b59c0d17..390c011cf7cb 100644 --- a/code/modules/spells/spell_types/voice_of_god.dm +++ b/code/modules/spells/spell_types/voice_of_god.dm @@ -14,10 +14,10 @@ var/list/spans = list("colossus","yell") var/speech_sound = 'sound/magic/clockwork/invoke_general.ogg' -/obj/effect/proc_holder/spell/voice_of_god/can_cast(mob/user = usr, skipcharge = FALSE, silent = TRUE) +/obj/effect/proc_holder/spell/voice_of_god/can_cast(mob/user = usr, skipcharge = FALSE, feedback = TRUE) if(!user.can_speak()) - if(!silent) - to_chat(user, "You are unable to speak!") + if(feedback) + to_chat(user, span_warning("You are unable to speak!")) return FALSE return TRUE diff --git a/code/modules/surgery/dental_implant.dm b/code/modules/surgery/dental_implant.dm index b5461da25adc..1f02f8880661 100644 --- a/code/modules/surgery/dental_implant.dm +++ b/code/modules/surgery/dental_implant.dm @@ -18,9 +18,9 @@ user.transferItemToLoc(tool, target, TRUE) - var/datum/action/item_action/hands_free/activate_pill/pill_action = new(tool) + var/datum/action/item_action/hands_free/activate_pill/pill_action = tool.add_item_action(/datum/action/item_action/hands_free/activate_pill) pill_action.name = "Activate [tool.name]" - pill_action.UpdateButtons() + pill_action.build_all_button_icons() pill_action.target = tool pill_action.Grant(target) //The pill never actually goes in an inventory slot, so the owner doesn't inherit actions from it @@ -30,10 +30,13 @@ /datum/action/item_action/hands_free/activate_pill name = "Activate Pill" -/datum/action/item_action/hands_free/activate_pill/Trigger() - if(!..()) - return FALSE +/datum/action/item_action/hands_free/activate_pill/do_effect(trigger_flags) + . = ..() + if(!.) + return var/obj/item/item_target = target + if(!istype(item_target)) + return FALSE to_chat(owner, span_notice("You grit your teeth and burst the implanted [item_target.name]!")) log_combat(owner, null, "swallowed an implanted pill", target) if(item_target.reagents.total_volume) diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index d7ae2b73e462..bf865b27dc35 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -8,10 +8,10 @@ healing_factor = STANDARD_ORGAN_HEALING decay_factor = 2 * STANDARD_ORGAN_DECAY - low_threshold_passed = "Prickles of pain appear then die out from within your chest..." - high_threshold_passed = "Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before." - now_fixed = "Your heart begins to beat again." - high_threshold_cleared = "The pain in your chest has died down, and your breathing becomes more relaxed." + low_threshold_passed = span_info("Prickles of pain appear then die out from within your chest...") + high_threshold_passed = span_warning("Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before.") + now_fixed = span_info("Your heart begins to beat again.") + high_threshold_cleared = span_info("The pain in your chest has died down, and your breathing becomes more relaxed.") // Heart attack code is in code/modules/mob/living/carbon/human/life.dm var/beating = 1 @@ -41,8 +41,8 @@ /obj/item/organ/heart/attack_self(mob/user) ..() if(!beating) - user.visible_message("[user] squeezes [src] to \ - make it beat again!","You squeeze [src] to make it beat again!") + user.visible_message(span_notice("[user] squeezes [src] to make it beat again!"), + span_notice("You squeeze [src] to make it beat again!")) Restart() addtimer(CALLBACK(src, PROC_REF(stop_if_unowned)), 80) @@ -59,7 +59,7 @@ /obj/item/organ/heart/proc/HeartStrengthMessage() if(beating) return "a healthy" - return "an unstable" + return span_danger("an unstable") /obj/item/organ/heart/OnEatFrom(eater, feeder) . = ..() @@ -93,7 +93,7 @@ if(organ_flags & ORGAN_FAILING) //heart broke, stopped beating, death imminent if(owner.stat == CONSCIOUS) - owner.visible_message("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!") + owner.visible_message(span_userdanger("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!")) owner.set_heartattack(TRUE) failed = TRUE @@ -162,34 +162,39 @@ return ..() /datum/action/item_action/organ_action/cursed_heart - check_flags = AB_CHECK_ALIVE //We wanna be able to do this always, else thisll just stupidly kill whoever has it + check_flags = AB_CHECK_CONSCIOUS //We wanna be able to do this always, else thisll just stupidly kill whoever has it required_mobility_flags = NONE name = "Pump your blood" //You are now brea- pumping blood manually -/datum/action/item_action/organ_action/cursed_heart/Trigger() +/datum/action/item_action/organ_action/cursed_heart/do_effect(trigger_flags) . = ..() - if(. && istype(target, /obj/item/organ/heart/cursed)) - var/obj/item/organ/heart/cursed/cursed_heart = target - - if(world.time < (cursed_heart.last_pump + (cursed_heart.pump_delay-10))) //no spam - to_chat(owner, "Too soon!") - return - - cursed_heart.last_pump = world.time - playsound(owner,'sound/effects/singlebeat.ogg',40,1) - to_chat(owner, "Your heart beats.") - - var/mob/living/carbon/human/H = owner - if(istype(H)) - if(H.dna && !(NOBLOOD in H.dna.species.species_traits)) - if(H.blood_volume < BLOOD_VOLUME_NORMAL) //We don't need to go too high, otherwise we get annoying messages. - H.blood_volume = min(H.blood_volume + cursed_heart.blood_loss * 0.5, BLOOD_VOLUME_MAXIMUM) - H.remove_client_colour(/datum/client_colour/cursed_heart_blood) - cursed_heart.add_colour = TRUE - H.adjustBruteLoss(-cursed_heart.heal_brute) - H.adjustFireLoss(-cursed_heart.heal_burn) - H.adjustOxyLoss(-cursed_heart.heal_oxy) + if(!.) + return + var/obj/item/organ/heart/cursed/cursed_heart = target + if(!istype(cursed_heart)) + return FALSE + + if(world.time < (cursed_heart.last_pump + (cursed_heart.pump_delay-10))) //no spam + to_chat(owner, span_userdanger("Too soon!")) + return FALSE + + cursed_heart.last_pump = world.time + playsound(owner,'sound/effects/singlebeat.ogg',40,1) + to_chat(owner, span_notice("Your heart beats.")) + + var/mob/living/carbon/human/H = owner + if(!istype(H)) + return FALSE + if(H.dna && !(NOBLOOD in H.dna.species.species_traits)) + if(H.blood_volume < BLOOD_VOLUME_NORMAL) //We don't need to go too high, otherwise we get annoying messages. + H.blood_volume = min(H.blood_volume + cursed_heart.blood_loss * 0.5, BLOOD_VOLUME_MAXIMUM) + H.remove_client_colour(/datum/client_colour/cursed_heart_blood) + cursed_heart.add_colour = TRUE + H.adjustBruteLoss(-cursed_heart.heal_brute) + H.adjustFireLoss(-cursed_heart.heal_burn) + H.adjustOxyLoss(-cursed_heart.heal_oxy) + return TRUE /datum/client_colour/cursed_heart_blood @@ -242,8 +247,8 @@ if(prob(severity/emp_vulnerability)) //Chance of permanent effects organ_flags |= ORGAN_SYNTHETIC_EMP //Starts organ faliure - gonna need replacing soon. Stop() - owner.visible_message("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!", \ - "You feel a terrible pain in your chest, as if your heart has stopped!") + owner.visible_message(span_danger("[owner] clutches at [owner.p_their()] chest as if [owner.p_their()] heart is stopping!"), \ + span_userdanger("You feel a terrible pain in your chest, as if your heart has stopped!")) addtimer(CALLBACK(src, PROC_REF(Restart)), 10 SECONDS) /obj/item/organ/heart/cybernetic/on_life(delta_time, times_fired) @@ -274,7 +279,7 @@ . = ..() if(. && owner.health < 5 && world.time > min_next_adrenaline) min_next_adrenaline = world.time + rand(250, 600) //anywhere from 4.5 to 10 minutes - to_chat(owner, "You feel yourself dying, but you refuse to give up!") + to_chat(owner, span_userdanger("You feel yourself dying, but you refuse to give up!")) owner.heal_overall_damage(15, 15) if(owner.reagents.get_reagent_amount(/datum/reagent/medicine/ephedrine) < 20) owner.reagents.add_reagent(/datum/reagent/medicine/ephedrine, 10) diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 7cb8ce9538a5..554c4c6792a7 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -43,16 +43,18 @@ icon_state = "adamantine_cords" decay_factor = 0 -/datum/action/item_action/organ_action/use/adamantine_vocal_cords/Trigger() - if(!IsAvailable()) +/datum/action/item_action/organ_action/use/adamantine_vocal_cords/do_effect(trigger_flags) + . = ..() + if(!.) return var/message = input(owner, "Resonate a message to all nearby golems.", "Resonate") if(QDELETED(src) || QDELETED(owner) || !message) - return + return FALSE owner.say(".x[message]") + return TRUE /obj/item/organ/vocal_cords/adamantine/handle_speech(message) - var/msg = "[owner.real_name] resonates, \"[message]\"" + var/msg = span_resonate("[span_name(owner.real_name)] resonates, \"[message]\"") for(var/m in GLOB.player_list) if(iscarbon(m)) var/mob/living/carbon/C = m @@ -82,8 +84,10 @@ ..() cords = target -/datum/action/item_action/organ_action/colossus/IsAvailable(silent = FALSE) +/datum/action/item_action/organ_action/colossus/IsAvailable(feedback) if(world.time < cords.next_command) + if(feedback) + to_chat(owner, span_notice("You must wait [DisplayTimeText(cords.next_command - world.time)] before Speaking again.")) return FALSE if(!owner) return FALSE @@ -94,27 +98,26 @@ return FALSE return TRUE -/datum/action/item_action/organ_action/colossus/Trigger() +/datum/action/item_action/organ_action/colossus/do_effect(trigger_flags) . = ..() - if(!IsAvailable()) - if(world.time < cords.next_command) - to_chat(owner, "You must wait [DisplayTimeText(cords.next_command - world.time)] before Speaking again.") + if(!.) return var/command = input(owner, "Speak with the Voice of God", "Command") if(QDELETED(src) || QDELETED(owner)) - return + return FALSE if(!command) - return + return FALSE owner.say(".x[command]") + return TRUE /obj/item/organ/vocal_cords/colossus/can_speak_with() if(world.time < next_command) - to_chat(owner, "You must wait [DisplayTimeText(next_command - world.time)] before Speaking again.") + to_chat(owner, span_notice("You must wait [DisplayTimeText(next_command - world.time)] before Speaking again.")) return FALSE if(!owner) return FALSE if(!owner.can_speak()) - to_chat(owner, "You are unable to speak!") + to_chat(owner, span_warning("You are unable to speak!")) return FALSE return TRUE @@ -639,17 +642,20 @@ ..() cords = target -/datum/action/item_action/organ_action/velvet/IsAvailable(silent = FALSE) +/datum/action/item_action/organ_action/velvet/IsAvailable(feedback = TRUE) return TRUE -/datum/action/item_action/organ_action/velvet/Trigger() +/datum/action/item_action/organ_action/velvet/do_effect(trigger_flags) . = ..() + if(!.) + return var/command = input(owner, "Speak in a sultry tone", "Command") if(QDELETED(src) || QDELETED(owner)) - return + return FALSE if(!command) - return + return FALSE owner.say(".x[command]") + return TRUE /obj/item/organ/vocal_cords/velvet/can_speak_with() return TRUE @@ -814,7 +820,7 @@ else E.enthrallTally += power_multiplier*1.25 //thinking about it, I don't know how this can proc if(E.lewd) - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "[E.enthrallGender] is so nice to listen to."), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_nicegreen("[E.enthrallGender] is so nice to listen to.")), 5) E.cooldown += 1 //REWARD mixable works @@ -826,16 +832,16 @@ if(L == user) continue if (E.lewd) - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "[E.enthrallGender] has praised me!!"), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_love("[E.enthrallGender] has praised me!!")), 5) if(HAS_TRAIT(L, TRAIT_MASO)) E.enthrallTally -= power_multiplier E.resistanceTally += power_multiplier E.cooldown += 1 else - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "I've been praised for doing a good job!"), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_nicegreen("I've been praised for doing a good job!")), 5) E.resistanceTally -= power_multiplier E.enthrallTally += power_multiplier - var/descmessage = "[(E.lewd?"I feel so happy! I'm a good pet who [E.enthrallGender] loves!":"I did a good job!")]" + var/descmessage = span_love("[(E.lewd?"I feel so happy! I'm a good pet who [E.enthrallGender] loves!":"I did a good job!")]") SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "enthrallpraise", /datum/mood_event/enthrallpraise, descmessage) E.cooldown += 1 @@ -855,11 +861,11 @@ descmessage += "And yet, it feels so good..!" //I don't really understand masco, is this the right sort of thing they like? E.enthrallTally += power_multiplier E.resistanceTally -= power_multiplier - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "I've let [E.enthrallGender] down...!"), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_love("I've let [E.enthrallGender] down...!")), 5) else - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "I've let [E.enthrallGender] down..."), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_warning("I've let [E.enthrallGender] down...")), 5) else - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "I've failed [E.master]..."), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_warning("I've failed [E.master]...")), 5) E.resistanceTally += power_multiplier E.enthrallTally += power_multiplier E.cooldown += 1 @@ -896,7 +902,7 @@ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "The snapping of your [E.enthrallGender]'s fingers brings you back to your enthralled state, obedient and ready to serve."), 5) else addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "The snapping of [E.master]'s fingers brings you back to being under their influence."), 5) - to_chat(user, "You wake up [L]!") + to_chat(user, span_notice("You wake up [L]!")) //tier 1 @@ -1028,8 +1034,8 @@ ADD_TRAIT(C, TRAIT_MUTE, "enthrall") else C.silent += ((10 * power_multiplier) * E.phase) - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, "You are unable to speak!"), 5) - to_chat(user, "You silence [C].") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, span_notice("You are unable to speak!")), 5) + to_chat(user, span_notice("You silence [C].")) E.cooldown += 3 //SPEAK @@ -1039,7 +1045,7 @@ REMOVE_TRAIT(C, TRAIT_MUTE, "enthrall") C.silent = 0 E.cooldown += 3 - to_chat(user, "You [(E.lewd?"allow [C] to speak again":"encourage [C] to speak again")].") + to_chat(user, span_notice("You [(E.lewd?"allow [C] to speak again":"encourage [C] to speak again")].")) //Antiresist @@ -1051,7 +1057,7 @@ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "Your mind clouds over, as you find yourself unable to resist!"), 5) E.statusStrength = (1 * power_multiplier * E.phase) E.cooldown += 15//Too short? yes, made 15 - to_chat(user, "You frustrate [L]'s attempts at resisting.") + to_chat(user, span_notice("You frustrate [L]'s attempts at resisting.")) //RESIST else if((findtext(message, resist_words))) @@ -1061,23 +1067,23 @@ E.deltaResist += (power_multiplier) E.owner_resist() E.cooldown += 2 - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, "You are spurred into resisting from [user]'s words!'"), 5) - to_chat(user, "You spark resistance in [C].") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, span_notice("You are spurred into resisting from [user]'s words!'")), 5) + to_chat(user, span_notice("You spark resistance in [C].")) //FORGET (A way to cancel the process) else if((findtext(message, forget_words))) for(var/mob/living/carbon/C in listeners) var/datum/status_effect/chem/enthrall/E = C.has_status_effect(/datum/status_effect/chem/enthrall) if(E.phase == 4) - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, "You're unable to forget about [(E.lewd?"the dominating presence of [E.enthrallGender]":"[E.master]")]!"), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, span_warning("You're unable to forget about [(E.lewd?"the dominating presence of [E.enthrallGender]":"[E.master]")]!")), 5) continue - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, "You wake up, forgetting everything that just happened. You must've dozed off..? How embarassing!"), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, span_warning("You wake up, forgetting everything that just happened. You must've dozed off..? How embarassing!")), 5) C.Sleeping(50) switch(E.phase) if(1 to 2) E.phase = -1 to_chat(C, "You have no recollection of being enthralled by [E.master]!") - to_chat(user, "You revert [C] back to their state before enthrallment.") + to_chat(user, span_notice("You revert [C] back to their state before enthrallment.")) if(3) E.phase = 0 E.cooldown = 0 @@ -1085,7 +1091,7 @@ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, "You revert to yourself before being enthralled by your [E.enthrallGender], with no memory of what happened."), 5) else addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, "You revert to who you were before, with no memory of what happened with [E.master]."), 5) - to_chat(user, "You put [C] into a sleeper state, ready to turn them back at the snap of your fingers.") + to_chat(user, span_notice("You put [C] into a sleeper state, ready to turn them back at the snap of your fingers.")) //ATTRACT else if((findtext(message, attract_words))) @@ -1094,8 +1100,8 @@ var/datum/status_effect/chem/enthrall/E = L.has_status_effect(/datum/status_effect/chem/enthrall) L.throw_at(get_step_towards(user,L), 3 * power_multiplier, 1 * power_multiplier) E.cooldown += 3 - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "You are drawn towards [user]!"), 5) - to_chat(user, "You draw [L] towards you!") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_notice("You are drawn towards [user]!")), 5) + to_chat(user, span_notice("You draw [L] towards you!")) //awoo else if((findtext(message, awoo_words))) @@ -1142,8 +1148,8 @@ if(L.m_intent != MOVE_INTENT_WALK) L.toggle_move_intent() E.cooldown += 1 - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "You slow down to a walk."), 5) - to_chat(user, "You encourage [L] to slow down.") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_notice("You slow down to a walk.")), 5) + to_chat(user, span_notice("You encourage [L] to slow down.")) //RUN else if((findtext(message, run_words))) @@ -1155,8 +1161,8 @@ if(L.m_intent != MOVE_INTENT_RUN) L.toggle_move_intent() E.cooldown += 1 - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "You speed up into a jog!"), 5) - to_chat(user, "You encourage [L] to pick up the pace!") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_notice("You speed up into a jog!")), 5) + to_chat(user, span_notice("You encourage [L] to pick up the pace!")) //LIE DOWN else if(findtext(message, liedown_words)) @@ -1168,7 +1174,7 @@ L.lay_down() E.cooldown += 10 addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "[(E.lewd?"You eagerly lie down!":"You suddenly lie down!")]"), 5) - to_chat(user, "You encourage [L] to lie down.") + to_chat(user, span_notice("You encourage [L] to lie down.")) //KNOCKDOWN else if(findtext(message, knockdown_words)) @@ -1179,8 +1185,8 @@ if(2 to INFINITY) L.DefaultCombatKnockdown(30 * power_multiplier * E.phase) E.cooldown += 8 - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "You suddenly drop to the ground!"), 5) - to_chat(user, "You encourage [L] to drop down to the ground.") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_notice("You suddenly drop to the ground!")), 5) + to_chat(user, span_notice("You encourage [L] to drop down to the ground.")) //tier3 @@ -1193,12 +1199,12 @@ var/speaktrigger = "" C.emote("me", EMOTE_VISIBLE, "whispers something quietly.") if (get_dist(user, C) > 1)//Requires user to be next to their pet. - to_chat(user, "You need to be next to your pet to hear them!") + to_chat(user, span_warning("You need to be next to your pet to hear them!")) continue for (var/trigger in E.customTriggers) speaktrigger += "[trigger], " to_chat(user, "[C] whispers, \"[speaktrigger] are my triggers.\"")//So they don't trigger themselves! - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, "You whisper your triggers to [(E.lewd?"Your [E.enthrallGender]":"[E.master]")]."), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), C, span_notice("You whisper your triggers to [(E.lewd?"Your [E.enthrallGender]":"[E.master]")].")), 5) //CUSTOM TRIGGERS @@ -1208,10 +1214,10 @@ var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall) if(E.phase == 3) if (get_dist(user, H) > 1)//Requires user to be next to their pet. - to_chat(user, "You need to be next to your pet to give them a new trigger!") + to_chat(user, span_warning("You need to be next to your pet to give them a new trigger!")) continue if(!E.lewd) - to_chat(user, "[H] seems incapable of being implanted with triggers.") + to_chat(user, span_warning("[H] seems incapable of being implanted with triggers.")) continue else user.emote("me", EMOTE_VISIBLE, "puts their hands upon [H.name]'s head and looks deep into their eyes, whispering something to them.") @@ -1233,12 +1239,12 @@ E.customTriggers[trigger] = trigger2 log_reagent("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2].") E.mental_capacity -= 5 - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), H, "[(E.lewd?"your [E.enthrallGender]":"[E.master]")] whispers you a new trigger."), 5) - to_chat(user, "You sucessfully set the trigger word [trigger] in [H]") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), H, span_notice("[(E.lewd?"your [E.enthrallGender]":"[E.master]")] whispers you a new trigger.")), 5) + to_chat(user, span_notice("You sucessfully set the trigger word [trigger] in [H]")) else - to_chat(user, "Your pet looks at you confused, it seems they don't understand that effect!") + to_chat(user, span_warning("Your pet looks at you confused, it seems they don't understand that effect!")) else - to_chat(user, "Your pet looks at you with a vacant blase expression, you don't think you can program anything else into them") + to_chat(user, span_warning("Your pet looks at you with a vacant blase expression, you don't think you can program anything else into them")) user.SetStun(0) H.SetStun(0) @@ -1249,10 +1255,10 @@ var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall) if(E.phase == 3) if (get_dist(user, H) > 1)//Requires user to be next to their pet. - to_chat(user, "You need to be next to your pet to give them a new echophrase!") + to_chat(user, span_warning("You need to be next to your pet to give them a new echophrase!")) continue if(!E.lewd) - to_chat(user, "[H] seems incapable of being implanted with an echoing phrase.") + to_chat(user, span_warning("[H] seems incapable of being implanted with an echoing phrase.")) continue else user.emote("me", EMOTE_VISIBLE, "puts their hands upon [H.name]'s head and looks deep into their eyes, whispering something to them.") @@ -1266,7 +1272,7 @@ E.customSpan = trigger2 user.SetStun(0) H.SetStun(0) - to_chat(user, "You sucessfully set an echoing phrase in [H]") + to_chat(user, span_notice("You sucessfully set an echoing phrase in [H]")) //CUSTOM OBJECTIVE else if((findtext(message, objective_words))) @@ -1275,7 +1281,7 @@ var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall) if(E.phase == 3) if (get_dist(user, H) > 1)//Requires user to be next to their pet. - to_chat(user, "You need to be next to your pet to give them a new objective!") + to_chat(user, span_warning("You need to be next to your pet to give them a new objective!")) continue else user.emote("me", EMOTE_VISIBLE, "puts their hands upon [H.name]'s head and looks deep into their eyes, whispering something to them.'") @@ -1284,7 +1290,7 @@ if (E.mental_capacity >= 200) var/datum/objective/brainwashing/objective = stripped_input(user, "Add an objective to give your pet.", MAX_MESSAGE_LEN) if(!LAZYLEN(objective)) - to_chat(user, "You can't give your pet an objective to do nothing!") + to_chat(user, span_warning("You can't give your pet an objective to do nothing!")) continue //Pets don't understand harm objective = replacetext(lowertext(objective), "kill", "hug") @@ -1295,12 +1301,12 @@ objective = replacetext(lowertext(objective), "suicide", "self-love") message_admins("[H] has been implanted by [user] with the objective [objective].") log_reagent("FERMICHEM: [H] has been implanted by [user] with the objective [objective] via MKUltra.") - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), H, "[(E.lewd?"Your [E.enthrallGender]":"[E.master]")] whispers you a new objective."), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), H, span_notice("[(E.lewd?"Your [E.enthrallGender]":"[E.master]")] whispers you a new objective.")), 5) brainwash(H, objective) E.mental_capacity -= 200 - to_chat(user, "You sucessfully give an objective to [H]") + to_chat(user, span_notice("You sucessfully give an objective to [H]")) else - to_chat(user, "Your pet looks at you with a vacant blasé expression, you don't think you can program anything else into them") + to_chat(user, span_warning("Your pet looks at you with a vacant blasé expression, you don't think you can program anything else into them")) user.SetStun(0) H.SetStun(0) @@ -1312,7 +1318,7 @@ if(E.phase >= 3 && E.lewd) var/instill = stripped_input(user, "Instill an emotion in [H].", MAX_MESSAGE_LEN) to_chat(H, "[instill]") - to_chat(user, "You sucessfully instill a feeling in [H]") + to_chat(user, span_notice("You sucessfully instill a feeling in [H]")) log_reagent("FERMICHEM: [H] has been instilled by [user] with [instill] via MKUltra.") E.cooldown += 1 @@ -1324,8 +1330,8 @@ if(E.phase > 1) if(user.ckey == E.enthrallID && user.real_name == E.master.real_name) E.master = user - to_chat(H, "[(E.lewd?"You hear the words of your [E.enthrallGender] again!! They're back!!":"You recognise the voice of [E.master].")]") - to_chat(user, "[H] looks at you with sparkling eyes, recognising you!") + to_chat(H, span_nicegreen("[(E.lewd?"You hear the words of your [E.enthrallGender] again!! They're back!!":"You recognise the voice of [E.master].")]")) + to_chat(user, span_notice("[H] looks at you with sparkling eyes, recognising you!")) //I dunno how to do state objectives without them revealing they're an antag @@ -1339,9 +1345,9 @@ E.status = "heal" E.statusStrength = (5 * power_multiplier) E.cooldown += 5 - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "You begin to lick your wounds."), 5) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_notice("You begin to lick your wounds.")), 5) L.Stun(15 * power_multiplier) - to_chat(user, "[L] begins to lick their wounds.") + to_chat(user, span_notice("[L] begins to lick their wounds.")) //STUN else if(findtext(message, stun_words)) @@ -1352,8 +1358,8 @@ if(3 to INFINITY) L.Stun(40 * power_multiplier) E.cooldown += 8 - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "Your muscles freeze up!"), 5) - to_chat(user, "You cause [L] to freeze up!") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_notice("Your muscles freeze up!")), 5) + to_chat(user, span_notice("You cause [L] to freeze up!")) //HALLUCINATE else if(findtext(message, hallucinate_words)) @@ -1363,7 +1369,7 @@ switch(E.phase) if(3 to INFINITY) new /datum/hallucination/delusion(C, TRUE, null,150 * power_multiplier,0) - to_chat(user, "You send [C] on a trip.") + to_chat(user, span_notice("You send [C] on a trip.")) //HOT else if(findtext(message, hot_words)) @@ -1373,8 +1379,8 @@ switch(E.phase) if(3 to INFINITY) L.adjust_bodytemperature(50 * power_multiplier)//This seems nuts, reduced it, but then it didn't do anything, so I reverted it. - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "You feel your metabolism speed up!"), 5) - to_chat(user, "You speed [L]'s metabolism up!") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_notice("You feel your metabolism speed up!")), 5) + to_chat(user, span_notice("You speed [L]'s metabolism up!")) //COLD else if(findtext(message, cold_words)) @@ -1384,8 +1390,8 @@ switch(E.phase) if(3 to INFINITY) L.adjust_bodytemperature(-50 * power_multiplier) - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "You feel your metabolism slow down!"), 5) - to_chat(user, "You slow [L]'s metabolism down!") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_notice("You feel your metabolism slow down!")), 5) + to_chat(user, span_notice("You slow [L]'s metabolism down!")) //GET UP else if(findtext(message, getup_words)) @@ -1398,8 +1404,8 @@ L.SetAllImmobility(0) L.SetUnconscious(0) //i said get up i don't care if you're being tased E.cooldown += 10 //This could be really strong - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "You jump to your feet from sheer willpower!"), 5) - to_chat(user, "You spur [L] to their feet!") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_notice("You jump to your feet from sheer willpower!")), 5) + to_chat(user, span_notice("You spur [L] to their feet!")) //PACIFY else if(findtext(message, pacify_words)) @@ -1410,8 +1416,8 @@ if(3)//Tier 3 only E.status = "pacify" E.cooldown += 10 - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, "You feel like never hurting anyone ever again."), 5) - to_chat(user, "You remove any intent to harm from [L]'s mind.") + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), L, span_notice("You feel like never hurting anyone ever again.")), 5) + to_chat(user, span_notice("You remove any intent to harm from [L]'s mind.")) //CHARGE else if(findtext(message, charge_words)) @@ -1423,7 +1429,7 @@ E.statusStrength = 2* power_multiplier E.status = "charge" E.cooldown += 10 - to_chat(user, "You rally [L], leading them into a charge!") + to_chat(user, span_notice("You rally [L], leading them into a charge!")) if(message_admins || debug)//Do you want this in? message_admins("[ADMIN_LOOKUPFLW(user)] has said '[log_message]' with a Velvet Voice, affecting [english_list(listeners)], with a power multiplier of [power_multiplier].") diff --git a/code/modules/vehicles/mecha/combat/durand.dm b/code/modules/vehicles/mecha/combat/durand.dm index d351300764d9..01b2f75e0a0a 100644 --- a/code/modules/vehicles/mecha/combat/durand.dm +++ b/code/modules/vehicles/mecha/combat/durand.dm @@ -194,7 +194,7 @@ own integrity back to max. Shield is automatically dropped if we run out of powe for(var/occupant in chassis.occupants) var/datum/action/button = chassis.occupant_actions[occupant][/datum/action/vehicle/sealed/mecha/mech_defense_mode] button.button_icon_state = "mech_defense_mode_[chassis.defense_mode ? "on" : "off"]" - button.UpdateButtons() + button.build_all_button_icons() set_light(light_range, light_power, light_color) diff --git a/code/modules/vehicles/mecha/mecha_actions.dm b/code/modules/vehicles/mecha/mecha_actions.dm index 976ffea40a65..c7ead102907e 100644 --- a/code/modules/vehicles/mecha/mecha_actions.dm +++ b/code/modules/vehicles/mecha/mecha_actions.dm @@ -8,7 +8,7 @@ /datum/action/vehicle/sealed/mecha - icon_icon = 'icons/mob/actions/actions_mecha.dmi' + button_icon = 'icons/mob/actions/actions_mecha.dmi' var/obj/vehicle/sealed/mecha/chassis /datum/action/vehicle/sealed/mecha/Destroy() @@ -19,33 +19,44 @@ name = "Eject From Mech" button_icon_state = "mech_eject" -/datum/action/vehicle/sealed/mecha/mech_eject/Trigger() +/datum/action/vehicle/sealed/mecha/mech_eject/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner) - return + return FALSE if(!chassis || !(owner in chassis.occupants)) - return + return FALSE chassis.container_resist(owner) + return TRUE /datum/action/vehicle/sealed/mecha/mech_toggle_internals name = "Toggle Internal Airtank Usage" button_icon_state = "mech_internals_off" -/datum/action/vehicle/sealed/mecha/mech_toggle_internals/Trigger() +/datum/action/vehicle/sealed/mecha/mech_toggle_internals/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return + return FALSE chassis.use_internal_tank = !chassis.use_internal_tank button_icon_state = "mech_internals_[chassis.use_internal_tank ? "on" : "off"]" to_chat(chassis.occupants, "[icon2html(chassis, owner)]Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].") chassis.log_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].", LOG_MECHA) - UpdateButtons() + build_all_button_icons() + return TRUE /datum/action/vehicle/sealed/mecha/mech_cycle_equip name = "Cycle Equipment" button_icon_state = "mech_cycle_equip_off" -/datum/action/vehicle/sealed/mecha/mech_cycle_equip/Trigger() +/datum/action/vehicle/sealed/mecha/mech_cycle_equip/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return + return FALSE var/list/available_equipment = list() for(var/e in chassis.equipment) @@ -55,14 +66,14 @@ if(available_equipment.len == 0) to_chat(owner, "[icon2html(chassis, owner)]No equipment available!") - return + return FALSE if(!chassis.selected) chassis.selected = available_equipment[1] to_chat(owner, "[icon2html(chassis, owner)]You select [chassis.selected].") send_byjax(chassis.occupants,"exosuit.browser","eq_list",chassis.get_equipment_list()) button_icon_state = "mech_cycle_equip_on" - UpdateButtons() - return + build_all_button_icons() + return TRUE var/number = 0 for(var/equipment in available_equipment) number++ @@ -77,20 +88,23 @@ to_chat(owner, "[icon2html(chassis, owner)]You switch to [chassis.selected].") button_icon_state = "mech_cycle_equip_on" send_byjax(chassis.occupants,"exosuit.browser","eq_list",chassis.get_equipment_list()) - UpdateButtons() - return + build_all_button_icons() + return TRUE /datum/action/vehicle/sealed/mecha/mech_toggle_lights name = "Toggle Lights" button_icon_state = "mech_lights_off" -/datum/action/vehicle/sealed/mecha/mech_toggle_lights/Trigger() +/datum/action/vehicle/sealed/mecha/mech_toggle_lights/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return + return FALSE if(!(chassis.mecha_flags & HAS_LIGHTS)) to_chat(owner, "This mechs lights are destroyed!") - return + return FALSE chassis.mecha_flags ^= LIGHTS_ON if(chassis.mecha_flags & LIGHTS_ON) button_icon_state = "mech_lights_on" @@ -100,28 +114,36 @@ chassis.set_light(0) to_chat(owner, "[icon2html(chassis, owner)]Toggled lights [(chassis.mecha_flags & LIGHTS_ON)?"on":"off"].") chassis.log_message("Toggled lights [(chassis.mecha_flags & LIGHTS_ON)?"on":"off"].", LOG_MECHA) - UpdateButtons() + build_all_button_icons() + return TRUE /datum/action/vehicle/sealed/mecha/mech_view_stats name = "View Stats" button_icon_state = "mech_view_stats" -/datum/action/vehicle/sealed/mecha/mech_view_stats/Trigger() +/datum/action/vehicle/sealed/mecha/mech_view_stats/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return + return FALSE var/datum/browser/popup = new(owner , "exosuit") popup.set_content(chassis.get_stats_html(owner)) popup.open() - + return TRUE /datum/action/vehicle/sealed/mecha/strafe name = "Toggle Strafing. Disabled when Alt is held." button_icon_state = "strafe" -/datum/action/vehicle/sealed/mecha/strafe/Trigger() +/datum/action/vehicle/sealed/mecha/strafe/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return + return FALSE chassis.toggle_strafe() + return TRUE /obj/vehicle/sealed/mecha/AltClick(mob/living/user) if(!(user in occupants) || !user.canUseTopic(src)) @@ -140,7 +162,7 @@ for(var/occupant in occupants) var/datum/action/action = LAZYACCESSASSOC(occupant_actions, occupant, /datum/action/vehicle/sealed/mecha/strafe) - action?.UpdateButtons() + action?.build_all_button_icons() //////////////////////////////////////// Specific Ability Actions /////////////////////////////////////////////// //Need to be granted by the mech type, Not default abilities. @@ -149,16 +171,23 @@ name = "Toggle an energy shield that blocks all attacks from the faced direction at a heavy power cost." button_icon_state = "mech_defense_mode_off" -/datum/action/vehicle/sealed/mecha/mech_defense_mode/Trigger(forced_state = FALSE) +/datum/action/vehicle/sealed/mecha/mech_defense_mode/Trigger(trigger_flags, forced_state = FALSE) + . = ..() + if(!.) + return FALSE SEND_SIGNAL(chassis, COMSIG_MECHA_ACTION_TRIGGER, owner, args) //Signal sent to the mech, to be handed to the shield. See durand.dm for more details + return TRUE /datum/action/vehicle/sealed/mecha/mech_overload_mode name = "Toggle leg actuators overload" button_icon_state = "mech_overload_off" -/datum/action/vehicle/sealed/mecha/mech_overload_mode/Trigger(forced_state = null) +/datum/action/vehicle/sealed/mecha/mech_overload_mode/Trigger(trigger_flags, forced_state = null) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return + return FALSE if(!isnull(forced_state)) chassis.leg_overload_mode = forced_state else @@ -176,47 +205,60 @@ chassis.movedelay = initial(chassis.movedelay) chassis.step_energy_drain = chassis.normal_step_energy_drain to_chat(owner, "[icon2html(chassis, owner)]You disable leg actuators overload.") - UpdateButtons() + build_all_button_icons() + return TRUE /datum/action/vehicle/sealed/mecha/mech_smoke name = "Smoke" button_icon_state = "mech_smoke" -/datum/action/vehicle/sealed/mecha/mech_smoke/Trigger() +/datum/action/vehicle/sealed/mecha/mech_smoke/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return + return FALSE if(!TIMER_COOLDOWN_CHECK(src, COOLDOWN_MECHA_SMOKE) && chassis.smoke_charges>0) chassis.smoke_system.start() chassis.smoke_charges-- TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_SMOKE, chassis.smoke_cooldown) + return TRUE /datum/action/vehicle/sealed/mecha/mech_zoom name = "Zoom" button_icon_state = "mech_zoom_off" -/datum/action/vehicle/sealed/mecha/mech_zoom/Trigger() +/datum/action/vehicle/sealed/mecha/mech_zoom/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return - if(owner.client) - chassis.zoom_mode = !chassis.zoom_mode - button_icon_state = "mech_zoom_[chassis.zoom_mode ? "on" : "off"]" - chassis.log_message("Toggled zoom mode.", LOG_MECHA) - to_chat(owner, "[icon2html(chassis, owner)]Zoom mode [chassis.zoom_mode?"en":"dis"]abled.") - if(chassis.zoom_mode) - owner.client.view_size.setTo(4.5) - SEND_SOUND(owner, sound('sound/mecha/imag_enh.ogg',volume=50)) - else - owner.client.view_size.resetToDefault() //Let's not let this stack shall we? - UpdateButtons() + return FALSE + if(!owner.client) + return FALSE + chassis.zoom_mode = !chassis.zoom_mode + button_icon_state = "mech_zoom_[chassis.zoom_mode ? "on" : "off"]" + chassis.log_message("Toggled zoom mode.", LOG_MECHA) + to_chat(owner, "[icon2html(chassis, owner)]Zoom mode [chassis.zoom_mode?"en":"dis"]abled.") + if(chassis.zoom_mode) + owner.client.view_size.setTo(4.5) + SEND_SOUND(owner, sound('sound/mecha/imag_enh.ogg',volume=50)) + else + owner.client.view_size.resetToDefault() //Let's not let this stack shall we? + build_all_button_icons() + return TRUE /datum/action/vehicle/sealed/mecha/mech_switch_damtype name = "Reconfigure arm microtool arrays" button_icon_state = "mech_damtype_brute" -/datum/action/vehicle/sealed/mecha/mech_switch_damtype/Trigger() +/datum/action/vehicle/sealed/mecha/mech_switch_damtype/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return + return FALSE var/new_damtype switch(chassis.damtype) if("tox") @@ -231,26 +273,30 @@ chassis.damtype = new_damtype button_icon_state = "mech_damtype_[new_damtype]" playsound(chassis, 'sound/mecha/mechmove01.ogg', 50, TRUE) - UpdateButtons() + build_all_button_icons() + return TRUE ///swap seats, for two person mecha /datum/action/vehicle/sealed/mecha/swap_seat name = "Switch Seats" button_icon_state = "mech_seat_swap" -/datum/action/vehicle/sealed/mecha/swap_seat/Trigger() +/datum/action/vehicle/sealed/mecha/swap_seat/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return + return FALSE if(chassis.occupants.len == chassis.max_occupants) to_chat(owner, "The other seat is occupied!") - return + return FALSE var/list/drivers = chassis.return_drivers() to_chat(owner, "Switching seats...") chassis.is_currently_ejecting = TRUE if(!do_after(owner, chassis.has_gravity() ? chassis.exit_delay : 0 , target = chassis)) chassis.is_currently_ejecting = FALSE - return + return FALSE chassis.is_currently_ejecting = FALSE if(owner in drivers) to_chat(owner, "You shift to the gunner seat!") @@ -261,15 +307,20 @@ chassis.remove_control_flags(owner, VEHICLE_CONTROL_MELEE|VEHICLE_CONTROL_EQUIPMENT) chassis.add_control_flags(owner, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_SETTINGS) chassis.update_icon_state() + return TRUE /datum/action/vehicle/sealed/mecha/mech_toggle_phasing name = "Toggle Phasing" button_icon_state = "mech_phasing_off" -/datum/action/vehicle/sealed/mecha/mech_toggle_phasing/Trigger() +/datum/action/vehicle/sealed/mecha/mech_toggle_phasing/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!owner || !chassis || !(owner in chassis.occupants)) - return + return FALSE chassis.phasing = !chassis.phasing button_icon_state = "mech_phasing_[chassis.phasing ? "on" : "off"]" to_chat(owner, "[icon2html(chassis, owner)]En":"#f00\">Dis"]abled phasing.") - UpdateButtons() + build_all_button_icons() + return TRUE diff --git a/code/modules/vehicles/vehicle_actions.dm b/code/modules/vehicles/vehicle_actions.dm index 28d469d5189a..725e50cc86b6 100644 --- a/code/modules/vehicles/vehicle_actions.dm +++ b/code/modules/vehicles/vehicle_actions.dm @@ -93,7 +93,7 @@ /datum/action/vehicle check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUN | AB_CHECK_CONSCIOUS - icon_icon = 'icons/mob/actions/actions_vehicle.dmi' + button_icon = 'icons/mob/actions/actions_vehicle.dmi' button_icon_state = "vehicle_eject" var/obj/vehicle/vehicle_target @@ -105,9 +105,14 @@ desc = "Climb out of your vehicle!" button_icon_state = "car_eject" -/datum/action/vehicle/sealed/climb_out/Trigger() - if(..() && istype(vehicle_entered_target)) - vehicle_entered_target.mob_try_exit(owner, owner) +/datum/action/vehicle/sealed/climb_out/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + if(!istype(vehicle_entered_target)) + return FALSE + vehicle_entered_target.mob_try_exit(owner, owner) + return TRUE /datum/action/vehicle/ridden var/obj/vehicle/ridden/vehicle_ridden_target @@ -117,8 +122,12 @@ desc = "Take your key out of the vehicle's ignition" button_icon_state = "car_removekey" -/datum/action/vehicle/sealed/remove_key/Trigger() +/datum/action/vehicle/sealed/remove_key/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE vehicle_entered_target.remove_key(owner) + return TRUE //CLOWN CAR ACTION DATUMS /datum/action/vehicle/sealed/horn @@ -127,48 +136,63 @@ button_icon_state = "car_horn" var/hornsound = 'sound/items/carhorn.ogg' -/datum/action/vehicle/sealed/horn/Trigger() +/datum/action/vehicle/sealed/horn/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_CAR_HONK)) - return + return FALSE TIMER_COOLDOWN_START(src, COOLDOWN_CAR_HONK, 2 SECONDS) vehicle_entered_target.visible_message(span_danger("[vehicle_entered_target] loudly honks!")) to_chat(owner, span_notice("You press [vehicle_entered_target]'s horn.")) if(istype(vehicle_target.inserted_key, /obj/item/bikehorn)) vehicle_target.inserted_key.attack_self(owner) //The bikehorn plays a sound instead - return + return FALSE playsound(vehicle_entered_target, hornsound, 75) + return TRUE /datum/action/vehicle/sealed/dump_kidnapped_mobs name = "Dump Kidnapped Mobs" desc = "Dump all objects and people in your car on the floor." button_icon_state = "car_dump" -/datum/action/vehicle/sealed/dump_kidnapped_mobs/Trigger() +/datum/action/vehicle/sealed/dump_kidnapped_mobs/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE vehicle_entered_target.visible_message(span_danger("[vehicle_entered_target] starts dumping the people inside of it.")) vehicle_entered_target.dump_specific_mobs(VEHICLE_CONTROL_KIDNAPPED) + return TRUE /datum/action/vehicle/sealed/roll_the_dice name = "Press Colorful Button" desc = "Press one of those colorful buttons on your display panel!" button_icon_state = "car_rtd" -/datum/action/vehicle/sealed/roll_the_dice/Trigger() +/datum/action/vehicle/sealed/roll_the_dice/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar)) - return + return FALSE var/obj/vehicle/sealed/car/clowncar/C = vehicle_entered_target C.roll_the_dice(owner) + return TRUE /datum/action/vehicle/sealed/cannon name = "Toggle Siege Mode" desc = "Destroy them with their own fodder!" button_icon_state = "car_cannon" -/datum/action/vehicle/sealed/cannon/Trigger() +/datum/action/vehicle/sealed/cannon/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar)) - return + return FALSE var/obj/vehicle/sealed/car/clowncar/C = vehicle_entered_target C.toggle_cannon(owner) - + return TRUE /datum/action/vehicle/sealed/thank name = "Thank the Clown Car Driver" @@ -177,55 +201,63 @@ COOLDOWN_DECLARE(thank_time_cooldown) -/datum/action/vehicle/sealed/thank/Trigger() +/datum/action/vehicle/sealed/thank/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(!istype(vehicle_entered_target, /obj/vehicle/sealed/car/clowncar)) - return + return FALSE if(!COOLDOWN_FINISHED(src, thank_time_cooldown)) - return + return FALSE COOLDOWN_START(src, thank_time_cooldown, 6 SECONDS) var/obj/vehicle/sealed/car/clowncar/clown_car = vehicle_entered_target var/mob/living/carbon/human/clown = pick(clown_car.return_drivers()) if(!clown) - return + return FALSE owner.say("Thank you for the fun ride, [clown.name]!") clown_car.increment_thanks_counter() - + return TRUE /datum/action/vehicle/ridden/scooter/skateboard/ollie name = "Ollie" desc = "Get some air! Land on a table to do a gnarly grind." button_icon_state = "skateboard_ollie" ///Cooldown to next jump - var/next_ollie - -/datum/action/vehicle/ridden/scooter/skateboard/ollie/Trigger() - if(world.time > next_ollie) - var/obj/vehicle/ridden/scooter/skateboard/V = vehicle_target - if (V.grinding) - return - var/mob/living/L = owner - var/turf/landing_turf = get_step(V.loc, V.dir) - L.adjustStaminaLoss(V.instability*2) - if (L.getStaminaLoss() >= 100) - playsound(src, 'sound/effects/bang.ogg', 20, TRUE) - V.unbuckle_mob(L) - L.throw_at(landing_turf, 2, 2) - L.Knockdown(40) - V.visible_message("[L] misses the landing and falls on [L.p_their()] face!") - else - L.spin(4, 1) - animate(L, pixel_y = -6, time = 4) - animate(V, pixel_y = -6, time = 3) - playsound(V, 'sound/vehicles/skateboard_ollie.ogg', 50, TRUE) - passtable_on(L, VEHICLE_TRAIT) - V.pass_flags |= PASSTABLE - L.Move(landing_turf, vehicle_target.dir) - passtable_off(L, VEHICLE_TRAIT) - V.pass_flags &= ~PASSTABLE - if((locate(/obj/structure/table) in V.loc.contents) || (locate(/obj/structure/fluff/railing) in V.loc.contents)) - if(locate(/obj/structure/fluff/railing) in V.loc.contents) - L.client.give_award(/datum/award/achievement/misc/tram_surfer, L) - V.grinding = TRUE - V.icon_state = "[V.board_icon]-grind" - addtimer(CALLBACK(V, TYPE_PROC_REF(/obj/vehicle/ridden/scooter/skateboard, grind)), 2) - next_ollie = world.time + 5 + COOLDOWN_DECLARE(next_ollie) + +/datum/action/vehicle/ridden/scooter/skateboard/ollie/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE + if(!COOLDOWN_FINISHED(src, next_ollie)) + return FALSE + var/obj/vehicle/ridden/scooter/skateboard/V = vehicle_target + if (V.grinding) + return FALSE + var/mob/living/L = owner + var/turf/landing_turf = get_step(V.loc, V.dir) + L.adjustStaminaLoss(V.instability*2) + if (L.getStaminaLoss() >= 100) + playsound(src, 'sound/effects/bang.ogg', 20, TRUE) + V.unbuckle_mob(L) + L.throw_at(landing_turf, 2, 2) + L.Knockdown(40) + V.visible_message("[L] misses the landing and falls on [L.p_their()] face!") + else + L.spin(4, 1) + animate(L, pixel_y = -6, time = 4) + animate(V, pixel_y = -6, time = 3) + playsound(V, 'sound/vehicles/skateboard_ollie.ogg', 50, TRUE) + passtable_on(L, VEHICLE_TRAIT) + V.pass_flags |= PASSTABLE + L.Move(landing_turf, vehicle_target.dir) + passtable_off(L, VEHICLE_TRAIT) + V.pass_flags &= ~PASSTABLE + if((locate(/obj/structure/table) in V.loc.contents) || (locate(/obj/structure/fluff/railing) in V.loc.contents)) + if(locate(/obj/structure/fluff/railing) in V.loc.contents) + L.client.give_award(/datum/award/achievement/misc/tram_surfer, L) + V.grinding = TRUE + V.icon_state = "[V.board_icon]-grind" + addtimer(CALLBACK(V, TYPE_PROC_REF(/obj/vehicle/ridden/scooter/skateboard, grind)), 2) + COOLDOWN_START(src, next_ollie, 0.5 SECONDS) + return TRUE diff --git a/code/modules/wiremod/shell/brain_computer_interface.dm b/code/modules/wiremod/shell/brain_computer_interface.dm index 4bed63c734a0..8ef10b53f93b 100644 --- a/code/modules/wiremod/shell/brain_computer_interface.dm +++ b/code/modules/wiremod/shell/brain_computer_interface.dm @@ -133,7 +133,7 @@ /datum/action/innate/bci_action name = "Action" - icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon = 'icons/mob/actions/actions_items.dmi' check_flags = AB_CHECK_CONSCIOUS button_icon_state = "bci_power" @@ -278,7 +278,7 @@ /datum/action/innate/bci_charge_action name = "Check BCI Charge" check_flags = NONE - icon_icon = 'icons/obj/power.dmi' + button_icon = 'icons/obj/power.dmi' button_icon_state = "cell" var/obj/item/circuit_component/bci_core/circuit_component diff --git a/icons/mob/actions.dmi b/icons/hud/actions.dmi similarity index 100% rename from icons/mob/actions.dmi rename to icons/hud/actions.dmi diff --git a/modular_citadel/code/modules/clothing/neck.dm b/modular_citadel/code/modules/clothing/neck.dm index 9507e65e0e53..f1c74d6b83b2 100644 --- a/modular_citadel/code/modules/clothing/neck.dm +++ b/modular_citadel/code/modules/clothing/neck.dm @@ -13,11 +13,15 @@ var/toggled = FALSE var/obj/effect/heart/heart -/datum/action/item_action/zanderlocket/Trigger() +/datum/action/item_action/zanderlocket/do_effect(trigger_flags) + . = ..() + if(!.) + return new/obj/effect/temp_visual/souldeath(owner.loc, owner) playsound(owner, 'sound/misc/souldeath.ogg', 100, FALSE) + return TRUE /obj/item/clothing/neck/undertale/Initialize(mapload) - ..() + . = ..() AddComponent(/datum/component/souldeath/neck) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm index 2be1a97873f1..1f99a95dab71 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm @@ -37,18 +37,22 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die var/mob/living/carbon/origin var/datum/mind/originalmind -/datum/action/chem/astral/Trigger() +/datum/action/chem/astral/Trigger(trigger_flags) + . = ..() + if(!.) + return FALSE if(origin.mind && origin.mind != originalmind) - to_chat(originalmind.current, "There's a foreign presence in your body blocking your return!") - return ..() + to_chat(originalmind.current, span_warning("There's a foreign presence in your body blocking your return!")) + return FALSE if(origin.reagents.has_reagent(/datum/reagent/fermi/astral) ) var/datum/reagent/fermi/astral/As = locate(/datum/reagent/fermi/astral) in origin.reagents.reagent_list if(As.current_cycle < 10) - to_chat(originalmind.current, "The intensity of the astrogen in your body is too much allow you to return to yourself yet!") - return ..() + to_chat(originalmind.current, span_warning("The intensity of the astrogen in your body is too much allow you to return to yourself yet!")) + return FALSE originalmind.transfer_to(origin) if(origin.mind == originalmind) qdel(src) + return TRUE /datum/reagent/fermi/astral/reaction_turf(turf/T, reac_volume) @@ -88,7 +92,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die if(overdosed) if(prob(50)) - to_chat(G, "The high conentration of Astrogen in your blood causes you to lapse your concentration for a moment, bringing your projection back to yourself!") + to_chat(G, span_warning("The high conentration of Astrogen in your blood causes you to lapse your concentration for a moment, bringing your projection back to yourself!")) do_teleport(G, M.loc) metabolization_rate = current_cycle/10 //exponential sleepytime+=5 @@ -107,12 +111,12 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die if(M.mind) //Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. var/mob/living/simple_animal/astral/G2 = new(get_turf(M)) M.mind.transfer_to(G2) - to_chat(G2, "[M]'s conciousness snaps back to them as [M.p_their()] astrogen runs out, kicking your projected mind out!'") + to_chat(G2, span_warning("[M]'s conciousness snaps back to them as [M.p_their()] astrogen runs out, kicking your projected mind out!'")) log_reagent("FERMICHEM: [G2.mind.name] has been booted out of [M] as their original mind came back as the Astrogen reagent ran out!") G.mind.transfer_to(origin) qdel(G) if(overdosed) - to_chat(M, "The high volume of astrogen you just took causes you to black out momentarily as your mind snaps back to your body.") + to_chat(M, span_warning("The high volume of astrogen you just took causes you to black out momentarily as your mind snaps back to your body.")) M.Sleeping(sleepytime, 0) antiGenetics = 255 log_reagent("FERMICHEM: [M] has astrally returned to their body!") @@ -130,39 +134,39 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die antiGenetics-- switch(antiGenetics) if(245) - to_chat(M, "You notice your body starting to disappear, maybe you took too much Astrogen...?") + to_chat(M, span_warning("You notice your body starting to disappear, maybe you took too much Astrogen...?")) M.alpha-- antiGenetics-- log_reagent("FERMICHEM: [M] ckey: [M.key] has become addicted to Astrogen") if(220) - to_chat(M, "Your addiction is only getting worse as your body disappears. Maybe you should get some more, and fast?") + to_chat(M, span_notice("Your addiction is only getting worse as your body disappears. Maybe you should get some more, and fast?")) M.alpha-- antiGenetics-- if(200) - to_chat(M, "You feel a substantial part of your soul flake off into the ethereal world, rendering yourself unclonable.") + to_chat(M, span_notice("You feel a substantial part of your soul flake off into the ethereal world, rendering yourself unclonable.")) M.alpha-- antiGenetics-- ADD_TRAIT(M, TRAIT_NOCLONE, "astral") //So you can't scan yourself, then die, to metacomm. You can only use your memories if you come back as something else. M.hellbound = TRUE if(180) - to_chat(M, "You feel fear build up in yourself as more and more of your body and consciousness begins to fade.") + to_chat(M, span_notice("You feel fear build up in yourself as more and more of your body and consciousness begins to fade.")) M.alpha-- antiGenetics-- if(120) - to_chat(M, "As you lose more and more of yourself, you start to think that maybe shedding your mortality isn't too bad.") + to_chat(M, span_notice("As you lose more and more of yourself, you start to think that maybe shedding your mortality isn't too bad.")) M.alpha-- antiGenetics-- if(80) - to_chat(M, "You feel a thrill shoot through your body as what's left of your mind contemplates your forthcoming oblivion.") + to_chat(M, span_notice("You feel a thrill shoot through your body as what's left of your mind contemplates your forthcoming oblivion.")) M.alpha-- antiGenetics-- if(45) - to_chat(M, "The last vestiges of your mind eagerly await your imminent annihilation.") + to_chat(M, span_warning("The last vestiges of your mind eagerly await your imminent annihilation.")) M.alpha-- antiGenetics-- if(-INFINITY to 30) - to_chat(M, "Your body disperses from existence, as you become one with the universe.") - to_chat(M, "As your body disappears, your consciousness doesn't. Should you find a way back into the mortal coil, your memories of your previous life remain with you. (At the cost of staying in character while dead. Failure to do this may get you banned from this chem. You are still obligated to follow your directives if you play a midround antag, you do not remember the afterlife IC)")//Legalised IC OOK? I have a suspicion this won't make it past the review. At least it'll be presented as a neat idea! If this is unacceptable how about the player can retain living memories across lives if they die in this way only. + to_chat(M, span_warning("Your body disperses from existence, as you become one with the universe.")) + to_chat(M, span_userdanger("As your body disappears, your consciousness doesn't. Should you find a way back into the mortal coil, your memories of your previous life remain with you. (At the cost of staying in character while dead. Failure to do this may get you banned from this chem. You are still obligated to follow your directives if you play a midround antag, you do not remember the afterlife IC)"))//Legalised IC OOK? I have a suspicion this won't make it past the review. At least it'll be presented as a neat idea! If this is unacceptable how about the player can retain living memories across lives if they die in this way only. deadchat_broadcast(" has become one with the universe, meaning that their IC conciousness is continuous in a new life. If they find a way back to life, they are allowed to remember their previous life. Be careful what you say. If they abuse this, bwoink the FUCK outta them.", "[M]", M, message_type=DEADCHAT_ANNOUNCEMENT) M.visible_message("[M] suddenly disappears, their body evaporating from existence, freeing [M] from their mortal coil.") message_admins("[M] (ckey: [M.ckey]) has become one with the universe, and have continuous memories thoughout their lives should they find a way to come back to life (such as an inteligence potion, midround antag, ghost role).") diff --git a/tgstation.dme b/tgstation.dme index 14b128e4c816..4967e20e4b8f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -26,6 +26,7 @@ #include "code\__DEFINES\_tick.dm" #include "code\__DEFINES\access.dm" #include "code\__DEFINES\achievements.dm" +#include "code\__DEFINES\actions.dm" #include "code\__DEFINES\actionspeed_modifiers.dm" #include "code\__DEFINES\admin.dm" #include "code\__DEFINES\alarm.dm" @@ -168,6 +169,7 @@ #include "code\__DEFINES\dcs\signals\signals_global.dm" #include "code\__DEFINES\dcs\signals\signals_hud.dm" #include "code\__DEFINES\dcs\signals\signals_medical.dm" +#include "code\__DEFINES\dcs\signals\signals_object.dm" #include "code\__DEFINES\dcs\signals\signals_mod.dm" #include "code\__DEFINES\dcs\signals\signals_painting.dm" #include "code\__DEFINES\dcs\signals\signals_reagent.dm" @@ -524,6 +526,9 @@ #include "code\datums\achievements\misc_achievements.dm" #include "code\datums\achievements\misc_scores.dm" #include "code\datums\achievements\skill_achievements.dm" +#include "code\datums\actions\cooldown_action.dm" +#include "code\datums\actions\innate_action.dm" +#include "code\datums\actions\item_action.dm" #include "code\datums\actions\beam_rifle.dm" #include "code\datums\announcers\_announcer.dm" #include "code\datums\announcers\default_announcer.dm" @@ -543,6 +548,7 @@ #include "code\datums\changelog\changelog.dm" #include "code\datums\components\_component.dm" #include "code\datums\components\acid.dm" +#include "code\datums\components\action_item_overlay.dm" #include "code\datums\components\activity.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\area_sound_manager.dm" diff --git a/tools/build/build.js b/tools/build/build.js index f8d3a9a7dd7e..c3946dcbe06c 100755 --- a/tools/build/build.js +++ b/tools/build/build.js @@ -61,6 +61,7 @@ export const DmTarget = new Juke.Target({ 'html/**', 'icons/**', 'interface/**', + 'modular_citadel/**', `${DME_NAME}.dme`, ], outputs: [