Capaverde 5 Postado Setembro 30, 2011 Share Postado Setembro 30, 2011 (editado) Fiz isso com a idéia de permitir aos players construir casas no meio do mato e salvar essas casas e tal Não consegui fazer salvar towns ainda (temple positions), daí você teria que editar o otbm e adicionar elas depois Como eu fiz? Peguei o saveMap do remere (que é open source) e modifiquei um pouco, adaptando ao que o otserver tem. Testei e funcionou em theforgottenserver 0.2rc9 Bom, vamos ao código luascript.h: static int32_t luaSaveMap(lua_State* L); luascript.cpp, dentro de registerFunctions(): //saveMap() lua_register(m_luaState, "saveMap", LuaScriptInterface::luaSaveMap); luascript.cpp: int32_t LuaScriptInterface::luaSaveMap(lua_State* L) { //saveMap() g_game.saveMapzord(); } game.h(public): void saveMapzord(){map->saveMapzord();} map.h, embaixo de bool saveMap();: bool saveMapzord(); map.cpp: 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: bool saveMap(Map* map, const std::string& identifier, bool showdialog); iomap.cpp: 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 da class Item: //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 da class ItemAttributes: virtual bool isComplex() const {return (15 & m_attributes) != 0;} item.cpp: 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: troca as funções addU8 e addU16 por essas(ou o mapa gerado vai tá corrompido, aconteceu comigo): 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; } Como usa isso? Só colocar saveMap() em algum script, mas olha que vai lagar. Dá pra facilmente criar um npc que salva o mapa de x em x horas, e se você for reiniciar o server por algum motivo é só kickar todo mundo e usar uma talkaction que salve. Editado Outubro 10, 2011 por Capaverde Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/ Compartilhar em outros sites More sharing options...
Trivelatos 2 Postado Setembro 30, 2011 Share Postado Setembro 30, 2011 intereçante, eu não vou usar, mais gostei do script e é bem criativo, parabéns • Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1109655 Compartilhar em outros sites More sharing options...
arkires 8 Postado Outubro 1, 2011 Share Postado Outubro 1, 2011 poho mano meu repe não teste mais veleu por compartilha com o xtibia velho isso vai ser utill para muitos Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1110268 Compartilhar em outros sites More sharing options...
paulgrande 23 Postado Outubro 1, 2011 Share Postado Outubro 1, 2011 olha bem legal vc se vc criar um auto boarder da pra fazer um sistema de contruçao de casas muit limdo com telhado e tudo Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1110278 Compartilhar em outros sites More sharing options...
LukaszG 32 Postado Outubro 1, 2011 Share Postado Outubro 1, 2011 é intereçante de botar num server. Mais como to sem server num momento entao vo ficar sem usar mais parabens Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1110328 Compartilhar em outros sites More sharing options...
igorbrunomax 3 Postado Outubro 1, 2011 Share Postado Outubro 1, 2011 Legal, não sabia que era possivel de se fazer isso. Bem útil para alguns, Parabéns pela criatividade. se o script for seu! Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1110506 Compartilhar em outros sites More sharing options...
Capaverde 5 Postado Outubro 10, 2011 Autor Share Postado Outubro 10, 2011 Tá salvando towns agora Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1114152 Compartilhar em outros sites More sharing options...
Henrique Moura 193 Postado Outubro 10, 2011 Share Postado Outubro 10, 2011 Isso sem dúvidas abre uma porção de possibilidades pra quem é dono, tanto quanto para o jogador. Ótimo código! Parabéns Abraços. Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1114157 Compartilhar em outros sites More sharing options...
MatheusEnjoy 70 Postado Setembro 14, 2015 Share Postado Setembro 14, 2015 Editar mapas in game? Para isso e mto fino, script ainda por Capaverde. Muito bom para corrigir bugs do mapa in game. Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1668795 Compartilhar em outros sites More sharing options...
Capaverde 5 Postado Outubro 28, 2017 Autor Share Postado Outubro 28, 2017 Eis a função equivalente, puramente em Lua. Coloque-a no seu global.lua: bit32 = bit print = debugPrint --SPECIAL CHARACTERS NODE_START = 0xfe NODE_END = 0xff ESCAPE_CHAR = 0xfd --OTBM NODE TYPES OTBM_ROOTV1 = 1 OTBM_MAP_DATA = 2 OTBM_ITEM_DEF = 3 OTBM_TILE_AREA = 4 OTBM_TILE = 5 OTBM_ITEM = 6 OTBM_TILE_SQUARE = 7 OTBM_TILE_REF = 8 OTBM_SPAWNS = 9 OTBM_SPAWN_AREA = 10 OTBM_MONSTER = 11 OTBM_TOWNS = 12 OTBM_TOWN = 13 OTBM_HOUSETILE = 14 --OTBM ATTR TYPES OTBM_ATTR_DESCRIPTION = 1 OTBM_ATTR_EXT_FILE = 2 OTBM_ATTR_TILE_FLAGS = 3 OTBM_ATTR_ACTION_ID = 4 OTBM_ATTR_UNIQUE_ID = 5 OTBM_ATTR_TEXT = 6 OTBM_ATTR_DESC = 7 OTBM_ATTR_TELE_DEST = 8 OTBM_ATTR_ITEM = 9 OTBM_ATTR_DEPOT_ID = 10 OTBM_ATTR_EXT_SPAWN_FILE = 11 OTBM_ATTR_RUNE_CHARGES = 12 OTBM_ATTR_EXT_HOUSE_FILE = 13 OTBM_ATTR_HOUSEDOORID = 14 OTBM_ATTR_COUNT = 15 OTBM_ATTR_DURATION = 16 OTBM_ATTR_DECAYING_STATE = 17 OTBM_ATTR_WRITTENDATE = 18 OTBM_ATTR_WRITTENBY = 19 OTBM_ATTR_SLEEPERGUID = 20 OTBM_ATTR_SLEEPSTART = 21 OTBM_ATTR_CHARGES = 22 function lchar(i) s="" while i>0 do s=s..string.char(i%256) i=math.floor(i/256) end return s end function format(s,size) local len = #s for x=1,size/8-len do s=s.."\0" end return s end function writeData(f,data,size,unescape) local thestr if type(data) == "string" then thestr = format(data,size) elseif type(data) == "number" then thestr = format(lchar(data),size) elseif type(data) == "table" then for k,v in pairs(data) do print(k,v) end return else print(data) return end for x=1,size/8 do local c = thestr:sub(x,x) --print(#thestr,size,string.byte(c)) --if c == string.char(0x0D) then error("daonde") end if unescape and (c==string.char(NODE_START) or c==string.char(NODE_END) or c==string.char(ESCAPE_CHAR)) then f:write(string.char(ESCAPE_CHAR)) end f:write(c) end end function addU8(f,data) writeData(f,data,8,true) end function addByte(f,data) writeData(f,data,8,false) end function addU16(f,data) writeData(f,data,16,true) end function addU32(f,data) writeData(f,data,32,false) end function addString(f,data) if #data > 0xffff then return false end addU16(f,#data) writeData(f,data,#data*8,false) end function startNode(f,c) --c is a char writeData(f,NODE_START,8,false) writeData(f,c,8,true) end function endNode(f) writeData(f,NODE_END,8,false) end WIDTH = 128 --put here the dimensions of your map HEIGHT = 128 -- ITEMDWMAJORVERSION = 2 ITEMDWMINORVERSION = 8 function saveMap(name) --e.g. "map.otbm" local minv = math.huge local maxv = 0 print("saveMap start") f = io.open(name,"wb") addU32(f,0); --version startNode(f,0) addU32(f,0); --version again :O addU16(f,WIDTH) addU16(f,HEIGHT) addU32(f,ITEMDWMAJORVERSION) addU32(f,ITEMDWMINORVERSION) startNode(f,OTBM_MAP_DATA) --addByte(f,OTBM_ATTR_DESCRIPTION) --addString(f,"Created with saveMap script, a translation of Remere's") local first = true local l_x=-1 local l_y=-1 local l_Z=-1 for z=0,7 do for xi=0,WIDTH-1,256 do for yi=0,HEIGHT-1,256 do for x=xi,math.min(xi+256-1,WIDTH-1) do for y=yi,math.min(yi+256-1,HEIGHT-1) do if x<l_x or x>=l_x+256 or y<l_y or y>=l_y+256 or z~=l_z then if not first then endNode(f) end first = false --start new node startNode(f,OTBM_TILE_AREA) l_x=bit32.band(x,0xff00) l_y=bit32.band(y,0xff00) l_z=z addU16(f,l_x) addU16(f,l_y) addU8(f,l_z) end startNode(f,OTBM_TILE) addU8(f,bit32.band(x,0xff)) addU8(f,bit32.band(y,0xff)) for stackpos=0,10 do local pos = {x=x,y=y,z=z,stackpos=stackpos} local thing = getTileThingByPos(pos) if (thing.itemid==0 and stackpos==0) then --no tile, so we can skip it break end if thing.itemid > 0 and stackpos ~= 253 then --TODO: save item counts, save containers addByte(f,OTBM_ATTR_ITEM) addU16(f,thing.itemid) end end endNode(f) end end end end end if not first then endNode(f) end endNode(f) endNode(f) f:close() print(minv,maxv) end Dessa forma não precisa-se editar uma linha do source ou recompilar Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1723245 Compartilhar em outros sites More sharing options...
Benny 736 Postado Outubro 28, 2017 Share Postado Outubro 28, 2017 Obrigado pela modificação, @Capaverde xTibia agradece o conteúdo (: Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1723247 Compartilhar em outros sites More sharing options...
wevertonvrb 25 Postado Agosto 15, 2020 Share Postado Agosto 15, 2020 Em 28/10/2017 em 05:36, Capaverde disse: Eis a função equivalente, puramente em Lua. Coloque-a no seu global.lua: bit32 = bit print = debugPrint --SPECIAL CHARACTERS NODE_START = 0xfe NODE_END = 0xff ESCAPE_CHAR = 0xfd --OTBM NODE TYPES OTBM_ROOTV1 = 1 OTBM_MAP_DATA = 2 OTBM_ITEM_DEF = 3 OTBM_TILE_AREA = 4 OTBM_TILE = 5 OTBM_ITEM = 6 OTBM_TILE_SQUARE = 7 OTBM_TILE_REF = 8 OTBM_SPAWNS = 9 OTBM_SPAWN_AREA = 10 OTBM_MONSTER = 11 OTBM_TOWNS = 12 OTBM_TOWN = 13 OTBM_HOUSETILE = 14 --OTBM ATTR TYPES OTBM_ATTR_DESCRIPTION = 1 OTBM_ATTR_EXT_FILE = 2 OTBM_ATTR_TILE_FLAGS = 3 OTBM_ATTR_ACTION_ID = 4 OTBM_ATTR_UNIQUE_ID = 5 OTBM_ATTR_TEXT = 6 OTBM_ATTR_DESC = 7 OTBM_ATTR_TELE_DEST = 8 OTBM_ATTR_ITEM = 9 OTBM_ATTR_DEPOT_ID = 10 OTBM_ATTR_EXT_SPAWN_FILE = 11 OTBM_ATTR_RUNE_CHARGES = 12 OTBM_ATTR_EXT_HOUSE_FILE = 13 OTBM_ATTR_HOUSEDOORID = 14 OTBM_ATTR_COUNT = 15 OTBM_ATTR_DURATION = 16 OTBM_ATTR_DECAYING_STATE = 17 OTBM_ATTR_WRITTENDATE = 18 OTBM_ATTR_WRITTENBY = 19 OTBM_ATTR_SLEEPERGUID = 20 OTBM_ATTR_SLEEPSTART = 21 OTBM_ATTR_CHARGES = 22 function lchar(i) s="" while i>0 do s=s..string.char(i%256) i=math.floor(i/256) end return s end function format(s,size) local len = #s for x=1,size/8-len do s=s.."\0" end return s end function writeData(f,data,size,unescape) local thestr if type(data) == "string" then thestr = format(data,size) elseif type(data) == "number" then thestr = format(lchar(data),size) elseif type(data) == "table" then for k,v in pairs(data) do print(k,v) end return else print(data) return end for x=1,size/8 do local c = thestr:sub(x,x) --print(#thestr,size,string.byte(c)) --if c == string.char(0x0D) then error("daonde") end if unescape and (c==string.char(NODE_START) or c==string.char(NODE_END) or c==string.char(ESCAPE_CHAR)) then f:write(string.char(ESCAPE_CHAR)) end f:write(c) end end function addU8(f,data) writeData(f,data,8,true) end function addByte(f,data) writeData(f,data,8,false) end function addU16(f,data) writeData(f,data,16,true) end function addU32(f,data) writeData(f,data,32,false) end function addString(f,data) if #data > 0xffff then return false end addU16(f,#data) writeData(f,data,#data*8,false) end function startNode(f,c) --c is a char writeData(f,NODE_START,8,false) writeData(f,c,8,true) end function endNode(f) writeData(f,NODE_END,8,false) end WIDTH = 128 --put here the dimensions of your map HEIGHT = 128 -- ITEMDWMAJORVERSION = 2 ITEMDWMINORVERSION = 8 function saveMap(name) --e.g. "map.otbm" local minv = math.huge local maxv = 0 print("saveMap start") f = io.open(name,"wb") addU32(f,0); --version startNode(f,0) addU32(f,0); --version again :O addU16(f,WIDTH) addU16(f,HEIGHT) addU32(f,ITEMDWMAJORVERSION) addU32(f,ITEMDWMINORVERSION) startNode(f,OTBM_MAP_DATA) --addByte(f,OTBM_ATTR_DESCRIPTION) --addString(f,"Created with saveMap script, a translation of Remere's") local first = true local l_x=-1 local l_y=-1 local l_Z=-1 for z=0,7 do for xi=0,WIDTH-1,256 do for yi=0,HEIGHT-1,256 do for x=xi,math.min(xi+256-1,WIDTH-1) do for y=yi,math.min(yi+256-1,HEIGHT-1) do if x<l_x or x>=l_x+256 or y<l_y or y>=l_y+256 or z~=l_z then if not first then endNode(f) end first = false --start new node startNode(f,OTBM_TILE_AREA) l_x=bit32.band(x,0xff00) l_y=bit32.band(y,0xff00) l_z=z addU16(f,l_x) addU16(f,l_y) addU8(f,l_z) end startNode(f,OTBM_TILE) addU8(f,bit32.band(x,0xff)) addU8(f,bit32.band(y,0xff)) for stackpos=0,10 do local pos = {x=x,y=y,z=z,stackpos=stackpos} local thing = getTileThingByPos(pos) if (thing.itemid==0 and stackpos==0) then --no tile, so we can skip it break end if thing.itemid > 0 and stackpos ~= 253 then --TODO: save item counts, save containers addByte(f,OTBM_ATTR_ITEM) addU16(f,thing.itemid) end end endNode(f) end end end end end if not first then endNode(f) end endNode(f) endNode(f) f:close() print(minv,maxv) end Dessa forma não precisa-se editar uma linha do source ou recompilar sera que alguem pode dar uma ajudinha explicando como eu instalo e uso isso? Link para o comentário https://xtibia.com/forum/topic/168802-salvar-mapa-in-game/#findComment-1761991 Compartilhar em outros sites More sharing options...
Posts Recomendados