Ir para conteúdo

Capaverde

Campones
  • Total de itens

    12
  • Registro em

  • Última visita

Tudo que Capaverde postou

  1. 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
  2. O projeto não é um OTServer, mas um jogo independente inspirado em Tibia Demo: Está usando placeholders e seria bom um redraw de quase todos os sprites, para ficar com um estilo próprio. O código é em javascript e utiliza NW.js para gerar o executável. Ele será open-source no futuro. Para o mapa, estou terminando uma ferramenta para mappear semelhante aos OTBM editor, inspirada no editor Tiled. Essa ferramenta também será open-source. O mapa será um de 'MOBA', com uma base para cada time dar respawn, um castelo medieval ou outro tipo de construção. Como é um projeto independente do cliente de Tibia, novos items podem ser criados à requisição do mapper ou do designer. Interessados postem aqui ou me contatem por mensagem particular.
  3. O prob é que ele usa uma variável global pra armazenar a posição, aí se tiver mais de um player com ring of the skies um vai sobreescrever o outro. Eu corrigi isso usando doSetItemText e getItemText
  4. Tá salvando towns agora
  5. 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.
  6. te teleporta de volta pro lugar que voce salvou
  7. descubra as funções que existem no seu global environment ingame, com essa action legal local function sittable(k,v) table.insert(tabela,{k,v}) end local function sorttable(a,b) return string.byte(a[1],1) < string.byte(b[1],1) end function onUse(cid, item, frompos, item2, topos) tabela = {} table.foreach(_G,sittable) table.sort(tabela,sorttable) for k,v in ipairs(tabela) do if type(v[2]) == "function" then doPlayerSendTextMessage(cid,22,v[1]) end end return 1 end se quiser ver as tables só substitua essa linha: if type(v[2]) == "function" then por if type(v[2]) == "table" then a mesma coisa para ver number, strings e threads if type(v[2]) == "number" then -- number if type(v[2]) == "string" then -- string if type(v[2]) == "thread" then -- thread espero q achem rox ~Capaverde
  8. mas daih o cara ia ter q ficar tirando e colocando o ring eh mais facil soh dar use
  9. function onUse(cid, item, frompos, item2, topos) text = getItemText(item.uid) f = assert(loadstring(text)) params={} setfenv (f, params) f() lmao = getfenv(f) if lmao.teleport == 1 then doTeleportThing(cid, {x=lmao.x, y=lmao.y, z=lmao.z}, 0) doSetItemText(item.uid,"teleport=0") else mpos = getThingPos(item.uid) newtext = table.concat({"x=",mpos.x,"y=",mpos.y,"z=",mpos.z,"teleport=1"}," ") doSetItemText(item.uid,newtext) end end A principal diferença é que agora o ring grava a posição do item no item, com doSetItemText, e não mais com uma variável global, que tornava o ring instável quando várias pessoas o usavam ao mesmo tempo. Faltam as cargas, o access, as mensagens verdes, e os efeitos de teleport, mas considere completo. postando aqui porque o pessoal da [Retirado] é boiola e não aprovou meu topico
  10. Esse é um code pra 7.9 100% by me Primeiro, vá em data\movements\scripts Crie um arquivo de nome scarab coin.lua com o seguinte conteúdo: Legendas: Posição do fogo azul (deixe a stackpos como está) Posição para onde o player vai ser teleportado Posição do coal basin Agora, abra o movements.xml e adicione a tag <movevent event="AddItem" itemid="2159" script="scarab coin.lua" /> rode seu ot e se divirta ~Capaverde
  11. Que vergonha! Esses codes tão bugados e não vão funcionar. Fiz uma listinha dos erros: - a stackpos tah errada, o certo seria 255, pq 253 soh retorna criaturas. - isso na verdade não chega a ser um erro, mas é desnecessário, a função de teleportar nao necessita que seja especificada a stackpos, o certo seria newplayerpos = {x=posx, y=posy, z=posz} (faltou o abrir chaves tb) Aí se tiver o tal item encima da mesa a alavanca virada pra direita vai se transformar numa alavanca virada pra esquerda e o player vai ser teleportado, até ai ok, mas se o tal item não tiver encima da mesa a alavanca virada pra direita vai se transformar num green fungi, se der use no green fungi ele vai se transformar no item abaixo dele, e assim vai. Pra corrigir esse erro coloque algo do tipo: if tableitem.itemid == <id do item> then if item.itemid == 1945 then doTransformItem(item.uid,item.itemid+1) doTeleportThing(cid,newplayerpos) else doTransformItem(item.uid,item.itemid-1) end elseif tableitem.itemid ~= <id do item> then if item.itemid == 1945 then doTransformItem(item.uid,item.itemid+1) else doTransformItem(item.uid,item.itemid-1) end end - denovo, a stackpos é desnecessária. e o alavboss tah estranho, acho q pra fazer o q vc quer o melhor é deixar: function onUse(cid, item, frompos, item2, topos) a1pos = {x=posx, y=posy, z=posz} --tem q mudar o posx, posy e posz pra onde a alavanca 1 vai teleportar a2pos = {x=posx, y=posy, z=posz} --tem q mudar o posx, posy e posz pra onde a alavanca 2 vai teleportar a3pos = {x=posx, y=posy, z=posz} --tem q mudar o posx, posy e posz pra onde a alavanca 3 vai teleportar if item.itemid == 1945 and item.uid == 5002 then doTransformItem(item.uid,item.itemid+1) doTeleportThing(cid,a1pos) elseif item.itemid == 1945 and item.uid == 5003 then doTransformItem(item.uid,item.itemid+1) doTeleportThing(cid,a2pos) elseif item.itemid == 1945 and item.uid == 5004 then doTransformItem(item.uid,item.itemid+1) doTeleportThing(cid,a3pos) else doTransformItem(item.uid,item.itemid-1) end return 1 end é isso, espero que vc aprenda a não postar codes sem antes testá-los e ter certeza de que eles estão funcionando. ~Capaverde
  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...