-
Total de itens
12 -
Registro em
-
Última visita
Sobre Capaverde

Perfil
-
Gênero
Masculino
Informações
-
Forma que conheci o xTibia
Otservs
-
Sou
Programador
Últimos Visitantes
2291 visualizações
Capaverde's Achievements
-
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
-
[Encerrado][Fighting Spirit] Procurando spriter, mapper ou programador coadjuvante
um tópico no fórum postou Capaverde Formação de Equipes
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. -
Capaverde alterou sua foto pessoal
-
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
-
Tá salvando towns agora
-
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.
-
te teleporta de volta pro lugar que voce salvou
-
up
-
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
-
mas daih o cara ia ter q ficar tirando e colocando o ring eh mais facil soh dar use
-
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
-
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
-
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.