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

Liquid attacks can do damage, apply flags, apply effects #71584

Closed
wants to merge 96 commits into from

Conversation

fairyarmadillo
Copy link
Contributor

@fairyarmadillo fairyarmadillo commented Feb 7, 2024

Summary

Features "Liquid attacks can do damage, apply flags, damage items, and apply effects"

Purpose of change

edit: This PR is being split up. Part 1 (boomers) is now in #71964

#69555 was a step toward creating liquid attacks that actually respect what a character is wearing, but it still fell short as it was relying only on a simple wet protection check, and could only apply effects. Our game has the player getting splashed with all kinds of stuff pretty frequently, so it would be nice to have a better simulation.

Describe the solution

Creates the splash_attack() function, which simulates splashing a volume of liquid onto a character.

  • The liquid targets a body part and rolls coverage on each item on the bp, starting with the outermost.
  • Whenever the liquid rolls under an item's coverage, an amount of liquid equal to the average of that item's coverage and breathability is deducted from the total. Non-breathable items deflect more liquid, breathable items let more soak through.
  • When this happens, there is a chance the item will be affected by the liquid, proportional to the volume of liquid used in the attack. An item's breathability greatly increases the likelihood that it will be affected. Liquids can do damage (like acid), apply flags to clothes (like bile making them filthy), and optionally can ignite clothing (like napalm).
  • If any liquid remains, that amount continues on to the next layer to be potentially blocked, and so on until the amount either reaches zero or the liquid runs out of items and hits the character's skin.
  • When the liquid reaches the skin, it can deal damage (like boiling water) or apply an effect (like acid or boomer bile). The damage and intensity, as well as the likelihood of the effect being applied, are adjusted according to what percentage of the fluid reached the skin.
  • Monsters do not have armor to damage, nor do they have coverage or breathability. Instead, they will resist damage and effects according to their armor values.
  • Splash attacks do not work at all underwater
  • Being in deep water will automatically wash you off.

Expands Magic code to support splash attacks

  • Adds the DODGEABLE flag to the magic system. DODGEABLE spells can be completely evaded like any other attack. This is based on a contested roll of the spell's accuracy score vs the target's dodging ability, and consumes a dodge attempt as normal. Spells with this flag do not allow melee and dodge skill to mitigate damage as they can with normal spells.
  • The existing LIQUID flag now causes spells to use splash_attack() in place of dealing damage or applying effects directly.
  • Adds the LIQUID_DAMAGE_ARMOR flag to spells. If this is present, liquids will potentially use their damage number and type to damage armor according to the rules laid out in splash_attack().
  • Adds the LIQUID_DAMAGE_TARGET flag to spells. If this is present, liquids will damage the player according to the rules laid out in splash_attack().
  • Adds the MAKE_FILTHY flag to spells. If this is present, it can potentially apply the filthy flag to armor according to the rules laid out in splash_attack(). Currently doesn't work for non-liquid spells.
  • Adds dodge_training values to spell jsons. If these are non-zero, they will cap skill gain when a character dodges DODGEABLE spells. There is no effect on spells which lack the flag.
  • Adds liquid_volume values to spell jsons, which are used in splash_attack(). LIQUID spells without a defined volume will have no effect. liquid_volume has no effect on non-LIQUID spells.
  • LIQUID spells with defined body parts will always target those parts. If no parts are defined, they'll hit a random body part. This can include subparts.
  • field_chance now takes floats as well as integers.

