CleverRaven / CleverRaven/Cataclysm-DDA

Mutations that make a player huge and breaking gear errors

Open
#48,866 1 comment 0 reactions 0 assignees View on GitHub
<Bug> Mutations / Traits / Professions/ Hobbies
Dominant language
C++
Stars
13.1k
Forks
4.6k
Avg merge
2d 1h
Merged PRs (30d)
200

Description

# Describe the bug

When I apply a serum that causes the player grow to `creature_size::huge` and thus destroying most of the players gear it errors because the serum gets dropped to the ground before the game gets the chance to remove it from the players inventory. In my tests I could repeat it with the serum being inside the messenger bag.

# Steps To Reproduce

1. Create a new character with a messenger bag equipped (e. g. with the profession Survivor).
2. Add a syringe and a bunch of ursine serums. 50 should do.
3. Now inject the serums until you gain the `HUGE` mutation, destroying worn gear including the mesenger bag.

# Expected behavior

The ursine serum gets remove from the inventory (or the ground) without error.

# Versions and configuration

- OS: Windows
- OS Version: 10.0 2009
- Game Version: 07c58d9 [64-bit]
- Graphics Version: Tiles
- Game Language: English [en]
- Mods loaded: [
Dark Days Ahead [dda],
Disable NPC Needs [no_npc_food],
Bionic Professions [package_bionic_professions],
Magiclysm [magiclysm],
C.R.I.T Expansion Mod [crt_expansion]
]

# Additional context

When the player becomes huge the messenger bags contents get dropped to the ground along with all serums in it before the game gets the chance to remove it from the inventory, thus causing the following error:
```
DEBUG : did not found item ursine serum to remove it!

FUNCTION : item Character::i_rem(const item*)
FILE : src/character.cpp
LINE : 3041
```

Note, that the game just outright crashes in my test build made with Visual Studio but it doesn't create an error report, hence I can't provide a stacktrace. But I guess it's due to the same code.

It happens most likely because the item location doesn't get updated before the game tries to remove it in `player::consume` in `consumption.cpp`:
```cpp
trinary player::consume( item_location loc, bool force )
{
if( !loc ) {
debugmsg( "Null loc to consume." );
return trinary::NONE;
}
contents_change_handler handler;
item &target = *loc;
trinary result = consume( target, force );
if( result != trinary::NONE ) {
handler.unseal_pocket_containing( loc );
}
if( result == trinary::ALL ) {
if( loc.where() == item_location::type::character ) {
i_rem( loc.get_item() );
} else {
loc.remove_item();
}
}
handler.handle_by( *this );
return result;
}
```

I could bet the `loc.where()` in the line `if( loc.where() == item_location::type::character ) {` still returns `item_location::type::character` because the item location doesn't get updated properly in `item_pocket::spill_contents`.

I'd have to dig my head a more into the code structure to provide a fix for it, but maybe someone else could look into a fix for this?

Contributor guide

Open the contributing guide

Research direction

Start with player::consume in src/consumption.cpp and the reported item_location handling around item_pocket::spill_contents; inspect how the location changes when the messenger bag is destroyed. Reproduce the HUGE mutation with ursine serums in a messenger bag, then verify that consuming the serum removes it from the inventory or ground without the reported error or crash.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.