tibia-client/src/client/position.h

259 lines
8.3 KiB
C
Raw Normal View History

2011-08-28 15:17:58 +02:00
/*
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
2011-08-28 15:17:58 +02:00
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
2011-08-15 16:11:24 +02:00
#ifndef POSITION_H
#define POSITION_H
#include "const.h"
#include <framework/stdext/types.h>
2012-07-19 15:55:10 +02:00
#include <framework/const.h>
#include <framework/util/point.h>
2011-08-15 16:11:24 +02:00
#include <vector>
2011-08-15 16:11:24 +02:00
class Position
{
public:
2012-01-30 19:18:10 +01:00
Position() : x(65535), y(65535), z(255) { }
Position(uint16 x, uint16 y, uint8 z) : x(x), y(y), z(z) { }
2011-08-15 16:11:24 +02:00
2012-01-30 19:18:10 +01:00
Position translatedToDirection(Otc::Direction direction) {
Position pos = *this;
2011-08-30 16:37:48 +02:00
switch(direction) {
case Otc::North:
2012-01-30 19:18:10 +01:00
pos.y--;
break;
2011-08-30 16:37:48 +02:00
case Otc::East:
2012-01-30 19:18:10 +01:00
pos.x++;
break;
2011-08-30 16:37:48 +02:00
case Otc::South:
2012-01-30 19:18:10 +01:00
pos.y++;
break;
2011-08-30 16:37:48 +02:00
case Otc::West:
2012-01-30 19:18:10 +01:00
pos.x--;
break;
2011-08-30 16:37:48 +02:00
case Otc::NorthEast:
2012-01-30 19:18:10 +01:00
pos.x++;
pos.y--;
break;
2011-08-30 16:37:48 +02:00
case Otc::SouthEast:
2012-01-30 19:18:10 +01:00
pos.x++;
pos.y++;
break;
2011-08-30 16:37:48 +02:00
case Otc::SouthWest:
2012-01-30 19:18:10 +01:00
pos.x--;
pos.y++;
break;
2011-08-30 16:37:48 +02:00
case Otc::NorthWest:
2012-01-30 19:18:10 +01:00
pos.x--;
pos.y--;
break;
default:
break;
2011-08-30 16:37:48 +02:00
}
2012-01-30 19:18:10 +01:00
return pos;
}
Position translatedToReverseDirection(Otc::Direction direction) {
Position pos = *this;
switch(direction) {
case Otc::North:
pos.y++;
break;
case Otc::East:
pos.x--;
break;
case Otc::South:
pos.y--;
break;
case Otc::West:
pos.x++;
break;
case Otc::NorthEast:
pos.x--;
pos.y++;
break;
case Otc::SouthEast:
pos.x--;
pos.y--;
break;
case Otc::SouthWest:
pos.x++;
pos.y--;
break;
case Otc::NorthWest:
pos.x++;
pos.y++;
break;
default:
break;
2012-01-30 19:18:10 +01:00
}
return pos;
2011-08-30 16:37:48 +02:00
}
double getAngleFromPosition(const Position& position) const {
// Returns angle in radians from 0 to 2Pi. -1 means positions are equal.
int dx = position.x - x;
int dy = position.y - y;
if(dx == 0 && dy == 0)
return -1;
float angle = std::atan2(dy * -1, dx);
if(angle < 0)
angle += 2 * Fw::pi;
return angle;
}
std::vector<Position> translatedToDirections(const std::vector<Otc::Direction>& dirs) const {
Position lastPos = *this;
std::vector<Position> positions;
2013-01-22 19:04:36 +01:00
if(!lastPos.isValid())
return positions;
positions.push_back(lastPos);
for(auto dir : dirs) {
lastPos = lastPos.translatedToDirection(dir);
2013-01-22 19:04:36 +01:00
if(!lastPos.isValid())
break;
positions.push_back(lastPos);
}
return positions;
}
2011-12-26 07:14:57 +01:00
Otc::Direction getDirectionFromPosition(const Position& position) const {
2013-01-21 01:40:47 +01:00
float angle = getAngleFromPosition(position) * RAD_TO_DEC;
if(angle >= 360 - 22.5 || angle < 0 + 22.5)
return Otc::East;
else if(angle >= 45 - 22.5 && angle < 45 + 22.5)
return Otc::NorthEast;
else if(angle >= 90 - 22.5 && angle < 90 + 22.5)
return Otc::North;
else if(angle >= 135 - 22.5 && angle < 135 + 22.5)
return Otc::NorthWest;
else if(angle >= 180 - 22.5 && angle < 180 + 22.5)
return Otc::West;
else if(angle >= 225 - 22.5 && angle < 225 + 22.5)
return Otc::SouthWest;
else if(angle >= 270 - 22.5 && angle < 270 + 22.5)
return Otc::South;
else if(angle >= 315 - 22.5 && angle < 315 + 22.5)
return Otc::SouthEast;
else
2011-12-26 07:14:57 +01:00
return Otc::InvalidDirection;
}
2013-02-06 20:35:59 +01:00
bool isMapPosition() const { return (x >=0 && y >= 0 && z >= 0 && x < 65535 && y < 65535 && z <= Otc::MAX_Z); }
2012-01-30 19:18:10 +01:00
bool isValid() const { return !(x == 65535 && y == 65535 && z == 255); }
float distance(const Position& pos) const { return sqrt(pow((pos.x - x), 2) + pow((pos.y - y), 2)); }
int manhattanDistance(const Position& pos) const { return std::abs(pos.x - x) + std::abs(pos.y - y); }
2012-01-30 19:18:10 +01:00
void translate(int dx, int dy, short dz = 0) { x += dx; y += dy; z += dz; }
Position translated(int dx, int dy, short dz = 0) const { Position pos = *this; pos.x += dx; pos.y += dy; pos.z += dz; return pos; }
2011-08-15 16:11:24 +02:00
Position operator+(const Position& other) const { return Position(x + other.x, y + other.y, z + other.z); }
Position& operator+=(const Position& other) { x+=other.x; y+=other.y; z +=other.z; return *this; }
2011-11-08 02:44:30 +01:00
Position operator-(const Position& other) const { return Position(x - other.x, y - other.y, z - other.z); }
2011-08-15 16:11:24 +02:00
Position& operator-=(const Position& other) { x-=other.x; y-=other.y; z-=other.z; return *this; }
2012-07-19 15:55:10 +02:00
// Point conversion(s)
Position operator+(const Point& other) const { return Position(x + other.x, y + other.y, z); }
Position& operator+=(const Point& other) { x += other.x; y += other.y; return *this; }
2011-08-15 16:11:24 +02:00
Position& operator=(const Position& other) { x = other.x; y = other.y; z = other.z; return *this; }
bool operator==(const Position& other) const { return other.x == x && other.y == y && other.z == z; }
bool operator!=(const Position& other) const { return other.x!=x || other.y!=y || other.z!=z; }
bool isInRange(const Position& pos, int xRange, int yRange) const { return std::abs(x-pos.x) <= xRange && std::abs(y-pos.y) <= yRange && z == pos.z; }
2012-01-30 19:18:10 +01:00
bool isInRange(const Position& pos, int minXRange, int maxXRange, int minYRange, int maxYRange) const {
return (pos.x >= x-minXRange && pos.x <= x+maxXRange && pos.y >= y-minYRange && pos.y <= y+maxYRange && pos.z == z);
2012-01-30 19:18:10 +01:00
}
// operator less than for std::map
2013-09-02 21:12:12 +02:00
bool operator<(const Position& other) const { return x < other.x || y < other.y || z < other.z; }
2012-01-30 19:18:10 +01:00
bool up(int n = 1) {
int nz = z-n;
if(nz >= 0 && nz <= Otc::MAX_Z) {
z = nz;
return true;
}
return false;
2011-08-31 01:39:14 +02:00
}
2012-01-30 19:18:10 +01:00
bool down(int n = 1) {
int nz = z+n;
if(nz >= 0 && nz <= Otc::MAX_Z) {
z = nz;
return true;
}
return false;
}
2011-08-31 01:39:14 +02:00
2012-01-30 19:18:10 +01:00
bool coveredUp(int n = 1) {
int nx = x+n, ny = y+n, nz = z-n;
if(nx >= 0 && nx <= 65535 && ny >= 0 && ny <= 65535 && nz >= 0 && nz <= Otc::MAX_Z) {
x = nx; y = ny; z = nz;
return true;
}
return false;
}
bool coveredDown(int n = 1) {
int nx = x-n, ny = y-n, nz = z+n;
if(nx >= 0 && nx <= 65535 && ny >= 0 && ny <= 65535 && nz >= 0 && nz <= Otc::MAX_Z) {
x = nx; y = ny; z = nz;
return true;
}
return false;
}
2011-08-31 01:39:14 +02:00
2013-02-06 20:35:59 +01:00
int x;
int y;
short z;
2011-08-15 16:11:24 +02:00
};
2011-08-16 02:30:31 +02:00
struct PositionHasher : std::unary_function<Position, std::size_t> {
std::size_t operator()(const Position& pos) const {
return (((pos.x * 8192) + pos.y) * 16) + pos.z;
2011-08-16 02:30:31 +02:00
}
};
2011-08-31 01:39:14 +02:00
inline std::ostream& operator<<(std::ostream& out, const Position& pos)
2011-08-15 16:11:24 +02:00
{
2012-01-30 19:18:10 +01:00
out << (int)pos.x << " " << (int)pos.y << " " << (int)pos.z;
2011-08-15 16:11:24 +02:00
return out;
}
2011-08-31 01:39:14 +02:00
inline std::istream& operator>>(std::istream& in, Position& pos)
2011-08-15 16:11:24 +02:00
{
2012-01-30 19:18:10 +01:00
int x, y, z;
in >> x >> y >> z;
pos.x = x;
pos.y = y;
pos.z = z;
2011-08-15 16:11:24 +02:00
return in;
}
#endif