Reworks boomers and huge boomers

  • All monsters are now slightly less likely to slip in bile. It was a little overtuned for them compared to the player before.
  • Huge boomers were never Huge, merely Large. They have been renamed to Big Boomers to avoid misleading players.
  • Boomers and Big Boomers now use splash_attack to vomit bile. They cast the same spell, but Big Boomers cast it at a higher level with greater range, frequency, and fluid volume.
  • Boomer gluttons use a different attack which was already a spell, and are mostly unchanged.
  • If the player dodges, nothing happens.
  • If the player is hit, the attack has a chance to hit the eyes relative to the boomer's melee skill. If they fail, it will hit another random body part instead.
  • Bile can make clothes filthy. It doesn't do this every time, but you don't want to get it on you.
  • If bile reaches your skin, it reacts with your sweat to make your scent much stronger for a short time. This makes boomers perform more like you may be used to in Left 4 Dead. Most of the early game zombies can't track by scent, so this is an effect that will become more dangerous later in the cataclysm.
  • If bile gets in your eyes, it functions as above and also blinds you and risks conjunctivitis, as it does now.
  • Both effects are very minorly deleterious to your lifestyle score. It's corpse bile, wear PPE! Every second that you have the effect, you have a 0.3% chance to lose one lifestyle point, giving you around a 10% chance to lose a lifestyle point if you've got the effect for the full 30 seconds. This is per body part, so having bile on multiple parts is multiplicative. Saprovores, Saprophages, and Eaters of the Dead are immune to this part of the effect.
  • Huge boomers now use the same attack, but have greater range, frequency, accuracy, and volume. Their previous glowing bile ability is being repurposed for a bioluminescent variation of the enemy. I'll do that in a later PR as I don't want to cram too much into this one.
  • The explosion that boomers, boomer gluttons, and huge boomers leaves creates a significantly bigger splash than their vomit attacks.
  • This changes boomers up a bit in terms of gameplay: their slippery bile presents an immediate hazard, but has more insidious long-term effects on your mood and lifestyle score. They also continue to serve as a force multiplier for scent-hunting zombies by luring them to your location.
  • Boomer filth chance for the vomit attack maxes out at 12.5% for a 110 breathability item and 5% vs a 0 breathability item. Big Boomer filth chance for the vomit attack maxes out at 25% vs a 110 breathability item and 6% vs a 0 breathability item. These attacks can be dodged.

Partially reworks acid-spitting zombies

  • Creates a new spell, acid_barf.
  • acid_barf replaces the old ACIDBARF melee-ranged acid attack. This spell scales, so stronger monsters can deliver more acid this way.
  • If the acid is blocked by any clothing or armor, it has a small chance to damage that item. As mentioned, this chance is lessened (but not removed) on items with low breathability, as the fluid splashes away and doesn't soak into the fabric.
  • The base damage is modified by the percentage of fluid remaining from the initial attack, and items resist being damaged by acid with their acid armor stat.
  • Since less acid reaches the next layer every time it encounters an item, the chance for items to be damaged and the amount of damage they will take drops significantly every layer
  • If acid reaches a character's skin or the integrated item they've replaced it with, they get the corroding effect. The intensity and chance for this to happen are modified by the amount of acid that hits them.
  • Corroding has been slightly upgraded. It has a 50% chance to deal 1 point of damage and 1 point of pain to the afflicted body part every second. This scales up to 2 damage at 4 and 5 intensity. Each level of intensity adds 5 seconds to corroding's duration, to a maximum of 5. The maximum damage it can deal at max intensity, if it somehow procs damage every single second, is 40, but the likely result of getting 5 stacks of corroding is that you'll take around 20 damage.
  • The corroding effect has a 0.01% chance of reducing your lifestyle score by 1 point for every second it's on your skin. This scales up by 0.1% per level of intensity. This comes out to about a a 4.5% chance to lose 1 lifestyle point if acid is on your skin for a full 30 seconds. Don't play with weird chemicals!
  • Slimy reduces the odds of taking damage or losing lifestyle to the corroding effect by 75%.
  • If acid gets in a character's eyes, they will be blinded. For now this is a temporary effect.
  • Acid zombies do not specifically aim for eyes the way boomers do. Maybe they'd like to, but just evolving to be able to contain all that acid is hard enough.
  • This begins the process of changing acid zombies from a "the floor is lava" enemy which could be circumvented with a single pair of shoes to a more general gear check.

