diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 7e585da9240..bc71bc13732 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -974,6 +974,8 @@ GLOBAL_LIST_INIT(layers_to_offset, list( /// The duration of the flip emote animation #define FLIP_EMOTE_DURATION 0.7 SECONDS +///The duration of a taunt emote, so how long they can deflect projectiles +#define TAUNT_EMOTE_DURATION 0.9 SECONDS // Sprites for photocopying butts #define BUTT_SPRITE_HUMAN_MALE "human_male" diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 8f454d78ce7..7475b96afd8 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -362,8 +362,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_GUNFLIP "gunflip" /// Increases chance of getting special traumas, makes them harder to cure #define TRAIT_SPECIAL_TRAUMA_BOOST "special_trauma_boost" -/// Doubles the duration and cooldown of a flip -#define TRAIT_SLOW_FLIP "slow_flip" #define TRAIT_SPACEWALK "spacewalk" /// Sanity trait to keep track of when we're in hyperspace and add the appropriate element if we werent #define TRAIT_HYPERSPACED "hyperspaced" @@ -677,6 +675,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// This movable atom has the explosive block element #define TRAIT_BLOCKING_EXPLOSIVES "blocking_explosives" +///This mob is currently blocking a projectile. +#define TRAIT_BLOCKING_PROJECTILES "blocking_projectiles" /// This turf contains something using split visiblity #define TRAIT_CONTAINS_SPLITVIS "contains_splitvis" diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index f11cc50dbbd..e9037e891e6 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -45,7 +45,8 @@ /// Trait given by an Action datum #define ACTION_TRAIT "action" - +///A trait given by someone blocking. +#define BLOCKING_TRAIT "blocking" #define CLOTHING_TRAIT "clothing" #define HELMET_TRAIT "helmet" /// inherited from the mask diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index f286cf46c8c..164826982b5 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -150,6 +150,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_BIRTHDAY_BOY" = TRAIT_BIRTHDAY_BOY, "TRAIT_BLOB_ALLY" = TRAIT_BLOB_ALLY, "TRAIT_BLOCK_SHUTTLE_MOVEMENT" = TRAIT_BLOCK_SHUTTLE_MOVEMENT, + "TRAIT_BLOCKING_PROJECTILES" = TRAIT_BLOCKING_PROJECTILES, "TRAIT_BLOOD_CLANS" = TRAIT_BLOOD_CLANS, "TRAIT_BLOODSHOT_EYES" = TRAIT_BLOODSHOT_EYES, "TRAIT_BLOODY_MESS" = TRAIT_BLOODY_MESS, @@ -451,7 +452,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_SIXTHSENSE" = TRAIT_SIXTHSENSE, "TRAIT_SKITTISH" = TRAIT_SKITTISH, "TRAIT_SLEEPIMMUNE" = TRAIT_SLEEPIMMUNE, - "TRAIT_SLOW_FLIP" = TRAIT_SLOW_FLIP, "TRAIT_SMOKER" = TRAIT_SMOKER, "TRAIT_SNEAK" = TRAIT_SNEAK, "TRAIT_SNOB" = TRAIT_SNOB, diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index 53d1dd56a2f..0aedfbd28ea 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -259,7 +259,6 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_SIXTHSENSE" = TRAIT_SIXTHSENSE, "TRAIT_SKITTISH" = TRAIT_SKITTISH, "TRAIT_SLEEPIMMUNE" = TRAIT_SLEEPIMMUNE, - "TRAIT_SLOW_FLIP" = TRAIT_SLOW_FLIP, "TRAIT_SMOKER" = TRAIT_SMOKER, "TRAIT_SNOB" = TRAIT_SNOB, "TRAIT_SOFTSPOKEN" = TRAIT_SOFTSPOKEN, diff --git a/code/datums/components/style/style.dm b/code/datums/components/style/style.dm index 9bc420cc175..cc8b061fd35 100644 --- a/code/datums/components/style/style.dm +++ b/code/datums/components/style/style.dm @@ -98,8 +98,7 @@ RegisterSignal(parent, COMSIG_USER_ITEM_INTERACTION, PROC_REF(hotswap)) RegisterSignal(parent, COMSIG_MOB_MINED, PROC_REF(on_mine)) RegisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(on_take_damage)) - RegisterSignal(parent, COMSIG_MOB_EMOTED("flip"), PROC_REF(on_flip)) - RegisterSignal(parent, COMSIG_MOB_EMOTED("spin"), PROC_REF(on_spin)) + RegisterSignal(parent, COMSIG_MOB_EMOTED("taunt"), PROC_REF(on_taunt)) RegisterSignal(parent, COMSIG_MOB_ITEM_ATTACK, PROC_REF(on_attack)) RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_punch)) RegisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH, PROC_REF(on_death)) @@ -114,7 +113,7 @@ UnregisterSignal(parent, COMSIG_USER_ITEM_INTERACTION) UnregisterSignal(parent, COMSIG_MOB_MINED) UnregisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE) - UnregisterSignal(parent, list(COMSIG_MOB_EMOTED("flip"), COMSIG_MOB_EMOTED("spin"))) + UnregisterSignal(parent, COMSIG_MOB_EMOTED("taunt")) UnregisterSignal(parent, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_LIVING_UNARMED_ATTACK)) UnregisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH) UnregisterSignal(parent, COMSIG_LIVING_RESONATOR_BURST) @@ -407,19 +406,12 @@ // Emote-based multipliers -/datum/component/style/proc/on_flip() +/datum/component/style/proc/on_taunt() SIGNAL_HANDLER point_multiplier = round(min(point_multiplier + 0.5, 3), 0.1) update_screen() -/datum/component/style/proc/on_spin() - SIGNAL_HANDLER - - point_multiplier = round(min(point_multiplier + 0.3, 3), 0.1) - update_screen() - - // Negative effects /datum/component/style/proc/on_take_damage(...) SIGNAL_HANDLER diff --git a/code/modules/bitrunning/orders/tech.dm b/code/modules/bitrunning/orders/tech.dm index 7e987e48181..0b097127ffb 100644 --- a/code/modules/bitrunning/orders/tech.dm +++ b/code/modules/bitrunning/orders/tech.dm @@ -32,7 +32,7 @@ desc = "This disk contains a program that lets you shapeshift into a lesser ashdrake, or a polar bear." /datum/orderable_item/bitrunning_tech/flip_skillchip - item_path = /obj/item/skillchip/matrix_flip + item_path = /obj/item/skillchip/matrix_taunt cost_per_order = 2000 /datum/orderable_item/bitrunning_tech/pka_mod diff --git a/code/modules/library/skill_learning/generic_skillchips/matrix_flip.dm b/code/modules/library/skill_learning/generic_skillchips/matrix_flip.dm deleted file mode 100644 index a836442eca0..00000000000 --- a/code/modules/library/skill_learning/generic_skillchips/matrix_flip.dm +++ /dev/null @@ -1,40 +0,0 @@ -#define FLIP_STAMINA_COST 19 - -/obj/item/skillchip/matrix_flip - name = "BULLET_DODGER skillchip" - skill_name = "Flip 2 Dodge" - skill_description = "At the cost of stamina, your flips can also be used to dodge incoming projectiles." - skill_icon = FA_ICON_SPINNER - activate_message = span_notice("You feel the urge to flip scenically as if you are the 'Chosen One'.") - deactivate_message = span_notice("The urge to flip goes away.") - -/obj/item/skillchip/matrix_flip/on_activate(mob/living/carbon/user, silent = FALSE) - . = ..() - ADD_TRAIT(user, TRAIT_SLOW_FLIP, SKILLCHIP_TRAIT) - RegisterSignal(user, COMSIG_MOB_EMOTED("flip"), PROC_REF(on_flip)) - RegisterSignal(user, COMSIG_MOB_PRE_EMOTED, PROC_REF(check_if_we_can_flip)) - -/obj/item/skillchip/matrix_flip/on_deactivate(mob/living/carbon/user, silent=FALSE) - REMOVE_TRAIT(user, TRAIT_SLOW_FLIP, SKILLCHIP_TRAIT) - UnregisterSignal(user, list(COMSIG_MOB_EMOTED("flip"), COMSIG_MOB_PRE_EMOTED)) - return ..() - -///Prevent players from stamcritting from INTENTIONAL flips. 1.4s of bullet immunity isn't worth several secs of stun. -/obj/item/skillchip/matrix_flip/proc/check_if_we_can_flip(mob/living/source, key, params, type_override, intentional, datum/emote/emote) - SIGNAL_HANDLER - if(key != "flip" || !intentional) - return - if((source.maxHealth - (source.getStaminaLoss() + FLIP_STAMINA_COST)) <= source.crit_threshold) - source.balloon_alert(source, "too tired!") - return COMPONENT_CANT_EMOTE - -/obj/item/skillchip/matrix_flip/proc/on_flip(mob/living/source) - SIGNAL_HANDLER - if(HAS_TRAIT_FROM(source, TRAIT_UNHITTABLE_BY_PROJECTILES, SKILLCHIP_TRAIT)) - return - playsound(source, 'sound/weapons/fwoosh.ogg', 90, FALSE, frequency = 0.7) - ADD_TRAIT(source, TRAIT_UNHITTABLE_BY_PROJECTILES, SKILLCHIP_TRAIT) - source.adjustStaminaLoss(FLIP_STAMINA_COST) - addtimer(TRAIT_CALLBACK_REMOVE(source, TRAIT_UNHITTABLE_BY_PROJECTILES, SKILLCHIP_TRAIT), FLIP_EMOTE_DURATION * 2) - -#undef FLIP_STAMINA_COST diff --git a/code/modules/library/skill_learning/generic_skillchips/matrix_taunt.dm b/code/modules/library/skill_learning/generic_skillchips/matrix_taunt.dm new file mode 100644 index 00000000000..cfe61b08e0c --- /dev/null +++ b/code/modules/library/skill_learning/generic_skillchips/matrix_taunt.dm @@ -0,0 +1,37 @@ +#define TAUNT_STAMINA_COST 19 + +/obj/item/skillchip/matrix_taunt + name = "BULLET_DODGER skillchip" + skill_name = "Taunt 2 Dodge" + skill_description = "At the cost of stamina, your taunts can also be used to dodge incoming projectiles." + skill_icon = FA_ICON_SPINNER + activate_message = span_notice("You feel the urge to taunt scenically as if you are the 'Chosen One'.") + deactivate_message = span_notice("The urge to taunt goes away.") + +/obj/item/skillchip/matrix_taunt/on_activate(mob/living/carbon/user, silent = FALSE) + . = ..() + RegisterSignal(user, COMSIG_MOB_EMOTED("taunt"), PROC_REF(on_taunt)) + RegisterSignal(user, COMSIG_MOB_PRE_EMOTED, PROC_REF(check_if_we_can_taunt)) + +/obj/item/skillchip/matrix_taunt/on_deactivate(mob/living/carbon/user, silent=FALSE) + UnregisterSignal(user, list(COMSIG_MOB_EMOTED("taunt"), COMSIG_MOB_PRE_EMOTED)) + return ..() + +///Prevent players from stamcritting from INTENTIONAL flips. 1.4s of bullet immunity isn't worth several secs of stun. +/obj/item/skillchip/matrix_taunt/proc/check_if_we_can_taunt(mob/living/source, key, params, type_override, intentional, datum/emote/emote) + SIGNAL_HANDLER + if(key != "taunt" || !intentional) + return + if((source.maxHealth - (source.getStaminaLoss() + TAUNT_STAMINA_COST)) <= source.crit_threshold) + source.balloon_alert(source, "too tired!") + return COMPONENT_CANT_EMOTE + +/obj/item/skillchip/matrix_taunt/proc/on_taunt(mob/living/source) + SIGNAL_HANDLER + if(HAS_TRAIT_FROM(source, TRAIT_UNHITTABLE_BY_PROJECTILES, SKILLCHIP_TRAIT)) + return + ADD_TRAIT(source, TRAIT_UNHITTABLE_BY_PROJECTILES, SKILLCHIP_TRAIT) + source.adjustStaminaLoss(TAUNT_STAMINA_COST) + addtimer(TRAIT_CALLBACK_REMOVE(source, TRAIT_UNHITTABLE_BY_PROJECTILES, SKILLCHIP_TRAIT), TAUNT_EMOTE_DURATION * 1.5) + +#undef TAUNT_STAMINA_COST diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 84b00249a49..308e4cc830d 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -83,15 +83,10 @@ /datum/emote/flip/run_emote(mob/user, params , type_override, intentional) . = ..() - user.SpinAnimation(HAS_TRAIT(user, TRAIT_SLOW_FLIP) ? FLIP_EMOTE_DURATION * 2 : FLIP_EMOTE_DURATION, 1) + user.SpinAnimation(FLIP_EMOTE_DURATION, 1) /datum/emote/flip/check_cooldown(mob/user, intentional) - var/slow_flipper = HAS_TRAIT(user, TRAIT_SLOW_FLIP) - if(slow_flipper) - cooldown *= 2 . = ..() - if(slow_flipper) - cooldown *= 0.5 if(.) return if(!can_run_emote(user, intentional=intentional)) diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 17e98b9b73e..da7f817db75 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -4,6 +4,16 @@ mob_type_allowed_typecache = /mob/living mob_type_blacklist_typecache = list(/mob/living/brain) +/datum/emote/living/taunt + key = "taunt" + key_third_person = "taunts" + message = "taunts!" + cooldown = 1.6 SECONDS //note when changing this- this is used by the matrix taunt to block projectiles. + +/datum/emote/living/taunt/run_emote(mob/living/user, params, type_override, intentional) + . = ..() + user.spin(TAUNT_EMOTE_DURATION, 0.1 SECONDS) + /datum/emote/living/blush key = "blush" key_third_person = "blushes" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 7103bb2c42c..235bf210c3e 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2824,3 +2824,25 @@ GLOBAL_LIST_EMPTY(fire_appearances) return "[span_notice("You'd estimate [p_their()] fitness level at about...")] [span_boldwarning("What?!? [our_fitness_level]???")]" return span_notice("You'd estimate [p_their()] fitness level at about [our_fitness_level]. [comparative_fitness <= 0.33 ? "Pathetic." : ""]") + +///Performs the aftereffects of blocking a projectile. +/mob/living/proc/block_projectile_effects() + var/static/list/icon/blocking_overlay + if(isnull(blocking_overlay)) + blocking_overlay = list( + mutable_appearance('icons/mob/effects/blocking.dmi', "wow"), + mutable_appearance('icons/mob/effects/blocking.dmi', "nice"), + mutable_appearance('icons/mob/effects/blocking.dmi', "good"), + ) + ADD_TRAIT(src, TRAIT_BLOCKING_PROJECTILES, BLOCKING_TRAIT) + var/icon/selected_overlay = pick(blocking_overlay) + add_overlay(selected_overlay) + playsound(src, 'sound/weapons/fwoosh.ogg', 90, FALSE, frequency = 0.7) + update_transform(1.25) + addtimer(CALLBACK(src, PROC_REF(end_block_effects), selected_overlay), 0.6 SECONDS) + +///Remoevs the effects of blocking a projectile and allows the user to block another. +/mob/living/proc/end_block_effects(selected_overlay) + REMOVE_TRAIT(src, TRAIT_BLOCKING_PROJECTILES, BLOCKING_TRAIT) + cut_overlay(selected_overlay) + update_transform(0.8) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 0fdafa766cf..fd6f145eaba 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -571,6 +571,9 @@ if((target.pass_flags_self & pass_flags) && !direct_target) return FALSE if(HAS_TRAIT(target, TRAIT_UNHITTABLE_BY_PROJECTILES)) + if(!HAS_TRAIT(target, TRAIT_BLOCKING_PROJECTILES) && isliving(target)) + var/mob/living/living_target = target + living_target.block_projectile_effects() return FALSE if(!ignore_source_check && firer) var/mob/M = firer diff --git a/icons/mob/effects/blocking.dmi b/icons/mob/effects/blocking.dmi new file mode 100644 index 00000000000..03872fa0fe3 Binary files /dev/null and b/icons/mob/effects/blocking.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 7e329f3bd42..afff6b31400 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4484,7 +4484,7 @@ #include "code\modules\library\random_books.dm" #include "code\modules\library\skill_learning\skill_station.dm" #include "code\modules\library\skill_learning\skillchip.dm" -#include "code\modules\library\skill_learning\generic_skillchips\matrix_flip.dm" +#include "code\modules\library\skill_learning\generic_skillchips\matrix_taunt.dm" #include "code\modules\library\skill_learning\generic_skillchips\point.dm" #include "code\modules\library\skill_learning\generic_skillchips\rod_suplex.dm" #include "code\modules\library\skill_learning\job_skillchips\_job.dm"