Browse Source

Unify gold handling (withdraw any amount from stash)

pull/4219/head
Anders Jenbo 4 years ago committed by GitHub
parent
commit
1ba817ca53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      Source/control.cpp
  2. 27
      Source/debug.cpp
  3. 105
      Source/inv.cpp
  4. 10
      Source/inv.h
  5. 48
      Source/items.cpp
  6. 7
      Source/items.h
  7. 17
      Source/objects.cpp
  8. 16
      Source/player.cpp
  9. 3
      Source/player.h
  10. 12
      Source/qol/stash.cpp
  11. 80
      Source/stores.cpp
  12. 3
      Source/stores.h

6
Source/control.cpp

@ -369,11 +369,7 @@ void RemoveGold(Player &player, int goldIndex)
SetPlrHandGoldCurs(player.InvList[gi]);
else
player.RemoveInvItem(gi);
InitializeItem(player.HoldItem, IDI_GOLD);
SetGoldSeed(player, player.HoldItem);
player.HoldItem._ivalue = dropGoldValue;
player.HoldItem._iStatFlag = true;
ControlSetGoldCurs(player.HoldItem);
MakeGoldStack(player.HoldItem, dropGoldValue);
player._pGold = CalculateGold(player);
dropGoldValue = 0;
}

27
Source/debug.cpp

