position.h

main 274 lines · 8.8 KB Raw
Alex Alex Commit Client Upload Part 2 19/10/2026 00:06
1/*
2 * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#ifndef POSITION_H
24#define POSITION_H
25
26#include "const.h"
27#include <framework/stdext/types.h>
28#include <framework/const.h>
29#include <framework/util/point.h>
30
31#include <vector>
32
33class Position
34{
35public:
36 Position() : x(65535), y(65535), z(255) { }
37 Position(uint16 x, uint16 y, uint8 z) : x(x), y(y), z(z) { }
38
39 Position translatedToDirection(Otc::Direction direction) {
40 Position pos = *this;
41 switch(direction) {
42 case Otc::North:
43 pos.y--;
44 break;
45 case Otc::East:
46 pos.x++;
47 break;
48 case Otc::South:
49 pos.y++;
50 break;
51 case Otc::West:
52 pos.x--;
53 break;
54 case Otc::NorthEast:
55 pos.x++;
56 pos.y--;
57 break;
58 case Otc::SouthEast:
59 pos.x++;
60 pos.y++;
61 break;
62 case Otc::SouthWest:
63 pos.x--;
64 pos.y++;
65 break;
66 case Otc::NorthWest:
67 pos.x--;
68 pos.y--;
69 break;
70 default:
71 break;
72 }
73 return pos;
74 }
75
76 Position translatedToReverseDirection(Otc::Direction direction) {
77 Position pos = *this;
78 switch(direction) {
79 case Otc::North:
80 pos.y++;
81 break;
82 case Otc::East:
83 pos.x--;
84 break;
85 case Otc::South:
86 pos.y--;
87 break;
88 case Otc::West:
89 pos.x++;
90 break;
91 case Otc::NorthEast:
92 pos.x--;
93 pos.y++;
94 break;
95 case Otc::SouthEast:
96 pos.x--;
97 pos.y--;
98 break;
99 case Otc::SouthWest:
100 pos.x++;
101 pos.y--;
102 break;
103 case Otc::NorthWest:
104 pos.x++;
105 pos.y++;
106 break;
107 default:
108 break;
109 }
110 return pos;
111 }
112
113 std::vector<Position> translatedToDirections(const std::vector<Otc::Direction>& dirs) const {
114 Position lastPos = *this;
115 std::vector<Position> positions;
116
117 if(!lastPos.isValid())
118 return positions;
119
120 positions.push_back(lastPos);
121
122 for(auto dir : dirs) {
123 lastPos = lastPos.translatedToDirection(dir);
124 if(!lastPos.isValid())
125 break;
126 positions.push_back(lastPos);
127 }
128
129 return positions;
130 }
131
132 static double getAngleFromPositions(const Position& fromPos, const Position& toPos) {
133 // Returns angle in radians from 0 to 2Pi. -1 means positions are equal.
134 int dx = toPos.x - fromPos.x;
135 int dy = toPos.y - fromPos.y;
136 if(dx == 0 && dy == 0)
137 return -1;
138
139 float angle = std::atan2(dy * -1, dx);
140 if(angle < 0)
141 angle += 2 * Fw::pi;
142
143 return angle;
144 }
145
146 double getAngleFromPosition(const Position& position) const {
147 return getAngleFromPositions(*this, position);
148 }
149
150 static Otc::Direction getDirectionFromPositions(const Position& fromPos,
151 const Position& toPos)
152 {
153 float angle = getAngleFromPositions(fromPos, toPos) * RAD_TO_DEC;
154
155 if(angle >= 360 - 22.5 || angle < 0 + 22.5)
156 return Otc::East;
157 else if(angle >= 45 - 22.5 && angle < 45 + 22.5)
158 return Otc::NorthEast;
159 else if(angle >= 90 - 22.5 && angle < 90 + 22.5)
160 return Otc::North;
161 else if(angle >= 135 - 22.5 && angle < 135 + 22.5)
162 return Otc::NorthWest;
163 else if(angle >= 180 - 22.5 && angle < 180 + 22.5)
164 return Otc::West;
165 else if(angle >= 225 - 22.5 && angle < 225 + 22.5)
166 return Otc::SouthWest;
167 else if(angle >= 270 - 22.5 && angle < 270 + 22.5)
168 return Otc::South;
169 else if(angle >= 315 - 22.5 && angle < 315 + 22.5)
170 return Otc::SouthEast;
171 else
172 return Otc::InvalidDirection;
173 }
174
175 Otc::Direction getDirectionFromPosition(const Position& position) const {
176 return getDirectionFromPositions(*this, position);
177 }
178
179 bool isMapPosition() const { return (x >=0 && y >= 0 && z >= 0 && x < 65535 && y < 65535 && z <= Otc::MAX_Z); }
180 bool isValid() const { return !(x == 65535 && y == 65535 && z == 255); }
181 float distance(const Position& pos) const { return sqrt(pow((pos.x - x), 2) + pow((pos.y - y), 2)); }
182 int manhattanDistance(const Position& pos) const { return std::abs(pos.x - x) + std::abs(pos.y - y); }
183
184 void translate(int dx, int dy, short dz = 0) { x += dx; y += dy; z += dz; }
185 Position translated(int dx, int dy, short dz = 0) const { Position pos = *this; pos.x += dx; pos.y += dy; pos.z += dz; return pos; }
186
187 Position operator+(const Position& other) const { return Position(x + other.x, y + other.y, z + other.z); }
188 Position& operator+=(const Position& other) { x+=other.x; y+=other.y; z +=other.z; return *this; }
189 Position operator-(const Position& other) const { return Position(x - other.x, y - other.y, z - other.z); }
190 Position& operator-=(const Position& other) { x-=other.x; y-=other.y; z-=other.z; return *this; }
191 // Point conversion(s)
192 Position operator+(const Point& other) const { return Position(x + other.x, y + other.y, z); }
193 Position& operator+=(const Point& other) { x += other.x; y += other.y; return *this; }
194
195 Position& operator=(const Position& other) { x = other.x; y = other.y; z = other.z; return *this; }
196 bool operator==(const Position& other) const { return other.x == x && other.y == y && other.z == z; }
197 bool operator!=(const Position& other) const { return other.x!=x || other.y!=y || other.z!=z; }
198 bool isInRange(const Position& pos, int xRange, int yRange, int zRange = 0) const { return std::abs(x-pos.x) <= xRange && std::abs(y-pos.y) <= yRange && std::abs(z - pos.z) <= zRange; }
199 bool isInRange(const Position& pos, int minXRange, int maxXRange, int minYRange, int maxYRange) const {
200 return (pos.x >= x-minXRange && pos.x <= x+maxXRange && pos.y >= y-minYRange && pos.y <= y+maxYRange && pos.z == z);
201 }
202 // operator less than for std::map
203 bool operator<(const Position& other) const { return x < other.x || y < other.y || z < other.z; }
204
205 bool up(int n = 1) {
206 int nz = z-n;
207 if(nz >= 0 && nz <= Otc::MAX_Z) {
208 z = nz;
209 return true;
210 }
211 return false;
212 }
213
214 bool down(int n = 1) {
215 int nz = z+n;
216 if(nz >= 0 && nz <= Otc::MAX_Z) {
217 z = nz;
218 return true;
219 }
220 return false;
221 }
222
223 bool coveredUp(int n = 1) {
224 int nx = x+n, ny = y+n, nz = z-n;
225 if(nx >= 0 && nx <= 65535 && ny >= 0 && ny <= 65535 && nz >= 0 && nz <= Otc::MAX_Z) {
226 x = nx; y = ny; z = nz;
227 return true;
228 }
229 return false;
230 }
231
232 bool coveredDown(int n = 1) {
233 int nx = x-n, ny = y-n, nz = z+n;
234 if(nx >= 0 && nx <= 65535 && ny >= 0 && ny <= 65535 && nz >= 0 && nz <= Otc::MAX_Z) {
235 x = nx; y = ny; z = nz;
236 return true;
237 }
238 return false;
239 }
240
241 std::string toString()
242 {
243 return std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z);
244 }
245
246 int x;
247 int y;
248 short z;
249};
250
251struct PositionHasher {
252 std::size_t operator()(const Position& pos) const {
253 return (((pos.x * 8192) + pos.y) * 16) + pos.z;
254 }
255};
256
257inline std::ostream& operator<<(std::ostream& out, const Position& pos)
258{
259 out << (int)pos.x << " " << (int)pos.y << " " << (int)pos.z;
260 return out;
261}
262
263inline std::istream& operator>>(std::istream& in, Position& pos)
264{
265 int x, y, z;
266 in >> x >> y >> z;
267 pos.x = x;
268 pos.y = y;
269 pos.z = z;
270 return in;
271}
272
273#endif
274
Top