diff --git a/client/CSpellWindow.cpp b/client/CSpellWindow.cpp index 8c43b9dae..1f88df9e2 100644 --- a/client/CSpellWindow.cpp +++ b/client/CSpellWindow.cpp @@ -744,23 +744,26 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState) if (h->getSpellSchoolLevel(CGI->spellh->objects[spell]) < 2) //not advanced or expert - teleport to nearest available city { - int nearest = -1; //nearest town's ID - double dist = -1; - for (int g=0; gcb->getTown((*nearest)->id)->pos.dist2dSQ(h->pos); + + for (auto i = nearest + 1; i != Towns.cend(); ++i) { - const CGTownInstance * dest = LOCPLINT->cb->getTown(Towns[g]->id); - double curDist = dest->pos.dist2d(h->pos); - if (nearest == -1 || curDist < dist) + const CGTownInstance * dest = LOCPLINT->cb->getTown((*i)->id); + si32 curDist = dest->pos.dist2dSQ(h->pos); + + if (curDist < dist) { - nearest = g; + nearest = i; dist = curDist; } } - if ( Towns[nearest]->visitingHero ) + + if ((*nearest)->visitingHero) LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[123]); else { - const CGTownInstance * town = LOCPLINT->cb->getTown(Towns[nearest]->id); + const CGTownInstance * town = LOCPLINT->cb->getTown((*nearest)->id); LOCPLINT->cb->castSpell(h, spell, town->visitablePos());// - town->getVisitableOffset()); } } diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 137852662..3e9165e0d 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -1032,7 +1032,7 @@ void CGameState::initGrailPosition() && !t.visitable && t.terType != ETerrainType::WATER && t.terType != ETerrainType::ROCK - && map->grailPos.dist2d(int3(i,j,k)) <= map->grailRadious) + && map->grailPos.dist2dSQ(int3(i, j, k)) <= (map->grailRadious * map->grailRadious)) allowedPos.push_back(int3(i,j,k)); } } diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index 8e4a38861..477331735 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -4173,13 +4173,13 @@ void CGTeleport::postInit() //matches subterranean gates into pairs const CGObjectInstance *cur = gatesSplit[0][i]; //find nearest underground exit - std::pair best(-1,150000); //pair + std::pair best(-1, std::numeric_limits::max()); //pair for(int j = 0; j < gatesSplit[1].size(); j++) { const CGObjectInstance *checked = gatesSplit[1][j]; if(!checked) continue; - double hlp = checked->pos.dist2d(cur->pos); + si32 hlp = checked->pos.dist2dSQ(cur->pos); if(hlp < best.second) { best.first = j; @@ -4193,9 +4193,7 @@ void CGTeleport::postInit() //matches subterranean gates into pairs gatesSplit[1][best.first] = nullptr; } else - { gates.push_back(std::make_pair(cur->id, ObjectInstanceID())); - } } objs.erase(Obj::SUBTERRANEAN_GATE); } diff --git a/lib/int3.h b/lib/int3.h index 4b2a8ca22..ad62e4e8b 100644 --- a/lib/int3.h +++ b/lib/int3.h @@ -14,96 +14,135 @@ class int3 { public: - si32 x,y,z; - inline int3():x(0),y(0),z(0){}; //c-tor, x/y/z initialized to 0 - inline int3(const si32 X, const si32 Y, const si32 Z):x(X),y(Y),z(Z){}; //c-tor - inline int3(const int3 & val) : x(val.x), y(val.y), z(val.z){} //copy c-tor - inline int3 & operator=(const int3 & val) {x = val.x; y = val.y; z = val.z; return *this;} //assignemt operator - ~int3() {} // d-tor - does nothing - inline int3 operator+(const int3 & i) const //returns int3 with coordinates increased by corresponding coordinate of given int3 - {return int3(x+i.x,y+i.y,z+i.z);} - inline int3 operator+(const si32 i) const //returns int3 with coordinates increased by given numer - {return int3(x+i,y+i,z+i);} - inline int3 operator-(const int3 & i) const //returns int3 with coordinates decreased by corresponding coordinate of given int3 - {return int3(x-i.x,y-i.y,z-i.z);} - inline int3 operator-(const si32 i) const //returns int3 with coordinates decreased by given numer - {return int3(x-i,y-i,z-i);} - inline int3 operator-() const //returns opposite position - {return int3(-x,-y,-z);} - inline double dist2d(const int3 &other) const //distance (z coord is not used) - {return std::sqrt((double)(x-other.x)*(x-other.x) + (y-other.y)*(y-other.y));} - inline bool areNeighbours(const int3 &other) const - {return dist2d(other) < 2. && z == other.z;} - inline void operator+=(const int3 & i) + si32 x, y, z; + + //c-tor: x, y, z initialized to 0 + int3() : x(0), y(0), z(0) {} // I think that x, y, z should be left uninitialized. + //c-tor: x, y, z initialized to i + explicit int3(const si32 i) : x(i), y(i), z(i) {} + //c-tor: x, y, z initialized to X, Y, Z + int3(const si32 X, const si32 Y, const si32 Z) : x(X), y(Y), z(Z) {} + int3(const int3 & c) : x(c.x), y(c.y), z(c.z) {} // Should be set to default (C++11)? + + int3 & operator=(const int3 & c) // Should be set to default (C++11)? { - x+=i.x; - y+=i.y; - z+=i.z; + x = c.x; + y = c.y; + z = c.z; + + return *this; } - inline void operator+=(const si32 & i) + int3 operator-() const { return int3(-x, -y, -z); } + + int3 operator+(const int3 & i) const { return int3(x + i.x, y + i.y, z + i.z); } + int3 operator-(const int3 & i) const { return int3(x - i.x, y - i.y, z - i.z); } + //returns int3 with coordinates increased by given number + int3 operator+(const si32 i) const { return int3(x + i, y + i, z + i); } + //returns int3 with coordinates decreased by given number + int3 operator-(const si32 i) const { return int3(x - i, y - i, z - i); } + + int3 & operator+=(const int3 & i) { - x+=i; - y+=i; - z+=i; + x += i.x; + y += i.y; + z += i.z; + return *this; } - inline void operator-=(const int3 & i) + int3 & operator-=(const int3 & i) { - x-=i.x; - y-=i.y; - z-=i.z; + x -= i.x; + y -= i.y; + z -= i.z; + return *this; } - inline void operator-=(const si32 & i) + + //increases all coordinates by given number + int3 & operator+=(const si32 i) { - x+=i; - y+=i; - z+=i; + x += i; + y += i; + z += i; + return *this; } - inline bool operator==(const int3 & i) const - {return (x==i.x) && (y==i.y) && (z==i.z);} - inline bool operator!=(const int3 & i) const - {return !(*this==i);} - inline bool operator<(const int3 & i) const + //decreases all coordinates by given number + int3 & operator-=(const si32 i) { - if (zi.z) + if (z > i.z) return false; - if (yi.y) + if (y > i.y) return false; - if (xi.x) + if (x > i.x) return false; return false; } - inline std::string operator ()() const + + //returns squared distance on Oxy plane (z coord is not used) + si32 dist2dSQ(const int3 & o) const { - return "(" + boost::lexical_cast(x) + - " " + boost::lexical_cast(y) + - " " + boost::lexical_cast(z) + ")"; + const si32 dx = (x - o.x); + const si32 dy = (y - o.y); + return dx*dx + dy*dy; } - inline bool valid() const + //returns distance on Oxy plane (z coord is not used) + double dist2d(const int3 & o) const + { + return std::sqrt((double)dist2dSQ(o)); + } + + bool areNeighbours(const int3 & o) const + { + return (dist2dSQ(o) < 4) && (z == o.z); + } + + //returns "(x y z)" string + std::string operator ()() const //Change to int3::toString()? + { + std::string result("("); + result += boost::lexical_cast(x); result += ' '; + result += boost::lexical_cast(y); result += ' '; + result += boost::lexical_cast(z); result += ')'; + return result; + } + + bool valid() const //Should be named "isValid"? { return z >= 0; //minimal condition that needs to be fulfilled for tiles in the map } - template void serialize(Handler &h, const int version) + + template + void serialize(Handler &h, const int version) { h & x & y & z; } - }; -inline std::istream & operator>>(std::istream & str, int3 & dest) -{ - str>>dest.x>>dest.y>>dest.z; - return str; -} + inline std::ostream & operator<<(std::ostream & str, const int3 & sth) { - return str<>(std::istream & str, int3 & dest) +{ + return str >> dest.x >> dest.y >> dest.z; } +//Why not normal function? struct ShashInt3 { size_t operator()(int3 const& pos) const @@ -113,4 +152,4 @@ struct ShashInt3 vstd::hash_combine(ret, pos.z); return ret; } -}; +}; \ No newline at end of file diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index bd97fd117..2231fd5f2 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -424,7 +424,7 @@ const CGObjectInstance * CMap::getObjectiveObjectFrom(int3 pos, Obj::EObj type) bestMatch = object; else { - if (object->pos.dist2d(pos) < bestMatch->pos.dist2d(pos)) + if (object->pos.dist2dSQ(pos) < bestMatch->pos.dist2dSQ(pos)) bestMatch = object;// closer than one we already found } } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 3e833a7eb..19e91c912 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -5592,15 +5592,15 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, SpellID spellID, const int if (h->getSpellSchoolLevel(s) < 2) { - double dist = town->pos.dist2d(h->pos); + si32 dist = town->pos.dist2dSQ(h->pos); ObjectInstanceID nearest = town->id; //nearest town's ID for(const CGTownInstance * currTown : gs->getPlayer(h->tempOwner)->towns) { - double curDist = currTown->pos.dist2d(h->pos); - if (nearest == ObjectInstanceID() || curDist < dist) + si32 currDist = currTown->pos.dist2dSQ(h->pos); + if (currDist < dist) { - nearest = town->id; - dist = curDist; + nearest = currTown->id; + dist = currDist; } } if (town->id != nearest)