Browse Source

Use ObjectAtPosition when checking if an item can be dropped

This extracts some of the common object logic from ItemSpaceOk and CanPut, these functions are almost identical except for the way players and monsters are checked...
pull/3859/head
ephphatha 4 years ago committed by Anders Jenbo
parent
commit
77a783098d
  1. 27
      Source/inv.cpp
  2. 41
      Source/items.cpp
  3. 37
      Source/objects.cpp
  4. 16
      Source/objects.h

27
Source/inv.cpp

@ -1769,29 +1769,30 @@ void SyncGetItem(Point position, int32_t iseed, _item_indexes idx, uint16_t ci)
bool CanPut(Point position)
{
if (dItem[position.x][position.y] != 0)
if (!InDungeonBounds(position)) {
return false;
if (nSolidTable[dPiece[position.x][position.y]])
}
if (IsTileSolid(position)) {
return false;
if (dObject[position.x][position.y] != 0 && Objects[abs(dObject[position.x][position.y]) - 1]._oSolidFlag)
}
if (dItem[position.x][position.y] != 0) {
return false;
}
if (dObject[position.x + 1][position.y + 1] != 0) {
int8_t oi = abs(dObject[position.x + 1][position.y + 1]) - 1;
if (Objects[oi]._oSelFlag != 0) {
if (currlevel == 0) {
if (dMonster[position.x][position.y] != 0) {
return false;
}
}
if (dObject[position.x + 1][position.y] > 0 && dObject[position.x][position.y + 1] > 0) {
if (Objects[dObject[position.x + 1][position.y] - 1]._oSelFlag != 0 && Objects[dObject[position.x][position.y + 1] - 1]._oSelFlag != 0)
if (dMonster[position.x + 1][position.y + 1] != 0) {
return false;
}
}
if (currlevel == 0 && dMonster[position.x][position.y] != 0)
return false;
if (currlevel == 0 && dMonster[position.x + 1][position.y + 1] != 0)
if (IsItemBlockingObjectAtPosition(position)) {
return false;
}
return true;
}

41
Source/items.cpp

@ -396,11 +396,11 @@ bool ItemPlace(Point position)
return false;
if (dItem[position.x][position.y] != 0)
return false;
if (dObject[position.x][position.y] != 0)
if (IsObjectAtPosition(position))
return false;
if (TileContainsSetPiece(position))
return false;
if (nSolidTable[dPiece[position.x][position.y]])
if (IsTileSolid(position))
return false;
return true;
@ -3106,44 +3106,31 @@ void CreatePlrItems(int playerId)
bool ItemSpaceOk(Point position)
{
if (!InDungeonBounds(position))
if (!InDungeonBounds(position)) {
return false;
}
if (dMonster[position.x][position.y] != 0)
if (IsTileSolid(position)) {
return false;
}
if (dPlayer[position.x][position.y] != 0)
if (dItem[position.x][position.y] != 0) {
return false;
}
if (dItem[position.x][position.y] != 0)
if (dMonster[position.x][position.y] != 0) {
return false;
if (dObject[position.x][position.y] != 0) {
int oi = abs(dObject[position.x][position.y]) - 1;
if (Objects[oi]._oSolidFlag)
return false;
}
Point south = position + Direction::South;
if (InDungeonBounds(south)) {
int objectId = dObject[south.x][south.y];
if (objectId != 0 && Objects[abs(objectId) - 1]._oSelFlag != 0)
return false;
if (dPlayer[position.x][position.y] != 0) {
return false;
}
Point southEast = position + Direction::SouthEast;
Point southWest = position + Direction::SouthWest;
if (InDungeonBounds(southEast) && InDungeonBounds(southWest)) {
int objectIdSE = dObject[southEast.x][southEast.y];
int objectIdSW = dObject[southWest.x][southWest.y];
if (objectIdSE > 0 && objectIdSW > 0) {
if (Objects[objectIdSE - 1]._oSelFlag != 0 && Objects[objectIdSW - 1]._oSelFlag != 0) {
return false;
}
}
if (IsItemBlockingObjectAtPosition(position)) {
return false;
}
return IsTileNotSolid(position);
return true;
}
int AllocateItem()

37
Source/objects.cpp

@ -4347,19 +4347,46 @@ bool Object::IsDisabled() const
return IsAnyOf(static_cast<shrine_type>(_oVar1), shrine_type::ShrineFascinating, shrine_type::ShrineOrnate, shrine_type::ShrineSacred);
}
Object *ObjectAtPosition(Point position)
Object *ObjectAtPosition(Point position, bool considerLargeObjects)
{
if (InDungeonBounds(position) && dObject[position.x][position.y] != 0) {
return &Objects[abs(dObject[position.x][position.y]) - 1];
if (!InDungeonBounds(position)) {
return nullptr;
}
auto objectId = dObject[position.x][position.y];
if (objectId > 0 || (considerLargeObjects && objectId != 0)) {
return &Objects[abs(objectId) - 1];
}
// nothing at this position, return a nullptr
return nullptr;
}
bool IsObjectAtPosition(Point position)
bool IsItemBlockingObjectAtPosition(Point position)
{
return ObjectAtPosition(position) != nullptr;
Object *object = ObjectAtPosition(position);
if (object != nullptr && object->_oSolidFlag) {
// solid object
return true;
}
object = ObjectAtPosition(position + Direction::South);
if (object != nullptr && object->_oSelFlag != 0) {
// An unopened container or breakable object exists which potentially overlaps this tile, the player might not be able to pick up an item dropped here.
return true;
}
object = ObjectAtPosition(position + Direction::SouthEast, false);
if (object != nullptr) {
Object *otherDoor = ObjectAtPosition(position + Direction::SouthWest, false);
if (otherDoor != nullptr && object->_oSelFlag != 0 && otherDoor->_oSelFlag != 0) {
// Two interactive objects potentially overlap both sides of this tile, as above the player might not be able to pick up an item which is dropped here.
return true;
}
}
return false;
}
void InitObjectGFX()

16
Source/objects.h

@ -242,16 +242,28 @@ extern bool LoadingMapObjects;
* @brief Find an object given a point in map coordinates
*
* @param position The map coordinate to test
* @param considerLargeObjects Default behaviour will return a pointer to a large object that covers this tile, set
* this param to false if you only want the object whose base position matches this tile
* @return A pointer to the object or nullptr if no object exists at this location
*/
Object *ObjectAtPosition(Point position);
Object *ObjectAtPosition(Point position, bool considerLargeObjects = true);
/**
* @brief Check whether an item occupies this tile position
* @param position The map coordinate to test
* @return true if the tile is occupied
*/
bool IsObjectAtPosition(Point position);
inline bool IsObjectAtPosition(Point position)
{
return ObjectAtPosition(position) != nullptr;
}
/**
* @brief Check whether an item blocking object (solid object or open door) is located at this tile position
* @param position The map coordinate to test
* @return true if the tile is blocked
*/
bool IsItemBlockingObjectAtPosition(Point position);
void InitObjectGFX();
void FreeObjectGFX();

Loading…
Cancel
Save