Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow using stronger bows at penalty #1501

Merged
merged 10 commits into from
Jun 7, 2022

Conversation

chaosvolt
Copy link
Member

@chaosvolt chaosvolt commented May 1, 2022

Summary

SUMMARY: Balance "Make bow strength requirement a soft limit, allowing you to fire stronger bows at penalty"

Purpose of change

A while ago I wanted to set it up so that the strength requirement of bows is a soft one instead of a hard one, with penalties that scale based on how much strength you're missing relative to the weapon's requirement.

Describe the solution

  1. Set it so Character::meets_stat_requirements waives strength requirement if ye olden STR_DRAW flag is present. Instead, a separate check in ranged::gunmode_checks_common prevents firing if you have less than half the strength needed.
  2. Per request, set up a tier set of penalties for bows based on how severely understrength you are. As you get weaker and weaker the penalties get worse, and more penalties added, in stages until the above effect leaves you unable to use your weapon at all.
  3. Damage scales down in two stages, with item::gun_info showing damage multiplier and player::fire_gun actually implementing it on firing. The first tier of insufficient strength reduces damage and range by 25%. Below 75% strength it jumps up to a 50% penalty, also adding a dispersion penalty.
  4. Fixed up item::gun_range so that the old unused STR_DRAW flag actually works.
  5. Set it so that player::get_weapon_dispersion adds a dispersion penalty that kicks in at the second tier of penalty,
  6. Set it so the strength requirement listed on the item's info display will also summarize how bad the penalty is if your strength is lower than the requirement, also providing a more visible hint that it's still usable. Per request, it displays different messages summarizing the penalties with different text colors.
  7. MISC: Found out that the stamina cost that's supposed to be for drawing a bow was backwards, restoring stamina instead of draining it. Fixed that.
  8. Added STR_DRAW back to flag JSON, with it explaining that you can fire the weapon at penalty.
  9. Added the STR_DRAW flag to all bows.
  10. Set it so compound bow also scales its base range up or down to the same extent its damage does.
  11. Updated woodbow in Magiclysm, the only bow-type weapon in mods to not already have the STR_DRAW flag.

Describe alternatives you've considered

  1. Early on I couldn't figure out how to implement the actual damage reduction, so I was going to just make the stamina cost for firing also increase if you're under-strength, as a dirty hack to justify not having to mess with damage. Now that it does correctly adjust damage, it seemed a bit pointless and inane to drain half your stamina bar to deal like 5 damage with a greatbow when you use it at very low strength.
  2. Originally it applied all three penalties at once, scaling lineraly in intensity exactly tied to how understrength you were compared to the bow's requirements, with it allowing you to fire even at the lowest possible strength (as alluded to in the above alternative). It was requested that I stagger the effects out into progressively escalating tiers of penalties.

Testing

  1. Compiled and load tested.
  2. Tested setting a bow to have strength requirement but without the flag, you still can't fire it.
  3. Tested what the item UI says with different strength values, confirming the listed range, damage multiplier, and requirement info was as expected.
  4. Tested a bow with the flag and insufficient strength, range is shown as less than the default and I can actually fire it out to that range.
  5. Set strength to above the requirement, confirmed I get full range and 1x multiplier.
  6. Shot a bow while just barely strong enough to fire it, confirmed it does far less damage.
  7. Ran affected JSON through linter and ran affected C++ files through astyle.

Additional context

image

Archery damage/range/dispersion penalties, ordinary character:

Item Str Requirement 4 Str 6 Str 8 Str 10 Str 12 Str 14 Str 16 Str
Compound bow (low) 7 50%/50%/200% 75%/75% none none none none none
Short bow 8 50%/50%/200% 75%/75% none none none none none
Longbow 9 Can't Use 50%/50%/200% 75%/75% none none none none
Compound bow (med) 9 Can't Use 50%/50%/200% 75%/75% none none none none
Compound bow (high) 11 Can't Use 50%/50%/200% 50%/50%/200% 75%/75% none none none
Composite bow 12 Can't Use 50%/50%/200% 50%/50%/200% 75%/75% none none none
Greatbow 15 Can't Use Can't Use 50%/50%/200% 50%/50%/200% 75%/75% 75%/75% none

@Proxiehunter
Copy link

Proxiehunter commented May 1, 2022

I do think this makes bows much more viable in general. I used to start with bows and move to a repeating crossbow as soon as I could because the big problem with bows was if you take a few hits suddenly you can't fire your bow at all. But any crossbow besides a repeater reloads and fires so slowly you can rarely get more than a single shot before you have to drop it and go melee.

You might want to consider including the self bow because I've had the issue as low as that if I've been caught in a bad spot or just hit by a wasp a couple times.

@chaosvolt
Copy link
Member Author

You might want to consider including the self bow because I've had the issue as low as that if I've been caught in a bad spot or just hit by a wasp a couple times.

Self bows in BN currently have no strength requirement, unlike in DDA.

@Proxiehunter
Copy link

You might want to consider including the self bow because I've had the issue as low as that if I've been caught in a bad spot or just hit by a wasp a couple times.

Self bows in BN currently have no strength requirement, unlike in DDA.

I hadn't noticed that. Maybe I'm misremembering and it was a short bow then. Anyway, thanks for this fix because as I said the old way made bows kind of risky to use.

chaosvolt and others added 2 commits May 1, 2022 10:04
@Coolthulhu Coolthulhu self-assigned this May 2, 2022
@Coolthulhu
Copy link
Member

Had a big comment typed out, then my power died...

The current penalties are a bit too linear. I'd rather see something more quantified, with bow requirements being more strict.
or example:

  • Meets the requirements
  • Meets 3/4 of the requirements - 75% damage, no other penalties - can happen if you get debuffed, but if it's not from debuffs, it shouldn't be "potentially optimal". Could be "yellow" in requirements UI.
  • Meets 1/2 of the requirements - 50% damage, 50% range, 200% dispersion - either heavy debuffing or you really shouldn't be using this bow. "Red" in requirements.
  • Doesn't meet 1/2 - can't try.

I mostly want to avoid cases where a "stronger" bow, above your str, is still better than properly sized one.

I like the line in requirements. I think you can add colors either by using tags or colorize function. Not 100% sure, but worth a try.

@chaosvolt
Copy link
Member Author

Hmm, worth a try tomorrow perhaps. Though "can't try" does mean we'd be putting back in a hard limit, just a much more generous one, which I guess is okay.

@chaosvolt
Copy link
Member Author

How should these penalties scale? i.e. when do they actually start to kick in, and how extreme should they get? If I'm reading it right, your idea would be something like:

  1. Damage scales down linearly from 100% strength as current.
  2. Range and dispersion start to get below normal once you hit 75% strength, but ramp up faster until they reach 50% at 50% strength.
  3. Can't fire without at least half the required strength.

@Coolthulhu
Copy link
Member

I'd say no scaling, just breakpoints.

@chaosvolt
Copy link
Member Author

chaosvolt commented May 5, 2022

I'd say no scaling, just breakpoints.

Ah, hmm. So basically if I'm reading the earlier post right:

  1. If strength is 100% or more, no debuffs.
  2. If strength is 76-99% of the requirement, 75% damage.
  3. If strength is 50-75% of the requirement, 50% damage and range, 200% dispersion.
  4. If strength is 49% or less, no firing allowed.

I think I get the rough idea, though the breakpoint between 75% and 76% strength will carry a lot of debuffs with it. Will tinker with it when I get the chance today, likely will be out and about.

src/item.cpp Outdated
req.push_back( string_format( "%s %d", _( "strength" ), get_min_str() ) );
avatar &viewer = get_avatar();
int weapon_str = get_min_str();
if( has_flag( flag_STR_DRAW ) && viewer.has_trait( trait_PROF_CHURL ) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arcane bonus, badly documented.

@Coolthulhu
Copy link
Member

Display shows new values, but game still uses the old ones.

@chaosvolt
Copy link
Member Author

Oh hecc, I thought I fixed all those, I'll tinker with that in a bit. Regarding the Churl mechanic, should I just remove it, or write a mention into the description of the Churl trait?

@Coolthulhu
Copy link
Member

Oh hecc, I thought I fixed all those, I'll tinker with that in a bit. Regarding the Churl mechanic, should I just remove it, or write a mention into the description of the Churl trait?

For now, remove.
If it was good enough, we could have a practiced bowman trait or something. Churl would just start with it.

@chaosvolt
Copy link
Member Author

That works then.

@chaosvolt
Copy link
Member Author

Display shows new values, but game still uses the old ones.

So I'm looking at this, and I don't see any case of this?

  1. item::gun_range uses ranged::get_str_draw_range_penalty instead of ranged::get_str_draw_penalty.
  2. player::fire_gun uses ranged::get_str_draw_damage_penalty instead of ranged::get_str_draw_penalty.
  3. player::get_weapon_dispersion uses ranged::get_str_draw_dispersion_penalty instead of ranged::get_str_draw_penalty

Am I missing something, or is a case where I should rename the functions to be less confusing?

@@ -3326,7 +3327,7 @@ bool Character::meets_skill_requirements( const construction &con ) const

bool Character::meets_stat_requirements( const item &it ) const
{
return get_str() >= it.get_min_str() &&
return ( it.has_flag( flag_STR_DRAW ) || get_str() >= it.get_min_str() ) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use a check for 0.5 of min.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It checks for this at a different part of the firing process, to allow for it to print a different failure message.

_( "strength" ), get_min_str() ) );
} else {
req.push_back( string_format( "%s %d <color_yellow>(Damage 0.9x)</color>", _( "strength" ),
get_min_str() ) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This 0.9 is too "graded". The strength requirements are supposed to be the minimum, anything below is already low, not "almost optimal".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be a better multiplier to use?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Treat full minimum requirements as "barely enough". Below that, 0.75 multipliers are good - 0.75 means it's still usable, but with a noticeable dip in power. Good enough to finish a fight, but you shouldn't be using the bow if your base strength is below minimum.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay. Should all three stat penalties kick in and be 0.75x when below 100% strength, or should they still kick in one per stage (damage, damage+range, damage+range+dispersion) as they do now?

@Coolthulhu Coolthulhu merged commit b2083d2 into cataclysmbnteam:upload Jun 7, 2022
@Coolthulhu
Copy link
Member

I tested something I expected not to work: stat loss causing inability to use the weapon at range.
It works, as in, it properly prevents the player from using the weapon when its range is clipped by your strength.

@chaosvolt
Copy link
Member Author

chaosvolt commented Jun 7, 2022

I tested something I expected not to work: stat loss causing inability to use the weapon at range.
It works, as in, it properly prevents the player from using the weapon when its range is clipped by your strength.

That was already a feature of the existing stat requirements if I recall. The stat penalties for "strength below requirement but still 50% or more" should also update correctly as your stats change since they're checked at the moment of firing, but I don't recall if I double-checked that.

@chaosvolt chaosvolt deleted the str-fire-rework branch June 7, 2022 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants