cataclysmbnteam / Cataclysm-BN

Cataclysm: Bright Nights, A fork/variant of Cataclysm:DDA by CleverRaven.
https://docs.cataclysmbn.org
Other
696 stars 272 forks source link

Putrid Hearts from Jabberwocks may be repeatedly activated to gain infinite mutations #5481

Open Soadreqm opened 1 month ago

Soadreqm commented 1 month ago

Describe the bug

A putrid heart, acquired by dissecting a dead Jabberwock, may be eaten or activated to gain mutations. However, activating it doesn't consume the heart, meaning it can be activated again to mutate more.

The heart should only work once.

Steps To Reproduce

  1. spawn putrid heart
  2. apply putrid heart
  3. apply the heart again
  4. and again

Screenshots

No response

Versions and configuration

Additional context

No response

IllusionDX commented 1 month ago

I tested it and the same thing happens with seeping heart, mutated arm, mutated leg, etc. Basically all the comestibles with type food and use_action mutagen

The problem is in avatar_functions.cpp in the void use_item( avatar &you, item &used ) function

A mutagen like lupine mutagen is inside a flask, so the item is glass flask, and the glass flask returns false on used.type->has_use() so the item goes here and it gets consumed

    } else if( !used.is_craft() && ( used.is_medication() || ( !used.type->has_use() &&
                                     ( used.is_food() ||
                                       used.get_contained().is_food() ||
                                       used.get_contained().is_medication() ) ) ) ) {
        you.consume( used );

But the putrid heart returns true on used.type->has_use() so it goes here instead

    } else if( used.type->has_use() ) {
        you.invoke_item( &used, used.position() );

I tried to add more checks on bool Character::invoke_item( item *used, const std::string &method, const tripoint &pt ) on character.cpp

if( used->is_tool() || used->is_food() || used->get_contained().is_food() ||
        used->is_medication() || used->get_contained().is_medication() ) {
        return consume_charges( *actually_used, charges_used );
    } else if( used->is_bionic() || used->is_deployable() || method == "place_trap" ) {
        used->detach();
        return true;
    }

And that causes it to consume charges as it should but then it doesn't show the message that says "You eat your x", and I don't know how to fix it properly

Edit: I think I got it but I'm gonna wait on another PR