-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Transfer inhaler to NPC inventory on mission end #37454
Conversation
I recruited an asthmatic NPC after completing their inhaler mission and was startled to see they had already lost it. This allows them to keep the inhaler you find for them. Attempted fix for CleverRaven#31773. I have detailed some problems with this commit in comments on that issue.
Hmm. I don't think this is an adequate solution to the problem, it just creates a new bug - that you give the npc all your inhalers. I would suggest you keep the At least for verissimilitude, the NPC appears to be using a puff of the inhaler you brought |
Agreed, I don’t like the current solution either. Fixing |
This may be a case of the workaround being worse than what's being worked around. Will find a better solution.
It's a bit complicated. This appears to be the relevant section of Lines 1971 to 1990 in ff90cbb
I think what's happening here is, after quest completion:
My guess is the I've done some testing using the normal NPC "let's trade items" UI, and when I do it that way, the entire inhaler item (with its remaining charges) is transferred as expected. Seems like it's only when |
L1983-1985 are not used. The inhaler is not counted by charges, The problem is the Final note: |
When using this function to sell an inhaler to an NPC, `u.has_charges` is (apparently) returning true (since player has inhaler charges), although the inhaler itself is not counted by charges according to @BevapDin. This change makes `set_u_sell_item` follow more closely the pattern of `set_u_buy_item`, by merging the two separate `if/else` blocks into one, handling both the charge adjustment and `p.i_add` to transfer them item. Most importantly, the first condition for doing charge-based adjustment is whether `count_by_charges()` is true. I've preserved the check for `u.has_charges`, because we need to ensure the requested number of charges are available. Partial fix for CleverRaven#31773
Thanks @BevapDin for the explanation - this helped me make some progress. I think my last commits are pretty close to a final fix, but I'd appreciate further review and suggestions from devs. Here is the current behavior I see in my testing:
If the inhaler is really not to be treated as having charges, I don't see a way around the magical-recharge-on-transfer issue (at least not without further rewrites to this function, which I don't feel too confident attempting). |
To avoid transferring items with an unknown amount of charges.
The layers of onion around this bug are many. My latest commit is very close to working exactly as expected, except I have to save and reload my game in order for the inhaler to appear in the NPC's inventory. |
item_name is a raw id, not user-presentable
I just tested your branch and it works fine for me: the NPC has my inhaler - it shows up when trading with the NPC. How do you check for the appearance of the inhaler in the NPC inventory? |
This is how I've been setting up the inhaler quest for testing:
Here's the "You give X a inhaler" (sic) popup displaying as expected: After this, if I choose "How about some items as payment?" or quit, chat again, and ask "Care to trade?", their inventory does not include the inhaler: But after a quick save and reload, it is there, with the correct number of charges:
|
I tested this again with a recent pull from master, and got the same results. For the first NPC, it actually worked immediately - after quest completion, they had the inhaler in their inventory right away. But for the next two NPCs I spawned for testing, neither would show the inhaler in their inventory until after I saved/loaded the game. Considering the failed testing, I'm gonna leave this as WIP until I can figure out what's going on. |
Alright, I have now tested this some more, and found that the inhaler does appear in the NPC's inventory (visible in the "let's trade items" screen) if I successfully persuade the NPC to travel with me (two successes so far). I didn't do extended testing to see if they were able to treat their asthma attacks. Having other conversations with the NPC or waiting a while does not seem to trigger the appearance of the inhaler in the trading screen. So maybe the notion is they aren't ready to immediately trade away the very item they wanted for their quest. In any case, saving and loading has always allowed me to see the inhaler in the trade UI, so the item transfer is certainly happening as expected. I spent some time looking into maybe adding some test cases for this edge case to Long story short, I am satisfied that this is ready to merge now, so I am removing the WIP tag for what I hope is the last time. |
Summary
SUMMARY: Bugfixes "Let asthmatic NPC keep inhaler after mission complete"
Purpose of change
Attempted fix for #31773
Describe the solution
In my early testing I learned that for missions with
MGOAL_FIND_ITEM
type, the found item appears to be simply deleted when the mission is complete:Cataclysm-DDA/src/mission.cpp
Lines 327 to 329 in bfee67a
To solve this, I changed the mission goal to
MGOAL_CONDITION
, with a condition of"u_has_item": "inhaler"
. Effectively the same criteria, but prevents thewrap_up
function from deleting it.Then, I added an ending effect of
"u_sell_item": "inhaler"
to transfer it to the NPC's inventory. Sounds good, right?Well, what happened was that my inhaler loses (1) of its possibly (100) charges, and the NPC gains a new fully-charged inhaler. Complete the quest again for another NPC, and they get a full inhaler, while mine drops to (98/100). This seems like a bug for which I'll open a separate ticket when I have time to test it more (if someone else doesn't do it first!)
My crude workaround to this bug is, after quest completion, to remove the player's inhaler from inventory with"u_remove_item_with": "inhaler"
. Unfortunately this will remove all inhalers, since there appears to be no way to remove only 1, unlessu_remove_item_with
accepts a count that isn't documented in NPCs.md, so hopefully the player isn't hoarding them to distribute to a bunch of NPCs. The upside is, a depleted inhaler will be magically refilled on transfer due to the above bug, so if you have an inhaler with (1/100) charges, I think it will become (100/100) in the NPC's inventory.Workaround turned into a working solution with the help of other developers - see discussion below.
Describe alternatives you've considered
Considered looking at a more general way of allowing NPCs to keep completed quest items for
MGOAL_FIND_ITEM
, but didn't want to run into volume concerns (for example with Draco's guitar quest) of NPC being unable to hold the thing. Inhaler is small enough to avoid this problem, I hope.Testing
Using an invincible player in a test world, I spawned many NPCs until I got asthmatic ones, and spawned inhalers as needed to complete their quests. Then I asked the NPCs to trade and made sure they had an inhaler in their inventory.
Additional context
I had a personal interest in fixing this, because my latest character is in a world with maximum (100.0) NPC spawns, and the first friendly recruit she found was asthmatic.