diff --git a/code/__DEFINES/melee.dm b/code/__DEFINES/melee.dm index 8b3a422fc0b25..1880c75c97b8d 100644 --- a/code/__DEFINES/melee.dm +++ b/code/__DEFINES/melee.dm @@ -1,8 +1,9 @@ //Martial arts defines #define MARTIALART_BOXING "boxing" -#define MARTIALART_EVIL_BOXING "evil boxing" #define MARTIALART_CQC "CQC" +#define MARTIALART_EVIL_BOXING "evil boxing" +#define MARTIALART_HUNTER_BOXING "hunter boxing" #define MARTIALART_KRAVMAGA "krav maga" #define MARTIALART_MUSHPUNCH "mushroom punch" #define MARTIALART_PLASMAFIST "plasma fist" diff --git a/code/datums/martial/boxing.dm b/code/datums/martial/boxing.dm index 5c24aaf45b7b2..3465fe300a5ac 100644 --- a/code/datums/martial/boxing.dm +++ b/code/datums/martial/boxing.dm @@ -7,8 +7,10 @@ name = "Boxing" id = MARTIALART_BOXING pacifist_style = TRUE - ///Boolean on whether we are sportsmanlike in our tussling; TRUE means we have restrictions + /// Boolean on whether we are sportsmanlike in our tussling; TRUE means we have restrictions var/honorable_boxer = TRUE + /// Default damage type for our boxing. + var/default_damage_type = STAMINA /// List of traits applied to users of this martial art. var/list/boxing_traits = list(TRAIT_BOXING_READY) /// Balloon alert cooldown for warning our boxer to alternate their blows to get more damage @@ -40,10 +42,16 @@ if(findtext(streak, LEFT_RIGHT_COMBO) || findtext(streak, RIGHT_LEFT_COMBO)) reset_streak() + // If we have an extra effect from the combo, perform it here. By default, we have no extra effect. + perform_extra_effect(attacker, defender) return combo_multiplier * 1.5 return combo_multiplier +/// An extra effect on some moves and attacks. +/datum/martial_art/boxing/proc/perform_extra_effect(mob/living/attacker, mob/living/defender) + return + /datum/martial_art/boxing/disarm_act(mob/living/attacker, mob/living/defender) if(honor_check(defender)) add_to_streak("D", defender) @@ -88,8 +96,8 @@ // If true, grants experience for punching; we only gain experience if we punch another boxer. var/grant_experience = FALSE - // What type of damage does our kind of boxing do? Defaults to STAMINA, unless you're performing EVIL BOXING - var/damage_type = honorable_boxer ? STAMINA : attacker.get_attack_type() + // What type of damage does our kind of boxing do? Defaults to STAMINA for normal boxing, unless you're performing EVIL BOXING. Subtypes use different damage types. + var/damage_type = honorable_boxer ? default_damage_type : attacker.get_attack_type() attacker.do_attack_animation(defender, ATTACK_EFFECT_PUNCH) @@ -147,12 +155,12 @@ log_combat(attacker, defender, "punched (boxing) ") + if(defender.stat == DEAD || !honor_check(defender)) //early returning here so we don't worry about knockout probs or experience gain + return TRUE + if(grant_experience) skill_experience_adjustment(attacker, (damage/lower_force)) - if(defender.stat == DEAD || !honor_check(defender)) //early returning here so we don't worry about knockout probs - return TRUE - //Determine our attackers athletics level as a knockout probability bonus var/attacker_athletics_skill = (attacker.mind?.get_skill_modifier(/datum/skill/athletics, SKILL_RANDS_MODIFIER) + base_unarmed_effectiveness) @@ -165,6 +173,18 @@ if(!prob(final_knockout_probability)) return TRUE + crit_effect(attacker, defender, armor_block, damage_type, damage) + + experience_earned *= 2 //Double our experience gain on a crit hit + + playsound(defender, 'sound/effects/coin2.ogg', 40, TRUE) + new /obj/effect/temp_visual/crit(get_turf(defender)) + skill_experience_adjustment(attacker, experience_earned) //double experience for a successful crit + + return TRUE + +/// Our crit effect. For normal boxing, this applies a stagger, then applies a knockout if they're staggered. Other types of boxing apply different kinds of effects. +/datum/martial_art/boxing/proc/crit_effect(mob/living/attacker, mob/living/defender, armor_block = 0, damage_type = STAMINA, damage = 0) if(defender.get_timed_status_effect_duration(/datum/status_effect/staggered)) defender.visible_message( span_danger("[attacker] knocks [defender] out with a haymaker!"), @@ -189,14 +209,6 @@ to_chat(attacker, span_danger("You stagger [defender] with a haymaker!")) log_combat(attacker, defender, "staggered (boxing) ") - experience_earned *= 2 //Double our experience gain on a crit hit - - playsound(defender, 'sound/effects/coin2.ogg', 40, TRUE) - new /obj/effect/temp_visual/crit(get_turf(defender)) - skill_experience_adjustment(attacker, experience_earned) //double experience for a successful crit - - return TRUE - /// Returns whether whoever is checked by this proc is complying with the rules of boxing. The boxer cannot block non-boxers, and cannot apply their scariest moves against non-boxers. /datum/martial_art/boxing/proc/honor_check(mob/living/possible_boxer) if(!honorable_boxer) @@ -254,8 +266,9 @@ return NONE if(istype(attacker) && boxer.Adjacent(attacker)) - attacker.apply_damage(10, STAMINA) + attacker.apply_damage(10, default_damage_type) boxer.apply_damage(5, STAMINA) + perform_extra_effect(boxer, attacker) boxer.visible_message( span_danger("[boxer] [block_text]s [attack_text]!"), @@ -271,6 +284,8 @@ return FALSE return ..() +// Boxing Variants! + /// Evil Boxing; for sick, evil scoundrels. Has no honor, making it more lethal (therefore unable to be used by pacifists). /// Grants Strength and Stimmed to speed up any experience gain. @@ -281,6 +296,68 @@ honorable_boxer = FALSE boxing_traits = list(TRAIT_BOXING_READY, TRAIT_STRENGTH, TRAIT_STIMMED) +/// Hunter Boxing: for the uncaring, completely deranged one-spacer ecological disaster. +/// The honor check accepts boxing ready targets, OR various biotypes as valid targets. Uses a special crit effect rather than the standard one (against monsters). +/// I guess technically, this allows for lethal boxing. If you want. +/datum/martial_art/boxing/hunter + name = "Hunter Boxing" + id = MARTIALART_HUNTER_BOXING + pacifist_style = FALSE + default_damage_type = BRUTE + boxing_traits = list(TRAIT_BOXING_READY) + /// The mobs we are looking for to pass the honor check + var/honorable_mob_biotypes = MOB_BEAST | MOB_SPECIAL | MOB_PLANT | MOB_BUG + /// Our crit shout words. First word is then paired with a second word to form an attack name. + var/list/first_word_strike = list("Extinction", "Brutalization", "Explosion", "Adventure", "Thunder", "Lightning", "Sonic", "Atomizing", "Whirlwind", "Tornado", "Shark", "Falcon") + var/list/second_word_strike = list(" Punch", " Pawnch", "-punch", " Jab", " Hook", " Fist", " Uppercut", " Straight", " Strike", " Lunge") + +/datum/martial_art/boxing/hunter/honor_check(mob/living/possible_boxer) + if(HAS_TRAIT(possible_boxer, TRAIT_BOXING_READY)) + return TRUE + + if(possible_boxer.mob_biotypes & MOB_HUMANOID && !istype(possible_boxer, /mob/living/simple_animal/hostile/megafauna)) //We're after animals, not people. Unless they want to box. (Or a megafauna) + return FALSE + + if(possible_boxer.mob_biotypes & honorable_mob_biotypes) //We're after animals, not people + return TRUE + + return FALSE //rather than default assume TRUE, we default assume FALSE. After all, there could be mobs that are none of our biotypes and also not humanoid. By default, they would be valid for being boxed if TRUE. + +// Our hunter boxer applies a rebuke and double damage against the target of their crit. If the target is humanoid, we just perform our regular crit effect instead. + +/datum/martial_art/boxing/hunter/crit_effect(mob/living/attacker, mob/living/defender, armor_block = 0, damage_type = STAMINA, damage = 0) + if(defender.mob_biotypes & MOB_HUMANOID && !istype(defender, /mob/living/simple_animal/hostile/megafauna)) + return ..() //Applies the regular crit effect if it is a normal human, and not a megafauna + + var/first_word_pick = pick(first_word_strike) + var/second_word_pick = pick(second_word_strike) + + defender.visible_message( + span_danger("[attacker] knocks the absolute bajeezus out of [defender] utilizing the terrifying [first_word_pick][second_word_pick]!!!"), + span_userdanger("You have the absolute bajeezus knocked out of you by [attacker]!!!"), + span_hear("You hear a sickening sound of flesh hitting flesh!"), + COMBAT_MESSAGE_RANGE, + attacker, + ) + to_chat(attacker, span_danger("You knock the absolute bajeezus out of [defender] out with the terrifying [first_word_pick][second_word_pick]!!!")) + if(ishuman(attacker)) + var/mob/living/carbon/human/human_attacker = attacker + human_attacker.force_say() + human_attacker.say("[first_word_pick][second_word_pick]!!!", forced = "hunter boxing enthusiastic battlecry") + defender.apply_status_effect(/datum/status_effect/rebuked) + defender.apply_damage(damage * 2, default_damage_type, BODY_ZONE_CHEST, armor_block) //deals double our damage AGAIN + attacker.reagents.add_reagent(/datum/reagent/medicine/omnizine/godblood, 3) //Get a little healing in return for a successful crit + log_combat(attacker, defender, "hunter crit punched (boxing)") + +// Our hunter boxer speeds up their attacks when completing a combo against a valid target, and does a sizable amount of extra damage. + +/datum/martial_art/boxing/hunter/perform_extra_effect(mob/living/attacker, mob/living/defender) + if(defender.mob_biotypes & MOB_HUMANOID && !istype(defender, /mob/living/simple_animal/hostile/megafauna)) + return // Does not apply to humans (who aren't megafauna) + + attacker.changeNext_move(CLICK_CD_RAPID) + defender.apply_damage(rand(15,20), default_damage_type, BODY_ZONE_CHEST) + #undef LEFT_RIGHT_COMBO #undef RIGHT_LEFT_COMBO #undef LEFT_LEFT_COMBO diff --git a/code/game/objects/structures/icemoon/cave_entrance.dm b/code/game/objects/structures/icemoon/cave_entrance.dm index 4401b87d23eca..6efa671875915 100644 --- a/code/game/objects/structures/icemoon/cave_entrance.dm +++ b/code/game/objects/structures/icemoon/cave_entrance.dm @@ -178,7 +178,8 @@ GLOBAL_LIST_INIT(ore_probability, list( if(16) new /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/doom(loc) if(17) - new /obj/item/reagent_containers/cup/glass/drinkingglass/filled/nuka_cola(loc) + new /obj/item/clothing/gloves/fingerless/punch_mitts(loc) + new /obj/item/clothing/head/cowboy(loc) if(18) new /obj/item/soulstone/anybody(loc) if(19) diff --git a/code/modules/clothing/gloves/punch_mitts.dm b/code/modules/clothing/gloves/punch_mitts.dm new file mode 100644 index 0000000000000..07d93d5ab021c --- /dev/null +++ b/code/modules/clothing/gloves/punch_mitts.dm @@ -0,0 +1,24 @@ +/obj/item/clothing/gloves/fingerless/punch_mitts + name = "punching mitts" + desc = "Fingerless gloves with nasty spikes attached. Allows the wearer to utilize the ill-reputed fighting technique known as Hunter Boxing. The style \ + allows the user to punch wildlife rapidly to death. Supposedly, this is an incredible workout, but few people are insane enough to attempt to \ + punch every dangerous creature they encounter in the wild to death with their bare hands. Also kinda works against humanoids as well. \ + Not that you would... right?" + icon_state = "punch_mitts" + body_parts_covered = HANDS|ARMS + resistance_flags = LAVA_PROOF | FIRE_PROOF + armor_type = /datum/armor/gloves_mitts + +/obj/item/clothing/gloves/fingerless/punch_mitts/Initialize(mapload) + . = ..() + + AddComponent(/datum/component/martial_art_giver, /datum/martial_art/boxing/hunter) + +/datum/armor/gloves_mitts + melee = 25 + bullet = 5 + laser = 5 + energy = 5 + bomb = 100 + fire = 100 + acid = 30 diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index a553415176ea5..f833e15d3f3de 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -18,7 +18,7 @@ /obj/structure/closet/crate/necropolis/tendril/attackby(obj/item/item, mob/user, params) if(!istype(item, /obj/item/skeleton_key) || spawned_loot) return ..() - var/loot = rand(1,20) + var/loot = rand(1,21) var/mod switch(loot) if(1) @@ -71,6 +71,9 @@ new /obj/item/bedsheet/cult(src) if(20) new /obj/item/clothing/neck/necklace/memento_mori(src) + if(21) + new /obj/item/clothing/gloves/fingerless/punch_mitts(src) + new /obj/item/clothing/head/cowboy(src) if(!contents.len) to_chat(user, span_warning("[src] makes a clunking sound as you try to open it. You feel compelled to let the gods know! (Please open an adminhelp and try again!)")) CRASH("Failed to generate loot. loot number: [loot][mod ? "subloot: [mod]" : null]") diff --git a/code/modules/mob/living/basic/lavaland/legion/legion.dm b/code/modules/mob/living/basic/lavaland/legion/legion.dm index 1abd916461bb8..12bf6555d97d4 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion.dm @@ -10,7 +10,7 @@ icon_living = "legion" icon_dead = "legion" icon_gib = "syndicate_gib" - mob_biotypes = MOB_ORGANIC|MOB_HUMANOID + mob_biotypes = MOB_ORGANIC|MOB_SPECIAL|MOB_UNDEAD basic_mob_flags = DEL_ON_DEATH speed = 3 maxHealth = 75 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 79efa83e0b33a..817845ef56882 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm @@ -65,7 +65,7 @@ if(gps_name && true_spawn) AddComponent(/datum/component/gps, gps_name) ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) - add_traits(list(TRAIT_NO_TELEPORT, TRAIT_MARTIAL_ARTS_IMMUNE), MEGAFAUNA_TRAIT) + add_traits(list(TRAIT_NO_TELEPORT), MEGAFAUNA_TRAIT) grant_actions_by_list(attack_action_types) /mob/living/simple_animal/hostile/megafauna/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) 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 3b8eb1eb8af23..98e404934f263 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 @@ -27,7 +27,7 @@ Difficulty: Medium icon_living = "miner" icon = 'icons/mob/simple/broadMobs.dmi' health_doll_icon = "miner" - mob_biotypes = MOB_ORGANIC|MOB_HUMANOID + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_SPECIAL light_color = COLOR_LIGHT_GRAYISH_RED speak_emote = list("roars") speed = 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 85a0ec089be4f..2e2eba289d72c 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 @@ -18,7 +18,7 @@ Difficulty: Extremely Hard attack_verb_continuous = "pummels" attack_verb_simple = "pummels" attack_sound = 'sound/weapons/sonic_jackhammer.ogg' - mob_biotypes = MOB_ORGANIC|MOB_HUMANOID + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_SPECIAL light_color = COLOR_LIGHT_GRAYISH_RED movement_type = GROUND weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE) diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi index b62b6a0a8ee58..449be68d4e531 100644 Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index 4739498c16426..a4549f9e74b3b 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 50f46f5a547de..f6c90844e0c29 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3867,6 +3867,7 @@ #include "code\modules\clothing\gloves\costume.dm" #include "code\modules\clothing\gloves\insulated.dm" #include "code\modules\clothing\gloves\plasmaman.dm" +#include "code\modules\clothing\gloves\punch_mitts.dm" #include "code\modules\clothing\gloves\special.dm" #include "code\modules\clothing\gloves\tacklers.dm" #include "code\modules\clothing\head\_head.dm"