Fixes and updates nonphysical armor

  • Environmental protection does not respect thickness. This is intended. It is however supposed to average protection across all material layers on an item. It looks like when armor was updated to have protection by body part, that was not carried over to that part of the function, meaning that an item that had one 2mm layer of rubber with 100% coverage was protecting less against environmental damage less than an item that had two 1mm layers of rubber with 100% coverage each. This has been fixed.
  • Acid was previously totally unable to damage worn items as it was defined as non-physical. Acid is now defined as physical, as it is an object (albeit a liquid) and needs to be able to interact with equipment to damage it.
  • Environmental protection was being factored in for liquid acid. This is no longer the case. Enviro armor is a rating from before we had breathability, and now mostly applies to gas/smoke/spore/temperature effects. It may still be appropriate for enviro to protect from something like an acid fog, but that could easily be defined as a new damage_type in json which derived all its properties from acid but is set to non-physical.
  • Acid is still flagged in json as both physical and environmental. This makes it so that attacks which deal acid damage do not respect armor thickness, as it is a liquid that simply splashes against the surface of the armor, rather than a solid object or force which can penetrate it. This is probably a model we can use for all liquid damage types going forward. For this reason, liquid acid should primarily damage characters via effects - acid's interactions with armor are best used to calculate whether it damages the armor, not the person inside of it.
  • When an attack attempts to damage armor durability, its chances to do so are reduced according to the number of body parts the armor covers. Acid mitigates this reduction by 33% (to a minimum of 1 in 2), as it's a liquid that spreads over the surface rather than a bullet or a knife trying to drill or slice a hole. Note that the resulting chance to damage durability is still very low unless the damage is obnoxiously high.

Describe alternatives you've considered

Once this is merged and there are no issues, the plan is as follows:

  • Allow fields to cast spells, and allow spells to target sub-bodyparts, so that we can jsonize field effects much better.
  • Write acid_spray, a replacement for the hardcoded counterattack that blistered horrors and corrosive zombies do.
  • Write acid_spit, a replacement for what corrosive zombies, spitter zombies, acid ants, giant snails, etc get. Essentially a long-ranged acid_barf.
  • Redo the bilious soldier zombie's acid dart to be a dodgeable spell (the dart) which procs a second spell (an acid splash, undodgeable) if it hits.
  • Allow spells to try to target specific body parts based on RNG, and hit randomly elsewhere if they don't make it.
  • Many materials may need their acid resistance increased, particularly vinyl, rubber, plastic, and treated leather.
  • It should be possible to wash acid or bile off of your skin with water that you have in a container.
  • Can acid damage items and corpses on the ground without lagging the game to hell? How about terrain and furniture?
  • Acid fumes ought to be a thing.
  • Do a mini armor audit. Lots of stuff should have vinyl or treated leather but doesn't.
  • Fields should have burn_data so that gasoline and napalm can be fields. If we had that, flamethrowers could stop being a weird gun that shoots fire bullets and become a thing that sprays a line of burning liquid like irl.
  • Is there a good way to change how acid protection is displayed when examining a piece of armor? The numbers shown to the player are currently the item's resistance to acid, and will not protect the wearer. Maybe it should be on its own line?

After that, the sky's the limit. I think slimes could probably do something interesting with this - imagine a boss slime in some evil slime lair that splashes you with a fluid that gives you slime mutations in an attempt to assimilate you. Free mutations until you get one too many and cease to exist. Or how about vombie, the zombie that vomits diseases on you? At the very least we need to make the sewer slimes explode in a shower of lifestyle-sapping grossness.

Testing

image
These gloves are 95% steel on the outside (acid resistance 7), leaving a 5% chance that the acid will affect the canvas where there is no metal (acid resistance 4)

image
This brigandine, reversed from the gloves, is 100% canvas on the outside, 90% steel on the inside. Because the outer layer covers 100%, the steel is not counted in the item's acid resistance - the acid splashes the outside of the garment and potentially damages it there. Note that physical non-environmental resistances are unchanged.

image
Fire, being non-physical environmental damage, doesn't respect thickness and averages the value of all included materials according to their coverage. This is, per notes in the code, the intended behavior, but it wasn't averaging, it was just adding layers together while also not respecting thickness.

  • Tried fighting boomers, saw that regular clothes got filthy fairly often, but non-breathable outerwear did a good job of keeping bad stuff out.
  • Noted that having a boomer explode on you is worse than just getting barfed on, as there's 25% more fluid.
  • Was able to get up to 2 ranks of dodge avoiding boomer barfs, but no higher than that.
  • Saw acid barf was damaging mundane clothes, but not better anti-acid gear.

Additional context

image
Acidic zombies, being the most basic form, frequently damage basic clothes, but only infrequently damage tougher materials like leather, and will never damage rubber, metal or plastic.

I'm a player, what do I do about all this?

  • It'll basically work like before except you'll have to do laundry sometimes. The best way to keep nasty fluids off of you is to stay out of melee with boomers and acid zombies.
  • Wearing something like a raincoat or rain poncho over your gear will do a very good job protecting it from damage and filth. Look for outerwear with high coverage and low breathability. Cloaks and ponchos are on the BELTED layer and can be worn over armor, even outer armor like plate mail.
  • Armor which has good acid protection is safe from being damaged. This includes the activity suit, turnout gear, kevlar jumpsuit, most survivor gear, biosilicified chitin, and others.
  • Eye protection is very very important!
  • Consider having more than one outfit, swap stuff out as it gets messed up or dirty, like real life.
  • My goal is to get players to want gear that isn't just the thing with the highest bash and bullet value, and to think more carefully about the enemies they're fighting vs the equipment they have. It is not to force people to do laundry and repair their armor after every fight. Clothes shouldn't get messed up so frequently by these attacks that it becomes an annoying chore.

@github-actions github-actions bot added [C++] Changes (can be) made in C++. Previously named `Code` Monsters Monsters both friendly and unfriendly. <Enhancement / Feature> New features, or enhancements on existing json-styled JSON lint passed, label assigned by github actions labels Feb 7, 2024
@DSeyka
Copy link
Contributor

DSeyka commented Feb 7, 2024

This sounds pretty cool! The only issue I'm seeing is that it might not be immediately obvious that low breathability contributes to liquid attack protection, but I'm drawing a blank on how to communicate this to the player.

@fairyarmadillo
Copy link
Contributor Author

This sounds pretty cool! The only issue I'm seeing is that it might not be immediately obvious that low breathability contributes to liquid attack protection, but I'm drawing a blank on how to communicate this to the player.

There will be messaging in the logs that should help. This is also a change worth writing/editing helpfiles over.

@Venera3
Copy link
Member

Venera3 commented Feb 7, 2024

Please go through mattacks, not the hardcoded monattack stuff - that keeps the dodge calcs etc consistent and much more flexible.

@fairyarmadillo
Copy link
Contributor Author

Can do.

@PatrikLundell
Copy link
Contributor

I'd factor out the poncho change to a separate, simple PR. It doesn't really fit into this PR apart from being a mitigation avenue. A separate PR would probably be approved well before this PR is ready.

Water proof materials aren't breathable, as far as I understand, but many water resistant ones are, and there's no such property in the game, which I guess is why we end up with water proof + breathable.

@github-actions github-actions bot added the BasicBuildPassed This PR builds correctly, label assigned by github actions label Feb 7, 2024
@fairyarmadillo fairyarmadillo mentioned this pull request Feb 9, 2024
4 tasks
@github-actions github-actions bot added [JSON] Changes (can be) made in JSON Mechanics: Enchantments / Spells Enchantments and spells and removed json-styled JSON lint passed, label assigned by github actions BasicBuildPassed This PR builds correctly, label assigned by github actions labels Feb 11, 2024
@github-actions github-actions bot added the EOC: Effects On Condition Anything concerning Effects On Condition label Feb 12, 2024
@github-actions github-actions bot added the <Documentation> Design documents, internal info, guides and help. label Feb 12, 2024
@github-actions github-actions bot removed the astyled astyled PR, label is assigned by github actions label Feb 24, 2024
src/character_attire.cpp Outdated Show resolved Hide resolved
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions github-actions bot added BasicBuildPassed This PR builds correctly, label assigned by github actions astyled astyled PR, label is assigned by github actions labels Feb 24, 2024
@github-actions github-actions bot removed the BasicBuildPassed This PR builds correctly, label assigned by github actions label Feb 24, 2024
@@ -1945,6 +1950,171 @@ void outfit::absorb_damage( Character &guy, damage_unit &elem, bodypart_id bp,
}
}

