Ir para conteúdo

AlexandreKG

Marquês
  • Total de itens

    1153
  • Registro em

  • Última visita

  • Dias Ganhos

    3

Tudo que AlexandreKG postou

  1. Bom,gente eu nao sei se fis algo,errado mas eu botei nas sources do meu esrver assim, //////////////////////////////////////////////////////////////////////// // OpenTibia - an opensource roleplaying game //////////////////////////////////////////////////////////////////////// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. //////////////////////////////////////////////////////////////////////// #include "otpch.h" #include <iomanip> #include <boost/config.hpp> #include <boost/bind.hpp> #include "iomap.h" #include "map.h" #include "tile.h" #include "creature.h" #include "player.h" #include "combat.h" #include "iomapserialize.h" #include "items.h" #include "game.h" extern Game g_game; Map::Map() { mapWidth = 0; mapHeight = 0; } bool Map::loadMap(const std::string& identifier) { int64_t start = OTSYS_TIME(); IOMap* loader = new IOMap(); if(!loader->loadMap(this, identifier)) /*{ std::cout << "> FATAL: OTBM Loader - " << loader->getLastErrorString() << std::endl; return false; } std::cout << "> Map loading time: " << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl; start = OTSYS_TIME(); if(!loader->loadSpawns(this)) std::cout << "> WARNING: Could not load spawn data." << std::endl; if(!loader->loadHouses(this)) std::cout << "> WARNING: Could not load house data." << std::endl; }*/ delete loader; std::cout << "> Data parsing time: " << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl; start = OTSYS_TIME(); IOMapSerialize::getInstance()->updateHouses(); IOMapSerialize::getInstance()->updateAuctions(); std::cout << "> Houses synchronization time: " << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl; start = OTSYS_TIME(); IOMapSerialize::getInstance()->loadHouses(); IOMapSerialize::getInstance()->loadMap(this); std::cout << "> Content unserialization time: " << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl; return true; } bool Map::saveMap() { IOMapSerialize* IOLoader = IOMapSerialize::getInstance(); bool saved = false; for(uint32_t tries = 0; tries < 3; ++tries) { if(!IOLoader->saveHouses()) continue; saved = true; break; } if(!saved) return false; saved = false; for(uint32_t tries = 0; tries < 3; ++tries) { if(!IOLoader->saveMap(this)) continue; saved = true; break; } return saved; } Tile* Map::getTile(int32_t x, int32_t y, int32_t z) { if(x < 0 || x > 0xFFFF || y < 0 || y > 0xFFFF || z < 0 || z >= MAP_MAX_LAYERS) return NULL; QTreeLeafNode* leaf = QTreeNode::getLeafStatic(&root, x, y); if(!leaf) return NULL; Floor* floor = leaf->getFloor(z); if(!floor) return NULL; return floor->tiles[x & FLOOR_MASK][y & FLOOR_MASK]; } void Map::setTile(uint16_t x, uint16_t y, uint16_t z, Tile* newTile) { if(z >= MAP_MAX_LAYERS) { std::cout << "[Error - Map::setTile]: Attempt to set tile on invalid Z coordinate - " << z << "!" << std::endl; return; } QTreeLeafNode::newLeaf = false; QTreeLeafNode* leaf = root.createLeaf(x, y, 15); if(QTreeLeafNode::newLeaf) { //update north QTreeLeafNode* northLeaf = root.getLeaf(x, y - FLOOR_SIZE); if(northLeaf) northLeaf->m_leafS = leaf; //update west leaf QTreeLeafNode* westLeaf = root.getLeaf(x - FLOOR_SIZE, y); if(westLeaf) westLeaf->m_leafE = leaf; //update south QTreeLeafNode* southLeaf = root.getLeaf(x, y + FLOOR_SIZE); if(southLeaf) leaf->m_leafS = southLeaf; //update east QTreeLeafNode* eastLeaf = root.getLeaf(x + FLOOR_SIZE, y); if(eastLeaf) leaf->m_leafE = eastLeaf; } uint32_t offsetX = x & FLOOR_MASK, offsetY = y & FLOOR_MASK; Floor* floor = leaf->createFloor(z); if(!floor->tiles[offsetX][offsetY]) { floor->tiles[offsetX][offsetY] = newTile; newTile->qt_node = leaf; } else std::cout << "[Error - Map::setTile] Tile already exists - pos " << offsetX << "/" << offsetY << "/" << z << std::endl; if(newTile->hasFlag(TILESTATE_REFRESH)) { RefreshBlock_t rb; if(TileItemVector* tileItems = newTile->getItemList()) { for(ItemVector::iterator it = tileItems->getBeginDownItem(); it != tileItems->getEndDownItem(); ++it) rb.list.push_back((*it)->clone()); } rb.lastRefresh = OTSYS_TIME(); g_game.addRefreshTile(newTile, rb); } } bool Map::placeCreature(const Position& centerPos, Creature* creature, bool extendedPos /*= false*/, bool forced /*= false*/) { bool foundTile = false, placeInPz = false; Tile* tile = getTile(centerPos); if(tile) { placeInPz = tile->hasFlag(TILESTATE_PROTECTIONZONE); uint32_t flags = FLAG_IGNOREBLOCKITEM; if(creature->isAccountManager()) flags |= FLAG_IGNOREBLOCKCREATURE; ReturnValue ret = tile->__queryAdd(0, creature, 1, flags); if(forced || ret == RET_NOERROR || ret == RET_PLAYERISNOTINVITED) foundTile = true; } size_t shufflePos = 0; PairVector relList; if(extendedPos) { shufflePos = 8; relList.push_back(PositionPair(-2, 0)); relList.push_back(PositionPair(0, -2)); relList.push_back(PositionPair(0, 2)); relList.push_back(PositionPair(2, 0)); std::random_shuffle(relList.begin(), relList.end()); } relList.push_back(PositionPair(-1, -1)); relList.push_back(PositionPair(-1, 0)); relList.push_back(PositionPair(-1, 1)); relList.push_back(PositionPair(0, -1)); relList.push_back(PositionPair(0, 1)); relList.push_back(PositionPair(1, -1)); relList.push_back(PositionPair(1, 0)); relList.push_back(PositionPair(1, 1)); std::random_shuffle(relList.begin() + shufflePos, relList.end()); uint32_t radius = 1; Position tryPos; for(uint32_t n = 1; n <= radius && !foundTile; ++n) { for(PairVector::iterator it = relList.begin(); it != relList.end() && !foundTile; ++it) { int32_t dx = it->first * n, dy = it->second * n; tryPos = centerPos; tryPos.x = tryPos.x + dx; tryPos.y = tryPos.y + dy; if(!(tile = getTile(tryPos)) || (placeInPz && !tile->hasFlag(TILESTATE_PROTECTIONZONE))) continue; if(tile->__queryAdd(0, creature, 1, 0) == RET_NOERROR) { if(!extendedPos) { foundTile = true; break; } if(isSightClear(centerPos, tryPos, false)) { foundTile = true; break; } } } } if(!foundTile) return false; int32_t index = 0; uint32_t flags = 0; Item* toItem = NULL; if(Cylinder* toCylinder = tile->__queryDestination(index, creature, &toItem, flags)) { toCylinder->__internalAddThing(creature); if(Tile* toTile = toCylinder->getTile()) toTile->qt_node->addCreature(creature); } return true; } bool Map::removeCreature(Creature* creature) { Tile* tile = creature->getTile(); if(!tile) return false; tile->qt_node->removeCreature(creature); tile->__removeThing(creature, 0); return true; } void Map::getSpectatorsInternal(SpectatorVec& list, const Position& centerPos, bool checkForDuplicate, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY, int32_t minRangeZ, int32_t maxRangeZ) { int32_t minoffset = centerPos.z - maxRangeZ, maxoffset = centerPos.z - minRangeZ, x1 = std::min((int32_t)0xFFFF, std::max((int32_t)0, (centerPos.x + minRangeX + minoffset))), y1 = std::min((int32_t)0xFFFF, std::max((int32_t)0, (centerPos.y + minRangeY + minoffset))), x2 = std::min((int32_t)0xFFFF, std::max((int32_t)0, (centerPos.x + maxRangeX + maxoffset))), y2 = std::min((int32_t)0xFFFF, std::max((int32_t)0, (centerPos.y + maxRangeY + maxoffset))), startx1 = x1 - (x1 % FLOOR_SIZE), starty1 = y1 - (y1 % FLOOR_SIZE), endx2 = x2 - (x2 % FLOOR_SIZE), endy2 = y2 - (y2 % FLOOR_SIZE); QTreeLeafNode* startLeaf = getLeaf(startx1, starty1); QTreeLeafNode* leafS = startLeaf; QTreeLeafNode* leafE; for(int32_t ny = starty1; ny <= endy2; ny += FLOOR_SIZE) { leafE = leafS; for(int32_t nx = startx1; nx <= endx2; nx += FLOOR_SIZE) { if(leafE) { CreatureVector& nodeList = leafE->creatureList; CreatureVector::const_iterator it = nodeList.begin(); if(it != nodeList.end()) { do { Creature* creature = (*it); const Position& pos = creature->getPosition(); int32_t offsetZ = centerPos.z - pos.z; if(pos.z < minRangeZ || pos.z > maxRangeZ) continue; if(pos.y < (centerPos.y + minRangeY + offsetZ) || pos.y > (centerPos.y + maxRangeY + offsetZ)) continue; if(pos.x < (centerPos.x + minRangeX + offsetZ) || pos.x > (centerPos.x + maxRangeX + offsetZ)) continue; if(!checkForDuplicate || std::find(list.begin(), list.end(), creature) == list.end()) list.push_back(creature); } while(++it != nodeList.end()); } leafE = leafE->stepEast(); } else leafE = getLeaf(nx + FLOOR_SIZE, ny); } if(leafS) leafS = leafS->stepSouth(); else leafS = getLeaf(startx1, ny + FLOOR_SIZE); } } void Map::getSpectators(SpectatorVec& list, const Position& centerPos, bool checkforduplicate /*= false*/, bool multifloor /*= false*/, int32_t minRangeX /*= 0*/, int32_t maxRangeX /*= 0*/, int32_t minRangeY /*= 0*/, int32_t maxRangeY /*= 0*/) { if(centerPos.z >= MAP_MAX_LAYERS) return; bool foundCache = false, cacheResult = false; if(!minRangeX && !maxRangeX && !minRangeY && !maxRangeY && multifloor && !checkforduplicate) { SpectatorCache::iterator it = spectatorCache.find(centerPos); if(it != spectatorCache.end()) { list = *it->second; foundCache = true; } else cacheResult = true; } if(!foundCache) { minRangeX = (!minRangeX ? -maxViewportX : -minRangeX); maxRangeX = (!maxRangeX ? maxViewportX : maxRangeX); minRangeY = (!minRangeY ? -maxViewportY : -minRangeY); maxRangeY = (!maxRangeY ? maxViewportY : maxRangeY); int32_t minRangeZ, maxRangeZ; if(multifloor) { if(centerPos.z > 7) { //underground, 8->15 minRangeZ = std::max(centerPos.z - 2, 0); maxRangeZ = std::min(centerPos.z + 2, MAP_MAX_LAYERS - 1); } //above ground else if(centerPos.z == 6) { minRangeZ = 0; maxRangeZ = 8; } else if(centerPos.z == 7) { minRangeZ = 0; maxRangeZ = 9; } else { minRangeZ = 0; maxRangeZ = 7; } } else { minRangeZ = centerPos.z; maxRangeZ = centerPos.z; } getSpectatorsInternal(list, centerPos, true, minRangeX, maxRangeX, minRangeY, maxRangeY, minRangeZ, maxRangeZ); if(cacheResult) spectatorCache[centerPos].reset(new SpectatorVec(list)); } } const SpectatorVec& Map::getSpectators(const Position& centerPos) { if(centerPos.z >= MAP_MAX_LAYERS) { boost::shared_ptr<SpectatorVec> p(new SpectatorVec()); SpectatorVec& list = *p; return list; } SpectatorCache::iterator it = spectatorCache.find(centerPos); if(it != spectatorCache.end()) return *it->second; boost::shared_ptr<SpectatorVec> p(new SpectatorVec()); spectatorCache[centerPos] = p; SpectatorVec& list = *p; int32_t minRangeX = -maxViewportX, maxRangeX = maxViewportX, minRangeY = -maxViewportY, maxRangeY = maxViewportY, minRangeZ, maxRangeZ; if(centerPos.z > 7) { //underground, 8->15 minRangeZ = std::max(centerPos.z - 2, 0); maxRangeZ = std::min(centerPos.z + 2, MAP_MAX_LAYERS - 1); } //above ground else if(centerPos.z == 6) { minRangeZ = 0; maxRangeZ = 8; } else if(centerPos.z == 7) { minRangeZ = 0; maxRangeZ = 9; } else { minRangeZ = 0; maxRangeZ = 7; } getSpectatorsInternal(list, centerPos, false, minRangeX, maxRangeX, minRangeY, maxRangeY, minRangeZ, maxRangeZ); return list; } bool Map::canThrowObjectTo(const Position& fromPos, const Position& toPos, bool checkLineOfSight /*= true*/, int32_t rangex /*= Map::maxClientViewportX*/, int32_t rangey /*= Map::maxClientViewportY*/) { //z checks //underground 8->15 //ground level and above 7->0 if((fromPos.z >= 8 && toPos.z < 8) || (toPos.z >= 8 && fromPos.z < 8) || fromPos.z - fromPos.z > 2) return false; int32_t deltax = std::abs(fromPos.x - toPos.x), deltay = std::abs( fromPos.y - toPos.y), deltaz = std::abs(fromPos.z - toPos.z); if(deltax - deltaz > rangex || deltay - deltaz > rangey) return false; if(!checkLineOfSight) return true; return isSightClear(fromPos, toPos, false); } bool Map::checkSightLine(const Position& fromPos, const Position& toPos) const { Position start = fromPos; Position end = toPos; int32_t x, y, z, dx = std::abs(start.x - end.x), dy = std::abs(start.y - end.y), dz = std::abs(start.z - end.z), sx, sy, sz, ey, ez, max = dx, dir = 0; if(dy > max) { max = dy; dir = 1; } if(dz > max) { max = dz; dir = 2; } switch(dir) { case 1: //x -> y //y -> x //z -> z std::swap(start.x, start.y); std::swap(end.x, end.y); std::swap(dx, dy); break; case 2: //x -> z //y -> y //z -> x std::swap(start.x, start.z); std::swap(end.x, end.z); std::swap(dx, dz); break; default: //x -> x //y -> y //z -> z break; } sx = ((start.x < end.x) ? 1 : -1); sy = ((start.y < end.y) ? 1 : -1); sz = ((start.z < end.z) ? 1 : -1); ey = ez = 0; x = start.x; y = start.y; z = start.z; int32_t lastrx = 0, lastry = 0, lastrz = 0; for(; x != end.x + sx; x += sx) { int32_t rx, ry, rz; switch(dir) { case 1: rx = y; ry = x; rz = z; break; case 2: rx = z; ry = y; rz = x; break; default: rx = x; ry = y; rz = z; break; } if(!lastrx && !lastry && !lastrz) { lastrx = rx; lastry = ry; lastrz = rz; } if(lastrz != rz || ((toPos.x != rx || toPos.y != ry || toPos.z != rz) && (fromPos.x != rx || fromPos.y != ry || fromPos.z != rz))) { if(lastrz != rz && const_cast<Map*>(this)->getTile(lastrx, lastry, std::min(lastrz, rz))) return false; lastrx = rx; lastry = ry; lastrz = rz; const Tile* tile = const_cast<Map*>(this)->getTile(rx, ry, rz); if(tile && tile->hasProperty(BLOCKPROJECTILE)) return false; } ey += dy; ez += dz; if(2 * ey >= dx) { y += sy; ey -= dx; } if(2 * ez >= dx) { z += sz; ez -= dx; } } return true; } bool Map::isSightClear(const Position& fromPos, const Position& toPos, bool floorCheck) const { if(floorCheck && fromPos.z != toPos.z) return false; // Cast two converging rays and see if either yields a result. return checkSightLine(fromPos, toPos) || checkSightLine(toPos, fromPos); } const Tile* Map::canWalkTo(const Creature* creature, const Position& pos) { switch(creature->getWalkCache(pos)) { case 0: return NULL; case 1: return getTile(pos); default: break; } //used for none-cached tiles Tile* tile = getTile(pos); if(creature->getTile() != tile && (!tile || tile->__queryAdd(0, creature, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) != RET_NOERROR)) return NULL; return tile; } bool Map::getPathTo(const Creature* creature, const Position& destPos, std::list<Direction>& listDir, int32_t maxSearchDist /*= -1*/) { if(!canWalkTo(creature, destPos)) return false; Position startPos = destPos; Position endPos = creature->getPosition(); listDir.clear(); if(startPos.z != endPos.z) return false; AStarNodes nodes; AStarNode* startNode = nodes.createOpenNode(); startNode->x = startPos.x; startNode->y = startPos.y; startNode->g = 0; startNode->h = nodes.getEstimatedDistance(startPos.x, startPos.y, endPos.x, endPos.y); startNode->f = startNode->g + startNode->h; startNode->parent = NULL; Position pos; pos.z = startPos.z; static int32_t neighbourOrderList[8][2] = { {-1, 0}, {0, 1}, {1, 0}, {0, -1}, //diagonal {-1, -1}, {1, -1}, {1, 1}, {-1, 1}, }; AStarNode* found = NULL; AStarNode* n = NULL; const Tile* tile = NULL; while(maxSearchDist != -1 || nodes.countClosedNodes() < 100) { if(!(n = nodes.getBestNode())) { listDir.clear(); return false; //no path found } if(n->x == endPos.x && n->y == endPos.y) { found = n; break; } for(uint8_t i = 0; i < 8; ++i) { pos.x = n->x + neighbourOrderList[i][0]; pos.y = n->y + neighbourOrderList[i][1]; bool outOfRange = false; if(maxSearchDist != -1 && (std::abs(endPos.x - pos.x) > maxSearchDist || std::abs(endPos.y - pos.y) > maxSearchDist)) outOfRange = true; if(!outOfRange && (tile = canWalkTo(creature, pos))) { //The cost (g) for this neighbour int32_t cost = nodes.getMapWalkCost(creature, n, tile, pos), extraCost = nodes.getTileWalkCost(creature, tile), newg = n->g + cost + extraCost; //Check if the node is already in the closed/open list //If it exists and the nodes already on them has a lower cost (g) then we can ignore this neighbour node AStarNode* neighbourNode = nodes.getNodeInList(pos.x, pos.y); if(neighbourNode) { if(neighbourNode->g <= newg) //The node on the closed/open list is cheaper than this one continue; nodes.openNode(neighbourNode); } else if(!(neighbourNode = nodes.createOpenNode())) //Does not exist in the open/closed list, create a new node { //seems we ran out of nodes listDir.clear(); return false; } //This node is the best node so far with this state neighbourNode->x = pos.x; neighbourNode->y = pos.y; neighbourNode->g = newg; neighbourNode->h = nodes.getEstimatedDistance(neighbourNode->x, neighbourNode->y, endPos.x, endPos.y); neighbourNode->f = neighbourNode->g + neighbourNode->h; neighbourNode->parent = n; } } nodes.closeNode(n); } int32_t prevx = endPos.x, prevy = endPos.y, dx, dy; while(found) { pos.x = found->x; pos.y = found->y; dx = pos.x - prevx; dy = pos.y - prevy; prevx = pos.x; prevy = pos.y; found = found->parent; if(dx == -1 && dy == -1) listDir.push_back(NORTHWEST); else if(dx == 1 && dy == -1) listDir.push_back(NORTHEAST); else if(dx == -1 && dy == 1) listDir.push_back(SOUTHWEST); else if(dx == 1 && dy == 1) listDir.push_back(SOUTHEAST); else if(dx == -1) listDir.push_back(WEST); else if(dx == 1) listDir.push_back(EAST); else if(dy == -1) listDir.push_back(NORTH); else if(dy == 1) listDir.push_back(SOUTH); } return !listDir.empty(); } bool Map::getPathMatching(const Creature* creature, std::list<Direction>& dirList, const FrozenPathingConditionCall& pathCondition, const FindPathParams& fpp) { Position startPos = creature->getPosition(); Position endPos; AStarNodes nodes; AStarNode* startNode = nodes.createOpenNode(); startNode->x = startPos.x; startNode->y = startPos.y; startNode->f = 0; startNode->parent = NULL; dirList.clear(); int32_t bestMatch = 0; Position pos; pos.z = startPos.z; static int32_t neighbourOrderList[8][2] = { {-1, 0}, {0, 1}, {1, 0}, {0, -1}, //diagonal {-1, -1}, {1, -1}, {1, 1}, {-1, 1}, }; AStarNode* found = NULL; AStarNode* n = NULL; const Tile* tile = NULL; while(fpp.maxSearchDist != -1 || nodes.countClosedNodes() < 100) { if(!(n = nodes.getBestNode())) { if(found) //not quite what we want, but we found something break; dirList.clear(); return false; //no path found } if(pathCondition(startPos, Position(n->x, n->y, startPos.z), fpp, bestMatch)) { found = n; endPos = Position(n->x, n->y, startPos.z); if(!bestMatch) break; } int32_t dirCount = (fpp.allowDiagonal ? 8 : 4); for(int32_t i = 0; i < dirCount; ++i) { pos.x = n->x + neighbourOrderList[i][0]; pos.y = n->y + neighbourOrderList[i][1]; bool inRange = true; if(fpp.maxSearchDist != -1 && (std::abs(startPos.x - pos.x) > fpp.maxSearchDist || std::abs(startPos.y - pos.y) > fpp.maxSearchDist)) inRange = false; if(fpp.keepDistance) { if(!pathCondition.isInRange(startPos, pos, fpp)) inRange = false; } if(inRange && (tile = canWalkTo(creature, pos))) { //The cost (g) for this neighbour int32_t cost = nodes.getMapWalkCost(creature, n, tile, pos), extraCost = nodes.getTileWalkCost(creature, tile), newf = n->f + cost + extraCost; //Check if the node is already in the closed/open list //If it exists and the nodes already on them has a lower cost (g) then we can ignore this neighbour node AStarNode* neighbourNode = nodes.getNodeInList(pos.x, pos.y); if(neighbourNode) { if(neighbourNode->f <= newf) //The node on the closed/open list is cheaper than this one continue; nodes.openNode(neighbourNode); } else if(!(neighbourNode = nodes.createOpenNode())) //Does not exist in the open/closed list, create a new node { if(found) //not quite what we want, but we found something break; //seems we ran out of nodes dirList.clear(); return false; } //This node is the best node so far with this state neighbourNode->x = pos.x; neighbourNode->y = pos.y; neighbourNode->parent = n; neighbourNode->f = newf; } } nodes.closeNode(n); } if(!found) return false; int32_t prevx = endPos.x, prevy = endPos.y, dx, dy; found = found->parent; while(found) { pos.x = found->x; pos.y = found->y; dx = pos.x - prevx; dy = pos.y - prevy; prevx = pos.x; prevy = pos.y; found = found->parent; if(dx == 1 && dy == 1) dirList.push_front(NORTHWEST); else if(dx == -1 && dy == 1) dirList.push_front(NORTHEAST); else if(dx == 1 && dy == -1) dirList.push_front(SOUTHWEST); else if(dx == -1 && dy == -1) dirList.push_front(SOUTHEAST); else if(dx == 1) dirList.push_front(WEST); else if(dx == -1) dirList.push_front(EAST); else if(dy == 1) dirList.push_front(NORTH); else if(dy == -1) dirList.push_front(SOUTH); } return true; } //*********** AStarNodes ************* AStarNodes::AStarNodes() { curNode = 0; openNodes.reset(); } AStarNode* AStarNodes::createOpenNode() { if(curNode >= MAX_NODES) return NULL; uint32_t retNode = curNode; curNode++; openNodes[retNode] = 1; return &nodes[retNode]; } AStarNode* AStarNodes::getBestNode() { if(!curNode) return NULL; int32_t bestNodeF = 100000; uint32_t bestNode = 0; bool found = false; for(uint32_t i = 0; i < curNode; i++) { if(nodes[i].f < bestNodeF && openNodes[i] == 1) { found = true; bestNodeF = nodes[i].f; bestNode = i; } } if(found) return &nodes[bestNode]; return NULL; } void AStarNodes::closeNode(AStarNode* node) { uint32_t pos = GET_NODE_INDEX(node); if(pos < MAX_NODES) { openNodes[pos] = 0; return; } assert(pos >= MAX_NODES); std::cout << "AStarNodes. trying to close node out of range" << std::endl; return; } void AStarNodes::openNode(AStarNode* node) { uint32_t pos = GET_NODE_INDEX(node); if(pos < MAX_NODES) { openNodes[pos] = 1; return; } assert(pos >= MAX_NODES); std::cout << "AStarNodes. trying to open node out of range" << std::endl; return; } uint32_t AStarNodes::countClosedNodes() { uint32_t counter = 0; for(uint32_t i = 0; i < curNode; i++) { if(!openNodes[i]) counter++; } return counter; } uint32_t AStarNodes::countOpenNodes() { uint32_t counter = 0; for(uint32_t i = 0; i < curNode; i++) { if(openNodes[i] == 1) counter++; } return counter; } bool AStarNodes::isInList(uint16_t x, uint16_t y) { for(uint32_t i = 0; i < curNode; i++) { if(nodes[i].x == x && nodes[i].y == y) return true; } return false; } AStarNode* AStarNodes::getNodeInList(uint16_t x, uint16_t y) { for(uint32_t i = 0; i < curNode; i++) { if(nodes[i].x == x && nodes[i].y == y) return &nodes[i]; } return NULL; } int32_t AStarNodes::getMapWalkCost(const Creature* creature, AStarNode* node, const Tile* neighbourTile, const Position& neighbourPos) { if(std::abs(node->x - neighbourPos.x) == std::abs(node->y - neighbourPos.y)) //diagonal movement extra cost return MAP_DIAGONALWALKCOST; return MAP_NORMALWALKCOST; } int32_t AStarNodes::getTileWalkCost(const Creature* creature, const Tile* tile) { int32_t cost = 0; if(tile->getTopVisibleCreature(creature)) //destroy creature cost cost += MAP_NORMALWALKCOST * 3; if(const MagicField* field = tile->getFieldItem()) { if(!creature->isImmune(field->getCombatType())) cost += MAP_NORMALWALKCOST * 3; } return cost; } int32_t AStarNodes::getEstimatedDistance(uint16_t x, uint16_t y, uint16_t xGoal, uint16_t yGoal) { int32_t diagonal = std::min(std::abs(x - xGoal), std::abs(y - yGoal)); return (MAP_DIAGONALWALKCOST * diagonal) + (MAP_NORMALWALKCOST * ((std::abs( x - xGoal) + std::abs(y - yGoal)) - (2 * diagonal))); } //*********** Floor constructor ************** Floor::Floor() { for(int32_t i = 0; i < FLOOR_SIZE; ++i) { for(int32_t j = 0; j < FLOOR_SIZE; ++j) tiles[i][j] = 0; } } //**************** QTreeNode ********************** QTreeNode::QTreeNode() { m_isLeaf = false; for(int32_t i = 0; i < 4; ++i) m_child[i] = NULL; } QTreeNode::~QTreeNode() { for(int32_t i = 0; i < 4; ++i) delete m_child[i]; } QTreeLeafNode* QTreeNode::getLeaf(uint16_t x, uint16_t y) { if(isLeaf()) return static_cast<QTreeLeafNode*>(this); uint32_t index = ((x & 0x8000) >> 15) | ((y & 0x8000) >> 14); if(m_child[index]) return m_child[index]->getLeaf(x * 2, y * 2); return NULL; } QTreeLeafNode* QTreeNode::getLeafStatic(QTreeNode* root, uint16_t x, uint16_t y) { QTreeNode* currentNode = root; uint32_t currentX = x, currentY = y; while(currentNode) { if(currentNode->isLeaf()) return static_cast<QTreeLeafNode*>(currentNode); uint32_t index = ((currentX & 0x8000) >> 15) | ((currentY & 0x8000) >> 14); if(!currentNode->m_child[index]) return NULL; currentNode = currentNode->m_child[index]; currentX = currentX * 2; currentY = currentY * 2; } return NULL; } QTreeLeafNode* QTreeNode::createLeaf(uint16_t x, uint16_t y, uint16_t level) { if(!isLeaf()) { uint32_t index = ((x & 0x8000) >> 15) | ((y & 0x8000) >> 14); if(!m_child[index]) { if(level != FLOOR_BITS) m_child[index] = new QTreeNode(); else { m_child[index] = new QTreeLeafNode(); QTreeLeafNode::newLeaf = true; } } return m_child[index]->createLeaf(x * 2, y * 2, level - 1); } return static_cast<QTreeLeafNode*>(this); } //************ LeafNode ************************ bool QTreeLeafNode::newLeaf = false; QTreeLeafNode::QTreeLeafNode() { for(int32_t i = 0; i < MAP_MAX_LAYERS; ++i) m_array[i] = NULL; m_isLeaf = true; m_leafS = NULL; m_leafE = NULL; } QTreeLeafNode::~QTreeLeafNode() { for(int32_t i = 0; i < MAP_MAX_LAYERS; ++i) delete m_array[i]; } Floor* QTreeLeafNode::createFloor(uint16_t z) { if(!m_array[z]) m_array[z] = new Floor(); return m_array[z]; } Para o server nao verificar a versao do mapa,e eu poder entrar no server,usando mapa de uma versao mais antiga,por exemplo meu serv é 8.6,queria usar o mapa de 8.0. Ta eu compilei deu tudo certin,so que quando vou entrar no server,dis que a posição esta íncorreta.Nao da nenhum erro no distro,nao sei oque pode ser. Notem,que eu botei o */ e /* para nao verificar a versao do mapa.Pode ser que esteje no local errado.
  2. vlw funciono so que agr esta dando erro no items.otbm,sendo que eu baixei otro server 8.6 botei la e mesmo assim o erro persiste.
  3. Bom,este topico tem muita utilidade pois muitos membros ,sempre tem duvida de que webserver escolher. E fes muito bem em por o xampp 1.7.3 na lista ^^
  4. Fala galerinha,sempre tem que dar um erro comigo.Eu estava com o erro na hora de compilar mais ja consegui so que agora quando vou abri ele fica assim. Sendo que esta tudo certo no config.lua Eu queria saber,se teria como compilar por console,que dai da pra dar reload e talz.
  5. Tente usar outro server,este pode estar com algum arquivo bugado.
  6. accountManager = "no" namelockManager = "yes" newPlayerChooseVoc = "yes" newPlayerSpawnPosX = 155 newPlayerSpawnPosY = 52 newPlayerSpawnPosZ = 7 newPlayerTownId = 2 newPlayerLevel = 8 newPlayerMagicLevel = 0 generateAccountNumber = "no" Esses "no" e "yes",funcionam em lua assim? Tente trocar: no - false yes - true Assim,deverá funcionar.
  7. Não adianta,voce arrumar no config.lua . Depois que voce criou um char,isso nao vai mudar em nada.Então para arrumar voce precisa do SQL Studio,voce abre sua database,entra na tabela players,procure seu char e edita posição.
  8. Amigo,wodbo.com era do Jacolos,Crash e Hajbos. Quem são eles? Eles sao os criadores de dbztibia,eles tiverem a ideia de criar o famoso wodbo (World of Dragon Ball Online),o problema é que nesse mundo de wodbo,os paises tem rivalidade,os chilenos nao gostam dos brasileiros.Poloneses que são onde esses 3 especialistas vivem,tambem nao gostam dos brasileiros,bom pelo menos antigamente.Agora as coisas estão mudando e os paises,tao se convivendo junto. Por isso os criadores do wodbo.com,tinham as sources,e só para avisar quando você compila uma source é impossivel descompilar-la.Os criadores do wodbo.com(J&C&H) ,compilaram a source em GUI.Por isso abre como o CMD.Eu nunca tentei,mas eu estava até pensando em criar um 8.0,sem esses bugs que tem nos wodbo hoje em dia.Eu iria criar um 8.0,mas sem o bug do level 631.Bom mas isso nao vem ao caso talves eu crie talves nao. Então isso so escrevi para lhe explicar,que o que voce pode fazer é deletar as vocações e refaze-las,por script. Espero ter ajudado.. Obrigado,Mozark001.
  9. Bom dia,amigo. Bom em primeiro caso,eu achei este video que provavelmente irá servir como ajuda a você então decidi colocar aqui,so seguir ele abaixo,para nao precisar ir ate o youtube e carregar e talz ....Bom ele é para criar um server de tibia,mas é quase mesma coisa,voce vai seguindo o tutorial passo -a passo. Espero ter ajudado...
  10. Procure o script em seu server,abra-o com bloco de notas e veja o ID do storage.
  11. Bom,boa noite XTibia,estou com uma duvida,quero montar um servidor inovador,de wodbo 9.6,so que eu queria saber como faço para mudar a versao dos arquivos .dat e .spr de 8.54,para 9.6. Quem puder ajudar,valeu ai.
  12. mais eu nao tenho seu msn ='( queria te ver =/ Gato, nao sei com qntos paus se faz uma canoa... ...mais seu pai com apenas 1 fez um avião! Eu ouvi isso na minha escola 3 mes atras kkk
  13. Boa noite amigo,eu hospedei o meu Dat Editor,aqui nao pego virus nem nada. http://speedy.sh/hus56/Dat-Editor.rar
  14. Bom,primeiramente. Boa noite,amigo.Gostaria de ir explicando uma coisa extremamente,importante,voce nao irá ser scripter da noite pro dia,entao recomendo voce a ter amigo,ou companheiro para lhe ajudar,nao fique so lendo as aulas,treine as funçoes também.A sessão abaixo tem varios tutoriais interessantes,basta dar uma olhada. Tutoriais de Scripting Espero ter ajudado...
  15. Olá amigo,bom primeiramente,baixe esta versao dos arquivos. xampp 1.7.3 Gesior 10.1.6 Concerteza nao terá mais erros.Eu uso esses documentos e aprovo. Espero ter ajudado...
  16. Fala galerinha do Ékz,estou mais uma ves postando um tutorial,desta ves como adicionar a pagina house.php no GesiorACC para servers 0.3+. Começando: Vá na pasta xampp/htdocs Procure o houses.php " caso não tenha abra o bloco de notas copie e cole o codigo e no nome coloque houses.php, salve dentro da pasta htdocs" Apague tudo e ponha isso: <?PHP $main_content .= '<form method="post" action=""><table>'; if(count($config['site']['worlds']) > 1) { if(isset($_POST['world']) and is_numeric($_POST['world'])) { $wid = (int) $_POST['world']; $wid = '<option value='.$wid.'>'.$config['site']['worlds'][$wid].'</option>'; } $select_w .= '<tr><td>Select World:</td><td><select name="world" onchange="submit()">'.$wid.''; $i=1; foreach($config['site']['worlds'] as $id => $world_n) { if($_POST['world'] != $id) { $worlds[$i] .= '<option value="'.$id.'">'.$world_n.'</option>'; } if($id == (int) $_POST['world']) { $world_id = $id; $world_name = $world_n; } $i++; } $main_content .= ''.$select_w.''; for($i=0;$i <= count($config['site']['worlds']); $i++) { $main_content .= ''.$worlds[$i].''; } $main_content .= '</td></tr></select>'; } if(!isset($world_id)) { $world_id = 0; $world_name = $config['server']['serverName']; } if(count($towns_list) > 1) { if(isset($_POST['town']) and is_numeric($_POST['town'])) { $pid = (int) $_POST['town']; $pid = '<option value='.$pid.'>'.$towns_list[$world_id][$pid].'</option>'; } else { $pid = '<option value="all">[ALL]</option>'; $all=true; } $select .= '<tr><td>Select City:</td><td><select name="town" onchange="submit()">'.$pid.''; $i=1; foreach($towns_list[$world_id] as $id => $town_n) { if($_POST['town'] != $id) { $towns[$i] .= '<option value="'.$id.'">'.$town_n.'</option>'; } if($id == (int) $_POST['town']) { $town_id = $id; $town_name = $town_n; } $i++; } $main_content .= ''.$select.''; for($i=1;$i <= count($towns_list[$world_id]); $i++) { $main_content .= ''.$towns[$i].''; } if(!$all) $main_content .= '<option value="all">[ALL]</option>'; $main_content .= '</td></tr></select>'; } if(isset($town_id)) { $a_status = array(1 => "Empty", "Rented", "[ALL]"); if(isset($_POST['status']) and is_numeric($_POST['status'])) { $sid = (int) $_POST['status']; $sid = '<option value='.$sid.'>'.$a_status[$sid].'</option>'; if($_POST['status'] == 1) $s[1] = true; elseif($_POST['status'] == 2) $s[2] = true; elseif($_POST['status'] == 3) $s[3] = true; } $main_content .= '<tr><td>Select by status:</td><td><select name="status" onchange="submit()">'.$sid.''; if(!$s[3]) $main_content .= '<option value="3">[ALL]</opyion>'; if(!$s[2]) $main_content .= '<option value="2">Rented</option>'; if(!$s[1]) $main_content .= '<option value="1">Empty</option>'; $main_content .= '</td></tr></select>'; } $main_content .= '</table></form>'; if(isset($_POST['status'])) { if($_POST['status'] == 1) $stat = "and `owner` = ''"; elseif($_POST['status'] == 2) $stat = "and `owner` > 0"; } if(!isset($town_id)) { $houses_info = $SQL->query("SELECT * FROM `houses` WHERE `world_id` = ".$world_id." ORDER BY `town` , `name`"); $towns_all = true; } $main_content .= '<h2>Houses on '.$config['site']['worlds'][(int) $_GET['world']].'</h2>'; $main_content .= '<table><tr bgcolor="'.$config['site']['vdarkborder'].'"><td><font color="white"><b>Address</b></font></td><td><font color="white"><b>Size</b></font></td><td><font color="white"><b>Price</b></font></td><td><font color="white"><b>City</b></font></td><td><font color="white"><b>Status</b></font></td></tr>'; $number_of_rows = 1; if(!$towns_all) $houses_info = $SQL->query("SELECT * FROM `houses` WHERE `world_id` = ".$world_id." and `town` = ".$town_id." ".$stat." ORDER BY `name`"); $players_info = $SQL->query("SELECT `houses`.`id` AS `houseid` , `players`.`name` AS `ownername` , `accounts`.`premdays` AS `premdays` , `accounts`.`lastday` AS `lastlogin` FROM `houses` , `players` , `accounts` WHERE `players`.`id` = `houses`.`owner` AND `accounts`.`id` = `players`.`account_id`"); $players = array(); foreach($players_info->fetchAll() as $player) $players[$player['houseid']] = array('name' => $player['ownername'], 'days' => $player['premdays'], 'last' => $player['lastlogin']); foreach($houses_info->fetchAll() as $house) { $owner = $players[$house['id']]; if(is_int($number_of_rows / 2)) { $bgcolor = $config['site']['darkborder']; } else { $bgcolor = $config['site']['lightborder']; } $number_of_rows++; $main_content .= '<tr bgcolor="'.$bgcolor.'"><td>'.$house['name'].'</td><td align="right" width="35">'.$house['size'].'</td><td align="right" width="65">'.($house['price'] / 1000).'k gp</td><td>'.$towns_list[(int) $house['world_id']][(int) $house['town']].'</td><td>'; if(!empty($owner['name'])) { if($owner['deleted'] > 0) $status='<font color=red><b>[DELETED]</b></font>'; if(isPremium($owner['days'], $owner['last'])) { $main_content .= 'Rented by <a href="?subtopic=characters&name='.urlencode($owner['name']).'">'.$owner['name'].'</a>'.$status.''; } else { $main_content .= 'Rented by <a href="?subtopic=characters&name='.urlencode($owner['name']).'">'.$owner['name'].'</a>'.$status.' (FACC)'; } } else { $main_content .= 'Empty'; } $main_content .= '</td></tr>'; } $main_content .= '</TABLE>'; ?> Vá em xampp/htdocs e abra o index.php e adicione case "houses"; $topic = "houses"; $subtopic = "houses"; include("houses.php"); break; Vá em xampp/htdocs/layout/"pasta do seu layout" Abra o layout.php aperte control+F e procure por guild em seguida adicione o: <li><a href="?subtopic=houses"> » Houses</a></li> Créditos: Mozark001 Paulinho
  17. Amigo,tente expressar mais sua energia em tibia,pois aqui é uma comunidade de tibia,e nao de jogos derivados.Mas está bom sua entrada parabéns.
  18. Bom,pessoal vou encinar agora,alguns comandos basicos porem muito uteis,no seu phpmyadmin.Voce pode estar com alguma duvida,de como colocar,entao algum desses pode ser a sua solução. Não sabe onde adicionar esses comandos? Muito simples abra seu phpmyadmin,e entra na database de seu servidor.Logo após clique na aba SQL,la encima.E pronto vai usando os codigos ali. -------------------------------------------------------------------------------------- Lista: Remover Premium ACC de todos. Não funciona com VIP System . UPDATE account SET premdays=0; -------------------------------------------------------------------------------------- Dar 7 Dias de premium para todos os players da acc.. Não funciona com VIP System. UPDATE accounts SET premdays = premdays + 7 -------------------------------------------------------------------------------------- Colocar todos os players em posição definida UPDATE players SET posx = X, posy = Y, posz = Z; -------------------------------------------------------------------------------------- Colocar todos os players com acesso 1-Player. UPDATE groups SET flags=0,name="Player" WHERE id=1; UPDATE players SET group_id=1; DELETE FROM groups WHERE id<>1; -------------------------------------------------------------------------------------- Criar Account Manager. (Original em forgottenserver.sql) INSERT INTO `players` VALUES (1, 'Account Manager', 1, 1, 1, 0, 150, 150, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 50, 50, 7, '', 400, 0, 0, 0, 0, 0, 0, 0, '', 0, 0, 0, 0, 10, 10, 10, 0, 0); -------------------------------------------------------------------------------------- Remover Red Skull e frags de todos. UPDATE `players` SET `redskulltime`=0; -------------------------------------------------------------------------------------- Dar Todas as Blesses aos players. UPDATE `players` SET `blessings`=31; -------------------------------------------------------------------------------------- Deletar todos os itens de um único player .Onde 1234 é o ID do player. DELETE FROM `player_depotitems` , `player_items` WHERE `player_id` = '1234' -------------------------------------------------------------------------------------- Agora,vou postar uma query que á solução de um erro em Gesior que é aquele erro que da quando voce loga acc no char e da erro OTS_AccountBans.php Algo assim. [/center] CREATE TABLE `bans` ( `id` INT UNSIGNED NOT NULL auto_increment, `type` TINYINT(1) NOT NULL COMMENT '1 - ip banishment, 2 - namelock, 3 - account banishment, 4 - notation, 5 - deletion', `value` INT UNSIGNED NOT NULL COMMENT 'ip address (integer), player guid or account number', `param` INT UNSIGNED NOT NULL DEFAULT 4294967295 COMMENT 'used only for ip banishment mask (integer)', `active` TINYINT(1) NOT NULL DEFAULT TRUE, `expires` INT NOT NULL, `added` INT UNSIGNED NOT NULL, `admin_id` INT UNSIGNED NOT NULL DEFAULT 0, `comment` TEXT NOT NULL, `reason` INT UNSIGNED NOT NULL DEFAULT 0, `action` INT UNSIGNED NOT NULL DEFAULT 0, `statement` VARCHAR(255) NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `type` (`type`, `value`), KEY `active` (`active`) ) ENGINE = InnoDB; Bom é isso galera,tomara que gostem. Créditos: Mozark001. Matheus. Kimoszin Irei atualizar o topico sempre que eu achar query novas.
  19. Porque nao usa esse Gesior? http://www.4shared.com/rar/0BjGRCeJ/Website_1016.html? Ele funciona em todas versoes de OTServ.
  20. Nao esqueça que tem que liberar as portas 7171 e 7172 tambem.
  21. AlexandreKG

    Xampp

    Download xampp 1.7.3 >> http://clickdownloads.uol.com.br/download/xampp-173.html Tomara que tenha ajudado...
  22. Amigo,eu sei por que da isso,comigo tambem da. Pois isso é problema no Word,verifique se no seu phpmyadmin,do personagem está 0,voce muda para 1. Espero ter ajudado...
  23. Execute isso na sua database: CREATE TABLE `bans` ( `id` INT UNSIGNED NOT NULL auto_increment, `type` TINYINT(1) NOT NULL COMMENT '1 - ip banishment, 2 - namelock, 3 - account banishment, 4 - notation, 5 - deletion', `value` INT UNSIGNED NOT NULL COMMENT 'ip address (integer), player guid or account number', `param` INT UNSIGNED NOT NULL DEFAULT 4294967295 COMMENT 'used only for ip banishment mask (integer)', `active` TINYINT(1) NOT NULL DEFAULT TRUE, `expires` INT NOT NULL, `added` INT UNSIGNED NOT NULL, `admin_id` INT UNSIGNED NOT NULL DEFAULT 0, `comment` TEXT NOT NULL, `reason` INT UNSIGNED NOT NULL DEFAULT 0, `action` INT UNSIGNED NOT NULL DEFAULT 0, `statement` VARCHAR(255) NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `type` (`type`, `value`), KEY `active` (`active`) ) ENGINE = InnoDB;
  24. AlexandreKG

    Site Wodbo

    Olá amigo,se voce quer o template existe um aqui no forum.Só que é para wodbo. http://www.xtibia.com/forum/topic/194916-modernacc-wodbo-template-v1-by-mrcatra/ Espero ter ajudado...
  • Quem Está Navegando   0 membros estão online

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