@ -169,17 +169,16 @@ std::string DebugCmdGiveGoldCheat(const string_view parameter)
{
auto &myPlayer = Players[MyPlayerId];
for (int8_t &itemId : myPlayer.InvGrid) {
if (itemId != 0)
for (int8_t &itemIndex : myPlayer.InvGrid) {
if (itemIndex != 0)
continue;
int ni = myPlayer._pNumInv++;
InitializeItem(myPlayer.InvList[ni], IDI_GOLD);
GenerateNewSeed(myPlayer.InvList[ni]);
myPlayer.InvList[ni]._ivalue = GOLD_MAX_LIMIT;
myPlayer.InvList[ni]._iCurs = ICURS_GOLD_LARGE;
myPlayer._pGold += GOLD_MAX_LIMIT;
itemId = myPlayer._pNumInv;
Item &goldItem = myPlayer.InvList[myPlayer._pNumInv];
MakeGoldStack(goldItem, GOLD_MAX_LIMIT);
myPlayer._pNumInv++;
itemIndex = myPlayer._pNumInv;
myPlayer._pGold += goldItem._ivalue;
}
CalcPlrInv(myPlayer, true);
@ -190,15 +189,15 @@ std::string DebugCmdTakeGoldCheat(const string_view parameter)
{
auto &myPlayer = Players[MyPlayerId];
for (auto itemId : myPlayer.InvGrid) {
itemId -= 1;
for (auto itemIndex : myPlayer.InvGrid) {
itemIndex -= 1;
if (itemId < 0)
if (itemIndex < 0)
continue;
if (myPlayer.InvList[itemId]._itype != ItemType::Gold)
if (myPlayer.InvList[itemIndex]._itype != ItemType::Gold)
continue;
myPlayer.RemoveInvItem(itemId);
myPlayer.RemoveInvItem(itemIndex);
}
myPlayer._pGold = 0;

105
Source/inv.cpp

@ -571,11 +571,11 @@ void CheckInvPaste(int pnum, Point cursorPosition)
cn = SwapItem(player.InvList[invIndex], player.HoldItem);
if (player.HoldItem._itype == ItemType::Gold)
player._pGold = CalculateGold(player);
for (auto &itemId : player.InvGrid) {
if (itemId == it)
itemId = 0;
if (itemId == -it)
itemId = 0;
for (auto &itemIndex : player.InvGrid) {
if (itemIndex == it)
itemIndex = 0;
if (itemIndex == -it)
itemIndex = 0;
}
}
int ii = r - SLOTXY_INV_FIRST;
@ -1128,31 +1128,20 @@ void StartGoldDrop()
SDL_StartTextInput();
}
bool GoldAutoPlaceInInventorySlot(Player &player, int slotIndex, Item &goldStack)
int CreateGoldItemInInventorySlot(Player &player, int slotIndex, int value)
{
if (player.InvGrid[slotIndex] != 0) {
return false;
return value;
}
int ii = player._pNumInv;
player.InvList[ii] = goldStack;
Item &goldItem = player.InvList[player._pNumInv];
MakeGoldStack(goldItem, std::min(value, MaxGold));
player._pNumInv++;
player.InvGrid[slotIndex] = player._pNumInv;
GenerateNewSeed(player.InvList[ii]);
int gold = goldStack._ivalue;
if (gold > MaxGold) {
gold -= MaxGold;
goldStack._ivalue = gold;
GenerateNewSeed(goldStack);
player.InvList[ii]._ivalue = MaxGold;
return false;
}
goldStack._ivalue = 0;
player._pGold = CalculateGold(player);
value -= goldItem._ivalue;
return true;
return value;
}
} // namespace
@ -1519,42 +1508,72 @@ bool AutoPlaceItemInInventorySlot(Player &player, int slotIndex, const Item &ite
return true;
}
bool GoldAutoPlace(Player &player, Item &goldStack)
int RoomForGold()
{
bool done = false;
int amount = 0;
for (int8_t &itemIndex : MyPlayer->InvGrid) {
if (itemIndex < 0) {
continue;
}
if (itemIndex == 0) {
amount += MaxGold;
continue;
}
for (int i = 0; i < player._pNumInv && !done; i++) {
if (player.InvList[i]._itype != ItemType::Gold)
Item &goldItem = MyPlayer->InvList[itemIndex - 1];
if (goldItem._itype != ItemType::Gold || goldItem._ivalue == MaxGold) {
continue;
if (player.InvList[i]._ivalue >= MaxGold)
}
amount += MaxGold - goldItem._ivalue;
}
return amount;
}
int AddGoldToInventory(Player &player, int value)
{
// Top off existing piles
for (int i = 0; i < player._pNumInv && value > 0; i++) {
Item &goldItem = player.InvList[i];
if (goldItem._itype != ItemType::Gold || goldItem._ivalue >= MaxGold) {
continue;
}
player.InvList[i]._ivalue += goldStack._ivalue;
if (player.InvList[i]._ivalue > MaxGold) {
goldStack._ivalue = player.InvList[i]._ivalue - MaxGold;
SetPlrHandGoldCurs(goldStack);
player.InvList[i]._ivalue = MaxGold;
if (gbIsHellfire)
GenerateNewSeed(goldStack);
if (goldItem._ivalue + value > MaxGold) {
value -= MaxGold - goldItem._ivalue;
goldItem._ivalue = MaxGold;
} else {
goldStack._ivalue = 0;
done = true;
goldItem._ivalue += value;
value = 0;
}
SetPlrHandGoldCurs(player.InvList[i]);
SetPlrHandGoldCurs(goldItem);
}
for (int i = 39; i >= 30 && !done; i--) {
done = GoldAutoPlaceInInventorySlot(player, i, goldStack);
// Last row right to left
for (int i = 39; i >= 30 && value > 0; i--) {
value = CreateGoldItemInInventorySlot(player, i, value);
}
for (int x = 9; x >= 0 && !done; x--) {
for (int y = 2; y >= 0 && !done; y--) {
done = GoldAutoPlaceInInventorySlot(player, 10 * y + x, goldStack);
// Remaining inventory in columns, bottom to top, right to left
for (int x = 9; x >= 0 && value > 0; x--) {
for (int y = 2; y >= 0 && value > 0; y--) {
value = CreateGoldItemInInventorySlot(player, 10 * y + x, value);
}
}
return value;
}
bool GoldAutoPlace(Player &player, Item &goldStack)
{
goldStack._ivalue = AddGoldToInventory(player, goldStack._ivalue);
SetPlrHandGoldCurs(goldStack);
player._pGold = CalculateGold(player);
return done;
return goldStack._ivalue == 0;
}
void CheckInvSwap(Player &player, inv_body_loc bLoc, int idx, uint16_t wCI, int seed, bool bId, uint32_t dwBuff)

10
Source/inv.h

@ -159,6 +159,16 @@ bool AutoPlaceItemInInventorySlot(Player &player, int slotIndex, const Item &ite
* @return 'True' in case the item can be placed on the player's belt and 'False' otherwise.
*/
bool AutoPlaceItemInBelt(Player &player, const Item &item, bool persistItem = false);
/**
* @brief Calculate the maximum aditional gold that may fit in the user's inventory
*/
int RoomForGold();
/**
* @return The leftover amount that didn't fit, if any
*/
int AddGoldToInventory(Player &player, int value);
bool GoldAutoPlace(Player &player, Item &goldStack);
void CheckInvSwap(Player &player, inv_body_loc bLoc, int idx, uint16_t wCI, int seed, bool bId, uint32_t dwBuff);
void inv_update_rem_item(Player &player, inv_body_loc iv);

48
Source/items.cpp

@ -2298,9 +2298,6 @@ void InitItemGFX()
void InitItems()
{
golditem = {};
GetItemAttrs(golditem, IDI_GOLD, 1);
golditem._iStatFlag = true;
ActiveItemCount = 0;
memset(dItem, 0, sizeof(dItem));
@ -2764,31 +2761,6 @@ void GenerateNewSeed(Item &item)
item._iSeed = AdvanceRndSeed();
}
void SetGoldSeed(Player &player, Item &gold)
{
int s = 0;
bool doneflag;
do {
doneflag = true;
s = AdvanceRndSeed();
for (int i = 0; i < ActiveItemCount; i++) {
int ii = ActiveItems[i];
auto &item = Items[ii];
if (item._iSeed == s)
doneflag = false;
}
if (&player == &Players[MyPlayerId]) {
for (int i = 0; i < player._pNumInv; i++) {
if (player.InvList[i]._iSeed == s)
doneflag = false;
}
}
} while (!doneflag);
gold._iSeed = s;
}
int GetGoldCursor(int value)
{
if (value >= GOLD_MEDIUM_LIMIT)
@ -2901,15 +2873,13 @@ void CreatePlrItems(int playerId)
break;
}
auto &startingGold = player.InvList[player._pNumInv];
Item &goldItem = player.InvList[player._pNumInv];
MakeGoldStack(goldItem, 100);
player._pNumInv++;
player.InvGrid[30] = player._pNumInv;
InitializeItem(startingGold, IDI_GOLD);
GenerateNewSeed(startingGold);
startingGold._ivalue = 100;
startingGold._iCurs = ICURS_GOLD_SMALL;
player._pGold = startingGold._ivalue;
player._pGold = goldItem._ivalue;
CalcPlrItemVals(player, false);
}
@ -4336,11 +4306,13 @@ void SpawnHealer(int lvl)
SortVendor(healitem + PinnedItemCount);
}
void SpawnStoreGold()
void MakeGoldStack(Item &goldItem, int value)
{
golditem = {};
GetItemAttrs(golditem, IDI_GOLD, 1);
golditem._iStatFlag = true;
InitializeItem(goldItem, IDI_GOLD);
GenerateNewSeed(goldItem);
goldItem._iStatFlag = true;
goldItem._ivalue = value;
SetPlrHandGoldCurs(goldItem);
}
int ItemNoFlippy()

7
Source/items.h

@ -432,11 +432,6 @@ void CalcPlrItemVals(Player &player, bool Loadgfx);
void CalcPlrInv(Player &player, bool Loadgfx);
void InitializeItem(Item &item, int itemData);
void GenerateNewSeed(Item &h);
/**
* @brief Set a new unique seed value on the given item
*/
void SetGoldSeed(Player &player, Item &gold);
int GetGoldCursor(int value);
/**
@ -487,7 +482,7 @@ void SpawnPremium(int pnum);
void SpawnWitch(int lvl);
void SpawnBoy(int lvl);
void SpawnHealer(int lvl);
void SpawnStoreGold();
void MakeGoldStack(Item &goldItem, int value);
int ItemNoFlippy();
void CreateSpellBook(Point position, spell_id ispell, bool sendmsg, bool delta);
void CreateMagicArmor(Point position, ItemType itemType, int icurs, bool sendmsg, bool delta);

17
Source/objects.cpp

@ -3086,17 +3086,14 @@ bool OperateShrineSpiritual(int pnum)
auto &player = Players[pnum];
for (int8_t &gridItem : player.InvGrid) {
if (gridItem == 0) {
int r = 5 * leveltype + GenerateRnd(10 * leveltype);
DWORD t = player._pNumInv; // check
player.InvList[t] = golditem;
player.InvList[t]._iSeed = AdvanceRndSeed();
for (int8_t &itemIndex : player.InvGrid) {
if (itemIndex == 0) {
Item &goldItem = player.InvList[player._pNumInv];
MakeGoldStack(goldItem, 5 * leveltype + GenerateRnd(10 * leveltype));
player._pNumInv++;
gridItem = player._pNumInv;
player.InvList[t]._ivalue = r;
player._pGold += r;
SetPlrHandGoldCurs(player.InvList[t]);
itemIndex = player._pNumInv;
player._pGold += goldItem._ivalue;
}
}

16
Source/player.cpp

@ -586,14 +586,12 @@ int DropGold(Player &player, int amount, bool skipFullStacks)
continue;
if (amount < item._ivalue) {
Item gold {};
InitializeItem(gold, IDI_GOLD);
SetGoldSeed(player, gold);
Item goldItem;
MakeGoldStack(goldItem, amount);
DeadItem(player, std::move(goldItem), { 0, 0 });
gold._ivalue = amount;
item._ivalue -= amount;
SetPlrHandGoldCurs(gold);
DeadItem(player, std::move(gold), { 0, 0 });
return 0;
}
@ -3201,11 +3199,9 @@ void StripTopGold(Player &player)
if (item._itype == ItemType::Gold) {
if (item._ivalue > MaxGold) {
Item excessGold;
InitializeItem(excessGold, IDI_GOLD);
SetGoldSeed(player, excessGold);
excessGold._ivalue = item._ivalue - MaxGold;
SetPlrHandGoldCurs(excessGold);
MakeGoldStack(excessGold, item._ivalue - MaxGold);
item._ivalue = MaxGold;
if (!GoldAutoPlace(player, excessGold)) {
DeadItem(player, std::move(excessGold), { 0, 0 });
}

3
Source/player.h

@ -740,6 +740,9 @@ void FixPlrWalkTags(int pnum);
void RemovePlrFromMap(int pnum);
void StartPlrHit(int pnum, int dam, bool forcehit);
void StartPlayerKill(int pnum, int earflag);
/**
* @brief Strip the top off gold piles that are larger than MaxGold
*/
void StripTopGold(Player &player);
void SyncPlrKill(int pnum, int earflag);
void RemovePlrMissiles(int pnum);

12
Source/qol/stash.cpp

@ -248,7 +248,7 @@ void StartGoldWithdraw()
{
CloseGoldDrop();
InitialWithdrawGoldValue = Stash.gold;
InitialWithdrawGoldValue = std::min(RoomForGold(), Stash.gold);
if (talkflag)
control_reset_talk();
@ -264,11 +264,7 @@ void StartGoldWithdraw()
void WithdrawGold(Player &player, int amount)
{
InitializeItem(player.HoldItem, IDI_GOLD);
SetGoldSeed(player, player.HoldItem);
player.HoldItem._ivalue = amount;
player.HoldItem._iStatFlag = true;
ControlSetGoldCurs(player.HoldItem);
AddGoldToInventory(player, amount);
Stash.gold -= amount;
Stash.dirty = true;
}
@ -587,7 +583,7 @@ void DrawGoldWithdraw(const Surface &out, int amount)
CelDrawTo(out, GetPanelPosition(UiPanels::Stash, { dialogX, 178 }), *pGBoxBuff, 1);
// Pre-wrap the string at spaces, otherwise DrawString would hard wrap in the middle of words
const std::string wrapped = WordWrapString(_("How many gold pieces do you want to withdraw? (MAX 5000)"), 200);
const std::string wrapped = WordWrapString(_("How many gold pieces do you want to withdraw?"), 200);
// The split gold dialog is roughly 4 lines high, but we need at least one line for the player to input an amount.
// Using a clipping region 50 units high (approx 3 lines with a lineheight of 17) to ensure there is enough room left
@ -619,7 +615,7 @@ void GoldWithdrawNewText(string_view text)
if (digit >= 0 && digit <= 9) {
int newGoldValue = WithdrawGoldValue * 10;
newGoldValue += digit;
if (newGoldValue <= GOLD_MAX_LIMIT && newGoldValue <= InitialWithdrawGoldValue) {
if (newGoldValue <= InitialWithdrawGoldValue) {
WithdrawGoldValue = newGoldValue;
}
}

80
Source/stores.cpp

@ -27,8 +27,6 @@
namespace devilution {
Item golditem;
talk_id stextflag;
int storenumh;
@ -1479,61 +1477,15 @@ void SmithPremiumBuyEnter()
bool StoreGoldFit(int idx)
{
int cost = storehold[idx]._iIvalue;
int sz = cost / MaxGold;
if (cost % MaxGold != 0)
sz++;
NewCursor(storehold[idx]._iCurs + CURSOR_FIRSTITEM);
int numsqrs = cursSize.width / 28 * (cursSize.height / 28);
NewCursor(CURSOR_HAND);
Size itemSize = GetInventorySize(storehold[idx]);
int itemRoomForGold = itemSize.width * itemSize.height * MaxGold;
if (numsqrs >= sz)
if (cost <= itemRoomForGold) {
return true;
auto &myPlayer = Players[MyPlayerId];
for (int8_t itemId : myPlayer.InvGrid) {
if (itemId == 0)
numsqrs++;
}
for (int i = 0; i < myPlayer._pNumInv; i++) {
const auto &item = myPlayer.InvList[i];
if (item._itype == ItemType::Gold && item._ivalue != MaxGold) {
if (cost + item._ivalue <= MaxGold)
cost = 0;
else
cost -= MaxGold - item._ivalue;
}
}
sz = cost / MaxGold;
if ((cost % MaxGold) != 0)
sz++;
return numsqrs >= sz;
}
/**
* @brief Add gold pile to the players invetory
* @param v The value of the gold pile
*/
void PlaceStoreGold(int v)
{
auto &myPlayer = Players[MyPlayerId];
for (auto &gridNum : myPlayer.InvGrid) {
if (gridNum == 0) {
int ii = myPlayer._pNumInv;
SetGoldSeed(myPlayer, golditem);
myPlayer.InvList[ii] = golditem;
myPlayer._pNumInv++;
gridNum = myPlayer._pNumInv;
myPlayer.InvList[ii]._ivalue = v;
SetPlrHandGoldCurs(myPlayer.InvList[ii]);
return;
}
}
return cost <= itemRoomForGold + RoomForGold();
}
/**
@ -1558,27 +1510,10 @@ void StoreSellItem()
idx++;
}
}
AddGoldToInventory(myPlayer, cost);
myPlayer._pGold += cost;
for (int i = 0; i < myPlayer._pNumInv && cost > 0; i++) {
auto &item = myPlayer.InvList[i];
if (item._itype == ItemType::Gold && item._ivalue != MaxGold) {
if (cost + item._ivalue <= MaxGold) {
item._ivalue += cost;
cost = 0;
} else {
cost -= MaxGold - item._ivalue;
item._ivalue = MaxGold;
}
SetPlrHandGoldCurs(myPlayer.InvList[i]);
}
}
if (cost > 0) {
while (cost > MaxGold) {
PlaceStoreGold(MaxGold);
cost -= MaxGold;
}
PlaceStoreGold(cost);
}
}
void SmithSellEnter()
@ -2293,7 +2228,6 @@ void SetupTownStores()
}
l = clamp(l + 2, 6, 16);
SpawnStoreGold();
SpawnSmith(l);
SpawnWitch(l);
SpawnHealer(l);

3
Source/stores.h

@ -77,9 +77,6 @@ extern char storehidx[48];
/** Copies of the players items as presented in the store */
extern DVL_API_FOR_TEST Item storehold[48];
/** Temporary item used to generate gold piles by various function */
extern Item golditem;
/** Items sold by Griswold */
extern Item smithitem[SMITH_ITEMS];
/** Number of premium items for sale by Griswold */

Loading…
Cancel
Save