std::string outfit::get_liquid_descriptor( int liquid_remaining )
{
std::string liquid_descriptor = "some";
Copy link
Member

Choose a reason for hiding this comment

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

None of this is extracted for translation, you'll need to use the call to translation function, e.g.

liquid_descriptor += string_format( _( "%s", liquid_descriptor  ) );

@github-actions github-actions bot added the BasicBuildPassed This PR builds correctly, label assigned by github actions label Feb 25, 2024
if( !destroy ) {
// The roll here is 0 because we already rolled to see if the attack hurts the armor.
// Not -1 so that we can't splash items with 0 coverage.
if( secondary_sbp != sub_bodypart_id() ) {
Copy link
Member

Choose a reason for hiding this comment

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

Neither secondary_sbp nor sbp is guaranteed to be non-null at this point, this whole if block will likely result in a crash or undefined behavior.

}
// If this is an armor-damaging liquid, the damage is relative to fluid_remaining
// and the coverage of the item.
if( damage.amount >= 1.0f && damage_armor ) {
Copy link
Member

Choose a reason for hiding this comment

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

This whole block should probably be replaced to calls with item::damage_armor_durability and other related functions, to avoid duplication. (Also because right now it isn't doing things like checking if the armor is unbreakable, etc

guy.add_effect( spell_effect, dur_td, bp, permanent, intensity );
}
}
if( liquid_remaining == liquid_amount && !guy.is_avatar() ) {
Copy link
Member

Choose a reason for hiding this comment

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

is _avatar() check is redundant (and erroneous), this message can be handled with Character::add_msg_player_or_npc. Assuming that you are working around the vision check, it would still be better to opt it with Character::add_msg_if_player

Comment on lines +2099 to +2102
// If any containers were destroyed, dump the contents on the ground
map &here = get_map();
for( item &remain : worn_remains ) {
here.add_item_or_charges( guy.pos(), remain );
Copy link
Member

Choose a reason for hiding this comment

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

All of this should be handled by Character::drop_invalid_inventory()

// Acid damages clothes directly, but should only harm players via the corroding effect
// However, something like boiling water should just deal damage instantly. guy_damage == true if so.
if( damage_target ) {
guy.deal_damage( nullptr, bp, damage_instance( damage.type, damage.amount ) );
Copy link
Member

Choose a reason for hiding this comment

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

Source should be the caster, not nullptr.

Copy link
Member

@kevingranade kevingranade left a comment

Choose a reason for hiding this comment

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

Break up your PRs, this is becoming a problem rather than a reminder.

I'm getting the impression that you are working on some main feature and "fixing other things as you notice them". That kind of thing is tolerable when the main feature and the "while I'm at it"'s are pretty small, but that is not the case here.

@fairyarmadillo
Copy link
Contributor Author

fairyarmadillo commented Feb 25, 2024

Break up your PRs, this is becoming a problem rather than a reminder.

I'm getting the impression that you are working on some main feature and "fixing other things as you notice them". That kind of thing is tolerable when the main feature and the "while I'm at it"'s are pretty small, but that is not the case here.

There was some of that here, but mostly it was that in this case my starting goal was to move acid and bile over to this system and it unexpectedly required me to do a bunch of work on armor and materials. I'll go ahead and split the bile stuff off from this one and see if that can get merged first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
astyled astyled PR, label is assigned by github actions [C++] Changes (can be) made in C++. Previously named `Code` Code: Tests Measurement, self-control, statistics, balancing. <Documentation> Design documents, internal info, guides and help. <Enhancement / Feature> New features, or enhancements on existing EOC: Effects On Condition Anything concerning Effects On Condition Fields / Furniture / Terrain / Traps Objects that are part of the map or its features. Items: Armor / Clothing Armor and clothing [JSON] Changes (can be) made in JSON json-styled JSON lint passed, label assigned by github actions [Markdown] Markdown issues and PRs Mechanics: Enchantments / Spells Enchantments and spells Mods: Aftershock Anything to do with the Aftershock mod Mods: Innawood 🌲 Anything to do with Innawood mod Mods: Magiclysm Anything to do with the Magiclysm mod Mods: Mind Over Matter Mods: Xedra Evolved Anything to do with Xedra Evolved Monsters Monsters both friendly and unfriendly. Mutations / Traits / Professions/ Hobbies Mutations / Traits / Professions/ Hobbies NPC / Factions NPCs, AI, Speech, Factions, Ownership
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants