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

Clean up selection type #7416

Merged
merged 1 commit into from
Sep 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions Source/controls/plrctrls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ void FindItemOrObject()
continue;
}
Item &item = Items[itemId];
if (item.isEmpty() || item._iSelFlag == 0) {
if (item.isEmpty() || item.selectionRegion == SelectionRegion::None) {
continue;
}

Expand All @@ -189,7 +189,7 @@ void FindItemOrObject()

for (WorldTilePosition targetPosition : searchArea) {
Object *object = FindObjectAtPosition(targetPosition);
if (object == nullptr || object->_oSelFlag == 0) {
if (object == nullptr || !object->canInteractWith()) {
// No object or non-interactive object
continue;
}
Expand Down
34 changes: 17 additions & 17 deletions Source/cursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,29 +69,29 @@ bool IsValidMonsterForSelection(const Monster &monster)

bool TrySelectMonster(bool flipflag, Point tile, tl::function_ref<bool(const Monster &)> isValidMonster)
{
auto checkPosition = [&](int8_t selectionType, Displacement displacement) {
auto checkPosition = [&](SelectionRegion selectionRegion, Displacement displacement) {
Point posToCheck = tile + displacement;
if (!InDungeonBounds(posToCheck) || dMonster[posToCheck.x][posToCheck.y] == 0)
return;
const uint16_t monsterId = std::abs(dMonster[posToCheck.x][posToCheck.y]) - 1;
const Monster &monster = Monsters[monsterId];
if (IsTileLit(posToCheck) && (monster.data().selectionType & selectionType) != 0 && isValidMonster(monster)) {
if (IsTileLit(posToCheck) && HasAnyOf(monster.data().selectionRegion, selectionRegion) && isValidMonster(monster)) {
cursPosition = posToCheck;
pcursmonst = monsterId;
}
};

if (!flipflag)
checkPosition(4, { 2, 1 });
checkPosition(SelectionRegion::Top, { 2, 1 });
if (flipflag)
checkPosition(4, { 1, 2 });
checkPosition(4, { 2, 2 });
checkPosition(SelectionRegion::Top, { 1, 2 });
checkPosition(SelectionRegion::Top, { 2, 2 });
if (!flipflag)
checkPosition(2, { 1, 0 });
checkPosition(SelectionRegion::Middle, { 1, 0 });
if (flipflag)
checkPosition(2, { 0, 1 });
checkPosition(1, { 0, 0 });
checkPosition(2, { 1, 1 });
checkPosition(SelectionRegion::Middle, { 0, 1 });
checkPosition(SelectionRegion::Bottom, { 0, 0 });
checkPosition(SelectionRegion::Middle, { 1, 1 });
return pcursmonst != -1;
}

Expand Down Expand Up @@ -181,18 +181,18 @@ bool TrySelectObject(bool flipflag, Point tile)
Point testPosition = tile + Direction::South;
Object *object = FindObjectAtPosition(testPosition);

if (object == nullptr || object->_oSelFlag < 2) {
if (object == nullptr || HasNoneOf(object->selectionRegion, SelectionRegion::Middle)) {
// Either no object or can't interact from the test position, try the current tile
testPosition = tile;
object = FindObjectAtPosition(testPosition);

if (object == nullptr || IsNoneOf(object->_oSelFlag, 1, 3)) {
if (object == nullptr || HasNoneOf(object->selectionRegion, SelectionRegion::Bottom)) {
// Still no object (that could be activated from this position), try the tile to the bottom left or right
// (whichever is closest to the cursor as determined when we set flipflag earlier)
testPosition = tile + (flipflag ? Direction::SouthWest : Direction::SouthEast);
object = FindObjectAtPosition(testPosition);

if (object != nullptr && object->_oSelFlag < 2) {
if (object != nullptr && HasNoneOf(object->selectionRegion, SelectionRegion::Middle)) {
// Found an object but it's not in range, clear the pointer
object = nullptr;
}
Expand All @@ -211,28 +211,28 @@ bool TrySelectItem(bool flipflag, int mx, int my)
{
if (!flipflag && mx + 1 < MAXDUNX && dItem[mx + 1][my] > 0) {
const uint8_t itemId = dItem[mx + 1][my] - 1;
if (Items[itemId]._iSelFlag >= 2) {
if (HasAnyOf(Items[itemId].selectionRegion, SelectionRegion::Middle)) {
cursPosition = Point { mx, my } + Displacement { 1, 0 };
pcursitem = static_cast<int8_t>(itemId);
}
}
if (flipflag && my + 1 < MAXDUNY && dItem[mx][my + 1] > 0) {
const uint8_t itemId = dItem[mx][my + 1] - 1;
if (Items[itemId]._iSelFlag >= 2) {
if (HasAnyOf(Items[itemId].selectionRegion, SelectionRegion::Middle)) {
cursPosition = Point { mx, my } + Displacement { 0, 1 };
pcursitem = static_cast<int8_t>(itemId);
}
}
if (dItem[mx][my] > 0) {
const uint8_t itemId = dItem[mx][my] - 1;
if (Items[itemId]._iSelFlag == 1 || Items[itemId]._iSelFlag == 3) {
if (HasAnyOf(Items[itemId].selectionRegion, SelectionRegion::Bottom)) {
cursPosition = { mx, my };
pcursitem = static_cast<int8_t>(itemId);
}
}
if (mx + 1 < MAXDUNX && my + 1 < MAXDUNY && dItem[mx + 1][my + 1] > 0) {
const uint8_t itemId = dItem[mx + 1][my + 1] - 1;
if (Items[itemId]._iSelFlag >= 2) {
if (HasAnyOf(Items[itemId].selectionRegion, SelectionRegion::Middle)) {
cursPosition = Point { mx, my } + Displacement { 1, 1 };
pcursitem = static_cast<int8_t>(itemId);
}
Expand Down Expand Up @@ -341,7 +341,7 @@ bool TrySelectPixelBased(Point tile)
}

Object *object = FindObjectAtPosition(adjacentTile);
if (object != nullptr && object->_oSelFlag != 0) {
if (object != nullptr && object->canInteractWith()) {
const ClxSprite sprite = object->currentSprite();
Displacement renderingOffset = object->getRenderingOffset(sprite, adjacentTile);
if (checkSprite(adjacentTile, sprite, renderingOffset)) {
Expand Down
9 changes: 9 additions & 0 deletions Source/cursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,18 @@
#include "engine.h"
#include "engine/clx_sprite.hpp"
#include "utils/attributes.h"
#include "utils/enum_traits.h"

namespace devilution {

enum class SelectionRegion : uint8_t {
None = 0,
Bottom = 1U << 0,
Middle = 1U << 1,
Top = 1U << 2,
};
use_enum_as_flags(SelectionRegion);

enum cursor_id : uint8_t {
CURSOR_NONE,
CURSOR_HAND,
Expand Down
2 changes: 1 addition & 1 deletion Source/inv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ void CleanupItems(int ii)

if (CornerStone.isAvailable() && item.position == CornerStone.position) {
CornerStone.item.clear();
CornerStone.item._iSelFlag = 0;
CornerStone.item.selectionRegion = SelectionRegion::None;
CornerStone.item.position = { 0, 0 };
CornerStone.item._iAnimFlag = false;
CornerStone.item._iIdentified = false;
Expand Down
44 changes: 22 additions & 22 deletions Source/items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ void AddInitItems()
SetupItem(item);
item.AnimInfo.currentFrame = item.AnimInfo.numberOfFrames - 1;
item._iAnimFlag = false;
item._iSelFlag = 1;
item.selectionRegion = SelectionRegion::Bottom;
DeltaAddItem(ii);
}
}
Expand All @@ -485,7 +485,7 @@ void SpawnNote()
}

Point position = GetRandomAvailableItemPosition();
SpawnQuestItem(id, position, 0, 1, false);
SpawnQuestItem(id, position, 0, SelectionRegion::Bottom, false);
}

void CalcSelfItems(Player &player)
Expand Down Expand Up @@ -1603,7 +1603,7 @@ void SpawnRock()
int curlv = ItemsGetCurrlevel();
GetItemAttrs(item, IDI_ROCK, curlv);
SetupItem(item);
item._iSelFlag = 2;
item.selectionRegion = SelectionRegion::Middle;
item._iPostDraw = true;
item.AnimInfo.currentFrame = 10;
item._iCreateInfo |= CF_PREGEN;
Expand Down Expand Up @@ -2433,7 +2433,7 @@ void InitItems()
item.clear();
item.position = { 0, 0 };
item._iAnimFlag = false;
item._iSelFlag = 0;
item.selectionRegion = SelectionRegion::None;
item._iIdentified = false;
item._iPostDraw = false;
}
Expand All @@ -2447,17 +2447,17 @@ void InitItems()
if (Quests[Q_ROCK].IsAvailable())
SpawnRock();
if (Quests[Q_ANVIL].IsAvailable())
SpawnQuestItem(IDI_ANVIL, SetPiece.position.megaToWorld() + Displacement { 11, 11 }, 0, 1, false);
SpawnQuestItem(IDI_ANVIL, SetPiece.position.megaToWorld() + Displacement { 11, 11 }, 0, SelectionRegion::Bottom, false);
if (sgGameInitInfo.bCowQuest != 0 && currlevel == 20)
SpawnQuestItem(IDI_BROWNSUIT, { 25, 25 }, 3, 1, false);
SpawnQuestItem(IDI_BROWNSUIT, { 25, 25 }, 3, SelectionRegion::Bottom, false);
if (sgGameInitInfo.bCowQuest != 0 && currlevel == 19)
SpawnQuestItem(IDI_GREYSUIT, { 25, 25 }, 3, 1, false);
SpawnQuestItem(IDI_GREYSUIT, { 25, 25 }, 3, SelectionRegion::Bottom, false);
// In multiplayer items spawn during level generation to avoid desyncs
if (gbIsMultiplayer) {
if (Quests[Q_MUSHROOM].IsAvailable())
SpawnQuestItem(IDI_FUNGALTM, { 0, 0 }, 5, 1, false);
SpawnQuestItem(IDI_FUNGALTM, { 0, 0 }, 5, SelectionRegion::Bottom, false);
if (currlevel == Quests[Q_VEIL]._qlevel + 1 && Quests[Q_VEIL]._qactive != QUEST_NOTAVAIL)
SpawnQuestItem(IDI_GLDNELIX, { 0, 0 }, 5, 1, false);
SpawnQuestItem(IDI_GLDNELIX, { 0, 0 }, 5, SelectionRegion::Bottom, false);
}
if (currlevel > 0 && currlevel < 16)
AddInitItems();
Expand Down Expand Up @@ -3420,7 +3420,7 @@ void SpawnItem(Monster &monster, Point position, bool sendmsg, bool spawn /*= fa
// Drop the brain as extra item to ensure that all clients see the brain drop
// When executing SpawnItem is not reliable, because another client can already have the quest state updated before SpawnItem is executed
Point posBrain = GetSuperItemLoc(position);
SpawnQuestItem(IDI_BRAIN, posBrain, 0, 0, true);
SpawnQuestItem(IDI_BRAIN, posBrain, 0, SelectionRegion::None, true);
}
// Normal monster
if ((monster.data().treasure & T_NODROP) != 0)
Expand Down Expand Up @@ -3612,7 +3612,7 @@ void CornerstoneLoad(Point position)
CornerStone.item = item;
}

void SpawnQuestItem(_item_indexes itemid, Point position, int randarea, int selflag, bool sendmsg)
void SpawnQuestItem(_item_indexes itemid, Point position, int randarea, SelectionRegion selectionRegion, bool sendmsg)
{
if (randarea > 0) {
int tries = 0;
Expand Down Expand Up @@ -3652,8 +3652,8 @@ void SpawnQuestItem(_item_indexes itemid, Point position, int randarea, int self
item._iSeed = AdvanceRndSeed();
SetRndSeed(item._iSeed);
item._iPostDraw = true;
if (selflag != 0) {
item._iSelFlag = selflag;
if (selectionRegion != SelectionRegion::None) {
item.selectionRegion = selectionRegion;
item.AnimInfo.currentFrame = item.AnimInfo.numberOfFrames - 1;
item._iAnimFlag = false;
}
Expand All @@ -3679,7 +3679,7 @@ void SpawnRewardItem(_item_indexes itemid, Point position, bool sendmsg)
int curlv = ItemsGetCurrlevel();
GetItemAttrs(item, itemid, curlv);
item.setNewAnimation(true);
item._iSelFlag = 2;
item.selectionRegion = SelectionRegion::Middle;
item._iPostDraw = true;
item._iIdentified = true;
GenerateNewSeed(item);
Expand Down Expand Up @@ -3711,9 +3711,9 @@ void RespawnItem(Item &item, bool flipFlag)
item._iRequest = false;

if (IsAnyOf(item._iCurs, ICURS_MAGIC_ROCK, ICURS_TAVERN_SIGN, ICURS_ANVIL_OF_FURY))
item._iSelFlag = 1;
item.selectionRegion = SelectionRegion::Bottom;
else if (IsAnyOf(item._iCurs, ICURS_MAP_OF_THE_STARS, ICURS_RUNE_BOMB, ICURS_THEODORE, ICURS_AURIC_AMULET))
item._iSelFlag = 2;
item.selectionRegion = SelectionRegion::Middle;

if (item._iCurs == ICURS_MAGIC_ROCK) {
PlaySfxLoc(ItemDropSnds[it], item.position);
Expand Down Expand Up @@ -3745,9 +3745,9 @@ void ProcessItems()
continue;
item.AnimInfo.processAnimation();
if (item._iCurs == ICURS_MAGIC_ROCK) {
if (item._iSelFlag == 1 && item.AnimInfo.currentFrame == 10)
if (item.selectionRegion == SelectionRegion::Bottom && item.AnimInfo.currentFrame == 10)
item.AnimInfo.currentFrame = 0;
if (item._iSelFlag == 2 && item.AnimInfo.currentFrame == 20)
if (item.selectionRegion == SelectionRegion::Middle && item.AnimInfo.currentFrame == 20)
item.AnimInfo.currentFrame = 10;
} else {
if (item.AnimInfo.currentFrame == (item.AnimInfo.numberOfFrames - 1) / 2)
Expand All @@ -3756,7 +3756,7 @@ void ProcessItems()
if (item.AnimInfo.isLastFrame()) {
item.AnimInfo.currentFrame = item.AnimInfo.numberOfFrames - 1;
item._iAnimFlag = false;
item._iSelFlag = 1;
item.selectionRegion = SelectionRegion::Bottom;
}
}
}
Expand Down Expand Up @@ -4639,7 +4639,7 @@ int ItemNoFlippy()
int r = ActiveItems[ActiveItemCount - 1];
Items[r].AnimInfo.currentFrame = Items[r].AnimInfo.numberOfFrames - 1;
Items[r]._iAnimFlag = false;
Items[r]._iSelFlag = 1;
Items[r].selectionRegion = SelectionRegion::Bottom;

return r;
}
Expand Down Expand Up @@ -4766,11 +4766,11 @@ void Item::setNewAnimation(bool showAnimation)
_iRequest = false;
if (showAnimation) {
_iAnimFlag = true;
_iSelFlag = 0;
selectionRegion = SelectionRegion::None;
} else {
AnimInfo.currentFrame = AnimInfo.numberOfFrames - 1;
_iAnimFlag = false;
_iSelFlag = 1;
selectionRegion = SelectionRegion::Bottom;
}
}

Expand Down
5 changes: 3 additions & 2 deletions Source/items.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <optional>

#include "DiabloUI/ui_flags.hpp"
#include "cursor.h"
#include "engine.h"
#include "engine/animationinfo.h"
#include "engine/point.hpp"
Expand Down Expand Up @@ -188,7 +189,7 @@ struct Item {
*/
AnimationInfo AnimInfo;
bool _iDelFlag = false; // set when item is flagged for deletion, deprecated in 1.02
uint8_t _iSelFlag = 0;
SelectionRegion selectionRegion = SelectionRegion::None;
bool _iPostDraw = false;
bool _iIdentified = false;
item_quality _iMagical = ITEM_QUALITY_NORMAL;
Expand Down Expand Up @@ -525,7 +526,7 @@ void RecreateItem(const Player &player, Item &item, _item_indexes idx, uint16_t
void RecreateEar(Item &item, uint16_t ic, uint32_t iseed, uint8_t bCursval, std::string_view heroName);
void CornerstoneSave();
void CornerstoneLoad(Point position);
void SpawnQuestItem(_item_indexes itemid, Point position, int randarea, int selflag, bool sendmsg);
void SpawnQuestItem(_item_indexes itemid, Point position, int randarea, SelectionRegion selectionRegion, bool sendmsg);
void SpawnRewardItem(_item_indexes itemid, Point position, bool sendmsg);
void SpawnMapOfDoom(Point position, bool sendmsg);
void SpawnRuneBomb(Point position, bool sendmsg);
Expand Down
2 changes: 1 addition & 1 deletion Source/levels/themes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ void Theme_Library(int t)
Object *bookstand = AddObject(OBJ_BOOKSTAND, { xp, yp });
if (!FlipCoin(2 * librnd[leveltype - 1])) {
if (bookstand != nullptr) {
bookstand->_oSelFlag = 0;
bookstand->selectionRegion = SelectionRegion::None;
bookstand->_oAnimFrame += 2;
}
}
Expand Down
8 changes: 4 additions & 4 deletions Source/loadsave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ void LoadItemData(LoadHelper &file, Item &item)
item.AnimInfo.currentFrame = file.NextLENarrow<int32_t, int8_t>(-1);
file.Skip(8); // Skip _iAnimWidth and _iAnimWidth2
file.Skip(4); // Unused since 1.02
item._iSelFlag = file.NextLE<uint8_t>();
item.selectionRegion = static_cast<SelectionRegion>(file.NextLE<uint8_t>());
file.Skip(3); // Alignment
item._iPostDraw = file.NextBool32();
item._iIdentified = file.NextBool32();
Expand Down Expand Up @@ -842,7 +842,7 @@ void LoadObject(LoadHelper &file, Object &object)
object._oSolidFlag = file.NextBool32();
object._oMissFlag = file.NextBool32();

object._oSelFlag = file.NextLE<int8_t>();
object.selectionRegion = static_cast<SelectionRegion>(file.NextLE<int8_t>());
file.Skip(3); // Alignment
object._oPreFlag = file.NextBool32();
object._oTrapFlag = file.NextBool32();
Expand Down Expand Up @@ -1094,7 +1094,7 @@ void SaveItem(SaveHelper &file, const Item &item)
// write _iAnimWidth2 for vanilla compatibility
file.WriteLE<int32_t>(CalculateWidth2(ItemAnimWidth));
file.Skip<uint32_t>(); // _delFlag, unused since 1.02
file.WriteLE<uint8_t>(item._iSelFlag);
file.WriteLE<uint8_t>(static_cast<uint8_t>(item.selectionRegion));
file.Skip(3); // Alignment
file.WriteLE<uint32_t>(item._iPostDraw ? 1 : 0);
file.WriteLE<uint32_t>(item._iIdentified ? 1 : 0);
Expand Down Expand Up @@ -1626,7 +1626,7 @@ void SaveObject(SaveHelper &file, const Object &object)
file.WriteLE<uint32_t>(object._oSolidFlag ? 1 : 0);
file.WriteLE<uint32_t>(object._oMissFlag ? 1 : 0);

file.WriteLE<int8_t>(object._oSelFlag);
file.WriteLE<int8_t>(static_cast<uint8_t>(object.selectionRegion));
file.Skip(3); // Alignment
file.WriteLE<uint32_t>(object._oPreFlag ? 1 : 0);
file.WriteLE<uint32_t>(object._oTrapFlag ? 1 : 0);
Expand Down
Loading
Loading