Skip to content

Commit

Permalink
Drunken Brawlening: Intoxication alters your unarmed effectiveness, b…
Browse files Browse the repository at this point in the history
…artenders are stronger fighters while drunk, deterministic stagger combo is back (your average assistant doesn't get knockdowns) (tgstation#85449)

## About The Pull Request

### Intoxication and Punching

Being drunk juuuust enough allows you to land stronger punches and take
punches a little more easily.

However, being TOO drunk makes you WORSE at these things, and makes your
unarmed accuracy an unarmed PENALTY. Don't get drunk if you can't hold
your liquor.

However, fighting drunk makes you really sick, so be careful as to not
suddenly start vomiting everywhere.

### Drunken Brawler

Bartenders are now drunken brawlers. They gain additional punching
prowess if they're ever intoxicated, it does not matter how much nor do
they ever suffer a penalty as a result of being TOO drunk.

The more damage the bartender has taken, the stronger they hit back.
(added by recommendation from WalterTruck) I have to mess the scaling on
this more.

### Stagger Combo/Unarmed Combos

The stagger combo is back, but significantly less stun heavy except on
the extreme ends of unarmed upgrading.

When your opponent has been sufficiently damaged enough, staggered and
doesn't have any riot protection gear on, you can inflict additional
status effects when you punch an opponent.

The necessary value for this effect is: Half the target's Brute and Burn
damage combined exceeds a value of: Limb accuracy + armor block (min.
40. max 200)

While the thresholds are more deterministic, the effects are random. The
better you are at punching, the better the effect, but the higher your
targets armor, the weaker the effect. All effects are positive for the
attacker and negative for the target.

The dice roll is such; (a roll between -20 to 20) + limb accuracy -
armor block

| Stage/Value | Effect |
| ------------- | ------------- |
| Stage 1 (-Infinity to 0  | Staggered for 1 second |
| Stage 2 (1 to 10)  | Eye Blur for 5 seconds |
| Stage 3 (11 to 30)  | Eye Blur, Dizzying, Confusion for 5 seconds |
| Stage 4 (31 to 40)  | Blindness, Dizzying, Confusion for 5 seconds |
| Stage 5 (41 to 45)  | Knockdown for 4 seconds |
| Stage 6 (46 to Infinity) | Knockdown for 4 seconds, 5 Brute with huge
wound chance |

Stages 5 and 6 are not possible to reach for roundstart humans who
aren't intoxicated. It is almost impossible to get high effects against
someone who is in full security gear as a roundstart human

### Minor Changes

Any unarmed related thresholds or values that would use Stamina damage
now use half of the total of Burn and Brute damage on the relevant
individual. This affects punch accuracy, the threshold for getting a
stagger combo, and the threshold for someone being more vulnerable to
grabs.

## Why It's Good For The Game

I just really wanted to add some drunken brawling/drunk fist style
martial art stuff because I thought it would be fun, and bar brawls are
where most people start fist fights. It's thematically entertaining.

The bartender, by extension, should be pretty proficient at this kind of
brawling. It also works out great when working with chefs to beat people
up with their fists in their own, more unrefined style.

The situation with the unarmed knockdown/stamina pr was kind of a mess,
since at the time I was already going to take it out after discussing
things with Walter and we were working out some alternatives together.
But uh...well, it wasn't to be. Particularly, there was a lot of stuff
in unarmed fighting that used Stamina damage that didn't actually get
removed at all. So this cleans that up.

I said I'd find a good alternative down the line to fill that gap, and
this is it. For your run-of-the-mill fistfights, there are no random
knockdowns. It's only when you are actually trying to brawl with a
cybernetically enhanced human that this kind of thing starts to crop up.
Or your opponent is a golem. Or you are both really drunk (and thus
everyone starts vomiting because they're getting beaten up)

The average assistant beating up another assistant is at best going to
inflict some eye blurring and dizziness, assuming the fight even lasts
that long. But this should be sufficient to create space to escape, or
even meaningfully disable someone who might simply be invading your
department. It is much less helpful against a more sufficiently geared
opponent.

The main reason for focusing on this is to give the average joe some
kind of way for a heel turn in the event they're having to scuffle with
departmental invaders or escape some determined opponent. It does not,
however, allow them to manhandle a nuclear operative in an elite suit
while our would-be hero is entirely butt-naked and drunk. Not that they
shouldn't try, that's funny as hell.

Thus, the effects chosen are more useful for escaping and befuddlement
than necessarily stopping the fight outright. If you have improved arms,
your arms are weapons and start to act like them, so you start seeing
more significant results.

It is also a nice thematic tie to unarmed's zany cousin; tackling, since
the randomized effects are borrowing the logic form there, and it is
cool to have those tied a bit closer.

## Changelog
:cl:
add: Drunken fist fighting now has bonuses and penalties based on how
intoxicated you are. Controlled liquor intake could make you a better
brawler. Though you might vomit if you go too hard.
add: Bartenders are now Drunken Brawlers. If they're drunk at all (no
matter how drunk), they're stronger at fist fighting.
add: Reintroduces the deterministic stagger combo. The effects of the
combo are more varied, and based on attacker unarmed effectiveness and
the defender's armor. Read the PR for more details. It's complicated.
qol: Unarmed effects that would utilize stamina values now use a split
of half brute, half burn to determine outcomes or for meeting
thresholds. This affects; punch accuracy, stagger combo thresholds and
grab vulnerability thresholds.
/:cl:
  • Loading branch information
necromanceranne authored Aug 17, 2024
1 parent eb03297 commit 0b68257
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 3 deletions.
3 changes: 3 additions & 0 deletions code/__DEFINES/traits/declarations.dm
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Trait that determines vulnerability to being stunned from a shove
#define TRAIT_STUN_ON_NEXT_SHOVE "stun on next shove"

/// Trait that determines whether our mob gains more strength from drinking during a fist fight
#define TRAIT_DRUNKEN_BRAWLER "drunken brawler"

// METABOLISMS
// Various jobs on the station have historically had better reactions
// to various drinks and foodstuffs. Security liking donuts is a classic
Expand Down
1 change: 1 addition & 0 deletions code/_globalvars/traits/_traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_DOUBLE_TAP" = TRAIT_DOUBLE_TAP,
"TRAIT_DREAMING" = TRAIT_DREAMING,
"TRAIT_DRINKS_BLOOD" = TRAIT_DRINKS_BLOOD,
"TRAIT_DRUNKEN_BRAWLER" = TRAIT_DRUNKEN_BRAWLER,
"TRAIT_DUMB" = TRAIT_DUMB,
"TRAIT_DWARF" = TRAIT_DWARF,
"TRAIT_EASILY_WOUNDED" = TRAIT_EASILY_WOUNDED,
Expand Down
2 changes: 2 additions & 0 deletions code/modules/jobs/job_types/bartender.dm
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
glasses = /obj/item/clothing/glasses/sunglasses/reagent
shoes = /obj/item/clothing/shoes/laceup

skillchips = list(/obj/item/skillchip/drunken_brawler)

/datum/outfit/job/bartender/post_equip(mob/living/carbon/human/H, visualsOnly)
. = ..()

Expand Down
9 changes: 9 additions & 0 deletions code/modules/library/skill_learning/skillchip.dm
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,15 @@
activate_message = span_notice("You think of your favourite food and realise that you can rotate its flavour in your mind.")
deactivate_message = span_notice("You feel your food-based mind palace crumbling...")

/obj/item/skillchip/drunken_brawler
name = "F0RC3 4DD1CT10N skillchip"
auto_traits = list(TRAIT_DRUNKEN_BRAWLER)
skill_name = "Drunken Unarmed Proficiency"
skill_description = "When intoxicated, you gain increased unarmed effectiveness."
skill_icon = "wine-bottle"
activate_message = span_notice("You honestly could do with a drink. Never know when someone might try and jump you around here.")
deactivate_message = span_notice("You suddenly feel a lot safer going around the station sober... ")

/obj/item/skillchip/musical
name = "\improper Old Copy of \"Space Station 13: The Musical\""
desc = "An old copy of \"Space Station 13: The Musical\", \
Expand Down
95 changes: 93 additions & 2 deletions code/modules/mob/living/carbon/human/_species.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1034,14 +1034,32 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/damage = rand(attacking_bodypart.unarmed_damage_low, attacking_bodypart.unarmed_damage_high)
var/limb_accuracy = attacking_bodypart.unarmed_effectiveness

// In a brawl, drunkenness can make you swing more wildly and with more force, and thus catch your opponent off guard, but it could also totally throw you off if you're too intoxicated
// But god is it going to make you sick moving too much while drunk
var/user_drunkenness = user.get_drunk_amount()

if(user_drunkenness && HAS_TRAIT(user, TRAIT_DRUNKEN_BRAWLER)) // Drunken brawlers only need to be intoxicated, doesn't matter how much
limb_accuracy += clamp((user.getFireLoss() + user.getBruteLoss()) * 0.5, 10, 200)
damage += damage * clamp((user.getFireLoss() + user.getBruteLoss()) / 100, 0.3, 2) //Basically a multiplier of how much extra damage you get based on how low your health is overall. A floor of about a 30%.
var/drunken_martial_descriptor = pick("Drunken", "Intoxicated", "Tipsy", "Inebriated", "Delirious", "Day-Drinker's", "Firegut", "Blackout")
atk_verb = "[drunken_martial_descriptor] [atk_verb]"

else if(user_drunkenness > 30 && user_drunkenness < 60)
limb_accuracy *= 1.2
user.adjust_disgust(2)

else if(user_drunkenness >= 60)
limb_accuracy = -limb_accuracy // good luck landing a punch now, you drunk fuck
user.adjust_disgust(5)

var/obj/item/bodypart/affecting = target.get_bodypart(target.get_random_valid_zone(user.zone_selected))

var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases
if(attacking_bodypart.unarmed_damage_low)
if((target.body_position == LYING_DOWN) || HAS_TRAIT(user, TRAIT_PERFECT_ATTACKER) || staggered) //kicks and attacks against staggered targets never miss (provided your species deals more than 0 damage)
if((target.body_position == LYING_DOWN) || HAS_TRAIT(user, TRAIT_PERFECT_ATTACKER) || staggered || user_drunkenness && HAS_TRAIT(user, TRAIT_DRUNKEN_BRAWLER)) //kicks and attacks against staggered targets never miss (provided your species deals more than 0 damage). Drunken brawlers while drunk also don't miss
miss_chance = 0
else
miss_chance = clamp(UNARMED_MISS_CHANCE_BASE - limb_accuracy + user.getStaminaLoss() + (user.getBruteLoss()*0.5), 0, UNARMED_MISS_CHANCE_MAX) //Limb miss chance + various damage. capped at 80 so there is at least a chance to land a hit.
miss_chance = clamp(UNARMED_MISS_CHANCE_BASE - limb_accuracy + (user.getFireLoss()*0.5 + user.getBruteLoss()*0.5), 0, UNARMED_MISS_CHANCE_MAX) //Limb miss chance + various damage. capped at 80 so there is at least a chance to land a hit.

if(!damage || !affecting || prob(miss_chance))//future-proofing for species that have 0 damage/weird cases where no zone is targeted
playsound(target.loc, attacking_bodypart.unarmed_miss_sound, 25, TRUE, -1)
Expand All @@ -1053,6 +1071,20 @@ GLOBAL_LIST_EMPTY(features_by_species)

var/armor_block = target.run_armor_check(affecting, MELEE)

// In a brawl, drunkenness is a boon if you're a bit drunk but not too much. Else you're easier to hit.
// But, generally, getting hit while drunk is probably a good way to start throwing up
var/target_drunkenness = target.get_drunk_amount()
if(target_drunkenness && HAS_TRAIT(target, TRAIT_DRUNKEN_BRAWLER)) // Drunken brawlers only need to be intoxicated, doesn't matter how much
armor_block += 20

else if(target_drunkenness > 30 && target_drunkenness < 60)
armor_block += 10
target.adjust_disgust(2)

else if(target_drunkenness >= 60)
armor_block *= 0.5
target.adjust_disgust(5)

playsound(target.loc, attacking_bodypart.unarmed_attack_sound, 25, TRUE, -1)

if(grappled && attacking_bodypart.grappled_attack_verb)
Expand Down Expand Up @@ -1080,6 +1112,65 @@ GLOBAL_LIST_EMPTY(features_by_species)
target.force_say()
log_combat(user, target, "punched")

// If our target is staggered and has sustained enough damage, we can apply a randomly determined status effect to inflict when we punch them.
// The effects are based on the punching effectiveness of our attacker. Some effects are not reachable by the average human, and require augmentation to reach or being a species with a heavy punch effectiveness.
// Or they're just drunk enough.
if(HAS_TRAIT(target, TRAIT_BRAWLING_KNOCKDOWN_BLOCKED) || target.stat == DEAD) //If our target is dead or has specailized armor, there is no way to inflict these effects.
return

// If our target is staggered, the target's armor, minus our limb effectiveness sets the minimum necessary amount of damage sustained to cause an effect. Minimum 40, max 200 for sanity reasons
if(staggered && (target.getFireLoss()*0.5 + target.getBruteLoss()*0.5) >= min(armor_block - limb_accuracy, 40, 200))
stagger_combo(user, target, atk_verb, limb_accuracy, armor_block)

/// Handles the stagger combo effect of our punch. Follows the same logic as the above proc, target is our owner, user is our attacker.
/datum/species/proc/stagger_combo(mob/living/carbon/human/user, mob/living/carbon/human/target, atk_verb = "hit", limb_accuracy = 0, armor_block = 0)
// Randomly determines the effects of our punch. Limb accuracy is a bonus, armor block is a defense
var/roll_them_bones = rand(-20, 20) + limb_accuracy - armor_block

switch(roll_them_bones)
if (-INFINITY to 0) //Mostly a gimmie, this one just keeps them staggered briefly
target.adjust_staggered_up_to(1 SECONDS, 10 SECONDS)
target.visible_message(span_warning("[user]'s [atk_verb] briefly winds [target]!"), \
span_warning("You are briefly winded by [user]'s [atk_verb]!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] briefly winds [target]!"))

if (1 to 10)
target.adjust_eye_blur_up_to(5 SECONDS, 10 SECONDS)
target.visible_message(span_warning("[user]'s [atk_verb] hits [target] so hard, their eyes water! Ouch!"), \
span_warning("You are hit viciously by [user]'s [atk_verb], and your eyes begin to water!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] causes [target] to tear up!"))

if (11 to 30)
target.adjust_dizzy_up_to(5 SECONDS, 10 SECONDS)
target.adjust_eye_blur_up_to(5 SECONDS, 10 SECONDS)
target.adjust_confusion_up_to(5 SECONDS, 10 SECONDS)
target.visible_message(span_warning("[user]'s [atk_verb] hits [target] so hard, they are sent reeling in agony! Damn!"), \
span_warning("You are hit viciously by [user]'s [atk_verb], and everything becomes a dizzying blur!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] causes [target] to go stumbling about in a confuzed daze!"))

if(31 to 40)
target.adjust_dizzy_up_to(5 SECONDS, 10 SECONDS)
target.adjust_confusion_up_to(5 SECONDS, 10 SECONDS)
target.adjust_temp_blindness_up_to(5 SECONDS, 10 SECONDS)
target.visible_message(span_warning("[user]'s [atk_verb] hits [target] so hard, they are sent reeling blindly in agony! Goddamn!"), \
span_warning("You are hit viciously by [user]'s [atk_verb], and everything becomes a dizzying, blinding blur!"), span_hear("You hear a thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] causes [target] to go stumbling about in a confuzed, blind daze!"))

if (41 to 45)
target.apply_effect(4 SECONDS, EFFECT_KNOCKDOWN, armor_block)
target.visible_message(span_warning("[user]'s [atk_verb] hits [target] so hard, you knock them off their feet! Holy shit!"), \
span_warning("You are hit viciously by [user]'s [atk_verb] and sent toppling head over heels!"), span_hear("You hear a sickening thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] lands, and you send [target] sailing off their feet!"))

if (46 to INFINITY)
target.apply_effect(4 SECONDS, EFFECT_KNOCKDOWN, armor_block)
var/obj/item/bodypart/affecting = target.get_bodypart(target.get_random_valid_zone(user.zone_selected))
target.apply_damage(5, BRUTE, affecting, armor_block, wound_bonus = limb_accuracy * 2) //Mostly for the crunchy wounding effect than actually doing damage
target.visible_message(span_warning("[user]'s [atk_verb] hits [target] so hard, you hit them off their feet with a loud crunch! Fucking hell!"), \
span_warning("You are hit viciously by [user]'s [atk_verb], and suddenly feel an overwhelming pain as you topple head over heels!"), span_hear("You hear a sickening crack and a loud thud!"), COMBAT_MESSAGE_RANGE, user)
to_chat(user, span_warning("Your [atk_verb] lands, and [target] is sent crashing to the floor with the immense force! Good god!"))


/datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
if(user.body_position != STANDING_UP)
return FALSE
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,7 @@
/mob/living/resist_grab(moving_resist)
. = TRUE
//If we're in an aggressive grab or higher, we're lying down, we're vulnerable to grabs, or we're staggered and we have some amount of stamina loss, we must resist
if(pulledby.grab_state || body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_GRABWEAKNESS) || get_timed_status_effect_duration(/datum/status_effect/staggered) && getStaminaLoss() >= 30)
if(pulledby.grab_state || body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_GRABWEAKNESS) || get_timed_status_effect_duration(/datum/status_effect/staggered) && (getFireLoss()*0.5 + getBruteLoss()*0.5) >= 40)
var/altered_grab_state = pulledby.grab_state
if((body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_GRABWEAKNESS) || get_timed_status_effect_duration(/datum/status_effect/staggered)) && pulledby.grab_state < GRAB_KILL) //If prone, resisting out of a grab is equivalent to 1 grab state higher. won't make the grab state exceed the normal max, however
altered_grab_state++
Expand Down

0 comments on commit 0b68257

Please sign in to comment.