[C++] Guardar mapas in game.
Miér Mayo 16, 2012 10:02 pm
¡Hola!
hoy les traigo éste espectacular código en C++ que hace que puedas modificar y guardar los mapas dentro del juego.
DATOS
Código
luascript.h:
cambia el addU8 y el addU16 por estas (o el mapa estará corrupto):
¿Cómo Funciona?
Sólo añade la función saveMap() en un script.
hoy les traigo éste espectacular código en C++ que hace que puedas modificar y guardar los mapas dentro del juego.
DATOS
Código
luascript.h:
- Código:
static int32_t luaSaveMap(lua_State* L);
- Código:
int32_t LuaScriptInterface::luaSaveMap(lua_State* L)
{
//saveMap()
g_game.saveMapzord();
}
- Código:
void saveMapzord(){map->saveMapzord();}
- Código:
bool saveMapzord();
- Código:
bool Map::saveMapzord()
{
IOMap* loader = new IOMap();
bool saved = false;
for(uint32_t tries = 0; tries < 3; tries++)
{
if(loader->saveMap(this, "eai.otbm", false))
{
saved = true;
break;
}
}
return saved;
}
- Código:
bool saveMap(Map* map, const std::string& identifier, bool showdialog);
- Código:
bool IOMap::saveMap(Map* map, const std::string& identifier, bool showdialog) {
/* STOP!
* Before you even think about modifying this, please reconsider.
* while adding stuff to the binary format may be "cool", you'll
* inevitably make it incompatible with any future releases of
* the map editor, meaning you cannot reuse your map. Before you
* try to modify this, PLEASE consider using an external file
* like spawns.xml or houses.xml, as that will be MUCH easier
* to port to newer versions of the editor than a custom binary
* format.
*/
/*if(Items::dwMajorVersion < 3) {
version = 0;
} else {
version = 1;
}*/
FileLoader f;
f.openFile(identifier.c_str(), true, false);
f.startNode(0); {
f.addU32(0); // Version
f.addU16((uint16_t)map->mapWidth);
f.addU16((uint16_t)map->mapHeight);
f.addU32(Items::dwMajorVersion);
f.addU32(Items::dwMinorVersion);
f.startNode(OTBM_MAP_DATA); {
f.addByte(OTBM_ATTR_DESCRIPTION);
// Neither SimOne's nor OpenTibia cares for additional description tags
f.addString("Saved with Remere's Map Editor ");
f.addU8(OTBM_ATTR_DESCRIPTION);
f.addString("Esse mapa é maneiro.");
/*f.addU8(OTBM_ATTR_EXT_SPAWN_FILE);
FileName fn(wxstr(map->spawnfile));
f.addString(std::string((const char*)fn.GetFullName().mb_str(wxConvUTF8)));
if(gui.GetCurrentVersion() > CLIENT_VERSION_760) {
f.addU8(OTBM_ATTR_EXT_HOUSE_FILE);
fn.Assign(wxstr(map->housefile));
f.addString(std::string((const char*)fn.GetFullName().mb_str(wxConvUTF8)));
}*/
// Start writing tiles
//uint64_t tiles_saved = 0;
bool first = true;
int local_x = -1, local_y = -1, local_z = -1;
for (uint64_t z=0; z<=15; ++z)
for (uint64_t xi = 0; xi<map->mapWidth; xi+=256)
for (uint64_t yi = 0; yi<map->mapHeight; yi+=256)
for (uint64_t x = xi; x<xi+256; x++)="" for="" (uint64_t="" y="yi;" y<yi+256;="" y++){="" mapiterator="" map_iterator="map.begin();" while(map_iterator="" !="map.end())" {="" update="" progressbar="" ++tiles_saved;="" if(showdialog="" &&="" tiles_saved="" %="" 8192="=" 0)="" gui.setloaddone(int(tiles_saved="" double(map.gettilecount())="" *="" 100.0));="" }="" get="" tile="" tile*="" save_tile="map-">getTile(x,y,z); //Tile* save_tile = *map_iterator;
if (!save_tile)
continue;
const Position& pos = save_tile->getPosition();
/*// Is it an empty tile that we can skip? (Leftovers...)
if(save_tile->size() == 0) {
++map_iterator;
continue;
}*/
// Decide if new node should be created
if(pos.x < local_x || pos.x >= local_x + 256 ||
pos.y < local_y || pos.y >= local_y + 256 ||
pos.z != local_z) {
// End last node
if(!first) {
f.endNode();
}
first = false;
// Start new node
f.startNode(OTBM_TILE_AREA);
f.addU16(local_x = pos.x & 0xFF00);
f.addU16(local_y = pos.y & 0xFF00);
f.addU8( local_z = pos.z);
}
//HouseTile* houseTile = dynamic_cast<housetile*>(save_tile);
f.startNode(/*houseTile? OTBM_HOUSETILE : */OTBM_TILE);
f.addU8(pos.x & 0xFF);
f.addU8(pos.y & 0xFF);
/*if(houseTile) {
f.addU32(houseTile->getHouse()->getHouseId());
}*/
/*if(save_tile->getMapFlags()) {
f.addByte(OTBM_ATTR_TILE_FLAGS);
f.addU32(save_tile->getMapFlags());
}*/
if(save_tile->ground) {
Item* ground = save_tile->ground;
/*if(ground->hasBorderEquivalent()) {
bool found = false;
for(ItemVector::iterator it = save_tile->items.begin(); it != save_tile->items.end(); ++it) {
if((*it)->getGroundEquivalent() == ground->getID()) {
// Do nothing
// Found equivalent
found = true;
break;
}
}
if(found == false) {
ground->serializeItemNode_OTBM(*this, f);
}
} else*/ if(ground->isComplex()) {
ground->serializeItemNode_OTBM(f);
} else {
f.addByte(OTBM_ATTR_ITEM);
ground->serializeItemCompact_OTBM(f);
}
}
for(ItemVector::reverse_iterator it = save_tile->downItems.rbegin(); it != save_tile->downItems.rend(); ++it) {
//if(!(*it)->isMetaItem()) {
(*it)->serializeItemNode_OTBM(f);
//}
}
for(ItemVector::iterator it = save_tile->topItems.begin(); it != save_tile->topItems.end(); ++it) {
//if(!(*it)->isMetaItem()) {
(*it)->serializeItemNode_OTBM(f);
//}
}
f.endNode();
//++map_iterator;
}
// Only close the last node if one has actually been created
if(!first) {
f.endNode();
}
f.startNode(OTBM_TOWNS); {
//for(TownMap::const_iterator it = townMap.begin(); it != townMap.end(); ++it) {
for(TownMap::const_iterator it = Towns::getInstance().getFirstTown(); it != Towns::getInstance().getLastTown(); ++it){
Town* town = it->second;
f.startNode(OTBM_TOWN);
f.addU32(town->getTownID());
f.addString(town->getName());
f.addU16(town->getTemplePosition().x);
f.addU16(town->getTemplePosition().y);
f.addU8 (town->getTemplePosition().z);
f.endNode();
}
} f.endNode();
} f.endNode();
//std::cout << tiles_saved << std::endl;
} f.endNode();
/*if(showdialog) gui.SetLoadDone(100, wxT("Saving spawns..."));
saveSpawns(map, identifier);
if(gui.GetCurrentVersion() > CLIENT_VERSION_760) {
if(showdialog) gui.SetLoadDone(100, wxT("Saving houses..."));
saveHouses(map, identifier);
}*/
return true;
}
- Código:
//map-saving
virtual bool serializeItemNode_OTBM(FileLoader& f) const;
// Will write this item to the stream supplied in the argument
virtual void serializeItemCompact_OTBM(FileLoader& f) const;
virtual void serializeItemAttributes_OTBM(FileLoader& f) const;
- Código:
virtual bool isComplex() const {return (15 & m_attributes) != 0;}
- Código:
bool Item::serializeItemNode_OTBM(FileLoader& f) const {
f.startNode(OTBM_ITEM);
f.addU16(id);
//if(maphandle.version == 0) {
/*const ItemType& iType = items[id];
if(iType.stackable || iType.isSplash() || iType.isFluidContainer()){
f.addU8(getSubType());
}*/
//}
serializeItemAttributes_OTBM(f);
f.endNode();
return true;
}
void Item::serializeItemAttributes_OTBM(FileLoader& stream) const {
//if(maphandle.version > 0) {
const ItemType& iType = items[id];
if(iType.stackable || iType.isSplash() || iType.isFluidContainer()){
//stream.addU8(OTBM_ATTR_COUNT);
stream.addU8(getItemCountOrSubtype());
}
//}*/
/* if(items.dwMinorVersion >= CLIENT_VERSION_820 && isCharged()) {
stream.addU8(OTBM_ATTR_CHARGES);
stream.addU16(getSubtype());
}*/
if(getActionId()) {
stream.addU8(OTBM_ATTR_ACTION_ID);
stream.addU16(getActionId());
}
if(getUniqueId()) {
stream.addU8(OTBM_ATTR_UNIQUE_ID);
stream.addU16(getUniqueId());
}
if(getText().length() > 0) {
stream.addU8(OTBM_ATTR_TEXT);
stream.addString(getText());
}
if(getSpecialDescription().length() > 0) {
stream.addU8(OTBM_ATTR_DESC);
stream.addString(getSpecialDescription());
}
}
void Item::serializeItemCompact_OTBM(FileLoader& stream) const {
stream.addU16(id);
/* This is impossible
const ItemType& iType = item_db[id];
if(iType.stackable || iType.isSplash() || iType.isFluidContainer()){
stream.addU8(getSubtype());
}
*/
}
cambia el addU8 y el addU16 por estas (o el mapa estará corrupto):
- Código:
bool FileLoader::addU8(uint8_t u8) {
writeData(&u8, sizeof(u8), true); //unescape=true, or else some FEsomething itemid might be recognized as the start of a node
return m_lastError == ERROR_NONE;
}
bool FileLoader::addU16(uint16_t u16) {
writeData(reinterpret_cast<uint8_t*>(&u16), sizeof(u16), true);
return m_lastError == ERROR_NONE;
}
¿Cómo Funciona?
Sólo añade la función saveMap() en un script.
Permisos de este foro:
No puedes responder a temas en este foro.