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

[Issue Report]: Expensive Wirt items are considered invalid and cannot be used #7561

Open
StephenCWills opened this issue Nov 27, 2024 · 2 comments · May be fixed by #7565
Open

[Issue Report]: Expensive Wirt items are considered invalid and cannot be used #7561

StephenCWills opened this issue Nov 27, 2024 · 2 comments · May be fixed by #7565

Comments

@StephenCWills
Copy link
Member

StephenCWills commented Nov 27, 2024

Operating System

Windows x64

DevilutionX version

Custom build (please specify commit ID)

Describe

You can buy an item from Wirt in Diablo and, due to the 1.5x price adjustment, immediately be unable to use it because it's too expensive.

To Reproduce

Note: The following steps will no longer reproduce the issue using the latest commits from master. You will need to either test using a commit before d8811eb or find a way to reproduce in Multiplayer.

  1. Download single_0.sv.zip
  2. Load game
  3. Buy the Great Sword of Haste from Wirt
  4. Open your inventory and observe that it cannot be used

Expected Behavior

No response

Additional context

Wirt's price adjustment gets applied to the item's _iIvalue field in BoyBuyEnter().

devilutionX/Source/stores.cpp

Lines 1769 to 1786 in 9427513

int price = BoyItem._iIvalue;
if (gbIsHellfire)
price -= BoyItem._iIvalue / 4;
else
price += BoyItem._iIvalue / 2;
if (!PlayerCanAfford(price)) {
StartStore(TalkID::NoMoney);
return;
}
if (!StoreAutoPlace(BoyItem, false)) {
StartStore(TalkID::NoRoom);
return;
}
TempItem = BoyItem;
TempItem._iIvalue = price;

Since the price goes up in Diablo, the price adjustment can drive the _iIvalue stat above the price limit and cause the logic in IsShopPriceValid() to produce the wrong result.

bool IsShopPriceValid(const Item &item)
{
const int boyPriceLimit = MaxBoyValue;
if (!gbIsHellfire && (item._iCreateInfo & CF_BOY) != 0 && item._iIvalue > boyPriceLimit)
return false;

Introduced by commit cfac786. Prior to that commit, IsShopPriceValid() was only called on items that were just regenerated and therefore not price-adjusted.

Tested using commit f4b6b54

@StephenCWills
Copy link
Member Author

To fix this issue, I'd recommend applying Wirt's price adjustment as-needed rather than storing it directly in _iIvalue. However, I haven't really evaluated that solution to see if it's viable. Given how messy the shop code is, I wouldn't be surprised if it wasn't.

@StephenCWills
Copy link
Member Author

New steps to reproduce in Multiplayer:

  1. Download multi_0.sv.zip
  2. Force DungeonSeed[0] to 3383747080 in the NetInit() function
  3. Start a game, walk to Wirt, and buy the Emerald Axe
  4. Open your inventory and observe that it cannot be used

@StephenCWills StephenCWills linked a pull request Nov 27, 2024 that will close this issue
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 a pull request may close this issue.

1 participant