|
|
|
|
@ -60,6 +60,7 @@ namespace {
|
|
|
|
|
int Slot = SLOTXY_INV_FIRST; |
|
|
|
|
Point ActiveStashSlot = InvalidStashPoint; |
|
|
|
|
int PreviousInventoryColumn = -1; |
|
|
|
|
bool BeltReturnsToStash = false; |
|
|
|
|
|
|
|
|
|
const Direction FaceDir[3][3] = { |
|
|
|
|
// NONE UP DOWN
|
|
|
|
|
@ -590,28 +591,29 @@ Point InvGetEquipSlotCoord(const inv_body_loc invSlot)
|
|
|
|
|
|
|
|
|
|
Point InvGetEquipSlotCoordFromInvSlot(const inv_xy_slot slot) |
|
|
|
|
{ |
|
|
|
|
switch (slot) { |
|
|
|
|
case SLOTXY_HEAD_FIRST: |
|
|
|
|
case SLOTXY_HEAD_LAST: |
|
|
|
|
if (slot >= SLOTXY_HEAD_FIRST && slot <= SLOTXY_HEAD_LAST) { |
|
|
|
|
return InvGetEquipSlotCoord(INVLOC_HEAD); |
|
|
|
|
case SLOTXY_RING_LEFT: |
|
|
|
|
} |
|
|
|
|
if (slot == SLOTXY_RING_LEFT) { |
|
|
|
|
return InvGetEquipSlotCoord(INVLOC_RING_LEFT); |
|
|
|
|
case SLOTXY_RING_RIGHT: |
|
|
|
|
} |
|
|
|
|
if (slot == SLOTXY_RING_RIGHT) { |
|
|
|
|
return InvGetEquipSlotCoord(INVLOC_RING_RIGHT); |
|
|
|
|
case SLOTXY_AMULET: |
|
|
|
|
} |
|
|
|
|
if (slot == SLOTXY_AMULET) { |
|
|
|
|
return InvGetEquipSlotCoord(INVLOC_AMULET); |
|
|
|
|
case SLOTXY_HAND_LEFT_FIRST: |
|
|
|
|
case SLOTXY_HAND_LEFT_LAST: |
|
|
|
|
} |
|
|
|
|
if (slot >= SLOTXY_HAND_LEFT_FIRST && slot <= SLOTXY_HAND_LEFT_LAST) { |
|
|
|
|
return InvGetEquipSlotCoord(INVLOC_HAND_LEFT); |
|
|
|
|
case SLOTXY_HAND_RIGHT_FIRST: |
|
|
|
|
case SLOTXY_HAND_RIGHT_LAST: |
|
|
|
|
} |
|
|
|
|
if (slot >= SLOTXY_HAND_RIGHT_FIRST && slot <= SLOTXY_HAND_RIGHT_LAST) { |
|
|
|
|
return InvGetEquipSlotCoord(INVLOC_HAND_RIGHT); |
|
|
|
|
case SLOTXY_CHEST_FIRST: |
|
|
|
|
case SLOTXY_CHEST_LAST: |
|
|
|
|
} |
|
|
|
|
if (slot >= SLOTXY_CHEST_FIRST && slot <= SLOTXY_CHEST_LAST) { |
|
|
|
|
return InvGetEquipSlotCoord(INVLOC_CHEST); |
|
|
|
|
default: |
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -695,20 +697,28 @@ void ResetInvCursorPosition()
|
|
|
|
|
Point mousePos {}; |
|
|
|
|
if (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_INV_LAST) { |
|
|
|
|
int8_t itemInvId = GetItemIdOnSlot(Slot); |
|
|
|
|
int itemSlot = FindFirstSlotOnItem(itemInvId); |
|
|
|
|
if (itemSlot >= 0) |
|
|
|
|
Slot = itemSlot; |
|
|
|
|
if (itemInvId != 0) { |
|
|
|
|
mousePos = GetSlotCoord(FindFirstSlotOnItem(itemInvId)); |
|
|
|
|
Size itemSize = GetItemSizeOnSlot(Slot); |
|
|
|
|
mousePos.x += ((itemSize.width - 1) * InventorySlotSizeInPixels.width) / 2; |
|
|
|
|
mousePos.y += ((itemSize.height - 1) * InventorySlotSizeInPixels.height) / 2; |
|
|
|
|
} else { |
|
|
|
|
mousePos = GetSlotCoord(Slot); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// offset the slot to always move to the top-left most slot of that item
|
|
|
|
|
Size itemSize = GetItemSizeOnSlot(Slot); |
|
|
|
|
Slot -= ((itemSize.height - 1) * INV_ROW_SLOT_SIZE); |
|
|
|
|
mousePos = GetSlotCoord(Slot); |
|
|
|
|
mousePos.x += ((itemSize.width - 1) * InventorySlotSizeInPixels.width) / 2; |
|
|
|
|
mousePos.y += ((itemSize.height - 1) * InventorySlotSizeInPixels.height) / 2; |
|
|
|
|
if (pcurs >= CURSOR_FIRSTITEM) { |
|
|
|
|
mousePos += Displacement { -INV_SLOT_HALF_SIZE_PX, -INV_SLOT_HALF_SIZE_PX }; |
|
|
|
|
} |
|
|
|
|
} else if (Slot >= SLOTXY_BELT_FIRST && Slot <= SLOTXY_BELT_LAST) { |
|
|
|
|
mousePos = GetSlotCoord(Slot); |
|
|
|
|
if (pcurs >= CURSOR_FIRSTITEM) |
|
|
|
|
mousePos += Displacement { -INV_SLOT_HALF_SIZE_PX, -INV_SLOT_HALF_SIZE_PX }; |
|
|
|
|
} else { |
|
|
|
|
mousePos = InvGetEquipSlotCoordFromInvSlot((inv_xy_slot)Slot); |
|
|
|
|
if (pcurs >= CURSOR_FIRSTITEM) { |
|
|
|
|
Size itemSize = GetInventorySize(MyPlayer->HoldItem); |
|
|
|
|
mousePos += Displacement { -INV_SLOT_HALF_SIZE_PX, -INV_SLOT_HALF_SIZE_PX * itemSize.height }; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
mousePos.x += (InventorySlotSizeInPixels.width / 2); |
|
|
|
|
@ -738,7 +748,7 @@ Point FindClosestStashSlot(Point mousePos)
|
|
|
|
|
{ |
|
|
|
|
int shortestDistance = std::numeric_limits<int>::max(); |
|
|
|
|
Point bestSlot = {}; |
|
|
|
|
mousePos += Displacement { -INV_SLOT_HALF_SIZE_PX, INV_SLOT_HALF_SIZE_PX }; |
|
|
|
|
mousePos += Displacement { -INV_SLOT_HALF_SIZE_PX, -INV_SLOT_HALF_SIZE_PX }; |
|
|
|
|
|
|
|
|
|
for (auto point : PointsInRectangleRange({ { 0, 0 }, { 10, 10 } })) { |
|
|
|
|
int distance = mousePos.ManhattanDistance(GetStashSlotCoord(point)); |
|
|
|
|
@ -754,7 +764,7 @@ Point FindClosestStashSlot(Point mousePos)
|
|
|
|
|
/**
|
|
|
|
|
* @brief Figures out where on the body to move when on the first row |
|
|
|
|
*/ |
|
|
|
|
Point InvMoveToBody(int slot) |
|
|
|
|
Point InventoryMoveToBody(int slot) |
|
|
|
|
{ |
|
|
|
|
PreviousInventoryColumn = slot - SLOTXY_INV_ROW1_FIRST; |
|
|
|
|
if (slot <= SLOTXY_INV_ROW1_FIRST + 2) { // first 3 general slots
|
|
|
|
|
@ -771,18 +781,8 @@ Point InvMoveToBody(int slot)
|
|
|
|
|
return GetSlotCoord(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Move the cursor around in our inventory |
|
|
|
|
* If mouse coords are at SLOTXY_CHEST_LAST, consider this center of equipment |
|
|
|
|
* small inventory squares are 29x29 (roughly) |
|
|
|
|
*/ |
|
|
|
|
void InvMove(AxisDirection dir) |
|
|
|
|
void InventoryMove(AxisDirection dir) |
|
|
|
|
{ |
|
|
|
|
static AxisDirectionRepeater repeater(/*min_interval_ms=*/150); |
|
|
|
|
dir = repeater.Get(dir); |
|
|
|
|
if (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
Point mousePos = MousePosition; |
|
|
|
|
|
|
|
|
|
const bool isHoldingItem = pcurs >= CURSOR_FIRSTITEM; |
|
|
|
|
@ -923,7 +923,7 @@ void InvMove(AxisDirection dir)
|
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (Slot >= SLOTXY_INV_ROW1_FIRST && Slot <= SLOTXY_INV_ROW1_LAST) { |
|
|
|
|
mousePos = InvMoveToBody(Slot); |
|
|
|
|
mousePos = InventoryMoveToBody(Slot); |
|
|
|
|
} else if (Slot == SLOTXY_CHEST_FIRST || Slot == SLOTXY_HAND_LEFT_FIRST) { |
|
|
|
|
Slot = SLOTXY_HEAD_FIRST; |
|
|
|
|
mousePos = InvGetEquipSlotCoord(INVLOC_HEAD); |
|
|
|
|
@ -941,7 +941,7 @@ void InvMove(AxisDirection dir)
|
|
|
|
|
if (itemId != 0) { |
|
|
|
|
for (int i = 1; i < 5; i++) { |
|
|
|
|
if (Slot - i * INV_ROW_SLOT_SIZE < SLOTXY_INV_ROW1_FIRST) { |
|
|
|
|
mousePos = InvMoveToBody(Slot - (i - 1) * INV_ROW_SLOT_SIZE); |
|
|
|
|
mousePos = InventoryMoveToBody(Slot - (i - 1) * INV_ROW_SLOT_SIZE); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (itemId != GetItemIdOnSlot(Slot - i * INV_ROW_SLOT_SIZE)) { |
|
|
|
|
@ -1059,6 +1059,140 @@ void InvMove(AxisDirection dir)
|
|
|
|
|
SetCursorPos(mousePos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Move the cursor around in the inventory |
|
|
|
|
* If mouse coords are at SLOTXY_CHEST_LAST, consider this center of equipment |
|
|
|
|
* small inventory squares are 29x29 (roughly) |
|
|
|
|
*/ |
|
|
|
|
void CheckInventoryMove(AxisDirection dir) |
|
|
|
|
{ |
|
|
|
|
static AxisDirectionRepeater repeater(/*min_interval_ms=*/150); |
|
|
|
|
dir = repeater.Get(dir); |
|
|
|
|
if (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
InventoryMove(dir); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void StashMove(AxisDirection dir) |
|
|
|
|
{ |
|
|
|
|
static AxisDirectionRepeater repeater(/*min_interval_ms=*/150); |
|
|
|
|
dir = repeater.Get(dir); |
|
|
|
|
if (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
if (Slot < 0 && ActiveStashSlot == InvalidStashPoint) { |
|
|
|
|
int invSlot = FindClosestInventorySlot(MousePosition); |
|
|
|
|
Point invSlotCoord = GetSlotCoord(invSlot); |
|
|
|
|
int invDistance = MousePosition.ManhattanDistance(invSlotCoord); |
|
|
|
|
|
|
|
|
|
Point stashSlot = FindClosestStashSlot(MousePosition); |
|
|
|
|
Point stashSlotCoord = GetStashSlotCoord(stashSlot); |
|
|
|
|
int stashDistance = MousePosition.ManhattanDistance(stashSlotCoord); |
|
|
|
|
|
|
|
|
|
if (invDistance < stashDistance) { |
|
|
|
|
BeltReturnsToStash = false; |
|
|
|
|
InventoryMove(dir); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ActiveStashSlot = stashSlot; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Item &holdItem = MyPlayer->HoldItem; |
|
|
|
|
Size itemSize = holdItem.isEmpty() ? Size { 1, 1 } : GetInventorySize(holdItem); |
|
|
|
|
|
|
|
|
|
// Jump from belt to stash
|
|
|
|
|
if (BeltReturnsToStash && Slot >= SLOTXY_BELT_FIRST && Slot <= SLOTXY_BELT_LAST) { |
|
|
|
|
if (dir.y == AxisDirectionY_UP) { |
|
|
|
|
int beltSlot = Slot - SLOTXY_BELT_FIRST; |
|
|
|
|
InvalidateInventorySlot(); |
|
|
|
|
ActiveStashSlot = { 2 + beltSlot, 10 - itemSize.height }; |
|
|
|
|
dir.y = AxisDirectionY_NONE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Jump from general inventory to stash
|
|
|
|
|
if (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_INV_LAST) { |
|
|
|
|
int firstSlot = Slot; |
|
|
|
|
if (pcurs < CURSOR_FIRSTITEM) { |
|
|
|
|
int8_t itemId = GetItemIdOnSlot(Slot); |
|
|
|
|
if (itemId != 0) { |
|
|
|
|
firstSlot = FindFirstSlotOnItem(itemId); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (IsAnyOf(firstSlot, SLOTXY_INV_ROW1_FIRST, SLOTXY_INV_ROW2_FIRST, SLOTXY_INV_ROW3_FIRST, SLOTXY_INV_ROW4_FIRST)) { |
|
|
|
|
if (dir.x == AxisDirectionX_LEFT) { |
|
|
|
|
Point slotCoord = GetSlotCoord(Slot); |
|
|
|
|
InvalidateInventorySlot(); |
|
|
|
|
ActiveStashSlot = FindClosestStashSlot(slotCoord) - Displacement { itemSize.width - 1, 0 }; |
|
|
|
|
dir.x = AxisDirectionX_NONE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool isHeadSlot = SLOTXY_HEAD_FIRST <= Slot && Slot <= SLOTXY_HEAD_LAST; |
|
|
|
|
bool isLeftHandSlot = SLOTXY_HAND_LEFT_FIRST <= Slot && Slot <= SLOTXY_HAND_LEFT_LAST; |
|
|
|
|
bool isLeftRingSlot = Slot == SLOTXY_RING_LEFT; |
|
|
|
|
if (isHeadSlot || isLeftHandSlot || isLeftRingSlot) { |
|
|
|
|
if (dir.x == AxisDirectionX_LEFT) { |
|
|
|
|
Point slotCoord = GetSlotCoord(Slot); |
|
|
|
|
InvalidateInventorySlot(); |
|
|
|
|
ActiveStashSlot = FindClosestStashSlot(slotCoord) - Displacement { itemSize.width - 1, 0 }; |
|
|
|
|
dir.x = AxisDirectionX_NONE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (Slot >= 0) { |
|
|
|
|
InventoryMove(dir); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (dir.x == AxisDirectionX_LEFT) { |
|
|
|
|
if (ActiveStashSlot.x > 0) |
|
|
|
|
ActiveStashSlot.x--; |
|
|
|
|
} else if (dir.x == AxisDirectionX_RIGHT) { |
|
|
|
|
if (ActiveStashSlot.x < 10 - itemSize.width) { |
|
|
|
|
ActiveStashSlot.x++; |
|
|
|
|
} else { |
|
|
|
|
Point stashSlotCoord = GetStashSlotCoord(ActiveStashSlot); |
|
|
|
|
Point rightPanelCoord = { GetRightPanel().position.x, stashSlotCoord.y }; |
|
|
|
|
Slot = FindClosestInventorySlot(rightPanelCoord); |
|
|
|
|
ActiveStashSlot = InvalidStashPoint; |
|
|
|
|
BeltReturnsToStash = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (dir.y == AxisDirectionY_UP) { |
|
|
|
|
if (ActiveStashSlot.y > 0) |
|
|
|
|
ActiveStashSlot.y--; |
|
|
|
|
} else if (dir.y == AxisDirectionY_DOWN) { |
|
|
|
|
if (ActiveStashSlot.y < 10 - itemSize.height) { |
|
|
|
|
ActiveStashSlot.y++; |
|
|
|
|
} else if ((holdItem.isEmpty() || CanBePlacedOnBelt(holdItem)) && ActiveStashSlot.x > 1) { |
|
|
|
|
int beltSlot = ActiveStashSlot.x - 2; |
|
|
|
|
Slot = SLOTXY_BELT_FIRST + beltSlot; |
|
|
|
|
ActiveStashSlot = InvalidStashPoint; |
|
|
|
|
BeltReturnsToStash = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (Slot >= 0) { |
|
|
|
|
ResetInvCursorPosition(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ActiveStashSlot != InvalidStashPoint) { |
|
|
|
|
Point mousePos = GetStashSlotCoord(ActiveStashSlot); |
|
|
|
|
if (pcurs == CURSOR_HAND) { |
|
|
|
|
mousePos += Displacement { INV_SLOT_HALF_SIZE_PX, INV_SLOT_HALF_SIZE_PX }; |
|
|
|
|
} |
|
|
|
|
SetCursorPos(mousePos); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FocusOnInventory(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void HotSpellMove(AxisDirection dir) |
|
|
|
|
{ |
|
|
|
|
static AxisDirectionRepeater repeater; |
|
|
|
|
@ -1215,8 +1349,11 @@ using HandleLeftStickOrDPadFn = void (*)(devilution::AxisDirection);
|
|
|
|
|
|
|
|
|
|
HandleLeftStickOrDPadFn GetLeftStickOrDPadGameUIHandler() |
|
|
|
|
{ |
|
|
|
|
if (IsStashOpen) { |
|
|
|
|
return &StashMove; |
|
|
|
|
} |
|
|
|
|
if (invflag) { |
|
|
|
|
return &InvMove; |
|
|
|
|
return &CheckInventoryMove; |
|
|
|
|
} |
|
|
|
|
if (chrflag && Players[MyPlayerId]._pStatPts > 0) { |
|
|
|
|
return &AttrIncBtnSnap; |
|
|
|
|
@ -1440,6 +1577,7 @@ void HandleRightStickMotion()
|
|
|
|
|
void InvalidateInventorySlot() |
|
|
|
|
{ |
|
|
|
|
Slot = -1; |
|
|
|
|
ActiveStashSlot = InvalidStashPoint; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -1729,26 +1867,17 @@ void PerformSpellAction()
|
|
|
|
|
|
|
|
|
|
void CtrlUseInvItem() |
|
|
|
|
{ |
|
|
|
|
Item *item; |
|
|
|
|
|
|
|
|
|
if (pcursinvitem == -1) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
auto &myPlayer = Players[MyPlayerId]; |
|
|
|
|
|
|
|
|
|
if (pcursinvitem < INVITEM_INV_FIRST) |
|
|
|
|
item = &myPlayer.InvBody[pcursinvitem]; |
|
|
|
|
else if (pcursinvitem <= INVITEM_INV_LAST) |
|
|
|
|
item = &myPlayer.InvList[pcursinvitem - INVITEM_INV_FIRST]; |
|
|
|
|
else |
|
|
|
|
item = &myPlayer.SpdList[pcursinvitem - INVITEM_BELT_FIRST]; |
|
|
|
|
|
|
|
|
|
if (item->IsScroll() && spelldata[item->_iSpell].sTargeted) { |
|
|
|
|
Item &item = GetInventoryItem(myPlayer, pcursinvitem); |
|
|
|
|
if (item.IsScroll() && spelldata[item._iSpell].sTargeted) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int itemId = GetItemIdOnSlot(Slot); |
|
|
|
|
if (item->isEquipment()) { |
|
|
|
|
if (item.isEquipment()) { |
|
|
|
|
CheckInvItem(true, false); // auto-equip if it's an equipment
|
|
|
|
|
} else { |
|
|
|
|
UseInvItem(MyPlayerId, pcursinvitem); |
|
|
|
|
@ -1777,10 +1906,17 @@ void CtrlUseStashItem()
|
|
|
|
|
|
|
|
|
|
void PerformSecondaryAction() |
|
|
|
|
{ |
|
|
|
|
auto &myPlayer = Players[MyPlayerId]; |
|
|
|
|
if (invflag) { |
|
|
|
|
if (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) { |
|
|
|
|
TryIconCurs(); |
|
|
|
|
NewCursor(CURSOR_HAND); |
|
|
|
|
} else if (IsStashOpen) { |
|
|
|
|
if (pcursstashitem != uint16_t(-1)) { |
|
|
|
|
TransferItemToInventory(myPlayer, pcursstashitem); |
|
|
|
|
} else if (pcursinvitem != -1) { |
|
|
|
|
TransferItemToStash(myPlayer, pcursinvitem); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
CtrlUseInvItem(); |
|
|
|
|
} |
|
|
|
|
@ -1797,7 +1933,6 @@ void PerformSecondaryAction()
|
|
|
|
|
} else if (pcursobj != -1) { |
|
|
|
|
NetSendCmdLocParam1(true, CMD_OPOBJXY, cursPosition, pcursobj); |
|
|
|
|
} else { |
|
|
|
|
auto &myPlayer = Players[MyPlayerId]; |
|
|
|
|
if (pcursmissile != nullptr) { |
|
|
|
|
MakePlrPath(myPlayer, pcursmissile->position.tile, true); |
|
|
|
|
myPlayer.destAction = ACTION_WALK; |
|
|
|
|
|