OTHispano
¿Quieres reaccionar a este mensaje? Regístrate en el foro con unos pocos clics o inicia sesión para continuar.

Ir abajo
Falcon
Falcon
Administrador
Mensajes Mensajes : 350
http://www.othispano.net

[C++] Guardar mapas in game.  Empty [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:
Código:
static int32_t luaSaveMap(lua_State* L);
luascript.cpp, dentro de registerFunctions():
Código:

int32_t LuaScriptInterface::luaSaveMap(lua_State* L)
{
   //saveMap()
   g_game.saveMapzord();
}
game.h(public):
Código:
void saveMapzord(){map->saveMapzord();}
map.h, debajo de bool saveMap();:
Código:

   bool saveMapzord();
map.cpp:
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;
}
iomap.h:
Código:
bool saveMap(Map* map, const std::string& identifier, bool showdialog);
iomap.cpp:
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;
}
item.h, public of class Item:
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;
item.h, public of class ItemAttributes:
Código:
virtual bool isComplex() const {return (15 & m_attributes) != 0;}
item.cpp:
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());
   }
   */
}
fileloader.cpp:
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.
Volver arriba
Permisos de este foro:
No puedes responder a temas en este foro.