Browse Source

Use Point/range iterator in FindItemOrObject

This addresses a todo comment, though not in the way that was originally intended as we no longer use Direction::Omni
pull/3969/head
ephphatha 4 years ago committed by Anders Jenbo
parent
commit
5c4f6d80e8
  1. 102
      Source/controls/plrctrls.cpp

102
Source/controls/plrctrls.cpp

@ -15,6 +15,7 @@
#include "cursor.h"
#include "doom.h"
#include "engine/point.hpp"
#include "engine/points_in_rectangle_range.hpp"
#include "gmenu.h"
#include "help.h"
#include "hwcursor.hpp"
@ -124,61 +125,72 @@ int GetDistanceRanged(Point destination)
return Players[MyPlayerId].position.future.ExactDistance(destination);
}
/**
* @todo The loops in this function are iterating through tiles offset from the player position. This
* could be accomplished by looping over the values in the Direction enum and making use of
* Point math instead of nested loops from [-1, 1].
*/
void FindItemOrObject()
{
int mx = Players[MyPlayerId].position.future.x;
int my = Players[MyPlayerId].position.future.y;
Point futurePosition = Players[MyPlayerId].position.future;
int rotations = 5;
// As the player can not stand on the edge of the map this is safe from OOB
for (int xx = -1; xx < 2; xx++) {
for (int yy = -1; yy < 2; yy++) {
if (dItem[mx + xx][my + yy] <= 0)
continue;
int i = dItem[mx + xx][my + yy] - 1;
auto &item = Items[i];
if (item.isEmpty()
|| item._iSelFlag == 0)
continue;
int newRotations = GetRotaryDistance({ mx + xx, my + yy });
if (rotations < newRotations)
continue;
if (xx != 0 && yy != 0 && GetDistance({ mx + xx, my + yy }, 1) == 0)
continue;
rotations = newRotations;
pcursitem = i;
cursPosition = Point { mx, my } + Displacement { xx, yy };
auto searchArea = PointsInRectangleRangeColMajor { Rectangle { futurePosition, 1 } };
for (Point targetPosition : searchArea) {
// As the player can not stand on the edge of the map this is safe from OOB
int8_t itemId = dItem[targetPosition.x][targetPosition.y] - 1;
if (itemId < 0) {
// there shouldn't be any items that occupy multiple ground tiles, but just in case only considering positive indexes here
continue;
}
auto &item = Items[itemId];
if (item.isEmpty() || item._iSelFlag == 0) {
continue;
}
int newRotations = GetRotaryDistance(targetPosition);
if (rotations < newRotations) {
continue;
}
if (targetPosition != futurePosition && GetDistance(targetPosition, 1) == 0) {
// Don't check the tile we're leaving if the player is walking
continue;
}
rotations = newRotations;
pcursitem = itemId;
cursPosition = targetPosition;
}
if (leveltype == DTYPE_TOWN || pcursitem != -1)
if (leveltype == DTYPE_TOWN || pcursitem != -1) {
return; // Don't look for objects in town
}
for (int xx = -1; xx < 2; xx++) {
for (int yy = -1; yy < 2; yy++) {
if (dObject[mx + xx][my + yy] == 0)
continue;
int o = abs(dObject[mx + xx][my + yy]) - 1;
if (Objects[o]._oSelFlag == 0)
continue;
if (xx == 0 && yy == 0 && Objects[o]._oDoorFlag)
continue; // Ignore doorway so we don't get stuck behind barrels
int newRotations = GetRotaryDistance({ mx + xx, my + yy });
if (rotations < newRotations)
continue;
if (xx != 0 && yy != 0 && GetDistance({ mx + xx, my + yy }, 1) == 0)
continue;
if (Objects[o].IsDisabled())
continue;
rotations = newRotations;
pcursobj = o;
cursPosition = Point { mx, my } + Displacement { xx, yy };
for (Point targetPosition : searchArea) {
int8_t objectId = abs(dObject[targetPosition.x][targetPosition.y]) - 1;
if (objectId < 0) {
continue;
}
Object &object = Objects[objectId];
if (object._oSelFlag == 0) {
continue;
}
if (targetPosition == futurePosition && object._oDoorFlag) {
continue; // Ignore doorway so we don't get stuck behind barrels
}
int newRotations = GetRotaryDistance(targetPosition);
if (rotations < newRotations) {
continue;
}
if (targetPosition != futurePosition && GetDistance(targetPosition, 1) == 0) {
// Don't check the tile we're leaving if the player is walking
continue;
}
if (object.IsDisabled()) {
continue;
}
rotations = newRotations;
pcursobj = objectId;
cursPosition = targetPosition;
}
}

Loading…
Cancel
Save