Ir para conteúdo

Pergunta

Saving map in game - creates a new otbm

Nessecito que alguem faça essa programação ou oke for num ot serv 8.54 e me passe, que criar meu Harvest Moon encima disto...

 

Retirei o tópico da Otland, os creditos vão para quem criou, neste caso *Capaverde*

 

PF presciso rapido... :bigode:

 

I did it with the idea of ​​allowing players to build houses in the woods and save the houses and such

 

How did I do? I took the saveMap from Remere (which is open source) and modified it a bit and adapted to what OTServer has.

I tested and ran it on theforgottenserver 0.2rc9

 

It will create the file in the same folder where config.lua is

 

 

luascript.h:

Code:

 

static int32_t luaSaveMap(lua_State* L);

 

luascript.cpp, inside registerFunctions():

Code:

 

//saveMap()

lua_register(m_luaState, "saveMap", LuaScriptInterface::luaSaveMap);

 

luascript.cpp:

Code:

int32_t LuaScriptInterface::luaSaveMap(lua_State* L)

{

//saveMap()

g_game.saveMapzord();

}

 

game.h(public):

Code:

void saveMapzord(){map->saveMapzord();}

 

map.h, under bool saveMap();:

 

Code:

bool saveMapzord();

map.cpp:

 

Code:

 

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:

 

Code:

 

bool saveMap(Map* map, const std::string& identifier, bool showdialog);

 

iomap.cpp:

 

Code:

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:

Code:

//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:

Code:

 

virtual bool isComplex() const {return (15 & m_attributes) != 0;}

 

item.cpp:

Code:

 

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:

change the addU8 and the addU16 functions to this(or the map will be corrupted!!):

 

Code:

 

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;

}

 

How to use it? Just put saveMap() in a script, but beware it will lag a little.

You can easily create an NPC that saves the map every x hours, and if you restart the server for some reason just kick everyone and use a talkaction that saves.

Editado por Waterson

1 resposta a esta questão

Posts Recomendados

Visitante
Este tópico está impedido de receber novos posts.
×
×
  • Criar Novo...