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

Merge master into development #6547

Merged
merged 23 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
00e8d8d
Add Save Game confirmation
kphoenix137 Aug 25, 2023
2a39339
Fix cursor jitter when clicking inv items (#6510)
kphoenix137 Aug 25, 2023
c91e693
Revert "Fix cursor jitter when clicking inv items (#6510)"
AJenbo Aug 26, 2023
45dbe6a
Shift software cursor graphic and remove special casing (#6512)
StephenCWills Aug 26, 2023
dd296d2
Find the closest point when pasting items on the edge of the stash
ephphatha Aug 27, 2023
fb97eb7
Clean up hit detection for inventory slots when pasting large items
ephphatha Aug 27, 2023
9995c00
Validate Item Locations (#6427)
kphoenix137 Aug 27, 2023
4deae11
Fix PlayerNetPack validation and tests
StephenCWills Aug 27, 2023
e9de3cc
Upgrade vcpkg baseline commit (#6528)
tsunamistate Aug 29, 2023
e3d79ae
Fix automap (#6513)
kphoenix137 Aug 29, 2023
6cfa1cc
Add draft for 1.5.1 release notes in metainfo
tsunamistate Aug 16, 2023
3411bd0
Fix typo in changelog
tsunamistate Aug 16, 2023
37614c4
Small changes to swedish translation (#6397)
Mr-Bajs Aug 29, 2023
c0caedc
Delete .bettercodehub.yml
AJenbo Aug 31, 2023
d468208
Add duration parameter to InitDiabloMsg() (#6514)
kphoenix137 Aug 31, 2023
24b3455
Update CHANGELOG.md (#6531)
AJenbo Aug 31, 2023
26977f3
Update 1.5.1 release notes in metainfo
AJenbo Aug 31, 2023
070a119
Fix handling of gamepad cursor movement following item cursor change
ephphatha Aug 31, 2023
0d292b1
Move to the first inventory column from the left hand while holding w…
ephphatha Aug 31, 2023
52b806c
Update CHANGELOG.md
AJenbo Aug 31, 2023
c85fcbd
fix cursor alignment following gamepad movement in stash
ephphatha Sep 1, 2023
bd8aab0
handle stash item swapping using the gamepad a bit better
ephphatha Sep 1, 2023
af869ac
Merge branch 'master' into dev-merged
glebm Sep 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .bettercodehub.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/Windows_MSVC_x64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ jobs:
uses: lukka/get-cmake@latest

- name: Restore or setup vcpkg
uses: lukka/run-vcpkg@v11
uses: lukka/run-vcpkg@v11.1
with:
vcpkgGitCommitId: '78b61582c9e093fda56a01ebb654be15a0033897'
vcpkgGitCommitId: '927bc12e31148b0d44ae9d174b96c20e3bcf08eb'

- name: Fetch test data
run: |
Expand Down
17 changes: 17 additions & 0 deletions Packaging/nix/devilutionx.metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,23 @@
</screenshot>
</screenshots>
<releases>
<release version="1.5.1" date="2023-xx-xx">
<description>
<p>This is a primarily bugfix release, which includes the following updates:</p>
<ul>
<li>Resolve various gameplay and graphical issues</li>
<li>Revamped settings menu for better organization</li>
<li>Rectification of crashes identified in version 1.5.0</li>
<li>Reduced RAM usage for improved performance</li>
<li>Updates to PVP arenas</li>
<li>Increased reliability in multiplayer functionality</li>
<li>Improved translations</li>
<li>Fixed gameplay recording playback issues</li>
</ul>
<p>Please visit the full changelog for more detailed notes</p>
</description>
<url>https://github.com/diasurgical/devilutionX/releases/tag/1.5.1</url>
</release>
<release version="1.5.0" date="2023-06-13">
<description>
<p>This release includes a lot of features, such as:</p>
Expand Down
28 changes: 22 additions & 6 deletions Source/automap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,28 @@ void DrawDiamond(const Surface &out, Point center, uint8_t color)

void DrawMapVerticalDoor(const Surface &out, Point center, uint8_t colorBright, uint8_t colorDim)
{
DrawMapLineNE(out, { center.x + AmLine(8), center.y - AmLine(4) }, AmLine(4), colorDim);
DrawMapLineNE(out, { center.x - AmLine(16), center.y + AmLine(8) }, AmLine(4), colorDim);
DrawDiamond(out, center, colorBright);
if (leveltype != DTYPE_CATACOMBS) {
DrawMapLineNE(out, { center.x + AmLine(8), center.y - AmLine(4) }, AmLine(4), colorDim);
DrawMapLineNE(out, { center.x - AmLine(16), center.y + AmLine(8) }, AmLine(4), colorDim);
DrawDiamond(out, center, colorBright);
} else {
DrawMapLineNE(out, { center.x - AmLine(8), center.y + AmLine(4) }, AmLine(8), colorDim);
DrawMapLineNE(out, { center.x - AmLine(16), center.y + AmLine(8) }, AmLine(4), colorDim);
DrawDiamond(out, { center.x + AmLine(16), center.y - AmLine(8) }, colorBright);
}
}

void DrawMapHorizontalDoor(const Surface &out, Point center, uint8_t colorBright, uint8_t colorDim)
{
DrawMapLineSE(out, { center.x - AmLine(16), center.y - AmLine(8) }, AmLine(4), colorDim);
DrawMapLineSE(out, { center.x + AmLine(8), center.y + AmLine(4) }, AmLine(4), colorDim);
DrawDiamond(out, center, colorBright);
if (leveltype != DTYPE_CATACOMBS) {
DrawMapLineSE(out, { center.x - AmLine(16), center.y - AmLine(8) }, AmLine(4), colorDim);
DrawMapLineSE(out, { center.x + AmLine(8), center.y + AmLine(4) }, AmLine(4), colorDim);
DrawDiamond(out, center, colorBright);
} else {
DrawMapLineSE(out, { center.x - AmLine(8), center.y - AmLine(4) }, AmLine(8), colorDim);
DrawMapLineSE(out, { center.x + AmLine(8), center.y + AmLine(4) }, AmLine(4), colorDim);
DrawDiamond(out, { center.x - AmLine(16), center.y - AmLine(8) }, colorBright);
}
}

void DrawDirt(const Surface &out, Point center, uint8_t color)
Expand Down Expand Up @@ -897,6 +909,7 @@ void DrawAutomap(const Surface &out)
Displacement myPlayerOffset = {};
if (myPlayer.isWalking())
myPlayerOffset = GetOffsetForWalking(myPlayer.AnimInfo, myPlayer._pdir, true);
myPlayerOffset += Displacement { -1, (leveltype != DTYPE_CAVES) ? TILE_HEIGHT - 1 : -1 };

int d = (AutoMapScale * 64) / 100;
int cells = 2 * (gnScreenWidth / 2 / d) + 1;
Expand Down Expand Up @@ -958,13 +971,16 @@ void DrawAutomap(const Surface &out)
screen.y += AmLine(32);
}

if (leveltype == DTYPE_CAVES)
myPlayerOffset.deltaY += TILE_HEIGHT;
for (size_t playerId = 0; playerId < Players.size(); playerId++) {
Player &player = Players[playerId];
if (player.isOnActiveLevel() && player.plractive && !player._pLvlChanging && (&player == MyPlayer || player.friendlyMode)) {
DrawAutomapPlr(out, myPlayerOffset, playerId);
}
}

myPlayerOffset.deltaY -= TILE_HEIGHT / 2;
if (AutoMapShowItems)
SearchAutomapItem(out, myPlayerOffset, 8, [](Point position) { return dItem[position.x][position.y] != 0; });
#ifdef _DEBUG
Expand Down
151 changes: 72 additions & 79 deletions Source/controls/plrctrls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -655,10 +655,10 @@ Point InvGetEquipSlotCoordFromInvSlot(const inv_xy_slot slot)
Point GetSlotCoord(int slot)
{
if (slot >= SLOTXY_BELT_FIRST && slot <= SLOTXY_BELT_LAST) {
return GetPanelPosition(UiPanels::Main, InvRect[slot].position);
return GetPanelPosition(UiPanels::Main, InvRect[slot].Center());
}

return GetPanelPosition(UiPanels::Inventory, InvRect[slot].position);
return GetPanelPosition(UiPanels::Inventory, InvRect[slot].Center());
}

/**
Expand Down Expand Up @@ -734,33 +734,19 @@ void ResetInvCursorPosition()
} else {
mousePos = GetSlotCoord(Slot);
}

if (!MyPlayer->HoldItem.isEmpty()) {
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 (!MyPlayer->HoldItem.isEmpty())
mousePos += Displacement { -INV_SLOT_HALF_SIZE_PX, -INV_SLOT_HALF_SIZE_PX };
} else {
mousePos = InvGetEquipSlotCoordFromInvSlot((inv_xy_slot)Slot);
if (!MyPlayer->HoldItem.isEmpty()) {
Size itemSize = GetInventorySize(MyPlayer->HoldItem);
mousePos += Displacement { -INV_SLOT_HALF_SIZE_PX, -INV_SLOT_HALF_SIZE_PX * itemSize.height };
}
}

mousePos.x += (InventorySlotSizeInPixels.width / 2);
mousePos.y -= (InventorySlotSizeInPixels.height / 2);

SetCursorPos(mousePos);
}

int FindClosestInventorySlot(Point mousePos)
{
int shortestDistance = std::numeric_limits<int>::max();
int bestSlot = 0;
mousePos += Displacement { -INV_SLOT_HALF_SIZE_PX, INV_SLOT_HALF_SIZE_PX };

for (int i = 0; i < NUM_XY_SLOTS; i++) {
int distance = mousePos.ManhattanDistance(GetSlotCoord(i));
Expand All @@ -777,7 +763,6 @@ 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 };

for (Point point : PointsInRectangle(Rectangle { { 0, 0 }, Size { 10, 10 } })) {
int distance = mousePos.ManhattanDistance(GetStashSlotCoord(point));
Expand Down Expand Up @@ -820,7 +805,7 @@ void InventoryMove(AxisDirection dir)

const Item &heldItem = MyPlayer->HoldItem;
const bool isHoldingItem = !heldItem.isEmpty();
Size itemSize = GetInventorySize(heldItem);
Size itemSize = isHoldingItem ? GetInventorySize(heldItem) : Size { 1 };

// when item is on cursor (pcurs > 1), this is the real cursor XY
if (dir.x == AxisDirectionX_LEFT) {
Expand Down Expand Up @@ -949,7 +934,7 @@ void InventoryMove(AxisDirection dir)
if (Slot == SLOTXY_HEAD || Slot == SLOTXY_CHEST) {
Slot = SLOTXY_INV_ROW1_FIRST + 4;
} else if (Slot == SLOTXY_RING_LEFT || Slot == SLOTXY_HAND_LEFT) {
Slot = SLOTXY_INV_ROW1_FIRST + 1;
Slot = SLOTXY_INV_ROW1_FIRST + (itemSize.width > 1 ? 0 : 1);
} else if (Slot == SLOTXY_RING_RIGHT || Slot == SLOTXY_HAND_RIGHT || Slot == SLOTXY_AMULET) {
Slot = SLOTXY_INV_ROW1_LAST - 1;
} else if (Slot <= (SLOTXY_INV_ROW4_LAST - (itemSize.height * INV_ROW_SLOT_SIZE))) {
Expand Down Expand Up @@ -1007,28 +992,27 @@ void InventoryMove(AxisDirection dir)
} else {
mousePos = GetSlotCoord(Slot);
}
// move cursor to the center of the slot if not holding anything or top left is holding an object
if (isHoldingItem) {
if (Slot < SLOTXY_INV_FIRST) {
// The coordinates we get for body slots are based on the centre of the region relative to the hand cursor
// Need to adjust the position for items larger than 1x1 so they're aligned as expected
mousePos.x -= itemSize.width * INV_SLOT_HALF_SIZE_PX;
mousePos.y -= itemSize.height * INV_SLOT_HALF_SIZE_PX;
}
} else {
// get item under new slot if navigating on the inventory
if (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_BELT_LAST) {
// If we're in the inventory we may need to move the cursor to an area that doesn't line up with the center of a cell
if (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_INV_LAST) {
if (!isHoldingItem) {
// If we're not holding an item
int8_t itemInvId = GetItemIdOnSlot(Slot);
int itemSlot = FindFirstSlotOnItem(itemInvId);
if (itemSlot < 0)
itemSlot = Slot;

// offset the cursor so it shows over the center of the item
mousePos = GetSlotCoord(itemSlot);
itemSize = GetItemSizeOnSlot(itemSlot);
mousePos.x += (itemSize.width * InventorySlotSizeInPixels.width) / 2;
mousePos.y += (itemSize.height * InventorySlotSizeInPixels.height) / 2;
if (itemInvId != 0) {
// but the cursor moved over an item
int itemSlot = FindFirstSlotOnItem(itemInvId);
if (itemSlot < 0)
itemSlot = Slot;

// then we need to offset the cursor so it shows over the center of the item
mousePos = GetSlotCoord(itemSlot);
itemSize = GetItemSizeOnSlot(itemSlot);
}
}
// At this point itemSize is either the size of the cell/item the hand cursor is over, or the size of the item we're currently holding.
// mousePos is the center of the top left cell of the item under the hand cursor, or the top left cell of the region that could fit the item we're holding.
// either way we need to offset the mouse position to account for items (we're holding or hovering over) with a dimension larger than a single cell.
mousePos.x += ((itemSize.width - 1) * InventorySlotSizeInPixels.width) / 2;
mousePos.y += ((itemSize.height - 1) * InventorySlotSizeInPixels.height) / 2;
}

if (mousePos == MousePosition) {
Expand Down Expand Up @@ -1184,9 +1168,9 @@ void StashMove(AxisDirection dir)

if (ActiveStashSlot != InvalidStashPoint) {
Point mousePos = GetStashSlotCoord(ActiveStashSlot);
if (pcurs == CURSOR_HAND) {
mousePos += Displacement { INV_SLOT_HALF_SIZE_PX, INV_SLOT_HALF_SIZE_PX };
}
// Stash coordinates are all the top left of the cell, so we need to shift the mouse to the center of the held item
// or the center of the cell if we have a hand cursor (itemSize will be 1x1 here so we can use the same calculation)
mousePos += Displacement { itemSize.width * INV_SLOT_HALF_SIZE_PX, itemSize.height * INV_SLOT_HALF_SIZE_PX };
SetCursorPos(mousePos);
return;
}
Expand Down Expand Up @@ -1827,46 +1811,49 @@ void PerformPrimaryAction()
} else if (GetRightPanel().contains(MousePosition) || GetMainPanel().contains(MousePosition)) {
int inventorySlot = (Slot >= 0) ? Slot : FindClosestInventorySlot(MousePosition);

const Size cursorSizeInCells = MyPlayer->HoldItem.isEmpty() ? Size { 1, 1 } : GetInventorySize(MyPlayer->HoldItem);

// Find any item occupying a slot that is currently under the cursor
int8_t itemUnderCursor = [](int inventorySlot, Size cursorSizeInCells) {
if (inventorySlot < SLOTXY_INV_FIRST || inventorySlot > SLOTXY_INV_LAST)
return 0;
for (int x = 0; x < cursorSizeInCells.width; x++) {
for (int y = 0; y < cursorSizeInCells.height; y++) {
int slotUnderCursor = inventorySlot + x + y * INV_ROW_SLOT_SIZE;
if (slotUnderCursor > SLOTXY_INV_LAST)
continue;
int itemId = GetItemIdOnSlot(slotUnderCursor);
if (itemId != 0)
return itemId;
int jumpSlot = inventorySlot; // If the cursor is over an inventory slot we may need to adjust it due to pasting items of different sizes over each other
if (inventorySlot >= SLOTXY_INV_FIRST && inventorySlot <= SLOTXY_INV_LAST) {
const Size cursorSizeInCells = MyPlayer->HoldItem.isEmpty() ? Size { 1, 1 } : GetInventorySize(MyPlayer->HoldItem);

// Find any item occupying a slot that is currently under the cursor
int8_t itemUnderCursor = [](int inventorySlot, Size cursorSizeInCells) {
if (inventorySlot < SLOTXY_INV_FIRST || inventorySlot > SLOTXY_INV_LAST)
return 0;
for (int x = 0; x < cursorSizeInCells.width; x++) {
for (int y = 0; y < cursorSizeInCells.height; y++) {
int slotUnderCursor = inventorySlot + x + y * INV_ROW_SLOT_SIZE;
if (slotUnderCursor > SLOTXY_INV_LAST)
continue;
int itemId = GetItemIdOnSlot(slotUnderCursor);
if (itemId != 0)
return itemId;
}
}
}
return 0;
}(inventorySlot, cursorSizeInCells);
return 0;
}(inventorySlot, cursorSizeInCells);

// The cursor will need to be shifted to
// this slot if the item is swapped or lifted
int jumpSlot = FindFirstSlotOnItem(itemUnderCursor);
// Capture the first slot of the first item (if any) under the cursor
if (itemUnderCursor > 0)
jumpSlot = FindFirstSlotOnItem(itemUnderCursor);
}
CheckInvItem();

// If we don't find the item in the same position as before,
// it suggests that the item was swapped or lifted
int newSlot = FindFirstSlotOnItem(itemUnderCursor);
if (jumpSlot >= 0 && jumpSlot != newSlot) {
if (inventorySlot >= SLOTXY_INV_FIRST && inventorySlot <= SLOTXY_INV_LAST) {
Point mousePos = GetSlotCoord(jumpSlot);
Slot = jumpSlot;
const Size newCursorSizeInCells = MyPlayer->HoldItem.isEmpty() ? GetItemSizeOnSlot(jumpSlot) : GetInventorySize(MyPlayer->HoldItem);
mousePos.x += ((newCursorSizeInCells.width - 1) * InventorySlotSizeInPixels.width) / 2;
mousePos.y += ((newCursorSizeInCells.height - 1) * InventorySlotSizeInPixels.height) / 2;
SetCursorPos(mousePos);
}
} else if (IsStashOpen && GetLeftPanel().contains(MousePosition)) {
Point stashSlot = (ActiveStashSlot != InvalidStashPoint) ? ActiveStashSlot : FindClosestStashSlot(MousePosition);

const Size cursorSizeInCells = MyPlayer->HoldItem.isEmpty() ? Size { 1, 1 } : GetInventorySize(MyPlayer->HoldItem);
Size cursorSizeInCells = MyPlayer->HoldItem.isEmpty() ? Size { 1, 1 } : GetInventorySize(MyPlayer->HoldItem);

// Find any item occupying a slot that is currently under the cursor
StashStruct::StashCell itemUnderCursor = [](Point stashSlot, Size cursorSizeInCells) -> StashStruct::StashCell {
if (stashSlot != InvalidStashPoint)
if (stashSlot == InvalidStashPoint)
return StashStruct::EmptyCell;
for (Point slotUnderCursor : PointsInRectangle(Rectangle { stashSlot, cursorSizeInCells })) {
if (slotUnderCursor.x >= 10 || slotUnderCursor.y >= 10)
Expand All @@ -1878,20 +1865,26 @@ void PerformPrimaryAction()
return StashStruct::EmptyCell;
}(stashSlot, cursorSizeInCells);

// The cursor will need to be shifted to
// this slot if the item is swapped or lifted
Point jumpSlot = FindFirstStashSlotOnItem(itemUnderCursor);
Point jumpSlot = itemUnderCursor == StashStruct::EmptyCell ? stashSlot : FindFirstStashSlotOnItem(itemUnderCursor);
CheckStashItem(MousePosition);

// If we don't find the item in the same position as before,
// it suggests that the item was swapped or lifted
Point newSlot = FindFirstStashSlotOnItem(itemUnderCursor);
if (jumpSlot != InvalidStashPoint && jumpSlot != newSlot) {
Point mousePos = GetStashSlotCoord(jumpSlot);
mousePos.y -= InventorySlotSizeInPixels.height;
ActiveStashSlot = jumpSlot;
SetCursorPos(mousePos);
Point mousePos = GetStashSlotCoord(jumpSlot);
ActiveStashSlot = jumpSlot;
if (MyPlayer->HoldItem.isEmpty()) {
// For inventory cut/paste we can combine the cases where we swap or simply paste items. Because stash movement is always cell based (there's no fast
// movement over large items) it looks better if we offset the hand cursor to the bottom right cell of the item we just placed.
ActiveStashSlot += Displacement { cursorSizeInCells - 1 }; // shift the active stash slot coordinates to account for items larger than 1x1
// Then we displace the mouse position to the bottom right corner of the item, then shift it back half a cell to center it.
// Could also be written as (cursorSize - 1) * InventorySlotSize + HalfInventorySlotSize, same thing in the end.
mousePos += Displacement { cursorSizeInCells } * Displacement { InventorySlotSizeInPixels } - Displacement { InventorySlotSizeInPixels } / 2;
} else {
// If we've picked up an item then use the same logic as the inventory so that the cursor is offset to the center of where the old item location was
// (in this case jumpSlot was the top left cell of where it used to be in the grid, and we need to update the cursor size since we're now holding the item)
cursorSizeInCells = GetInventorySize(MyPlayer->HoldItem);
mousePos.x += ((cursorSizeInCells.width) * InventorySlotSizeInPixels.width) / 2;
mousePos.y += ((cursorSizeInCells.height) * InventorySlotSizeInPixels.height) / 2;
}
SetCursorPos(mousePos);
}
return;
}
Expand Down
8 changes: 5 additions & 3 deletions Source/engine/render/scrollrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,21 +240,23 @@ void DrawCursor(const Surface &out)

// Copy the buffer before the item cursor and its 1px outline are drawn to a temporary buffer.
const int outlineWidth = !MyPlayer->HoldItem.isEmpty() ? 1 : 0;
Displacement offset = !MyPlayer->HoldItem.isEmpty() ? Displacement { cursSize / 2 } : Displacement { 0 };
Point cursPosition = MousePosition - offset;

Rectangle &rect = cursor.rect;
rect.position.x = MousePosition.x - outlineWidth;
rect.position.x = cursPosition.x - outlineWidth;
rect.size.width = cursSize.width + 2 * outlineWidth;
Clip(rect.position.x, rect.size.width, out.w());

rect.position.y = MousePosition.y - outlineWidth;
rect.position.y = cursPosition.y - outlineWidth;
rect.size.height = cursSize.height + 2 * outlineWidth;
Clip(rect.position.y, rect.size.height, out.h());

if (rect.size.width == 0 || rect.size.height == 0)
return;

BlitCursor(cursor.behindBuffer, rect.size.width, &out[rect.position], out.pitch(), rect.size.width, rect.size.height);
DrawSoftwareCursor(out, MousePosition + Displacement { 0, cursSize.height - 1 }, pcurs);
DrawSoftwareCursor(out, cursPosition + Displacement { 0, cursSize.height - 1 }, pcurs);
}

/**
Expand Down
Loading
Loading