2015-12-03 00:37:02 +00:00
|
|
|
/************************************************************************
|
2015-12-03 00:37:37 +00:00
|
|
|
* Copyright (c) 2005-2007 tok@openlinux.org.uk *
|
2015-12-03 00:37:02 +00:00
|
|
|
* *
|
|
|
|
* This file contains code derived from information copyrighted by *
|
|
|
|
* DMA Design. It may not be used in a commercial product. *
|
|
|
|
* *
|
|
|
|
* See license.txt for details. *
|
|
|
|
* *
|
|
|
|
* This notice may not be removed or altered. *
|
|
|
|
************************************************************************/
|
|
|
|
#include <cassert>
|
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
2015-12-03 00:37:37 +00:00
|
|
|
#include <iomanip>
|
2015-12-03 00:37:02 +00:00
|
|
|
#include "navdata.h"
|
|
|
|
#include "log.h"
|
2015-12-03 00:37:37 +00:00
|
|
|
#include "dataholder.h"
|
2015-12-03 00:37:02 +00:00
|
|
|
#include "m_exceptions.h"
|
|
|
|
|
|
|
|
namespace OpenGTA {
|
|
|
|
Rect2D::Rect2D() {
|
|
|
|
x = y = w = h = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Rect2D::Rect2D(PHYSFS_uint8 a, PHYSFS_uint8 b, PHYSFS_uint8 c, PHYSFS_uint8 d) {
|
|
|
|
x = a;
|
|
|
|
y = b;
|
|
|
|
w = c;
|
|
|
|
h = d;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Rect2D::isInside(PHYSFS_uint8 _x, PHYSFS_uint8 _y) {
|
|
|
|
if ((_x >= x ) && (_y >= y) &&
|
|
|
|
(PHYSFS_uint16(_x) <= PHYSFS_uint16(x) + w) &&
|
|
|
|
(PHYSFS_uint16(_y) <= PHYSFS_uint16(y) + h)) {
|
|
|
|
lastSubLocation = subLocation(_x, _y);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
PHYSFS_uint16 Rect2D::getSize() {
|
|
|
|
PHYSFS_uint16 res = w;
|
|
|
|
res *= h;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 0 = central, 1 = north, 2 = south, 4 = east, 8 = west
|
|
|
|
PHYSFS_uint8 Rect2D::subLocation(PHYSFS_uint8 _x, PHYSFS_uint8 _y) {
|
|
|
|
PHYSFS_uint8 in_x = _x - x; // offset in rect; assume: x <= _x
|
|
|
|
PHYSFS_uint8 in_y = _y - y;
|
|
|
|
float rel_x = float(in_x)/w;
|
|
|
|
float rel_y = float(in_y)/h;
|
|
|
|
PHYSFS_uint8 res = 0;
|
|
|
|
#define ONE_THIRD 1.0f/3.0f
|
|
|
|
#define TWO_THIRDS 2.0f/3.0f
|
|
|
|
if (rel_x <= ONE_THIRD)
|
|
|
|
// INFO << "west" << std::endl;
|
|
|
|
res |= 8;
|
|
|
|
else if (rel_x >= TWO_THIRDS)
|
|
|
|
//INFO << "east" << std::endl;
|
|
|
|
res |= 4;
|
|
|
|
if (rel_y <= ONE_THIRD)
|
|
|
|
res |= 1;
|
|
|
|
//INFO << "north" << std::endl;
|
|
|
|
else if (rel_y >= TWO_THIRDS)
|
|
|
|
res |= 2;
|
|
|
|
//INFO << "south" << std::endl;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-12-03 00:37:37 +00:00
|
|
|
NavData::Sector::Sector(PHYSFS_file* fd) : Rect2D(), sam(0), name("") {
|
2015-12-03 00:37:02 +00:00
|
|
|
sam = 0;
|
|
|
|
isADummy = 0;
|
|
|
|
assert(fd);
|
2015-12-03 00:37:37 +00:00
|
|
|
//memset(name2, 0, 30);
|
2015-12-03 00:37:02 +00:00
|
|
|
PHYSFS_read(fd, static_cast<void*>(&x), 1, 1);
|
|
|
|
PHYSFS_read(fd, static_cast<void*>(&y), 1, 1);
|
|
|
|
PHYSFS_read(fd, static_cast<void*>(&w), 1, 1);
|
|
|
|
PHYSFS_read(fd, static_cast<void*>(&h), 1, 1);
|
|
|
|
PHYSFS_read(fd, static_cast<void*>(&sam), 1, 1);
|
2015-12-03 00:37:37 +00:00
|
|
|
// seek over the name embedded in the mapfile; use sample-num to
|
|
|
|
// lookup in msg-db
|
|
|
|
//PHYSFS_read(fd, static_cast<void*>(&name2), 30, 1);
|
|
|
|
PHYSFS_seek(fd, PHYSFS_tell(fd) + 30);
|
2015-12-03 00:37:02 +00:00
|
|
|
}
|
|
|
|
|
2015-12-03 00:37:37 +00:00
|
|
|
NavData::Sector::Sector() : Rect2D(), sam(0), name("") {
|
2015-12-03 00:37:02 +00:00
|
|
|
x = 0;
|
|
|
|
y = 0;
|
|
|
|
w = 255;
|
|
|
|
h = 255;
|
|
|
|
sam = 0;
|
|
|
|
isADummy = 1;
|
2015-12-03 00:37:37 +00:00
|
|
|
//memset(name2, 0, 30);
|
2015-12-03 00:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char* NavData::Sector::getFullName() {
|
|
|
|
if (isADummy)
|
|
|
|
return "";
|
|
|
|
std::string n;
|
|
|
|
if (lastSubLocation == 0)
|
2015-12-03 00:38:22 +00:00
|
|
|
//n.append("Central ");
|
|
|
|
n.append(_c);
|
2015-12-03 00:37:02 +00:00
|
|
|
else if (lastSubLocation == 1)
|
2015-12-03 00:38:22 +00:00
|
|
|
//n.append("North ");
|
|
|
|
n.append(_n);
|
2015-12-03 00:37:02 +00:00
|
|
|
else if (lastSubLocation == 2)
|
2015-12-03 00:38:22 +00:00
|
|
|
n.append(_s);
|
|
|
|
//n.append("South ");
|
2015-12-03 00:37:02 +00:00
|
|
|
else if (lastSubLocation == 4)
|
2015-12-03 00:38:22 +00:00
|
|
|
n.append(_e);
|
|
|
|
//n.append("East ");
|
2015-12-03 00:37:02 +00:00
|
|
|
else if (lastSubLocation == 8)
|
2015-12-03 00:38:22 +00:00
|
|
|
n.append(_w);
|
|
|
|
//n.append("West ");
|
2015-12-03 00:37:02 +00:00
|
|
|
else if (lastSubLocation == 9)
|
2015-12-03 00:38:22 +00:00
|
|
|
n.append(_nw);
|
|
|
|
//n.append("Northwest ");
|
2015-12-03 00:37:02 +00:00
|
|
|
else if (lastSubLocation == 10)
|
2015-12-03 00:38:22 +00:00
|
|
|
n.append(_sw);
|
|
|
|
//n.append("Southwest ");
|
2015-12-03 00:37:02 +00:00
|
|
|
else if (lastSubLocation == 5)
|
2015-12-03 00:38:22 +00:00
|
|
|
n.append(_ne);
|
|
|
|
//n.append("Northeast ");
|
2015-12-03 00:37:02 +00:00
|
|
|
else if (lastSubLocation == 6)
|
2015-12-03 00:38:22 +00:00
|
|
|
n.append(_se);
|
|
|
|
//n.append("Southeast ");
|
|
|
|
|
|
|
|
n.append(" ");
|
2015-12-03 00:37:02 +00:00
|
|
|
n.append(name);
|
|
|
|
return n.c_str();
|
|
|
|
}
|
|
|
|
|
2015-12-03 00:38:22 +00:00
|
|
|
std::string NavData::_c;
|
|
|
|
std::string NavData::_n;
|
|
|
|
std::string NavData::_s;
|
|
|
|
std::string NavData::_w;
|
|
|
|
std::string NavData::_e;
|
|
|
|
std::string NavData::_nw;
|
|
|
|
std::string NavData::_ne;
|
|
|
|
std::string NavData::_sw;
|
|
|
|
std::string NavData::_se;
|
|
|
|
|
2015-12-03 00:37:37 +00:00
|
|
|
NavData::NavData(PHYSFS_uint32 size, PHYSFS_file *fd, const size_t level_num) {
|
2015-12-03 00:37:02 +00:00
|
|
|
if (size % 35) {
|
|
|
|
std::ostringstream o;
|
|
|
|
o << "Navdata size: " << size << " % 35 != 0";
|
|
|
|
throw E_INVALIDFORMAT(o.str());
|
|
|
|
//throw std::string("Invalid NavData size in mapfile");
|
|
|
|
}
|
|
|
|
PHYSFS_uint32 c = size / 35;
|
|
|
|
assert(fd);
|
2015-12-03 00:37:37 +00:00
|
|
|
|
|
|
|
MessageDB & msg = MainMsgHolder::Instance().get();
|
2015-12-03 00:38:22 +00:00
|
|
|
_c =msg.getText("c");
|
|
|
|
_n = msg.getText("n");
|
|
|
|
_s = msg.getText("s");
|
|
|
|
_w = msg.getText("w");
|
|
|
|
_e = msg.getText("e");
|
|
|
|
_nw = msg.getText("nw");
|
|
|
|
_ne = msg.getText("ne");
|
|
|
|
_sw = msg.getText("sw");
|
|
|
|
_se = msg.getText("se");
|
2015-12-03 00:37:02 +00:00
|
|
|
for (PHYSFS_uint32 i = 0; i < c; ++i) {
|
|
|
|
Sector *sec = new Sector(fd);
|
|
|
|
if (sec->getSize() == 0) { // workaround for 'NYC.CMP' (empty sectors)
|
|
|
|
delete sec;
|
|
|
|
WARN << "skipping zero size sector" << std::endl;
|
|
|
|
continue;
|
|
|
|
}
|
2015-12-03 00:37:37 +00:00
|
|
|
else {
|
|
|
|
std::ostringstream os;
|
|
|
|
os << std::setfill('0') << std::setw(3) << level_num << "area" << std::setfill('0') <<
|
|
|
|
std::setw(3) << int(sec->sam);
|
|
|
|
|
|
|
|
//INFO << i << " " << sec->name2 << std::endl << os.str() << " : " << msg.getText(os.str()) << std::endl;
|
|
|
|
sec->name = msg.getText(os.str());
|
|
|
|
|
2015-12-03 00:37:02 +00:00
|
|
|
areas.insert(std::pair<PHYSFS_uint16, Sector*>(sec->getSize(), sec));
|
2015-12-03 00:37:37 +00:00
|
|
|
}
|
2015-12-03 00:37:02 +00:00
|
|
|
}
|
|
|
|
// dummy catch-all sector for gta london maps
|
|
|
|
areas.insert(std::pair<PHYSFS_uint16, Sector*>(255*255, new Sector()));
|
2015-12-03 00:37:37 +00:00
|
|
|
|
2015-12-03 00:37:02 +00:00
|
|
|
/*
|
|
|
|
std::cout << "map areas (by size)" << std::endl;
|
|
|
|
SectorMapType::iterator i = areas.begin();
|
|
|
|
while (i != areas.end()) {
|
2015-12-03 00:37:37 +00:00
|
|
|
std::cout << " " << i->first << " : " << i->second->name2 << " @ " <<
|
2015-12-03 00:37:02 +00:00
|
|
|
int(i->second->x) << "," << int(i->second->y) << " " << int(i->second->w) << "x" <<
|
|
|
|
int(i->second->h) << " sample " << int(i->second->sam) << std::endl;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
NavData::~NavData() {
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
NavData::Sector* NavData::getSectorAt(PHYSFS_uint8 x, PHYSFS_uint8 y) {
|
|
|
|
SectorMapType::iterator it = areas.begin();
|
|
|
|
while (it != areas.end()) {
|
|
|
|
if (it->second->isInside(x, y))
|
|
|
|
return it->second;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
std::ostringstream o;
|
|
|
|
o << "Querying invalid sector at " << int(x) << ", " << int(y);
|
|
|
|
throw E_OUTOFRANGE(o.str());
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NavData::clear() {
|
|
|
|
SectorMapType::iterator it = areas.begin();
|
|
|
|
while (it != areas.end()) {
|
|
|
|
delete it->second;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
areas.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
int main(int argc, char* argv[]) {
|
|
|
|
OpenGTA::Rect2D a(3, 4, 10, 20);
|
|
|
|
a.subLocation(atoi(argv[1]), atoi(argv[2]));
|
|
|
|
}
|
|
|
|
#endif
|