From 204b846fe695768ad56f8f8c832d6deaa6dc2e1c Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 14:45:05 +0200 Subject: Core/Tools: Implemented mmaps_generator. --- src/tools/CMakeLists.txt | 1 + src/tools/mmap_extractor/CMakeLists.txt | 68 ++ src/tools/mmap_extractor/Info/readme.txt | 66 ++ src/tools/mmap_extractor/IntermediateValues.cpp | 277 ++++++++ src/tools/mmap_extractor/IntermediateValues.h | 53 ++ src/tools/mmap_extractor/MapBuilder.cpp | 894 ++++++++++++++++++++++++ src/tools/mmap_extractor/MapBuilder.h | 129 ++++ src/tools/mmap_extractor/PathCommon.h | 128 ++++ src/tools/mmap_extractor/PathGenerator.cpp | 273 ++++++++ src/tools/mmap_extractor/TerrainBuilder.cpp | 854 ++++++++++++++++++++++ src/tools/mmap_extractor/TerrainBuilder.h | 138 ++++ src/tools/mmap_extractor/VMapExtensions.cpp | 72 ++ 12 files changed, 2953 insertions(+) create mode 100644 src/tools/mmap_extractor/CMakeLists.txt create mode 100644 src/tools/mmap_extractor/Info/readme.txt create mode 100644 src/tools/mmap_extractor/IntermediateValues.cpp create mode 100644 src/tools/mmap_extractor/IntermediateValues.h create mode 100644 src/tools/mmap_extractor/MapBuilder.cpp create mode 100644 src/tools/mmap_extractor/MapBuilder.h create mode 100644 src/tools/mmap_extractor/PathCommon.h create mode 100644 src/tools/mmap_extractor/PathGenerator.cpp create mode 100644 src/tools/mmap_extractor/TerrainBuilder.cpp create mode 100644 src/tools/mmap_extractor/TerrainBuilder.h create mode 100644 src/tools/mmap_extractor/VMapExtensions.cpp (limited to 'src') diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index a956655ffaa..f4c5f695b26 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -11,3 +11,4 @@ add_subdirectory(map_extractor) add_subdirectory(vmap4_assembler) add_subdirectory(vmap4_extractor) +add_subdirectory(mmaps_extractor) diff --git a/src/tools/mmap_extractor/CMakeLists.txt b/src/tools/mmap_extractor/CMakeLists.txt new file mode 100644 index 00000000000..c7c1a954371 --- /dev/null +++ b/src/tools/mmap_extractor/CMakeLists.txt @@ -0,0 +1,68 @@ +# Copyright (C) 2008-2011 Trinity +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +file(GLOB_RECURSE sources *.cpp *.h) + +# definitions +add_definitions(-DNO_CORE_FUNCS) +add_definitions(-DDEBUG) +add_definitions(-DNO_vsnprintf) + +include_directories( + ${CMAKE_BINARY_DIR} + ${ACE_INCLUDE_DIR} + ${MYSQL_INCLUDE_DIR} + ${CMAKE_SOURCE_DIR}/dep/libmpq + ${CMAKE_SOURCE_DIR}/dep/zlib + ${CMAKE_SOURCE_DIR}/dep/bzip2 + ${CMAKE_SOURCE_DIR}/dep/acelite + ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/Database + ${CMAKE_SOURCE_DIR}/src/server/shared/Database/Implementation + ${CMAKE_SOURCE_DIR}/src/server/shared/Threading + ${CMAKE_SOURCE_DIR}/src/server/shared/Logging + ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference + ${CMAKE_SOURCE_DIR}/src/server/game/Maps + ${CMAKE_SOURCE_DIR}/src/server/game/DataStores + ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints + ${CMAKE_SOURCE_DIR}/src/server/game/Grids + ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells + ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous + ${CMAKE_SOURCE_DIR}/src/server/game/Conditions + ${CMAKE_SOURCE_DIR}/src/server/collision + ${CMAKE_SOURCE_DIR}/src/server/collision/Management + ${CMAKE_SOURCE_DIR}/src/server/collision/Maps + ${CMAKE_SOURCE_DIR}/src/server/collision/Models +) + +add_executable(movements_extractor ${sources}) + +target_link_libraries(movements_extractor + ${MYSQL_LIBRARY} + ${ACE_LIBRARY} + ${BZIP2_LIBRARIES} + ${ZLIB_LIBRARIES} + Recast + Detour + collision + g3dlib + shared +) + +if( UNIX ) + install(TARGETS movements_extractor DESTINATION bin) +elseif( WIN32 ) + install(TARGETS movements_extractor DESTINATION "${CMAKE_INSTALL_PREFIX}") +endif() diff --git a/src/tools/mmap_extractor/Info/readme.txt b/src/tools/mmap_extractor/Info/readme.txt new file mode 100644 index 00000000000..8d7c4f9d2e0 --- /dev/null +++ b/src/tools/mmap_extractor/Info/readme.txt @@ -0,0 +1,66 @@ +Generator command line args + +--offMeshInput [file.*] Path to file containing off mesh connections data. + Format must be: (see offmesh_example.txt) + "map_id tile_x,tile_y (start_x start_y start_z) (end_x end_y end_z) size //optional comments" + Single mesh connection per line. + +--silent Make us script friendly. Do not wait for user input + on error or completion. + +--bigBaseUnit [true|false] Generate tile/map using bigger basic unit. + Use this option only if you have unexpected gaps. + + false: use normal metrics (default) + +--maxAngle [#] Max walkable inclination angle + + float between 45 and 90 degrees (default 60) + +--skipLiquid liquid data for maps + + false: include liquid data (default) + +--skipContinents [true|false] continents are maps 0 (Eastern Kingdoms), + 1 (Kalimdor), 530 (Outlands), 571 (Northrend) + + false: build continents (default) + +--skipJunkMaps [true|false] junk maps include some unused + maps, transport maps, and some other + + true: skip junk maps (default) + +--skipBattlegrounds [true|false] does not include PVP arenas + + false: skip battlegrounds (default) + +--debugOutput [true|false] create debugging files for use with RecastDemo + if you are only creating mmaps for use with MaNGOS, + you don't want debugging files + + false: don't create debugging files (default) + +--tile [#,#] Build the specified tile + seperate number with a comma ',' + must specify a map number (see below) + if this option is not used, all tiles are built + + [#] Build only the map specified by # + this command will build the map regardless of --skip* option settings + if you do not specify a map number, builds all maps that pass the filters specified by --skip* options + + +examples: + +movement_extractor +builds maps using the default settings (see above for defaults) + +movement_extractor --skipContinents true +builds the default maps, except continents + +movement_extractor 0 +builds all tiles of map 0 + +movement_extractor 0 --tile 34,46 +builds only tile 34,46 of map 0 (this is the southern face of blackrock mountain) \ No newline at end of file diff --git a/src/tools/mmap_extractor/IntermediateValues.cpp b/src/tools/mmap_extractor/IntermediateValues.cpp new file mode 100644 index 00000000000..9eefb1e65f0 --- /dev/null +++ b/src/tools/mmap_extractor/IntermediateValues.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#include "IntermediateValues.h" + +namespace MMAP +{ + IntermediateValues::~IntermediateValues() + { + rcFreeCompactHeightfield(compactHeightfield); + rcFreeHeightField(heightfield); + rcFreeContourSet(contours); + rcFreePolyMesh(polyMesh); + rcFreePolyMeshDetail(polyMeshDetail); + } + + void IntermediateValues::writeIV(uint32 mapID, uint32 tileX, uint32 tileY) + { + char fileName[255]; + char tileString[25]; + sprintf(tileString, "[%02u,%02u]: ", tileX, tileY); + + printf("%sWriting debug output... \r", tileString); + + string name("meshes/%03u%02i%02i."); + +#define DEBUG_WRITE(fileExtension,data) \ + do { \ + sprintf(fileName, (name + fileExtension).c_str(), mapID, tileY, tileX); \ + FILE* file = fopen(fileName, "wb"); \ + if (!file) \ + { \ + char message[1024]; \ + sprintf(message, "%sFailed to open %s for writing!\n", tileString, fileName); \ + perror(message); \ + } \ + else \ + debugWrite(file, data); \ + if (file) fclose(file); \ + printf("%sWriting debug output... \r", tileString); \ + } while (false) + + if (heightfield) + DEBUG_WRITE("hf", heightfield); + if (compactHeightfield) + DEBUG_WRITE("chf", compactHeightfield); + if (contours) + DEBUG_WRITE("cs", contours); + if (polyMesh) + DEBUG_WRITE("pmesh", polyMesh); + if (polyMeshDetail) + DEBUG_WRITE("dmesh", polyMeshDetail); + +#undef DEBUG_WRITE + } + + void IntermediateValues::debugWrite(FILE* file, const rcHeightfield* mesh) + { + if (!file || !mesh) + return; + + fwrite(&(mesh->cs), sizeof(float), 1, file); + fwrite(&(mesh->ch), sizeof(float), 1, file); + fwrite(&(mesh->width), sizeof(int), 1, file); + fwrite(&(mesh->height), sizeof(int), 1, file); + fwrite(mesh->bmin, sizeof(float), 3, file); + fwrite(mesh->bmax, sizeof(float), 3, file); + + for (int y = 0; y < mesh->height; ++y) + for (int x = 0; x < mesh->width; ++x) + { + rcSpan* span = mesh->spans[x+y*mesh->width]; + + // first, count the number of spans + int spanCount = 0; + while (span) + { + spanCount++; + span = span->next; + } + + // write the span count + fwrite(&spanCount, sizeof(int), 1, file); + + // write the spans + span = mesh->spans[x+y*mesh->width]; + while (span) + { + fwrite(span, sizeof(rcSpan), 1, file); + span = span->next; + } + } + } + + void IntermediateValues::debugWrite(FILE* file, const rcCompactHeightfield* chf) + { + if (!file | !chf) + return; + + fwrite(&(chf->width), sizeof(chf->width), 1, file); + fwrite(&(chf->height), sizeof(chf->height), 1, file); + fwrite(&(chf->spanCount), sizeof(chf->spanCount), 1, file); + + fwrite(&(chf->walkableHeight), sizeof(chf->walkableHeight), 1, file); + fwrite(&(chf->walkableClimb), sizeof(chf->walkableClimb), 1, file); + + fwrite(&(chf->maxDistance), sizeof(chf->maxDistance), 1, file); + fwrite(&(chf->maxRegions), sizeof(chf->maxRegions), 1, file); + + fwrite(chf->bmin, sizeof(chf->bmin), 1, file); + fwrite(chf->bmax, sizeof(chf->bmax), 1, file); + + fwrite(&(chf->cs), sizeof(chf->cs), 1, file); + fwrite(&(chf->ch), sizeof(chf->ch), 1, file); + + int tmp = 0; + if (chf->cells) tmp |= 1; + if (chf->spans) tmp |= 2; + if (chf->dist) tmp |= 4; + if (chf->areas) tmp |= 8; + + fwrite(&tmp, sizeof(tmp), 1, file); + + if (chf->cells) + fwrite(chf->cells, sizeof(rcCompactCell), chf->width*chf->height, file); + if (chf->spans) + fwrite(chf->spans, sizeof(rcCompactSpan), chf->spanCount, file); + if (chf->dist) + fwrite(chf->dist, sizeof(unsigned short), chf->spanCount, file); + if (chf->areas) + fwrite(chf->areas, sizeof(unsigned char), chf->spanCount, file); + } + + void IntermediateValues::debugWrite(FILE* file, const rcContourSet* cs) + { + if (!file || !cs) + return; + + fwrite(&(cs->cs), sizeof(float), 1, file); + fwrite(&(cs->ch), sizeof(float), 1, file); + fwrite(cs->bmin, sizeof(float), 3, file); + fwrite(cs->bmax, sizeof(float), 3, file); + fwrite(&(cs->nconts), sizeof(int), 1, file); + for (int i = 0; i < cs->nconts; ++i) + { + fwrite(&cs->conts[i].area, sizeof(unsigned char), 1, file); + fwrite(&cs->conts[i].reg, sizeof(unsigned short), 1, file); + fwrite(&cs->conts[i].nverts, sizeof(int), 1, file); + fwrite(cs->conts[i].verts, sizeof(int), cs->conts[i].nverts*4, file); + fwrite(&cs->conts[i].nrverts, sizeof(int), 1, file); + fwrite(cs->conts[i].rverts, sizeof(int), cs->conts[i].nrverts*4, file); + } + } + + void IntermediateValues::debugWrite(FILE* file, const rcPolyMesh* mesh) + { + if (!file || !mesh) + return; + + fwrite(&(mesh->cs), sizeof(float), 1, file); + fwrite(&(mesh->ch), sizeof(float), 1, file); + fwrite(&(mesh->nvp), sizeof(int), 1, file); + fwrite(mesh->bmin, sizeof(float), 3, file); + fwrite(mesh->bmax, sizeof(float), 3, file); + fwrite(&(mesh->nverts), sizeof(int), 1, file); + fwrite(mesh->verts, sizeof(unsigned short), mesh->nverts*3, file); + fwrite(&(mesh->npolys), sizeof(int), 1, file); + fwrite(mesh->polys, sizeof(unsigned short), mesh->npolys*mesh->nvp*2, file); + fwrite(mesh->flags, sizeof(unsigned short), mesh->npolys, file); + fwrite(mesh->areas, sizeof(unsigned char), mesh->npolys, file); + fwrite(mesh->regs, sizeof(unsigned short), mesh->npolys, file); + } + + void IntermediateValues::debugWrite(FILE* file, const rcPolyMeshDetail* mesh) + { + if (!file || !mesh) + return; + + fwrite(&(mesh->nverts), sizeof(int), 1, file); + fwrite(mesh->verts, sizeof(float), mesh->nverts*3, file); + fwrite(&(mesh->ntris), sizeof(int), 1, file); + fwrite(mesh->tris, sizeof(char), mesh->ntris*4, file); + fwrite(&(mesh->nmeshes), sizeof(int), 1, file); + fwrite(mesh->meshes, sizeof(int), mesh->nmeshes*4, file); + } + + void IntermediateValues::generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) + { + char objFileName[255]; + sprintf(objFileName, "meshes/map%03u.obj", mapID); + + FILE* objFile = fopen(objFileName, "wb"); + if (!objFile) + { + char message[1024]; + sprintf(message, "Failed to open %s for writing!\n", objFileName); + perror(message); + return; + } + + G3D::Array allVerts; + G3D::Array allTris; + + allTris.append(meshData.liquidTris); + allVerts.append(meshData.liquidVerts); + TerrainBuilder::copyIndices(meshData.solidTris, allTris, allVerts.size() / 3); + allVerts.append(meshData.solidVerts); + + float* verts = allVerts.getCArray(); + int vertCount = allVerts.size() / 3; + int* tris = allTris.getCArray(); + int triCount = allTris.size() / 3; + + for (int i = 0; i < allVerts.size() / 3; i++) + fprintf(objFile, "v %f %f %f\n", verts[i*3], verts[i*3 + 1], verts[i*3 + 2]); + + for (int i = 0; i < allTris.size() / 3; i++) + fprintf(objFile, "f %i %i %i\n", tris[i*3] + 1, tris[i*3 + 1] + 1, tris[i*3 + 2] + 1); + + fclose(objFile); + + + char tileString[25]; + sprintf(tileString, "[%02u,%02u]: ", tileY, tileX); + printf("%sWriting debug output... \r", tileString); + + sprintf(objFileName, "meshes/%03u.map", mapID); + + objFile = fopen(objFileName, "wb"); + if (!objFile) + { + char message[1024]; + sprintf(message, "Failed to open %s for writing!\n", objFileName); + perror(message); + return; + } + + char b = '\0'; + fwrite(&b, sizeof(char), 1, objFile); + fclose(objFile); + + sprintf(objFileName, "meshes/%03u%02u%02u.mesh", mapID, tileY, tileX); + objFile = fopen(objFileName, "wb"); + if (!objFile) + { + char message[1024]; + sprintf(message, "Failed to open %s for writing!\n", objFileName); + perror(message); + return; + } + + fwrite(&vertCount, sizeof(int), 1, objFile); + fwrite(verts, sizeof(float), vertCount*3, objFile); + fflush(objFile); + + fwrite(&triCount, sizeof(int), 1, objFile); + fwrite(tris, sizeof(int), triCount*3, objFile); + fflush(objFile); + + fclose(objFile); + } +} diff --git a/src/tools/mmap_extractor/IntermediateValues.h b/src/tools/mmap_extractor/IntermediateValues.h new file mode 100644 index 00000000000..a267a0f6412 --- /dev/null +++ b/src/tools/mmap_extractor/IntermediateValues.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#ifndef _INTERMEDIATE_VALUES_H +#define _INTERMEDIATE_VALUES_H + +#include "PathCommon.h" +#include "TerrainBuilder.h" +#include "Recast.h" +#include "DetourNavMesh.h" + +namespace MMAP +{ + // this class gathers all debug info holding and output + struct IntermediateValues + { + rcHeightfield* heightfield; + rcCompactHeightfield* compactHeightfield; + rcContourSet* contours; + rcPolyMesh* polyMesh; + rcPolyMeshDetail* polyMeshDetail; + + IntermediateValues() : compactHeightfield(NULL), heightfield(NULL), + contours(NULL), polyMesh(NULL), polyMeshDetail(NULL) {} + ~IntermediateValues(); + + void writeIV(uint32 mapID, uint32 tileX, uint32 tileY); + + void debugWrite(FILE* file, const rcHeightfield* mesh); + void debugWrite(FILE* file, const rcCompactHeightfield* chf); + void debugWrite(FILE* file, const rcContourSet* cs); + void debugWrite(FILE* file, const rcPolyMesh* mesh); + void debugWrite(FILE* file, const rcPolyMeshDetail* mesh); + + void generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); + }; +} +#endif diff --git a/src/tools/mmap_extractor/MapBuilder.cpp b/src/tools/mmap_extractor/MapBuilder.cpp new file mode 100644 index 00000000000..3ca158f0127 --- /dev/null +++ b/src/tools/mmap_extractor/MapBuilder.cpp @@ -0,0 +1,894 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#include "PathCommon.h" +#include "MapBuilder.h" + +#include "MapTree.h" +#include "ModelInstance.h" +#include "LoginDatabase.h" + +#include "DetourNavMeshBuilder.h" +#include "DetourCommon.h" + +// These make the linker happy. +LoginDatabaseWorkerPool LoginDatabase; +#include "DisableMgr.h" +namespace DisableMgr +{ + bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags) + { + return 0; + } +} + +using namespace VMAP; + +namespace MMAP +{ + MapBuilder::MapBuilder(float maxWalkableAngle, bool skipLiquid, + bool skipContinents, bool skipJunkMaps, bool skipBattlegrounds, + bool debugOutput, bool bigBaseUnit, const char* offMeshFilePath) : + m_terrainBuilder(NULL), + m_debugOutput (debugOutput), + m_skipContinents (skipContinents), + m_skipJunkMaps (skipJunkMaps), + m_skipBattlegrounds (skipBattlegrounds), + m_maxWalkableAngle (maxWalkableAngle), + m_bigBaseUnit (bigBaseUnit), + m_rcContext (NULL), + m_offMeshFilePath (offMeshFilePath) + { + m_terrainBuilder = new TerrainBuilder(skipLiquid); + + m_rcContext = new rcContext(false); + + discoverTiles(); + } + + /**************************************************************************/ + MapBuilder::~MapBuilder() + { + for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) + { + (*it).second->clear(); + delete (*it).second; + } + + delete m_terrainBuilder; + delete m_rcContext; + } + + /**************************************************************************/ + void MapBuilder::discoverTiles() + { + vector files; + uint32 mapID, tileX, tileY, tileID, count = 0; + char filter[12]; + + printf("Discovering maps... "); + getDirContents(files, "maps"); + for (uint32 i = 0; i < files.size(); ++i) + { + mapID = uint32(atoi(files[i].substr(0,3).c_str())); + if (m_tiles.find(mapID) == m_tiles.end()) + { + m_tiles.insert(pair*>(mapID, new set)); + count++; + } + } + + files.clear(); + getDirContents(files, "vmaps", "*.vmtree"); + for (uint32 i = 0; i < files.size(); ++i) + { + mapID = uint32(atoi(files[i].substr(0,3).c_str())); + m_tiles.insert(pair*>(mapID, new set)); + count++; + } + printf("found %u.\n", count); + + count = 0; + printf("Discovering tiles... "); + for (TileList::iterator itr = m_tiles.begin(); itr != m_tiles.end(); ++itr) + { + set* tiles = (*itr).second; + mapID = (*itr).first; + + sprintf(filter, "%03u*.vmtile", mapID); + files.clear(); + getDirContents(files, "vmaps", filter); + for (uint32 i = 0; i < files.size(); ++i) + { + tileX = uint32(atoi(files[i].substr(7,2).c_str())); + tileY = uint32(atoi(files[i].substr(4,2).c_str())); + tileID = StaticMapTree::packTileID(tileY, tileX); + + tiles->insert(tileID); + count++; + } + + sprintf(filter, "%03u*", mapID); + files.clear(); + getDirContents(files, "maps", filter); + for (uint32 i = 0; i < files.size(); ++i) + { + tileY = uint32(atoi(files[i].substr(3,2).c_str())); + tileX = uint32(atoi(files[i].substr(5,2).c_str())); + tileID = StaticMapTree::packTileID(tileX, tileY); + + if (tiles->insert(tileID).second) + count++; + } + } + printf("found %u.\n\n", count); + } + + /**************************************************************************/ + set* MapBuilder::getTileList(uint32 mapID) + { + TileList::iterator itr = m_tiles.find(mapID); + if (itr != m_tiles.end()) + return (*itr).second; + + set* tiles = new set(); + m_tiles.insert(pair*>(mapID, tiles)); + return tiles; + } + + /**************************************************************************/ + void MapBuilder::buildAllMaps() + { + for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) + { + uint32 mapID = (*it).first; + if (!shouldSkipMap(mapID)) + buildMap(mapID); + } + } + + /**************************************************************************/ + void MapBuilder::getGridBounds(uint32 mapID, uint32 &minX, uint32 &minY, uint32 &maxX, uint32 &maxY) + { + maxX = INT_MAX; + maxY = INT_MAX; + minX = INT_MIN; + minY = INT_MIN; + + float bmin[3], bmax[3], lmin[3], lmax[3]; + MeshData meshData; + + // make sure we process maps which don't have tiles + // initialize the static tree, which loads WDT models + if (!m_terrainBuilder->loadVMap(mapID, 64, 64, meshData)) + return; + + // get the coord bounds of the model data + if (meshData.solidVerts.size() + meshData.liquidVerts.size() == 0) + return; + + // get the coord bounds of the model data + if (meshData.solidVerts.size() && meshData.liquidVerts.size()) + { + rcCalcBounds(meshData.solidVerts.getCArray(), meshData.solidVerts.size() / 3, bmin, bmax); + rcCalcBounds(meshData.liquidVerts.getCArray(), meshData.liquidVerts.size() / 3, lmin, lmax); + rcVmin(bmin, lmin); + rcVmax(bmax, lmax); + } + else if (meshData.solidVerts.size()) + rcCalcBounds(meshData.solidVerts.getCArray(), meshData.solidVerts.size() / 3, bmin, bmax); + else + rcCalcBounds(meshData.liquidVerts.getCArray(), meshData.liquidVerts.size() / 3, lmin, lmax); + + // convert coord bounds to grid bounds + maxX = 32 - bmin[0] / GRID_SIZE; + maxY = 32 - bmin[2] / GRID_SIZE; + minX = 32 - bmax[0] / GRID_SIZE; + minY = 32 - bmax[2] / GRID_SIZE; + } + + /**************************************************************************/ + void MapBuilder::buildSingleTile(uint32 mapID, uint32 tileX, uint32 tileY) + { + dtNavMesh* navMesh = NULL; + buildNavMesh(mapID, navMesh); + if (!navMesh) + { + printf("Failed creating navmesh! \n"); + return; + } + + buildTile(mapID, tileX, tileY, navMesh); + dtFreeNavMesh(navMesh); + } + + /**************************************************************************/ + void MapBuilder::buildMap(uint32 mapID) + { + printf("Building map %03u:\n", mapID); + + set* tiles = getTileList(mapID); + + // make sure we process maps which don't have tiles + if (!tiles->size()) + { + // convert coord bounds to grid bounds + uint32 minX, minY, maxX, maxY; + getGridBounds(mapID, minX, minY, maxX, maxY); + + // add all tiles within bounds to tile list. + for (uint32 i = minX; i <= maxX; ++i) + for (uint32 j = minY; j <= maxY; ++j) + tiles->insert(StaticMapTree::packTileID(i, j)); + } + + if (!tiles->size()) + return; + + // build navMesh + dtNavMesh* navMesh = NULL; + buildNavMesh(mapID, navMesh); + if (!navMesh) + { + printf("Failed creating navmesh! \n"); + return; + } + + // now start building mmtiles for each tile + printf("We have %u tiles. \n", (unsigned int)tiles->size()); + for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) + { + uint32 tileX, tileY; + + // unpack tile coords + StaticMapTree::unpackTileID((*it), tileX, tileY); + + if (shouldSkipTile(mapID, tileX, tileY)) + continue; + + buildTile(mapID, tileX, tileY, navMesh); + } + + dtFreeNavMesh(navMesh); + + printf("Complete! \n\n"); + } + + /**************************************************************************/ + void MapBuilder::buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh) + { + printf("Building map %03u, tile [%02u,%02u]\n", mapID, tileX, tileY); + + MeshData meshData; + + // get heightmap data + m_terrainBuilder->loadMap(mapID, tileX, tileY, meshData); + + // get model data + m_terrainBuilder->loadVMap(mapID, tileY, tileX, meshData); + + // if there is no data, give up now + if (!meshData.solidVerts.size() && !meshData.liquidVerts.size()) + return; + + // remove unused vertices + TerrainBuilder::cleanVertices(meshData.solidVerts, meshData.solidTris); + TerrainBuilder::cleanVertices(meshData.liquidVerts, meshData.liquidTris); + + // gather all mesh data for final data check, and bounds calculation + G3D::Array allVerts; + allVerts.append(meshData.liquidVerts); + allVerts.append(meshData.solidVerts); + + if (!allVerts.size()) + return; + + // get bounds of current tile + float bmin[3], bmax[3]; + getTileBounds(tileX, tileY, allVerts.getCArray(), allVerts.size() / 3, bmin, bmax); + + m_terrainBuilder->loadOffMeshConnections(mapID, tileX, tileY, meshData, m_offMeshFilePath); + + // build navmesh tile + buildMoveMapTile(mapID, tileX, tileY, meshData, bmin, bmax, navMesh); + } + + /**************************************************************************/ + void MapBuilder::buildNavMesh(uint32 mapID, dtNavMesh* &navMesh) + { + set* tiles = getTileList(mapID); + + // old code for non-statically assigned bitmask sizes: + ///*** calculate number of bits needed to store tiles & polys ***/ + //int tileBits = dtIlog2(dtNextPow2(tiles->size())); + //if (tileBits < 1) tileBits = 1; // need at least one bit! + //int polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits; + + int tileBits = STATIC_TILE_BITS; + int polyBits = STATIC_POLY_BITS; + + int maxTiles = tiles->size(); + int maxPolysPerTile = 1 << polyBits; + + /*** calculate bounds of map ***/ + + uint32 tileXMin = 64, tileYMin = 64, tileXMax = 0, tileYMax = 0, tileX, tileY; + for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) + { + StaticMapTree::unpackTileID((*it), tileX, tileY); + + if (tileX > tileXMax) + tileXMax = tileX; + else if (tileX < tileXMin) + tileXMin = tileX; + + if (tileY > tileYMax) + tileYMax = tileY; + else if (tileY < tileYMin) + tileYMin = tileY; + } + + // use Max because '32 - tileX' is negative for values over 32 + float bmin[3], bmax[3]; + getTileBounds(tileXMax, tileYMax, NULL, 0, bmin, bmax); + + /*** now create the navmesh ***/ + + // navmesh creation params + dtNavMeshParams navMeshParams; + memset(&navMeshParams, 0, sizeof(dtNavMeshParams)); + navMeshParams.tileWidth = GRID_SIZE; + navMeshParams.tileHeight = GRID_SIZE; + rcVcopy(navMeshParams.orig, bmin); + navMeshParams.maxTiles = maxTiles; + navMeshParams.maxPolys = maxPolysPerTile; + + navMesh = dtAllocNavMesh(); + printf("Creating navMesh... \r"); + if (!navMesh->init(&navMeshParams)) + { + printf("Failed creating navmesh! \n"); + return; + } + + char fileName[25]; + sprintf(fileName, "mmaps/%03u.mmap", mapID); + + FILE* file = fopen(fileName, "wb"); + if (!file) + { + dtFreeNavMesh(navMesh); + char message[1024]; + sprintf(message, "Failed to open %s for writing!\n", fileName); + perror(message); + return; + } + + // now that we know navMesh params are valid, we can write them to file + fwrite(&navMeshParams, sizeof(dtNavMeshParams), 1, file); + fclose(file); + } + + /**************************************************************************/ + void MapBuilder::buildMoveMapTile(uint32 mapID, uint32 tileX, uint32 tileY, + MeshData &meshData, float bmin[3], float bmax[3], + dtNavMesh* navMesh) + { + // console output + char tileString[10]; + sprintf(tileString, "[%02i,%02i]: ", tileX, tileY); + printf("%s Building movemap tiles... \r", tileString); + + IntermediateValues iv; + + float* tVerts = meshData.solidVerts.getCArray(); + int tVertCount = meshData.solidVerts.size() / 3; + int* tTris = meshData.solidTris.getCArray(); + int tTriCount = meshData.solidTris.size() / 3; + + float* lVerts = meshData.liquidVerts.getCArray(); + int lVertCount = meshData.liquidVerts.size() / 3; + int* lTris = meshData.liquidTris.getCArray(); + int lTriCount = meshData.liquidTris.size() / 3; + uint8* lTriFlags = meshData.liquidType.getCArray(); + + // these are WORLD UNIT based metrics + // this are basic unit dimentions + // value have to divide GRID_SIZE(533.33333f) ( aka: 0.5333, 0.2666, 0.3333, 0.1333, etc ) + const static float BASE_UNIT_DIM = m_bigBaseUnit ? 0.533333f : 0.266666f; + + // All are in UNIT metrics! + const static int VERTEX_PER_MAP = int(GRID_SIZE/BASE_UNIT_DIM + 0.5f); + const static int VERTEX_PER_TILE = m_bigBaseUnit ? 40 : 80; // must divide VERTEX_PER_MAP + const static int TILES_PER_MAP = VERTEX_PER_MAP/VERTEX_PER_TILE; + + rcConfig config; + memset(&config, 0, sizeof(rcConfig)); + + rcVcopy(config.bmin, bmin); + rcVcopy(config.bmax, bmax); + + config.maxVertsPerPoly = DT_VERTS_PER_POLYGON; + config.cs = BASE_UNIT_DIM; + config.ch = BASE_UNIT_DIM; + config.walkableSlopeAngle = m_maxWalkableAngle; + config.tileSize = VERTEX_PER_TILE; + config.walkableRadius = m_bigBaseUnit ? 1 : 2; + config.borderSize = config.walkableRadius + 3; + config.maxEdgeLen = VERTEX_PER_TILE + 1; //anything bigger than tileSize + config.walkableHeight = m_bigBaseUnit ? 3 : 6; + config.walkableClimb = m_bigBaseUnit ? 2 : 4; // keep less than walkableHeight + config.minRegionArea = rcSqr(60); + config.mergeRegionArea = rcSqr(50); + config.maxSimplificationError = 2.0f; // eliminates most jagged edges (tinny polygons) + config.detailSampleDist = config.cs * 64; + config.detailSampleMaxError = config.ch * 2; + + // this sets the dimensions of the heightfield - should maybe happen before border padding + rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); + + // allocate subregions : tiles + Tile* tiles = new Tile[TILES_PER_MAP * TILES_PER_MAP]; + + // Initialize per tile config. + rcConfig tileCfg; + memcpy(&tileCfg, &config, sizeof(rcConfig)); + tileCfg.width = config.tileSize + config.borderSize*2; + tileCfg.height = config.tileSize + config.borderSize*2; + + // build all tiles + for (int y = 0; y < TILES_PER_MAP; ++y) + { + for (int x = 0; x < TILES_PER_MAP; ++x) + { + Tile& tile = tiles[x + y*TILES_PER_MAP]; + + // Calculate the per tile bounding box. + tileCfg.bmin[0] = config.bmin[0] + (x*config.tileSize - config.borderSize)*config.cs; + tileCfg.bmin[2] = config.bmin[2] + (y*config.tileSize - config.borderSize)*config.cs; + tileCfg.bmax[0] = config.bmin[0] + ((x+1)*config.tileSize + config.borderSize)*config.cs; + tileCfg.bmax[2] = config.bmin[2] + ((y+1)*config.tileSize + config.borderSize)*config.cs; + + float tbmin[2], tbmax[2]; + tbmin[0] = tileCfg.bmin[0]; + tbmin[1] = tileCfg.bmin[2]; + tbmax[0] = tileCfg.bmax[0]; + tbmax[1] = tileCfg.bmax[2]; + + // build heightfield + tile.solid = rcAllocHeightfield(); + if (!tile.solid || !rcCreateHeightfield(m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch)) + { + printf("%sFailed building heightfield! \n", tileString); + continue; + } + + // mark all walkable tiles, both liquids and solids + unsigned char* triFlags = new unsigned char[tTriCount]; + memset(triFlags, NAV_GROUND, tTriCount*sizeof(unsigned char)); + rcClearUnwalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags); + rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb); + delete [] triFlags; + + rcFilterLowHangingWalkableObstacles(m_rcContext, config.walkableClimb, *tile.solid); + rcFilterLedgeSpans(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid); + rcFilterWalkableLowHeightSpans(m_rcContext, tileCfg.walkableHeight, *tile.solid); + + rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.solid, config.walkableClimb); + + // compact heightfield spans + tile.chf = rcAllocCompactHeightfield(); + if (!tile.chf || !rcBuildCompactHeightfield(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid, *tile.chf)) + { + printf("%sFailed compacting heightfield! \n", tileString); + continue; + } + + // build polymesh intermediates + if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *tile.chf)) + { + printf("%sFailed eroding area! \n", tileString); + continue; + } + + if (!rcBuildDistanceField(m_rcContext, *tile.chf)) + { + printf("%sFailed building distance field! \n", tileString); + continue; + } + + if (!rcBuildRegions(m_rcContext, *tile.chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea)) + { + printf("%sFailed building regions! \n", tileString); + continue; + } + + tile.cset = rcAllocContourSet(); + if (!tile.cset || !rcBuildContours(m_rcContext, *tile.chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.cset)) + { + printf("%sFailed building contours! \n", tileString); + continue; + } + + // build polymesh + tile.pmesh = rcAllocPolyMesh(); + if (!tile.pmesh || !rcBuildPolyMesh(m_rcContext, *tile.cset, tileCfg.maxVertsPerPoly, *tile.pmesh)) + { + printf("%sFailed building polymesh! \n", tileString); + continue; + } + + tile.dmesh = rcAllocPolyMeshDetail(); + if (!tile.dmesh || !rcBuildPolyMeshDetail(m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg .detailSampleMaxError, *tile.dmesh)) + { + printf("%sFailed building polymesh detail! \n", tileString); + continue; + } + + // free those up + // we may want to keep them in the future for debug + // but right now, we don't have the code to merge them + rcFreeHeightField(tile.solid); + tile.solid = NULL; + rcFreeCompactHeightfield(tile.chf); + tile.chf = NULL; + rcFreeContourSet(tile.cset); + tile.cset = NULL; + } + } + + // merge per tile poly and detail meshes + rcPolyMesh** pmmerge = new rcPolyMesh*[TILES_PER_MAP * TILES_PER_MAP]; + if (!pmmerge) + { + printf("%s alloc pmmerge FIALED! \r", tileString); + return; + } + + rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[TILES_PER_MAP * TILES_PER_MAP]; + if (!dmmerge) + { + printf("%s alloc dmmerge FIALED! \r", tileString); + return; + } + + int nmerge = 0; + for (int y = 0; y < TILES_PER_MAP; ++y) + { + for (int x = 0; x < TILES_PER_MAP; ++x) + { + Tile& tile = tiles[x + y*TILES_PER_MAP]; + if (tile.pmesh) + { + pmmerge[nmerge] = tile.pmesh; + dmmerge[nmerge] = tile.dmesh; + nmerge++; + } + } + } + + iv.polyMesh = rcAllocPolyMesh(); + if (!iv.polyMesh) + { + printf("%s alloc iv.polyMesh FIALED! \r", tileString); + return; + } + rcMergePolyMeshes(m_rcContext, pmmerge, nmerge, *iv.polyMesh); + + iv.polyMeshDetail = rcAllocPolyMeshDetail(); + if (!iv.polyMeshDetail) + { + printf("%s alloc m_dmesh FIALED! \r", tileString); + return; + } + rcMergePolyMeshDetails(m_rcContext, dmmerge, nmerge, *iv.polyMeshDetail); + + // free things up + delete [] pmmerge; + delete [] dmmerge; + + delete [] tiles; + + // remove padding for extraction + for (int i = 0; i < iv.polyMesh->nverts; ++i) + { + unsigned short* v = &iv.polyMesh->verts[i*3]; + v[0] -= (unsigned short)config.borderSize; + v[2] -= (unsigned short)config.borderSize; + } + + // set polygons as walkable + // TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off + for (int i = 0; i < iv.polyMesh->npolys; ++i) + if (iv.polyMesh->areas[i] & RC_WALKABLE_AREA) + iv.polyMesh->flags[i] = iv.polyMesh->areas[i]; + + // setup mesh parameters + dtNavMeshCreateParams params; + memset(¶ms, 0, sizeof(params)); + params.verts = iv.polyMesh->verts; + params.vertCount = iv.polyMesh->nverts; + params.polys = iv.polyMesh->polys; + params.polyAreas = iv.polyMesh->areas; + params.polyFlags = iv.polyMesh->flags; + params.polyCount = iv.polyMesh->npolys; + params.nvp = iv.polyMesh->nvp; + params.detailMeshes = iv.polyMeshDetail->meshes; + params.detailVerts = iv.polyMeshDetail->verts; + params.detailVertsCount = iv.polyMeshDetail->nverts; + params.detailTris = iv.polyMeshDetail->tris; + params.detailTriCount = iv.polyMeshDetail->ntris; + + params.offMeshConVerts = meshData.offMeshConnections.getCArray(); + params.offMeshConCount = meshData.offMeshConnections.size()/6; + params.offMeshConRad = meshData.offMeshConnectionRads.getCArray(); + params.offMeshConDir = meshData.offMeshConnectionDirs.getCArray(); + params.offMeshConAreas = meshData.offMeshConnectionsAreas.getCArray(); + params.offMeshConFlags = meshData.offMeshConnectionsFlags.getCArray(); + + params.walkableHeight = BASE_UNIT_DIM*config.walkableHeight; // agent height + params.walkableRadius = BASE_UNIT_DIM*config.walkableRadius; // agent radius + params.walkableClimb = BASE_UNIT_DIM*config.walkableClimb; // keep less that walkableHeight (aka agent height)! + params.tileX = (((bmin[0] + bmax[0]) / 2) - navMesh->getParams()->orig[0]) / GRID_SIZE; + params.tileY = (((bmin[2] + bmax[2]) / 2) - navMesh->getParams()->orig[2]) / GRID_SIZE; + rcVcopy(params.bmin, bmin); + rcVcopy(params.bmax, bmax); + params.cs = config.cs; + params.ch = config.ch; + params.tileSize = VERTEX_PER_MAP; + + // will hold final navmesh + unsigned char* navData = NULL; + int navDataSize = 0; + + do + { + // these values are checked within dtCreateNavMeshData - handle them here + // so we have a clear error message + if (params.nvp > DT_VERTS_PER_POLYGON) + { + printf("%s Invalid verts-per-polygon value! \n", tileString); + continue; + } + if (params.vertCount >= 0xffff) + { + printf("%s Too many vertices! \n", tileString); + continue; + } + if (!params.vertCount || !params.verts) + { + // occurs mostly when adjacent tiles have models + // loaded but those models don't span into this tile + + // message is an annoyance + //printf("%sNo vertices to build tile! \n", tileString); + continue; + } + if (!params.polyCount || !params.polys || + TILES_PER_MAP*TILES_PER_MAP == params.polyCount) + { + // we have flat tiles with no actual geometry - don't build those, its useless + // keep in mind that we do output those into debug info + // drop tiles with only exact count - some tiles may have geometry while having less tiles + printf("%s No polygons to build on tile! \n", tileString); + continue; + } + if (!params.detailMeshes || !params.detailVerts || !params.detailTris) + { + printf("%s No detail mesh to build tile! \n", tileString); + continue; + } + + printf("%s Building navmesh tile... \r", tileString); + if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) + { + printf("%s Failed building navmesh tile! \n", tileString); + continue; + } + + dtTileRef tileRef = 0; + printf("%s Adding tile to navmesh... \r", tileString); + // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile + // is removed via removeTile() + dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef); + if (!tileRef || dtResult != DT_SUCCESS) + { + printf("%s Failed adding tile to navmesh! \n", tileString); + continue; + } + + // file output + char fileName[255]; + sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX); + FILE* file = fopen(fileName, "wb"); + if (!file) + { + char message[1024]; + sprintf(message, "Failed to open %s for writing!\n", fileName); + perror(message); + navMesh->removeTile(tileRef, NULL, NULL); + continue; + } + + printf("%s Writing to file... \r", tileString); + + // write header + MmapTileHeader header; + header.usesLiquids = m_terrainBuilder->usesLiquids(); + header.size = uint32(navDataSize); + fwrite(&header, sizeof(MmapTileHeader), 1, file); + + // write data + fwrite(navData, sizeof(unsigned char), navDataSize, file); + fclose(file); + + // now that tile is written to disk, we can unload it + navMesh->removeTile(tileRef, NULL, NULL); + } + while (0); + + if (m_debugOutput) + { + // restore padding so that the debug visualization is correct + for (int i = 0; i < iv.polyMesh->nverts; ++i) + { + unsigned short* v = &iv.polyMesh->verts[i*3]; + v[0] += (unsigned short)config.borderSize; + v[2] += (unsigned short)config.borderSize; + } + + iv.generateObjFile(mapID, tileX, tileY, meshData); + iv.writeIV(mapID, tileX, tileY); + } + } + + /**************************************************************************/ + void MapBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax) + { + // this is for elevation + if (verts && vertCount) + rcCalcBounds(verts, vertCount, bmin, bmax); + else + { + bmin[1] = FLT_MIN; + bmax[1] = FLT_MAX; + } + + // this is for width and depth + bmax[0] = (32 - int(tileX)) * GRID_SIZE; + bmax[2] = (32 - int(tileY)) * GRID_SIZE; + bmin[0] = bmax[0] - GRID_SIZE; + bmin[2] = bmax[2] - GRID_SIZE; + } + + /**************************************************************************/ + bool MapBuilder::shouldSkipMap(uint32 mapID) + { + if (m_skipContinents) + switch (mapID) + { + case 0: + case 1: + case 530: + case 571: + return true; + default: + break; + } + + if (m_skipJunkMaps) + switch (mapID) + { + case 13: // test.wdt + case 25: // ScottTest.wdt + case 29: // Test.wdt + case 42: // Colin.wdt + case 169: // EmeraldDream.wdt (unused, and very large) + case 451: // development.wdt + case 573: // ExteriorTest.wdt + case 597: // CraigTest.wdt + case 605: // development_nonweighted.wdt + case 606: // QA_DVD.wdt + return true; + default: + if (isTransportMap(mapID)) + return true; + break; + } + + if (m_skipBattlegrounds) + switch (mapID) + { + case 30: // AV + case 37: // ? + case 489: // WSG + case 529: // AB + case 566: // EotS + case 607: // SotA + case 628: // IoC + return true; + default: + break; + } + + return false; + } + + /**************************************************************************/ + bool MapBuilder::isTransportMap(uint32 mapID) + { + switch (mapID) + { + // transport maps + case 582: + case 584: + case 586: + case 587: + case 588: + case 589: + case 590: + case 591: + case 592: + case 593: + case 594: + case 596: + case 610: + case 612: + case 613: + case 614: + case 620: + case 621: + case 622: + case 623: + case 641: + case 642: + case 647: + case 672: + case 673: + case 712: + case 713: + case 718: + return true; + default: + return false; + } + } + + /**************************************************************************/ + bool MapBuilder::shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY) + { + char fileName[255]; + sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX); + FILE* file = fopen(fileName, "rb"); + if (!file) + return false; + + MmapTileHeader header; + fread(&header, sizeof(MmapTileHeader), 1, file); + fclose(file); + + if (header.mmapMagic != MMAP_MAGIC || header.dtVersion != DT_NAVMESH_VERSION) + return false; + + if (header.mmapVersion != MMAP_VERSION) + return false; + + return true; + } + +} diff --git a/src/tools/mmap_extractor/MapBuilder.h b/src/tools/mmap_extractor/MapBuilder.h new file mode 100644 index 00000000000..d0f33ce9a79 --- /dev/null +++ b/src/tools/mmap_extractor/MapBuilder.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#ifndef _MAP_BUILDER_H +#define _MAP_BUILDER_H + +#include +#include +#include + +#include "TerrainBuilder.h" +#include "IntermediateValues.h" + +#include "IVMapManager.h" +#include "WorldModel.h" + +#include "Recast.h" +#include "DetourNavMesh.h" + +using namespace std; +using namespace VMAP; + +// G3D namespace typedefs conflicts with ACE typedefs + +namespace MMAP +{ + typedef map*> TileList; + struct Tile + { + Tile() : chf(NULL), solid(NULL), cset(NULL), pmesh(NULL), dmesh(NULL) {} + ~Tile() + { + rcFreeCompactHeightfield(chf); + rcFreeContourSet(cset); + rcFreeHeightField(solid); + rcFreePolyMesh(pmesh); + rcFreePolyMeshDetail(dmesh); + } + rcCompactHeightfield* chf; + rcHeightfield* solid; + rcContourSet* cset; + rcPolyMesh* pmesh; + rcPolyMeshDetail* dmesh; + }; + + class MapBuilder + { + public: + MapBuilder(float maxWalkableAngle = 60.f, + bool skipLiquid = false, + bool skipContinents = false, + bool skipJunkMaps = true, + bool skipBattlegrounds = false, + bool debugOutput = false, + bool bigBaseUnit = false, + const char* offMeshFilePath = NULL); + + ~MapBuilder(); + + // builds all mmap tiles for the specified map id (ignores skip settings) + void buildMap(uint32 mapID); + + // builds an mmap tile for the specified map and its mesh + void buildSingleTile(uint32 mapID, uint32 tileX, uint32 tileY); + + // builds list of maps, then builds all of mmap tiles (based on the skip settings) + void buildAllMaps(); + + private: + // detect maps and tiles + void discoverTiles(); + set* getTileList(uint32 mapID); + + void buildNavMesh(uint32 mapID, dtNavMesh* &navMesh); + + void buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh); + + // move map building + void buildMoveMapTile(uint32 mapID, + uint32 tileX, + uint32 tileY, + MeshData &meshData, + float bmin[3], + float bmax[3], + dtNavMesh* navMesh); + + void getTileBounds(uint32 tileX, uint32 tileY, + float* verts, int vertCount, + float* bmin, float* bmax); + void getGridBounds(uint32 mapID, uint32 &minX, uint32 &minY, uint32 &maxX, uint32 &maxY); + + bool shouldSkipMap(uint32 mapID); + bool isTransportMap(uint32 mapID); + bool shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY); + + TerrainBuilder* m_terrainBuilder; + TileList m_tiles; + + bool m_debugOutput; + + const char* m_offMeshFilePath; + bool m_skipContinents; + bool m_skipJunkMaps; + bool m_skipBattlegrounds; + + float m_maxWalkableAngle; + bool m_bigBaseUnit; + + // build performance - not really used for now + rcContext* m_rcContext; + }; +} + +#endif diff --git a/src/tools/mmap_extractor/PathCommon.h b/src/tools/mmap_extractor/PathCommon.h new file mode 100644 index 00000000000..fd02ec02d50 --- /dev/null +++ b/src/tools/mmap_extractor/PathCommon.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#ifndef _MMAP_COMMON_H +#define _MMAP_COMMON_H + +#include +#include + +#include "Define.h" + +#ifndef _WIN32 + #include + #include +#endif + +#ifdef __linux__ + #include +#endif + +using namespace std; + +namespace MMAP +{ + inline bool matchWildcardFilter(const char* filter, const char* str) + { + if (!filter || !str) + return false; + + // end on null character + while (*filter && *str) + { + if (*filter == '*') + { + if (*++filter == '\0') // wildcard at end of filter means all remaing chars match + return true; + + while (true) + { + if (*filter == *str) + break; + if (*str == '\0') + return false; // reached end of string without matching next filter character + str++; + } + } + else if (*filter != *str) + return false; // mismatch + + filter++; + str++; + } + + return ((*filter == '\0' || (*filter == '*' && *++filter == '\0')) && *str == '\0'); + } + + enum ListFilesResult + { + LISTFILE_DIRECTORY_NOT_FOUND = 0, + LISTFILE_OK = 1 + }; + + inline ListFilesResult getDirContents(vector &fileList, string dirpath = ".", string filter = "*", bool includeSubDirs = false) + { + #ifdef WIN32 + HANDLE hFind; + WIN32_FIND_DATA findFileInfo; + string directory; + + directory = dirpath + "/" + filter; + + hFind = FindFirstFile(directory.c_str(), &findFileInfo); + + if (hFind == INVALID_HANDLE_VALUE) + return LISTFILE_DIRECTORY_NOT_FOUND; + do + { + if (includeSubDirs || (findFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) + fileList.push_back(string(findFileInfo.cFileName)); + } + while (FindNextFile(hFind, &findFileInfo)); + + FindClose(hFind); + + #else + const char *p = dirpath.c_str(); + DIR * dirp = opendir(p); + struct dirent * dp; + dirp = opendir(p); + + while (dirp) + { + errno = 0; + if ((dp = readdir(dirp)) != NULL) + { + if (matchWildcardFilter(filter.c_str(), dp->d_name)) + fileList.push_back(string(dp->d_name)); + } + else + break; + } + + if (dirp) + closedir(dirp); + else + return LISTFILE_DIRECTORY_NOT_FOUND; + #endif + + return LISTFILE_OK; + } +} + +#endif diff --git a/src/tools/mmap_extractor/PathGenerator.cpp b/src/tools/mmap_extractor/PathGenerator.cpp new file mode 100644 index 00000000000..2eb2c6545c4 --- /dev/null +++ b/src/tools/mmap_extractor/PathGenerator.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "PathCommon.h" +#include "MapBuilder.h" + +using namespace MMAP; + +bool checkDirectories(bool debugOutput) +{ + vector dirFiles; + + if (getDirContents(dirFiles, "maps") == LISTFILE_DIRECTORY_NOT_FOUND || !dirFiles.size()) + { + printf("'maps' directory is empty or does not exist\n"); + return false; + } + + dirFiles.clear(); + if (getDirContents(dirFiles, "vmaps", "*.vmtree") == LISTFILE_DIRECTORY_NOT_FOUND || !dirFiles.size()) + { + printf("'vmaps' directory is empty or does not exist\n"); + return false; + } + + dirFiles.clear(); + if (getDirContents(dirFiles, "mmaps") == LISTFILE_DIRECTORY_NOT_FOUND) + { + printf("'mmaps' directory does not exist\n"); + return false; + } + + dirFiles.clear(); + if (debugOutput) + { + if (getDirContents(dirFiles, "meshes") == LISTFILE_DIRECTORY_NOT_FOUND) + { + printf("'meshes' directory does not exist (no place to put debugOutput files)\n"); + return false; + } + } + + return true; +} + +bool handleArgs(int argc, char** argv, + int &mapnum, + int &tileX, + int &tileY, + float &maxAngle, + bool &skipLiquid, + bool &skipContinents, + bool &skipJunkMaps, + bool &skipBattlegrounds, + bool &debugOutput, + bool &silent, + bool &bigBaseUnit, + char* &offMeshInputPath) +{ + char* param = NULL; + for (int i = 1; i < argc; ++i) + { + if (strcmp(argv[i], "--maxAngle") == 0) + { + param = argv[++i]; + if (!param) + return false; + + float maxangle = atof(param); + if (maxangle <= 90.f && maxangle >= 45.f) + maxAngle = maxangle; + else + printf("invalid option for '--maxAngle', using default\n"); + } + else if (strcmp(argv[i], "--tile") == 0) + { + param = argv[++i]; + if (!param) + return false; + + char* stileX = strtok(param, ","); + char* stileY = strtok(NULL, ","); + int tilex = atoi(stileX); + int tiley = atoi(stileY); + + if ((tilex > 0 && tilex < 64) || (tilex == 0 && strcmp(stileX, "0") == 0)) + tileX = tilex; + if ((tiley > 0 && tiley < 64) || (tiley == 0 && strcmp(stileY, "0") == 0)) + tileY = tiley; + + if (tileX < 0 || tileY < 0) + { + printf("invalid tile coords.\n"); + return false; + } + } + else if (strcmp(argv[i], "--skipLiquid") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + skipLiquid = true; + else if (strcmp(param, "false") == 0) + skipLiquid = false; + else + printf("invalid option for '--skipLiquid', using default\n"); + } + else if (strcmp(argv[i], "--skipContinents") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + skipContinents = true; + else if (strcmp(param, "false") == 0) + skipContinents = false; + else + printf("invalid option for '--skipContinents', using default\n"); + } + else if (strcmp(argv[i], "--skipJunkMaps") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + skipJunkMaps = true; + else if (strcmp(param, "false") == 0) + skipJunkMaps = false; + else + printf("invalid option for '--skipJunkMaps', using default\n"); + } + else if (strcmp(argv[i], "--skipBattlegrounds") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + skipBattlegrounds = true; + else if (strcmp(param, "false") == 0) + skipBattlegrounds = false; + else + printf("invalid option for '--skipBattlegrounds', using default\n"); + } + else if (strcmp(argv[i], "--debugOutput") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + debugOutput = true; + else if (strcmp(param, "false") == 0) + debugOutput = false; + else + printf("invalid option for '--debugOutput', using default true\n"); + } + else if (strcmp(argv[i], "--silent") == 0) + { + silent = true; + } + else if (strcmp(argv[i], "--bigBaseUnit") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + bigBaseUnit = true; + else if (strcmp(param, "false") == 0) + bigBaseUnit = false; + else + printf("invalid option for '--bigBaseUnit', using default false\n"); + } + else if (strcmp(argv[i], "--offMeshInput") == 0) + { + param = argv[++i]; + if (!param) + return false; + + offMeshInputPath = param; + } + else + { + int map = atoi(argv[i]); + if (map > 0 || (map == 0 && (strcmp(argv[i], "0") == 0))) + mapnum = map; + else + { + printf("invalid map id\n"); + return false; + } + } + } + + return true; +} + +int finish(const char* message, int returnValue) +{ + printf("%s", message); + getchar(); + return returnValue; +} + +int main(int argc, char** argv) +{ + int mapnum = -1; + float maxAngle = 60.0f; + int tileX = -1, tileY = -1; + bool skipLiquid = false, + skipContinents = false, + skipJunkMaps = true, + skipBattlegrounds = false, + debugOutput = false, + silent = false, + bigBaseUnit = false; + char* offMeshInputPath = NULL; + + bool validParam = handleArgs(argc, argv, mapnum, + tileX, tileY, maxAngle, + skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, + debugOutput, silent, bigBaseUnit, offMeshInputPath); + + if (!validParam) + return silent ? -1 : finish("You have specified invalid parameters", -1); + + if (mapnum == -1 && debugOutput) + { + if (silent) + return -2; + + printf("You have specifed debug output, but didn't specify a map to generate.\n"); + printf("This will generate debug output for ALL maps.\n"); + printf("Are you sure you want to continue? (y/n) "); + if (getchar() != 'y') + return 0; + } + + if (!checkDirectories(debugOutput)) + return silent ? -3 : finish("Press any key to close...", -3); + + MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps, + skipBattlegrounds, debugOutput, bigBaseUnit, offMeshInputPath); + + if (tileX > -1 && tileY > -1 && mapnum >= 0) + builder.buildSingleTile(mapnum, tileX, tileY); + else if (mapnum >= 0) + builder.buildMap(uint32(mapnum)); + else + builder.buildAllMaps(); + + return silent ? 1 : finish("Movemap build is complete!", 1); +} diff --git a/src/tools/mmap_extractor/TerrainBuilder.cpp b/src/tools/mmap_extractor/TerrainBuilder.cpp new file mode 100644 index 00000000000..c696f6017a5 --- /dev/null +++ b/src/tools/mmap_extractor/TerrainBuilder.cpp @@ -0,0 +1,854 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#include "TerrainBuilder.h" + +#include "PathCommon.h" +#include "MapBuilder.h" + +#include "VMapManager2.h" +#include "MapTree.h" +#include "ModelInstance.h" + +namespace MMAP +{ + TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ } + TerrainBuilder::~TerrainBuilder() { } + + /**************************************************************************/ + void TerrainBuilder::getLoopVars(Spot portion, int &loopStart, int &loopEnd, int &loopInc) + { + switch (portion) + { + case ENTIRE: + loopStart = 0; + loopEnd = V8_SIZE_SQ; + loopInc = 1; + break; + case TOP: + loopStart = 0; + loopEnd = V8_SIZE; + loopInc = 1; + break; + case LEFT: + loopStart = 0; + loopEnd = V8_SIZE_SQ - V8_SIZE + 1; + loopInc = V8_SIZE; + break; + case RIGHT: + loopStart = V8_SIZE - 1; + loopEnd = V8_SIZE_SQ; + loopInc = V8_SIZE; + break; + case BOTTOM: + loopStart = V8_SIZE_SQ - V8_SIZE; + loopEnd = V8_SIZE_SQ; + loopInc = 1; + break; + } + } + + /**************************************************************************/ + void TerrainBuilder::loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) + { + if (loadMap(mapID, tileX, tileY, meshData, ENTIRE)) + { + loadMap(mapID, tileX+1, tileY, meshData, LEFT); + loadMap(mapID, tileX-1, tileY, meshData, RIGHT); + loadMap(mapID, tileX, tileY+1, meshData, TOP); + loadMap(mapID, tileX, tileY-1, meshData, BOTTOM); + } + } + + /**************************************************************************/ + bool TerrainBuilder::loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, Spot portion) + { + char mapFileName[255]; + sprintf(mapFileName, "maps/%03u%02u%02u.map", mapID, tileY, tileX); + + FILE* mapFile = fopen(mapFileName, "rb"); + if (!mapFile) + return false; + + map_fileheader fheader; + fread(&fheader, sizeof(map_fileheader), 1, mapFile); + + if (fheader.versionMagic != *((uint32 const*)(MAP_VERSION_MAGIC))) + { + fclose(mapFile); + printf("%s is the wrong version, please extract new .map files\n", mapFileName); + return false; + } + + map_heightHeader hheader; + fseek(mapFile, fheader.heightMapOffset, SEEK_SET); + fread(&hheader, sizeof(map_heightHeader), 1, mapFile); + + bool haveTerrain = !(hheader.flags & MAP_HEIGHT_NO_HEIGHT); + bool haveLiquid = fheader.liquidMapOffset && !m_skipLiquid; + + // no data in this map file + if (!haveTerrain && !haveLiquid) + { + fclose(mapFile); + return false; + } + + // data used later + uint16 holes[16][16]; + memset(holes, 0, sizeof(holes)); + uint8 liquid_type[16][16]; + memset(liquid_type, 0, sizeof(liquid_type)); + G3D::Array ltriangles; + G3D::Array ttriangles; + + // terrain data + if (haveTerrain) + { + int i; + float heightMultiplier; + float V9[V9_SIZE_SQ], V8[V8_SIZE_SQ]; + + if (hheader.flags & MAP_HEIGHT_AS_INT8) + { + uint8 v9[V9_SIZE_SQ]; + uint8 v8[V8_SIZE_SQ]; + fread(v9, sizeof(uint8), V9_SIZE_SQ, mapFile); + fread(v8, sizeof(uint8), V8_SIZE_SQ, mapFile); + heightMultiplier = (hheader.gridMaxHeight - hheader.gridHeight) / 255; + + for (i = 0; i < V9_SIZE_SQ; ++i) + V9[i] = (float)v9[i]*heightMultiplier + hheader.gridHeight; + + for (i = 0; i < V8_SIZE_SQ; ++i) + V8[i] = (float)v8[i]*heightMultiplier + hheader.gridHeight; + } + else if (hheader.flags & MAP_HEIGHT_AS_INT16) + { + uint16 v9[V9_SIZE_SQ]; + uint16 v8[V8_SIZE_SQ]; + fread(v9, sizeof(uint16), V9_SIZE_SQ, mapFile); + fread(v8, sizeof(uint16), V8_SIZE_SQ, mapFile); + heightMultiplier = (hheader.gridMaxHeight - hheader.gridHeight) / 65535; + + for (i = 0; i < V9_SIZE_SQ; ++i) + V9[i] = (float)v9[i]*heightMultiplier + hheader.gridHeight; + + for (i = 0; i < V8_SIZE_SQ; ++i) + V8[i] = (float)v8[i]*heightMultiplier + hheader.gridHeight; + } + else + { + fread (V9, sizeof(float), V9_SIZE_SQ, mapFile); + fread(V8, sizeof(float), V8_SIZE_SQ, mapFile); + } + + // hole data + memset(holes, 0, fheader.holesSize); + fseek(mapFile, fheader.holesOffset, SEEK_SET); + fread(holes, fheader.holesSize, 1, mapFile); + + int count = meshData.solidVerts.size() / 3; + float xoffset = (float(tileX)-32)*GRID_SIZE; + float yoffset = (float(tileY)-32)*GRID_SIZE; + + float coord[3]; + + for (i = 0; i < V9_SIZE_SQ; ++i) + { + getHeightCoord(i, GRID_V9, xoffset, yoffset, coord, V9); + meshData.solidVerts.append(coord[0]); + meshData.solidVerts.append(coord[2]); + meshData.solidVerts.append(coord[1]); + } + + for (i = 0; i < V8_SIZE_SQ; ++i) + { + getHeightCoord(i, GRID_V8, xoffset, yoffset, coord, V8); + meshData.solidVerts.append(coord[0]); + meshData.solidVerts.append(coord[2]); + meshData.solidVerts.append(coord[1]); + } + + int j, indices[3], loopStart, loopEnd, loopInc; + getLoopVars(portion, loopStart, loopEnd, loopInc); + for (i = loopStart; i < loopEnd; i+=loopInc) + for (j = TOP; j <= BOTTOM; j+=1) + { + getHeightTriangle(i, Spot(j), indices); + ttriangles.append(indices[2] + count); + ttriangles.append(indices[1] + count); + ttriangles.append(indices[0] + count); + } + } + + // liquid data + if (haveLiquid) + { + map_liquidHeader lheader; + fseek(mapFile, fheader.liquidMapOffset, SEEK_SET); + fread(&lheader, sizeof(map_liquidHeader), 1, mapFile); + + float* liquid_map = NULL; + + if (!(lheader.flags & MAP_LIQUID_NO_TYPE)) + fread(liquid_type, sizeof(liquid_type), 1, mapFile); + + if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT)) + { + liquid_map = new float [lheader.width*lheader.height]; + fread(liquid_map, sizeof(float), lheader.width*lheader.height, mapFile); + } + + if (liquid_type && liquid_map) + { + int count = meshData.liquidVerts.size() / 3; + float xoffset = (float(tileX)-32)*GRID_SIZE; + float yoffset = (float(tileY)-32)*GRID_SIZE; + + float coord[3]; + int row, col; + + // generate coordinates + if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT)) + { + int j = 0; + for (int i = 0; i < V9_SIZE_SQ; ++i) + { + row = i / V9_SIZE; + col = i % V9_SIZE; + + if (row < lheader.offsetY || row >= lheader.offsetY + lheader.height || + col < lheader.offsetX || col >= lheader.offsetX + lheader.width) + { + // dummy vert using invalid height + meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, INVALID_MAP_LIQ_HEIGHT, (yoffset+row*GRID_PART_SIZE)*-1); + continue; + } + + getLiquidCoord(i, j, xoffset, yoffset, coord, liquid_map); + meshData.liquidVerts.append(coord[0]); + meshData.liquidVerts.append(coord[2]); + meshData.liquidVerts.append(coord[1]); + j++; + } + } + else + { + for (int i = 0; i < V9_SIZE_SQ; ++i) + { + row = i / V9_SIZE; + col = i % V9_SIZE; + meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, lheader.liquidLevel, (yoffset+row*GRID_PART_SIZE)*-1); + } + } + + delete [] liquid_map; + + int indices[3], loopStart, loopEnd, loopInc, triInc; + getLoopVars(portion, loopStart, loopEnd, loopInc); + triInc = BOTTOM-TOP; + + // generate triangles + for (int i = loopStart; i < loopEnd; i+=loopInc) + for (int j = TOP; j <= BOTTOM; j+= triInc) + { + getHeightTriangle(i, Spot(j), indices, true); + ltriangles.append(indices[2] + count); + ltriangles.append(indices[1] + count); + ltriangles.append(indices[0] + count); + } + } + } + + fclose(mapFile); + + // now that we have gathered the data, we can figure out which parts to keep: + // liquid above ground, ground above liquid + int loopStart, loopEnd, loopInc, tTriCount = 4; + bool useTerrain, useLiquid; + + float* lverts = meshData.liquidVerts.getCArray(); + int* ltris = ltriangles.getCArray(); + + float* tverts = meshData.solidVerts.getCArray(); + int* ttris = ttriangles.getCArray(); + + if (ltriangles.size() + ttriangles.size() == 0) + return false; + + // make a copy of liquid vertices + // used to pad right-bottom frame due to lost vertex data at extraction + float* lverts_copy = NULL; + if (meshData.liquidVerts.size()) + { + lverts_copy = new float[meshData.liquidVerts.size()]; + memcpy(lverts_copy, lverts, sizeof(float)*meshData.liquidVerts.size()); + } + + getLoopVars(portion, loopStart, loopEnd, loopInc); + for (int i = loopStart; i < loopEnd; i+=loopInc) + { + for (int j = 0; j < 2; ++j) + { + // default is true, will change to false if needed + useTerrain = true; + useLiquid = true; + uint8 liquidType = MAP_LIQUID_TYPE_NO_WATER; + + // if there is no liquid, don't use liquid + if (!liquid_type || !meshData.liquidVerts.size() || !ltriangles.size()) + useLiquid = false; + else + { + liquidType = getLiquidType(i, liquid_type); + switch (liquidType) + { + default: + useLiquid = false; + break; + case MAP_LIQUID_TYPE_WATER: + case MAP_LIQUID_TYPE_OCEAN: + // merge different types of water + liquidType = NAV_WATER; + break; + case MAP_LIQUID_TYPE_MAGMA: + liquidType = NAV_MAGMA; + break; + case MAP_LIQUID_TYPE_SLIME: + liquidType = NAV_SLIME; + break; + case MAP_LIQUID_TYPE_DARK_WATER: + // players should not be here, so logically neither should creatures + useTerrain = false; + useLiquid = false; + break; + } + } + + // if there is no terrain, don't use terrain + if (!ttriangles.size()) + useTerrain = false; + + // while extracting ADT data we are losing right-bottom vertices + // this code adds fair approximation of lost data + if (useLiquid) + { + float quadHeight = 0; + uint32 validCount = 0; + for(uint32 idx = 0; idx < 3; idx++) + { + float h = lverts_copy[ltris[idx]*3 + 1]; + if (h != INVALID_MAP_LIQ_HEIGHT && h < INVALID_MAP_LIQ_HEIGHT_MAX) + { + quadHeight += h; + validCount++; + } + } + + // update vertex height data + if (validCount > 0 && validCount < 3) + { + quadHeight /= validCount; + for(uint32 idx = 0; idx < 3; idx++) + { + float h = lverts[ltris[idx]*3 + 1]; + if (h == INVALID_MAP_LIQ_HEIGHT || h > INVALID_MAP_LIQ_HEIGHT_MAX) + lverts[ltris[idx]*3 + 1] = quadHeight; + } + } + + // no valid vertexes - don't use this poly at all + if (validCount == 0) + useLiquid = false; + } + + // if there is a hole here, don't use the terrain + if (useTerrain) + useTerrain = !isHole(i, holes); + + // we use only one terrain kind per quad - pick higher one + if (useTerrain && useLiquid) + { + float minLLevel = INVALID_MAP_LIQ_HEIGHT_MAX; + float maxLLevel = INVALID_MAP_LIQ_HEIGHT; + for(uint32 x = 0; x < 3; x++) + { + float h = lverts[ltris[x]*3 + 1]; + if (minLLevel > h) + minLLevel = h; + + if (maxLLevel < h) + maxLLevel = h; + } + + float maxTLevel = INVALID_MAP_LIQ_HEIGHT; + float minTLevel = INVALID_MAP_LIQ_HEIGHT_MAX; + for(uint32 x = 0; x < 6; x++) + { + float h = tverts[ttris[x]*3 + 1]; + if (maxTLevel < h) + maxTLevel = h; + + if (minTLevel > h) + minTLevel = h; + } + + // terrain under the liquid? + if (minLLevel > maxTLevel) + useTerrain = false; + + //liquid under the terrain? + if (minTLevel > maxLLevel) + useLiquid = false; + } + + // store the result + if (useLiquid) + { + meshData.liquidType.append(liquidType); + for (int k = 0; k < 3; ++k) + meshData.liquidTris.append(ltris[k]); + } + + if (useTerrain) + for (int k = 0; k < 3*tTriCount/2; ++k) + meshData.solidTris.append(ttris[k]); + + // advance to next set of triangles + ltris += 3; + ttris += 3*tTriCount/2; + } + } + + if (lverts_copy) + delete [] lverts_copy; + + return meshData.solidTris.size() || meshData.liquidTris.size(); + } + + /**************************************************************************/ + void TerrainBuilder::getHeightCoord(int index, Grid grid, float xOffset, float yOffset, float* coord, float* v) + { + // wow coords: x, y, height + // coord is mirroed about the horizontal axes + switch (grid) + { + case GRID_V9: + coord[0] = (xOffset + index%(V9_SIZE)*GRID_PART_SIZE) * -1.f; + coord[1] = (yOffset + (int)(index/(V9_SIZE))*GRID_PART_SIZE) * -1.f; + coord[2] = v[index]; + break; + case GRID_V8: + coord[0] = (xOffset + index%(V8_SIZE)*GRID_PART_SIZE + GRID_PART_SIZE/2.f) * -1.f; + coord[1] = (yOffset + (int)(index/(V8_SIZE))*GRID_PART_SIZE + GRID_PART_SIZE/2.f) * -1.f; + coord[2] = v[index]; + break; + } + } + + /**************************************************************************/ + void TerrainBuilder::getHeightTriangle(int square, Spot triangle, int* indices, bool liquid/* = false*/) + { + int rowOffset = square/V8_SIZE; + if (!liquid) + switch (triangle) + { + case TOP: + indices[0] = square+rowOffset; // 0-----1 .... 128 + indices[1] = square+1+rowOffset; // |\ T /| + indices[2] = (V9_SIZE_SQ)+square; // | \ / | + break; // |L 0 R| .. 127 + case LEFT: // | / \ | + indices[0] = square+rowOffset; // |/ B \| + indices[1] = (V9_SIZE_SQ)+square; // 129---130 ... 386 + indices[2] = square+V9_SIZE+rowOffset; // |\ /| + break; // | \ / | + case RIGHT: // | 128 | .. 255 + indices[0] = square+1+rowOffset; // | / \ | + indices[1] = square+V9_SIZE+1+rowOffset; // |/ \| + indices[2] = (V9_SIZE_SQ)+square; // 258---259 ... 515 + break; + case BOTTOM: + indices[0] = (V9_SIZE_SQ)+square; + indices[1] = square+V9_SIZE+1+rowOffset; + indices[2] = square+V9_SIZE+rowOffset; + break; + default: break; + } + else + switch (triangle) + { // 0-----1 .... 128 + case TOP: // |\ | + indices[0] = square+rowOffset; // | \ T | + indices[1] = square+1+rowOffset; // | \ | + indices[2] = square+V9_SIZE+1+rowOffset; // | B \ | + break; // | \| + case BOTTOM: // 129---130 ... 386 + indices[0] = square+rowOffset; // |\ | + indices[1] = square+V9_SIZE+1+rowOffset; // | \ | + indices[2] = square+V9_SIZE+rowOffset; // | \ | + break; // | \ | + default: break; // | \| + } // 258---259 ... 515 + + } + + /**************************************************************************/ + void TerrainBuilder::getLiquidCoord(int index, int index2, float xOffset, float yOffset, float* coord, float* v) + { + // wow coords: x, y, height + // coord is mirroed about the horizontal axes + coord[0] = (xOffset + index%(V9_SIZE)*GRID_PART_SIZE) * -1.f; + coord[1] = (yOffset + (int)(index/(V9_SIZE))*GRID_PART_SIZE) * -1.f; + coord[2] = v[index2]; + } + + static uint16 holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; + static uint16 holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; + + /**************************************************************************/ + bool TerrainBuilder::isHole(int square, const uint16 holes[16][16]) + { + int row = square / 128; + int col = square % 128; + int cellRow = row / 8; // 8 squares per cell + int cellCol = col / 8; + int holeRow = row % 8 / 2; + int holeCol = (square - (row * 128 + cellCol * 8)) / 2; + + uint16 hole = holes[cellRow][cellCol]; + + return (hole & holetab_h[holeCol] & holetab_v[holeRow]) != 0; + } + + /**************************************************************************/ + uint8 TerrainBuilder::getLiquidType(int square, const uint8 liquid_type[16][16]) + { + int row = square / 128; + int col = square % 128; + int cellRow = row / 8; // 8 squares per cell + int cellCol = col / 8; + + return liquid_type[cellRow][cellCol]; + } + + /**************************************************************************/ + bool TerrainBuilder::loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) + { + IVMapManager* vmapManager = new VMapManager2(); + int result = vmapManager->loadMap("vmaps", mapID, tileX, tileY); + bool retval = false; + + do + { + if (result == VMAP_LOAD_RESULT_ERROR) + break; + + InstanceTreeMap instanceTrees; + ((VMapManager2*)vmapManager)->getInstanceMapTree(instanceTrees); + + if (!instanceTrees[mapID]) + break; + + ModelInstance* models = NULL; + uint32 count = 0; + instanceTrees[mapID]->getModelInstances(models, count); + + if (!models) + break; + + for (uint32 i = 0; i < count; ++i) + { + ModelInstance instance = models[i]; + + // model instances exist in tree even though there are instances of that model in this tile + WorldModel* worldModel = instance.getWorldModel(); + if (!worldModel) + continue; + + // now we have a model to add to the meshdata + retval = true; + + vector groupModels; + worldModel->getGroupModels(groupModels); + + // all M2s need to have triangle indices reversed + bool isM2 = instance.name.find(".m2") != instance.name.npos || instance.name.find(".M2") != instance.name.npos; + + // transform data + float scale = instance.iScale; + G3D::Matrix3 rotation = G3D::Matrix3::fromEulerAnglesXYZ(G3D::pi()*instance.iRot.z/-180.f, G3D::pi()*instance.iRot.x/-180.f, G3D::pi()*instance.iRot.y/-180.f); + Vector3 position = instance.iPos; + position.x -= 32*GRID_SIZE; + position.y -= 32*GRID_SIZE; + + for (vector::iterator it = groupModels.begin(); it != groupModels.end(); ++it) + { + vector tempVertices; + vector transformedVertices; + vector tempTriangles; + WmoLiquid* liquid = NULL; + + (*it).getMeshData(tempVertices, tempTriangles, liquid); + + // first handle collision mesh + transform(tempVertices, transformedVertices, scale, rotation, position); + + int offset = meshData.solidVerts.size() / 3; + + copyVertices(transformedVertices, meshData.solidVerts); + copyIndices(tempTriangles, meshData.solidTris, offset, isM2); + + // now handle liquid data + if (liquid) + { + vector liqVerts; + vector liqTris; + uint32 tilesX, tilesY, vertsX, vertsY; + Vector3 corner; + liquid->getPosInfo(tilesX, tilesY, corner); + vertsX = tilesX + 1; + vertsY = tilesY + 1; + uint8* flags = liquid->GetFlagsStorage(); + float* data = liquid->GetHeightStorage(); + uint8 type = NAV_EMPTY; + + // convert liquid type to NavTerrain + switch (liquid->GetType()) + { + case 0: + case 1: + type = NAV_WATER; + break; + case 2: + type = NAV_MAGMA; + break; + case 3: + type = NAV_SLIME; + break; + } + + // indexing is weird... + // after a lot of trial and error, this is what works: + // vertex = y*vertsX+x + // tile = x*tilesY+y + // flag = y*tilesY+x + + Vector3 vert; + for (uint32 x = 0; x < vertsX; ++x) + for (uint32 y = 0; y < vertsY; ++y) + { + vert = Vector3(corner.x + x * GRID_PART_SIZE, corner.y + y * GRID_PART_SIZE, data[y*vertsX + x]); + vert = vert * rotation * scale + position; + vert.x *= -1.f; + vert.y *= -1.f; + liqVerts.push_back(vert); + } + + int idx1, idx2, idx3, idx4; + uint32 square; + for (uint32 x = 0; x < tilesX; ++x) + for (uint32 y = 0; y < tilesY; ++y) + if ((flags[x+y*tilesX] & 0x0f) != 0x0f) + { + square = x * tilesY + y; + idx1 = square+x; + idx2 = square+1+x; + idx3 = square+tilesY+1+1+x; + idx4 = square+tilesY+1+x; + + // top triangle + liqTris.push_back(idx3); + liqTris.push_back(idx2); + liqTris.push_back(idx1); + // bottom triangle + liqTris.push_back(idx4); + liqTris.push_back(idx3); + liqTris.push_back(idx1); + } + + uint32 liqOffset = meshData.liquidVerts.size() / 3; + for (uint32 i = 0; i < liqVerts.size(); ++i) + meshData.liquidVerts.append(liqVerts[i].y, liqVerts[i].z, liqVerts[i].x); + + for (uint32 i = 0; i < liqTris.size() / 3; ++i) + { + meshData.liquidTris.append(liqTris[i*3+1] + liqOffset, liqTris[i*3+2] + liqOffset, liqTris[i*3] + liqOffset); + meshData.liquidType.append(type); + } + } + } + } + } + while (false); + + vmapManager->unloadMap(mapID, tileX, tileY); + delete vmapManager; + + return retval; + } + + /**************************************************************************/ + void TerrainBuilder::transform(vector &source, vector &transformedVertices, float scale, G3D::Matrix3 &rotation, Vector3 &position) + { + for (vector::iterator it = source.begin(); it != source.end(); ++it) + { + // apply tranform, then mirror along the horizontal axes + Vector3 v((*it) * rotation * scale + position); + v.x *= -1.f; + v.y *= -1.f; + transformedVertices.push_back(v); + } + } + + /**************************************************************************/ + void TerrainBuilder::copyVertices(vector &source, G3D::Array &dest) + { + for (vector::iterator it = source.begin(); it != source.end(); ++it) + { + dest.push_back((*it).y); + dest.push_back((*it).z); + dest.push_back((*it).x); + } + } + + /**************************************************************************/ + void TerrainBuilder::copyIndices(vector &source, G3D::Array &dest, int offset, bool flip) + { + if (flip) + { + for (vector::iterator it = source.begin(); it != source.end(); ++it) + { + dest.push_back((*it).idx2+offset); + dest.push_back((*it).idx1+offset); + dest.push_back((*it).idx0+offset); + } + } + else + { + for (vector::iterator it = source.begin(); it != source.end(); ++it) + { + dest.push_back((*it).idx0+offset); + dest.push_back((*it).idx1+offset); + dest.push_back((*it).idx2+offset); + } + } + } + + /**************************************************************************/ + void TerrainBuilder::copyIndices(G3D::Array &source, G3D::Array &dest, int offset) + { + int* src = source.getCArray(); + for (int32 i = 0; i < source.size(); ++i) + dest.append(src[i] + offset); + } + + /**************************************************************************/ + void TerrainBuilder::cleanVertices(G3D::Array &verts, G3D::Array &tris) + { + map vertMap; + + int* t = tris.getCArray(); + float* v = verts.getCArray(); + + // collect all the vertex indices from triangle + for (int i = 0; i < tris.size(); ++i) + { + if (vertMap.find(t[i]) != vertMap.end()) + continue; + + vertMap.insert(std::pair(t[i], 0)); + } + + // collect the vertices + G3D::Array cleanVerts; + int index, count = 0; + for (map::iterator it = vertMap.begin(); it != vertMap.end(); ++it) + { + index = (*it).first; + (*it).second = count; + cleanVerts.append(v[index*3], v[index*3+1], v[index*3+2]); + count++; + } + verts.fastClear(); + verts.append(cleanVerts); + cleanVerts.clear(); + + // update triangles to use new indices + for (int i = 0; i < tris.size(); ++i) + { + map::iterator it; + if ((it = vertMap.find(t[i])) == vertMap.end()) + continue; + + t[i] = (*it).second; + } + + vertMap.clear(); + } + + /**************************************************************************/ + void TerrainBuilder::loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, const char* offMeshFilePath) + { + // no meshfile input given? + if (offMeshFilePath == NULL) + return; + + FILE* fp = fopen(offMeshFilePath, "rb"); + if (!fp) + { + printf(" loadOffMeshConnections:: input file %s not found!\n", offMeshFilePath); + return; + } + + // pretty silly thing, as we parse entire file and load only the tile we need + // but we don't expect this file to be too large + char* buf = new char[512]; + while(fgets(buf, 512, fp)) + { + float p0[3], p1[3]; + int mid, tx, ty; + float size; + if (10 != sscanf(buf, "%d %d,%d (%f %f %f) (%f %f %f) %f", &mid, &tx, &ty, + &p0[0], &p0[1], &p0[2], &p1[0], &p1[1], &p1[2], &size)) + continue; + + if (mapID == mid, tileX == tx, tileY == ty) + { + meshData.offMeshConnections.append(p0[1]); + meshData.offMeshConnections.append(p0[2]); + meshData.offMeshConnections.append(p0[0]); + + meshData.offMeshConnections.append(p1[1]); + meshData.offMeshConnections.append(p1[2]); + meshData.offMeshConnections.append(p1[0]); + + meshData.offMeshConnectionDirs.append(1); // 1 - both direction, 0 - one sided + meshData.offMeshConnectionRads.append(size); // agent size equivalent + // can be used same way as polygon flags + meshData.offMeshConnectionsAreas.append((unsigned char)0xFF); + meshData.offMeshConnectionsFlags.append((unsigned short)0xFF); // all movement masks can make this path + } + + } + + delete [] buf; + fclose(fp); + } +} diff --git a/src/tools/mmap_extractor/TerrainBuilder.h b/src/tools/mmap_extractor/TerrainBuilder.h new file mode 100644 index 00000000000..a7f21883af2 --- /dev/null +++ b/src/tools/mmap_extractor/TerrainBuilder.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#ifndef _MMAP_TERRAIN_BUILDER_H +#define _MMAP_TERRAIN_BUILDER_H + +#include "PathCommon.h" +#include "Map.h" +#include "SharedDefines.h" + +#include "WorldModel.h" + +#include "G3D/Array.h" +#include "G3D/Vector3.h" +#include "G3D/Matrix3.h" + +using namespace Trinity; + +namespace MMAP +{ + enum Spot + { + TOP = 1, + RIGHT = 2, + LEFT = 3, + BOTTOM = 4, + ENTIRE = 5 + }; + + enum Grid + { + GRID_V8, + GRID_V9 + }; + + static const int V9_SIZE = 129; + static const int V9_SIZE_SQ = V9_SIZE*V9_SIZE; + static const int V8_SIZE = 128; + static const int V8_SIZE_SQ = V8_SIZE*V8_SIZE; + static const float GRID_SIZE = 533.33333f; + static const float GRID_PART_SIZE = GRID_SIZE/V8_SIZE; + + // see contrib/extractor/system.cpp, CONF_use_minHeight + static const float INVALID_MAP_LIQ_HEIGHT = -500.f; + static const float INVALID_MAP_LIQ_HEIGHT_MAX = 5000.0f; + + // see following files: + // contrib/extractor/system.cpp + // src/game/Map.cpp + static char const* MAP_VERSION_MAGIC = "v1.2"; + + struct MeshData + { + G3D::Array solidVerts; + G3D::Array solidTris; + + G3D::Array liquidVerts; + G3D::Array liquidTris; + G3D::Array liquidType; + + // offmesh connection data + G3D::Array offMeshConnections; // [p0y,p0z,p0x,p1y,p1z,p1x] - per connection + G3D::Array offMeshConnectionRads; + G3D::Array offMeshConnectionDirs; + G3D::Array offMeshConnectionsAreas; + G3D::Array offMeshConnectionsFlags; + }; + + class TerrainBuilder + { + public: + TerrainBuilder(bool skipLiquid); + ~TerrainBuilder(); + + void loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); + bool loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); + void loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, const char* offMeshFilePath); + + bool usesLiquids() { return !m_skipLiquid; } + + // vert and triangle methods + static void transform(vector &original, vector &transformed, + float scale, G3D::Matrix3 &rotation, G3D::Vector3 &position); + static void copyVertices(vector &source, G3D::Array &dest); + static void copyIndices(vector &source, G3D::Array &dest, int offest, bool flip); + static void copyIndices(G3D::Array &src, G3D::Array &dest, int offset); + static void cleanVertices(G3D::Array &verts, G3D::Array &tris); + private: + /// Loads a portion of a map's terrain + bool loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, Spot portion); + + /// Sets loop variables for selecting only certain parts of a map's terrain + void getLoopVars(Spot portion, int &loopStart, int &loopEnd, int &loopInc); + + /// Controls whether liquids are loaded + bool m_skipLiquid; + + /// Load the map terrain from file + bool loadHeightMap(uint32 mapID, uint32 tileX, uint32 tileY, G3D::Array &vertices, G3D::Array &triangles, Spot portion); + + /// Get the vector coordinate for a specific position + void getHeightCoord(int index, Grid grid, float xOffset, float yOffset, float* coord, float* v); + + /// Get the triangle's vector indices for a specific position + void getHeightTriangle(int square, Spot triangle, int* indices, bool liquid = false); + + /// Determines if the specific position's triangles should be rendered + bool isHole(int square, const uint16 holes[16][16]); + + /// Get the liquid vector coordinate for a specific position + void getLiquidCoord(int index, int index2, float xOffset, float yOffset, float* coord, float* v); + + /// Get the liquid type for a specific position + uint8 getLiquidType(int square, const uint8 liquid_type[16][16]); + + // hide parameterless and copy constructor + TerrainBuilder(); + TerrainBuilder(const TerrainBuilder &tb); + }; +} + +#endif + diff --git a/src/tools/mmap_extractor/VMapExtensions.cpp b/src/tools/mmap_extractor/VMapExtensions.cpp new file mode 100644 index 00000000000..4f203e11c21 --- /dev/null +++ b/src/tools/mmap_extractor/VMapExtensions.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#include +#include "MapTree.h" +#include "VMapManager2.h" +#include "WorldModel.h" +#include "ModelInstance.h" + +using namespace std; + +namespace VMAP +{ + // Need direct access to encapsulated VMAP data, so we add functions for MMAP generator + // maybe add MapBuilder as friend to all of the below classes would be better? + + // declared in src/shared/vmap/MapTree.h + void StaticMapTree::getModelInstances(ModelInstance* &models, uint32 &count) + { + models = iTreeValues; + count = iNTreeValues; + } + + // declared in src/shared/vmap/VMapManager2.h + void VMapManager2::getInstanceMapTree(InstanceTreeMap &instanceMapTree) + { + instanceMapTree = iInstanceMapTrees; + } + + // declared in src/shared/vmap/WorldModel.h + void WorldModel::getGroupModels(vector &groupModels) + { + groupModels = this->groupModels; + } + + // declared in src/shared/vmap/WorldModel.h + void GroupModel::getMeshData(vector &vertices, vector &triangles, WmoLiquid* &liquid) + { + vertices = this->vertices; + triangles = this->triangles; + liquid = iLiquid; + } + + // declared in src/shared/vmap/ModelInstance.h + WorldModel* const ModelInstance::getWorldModel() + { + return iModel; + } + + // declared in src/shared/vmap/WorldModel.h + void WmoLiquid::getPosInfo(uint32 &tilesX, uint32 &tilesY, Vector3 &corner) const + { + tilesX = iTilesX; + tilesY = iTilesY; + corner = iCorner; + } +} -- cgit v1.2.3 From eae627f75287493ee12744af51112d43a8aaa10b Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 14:51:03 +0200 Subject: Core: + add mmaps files. + add the generator for movement. --- src/server/collision/Management/MMapFactory.cpp | 80 +++ src/server/collision/Management/MMapFactory.h | 51 ++ src/server/collision/Management/MMapManager.cpp | 301 ++++++++ src/server/collision/Management/MMapManager.h | 84 +++ .../PathFinderMovementGenerator.cpp | 780 +++++++++++++++++++++ .../PathFinderMovementGenerator.h | 135 ++++ 6 files changed, 1431 insertions(+) create mode 100644 src/server/collision/Management/MMapFactory.cpp create mode 100644 src/server/collision/Management/MMapFactory.h create mode 100644 src/server/collision/Management/MMapManager.cpp create mode 100644 src/server/collision/Management/MMapManager.h create mode 100644 src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp create mode 100644 src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h (limited to 'src') diff --git a/src/server/collision/Management/MMapFactory.cpp b/src/server/collision/Management/MMapFactory.cpp new file mode 100644 index 00000000000..f4b2f3d47e4 --- /dev/null +++ b/src/server/collision/Management/MMapFactory.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2010 MaNGOS + * + * 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 2 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 . + */ + +#include "MMapFactory.h" +#include "World.h" +#include "Config.h" +#include + +namespace MMAP +{ + // ######################## MMapFactory ######################## + // our global singleton copy + MMapManager *g_MMapManager = NULL; + + // stores list of mapids which do not use pathfinding + std::set* g_mmapDisabledIds = NULL; + + MMapManager* MMapFactory::createOrGetMMapManager() + { + if (g_MMapManager == NULL) + g_MMapManager = new MMapManager(); + + return g_MMapManager; + } + + void MMapFactory::preventPathfindingOnMaps(const char* ignoreMapIds) + { + if (!g_mmapDisabledIds) + g_mmapDisabledIds = new std::set(); + + uint32 strLenght = strlen(ignoreMapIds)+1; + char* mapList = new char[strLenght]; + memcpy(mapList, ignoreMapIds, sizeof(char)*strLenght); + + char* idstr = strtok(mapList, ","); + while (idstr) + { + g_mmapDisabledIds->insert(uint32(atoi(idstr))); + idstr = strtok(NULL, ","); + } + + delete[] mapList; + } + + bool MMapFactory::IsPathfindingEnabled(uint32 mapId) + { + return sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) + && g_mmapDisabledIds->find(mapId) == g_mmapDisabledIds->end(); + } + + void MMapFactory::clear() + { + if (g_mmapDisabledIds) + { + delete g_mmapDisabledIds; + g_mmapDisabledIds = NULL; + } + + if (g_MMapManager) + { + delete g_MMapManager; + g_MMapManager = NULL; + } + } +} \ No newline at end of file diff --git a/src/server/collision/Management/MMapFactory.h b/src/server/collision/Management/MMapFactory.h new file mode 100644 index 00000000000..ab047333a19 --- /dev/null +++ b/src/server/collision/Management/MMapFactory.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2010 MaNGOS + * + * 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 2 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 . + */ + +#ifndef _MMAP_FACTORY_H +#define _MMAP_FACTORY_H + +#include "MMapManager.h" +#include "UnorderedMap.h" +#include "DetourAlloc.h" +#include "DetourNavMesh.h" +#include "DetourNavMeshQuery.h" + +namespace MMAP +{ + enum MMAP_LOAD_RESULT + { + MMAP_LOAD_RESULT_ERROR, + MMAP_LOAD_RESULT_OK, + MMAP_LOAD_RESULT_IGNORED, + }; + + // static class + // holds all mmap global data + // access point to MMapManager singleton + class MMapFactory + { + public: + static MMapManager* createOrGetMMapManager(); + static void clear(); + static void preventPathfindingOnMaps(const char* ignoreMapIds); + static bool IsPathfindingEnabled(uint32 mapId); + }; +} + +#endif + diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp new file mode 100644 index 00000000000..aac5647a6de --- /dev/null +++ b/src/server/collision/Management/MMapManager.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2010 MaNGOS + * + * 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 2 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 . + */ + +#include "MMapManager.h" +#include "Log.h" +#include "World.h" + +namespace MMAP +{ + // ######################## MMapManager ######################## + MMapManager::~MMapManager() + { + for (MMapDataSet::iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i) + delete i->second; + + // by now we should not have maps loaded + // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost! + } + + bool MMapManager::loadMapData(uint32 mapId) + { + // we already have this map loaded? + if (loadedMMaps.find(mapId) != loadedMMaps.end()) + return true; + + // load and init dtNavMesh - read parameters from file + uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap")+1; + char *fileName = new char[pathLen]; + snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i.mmap").c_str(), mapId); + + FILE* file = fopen(fileName, "rb"); + if (!file) + { + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName); + delete [] fileName; + return false; + } + + dtNavMeshParams params; + fread(¶ms, sizeof(dtNavMeshParams), 1, file); + fclose(file); + + dtNavMesh* mesh = dtAllocNavMesh(); + ASSERT(mesh); + if (DT_SUCCESS != mesh->init(¶ms)) + { + dtFreeNavMesh(mesh); + sLog->outError("MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName); + delete [] fileName; + return false; + } + + delete [] fileName; + + sLog->outDetail("MMAP:loadMapData: Loaded %03i.mmap", mapId); + + // store inside our map list + MMapData* mmap_data = new MMapData(mesh); + mmap_data->mmapLoadedTiles.clear(); + + loadedMMaps.insert(std::pair(mapId, mmap_data)); + return true; + } + + uint32 MMapManager::packTileID(int32 x, int32 y) + { + return uint32(x << 16 | y); + } + + bool MMapManager::loadMap(uint32 mapId, int32 x, int32 y) + { + // make sure the mmap is loaded and ready to load tiles + if(!loadMapData(mapId)) + return false; + + // get this mmap data + MMapData* mmap = loadedMMaps[mapId]; + ASSERT(mmap->navMesh); + + // check if we already have this tile loaded + uint32 packedGridPos = packTileID(x, y); + if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end()) + { + //sLog->outError("MMAP:loadMap: Asked to load already loaded navmesh tile. %03u%02i%02i.mmtile", mapId, y, x); + return false; + } + + // load this tile :: mmaps/MMMXXYY.mmtile + uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1; + char *fileName = new char[pathLen]; + // this change of y and x is needed because of mapbuilder.cpp (x and y are swapped there) so change it here so we dont need to re-extract. All swappes are done in other files. DONT CHANGE THIS! + snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, y, x); + + FILE *file = fopen(fileName, "rb"); + if (!file) + { + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:loadMap: Could not open mmtile file '%s'", fileName); + delete [] fileName; + return false; + } + delete [] fileName; + + // read header + MmapTileHeader fileHeader; + fread(&fileHeader, sizeof(MmapTileHeader), 1, file); + + if (fileHeader.mmapMagic != MMAP_MAGIC) + { + sLog->outError("MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, y, x); + return false; + } + + if (fileHeader.mmapVersion != MMAP_VERSION) + { + sLog->outError("MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", + mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION); + return false; + } + + unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM); + ASSERT(data); + + size_t result = fread(data, fileHeader.size, 1, file); + if(!result) + { + sLog->outError("MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, y, x); + fclose(file); + return false; + } + + fclose(file); + + dtMeshHeader* header = (dtMeshHeader*)data; + dtTileRef tileRef = 0; + + // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed + if (DT_SUCCESS == mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)) + { + mmap->mmapLoadedTiles.insert(std::pair(packedGridPos, tileRef)); + ++loadedTiles; + sLog->outDetail("MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, y, x, mapId, header->x, header->y); + return true; + } + else + { + sLog->outError("MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, y, x); + dtFree(data); + return false; + } + + return false; + } + + bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y) + { + // check if we have this map loaded + if (loadedMMaps.find(mapId) == loadedMMaps.end()) + { + // file may not exist, therefore not loaded + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, y, x); + return false; + } + + MMapData* mmap = loadedMMaps[mapId]; + + // check if we have this tile loaded + uint32 packedGridPos = packTileID(x, y); + if (mmap->mmapLoadedTiles.find(packedGridPos) == mmap->mmapLoadedTiles.end()) + { + // file may not exist, therefore not loaded + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, y, x); + return false; + } + + dtTileRef tileRef = mmap->mmapLoadedTiles[packedGridPos]; + + // unload, and mark as non loaded + if (DT_SUCCESS != mmap->navMesh->removeTile(tileRef, NULL, NULL)) + { + // this is technically a memory leak + // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used + // we cannot recover from this error - assert out + sLog->outError("MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, y, x); + ASSERT(false); + } + else + { + mmap->mmapLoadedTiles.erase(packedGridPos); + --loadedTiles; + sLog->outDetail("MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, y, x, mapId); + return true; + } + + return false; + } + + bool MMapManager::unloadMap(uint32 mapId) + { + if (loadedMMaps.find(mapId) == loadedMMaps.end()) + { + // file may not exist, therefore not loaded + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId); + return false; + } + + // unload all tiles from given map + MMapData* mmap = loadedMMaps[mapId]; + for (MMapTileSet::iterator i = mmap->mmapLoadedTiles.begin(); i != mmap->mmapLoadedTiles.end(); ++i) + { + uint32 x = (i->first >> 16); + uint32 y = (i->first & 0x0000FFFF); + if (DT_SUCCESS != mmap->navMesh->removeTile(i->second, NULL, NULL)) + sLog->outError("MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, y, x); + else + { + --loadedTiles; + sLog->outDetail("MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, y, x, mapId); + } + } + + delete mmap; + loadedMMaps.erase(mapId); + sLog->outDetail("MMAP:unloadMap: Unloaded %03i.mmap", mapId); + + return true; + } + + bool MMapManager::unloadMapInstance(uint32 mapId, uint32 instanceId) + { + // check if we have this map loaded + if (loadedMMaps.find(mapId) == loadedMMaps.end()) + { + // file may not exist, therefore not loaded + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId); + return false; + } + + MMapData* mmap = loadedMMaps[mapId]; + if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) + { + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId); + return false; + } + + dtNavMeshQuery* query = mmap->navMeshQueries[instanceId]; + + dtFreeNavMeshQuery(query); + mmap->navMeshQueries.erase(instanceId); + sLog->outDetail("MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId); + + return true; + } + + dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId) + { + if (loadedMMaps.find(mapId) == loadedMMaps.end()) + return NULL; + + return loadedMMaps[mapId]->navMesh; + } + + dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId) + { + if (loadedMMaps.find(mapId) == loadedMMaps.end()) + return NULL; + + MMapData* mmap = loadedMMaps[mapId]; + if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) + { + // allocate mesh query + dtNavMeshQuery* query = dtAllocNavMeshQuery(); + ASSERT(query); + if (DT_SUCCESS != query->init(mmap->navMesh, 1024)) + { + dtFreeNavMeshQuery(query); + sLog->outError("MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + return NULL; + } + + sLog->outDetail("MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + mmap->navMeshQueries.insert(std::pair(instanceId, query)); + } + + return mmap->navMeshQueries[instanceId]; + } +} \ No newline at end of file diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h new file mode 100644 index 00000000000..8af452032d1 --- /dev/null +++ b/src/server/collision/Management/MMapManager.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2010 MaNGOS + * + * 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 2 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 . + */ + +#ifndef _MMAP_MANAGER_H +#define _MMAP_MANAGER_H + +#include "UnorderedMap.h" +#include "DetourAlloc.h" +#include "DetourNavMesh.h" +#include "DetourNavMeshQuery.h" + +// move map related classes +namespace MMAP +{ + typedef UNORDERED_MAP MMapTileSet; + typedef UNORDERED_MAP NavMeshQuerySet; + + // dummy struct to hold map's mmap data + struct MMapData + { + MMapData(dtNavMesh* mesh) : navMesh(mesh) {} + ~MMapData() + { + for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i) + dtFreeNavMeshQuery(i->second); + + if (navMesh) + dtFreeNavMesh(navMesh); + } + + dtNavMesh* navMesh; + + // we have to use single dtNavMeshQuery for every instance, since those are not thread safe + NavMeshQuerySet navMeshQueries; // instanceId to query + MMapTileSet mmapLoadedTiles; // maps [map grid coords] to [dtTile] + }; + + + typedef UNORDERED_MAP MMapDataSet; + + // singleton class + // holds all all access to mmap loading unloading and meshes + class MMapManager + { + public: + MMapManager() : loadedTiles(0) {} + ~MMapManager(); + + bool loadMap(uint32 mapId, int32 x, int32 y); + bool unloadMap(uint32 mapId, int32 x, int32 y); + bool unloadMap(uint32 mapId); + bool unloadMapInstance(uint32 mapId, uint32 instanceId); + + // the returned [dtNavMeshQuery const*] is NOT threadsafe + dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId); + dtNavMesh const* GetNavMesh(uint32 mapId); + + uint32 getLoadedTilesCount() const { return loadedTiles; } + uint32 getLoadedMapsCount() const { return loadedMMaps.size(); } + private: + bool loadMapData(uint32 mapId); + uint32 packTileID(int32 x, int32 y); + + MMapDataSet loadedMMaps; + uint32 loadedTiles; + }; +} + +#endif \ No newline at end of file diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp new file mode 100644 index 00000000000..686c57cb634 --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp @@ -0,0 +1,780 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "PathFinderMovementGenerator.h" +#include "Map.h" +#include "Creature.h" +#include "MMapFactory.h" +#include "MMapManager.h" +#include "Log.h" + +#include "DetourCommon.h" +#include "DetourNavMeshQuery.h" + +////////////////// PathFinderMovementGenerator ////////////////// +PathFinderMovementGenerator::PathFinderMovementGenerator(const Unit* owner) : + m_polyLength(0), m_type(PATHFIND_BLANK), + m_useStraightPath(false), m_forceDestination(false), m_pointPathLimit(MAX_POINT_PATH_LENGTH), + m_sourceUnit(owner), m_navMesh(NULL), m_navMeshQuery(NULL) +{ + sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::PathFinderMovementGenerator for %u \n", m_sourceUnit->GetGUIDLow()); + + uint32 mapId = m_sourceUnit->GetMapId(); + if (MMAP::MMapFactory::IsPathfindingEnabled(mapId)) + { + MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); + m_navMesh = mmap->GetNavMesh(mapId); + m_navMeshQuery = mmap->GetNavMeshQuery(mapId, m_sourceUnit->GetInstanceId()); + } + + createFilter(); +} + +PathFinderMovementGenerator::~PathFinderMovementGenerator() +{ + sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::~PathFinderMovementGenerator() for %u \n", m_sourceUnit->GetGUIDLow()); +} + +bool PathFinderMovementGenerator::calculate(float destX, float destY, float destZ, bool forceDest) +{ + if (!Trinity::IsValidMapCoord(destX, destY, destZ) || + !Trinity::IsValidMapCoord(m_sourceUnit->GetPositionX(), m_sourceUnit->GetPositionY(), m_sourceUnit->GetPositionZ())) + return false; + + Vector3 oldDest = getEndPosition(); + Vector3 dest(destX, destY, destZ); + setEndPosition(dest); + + float x, y, z; + m_sourceUnit->GetPosition(x, y, z); + Vector3 start(x, y, z); + setStartPosition(start); + + m_forceDestination = forceDest; + + sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); + + // make sure navMesh works - we can run on map w/o mmap + // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) + if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->HasUnitState(UNIT_STAT_IGNORE_PATHFINDING) || + !HaveTile(start) || !HaveTile(dest)) + { + BuildShortcut(); + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + return true; + } + + updateFilter(); + + // check if destination moved - if not we can optimize something here + // we are following old, precalculated path? + float dist = m_sourceUnit->GetObjectSize(); + if (inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) + { + // our target is not moving - we just coming closer + // we are moving on precalculated path - enjoy the ride + sLog->outStaticDebug("++ PathFinderMovementGenerator::calculate:: precalculated path\n"); + + m_pathPoints.erase(m_pathPoints.begin()); + return false; + } + else + { + // target moved, so we need to update the poly path + BuildPolyPath(start, dest); + return true; + } +} + +dtPolyRef PathFinderMovementGenerator::getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance) const +{ + if (!polyPath || !polyPathSize) + return INVALID_POLYREF; + + dtPolyRef nearestPoly = INVALID_POLYREF; + float minDist2d = FLT_MAX; + float minDist3d = 0.0f; + + for (uint32 i = 0; i < polyPathSize; ++i) + { + float closestPoint[VERTEX_SIZE]; + if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint)) + continue; + + float d = dtVdist2DSqr(point, closestPoint); + if (d < minDist2d) + { + minDist2d = d; + nearestPoly = polyPath[i]; + minDist3d = dtVdistSqr(point, closestPoint); + } + + if(minDist2d < 1.0f) // shortcut out - close enough for us + break; + } + + if (distance) + *distance = dtSqrt(minDist3d); + + return (minDist2d < 3.0f) ? nearestPoly : INVALID_POLYREF; +} + +dtPolyRef PathFinderMovementGenerator::getPolyByLocation(const float* point, float *distance) const +{ + // first we check the current path + // if the current path doesn't contain the current poly, + // we need to use the expensive navMesh.findNearestPoly + dtPolyRef polyRef = getPathPolyByPosition(m_pathPolyRefs, m_polyLength, point, distance); + if (polyRef != INVALID_POLYREF) + return polyRef; + + // we don't have it in our old path + // try to get it by findNearestPoly() + // first try with low search box + float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area + float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f}; + dtStatus result = m_navMeshQuery->findNearestPoly(point, extents, &m_filter, &polyRef, closestPoint); + if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) + { + *distance = dtVdist(closestPoint, point); + return polyRef; + } + + // still nothing .. + // try with bigger search box + extents[1] = 200.0f; + result = m_navMeshQuery->findNearestPoly(point, extents, &m_filter, &polyRef, closestPoint); + if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) + { + *distance = dtVdist(closestPoint, point); + return polyRef; + } + + return INVALID_POLYREF; +} + +void PathFinderMovementGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos) +{ + // *** getting start/end poly logic *** + + float distToStartPoly, distToEndPoly; + float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x}; + float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x}; + + dtPolyRef startPoly = getPolyByLocation(startPoint, &distToStartPoly); + dtPolyRef endPoly = getPolyByLocation(endPoint, &distToEndPoly); + + // we have a hole in our mesh + // make shortcut path and mark it as NOPATH ( with flying exception ) + // its up to caller how he will use this info + if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); + BuildShortcut(); + m_type = (m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->canFly()) + ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; + return; + } + + // we may need a better number here + bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f); + if (farFromPoly) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly); + + bool buildShotrcut = false; + if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) + { + Creature* owner = (Creature*)m_sourceUnit; + + Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos; + if (m_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: underWater case\n"); + if (owner->canSwim()) + buildShotrcut = true; + } + else + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: flying case\n"); + if (owner->canFly()) + buildShotrcut = true; + } + } + + if (buildShotrcut) + { + BuildShortcut(); + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + return; + } + else + { + float closestPoint[VERTEX_SIZE]; + // we may want to use closestPointOnPolyBoundary instead + if (DT_SUCCESS == m_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) + { + dtVcopy(endPoint, closestPoint); + setActualEndPosition(Vector3(endPoint[2],endPoint[0],endPoint[1])); + } + + m_type = PATHFIND_INCOMPLETE; + } + } + + // *** poly path generating logic *** + + // start and end are on same polygon + // just need to move in straight line + if (startPoly == endPoly) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == endPoly)\n"); + + BuildShortcut(); + + m_pathPolyRefs[0] = startPoly; + m_polyLength = 1; + + m_type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL; + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: path type %d\n", m_type); + return; + } + + // look for startPoly/endPoly in current path + // TODO: we can merge it with getPathPolyByPosition() loop + bool startPolyFound = false; + bool endPolyFound = false; + uint32 pathStartIndex, pathEndIndex; + + if (m_polyLength) + { + for (pathStartIndex = 0; pathStartIndex < m_polyLength; ++pathStartIndex) + { + // here to carch few bugs + ASSERT(m_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); + + if (m_pathPolyRefs[pathStartIndex] == startPoly) + { + startPolyFound = true; + break; + } + } + + for (pathEndIndex = m_polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) + if (m_pathPolyRefs[pathEndIndex] == endPoly) + { + endPolyFound = true; + break; + } + } + + if (startPolyFound && endPolyFound) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPolyFound && endPolyFound)\n"); + + // we moved along the path and the target did not move out of our old poly-path + // our path is a simple subpath case, we have all the data we need + // just "cut" it out + + m_polyLength = pathEndIndex - pathStartIndex + 1; + memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, m_polyLength*sizeof(dtPolyRef)); + } + else if (startPolyFound && !endPolyFound) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n"); + + // we are moving on the old path but target moved out + // so we have atleast part of poly-path ready + + m_polyLength -= pathStartIndex; + + // try to adjust the suffix of the path instead of recalculating entire length + // at given interval the target cannot get too far from its last location + // thus we have less poly to cover + // sub-path of optimal path is optimal + + // take ~80% of the original length + // TODO : play with the values here + uint32 prefixPolyLength = uint32(m_polyLength*0.8f + 0.5f); + memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, prefixPolyLength*sizeof(dtPolyRef)); + + dtPolyRef suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; + + // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data + float suffixEndPoint[VERTEX_SIZE]; + if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) + { + // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that + // try to recover by using prev polyref + --prefixPolyLength; + suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; + if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) + { + // suffixStartPoly is still invalid, error state + BuildShortcut(); + m_type = PATHFIND_NOPATH; + return; + } + } + + // generate suffix + uint32 suffixPolyLength = 0; + dtStatus dtResult = m_navMeshQuery->findPath( + suffixStartPoly, // start polygon + endPoly, // end polygon + suffixEndPoint, // start position + endPoint, // end position + &m_filter, // polygon search filter + m_pathPolyRefs + prefixPolyLength - 1, // [out] path + (int*)&suffixPolyLength, + MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path + + if (!suffixPolyLength || dtResult != DT_SUCCESS) + { + // this is probably an error state, but we'll leave it + // and hopefully recover on the next Update + // we still need to copy our preffix + sLog->outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); + } + + sLog->outDebug(LOG_FILTER_MAPS, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength); + + // new path = prefix + suffix - overlap + m_polyLength = prefixPolyLength + suffixPolyLength - 1; + } + else + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n"); + + // either we have no path at all -> first run + // or something went really wrong -> we aren't moving along the path to the target + // just generate new path + + // free and invalidate old path data + clear(); + + dtStatus dtResult = m_navMeshQuery->findPath( + startPoly, // start polygon + endPoly, // end polygon + startPoint, // start position + endPoint, // end position + &m_filter, // polygon search filter + m_pathPolyRefs, // [out] path + (int*)&m_polyLength, + MAX_PATH_LENGTH); // max number of polygons in output path + + if (!m_polyLength || dtResult != DT_SUCCESS) + { + // only happens if we passed bad data to findPath(), or navmesh is messed up + sLog->outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); + BuildShortcut(); + m_type = PATHFIND_NOPATH; + return; + } + } + + // by now we know what type of path we can get + if (m_pathPolyRefs[m_polyLength - 1] == endPoly && !(m_type & PATHFIND_INCOMPLETE)) + m_type = PATHFIND_NORMAL; + else + m_type = PATHFIND_INCOMPLETE; + + // generate the point-path out of our up-to-date poly-path + BuildPointPath(startPoint, endPoint); +} + +void PathFinderMovementGenerator::BuildPointPath(const float *startPoint, const float *endPoint) +{ + float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; + uint32 pointCount = 0; + dtStatus dtResult = DT_FAILURE; + if (m_useStraightPath) + { + dtResult = m_navMeshQuery->findStraightPath( + startPoint, // start position + endPoint, // end position + m_pathPolyRefs, // current path + m_polyLength, // lenth of current path + pathPoints, // [out] path corner points + NULL, // [out] flags + NULL, // [out] shortened path + (int*)&pointCount, + m_pointPathLimit); // maximum number of points/polygons to use + } + else + { + dtResult = findSmoothPath( + startPoint, // start position + endPoint, // end position + m_pathPolyRefs, // current path + m_polyLength, // length of current path + pathPoints, // [out] path corner points + (int*)&pointCount, + m_pointPathLimit); // maximum number of points + } + + if (pointCount < 2 || dtResult != DT_SUCCESS) + { + // only happens if pass bad data to findStraightPath or navmesh is broken + // single point paths can be generated here + // TODO : check the exact cases + sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount); + BuildShortcut(); + m_type = PATHFIND_NOPATH; + return; + } + + m_pathPoints.resize(pointCount); + for (uint32 i = 0; i < pointCount; ++i) + m_pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); + + // first point is always our current location - we need the next one + setActualEndPosition(m_pathPoints[pointCount-1]); + + // force the given destination, if needed + if(m_forceDestination && + (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f))) + { + // we may want to keep partial subpath + if(dist3DSqr(getActualEndPosition(), getEndPosition()) < + 0.3f * dist3DSqr(getStartPosition(), getEndPosition())) + { + setActualEndPosition(getEndPosition()); + m_pathPoints[m_pathPoints.size()-1] = getEndPosition(); + } + else + { + setActualEndPosition(getEndPosition()); + BuildShortcut(); + } + + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + } + + sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); +} + +void PathFinderMovementGenerator::BuildShortcut() +{ + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildShortcut :: making shortcut\n"); + + clear(); + + // make two point path, our curr pos is the start, and dest is the end + m_pathPoints.resize(2); + + // set start and a default next position + m_pathPoints[0] = getStartPosition(); + m_pathPoints[1] = getActualEndPosition(); + + m_type = PATHFIND_SHORTCUT; +} + +void PathFinderMovementGenerator::createFilter() +{ + uint16 includeFlags = 0; + uint16 excludeFlags = 0; + + if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) + { + Creature* creature = (Creature*)m_sourceUnit; + if (creature->canWalk()) + includeFlags |= NAV_GROUND; // walk + + // creatures don't take environmental damage + if (creature->canSwim()) + includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim + } + else if (m_sourceUnit->GetTypeId() == TYPEID_PLAYER) + { + // perfect support not possible, just stay 'safe' + includeFlags |= (NAV_GROUND | NAV_WATER); + } + + m_filter.setIncludeFlags(includeFlags); + m_filter.setExcludeFlags(excludeFlags); + + updateFilter(); +} + +void PathFinderMovementGenerator::updateFilter() +{ + // allow creatures to cheat and use different movement types if they are moved + // forcefully into terrain they can't normally move in + if (m_sourceUnit->IsInWater() || m_sourceUnit->IsUnderWater()) + { + uint16 includedFlags = m_filter.getIncludeFlags(); + includedFlags |= getNavTerrain(m_sourceUnit->GetPositionX(), + m_sourceUnit->GetPositionY(), + m_sourceUnit->GetPositionZ()); + + m_filter.setIncludeFlags(includedFlags); + } +} + +NavTerrain PathFinderMovementGenerator::getNavTerrain(float x, float y, float z) +{ + LiquidData data; + m_sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); + + switch (data.type) + { + case MAP_LIQUID_TYPE_WATER: + case MAP_LIQUID_TYPE_OCEAN: + return NAV_WATER; + case MAP_LIQUID_TYPE_MAGMA: + return NAV_MAGMA; + case MAP_LIQUID_TYPE_SLIME: + return NAV_SLIME; + default: + return NAV_GROUND; + } +} + +bool PathFinderMovementGenerator::HaveTile(const Vector3 &p) const +{ + int tx, ty; + float point[VERTEX_SIZE] = {p.y, p.z, p.x}; + + m_navMesh->calcTileLoc(point, &tx, &ty); + return (m_navMesh->getTileAt(tx, ty) != NULL); +} + +uint32 PathFinderMovementGenerator::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, + const dtPolyRef* visited, uint32 nvisited) +{ + int32 furthestPath = -1; + int32 furthestVisited = -1; + + // Find furthest common polygon. + for (int32 i = npath-1; i >= 0; --i) + { + bool found = false; + for (int32 j = nvisited-1; j >= 0; --j) + { + if (path[i] == visited[j]) + { + furthestPath = i; + furthestVisited = j; + found = true; + } + } + if (found) + break; + } + + // If no intersection found just return current path. + if (furthestPath == -1 || furthestVisited == -1) + return npath; + + // Concatenate paths. + + // Adjust beginning of the buffer to include the visited. + uint32 req = nvisited - furthestVisited; + uint32 orig = uint32(furthestPath+1) < npath ? furthestPath+1 : npath; + uint32 size = npath-orig > 0 ? npath-orig : 0; + if (req+size > maxPath) + size = maxPath-req; + + if (size) + memmove(path+req, path+orig, size*sizeof(dtPolyRef)); + + // Store visited + for (uint32 i = 0; i < req; ++i) + path[i] = visited[(nvisited-1)-i]; + + return req+size; +} + +bool PathFinderMovementGenerator::getSteerTarget(const float* startPos, const float* endPos, + float minTargetDist, const dtPolyRef* path, uint32 pathSize, + float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef) +{ + // Find steer target. + static const uint32 MAX_STEER_POINTS = 3; + float steerPath[MAX_STEER_POINTS*VERTEX_SIZE]; + unsigned char steerPathFlags[MAX_STEER_POINTS]; + dtPolyRef steerPathPolys[MAX_STEER_POINTS]; + uint32 nsteerPath = 0; + dtStatus dtResult = m_navMeshQuery->findStraightPath(startPos, endPos, path, pathSize, + steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS); + if (!nsteerPath || DT_SUCCESS != dtResult) + return false; + + // Find vertex far enough to steer to. + uint32 ns = 0; + while (ns < nsteerPath) + { + // Stop at Off-Mesh link or when point is further than slop away. + if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || + !inRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f)) + break; + ns++; + } + // Failed to find good point to steer to. + if (ns >= nsteerPath) + return false; + + dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]); + steerPos[1] = startPos[1]; // keep Z value + steerPosFlag = steerPathFlags[ns]; + steerPosRef = steerPathPolys[ns]; + + return true; +} + +dtStatus PathFinderMovementGenerator::findSmoothPath(const float* startPos, const float* endPos, + const dtPolyRef* polyPath, uint32 polyPathSize, + float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize) +{ + *smoothPathSize = 0; + uint32 nsmoothPath = 0; + + dtPolyRef polys[MAX_PATH_LENGTH]; + memcpy(polys, polyPath, sizeof(dtPolyRef)*polyPathSize); + uint32 npolys = polyPathSize; + + float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE]; + if (DT_SUCCESS != m_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos)) + return DT_FAILURE; + + if (DT_SUCCESS != m_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos)) + return DT_FAILURE; + + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); + nsmoothPath++; + + // Move towards target a small advancement at a time until target reached or + // when ran out of memory to store the path. + while (npolys && nsmoothPath < maxSmoothPathSize) + { + // Find location to steer towards. + float steerPos[VERTEX_SIZE]; + unsigned char steerPosFlag; + dtPolyRef steerPosRef = INVALID_POLYREF; + + if (!getSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef)) + break; + + bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END); + bool offMeshConnection = (steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION); + + // Find movement delta. + float delta[VERTEX_SIZE]; + dtVsub(delta, steerPos, iterPos); + float len = dtSqrt(dtVdot(delta,delta)); + // If the steer target is end of path or off-mesh link, do not move past the location. + if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE) + len = 1.0f; + else + len = SMOOTH_PATH_STEP_SIZE / len; + + float moveTgt[VERTEX_SIZE]; + dtVmad(moveTgt, iterPos, delta, len); + + // Move + float result[VERTEX_SIZE]; + const static uint32 MAX_VISIT_POLY = 16; + dtPolyRef visited[MAX_VISIT_POLY]; + + uint32 nvisited = 0; + m_navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &m_filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY); + npolys = fixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited); + + m_navMeshQuery->getPolyHeight(polys[0], result, &result[1]); + result[1] += 0.5f; + dtVcopy(iterPos, result); + + // Handle end of path and off-mesh links when close enough. + if (endOfPath && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) + { + // Reached end of path. + dtVcopy(iterPos, targetPos); + if (nsmoothPath < maxSmoothPathSize) + { + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); + nsmoothPath++; + } + break; + } + else if (offMeshConnection && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) + { + // Advance the path up to and over the off-mesh connection. + dtPolyRef prevRef = INVALID_POLYREF; + dtPolyRef polyRef = polys[0]; + uint32 npos = 0; + while (npos < npolys && polyRef != steerPosRef) + { + prevRef = polyRef; + polyRef = polys[npos]; + npos++; + } + + for (uint32 i = npos; i < npolys; ++i) + polys[i-npos] = polys[i]; + + npolys -= npos; + + // Handle the connection. + float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE]; + if (DT_SUCCESS == m_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos)) + { + if (nsmoothPath < maxSmoothPathSize) + { + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos); + nsmoothPath++; + } + // Move position at the other side of the off-mesh link. + dtVcopy(iterPos, endPos); + m_navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]); + iterPos[1] += 0.5f; + } + } + + // Store results. + if (nsmoothPath < maxSmoothPathSize) + { + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); + nsmoothPath++; + } + } + + *smoothPathSize = nsmoothPath; + + // this is most likely a loop + return nsmoothPath < MAX_POINT_PATH_LENGTH ? DT_SUCCESS : DT_FAILURE; +} + +bool PathFinderMovementGenerator::inRangeYZX(const float* v1, const float* v2, float r, float h) const +{ + const float dx = v2[0] - v1[0]; + const float dy = v2[1] - v1[1]; // elevation + const float dz = v2[2] - v1[2]; + return (dx*dx + dz*dz) < r*r && fabsf(dy) < h; +} + +bool PathFinderMovementGenerator::inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const +{ + Vector3 d = p1-p2; + return (d.x*d.x + d.y*d.y) < r*r && fabsf(d.z) < h; +} + +float PathFinderMovementGenerator::dist3DSqr(const Vector3 &p1, const Vector3 &p2) const +{ + return (p1-p2).squaredLength(); +} diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h new file mode 100644 index 00000000000..f4edd1a1789 --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PATH_INFO_H +#define _PATH_INFO_H + +#include "SharedDefines.h" +#include "DetourNavMesh.h" +#include "DetourNavMeshQuery.h" +#include "MoveSplineInitArgs.h" + +using Movement::Vector3; +using Movement::PointsArray; + +class Unit; + +// 74*4.0f=296y number_of_points*interval = max_path_len +// this is way more than actual evade range +// I think we can safely cut those down even more +#define MAX_PATH_LENGTH 74 +#define MAX_POINT_PATH_LENGTH 74 + +#define SMOOTH_PATH_STEP_SIZE 4.0f +#define SMOOTH_PATH_SLOP 0.3f + +#define VERTEX_SIZE 3 +#define INVALID_POLYREF 0 + +enum PathType +{ + PATHFIND_BLANK = 0x0000, // path not built yet + PATHFIND_NORMAL = 0x0001, // normal path + PATHFIND_SHORTCUT = 0x0002, // travel through obstacles, terrain, air, etc (old behavior) + PATHFIND_INCOMPLETE = 0x0004, // we have partial path to follow - getting closer to target + PATHFIND_NOPATH = 0x0008, // no valid path at all or error in generating one + PATHFIND_NOT_USING_PATH = 0x0010 // used when we are either flying/swiming or on map w/o mmaps +}; + +class PathFinderMovementGenerator +{ + public: + PathFinderMovementGenerator(Unit const* owner); + ~PathFinderMovementGenerator(); + + // Calculate the path from owner to given destination + // return: true if new path was calculated, false otherwise (no change needed) + bool calculate(float destX, float destY, float destZ, bool forceDest = false); + + // option setters - use optional + void setUseStrightPath(bool useStraightPath) { m_useStraightPath = useStraightPath; }; + void setPathLengthLimit(float distance) { m_pointPathLimit = std::min(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }; + + // result getters + Vector3 getStartPosition() const { return m_startPosition; } + Vector3 getEndPosition() const { return m_endPosition; } + Vector3 getActualEndPosition() const { return m_actualEndPosition; } + + PointsArray& getPath() { return m_pathPoints; } + PathType getPathType() const { return m_type; } + + private: + + dtPolyRef m_pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references + uint32 m_polyLength; // number of polygons in the path + + PointsArray m_pathPoints; // our actual (x,y,z) path to the target + PathType m_type; // tells what kind of path this is + + bool m_useStraightPath; // type of path will be generated + bool m_forceDestination; // when set, we will always arrive at given point + uint32 m_pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH) + + Vector3 m_startPosition; // {x, y, z} of current location + Vector3 m_endPosition; // {x, y, z} of the destination + Vector3 m_actualEndPosition;// {x, y, z} of the closest possible point to given destination + + const Unit* const m_sourceUnit; // the unit that is moving + const dtNavMesh* m_navMesh; // the nav mesh + const dtNavMeshQuery* m_navMeshQuery; // the nav mesh query used to find the path + + dtQueryFilter m_filter; // use single filter for all movements, update it when needed + + void setStartPosition(Vector3 point) { m_startPosition = point; } + void setEndPosition(Vector3 point) { m_actualEndPosition = point; m_endPosition = point; } + void setActualEndPosition(Vector3 point) { m_actualEndPosition = point; } + + void clear() + { + m_polyLength = 0; + m_pathPoints.clear(); + } + + bool inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const; + float dist3DSqr(const Vector3 &p1, const Vector3 &p2) const; + bool inRangeYZX(const float* v1, const float* v2, float r, float h) const; + + dtPolyRef getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance = NULL) const; + dtPolyRef getPolyByLocation(const float* point, float *distance) const; + bool HaveTile(const Vector3 &p) const; + + void BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos); + void BuildPointPath(const float *startPoint, const float *endPoint); + void BuildShortcut(); + + NavTerrain getNavTerrain(float x, float y, float z); + void createFilter(); + void updateFilter(); + + // smooth path aux functions + uint32 fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, + const dtPolyRef* visited, uint32 nvisited); + bool getSteerTarget(const float* startPos, const float* endPos, float minTargetDist, + const dtPolyRef* path, uint32 pathSize, float* steerPos, + unsigned char& steerPosFlag, dtPolyRef& steerPosRef); + dtStatus findSmoothPath(const float* startPos, const float* endPos, + const dtPolyRef* polyPath, uint32 polyPathSize, + float* smoothPath, int* smoothPathSize, uint32 smoothPathMaxSize); +}; + +#endif -- cgit v1.2.3 From d6bddc1c94427b325d9b4fd842562c5d8ae2f0c9 Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 15:11:39 +0200 Subject: Core/Mmaps: * implemented loading part. --- src/server/collision/CMakeLists.txt | 2 ++ src/server/collision/Management/VMapManager2.h | 2 ++ src/server/collision/Maps/MapTree.h | 1 + src/server/collision/Models/ModelInstance.h | 2 ++ src/server/collision/Models/WorldModel.h | 6 ++++++ src/server/game/CMakeLists.txt | 2 ++ src/server/game/Entities/Unit/Unit.h | 3 ++- src/server/game/Maps/Map.cpp | 24 ++++++++++++++++++++++++ src/server/game/Maps/Map.h | 3 +++ src/server/game/Maps/MapInstanced.cpp | 2 ++ src/server/game/Movement/MovementGenerator.h | 3 +++ 11 files changed, 49 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/collision/CMakeLists.txt b/src/server/collision/CMakeLists.txt index 9fc696ab19a..d54d5f91046 100644 --- a/src/server/collision/CMakeLists.txt +++ b/src/server/collision/CMakeLists.txt @@ -34,7 +34,9 @@ set(collision_STAT_SRCS include_directories( ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging ${CMAKE_SOURCE_DIR}/src/server/shared/Database ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging diff --git a/src/server/collision/Management/VMapManager2.h b/src/server/collision/Management/VMapManager2.h index 1fba108388a..c87c42fd832 100755 --- a/src/server/collision/Management/VMapManager2.h +++ b/src/server/collision/Management/VMapManager2.h @@ -112,6 +112,8 @@ namespace VMAP return getMapFileName(mapId); } virtual bool existsMap(const char* basePath, unsigned int mapId, int x, int y); + public: + void getInstanceMapTree(InstanceTreeMap &instanceMapTree); }; } diff --git a/src/server/collision/Maps/MapTree.h b/src/server/collision/Maps/MapTree.h index 1732209c6bc..f0df713bf57 100755 --- a/src/server/collision/Maps/MapTree.h +++ b/src/server/collision/Maps/MapTree.h @@ -80,6 +80,7 @@ namespace VMAP void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); bool isTiled() const { return iIsTiled; } uint32 numLoadedTiles() const { return iLoadedTiles.size(); } + void getModelInstances(ModelInstance* &models, uint32 &count); }; struct AreaInfo diff --git a/src/server/collision/Models/ModelInstance.h b/src/server/collision/Models/ModelInstance.h index 1118b654578..3c46967980f 100755 --- a/src/server/collision/Models/ModelInstance.h +++ b/src/server/collision/Models/ModelInstance.h @@ -74,6 +74,8 @@ namespace VMAP G3D::Matrix3 iInvRot; float iInvScale; WorldModel* iModel; + public: + WorldModel* const getWorldModel(); }; } // namespace VMAP diff --git a/src/server/collision/Models/WorldModel.h b/src/server/collision/Models/WorldModel.h index ebf828e4935..98be3494927 100755 --- a/src/server/collision/Models/WorldModel.h +++ b/src/server/collision/Models/WorldModel.h @@ -66,6 +66,8 @@ namespace VMAP uint32 iType; //!< liquid type float *iHeight; //!< (tilesX + 1)*(tilesY + 1) height values uint8 *iFlags; //!< info if liquid tile is used + public: + void getPosInfo(uint32 &tilesX, uint32 &tilesY, Vector3 &corner) const; }; /*! holding additional info for WMO group files */ @@ -98,6 +100,8 @@ namespace VMAP std::vector triangles; BIH meshTree; WmoLiquid* iLiquid; + public: + void getMeshData(std::vector &vertices, std::vector &triangles, WmoLiquid* &liquid); }; /*! Holds a model (converted M2 or WMO) in its original coordinate space */ class WorldModel @@ -117,6 +121,8 @@ namespace VMAP uint32 RootWMOID; std::vector groupModels; BIH groupTree; + public: + void getGroupModels(std::vector &groupModels); }; } // namespace VMAP diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index 1f680f6e9b0..ec5833b0368 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -106,6 +106,8 @@ set(game_STAT_SRCS include_directories( ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast ${CMAKE_SOURCE_DIR}/dep/g3dlite/include ${CMAKE_SOURCE_DIR}/dep/mersennetwister ${CMAKE_SOURCE_DIR}/dep/SFMT diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index bb826c14dfc..b47c5a78dd5 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -498,6 +498,7 @@ enum UnitState UNIT_STATE_FLEEING_MOVE = 0x02000000, UNIT_STATE_CHASE_MOVE = 0x04000000, UNIT_STATE_FOLLOW_MOVE = 0x08000000, + UNIT_STATE_IGNORE_PATHFINDING = 0x10000000, // do not use pathfinding in any MovementGenerator UNIT_STATE_UNATTACKABLE = (UNIT_STATE_IN_FLIGHT | UNIT_STATE_ONVEHICLE), // for real move using movegen check and stop (except unstoppable flight) UNIT_STATE_MOVING = UNIT_STATE_ROAMING_MOVE | UNIT_STATE_CONFUSED_MOVE | UNIT_STATE_FLEEING_MOVE | UNIT_STATE_CHASE_MOVE | UNIT_STATE_FOLLOW_MOVE , @@ -1626,7 +1627,7 @@ class Unit : public WorldObject void JumpTo(float speedXY, float speedZ, bool forward = true); void JumpTo(WorldObject* obj, float speedZ); - void MonsterMoveWithSpeed(float x, float y, float z, float speed); + void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath = false, bool forceDestination = false); //void SetFacing(float ori, WorldObject* obj = NULL); void SendMonsterMoveExitVehicle(Position const* newPos); //void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index a1b3d913c99..c3732769d04 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -20,6 +20,7 @@ #include "GridStates.h" #include "ScriptMgr.h" #include "VMapFactory.h" +#include "MMapFactory.h" #include "MapInstanced.h" #include "CellImpl.h" #include "GridNotifiers.h" @@ -69,6 +70,9 @@ Map::~Map() if (!m_scriptSchedule.empty()) sScriptMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size()); + + MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId()); + MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId); } bool Map::ExistMap(uint32 mapid, int gx, int gy) @@ -117,6 +121,24 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy) return true; } +void Map::LoadMMap(int gx, int gy) +{ + // DONT CHANGE "gy" and "gx" - Its necessary ! + int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap(GetId(), gy, gx); + switch (mmapLoadResult) + { + case MMAP::MMAP_LOAD_RESULT_OK: + sLog->outDetail("MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); + break; + case MMAP::MMAP_LOAD_RESULT_ERROR: + sLog->outDetail("Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); + break; + case MMAP::MMAP_LOAD_RESULT_IGNORED: + sLog->outStaticDebug("Ignored MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); + break; + } +} + void Map::LoadVMap(int gx, int gy) { // x and y are swapped !! @@ -184,6 +206,7 @@ void Map::LoadMap(int gx, int gy, bool reload) void Map::LoadMapAndVMap(int gx, int gy) { LoadMap(gx, gy); + LoadMMap(gx, gy); if (i_InstanceId == 0) LoadVMap(gx, gy); // Only load the data for the base map } @@ -996,6 +1019,7 @@ bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll) } // x and y are swapped VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gx, gy); + MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId(), gx, gy); } else ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy)); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 766e3d23f93..925adfbc15a 100755 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -76,6 +76,8 @@ struct map_fileheader uint32 heightMapSize; uint32 liquidMapOffset; uint32 liquidMapSize; + uint32 holesOffset; + uint32 holesSize; }; #define MAP_AREA_NO_AREA 0x0001 @@ -447,6 +449,7 @@ class Map : public GridRefManager void LoadMapAndVMap(int gx, int gy); void LoadVMap(int gx, int gy); void LoadMap(int gx, int gy, bool reload = false); + void LoadMMap(int gx, int gy); GridMap* GetGrid(float x, float y); void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 5543251e115..5924b9246f6 100755 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -21,6 +21,7 @@ #include "MapManager.h" #include "Battleground.h" #include "VMapFactory.h" +#include "MMapFactory.h" #include "InstanceSaveMgr.h" #include "World.h" #include "Group.h" @@ -258,6 +259,7 @@ bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr) if (m_InstancedMaps.size() <= 1 && sWorld->getBoolConfig(CONFIG_GRID_UNLOAD)) { VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(itr->second->GetId()); + MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(itr->second->GetId()); // in that case, unload grids of the base map, too // so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded Map::UnloadAll(); diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h index 0a2ebcfaeee..85e1fec0c2d 100755 --- a/src/server/game/Movement/MovementGenerator.h +++ b/src/server/game/Movement/MovementGenerator.h @@ -43,6 +43,9 @@ class MovementGenerator virtual MovementGeneratorType GetMovementGeneratorType() = 0; virtual void unitSpeedChanged() { } + + // used by Evade code for select point to evade with expected restart default movement + virtual bool GetResetPosition(Unit &, float& /*x*/, float& /*y*/, float& /*z*/) { return false; } }; template -- cgit v1.2.3 From b1b831a1d77e9c594de176805591a339beb7ef5e Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 15:20:45 +0200 Subject: Core/Movement: Implemented mmaps in ConfusedMovementGenerator. --- .../ConfusedMovementGenerator.cpp | 36 ++++++++++------------ .../MovementGenerators/ConfusedMovementGenerator.h | 6 +--- 2 files changed, 17 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index 54a68f92c66..6357f3950ea 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -79,29 +79,15 @@ void ConfusedMovementGenerator::Initialize(T &unit) i_waypoints[idx][2] = z; } + unit.GetPosition(i_x, i_y, i_z); unit.StopMoving(); unit.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); unit.AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); } -template<> -void ConfusedMovementGenerator::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok) -{ - is_water_ok = creature.canSwim(); - is_land_ok = creature.canWalk(); -} - -template<> -void ConfusedMovementGenerator::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok) -{ - is_water_ok = true; - is_land_ok = true; -} - template void ConfusedMovementGenerator::Reset(T &unit) { - i_nextMove = 1; i_nextMoveTime.Reset(0); unit.StopMoving(); unit.AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); @@ -119,10 +105,7 @@ bool ConfusedMovementGenerator::Update(T &unit, const uint32 &diff) unit.AddUnitState(UNIT_STATE_CONFUSED_MOVE); if (unit.movespline->Finalized()) - { - i_nextMove = urand(1, MAX_CONF_WAYPOINTS); - i_nextMoveTime.Reset(urand(500, 1200)); // Guessed - } + i_nextMoveTime.Reset(urand(800, 1500)); } else { @@ -137,8 +120,20 @@ bool ConfusedMovementGenerator::Update(T &unit, const uint32 &diff) float x = i_waypoints[i_nextMove][0]; float y = i_waypoints[i_nextMove][1]; float z = i_waypoints[i_nextMove][2]; + + unit.UpdateAllowedPositionZ(x, y, z); + + PathFinderMovementGenerator path(&unit); + path.setPathLengthLimit(30.0f); + path.calculate(x, y, z); + if (path.getPathType() & PATHFIND_NOPATH) + { + i_nextMoveTime.Reset(urand(800, 1000)); + return true; + } + Movement::MoveSplineInit init(unit); - init.MoveTo(x, y, z); + init.MovebyPath(path.getPath()); init.SetWalk(true); init.Launch(); } @@ -152,6 +147,7 @@ void ConfusedMovementGenerator::Finalize(Player &unit) { unit.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); unit.ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); + unit.StopMoving(); } template<> diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h index 7f2226ea069..c390892d0d0 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h @@ -22,8 +22,6 @@ #include "MovementGenerator.h" #include "Timer.h" -#define MAX_CONF_WAYPOINTS 24 //! Allows a twelve second confusion if i_nextMove always is the absolute minimum timer. - template class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMovementGenerator > { @@ -37,10 +35,8 @@ class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMov MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; } private: - void _InitSpecific(T &, bool &, bool &); TimeTracker i_nextMoveTime; - float i_waypoints[MAX_CONF_WAYPOINTS+1][3]; - uint32 i_nextMove; + float i_waypoints[24+1][3]; }; #endif -- cgit v1.2.3 From 973adf112bff7d8ec0aeb09f9fd2545d82943868 Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 15:48:19 +0200 Subject: More changes for mmaps. --- .../ConfusedMovementGenerator.cpp | 3 +-- src/server/game/Movement/Waypoints/Path.h | 24 ++++++++++++++++++---- src/server/game/World/World.cpp | 6 ++++++ src/server/game/World/World.h | 1 + src/server/scripts/CMakeLists.txt | 3 +++ src/server/shared/CMakeLists.txt | 1 + src/server/worldserver/CMakeLists.txt | 2 ++ 7 files changed, 34 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index 6357f3950ea..caf81a0a141 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -19,6 +19,7 @@ #include "Creature.h" #include "MapManager.h" #include "ConfusedMovementGenerator.h" +#include "PathFinderMovementGenerator.h" #include "VMapFactory.h" #include "MoveSplineInit.h" #include "MoveSpline.h" @@ -42,8 +43,6 @@ void ConfusedMovementGenerator::Initialize(T &unit) i_nextMove = 1; bool is_water_ok, is_land_ok; - _InitSpecific(unit, is_water_ok, is_land_ok); - for (uint8 idx = 0; idx < MAX_CONF_WAYPOINTS + 1; ++idx) { float wanderX = x + (wander_distance * (float)rand_norm() - wander_distance/2); diff --git a/src/server/game/Movement/Waypoints/Path.h b/src/server/game/Movement/Waypoints/Path.h index b6ddaa9d726..038958593fb 100755 --- a/src/server/game/Movement/Waypoints/Path.h +++ b/src/server/game/Movement/Waypoints/Path.h @@ -20,10 +20,12 @@ #define TRINITYCORE_PATH_H #include "Common.h" -#include +#include -struct SimplePathNode +struct PathNode { + PathNode(): x(0.0f), y(0.0f), z(0.0f) { } + PathNode(float _x, float _y, float _z): x(_x), y(_y), z(_z) { } float x, y, z; }; template @@ -36,6 +38,20 @@ class Path void resize(unsigned int sz) { i_nodes.resize(sz); } void clear() { i_nodes.clear(); } void erase(uint32 idx) { i_nodes.erase(i_nodes.begin()+idx); } + void crop(unsigned int start, unsigned int end) + { + while(start && !i_nodes.empty()) + { + i_nodes.pop_front(); + --start; + } + + while(end && !i_nodes.empty()) + { + i_nodes.pop_back(); + --end; + } + } float GetTotalLength(uint32 start, uint32 end) const { @@ -76,10 +92,10 @@ class Path void set(size_t idx, PathElem elem) { i_nodes[idx] = elem; } protected: - std::vector i_nodes; + std::deque i_nodes; }; -typedef Path SimplePath; +typedef Path SimplePath; #endif diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 6e32d33a7bb..3870a108d57 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -21,6 +21,7 @@ */ #include "Common.h" +#include "Memory.h" #include "DatabaseEnv.h" #include "Config.h" #include "SystemConfig.h" @@ -54,6 +55,7 @@ #include "TemporarySummon.h" #include "WaypointMovementGenerator.h" #include "VMapFactory.h" +#include "MMapFactory.h" #include "GameEventMgr.h" #include "PoolMgr.h" #include "GridNotifiersImpl.h" @@ -1121,6 +1123,7 @@ void World::LoadConfigSettings(bool reload) } m_bool_configs[CONFIG_VMAP_INDOOR_CHECK] = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", 0); + m_bool_configs[CONFIG_ENABLE_MMAPS] = ConfigMgr::GetBoolDefault("mmap.enablePathFinding", true); bool enableIndoor = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", true); bool enableLOS = ConfigMgr::GetBoolDefault("vmap.enableLOS", true); bool enableHeight = ConfigMgr::GetBoolDefault("vmap.enableHeight", true); @@ -1216,6 +1219,9 @@ void World::SetInitialWorldSettings() ///- Initialize the random number generator srand((unsigned int)time(NULL)); + ///- Initialize detour memory management + dtAllocSetCustom(dtCustomAlloc, dtCustomFree); + ///- Initialize config settings LoadConfigSettings(); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 95e9fbda8ca..ec3d09006bd 100755 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -164,6 +164,7 @@ enum WorldBoolConfigs CONFIG_QUEST_IGNORE_AUTO_ACCEPT, CONFIG_QUEST_IGNORE_AUTO_COMPLETE, CONFIG_WARDEN_ENABLED, + CONFIG_ENABLE_MMAPS, BOOL_CONFIG_VALUE_COUNT }; diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index 728d95a0851..e249943eb7c 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -51,6 +51,8 @@ message("") include_directories( ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast ${CMAKE_SOURCE_DIR}/dep/g3dlite/include ${CMAKE_SOURCE_DIR}/dep/SFMT ${CMAKE_SOURCE_DIR}/dep/mersennetwister @@ -120,6 +122,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/game/Maps ${CMAKE_SOURCE_DIR}/src/server/game/Movement ${CMAKE_SOURCE_DIR}/src/server/game/Movement/MovementGenerators + ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints ${CMAKE_SOURCE_DIR}/src/server/game/Opcodes ${CMAKE_SOURCE_DIR}/src/server/game/OutdoorPvP diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt index 3ec35b5394a..d42049b1cdf 100644 --- a/src/server/shared/CMakeLists.txt +++ b/src/server/shared/CMakeLists.txt @@ -52,6 +52,7 @@ set(shared_STAT_SRCS include_directories( ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour ${CMAKE_SOURCE_DIR}/dep/SFMT ${CMAKE_SOURCE_DIR}/dep/mersennetwister ${CMAKE_SOURCE_DIR}/dep/sockets/include diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt index d1419cb0fcb..080e71846a6 100644 --- a/src/server/worldserver/CMakeLists.txt +++ b/src/server/worldserver/CMakeLists.txt @@ -45,6 +45,7 @@ endif() include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour ${CMAKE_SOURCE_DIR}/dep/gsoap ${CMAKE_SOURCE_DIR}/dep/sockets/include ${CMAKE_SOURCE_DIR}/dep/SFMT @@ -168,6 +169,7 @@ target_link_libraries(worldserver collision g3dlib gsoap + Detour ${JEMALLOC_LIBRARY} ${READLINE_LIBRARY} ${TERMCAP_LIBRARY} -- cgit v1.2.3 From 710a617a3cf7b0f59c268fd0a6396d1e6e7393ba Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 15:52:00 +0200 Subject: Core/Tools: Store hole data. --- src/tools/map_extractor/System.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src') diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index bbde9f4675e..29836506861 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -292,6 +292,8 @@ struct map_fileheader uint32 heightMapSize; uint32 liquidMapOffset; uint32 liquidMapSize; + uint32 holesOffset; + uint32 holesSize; }; #define MAP_AREA_NO_AREA 0x0001 @@ -826,6 +828,28 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x, uint32 map.liquidMapSize += sizeof(float)*liquidHeader.width*liquidHeader.height; } + // map hole info + uint16 holes[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]; + + if (map.liquidMapOffset) + map.holesOffset = map.liquidMapOffset + map.liquidMapSize; + else + map.holesOffset = map.heightMapOffset + map.heightMapSize; + + map.holesSize = sizeof(holes); + memset(holes, 0, map.holesSize); + + for (int i = 0; i < ADT_CELLS_PER_GRID; ++i) + { + for (int j = 0; j < ADT_CELLS_PER_GRID; ++j) + { + adt_MCNK * cell = cells->getMCNK(i,j); + if (!cell) + continue; + holes[i][j] = cell->holes; + } + } + // Ok all data prepared - store it FILE *output=fopen(filename2, "wb"); if(!output) @@ -875,6 +899,9 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x, uint32 fwrite(&liquid_height[y+liquidHeader.offsetY][liquidHeader.offsetX], sizeof(float), liquidHeader.width, output); } } + // store hole data + fwrite(holes, map.holesSize, 1, output); + fclose(output); return true; -- cgit v1.2.3 From ccb7a5a809a45bcf0ba6f5fbb59a71d475891564 Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 15:53:21 +0200 Subject: Add config options. --- src/server/worldserver/worldserver.conf.dist | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src') diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 5d837100b0e..7366d248950 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -266,6 +266,21 @@ PlayerSave.Stats.MinLevel = 0 PlayerSave.Stats.SaveOnlyOnLogout = 1 +# +# mmap.enablePathFinding +# Description: Enable/Disable pathfinding using mmaps +# Default: 1 - (Enabled) +# 0 - (Disabled) + +mmap.enablePathFinding = 1 + +# +# mmap.ignoreMapIds +# Disable mmap pathfinding on the listed maps. +# List of map ids with delimiter ',' + +mmap.ignoreMapIds = "" + # # vmap.enableLOS # vmap.enableHeight -- cgit v1.2.3 From 2181b123ba1b45ae8725d4e06799bf3d3bee282d Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 15:55:27 +0200 Subject: Give mmap generator the correct name. --- src/tools/CMakeLists.txt | 2 +- src/tools/mmap_extractor/CMakeLists.txt | 68 -- src/tools/mmap_extractor/Info/readme.txt | 66 -- src/tools/mmap_extractor/IntermediateValues.cpp | 277 ------- src/tools/mmap_extractor/IntermediateValues.h | 53 -- src/tools/mmap_extractor/MapBuilder.cpp | 894 ----------------------- src/tools/mmap_extractor/MapBuilder.h | 129 ---- src/tools/mmap_extractor/PathCommon.h | 128 ---- src/tools/mmap_extractor/PathGenerator.cpp | 273 ------- src/tools/mmap_extractor/TerrainBuilder.cpp | 854 ---------------------- src/tools/mmap_extractor/TerrainBuilder.h | 138 ---- src/tools/mmap_extractor/VMapExtensions.cpp | 72 -- src/tools/mmaps_generator/CMakeLists.txt | 68 ++ src/tools/mmaps_generator/Info/readme.txt | 66 ++ src/tools/mmaps_generator/IntermediateValues.cpp | 277 +++++++ src/tools/mmaps_generator/IntermediateValues.h | 53 ++ src/tools/mmaps_generator/MapBuilder.cpp | 894 +++++++++++++++++++++++ src/tools/mmaps_generator/MapBuilder.h | 129 ++++ src/tools/mmaps_generator/PathCommon.h | 128 ++++ src/tools/mmaps_generator/PathGenerator.cpp | 273 +++++++ src/tools/mmaps_generator/TerrainBuilder.cpp | 854 ++++++++++++++++++++++ src/tools/mmaps_generator/TerrainBuilder.h | 138 ++++ src/tools/mmaps_generator/VMapExtensions.cpp | 72 ++ 23 files changed, 2953 insertions(+), 2953 deletions(-) delete mode 100644 src/tools/mmap_extractor/CMakeLists.txt delete mode 100644 src/tools/mmap_extractor/Info/readme.txt delete mode 100644 src/tools/mmap_extractor/IntermediateValues.cpp delete mode 100644 src/tools/mmap_extractor/IntermediateValues.h delete mode 100644 src/tools/mmap_extractor/MapBuilder.cpp delete mode 100644 src/tools/mmap_extractor/MapBuilder.h delete mode 100644 src/tools/mmap_extractor/PathCommon.h delete mode 100644 src/tools/mmap_extractor/PathGenerator.cpp delete mode 100644 src/tools/mmap_extractor/TerrainBuilder.cpp delete mode 100644 src/tools/mmap_extractor/TerrainBuilder.h delete mode 100644 src/tools/mmap_extractor/VMapExtensions.cpp create mode 100644 src/tools/mmaps_generator/CMakeLists.txt create mode 100644 src/tools/mmaps_generator/Info/readme.txt create mode 100644 src/tools/mmaps_generator/IntermediateValues.cpp create mode 100644 src/tools/mmaps_generator/IntermediateValues.h create mode 100644 src/tools/mmaps_generator/MapBuilder.cpp create mode 100644 src/tools/mmaps_generator/MapBuilder.h create mode 100644 src/tools/mmaps_generator/PathCommon.h create mode 100644 src/tools/mmaps_generator/PathGenerator.cpp create mode 100644 src/tools/mmaps_generator/TerrainBuilder.cpp create mode 100644 src/tools/mmaps_generator/TerrainBuilder.h create mode 100644 src/tools/mmaps_generator/VMapExtensions.cpp (limited to 'src') diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index f4c5f695b26..2d378966aff 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -11,4 +11,4 @@ add_subdirectory(map_extractor) add_subdirectory(vmap4_assembler) add_subdirectory(vmap4_extractor) -add_subdirectory(mmaps_extractor) +add_subdirectory(mmaps_generator) diff --git a/src/tools/mmap_extractor/CMakeLists.txt b/src/tools/mmap_extractor/CMakeLists.txt deleted file mode 100644 index c7c1a954371..00000000000 --- a/src/tools/mmap_extractor/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) 2008-2011 Trinity -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -file(GLOB_RECURSE sources *.cpp *.h) - -# definitions -add_definitions(-DNO_CORE_FUNCS) -add_definitions(-DDEBUG) -add_definitions(-DNO_vsnprintf) - -include_directories( - ${CMAKE_BINARY_DIR} - ${ACE_INCLUDE_DIR} - ${MYSQL_INCLUDE_DIR} - ${CMAKE_SOURCE_DIR}/dep/libmpq - ${CMAKE_SOURCE_DIR}/dep/zlib - ${CMAKE_SOURCE_DIR}/dep/bzip2 - ${CMAKE_SOURCE_DIR}/dep/acelite - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/Database/Implementation - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/game/Maps - ${CMAKE_SOURCE_DIR}/src/server/game/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints - ${CMAKE_SOURCE_DIR}/src/server/game/Grids - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells - ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous - ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/server/collision - ${CMAKE_SOURCE_DIR}/src/server/collision/Management - ${CMAKE_SOURCE_DIR}/src/server/collision/Maps - ${CMAKE_SOURCE_DIR}/src/server/collision/Models -) - -add_executable(movements_extractor ${sources}) - -target_link_libraries(movements_extractor - ${MYSQL_LIBRARY} - ${ACE_LIBRARY} - ${BZIP2_LIBRARIES} - ${ZLIB_LIBRARIES} - Recast - Detour - collision - g3dlib - shared -) - -if( UNIX ) - install(TARGETS movements_extractor DESTINATION bin) -elseif( WIN32 ) - install(TARGETS movements_extractor DESTINATION "${CMAKE_INSTALL_PREFIX}") -endif() diff --git a/src/tools/mmap_extractor/Info/readme.txt b/src/tools/mmap_extractor/Info/readme.txt deleted file mode 100644 index 8d7c4f9d2e0..00000000000 --- a/src/tools/mmap_extractor/Info/readme.txt +++ /dev/null @@ -1,66 +0,0 @@ -Generator command line args - ---offMeshInput [file.*] Path to file containing off mesh connections data. - Format must be: (see offmesh_example.txt) - "map_id tile_x,tile_y (start_x start_y start_z) (end_x end_y end_z) size //optional comments" - Single mesh connection per line. - ---silent Make us script friendly. Do not wait for user input - on error or completion. - ---bigBaseUnit [true|false] Generate tile/map using bigger basic unit. - Use this option only if you have unexpected gaps. - - false: use normal metrics (default) - ---maxAngle [#] Max walkable inclination angle - - float between 45 and 90 degrees (default 60) - ---skipLiquid liquid data for maps - - false: include liquid data (default) - ---skipContinents [true|false] continents are maps 0 (Eastern Kingdoms), - 1 (Kalimdor), 530 (Outlands), 571 (Northrend) - - false: build continents (default) - ---skipJunkMaps [true|false] junk maps include some unused - maps, transport maps, and some other - - true: skip junk maps (default) - ---skipBattlegrounds [true|false] does not include PVP arenas - - false: skip battlegrounds (default) - ---debugOutput [true|false] create debugging files for use with RecastDemo - if you are only creating mmaps for use with MaNGOS, - you don't want debugging files - - false: don't create debugging files (default) - ---tile [#,#] Build the specified tile - seperate number with a comma ',' - must specify a map number (see below) - if this option is not used, all tiles are built - - [#] Build only the map specified by # - this command will build the map regardless of --skip* option settings - if you do not specify a map number, builds all maps that pass the filters specified by --skip* options - - -examples: - -movement_extractor -builds maps using the default settings (see above for defaults) - -movement_extractor --skipContinents true -builds the default maps, except continents - -movement_extractor 0 -builds all tiles of map 0 - -movement_extractor 0 --tile 34,46 -builds only tile 34,46 of map 0 (this is the southern face of blackrock mountain) \ No newline at end of file diff --git a/src/tools/mmap_extractor/IntermediateValues.cpp b/src/tools/mmap_extractor/IntermediateValues.cpp deleted file mode 100644 index 9eefb1e65f0..00000000000 --- a/src/tools/mmap_extractor/IntermediateValues.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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 . - */ - -#include "IntermediateValues.h" - -namespace MMAP -{ - IntermediateValues::~IntermediateValues() - { - rcFreeCompactHeightfield(compactHeightfield); - rcFreeHeightField(heightfield); - rcFreeContourSet(contours); - rcFreePolyMesh(polyMesh); - rcFreePolyMeshDetail(polyMeshDetail); - } - - void IntermediateValues::writeIV(uint32 mapID, uint32 tileX, uint32 tileY) - { - char fileName[255]; - char tileString[25]; - sprintf(tileString, "[%02u,%02u]: ", tileX, tileY); - - printf("%sWriting debug output... \r", tileString); - - string name("meshes/%03u%02i%02i."); - -#define DEBUG_WRITE(fileExtension,data) \ - do { \ - sprintf(fileName, (name + fileExtension).c_str(), mapID, tileY, tileX); \ - FILE* file = fopen(fileName, "wb"); \ - if (!file) \ - { \ - char message[1024]; \ - sprintf(message, "%sFailed to open %s for writing!\n", tileString, fileName); \ - perror(message); \ - } \ - else \ - debugWrite(file, data); \ - if (file) fclose(file); \ - printf("%sWriting debug output... \r", tileString); \ - } while (false) - - if (heightfield) - DEBUG_WRITE("hf", heightfield); - if (compactHeightfield) - DEBUG_WRITE("chf", compactHeightfield); - if (contours) - DEBUG_WRITE("cs", contours); - if (polyMesh) - DEBUG_WRITE("pmesh", polyMesh); - if (polyMeshDetail) - DEBUG_WRITE("dmesh", polyMeshDetail); - -#undef DEBUG_WRITE - } - - void IntermediateValues::debugWrite(FILE* file, const rcHeightfield* mesh) - { - if (!file || !mesh) - return; - - fwrite(&(mesh->cs), sizeof(float), 1, file); - fwrite(&(mesh->ch), sizeof(float), 1, file); - fwrite(&(mesh->width), sizeof(int), 1, file); - fwrite(&(mesh->height), sizeof(int), 1, file); - fwrite(mesh->bmin, sizeof(float), 3, file); - fwrite(mesh->bmax, sizeof(float), 3, file); - - for (int y = 0; y < mesh->height; ++y) - for (int x = 0; x < mesh->width; ++x) - { - rcSpan* span = mesh->spans[x+y*mesh->width]; - - // first, count the number of spans - int spanCount = 0; - while (span) - { - spanCount++; - span = span->next; - } - - // write the span count - fwrite(&spanCount, sizeof(int), 1, file); - - // write the spans - span = mesh->spans[x+y*mesh->width]; - while (span) - { - fwrite(span, sizeof(rcSpan), 1, file); - span = span->next; - } - } - } - - void IntermediateValues::debugWrite(FILE* file, const rcCompactHeightfield* chf) - { - if (!file | !chf) - return; - - fwrite(&(chf->width), sizeof(chf->width), 1, file); - fwrite(&(chf->height), sizeof(chf->height), 1, file); - fwrite(&(chf->spanCount), sizeof(chf->spanCount), 1, file); - - fwrite(&(chf->walkableHeight), sizeof(chf->walkableHeight), 1, file); - fwrite(&(chf->walkableClimb), sizeof(chf->walkableClimb), 1, file); - - fwrite(&(chf->maxDistance), sizeof(chf->maxDistance), 1, file); - fwrite(&(chf->maxRegions), sizeof(chf->maxRegions), 1, file); - - fwrite(chf->bmin, sizeof(chf->bmin), 1, file); - fwrite(chf->bmax, sizeof(chf->bmax), 1, file); - - fwrite(&(chf->cs), sizeof(chf->cs), 1, file); - fwrite(&(chf->ch), sizeof(chf->ch), 1, file); - - int tmp = 0; - if (chf->cells) tmp |= 1; - if (chf->spans) tmp |= 2; - if (chf->dist) tmp |= 4; - if (chf->areas) tmp |= 8; - - fwrite(&tmp, sizeof(tmp), 1, file); - - if (chf->cells) - fwrite(chf->cells, sizeof(rcCompactCell), chf->width*chf->height, file); - if (chf->spans) - fwrite(chf->spans, sizeof(rcCompactSpan), chf->spanCount, file); - if (chf->dist) - fwrite(chf->dist, sizeof(unsigned short), chf->spanCount, file); - if (chf->areas) - fwrite(chf->areas, sizeof(unsigned char), chf->spanCount, file); - } - - void IntermediateValues::debugWrite(FILE* file, const rcContourSet* cs) - { - if (!file || !cs) - return; - - fwrite(&(cs->cs), sizeof(float), 1, file); - fwrite(&(cs->ch), sizeof(float), 1, file); - fwrite(cs->bmin, sizeof(float), 3, file); - fwrite(cs->bmax, sizeof(float), 3, file); - fwrite(&(cs->nconts), sizeof(int), 1, file); - for (int i = 0; i < cs->nconts; ++i) - { - fwrite(&cs->conts[i].area, sizeof(unsigned char), 1, file); - fwrite(&cs->conts[i].reg, sizeof(unsigned short), 1, file); - fwrite(&cs->conts[i].nverts, sizeof(int), 1, file); - fwrite(cs->conts[i].verts, sizeof(int), cs->conts[i].nverts*4, file); - fwrite(&cs->conts[i].nrverts, sizeof(int), 1, file); - fwrite(cs->conts[i].rverts, sizeof(int), cs->conts[i].nrverts*4, file); - } - } - - void IntermediateValues::debugWrite(FILE* file, const rcPolyMesh* mesh) - { - if (!file || !mesh) - return; - - fwrite(&(mesh->cs), sizeof(float), 1, file); - fwrite(&(mesh->ch), sizeof(float), 1, file); - fwrite(&(mesh->nvp), sizeof(int), 1, file); - fwrite(mesh->bmin, sizeof(float), 3, file); - fwrite(mesh->bmax, sizeof(float), 3, file); - fwrite(&(mesh->nverts), sizeof(int), 1, file); - fwrite(mesh->verts, sizeof(unsigned short), mesh->nverts*3, file); - fwrite(&(mesh->npolys), sizeof(int), 1, file); - fwrite(mesh->polys, sizeof(unsigned short), mesh->npolys*mesh->nvp*2, file); - fwrite(mesh->flags, sizeof(unsigned short), mesh->npolys, file); - fwrite(mesh->areas, sizeof(unsigned char), mesh->npolys, file); - fwrite(mesh->regs, sizeof(unsigned short), mesh->npolys, file); - } - - void IntermediateValues::debugWrite(FILE* file, const rcPolyMeshDetail* mesh) - { - if (!file || !mesh) - return; - - fwrite(&(mesh->nverts), sizeof(int), 1, file); - fwrite(mesh->verts, sizeof(float), mesh->nverts*3, file); - fwrite(&(mesh->ntris), sizeof(int), 1, file); - fwrite(mesh->tris, sizeof(char), mesh->ntris*4, file); - fwrite(&(mesh->nmeshes), sizeof(int), 1, file); - fwrite(mesh->meshes, sizeof(int), mesh->nmeshes*4, file); - } - - void IntermediateValues::generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) - { - char objFileName[255]; - sprintf(objFileName, "meshes/map%03u.obj", mapID); - - FILE* objFile = fopen(objFileName, "wb"); - if (!objFile) - { - char message[1024]; - sprintf(message, "Failed to open %s for writing!\n", objFileName); - perror(message); - return; - } - - G3D::Array allVerts; - G3D::Array allTris; - - allTris.append(meshData.liquidTris); - allVerts.append(meshData.liquidVerts); - TerrainBuilder::copyIndices(meshData.solidTris, allTris, allVerts.size() / 3); - allVerts.append(meshData.solidVerts); - - float* verts = allVerts.getCArray(); - int vertCount = allVerts.size() / 3; - int* tris = allTris.getCArray(); - int triCount = allTris.size() / 3; - - for (int i = 0; i < allVerts.size() / 3; i++) - fprintf(objFile, "v %f %f %f\n", verts[i*3], verts[i*3 + 1], verts[i*3 + 2]); - - for (int i = 0; i < allTris.size() / 3; i++) - fprintf(objFile, "f %i %i %i\n", tris[i*3] + 1, tris[i*3 + 1] + 1, tris[i*3 + 2] + 1); - - fclose(objFile); - - - char tileString[25]; - sprintf(tileString, "[%02u,%02u]: ", tileY, tileX); - printf("%sWriting debug output... \r", tileString); - - sprintf(objFileName, "meshes/%03u.map", mapID); - - objFile = fopen(objFileName, "wb"); - if (!objFile) - { - char message[1024]; - sprintf(message, "Failed to open %s for writing!\n", objFileName); - perror(message); - return; - } - - char b = '\0'; - fwrite(&b, sizeof(char), 1, objFile); - fclose(objFile); - - sprintf(objFileName, "meshes/%03u%02u%02u.mesh", mapID, tileY, tileX); - objFile = fopen(objFileName, "wb"); - if (!objFile) - { - char message[1024]; - sprintf(message, "Failed to open %s for writing!\n", objFileName); - perror(message); - return; - } - - fwrite(&vertCount, sizeof(int), 1, objFile); - fwrite(verts, sizeof(float), vertCount*3, objFile); - fflush(objFile); - - fwrite(&triCount, sizeof(int), 1, objFile); - fwrite(tris, sizeof(int), triCount*3, objFile); - fflush(objFile); - - fclose(objFile); - } -} diff --git a/src/tools/mmap_extractor/IntermediateValues.h b/src/tools/mmap_extractor/IntermediateValues.h deleted file mode 100644 index a267a0f6412..00000000000 --- a/src/tools/mmap_extractor/IntermediateValues.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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 . - */ - -#ifndef _INTERMEDIATE_VALUES_H -#define _INTERMEDIATE_VALUES_H - -#include "PathCommon.h" -#include "TerrainBuilder.h" -#include "Recast.h" -#include "DetourNavMesh.h" - -namespace MMAP -{ - // this class gathers all debug info holding and output - struct IntermediateValues - { - rcHeightfield* heightfield; - rcCompactHeightfield* compactHeightfield; - rcContourSet* contours; - rcPolyMesh* polyMesh; - rcPolyMeshDetail* polyMeshDetail; - - IntermediateValues() : compactHeightfield(NULL), heightfield(NULL), - contours(NULL), polyMesh(NULL), polyMeshDetail(NULL) {} - ~IntermediateValues(); - - void writeIV(uint32 mapID, uint32 tileX, uint32 tileY); - - void debugWrite(FILE* file, const rcHeightfield* mesh); - void debugWrite(FILE* file, const rcCompactHeightfield* chf); - void debugWrite(FILE* file, const rcContourSet* cs); - void debugWrite(FILE* file, const rcPolyMesh* mesh); - void debugWrite(FILE* file, const rcPolyMeshDetail* mesh); - - void generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); - }; -} -#endif diff --git a/src/tools/mmap_extractor/MapBuilder.cpp b/src/tools/mmap_extractor/MapBuilder.cpp deleted file mode 100644 index 3ca158f0127..00000000000 --- a/src/tools/mmap_extractor/MapBuilder.cpp +++ /dev/null @@ -1,894 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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 . - */ - -#include "PathCommon.h" -#include "MapBuilder.h" - -#include "MapTree.h" -#include "ModelInstance.h" -#include "LoginDatabase.h" - -#include "DetourNavMeshBuilder.h" -#include "DetourCommon.h" - -// These make the linker happy. -LoginDatabaseWorkerPool LoginDatabase; -#include "DisableMgr.h" -namespace DisableMgr -{ - bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags) - { - return 0; - } -} - -using namespace VMAP; - -namespace MMAP -{ - MapBuilder::MapBuilder(float maxWalkableAngle, bool skipLiquid, - bool skipContinents, bool skipJunkMaps, bool skipBattlegrounds, - bool debugOutput, bool bigBaseUnit, const char* offMeshFilePath) : - m_terrainBuilder(NULL), - m_debugOutput (debugOutput), - m_skipContinents (skipContinents), - m_skipJunkMaps (skipJunkMaps), - m_skipBattlegrounds (skipBattlegrounds), - m_maxWalkableAngle (maxWalkableAngle), - m_bigBaseUnit (bigBaseUnit), - m_rcContext (NULL), - m_offMeshFilePath (offMeshFilePath) - { - m_terrainBuilder = new TerrainBuilder(skipLiquid); - - m_rcContext = new rcContext(false); - - discoverTiles(); - } - - /**************************************************************************/ - MapBuilder::~MapBuilder() - { - for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) - { - (*it).second->clear(); - delete (*it).second; - } - - delete m_terrainBuilder; - delete m_rcContext; - } - - /**************************************************************************/ - void MapBuilder::discoverTiles() - { - vector files; - uint32 mapID, tileX, tileY, tileID, count = 0; - char filter[12]; - - printf("Discovering maps... "); - getDirContents(files, "maps"); - for (uint32 i = 0; i < files.size(); ++i) - { - mapID = uint32(atoi(files[i].substr(0,3).c_str())); - if (m_tiles.find(mapID) == m_tiles.end()) - { - m_tiles.insert(pair*>(mapID, new set)); - count++; - } - } - - files.clear(); - getDirContents(files, "vmaps", "*.vmtree"); - for (uint32 i = 0; i < files.size(); ++i) - { - mapID = uint32(atoi(files[i].substr(0,3).c_str())); - m_tiles.insert(pair*>(mapID, new set)); - count++; - } - printf("found %u.\n", count); - - count = 0; - printf("Discovering tiles... "); - for (TileList::iterator itr = m_tiles.begin(); itr != m_tiles.end(); ++itr) - { - set* tiles = (*itr).second; - mapID = (*itr).first; - - sprintf(filter, "%03u*.vmtile", mapID); - files.clear(); - getDirContents(files, "vmaps", filter); - for (uint32 i = 0; i < files.size(); ++i) - { - tileX = uint32(atoi(files[i].substr(7,2).c_str())); - tileY = uint32(atoi(files[i].substr(4,2).c_str())); - tileID = StaticMapTree::packTileID(tileY, tileX); - - tiles->insert(tileID); - count++; - } - - sprintf(filter, "%03u*", mapID); - files.clear(); - getDirContents(files, "maps", filter); - for (uint32 i = 0; i < files.size(); ++i) - { - tileY = uint32(atoi(files[i].substr(3,2).c_str())); - tileX = uint32(atoi(files[i].substr(5,2).c_str())); - tileID = StaticMapTree::packTileID(tileX, tileY); - - if (tiles->insert(tileID).second) - count++; - } - } - printf("found %u.\n\n", count); - } - - /**************************************************************************/ - set* MapBuilder::getTileList(uint32 mapID) - { - TileList::iterator itr = m_tiles.find(mapID); - if (itr != m_tiles.end()) - return (*itr).second; - - set* tiles = new set(); - m_tiles.insert(pair*>(mapID, tiles)); - return tiles; - } - - /**************************************************************************/ - void MapBuilder::buildAllMaps() - { - for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) - { - uint32 mapID = (*it).first; - if (!shouldSkipMap(mapID)) - buildMap(mapID); - } - } - - /**************************************************************************/ - void MapBuilder::getGridBounds(uint32 mapID, uint32 &minX, uint32 &minY, uint32 &maxX, uint32 &maxY) - { - maxX = INT_MAX; - maxY = INT_MAX; - minX = INT_MIN; - minY = INT_MIN; - - float bmin[3], bmax[3], lmin[3], lmax[3]; - MeshData meshData; - - // make sure we process maps which don't have tiles - // initialize the static tree, which loads WDT models - if (!m_terrainBuilder->loadVMap(mapID, 64, 64, meshData)) - return; - - // get the coord bounds of the model data - if (meshData.solidVerts.size() + meshData.liquidVerts.size() == 0) - return; - - // get the coord bounds of the model data - if (meshData.solidVerts.size() && meshData.liquidVerts.size()) - { - rcCalcBounds(meshData.solidVerts.getCArray(), meshData.solidVerts.size() / 3, bmin, bmax); - rcCalcBounds(meshData.liquidVerts.getCArray(), meshData.liquidVerts.size() / 3, lmin, lmax); - rcVmin(bmin, lmin); - rcVmax(bmax, lmax); - } - else if (meshData.solidVerts.size()) - rcCalcBounds(meshData.solidVerts.getCArray(), meshData.solidVerts.size() / 3, bmin, bmax); - else - rcCalcBounds(meshData.liquidVerts.getCArray(), meshData.liquidVerts.size() / 3, lmin, lmax); - - // convert coord bounds to grid bounds - maxX = 32 - bmin[0] / GRID_SIZE; - maxY = 32 - bmin[2] / GRID_SIZE; - minX = 32 - bmax[0] / GRID_SIZE; - minY = 32 - bmax[2] / GRID_SIZE; - } - - /**************************************************************************/ - void MapBuilder::buildSingleTile(uint32 mapID, uint32 tileX, uint32 tileY) - { - dtNavMesh* navMesh = NULL; - buildNavMesh(mapID, navMesh); - if (!navMesh) - { - printf("Failed creating navmesh! \n"); - return; - } - - buildTile(mapID, tileX, tileY, navMesh); - dtFreeNavMesh(navMesh); - } - - /**************************************************************************/ - void MapBuilder::buildMap(uint32 mapID) - { - printf("Building map %03u:\n", mapID); - - set* tiles = getTileList(mapID); - - // make sure we process maps which don't have tiles - if (!tiles->size()) - { - // convert coord bounds to grid bounds - uint32 minX, minY, maxX, maxY; - getGridBounds(mapID, minX, minY, maxX, maxY); - - // add all tiles within bounds to tile list. - for (uint32 i = minX; i <= maxX; ++i) - for (uint32 j = minY; j <= maxY; ++j) - tiles->insert(StaticMapTree::packTileID(i, j)); - } - - if (!tiles->size()) - return; - - // build navMesh - dtNavMesh* navMesh = NULL; - buildNavMesh(mapID, navMesh); - if (!navMesh) - { - printf("Failed creating navmesh! \n"); - return; - } - - // now start building mmtiles for each tile - printf("We have %u tiles. \n", (unsigned int)tiles->size()); - for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) - { - uint32 tileX, tileY; - - // unpack tile coords - StaticMapTree::unpackTileID((*it), tileX, tileY); - - if (shouldSkipTile(mapID, tileX, tileY)) - continue; - - buildTile(mapID, tileX, tileY, navMesh); - } - - dtFreeNavMesh(navMesh); - - printf("Complete! \n\n"); - } - - /**************************************************************************/ - void MapBuilder::buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh) - { - printf("Building map %03u, tile [%02u,%02u]\n", mapID, tileX, tileY); - - MeshData meshData; - - // get heightmap data - m_terrainBuilder->loadMap(mapID, tileX, tileY, meshData); - - // get model data - m_terrainBuilder->loadVMap(mapID, tileY, tileX, meshData); - - // if there is no data, give up now - if (!meshData.solidVerts.size() && !meshData.liquidVerts.size()) - return; - - // remove unused vertices - TerrainBuilder::cleanVertices(meshData.solidVerts, meshData.solidTris); - TerrainBuilder::cleanVertices(meshData.liquidVerts, meshData.liquidTris); - - // gather all mesh data for final data check, and bounds calculation - G3D::Array allVerts; - allVerts.append(meshData.liquidVerts); - allVerts.append(meshData.solidVerts); - - if (!allVerts.size()) - return; - - // get bounds of current tile - float bmin[3], bmax[3]; - getTileBounds(tileX, tileY, allVerts.getCArray(), allVerts.size() / 3, bmin, bmax); - - m_terrainBuilder->loadOffMeshConnections(mapID, tileX, tileY, meshData, m_offMeshFilePath); - - // build navmesh tile - buildMoveMapTile(mapID, tileX, tileY, meshData, bmin, bmax, navMesh); - } - - /**************************************************************************/ - void MapBuilder::buildNavMesh(uint32 mapID, dtNavMesh* &navMesh) - { - set* tiles = getTileList(mapID); - - // old code for non-statically assigned bitmask sizes: - ///*** calculate number of bits needed to store tiles & polys ***/ - //int tileBits = dtIlog2(dtNextPow2(tiles->size())); - //if (tileBits < 1) tileBits = 1; // need at least one bit! - //int polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits; - - int tileBits = STATIC_TILE_BITS; - int polyBits = STATIC_POLY_BITS; - - int maxTiles = tiles->size(); - int maxPolysPerTile = 1 << polyBits; - - /*** calculate bounds of map ***/ - - uint32 tileXMin = 64, tileYMin = 64, tileXMax = 0, tileYMax = 0, tileX, tileY; - for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) - { - StaticMapTree::unpackTileID((*it), tileX, tileY); - - if (tileX > tileXMax) - tileXMax = tileX; - else if (tileX < tileXMin) - tileXMin = tileX; - - if (tileY > tileYMax) - tileYMax = tileY; - else if (tileY < tileYMin) - tileYMin = tileY; - } - - // use Max because '32 - tileX' is negative for values over 32 - float bmin[3], bmax[3]; - getTileBounds(tileXMax, tileYMax, NULL, 0, bmin, bmax); - - /*** now create the navmesh ***/ - - // navmesh creation params - dtNavMeshParams navMeshParams; - memset(&navMeshParams, 0, sizeof(dtNavMeshParams)); - navMeshParams.tileWidth = GRID_SIZE; - navMeshParams.tileHeight = GRID_SIZE; - rcVcopy(navMeshParams.orig, bmin); - navMeshParams.maxTiles = maxTiles; - navMeshParams.maxPolys = maxPolysPerTile; - - navMesh = dtAllocNavMesh(); - printf("Creating navMesh... \r"); - if (!navMesh->init(&navMeshParams)) - { - printf("Failed creating navmesh! \n"); - return; - } - - char fileName[25]; - sprintf(fileName, "mmaps/%03u.mmap", mapID); - - FILE* file = fopen(fileName, "wb"); - if (!file) - { - dtFreeNavMesh(navMesh); - char message[1024]; - sprintf(message, "Failed to open %s for writing!\n", fileName); - perror(message); - return; - } - - // now that we know navMesh params are valid, we can write them to file - fwrite(&navMeshParams, sizeof(dtNavMeshParams), 1, file); - fclose(file); - } - - /**************************************************************************/ - void MapBuilder::buildMoveMapTile(uint32 mapID, uint32 tileX, uint32 tileY, - MeshData &meshData, float bmin[3], float bmax[3], - dtNavMesh* navMesh) - { - // console output - char tileString[10]; - sprintf(tileString, "[%02i,%02i]: ", tileX, tileY); - printf("%s Building movemap tiles... \r", tileString); - - IntermediateValues iv; - - float* tVerts = meshData.solidVerts.getCArray(); - int tVertCount = meshData.solidVerts.size() / 3; - int* tTris = meshData.solidTris.getCArray(); - int tTriCount = meshData.solidTris.size() / 3; - - float* lVerts = meshData.liquidVerts.getCArray(); - int lVertCount = meshData.liquidVerts.size() / 3; - int* lTris = meshData.liquidTris.getCArray(); - int lTriCount = meshData.liquidTris.size() / 3; - uint8* lTriFlags = meshData.liquidType.getCArray(); - - // these are WORLD UNIT based metrics - // this are basic unit dimentions - // value have to divide GRID_SIZE(533.33333f) ( aka: 0.5333, 0.2666, 0.3333, 0.1333, etc ) - const static float BASE_UNIT_DIM = m_bigBaseUnit ? 0.533333f : 0.266666f; - - // All are in UNIT metrics! - const static int VERTEX_PER_MAP = int(GRID_SIZE/BASE_UNIT_DIM + 0.5f); - const static int VERTEX_PER_TILE = m_bigBaseUnit ? 40 : 80; // must divide VERTEX_PER_MAP - const static int TILES_PER_MAP = VERTEX_PER_MAP/VERTEX_PER_TILE; - - rcConfig config; - memset(&config, 0, sizeof(rcConfig)); - - rcVcopy(config.bmin, bmin); - rcVcopy(config.bmax, bmax); - - config.maxVertsPerPoly = DT_VERTS_PER_POLYGON; - config.cs = BASE_UNIT_DIM; - config.ch = BASE_UNIT_DIM; - config.walkableSlopeAngle = m_maxWalkableAngle; - config.tileSize = VERTEX_PER_TILE; - config.walkableRadius = m_bigBaseUnit ? 1 : 2; - config.borderSize = config.walkableRadius + 3; - config.maxEdgeLen = VERTEX_PER_TILE + 1; //anything bigger than tileSize - config.walkableHeight = m_bigBaseUnit ? 3 : 6; - config.walkableClimb = m_bigBaseUnit ? 2 : 4; // keep less than walkableHeight - config.minRegionArea = rcSqr(60); - config.mergeRegionArea = rcSqr(50); - config.maxSimplificationError = 2.0f; // eliminates most jagged edges (tinny polygons) - config.detailSampleDist = config.cs * 64; - config.detailSampleMaxError = config.ch * 2; - - // this sets the dimensions of the heightfield - should maybe happen before border padding - rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); - - // allocate subregions : tiles - Tile* tiles = new Tile[TILES_PER_MAP * TILES_PER_MAP]; - - // Initialize per tile config. - rcConfig tileCfg; - memcpy(&tileCfg, &config, sizeof(rcConfig)); - tileCfg.width = config.tileSize + config.borderSize*2; - tileCfg.height = config.tileSize + config.borderSize*2; - - // build all tiles - for (int y = 0; y < TILES_PER_MAP; ++y) - { - for (int x = 0; x < TILES_PER_MAP; ++x) - { - Tile& tile = tiles[x + y*TILES_PER_MAP]; - - // Calculate the per tile bounding box. - tileCfg.bmin[0] = config.bmin[0] + (x*config.tileSize - config.borderSize)*config.cs; - tileCfg.bmin[2] = config.bmin[2] + (y*config.tileSize - config.borderSize)*config.cs; - tileCfg.bmax[0] = config.bmin[0] + ((x+1)*config.tileSize + config.borderSize)*config.cs; - tileCfg.bmax[2] = config.bmin[2] + ((y+1)*config.tileSize + config.borderSize)*config.cs; - - float tbmin[2], tbmax[2]; - tbmin[0] = tileCfg.bmin[0]; - tbmin[1] = tileCfg.bmin[2]; - tbmax[0] = tileCfg.bmax[0]; - tbmax[1] = tileCfg.bmax[2]; - - // build heightfield - tile.solid = rcAllocHeightfield(); - if (!tile.solid || !rcCreateHeightfield(m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch)) - { - printf("%sFailed building heightfield! \n", tileString); - continue; - } - - // mark all walkable tiles, both liquids and solids - unsigned char* triFlags = new unsigned char[tTriCount]; - memset(triFlags, NAV_GROUND, tTriCount*sizeof(unsigned char)); - rcClearUnwalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags); - rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb); - delete [] triFlags; - - rcFilterLowHangingWalkableObstacles(m_rcContext, config.walkableClimb, *tile.solid); - rcFilterLedgeSpans(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid); - rcFilterWalkableLowHeightSpans(m_rcContext, tileCfg.walkableHeight, *tile.solid); - - rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.solid, config.walkableClimb); - - // compact heightfield spans - tile.chf = rcAllocCompactHeightfield(); - if (!tile.chf || !rcBuildCompactHeightfield(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid, *tile.chf)) - { - printf("%sFailed compacting heightfield! \n", tileString); - continue; - } - - // build polymesh intermediates - if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *tile.chf)) - { - printf("%sFailed eroding area! \n", tileString); - continue; - } - - if (!rcBuildDistanceField(m_rcContext, *tile.chf)) - { - printf("%sFailed building distance field! \n", tileString); - continue; - } - - if (!rcBuildRegions(m_rcContext, *tile.chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea)) - { - printf("%sFailed building regions! \n", tileString); - continue; - } - - tile.cset = rcAllocContourSet(); - if (!tile.cset || !rcBuildContours(m_rcContext, *tile.chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.cset)) - { - printf("%sFailed building contours! \n", tileString); - continue; - } - - // build polymesh - tile.pmesh = rcAllocPolyMesh(); - if (!tile.pmesh || !rcBuildPolyMesh(m_rcContext, *tile.cset, tileCfg.maxVertsPerPoly, *tile.pmesh)) - { - printf("%sFailed building polymesh! \n", tileString); - continue; - } - - tile.dmesh = rcAllocPolyMeshDetail(); - if (!tile.dmesh || !rcBuildPolyMeshDetail(m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg .detailSampleMaxError, *tile.dmesh)) - { - printf("%sFailed building polymesh detail! \n", tileString); - continue; - } - - // free those up - // we may want to keep them in the future for debug - // but right now, we don't have the code to merge them - rcFreeHeightField(tile.solid); - tile.solid = NULL; - rcFreeCompactHeightfield(tile.chf); - tile.chf = NULL; - rcFreeContourSet(tile.cset); - tile.cset = NULL; - } - } - - // merge per tile poly and detail meshes - rcPolyMesh** pmmerge = new rcPolyMesh*[TILES_PER_MAP * TILES_PER_MAP]; - if (!pmmerge) - { - printf("%s alloc pmmerge FIALED! \r", tileString); - return; - } - - rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[TILES_PER_MAP * TILES_PER_MAP]; - if (!dmmerge) - { - printf("%s alloc dmmerge FIALED! \r", tileString); - return; - } - - int nmerge = 0; - for (int y = 0; y < TILES_PER_MAP; ++y) - { - for (int x = 0; x < TILES_PER_MAP; ++x) - { - Tile& tile = tiles[x + y*TILES_PER_MAP]; - if (tile.pmesh) - { - pmmerge[nmerge] = tile.pmesh; - dmmerge[nmerge] = tile.dmesh; - nmerge++; - } - } - } - - iv.polyMesh = rcAllocPolyMesh(); - if (!iv.polyMesh) - { - printf("%s alloc iv.polyMesh FIALED! \r", tileString); - return; - } - rcMergePolyMeshes(m_rcContext, pmmerge, nmerge, *iv.polyMesh); - - iv.polyMeshDetail = rcAllocPolyMeshDetail(); - if (!iv.polyMeshDetail) - { - printf("%s alloc m_dmesh FIALED! \r", tileString); - return; - } - rcMergePolyMeshDetails(m_rcContext, dmmerge, nmerge, *iv.polyMeshDetail); - - // free things up - delete [] pmmerge; - delete [] dmmerge; - - delete [] tiles; - - // remove padding for extraction - for (int i = 0; i < iv.polyMesh->nverts; ++i) - { - unsigned short* v = &iv.polyMesh->verts[i*3]; - v[0] -= (unsigned short)config.borderSize; - v[2] -= (unsigned short)config.borderSize; - } - - // set polygons as walkable - // TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off - for (int i = 0; i < iv.polyMesh->npolys; ++i) - if (iv.polyMesh->areas[i] & RC_WALKABLE_AREA) - iv.polyMesh->flags[i] = iv.polyMesh->areas[i]; - - // setup mesh parameters - dtNavMeshCreateParams params; - memset(¶ms, 0, sizeof(params)); - params.verts = iv.polyMesh->verts; - params.vertCount = iv.polyMesh->nverts; - params.polys = iv.polyMesh->polys; - params.polyAreas = iv.polyMesh->areas; - params.polyFlags = iv.polyMesh->flags; - params.polyCount = iv.polyMesh->npolys; - params.nvp = iv.polyMesh->nvp; - params.detailMeshes = iv.polyMeshDetail->meshes; - params.detailVerts = iv.polyMeshDetail->verts; - params.detailVertsCount = iv.polyMeshDetail->nverts; - params.detailTris = iv.polyMeshDetail->tris; - params.detailTriCount = iv.polyMeshDetail->ntris; - - params.offMeshConVerts = meshData.offMeshConnections.getCArray(); - params.offMeshConCount = meshData.offMeshConnections.size()/6; - params.offMeshConRad = meshData.offMeshConnectionRads.getCArray(); - params.offMeshConDir = meshData.offMeshConnectionDirs.getCArray(); - params.offMeshConAreas = meshData.offMeshConnectionsAreas.getCArray(); - params.offMeshConFlags = meshData.offMeshConnectionsFlags.getCArray(); - - params.walkableHeight = BASE_UNIT_DIM*config.walkableHeight; // agent height - params.walkableRadius = BASE_UNIT_DIM*config.walkableRadius; // agent radius - params.walkableClimb = BASE_UNIT_DIM*config.walkableClimb; // keep less that walkableHeight (aka agent height)! - params.tileX = (((bmin[0] + bmax[0]) / 2) - navMesh->getParams()->orig[0]) / GRID_SIZE; - params.tileY = (((bmin[2] + bmax[2]) / 2) - navMesh->getParams()->orig[2]) / GRID_SIZE; - rcVcopy(params.bmin, bmin); - rcVcopy(params.bmax, bmax); - params.cs = config.cs; - params.ch = config.ch; - params.tileSize = VERTEX_PER_MAP; - - // will hold final navmesh - unsigned char* navData = NULL; - int navDataSize = 0; - - do - { - // these values are checked within dtCreateNavMeshData - handle them here - // so we have a clear error message - if (params.nvp > DT_VERTS_PER_POLYGON) - { - printf("%s Invalid verts-per-polygon value! \n", tileString); - continue; - } - if (params.vertCount >= 0xffff) - { - printf("%s Too many vertices! \n", tileString); - continue; - } - if (!params.vertCount || !params.verts) - { - // occurs mostly when adjacent tiles have models - // loaded but those models don't span into this tile - - // message is an annoyance - //printf("%sNo vertices to build tile! \n", tileString); - continue; - } - if (!params.polyCount || !params.polys || - TILES_PER_MAP*TILES_PER_MAP == params.polyCount) - { - // we have flat tiles with no actual geometry - don't build those, its useless - // keep in mind that we do output those into debug info - // drop tiles with only exact count - some tiles may have geometry while having less tiles - printf("%s No polygons to build on tile! \n", tileString); - continue; - } - if (!params.detailMeshes || !params.detailVerts || !params.detailTris) - { - printf("%s No detail mesh to build tile! \n", tileString); - continue; - } - - printf("%s Building navmesh tile... \r", tileString); - if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) - { - printf("%s Failed building navmesh tile! \n", tileString); - continue; - } - - dtTileRef tileRef = 0; - printf("%s Adding tile to navmesh... \r", tileString); - // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile - // is removed via removeTile() - dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef); - if (!tileRef || dtResult != DT_SUCCESS) - { - printf("%s Failed adding tile to navmesh! \n", tileString); - continue; - } - - // file output - char fileName[255]; - sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX); - FILE* file = fopen(fileName, "wb"); - if (!file) - { - char message[1024]; - sprintf(message, "Failed to open %s for writing!\n", fileName); - perror(message); - navMesh->removeTile(tileRef, NULL, NULL); - continue; - } - - printf("%s Writing to file... \r", tileString); - - // write header - MmapTileHeader header; - header.usesLiquids = m_terrainBuilder->usesLiquids(); - header.size = uint32(navDataSize); - fwrite(&header, sizeof(MmapTileHeader), 1, file); - - // write data - fwrite(navData, sizeof(unsigned char), navDataSize, file); - fclose(file); - - // now that tile is written to disk, we can unload it - navMesh->removeTile(tileRef, NULL, NULL); - } - while (0); - - if (m_debugOutput) - { - // restore padding so that the debug visualization is correct - for (int i = 0; i < iv.polyMesh->nverts; ++i) - { - unsigned short* v = &iv.polyMesh->verts[i*3]; - v[0] += (unsigned short)config.borderSize; - v[2] += (unsigned short)config.borderSize; - } - - iv.generateObjFile(mapID, tileX, tileY, meshData); - iv.writeIV(mapID, tileX, tileY); - } - } - - /**************************************************************************/ - void MapBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax) - { - // this is for elevation - if (verts && vertCount) - rcCalcBounds(verts, vertCount, bmin, bmax); - else - { - bmin[1] = FLT_MIN; - bmax[1] = FLT_MAX; - } - - // this is for width and depth - bmax[0] = (32 - int(tileX)) * GRID_SIZE; - bmax[2] = (32 - int(tileY)) * GRID_SIZE; - bmin[0] = bmax[0] - GRID_SIZE; - bmin[2] = bmax[2] - GRID_SIZE; - } - - /**************************************************************************/ - bool MapBuilder::shouldSkipMap(uint32 mapID) - { - if (m_skipContinents) - switch (mapID) - { - case 0: - case 1: - case 530: - case 571: - return true; - default: - break; - } - - if (m_skipJunkMaps) - switch (mapID) - { - case 13: // test.wdt - case 25: // ScottTest.wdt - case 29: // Test.wdt - case 42: // Colin.wdt - case 169: // EmeraldDream.wdt (unused, and very large) - case 451: // development.wdt - case 573: // ExteriorTest.wdt - case 597: // CraigTest.wdt - case 605: // development_nonweighted.wdt - case 606: // QA_DVD.wdt - return true; - default: - if (isTransportMap(mapID)) - return true; - break; - } - - if (m_skipBattlegrounds) - switch (mapID) - { - case 30: // AV - case 37: // ? - case 489: // WSG - case 529: // AB - case 566: // EotS - case 607: // SotA - case 628: // IoC - return true; - default: - break; - } - - return false; - } - - /**************************************************************************/ - bool MapBuilder::isTransportMap(uint32 mapID) - { - switch (mapID) - { - // transport maps - case 582: - case 584: - case 586: - case 587: - case 588: - case 589: - case 590: - case 591: - case 592: - case 593: - case 594: - case 596: - case 610: - case 612: - case 613: - case 614: - case 620: - case 621: - case 622: - case 623: - case 641: - case 642: - case 647: - case 672: - case 673: - case 712: - case 713: - case 718: - return true; - default: - return false; - } - } - - /**************************************************************************/ - bool MapBuilder::shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY) - { - char fileName[255]; - sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX); - FILE* file = fopen(fileName, "rb"); - if (!file) - return false; - - MmapTileHeader header; - fread(&header, sizeof(MmapTileHeader), 1, file); - fclose(file); - - if (header.mmapMagic != MMAP_MAGIC || header.dtVersion != DT_NAVMESH_VERSION) - return false; - - if (header.mmapVersion != MMAP_VERSION) - return false; - - return true; - } - -} diff --git a/src/tools/mmap_extractor/MapBuilder.h b/src/tools/mmap_extractor/MapBuilder.h deleted file mode 100644 index d0f33ce9a79..00000000000 --- a/src/tools/mmap_extractor/MapBuilder.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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 . - */ - -#ifndef _MAP_BUILDER_H -#define _MAP_BUILDER_H - -#include -#include -#include - -#include "TerrainBuilder.h" -#include "IntermediateValues.h" - -#include "IVMapManager.h" -#include "WorldModel.h" - -#include "Recast.h" -#include "DetourNavMesh.h" - -using namespace std; -using namespace VMAP; - -// G3D namespace typedefs conflicts with ACE typedefs - -namespace MMAP -{ - typedef map*> TileList; - struct Tile - { - Tile() : chf(NULL), solid(NULL), cset(NULL), pmesh(NULL), dmesh(NULL) {} - ~Tile() - { - rcFreeCompactHeightfield(chf); - rcFreeContourSet(cset); - rcFreeHeightField(solid); - rcFreePolyMesh(pmesh); - rcFreePolyMeshDetail(dmesh); - } - rcCompactHeightfield* chf; - rcHeightfield* solid; - rcContourSet* cset; - rcPolyMesh* pmesh; - rcPolyMeshDetail* dmesh; - }; - - class MapBuilder - { - public: - MapBuilder(float maxWalkableAngle = 60.f, - bool skipLiquid = false, - bool skipContinents = false, - bool skipJunkMaps = true, - bool skipBattlegrounds = false, - bool debugOutput = false, - bool bigBaseUnit = false, - const char* offMeshFilePath = NULL); - - ~MapBuilder(); - - // builds all mmap tiles for the specified map id (ignores skip settings) - void buildMap(uint32 mapID); - - // builds an mmap tile for the specified map and its mesh - void buildSingleTile(uint32 mapID, uint32 tileX, uint32 tileY); - - // builds list of maps, then builds all of mmap tiles (based on the skip settings) - void buildAllMaps(); - - private: - // detect maps and tiles - void discoverTiles(); - set* getTileList(uint32 mapID); - - void buildNavMesh(uint32 mapID, dtNavMesh* &navMesh); - - void buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh); - - // move map building - void buildMoveMapTile(uint32 mapID, - uint32 tileX, - uint32 tileY, - MeshData &meshData, - float bmin[3], - float bmax[3], - dtNavMesh* navMesh); - - void getTileBounds(uint32 tileX, uint32 tileY, - float* verts, int vertCount, - float* bmin, float* bmax); - void getGridBounds(uint32 mapID, uint32 &minX, uint32 &minY, uint32 &maxX, uint32 &maxY); - - bool shouldSkipMap(uint32 mapID); - bool isTransportMap(uint32 mapID); - bool shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY); - - TerrainBuilder* m_terrainBuilder; - TileList m_tiles; - - bool m_debugOutput; - - const char* m_offMeshFilePath; - bool m_skipContinents; - bool m_skipJunkMaps; - bool m_skipBattlegrounds; - - float m_maxWalkableAngle; - bool m_bigBaseUnit; - - // build performance - not really used for now - rcContext* m_rcContext; - }; -} - -#endif diff --git a/src/tools/mmap_extractor/PathCommon.h b/src/tools/mmap_extractor/PathCommon.h deleted file mode 100644 index fd02ec02d50..00000000000 --- a/src/tools/mmap_extractor/PathCommon.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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 . - */ - -#ifndef _MMAP_COMMON_H -#define _MMAP_COMMON_H - -#include -#include - -#include "Define.h" - -#ifndef _WIN32 - #include - #include -#endif - -#ifdef __linux__ - #include -#endif - -using namespace std; - -namespace MMAP -{ - inline bool matchWildcardFilter(const char* filter, const char* str) - { - if (!filter || !str) - return false; - - // end on null character - while (*filter && *str) - { - if (*filter == '*') - { - if (*++filter == '\0') // wildcard at end of filter means all remaing chars match - return true; - - while (true) - { - if (*filter == *str) - break; - if (*str == '\0') - return false; // reached end of string without matching next filter character - str++; - } - } - else if (*filter != *str) - return false; // mismatch - - filter++; - str++; - } - - return ((*filter == '\0' || (*filter == '*' && *++filter == '\0')) && *str == '\0'); - } - - enum ListFilesResult - { - LISTFILE_DIRECTORY_NOT_FOUND = 0, - LISTFILE_OK = 1 - }; - - inline ListFilesResult getDirContents(vector &fileList, string dirpath = ".", string filter = "*", bool includeSubDirs = false) - { - #ifdef WIN32 - HANDLE hFind; - WIN32_FIND_DATA findFileInfo; - string directory; - - directory = dirpath + "/" + filter; - - hFind = FindFirstFile(directory.c_str(), &findFileInfo); - - if (hFind == INVALID_HANDLE_VALUE) - return LISTFILE_DIRECTORY_NOT_FOUND; - do - { - if (includeSubDirs || (findFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) - fileList.push_back(string(findFileInfo.cFileName)); - } - while (FindNextFile(hFind, &findFileInfo)); - - FindClose(hFind); - - #else - const char *p = dirpath.c_str(); - DIR * dirp = opendir(p); - struct dirent * dp; - dirp = opendir(p); - - while (dirp) - { - errno = 0; - if ((dp = readdir(dirp)) != NULL) - { - if (matchWildcardFilter(filter.c_str(), dp->d_name)) - fileList.push_back(string(dp->d_name)); - } - else - break; - } - - if (dirp) - closedir(dirp); - else - return LISTFILE_DIRECTORY_NOT_FOUND; - #endif - - return LISTFILE_OK; - } -} - -#endif diff --git a/src/tools/mmap_extractor/PathGenerator.cpp b/src/tools/mmap_extractor/PathGenerator.cpp deleted file mode 100644 index 2eb2c6545c4..00000000000 --- a/src/tools/mmap_extractor/PathGenerator.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "PathCommon.h" -#include "MapBuilder.h" - -using namespace MMAP; - -bool checkDirectories(bool debugOutput) -{ - vector dirFiles; - - if (getDirContents(dirFiles, "maps") == LISTFILE_DIRECTORY_NOT_FOUND || !dirFiles.size()) - { - printf("'maps' directory is empty or does not exist\n"); - return false; - } - - dirFiles.clear(); - if (getDirContents(dirFiles, "vmaps", "*.vmtree") == LISTFILE_DIRECTORY_NOT_FOUND || !dirFiles.size()) - { - printf("'vmaps' directory is empty or does not exist\n"); - return false; - } - - dirFiles.clear(); - if (getDirContents(dirFiles, "mmaps") == LISTFILE_DIRECTORY_NOT_FOUND) - { - printf("'mmaps' directory does not exist\n"); - return false; - } - - dirFiles.clear(); - if (debugOutput) - { - if (getDirContents(dirFiles, "meshes") == LISTFILE_DIRECTORY_NOT_FOUND) - { - printf("'meshes' directory does not exist (no place to put debugOutput files)\n"); - return false; - } - } - - return true; -} - -bool handleArgs(int argc, char** argv, - int &mapnum, - int &tileX, - int &tileY, - float &maxAngle, - bool &skipLiquid, - bool &skipContinents, - bool &skipJunkMaps, - bool &skipBattlegrounds, - bool &debugOutput, - bool &silent, - bool &bigBaseUnit, - char* &offMeshInputPath) -{ - char* param = NULL; - for (int i = 1; i < argc; ++i) - { - if (strcmp(argv[i], "--maxAngle") == 0) - { - param = argv[++i]; - if (!param) - return false; - - float maxangle = atof(param); - if (maxangle <= 90.f && maxangle >= 45.f) - maxAngle = maxangle; - else - printf("invalid option for '--maxAngle', using default\n"); - } - else if (strcmp(argv[i], "--tile") == 0) - { - param = argv[++i]; - if (!param) - return false; - - char* stileX = strtok(param, ","); - char* stileY = strtok(NULL, ","); - int tilex = atoi(stileX); - int tiley = atoi(stileY); - - if ((tilex > 0 && tilex < 64) || (tilex == 0 && strcmp(stileX, "0") == 0)) - tileX = tilex; - if ((tiley > 0 && tiley < 64) || (tiley == 0 && strcmp(stileY, "0") == 0)) - tileY = tiley; - - if (tileX < 0 || tileY < 0) - { - printf("invalid tile coords.\n"); - return false; - } - } - else if (strcmp(argv[i], "--skipLiquid") == 0) - { - param = argv[++i]; - if (!param) - return false; - - if (strcmp(param, "true") == 0) - skipLiquid = true; - else if (strcmp(param, "false") == 0) - skipLiquid = false; - else - printf("invalid option for '--skipLiquid', using default\n"); - } - else if (strcmp(argv[i], "--skipContinents") == 0) - { - param = argv[++i]; - if (!param) - return false; - - if (strcmp(param, "true") == 0) - skipContinents = true; - else if (strcmp(param, "false") == 0) - skipContinents = false; - else - printf("invalid option for '--skipContinents', using default\n"); - } - else if (strcmp(argv[i], "--skipJunkMaps") == 0) - { - param = argv[++i]; - if (!param) - return false; - - if (strcmp(param, "true") == 0) - skipJunkMaps = true; - else if (strcmp(param, "false") == 0) - skipJunkMaps = false; - else - printf("invalid option for '--skipJunkMaps', using default\n"); - } - else if (strcmp(argv[i], "--skipBattlegrounds") == 0) - { - param = argv[++i]; - if (!param) - return false; - - if (strcmp(param, "true") == 0) - skipBattlegrounds = true; - else if (strcmp(param, "false") == 0) - skipBattlegrounds = false; - else - printf("invalid option for '--skipBattlegrounds', using default\n"); - } - else if (strcmp(argv[i], "--debugOutput") == 0) - { - param = argv[++i]; - if (!param) - return false; - - if (strcmp(param, "true") == 0) - debugOutput = true; - else if (strcmp(param, "false") == 0) - debugOutput = false; - else - printf("invalid option for '--debugOutput', using default true\n"); - } - else if (strcmp(argv[i], "--silent") == 0) - { - silent = true; - } - else if (strcmp(argv[i], "--bigBaseUnit") == 0) - { - param = argv[++i]; - if (!param) - return false; - - if (strcmp(param, "true") == 0) - bigBaseUnit = true; - else if (strcmp(param, "false") == 0) - bigBaseUnit = false; - else - printf("invalid option for '--bigBaseUnit', using default false\n"); - } - else if (strcmp(argv[i], "--offMeshInput") == 0) - { - param = argv[++i]; - if (!param) - return false; - - offMeshInputPath = param; - } - else - { - int map = atoi(argv[i]); - if (map > 0 || (map == 0 && (strcmp(argv[i], "0") == 0))) - mapnum = map; - else - { - printf("invalid map id\n"); - return false; - } - } - } - - return true; -} - -int finish(const char* message, int returnValue) -{ - printf("%s", message); - getchar(); - return returnValue; -} - -int main(int argc, char** argv) -{ - int mapnum = -1; - float maxAngle = 60.0f; - int tileX = -1, tileY = -1; - bool skipLiquid = false, - skipContinents = false, - skipJunkMaps = true, - skipBattlegrounds = false, - debugOutput = false, - silent = false, - bigBaseUnit = false; - char* offMeshInputPath = NULL; - - bool validParam = handleArgs(argc, argv, mapnum, - tileX, tileY, maxAngle, - skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, - debugOutput, silent, bigBaseUnit, offMeshInputPath); - - if (!validParam) - return silent ? -1 : finish("You have specified invalid parameters", -1); - - if (mapnum == -1 && debugOutput) - { - if (silent) - return -2; - - printf("You have specifed debug output, but didn't specify a map to generate.\n"); - printf("This will generate debug output for ALL maps.\n"); - printf("Are you sure you want to continue? (y/n) "); - if (getchar() != 'y') - return 0; - } - - if (!checkDirectories(debugOutput)) - return silent ? -3 : finish("Press any key to close...", -3); - - MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps, - skipBattlegrounds, debugOutput, bigBaseUnit, offMeshInputPath); - - if (tileX > -1 && tileY > -1 && mapnum >= 0) - builder.buildSingleTile(mapnum, tileX, tileY); - else if (mapnum >= 0) - builder.buildMap(uint32(mapnum)); - else - builder.buildAllMaps(); - - return silent ? 1 : finish("Movemap build is complete!", 1); -} diff --git a/src/tools/mmap_extractor/TerrainBuilder.cpp b/src/tools/mmap_extractor/TerrainBuilder.cpp deleted file mode 100644 index c696f6017a5..00000000000 --- a/src/tools/mmap_extractor/TerrainBuilder.cpp +++ /dev/null @@ -1,854 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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 . - */ - -#include "TerrainBuilder.h" - -#include "PathCommon.h" -#include "MapBuilder.h" - -#include "VMapManager2.h" -#include "MapTree.h" -#include "ModelInstance.h" - -namespace MMAP -{ - TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ } - TerrainBuilder::~TerrainBuilder() { } - - /**************************************************************************/ - void TerrainBuilder::getLoopVars(Spot portion, int &loopStart, int &loopEnd, int &loopInc) - { - switch (portion) - { - case ENTIRE: - loopStart = 0; - loopEnd = V8_SIZE_SQ; - loopInc = 1; - break; - case TOP: - loopStart = 0; - loopEnd = V8_SIZE; - loopInc = 1; - break; - case LEFT: - loopStart = 0; - loopEnd = V8_SIZE_SQ - V8_SIZE + 1; - loopInc = V8_SIZE; - break; - case RIGHT: - loopStart = V8_SIZE - 1; - loopEnd = V8_SIZE_SQ; - loopInc = V8_SIZE; - break; - case BOTTOM: - loopStart = V8_SIZE_SQ - V8_SIZE; - loopEnd = V8_SIZE_SQ; - loopInc = 1; - break; - } - } - - /**************************************************************************/ - void TerrainBuilder::loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) - { - if (loadMap(mapID, tileX, tileY, meshData, ENTIRE)) - { - loadMap(mapID, tileX+1, tileY, meshData, LEFT); - loadMap(mapID, tileX-1, tileY, meshData, RIGHT); - loadMap(mapID, tileX, tileY+1, meshData, TOP); - loadMap(mapID, tileX, tileY-1, meshData, BOTTOM); - } - } - - /**************************************************************************/ - bool TerrainBuilder::loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, Spot portion) - { - char mapFileName[255]; - sprintf(mapFileName, "maps/%03u%02u%02u.map", mapID, tileY, tileX); - - FILE* mapFile = fopen(mapFileName, "rb"); - if (!mapFile) - return false; - - map_fileheader fheader; - fread(&fheader, sizeof(map_fileheader), 1, mapFile); - - if (fheader.versionMagic != *((uint32 const*)(MAP_VERSION_MAGIC))) - { - fclose(mapFile); - printf("%s is the wrong version, please extract new .map files\n", mapFileName); - return false; - } - - map_heightHeader hheader; - fseek(mapFile, fheader.heightMapOffset, SEEK_SET); - fread(&hheader, sizeof(map_heightHeader), 1, mapFile); - - bool haveTerrain = !(hheader.flags & MAP_HEIGHT_NO_HEIGHT); - bool haveLiquid = fheader.liquidMapOffset && !m_skipLiquid; - - // no data in this map file - if (!haveTerrain && !haveLiquid) - { - fclose(mapFile); - return false; - } - - // data used later - uint16 holes[16][16]; - memset(holes, 0, sizeof(holes)); - uint8 liquid_type[16][16]; - memset(liquid_type, 0, sizeof(liquid_type)); - G3D::Array ltriangles; - G3D::Array ttriangles; - - // terrain data - if (haveTerrain) - { - int i; - float heightMultiplier; - float V9[V9_SIZE_SQ], V8[V8_SIZE_SQ]; - - if (hheader.flags & MAP_HEIGHT_AS_INT8) - { - uint8 v9[V9_SIZE_SQ]; - uint8 v8[V8_SIZE_SQ]; - fread(v9, sizeof(uint8), V9_SIZE_SQ, mapFile); - fread(v8, sizeof(uint8), V8_SIZE_SQ, mapFile); - heightMultiplier = (hheader.gridMaxHeight - hheader.gridHeight) / 255; - - for (i = 0; i < V9_SIZE_SQ; ++i) - V9[i] = (float)v9[i]*heightMultiplier + hheader.gridHeight; - - for (i = 0; i < V8_SIZE_SQ; ++i) - V8[i] = (float)v8[i]*heightMultiplier + hheader.gridHeight; - } - else if (hheader.flags & MAP_HEIGHT_AS_INT16) - { - uint16 v9[V9_SIZE_SQ]; - uint16 v8[V8_SIZE_SQ]; - fread(v9, sizeof(uint16), V9_SIZE_SQ, mapFile); - fread(v8, sizeof(uint16), V8_SIZE_SQ, mapFile); - heightMultiplier = (hheader.gridMaxHeight - hheader.gridHeight) / 65535; - - for (i = 0; i < V9_SIZE_SQ; ++i) - V9[i] = (float)v9[i]*heightMultiplier + hheader.gridHeight; - - for (i = 0; i < V8_SIZE_SQ; ++i) - V8[i] = (float)v8[i]*heightMultiplier + hheader.gridHeight; - } - else - { - fread (V9, sizeof(float), V9_SIZE_SQ, mapFile); - fread(V8, sizeof(float), V8_SIZE_SQ, mapFile); - } - - // hole data - memset(holes, 0, fheader.holesSize); - fseek(mapFile, fheader.holesOffset, SEEK_SET); - fread(holes, fheader.holesSize, 1, mapFile); - - int count = meshData.solidVerts.size() / 3; - float xoffset = (float(tileX)-32)*GRID_SIZE; - float yoffset = (float(tileY)-32)*GRID_SIZE; - - float coord[3]; - - for (i = 0; i < V9_SIZE_SQ; ++i) - { - getHeightCoord(i, GRID_V9, xoffset, yoffset, coord, V9); - meshData.solidVerts.append(coord[0]); - meshData.solidVerts.append(coord[2]); - meshData.solidVerts.append(coord[1]); - } - - for (i = 0; i < V8_SIZE_SQ; ++i) - { - getHeightCoord(i, GRID_V8, xoffset, yoffset, coord, V8); - meshData.solidVerts.append(coord[0]); - meshData.solidVerts.append(coord[2]); - meshData.solidVerts.append(coord[1]); - } - - int j, indices[3], loopStart, loopEnd, loopInc; - getLoopVars(portion, loopStart, loopEnd, loopInc); - for (i = loopStart; i < loopEnd; i+=loopInc) - for (j = TOP; j <= BOTTOM; j+=1) - { - getHeightTriangle(i, Spot(j), indices); - ttriangles.append(indices[2] + count); - ttriangles.append(indices[1] + count); - ttriangles.append(indices[0] + count); - } - } - - // liquid data - if (haveLiquid) - { - map_liquidHeader lheader; - fseek(mapFile, fheader.liquidMapOffset, SEEK_SET); - fread(&lheader, sizeof(map_liquidHeader), 1, mapFile); - - float* liquid_map = NULL; - - if (!(lheader.flags & MAP_LIQUID_NO_TYPE)) - fread(liquid_type, sizeof(liquid_type), 1, mapFile); - - if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT)) - { - liquid_map = new float [lheader.width*lheader.height]; - fread(liquid_map, sizeof(float), lheader.width*lheader.height, mapFile); - } - - if (liquid_type && liquid_map) - { - int count = meshData.liquidVerts.size() / 3; - float xoffset = (float(tileX)-32)*GRID_SIZE; - float yoffset = (float(tileY)-32)*GRID_SIZE; - - float coord[3]; - int row, col; - - // generate coordinates - if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT)) - { - int j = 0; - for (int i = 0; i < V9_SIZE_SQ; ++i) - { - row = i / V9_SIZE; - col = i % V9_SIZE; - - if (row < lheader.offsetY || row >= lheader.offsetY + lheader.height || - col < lheader.offsetX || col >= lheader.offsetX + lheader.width) - { - // dummy vert using invalid height - meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, INVALID_MAP_LIQ_HEIGHT, (yoffset+row*GRID_PART_SIZE)*-1); - continue; - } - - getLiquidCoord(i, j, xoffset, yoffset, coord, liquid_map); - meshData.liquidVerts.append(coord[0]); - meshData.liquidVerts.append(coord[2]); - meshData.liquidVerts.append(coord[1]); - j++; - } - } - else - { - for (int i = 0; i < V9_SIZE_SQ; ++i) - { - row = i / V9_SIZE; - col = i % V9_SIZE; - meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, lheader.liquidLevel, (yoffset+row*GRID_PART_SIZE)*-1); - } - } - - delete [] liquid_map; - - int indices[3], loopStart, loopEnd, loopInc, triInc; - getLoopVars(portion, loopStart, loopEnd, loopInc); - triInc = BOTTOM-TOP; - - // generate triangles - for (int i = loopStart; i < loopEnd; i+=loopInc) - for (int j = TOP; j <= BOTTOM; j+= triInc) - { - getHeightTriangle(i, Spot(j), indices, true); - ltriangles.append(indices[2] + count); - ltriangles.append(indices[1] + count); - ltriangles.append(indices[0] + count); - } - } - } - - fclose(mapFile); - - // now that we have gathered the data, we can figure out which parts to keep: - // liquid above ground, ground above liquid - int loopStart, loopEnd, loopInc, tTriCount = 4; - bool useTerrain, useLiquid; - - float* lverts = meshData.liquidVerts.getCArray(); - int* ltris = ltriangles.getCArray(); - - float* tverts = meshData.solidVerts.getCArray(); - int* ttris = ttriangles.getCArray(); - - if (ltriangles.size() + ttriangles.size() == 0) - return false; - - // make a copy of liquid vertices - // used to pad right-bottom frame due to lost vertex data at extraction - float* lverts_copy = NULL; - if (meshData.liquidVerts.size()) - { - lverts_copy = new float[meshData.liquidVerts.size()]; - memcpy(lverts_copy, lverts, sizeof(float)*meshData.liquidVerts.size()); - } - - getLoopVars(portion, loopStart, loopEnd, loopInc); - for (int i = loopStart; i < loopEnd; i+=loopInc) - { - for (int j = 0; j < 2; ++j) - { - // default is true, will change to false if needed - useTerrain = true; - useLiquid = true; - uint8 liquidType = MAP_LIQUID_TYPE_NO_WATER; - - // if there is no liquid, don't use liquid - if (!liquid_type || !meshData.liquidVerts.size() || !ltriangles.size()) - useLiquid = false; - else - { - liquidType = getLiquidType(i, liquid_type); - switch (liquidType) - { - default: - useLiquid = false; - break; - case MAP_LIQUID_TYPE_WATER: - case MAP_LIQUID_TYPE_OCEAN: - // merge different types of water - liquidType = NAV_WATER; - break; - case MAP_LIQUID_TYPE_MAGMA: - liquidType = NAV_MAGMA; - break; - case MAP_LIQUID_TYPE_SLIME: - liquidType = NAV_SLIME; - break; - case MAP_LIQUID_TYPE_DARK_WATER: - // players should not be here, so logically neither should creatures - useTerrain = false; - useLiquid = false; - break; - } - } - - // if there is no terrain, don't use terrain - if (!ttriangles.size()) - useTerrain = false; - - // while extracting ADT data we are losing right-bottom vertices - // this code adds fair approximation of lost data - if (useLiquid) - { - float quadHeight = 0; - uint32 validCount = 0; - for(uint32 idx = 0; idx < 3; idx++) - { - float h = lverts_copy[ltris[idx]*3 + 1]; - if (h != INVALID_MAP_LIQ_HEIGHT && h < INVALID_MAP_LIQ_HEIGHT_MAX) - { - quadHeight += h; - validCount++; - } - } - - // update vertex height data - if (validCount > 0 && validCount < 3) - { - quadHeight /= validCount; - for(uint32 idx = 0; idx < 3; idx++) - { - float h = lverts[ltris[idx]*3 + 1]; - if (h == INVALID_MAP_LIQ_HEIGHT || h > INVALID_MAP_LIQ_HEIGHT_MAX) - lverts[ltris[idx]*3 + 1] = quadHeight; - } - } - - // no valid vertexes - don't use this poly at all - if (validCount == 0) - useLiquid = false; - } - - // if there is a hole here, don't use the terrain - if (useTerrain) - useTerrain = !isHole(i, holes); - - // we use only one terrain kind per quad - pick higher one - if (useTerrain && useLiquid) - { - float minLLevel = INVALID_MAP_LIQ_HEIGHT_MAX; - float maxLLevel = INVALID_MAP_LIQ_HEIGHT; - for(uint32 x = 0; x < 3; x++) - { - float h = lverts[ltris[x]*3 + 1]; - if (minLLevel > h) - minLLevel = h; - - if (maxLLevel < h) - maxLLevel = h; - } - - float maxTLevel = INVALID_MAP_LIQ_HEIGHT; - float minTLevel = INVALID_MAP_LIQ_HEIGHT_MAX; - for(uint32 x = 0; x < 6; x++) - { - float h = tverts[ttris[x]*3 + 1]; - if (maxTLevel < h) - maxTLevel = h; - - if (minTLevel > h) - minTLevel = h; - } - - // terrain under the liquid? - if (minLLevel > maxTLevel) - useTerrain = false; - - //liquid under the terrain? - if (minTLevel > maxLLevel) - useLiquid = false; - } - - // store the result - if (useLiquid) - { - meshData.liquidType.append(liquidType); - for (int k = 0; k < 3; ++k) - meshData.liquidTris.append(ltris[k]); - } - - if (useTerrain) - for (int k = 0; k < 3*tTriCount/2; ++k) - meshData.solidTris.append(ttris[k]); - - // advance to next set of triangles - ltris += 3; - ttris += 3*tTriCount/2; - } - } - - if (lverts_copy) - delete [] lverts_copy; - - return meshData.solidTris.size() || meshData.liquidTris.size(); - } - - /**************************************************************************/ - void TerrainBuilder::getHeightCoord(int index, Grid grid, float xOffset, float yOffset, float* coord, float* v) - { - // wow coords: x, y, height - // coord is mirroed about the horizontal axes - switch (grid) - { - case GRID_V9: - coord[0] = (xOffset + index%(V9_SIZE)*GRID_PART_SIZE) * -1.f; - coord[1] = (yOffset + (int)(index/(V9_SIZE))*GRID_PART_SIZE) * -1.f; - coord[2] = v[index]; - break; - case GRID_V8: - coord[0] = (xOffset + index%(V8_SIZE)*GRID_PART_SIZE + GRID_PART_SIZE/2.f) * -1.f; - coord[1] = (yOffset + (int)(index/(V8_SIZE))*GRID_PART_SIZE + GRID_PART_SIZE/2.f) * -1.f; - coord[2] = v[index]; - break; - } - } - - /**************************************************************************/ - void TerrainBuilder::getHeightTriangle(int square, Spot triangle, int* indices, bool liquid/* = false*/) - { - int rowOffset = square/V8_SIZE; - if (!liquid) - switch (triangle) - { - case TOP: - indices[0] = square+rowOffset; // 0-----1 .... 128 - indices[1] = square+1+rowOffset; // |\ T /| - indices[2] = (V9_SIZE_SQ)+square; // | \ / | - break; // |L 0 R| .. 127 - case LEFT: // | / \ | - indices[0] = square+rowOffset; // |/ B \| - indices[1] = (V9_SIZE_SQ)+square; // 129---130 ... 386 - indices[2] = square+V9_SIZE+rowOffset; // |\ /| - break; // | \ / | - case RIGHT: // | 128 | .. 255 - indices[0] = square+1+rowOffset; // | / \ | - indices[1] = square+V9_SIZE+1+rowOffset; // |/ \| - indices[2] = (V9_SIZE_SQ)+square; // 258---259 ... 515 - break; - case BOTTOM: - indices[0] = (V9_SIZE_SQ)+square; - indices[1] = square+V9_SIZE+1+rowOffset; - indices[2] = square+V9_SIZE+rowOffset; - break; - default: break; - } - else - switch (triangle) - { // 0-----1 .... 128 - case TOP: // |\ | - indices[0] = square+rowOffset; // | \ T | - indices[1] = square+1+rowOffset; // | \ | - indices[2] = square+V9_SIZE+1+rowOffset; // | B \ | - break; // | \| - case BOTTOM: // 129---130 ... 386 - indices[0] = square+rowOffset; // |\ | - indices[1] = square+V9_SIZE+1+rowOffset; // | \ | - indices[2] = square+V9_SIZE+rowOffset; // | \ | - break; // | \ | - default: break; // | \| - } // 258---259 ... 515 - - } - - /**************************************************************************/ - void TerrainBuilder::getLiquidCoord(int index, int index2, float xOffset, float yOffset, float* coord, float* v) - { - // wow coords: x, y, height - // coord is mirroed about the horizontal axes - coord[0] = (xOffset + index%(V9_SIZE)*GRID_PART_SIZE) * -1.f; - coord[1] = (yOffset + (int)(index/(V9_SIZE))*GRID_PART_SIZE) * -1.f; - coord[2] = v[index2]; - } - - static uint16 holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; - static uint16 holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; - - /**************************************************************************/ - bool TerrainBuilder::isHole(int square, const uint16 holes[16][16]) - { - int row = square / 128; - int col = square % 128; - int cellRow = row / 8; // 8 squares per cell - int cellCol = col / 8; - int holeRow = row % 8 / 2; - int holeCol = (square - (row * 128 + cellCol * 8)) / 2; - - uint16 hole = holes[cellRow][cellCol]; - - return (hole & holetab_h[holeCol] & holetab_v[holeRow]) != 0; - } - - /**************************************************************************/ - uint8 TerrainBuilder::getLiquidType(int square, const uint8 liquid_type[16][16]) - { - int row = square / 128; - int col = square % 128; - int cellRow = row / 8; // 8 squares per cell - int cellCol = col / 8; - - return liquid_type[cellRow][cellCol]; - } - - /**************************************************************************/ - bool TerrainBuilder::loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) - { - IVMapManager* vmapManager = new VMapManager2(); - int result = vmapManager->loadMap("vmaps", mapID, tileX, tileY); - bool retval = false; - - do - { - if (result == VMAP_LOAD_RESULT_ERROR) - break; - - InstanceTreeMap instanceTrees; - ((VMapManager2*)vmapManager)->getInstanceMapTree(instanceTrees); - - if (!instanceTrees[mapID]) - break; - - ModelInstance* models = NULL; - uint32 count = 0; - instanceTrees[mapID]->getModelInstances(models, count); - - if (!models) - break; - - for (uint32 i = 0; i < count; ++i) - { - ModelInstance instance = models[i]; - - // model instances exist in tree even though there are instances of that model in this tile - WorldModel* worldModel = instance.getWorldModel(); - if (!worldModel) - continue; - - // now we have a model to add to the meshdata - retval = true; - - vector groupModels; - worldModel->getGroupModels(groupModels); - - // all M2s need to have triangle indices reversed - bool isM2 = instance.name.find(".m2") != instance.name.npos || instance.name.find(".M2") != instance.name.npos; - - // transform data - float scale = instance.iScale; - G3D::Matrix3 rotation = G3D::Matrix3::fromEulerAnglesXYZ(G3D::pi()*instance.iRot.z/-180.f, G3D::pi()*instance.iRot.x/-180.f, G3D::pi()*instance.iRot.y/-180.f); - Vector3 position = instance.iPos; - position.x -= 32*GRID_SIZE; - position.y -= 32*GRID_SIZE; - - for (vector::iterator it = groupModels.begin(); it != groupModels.end(); ++it) - { - vector tempVertices; - vector transformedVertices; - vector tempTriangles; - WmoLiquid* liquid = NULL; - - (*it).getMeshData(tempVertices, tempTriangles, liquid); - - // first handle collision mesh - transform(tempVertices, transformedVertices, scale, rotation, position); - - int offset = meshData.solidVerts.size() / 3; - - copyVertices(transformedVertices, meshData.solidVerts); - copyIndices(tempTriangles, meshData.solidTris, offset, isM2); - - // now handle liquid data - if (liquid) - { - vector liqVerts; - vector liqTris; - uint32 tilesX, tilesY, vertsX, vertsY; - Vector3 corner; - liquid->getPosInfo(tilesX, tilesY, corner); - vertsX = tilesX + 1; - vertsY = tilesY + 1; - uint8* flags = liquid->GetFlagsStorage(); - float* data = liquid->GetHeightStorage(); - uint8 type = NAV_EMPTY; - - // convert liquid type to NavTerrain - switch (liquid->GetType()) - { - case 0: - case 1: - type = NAV_WATER; - break; - case 2: - type = NAV_MAGMA; - break; - case 3: - type = NAV_SLIME; - break; - } - - // indexing is weird... - // after a lot of trial and error, this is what works: - // vertex = y*vertsX+x - // tile = x*tilesY+y - // flag = y*tilesY+x - - Vector3 vert; - for (uint32 x = 0; x < vertsX; ++x) - for (uint32 y = 0; y < vertsY; ++y) - { - vert = Vector3(corner.x + x * GRID_PART_SIZE, corner.y + y * GRID_PART_SIZE, data[y*vertsX + x]); - vert = vert * rotation * scale + position; - vert.x *= -1.f; - vert.y *= -1.f; - liqVerts.push_back(vert); - } - - int idx1, idx2, idx3, idx4; - uint32 square; - for (uint32 x = 0; x < tilesX; ++x) - for (uint32 y = 0; y < tilesY; ++y) - if ((flags[x+y*tilesX] & 0x0f) != 0x0f) - { - square = x * tilesY + y; - idx1 = square+x; - idx2 = square+1+x; - idx3 = square+tilesY+1+1+x; - idx4 = square+tilesY+1+x; - - // top triangle - liqTris.push_back(idx3); - liqTris.push_back(idx2); - liqTris.push_back(idx1); - // bottom triangle - liqTris.push_back(idx4); - liqTris.push_back(idx3); - liqTris.push_back(idx1); - } - - uint32 liqOffset = meshData.liquidVerts.size() / 3; - for (uint32 i = 0; i < liqVerts.size(); ++i) - meshData.liquidVerts.append(liqVerts[i].y, liqVerts[i].z, liqVerts[i].x); - - for (uint32 i = 0; i < liqTris.size() / 3; ++i) - { - meshData.liquidTris.append(liqTris[i*3+1] + liqOffset, liqTris[i*3+2] + liqOffset, liqTris[i*3] + liqOffset); - meshData.liquidType.append(type); - } - } - } - } - } - while (false); - - vmapManager->unloadMap(mapID, tileX, tileY); - delete vmapManager; - - return retval; - } - - /**************************************************************************/ - void TerrainBuilder::transform(vector &source, vector &transformedVertices, float scale, G3D::Matrix3 &rotation, Vector3 &position) - { - for (vector::iterator it = source.begin(); it != source.end(); ++it) - { - // apply tranform, then mirror along the horizontal axes - Vector3 v((*it) * rotation * scale + position); - v.x *= -1.f; - v.y *= -1.f; - transformedVertices.push_back(v); - } - } - - /**************************************************************************/ - void TerrainBuilder::copyVertices(vector &source, G3D::Array &dest) - { - for (vector::iterator it = source.begin(); it != source.end(); ++it) - { - dest.push_back((*it).y); - dest.push_back((*it).z); - dest.push_back((*it).x); - } - } - - /**************************************************************************/ - void TerrainBuilder::copyIndices(vector &source, G3D::Array &dest, int offset, bool flip) - { - if (flip) - { - for (vector::iterator it = source.begin(); it != source.end(); ++it) - { - dest.push_back((*it).idx2+offset); - dest.push_back((*it).idx1+offset); - dest.push_back((*it).idx0+offset); - } - } - else - { - for (vector::iterator it = source.begin(); it != source.end(); ++it) - { - dest.push_back((*it).idx0+offset); - dest.push_back((*it).idx1+offset); - dest.push_back((*it).idx2+offset); - } - } - } - - /**************************************************************************/ - void TerrainBuilder::copyIndices(G3D::Array &source, G3D::Array &dest, int offset) - { - int* src = source.getCArray(); - for (int32 i = 0; i < source.size(); ++i) - dest.append(src[i] + offset); - } - - /**************************************************************************/ - void TerrainBuilder::cleanVertices(G3D::Array &verts, G3D::Array &tris) - { - map vertMap; - - int* t = tris.getCArray(); - float* v = verts.getCArray(); - - // collect all the vertex indices from triangle - for (int i = 0; i < tris.size(); ++i) - { - if (vertMap.find(t[i]) != vertMap.end()) - continue; - - vertMap.insert(std::pair(t[i], 0)); - } - - // collect the vertices - G3D::Array cleanVerts; - int index, count = 0; - for (map::iterator it = vertMap.begin(); it != vertMap.end(); ++it) - { - index = (*it).first; - (*it).second = count; - cleanVerts.append(v[index*3], v[index*3+1], v[index*3+2]); - count++; - } - verts.fastClear(); - verts.append(cleanVerts); - cleanVerts.clear(); - - // update triangles to use new indices - for (int i = 0; i < tris.size(); ++i) - { - map::iterator it; - if ((it = vertMap.find(t[i])) == vertMap.end()) - continue; - - t[i] = (*it).second; - } - - vertMap.clear(); - } - - /**************************************************************************/ - void TerrainBuilder::loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, const char* offMeshFilePath) - { - // no meshfile input given? - if (offMeshFilePath == NULL) - return; - - FILE* fp = fopen(offMeshFilePath, "rb"); - if (!fp) - { - printf(" loadOffMeshConnections:: input file %s not found!\n", offMeshFilePath); - return; - } - - // pretty silly thing, as we parse entire file and load only the tile we need - // but we don't expect this file to be too large - char* buf = new char[512]; - while(fgets(buf, 512, fp)) - { - float p0[3], p1[3]; - int mid, tx, ty; - float size; - if (10 != sscanf(buf, "%d %d,%d (%f %f %f) (%f %f %f) %f", &mid, &tx, &ty, - &p0[0], &p0[1], &p0[2], &p1[0], &p1[1], &p1[2], &size)) - continue; - - if (mapID == mid, tileX == tx, tileY == ty) - { - meshData.offMeshConnections.append(p0[1]); - meshData.offMeshConnections.append(p0[2]); - meshData.offMeshConnections.append(p0[0]); - - meshData.offMeshConnections.append(p1[1]); - meshData.offMeshConnections.append(p1[2]); - meshData.offMeshConnections.append(p1[0]); - - meshData.offMeshConnectionDirs.append(1); // 1 - both direction, 0 - one sided - meshData.offMeshConnectionRads.append(size); // agent size equivalent - // can be used same way as polygon flags - meshData.offMeshConnectionsAreas.append((unsigned char)0xFF); - meshData.offMeshConnectionsFlags.append((unsigned short)0xFF); // all movement masks can make this path - } - - } - - delete [] buf; - fclose(fp); - } -} diff --git a/src/tools/mmap_extractor/TerrainBuilder.h b/src/tools/mmap_extractor/TerrainBuilder.h deleted file mode 100644 index a7f21883af2..00000000000 --- a/src/tools/mmap_extractor/TerrainBuilder.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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 . - */ - -#ifndef _MMAP_TERRAIN_BUILDER_H -#define _MMAP_TERRAIN_BUILDER_H - -#include "PathCommon.h" -#include "Map.h" -#include "SharedDefines.h" - -#include "WorldModel.h" - -#include "G3D/Array.h" -#include "G3D/Vector3.h" -#include "G3D/Matrix3.h" - -using namespace Trinity; - -namespace MMAP -{ - enum Spot - { - TOP = 1, - RIGHT = 2, - LEFT = 3, - BOTTOM = 4, - ENTIRE = 5 - }; - - enum Grid - { - GRID_V8, - GRID_V9 - }; - - static const int V9_SIZE = 129; - static const int V9_SIZE_SQ = V9_SIZE*V9_SIZE; - static const int V8_SIZE = 128; - static const int V8_SIZE_SQ = V8_SIZE*V8_SIZE; - static const float GRID_SIZE = 533.33333f; - static const float GRID_PART_SIZE = GRID_SIZE/V8_SIZE; - - // see contrib/extractor/system.cpp, CONF_use_minHeight - static const float INVALID_MAP_LIQ_HEIGHT = -500.f; - static const float INVALID_MAP_LIQ_HEIGHT_MAX = 5000.0f; - - // see following files: - // contrib/extractor/system.cpp - // src/game/Map.cpp - static char const* MAP_VERSION_MAGIC = "v1.2"; - - struct MeshData - { - G3D::Array solidVerts; - G3D::Array solidTris; - - G3D::Array liquidVerts; - G3D::Array liquidTris; - G3D::Array liquidType; - - // offmesh connection data - G3D::Array offMeshConnections; // [p0y,p0z,p0x,p1y,p1z,p1x] - per connection - G3D::Array offMeshConnectionRads; - G3D::Array offMeshConnectionDirs; - G3D::Array offMeshConnectionsAreas; - G3D::Array offMeshConnectionsFlags; - }; - - class TerrainBuilder - { - public: - TerrainBuilder(bool skipLiquid); - ~TerrainBuilder(); - - void loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); - bool loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); - void loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, const char* offMeshFilePath); - - bool usesLiquids() { return !m_skipLiquid; } - - // vert and triangle methods - static void transform(vector &original, vector &transformed, - float scale, G3D::Matrix3 &rotation, G3D::Vector3 &position); - static void copyVertices(vector &source, G3D::Array &dest); - static void copyIndices(vector &source, G3D::Array &dest, int offest, bool flip); - static void copyIndices(G3D::Array &src, G3D::Array &dest, int offset); - static void cleanVertices(G3D::Array &verts, G3D::Array &tris); - private: - /// Loads a portion of a map's terrain - bool loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, Spot portion); - - /// Sets loop variables for selecting only certain parts of a map's terrain - void getLoopVars(Spot portion, int &loopStart, int &loopEnd, int &loopInc); - - /// Controls whether liquids are loaded - bool m_skipLiquid; - - /// Load the map terrain from file - bool loadHeightMap(uint32 mapID, uint32 tileX, uint32 tileY, G3D::Array &vertices, G3D::Array &triangles, Spot portion); - - /// Get the vector coordinate for a specific position - void getHeightCoord(int index, Grid grid, float xOffset, float yOffset, float* coord, float* v); - - /// Get the triangle's vector indices for a specific position - void getHeightTriangle(int square, Spot triangle, int* indices, bool liquid = false); - - /// Determines if the specific position's triangles should be rendered - bool isHole(int square, const uint16 holes[16][16]); - - /// Get the liquid vector coordinate for a specific position - void getLiquidCoord(int index, int index2, float xOffset, float yOffset, float* coord, float* v); - - /// Get the liquid type for a specific position - uint8 getLiquidType(int square, const uint8 liquid_type[16][16]); - - // hide parameterless and copy constructor - TerrainBuilder(); - TerrainBuilder(const TerrainBuilder &tb); - }; -} - -#endif - diff --git a/src/tools/mmap_extractor/VMapExtensions.cpp b/src/tools/mmap_extractor/VMapExtensions.cpp deleted file mode 100644 index 4f203e11c21..00000000000 --- a/src/tools/mmap_extractor/VMapExtensions.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2008-2011 TrinityCore - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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 . - */ - -#include -#include "MapTree.h" -#include "VMapManager2.h" -#include "WorldModel.h" -#include "ModelInstance.h" - -using namespace std; - -namespace VMAP -{ - // Need direct access to encapsulated VMAP data, so we add functions for MMAP generator - // maybe add MapBuilder as friend to all of the below classes would be better? - - // declared in src/shared/vmap/MapTree.h - void StaticMapTree::getModelInstances(ModelInstance* &models, uint32 &count) - { - models = iTreeValues; - count = iNTreeValues; - } - - // declared in src/shared/vmap/VMapManager2.h - void VMapManager2::getInstanceMapTree(InstanceTreeMap &instanceMapTree) - { - instanceMapTree = iInstanceMapTrees; - } - - // declared in src/shared/vmap/WorldModel.h - void WorldModel::getGroupModels(vector &groupModels) - { - groupModels = this->groupModels; - } - - // declared in src/shared/vmap/WorldModel.h - void GroupModel::getMeshData(vector &vertices, vector &triangles, WmoLiquid* &liquid) - { - vertices = this->vertices; - triangles = this->triangles; - liquid = iLiquid; - } - - // declared in src/shared/vmap/ModelInstance.h - WorldModel* const ModelInstance::getWorldModel() - { - return iModel; - } - - // declared in src/shared/vmap/WorldModel.h - void WmoLiquid::getPosInfo(uint32 &tilesX, uint32 &tilesY, Vector3 &corner) const - { - tilesX = iTilesX; - tilesY = iTilesY; - corner = iCorner; - } -} diff --git a/src/tools/mmaps_generator/CMakeLists.txt b/src/tools/mmaps_generator/CMakeLists.txt new file mode 100644 index 00000000000..46bf9d00d43 --- /dev/null +++ b/src/tools/mmaps_generator/CMakeLists.txt @@ -0,0 +1,68 @@ +# Copyright (C) 2008-2011 Trinity +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +file(GLOB_RECURSE sources *.cpp *.h) + +# definitions +add_definitions(-DNO_CORE_FUNCS) +add_definitions(-DDEBUG) +add_definitions(-DNO_vsnprintf) + +include_directories( + ${CMAKE_BINARY_DIR} + ${ACE_INCLUDE_DIR} + ${MYSQL_INCLUDE_DIR} + ${CMAKE_SOURCE_DIR}/dep/libmpq + ${CMAKE_SOURCE_DIR}/dep/zlib + ${CMAKE_SOURCE_DIR}/dep/bzip2 + ${CMAKE_SOURCE_DIR}/dep/acelite + ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/Database + ${CMAKE_SOURCE_DIR}/src/server/shared/Database/Implementation + ${CMAKE_SOURCE_DIR}/src/server/shared/Threading + ${CMAKE_SOURCE_DIR}/src/server/shared/Logging + ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference + ${CMAKE_SOURCE_DIR}/src/server/game/Maps + ${CMAKE_SOURCE_DIR}/src/server/game/DataStores + ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints + ${CMAKE_SOURCE_DIR}/src/server/game/Grids + ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells + ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous + ${CMAKE_SOURCE_DIR}/src/server/game/Conditions + ${CMAKE_SOURCE_DIR}/src/server/collision + ${CMAKE_SOURCE_DIR}/src/server/collision/Management + ${CMAKE_SOURCE_DIR}/src/server/collision/Maps + ${CMAKE_SOURCE_DIR}/src/server/collision/Models +) + +add_executable(mmaps_generator ${sources}) + +target_link_libraries(mmaps_generator + ${MYSQL_LIBRARY} + ${ACE_LIBRARY} + ${BZIP2_LIBRARIES} + ${ZLIB_LIBRARIES} + Recast + Detour + collision + g3dlib + shared +) + +if( UNIX ) + install(TARGETS mmaps_generator DESTINATION bin) +elseif( WIN32 ) + install(TARGETS mmaps_generator DESTINATION "${CMAKE_INSTALL_PREFIX}") +endif() diff --git a/src/tools/mmaps_generator/Info/readme.txt b/src/tools/mmaps_generator/Info/readme.txt new file mode 100644 index 00000000000..8d7c4f9d2e0 --- /dev/null +++ b/src/tools/mmaps_generator/Info/readme.txt @@ -0,0 +1,66 @@ +Generator command line args + +--offMeshInput [file.*] Path to file containing off mesh connections data. + Format must be: (see offmesh_example.txt) + "map_id tile_x,tile_y (start_x start_y start_z) (end_x end_y end_z) size //optional comments" + Single mesh connection per line. + +--silent Make us script friendly. Do not wait for user input + on error or completion. + +--bigBaseUnit [true|false] Generate tile/map using bigger basic unit. + Use this option only if you have unexpected gaps. + + false: use normal metrics (default) + +--maxAngle [#] Max walkable inclination angle + + float between 45 and 90 degrees (default 60) + +--skipLiquid liquid data for maps + + false: include liquid data (default) + +--skipContinents [true|false] continents are maps 0 (Eastern Kingdoms), + 1 (Kalimdor), 530 (Outlands), 571 (Northrend) + + false: build continents (default) + +--skipJunkMaps [true|false] junk maps include some unused + maps, transport maps, and some other + + true: skip junk maps (default) + +--skipBattlegrounds [true|false] does not include PVP arenas + + false: skip battlegrounds (default) + +--debugOutput [true|false] create debugging files for use with RecastDemo + if you are only creating mmaps for use with MaNGOS, + you don't want debugging files + + false: don't create debugging files (default) + +--tile [#,#] Build the specified tile + seperate number with a comma ',' + must specify a map number (see below) + if this option is not used, all tiles are built + + [#] Build only the map specified by # + this command will build the map regardless of --skip* option settings + if you do not specify a map number, builds all maps that pass the filters specified by --skip* options + + +examples: + +movement_extractor +builds maps using the default settings (see above for defaults) + +movement_extractor --skipContinents true +builds the default maps, except continents + +movement_extractor 0 +builds all tiles of map 0 + +movement_extractor 0 --tile 34,46 +builds only tile 34,46 of map 0 (this is the southern face of blackrock mountain) \ No newline at end of file diff --git a/src/tools/mmaps_generator/IntermediateValues.cpp b/src/tools/mmaps_generator/IntermediateValues.cpp new file mode 100644 index 00000000000..9eefb1e65f0 --- /dev/null +++ b/src/tools/mmaps_generator/IntermediateValues.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#include "IntermediateValues.h" + +namespace MMAP +{ + IntermediateValues::~IntermediateValues() + { + rcFreeCompactHeightfield(compactHeightfield); + rcFreeHeightField(heightfield); + rcFreeContourSet(contours); + rcFreePolyMesh(polyMesh); + rcFreePolyMeshDetail(polyMeshDetail); + } + + void IntermediateValues::writeIV(uint32 mapID, uint32 tileX, uint32 tileY) + { + char fileName[255]; + char tileString[25]; + sprintf(tileString, "[%02u,%02u]: ", tileX, tileY); + + printf("%sWriting debug output... \r", tileString); + + string name("meshes/%03u%02i%02i."); + +#define DEBUG_WRITE(fileExtension,data) \ + do { \ + sprintf(fileName, (name + fileExtension).c_str(), mapID, tileY, tileX); \ + FILE* file = fopen(fileName, "wb"); \ + if (!file) \ + { \ + char message[1024]; \ + sprintf(message, "%sFailed to open %s for writing!\n", tileString, fileName); \ + perror(message); \ + } \ + else \ + debugWrite(file, data); \ + if (file) fclose(file); \ + printf("%sWriting debug output... \r", tileString); \ + } while (false) + + if (heightfield) + DEBUG_WRITE("hf", heightfield); + if (compactHeightfield) + DEBUG_WRITE("chf", compactHeightfield); + if (contours) + DEBUG_WRITE("cs", contours); + if (polyMesh) + DEBUG_WRITE("pmesh", polyMesh); + if (polyMeshDetail) + DEBUG_WRITE("dmesh", polyMeshDetail); + +#undef DEBUG_WRITE + } + + void IntermediateValues::debugWrite(FILE* file, const rcHeightfield* mesh) + { + if (!file || !mesh) + return; + + fwrite(&(mesh->cs), sizeof(float), 1, file); + fwrite(&(mesh->ch), sizeof(float), 1, file); + fwrite(&(mesh->width), sizeof(int), 1, file); + fwrite(&(mesh->height), sizeof(int), 1, file); + fwrite(mesh->bmin, sizeof(float), 3, file); + fwrite(mesh->bmax, sizeof(float), 3, file); + + for (int y = 0; y < mesh->height; ++y) + for (int x = 0; x < mesh->width; ++x) + { + rcSpan* span = mesh->spans[x+y*mesh->width]; + + // first, count the number of spans + int spanCount = 0; + while (span) + { + spanCount++; + span = span->next; + } + + // write the span count + fwrite(&spanCount, sizeof(int), 1, file); + + // write the spans + span = mesh->spans[x+y*mesh->width]; + while (span) + { + fwrite(span, sizeof(rcSpan), 1, file); + span = span->next; + } + } + } + + void IntermediateValues::debugWrite(FILE* file, const rcCompactHeightfield* chf) + { + if (!file | !chf) + return; + + fwrite(&(chf->width), sizeof(chf->width), 1, file); + fwrite(&(chf->height), sizeof(chf->height), 1, file); + fwrite(&(chf->spanCount), sizeof(chf->spanCount), 1, file); + + fwrite(&(chf->walkableHeight), sizeof(chf->walkableHeight), 1, file); + fwrite(&(chf->walkableClimb), sizeof(chf->walkableClimb), 1, file); + + fwrite(&(chf->maxDistance), sizeof(chf->maxDistance), 1, file); + fwrite(&(chf->maxRegions), sizeof(chf->maxRegions), 1, file); + + fwrite(chf->bmin, sizeof(chf->bmin), 1, file); + fwrite(chf->bmax, sizeof(chf->bmax), 1, file); + + fwrite(&(chf->cs), sizeof(chf->cs), 1, file); + fwrite(&(chf->ch), sizeof(chf->ch), 1, file); + + int tmp = 0; + if (chf->cells) tmp |= 1; + if (chf->spans) tmp |= 2; + if (chf->dist) tmp |= 4; + if (chf->areas) tmp |= 8; + + fwrite(&tmp, sizeof(tmp), 1, file); + + if (chf->cells) + fwrite(chf->cells, sizeof(rcCompactCell), chf->width*chf->height, file); + if (chf->spans) + fwrite(chf->spans, sizeof(rcCompactSpan), chf->spanCount, file); + if (chf->dist) + fwrite(chf->dist, sizeof(unsigned short), chf->spanCount, file); + if (chf->areas) + fwrite(chf->areas, sizeof(unsigned char), chf->spanCount, file); + } + + void IntermediateValues::debugWrite(FILE* file, const rcContourSet* cs) + { + if (!file || !cs) + return; + + fwrite(&(cs->cs), sizeof(float), 1, file); + fwrite(&(cs->ch), sizeof(float), 1, file); + fwrite(cs->bmin, sizeof(float), 3, file); + fwrite(cs->bmax, sizeof(float), 3, file); + fwrite(&(cs->nconts), sizeof(int), 1, file); + for (int i = 0; i < cs->nconts; ++i) + { + fwrite(&cs->conts[i].area, sizeof(unsigned char), 1, file); + fwrite(&cs->conts[i].reg, sizeof(unsigned short), 1, file); + fwrite(&cs->conts[i].nverts, sizeof(int), 1, file); + fwrite(cs->conts[i].verts, sizeof(int), cs->conts[i].nverts*4, file); + fwrite(&cs->conts[i].nrverts, sizeof(int), 1, file); + fwrite(cs->conts[i].rverts, sizeof(int), cs->conts[i].nrverts*4, file); + } + } + + void IntermediateValues::debugWrite(FILE* file, const rcPolyMesh* mesh) + { + if (!file || !mesh) + return; + + fwrite(&(mesh->cs), sizeof(float), 1, file); + fwrite(&(mesh->ch), sizeof(float), 1, file); + fwrite(&(mesh->nvp), sizeof(int), 1, file); + fwrite(mesh->bmin, sizeof(float), 3, file); + fwrite(mesh->bmax, sizeof(float), 3, file); + fwrite(&(mesh->nverts), sizeof(int), 1, file); + fwrite(mesh->verts, sizeof(unsigned short), mesh->nverts*3, file); + fwrite(&(mesh->npolys), sizeof(int), 1, file); + fwrite(mesh->polys, sizeof(unsigned short), mesh->npolys*mesh->nvp*2, file); + fwrite(mesh->flags, sizeof(unsigned short), mesh->npolys, file); + fwrite(mesh->areas, sizeof(unsigned char), mesh->npolys, file); + fwrite(mesh->regs, sizeof(unsigned short), mesh->npolys, file); + } + + void IntermediateValues::debugWrite(FILE* file, const rcPolyMeshDetail* mesh) + { + if (!file || !mesh) + return; + + fwrite(&(mesh->nverts), sizeof(int), 1, file); + fwrite(mesh->verts, sizeof(float), mesh->nverts*3, file); + fwrite(&(mesh->ntris), sizeof(int), 1, file); + fwrite(mesh->tris, sizeof(char), mesh->ntris*4, file); + fwrite(&(mesh->nmeshes), sizeof(int), 1, file); + fwrite(mesh->meshes, sizeof(int), mesh->nmeshes*4, file); + } + + void IntermediateValues::generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) + { + char objFileName[255]; + sprintf(objFileName, "meshes/map%03u.obj", mapID); + + FILE* objFile = fopen(objFileName, "wb"); + if (!objFile) + { + char message[1024]; + sprintf(message, "Failed to open %s for writing!\n", objFileName); + perror(message); + return; + } + + G3D::Array allVerts; + G3D::Array allTris; + + allTris.append(meshData.liquidTris); + allVerts.append(meshData.liquidVerts); + TerrainBuilder::copyIndices(meshData.solidTris, allTris, allVerts.size() / 3); + allVerts.append(meshData.solidVerts); + + float* verts = allVerts.getCArray(); + int vertCount = allVerts.size() / 3; + int* tris = allTris.getCArray(); + int triCount = allTris.size() / 3; + + for (int i = 0; i < allVerts.size() / 3; i++) + fprintf(objFile, "v %f %f %f\n", verts[i*3], verts[i*3 + 1], verts[i*3 + 2]); + + for (int i = 0; i < allTris.size() / 3; i++) + fprintf(objFile, "f %i %i %i\n", tris[i*3] + 1, tris[i*3 + 1] + 1, tris[i*3 + 2] + 1); + + fclose(objFile); + + + char tileString[25]; + sprintf(tileString, "[%02u,%02u]: ", tileY, tileX); + printf("%sWriting debug output... \r", tileString); + + sprintf(objFileName, "meshes/%03u.map", mapID); + + objFile = fopen(objFileName, "wb"); + if (!objFile) + { + char message[1024]; + sprintf(message, "Failed to open %s for writing!\n", objFileName); + perror(message); + return; + } + + char b = '\0'; + fwrite(&b, sizeof(char), 1, objFile); + fclose(objFile); + + sprintf(objFileName, "meshes/%03u%02u%02u.mesh", mapID, tileY, tileX); + objFile = fopen(objFileName, "wb"); + if (!objFile) + { + char message[1024]; + sprintf(message, "Failed to open %s for writing!\n", objFileName); + perror(message); + return; + } + + fwrite(&vertCount, sizeof(int), 1, objFile); + fwrite(verts, sizeof(float), vertCount*3, objFile); + fflush(objFile); + + fwrite(&triCount, sizeof(int), 1, objFile); + fwrite(tris, sizeof(int), triCount*3, objFile); + fflush(objFile); + + fclose(objFile); + } +} diff --git a/src/tools/mmaps_generator/IntermediateValues.h b/src/tools/mmaps_generator/IntermediateValues.h new file mode 100644 index 00000000000..a267a0f6412 --- /dev/null +++ b/src/tools/mmaps_generator/IntermediateValues.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#ifndef _INTERMEDIATE_VALUES_H +#define _INTERMEDIATE_VALUES_H + +#include "PathCommon.h" +#include "TerrainBuilder.h" +#include "Recast.h" +#include "DetourNavMesh.h" + +namespace MMAP +{ + // this class gathers all debug info holding and output + struct IntermediateValues + { + rcHeightfield* heightfield; + rcCompactHeightfield* compactHeightfield; + rcContourSet* contours; + rcPolyMesh* polyMesh; + rcPolyMeshDetail* polyMeshDetail; + + IntermediateValues() : compactHeightfield(NULL), heightfield(NULL), + contours(NULL), polyMesh(NULL), polyMeshDetail(NULL) {} + ~IntermediateValues(); + + void writeIV(uint32 mapID, uint32 tileX, uint32 tileY); + + void debugWrite(FILE* file, const rcHeightfield* mesh); + void debugWrite(FILE* file, const rcCompactHeightfield* chf); + void debugWrite(FILE* file, const rcContourSet* cs); + void debugWrite(FILE* file, const rcPolyMesh* mesh); + void debugWrite(FILE* file, const rcPolyMeshDetail* mesh); + + void generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); + }; +} +#endif diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp new file mode 100644 index 00000000000..3ca158f0127 --- /dev/null +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -0,0 +1,894 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#include "PathCommon.h" +#include "MapBuilder.h" + +#include "MapTree.h" +#include "ModelInstance.h" +#include "LoginDatabase.h" + +#include "DetourNavMeshBuilder.h" +#include "DetourCommon.h" + +// These make the linker happy. +LoginDatabaseWorkerPool LoginDatabase; +#include "DisableMgr.h" +namespace DisableMgr +{ + bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags) + { + return 0; + } +} + +using namespace VMAP; + +namespace MMAP +{ + MapBuilder::MapBuilder(float maxWalkableAngle, bool skipLiquid, + bool skipContinents, bool skipJunkMaps, bool skipBattlegrounds, + bool debugOutput, bool bigBaseUnit, const char* offMeshFilePath) : + m_terrainBuilder(NULL), + m_debugOutput (debugOutput), + m_skipContinents (skipContinents), + m_skipJunkMaps (skipJunkMaps), + m_skipBattlegrounds (skipBattlegrounds), + m_maxWalkableAngle (maxWalkableAngle), + m_bigBaseUnit (bigBaseUnit), + m_rcContext (NULL), + m_offMeshFilePath (offMeshFilePath) + { + m_terrainBuilder = new TerrainBuilder(skipLiquid); + + m_rcContext = new rcContext(false); + + discoverTiles(); + } + + /**************************************************************************/ + MapBuilder::~MapBuilder() + { + for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) + { + (*it).second->clear(); + delete (*it).second; + } + + delete m_terrainBuilder; + delete m_rcContext; + } + + /**************************************************************************/ + void MapBuilder::discoverTiles() + { + vector files; + uint32 mapID, tileX, tileY, tileID, count = 0; + char filter[12]; + + printf("Discovering maps... "); + getDirContents(files, "maps"); + for (uint32 i = 0; i < files.size(); ++i) + { + mapID = uint32(atoi(files[i].substr(0,3).c_str())); + if (m_tiles.find(mapID) == m_tiles.end()) + { + m_tiles.insert(pair*>(mapID, new set)); + count++; + } + } + + files.clear(); + getDirContents(files, "vmaps", "*.vmtree"); + for (uint32 i = 0; i < files.size(); ++i) + { + mapID = uint32(atoi(files[i].substr(0,3).c_str())); + m_tiles.insert(pair*>(mapID, new set)); + count++; + } + printf("found %u.\n", count); + + count = 0; + printf("Discovering tiles... "); + for (TileList::iterator itr = m_tiles.begin(); itr != m_tiles.end(); ++itr) + { + set* tiles = (*itr).second; + mapID = (*itr).first; + + sprintf(filter, "%03u*.vmtile", mapID); + files.clear(); + getDirContents(files, "vmaps", filter); + for (uint32 i = 0; i < files.size(); ++i) + { + tileX = uint32(atoi(files[i].substr(7,2).c_str())); + tileY = uint32(atoi(files[i].substr(4,2).c_str())); + tileID = StaticMapTree::packTileID(tileY, tileX); + + tiles->insert(tileID); + count++; + } + + sprintf(filter, "%03u*", mapID); + files.clear(); + getDirContents(files, "maps", filter); + for (uint32 i = 0; i < files.size(); ++i) + { + tileY = uint32(atoi(files[i].substr(3,2).c_str())); + tileX = uint32(atoi(files[i].substr(5,2).c_str())); + tileID = StaticMapTree::packTileID(tileX, tileY); + + if (tiles->insert(tileID).second) + count++; + } + } + printf("found %u.\n\n", count); + } + + /**************************************************************************/ + set* MapBuilder::getTileList(uint32 mapID) + { + TileList::iterator itr = m_tiles.find(mapID); + if (itr != m_tiles.end()) + return (*itr).second; + + set* tiles = new set(); + m_tiles.insert(pair*>(mapID, tiles)); + return tiles; + } + + /**************************************************************************/ + void MapBuilder::buildAllMaps() + { + for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) + { + uint32 mapID = (*it).first; + if (!shouldSkipMap(mapID)) + buildMap(mapID); + } + } + + /**************************************************************************/ + void MapBuilder::getGridBounds(uint32 mapID, uint32 &minX, uint32 &minY, uint32 &maxX, uint32 &maxY) + { + maxX = INT_MAX; + maxY = INT_MAX; + minX = INT_MIN; + minY = INT_MIN; + + float bmin[3], bmax[3], lmin[3], lmax[3]; + MeshData meshData; + + // make sure we process maps which don't have tiles + // initialize the static tree, which loads WDT models + if (!m_terrainBuilder->loadVMap(mapID, 64, 64, meshData)) + return; + + // get the coord bounds of the model data + if (meshData.solidVerts.size() + meshData.liquidVerts.size() == 0) + return; + + // get the coord bounds of the model data + if (meshData.solidVerts.size() && meshData.liquidVerts.size()) + { + rcCalcBounds(meshData.solidVerts.getCArray(), meshData.solidVerts.size() / 3, bmin, bmax); + rcCalcBounds(meshData.liquidVerts.getCArray(), meshData.liquidVerts.size() / 3, lmin, lmax); + rcVmin(bmin, lmin); + rcVmax(bmax, lmax); + } + else if (meshData.solidVerts.size()) + rcCalcBounds(meshData.solidVerts.getCArray(), meshData.solidVerts.size() / 3, bmin, bmax); + else + rcCalcBounds(meshData.liquidVerts.getCArray(), meshData.liquidVerts.size() / 3, lmin, lmax); + + // convert coord bounds to grid bounds + maxX = 32 - bmin[0] / GRID_SIZE; + maxY = 32 - bmin[2] / GRID_SIZE; + minX = 32 - bmax[0] / GRID_SIZE; + minY = 32 - bmax[2] / GRID_SIZE; + } + + /**************************************************************************/ + void MapBuilder::buildSingleTile(uint32 mapID, uint32 tileX, uint32 tileY) + { + dtNavMesh* navMesh = NULL; + buildNavMesh(mapID, navMesh); + if (!navMesh) + { + printf("Failed creating navmesh! \n"); + return; + } + + buildTile(mapID, tileX, tileY, navMesh); + dtFreeNavMesh(navMesh); + } + + /**************************************************************************/ + void MapBuilder::buildMap(uint32 mapID) + { + printf("Building map %03u:\n", mapID); + + set* tiles = getTileList(mapID); + + // make sure we process maps which don't have tiles + if (!tiles->size()) + { + // convert coord bounds to grid bounds + uint32 minX, minY, maxX, maxY; + getGridBounds(mapID, minX, minY, maxX, maxY); + + // add all tiles within bounds to tile list. + for (uint32 i = minX; i <= maxX; ++i) + for (uint32 j = minY; j <= maxY; ++j) + tiles->insert(StaticMapTree::packTileID(i, j)); + } + + if (!tiles->size()) + return; + + // build navMesh + dtNavMesh* navMesh = NULL; + buildNavMesh(mapID, navMesh); + if (!navMesh) + { + printf("Failed creating navmesh! \n"); + return; + } + + // now start building mmtiles for each tile + printf("We have %u tiles. \n", (unsigned int)tiles->size()); + for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) + { + uint32 tileX, tileY; + + // unpack tile coords + StaticMapTree::unpackTileID((*it), tileX, tileY); + + if (shouldSkipTile(mapID, tileX, tileY)) + continue; + + buildTile(mapID, tileX, tileY, navMesh); + } + + dtFreeNavMesh(navMesh); + + printf("Complete! \n\n"); + } + + /**************************************************************************/ + void MapBuilder::buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh) + { + printf("Building map %03u, tile [%02u,%02u]\n", mapID, tileX, tileY); + + MeshData meshData; + + // get heightmap data + m_terrainBuilder->loadMap(mapID, tileX, tileY, meshData); + + // get model data + m_terrainBuilder->loadVMap(mapID, tileY, tileX, meshData); + + // if there is no data, give up now + if (!meshData.solidVerts.size() && !meshData.liquidVerts.size()) + return; + + // remove unused vertices + TerrainBuilder::cleanVertices(meshData.solidVerts, meshData.solidTris); + TerrainBuilder::cleanVertices(meshData.liquidVerts, meshData.liquidTris); + + // gather all mesh data for final data check, and bounds calculation + G3D::Array allVerts; + allVerts.append(meshData.liquidVerts); + allVerts.append(meshData.solidVerts); + + if (!allVerts.size()) + return; + + // get bounds of current tile + float bmin[3], bmax[3]; + getTileBounds(tileX, tileY, allVerts.getCArray(), allVerts.size() / 3, bmin, bmax); + + m_terrainBuilder->loadOffMeshConnections(mapID, tileX, tileY, meshData, m_offMeshFilePath); + + // build navmesh tile + buildMoveMapTile(mapID, tileX, tileY, meshData, bmin, bmax, navMesh); + } + + /**************************************************************************/ + void MapBuilder::buildNavMesh(uint32 mapID, dtNavMesh* &navMesh) + { + set* tiles = getTileList(mapID); + + // old code for non-statically assigned bitmask sizes: + ///*** calculate number of bits needed to store tiles & polys ***/ + //int tileBits = dtIlog2(dtNextPow2(tiles->size())); + //if (tileBits < 1) tileBits = 1; // need at least one bit! + //int polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits; + + int tileBits = STATIC_TILE_BITS; + int polyBits = STATIC_POLY_BITS; + + int maxTiles = tiles->size(); + int maxPolysPerTile = 1 << polyBits; + + /*** calculate bounds of map ***/ + + uint32 tileXMin = 64, tileYMin = 64, tileXMax = 0, tileYMax = 0, tileX, tileY; + for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) + { + StaticMapTree::unpackTileID((*it), tileX, tileY); + + if (tileX > tileXMax) + tileXMax = tileX; + else if (tileX < tileXMin) + tileXMin = tileX; + + if (tileY > tileYMax) + tileYMax = tileY; + else if (tileY < tileYMin) + tileYMin = tileY; + } + + // use Max because '32 - tileX' is negative for values over 32 + float bmin[3], bmax[3]; + getTileBounds(tileXMax, tileYMax, NULL, 0, bmin, bmax); + + /*** now create the navmesh ***/ + + // navmesh creation params + dtNavMeshParams navMeshParams; + memset(&navMeshParams, 0, sizeof(dtNavMeshParams)); + navMeshParams.tileWidth = GRID_SIZE; + navMeshParams.tileHeight = GRID_SIZE; + rcVcopy(navMeshParams.orig, bmin); + navMeshParams.maxTiles = maxTiles; + navMeshParams.maxPolys = maxPolysPerTile; + + navMesh = dtAllocNavMesh(); + printf("Creating navMesh... \r"); + if (!navMesh->init(&navMeshParams)) + { + printf("Failed creating navmesh! \n"); + return; + } + + char fileName[25]; + sprintf(fileName, "mmaps/%03u.mmap", mapID); + + FILE* file = fopen(fileName, "wb"); + if (!file) + { + dtFreeNavMesh(navMesh); + char message[1024]; + sprintf(message, "Failed to open %s for writing!\n", fileName); + perror(message); + return; + } + + // now that we know navMesh params are valid, we can write them to file + fwrite(&navMeshParams, sizeof(dtNavMeshParams), 1, file); + fclose(file); + } + + /**************************************************************************/ + void MapBuilder::buildMoveMapTile(uint32 mapID, uint32 tileX, uint32 tileY, + MeshData &meshData, float bmin[3], float bmax[3], + dtNavMesh* navMesh) + { + // console output + char tileString[10]; + sprintf(tileString, "[%02i,%02i]: ", tileX, tileY); + printf("%s Building movemap tiles... \r", tileString); + + IntermediateValues iv; + + float* tVerts = meshData.solidVerts.getCArray(); + int tVertCount = meshData.solidVerts.size() / 3; + int* tTris = meshData.solidTris.getCArray(); + int tTriCount = meshData.solidTris.size() / 3; + + float* lVerts = meshData.liquidVerts.getCArray(); + int lVertCount = meshData.liquidVerts.size() / 3; + int* lTris = meshData.liquidTris.getCArray(); + int lTriCount = meshData.liquidTris.size() / 3; + uint8* lTriFlags = meshData.liquidType.getCArray(); + + // these are WORLD UNIT based metrics + // this are basic unit dimentions + // value have to divide GRID_SIZE(533.33333f) ( aka: 0.5333, 0.2666, 0.3333, 0.1333, etc ) + const static float BASE_UNIT_DIM = m_bigBaseUnit ? 0.533333f : 0.266666f; + + // All are in UNIT metrics! + const static int VERTEX_PER_MAP = int(GRID_SIZE/BASE_UNIT_DIM + 0.5f); + const static int VERTEX_PER_TILE = m_bigBaseUnit ? 40 : 80; // must divide VERTEX_PER_MAP + const static int TILES_PER_MAP = VERTEX_PER_MAP/VERTEX_PER_TILE; + + rcConfig config; + memset(&config, 0, sizeof(rcConfig)); + + rcVcopy(config.bmin, bmin); + rcVcopy(config.bmax, bmax); + + config.maxVertsPerPoly = DT_VERTS_PER_POLYGON; + config.cs = BASE_UNIT_DIM; + config.ch = BASE_UNIT_DIM; + config.walkableSlopeAngle = m_maxWalkableAngle; + config.tileSize = VERTEX_PER_TILE; + config.walkableRadius = m_bigBaseUnit ? 1 : 2; + config.borderSize = config.walkableRadius + 3; + config.maxEdgeLen = VERTEX_PER_TILE + 1; //anything bigger than tileSize + config.walkableHeight = m_bigBaseUnit ? 3 : 6; + config.walkableClimb = m_bigBaseUnit ? 2 : 4; // keep less than walkableHeight + config.minRegionArea = rcSqr(60); + config.mergeRegionArea = rcSqr(50); + config.maxSimplificationError = 2.0f; // eliminates most jagged edges (tinny polygons) + config.detailSampleDist = config.cs * 64; + config.detailSampleMaxError = config.ch * 2; + + // this sets the dimensions of the heightfield - should maybe happen before border padding + rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); + + // allocate subregions : tiles + Tile* tiles = new Tile[TILES_PER_MAP * TILES_PER_MAP]; + + // Initialize per tile config. + rcConfig tileCfg; + memcpy(&tileCfg, &config, sizeof(rcConfig)); + tileCfg.width = config.tileSize + config.borderSize*2; + tileCfg.height = config.tileSize + config.borderSize*2; + + // build all tiles + for (int y = 0; y < TILES_PER_MAP; ++y) + { + for (int x = 0; x < TILES_PER_MAP; ++x) + { + Tile& tile = tiles[x + y*TILES_PER_MAP]; + + // Calculate the per tile bounding box. + tileCfg.bmin[0] = config.bmin[0] + (x*config.tileSize - config.borderSize)*config.cs; + tileCfg.bmin[2] = config.bmin[2] + (y*config.tileSize - config.borderSize)*config.cs; + tileCfg.bmax[0] = config.bmin[0] + ((x+1)*config.tileSize + config.borderSize)*config.cs; + tileCfg.bmax[2] = config.bmin[2] + ((y+1)*config.tileSize + config.borderSize)*config.cs; + + float tbmin[2], tbmax[2]; + tbmin[0] = tileCfg.bmin[0]; + tbmin[1] = tileCfg.bmin[2]; + tbmax[0] = tileCfg.bmax[0]; + tbmax[1] = tileCfg.bmax[2]; + + // build heightfield + tile.solid = rcAllocHeightfield(); + if (!tile.solid || !rcCreateHeightfield(m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch)) + { + printf("%sFailed building heightfield! \n", tileString); + continue; + } + + // mark all walkable tiles, both liquids and solids + unsigned char* triFlags = new unsigned char[tTriCount]; + memset(triFlags, NAV_GROUND, tTriCount*sizeof(unsigned char)); + rcClearUnwalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags); + rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb); + delete [] triFlags; + + rcFilterLowHangingWalkableObstacles(m_rcContext, config.walkableClimb, *tile.solid); + rcFilterLedgeSpans(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid); + rcFilterWalkableLowHeightSpans(m_rcContext, tileCfg.walkableHeight, *tile.solid); + + rcRasterizeTriangles(m_rcContext, lVerts, lVertCount, lTris, lTriFlags, lTriCount, *tile.solid, config.walkableClimb); + + // compact heightfield spans + tile.chf = rcAllocCompactHeightfield(); + if (!tile.chf || !rcBuildCompactHeightfield(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid, *tile.chf)) + { + printf("%sFailed compacting heightfield! \n", tileString); + continue; + } + + // build polymesh intermediates + if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *tile.chf)) + { + printf("%sFailed eroding area! \n", tileString); + continue; + } + + if (!rcBuildDistanceField(m_rcContext, *tile.chf)) + { + printf("%sFailed building distance field! \n", tileString); + continue; + } + + if (!rcBuildRegions(m_rcContext, *tile.chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea)) + { + printf("%sFailed building regions! \n", tileString); + continue; + } + + tile.cset = rcAllocContourSet(); + if (!tile.cset || !rcBuildContours(m_rcContext, *tile.chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.cset)) + { + printf("%sFailed building contours! \n", tileString); + continue; + } + + // build polymesh + tile.pmesh = rcAllocPolyMesh(); + if (!tile.pmesh || !rcBuildPolyMesh(m_rcContext, *tile.cset, tileCfg.maxVertsPerPoly, *tile.pmesh)) + { + printf("%sFailed building polymesh! \n", tileString); + continue; + } + + tile.dmesh = rcAllocPolyMeshDetail(); + if (!tile.dmesh || !rcBuildPolyMeshDetail(m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg .detailSampleMaxError, *tile.dmesh)) + { + printf("%sFailed building polymesh detail! \n", tileString); + continue; + } + + // free those up + // we may want to keep them in the future for debug + // but right now, we don't have the code to merge them + rcFreeHeightField(tile.solid); + tile.solid = NULL; + rcFreeCompactHeightfield(tile.chf); + tile.chf = NULL; + rcFreeContourSet(tile.cset); + tile.cset = NULL; + } + } + + // merge per tile poly and detail meshes + rcPolyMesh** pmmerge = new rcPolyMesh*[TILES_PER_MAP * TILES_PER_MAP]; + if (!pmmerge) + { + printf("%s alloc pmmerge FIALED! \r", tileString); + return; + } + + rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[TILES_PER_MAP * TILES_PER_MAP]; + if (!dmmerge) + { + printf("%s alloc dmmerge FIALED! \r", tileString); + return; + } + + int nmerge = 0; + for (int y = 0; y < TILES_PER_MAP; ++y) + { + for (int x = 0; x < TILES_PER_MAP; ++x) + { + Tile& tile = tiles[x + y*TILES_PER_MAP]; + if (tile.pmesh) + { + pmmerge[nmerge] = tile.pmesh; + dmmerge[nmerge] = tile.dmesh; + nmerge++; + } + } + } + + iv.polyMesh = rcAllocPolyMesh(); + if (!iv.polyMesh) + { + printf("%s alloc iv.polyMesh FIALED! \r", tileString); + return; + } + rcMergePolyMeshes(m_rcContext, pmmerge, nmerge, *iv.polyMesh); + + iv.polyMeshDetail = rcAllocPolyMeshDetail(); + if (!iv.polyMeshDetail) + { + printf("%s alloc m_dmesh FIALED! \r", tileString); + return; + } + rcMergePolyMeshDetails(m_rcContext, dmmerge, nmerge, *iv.polyMeshDetail); + + // free things up + delete [] pmmerge; + delete [] dmmerge; + + delete [] tiles; + + // remove padding for extraction + for (int i = 0; i < iv.polyMesh->nverts; ++i) + { + unsigned short* v = &iv.polyMesh->verts[i*3]; + v[0] -= (unsigned short)config.borderSize; + v[2] -= (unsigned short)config.borderSize; + } + + // set polygons as walkable + // TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off + for (int i = 0; i < iv.polyMesh->npolys; ++i) + if (iv.polyMesh->areas[i] & RC_WALKABLE_AREA) + iv.polyMesh->flags[i] = iv.polyMesh->areas[i]; + + // setup mesh parameters + dtNavMeshCreateParams params; + memset(¶ms, 0, sizeof(params)); + params.verts = iv.polyMesh->verts; + params.vertCount = iv.polyMesh->nverts; + params.polys = iv.polyMesh->polys; + params.polyAreas = iv.polyMesh->areas; + params.polyFlags = iv.polyMesh->flags; + params.polyCount = iv.polyMesh->npolys; + params.nvp = iv.polyMesh->nvp; + params.detailMeshes = iv.polyMeshDetail->meshes; + params.detailVerts = iv.polyMeshDetail->verts; + params.detailVertsCount = iv.polyMeshDetail->nverts; + params.detailTris = iv.polyMeshDetail->tris; + params.detailTriCount = iv.polyMeshDetail->ntris; + + params.offMeshConVerts = meshData.offMeshConnections.getCArray(); + params.offMeshConCount = meshData.offMeshConnections.size()/6; + params.offMeshConRad = meshData.offMeshConnectionRads.getCArray(); + params.offMeshConDir = meshData.offMeshConnectionDirs.getCArray(); + params.offMeshConAreas = meshData.offMeshConnectionsAreas.getCArray(); + params.offMeshConFlags = meshData.offMeshConnectionsFlags.getCArray(); + + params.walkableHeight = BASE_UNIT_DIM*config.walkableHeight; // agent height + params.walkableRadius = BASE_UNIT_DIM*config.walkableRadius; // agent radius + params.walkableClimb = BASE_UNIT_DIM*config.walkableClimb; // keep less that walkableHeight (aka agent height)! + params.tileX = (((bmin[0] + bmax[0]) / 2) - navMesh->getParams()->orig[0]) / GRID_SIZE; + params.tileY = (((bmin[2] + bmax[2]) / 2) - navMesh->getParams()->orig[2]) / GRID_SIZE; + rcVcopy(params.bmin, bmin); + rcVcopy(params.bmax, bmax); + params.cs = config.cs; + params.ch = config.ch; + params.tileSize = VERTEX_PER_MAP; + + // will hold final navmesh + unsigned char* navData = NULL; + int navDataSize = 0; + + do + { + // these values are checked within dtCreateNavMeshData - handle them here + // so we have a clear error message + if (params.nvp > DT_VERTS_PER_POLYGON) + { + printf("%s Invalid verts-per-polygon value! \n", tileString); + continue; + } + if (params.vertCount >= 0xffff) + { + printf("%s Too many vertices! \n", tileString); + continue; + } + if (!params.vertCount || !params.verts) + { + // occurs mostly when adjacent tiles have models + // loaded but those models don't span into this tile + + // message is an annoyance + //printf("%sNo vertices to build tile! \n", tileString); + continue; + } + if (!params.polyCount || !params.polys || + TILES_PER_MAP*TILES_PER_MAP == params.polyCount) + { + // we have flat tiles with no actual geometry - don't build those, its useless + // keep in mind that we do output those into debug info + // drop tiles with only exact count - some tiles may have geometry while having less tiles + printf("%s No polygons to build on tile! \n", tileString); + continue; + } + if (!params.detailMeshes || !params.detailVerts || !params.detailTris) + { + printf("%s No detail mesh to build tile! \n", tileString); + continue; + } + + printf("%s Building navmesh tile... \r", tileString); + if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) + { + printf("%s Failed building navmesh tile! \n", tileString); + continue; + } + + dtTileRef tileRef = 0; + printf("%s Adding tile to navmesh... \r", tileString); + // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile + // is removed via removeTile() + dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef); + if (!tileRef || dtResult != DT_SUCCESS) + { + printf("%s Failed adding tile to navmesh! \n", tileString); + continue; + } + + // file output + char fileName[255]; + sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX); + FILE* file = fopen(fileName, "wb"); + if (!file) + { + char message[1024]; + sprintf(message, "Failed to open %s for writing!\n", fileName); + perror(message); + navMesh->removeTile(tileRef, NULL, NULL); + continue; + } + + printf("%s Writing to file... \r", tileString); + + // write header + MmapTileHeader header; + header.usesLiquids = m_terrainBuilder->usesLiquids(); + header.size = uint32(navDataSize); + fwrite(&header, sizeof(MmapTileHeader), 1, file); + + // write data + fwrite(navData, sizeof(unsigned char), navDataSize, file); + fclose(file); + + // now that tile is written to disk, we can unload it + navMesh->removeTile(tileRef, NULL, NULL); + } + while (0); + + if (m_debugOutput) + { + // restore padding so that the debug visualization is correct + for (int i = 0; i < iv.polyMesh->nverts; ++i) + { + unsigned short* v = &iv.polyMesh->verts[i*3]; + v[0] += (unsigned short)config.borderSize; + v[2] += (unsigned short)config.borderSize; + } + + iv.generateObjFile(mapID, tileX, tileY, meshData); + iv.writeIV(mapID, tileX, tileY); + } + } + + /**************************************************************************/ + void MapBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax) + { + // this is for elevation + if (verts && vertCount) + rcCalcBounds(verts, vertCount, bmin, bmax); + else + { + bmin[1] = FLT_MIN; + bmax[1] = FLT_MAX; + } + + // this is for width and depth + bmax[0] = (32 - int(tileX)) * GRID_SIZE; + bmax[2] = (32 - int(tileY)) * GRID_SIZE; + bmin[0] = bmax[0] - GRID_SIZE; + bmin[2] = bmax[2] - GRID_SIZE; + } + + /**************************************************************************/ + bool MapBuilder::shouldSkipMap(uint32 mapID) + { + if (m_skipContinents) + switch (mapID) + { + case 0: + case 1: + case 530: + case 571: + return true; + default: + break; + } + + if (m_skipJunkMaps) + switch (mapID) + { + case 13: // test.wdt + case 25: // ScottTest.wdt + case 29: // Test.wdt + case 42: // Colin.wdt + case 169: // EmeraldDream.wdt (unused, and very large) + case 451: // development.wdt + case 573: // ExteriorTest.wdt + case 597: // CraigTest.wdt + case 605: // development_nonweighted.wdt + case 606: // QA_DVD.wdt + return true; + default: + if (isTransportMap(mapID)) + return true; + break; + } + + if (m_skipBattlegrounds) + switch (mapID) + { + case 30: // AV + case 37: // ? + case 489: // WSG + case 529: // AB + case 566: // EotS + case 607: // SotA + case 628: // IoC + return true; + default: + break; + } + + return false; + } + + /**************************************************************************/ + bool MapBuilder::isTransportMap(uint32 mapID) + { + switch (mapID) + { + // transport maps + case 582: + case 584: + case 586: + case 587: + case 588: + case 589: + case 590: + case 591: + case 592: + case 593: + case 594: + case 596: + case 610: + case 612: + case 613: + case 614: + case 620: + case 621: + case 622: + case 623: + case 641: + case 642: + case 647: + case 672: + case 673: + case 712: + case 713: + case 718: + return true; + default: + return false; + } + } + + /**************************************************************************/ + bool MapBuilder::shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY) + { + char fileName[255]; + sprintf(fileName, "mmaps/%03u%02i%02i.mmtile", mapID, tileY, tileX); + FILE* file = fopen(fileName, "rb"); + if (!file) + return false; + + MmapTileHeader header; + fread(&header, sizeof(MmapTileHeader), 1, file); + fclose(file); + + if (header.mmapMagic != MMAP_MAGIC || header.dtVersion != DT_NAVMESH_VERSION) + return false; + + if (header.mmapVersion != MMAP_VERSION) + return false; + + return true; + } + +} diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h new file mode 100644 index 00000000000..d0f33ce9a79 --- /dev/null +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#ifndef _MAP_BUILDER_H +#define _MAP_BUILDER_H + +#include +#include +#include + +#include "TerrainBuilder.h" +#include "IntermediateValues.h" + +#include "IVMapManager.h" +#include "WorldModel.h" + +#include "Recast.h" +#include "DetourNavMesh.h" + +using namespace std; +using namespace VMAP; + +// G3D namespace typedefs conflicts with ACE typedefs + +namespace MMAP +{ + typedef map*> TileList; + struct Tile + { + Tile() : chf(NULL), solid(NULL), cset(NULL), pmesh(NULL), dmesh(NULL) {} + ~Tile() + { + rcFreeCompactHeightfield(chf); + rcFreeContourSet(cset); + rcFreeHeightField(solid); + rcFreePolyMesh(pmesh); + rcFreePolyMeshDetail(dmesh); + } + rcCompactHeightfield* chf; + rcHeightfield* solid; + rcContourSet* cset; + rcPolyMesh* pmesh; + rcPolyMeshDetail* dmesh; + }; + + class MapBuilder + { + public: + MapBuilder(float maxWalkableAngle = 60.f, + bool skipLiquid = false, + bool skipContinents = false, + bool skipJunkMaps = true, + bool skipBattlegrounds = false, + bool debugOutput = false, + bool bigBaseUnit = false, + const char* offMeshFilePath = NULL); + + ~MapBuilder(); + + // builds all mmap tiles for the specified map id (ignores skip settings) + void buildMap(uint32 mapID); + + // builds an mmap tile for the specified map and its mesh + void buildSingleTile(uint32 mapID, uint32 tileX, uint32 tileY); + + // builds list of maps, then builds all of mmap tiles (based on the skip settings) + void buildAllMaps(); + + private: + // detect maps and tiles + void discoverTiles(); + set* getTileList(uint32 mapID); + + void buildNavMesh(uint32 mapID, dtNavMesh* &navMesh); + + void buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh); + + // move map building + void buildMoveMapTile(uint32 mapID, + uint32 tileX, + uint32 tileY, + MeshData &meshData, + float bmin[3], + float bmax[3], + dtNavMesh* navMesh); + + void getTileBounds(uint32 tileX, uint32 tileY, + float* verts, int vertCount, + float* bmin, float* bmax); + void getGridBounds(uint32 mapID, uint32 &minX, uint32 &minY, uint32 &maxX, uint32 &maxY); + + bool shouldSkipMap(uint32 mapID); + bool isTransportMap(uint32 mapID); + bool shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY); + + TerrainBuilder* m_terrainBuilder; + TileList m_tiles; + + bool m_debugOutput; + + const char* m_offMeshFilePath; + bool m_skipContinents; + bool m_skipJunkMaps; + bool m_skipBattlegrounds; + + float m_maxWalkableAngle; + bool m_bigBaseUnit; + + // build performance - not really used for now + rcContext* m_rcContext; + }; +} + +#endif diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h new file mode 100644 index 00000000000..fd02ec02d50 --- /dev/null +++ b/src/tools/mmaps_generator/PathCommon.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#ifndef _MMAP_COMMON_H +#define _MMAP_COMMON_H + +#include +#include + +#include "Define.h" + +#ifndef _WIN32 + #include + #include +#endif + +#ifdef __linux__ + #include +#endif + +using namespace std; + +namespace MMAP +{ + inline bool matchWildcardFilter(const char* filter, const char* str) + { + if (!filter || !str) + return false; + + // end on null character + while (*filter && *str) + { + if (*filter == '*') + { + if (*++filter == '\0') // wildcard at end of filter means all remaing chars match + return true; + + while (true) + { + if (*filter == *str) + break; + if (*str == '\0') + return false; // reached end of string without matching next filter character + str++; + } + } + else if (*filter != *str) + return false; // mismatch + + filter++; + str++; + } + + return ((*filter == '\0' || (*filter == '*' && *++filter == '\0')) && *str == '\0'); + } + + enum ListFilesResult + { + LISTFILE_DIRECTORY_NOT_FOUND = 0, + LISTFILE_OK = 1 + }; + + inline ListFilesResult getDirContents(vector &fileList, string dirpath = ".", string filter = "*", bool includeSubDirs = false) + { + #ifdef WIN32 + HANDLE hFind; + WIN32_FIND_DATA findFileInfo; + string directory; + + directory = dirpath + "/" + filter; + + hFind = FindFirstFile(directory.c_str(), &findFileInfo); + + if (hFind == INVALID_HANDLE_VALUE) + return LISTFILE_DIRECTORY_NOT_FOUND; + do + { + if (includeSubDirs || (findFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) + fileList.push_back(string(findFileInfo.cFileName)); + } + while (FindNextFile(hFind, &findFileInfo)); + + FindClose(hFind); + + #else + const char *p = dirpath.c_str(); + DIR * dirp = opendir(p); + struct dirent * dp; + dirp = opendir(p); + + while (dirp) + { + errno = 0; + if ((dp = readdir(dirp)) != NULL) + { + if (matchWildcardFilter(filter.c_str(), dp->d_name)) + fileList.push_back(string(dp->d_name)); + } + else + break; + } + + if (dirp) + closedir(dirp); + else + return LISTFILE_DIRECTORY_NOT_FOUND; + #endif + + return LISTFILE_OK; + } +} + +#endif diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp new file mode 100644 index 00000000000..2eb2c6545c4 --- /dev/null +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "PathCommon.h" +#include "MapBuilder.h" + +using namespace MMAP; + +bool checkDirectories(bool debugOutput) +{ + vector dirFiles; + + if (getDirContents(dirFiles, "maps") == LISTFILE_DIRECTORY_NOT_FOUND || !dirFiles.size()) + { + printf("'maps' directory is empty or does not exist\n"); + return false; + } + + dirFiles.clear(); + if (getDirContents(dirFiles, "vmaps", "*.vmtree") == LISTFILE_DIRECTORY_NOT_FOUND || !dirFiles.size()) + { + printf("'vmaps' directory is empty or does not exist\n"); + return false; + } + + dirFiles.clear(); + if (getDirContents(dirFiles, "mmaps") == LISTFILE_DIRECTORY_NOT_FOUND) + { + printf("'mmaps' directory does not exist\n"); + return false; + } + + dirFiles.clear(); + if (debugOutput) + { + if (getDirContents(dirFiles, "meshes") == LISTFILE_DIRECTORY_NOT_FOUND) + { + printf("'meshes' directory does not exist (no place to put debugOutput files)\n"); + return false; + } + } + + return true; +} + +bool handleArgs(int argc, char** argv, + int &mapnum, + int &tileX, + int &tileY, + float &maxAngle, + bool &skipLiquid, + bool &skipContinents, + bool &skipJunkMaps, + bool &skipBattlegrounds, + bool &debugOutput, + bool &silent, + bool &bigBaseUnit, + char* &offMeshInputPath) +{ + char* param = NULL; + for (int i = 1; i < argc; ++i) + { + if (strcmp(argv[i], "--maxAngle") == 0) + { + param = argv[++i]; + if (!param) + return false; + + float maxangle = atof(param); + if (maxangle <= 90.f && maxangle >= 45.f) + maxAngle = maxangle; + else + printf("invalid option for '--maxAngle', using default\n"); + } + else if (strcmp(argv[i], "--tile") == 0) + { + param = argv[++i]; + if (!param) + return false; + + char* stileX = strtok(param, ","); + char* stileY = strtok(NULL, ","); + int tilex = atoi(stileX); + int tiley = atoi(stileY); + + if ((tilex > 0 && tilex < 64) || (tilex == 0 && strcmp(stileX, "0") == 0)) + tileX = tilex; + if ((tiley > 0 && tiley < 64) || (tiley == 0 && strcmp(stileY, "0") == 0)) + tileY = tiley; + + if (tileX < 0 || tileY < 0) + { + printf("invalid tile coords.\n"); + return false; + } + } + else if (strcmp(argv[i], "--skipLiquid") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + skipLiquid = true; + else if (strcmp(param, "false") == 0) + skipLiquid = false; + else + printf("invalid option for '--skipLiquid', using default\n"); + } + else if (strcmp(argv[i], "--skipContinents") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + skipContinents = true; + else if (strcmp(param, "false") == 0) + skipContinents = false; + else + printf("invalid option for '--skipContinents', using default\n"); + } + else if (strcmp(argv[i], "--skipJunkMaps") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + skipJunkMaps = true; + else if (strcmp(param, "false") == 0) + skipJunkMaps = false; + else + printf("invalid option for '--skipJunkMaps', using default\n"); + } + else if (strcmp(argv[i], "--skipBattlegrounds") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + skipBattlegrounds = true; + else if (strcmp(param, "false") == 0) + skipBattlegrounds = false; + else + printf("invalid option for '--skipBattlegrounds', using default\n"); + } + else if (strcmp(argv[i], "--debugOutput") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + debugOutput = true; + else if (strcmp(param, "false") == 0) + debugOutput = false; + else + printf("invalid option for '--debugOutput', using default true\n"); + } + else if (strcmp(argv[i], "--silent") == 0) + { + silent = true; + } + else if (strcmp(argv[i], "--bigBaseUnit") == 0) + { + param = argv[++i]; + if (!param) + return false; + + if (strcmp(param, "true") == 0) + bigBaseUnit = true; + else if (strcmp(param, "false") == 0) + bigBaseUnit = false; + else + printf("invalid option for '--bigBaseUnit', using default false\n"); + } + else if (strcmp(argv[i], "--offMeshInput") == 0) + { + param = argv[++i]; + if (!param) + return false; + + offMeshInputPath = param; + } + else + { + int map = atoi(argv[i]); + if (map > 0 || (map == 0 && (strcmp(argv[i], "0") == 0))) + mapnum = map; + else + { + printf("invalid map id\n"); + return false; + } + } + } + + return true; +} + +int finish(const char* message, int returnValue) +{ + printf("%s", message); + getchar(); + return returnValue; +} + +int main(int argc, char** argv) +{ + int mapnum = -1; + float maxAngle = 60.0f; + int tileX = -1, tileY = -1; + bool skipLiquid = false, + skipContinents = false, + skipJunkMaps = true, + skipBattlegrounds = false, + debugOutput = false, + silent = false, + bigBaseUnit = false; + char* offMeshInputPath = NULL; + + bool validParam = handleArgs(argc, argv, mapnum, + tileX, tileY, maxAngle, + skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, + debugOutput, silent, bigBaseUnit, offMeshInputPath); + + if (!validParam) + return silent ? -1 : finish("You have specified invalid parameters", -1); + + if (mapnum == -1 && debugOutput) + { + if (silent) + return -2; + + printf("You have specifed debug output, but didn't specify a map to generate.\n"); + printf("This will generate debug output for ALL maps.\n"); + printf("Are you sure you want to continue? (y/n) "); + if (getchar() != 'y') + return 0; + } + + if (!checkDirectories(debugOutput)) + return silent ? -3 : finish("Press any key to close...", -3); + + MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps, + skipBattlegrounds, debugOutput, bigBaseUnit, offMeshInputPath); + + if (tileX > -1 && tileY > -1 && mapnum >= 0) + builder.buildSingleTile(mapnum, tileX, tileY); + else if (mapnum >= 0) + builder.buildMap(uint32(mapnum)); + else + builder.buildAllMaps(); + + return silent ? 1 : finish("Movemap build is complete!", 1); +} diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp new file mode 100644 index 00000000000..c696f6017a5 --- /dev/null +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -0,0 +1,854 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#include "TerrainBuilder.h" + +#include "PathCommon.h" +#include "MapBuilder.h" + +#include "VMapManager2.h" +#include "MapTree.h" +#include "ModelInstance.h" + +namespace MMAP +{ + TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ } + TerrainBuilder::~TerrainBuilder() { } + + /**************************************************************************/ + void TerrainBuilder::getLoopVars(Spot portion, int &loopStart, int &loopEnd, int &loopInc) + { + switch (portion) + { + case ENTIRE: + loopStart = 0; + loopEnd = V8_SIZE_SQ; + loopInc = 1; + break; + case TOP: + loopStart = 0; + loopEnd = V8_SIZE; + loopInc = 1; + break; + case LEFT: + loopStart = 0; + loopEnd = V8_SIZE_SQ - V8_SIZE + 1; + loopInc = V8_SIZE; + break; + case RIGHT: + loopStart = V8_SIZE - 1; + loopEnd = V8_SIZE_SQ; + loopInc = V8_SIZE; + break; + case BOTTOM: + loopStart = V8_SIZE_SQ - V8_SIZE; + loopEnd = V8_SIZE_SQ; + loopInc = 1; + break; + } + } + + /**************************************************************************/ + void TerrainBuilder::loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) + { + if (loadMap(mapID, tileX, tileY, meshData, ENTIRE)) + { + loadMap(mapID, tileX+1, tileY, meshData, LEFT); + loadMap(mapID, tileX-1, tileY, meshData, RIGHT); + loadMap(mapID, tileX, tileY+1, meshData, TOP); + loadMap(mapID, tileX, tileY-1, meshData, BOTTOM); + } + } + + /**************************************************************************/ + bool TerrainBuilder::loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, Spot portion) + { + char mapFileName[255]; + sprintf(mapFileName, "maps/%03u%02u%02u.map", mapID, tileY, tileX); + + FILE* mapFile = fopen(mapFileName, "rb"); + if (!mapFile) + return false; + + map_fileheader fheader; + fread(&fheader, sizeof(map_fileheader), 1, mapFile); + + if (fheader.versionMagic != *((uint32 const*)(MAP_VERSION_MAGIC))) + { + fclose(mapFile); + printf("%s is the wrong version, please extract new .map files\n", mapFileName); + return false; + } + + map_heightHeader hheader; + fseek(mapFile, fheader.heightMapOffset, SEEK_SET); + fread(&hheader, sizeof(map_heightHeader), 1, mapFile); + + bool haveTerrain = !(hheader.flags & MAP_HEIGHT_NO_HEIGHT); + bool haveLiquid = fheader.liquidMapOffset && !m_skipLiquid; + + // no data in this map file + if (!haveTerrain && !haveLiquid) + { + fclose(mapFile); + return false; + } + + // data used later + uint16 holes[16][16]; + memset(holes, 0, sizeof(holes)); + uint8 liquid_type[16][16]; + memset(liquid_type, 0, sizeof(liquid_type)); + G3D::Array ltriangles; + G3D::Array ttriangles; + + // terrain data + if (haveTerrain) + { + int i; + float heightMultiplier; + float V9[V9_SIZE_SQ], V8[V8_SIZE_SQ]; + + if (hheader.flags & MAP_HEIGHT_AS_INT8) + { + uint8 v9[V9_SIZE_SQ]; + uint8 v8[V8_SIZE_SQ]; + fread(v9, sizeof(uint8), V9_SIZE_SQ, mapFile); + fread(v8, sizeof(uint8), V8_SIZE_SQ, mapFile); + heightMultiplier = (hheader.gridMaxHeight - hheader.gridHeight) / 255; + + for (i = 0; i < V9_SIZE_SQ; ++i) + V9[i] = (float)v9[i]*heightMultiplier + hheader.gridHeight; + + for (i = 0; i < V8_SIZE_SQ; ++i) + V8[i] = (float)v8[i]*heightMultiplier + hheader.gridHeight; + } + else if (hheader.flags & MAP_HEIGHT_AS_INT16) + { + uint16 v9[V9_SIZE_SQ]; + uint16 v8[V8_SIZE_SQ]; + fread(v9, sizeof(uint16), V9_SIZE_SQ, mapFile); + fread(v8, sizeof(uint16), V8_SIZE_SQ, mapFile); + heightMultiplier = (hheader.gridMaxHeight - hheader.gridHeight) / 65535; + + for (i = 0; i < V9_SIZE_SQ; ++i) + V9[i] = (float)v9[i]*heightMultiplier + hheader.gridHeight; + + for (i = 0; i < V8_SIZE_SQ; ++i) + V8[i] = (float)v8[i]*heightMultiplier + hheader.gridHeight; + } + else + { + fread (V9, sizeof(float), V9_SIZE_SQ, mapFile); + fread(V8, sizeof(float), V8_SIZE_SQ, mapFile); + } + + // hole data + memset(holes, 0, fheader.holesSize); + fseek(mapFile, fheader.holesOffset, SEEK_SET); + fread(holes, fheader.holesSize, 1, mapFile); + + int count = meshData.solidVerts.size() / 3; + float xoffset = (float(tileX)-32)*GRID_SIZE; + float yoffset = (float(tileY)-32)*GRID_SIZE; + + float coord[3]; + + for (i = 0; i < V9_SIZE_SQ; ++i) + { + getHeightCoord(i, GRID_V9, xoffset, yoffset, coord, V9); + meshData.solidVerts.append(coord[0]); + meshData.solidVerts.append(coord[2]); + meshData.solidVerts.append(coord[1]); + } + + for (i = 0; i < V8_SIZE_SQ; ++i) + { + getHeightCoord(i, GRID_V8, xoffset, yoffset, coord, V8); + meshData.solidVerts.append(coord[0]); + meshData.solidVerts.append(coord[2]); + meshData.solidVerts.append(coord[1]); + } + + int j, indices[3], loopStart, loopEnd, loopInc; + getLoopVars(portion, loopStart, loopEnd, loopInc); + for (i = loopStart; i < loopEnd; i+=loopInc) + for (j = TOP; j <= BOTTOM; j+=1) + { + getHeightTriangle(i, Spot(j), indices); + ttriangles.append(indices[2] + count); + ttriangles.append(indices[1] + count); + ttriangles.append(indices[0] + count); + } + } + + // liquid data + if (haveLiquid) + { + map_liquidHeader lheader; + fseek(mapFile, fheader.liquidMapOffset, SEEK_SET); + fread(&lheader, sizeof(map_liquidHeader), 1, mapFile); + + float* liquid_map = NULL; + + if (!(lheader.flags & MAP_LIQUID_NO_TYPE)) + fread(liquid_type, sizeof(liquid_type), 1, mapFile); + + if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT)) + { + liquid_map = new float [lheader.width*lheader.height]; + fread(liquid_map, sizeof(float), lheader.width*lheader.height, mapFile); + } + + if (liquid_type && liquid_map) + { + int count = meshData.liquidVerts.size() / 3; + float xoffset = (float(tileX)-32)*GRID_SIZE; + float yoffset = (float(tileY)-32)*GRID_SIZE; + + float coord[3]; + int row, col; + + // generate coordinates + if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT)) + { + int j = 0; + for (int i = 0; i < V9_SIZE_SQ; ++i) + { + row = i / V9_SIZE; + col = i % V9_SIZE; + + if (row < lheader.offsetY || row >= lheader.offsetY + lheader.height || + col < lheader.offsetX || col >= lheader.offsetX + lheader.width) + { + // dummy vert using invalid height + meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, INVALID_MAP_LIQ_HEIGHT, (yoffset+row*GRID_PART_SIZE)*-1); + continue; + } + + getLiquidCoord(i, j, xoffset, yoffset, coord, liquid_map); + meshData.liquidVerts.append(coord[0]); + meshData.liquidVerts.append(coord[2]); + meshData.liquidVerts.append(coord[1]); + j++; + } + } + else + { + for (int i = 0; i < V9_SIZE_SQ; ++i) + { + row = i / V9_SIZE; + col = i % V9_SIZE; + meshData.liquidVerts.append((xoffset+col*GRID_PART_SIZE)*-1, lheader.liquidLevel, (yoffset+row*GRID_PART_SIZE)*-1); + } + } + + delete [] liquid_map; + + int indices[3], loopStart, loopEnd, loopInc, triInc; + getLoopVars(portion, loopStart, loopEnd, loopInc); + triInc = BOTTOM-TOP; + + // generate triangles + for (int i = loopStart; i < loopEnd; i+=loopInc) + for (int j = TOP; j <= BOTTOM; j+= triInc) + { + getHeightTriangle(i, Spot(j), indices, true); + ltriangles.append(indices[2] + count); + ltriangles.append(indices[1] + count); + ltriangles.append(indices[0] + count); + } + } + } + + fclose(mapFile); + + // now that we have gathered the data, we can figure out which parts to keep: + // liquid above ground, ground above liquid + int loopStart, loopEnd, loopInc, tTriCount = 4; + bool useTerrain, useLiquid; + + float* lverts = meshData.liquidVerts.getCArray(); + int* ltris = ltriangles.getCArray(); + + float* tverts = meshData.solidVerts.getCArray(); + int* ttris = ttriangles.getCArray(); + + if (ltriangles.size() + ttriangles.size() == 0) + return false; + + // make a copy of liquid vertices + // used to pad right-bottom frame due to lost vertex data at extraction + float* lverts_copy = NULL; + if (meshData.liquidVerts.size()) + { + lverts_copy = new float[meshData.liquidVerts.size()]; + memcpy(lverts_copy, lverts, sizeof(float)*meshData.liquidVerts.size()); + } + + getLoopVars(portion, loopStart, loopEnd, loopInc); + for (int i = loopStart; i < loopEnd; i+=loopInc) + { + for (int j = 0; j < 2; ++j) + { + // default is true, will change to false if needed + useTerrain = true; + useLiquid = true; + uint8 liquidType = MAP_LIQUID_TYPE_NO_WATER; + + // if there is no liquid, don't use liquid + if (!liquid_type || !meshData.liquidVerts.size() || !ltriangles.size()) + useLiquid = false; + else + { + liquidType = getLiquidType(i, liquid_type); + switch (liquidType) + { + default: + useLiquid = false; + break; + case MAP_LIQUID_TYPE_WATER: + case MAP_LIQUID_TYPE_OCEAN: + // merge different types of water + liquidType = NAV_WATER; + break; + case MAP_LIQUID_TYPE_MAGMA: + liquidType = NAV_MAGMA; + break; + case MAP_LIQUID_TYPE_SLIME: + liquidType = NAV_SLIME; + break; + case MAP_LIQUID_TYPE_DARK_WATER: + // players should not be here, so logically neither should creatures + useTerrain = false; + useLiquid = false; + break; + } + } + + // if there is no terrain, don't use terrain + if (!ttriangles.size()) + useTerrain = false; + + // while extracting ADT data we are losing right-bottom vertices + // this code adds fair approximation of lost data + if (useLiquid) + { + float quadHeight = 0; + uint32 validCount = 0; + for(uint32 idx = 0; idx < 3; idx++) + { + float h = lverts_copy[ltris[idx]*3 + 1]; + if (h != INVALID_MAP_LIQ_HEIGHT && h < INVALID_MAP_LIQ_HEIGHT_MAX) + { + quadHeight += h; + validCount++; + } + } + + // update vertex height data + if (validCount > 0 && validCount < 3) + { + quadHeight /= validCount; + for(uint32 idx = 0; idx < 3; idx++) + { + float h = lverts[ltris[idx]*3 + 1]; + if (h == INVALID_MAP_LIQ_HEIGHT || h > INVALID_MAP_LIQ_HEIGHT_MAX) + lverts[ltris[idx]*3 + 1] = quadHeight; + } + } + + // no valid vertexes - don't use this poly at all + if (validCount == 0) + useLiquid = false; + } + + // if there is a hole here, don't use the terrain + if (useTerrain) + useTerrain = !isHole(i, holes); + + // we use only one terrain kind per quad - pick higher one + if (useTerrain && useLiquid) + { + float minLLevel = INVALID_MAP_LIQ_HEIGHT_MAX; + float maxLLevel = INVALID_MAP_LIQ_HEIGHT; + for(uint32 x = 0; x < 3; x++) + { + float h = lverts[ltris[x]*3 + 1]; + if (minLLevel > h) + minLLevel = h; + + if (maxLLevel < h) + maxLLevel = h; + } + + float maxTLevel = INVALID_MAP_LIQ_HEIGHT; + float minTLevel = INVALID_MAP_LIQ_HEIGHT_MAX; + for(uint32 x = 0; x < 6; x++) + { + float h = tverts[ttris[x]*3 + 1]; + if (maxTLevel < h) + maxTLevel = h; + + if (minTLevel > h) + minTLevel = h; + } + + // terrain under the liquid? + if (minLLevel > maxTLevel) + useTerrain = false; + + //liquid under the terrain? + if (minTLevel > maxLLevel) + useLiquid = false; + } + + // store the result + if (useLiquid) + { + meshData.liquidType.append(liquidType); + for (int k = 0; k < 3; ++k) + meshData.liquidTris.append(ltris[k]); + } + + if (useTerrain) + for (int k = 0; k < 3*tTriCount/2; ++k) + meshData.solidTris.append(ttris[k]); + + // advance to next set of triangles + ltris += 3; + ttris += 3*tTriCount/2; + } + } + + if (lverts_copy) + delete [] lverts_copy; + + return meshData.solidTris.size() || meshData.liquidTris.size(); + } + + /**************************************************************************/ + void TerrainBuilder::getHeightCoord(int index, Grid grid, float xOffset, float yOffset, float* coord, float* v) + { + // wow coords: x, y, height + // coord is mirroed about the horizontal axes + switch (grid) + { + case GRID_V9: + coord[0] = (xOffset + index%(V9_SIZE)*GRID_PART_SIZE) * -1.f; + coord[1] = (yOffset + (int)(index/(V9_SIZE))*GRID_PART_SIZE) * -1.f; + coord[2] = v[index]; + break; + case GRID_V8: + coord[0] = (xOffset + index%(V8_SIZE)*GRID_PART_SIZE + GRID_PART_SIZE/2.f) * -1.f; + coord[1] = (yOffset + (int)(index/(V8_SIZE))*GRID_PART_SIZE + GRID_PART_SIZE/2.f) * -1.f; + coord[2] = v[index]; + break; + } + } + + /**************************************************************************/ + void TerrainBuilder::getHeightTriangle(int square, Spot triangle, int* indices, bool liquid/* = false*/) + { + int rowOffset = square/V8_SIZE; + if (!liquid) + switch (triangle) + { + case TOP: + indices[0] = square+rowOffset; // 0-----1 .... 128 + indices[1] = square+1+rowOffset; // |\ T /| + indices[2] = (V9_SIZE_SQ)+square; // | \ / | + break; // |L 0 R| .. 127 + case LEFT: // | / \ | + indices[0] = square+rowOffset; // |/ B \| + indices[1] = (V9_SIZE_SQ)+square; // 129---130 ... 386 + indices[2] = square+V9_SIZE+rowOffset; // |\ /| + break; // | \ / | + case RIGHT: // | 128 | .. 255 + indices[0] = square+1+rowOffset; // | / \ | + indices[1] = square+V9_SIZE+1+rowOffset; // |/ \| + indices[2] = (V9_SIZE_SQ)+square; // 258---259 ... 515 + break; + case BOTTOM: + indices[0] = (V9_SIZE_SQ)+square; + indices[1] = square+V9_SIZE+1+rowOffset; + indices[2] = square+V9_SIZE+rowOffset; + break; + default: break; + } + else + switch (triangle) + { // 0-----1 .... 128 + case TOP: // |\ | + indices[0] = square+rowOffset; // | \ T | + indices[1] = square+1+rowOffset; // | \ | + indices[2] = square+V9_SIZE+1+rowOffset; // | B \ | + break; // | \| + case BOTTOM: // 129---130 ... 386 + indices[0] = square+rowOffset; // |\ | + indices[1] = square+V9_SIZE+1+rowOffset; // | \ | + indices[2] = square+V9_SIZE+rowOffset; // | \ | + break; // | \ | + default: break; // | \| + } // 258---259 ... 515 + + } + + /**************************************************************************/ + void TerrainBuilder::getLiquidCoord(int index, int index2, float xOffset, float yOffset, float* coord, float* v) + { + // wow coords: x, y, height + // coord is mirroed about the horizontal axes + coord[0] = (xOffset + index%(V9_SIZE)*GRID_PART_SIZE) * -1.f; + coord[1] = (yOffset + (int)(index/(V9_SIZE))*GRID_PART_SIZE) * -1.f; + coord[2] = v[index2]; + } + + static uint16 holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; + static uint16 holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; + + /**************************************************************************/ + bool TerrainBuilder::isHole(int square, const uint16 holes[16][16]) + { + int row = square / 128; + int col = square % 128; + int cellRow = row / 8; // 8 squares per cell + int cellCol = col / 8; + int holeRow = row % 8 / 2; + int holeCol = (square - (row * 128 + cellCol * 8)) / 2; + + uint16 hole = holes[cellRow][cellCol]; + + return (hole & holetab_h[holeCol] & holetab_v[holeRow]) != 0; + } + + /**************************************************************************/ + uint8 TerrainBuilder::getLiquidType(int square, const uint8 liquid_type[16][16]) + { + int row = square / 128; + int col = square % 128; + int cellRow = row / 8; // 8 squares per cell + int cellCol = col / 8; + + return liquid_type[cellRow][cellCol]; + } + + /**************************************************************************/ + bool TerrainBuilder::loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) + { + IVMapManager* vmapManager = new VMapManager2(); + int result = vmapManager->loadMap("vmaps", mapID, tileX, tileY); + bool retval = false; + + do + { + if (result == VMAP_LOAD_RESULT_ERROR) + break; + + InstanceTreeMap instanceTrees; + ((VMapManager2*)vmapManager)->getInstanceMapTree(instanceTrees); + + if (!instanceTrees[mapID]) + break; + + ModelInstance* models = NULL; + uint32 count = 0; + instanceTrees[mapID]->getModelInstances(models, count); + + if (!models) + break; + + for (uint32 i = 0; i < count; ++i) + { + ModelInstance instance = models[i]; + + // model instances exist in tree even though there are instances of that model in this tile + WorldModel* worldModel = instance.getWorldModel(); + if (!worldModel) + continue; + + // now we have a model to add to the meshdata + retval = true; + + vector groupModels; + worldModel->getGroupModels(groupModels); + + // all M2s need to have triangle indices reversed + bool isM2 = instance.name.find(".m2") != instance.name.npos || instance.name.find(".M2") != instance.name.npos; + + // transform data + float scale = instance.iScale; + G3D::Matrix3 rotation = G3D::Matrix3::fromEulerAnglesXYZ(G3D::pi()*instance.iRot.z/-180.f, G3D::pi()*instance.iRot.x/-180.f, G3D::pi()*instance.iRot.y/-180.f); + Vector3 position = instance.iPos; + position.x -= 32*GRID_SIZE; + position.y -= 32*GRID_SIZE; + + for (vector::iterator it = groupModels.begin(); it != groupModels.end(); ++it) + { + vector tempVertices; + vector transformedVertices; + vector tempTriangles; + WmoLiquid* liquid = NULL; + + (*it).getMeshData(tempVertices, tempTriangles, liquid); + + // first handle collision mesh + transform(tempVertices, transformedVertices, scale, rotation, position); + + int offset = meshData.solidVerts.size() / 3; + + copyVertices(transformedVertices, meshData.solidVerts); + copyIndices(tempTriangles, meshData.solidTris, offset, isM2); + + // now handle liquid data + if (liquid) + { + vector liqVerts; + vector liqTris; + uint32 tilesX, tilesY, vertsX, vertsY; + Vector3 corner; + liquid->getPosInfo(tilesX, tilesY, corner); + vertsX = tilesX + 1; + vertsY = tilesY + 1; + uint8* flags = liquid->GetFlagsStorage(); + float* data = liquid->GetHeightStorage(); + uint8 type = NAV_EMPTY; + + // convert liquid type to NavTerrain + switch (liquid->GetType()) + { + case 0: + case 1: + type = NAV_WATER; + break; + case 2: + type = NAV_MAGMA; + break; + case 3: + type = NAV_SLIME; + break; + } + + // indexing is weird... + // after a lot of trial and error, this is what works: + // vertex = y*vertsX+x + // tile = x*tilesY+y + // flag = y*tilesY+x + + Vector3 vert; + for (uint32 x = 0; x < vertsX; ++x) + for (uint32 y = 0; y < vertsY; ++y) + { + vert = Vector3(corner.x + x * GRID_PART_SIZE, corner.y + y * GRID_PART_SIZE, data[y*vertsX + x]); + vert = vert * rotation * scale + position; + vert.x *= -1.f; + vert.y *= -1.f; + liqVerts.push_back(vert); + } + + int idx1, idx2, idx3, idx4; + uint32 square; + for (uint32 x = 0; x < tilesX; ++x) + for (uint32 y = 0; y < tilesY; ++y) + if ((flags[x+y*tilesX] & 0x0f) != 0x0f) + { + square = x * tilesY + y; + idx1 = square+x; + idx2 = square+1+x; + idx3 = square+tilesY+1+1+x; + idx4 = square+tilesY+1+x; + + // top triangle + liqTris.push_back(idx3); + liqTris.push_back(idx2); + liqTris.push_back(idx1); + // bottom triangle + liqTris.push_back(idx4); + liqTris.push_back(idx3); + liqTris.push_back(idx1); + } + + uint32 liqOffset = meshData.liquidVerts.size() / 3; + for (uint32 i = 0; i < liqVerts.size(); ++i) + meshData.liquidVerts.append(liqVerts[i].y, liqVerts[i].z, liqVerts[i].x); + + for (uint32 i = 0; i < liqTris.size() / 3; ++i) + { + meshData.liquidTris.append(liqTris[i*3+1] + liqOffset, liqTris[i*3+2] + liqOffset, liqTris[i*3] + liqOffset); + meshData.liquidType.append(type); + } + } + } + } + } + while (false); + + vmapManager->unloadMap(mapID, tileX, tileY); + delete vmapManager; + + return retval; + } + + /**************************************************************************/ + void TerrainBuilder::transform(vector &source, vector &transformedVertices, float scale, G3D::Matrix3 &rotation, Vector3 &position) + { + for (vector::iterator it = source.begin(); it != source.end(); ++it) + { + // apply tranform, then mirror along the horizontal axes + Vector3 v((*it) * rotation * scale + position); + v.x *= -1.f; + v.y *= -1.f; + transformedVertices.push_back(v); + } + } + + /**************************************************************************/ + void TerrainBuilder::copyVertices(vector &source, G3D::Array &dest) + { + for (vector::iterator it = source.begin(); it != source.end(); ++it) + { + dest.push_back((*it).y); + dest.push_back((*it).z); + dest.push_back((*it).x); + } + } + + /**************************************************************************/ + void TerrainBuilder::copyIndices(vector &source, G3D::Array &dest, int offset, bool flip) + { + if (flip) + { + for (vector::iterator it = source.begin(); it != source.end(); ++it) + { + dest.push_back((*it).idx2+offset); + dest.push_back((*it).idx1+offset); + dest.push_back((*it).idx0+offset); + } + } + else + { + for (vector::iterator it = source.begin(); it != source.end(); ++it) + { + dest.push_back((*it).idx0+offset); + dest.push_back((*it).idx1+offset); + dest.push_back((*it).idx2+offset); + } + } + } + + /**************************************************************************/ + void TerrainBuilder::copyIndices(G3D::Array &source, G3D::Array &dest, int offset) + { + int* src = source.getCArray(); + for (int32 i = 0; i < source.size(); ++i) + dest.append(src[i] + offset); + } + + /**************************************************************************/ + void TerrainBuilder::cleanVertices(G3D::Array &verts, G3D::Array &tris) + { + map vertMap; + + int* t = tris.getCArray(); + float* v = verts.getCArray(); + + // collect all the vertex indices from triangle + for (int i = 0; i < tris.size(); ++i) + { + if (vertMap.find(t[i]) != vertMap.end()) + continue; + + vertMap.insert(std::pair(t[i], 0)); + } + + // collect the vertices + G3D::Array cleanVerts; + int index, count = 0; + for (map::iterator it = vertMap.begin(); it != vertMap.end(); ++it) + { + index = (*it).first; + (*it).second = count; + cleanVerts.append(v[index*3], v[index*3+1], v[index*3+2]); + count++; + } + verts.fastClear(); + verts.append(cleanVerts); + cleanVerts.clear(); + + // update triangles to use new indices + for (int i = 0; i < tris.size(); ++i) + { + map::iterator it; + if ((it = vertMap.find(t[i])) == vertMap.end()) + continue; + + t[i] = (*it).second; + } + + vertMap.clear(); + } + + /**************************************************************************/ + void TerrainBuilder::loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, const char* offMeshFilePath) + { + // no meshfile input given? + if (offMeshFilePath == NULL) + return; + + FILE* fp = fopen(offMeshFilePath, "rb"); + if (!fp) + { + printf(" loadOffMeshConnections:: input file %s not found!\n", offMeshFilePath); + return; + } + + // pretty silly thing, as we parse entire file and load only the tile we need + // but we don't expect this file to be too large + char* buf = new char[512]; + while(fgets(buf, 512, fp)) + { + float p0[3], p1[3]; + int mid, tx, ty; + float size; + if (10 != sscanf(buf, "%d %d,%d (%f %f %f) (%f %f %f) %f", &mid, &tx, &ty, + &p0[0], &p0[1], &p0[2], &p1[0], &p1[1], &p1[2], &size)) + continue; + + if (mapID == mid, tileX == tx, tileY == ty) + { + meshData.offMeshConnections.append(p0[1]); + meshData.offMeshConnections.append(p0[2]); + meshData.offMeshConnections.append(p0[0]); + + meshData.offMeshConnections.append(p1[1]); + meshData.offMeshConnections.append(p1[2]); + meshData.offMeshConnections.append(p1[0]); + + meshData.offMeshConnectionDirs.append(1); // 1 - both direction, 0 - one sided + meshData.offMeshConnectionRads.append(size); // agent size equivalent + // can be used same way as polygon flags + meshData.offMeshConnectionsAreas.append((unsigned char)0xFF); + meshData.offMeshConnectionsFlags.append((unsigned short)0xFF); // all movement masks can make this path + } + + } + + delete [] buf; + fclose(fp); + } +} diff --git a/src/tools/mmaps_generator/TerrainBuilder.h b/src/tools/mmaps_generator/TerrainBuilder.h new file mode 100644 index 00000000000..a7f21883af2 --- /dev/null +++ b/src/tools/mmaps_generator/TerrainBuilder.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#ifndef _MMAP_TERRAIN_BUILDER_H +#define _MMAP_TERRAIN_BUILDER_H + +#include "PathCommon.h" +#include "Map.h" +#include "SharedDefines.h" + +#include "WorldModel.h" + +#include "G3D/Array.h" +#include "G3D/Vector3.h" +#include "G3D/Matrix3.h" + +using namespace Trinity; + +namespace MMAP +{ + enum Spot + { + TOP = 1, + RIGHT = 2, + LEFT = 3, + BOTTOM = 4, + ENTIRE = 5 + }; + + enum Grid + { + GRID_V8, + GRID_V9 + }; + + static const int V9_SIZE = 129; + static const int V9_SIZE_SQ = V9_SIZE*V9_SIZE; + static const int V8_SIZE = 128; + static const int V8_SIZE_SQ = V8_SIZE*V8_SIZE; + static const float GRID_SIZE = 533.33333f; + static const float GRID_PART_SIZE = GRID_SIZE/V8_SIZE; + + // see contrib/extractor/system.cpp, CONF_use_minHeight + static const float INVALID_MAP_LIQ_HEIGHT = -500.f; + static const float INVALID_MAP_LIQ_HEIGHT_MAX = 5000.0f; + + // see following files: + // contrib/extractor/system.cpp + // src/game/Map.cpp + static char const* MAP_VERSION_MAGIC = "v1.2"; + + struct MeshData + { + G3D::Array solidVerts; + G3D::Array solidTris; + + G3D::Array liquidVerts; + G3D::Array liquidTris; + G3D::Array liquidType; + + // offmesh connection data + G3D::Array offMeshConnections; // [p0y,p0z,p0x,p1y,p1z,p1x] - per connection + G3D::Array offMeshConnectionRads; + G3D::Array offMeshConnectionDirs; + G3D::Array offMeshConnectionsAreas; + G3D::Array offMeshConnectionsFlags; + }; + + class TerrainBuilder + { + public: + TerrainBuilder(bool skipLiquid); + ~TerrainBuilder(); + + void loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); + bool loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); + void loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, const char* offMeshFilePath); + + bool usesLiquids() { return !m_skipLiquid; } + + // vert and triangle methods + static void transform(vector &original, vector &transformed, + float scale, G3D::Matrix3 &rotation, G3D::Vector3 &position); + static void copyVertices(vector &source, G3D::Array &dest); + static void copyIndices(vector &source, G3D::Array &dest, int offest, bool flip); + static void copyIndices(G3D::Array &src, G3D::Array &dest, int offset); + static void cleanVertices(G3D::Array &verts, G3D::Array &tris); + private: + /// Loads a portion of a map's terrain + bool loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, Spot portion); + + /// Sets loop variables for selecting only certain parts of a map's terrain + void getLoopVars(Spot portion, int &loopStart, int &loopEnd, int &loopInc); + + /// Controls whether liquids are loaded + bool m_skipLiquid; + + /// Load the map terrain from file + bool loadHeightMap(uint32 mapID, uint32 tileX, uint32 tileY, G3D::Array &vertices, G3D::Array &triangles, Spot portion); + + /// Get the vector coordinate for a specific position + void getHeightCoord(int index, Grid grid, float xOffset, float yOffset, float* coord, float* v); + + /// Get the triangle's vector indices for a specific position + void getHeightTriangle(int square, Spot triangle, int* indices, bool liquid = false); + + /// Determines if the specific position's triangles should be rendered + bool isHole(int square, const uint16 holes[16][16]); + + /// Get the liquid vector coordinate for a specific position + void getLiquidCoord(int index, int index2, float xOffset, float yOffset, float* coord, float* v); + + /// Get the liquid type for a specific position + uint8 getLiquidType(int square, const uint8 liquid_type[16][16]); + + // hide parameterless and copy constructor + TerrainBuilder(); + TerrainBuilder(const TerrainBuilder &tb); + }; +} + +#endif + diff --git a/src/tools/mmaps_generator/VMapExtensions.cpp b/src/tools/mmaps_generator/VMapExtensions.cpp new file mode 100644 index 00000000000..4f203e11c21 --- /dev/null +++ b/src/tools/mmaps_generator/VMapExtensions.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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 . + */ + +#include +#include "MapTree.h" +#include "VMapManager2.h" +#include "WorldModel.h" +#include "ModelInstance.h" + +using namespace std; + +namespace VMAP +{ + // Need direct access to encapsulated VMAP data, so we add functions for MMAP generator + // maybe add MapBuilder as friend to all of the below classes would be better? + + // declared in src/shared/vmap/MapTree.h + void StaticMapTree::getModelInstances(ModelInstance* &models, uint32 &count) + { + models = iTreeValues; + count = iNTreeValues; + } + + // declared in src/shared/vmap/VMapManager2.h + void VMapManager2::getInstanceMapTree(InstanceTreeMap &instanceMapTree) + { + instanceMapTree = iInstanceMapTrees; + } + + // declared in src/shared/vmap/WorldModel.h + void WorldModel::getGroupModels(vector &groupModels) + { + groupModels = this->groupModels; + } + + // declared in src/shared/vmap/WorldModel.h + void GroupModel::getMeshData(vector &vertices, vector &triangles, WmoLiquid* &liquid) + { + vertices = this->vertices; + triangles = this->triangles; + liquid = iLiquid; + } + + // declared in src/shared/vmap/ModelInstance.h + WorldModel* const ModelInstance::getWorldModel() + { + return iModel; + } + + // declared in src/shared/vmap/WorldModel.h + void WmoLiquid::getPosInfo(uint32 &tilesX, uint32 &tilesY, Vector3 &corner) const + { + tilesX = iTilesX; + tilesY = iTilesY; + corner = iCorner; + } +} -- cgit v1.2.3 From 119a3ff5fc33eafdc8ab13c6dfaedda52b66ee77 Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 16:11:17 +0200 Subject: movementgenerator mmaps usage. Signed-off-by: Venugh --- .../FleeingMovementGenerator.cpp | 280 +++------------------ .../MovementGenerators/FleeingMovementGenerator.h | 12 - .../MovementGenerators/HomeMovementGenerator.cpp | 22 +- .../MovementGenerators/PointMovementGenerator.cpp | 19 +- .../MovementGenerators/PointMovementGenerator.h | 7 +- 5 files changed, 70 insertions(+), 270 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 08e27abf050..1b32bb16b2c 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -20,6 +20,7 @@ #include "CreatureAI.h" #include "MapManager.h" #include "FleeingMovementGenerator.h" +#include "PathFinderMovementGenerator.h" #include "ObjectAccessor.h" #include "MoveSplineInit.h" #include "MoveSpline.h" @@ -36,19 +37,26 @@ void FleeingMovementGenerator::_setTargetLocation(T &owner) if (owner.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) return; - if (!_setMoveData(owner)) - return; - float x, y, z; if (!_getPoint(owner, x, y, z)) return; owner.AddUnitState(UNIT_STATE_FLEEING_MOVE); + PathFinderMovementGenerator path(&owner); + path.setPathLengthLimit(30.0f); + path.calculate(x, y, z); + if (path.getPathType() & PATHFIND_NOPATH) + { + i_nextCheckTime.Reset(urand(1000, 1500)); + return; + } + Movement::MoveSplineInit init(owner); - init.MoveTo(x,y,z); + init.MovebyPath(path.getPath()); init.SetWalk(false); - init.Launch(); + int32 traveltime = init.Launch(); + i_nextCheckTime.Reset(traveltime + urand(800, 1500)); } template @@ -57,221 +65,46 @@ bool FleeingMovementGenerator::_getPoint(T &owner, float &x, float &y, float if (!&owner) return false; - x = owner.GetPositionX(); - y = owner.GetPositionY(); - z = owner.GetPositionZ(); - - float temp_x, temp_y, angle; - const Map* _map = owner.GetBaseMap(); - // primitive path-finding - for (uint8 i = 0; i < 18; ++i) - { - if (i_only_forward && i > 2) - break; - - float distance = 5.0f; - - switch (i) - { - case 0: - angle = i_cur_angle; - break; - case 1: - angle = i_cur_angle; - distance /= 2; - break; - case 2: - angle = i_cur_angle; - distance /= 4; - break; - case 3: - angle = i_cur_angle + static_cast(M_PI/4); - break; - case 4: - angle = i_cur_angle - static_cast(M_PI/4); - break; - case 5: - angle = i_cur_angle + static_cast(M_PI/4); - distance /= 2; - break; - case 6: - angle = i_cur_angle - static_cast(M_PI/4); - distance /= 2; - break; - case 7: - angle = i_cur_angle + static_cast(M_PI/2); - break; - case 8: - angle = i_cur_angle - static_cast(M_PI/2); - break; - case 9: - angle = i_cur_angle + static_cast(M_PI/2); - distance /= 2; - break; - case 10: - angle = i_cur_angle - static_cast(M_PI/2); - distance /= 2; - break; - case 11: - angle = i_cur_angle + static_cast(M_PI/4); - distance /= 4; - break; - case 12: - angle = i_cur_angle - static_cast(M_PI/4); - distance /= 4; - break; - case 13: - angle = i_cur_angle + static_cast(M_PI/2); - distance /= 4; - break; - case 14: - angle = i_cur_angle - static_cast(M_PI/2); - distance /= 4; - break; - case 15: - angle = i_cur_angle + static_cast(3*M_PI/4); - distance /= 2; - break; - case 16: - angle = i_cur_angle - static_cast(3*M_PI/4); - distance /= 2; - break; - case 17: - angle = i_cur_angle + static_cast(M_PI); - distance /= 2; - break; - } - temp_x = x + distance * cos(angle); - temp_y = y + distance * sin(angle); - Trinity::NormalizeMapCoord(temp_x); - Trinity::NormalizeMapCoord(temp_y); - if (owner.IsWithinLOS(temp_x, temp_y, z)) - { - bool is_water_now = _map->IsInWater(x,y,z); - - if (is_water_now && _map->IsInWater(temp_x,temp_y,z)) - { - x = temp_x; - y = temp_y; - return true; - } - float new_z = _map->GetHeight(owner.GetPhaseMask(), temp_x, temp_y, z, true); - - if (new_z <= INVALID_HEIGHT) - continue; - - bool is_water_next = _map->IsInWater(temp_x, temp_y, new_z); - - if ((is_water_now && !is_water_next && !is_land_ok) || (!is_water_now && is_water_next && !is_water_ok)) - continue; - - if (!(new_z - z) || distance / fabs(new_z - z) > 1.0f) - { - float new_z_left = _map->GetHeight(owner.GetPhaseMask(), temp_x + 1.0f*cos(angle+static_cast(M_PI/2)),temp_y + 1.0f*sin(angle+static_cast(M_PI/2)),z,true); - float new_z_right = _map->GetHeight(owner.GetPhaseMask(), temp_x + 1.0f*cos(angle-static_cast(M_PI/2)),temp_y + 1.0f*sin(angle-static_cast(M_PI/2)),z,true); - if (fabs(new_z_left - new_z) < 1.2f && fabs(new_z_right - new_z) < 1.2f) - { - x = temp_x; - y = temp_y; - z = new_z; - return true; - } - } - } - } - i_to_distance_from_caster = 0.0f; - i_nextCheckTime.Reset(urand(500,1000)); - return false; -} - -template -bool FleeingMovementGenerator::_setMoveData(T &owner) -{ - float cur_dist_xyz = owner.GetDistance(i_caster_x, i_caster_y, i_caster_z); - - if (i_to_distance_from_caster > 0.0f) - { - if ((i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz < i_to_distance_from_caster) || - // if we reach lower distance - (i_last_distance_from_caster > i_to_distance_from_caster && cur_dist_xyz > i_last_distance_from_caster) || - // if we can't be close - (i_last_distance_from_caster < i_to_distance_from_caster && cur_dist_xyz > i_to_distance_from_caster) || - // if we reach bigger distance - (cur_dist_xyz > MAX_QUIET_DISTANCE) || // if we are too far - (i_last_distance_from_caster > MIN_QUIET_DISTANCE && cur_dist_xyz < MIN_QUIET_DISTANCE)) - // if we leave 'quiet zone' - { - // we are very far or too close, stopping - i_to_distance_from_caster = 0.0f; - i_nextCheckTime.Reset(urand(500,1000)); - return false; - } - else - { - // now we are running, continue - i_last_distance_from_caster = cur_dist_xyz; - return true; - } - } - - float cur_dist; - float angle_to_caster; - + float dist_from_caster, angle_to_caster; if (Unit* fright = ObjectAccessor::GetUnit(owner, i_frightGUID)) { - cur_dist = fright->GetDistance(&owner); - if (cur_dist < cur_dist_xyz) - { - i_caster_x = fright->GetPositionX(); - i_caster_y = fright->GetPositionY(); - i_caster_z = fright->GetPositionZ(); + dist_from_caster = fright->GetDistance(&owner); + if (dist_from_caster > 0.2f) angle_to_caster = fright->GetAngle(&owner); - } else - { - cur_dist = cur_dist_xyz; - angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + static_cast(M_PI); - } + angle_to_caster = frand(0, 2*M_PI_F); } else { - cur_dist = cur_dist_xyz; - angle_to_caster = owner.GetAngle(i_caster_x, i_caster_y) + static_cast(M_PI); + dist_from_caster = 0.0f; + angle_to_caster = frand(0, 2*M_PI_F); } - // if we too close may use 'path-finding' else just stop - i_only_forward = cur_dist >= MIN_QUIET_DISTANCE/3; - - //get angle and 'distance from caster' to run - float angle; - - if (i_cur_angle == 0.0f && i_last_distance_from_caster == 0.0f) //just started, first time - { - angle = (float)rand_norm()*(1.0f - cur_dist/MIN_QUIET_DISTANCE) * static_cast(M_PI/3) + (float)rand_norm()*static_cast(M_PI*2/3); - i_to_distance_from_caster = MIN_QUIET_DISTANCE; - i_only_forward = true; - } - else if (cur_dist < MIN_QUIET_DISTANCE) + float dist, angle; + if (dist_from_caster < MIN_QUIET_DISTANCE) { - angle = static_cast(M_PI/6) + (float)rand_norm()*static_cast(M_PI*2/3); - i_to_distance_from_caster = cur_dist*2/3 + (float)rand_norm()*(MIN_QUIET_DISTANCE - cur_dist*2/3); + dist = frand(0.4f, 1.3f)*(MIN_QUIET_DISTANCE - dist_from_caster); + angle = angle_to_caster + frand(-M_PI_F/8, M_PI_F/8); } - else if (cur_dist > MAX_QUIET_DISTANCE) + else if(dist_from_caster > MAX_QUIET_DISTANCE) { - angle = (float)rand_norm()*static_cast(M_PI/3) + static_cast(M_PI*2/3); - i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + (float)rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f); + dist = frand(0.4f, 1.0f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); + angle = -angle_to_caster + frand(-M_PI_F/4, M_PI_F/4); } - else + else // we are inside quiet range { - angle = (float)rand_norm()*static_cast(M_PI); - i_to_distance_from_caster = MIN_QUIET_DISTANCE + 2.5f + (float)rand_norm()*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE - 2.5f); + dist = frand(0.6f, 1.2f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); + angle = frand(0, 2*M_PI_F); } - int8 sign = (float)rand_norm() > 0.5f ? 1 : -1; - i_cur_angle = sign*angle + angle_to_caster; + float curr_x, curr_y, curr_z; + owner.GetPosition(curr_x, curr_y, curr_z); - // current distance - i_last_distance_from_caster = cur_dist; + x = curr_x + dist*cos(angle); + y = curr_y + dist*sin(angle); + z = curr_z; + + owner.UpdateAllowedPositionZ(x, y, z); return true; } @@ -285,44 +118,10 @@ void FleeingMovementGenerator::Initialize(T &owner) owner.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); owner.AddUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); - _Init(owner); - - if (Unit *fright = ObjectAccessor::GetUnit(owner, i_frightGUID)) - { - i_caster_x = fright->GetPositionX(); - i_caster_y = fright->GetPositionY(); - i_caster_z = fright->GetPositionZ(); - } - else - { - i_caster_x = owner.GetPositionX(); - i_caster_y = owner.GetPositionY(); - i_caster_z = owner.GetPositionZ(); - } - - i_only_forward = true; - i_cur_angle = 0.0f; - i_last_distance_from_caster = 0.0f; - i_to_distance_from_caster = 0.0f; - _setTargetLocation(owner); -} - -template<> -void FleeingMovementGenerator::_Init(Creature &owner) -{ - if (!&owner) + if (owner.GetTypeId() == TYPEID_UNIT) return; - //owner.SetTargetGuid(ObjectGuid()); - is_water_ok = owner.canSwim(); - is_land_ok = owner.canWalk(); -} - -template<> -void FleeingMovementGenerator::_Init(Player &) -{ - is_water_ok = true; - is_land_ok = true; + _setTargetLocation(owner); } template<> @@ -330,6 +129,7 @@ void FleeingMovementGenerator::Finalize(Player &owner) { owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); owner.ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); + owner.StopMoving(); } template<> @@ -367,8 +167,6 @@ bool FleeingMovementGenerator::Update(T &owner, const uint32 &time_diff) template void FleeingMovementGenerator::Initialize(Player &); template void FleeingMovementGenerator::Initialize(Creature &); -template bool FleeingMovementGenerator::_setMoveData(Player &); -template bool FleeingMovementGenerator::_setMoveData(Creature &); template bool FleeingMovementGenerator::_getPoint(Player &, float &, float &, float &); template bool FleeingMovementGenerator::_getPoint(Creature &, float &, float &, float &); template void FleeingMovementGenerator::_setTargetLocation(Player &); diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h index aec93ad3375..cb3bd1cb69a 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h @@ -37,19 +37,7 @@ class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovem private: void _setTargetLocation(T &owner); bool _getPoint(T &owner, float &x, float &y, float &z); - bool _setMoveData(T &owner); - void _Init(T &); - bool is_water_ok :1; - bool is_land_ok :1; - bool i_only_forward:1; - - float i_caster_x; - float i_caster_y; - float i_caster_z; - float i_last_distance_from_caster; - float i_to_distance_from_caster; - float i_cur_angle; uint64 i_frightGUID; TimeTracker i_nextCheckTime; }; diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index 311b69c06b7..eaf48150a13 100755 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -25,10 +25,22 @@ void HomeMovementGenerator::Initialize(Creature & owner) { + owner.SetWalk(false); owner.AddUnitState(UNIT_STATE_EVADE); _setTargetLocation(owner); } +void HomeMovementGenerator::Finalize(Creature& owner) +{ + if (arrived) + { + owner.ClearUnitState(UNIT_STAT_EVADE); + owner.SetWalk(true); + owner.LoadCreaturesAddon(true); + owner.AI()->JustReachedHome(); + } +} + void HomeMovementGenerator::Reset(Creature &) { } @@ -41,11 +53,11 @@ void HomeMovementGenerator::_setTargetLocation(Creature & owner) Movement::MoveSplineInit init(owner); float x, y, z, o; // at apply we can select more nice return points base at current movegen - //if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner,x,y,z)) - //{ - owner.GetHomePosition(x, y, z, o); - init.SetFacing(o); - //} + if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner,x,y,z)) + { + owner.GetHomePosition(x, y, z, o); + init.SetFacing(o); + } init.MoveTo(x,y,z); init.SetWalk(false); init.Launch(); diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index a922c937b5f..f6f8b1fbafd 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -34,7 +34,7 @@ void PointMovementGenerator::Initialize(T &unit) unit.AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); Movement::MoveSplineInit init(unit); - init.MoveTo(i_x, i_y, i_z); + init.MoveTo(i_x, i_y, i_z, m_generatePath); if (speed > 0.0f) init.SetVelocity(speed); init.Launch(); @@ -59,7 +59,8 @@ bool PointMovementGenerator::Update(T &unit, const uint32 & /*diff*/) template void PointMovementGenerator::Finalize(T &unit) { - unit.ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + if (unit.HasUnitState(UNIT_STAT_CHARGING)) + unit.ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); if (unit.movespline->Finalized()) MovementInform(unit); @@ -120,11 +121,11 @@ void EffectMovementGenerator::Finalize(Unit &unit) if (((Creature&)unit).AI()) ((Creature&)unit).AI()->MovementInform(EFFECT_MOTION_TYPE, m_Id); // Need restore previous movement since we have no proper states system - //if (unit.isAlive() && !unit.HasUnitState(UNIT_STATE_CONFUSED|UNIT_STATE_FLEEING)) - //{ - // if (Unit * victim = unit.getVictim()) - // unit.GetMotionMaster()->MoveChase(victim); - // else - // unit.GetMotionMaster()->Initialize(); - //} + if (unit.isAlive() && !unit.HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_FLEEING)) + { + if (Unit* victim = unit.getVictim()) + unit.GetMotionMaster()->MoveChase(victim); + else + unit.GetMotionMaster()->Initialize(); + } } diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h index 13be9fee77b..404d3362bab 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h @@ -26,8 +26,8 @@ template class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementGenerator > { public: - PointMovementGenerator(uint32 _id, float _x, float _y, float _z, float _speed = 0.0f) : id(_id), - i_x(_x), i_y(_y), i_z(_z), speed(_speed) {} + PointMovementGenerator(uint32 _id, float _x, float _y, float _z, bool _generatePath, float _speed = 0.0f) : id(_id), + i_x(_x), i_y(_y), i_z(_z), m_generatePath(_generatePath), speed(_speed) {} void Initialize(T &); void Finalize(T &); @@ -43,13 +43,14 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG uint32 id; float i_x, i_y, i_z; float speed; + bool m_generatePath; }; class AssistanceMovementGenerator : public PointMovementGenerator { public: AssistanceMovementGenerator(float _x, float _y, float _z) : - PointMovementGenerator(0, _x, _y, _z) {} + PointMovementGenerator(0, _x, _y, _z, true) {} MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_MOTION_TYPE; } void Finalize(Unit &); -- cgit v1.2.3 From c8f708f9ad0bcc91bf35fab67f4ce7d7eda39b0c Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 16:20:22 +0200 Subject: remove useless pathfinding code. --- .../TargetedMovementGenerator.cpp | 50 ++-- .../MovementGenerators/TargetedMovementGenerator.h | 8 +- .../WaypointMovementGenerator.cpp | 328 --------------------- 3 files changed, 31 insertions(+), 355 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index eb61db8b4ba..5c0e24be440 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -26,8 +26,6 @@ #include "MoveSpline.h" #include "Player.h" -#include - template void TargetedMovementGeneratorMedium::_setTargetLocation(T &owner) { @@ -65,30 +63,27 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T &owner) i_target->GetClosePoint(x, y, z, owner.GetObjectSize(), i_offset, i_angle); } - /* - We MUST not check the distance difference and avoid setting the new location for smaller distances. - By that we risk having far too many GetContactPoint() calls freezing the whole system. - In TargetedMovementGenerator::Update() we check the distance to the target and at - some range we calculate a new position. The calculation takes some processor cycles due to vmaps. - If the distance to the target it too large to ignore, - but the distance to the new contact point is short enough to be ignored, - we will calculate a new contact point each update loop, but will never move to it. - The system will freeze. - ralf - - //We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize - float bothObjectSize = i_target->GetObjectBoundingRadius() + owner.GetObjectBoundingRadius() + CONTACT_DISTANCE; - if ( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize ) - return; - */ + if (!i_path) + i_path = new PathFinderMovementGenerator(&owner); + // allow pets following their master to cheat while generating paths + bool forceDest = (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->isPet() + && owner.HasUnitState(UNIT_STAT_FOLLOW)); + i_path->calculate(x, y, z, forceDest); + if (i_path->getPathType() & PATHFIND_NOPATH) + return; D::_addUnitStateMove(owner); i_targetReached = false; i_recalculateTravel = false; + owner.AddUnitState(UNIT_STATE_CHASE); Movement::MoveSplineInit init(owner); - init.MoveTo(x,y,z); + if (!i_target->IsInWater()) + init.MovebyPath(i_path->getPath()); + else + init.MoveTo(i_target->GetPositionX(), i_target->GetPositionY(), i_target->GetPositionZ(), false, false); + init.SetWalk(((D*)this)->EnableWalking()); init.Launch(); } @@ -125,7 +120,7 @@ bool TargetedMovementGeneratorMedium::Update(T &owner, const uint32 & time_ if (!i_target.isValid() || !i_target->IsInWorld()) return false; - if (!owner.isAlive()) + if (!&owner || !owner.isAlive()) return true; if (owner.HasUnitState(UNIT_STATE_NOT_MOVE)) @@ -152,11 +147,18 @@ bool TargetedMovementGeneratorMedium::Update(T &owner, const uint32 & time_ i_recheckDistance.Update(time_diff); if (i_recheckDistance.Passed()) { - i_recheckDistance.Reset(50); + i_recheckDistance.Reset(100); //More distance let have better performance, less distance let have more sensitive reaction at target move. - float allowed_dist = i_target->GetObjectSize() + owner.GetObjectSize() + MELEE_RANGE - 0.5f; - float dist = (owner.movespline->FinalDestination() - G3D::Vector3(i_target->GetPositionX(),i_target->GetPositionY(),i_target->GetPositionZ())).squaredLength(); - if (dist >= allowed_dist * allowed_dist) + float allowed_dist = owner.GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE); + G3D::Vector3 dest = owner.movespline->FinalDestination(); + + bool targetMoved = false; + if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly()) + targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist); + else + targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist); + + if (targetMoved) _setTargetLocation(owner); } diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 29fd73624e1..28893c44cfb 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -23,6 +23,7 @@ #include "FollowerReference.h" #include "Timer.h" #include "Unit.h" +#include "PathFinderMovementGenerator.h" class TargetedMovementGeneratorBase { @@ -38,12 +39,12 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, { protected: TargetedMovementGeneratorMedium(Unit &target, float offset, float angle) : - TargetedMovementGeneratorBase(target), i_recheckDistance(0), + TargetedMovementGeneratorBase(target), i_recheckDistance(0),, i_path(NULL), i_offset(offset), i_angle(angle), i_recalculateTravel(false), i_targetReached(false) { } - ~TargetedMovementGeneratorMedium() {} + ~TargetedMovementGeneratorMedium() { delete i_path; } public: bool Update(T &, const uint32 &); @@ -51,7 +52,7 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, void unitSpeedChanged() { i_recalculateTravel=true; } void UpdateFinalDistance(float fDistance); - + bool IsReachable() const { return (i_path) ? (i_path->getPathType() & PATHFIND_NORMAL) : true; } protected: void _setTargetLocation(T &); @@ -60,6 +61,7 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, float i_angle; bool i_recalculateTravel : 1; bool i_targetReached : 1; + PathFinderMovementGenerator* i_path; }; template diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 81fe1606ede..6d060668e4c 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -319,331 +319,3 @@ void FlightPathMovementGenerator::PreloadEndGrid() else sLog->outDetail("Unable to determine map to preload flightmaster grid"); } - - -// -// Unique1's ASTAR Pathfinding Code... For future use & reference... -// - -#ifdef __PATHFINDING__ - -int GetFCost(int to, int num, int parentNum, float *gcost); // Below... - -int ShortenASTARRoute(short int *pathlist, int number) -{ // Wrote this to make the routes a little smarter (shorter)... No point looping back to the same places... Unique1 - short int temppathlist[MAX_PATHLIST_NODES]; - int count = 0; - // int count2 = 0; - int temp, temp2; - int link; - int upto = 0; - - for (temp = number; temp >= 0; temp--) - { - qboolean shortened = qfalse; - - for (temp2 = 0; temp2 < temp; temp2++) - { - for (link = 0; link < nodes[pathlist[temp]].enodenum; link++) - { - if (nodes[pathlist[temp]].links[link].flags & PATH_BLOCKED) - continue; - - //if ((bot->client->ps.eFlags & EF_TANK) && nodes[bot->current_node].links[link].flags & PATH_NOTANKS) //if this path is blocked, skip it - // continue; - - //if (nodes[nodes[pathlist[temp]].links[link].targetNode].origin[2] > nodes[pathlist[temp]].origin[2] + 32) - // continue; - - if (nodes[pathlist[temp]].links[link].targetNode == pathlist[temp2]) - { // Found a shorter route... - //if (OrgVisible(nodes[pathlist[temp2]].origin, nodes[pathlist[temp]].origin, -1)) - { - temppathlist[count] = pathlist[temp2]; - temp = temp2; - ++count; - shortened = qtrue; - } - } - } - } - - if (!shortened) - { - temppathlist[count] = pathlist[temp]; - ++count; - } - } - - upto = count; - - for (temp = 0; temp < count; temp++) - { - pathlist[temp] = temppathlist[upto]; - --upto; - } - - G_Printf("ShortenASTARRoute: Path size reduced from %i to %i nodes...n", number, count); - return count; -} - -/* -=========================================================================== -CreatePathAStar -This function uses the A* pathfinding algorithm to determine the -shortest path between any two nodes. -It's fairly complex, so I'm not really going to explain it much. -Look up A* and binary heaps for more info. -pathlist stores the ideal path between the nodes, in reverse order, -and the return value is the number of nodes in that path -=========================================================================== -*/ -int CreatePathAStar(gentity_t *bot, int from, int to, short int *pathlist) -{ - //all the data we have to hold...since we can't do dynamic allocation, has to be MAX_NODES - //we can probably lower this later - eg, the open list should never have more than at most a few dozen items on it - short int openlist[MAX_NODES+1]; //add 1 because it's a binary heap, and they don't use 0 - 1 is the first used index - float gcost[MAX_NODES]; - int fcost[MAX_NODES]; - char list[MAX_NODES]; //0 is neither, 1 is open, 2 is closed - char because it's the smallest data type - short int parent[MAX_NODES]; - - short int numOpen = 0; - short int atNode, temp, newnode=-1; - qboolean found = qfalse; - int count = -1; - float gc; - int i, u, v, m; - vec3_t vec; - - //clear out all the arrays - memset(openlist, 0, sizeof(short int)*(MAX_NODES+1)); - memset(fcost, 0, sizeof(int)*MAX_NODES); - memset(list, 0, sizeof(char)*MAX_NODES); - memset(parent, 0, sizeof(short int)*MAX_NODES); - memset(gcost, -1, sizeof(float)*MAX_NODES); - - //make sure we have valid data before calculating everything - if ((from == NODE_INVALID) || (to == NODE_INVALID) || (from >= MAX_NODES) || (to >= MAX_NODES) || (from == to)) - return -1; - - openlist[1] = from; //add the starting node to the open list - ++numOpen; - gcost[from] = 0; //its f and g costs are obviously 0 - fcost[from] = 0; - - while (1) - { - if (numOpen != 0) //if there are still items in the open list - { - //pop the top item off of the list - atNode = openlist[1]; - list[atNode] = 2; //put the node on the closed list so we don't check it again - --numOpen; - - openlist[1] = openlist[numOpen+1]; //move the last item in the list to the top position - v = 1; - - //this while loop reorders the list so that the new lowest fcost is at the top again - while (1) - { - u = v; - if ((2*u+1) < numOpen) //if both children exist - { - if (fcost[openlist[u]] >= fcost[openlist[2*u]]) - v = 2*u; - if (fcost[openlist[v]] >= fcost[openlist[2*u+1]]) - v = 2*u+1; - } - else - { - if ((2*u) < numOpen) //if only one child exists - { - if (fcost[openlist[u]] >= fcost[openlist[2*u]]) - v = 2*u; - } - } - - if (u != v) //if they're out of order, swap this item with its parent - { - temp = openlist[u]; - openlist[u] = openlist[v]; - openlist[v] = temp; - } - else - break; - } - - for (i = 0; i < nodes[atNode].enodenum; ++i) //loop through all the links for this node - { - newnode = nodes[atNode].links[i].targetNode; - - //if this path is blocked, skip it - if (nodes[atNode].links[i].flags & PATH_BLOCKED) - continue; - //if this path is blocked, skip it - if (bot->client && (bot->client->ps.eFlags & EF_TANK) && nodes[atNode].links[i].flags & PATH_NOTANKS) - continue; - //skip any unreachable nodes - if (bot->client && (nodes[newnode].type & NODE_ALLY_UNREACHABLE) && (bot->client->sess.sessionTeam == TEAM_ALLIES)) - continue; - if (bot->client && (nodes[newnode].type & NODE_AXIS_UNREACHABLE) && (bot->client->sess.sessionTeam == TEAM_AXIS)) - continue; - - if (list[newnode] == 2) //if this node is on the closed list, skip it - continue; - - if (list[newnode] != 1) //if this node is not already on the open list - { - openlist[++numOpen] = newnode; //add the new node to the open list - list[newnode] = 1; - parent[newnode] = atNode; //record the node's parent - - if (newnode == to) //if we've found the goal, don't keep computing paths! - break; //this will break the 'for' and go all the way to 'if (list[to] == 1)' - - //store it's f cost value - fcost[newnode] = GetFCost(to, newnode, parent[newnode], gcost); - - //this loop re-orders the heap so that the lowest fcost is at the top - m = numOpen; - while (m != 1) //while this item isn't at the top of the heap already - { - //if it has a lower fcost than its parent - if (fcost[openlist[m]] <= fcost[openlist[m/2]]) - { - temp = openlist[m/2]; - openlist[m/2] = openlist[m]; - openlist[m] = temp; //swap them - m /= 2; - } - else - break; - } - } - else //if this node is already on the open list - { - gc = gcost[atNode]; - VectorSubtract(nodes[newnode].origin, nodes[atNode].origin, vec); - gc += VectorLength(vec); //calculate what the gcost would be if we reached this node along the current path - - if (gc < gcost[newnode]) //if the new gcost is less (ie, this path is shorter than what we had before) - { - parent[newnode] = atNode; //set the new parent for this node - gcost[newnode] = gc; //and the new g cost - - for (i = 1; i < numOpen; ++i) //loop through all the items on the open list - { - if (openlist[i] == newnode) //find this node in the list - { - //calculate the new fcost and store it - fcost[newnode] = GetFCost(to, newnode, parent[newnode], gcost); - - //reorder the list again, with the lowest fcost item on top - m = i; - while (m != 1) - { - //if the item has a lower fcost than it's parent - if (fcost[openlist[m]] < fcost[openlist[m/2]]) - { - temp = openlist[m/2]; - openlist[m/2] = openlist[m]; - openlist[m] = temp; //swap them - m /= 2; - } - else - break; - } - break; //exit the 'for' loop because we already changed this node - } //if - } //for - } //if (gc < gcost[newnode]) - } //if (list[newnode] != 1) --> else - } //for (loop through links) - } //if (numOpen != 0) - else - { - found = qfalse; //there is no path between these nodes - break; - } - - if (list[to] == 1) //if the destination node is on the open list, we're done - { - found = qtrue; - break; - } - } //while (1) - - if (found == qtrue) //if we found a path - { - //G_Printf("%s - path found!n", bot->client->pers.netname); - count = 0; - - temp = to; //start at the end point - while (temp != from) //travel along the path (backwards) until we reach the starting point - { - pathlist[count++] = temp; //add the node to the pathlist and increment the count - temp = parent[temp]; //move to the parent of this node to continue the path - } - - pathlist[count++] = from; //add the beginning node to the end of the pathlist - - #ifdef __BOT_SHORTEN_ROUTING__ - count = ShortenASTARRoute(pathlist, count); // This isn't working... Dunno why.. Unique1 - #endif //__BOT_SHORTEN_ROUTING__ - } - else - { - //G_Printf("^1*** ^4BOT DEBUG^5: (CreatePathAStar) There is no route between node ^7%i^5 and node ^7%i^5.n", from, to); - count = CreateDumbRoute(from, to, pathlist); - - if (count > 0) - { - #ifdef __BOT_SHORTEN_ROUTING__ - count = ShortenASTARRoute(pathlist, count); // This isn't working... Dunno why.. Unique1 - #endif //__BOT_SHORTEN_ROUTING__ - return count; - } - } - - return count; //return the number of nodes in the path, -1 if not found -} - -/* -=========================================================================== -GetFCost -Utility function used by A* pathfinding to calculate the -cost to move between nodes towards a goal. Using the A* -algorithm F = G + H, G here is the distance along the node -paths the bot must travel, and H is the straight-line distance -to the goal node. -Returned as an int because more precision is unnecessary and it -will slightly speed up heap access -=========================================================================== -*/ -int GetFCost(int to, int num, int parentNum, float *gcost) -{ - float gc = 0; - float hc = 0; - vec3_t v; - - if (gcost[num] == -1) - { - if (parentNum != -1) - { - gc = gcost[parentNum]; - VectorSubtract(nodes[num].origin, nodes[parentNum].origin, v); - gc += VectorLength(v); - } - gcost[num] = gc; - } - else - gc = gcost[num]; - - VectorSubtract(nodes[to].origin, nodes[num].origin, v); - hc = VectorLength(v); - - return (int)(gc + hc); -} -#endif //__PATHFINDING__ - -- cgit v1.2.3 From f478e6be2b5dd67cc1d26948d324045d75d6fdb1 Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 16:38:05 +0200 Subject: spline changes for mmaps. --- src/server/game/Movement/Spline/MoveSplineInit.cpp | 6 +++-- src/server/game/Movement/Spline/MoveSplineInit.h | 28 +++++++++++++++------- src/server/game/World/World.cpp | 1 + 3 files changed, 24 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index e586cb4f4f9..924db9ad726 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -54,7 +54,7 @@ namespace Movement return MOVE_RUN; } - void MoveSplineInit::Launch() + int32 MoveSplineInit::Launch() { MoveSpline& move_spline = *unit.movespline; @@ -86,7 +86,7 @@ namespace Movement args.velocity = unit.GetSpeed(SelectSpeedType(moveFlags)); if (!args.Validate()) - return; + return 0; if (moveFlags & MOVEMENTFLAG_ROOT) moveFlags &= ~MOVEMENTFLAG_MASK_MOVING; @@ -98,6 +98,8 @@ namespace Movement data.append(unit.GetPackGUID()); PacketBuilder::WriteMonsterMove(move_spline, data); unit.SendMessageToSet(&data,true); + + return move_spline.Duration(); } MoveSplineInit::MoveSplineInit(Unit& m) : unit(m) diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 7ef6cd7a120..24563f28c4f 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -20,6 +20,7 @@ #define TRINITYSERVER_MOVESPLINEINIT_H #include "MoveSplineInitArgs.h" +#include "PathFinderMovementGenerator.h" class Unit; @@ -43,7 +44,7 @@ namespace Movement /* Final pass of initialization that launches spline movement. */ - void Launch(); + int32 Launch(); /* Adds movement by parabolic trajectory * @param amplitude - the maximum height of parabola, value could be negative and positive @@ -72,8 +73,8 @@ namespace Movement /* Initializes simple A to B mition, A is current unit's position, B is destination */ - void MoveTo(const Vector3& destination); - void MoveTo(float x, float y, float z); + void MoveTo(const Vector3& destination, bool generatePath = false, bool forceDestination = false); + void MoveTo(float x, float y, float z, bool generatePath = false, bool forceDestination = false); /* Sets Id of fisrt point of the path. When N-th path point will be done ILisener will notify that pointId + N done * Needed for waypoint movement where path splitten into parts @@ -133,17 +134,26 @@ namespace Movement args.path.assign(controls.begin(),controls.end()); } - inline void MoveSplineInit::MoveTo(float x, float y, float z) + inline void MoveSplineInit::MoveTo(float x, float y, float z, bool generatePath, bool forceDestination) { Vector3 v(x,y,z); - MoveTo(v); + MoveTo(v, generatePath, forceDestination); } - inline void MoveSplineInit::MoveTo(const Vector3& dest) + inline void MoveSplineInit::MoveTo(const Vector3& dest, bool generatePath, bool forceDestination) { - args.path_Idx_offset = 0; - args.path.resize(2); - args.path[1] = dest; + if (generatePath) + { + PathFinderMovementGenerator path(&unit); + path.calculate(dest.x, dest.y, dest.z, forceDestination); + MovebyPath(path.getPath()); + } + else + { + args.path_Idx_offset = 0; + args.path.resize(2); + args.path[1] = dest; + } } inline void MoveSplineInit::SetParabolic(float amplitude, float time_shift) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 3870a108d57..90d4ce3604a 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -136,6 +136,7 @@ World::~World() delete command; VMAP::VMapFactory::clear(); + MMAP::MMapFactory::clear(); //TODO free addSessQueue } -- cgit v1.2.3 From 8452fd0dbd293a807da563f3203d2cad4985932a Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 17:05:32 +0200 Subject: fixed errors. --- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Miscellaneous/SharedDefines.h | 30 +++++++++++++ src/server/game/Movement/MotionMaster.cpp | 4 +- .../ConfusedMovementGenerator.cpp | 52 ++-------------------- .../MovementGenerators/ConfusedMovementGenerator.h | 2 +- .../FleeingMovementGenerator.cpp | 10 ++--- .../MovementGenerators/HomeMovementGenerator.cpp | 13 +----- .../PathFinderMovementGenerator.cpp | 8 ++-- .../MovementGenerators/PointMovementGenerator.cpp | 4 +- .../TargetedMovementGenerator.cpp | 4 +- .../MovementGenerators/TargetedMovementGenerator.h | 2 +- src/server/game/Movement/Spline/MoveSpline.h | 3 +- 12 files changed, 53 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 52269199146..69c2961691a 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -366,7 +366,7 @@ bool Unit::haveOffhandWeapon() const return m_canDualWield; } -void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed) +void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath, bool forceDestination) { Movement::MoveSplineInit init(*this); init.MoveTo(x,y,z); diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 1ddf80484e2..16821834669 100755 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -19,6 +19,7 @@ #ifndef TRINITY_SHAREDDEFINES_H #define TRINITY_SHAREDDEFINES_H +#include "DetourNavMesh.h" #include "Define.h" #include @@ -3524,4 +3525,33 @@ enum CalendarError // Calendar - end +#define MMAP_MAGIC 0x4d4d4150 // 'MMAP' +#define MMAP_VERSION 3 + +struct MmapTileHeader +{ + uint32 mmapMagic; + uint32 dtVersion; + uint32 mmapVersion; + uint32 size; + bool usesLiquids : 1; + + MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION), + mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) {} +}; + +enum NavTerrain +{ + NAV_EMPTY = 0x00, + NAV_GROUND = 0x01, + NAV_MAGMA = 0x02, + NAV_SLIME = 0x04, + NAV_WATER = 0x08, + NAV_UNUSED1 = 0x10, + NAV_UNUSED2 = 0x20, + NAV_UNUSED3 = 0x40, + NAV_UNUSED4 = 0x80 + // we only have 8 bits +}; + #endif diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index b0ac0b710c1..fca0260eb87 100755 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -285,13 +285,13 @@ void MotionMaster::MovePoint(uint32 id, float x, float y, float z) if (_owner->GetTypeId() == TYPEID_PLAYER) { sLog->outStaticDebug("Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), id, x, y, z); - Mutate(new PointMovementGenerator(id, x, y, z), MOTION_SLOT_ACTIVE); + Mutate(new PointMovementGenerator(id, x, y, z, true), MOTION_SLOT_ACTIVE); } else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)", _owner->GetEntry(), _owner->GetGUIDLow(), id, x, y, z); - Mutate(new PointMovementGenerator(id, x, y, z), MOTION_SLOT_ACTIVE); + Mutate(new PointMovementGenerator(id, x, y, z, true), MOTION_SLOT_ACTIVE); } } diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index caf81a0a141..bad45f65178 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -33,51 +33,6 @@ template void ConfusedMovementGenerator::Initialize(T &unit) { - float const wander_distance = 4; - float x = unit.GetPositionX(); - float y = unit.GetPositionY(); - float z = unit.GetPositionZ(); - - Map const* map = unit.GetBaseMap(); - - i_nextMove = 1; - - bool is_water_ok, is_land_ok; - for (uint8 idx = 0; idx < MAX_CONF_WAYPOINTS + 1; ++idx) - { - float wanderX = x + (wander_distance * (float)rand_norm() - wander_distance/2); - float wanderY = y + (wander_distance * (float)rand_norm() - wander_distance/2); - - // prevent invalid coordinates generation - Trinity::NormalizeMapCoord(wanderX); - Trinity::NormalizeMapCoord(wanderY); - - if (unit.IsWithinLOS(wanderX, wanderY, z)) - { - bool is_water = map->IsInWater(wanderX, wanderY, z); - - if ((is_water && !is_water_ok) || (!is_water && !is_land_ok)) - { - //! Cannot use coordinates outside our InhabitType. Use the current or previous position. - wanderX = idx > 0 ? i_waypoints[idx-1][0] : x; - wanderY = idx > 0 ? i_waypoints[idx-1][1] : y; - } - } - else - { - //! Trying to access path outside line of sight. Skip this by using the current or previous position. - wanderX = idx > 0 ? i_waypoints[idx-1][0] : x; - wanderY = idx > 0 ? i_waypoints[idx-1][1] : y; - } - - unit.UpdateAllowedPositionZ(wanderX, wanderY, z); - - //! Positions are fine - apply them to this waypoint - i_waypoints[idx][0] = wanderX; - i_waypoints[idx][1] = wanderY; - i_waypoints[idx][2] = z; - } - unit.GetPosition(i_x, i_y, i_z); unit.StopMoving(); unit.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); @@ -115,10 +70,9 @@ bool ConfusedMovementGenerator::Update(T &unit, const uint32 &diff) // start moving unit.AddUnitState(UNIT_STATE_CONFUSED_MOVE); - ASSERT(i_nextMove <= MAX_CONF_WAYPOINTS); - float x = i_waypoints[i_nextMove][0]; - float y = i_waypoints[i_nextMove][1]; - float z = i_waypoints[i_nextMove][2]; + float x = i_x + 10.0f*((float)rand_norm() - 0.5f); + float y = i_y + 10.0f*((float)rand_norm() - 0.5f); + float z = i_z; unit.UpdateAllowedPositionZ(x, y, z); diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h index c390892d0d0..72ffd7b734b 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h @@ -36,7 +36,7 @@ class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMov MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; } private: TimeTracker i_nextMoveTime; - float i_waypoints[24+1][3]; + float i_x, i_y, i_z; }; #endif diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 1b32bb16b2c..9d99e0ef000 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -72,29 +72,29 @@ bool FleeingMovementGenerator::_getPoint(T &owner, float &x, float &y, float if (dist_from_caster > 0.2f) angle_to_caster = fright->GetAngle(&owner); else - angle_to_caster = frand(0, 2*M_PI_F); + angle_to_caster = frand(0, 2 * static_cast(M_PI)); } else { dist_from_caster = 0.0f; - angle_to_caster = frand(0, 2*M_PI_F); + angle_to_caster = frand(0, 2 * static_cast(M_PI)); } float dist, angle; if (dist_from_caster < MIN_QUIET_DISTANCE) { dist = frand(0.4f, 1.3f)*(MIN_QUIET_DISTANCE - dist_from_caster); - angle = angle_to_caster + frand(-M_PI_F/8, M_PI_F/8); + angle = angle_to_caster + frand(-static_cast(M_PI)/8, static_cast(M_PI)/8); } else if(dist_from_caster > MAX_QUIET_DISTANCE) { dist = frand(0.4f, 1.0f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); - angle = -angle_to_caster + frand(-M_PI_F/4, M_PI_F/4); + angle = -angle_to_caster + frand(-static_cast(M_PI)/4, static_cast(M_PI)/4); } else // we are inside quiet range { dist = frand(0.6f, 1.2f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); - angle = frand(0, 2*M_PI_F); + angle = frand(0, 2*static_cast(M_PI)); } float curr_x, curr_y, curr_z; diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index eaf48150a13..216721360c6 100755 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -34,7 +34,7 @@ void HomeMovementGenerator::Finalize(Creature& owner) { if (arrived) { - owner.ClearUnitState(UNIT_STAT_EVADE); + owner.ClearUnitState(UNIT_STATE_EVADE); owner.SetWalk(true); owner.LoadCreaturesAddon(true); owner.AI()->JustReachedHome(); @@ -71,14 +71,3 @@ bool HomeMovementGenerator::Update(Creature &owner, const uint32 /*tim arrived = owner.movespline->Finalized(); return !arrived; } - -void HomeMovementGenerator::Finalize(Creature& owner) -{ - if (arrived) - { - owner.ClearUnitState(UNIT_STATE_EVADE); - owner.SetWalk(true); - owner.LoadCreaturesAddon(true); - owner.AI()->JustReachedHome(); - } -} diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp index 686c57cb634..4894b5eb841 100644 --- a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp @@ -71,7 +71,7 @@ bool PathFinderMovementGenerator::calculate(float destX, float destY, float dest // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) - if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->HasUnitState(UNIT_STAT_IGNORE_PATHFINDING) || + if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || !HaveTile(start) || !HaveTile(dest)) { BuildShortcut(); @@ -186,7 +186,7 @@ void PathFinderMovementGenerator::BuildPolyPath(const Vector3 &startPos, const V { sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); BuildShortcut(); - m_type = (m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->canFly()) + m_type = (m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->CanFly()) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; return; } @@ -212,7 +212,7 @@ void PathFinderMovementGenerator::BuildPolyPath(const Vector3 &startPos, const V else { sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: flying case\n"); - if (owner->canFly()) + if (owner->CanFly()) buildShotrcut = true; } } @@ -532,7 +532,7 @@ NavTerrain PathFinderMovementGenerator::getNavTerrain(float x, float y, float z) LiquidData data; m_sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); - switch (data.type) + switch (data.type_flags) { case MAP_LIQUID_TYPE_WATER: case MAP_LIQUID_TYPE_OCEAN: diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index f6f8b1fbafd..7a8ad4584b0 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -59,8 +59,8 @@ bool PointMovementGenerator::Update(T &unit, const uint32 & /*diff*/) template void PointMovementGenerator::Finalize(T &unit) { - if (unit.HasUnitState(UNIT_STAT_CHARGING)) - unit.ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + if (unit.HasUnitState(UNIT_STATE_CHARGING)) + unit.ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); if (unit.movespline->Finalized()) MovementInform(unit); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 5c0e24be440..63e3ebfd378 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -68,7 +68,7 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T &owner) // allow pets following their master to cheat while generating paths bool forceDest = (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->isPet() - && owner.HasUnitState(UNIT_STAT_FOLLOW)); + && owner.HasUnitState(UNIT_STATE_FOLLOW)); i_path->calculate(x, y, z, forceDest); if (i_path->getPathType() & PATHFIND_NOPATH) return; @@ -153,7 +153,7 @@ bool TargetedMovementGeneratorMedium::Update(T &owner, const uint32 & time_ G3D::Vector3 dest = owner.movespline->FinalDestination(); bool targetMoved = false; - if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly()) + if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->CanFly()) targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist); else targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 28893c44cfb..d855dfa1875 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -39,7 +39,7 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, { protected: TargetedMovementGeneratorMedium(Unit &target, float offset, float angle) : - TargetedMovementGeneratorBase(target), i_recheckDistance(0),, i_path(NULL), + TargetedMovementGeneratorBase(target), i_recheckDistance(0), i_path(NULL), i_offset(offset), i_angle(angle), i_recalculateTravel(false), i_targetReached(false) { diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h index d4b19b21634..4ec8d2c78ac 100644 --- a/src/server/game/Movement/Spline/MoveSpline.h +++ b/src/server/game/Movement/Spline/MoveSpline.h @@ -77,7 +77,6 @@ namespace Movement UpdateResult _updateState(int32& ms_time_diff); int32 next_timestamp() const { return spline.length(point_Idx+1);} int32 segment_time_elapsed() const { return next_timestamp()-time_passed;} - int32 Duration() const { return spline.length();} int32 timeElapsed() const { return Duration() - time_passed;} int32 timePassed() const { return time_passed;} @@ -88,7 +87,7 @@ namespace Movement void _Interrupt() { splineflags.done = true;} public: - + int32 Duration() const { return spline.length();} void Initialize(const MoveSplineInitArgs&); bool Initialized() const { return !spline.empty();} -- cgit v1.2.3 From 9ac2255fbcee4049ed4067fc18c8cabccef1047e Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 17:10:54 +0200 Subject: fix all build errors, only 1 linking error. --- src/server/shared/Memory.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/server/shared/Memory.h (limited to 'src') diff --git a/src/server/shared/Memory.h b/src/server/shared/Memory.h new file mode 100644 index 00000000000..ac697f7a1af --- /dev/null +++ b/src/server/shared/Memory.h @@ -0,0 +1,17 @@ + + +#ifndef _MEMORY_H +#define _MEMORY_H + +// memory management +inline void* dtCustomAlloc(int size, dtAllocHint /*hint*/) +{ + return (void*)new unsigned char[size]; +} + +inline void dtCustomFree(void* ptr) +{ + delete [] (unsigned char*)ptr; +} + +#endif \ No newline at end of file -- cgit v1.2.3 From d06c09271295f8199fa45ae9b7d8e2eb600bbe26 Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 17:17:31 +0200 Subject: fix linker error. --- src/tools/mmaps_generator/MapBuilder.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 3ca158f0127..2987e6596dd 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -28,6 +28,11 @@ // These make the linker happy. LoginDatabaseWorkerPool LoginDatabase; +uint32 GetLiquidFlags(uint32 liquidType) +{ + return 0; +} + #include "DisableMgr.h" namespace DisableMgr { -- cgit v1.2.3 From 8368112f453cc20672943dac533da1ee8ff933a3 Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 18:05:35 +0200 Subject: Try to check existance of mmaps folder. --- src/server/collision/Management/MMapManager.cpp | 9 +++------ src/server/collision/Management/MMapManager.h | 2 +- src/server/game/Maps/Map.cpp | 2 +- src/server/game/World/World.cpp | 4 +++- 4 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp index aac5647a6de..449abcb967d 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/server/collision/Management/MMapManager.cpp @@ -82,10 +82,10 @@ namespace MMAP return uint32(x << 16 | y); } - bool MMapManager::loadMap(uint32 mapId, int32 x, int32 y) + bool MMapManager::loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y) { // make sure the mmap is loaded and ready to load tiles - if(!loadMapData(mapId)) + if (!loadMapData(mapId)) return false; // get this mmap data @@ -95,10 +95,7 @@ namespace MMAP // check if we already have this tile loaded uint32 packedGridPos = packTileID(x, y); if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end()) - { - //sLog->outError("MMAP:loadMap: Asked to load already loaded navmesh tile. %03u%02i%02i.mmtile", mapId, y, x); return false; - } // load this tile :: mmaps/MMMXXYY.mmtile uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1; @@ -136,7 +133,7 @@ namespace MMAP ASSERT(data); size_t result = fread(data, fileHeader.size, 1, file); - if(!result) + if (!result) { sLog->outError("MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, y, x); fclose(file); diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h index 8af452032d1..23b7d5fc6f8 100644 --- a/src/server/collision/Management/MMapManager.h +++ b/src/server/collision/Management/MMapManager.h @@ -61,7 +61,7 @@ namespace MMAP MMapManager() : loadedTiles(0) {} ~MMapManager(); - bool loadMap(uint32 mapId, int32 x, int32 y); + bool loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y); bool unloadMap(uint32 mapId, int32 x, int32 y); bool unloadMap(uint32 mapId); bool unloadMapInstance(uint32 mapId, uint32 instanceId); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index c3732769d04..a9fc3f3350f 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -124,7 +124,7 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy) void Map::LoadMMap(int gx, int gy) { // DONT CHANGE "gy" and "gx" - Its necessary ! - int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap(GetId(), gy, gx); + int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gy, gx); switch (mmapLoadResult) { case MMAP::MMAP_LOAD_RESULT_OK: diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 90d4ce3604a..a5ec6be10d4 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1123,8 +1123,10 @@ void World::LoadConfigSettings(bool reload) sLog->outString("Using DataDir %s", m_dataPath.c_str()); } - m_bool_configs[CONFIG_VMAP_INDOOR_CHECK] = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", 0); m_bool_configs[CONFIG_ENABLE_MMAPS] = ConfigMgr::GetBoolDefault("mmap.enablePathFinding", true); + sLog->outString("WORLD: MMap data directory is: %smmaps", m_dataPath.c_str()); + + m_bool_configs[CONFIG_VMAP_INDOOR_CHECK] = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", 0); bool enableIndoor = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", true); bool enableLOS = ConfigMgr::GetBoolDefault("vmap.enableLOS", true); bool enableHeight = ConfigMgr::GetBoolDefault("vmap.enableHeight", true); -- cgit v1.2.3 From abc33c7b5d830c96b17ff2a0473702f8a5b31b87 Mon Sep 17 00:00:00 2001 From: Venugh Date: Mon, 9 Apr 2012 18:36:45 +0200 Subject: Core/Movement: Correct MotionMaster and fix a crash. --- src/server/game/Movement/MotionMaster.cpp | 12 ++++++------ src/server/game/Movement/MotionMaster.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index fca0260eb87..7e8020b7863 100755 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -280,18 +280,18 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlo } } -void MotionMaster::MovePoint(uint32 id, float x, float y, float z) +void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool generatePath) { if (_owner->GetTypeId() == TYPEID_PLAYER) { sLog->outStaticDebug("Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), id, x, y, z); - Mutate(new PointMovementGenerator(id, x, y, z, true), MOTION_SLOT_ACTIVE); + Mutate(new PointMovementGenerator(id, x, y, z, generatePath), MOTION_SLOT_ACTIVE); } else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)", _owner->GetEntry(), _owner->GetGUIDLow(), id, x, y, z); - Mutate(new PointMovementGenerator(id, x, y, z, true), MOTION_SLOT_ACTIVE); + Mutate(new PointMovementGenerator(id, x, y, z, generatePath), MOTION_SLOT_ACTIVE); } } @@ -396,7 +396,7 @@ void MotionMaster::MoveFall(uint32 id/*=0*/) Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED); } -void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id) +void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id, bool generatePath) { if (Impl[MOTION_SLOT_CONTROLLED] && Impl[MOTION_SLOT_CONTROLLED]->GetMovementGeneratorType() != DISTRACT_MOTION_TYPE) return; @@ -404,13 +404,13 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id) if (_owner->GetTypeId() == TYPEID_PLAYER) { sLog->outStaticDebug("Player (GUID: %u) charge point (X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), x, y, z); - Mutate(new PointMovementGenerator(id, x, y, z, speed), MOTION_SLOT_CONTROLLED); + Mutate(new PointMovementGenerator(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED); } else { sLog->outStaticDebug("Creature (Entry: %u GUID: %u) charge point (X: %f Y: %f Z: %f)", _owner->GetEntry(), _owner->GetGUIDLow(), x, y, z); - Mutate(new PointMovementGenerator(id, x, y, z, speed), MOTION_SLOT_CONTROLLED); + Mutate(new PointMovementGenerator(id, x, y, z, generatePath, speed), MOTION_SLOT_CONTROLLED); } } diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index d6144bfcc3a..a96a3e6391a 100755 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -154,13 +154,13 @@ class MotionMaster //: private std::stack void MoveFleeing(Unit* enemy, uint32 time = 0); void MovePoint(uint32 id, const Position &pos) { MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ); } - void MovePoint(uint32 id, float x, float y, float z); + void MovePoint(uint32 id, float x, float y, float z, bool generatePath = false); // These two movement types should only be used with creatures having landing/takeoff animations void MoveLand(uint32 id, Position const& pos, float speed); void MoveTakeoff(uint32 id, Position const& pos, float speed); - void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE); + void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, bool generatePath = false); void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ); void MoveJumpTo(float angle, float speedXY, float speedZ); void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = 0); -- cgit v1.2.3 From 5061fa626a72fa7c2632a4b2cef318633c56d85b Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 22 Aug 2012 17:39:25 -0500 Subject: Core/Mmaps: * Unload instanced mmaps before unloading the base map * Load only mmaps for base map on map creation * Extractor: Somewhat speed improvement --- src/server/game/Maps/Map.cpp | 9 +- src/server/game/Movement/MotionMaster.h | 4 +- src/tools/mmaps_generator/IntermediateValues.cpp | 2 +- src/tools/mmaps_generator/MapBuilder.cpp | 105 +++++++++++++++-------- src/tools/mmaps_generator/MapBuilder.h | 1 + src/tools/mmaps_generator/PathGenerator.cpp | 17 +++- src/tools/mmaps_generator/TerrainBuilder.cpp | 23 +++-- 7 files changed, 106 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index b38f89eab8f..5e3699146f2 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -71,8 +71,8 @@ Map::~Map() if (!m_scriptSchedule.empty()) sScriptMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size()); - MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId()); MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId); + MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId()); } bool Map::ExistMap(uint32 mapid, int gx, int gy) @@ -206,9 +206,12 @@ void Map::LoadMap(int gx, int gy, bool reload) void Map::LoadMapAndVMap(int gx, int gy) { LoadMap(gx, gy); - LoadMMap(gx, gy); + // Only load the data for the base map if (i_InstanceId == 0) - LoadVMap(gx, gy); // Only load the data for the base map + { + LoadVMap(gx, gy); + LoadMMap(gx, gy); + } } void Map::InitStateMachine() diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index f10c6569cad..918896a5a81 100755 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -154,13 +154,13 @@ class MotionMaster //: private std::stack void MoveFleeing(Unit* enemy, uint32 time = 0); void MovePoint(uint32 id, const Position &pos) { MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ); } - void MovePoint(uint32 id, float x, float y, float z, bool generatePath = false); + void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true); // These two movement types should only be used with creatures having landing/takeoff animations void MoveLand(uint32 id, Position const& pos); void MoveTakeoff(uint32 id, Position const& pos); - void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, bool generatePath = false); + void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, bool generatePath = true); void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ); void MoveJumpTo(float angle, float speedXY, float speedZ); void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = 0); diff --git a/src/tools/mmaps_generator/IntermediateValues.cpp b/src/tools/mmaps_generator/IntermediateValues.cpp index 9eefb1e65f0..b473d6472a0 100644 --- a/src/tools/mmaps_generator/IntermediateValues.cpp +++ b/src/tools/mmaps_generator/IntermediateValues.cpp @@ -202,7 +202,7 @@ namespace MMAP void IntermediateValues::generateObjFile(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) { char objFileName[255]; - sprintf(objFileName, "meshes/map%03u.obj", mapID); + sprintf(objFileName, "meshes/map%03u%02u%02u.obj", mapID, tileY, tileX); FILE* objFile = fopen(objFileName, "wb"); if (!objFile) diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 2987e6596dd..e47b2e5b44f 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -24,6 +24,7 @@ #include "LoginDatabase.h" #include "DetourNavMeshBuilder.h" +#include "DetourNavMesh.h" #include "DetourCommon.h" // These make the linker happy. @@ -206,6 +207,56 @@ namespace MMAP minX = 32 - bmax[0] / GRID_SIZE; minY = 32 - bmax[2] / GRID_SIZE; } + + void MapBuilder::buildMeshFromFile(char* name) + { + FILE* file = fopen(name, "rb"); + if (!file) + return; + + printf("Building mesh from file\n"); + int tileX, tileY, mapId; + fread(&mapId, sizeof(int), 1, file); + fread(&tileX, sizeof(int), 1, file); + fread(&tileY, sizeof(int), 1, file); + + dtNavMesh* navMesh = NULL; + buildNavMesh(mapId, navMesh); + if (!navMesh) + { + printf("Failed creating navmesh! \n"); + fclose(file); + return; + } + + + int verticesCount, indicesCount; + fread(&verticesCount, sizeof(int), 1, file); + fread(&indicesCount, sizeof(int), 1, file); + + float* verts = new float[verticesCount]; + int* inds = new int[indicesCount]; + + fread(verts, sizeof(float), verticesCount, file); + fread(inds, sizeof(int), indicesCount, file); + + MeshData data; + + for (int i = 0; i < verticesCount; ++i) + data.solidVerts.append(verts[i]); + + for (int i = 0; i < indicesCount; ++i) + data.solidTris.append(inds[i]); + + TerrainBuilder::cleanVertices(data.solidVerts, data.solidTris); + // get bounds of current tile + float bmin[3], bmax[3]; + getTileBounds(tileX, tileY, data.solidVerts.getCArray(), data.solidVerts.size() / 3, bmin, bmax); + + // build navmesh tile + buildMoveMapTile(mapId, tileX, tileY, data, bmin, bmax, navMesh); + fclose(file); + } /**************************************************************************/ void MapBuilder::buildSingleTile(uint32 mapID, uint32 tileX, uint32 tileY) @@ -451,17 +502,32 @@ namespace MMAP Tile* tiles = new Tile[TILES_PER_MAP * TILES_PER_MAP]; // Initialize per tile config. - rcConfig tileCfg; - memcpy(&tileCfg, &config, sizeof(rcConfig)); + rcConfig tileCfg = config; tileCfg.width = config.tileSize + config.borderSize*2; tileCfg.height = config.tileSize + config.borderSize*2; + // merge per tile poly and detail meshes + rcPolyMesh** pmmerge = new rcPolyMesh*[TILES_PER_MAP * TILES_PER_MAP]; + if (!pmmerge) + { + printf("%s alloc pmmerge FIALED! \r", tileString); + return; + } + + rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[TILES_PER_MAP * TILES_PER_MAP]; + if (!dmmerge) + { + printf("%s alloc dmmerge FIALED! \r", tileString); + return; + } + + int nmerge = 0; // build all tiles for (int y = 0; y < TILES_PER_MAP; ++y) { for (int x = 0; x < TILES_PER_MAP; ++x) { - Tile& tile = tiles[x + y*TILES_PER_MAP]; + Tile& tile = tiles[x + y * TILES_PER_MAP]; // Calculate the per tile bounding box. tileCfg.bmin[0] = config.bmin[0] + (x*config.tileSize - config.borderSize)*config.cs; @@ -469,12 +535,6 @@ namespace MMAP tileCfg.bmax[0] = config.bmin[0] + ((x+1)*config.tileSize + config.borderSize)*config.cs; tileCfg.bmax[2] = config.bmin[2] + ((y+1)*config.tileSize + config.borderSize)*config.cs; - float tbmin[2], tbmax[2]; - tbmin[0] = tileCfg.bmin[0]; - tbmin[1] = tileCfg.bmin[2]; - tbmax[0] = tileCfg.bmax[0]; - tbmax[1] = tileCfg.bmax[2]; - // build heightfield tile.solid = rcAllocHeightfield(); if (!tile.solid || !rcCreateHeightfield(m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch)) @@ -488,7 +548,7 @@ namespace MMAP memset(triFlags, NAV_GROUND, tTriCount*sizeof(unsigned char)); rcClearUnwalkableTriangles(m_rcContext, tileCfg.walkableSlopeAngle, tVerts, tVertCount, tTris, tTriCount, triFlags); rcRasterizeTriangles(m_rcContext, tVerts, tVertCount, tTris, triFlags, tTriCount, *tile.solid, config.walkableClimb); - delete [] triFlags; + delete[] triFlags; rcFilterLowHangingWalkableObstacles(m_rcContext, config.walkableClimb, *tile.solid); rcFilterLedgeSpans(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid); @@ -554,30 +614,7 @@ namespace MMAP tile.chf = NULL; rcFreeContourSet(tile.cset); tile.cset = NULL; - } - } - - // merge per tile poly and detail meshes - rcPolyMesh** pmmerge = new rcPolyMesh*[TILES_PER_MAP * TILES_PER_MAP]; - if (!pmmerge) - { - printf("%s alloc pmmerge FIALED! \r", tileString); - return; - } - - rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[TILES_PER_MAP * TILES_PER_MAP]; - if (!dmmerge) - { - printf("%s alloc dmmerge FIALED! \r", tileString); - return; - } - - int nmerge = 0; - for (int y = 0; y < TILES_PER_MAP; ++y) - { - for (int x = 0; x < TILES_PER_MAP; ++x) - { - Tile& tile = tiles[x + y*TILES_PER_MAP]; + if (tile.pmesh) { pmmerge[nmerge] = tile.pmesh; diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index d0f33ce9a79..20789bf9bff 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -74,6 +74,7 @@ namespace MMAP // builds all mmap tiles for the specified map id (ignores skip settings) void buildMap(uint32 mapID); + void buildMeshFromFile(char* name); // builds an mmap tile for the specified map and its mesh void buildSingleTile(uint32 mapID, uint32 tileX, uint32 tileY); diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 2eb2c6545c4..7d9f59ed138 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -70,7 +70,8 @@ bool handleArgs(int argc, char** argv, bool &debugOutput, bool &silent, bool &bigBaseUnit, - char* &offMeshInputPath) + char* &offMeshInputPath, + char* &file) { char* param = NULL; for (int i = 1; i < argc; ++i) @@ -87,6 +88,13 @@ bool handleArgs(int argc, char** argv, else printf("invalid option for '--maxAngle', using default\n"); } + else if (strcmp(argv[i], "--file") == 0) + { + param = argv[++i]; + if (!param) + return false; + file = param; + } else if (strcmp(argv[i], "--tile") == 0) { param = argv[++i]; @@ -235,11 +243,12 @@ int main(int argc, char** argv) silent = false, bigBaseUnit = false; char* offMeshInputPath = NULL; + char* file = NULL; bool validParam = handleArgs(argc, argv, mapnum, tileX, tileY, maxAngle, skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, - debugOutput, silent, bigBaseUnit, offMeshInputPath); + debugOutput, silent, bigBaseUnit, offMeshInputPath, file); if (!validParam) return silent ? -1 : finish("You have specified invalid parameters", -1); @@ -262,7 +271,9 @@ int main(int argc, char** argv) MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, debugOutput, bigBaseUnit, offMeshInputPath); - if (tileX > -1 && tileY > -1 && mapnum >= 0) + if (file) + builder.buildMeshFromFile(file); + else if (tileX > -1 && tileY > -1 && mapnum >= 0) builder.buildSingleTile(mapnum, tileX, tileY); else if (mapnum >= 0) builder.buildMap(uint32(mapnum)); diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index c696f6017a5..e16dd16707b 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -767,25 +767,24 @@ namespace MMAP int* t = tris.getCArray(); float* v = verts.getCArray(); + G3D::Array cleanVerts; + int index, count = 0; // collect all the vertex indices from triangle for (int i = 0; i < tris.size(); ++i) { if (vertMap.find(t[i]) != vertMap.end()) continue; - - vertMap.insert(std::pair(t[i], 0)); - } - - // collect the vertices - G3D::Array cleanVerts; - int index, count = 0; - for (map::iterator it = vertMap.begin(); it != vertMap.end(); ++it) - { - index = (*it).first; - (*it).second = count; - cleanVerts.append(v[index*3], v[index*3+1], v[index*3+2]); + std::pair val; + val.first = t[i]; + + index = val.first; + val.second = count; + + vertMap.insert(val); + cleanVerts.append(v[index * 3], v[index * 3 + 1], v[index * 3 + 2]); count++; } + verts.fastClear(); verts.append(cleanVerts); cleanVerts.clear(); -- cgit v1.2.3 From 4273690478ccdc74528fa6ea6698cfa2062fa2fc Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 22 Aug 2012 17:42:05 -0500 Subject: Core/Mmaps: Allow disabling pathfinding for specific maps in the config --- src/server/game/World/World.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 928a8184d5d..0d55d7a52e8 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1126,6 +1126,7 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_ENABLE_MMAPS] = ConfigMgr::GetBoolDefault("mmap.enablePathFinding", true); sLog->outString("WORLD: MMap data directory is: %smmaps", m_dataPath.c_str()); + MMap::MMapFactory::preventPathfindingOnMaps(ConfigMgr::GetStringDefault("mmap.ignoreMapIds", "").c_str()); m_bool_configs[CONFIG_VMAP_INDOOR_CHECK] = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", 0); bool enableIndoor = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", true); -- cgit v1.2.3 From c3f75cdf1d8c686a3061ef6c8b63a92bae5954c8 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 22 Aug 2012 17:47:58 -0500 Subject: Core/MMaps: Do not allow creatures that cant fly to take off the land, even when building shorcut paths. --- src/server/game/Entities/Unit/Unit.cpp | 2 +- .../MovementGenerators/PathFinderMovementGenerator.cpp | 10 ++++++++++ .../Movement/MovementGenerators/PathFinderMovementGenerator.h | 2 ++ .../Movement/MovementGenerators/TargetedMovementGenerator.cpp | 9 ++++----- src/server/game/Movement/Spline/MoveSplineInit.h | 6 +++--- 5 files changed, 20 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 2ba3b4e8c06..183eddfcae4 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -373,7 +373,7 @@ bool Unit::haveOffhandWeapon() const void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath, bool forceDestination) { Movement::MoveSplineInit init(*this); - init.MoveTo(x,y,z); + init.MoveTo(x, y, z, generatePath, forceDestination); init.SetVelocity(speed); init.Launch(); } diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp index 4894b5eb841..3172deb210e 100644 --- a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp @@ -443,6 +443,8 @@ void PathFinderMovementGenerator::BuildPointPath(const float *startPoint, const for (uint32 i = 0; i < pointCount; ++i) m_pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); + NormalizePath(); + // first point is always our current location - we need the next one setActualEndPosition(m_pathPoints[pointCount-1]); @@ -469,6 +471,12 @@ void PathFinderMovementGenerator::BuildPointPath(const float *startPoint, const sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); } +void PathFinderMovementGenerator::NormalizePath() +{ + for (uint32 i = 0; i < m_pathPoints.size(); ++i) + m_sourceUnit->UpdateAllowedPositionZ(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z); +} + void PathFinderMovementGenerator::BuildShortcut() { sLog->outDebug(LOG_FILTER_MAPS, "++ BuildShortcut :: making shortcut\n"); @@ -482,6 +490,8 @@ void PathFinderMovementGenerator::BuildShortcut() m_pathPoints[0] = getStartPosition(); m_pathPoints[1] = getActualEndPosition(); + NormalizePath(); + m_type = PATHFIND_SHORTCUT; } diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h index f4edd1a1789..5dd2ad82a0a 100644 --- a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h @@ -98,6 +98,8 @@ class PathFinderMovementGenerator void setStartPosition(Vector3 point) { m_startPosition = point; } void setEndPosition(Vector3 point) { m_actualEndPosition = point; m_endPosition = point; } void setActualEndPosition(Vector3 point) { m_actualEndPosition = point; } + + void NormalizePath(); void clear() { diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 1680bfeb1d4..766fe0b8032 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -79,11 +79,7 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T &owner) owner.AddUnitState(UNIT_STATE_CHASE); Movement::MoveSplineInit init(owner); - if (!i_target->IsInWater()) - init.MovebyPath(i_path->getPath()); - else - init.MoveTo(i_target->GetPositionX(), i_target->GetPositionY(), i_target->GetPositionZ(), false, false); - + init.MovebyPath(i_path->getPath()); init.SetWalk(((D*)this)->EnableWalking()); init.Launch(); } @@ -128,6 +124,9 @@ bool TargetedMovementGeneratorMedium::Update(T &owner, const uint32 & time_ D::_clearUnitStateMove(owner); return true; } + + if (owner.GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor((const Creature*)&owner)) + return false; // prevent movement while casting spells with cast time or channel time if (owner.HasUnitState(UNIT_STATE_CASTING)) diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 4efde66fcd5..740914c59db 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -84,10 +84,10 @@ namespace Movement */ void MovebyPath(const PointsArray& path, int32 pointId = 0); - /* Initializes simple A to B mition, A is current unit's position, B is destination + /* Initializes simple A to B motion, A is current unit's position, B is destination */ - void MoveTo(const Vector3& destination, bool generatePath = false, bool forceDestination = false); - void MoveTo(float x, float y, float z, bool generatePath = false, bool forceDestination = false); + void MoveTo(const Vector3& destination, bool generatePath = true, bool forceDestination = false); + void MoveTo(float x, float y, float z, bool generatePath = true, bool forceDestination = false); /* Sets Id of fisrt point of the path. When N-th path point will be done ILisener will notify that pointId + N done * Needed for waypoint movement where path splitten into parts -- cgit v1.2.3 From 4c765aad3ddb0e8a890ee163cf3162d14c396d7e Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 22 Aug 2012 18:00:58 -0500 Subject: Core/Maps: Reduce the output map file size in the maps extractor for maps that do not have any hole information Core/Mmaps: Fixed swimming creatures stuck in water. (Thanks Vlad and @Chevron ) Note: Re-extract maps --- src/server/game/Maps/Map.cpp | 33 ++++++++-------------- .../TargetedMovementGenerator.cpp | 3 -- src/tools/map_extractor/System.cpp | 19 +++++++++---- src/tools/mmaps_generator/TerrainBuilder.cpp | 11 +++++--- 4 files changed, 33 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 5e3699146f2..80668d23ed8 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -42,7 +42,7 @@ union u_map_magic }; u_map_magic MapMagic = { {'M','A','P','S'} }; -u_map_magic MapVersionMagic = { {'v','1','.','2'} }; +u_map_magic MapVersionMagic = { {'v','1','.','3'} }; u_map_magic MapAreaMagic = { {'A','R','E','A'} }; u_map_magic MapHeightMagic = { {'M','H','G','T'} }; u_map_magic MapLiquidMagic = { {'M','L','I','Q'} }; @@ -124,19 +124,12 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy) void Map::LoadMMap(int gx, int gy) { // DONT CHANGE "gy" and "gx" - Its necessary ! - int mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gy, gx); - switch (mmapLoadResult) - { - case MMAP::MMAP_LOAD_RESULT_OK: - sLog->outDetail("MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); - break; - case MMAP::MMAP_LOAD_RESULT_ERROR: - sLog->outDetail("Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); - break; - case MMAP::MMAP_LOAD_RESULT_IGNORED: - sLog->outStaticDebug("Ignored MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); - break; - } + bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gy, gx); + + if (result) + sLog->outDetail("MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); + else + sLog->outDetail("Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); } void Map::LoadVMap(int gx, int gy) @@ -187,18 +180,16 @@ void Map::LoadMap(int gx, int gy, bool reload) } // map file name - char *tmp=NULL; - int len = sWorld->GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1; + char* tmp = NULL; + int len = sWorld->GetDataPath().length() + strlen("maps/%03u%02u%02u.map") + 1; tmp = new char[len]; - snprintf(tmp, len, (char *)(sWorld->GetDataPath()+"maps/%03u%02u%02u.map").c_str(), GetId(), gx, gy); + snprintf(tmp, len, (char *)(sWorld->GetDataPath() + "maps/%03u%02u%02u.map").c_str(), GetId(), gx, gy); sLog->outInfo(LOG_FILTER_MAPS, "Loading map %s", tmp); // loading data GridMaps[gx][gy] = new GridMap(); if (!GridMaps[gx][gy]->loadData(tmp)) - { sLog->outError(LOG_FILTER_MAPS, "Error loading map file: \n %s\n", tmp); - } - delete [] tmp; + delete[] tmp; sScriptMgr->OnLoadGridMap(this, GridMaps[gx][gy], gx, gy); } @@ -1094,7 +1085,7 @@ GridMap::~GridMap() unloadData(); } -bool GridMap::loadData(char *filename) +bool GridMap::loadData(char* filename) { // Unload old data if exist unloadData(); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 766fe0b8032..1fc2ab5a6cb 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -125,9 +125,6 @@ bool TargetedMovementGeneratorMedium::Update(T &owner, const uint32 & time_ return true; } - if (owner.GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor((const Creature*)&owner)) - return false; - // prevent movement while casting spells with cast time or channel time if (owner.HasUnitState(UNIT_STATE_CASTING)) { diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index e34bc4221e7..ad9a663ac27 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -276,7 +276,7 @@ void ReadLiquidTypeTableDBC() // Map file format data static char const* MAP_MAGIC = "MAPS"; -static char const* MAP_VERSION_MAGIC = "v1.2"; +static char const* MAP_VERSION_MAGIC = "v1.3"; static char const* MAP_AREA_MAGIC = "AREA"; static char const* MAP_HEIGHT_MAGIC = "MHGT"; static char const* MAP_LIQUID_MAGIC = "MLIQ"; @@ -836,8 +836,8 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, else map.holesOffset = map.heightMapOffset + map.heightMapSize; - map.holesSize = sizeof(holes); memset(holes, 0, map.holesSize); + bool hasHoles = false; for (int i = 0; i < ADT_CELLS_PER_GRID; ++i) { @@ -847,12 +847,19 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, if (!cell) continue; holes[i][j] = cell->holes; + if (!hasHoles && cell->holes != 0) + hasHoles = true; } } + + if (hasHoles) + map.holesSize = sizeof(holes); + else + map.holesSize = 0; // Ok all data prepared - store it - FILE *output=fopen(filename2, "wb"); - if(!output) + FILE* output = fopen(filename2, "wb"); + if (!output) { printf("Can't create the output file '%s'\n", filename2); return false; @@ -899,8 +906,10 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, fwrite(&liquid_height[y+liquidHeader.offsetY][liquidHeader.offsetX], sizeof(float), liquidHeader.width, output); } } + // store hole data - fwrite(holes, map.holesSize, 1, output); + if (hasHoles) + fwrite(holes, map.holesSize, 1, output); fclose(output); diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index e16dd16707b..7ee4dc7f46c 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -159,9 +159,12 @@ namespace MMAP } // hole data - memset(holes, 0, fheader.holesSize); - fseek(mapFile, fheader.holesOffset, SEEK_SET); - fread(holes, fheader.holesSize, 1, mapFile); + if (fheader.holesSize != 0) + { + memset(holes, 0, fheader.holesSize); + fseek(mapFile, fheader.holesOffset, SEEK_SET); + fread(holes, fheader.holesSize, 1, mapFile); + } int count = meshData.solidVerts.size() / 3; float xoffset = (float(tileX)-32)*GRID_SIZE; @@ -379,7 +382,7 @@ namespace MMAP } // if there is a hole here, don't use the terrain - if (useTerrain) + if (useTerrain && fheader.holesSize != 0) useTerrain = !isHole(i, holes); // we use only one terrain kind per quad - pick higher one -- cgit v1.2.3 From 45fc80736dbb733628537612b478d9a5415aeb9e Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 22 Aug 2012 18:03:01 -0500 Subject: Core/Mmaps: Allow swimming creatures to move underwater when there is a hole in the mesh --- .../PathFinderMovementGenerator.cpp | 24 +++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp index 3172deb210e..82dcbc07648 100644 --- a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp @@ -180,14 +180,32 @@ void PathFinderMovementGenerator::BuildPolyPath(const Vector3 &startPos, const V dtPolyRef endPoly = getPolyByLocation(endPoint, &distToEndPoly); // we have a hole in our mesh - // make shortcut path and mark it as NOPATH ( with flying exception ) + // make shortcut path and mark it as NOPATH ( with flying and swimming exception ) // its up to caller how he will use this info if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF) { sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); BuildShortcut(); - m_type = (m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->CanFly()) - ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; + bool path = m_sourceUnit->GetTypeId() == TYPEID_UNIT && m_sourceUnit->ToCreature()->CanFly(); + + bool waterPath = m_sourceUnit->GetTypeId() == TYPEID_UNIT && m_sourceUnit->ToCreature()->canSwim(); + if (waterPath) + { + // Check both start and end points, if they're both in water, then we can *safely* let the creature move + for (int i = 0; i < m_pathPoints.size(); ++i) + { + LiquidData data; + m_sourceUnit->GetBaseMap()->getLiquidStatus(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z, MAP_ALL_LIQUIDS, &data); + // One of the points is not in the water, cancel movement. + if (data.type_flags == MAP_LIQUID_TYPE_NO_WATER) + { + waterPath = false; + break; + } + } + } + + m_type = (path || waterPath) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; return; } -- cgit v1.2.3 From 937518181f2513e4ef43700d5b856349ebb7c7e6 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 24 Aug 2012 11:38:39 -0500 Subject: Core/Mmaps: Fixed build after last merge --- src/server/collision/Management/MMapManager.cpp | 30 +++++++++++----------- src/server/game/Maps/Map.cpp | 6 ++--- .../PathFinderMovementGenerator.cpp | 6 ++--- src/server/game/Movement/Spline/MoveSplineInit.cpp | 21 ++++++++++----- src/server/game/Movement/Spline/MoveSplineInit.h | 18 +------------ src/server/game/World/World.cpp | 4 +-- src/tools/mmaps_generator/TerrainBuilder.h | 2 +- 7 files changed, 40 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp index 449abcb967d..0222f1a5995 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/server/collision/Management/MMapManager.cpp @@ -60,14 +60,14 @@ namespace MMAP if (DT_SUCCESS != mesh->init(¶ms)) { dtFreeNavMesh(mesh); - sLog->outError("MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName); + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName); delete [] fileName; return false; } delete [] fileName; - sLog->outDetail("MMAP:loadMapData: Loaded %03i.mmap", mapId); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:loadMapData: Loaded %03i.mmap", mapId); // store inside our map list MMapData* mmap_data = new MMapData(mesh); @@ -118,13 +118,13 @@ namespace MMAP if (fileHeader.mmapMagic != MMAP_MAGIC) { - sLog->outError("MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, y, x); + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, y, x); return false; } if (fileHeader.mmapVersion != MMAP_VERSION) { - sLog->outError("MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION); return false; } @@ -135,7 +135,7 @@ namespace MMAP size_t result = fread(data, fileHeader.size, 1, file); if (!result) { - sLog->outError("MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, y, x); + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, y, x); fclose(file); return false; } @@ -150,12 +150,12 @@ namespace MMAP { mmap->mmapLoadedTiles.insert(std::pair(packedGridPos, tileRef)); ++loadedTiles; - sLog->outDetail("MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, y, x, mapId, header->x, header->y); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, y, x, mapId, header->x, header->y); return true; } else { - sLog->outError("MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, y, x); + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, y, x); dtFree(data); return false; } @@ -192,14 +192,14 @@ namespace MMAP // this is technically a memory leak // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used // we cannot recover from this error - assert out - sLog->outError("MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, y, x); + sLog->outError(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, y, x); ASSERT(false); } else { mmap->mmapLoadedTiles.erase(packedGridPos); --loadedTiles; - sLog->outDetail("MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, y, x, mapId); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, y, x, mapId); return true; } @@ -222,17 +222,17 @@ namespace MMAP uint32 x = (i->first >> 16); uint32 y = (i->first & 0x0000FFFF); if (DT_SUCCESS != mmap->navMesh->removeTile(i->second, NULL, NULL)) - sLog->outError("MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, y, x); + sLog->outError(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, y, x); else { --loadedTiles; - sLog->outDetail("MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, y, x, mapId); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, y, x, mapId); } } delete mmap; loadedMMaps.erase(mapId); - sLog->outDetail("MMAP:unloadMap: Unloaded %03i.mmap", mapId); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded %03i.mmap", mapId); return true; } @@ -258,7 +258,7 @@ namespace MMAP dtFreeNavMeshQuery(query); mmap->navMeshQueries.erase(instanceId); - sLog->outDetail("MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId); return true; } @@ -285,11 +285,11 @@ namespace MMAP if (DT_SUCCESS != query->init(mmap->navMesh, 1024)) { dtFreeNavMeshQuery(query); - sLog->outError("MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + sLog->outError(LOG_FILTER_MAPS, "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); return NULL; } - sLog->outDetail("MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); mmap->navMeshQueries.insert(std::pair(instanceId, query)); } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 80668d23ed8..c960d8123fe 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -126,10 +126,10 @@ void Map::LoadMMap(int gx, int gy) // DONT CHANGE "gy" and "gx" - Its necessary ! bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gy, gx); - if (result) - sLog->outDetail("MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); + if (mmapLoadResult) + sLog->outInfo(LOG_FILTER_MAPS, "MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); else - sLog->outDetail("Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); + sLog->outInfo(LOG_FILTER_MAPS, "Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); } void Map::LoadVMap(int gx, int gy) diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp index 82dcbc07648..8988aa599da 100644 --- a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp @@ -88,7 +88,7 @@ bool PathFinderMovementGenerator::calculate(float destX, float destY, float dest { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride - sLog->outStaticDebug("++ PathFinderMovementGenerator::calculate:: precalculated path\n"); + sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::calculate:: precalculated path\n"); m_pathPoints.erase(m_pathPoints.begin()); return false; @@ -367,7 +367,7 @@ void PathFinderMovementGenerator::BuildPolyPath(const Vector3 &startPos, const V // this is probably an error state, but we'll leave it // and hopefully recover on the next Update // we still need to copy our preffix - sLog->outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); + sLog->outError(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); } sLog->outDebug(LOG_FILTER_MAPS, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength); @@ -399,7 +399,7 @@ void PathFinderMovementGenerator::BuildPolyPath(const Vector3 &startPos, const V if (!m_polyLength || dtResult != DT_SUCCESS) { // only happens if we passed bad data to findPath(), or navmesh is messed up - sLog->outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); + sLog->outError(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); BuildShortcut(); m_type = PATHFIND_NOPATH; return; diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index 5fca373503e..7452efc94ca 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -79,7 +79,7 @@ namespace Movement // should i do the things that user should do? - no. if (args.path.empty()) - return; + return 0; // corrent first vertex args.path[0] = real_position; @@ -148,12 +148,21 @@ namespace Movement args.flags.EnableFacingAngle(); } - void MoveSplineInit::MoveTo(Vector3 const& dest) + void MoveSplineInit::MoveTo(const Vector3& dest, bool generatePath, bool forceDestination) { - args.path_Idx_offset = 0; - args.path.resize(2); - TransportPathTransform transform(unit, args.TransformForTransport); - args.path[1] = transform(dest); + if (generatePath) + { + PathFinderMovementGenerator path(&unit); + path.calculate(dest.x, dest.y, dest.z, forceDestination); + MovebyPath(path.getPath()); + } + else + { + args.path_Idx_offset = 0; + args.path.resize(2); + TransportPathTransform transform(unit, args.TransformForTransport); + args.path[1] = transform(dest); + } } Vector3 TransportPathTransform::operator()(Vector3 input) diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 740914c59db..9130d2827e6 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -161,26 +161,10 @@ namespace Movement inline void MoveSplineInit::MoveTo(float x, float y, float z, bool generatePath, bool forceDestination) { - Vector3 v(x,y,z); + Vector3 v(x, y, z); MoveTo(v, generatePath, forceDestination); } - inline void MoveSplineInit::MoveTo(const Vector3& dest, bool generatePath, bool forceDestination) - { - if (generatePath) - { - PathFinderMovementGenerator path(&unit); - path.calculate(dest.x, dest.y, dest.z, forceDestination); - MovebyPath(path.getPath()); - } - else - { - args.path_Idx_offset = 0; - args.path.resize(2); - args.path[1] = dest; - } - } - inline void MoveSplineInit::SetParabolic(float amplitude, float time_shift) { args.time_perc = time_shift; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 0d55d7a52e8..dee1b6dcdb8 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1125,8 +1125,8 @@ void World::LoadConfigSettings(bool reload) } m_bool_configs[CONFIG_ENABLE_MMAPS] = ConfigMgr::GetBoolDefault("mmap.enablePathFinding", true); - sLog->outString("WORLD: MMap data directory is: %smmaps", m_dataPath.c_str()); - MMap::MMapFactory::preventPathfindingOnMaps(ConfigMgr::GetStringDefault("mmap.ignoreMapIds", "").c_str()); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "WORLD: MMap data directory is: %smmaps", m_dataPath.c_str()); + MMAP::MMapFactory::preventPathfindingOnMaps(ConfigMgr::GetStringDefault("mmap.ignoreMapIds", "").c_str()); m_bool_configs[CONFIG_VMAP_INDOOR_CHECK] = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", 0); bool enableIndoor = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", true); diff --git a/src/tools/mmaps_generator/TerrainBuilder.h b/src/tools/mmaps_generator/TerrainBuilder.h index a7f21883af2..6d478753279 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.h +++ b/src/tools/mmaps_generator/TerrainBuilder.h @@ -62,7 +62,7 @@ namespace MMAP // see following files: // contrib/extractor/system.cpp // src/game/Map.cpp - static char const* MAP_VERSION_MAGIC = "v1.2"; + static char const* MAP_VERSION_MAGIC = "v1.3"; struct MeshData { -- cgit v1.2.3 From 4351548c750f94425d8b7c24180a813acb6ac443 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 24 Aug 2012 15:33:38 -0500 Subject: Tools/MapExtractor: Fixed a crash caused by using a variable before it was initialized --- src/tools/map_extractor/System.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index ad9a663ac27..44e852b12b9 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -836,7 +836,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, else map.holesOffset = map.heightMapOffset + map.heightMapSize; - memset(holes, 0, map.holesSize); + memset(holes, 0, sizeof(holes)); bool hasHoles = false; for (int i = 0; i < ADT_CELLS_PER_GRID; ++i) -- cgit v1.2.3 From 9698d295b234bcbda3a52c9a47e57f66a98e5335 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 24 Aug 2012 20:03:57 -0500 Subject: Core/Mmaps: Refactored some code --- src/server/game/Movement/MotionMaster.h | 2 +- .../game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp | 2 +- .../game/Movement/MovementGenerators/FleeingMovementGenerator.cpp | 2 +- .../Movement/MovementGenerators/PathFinderMovementGenerator.cpp | 6 +++--- .../game/Movement/MovementGenerators/PathFinderMovementGenerator.h | 4 ++-- .../game/Movement/MovementGenerators/TargetedMovementGenerator.cpp | 2 +- src/server/game/Movement/Spline/MoveSplineInit.cpp | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 918896a5a81..16accff2ab4 100755 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -160,7 +160,7 @@ class MotionMaster //: private std::stack void MoveLand(uint32 id, Position const& pos); void MoveTakeoff(uint32 id, Position const& pos); - void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, bool generatePath = true); + void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, bool generatePath = false); void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ); void MoveJumpTo(float angle, float speedXY, float speedZ); void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = 0); diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index bad45f65178..a4f57a43701 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -78,7 +78,7 @@ bool ConfusedMovementGenerator::Update(T &unit, const uint32 &diff) PathFinderMovementGenerator path(&unit); path.setPathLengthLimit(30.0f); - path.calculate(x, y, z); + path.CalculatePath(x, y, z); if (path.getPathType() & PATHFIND_NOPATH) { i_nextMoveTime.Reset(urand(800, 1000)); diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 9d99e0ef000..4e96c641be7 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -45,7 +45,7 @@ void FleeingMovementGenerator::_setTargetLocation(T &owner) PathFinderMovementGenerator path(&owner); path.setPathLengthLimit(30.0f); - path.calculate(x, y, z); + path.CalculatePath(x, y, z); if (path.getPathType() & PATHFIND_NOPATH) { i_nextCheckTime.Reset(urand(1000, 1500)); diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp index 8988aa599da..adfd32c50b3 100644 --- a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp @@ -50,7 +50,7 @@ PathFinderMovementGenerator::~PathFinderMovementGenerator() sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::~PathFinderMovementGenerator() for %u \n", m_sourceUnit->GetGUIDLow()); } -bool PathFinderMovementGenerator::calculate(float destX, float destY, float destZ, bool forceDest) +bool PathFinderMovementGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest) { if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(m_sourceUnit->GetPositionX(), m_sourceUnit->GetPositionY(), m_sourceUnit->GetPositionZ())) @@ -67,7 +67,7 @@ bool PathFinderMovementGenerator::calculate(float destX, float destY, float dest m_forceDestination = forceDest; - sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); + sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::CalculatePath() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) @@ -88,7 +88,7 @@ bool PathFinderMovementGenerator::calculate(float destX, float destY, float dest { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride - sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::calculate:: precalculated path\n"); + sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::CalculatePath:: precalculated path\n"); m_pathPoints.erase(m_pathPoints.begin()); return false; diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h index 5dd2ad82a0a..9029fc1804e 100644 --- a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h @@ -59,10 +59,10 @@ class PathFinderMovementGenerator // Calculate the path from owner to given destination // return: true if new path was calculated, false otherwise (no change needed) - bool calculate(float destX, float destY, float destZ, bool forceDest = false); + bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false); // option setters - use optional - void setUseStrightPath(bool useStraightPath) { m_useStraightPath = useStraightPath; }; + void SetUseStraightPath(bool useStraightPath) { m_useStraightPath = useStraightPath; }; void setPathLengthLimit(float distance) { m_pointPathLimit = std::min(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }; // result getters diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 1fc2ab5a6cb..1b14cd385e8 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -69,7 +69,7 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T &owner) // allow pets following their master to cheat while generating paths bool forceDest = (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->isPet() && owner.HasUnitState(UNIT_STATE_FOLLOW)); - i_path->calculate(x, y, z, forceDest); + i_path->CalculatePath(x, y, z, forceDest); if (i_path->getPathType() & PATHFIND_NOPATH) return; diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index 7452efc94ca..fa2197f815e 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -73,7 +73,7 @@ namespace Movement } // there is a big chance that current position is unknown if current state is not finalized, need compute it - // this also allows calculate spline position and update map position in much greater intervals + // this also allows CalculatePath spline position and update map position in much greater intervals if (!move_spline.Finalized()) real_position = move_spline.ComputePosition(); @@ -153,7 +153,7 @@ namespace Movement if (generatePath) { PathFinderMovementGenerator path(&unit); - path.calculate(dest.x, dest.y, dest.z, forceDestination); + path.CalculatePath(dest.x, dest.y, dest.z, forceDestination); MovebyPath(path.getPath()); } else -- cgit v1.2.3 From f8cc38d65a3b8bca5f93f57e7f4cf7f93df2b38b Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 25 Aug 2012 11:38:33 -0500 Subject: Core/Mmaps: Make the mmaps_generator multithreaded, you can specify the max number of threads that are spawned at the same time (default 3) by using "--threads x" in the command line, where x is the number of threads you want. Core/Mmaps: Removed now useless sh script --- contrib/extract/extract_data.sh | 162 ---------------------------- contrib/extract/libmysql.dll | Bin 2316288 -> 0 bytes contrib/extract/mapextractor.exe | Bin 314368 -> 0 bytes contrib/extract/mmaps_generator.exe | Bin 2224128 -> 0 bytes contrib/extract/offmesh.txt | 3 - contrib/extract/only_extract_offmesh.sh | 158 --------------------------- contrib/extract/vmap4assembler.exe | Bin 1427456 -> 0 bytes contrib/extract/vmap4extractor.exe | Bin 321536 -> 0 bytes src/tools/mmaps_generator/MapBuilder.cpp | 74 ++++++++----- src/tools/mmaps_generator/MapBuilder.h | 20 +++- src/tools/mmaps_generator/PathGenerator.cpp | 17 ++- 11 files changed, 78 insertions(+), 356 deletions(-) delete mode 100644 contrib/extract/extract_data.sh delete mode 100644 contrib/extract/libmysql.dll delete mode 100644 contrib/extract/mapextractor.exe delete mode 100644 contrib/extract/mmaps_generator.exe delete mode 100644 contrib/extract/offmesh.txt delete mode 100644 contrib/extract/only_extract_offmesh.sh delete mode 100644 contrib/extract/vmap4assembler.exe delete mode 100644 contrib/extract/vmap4extractor.exe (limited to 'src') diff --git a/contrib/extract/extract_data.sh b/contrib/extract/extract_data.sh deleted file mode 100644 index d28c7b7d7f5..00000000000 --- a/contrib/extract/extract_data.sh +++ /dev/null @@ -1,162 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2005-2012 MaNGOS project -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -## Expected param 1 to be 'a' for all, else ask some questions - -## Normal log file (if not overwritten by second param -LOG_FILE="TrinityCoreExtractor.log" -## Detailed log file -DETAIL_LOG_FILE="TrinityCoreExtractor_detailed.log" - -## Change this to a value fitting for your sys! -NUM_CPU="2" - -## ! Use below only for finetuning or if you know what you are doing ! - -USE_MAPS="0" -USE_VMAPS="0" -USE_MMAPS="0" -USE_MMAPS_OFFMESH="0" - -if [ "$1" = "a" ] -then - ## extract all - USE_MAPS="1" - USE_VMAPS="1" - USE_MMAPS="1" -else - ## do some questioning! - echo - echo "Welcome to helper script to extract required dataz for TrinityCore!" - echo "Should all dataz (dbc, maps, vmaps and mmaps be extracted? (y/n)" - read line - if [ "$line" = "y" ] - then - ## extract all - USE_MAPS="1" - USE_VMAPS="1" - USE_MMAPS="1" - else - echo - echo "Should dbc and maps be extracted? (y/n)" - read line - if [ "$line" = "y" ]; then USE_MAPS="1"; fi - - echo - echo "Should vmaps be extracted? (y/n)" - read line - if [ "$line" = "y" ]; then USE_VMAPS="1"; fi - - echo - echo "Should mmaps be extracted? (y/n)" - echo "WARNING! This will take several hours!" - read line - if [ "$line" = "y" ] - then - USE_MMAPS="1"; - else - echo "Only reextract offmesh tiles for mmaps?" - read line - if [ "$line" = "y" ] - then - USE_MMAPS_OFFMESH="1"; - fi - fi - fi -fi - -## Special case: Only reextract offmesh tiles -if [ "$USE_MMAPS_OFFMESH" = "1" ] -then - echo "Only extracting offmesh meshes" - only_extract_offmesh.sh offmesh $LOG_FILE $DETAIL_LOG_FILE - exit 0 -fi - -## Obtain numbe ob processes -if [ "$USE_MMAPS" = "1" ] -then - echo "How many CPUs should be used for extracting mmaps? (1-4)" - read line - if [ "$line" -ge "1" -a "$line" -le "4" ] - then - NUM_CPU=$line - else - echo "Only number between 1 and 4 supported!" - exit 1 - fi -fi - -## Give some status -echo "Current Settings: Extract DBCs/maps: $USE_AD, Extract vmaps: $USE_VMAPS, Extract mmaps: $USE_MMAPS on $NUM_CPU processes" -if [ "$1" != "a" ] -then - echo "If you don't like this settings, interrupt with CTRL+C" - read line -fi - -echo "`date`: Start extracting dataz for TrinityCore" | tee $LOG_FILE - -## Handle log messages -if [ "$USE_AD" = "1" ]; -then - echo "DBC and map files will be extracted" | tee -a $LOG_FILE -else - echo "DBC and map files won't be extracted!" | tee -a $LOG_FILE -fi -if [ "$USE_VMAPS" = "1" ] -then - echo "Vmaps will be extracted" | tee -a $LOG_FILE -else - echo "Vmaps won't be extracted!" | tee -a $LOG_FILE -fi -if [ "$USE_MMAPS" = "1" ] -then - echo "Mmaps will be extracted with $NUM_CPU processes" | tee -a $LOG_FILE -else - echo "Mmaps files won't be extracted!" | tee -a $LOG_FILE -fi -echo | tee -a $LOG_FILE - -echo "`date`: Start extracting dataz for TrinityCore, DBCs/maps $USE_AD, vmaps $USE_VMAPS, mmaps $USE_MMAPS on $NUM_CPU processes" | tee $DETAIL_LOG_FILE -echo | tee -a $DETAIL_LOG_FILE - -## Extract dbcs and maps -if [ "$USE_AD" = "1" ] -then - echo "`date`: Start extraction of DBCs and map files..." | tee -a $LOG_FILE - ad | tee -a $DETAIL_LOG_FILE - echo "`date`: Extracting of DBCs and map files finished" | tee -a $LOG_FILE - echo | tee -a $LOG_FILE - echo | tee -a $DETAIL_LOG_FILE -fi - -## Extract vmaps -if [ "$USE_VMAPS" = "1" ] -then - echo "`date`: Start extraction of vmaps..." | tee -a $LOG_FILE - vmap4extractor | tee -a $DETAIL_LOG_FILE - echo "`date`: Extracting of vmaps finished" | tee -a $LOG_FILE - mkdir vmaps - echo "`date`: Start assembling of vmaps..." | tee -a $LOG_FILE - vmap4assembler.exe buildings vmaps | tee -a $DETAIL_LOG_FILE - echo "`date`: Assembling of vmaps finished" | tee -a $LOG_FILE - - echo | tee -a $LOG_FILE - echo | tee -a $DETAIL_LOG_FILE -fi - -## Extract mmaps -if [ "$USE_MMAPS" = "1" ] -then - only_extract_offmesh.sh $NUM_CPU $LOG_FILE $DETAIL_LOG_FILE -fi diff --git a/contrib/extract/libmysql.dll b/contrib/extract/libmysql.dll deleted file mode 100644 index 36de6064f98..00000000000 Binary files a/contrib/extract/libmysql.dll and /dev/null differ diff --git a/contrib/extract/mapextractor.exe b/contrib/extract/mapextractor.exe deleted file mode 100644 index ae6d150ba0e..00000000000 Binary files a/contrib/extract/mapextractor.exe and /dev/null differ diff --git a/contrib/extract/mmaps_generator.exe b/contrib/extract/mmaps_generator.exe deleted file mode 100644 index 8cd9ff65c26..00000000000 Binary files a/contrib/extract/mmaps_generator.exe and /dev/null differ diff --git a/contrib/extract/offmesh.txt b/contrib/extract/offmesh.txt deleted file mode 100644 index 10299a2c696..00000000000 --- a/contrib/extract/offmesh.txt +++ /dev/null @@ -1,3 +0,0 @@ -0 31,59 (-14429.889648 450.344452 15.430828) (-14424.218750 444.332855 12.773965) 2.5 // booty bay dock -562 31,20 (6234.545898 256.902100 11.075373) (6230.961914 252.127274 11.180979) 2.5 // Blade's Edge Arena -562 31,20 (6243.081543 266.918854 11.059557) (6246.507324 271.623505 11.230524) 2.5 // Blade's Edge Arena \ No newline at end of file diff --git a/contrib/extract/only_extract_offmesh.sh b/contrib/extract/only_extract_offmesh.sh deleted file mode 100644 index 700626856ee..00000000000 --- a/contrib/extract/only_extract_offmesh.sh +++ /dev/null @@ -1,158 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2005-2012 MaNGOS project -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -## Syntax of this helper -## First param must be number of to be used CPUs (only 1, 2, 3, 4 supported) or "offmesh" to recreate the special tiles from the OFFMESH_FILE -## Second param can be an additional filename for storing log -## Third param can be an addition filename for storing detailed log - -## Additional Parameters to be forwarded to MoveMapGen, see mmaps/readme for instructions -PARAMS="--silent" - -## Already a few map extracted, and don't care anymore -EXCLUDE_MAPS="" -#EXCLUDE_MAPS="0 1 530 571" # example to exclude the continents - -## Offmesh file -OFFMESH_FILE="offmesh.txt" - -## Normal log file (if not overwritten by second param -LOG_FILE="movemap.log" -## Detailed log file -DETAIL_LOG_FILE="movemap_detailed.log" - -## ! Use below only for finetuning or if you know what you are doing ! - -## All maps -MAP_LIST_A="1 37 543 595 289 572 529 562 531 269 47 649 650 599 548 559 429 230 573 349 13 25 409 229 43 48 546 553 547 604 545 90 576" -MAP_LIST_B="571 628 560 509 723 532 607 600 668 33 585 566 389 601 369 129 550 189 542 70 109 554 632 552 555 540 598 450 558 249 35 624 557" -MAP_LIST_C="0 631 609 534 533 619 469 602 329 580 615 578 36 556 44 565 544 34 617 608 618 449 616 42 451 582 584 586 587 588 589 590 591 592" -MAP_LIST_D="530 169 575 603 309 574 30 564 568 209 724 658 489 593 594 596 597 605 606 610 612 613 614 620 621 622 623 641 642 647 672 673 712 713 718" -MAP_LIST_D1="209 724 658 489 606 610 612 613 614 620 621" -MAP_LIST_D2="169 575 603 309 574 30 564 568 622 623 641 642 647 672 673 712 713 718" -MAP_LIST_D3="530 593 594 596 597 605" - -badParam() -{ - echo "ERROR! Bad arguments!" - echo "You can (re)extract mmaps with this helper script," - echo "or recreate only the tiles from the offmash file" - echo - echo "Call with number of processes (1 - 4) to create mmaps" - echo "Call with 'offmesh' to reextract the tiles from offmash file" - echo - echo "For further fine-tuning edit this helper script" - echo -} - -if [ "$#" = "3" ] -then - LOG_FILE=$2 - DETAIL_LOG_FILE=$3 -elif [ "$#" = "2" ] -then - LOG_FILE=$2 -fi - -# Offmesh file provided? -OFFMESH="" -if [ "$OFFMESH_FILE" != "" ] -then - if [ ! -f "$OFFMESH_FILE" ] - then - echo "ERROR! Offmesh file $OFFMESH_FILE could not be found." - echo "Provide valid file or none. You need to edit the script" - exit 1 - else - OFFMESH="--offMeshInput $OFFMESH_FILE" - fi -fi - -# Function to process a list -createMMaps() -{ - for i in $@ - do - for j in $EXCLUDE_MAPS - do - if [ "$i" = "$j" ] - then - continue 2 - fi - done - ./mmaps_generator $PARAMS $OFFMESH $i | tee -a $DETAIL_LOG_FILE - echo "`date`: (Re)created map $i" | tee -a $LOG_FILE - done -} - -createHeader() -{ - echo "`date`: Start creating mmaps_generator" | tee -a $LOG_FILE - echo "Used params: $PARAMS $OFFMESH" | tee -a $LOG_FILE - echo "Detailed log can be found in $DETAIL_LOG_FILE" | tee -a $LOG_FILE - echo "Start creating mmaps_generator" | tee -a $DETAIL_LOG_FILE - echo - echo "Be PATIENT - This will take a long time and might also have gaps between visible changes on the console." - echo "WAIT until you are informed that 'creating mmaps_generator' is 'finished'!" -} - -# Create mmaps directory if not exist -if [ ! -d mmaps ] -then - mkdir mmaps -fi - -# Param control -case "$1" in - "1" ) - createHeader $1 - createMMaps $MAP_LIST_A $MAP_LIST_B $MAP_LIST_C $MAP_LIST_D & - ;; - "2" ) - createHeader $1 - createMMaps $MAP_LIST_A $MAP_LIST_D & - createMMaps $MAP_LIST_B $MAP_LIST_C & - ;; - "3" ) - createHeader $1 - createMMaps $MAP_LIST_A $MAP_LIST_D1& - createMMaps $MAP_LIST_B $MAP_LIST_D2& - createMMaps $MAP_LIST_C $MAP_LIST_D3& - ;; - "4" ) - createHeader $1 - createMMaps $MAP_LIST_A & - createMMaps $MAP_LIST_B & - createMMaps $MAP_LIST_C & - createMMaps $MAP_LIST_D & - ;; - "offmesh" ) - echo "`date`: Recreate offmeshs from file $OFFMESH_FILE" | tee -a $LOG_FILE - echo "Recreate offmeshs from file $OFFMESH_FILE" | tee -a $DETAIL_LOG_FILE - while read map tile line - do - ./mmaps_generator $PARAMS $OFFMESH $map --tile $tile | tee -a $DETAIL_LOG_FILE - echo "`date`: Recreated $map $tile from $OFFMESH_FILE" | tee -a $LOG_FILE - done < $OFFMESH_FILE & - ;; - * ) - badParam - exit 1 - ;; -esac - -wait - -echo | tee -a $LOG_FILE -echo | tee -a $DETAIL_LOG_FILE -echo "`date`: Finished creating MoveMaps" | tee -a $LOG_FILE -echo "`date`: Finished creating MoveMaps" >> $DETAIL_LOG_FILE diff --git a/contrib/extract/vmap4assembler.exe b/contrib/extract/vmap4assembler.exe deleted file mode 100644 index e5331a5f70e..00000000000 Binary files a/contrib/extract/vmap4assembler.exe and /dev/null differ diff --git a/contrib/extract/vmap4extractor.exe b/contrib/extract/vmap4extractor.exe deleted file mode 100644 index 4866904d04f..00000000000 Binary files a/contrib/extract/vmap4extractor.exe and /dev/null differ diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index e47b2e5b44f..a0c40bc4392 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -158,13 +158,31 @@ namespace MMAP } /**************************************************************************/ - void MapBuilder::buildAllMaps() + void MapBuilder::buildAllMaps(int threads) { + int running = 0; for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { uint32 mapID = (*it).first; if (!shouldSkipMap(mapID)) - buildMap(mapID); + { + if (threads > 1) + { + BuilderThread* thread = new BuilderThread(this, mapID); + thread->activate(); + ++running; + // Do not allow more than {threads} threads running at the same time + if (running == threads) + { + // Wait for previous threads to finish + ACE_Thread_Manager::instance()->wait(); + // Reset the number of running threads + running = 0; + } + } + else + buildMap(mapID); + } } } @@ -306,7 +324,7 @@ namespace MMAP } // now start building mmtiles for each tile - printf("We have %u tiles. \n", (unsigned int)tiles->size()); + printf("[Map %i] We have %u tiles. \n", mapID, (unsigned int)tiles->size()); for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) { uint32 tileX, tileY; @@ -415,10 +433,10 @@ namespace MMAP navMeshParams.maxPolys = maxPolysPerTile; navMesh = dtAllocNavMesh(); - printf("Creating navMesh... \r"); + printf("[Map %i] Creating navMesh...\n", mapID); if (!navMesh->init(&navMeshParams)) { - printf("Failed creating navmesh! \n"); + printf("[Map %i] Failed creating navmesh! \n", mapID); return; } @@ -430,7 +448,7 @@ namespace MMAP { dtFreeNavMesh(navMesh); char message[1024]; - sprintf(message, "Failed to open %s for writing!\n", fileName); + sprintf(message, "[Map %i] Failed to open %s for writing!\n", mapID, fileName); perror(message); return; } @@ -446,9 +464,9 @@ namespace MMAP dtNavMesh* navMesh) { // console output - char tileString[10]; - sprintf(tileString, "[%02i,%02i]: ", tileX, tileY); - printf("%s Building movemap tiles... \r", tileString); + char tileString[20]; + sprintf(tileString, "[Map %03i] [%02i,%02i]: ", mapID, tileX, tileY); + printf("%s Building movemap tiles...\n", tileString); IntermediateValues iv; @@ -510,14 +528,14 @@ namespace MMAP rcPolyMesh** pmmerge = new rcPolyMesh*[TILES_PER_MAP * TILES_PER_MAP]; if (!pmmerge) { - printf("%s alloc pmmerge FIALED! \r", tileString); + printf("%s alloc pmmerge FIALED!\n", tileString); return; } rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[TILES_PER_MAP * TILES_PER_MAP]; if (!dmmerge) { - printf("%s alloc dmmerge FIALED! \r", tileString); + printf("%s alloc dmmerge FIALED!\n", tileString); return; } @@ -539,7 +557,7 @@ namespace MMAP tile.solid = rcAllocHeightfield(); if (!tile.solid || !rcCreateHeightfield(m_rcContext, *tile.solid, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch)) { - printf("%sFailed building heightfield! \n", tileString); + printf("%s Failed building heightfield! \n", tileString); continue; } @@ -560,33 +578,33 @@ namespace MMAP tile.chf = rcAllocCompactHeightfield(); if (!tile.chf || !rcBuildCompactHeightfield(m_rcContext, tileCfg.walkableHeight, tileCfg.walkableClimb, *tile.solid, *tile.chf)) { - printf("%sFailed compacting heightfield! \n", tileString); + printf("%s Failed compacting heightfield! \n", tileString); continue; } // build polymesh intermediates if (!rcErodeWalkableArea(m_rcContext, config.walkableRadius, *tile.chf)) { - printf("%sFailed eroding area! \n", tileString); + printf("%s Failed eroding area! \n", tileString); continue; } if (!rcBuildDistanceField(m_rcContext, *tile.chf)) { - printf("%sFailed building distance field! \n", tileString); + printf("%s Failed building distance field! \n", tileString); continue; } if (!rcBuildRegions(m_rcContext, *tile.chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea)) { - printf("%sFailed building regions! \n", tileString); + printf("%s Failed building regions! \n", tileString); continue; } tile.cset = rcAllocContourSet(); if (!tile.cset || !rcBuildContours(m_rcContext, *tile.chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *tile.cset)) { - printf("%sFailed building contours! \n", tileString); + printf("%s Failed building contours! \n", tileString); continue; } @@ -594,14 +612,14 @@ namespace MMAP tile.pmesh = rcAllocPolyMesh(); if (!tile.pmesh || !rcBuildPolyMesh(m_rcContext, *tile.cset, tileCfg.maxVertsPerPoly, *tile.pmesh)) { - printf("%sFailed building polymesh! \n", tileString); + printf("%s Failed building polymesh! \n", tileString); continue; } tile.dmesh = rcAllocPolyMeshDetail(); if (!tile.dmesh || !rcBuildPolyMeshDetail(m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg .detailSampleMaxError, *tile.dmesh)) { - printf("%sFailed building polymesh detail! \n", tileString); + printf("%s Failed building polymesh detail! \n", tileString); continue; } @@ -627,7 +645,7 @@ namespace MMAP iv.polyMesh = rcAllocPolyMesh(); if (!iv.polyMesh) { - printf("%s alloc iv.polyMesh FIALED! \r", tileString); + printf("%s alloc iv.polyMesh FIALED!\n", tileString); return; } rcMergePolyMeshes(m_rcContext, pmmerge, nmerge, *iv.polyMesh); @@ -635,16 +653,16 @@ namespace MMAP iv.polyMeshDetail = rcAllocPolyMeshDetail(); if (!iv.polyMeshDetail) { - printf("%s alloc m_dmesh FIALED! \r", tileString); + printf("%s alloc m_dmesh FIALED!\n", tileString); return; } rcMergePolyMeshDetails(m_rcContext, dmmerge, nmerge, *iv.polyMeshDetail); // free things up - delete [] pmmerge; - delete [] dmmerge; + delete[] pmmerge; + delete[] dmmerge; - delete [] tiles; + delete[] tiles; // remove padding for extraction for (int i = 0; i < iv.polyMesh->nverts; ++i) @@ -736,7 +754,7 @@ namespace MMAP continue; } - printf("%s Building navmesh tile... \r", tileString); + printf("%s Building navmesh tile...\n", tileString); if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) { printf("%s Failed building navmesh tile! \n", tileString); @@ -744,7 +762,7 @@ namespace MMAP } dtTileRef tileRef = 0; - printf("%s Adding tile to navmesh... \r", tileString); + printf("%s Adding tile to navmesh...\n", tileString); // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile // is removed via removeTile() dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef); @@ -761,13 +779,13 @@ namespace MMAP if (!file) { char message[1024]; - sprintf(message, "Failed to open %s for writing!\n", fileName); + sprintf(message, "[Map %i] Failed to open %s for writing!\n", mapID, fileName); perror(message); navMesh->removeTile(tileRef, NULL, NULL); continue; } - printf("%s Writing to file... \r", tileString); + printf("%s Writing to file...\n", tileString); // write header MmapTileHeader header; diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index 20789bf9bff..0c9dce05992 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -32,6 +32,8 @@ #include "Recast.h" #include "DetourNavMesh.h" +#include "ace/Task.h" + using namespace std; using namespace VMAP; @@ -80,7 +82,7 @@ namespace MMAP void buildSingleTile(uint32 mapID, uint32 tileX, uint32 tileY); // builds list of maps, then builds all of mmap tiles (based on the skip settings) - void buildAllMaps(); + void buildAllMaps(int threads); private: // detect maps and tiles @@ -125,6 +127,22 @@ namespace MMAP // build performance - not really used for now rcContext* m_rcContext; }; + + class BuilderThread : public ACE_Task + { + private: + MapBuilder* _builder; + uint32 _mapId; + public: + BuilderThread(MapBuilder* builder, uint32 mapId) : _builder(builder), _mapId(mapId) {} + + int svc() + { + if (_builder) + _builder->buildMap(_mapId); + return 0; + } + }; } #endif diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 7d9f59ed138..45d0aff958c 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -71,7 +71,8 @@ bool handleArgs(int argc, char** argv, bool &silent, bool &bigBaseUnit, char* &offMeshInputPath, - char* &file) + char* &file, + int& threads) { char* param = NULL; for (int i = 1; i < argc; ++i) @@ -88,6 +89,14 @@ bool handleArgs(int argc, char** argv, else printf("invalid option for '--maxAngle', using default\n"); } + else if (strcmp(argv[i], "--threads") == 0) + { + param = argv[++i]; + if (!param) + return false; + threads = atoi(param); + printf("Using %i threads to extract mmaps\n", threads); + } else if (strcmp(argv[i], "--file") == 0) { param = argv[++i]; @@ -232,7 +241,7 @@ int finish(const char* message, int returnValue) int main(int argc, char** argv) { - int mapnum = -1; + int threads = 3, mapnum = -1; float maxAngle = 60.0f; int tileX = -1, tileY = -1; bool skipLiquid = false, @@ -248,7 +257,7 @@ int main(int argc, char** argv) bool validParam = handleArgs(argc, argv, mapnum, tileX, tileY, maxAngle, skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, - debugOutput, silent, bigBaseUnit, offMeshInputPath, file); + debugOutput, silent, bigBaseUnit, offMeshInputPath, file, threads); if (!validParam) return silent ? -1 : finish("You have specified invalid parameters", -1); @@ -278,7 +287,7 @@ int main(int argc, char** argv) else if (mapnum >= 0) builder.buildMap(uint32(mapnum)); else - builder.buildAllMaps(); + builder.buildAllMaps(threads); return silent ? 1 : finish("Movemap build is complete!", 1); } -- cgit v1.2.3 From 35437149e210ed713b04e01bf7607aa1475e158f Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 25 Aug 2012 12:27:48 -0500 Subject: Core/Mmaps: Added some corrections to the logs in the mmaps_generator --- src/tools/mmaps_generator/MapBuilder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index a0c40bc4392..3b7a3e8d99d 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -294,7 +294,7 @@ namespace MMAP /**************************************************************************/ void MapBuilder::buildMap(uint32 mapID) { - printf("Building map %03u:\n", mapID); + printf("[Thread %i] Building map %03u:\n", ACE_Thread::self(), mapID); set* tiles = getTileList(mapID); @@ -340,7 +340,7 @@ namespace MMAP dtFreeNavMesh(navMesh); - printf("Complete! \n\n"); + printf("[Map %i] Complete!\n", mapID); } /**************************************************************************/ -- cgit v1.2.3 From c44601379179ad368bb2c80d371232c48f366f90 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 25 Aug 2012 12:40:04 -0500 Subject: Core/Mmaps: Added elapsed time to the mmaps_generator --- src/tools/mmaps_generator/PathGenerator.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 45d0aff958c..4da90fd153a 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -18,6 +18,7 @@ #include "PathCommon.h" #include "MapBuilder.h" +#include "Timer.h" using namespace MMAP; @@ -280,6 +281,7 @@ int main(int argc, char** argv) MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, debugOutput, bigBaseUnit, offMeshInputPath); + uint32 start = getMSTime(); if (file) builder.buildMeshFromFile(file); else if (tileX > -1 && tileY > -1 && mapnum >= 0) @@ -289,5 +291,7 @@ int main(int argc, char** argv) else builder.buildAllMaps(threads); - return silent ? 1 : finish("Movemap build is complete!", 1); + if (!silent) + printf("Finished. MMAPS were built in %u ms!", GetMSTimeDiffToNow(start)); + return 1; } -- cgit v1.2.3 From f0473777e2751ce53790d5b2628f00c287540691 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 25 Aug 2012 14:32:52 -0500 Subject: Core/Mmaps: Fixed jump effects (like Death Grip ). They should not use a path --- src/server/game/Movement/MotionMaster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index dd053534c8a..07d3760cf40 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -370,7 +370,7 @@ void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float spee float max_height = -Movement::computeFallElevation(moveTimeHalf,false,-speedZ); Movement::MoveSplineInit init(*_owner); - init.MoveTo(x,y,z); + init.MoveTo(x, y, z, false); init.SetParabolic(max_height,0); init.SetVelocity(speedXY); init.Launch(); -- cgit v1.2.3 From 92e72b2a5cd79c82625ceb6cc83125c546e7f1ab Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 25 Aug 2012 17:37:15 -0500 Subject: Core/Mmaps: Fixed a few mistakes in the mmaps_generator, should be somewhat faster now --- src/tools/mmaps_generator/MapBuilder.cpp | 82 +++++++++++++++++++------------- src/tools/mmaps_generator/MapBuilder.h | 8 +++- 2 files changed, 56 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 3b7a3e8d99d..b04300994f9 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -160,30 +160,46 @@ namespace MMAP /**************************************************************************/ void MapBuilder::buildAllMaps(int threads) { - int running = 0; + std::vector _threads; + + for (int i = 0; i < threads; ++i) + _threads.push_back(new BuilderThread(this)); + for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { - uint32 mapID = (*it).first; + uint32 mapID = it->first; if (!shouldSkipMap(mapID)) { if (threads > 1) { - BuilderThread* thread = new BuilderThread(this, mapID); - thread->activate(); - ++running; - // Do not allow more than {threads} threads running at the same time - if (running == threads) + bool next = false; + while (!next) { - // Wait for previous threads to finish - ACE_Thread_Manager::instance()->wait(); - // Reset the number of running threads - running = 0; + for (std::vector::iterator _th = _threads.begin(); _th != _threads.end(); ++_th) + { + if ((*_th)->Free) + { + printf("Thread is free for map %03i\n", mapID); + (*_th)->SetMapId(mapID); + (*_th)->activate(); + next = true; + break; + } + } + // Wait for 20 seconds + ACE_OS::sleep(ACE_Time_Value (0, 20000)); } } else buildMap(mapID); } } + // Wait for all threads to finish before closing down + ACE_Thread_Manager::instance()->wait(); + + // Free memory + for (std::vector::iterator _th = _threads.begin(); _th != _threads.end(); ++_th) + delete *_th; } /**************************************************************************/ @@ -311,34 +327,34 @@ namespace MMAP tiles->insert(StaticMapTree::packTileID(i, j)); } - if (!tiles->size()) - return; - - // build navMesh - dtNavMesh* navMesh = NULL; - buildNavMesh(mapID, navMesh); - if (!navMesh) + if (!tiles->empty()) { - printf("Failed creating navmesh! \n"); - return; - } + // build navMesh + dtNavMesh* navMesh = NULL; + buildNavMesh(mapID, navMesh); + if (!navMesh) + { + printf("Failed creating navmesh! \n"); + return; + } - // now start building mmtiles for each tile - printf("[Map %i] We have %u tiles. \n", mapID, (unsigned int)tiles->size()); - for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) - { - uint32 tileX, tileY; + // now start building mmtiles for each tile + printf("[Map %i] We have %u tiles. \n", mapID, (unsigned int)tiles->size()); + for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) + { + uint32 tileX, tileY; - // unpack tile coords - StaticMapTree::unpackTileID((*it), tileX, tileY); + // unpack tile coords + StaticMapTree::unpackTileID((*it), tileX, tileY); - if (shouldSkipTile(mapID, tileX, tileY)) - continue; + if (shouldSkipTile(mapID, tileX, tileY)) + continue; - buildTile(mapID, tileX, tileY, navMesh); - } + buildTile(mapID, tileX, tileY, navMesh); + } - dtFreeNavMesh(navMesh); + dtFreeNavMesh(navMesh); + } printf("[Map %i] Complete!\n", mapID); } diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index 0c9dce05992..61a71ff6d5b 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -134,14 +134,20 @@ namespace MMAP MapBuilder* _builder; uint32 _mapId; public: - BuilderThread(MapBuilder* builder, uint32 mapId) : _builder(builder), _mapId(mapId) {} + BuilderThread(MapBuilder* builder) : _builder(builder), Free(true) {} + + void SetMapId(uint32 mapId) { _mapId = mapId; } int svc() { + Free = false; if (_builder) _builder->buildMap(_mapId); + Free = true; return 0; } + + bool Free; }; } -- cgit v1.2.3 From e0abbfd86c3ce23daa9bccbb9c181bfe08c2d0c4 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 25 Aug 2012 21:55:03 -0500 Subject: Core/MMaps: Renamed PathFinderMovementGenerator to PathGenerator, since its not a MovementGenerator, and moved out of the MovementGenerators folder --- .../ConfusedMovementGenerator.cpp | 4 +- .../FleeingMovementGenerator.cpp | 4 +- .../PathFinderMovementGenerator.cpp | 808 --------------------- .../PathFinderMovementGenerator.h | 137 ---- .../TargetedMovementGenerator.cpp | 2 +- .../MovementGenerators/TargetedMovementGenerator.h | 4 +- src/server/game/Movement/PathGenerator.cpp | 808 +++++++++++++++++++++ src/server/game/Movement/PathGenerator.h | 137 ++++ src/server/game/Movement/Spline/MoveSplineInit.cpp | 2 +- src/server/game/Movement/Spline/MoveSplineInit.h | 2 +- 10 files changed, 954 insertions(+), 954 deletions(-) delete mode 100644 src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp delete mode 100644 src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h create mode 100644 src/server/game/Movement/PathGenerator.cpp create mode 100644 src/server/game/Movement/PathGenerator.h (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index a4f57a43701..b9b69baf0f8 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -19,7 +19,7 @@ #include "Creature.h" #include "MapManager.h" #include "ConfusedMovementGenerator.h" -#include "PathFinderMovementGenerator.h" +#include "PathGenerator.h" #include "VMapFactory.h" #include "MoveSplineInit.h" #include "MoveSpline.h" @@ -76,7 +76,7 @@ bool ConfusedMovementGenerator::Update(T &unit, const uint32 &diff) unit.UpdateAllowedPositionZ(x, y, z); - PathFinderMovementGenerator path(&unit); + PathGenerator path(&unit); path.setPathLengthLimit(30.0f); path.CalculatePath(x, y, z); if (path.getPathType() & PATHFIND_NOPATH) diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 4e96c641be7..ae1e89c8562 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -20,7 +20,7 @@ #include "CreatureAI.h" #include "MapManager.h" #include "FleeingMovementGenerator.h" -#include "PathFinderMovementGenerator.h" +#include "PathGenerator.h" #include "ObjectAccessor.h" #include "MoveSplineInit.h" #include "MoveSpline.h" @@ -43,7 +43,7 @@ void FleeingMovementGenerator::_setTargetLocation(T &owner) owner.AddUnitState(UNIT_STATE_FLEEING_MOVE); - PathFinderMovementGenerator path(&owner); + PathGenerator path(&owner); path.setPathLengthLimit(30.0f); path.CalculatePath(x, y, z); if (path.getPathType() & PATHFIND_NOPATH) diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp deleted file mode 100644 index adfd32c50b3..00000000000 --- a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.cpp +++ /dev/null @@ -1,808 +0,0 @@ -/* - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "PathFinderMovementGenerator.h" -#include "Map.h" -#include "Creature.h" -#include "MMapFactory.h" -#include "MMapManager.h" -#include "Log.h" - -#include "DetourCommon.h" -#include "DetourNavMeshQuery.h" - -////////////////// PathFinderMovementGenerator ////////////////// -PathFinderMovementGenerator::PathFinderMovementGenerator(const Unit* owner) : - m_polyLength(0), m_type(PATHFIND_BLANK), - m_useStraightPath(false), m_forceDestination(false), m_pointPathLimit(MAX_POINT_PATH_LENGTH), - m_sourceUnit(owner), m_navMesh(NULL), m_navMeshQuery(NULL) -{ - sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::PathFinderMovementGenerator for %u \n", m_sourceUnit->GetGUIDLow()); - - uint32 mapId = m_sourceUnit->GetMapId(); - if (MMAP::MMapFactory::IsPathfindingEnabled(mapId)) - { - MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); - m_navMesh = mmap->GetNavMesh(mapId); - m_navMeshQuery = mmap->GetNavMeshQuery(mapId, m_sourceUnit->GetInstanceId()); - } - - createFilter(); -} - -PathFinderMovementGenerator::~PathFinderMovementGenerator() -{ - sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::~PathFinderMovementGenerator() for %u \n", m_sourceUnit->GetGUIDLow()); -} - -bool PathFinderMovementGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest) -{ - if (!Trinity::IsValidMapCoord(destX, destY, destZ) || - !Trinity::IsValidMapCoord(m_sourceUnit->GetPositionX(), m_sourceUnit->GetPositionY(), m_sourceUnit->GetPositionZ())) - return false; - - Vector3 oldDest = getEndPosition(); - Vector3 dest(destX, destY, destZ); - setEndPosition(dest); - - float x, y, z; - m_sourceUnit->GetPosition(x, y, z); - Vector3 start(x, y, z); - setStartPosition(start); - - m_forceDestination = forceDest; - - sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::CalculatePath() for %u \n", m_sourceUnit->GetGUIDLow()); - - // make sure navMesh works - we can run on map w/o mmap - // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) - if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || - !HaveTile(start) || !HaveTile(dest)) - { - BuildShortcut(); - m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); - return true; - } - - updateFilter(); - - // check if destination moved - if not we can optimize something here - // we are following old, precalculated path? - float dist = m_sourceUnit->GetObjectSize(); - if (inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) - { - // our target is not moving - we just coming closer - // we are moving on precalculated path - enjoy the ride - sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::CalculatePath:: precalculated path\n"); - - m_pathPoints.erase(m_pathPoints.begin()); - return false; - } - else - { - // target moved, so we need to update the poly path - BuildPolyPath(start, dest); - return true; - } -} - -dtPolyRef PathFinderMovementGenerator::getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance) const -{ - if (!polyPath || !polyPathSize) - return INVALID_POLYREF; - - dtPolyRef nearestPoly = INVALID_POLYREF; - float minDist2d = FLT_MAX; - float minDist3d = 0.0f; - - for (uint32 i = 0; i < polyPathSize; ++i) - { - float closestPoint[VERTEX_SIZE]; - if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint)) - continue; - - float d = dtVdist2DSqr(point, closestPoint); - if (d < minDist2d) - { - minDist2d = d; - nearestPoly = polyPath[i]; - minDist3d = dtVdistSqr(point, closestPoint); - } - - if(minDist2d < 1.0f) // shortcut out - close enough for us - break; - } - - if (distance) - *distance = dtSqrt(minDist3d); - - return (minDist2d < 3.0f) ? nearestPoly : INVALID_POLYREF; -} - -dtPolyRef PathFinderMovementGenerator::getPolyByLocation(const float* point, float *distance) const -{ - // first we check the current path - // if the current path doesn't contain the current poly, - // we need to use the expensive navMesh.findNearestPoly - dtPolyRef polyRef = getPathPolyByPosition(m_pathPolyRefs, m_polyLength, point, distance); - if (polyRef != INVALID_POLYREF) - return polyRef; - - // we don't have it in our old path - // try to get it by findNearestPoly() - // first try with low search box - float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area - float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f}; - dtStatus result = m_navMeshQuery->findNearestPoly(point, extents, &m_filter, &polyRef, closestPoint); - if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) - { - *distance = dtVdist(closestPoint, point); - return polyRef; - } - - // still nothing .. - // try with bigger search box - extents[1] = 200.0f; - result = m_navMeshQuery->findNearestPoly(point, extents, &m_filter, &polyRef, closestPoint); - if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) - { - *distance = dtVdist(closestPoint, point); - return polyRef; - } - - return INVALID_POLYREF; -} - -void PathFinderMovementGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos) -{ - // *** getting start/end poly logic *** - - float distToStartPoly, distToEndPoly; - float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x}; - float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x}; - - dtPolyRef startPoly = getPolyByLocation(startPoint, &distToStartPoly); - dtPolyRef endPoly = getPolyByLocation(endPoint, &distToEndPoly); - - // we have a hole in our mesh - // make shortcut path and mark it as NOPATH ( with flying and swimming exception ) - // its up to caller how he will use this info - if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF) - { - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); - BuildShortcut(); - bool path = m_sourceUnit->GetTypeId() == TYPEID_UNIT && m_sourceUnit->ToCreature()->CanFly(); - - bool waterPath = m_sourceUnit->GetTypeId() == TYPEID_UNIT && m_sourceUnit->ToCreature()->canSwim(); - if (waterPath) - { - // Check both start and end points, if they're both in water, then we can *safely* let the creature move - for (int i = 0; i < m_pathPoints.size(); ++i) - { - LiquidData data; - m_sourceUnit->GetBaseMap()->getLiquidStatus(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z, MAP_ALL_LIQUIDS, &data); - // One of the points is not in the water, cancel movement. - if (data.type_flags == MAP_LIQUID_TYPE_NO_WATER) - { - waterPath = false; - break; - } - } - } - - m_type = (path || waterPath) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; - return; - } - - // we may need a better number here - bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f); - if (farFromPoly) - { - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly); - - bool buildShotrcut = false; - if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) - { - Creature* owner = (Creature*)m_sourceUnit; - - Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos; - if (m_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) - { - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: underWater case\n"); - if (owner->canSwim()) - buildShotrcut = true; - } - else - { - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: flying case\n"); - if (owner->CanFly()) - buildShotrcut = true; - } - } - - if (buildShotrcut) - { - BuildShortcut(); - m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); - return; - } - else - { - float closestPoint[VERTEX_SIZE]; - // we may want to use closestPointOnPolyBoundary instead - if (DT_SUCCESS == m_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) - { - dtVcopy(endPoint, closestPoint); - setActualEndPosition(Vector3(endPoint[2],endPoint[0],endPoint[1])); - } - - m_type = PATHFIND_INCOMPLETE; - } - } - - // *** poly path generating logic *** - - // start and end are on same polygon - // just need to move in straight line - if (startPoly == endPoly) - { - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == endPoly)\n"); - - BuildShortcut(); - - m_pathPolyRefs[0] = startPoly; - m_polyLength = 1; - - m_type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL; - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: path type %d\n", m_type); - return; - } - - // look for startPoly/endPoly in current path - // TODO: we can merge it with getPathPolyByPosition() loop - bool startPolyFound = false; - bool endPolyFound = false; - uint32 pathStartIndex, pathEndIndex; - - if (m_polyLength) - { - for (pathStartIndex = 0; pathStartIndex < m_polyLength; ++pathStartIndex) - { - // here to carch few bugs - ASSERT(m_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); - - if (m_pathPolyRefs[pathStartIndex] == startPoly) - { - startPolyFound = true; - break; - } - } - - for (pathEndIndex = m_polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) - if (m_pathPolyRefs[pathEndIndex] == endPoly) - { - endPolyFound = true; - break; - } - } - - if (startPolyFound && endPolyFound) - { - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPolyFound && endPolyFound)\n"); - - // we moved along the path and the target did not move out of our old poly-path - // our path is a simple subpath case, we have all the data we need - // just "cut" it out - - m_polyLength = pathEndIndex - pathStartIndex + 1; - memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, m_polyLength*sizeof(dtPolyRef)); - } - else if (startPolyFound && !endPolyFound) - { - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n"); - - // we are moving on the old path but target moved out - // so we have atleast part of poly-path ready - - m_polyLength -= pathStartIndex; - - // try to adjust the suffix of the path instead of recalculating entire length - // at given interval the target cannot get too far from its last location - // thus we have less poly to cover - // sub-path of optimal path is optimal - - // take ~80% of the original length - // TODO : play with the values here - uint32 prefixPolyLength = uint32(m_polyLength*0.8f + 0.5f); - memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, prefixPolyLength*sizeof(dtPolyRef)); - - dtPolyRef suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; - - // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data - float suffixEndPoint[VERTEX_SIZE]; - if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) - { - // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that - // try to recover by using prev polyref - --prefixPolyLength; - suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; - if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) - { - // suffixStartPoly is still invalid, error state - BuildShortcut(); - m_type = PATHFIND_NOPATH; - return; - } - } - - // generate suffix - uint32 suffixPolyLength = 0; - dtStatus dtResult = m_navMeshQuery->findPath( - suffixStartPoly, // start polygon - endPoly, // end polygon - suffixEndPoint, // start position - endPoint, // end position - &m_filter, // polygon search filter - m_pathPolyRefs + prefixPolyLength - 1, // [out] path - (int*)&suffixPolyLength, - MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path - - if (!suffixPolyLength || dtResult != DT_SUCCESS) - { - // this is probably an error state, but we'll leave it - // and hopefully recover on the next Update - // we still need to copy our preffix - sLog->outError(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); - } - - sLog->outDebug(LOG_FILTER_MAPS, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength); - - // new path = prefix + suffix - overlap - m_polyLength = prefixPolyLength + suffixPolyLength - 1; - } - else - { - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n"); - - // either we have no path at all -> first run - // or something went really wrong -> we aren't moving along the path to the target - // just generate new path - - // free and invalidate old path data - clear(); - - dtStatus dtResult = m_navMeshQuery->findPath( - startPoly, // start polygon - endPoly, // end polygon - startPoint, // start position - endPoint, // end position - &m_filter, // polygon search filter - m_pathPolyRefs, // [out] path - (int*)&m_polyLength, - MAX_PATH_LENGTH); // max number of polygons in output path - - if (!m_polyLength || dtResult != DT_SUCCESS) - { - // only happens if we passed bad data to findPath(), or navmesh is messed up - sLog->outError(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); - BuildShortcut(); - m_type = PATHFIND_NOPATH; - return; - } - } - - // by now we know what type of path we can get - if (m_pathPolyRefs[m_polyLength - 1] == endPoly && !(m_type & PATHFIND_INCOMPLETE)) - m_type = PATHFIND_NORMAL; - else - m_type = PATHFIND_INCOMPLETE; - - // generate the point-path out of our up-to-date poly-path - BuildPointPath(startPoint, endPoint); -} - -void PathFinderMovementGenerator::BuildPointPath(const float *startPoint, const float *endPoint) -{ - float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; - uint32 pointCount = 0; - dtStatus dtResult = DT_FAILURE; - if (m_useStraightPath) - { - dtResult = m_navMeshQuery->findStraightPath( - startPoint, // start position - endPoint, // end position - m_pathPolyRefs, // current path - m_polyLength, // lenth of current path - pathPoints, // [out] path corner points - NULL, // [out] flags - NULL, // [out] shortened path - (int*)&pointCount, - m_pointPathLimit); // maximum number of points/polygons to use - } - else - { - dtResult = findSmoothPath( - startPoint, // start position - endPoint, // end position - m_pathPolyRefs, // current path - m_polyLength, // length of current path - pathPoints, // [out] path corner points - (int*)&pointCount, - m_pointPathLimit); // maximum number of points - } - - if (pointCount < 2 || dtResult != DT_SUCCESS) - { - // only happens if pass bad data to findStraightPath or navmesh is broken - // single point paths can be generated here - // TODO : check the exact cases - sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount); - BuildShortcut(); - m_type = PATHFIND_NOPATH; - return; - } - - m_pathPoints.resize(pointCount); - for (uint32 i = 0; i < pointCount; ++i) - m_pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); - - NormalizePath(); - - // first point is always our current location - we need the next one - setActualEndPosition(m_pathPoints[pointCount-1]); - - // force the given destination, if needed - if(m_forceDestination && - (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f))) - { - // we may want to keep partial subpath - if(dist3DSqr(getActualEndPosition(), getEndPosition()) < - 0.3f * dist3DSqr(getStartPosition(), getEndPosition())) - { - setActualEndPosition(getEndPosition()); - m_pathPoints[m_pathPoints.size()-1] = getEndPosition(); - } - else - { - setActualEndPosition(getEndPosition()); - BuildShortcut(); - } - - m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); - } - - sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); -} - -void PathFinderMovementGenerator::NormalizePath() -{ - for (uint32 i = 0; i < m_pathPoints.size(); ++i) - m_sourceUnit->UpdateAllowedPositionZ(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z); -} - -void PathFinderMovementGenerator::BuildShortcut() -{ - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildShortcut :: making shortcut\n"); - - clear(); - - // make two point path, our curr pos is the start, and dest is the end - m_pathPoints.resize(2); - - // set start and a default next position - m_pathPoints[0] = getStartPosition(); - m_pathPoints[1] = getActualEndPosition(); - - NormalizePath(); - - m_type = PATHFIND_SHORTCUT; -} - -void PathFinderMovementGenerator::createFilter() -{ - uint16 includeFlags = 0; - uint16 excludeFlags = 0; - - if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) - { - Creature* creature = (Creature*)m_sourceUnit; - if (creature->canWalk()) - includeFlags |= NAV_GROUND; // walk - - // creatures don't take environmental damage - if (creature->canSwim()) - includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim - } - else if (m_sourceUnit->GetTypeId() == TYPEID_PLAYER) - { - // perfect support not possible, just stay 'safe' - includeFlags |= (NAV_GROUND | NAV_WATER); - } - - m_filter.setIncludeFlags(includeFlags); - m_filter.setExcludeFlags(excludeFlags); - - updateFilter(); -} - -void PathFinderMovementGenerator::updateFilter() -{ - // allow creatures to cheat and use different movement types if they are moved - // forcefully into terrain they can't normally move in - if (m_sourceUnit->IsInWater() || m_sourceUnit->IsUnderWater()) - { - uint16 includedFlags = m_filter.getIncludeFlags(); - includedFlags |= getNavTerrain(m_sourceUnit->GetPositionX(), - m_sourceUnit->GetPositionY(), - m_sourceUnit->GetPositionZ()); - - m_filter.setIncludeFlags(includedFlags); - } -} - -NavTerrain PathFinderMovementGenerator::getNavTerrain(float x, float y, float z) -{ - LiquidData data; - m_sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); - - switch (data.type_flags) - { - case MAP_LIQUID_TYPE_WATER: - case MAP_LIQUID_TYPE_OCEAN: - return NAV_WATER; - case MAP_LIQUID_TYPE_MAGMA: - return NAV_MAGMA; - case MAP_LIQUID_TYPE_SLIME: - return NAV_SLIME; - default: - return NAV_GROUND; - } -} - -bool PathFinderMovementGenerator::HaveTile(const Vector3 &p) const -{ - int tx, ty; - float point[VERTEX_SIZE] = {p.y, p.z, p.x}; - - m_navMesh->calcTileLoc(point, &tx, &ty); - return (m_navMesh->getTileAt(tx, ty) != NULL); -} - -uint32 PathFinderMovementGenerator::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, - const dtPolyRef* visited, uint32 nvisited) -{ - int32 furthestPath = -1; - int32 furthestVisited = -1; - - // Find furthest common polygon. - for (int32 i = npath-1; i >= 0; --i) - { - bool found = false; - for (int32 j = nvisited-1; j >= 0; --j) - { - if (path[i] == visited[j]) - { - furthestPath = i; - furthestVisited = j; - found = true; - } - } - if (found) - break; - } - - // If no intersection found just return current path. - if (furthestPath == -1 || furthestVisited == -1) - return npath; - - // Concatenate paths. - - // Adjust beginning of the buffer to include the visited. - uint32 req = nvisited - furthestVisited; - uint32 orig = uint32(furthestPath+1) < npath ? furthestPath+1 : npath; - uint32 size = npath-orig > 0 ? npath-orig : 0; - if (req+size > maxPath) - size = maxPath-req; - - if (size) - memmove(path+req, path+orig, size*sizeof(dtPolyRef)); - - // Store visited - for (uint32 i = 0; i < req; ++i) - path[i] = visited[(nvisited-1)-i]; - - return req+size; -} - -bool PathFinderMovementGenerator::getSteerTarget(const float* startPos, const float* endPos, - float minTargetDist, const dtPolyRef* path, uint32 pathSize, - float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef) -{ - // Find steer target. - static const uint32 MAX_STEER_POINTS = 3; - float steerPath[MAX_STEER_POINTS*VERTEX_SIZE]; - unsigned char steerPathFlags[MAX_STEER_POINTS]; - dtPolyRef steerPathPolys[MAX_STEER_POINTS]; - uint32 nsteerPath = 0; - dtStatus dtResult = m_navMeshQuery->findStraightPath(startPos, endPos, path, pathSize, - steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS); - if (!nsteerPath || DT_SUCCESS != dtResult) - return false; - - // Find vertex far enough to steer to. - uint32 ns = 0; - while (ns < nsteerPath) - { - // Stop at Off-Mesh link or when point is further than slop away. - if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || - !inRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f)) - break; - ns++; - } - // Failed to find good point to steer to. - if (ns >= nsteerPath) - return false; - - dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]); - steerPos[1] = startPos[1]; // keep Z value - steerPosFlag = steerPathFlags[ns]; - steerPosRef = steerPathPolys[ns]; - - return true; -} - -dtStatus PathFinderMovementGenerator::findSmoothPath(const float* startPos, const float* endPos, - const dtPolyRef* polyPath, uint32 polyPathSize, - float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize) -{ - *smoothPathSize = 0; - uint32 nsmoothPath = 0; - - dtPolyRef polys[MAX_PATH_LENGTH]; - memcpy(polys, polyPath, sizeof(dtPolyRef)*polyPathSize); - uint32 npolys = polyPathSize; - - float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE]; - if (DT_SUCCESS != m_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos)) - return DT_FAILURE; - - if (DT_SUCCESS != m_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos)) - return DT_FAILURE; - - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); - nsmoothPath++; - - // Move towards target a small advancement at a time until target reached or - // when ran out of memory to store the path. - while (npolys && nsmoothPath < maxSmoothPathSize) - { - // Find location to steer towards. - float steerPos[VERTEX_SIZE]; - unsigned char steerPosFlag; - dtPolyRef steerPosRef = INVALID_POLYREF; - - if (!getSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef)) - break; - - bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END); - bool offMeshConnection = (steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION); - - // Find movement delta. - float delta[VERTEX_SIZE]; - dtVsub(delta, steerPos, iterPos); - float len = dtSqrt(dtVdot(delta,delta)); - // If the steer target is end of path or off-mesh link, do not move past the location. - if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE) - len = 1.0f; - else - len = SMOOTH_PATH_STEP_SIZE / len; - - float moveTgt[VERTEX_SIZE]; - dtVmad(moveTgt, iterPos, delta, len); - - // Move - float result[VERTEX_SIZE]; - const static uint32 MAX_VISIT_POLY = 16; - dtPolyRef visited[MAX_VISIT_POLY]; - - uint32 nvisited = 0; - m_navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &m_filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY); - npolys = fixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited); - - m_navMeshQuery->getPolyHeight(polys[0], result, &result[1]); - result[1] += 0.5f; - dtVcopy(iterPos, result); - - // Handle end of path and off-mesh links when close enough. - if (endOfPath && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) - { - // Reached end of path. - dtVcopy(iterPos, targetPos); - if (nsmoothPath < maxSmoothPathSize) - { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); - nsmoothPath++; - } - break; - } - else if (offMeshConnection && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) - { - // Advance the path up to and over the off-mesh connection. - dtPolyRef prevRef = INVALID_POLYREF; - dtPolyRef polyRef = polys[0]; - uint32 npos = 0; - while (npos < npolys && polyRef != steerPosRef) - { - prevRef = polyRef; - polyRef = polys[npos]; - npos++; - } - - for (uint32 i = npos; i < npolys; ++i) - polys[i-npos] = polys[i]; - - npolys -= npos; - - // Handle the connection. - float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE]; - if (DT_SUCCESS == m_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos)) - { - if (nsmoothPath < maxSmoothPathSize) - { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos); - nsmoothPath++; - } - // Move position at the other side of the off-mesh link. - dtVcopy(iterPos, endPos); - m_navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]); - iterPos[1] += 0.5f; - } - } - - // Store results. - if (nsmoothPath < maxSmoothPathSize) - { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); - nsmoothPath++; - } - } - - *smoothPathSize = nsmoothPath; - - // this is most likely a loop - return nsmoothPath < MAX_POINT_PATH_LENGTH ? DT_SUCCESS : DT_FAILURE; -} - -bool PathFinderMovementGenerator::inRangeYZX(const float* v1, const float* v2, float r, float h) const -{ - const float dx = v2[0] - v1[0]; - const float dy = v2[1] - v1[1]; // elevation - const float dz = v2[2] - v1[2]; - return (dx*dx + dz*dz) < r*r && fabsf(dy) < h; -} - -bool PathFinderMovementGenerator::inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const -{ - Vector3 d = p1-p2; - return (d.x*d.x + d.y*d.y) < r*r && fabsf(d.z) < h; -} - -float PathFinderMovementGenerator::dist3DSqr(const Vector3 &p1, const Vector3 &p2) const -{ - return (p1-p2).squaredLength(); -} diff --git a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h deleted file mode 100644 index 9029fc1804e..00000000000 --- a/src/server/game/Movement/MovementGenerators/PathFinderMovementGenerator.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2005-2011 MaNGOS - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _PATH_INFO_H -#define _PATH_INFO_H - -#include "SharedDefines.h" -#include "DetourNavMesh.h" -#include "DetourNavMeshQuery.h" -#include "MoveSplineInitArgs.h" - -using Movement::Vector3; -using Movement::PointsArray; - -class Unit; - -// 74*4.0f=296y number_of_points*interval = max_path_len -// this is way more than actual evade range -// I think we can safely cut those down even more -#define MAX_PATH_LENGTH 74 -#define MAX_POINT_PATH_LENGTH 74 - -#define SMOOTH_PATH_STEP_SIZE 4.0f -#define SMOOTH_PATH_SLOP 0.3f - -#define VERTEX_SIZE 3 -#define INVALID_POLYREF 0 - -enum PathType -{ - PATHFIND_BLANK = 0x0000, // path not built yet - PATHFIND_NORMAL = 0x0001, // normal path - PATHFIND_SHORTCUT = 0x0002, // travel through obstacles, terrain, air, etc (old behavior) - PATHFIND_INCOMPLETE = 0x0004, // we have partial path to follow - getting closer to target - PATHFIND_NOPATH = 0x0008, // no valid path at all or error in generating one - PATHFIND_NOT_USING_PATH = 0x0010 // used when we are either flying/swiming or on map w/o mmaps -}; - -class PathFinderMovementGenerator -{ - public: - PathFinderMovementGenerator(Unit const* owner); - ~PathFinderMovementGenerator(); - - // Calculate the path from owner to given destination - // return: true if new path was calculated, false otherwise (no change needed) - bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false); - - // option setters - use optional - void SetUseStraightPath(bool useStraightPath) { m_useStraightPath = useStraightPath; }; - void setPathLengthLimit(float distance) { m_pointPathLimit = std::min(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }; - - // result getters - Vector3 getStartPosition() const { return m_startPosition; } - Vector3 getEndPosition() const { return m_endPosition; } - Vector3 getActualEndPosition() const { return m_actualEndPosition; } - - PointsArray& getPath() { return m_pathPoints; } - PathType getPathType() const { return m_type; } - - private: - - dtPolyRef m_pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references - uint32 m_polyLength; // number of polygons in the path - - PointsArray m_pathPoints; // our actual (x,y,z) path to the target - PathType m_type; // tells what kind of path this is - - bool m_useStraightPath; // type of path will be generated - bool m_forceDestination; // when set, we will always arrive at given point - uint32 m_pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH) - - Vector3 m_startPosition; // {x, y, z} of current location - Vector3 m_endPosition; // {x, y, z} of the destination - Vector3 m_actualEndPosition;// {x, y, z} of the closest possible point to given destination - - const Unit* const m_sourceUnit; // the unit that is moving - const dtNavMesh* m_navMesh; // the nav mesh - const dtNavMeshQuery* m_navMeshQuery; // the nav mesh query used to find the path - - dtQueryFilter m_filter; // use single filter for all movements, update it when needed - - void setStartPosition(Vector3 point) { m_startPosition = point; } - void setEndPosition(Vector3 point) { m_actualEndPosition = point; m_endPosition = point; } - void setActualEndPosition(Vector3 point) { m_actualEndPosition = point; } - - void NormalizePath(); - - void clear() - { - m_polyLength = 0; - m_pathPoints.clear(); - } - - bool inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const; - float dist3DSqr(const Vector3 &p1, const Vector3 &p2) const; - bool inRangeYZX(const float* v1, const float* v2, float r, float h) const; - - dtPolyRef getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance = NULL) const; - dtPolyRef getPolyByLocation(const float* point, float *distance) const; - bool HaveTile(const Vector3 &p) const; - - void BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos); - void BuildPointPath(const float *startPoint, const float *endPoint); - void BuildShortcut(); - - NavTerrain getNavTerrain(float x, float y, float z); - void createFilter(); - void updateFilter(); - - // smooth path aux functions - uint32 fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, - const dtPolyRef* visited, uint32 nvisited); - bool getSteerTarget(const float* startPos, const float* endPos, float minTargetDist, - const dtPolyRef* path, uint32 pathSize, float* steerPos, - unsigned char& steerPosFlag, dtPolyRef& steerPosRef); - dtStatus findSmoothPath(const float* startPos, const float* endPos, - const dtPolyRef* polyPath, uint32 polyPathSize, - float* smoothPath, int* smoothPathSize, uint32 smoothPathMaxSize); -}; - -#endif diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 1b14cd385e8..6d322a56a80 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -64,7 +64,7 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T &owner) } if (!i_path) - i_path = new PathFinderMovementGenerator(&owner); + i_path = new PathGenerator(&owner); // allow pets following their master to cheat while generating paths bool forceDest = (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->isPet() diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index d855dfa1875..db5e05c7b23 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -23,7 +23,7 @@ #include "FollowerReference.h" #include "Timer.h" #include "Unit.h" -#include "PathFinderMovementGenerator.h" +#include "PathGenerator.h" class TargetedMovementGeneratorBase { @@ -61,7 +61,7 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, float i_angle; bool i_recalculateTravel : 1; bool i_targetReached : 1; - PathFinderMovementGenerator* i_path; + PathGenerator* i_path; }; template diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp new file mode 100644 index 00000000000..4d7707020e1 --- /dev/null +++ b/src/server/game/Movement/PathGenerator.cpp @@ -0,0 +1,808 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "PathGenerator.h" +#include "Map.h" +#include "Creature.h" +#include "MMapFactory.h" +#include "MMapManager.h" +#include "Log.h" + +#include "DetourCommon.h" +#include "DetourNavMeshQuery.h" + +////////////////// PathGenerator ////////////////// +PathGenerator::PathGenerator(const Unit* owner) : + m_polyLength(0), m_type(PATHFIND_BLANK), + m_useStraightPath(false), m_forceDestination(false), m_pointPathLimit(MAX_POINT_PATH_LENGTH), + m_sourceUnit(owner), m_navMesh(NULL), m_navMeshQuery(NULL) +{ + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::PathGenerator for %u \n", m_sourceUnit->GetGUIDLow()); + + uint32 mapId = m_sourceUnit->GetMapId(); + if (MMAP::MMapFactory::IsPathfindingEnabled(mapId)) + { + MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); + m_navMesh = mmap->GetNavMesh(mapId); + m_navMeshQuery = mmap->GetNavMeshQuery(mapId, m_sourceUnit->GetInstanceId()); + } + + createFilter(); +} + +PathGenerator::~PathGenerator() +{ + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::~PathGenerator() for %u \n", m_sourceUnit->GetGUIDLow()); +} + +bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest) +{ + if (!Trinity::IsValidMapCoord(destX, destY, destZ) || + !Trinity::IsValidMapCoord(m_sourceUnit->GetPositionX(), m_sourceUnit->GetPositionY(), m_sourceUnit->GetPositionZ())) + return false; + + Vector3 oldDest = getEndPosition(); + Vector3 dest(destX, destY, destZ); + setEndPosition(dest); + + float x, y, z; + m_sourceUnit->GetPosition(x, y, z); + Vector3 start(x, y, z); + setStartPosition(start); + + m_forceDestination = forceDest; + + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::CalculatePath() for %u \n", m_sourceUnit->GetGUIDLow()); + + // make sure navMesh works - we can run on map w/o mmap + // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) + if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || + !HaveTile(start) || !HaveTile(dest)) + { + BuildShortcut(); + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + return true; + } + + updateFilter(); + + // check if destination moved - if not we can optimize something here + // we are following old, precalculated path? + float dist = m_sourceUnit->GetObjectSize(); + if (inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) + { + // our target is not moving - we just coming closer + // we are moving on precalculated path - enjoy the ride + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::CalculatePath:: precalculated path\n"); + + m_pathPoints.erase(m_pathPoints.begin()); + return false; + } + else + { + // target moved, so we need to update the poly path + BuildPolyPath(start, dest); + return true; + } +} + +dtPolyRef PathGenerator::getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance) const +{ + if (!polyPath || !polyPathSize) + return INVALID_POLYREF; + + dtPolyRef nearestPoly = INVALID_POLYREF; + float minDist2d = FLT_MAX; + float minDist3d = 0.0f; + + for (uint32 i = 0; i < polyPathSize; ++i) + { + float closestPoint[VERTEX_SIZE]; + if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint)) + continue; + + float d = dtVdist2DSqr(point, closestPoint); + if (d < minDist2d) + { + minDist2d = d; + nearestPoly = polyPath[i]; + minDist3d = dtVdistSqr(point, closestPoint); + } + + if(minDist2d < 1.0f) // shortcut out - close enough for us + break; + } + + if (distance) + *distance = dtSqrt(minDist3d); + + return (minDist2d < 3.0f) ? nearestPoly : INVALID_POLYREF; +} + +dtPolyRef PathGenerator::getPolyByLocation(const float* point, float *distance) const +{ + // first we check the current path + // if the current path doesn't contain the current poly, + // we need to use the expensive navMesh.findNearestPoly + dtPolyRef polyRef = getPathPolyByPosition(m_pathPolyRefs, m_polyLength, point, distance); + if (polyRef != INVALID_POLYREF) + return polyRef; + + // we don't have it in our old path + // try to get it by findNearestPoly() + // first try with low search box + float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area + float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f}; + dtStatus result = m_navMeshQuery->findNearestPoly(point, extents, &m_filter, &polyRef, closestPoint); + if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) + { + *distance = dtVdist(closestPoint, point); + return polyRef; + } + + // still nothing .. + // try with bigger search box + extents[1] = 200.0f; + result = m_navMeshQuery->findNearestPoly(point, extents, &m_filter, &polyRef, closestPoint); + if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) + { + *distance = dtVdist(closestPoint, point); + return polyRef; + } + + return INVALID_POLYREF; +} + +void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos) +{ + // *** getting start/end poly logic *** + + float distToStartPoly, distToEndPoly; + float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x}; + float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x}; + + dtPolyRef startPoly = getPolyByLocation(startPoint, &distToStartPoly); + dtPolyRef endPoly = getPolyByLocation(endPoint, &distToEndPoly); + + // we have a hole in our mesh + // make shortcut path and mark it as NOPATH ( with flying and swimming exception ) + // its up to caller how he will use this info + if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); + BuildShortcut(); + bool path = m_sourceUnit->GetTypeId() == TYPEID_UNIT && m_sourceUnit->ToCreature()->CanFly(); + + bool waterPath = m_sourceUnit->GetTypeId() == TYPEID_UNIT && m_sourceUnit->ToCreature()->canSwim(); + if (waterPath) + { + // Check both start and end points, if they're both in water, then we can *safely* let the creature move + for (int i = 0; i < m_pathPoints.size(); ++i) + { + LiquidData data; + m_sourceUnit->GetBaseMap()->getLiquidStatus(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z, MAP_ALL_LIQUIDS, &data); + // One of the points is not in the water, cancel movement. + if (data.type_flags == MAP_LIQUID_TYPE_NO_WATER) + { + waterPath = false; + break; + } + } + } + + m_type = (path || waterPath) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; + return; + } + + // we may need a better number here + bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f); + if (farFromPoly) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly); + + bool buildShotrcut = false; + if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) + { + Creature* owner = (Creature*)m_sourceUnit; + + Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos; + if (m_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: underWater case\n"); + if (owner->canSwim()) + buildShotrcut = true; + } + else + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: flying case\n"); + if (owner->CanFly()) + buildShotrcut = true; + } + } + + if (buildShotrcut) + { + BuildShortcut(); + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + return; + } + else + { + float closestPoint[VERTEX_SIZE]; + // we may want to use closestPointOnPolyBoundary instead + if (DT_SUCCESS == m_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) + { + dtVcopy(endPoint, closestPoint); + setActualEndPosition(Vector3(endPoint[2],endPoint[0],endPoint[1])); + } + + m_type = PATHFIND_INCOMPLETE; + } + } + + // *** poly path generating logic *** + + // start and end are on same polygon + // just need to move in straight line + if (startPoly == endPoly) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == endPoly)\n"); + + BuildShortcut(); + + m_pathPolyRefs[0] = startPoly; + m_polyLength = 1; + + m_type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL; + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: path type %d\n", m_type); + return; + } + + // look for startPoly/endPoly in current path + // TODO: we can merge it with getPathPolyByPosition() loop + bool startPolyFound = false; + bool endPolyFound = false; + uint32 pathStartIndex, pathEndIndex; + + if (m_polyLength) + { + for (pathStartIndex = 0; pathStartIndex < m_polyLength; ++pathStartIndex) + { + // here to carch few bugs + ASSERT(m_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); + + if (m_pathPolyRefs[pathStartIndex] == startPoly) + { + startPolyFound = true; + break; + } + } + + for (pathEndIndex = m_polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) + if (m_pathPolyRefs[pathEndIndex] == endPoly) + { + endPolyFound = true; + break; + } + } + + if (startPolyFound && endPolyFound) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPolyFound && endPolyFound)\n"); + + // we moved along the path and the target did not move out of our old poly-path + // our path is a simple subpath case, we have all the data we need + // just "cut" it out + + m_polyLength = pathEndIndex - pathStartIndex + 1; + memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, m_polyLength*sizeof(dtPolyRef)); + } + else if (startPolyFound && !endPolyFound) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n"); + + // we are moving on the old path but target moved out + // so we have atleast part of poly-path ready + + m_polyLength -= pathStartIndex; + + // try to adjust the suffix of the path instead of recalculating entire length + // at given interval the target cannot get too far from its last location + // thus we have less poly to cover + // sub-path of optimal path is optimal + + // take ~80% of the original length + // TODO : play with the values here + uint32 prefixPolyLength = uint32(m_polyLength*0.8f + 0.5f); + memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, prefixPolyLength*sizeof(dtPolyRef)); + + dtPolyRef suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; + + // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data + float suffixEndPoint[VERTEX_SIZE]; + if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) + { + // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that + // try to recover by using prev polyref + --prefixPolyLength; + suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; + if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) + { + // suffixStartPoly is still invalid, error state + BuildShortcut(); + m_type = PATHFIND_NOPATH; + return; + } + } + + // generate suffix + uint32 suffixPolyLength = 0; + dtStatus dtResult = m_navMeshQuery->findPath( + suffixStartPoly, // start polygon + endPoly, // end polygon + suffixEndPoint, // start position + endPoint, // end position + &m_filter, // polygon search filter + m_pathPolyRefs + prefixPolyLength - 1, // [out] path + (int*)&suffixPolyLength, + MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path + + if (!suffixPolyLength || dtResult != DT_SUCCESS) + { + // this is probably an error state, but we'll leave it + // and hopefully recover on the next Update + // we still need to copy our preffix + sLog->outError(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); + } + + sLog->outDebug(LOG_FILTER_MAPS, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength); + + // new path = prefix + suffix - overlap + m_polyLength = prefixPolyLength + suffixPolyLength - 1; + } + else + { + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n"); + + // either we have no path at all -> first run + // or something went really wrong -> we aren't moving along the path to the target + // just generate new path + + // free and invalidate old path data + clear(); + + dtStatus dtResult = m_navMeshQuery->findPath( + startPoly, // start polygon + endPoly, // end polygon + startPoint, // start position + endPoint, // end position + &m_filter, // polygon search filter + m_pathPolyRefs, // [out] path + (int*)&m_polyLength, + MAX_PATH_LENGTH); // max number of polygons in output path + + if (!m_polyLength || dtResult != DT_SUCCESS) + { + // only happens if we passed bad data to findPath(), or navmesh is messed up + sLog->outError(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); + BuildShortcut(); + m_type = PATHFIND_NOPATH; + return; + } + } + + // by now we know what type of path we can get + if (m_pathPolyRefs[m_polyLength - 1] == endPoly && !(m_type & PATHFIND_INCOMPLETE)) + m_type = PATHFIND_NORMAL; + else + m_type = PATHFIND_INCOMPLETE; + + // generate the point-path out of our up-to-date poly-path + BuildPointPath(startPoint, endPoint); +} + +void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoint) +{ + float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; + uint32 pointCount = 0; + dtStatus dtResult = DT_FAILURE; + if (m_useStraightPath) + { + dtResult = m_navMeshQuery->findStraightPath( + startPoint, // start position + endPoint, // end position + m_pathPolyRefs, // current path + m_polyLength, // lenth of current path + pathPoints, // [out] path corner points + NULL, // [out] flags + NULL, // [out] shortened path + (int*)&pointCount, + m_pointPathLimit); // maximum number of points/polygons to use + } + else + { + dtResult = findSmoothPath( + startPoint, // start position + endPoint, // end position + m_pathPolyRefs, // current path + m_polyLength, // length of current path + pathPoints, // [out] path corner points + (int*)&pointCount, + m_pointPathLimit); // maximum number of points + } + + if (pointCount < 2 || dtResult != DT_SUCCESS) + { + // only happens if pass bad data to findStraightPath or navmesh is broken + // single point paths can be generated here + // TODO : check the exact cases + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount); + BuildShortcut(); + m_type = PATHFIND_NOPATH; + return; + } + + m_pathPoints.resize(pointCount); + for (uint32 i = 0; i < pointCount; ++i) + m_pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); + + NormalizePath(); + + // first point is always our current location - we need the next one + setActualEndPosition(m_pathPoints[pointCount-1]); + + // force the given destination, if needed + if(m_forceDestination && + (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f))) + { + // we may want to keep partial subpath + if(dist3DSqr(getActualEndPosition(), getEndPosition()) < + 0.3f * dist3DSqr(getStartPosition(), getEndPosition())) + { + setActualEndPosition(getEndPosition()); + m_pathPoints[m_pathPoints.size()-1] = getEndPosition(); + } + else + { + setActualEndPosition(getEndPosition()); + BuildShortcut(); + } + + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + } + + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); +} + +void PathGenerator::NormalizePath() +{ + for (uint32 i = 0; i < m_pathPoints.size(); ++i) + m_sourceUnit->UpdateAllowedPositionZ(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z); +} + +void PathGenerator::BuildShortcut() +{ + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildShortcut :: making shortcut\n"); + + clear(); + + // make two point path, our curr pos is the start, and dest is the end + m_pathPoints.resize(2); + + // set start and a default next position + m_pathPoints[0] = getStartPosition(); + m_pathPoints[1] = getActualEndPosition(); + + NormalizePath(); + + m_type = PATHFIND_SHORTCUT; +} + +void PathGenerator::createFilter() +{ + uint16 includeFlags = 0; + uint16 excludeFlags = 0; + + if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) + { + Creature* creature = (Creature*)m_sourceUnit; + if (creature->canWalk()) + includeFlags |= NAV_GROUND; // walk + + // creatures don't take environmental damage + if (creature->canSwim()) + includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim + } + else if (m_sourceUnit->GetTypeId() == TYPEID_PLAYER) + { + // perfect support not possible, just stay 'safe' + includeFlags |= (NAV_GROUND | NAV_WATER); + } + + m_filter.setIncludeFlags(includeFlags); + m_filter.setExcludeFlags(excludeFlags); + + updateFilter(); +} + +void PathGenerator::updateFilter() +{ + // allow creatures to cheat and use different movement types if they are moved + // forcefully into terrain they can't normally move in + if (m_sourceUnit->IsInWater() || m_sourceUnit->IsUnderWater()) + { + uint16 includedFlags = m_filter.getIncludeFlags(); + includedFlags |= getNavTerrain(m_sourceUnit->GetPositionX(), + m_sourceUnit->GetPositionY(), + m_sourceUnit->GetPositionZ()); + + m_filter.setIncludeFlags(includedFlags); + } +} + +NavTerrain PathGenerator::getNavTerrain(float x, float y, float z) +{ + LiquidData data; + m_sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); + + switch (data.type_flags) + { + case MAP_LIQUID_TYPE_WATER: + case MAP_LIQUID_TYPE_OCEAN: + return NAV_WATER; + case MAP_LIQUID_TYPE_MAGMA: + return NAV_MAGMA; + case MAP_LIQUID_TYPE_SLIME: + return NAV_SLIME; + default: + return NAV_GROUND; + } +} + +bool PathGenerator::HaveTile(const Vector3 &p) const +{ + int tx, ty; + float point[VERTEX_SIZE] = {p.y, p.z, p.x}; + + m_navMesh->calcTileLoc(point, &tx, &ty); + return (m_navMesh->getTileAt(tx, ty) != NULL); +} + +uint32 PathGenerator::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, + const dtPolyRef* visited, uint32 nvisited) +{ + int32 furthestPath = -1; + int32 furthestVisited = -1; + + // Find furthest common polygon. + for (int32 i = npath-1; i >= 0; --i) + { + bool found = false; + for (int32 j = nvisited-1; j >= 0; --j) + { + if (path[i] == visited[j]) + { + furthestPath = i; + furthestVisited = j; + found = true; + } + } + if (found) + break; + } + + // If no intersection found just return current path. + if (furthestPath == -1 || furthestVisited == -1) + return npath; + + // Concatenate paths. + + // Adjust beginning of the buffer to include the visited. + uint32 req = nvisited - furthestVisited; + uint32 orig = uint32(furthestPath+1) < npath ? furthestPath+1 : npath; + uint32 size = npath-orig > 0 ? npath-orig : 0; + if (req+size > maxPath) + size = maxPath-req; + + if (size) + memmove(path+req, path+orig, size*sizeof(dtPolyRef)); + + // Store visited + for (uint32 i = 0; i < req; ++i) + path[i] = visited[(nvisited-1)-i]; + + return req+size; +} + +bool PathGenerator::getSteerTarget(const float* startPos, const float* endPos, + float minTargetDist, const dtPolyRef* path, uint32 pathSize, + float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef) +{ + // Find steer target. + static const uint32 MAX_STEER_POINTS = 3; + float steerPath[MAX_STEER_POINTS*VERTEX_SIZE]; + unsigned char steerPathFlags[MAX_STEER_POINTS]; + dtPolyRef steerPathPolys[MAX_STEER_POINTS]; + uint32 nsteerPath = 0; + dtStatus dtResult = m_navMeshQuery->findStraightPath(startPos, endPos, path, pathSize, + steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS); + if (!nsteerPath || DT_SUCCESS != dtResult) + return false; + + // Find vertex far enough to steer to. + uint32 ns = 0; + while (ns < nsteerPath) + { + // Stop at Off-Mesh link or when point is further than slop away. + if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || + !inRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f)) + break; + ns++; + } + // Failed to find good point to steer to. + if (ns >= nsteerPath) + return false; + + dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]); + steerPos[1] = startPos[1]; // keep Z value + steerPosFlag = steerPathFlags[ns]; + steerPosRef = steerPathPolys[ns]; + + return true; +} + +dtStatus PathGenerator::findSmoothPath(const float* startPos, const float* endPos, + const dtPolyRef* polyPath, uint32 polyPathSize, + float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize) +{ + *smoothPathSize = 0; + uint32 nsmoothPath = 0; + + dtPolyRef polys[MAX_PATH_LENGTH]; + memcpy(polys, polyPath, sizeof(dtPolyRef)*polyPathSize); + uint32 npolys = polyPathSize; + + float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE]; + if (DT_SUCCESS != m_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos)) + return DT_FAILURE; + + if (DT_SUCCESS != m_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos)) + return DT_FAILURE; + + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); + nsmoothPath++; + + // Move towards target a small advancement at a time until target reached or + // when ran out of memory to store the path. + while (npolys && nsmoothPath < maxSmoothPathSize) + { + // Find location to steer towards. + float steerPos[VERTEX_SIZE]; + unsigned char steerPosFlag; + dtPolyRef steerPosRef = INVALID_POLYREF; + + if (!getSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef)) + break; + + bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END); + bool offMeshConnection = (steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION); + + // Find movement delta. + float delta[VERTEX_SIZE]; + dtVsub(delta, steerPos, iterPos); + float len = dtSqrt(dtVdot(delta,delta)); + // If the steer target is end of path or off-mesh link, do not move past the location. + if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE) + len = 1.0f; + else + len = SMOOTH_PATH_STEP_SIZE / len; + + float moveTgt[VERTEX_SIZE]; + dtVmad(moveTgt, iterPos, delta, len); + + // Move + float result[VERTEX_SIZE]; + const static uint32 MAX_VISIT_POLY = 16; + dtPolyRef visited[MAX_VISIT_POLY]; + + uint32 nvisited = 0; + m_navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &m_filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY); + npolys = fixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited); + + m_navMeshQuery->getPolyHeight(polys[0], result, &result[1]); + result[1] += 0.5f; + dtVcopy(iterPos, result); + + // Handle end of path and off-mesh links when close enough. + if (endOfPath && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) + { + // Reached end of path. + dtVcopy(iterPos, targetPos); + if (nsmoothPath < maxSmoothPathSize) + { + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); + nsmoothPath++; + } + break; + } + else if (offMeshConnection && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) + { + // Advance the path up to and over the off-mesh connection. + dtPolyRef prevRef = INVALID_POLYREF; + dtPolyRef polyRef = polys[0]; + uint32 npos = 0; + while (npos < npolys && polyRef != steerPosRef) + { + prevRef = polyRef; + polyRef = polys[npos]; + npos++; + } + + for (uint32 i = npos; i < npolys; ++i) + polys[i-npos] = polys[i]; + + npolys -= npos; + + // Handle the connection. + float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE]; + if (DT_SUCCESS == m_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos)) + { + if (nsmoothPath < maxSmoothPathSize) + { + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos); + nsmoothPath++; + } + // Move position at the other side of the off-mesh link. + dtVcopy(iterPos, endPos); + m_navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]); + iterPos[1] += 0.5f; + } + } + + // Store results. + if (nsmoothPath < maxSmoothPathSize) + { + dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); + nsmoothPath++; + } + } + + *smoothPathSize = nsmoothPath; + + // this is most likely a loop + return nsmoothPath < MAX_POINT_PATH_LENGTH ? DT_SUCCESS : DT_FAILURE; +} + +bool PathGenerator::inRangeYZX(const float* v1, const float* v2, float r, float h) const +{ + const float dx = v2[0] - v1[0]; + const float dy = v2[1] - v1[1]; // elevation + const float dz = v2[2] - v1[2]; + return (dx*dx + dz*dz) < r*r && fabsf(dy) < h; +} + +bool PathGenerator::inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const +{ + Vector3 d = p1-p2; + return (d.x*d.x + d.y*d.y) < r*r && fabsf(d.z) < h; +} + +float PathGenerator::dist3DSqr(const Vector3 &p1, const Vector3 &p2) const +{ + return (p1-p2).squaredLength(); +} diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h new file mode 100644 index 00000000000..a0d925cb11f --- /dev/null +++ b/src/server/game/Movement/PathGenerator.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2005-2011 MaNGOS + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PATH_INFO_H +#define _PATH_INFO_H + +#include "SharedDefines.h" +#include "DetourNavMesh.h" +#include "DetourNavMeshQuery.h" +#include "MoveSplineInitArgs.h" + +using Movement::Vector3; +using Movement::PointsArray; + +class Unit; + +// 74*4.0f=296y number_of_points*interval = max_path_len +// this is way more than actual evade range +// I think we can safely cut those down even more +#define MAX_PATH_LENGTH 74 +#define MAX_POINT_PATH_LENGTH 74 + +#define SMOOTH_PATH_STEP_SIZE 4.0f +#define SMOOTH_PATH_SLOP 0.3f + +#define VERTEX_SIZE 3 +#define INVALID_POLYREF 0 + +enum PathType +{ + PATHFIND_BLANK = 0x0000, // path not built yet + PATHFIND_NORMAL = 0x0001, // normal path + PATHFIND_SHORTCUT = 0x0002, // travel through obstacles, terrain, air, etc (old behavior) + PATHFIND_INCOMPLETE = 0x0004, // we have partial path to follow - getting closer to target + PATHFIND_NOPATH = 0x0008, // no valid path at all or error in generating one + PATHFIND_NOT_USING_PATH = 0x0010 // used when we are either flying/swiming or on map w/o mmaps +}; + +class PathGenerator +{ + public: + PathGenerator(Unit const* owner); + ~PathGenerator(); + + // Calculate the path from owner to given destination + // return: true if new path was calculated, false otherwise (no change needed) + bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false); + + // option setters - use optional + void SetUseStraightPath(bool useStraightPath) { m_useStraightPath = useStraightPath; }; + void setPathLengthLimit(float distance) { m_pointPathLimit = std::min(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }; + + // result getters + Vector3 getStartPosition() const { return m_startPosition; } + Vector3 getEndPosition() const { return m_endPosition; } + Vector3 getActualEndPosition() const { return m_actualEndPosition; } + + PointsArray& getPath() { return m_pathPoints; } + PathType getPathType() const { return m_type; } + + private: + + dtPolyRef m_pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references + uint32 m_polyLength; // number of polygons in the path + + PointsArray m_pathPoints; // our actual (x,y,z) path to the target + PathType m_type; // tells what kind of path this is + + bool m_useStraightPath; // type of path will be generated + bool m_forceDestination; // when set, we will always arrive at given point + uint32 m_pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH) + + Vector3 m_startPosition; // {x, y, z} of current location + Vector3 m_endPosition; // {x, y, z} of the destination + Vector3 m_actualEndPosition;// {x, y, z} of the closest possible point to given destination + + const Unit* const m_sourceUnit; // the unit that is moving + const dtNavMesh* m_navMesh; // the nav mesh + const dtNavMeshQuery* m_navMeshQuery; // the nav mesh query used to find the path + + dtQueryFilter m_filter; // use single filter for all movements, update it when needed + + void setStartPosition(Vector3 point) { m_startPosition = point; } + void setEndPosition(Vector3 point) { m_actualEndPosition = point; m_endPosition = point; } + void setActualEndPosition(Vector3 point) { m_actualEndPosition = point; } + + void NormalizePath(); + + void clear() + { + m_polyLength = 0; + m_pathPoints.clear(); + } + + bool inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const; + float dist3DSqr(const Vector3 &p1, const Vector3 &p2) const; + bool inRangeYZX(const float* v1, const float* v2, float r, float h) const; + + dtPolyRef getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance = NULL) const; + dtPolyRef getPolyByLocation(const float* point, float *distance) const; + bool HaveTile(const Vector3 &p) const; + + void BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos); + void BuildPointPath(const float *startPoint, const float *endPoint); + void BuildShortcut(); + + NavTerrain getNavTerrain(float x, float y, float z); + void createFilter(); + void updateFilter(); + + // smooth path aux functions + uint32 fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, + const dtPolyRef* visited, uint32 nvisited); + bool getSteerTarget(const float* startPos, const float* endPos, float minTargetDist, + const dtPolyRef* path, uint32 pathSize, float* steerPos, + unsigned char& steerPosFlag, dtPolyRef& steerPosRef); + dtStatus findSmoothPath(const float* startPos, const float* endPos, + const dtPolyRef* polyPath, uint32 polyPathSize, + float* smoothPath, int* smoothPathSize, uint32 smoothPathMaxSize); +}; + +#endif diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index fa2197f815e..c5e314a8636 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -152,7 +152,7 @@ namespace Movement { if (generatePath) { - PathFinderMovementGenerator path(&unit); + PathGenerator path(&unit); path.CalculatePath(dest.x, dest.y, dest.z, forceDestination); MovebyPath(path.getPath()); } diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 9130d2827e6..759fc73d7fd 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -20,7 +20,7 @@ #define TRINITYSERVER_MOVESPLINEINIT_H #include "MoveSplineInitArgs.h" -#include "PathFinderMovementGenerator.h" +#include "PathGenerator.h" class Unit; -- cgit v1.2.3 From 97c3e2e6c105e3dd563ba1064e86f5503d3f22f6 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 25 Aug 2012 22:57:55 -0500 Subject: Core/Movement: Make MovementGenerators use pointers instead of references. cleanup --- src/server/game/Entities/Unit/Unit.cpp | 8 +- src/server/game/Entities/Vehicle/Vehicle.cpp | 2 +- src/server/game/Handlers/MovementHandler.cpp | 2 +- src/server/game/Movement/MotionMaster.cpp | 40 +++--- src/server/game/Movement/MovementGenerator.h | 37 ++--- .../ConfusedMovementGenerator.cpp | 60 ++++---- .../MovementGenerators/ConfusedMovementGenerator.h | 8 +- .../FleeingMovementGenerator.cpp | 108 +++++++-------- .../MovementGenerators/FleeingMovementGenerator.h | 16 +-- .../MovementGenerators/HomeMovementGenerator.cpp | 30 ++-- .../MovementGenerators/HomeMovementGenerator.h | 10 +- .../MovementGenerators/IdleMovementGenerator.cpp | 54 ++++---- .../MovementGenerators/IdleMovementGenerator.h | 26 ++-- .../MovementGenerators/PointMovementGenerator.cpp | 92 ++++++------- .../MovementGenerators/PointMovementGenerator.h | 22 +-- .../MovementGenerators/RandomMovementGenerator.cpp | 52 +++---- .../MovementGenerators/RandomMovementGenerator.h | 12 +- .../TargetedMovementGenerator.cpp | 152 ++++++++++----------- .../MovementGenerators/TargetedMovementGenerator.h | 52 +++---- .../WaypointMovementGenerator.cpp | 96 ++++++------- .../MovementGenerators/WaypointMovementGenerator.h | 32 ++--- src/server/game/Movement/Spline/MoveSplineInit.cpp | 48 +++---- src/server/game/Movement/Spline/MoveSplineInit.h | 10 +- .../Ulduar/Ulduar/boss_algalon_the_observer.cpp | 2 +- 24 files changed, 487 insertions(+), 484 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 183eddfcae4..b9396122bb1 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -372,7 +372,7 @@ bool Unit::haveOffhandWeapon() const void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath, bool forceDestination) { - Movement::MoveSplineInit init(*this); + Movement::MoveSplineInit init(this); init.MoveTo(x, y, z, generatePath, forceDestination); init.SetVelocity(speed); init.Launch(); @@ -14750,7 +14750,7 @@ void Unit::StopMoving() if (!IsInWorld()) return; - Movement::MoveSplineInit init(*this); + Movement::MoveSplineInit init(this); init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); init.SetFacing(GetOrientation()); init.Launch(); @@ -17152,7 +17152,7 @@ void Unit::_ExitVehicle(Position const* exitPosition) SendMessageToSet(&data, false); } - Movement::MoveSplineInit init(*this); + Movement::MoveSplineInit init(this); init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); init.SetFacing(GetOrientation()); init.SetTransportExit(); @@ -17562,7 +17562,7 @@ void Unit::SetInFront(Unit const* target) void Unit::SetFacingTo(float ori) { - Movement::MoveSplineInit init(*this); + Movement::MoveSplineInit init(this); init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); init.SetFacing(ori); init.Launch(); diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 710821f2f24..61e3fd877b4 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -365,7 +365,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) unit->SendClearTarget(); // SMSG_BREAK_TARGET unit->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) // also adds MOVEMENTFLAG_ROOT - Movement::MoveSplineInit init(*unit); + Movement::MoveSplineInit init(unit); init.DisableTransportPathTransformations(); init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); init.SetFacing(0.0f); diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 27b1f2eca3f..ca80921a7b2 100755 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -125,7 +125,7 @@ void WorldSession::HandleMoveWorldportAckOpcode() { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); - flight->Initialize(*GetPlayer()); + flight->Initialize(GetPlayer()); return; } diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 07d3760cf40..2ad8028ca4f 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -86,7 +86,7 @@ void MotionMaster::UpdateMotion(uint32 diff) ASSERT(!empty()); _cleanFlag |= MMCF_UPDATE; - if (!top()->Update(*_owner, diff)) + if (!top()->Update(_owner, diff)) { _cleanFlag &= ~MMCF_UPDATE; MovementExpired(); @@ -110,7 +110,7 @@ void MotionMaster::UpdateMotion(uint32 diff) else if (needInitTop()) InitTop(); else if (_cleanFlag & MMCF_RESET) - top()->Reset(*_owner); + top()->Reset(_owner); _cleanFlag &= ~MMCF_RESET; } @@ -131,7 +131,7 @@ void MotionMaster::DirectClean(bool reset) if (needInitTop()) InitTop(); else if (reset) - top()->Reset(*_owner); + top()->Reset(_owner); } void MotionMaster::DelayedClean() @@ -162,7 +162,7 @@ void MotionMaster::DirectExpire(bool reset) else if (needInitTop()) InitTop(); else if (reset) - top()->Reset(*_owner); + top()->Reset(_owner); } void MotionMaster::DelayedExpire() @@ -198,19 +198,19 @@ void MotionMaster::MoveTargetedHome() { Clear(false); - if (_owner->GetTypeId()==TYPEID_UNIT && !((Creature*)_owner)->GetCharmerOrOwnerGUID()) + if (_owner->GetTypeId() == TYPEID_UNIT && !_owner->ToCreature()->GetCharmerOrOwnerGUID()) { sLog->outDebug(LOG_FILTER_GENERAL, "Creature (Entry: %u GUID: %u) targeted home", _owner->GetEntry(), _owner->GetGUIDLow()); Mutate(new HomeMovementGenerator(), MOTION_SLOT_ACTIVE); } - else if (_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)_owner)->GetCharmerOrOwnerGUID()) + else if (_owner->GetTypeId() == TYPEID_UNIT && _owner->ToCreature()->GetCharmerOrOwnerGUID()) { sLog->outDebug(LOG_FILTER_GENERAL, "Pet or controlled creature (Entry: %u GUID: %u) targeting home", _owner->GetEntry(), _owner->GetGUIDLow()); - Unit *target = ((Creature*)_owner)->GetCharmerOrOwner(); + Unit* target = _owner->ToCreature()->GetCharmerOrOwner(); if (target) { sLog->outDebug(LOG_FILTER_GENERAL, "Following %s (GUID: %u)", target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow()); - Mutate(new FollowMovementGenerator(*target,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE), MOTION_SLOT_ACTIVE); + Mutate(new FollowMovementGenerator(target, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE), MOTION_SLOT_ACTIVE); } } else @@ -247,7 +247,7 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle) _owner->GetGUIDLow(), target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow()); - Mutate(new ChaseMovementGenerator(*target,dist,angle), MOTION_SLOT_ACTIVE); + Mutate(new ChaseMovementGenerator(target, dist, angle), MOTION_SLOT_ACTIVE); } else { @@ -255,7 +255,7 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle) _owner->GetEntry(), _owner->GetGUIDLow(), target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow()); - Mutate(new ChaseMovementGenerator(*target,dist,angle), MOTION_SLOT_ACTIVE); + Mutate(new ChaseMovementGenerator(target, dist, angle), MOTION_SLOT_ACTIVE); } } @@ -271,7 +271,7 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlo sLog->outDebug(LOG_FILTER_GENERAL, "Player (GUID: %u) follow to %s (GUID: %u)", _owner->GetGUIDLow(), target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow()); - Mutate(new FollowMovementGenerator(*target,dist,angle), slot); + Mutate(new FollowMovementGenerator(target, dist, angle), slot); } else { @@ -279,7 +279,7 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlo _owner->GetEntry(), _owner->GetGUIDLow(), target->GetTypeId() == TYPEID_PLAYER ? "player" : "creature", target->GetTypeId() == TYPEID_PLAYER ? target->GetGUIDLow() : target->ToCreature()->GetDBTableGUIDLow()); - Mutate(new FollowMovementGenerator(*target,dist,angle), slot); + Mutate(new FollowMovementGenerator(target, dist, angle), slot); } } @@ -305,7 +305,7 @@ void MotionMaster::MoveLand(uint32 id, Position const& pos) sLog->outDebug(LOG_FILTER_GENERAL, "Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)", _owner->GetEntry(), id, x, y, z); - Movement::MoveSplineInit init(*_owner); + Movement::MoveSplineInit init(_owner); init.MoveTo(x,y,z); init.SetAnimation(Movement::ToGround); init.Launch(); @@ -319,7 +319,7 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos) sLog->outDebug(LOG_FILTER_GENERAL, "Creature (Entry: %u) landing point (ID: %u X: %f Y: %f Z: %f)", _owner->GetEntry(), id, x, y, z); - Movement::MoveSplineInit init(*_owner); + Movement::MoveSplineInit init(_owner); init.MoveTo(x,y,z); init.SetAnimation(Movement::ToFly); init.Launch(); @@ -339,7 +339,7 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa _owner->GetNearPoint(_owner, x, y, z, _owner->GetObjectSize(), dist, _owner->GetAngle(srcX, srcY) + M_PI); - Movement::MoveSplineInit init(*_owner); + Movement::MoveSplineInit init(_owner); init.MoveTo(x,y,z); init.SetParabolic(max_height,0); init.SetOrientationFixed(true); @@ -369,7 +369,7 @@ void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float spee float moveTimeHalf = speedZ / Movement::gravity; float max_height = -Movement::computeFallElevation(moveTimeHalf,false,-speedZ); - Movement::MoveSplineInit init(*_owner); + Movement::MoveSplineInit init(_owner); init.MoveTo(x, y, z, false); init.SetParabolic(max_height,0); init.SetVelocity(speedXY); @@ -398,7 +398,7 @@ void MotionMaster::MoveFall(uint32 id/*=0*/) _owner->m_movementInfo.SetFallTime(0); } - Movement::MoveSplineInit init(*_owner); + Movement::MoveSplineInit init(_owner); init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz); init.SetFall(); init.Launch(); @@ -545,7 +545,7 @@ void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot) else { _needInit[slot] = false; - m->Initialize(*_owner); + m->Initialize(_owner); } } @@ -613,7 +613,7 @@ MovementGeneratorType MotionMaster::GetMotionSlotType(int slot) const void MotionMaster::InitTop() { - top()->Initialize(*_owner); + top()->Initialize(_owner); _needInit[_top] = false; } @@ -621,7 +621,7 @@ void MotionMaster::DirectDelete(_Ty curr) { if (isStatic(curr)) return; - curr->Finalize(*_owner); + curr->Finalize(_owner); delete curr; } diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h index 85e1fec0c2d..ee8dfb51cce 100755 --- a/src/server/game/Movement/MovementGenerator.h +++ b/src/server/game/Movement/MovementGenerator.h @@ -33,51 +33,54 @@ class MovementGenerator public: virtual ~MovementGenerator(); - virtual void Initialize(Unit &) = 0; - virtual void Finalize(Unit &) = 0; + virtual void Initialize(Unit*) = 0; + virtual void Finalize(Unit*) = 0; - virtual void Reset(Unit &) = 0; + virtual void Reset(Unit*) = 0; - virtual bool Update(Unit &, const uint32& time_diff) = 0; + virtual bool Update(Unit*, const uint32& time_diff) = 0; virtual MovementGeneratorType GetMovementGeneratorType() = 0; virtual void unitSpeedChanged() { } // used by Evade code for select point to evade with expected restart default movement - virtual bool GetResetPosition(Unit &, float& /*x*/, float& /*y*/, float& /*z*/) { return false; } + virtual bool GetResetPosition(Unit*, float& /*x*/, float& /*y*/, float& /*z*/) { return false; } }; template class MovementGeneratorMedium : public MovementGenerator { public: - void Initialize(Unit &u) + void Initialize(Unit* u) { //u->AssertIsType(); - (static_cast(this))->Initialize(*((T*)&u)); + (static_cast(this))->Initialize(static_cast(u)); } - void Finalize(Unit &u) + + void Finalize(Unit* u) { //u->AssertIsType(); - (static_cast(this))->Finalize(*((T*)&u)); + (static_cast(this))->Finalize(static_cast(u)); } - void Reset(Unit &u) + + void Reset(Unit* u) { //u->AssertIsType(); - (static_cast(this))->Reset(*((T*)&u)); + (static_cast(this))->Reset(static_cast(u)); } - bool Update(Unit &u, const uint32& time_diff) + + bool Update(Unit* u, const uint32& time_diff) { //u->AssertIsType(); - return (static_cast(this))->Update(*((T*)&u), time_diff); + return (static_cast(this))->Update(static_cast(u), time_diff); } public: // will not link if not overridden in the generators - void Initialize(T &u); - void Finalize(T &u); - void Reset(T &u); - bool Update(T &u, const uint32& time_diff); + void Initialize(T* u); + void Finalize(T* u); + void Reset(T* u); + bool Update(T* u, const uint32& time_diff); }; struct SelectableMovement : public FactoryHolder diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index b9b69baf0f8..f1d1d8cf04a 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -31,34 +31,34 @@ #endif template -void ConfusedMovementGenerator::Initialize(T &unit) +void ConfusedMovementGenerator::Initialize(T* unit) { - unit.GetPosition(i_x, i_y, i_z); - unit.StopMoving(); - unit.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); - unit.AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); + unit->GetPosition(i_x, i_y, i_z); + unit->StopMoving(); + unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); + unit->AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); } template -void ConfusedMovementGenerator::Reset(T &unit) +void ConfusedMovementGenerator::Reset(T* unit) { i_nextMoveTime.Reset(0); - unit.StopMoving(); - unit.AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); + unit->StopMoving(); + unit->AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); } template -bool ConfusedMovementGenerator::Update(T &unit, const uint32 &diff) +bool ConfusedMovementGenerator::Update(T* unit, const uint32& diff) { - if (unit.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) + if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) return true; if (i_nextMoveTime.Passed()) { // currently moving, update location - unit.AddUnitState(UNIT_STATE_CONFUSED_MOVE); + unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE); - if (unit.movespline->Finalized()) + if (unit->movespline->Finalized()) i_nextMoveTime.Reset(urand(800, 1500)); } else @@ -68,15 +68,15 @@ bool ConfusedMovementGenerator::Update(T &unit, const uint32 &diff) if (i_nextMoveTime.Passed()) { // start moving - unit.AddUnitState(UNIT_STATE_CONFUSED_MOVE); + unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE); float x = i_x + 10.0f*((float)rand_norm() - 0.5f); float y = i_y + 10.0f*((float)rand_norm() - 0.5f); float z = i_z; - unit.UpdateAllowedPositionZ(x, y, z); + unit->UpdateAllowedPositionZ(x, y, z); - PathGenerator path(&unit); + PathGenerator path(unit); path.setPathLengthLimit(30.0f); path.CalculatePath(x, y, z); if (path.getPathType() & PATHFIND_NOPATH) @@ -96,26 +96,26 @@ bool ConfusedMovementGenerator::Update(T &unit, const uint32 &diff) } template<> -void ConfusedMovementGenerator::Finalize(Player &unit) +void ConfusedMovementGenerator::Finalize(Player* unit) { - unit.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); - unit.ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); - unit.StopMoving(); + unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); + unit->ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); + unit->StopMoving(); } template<> -void ConfusedMovementGenerator::Finalize(Creature &unit) +void ConfusedMovementGenerator::Finalize(Creature* unit) { - unit.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); - unit.ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); - if (unit.getVictim()) - unit.SetTarget(unit.getVictim()->GetGUID()); + unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); + unit->ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); + if (unit->getVictim()) + unit->SetTarget(unit->getVictim()->GetGUID()); } -template void ConfusedMovementGenerator::Initialize(Player &player); -template void ConfusedMovementGenerator::Initialize(Creature &creature); -template void ConfusedMovementGenerator::Reset(Player &player); -template void ConfusedMovementGenerator::Reset(Creature &creature); -template bool ConfusedMovementGenerator::Update(Player &player, const uint32 &diff); -template bool ConfusedMovementGenerator::Update(Creature &creature, const uint32 &diff); +template void ConfusedMovementGenerator::Initialize(Player*); +template void ConfusedMovementGenerator::Initialize(Creature*); +template void ConfusedMovementGenerator::Reset(Player*); +template void ConfusedMovementGenerator::Reset(Creature*); +template bool ConfusedMovementGenerator::Update(Player*, const uint32&); +template bool ConfusedMovementGenerator::Update(Creature*, const uint32&); diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h index 72ffd7b734b..5b535e2d47d 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h @@ -28,10 +28,10 @@ class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMov public: explicit ConfusedMovementGenerator() : i_nextMoveTime(0) {} - void Initialize(T &); - void Finalize(T &); - void Reset(T &); - bool Update(T &, const uint32 &); + void Initialize(T*); + void Finalize(T*); + void Reset(T*); + bool Update(T*, const uint32&); MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; } private: diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index ae1e89c8562..e04f7b6fcbc 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -29,21 +29,21 @@ #define MAX_QUIET_DISTANCE 43.0f template -void FleeingMovementGenerator::_setTargetLocation(T &owner) +void FleeingMovementGenerator::_setTargetLocation(T* owner) { - if (!&owner) + if (!owner) return; - if (owner.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) + if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) return; float x, y, z; if (!_getPoint(owner, x, y, z)) return; - owner.AddUnitState(UNIT_STATE_FLEEING_MOVE); + owner->AddUnitState(UNIT_STATE_FLEEING_MOVE); - PathGenerator path(&owner); + PathGenerator path(owner); path.setPathLengthLimit(30.0f); path.CalculatePath(x, y, z); if (path.getPathType() & PATHFIND_NOPATH) @@ -60,17 +60,17 @@ void FleeingMovementGenerator::_setTargetLocation(T &owner) } template -bool FleeingMovementGenerator::_getPoint(T &owner, float &x, float &y, float &z) +bool FleeingMovementGenerator::_getPoint(T* owner, float &x, float &y, float &z) { - if (!&owner) + if (!owner) return false; float dist_from_caster, angle_to_caster; - if (Unit* fright = ObjectAccessor::GetUnit(owner, i_frightGUID)) + if (Unit* fright = ObjectAccessor::GetUnit(*owner, i_frightGUID)) { - dist_from_caster = fright->GetDistance(&owner); + dist_from_caster = fright->GetDistance(owner); if (dist_from_caster > 0.2f) - angle_to_caster = fright->GetAngle(&owner); + angle_to_caster = fright->GetAngle(owner); else angle_to_caster = frand(0, 2 * static_cast(M_PI)); } @@ -98,106 +98,106 @@ bool FleeingMovementGenerator::_getPoint(T &owner, float &x, float &y, float } float curr_x, curr_y, curr_z; - owner.GetPosition(curr_x, curr_y, curr_z); + owner->GetPosition(curr_x, curr_y, curr_z); x = curr_x + dist*cos(angle); y = curr_y + dist*sin(angle); z = curr_z; - owner.UpdateAllowedPositionZ(x, y, z); + owner->UpdateAllowedPositionZ(x, y, z); return true; } template -void FleeingMovementGenerator::Initialize(T &owner) +void FleeingMovementGenerator::Initialize(T* owner) { - if (!&owner) + if (!owner) return; - owner.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner.AddUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); + owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + owner->AddUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); - if (owner.GetTypeId() == TYPEID_UNIT) + if (owner->GetTypeId() == TYPEID_UNIT) return; _setTargetLocation(owner); } template<> -void FleeingMovementGenerator::Finalize(Player &owner) +void FleeingMovementGenerator::Finalize(Player* owner) { - owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner.ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); - owner.StopMoving(); + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE); + owner->StopMoving(); } template<> -void FleeingMovementGenerator::Finalize(Creature &owner) +void FleeingMovementGenerator::Finalize(Creature* owner) { - owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner.ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); - if (owner.getVictim()) - owner.SetTarget(owner.getVictim()->GetGUID()); + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); + if (owner->getVictim()) + owner->SetTarget(owner->getVictim()->GetGUID()); } template -void FleeingMovementGenerator::Reset(T &owner) +void FleeingMovementGenerator::Reset(T* owner) { Initialize(owner); } template -bool FleeingMovementGenerator::Update(T &owner, const uint32 &time_diff) +bool FleeingMovementGenerator::Update(T* owner, const uint32& time_diff) { - if (!&owner || !owner.isAlive()) + if (!owner || !owner->isAlive()) return false; - if (owner.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) + if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) { - owner.ClearUnitState(UNIT_STATE_FLEEING_MOVE); + owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE); return true; } i_nextCheckTime.Update(time_diff); - if (i_nextCheckTime.Passed() && owner.movespline->Finalized()) + if (i_nextCheckTime.Passed() && owner->movespline->Finalized()) _setTargetLocation(owner); return true; } -template void FleeingMovementGenerator::Initialize(Player &); -template void FleeingMovementGenerator::Initialize(Creature &); -template bool FleeingMovementGenerator::_getPoint(Player &, float &, float &, float &); -template bool FleeingMovementGenerator::_getPoint(Creature &, float &, float &, float &); -template void FleeingMovementGenerator::_setTargetLocation(Player &); -template void FleeingMovementGenerator::_setTargetLocation(Creature &); -template void FleeingMovementGenerator::Reset(Player &); -template void FleeingMovementGenerator::Reset(Creature &); -template bool FleeingMovementGenerator::Update(Player &, const uint32 &); -template bool FleeingMovementGenerator::Update(Creature &, const uint32 &); - -void TimedFleeingMovementGenerator::Finalize(Unit &owner) +template void FleeingMovementGenerator::Initialize(Player*); +template void FleeingMovementGenerator::Initialize(Creature*); +template bool FleeingMovementGenerator::_getPoint(Player*, float&, float&, float&); +template bool FleeingMovementGenerator::_getPoint(Creature*, float&, float&, float&); +template void FleeingMovementGenerator::_setTargetLocation(Player*); +template void FleeingMovementGenerator::_setTargetLocation(Creature*); +template void FleeingMovementGenerator::Reset(Player*); +template void FleeingMovementGenerator::Reset(Creature*); +template bool FleeingMovementGenerator::Update(Player*, const uint32&); +template bool FleeingMovementGenerator::Update(Creature*, const uint32&); + +void TimedFleeingMovementGenerator::Finalize(Unit* owner) { - owner.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner.ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); - if (Unit* victim = owner.getVictim()) + owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); + owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); + if (Unit* victim = owner->getVictim()) { - if (owner.isAlive()) + if (owner->isAlive()) { - owner.AttackStop(); - owner.ToCreature()->AI()->AttackStart(victim); + owner->AttackStop(); + owner->ToCreature()->AI()->AttackStart(victim); } } } -bool TimedFleeingMovementGenerator::Update(Unit & owner, const uint32& time_diff) +bool TimedFleeingMovementGenerator::Update(Unit* owner, const uint32& time_diff) { - if (!owner.isAlive()) + if (!owner->isAlive()) return false; - if (owner.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) + if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) { - owner.ClearUnitState(UNIT_STATE_FLEEING_MOVE); + owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE); return true; } diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h index cb3bd1cb69a..88dedd31af6 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h @@ -27,16 +27,16 @@ class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovem public: FleeingMovementGenerator(uint64 fright) : i_frightGUID(fright), i_nextCheckTime(0) {} - void Initialize(T &); - void Finalize(T &); - void Reset(T &); - bool Update(T &, const uint32 &); + void Initialize(T*); + void Finalize(T*); + void Reset(T*); + bool Update(T*, const uint32&); MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; } private: - void _setTargetLocation(T &owner); - bool _getPoint(T &owner, float &x, float &y, float &z); + void _setTargetLocation(T*); + bool _getPoint(T*, float &x, float &y, float &z); uint64 i_frightGUID; TimeTracker i_nextCheckTime; @@ -50,8 +50,8 @@ class TimedFleeingMovementGenerator : public FleeingMovementGenerator i_totalFleeTime(time) {} MovementGeneratorType GetMovementGeneratorType() { return TIMED_FLEEING_MOTION_TYPE; } - bool Update(Unit &, const uint32&); - void Finalize(Unit &); + bool Update(Unit*, const uint32&); + void Finalize(Unit*); private: TimeTracker i_totalFleeTime; diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index f122349a71c..78c1f80005c 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -23,49 +23,49 @@ #include "MoveSplineInit.h" #include "MoveSpline.h" -void HomeMovementGenerator::Initialize(Creature& owner) +void HomeMovementGenerator::Initialize(Creature* owner) { _setTargetLocation(owner); } -void HomeMovementGenerator::Finalize(Creature& owner) +void HomeMovementGenerator::Finalize(Creature* owner) { if (arrived) { - owner.ClearUnitState(UNIT_STATE_EVADE); - owner.SetWalk(true); - owner.LoadCreaturesAddon(true); - owner.AI()->JustReachedHome(); + owner->ClearUnitState(UNIT_STATE_EVADE); + owner->SetWalk(true); + owner->LoadCreaturesAddon(true); + owner->AI()->JustReachedHome(); } } -void HomeMovementGenerator::Reset(Creature &) +void HomeMovementGenerator::Reset(Creature*) { } -void HomeMovementGenerator::_setTargetLocation(Creature & owner) +void HomeMovementGenerator::_setTargetLocation(Creature* owner) { - if (owner.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) + if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) return; Movement::MoveSplineInit init(owner); float x, y, z, o; // at apply we can select more nice return points base at current movegen - if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner,x,y,z)) + if (owner->GetMotionMaster()->empty() || !owner->GetMotionMaster()->top()->GetResetPosition(owner, x, y, z)) { - owner.GetHomePosition(x, y, z, o); + owner->GetHomePosition(x, y, z, o); init.SetFacing(o); } - init.MoveTo(x,y,z); + init.MoveTo(x, y, z); init.SetWalk(false); init.Launch(); arrived = false; - owner.ClearUnitState(UNIT_STATE_ALL_STATE & ~UNIT_STATE_EVADE); + owner->ClearUnitState(UNIT_STATE_ALL_STATE & ~UNIT_STATE_EVADE); } -bool HomeMovementGenerator::Update(Creature &owner, const uint32 /*time_diff*/) +bool HomeMovementGenerator::Update(Creature* owner, const uint32 /*time_diff*/) { - arrived = owner.movespline->Finalized(); + arrived = owner->movespline->Finalized(); return !arrived; } diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h index 95eb05f281c..dfbea60d353 100755 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h @@ -34,14 +34,14 @@ class HomeMovementGenerator : public MovementGeneratorMedium< Creature HomeMovementGenerator() : arrived(false) {} ~HomeMovementGenerator() {} - void Initialize(Creature &); - void Finalize(Creature &); - void Reset(Creature &); - bool Update(Creature &, const uint32); + void Initialize(Creature*); + void Finalize(Creature*); + void Reset(Creature*); + bool Update(Creature*, const uint32); MovementGeneratorType GetMovementGeneratorType() { return HOME_MOTION_TYPE; } private: - void _setTargetLocation(Creature &); + void _setTargetLocation(Creature*); bool arrived; }; #endif diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp index 5a2090cfe28..8ef9bd7697a 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp @@ -24,33 +24,33 @@ IdleMovementGenerator si_idleMovement; // StopMoving is needed to make unit stop if its last movement generator expires // But it should not be sent otherwise there are many redundent packets -void IdleMovementGenerator::Initialize(Unit &owner) +void IdleMovementGenerator::Initialize(Unit* owner) { Reset(owner); } -void IdleMovementGenerator::Reset(Unit& owner) +void IdleMovementGenerator::Reset(Unit* owner) { - if (!owner.IsStopped()) - owner.StopMoving(); + if (!owner->IsStopped()) + owner->StopMoving(); } -void RotateMovementGenerator::Initialize(Unit& owner) +void RotateMovementGenerator::Initialize(Unit* owner) { - if (!owner.IsStopped()) - owner.StopMoving(); + if (!owner->IsStopped()) + owner->StopMoving(); - if (owner.getVictim()) - owner.SetInFront(owner.getVictim()); + if (owner->getVictim()) + owner->SetInFront(owner->getVictim()); - owner.AddUnitState(UNIT_STATE_ROTATING); + owner->AddUnitState(UNIT_STATE_ROTATING); - owner.AttackStop(); + owner->AttackStop(); } -bool RotateMovementGenerator::Update(Unit& owner, const uint32& diff) +bool RotateMovementGenerator::Update(Unit* owner, const uint32& diff) { - float angle = owner.GetOrientation(); + float angle = owner->GetOrientation(); if (m_direction == ROTATE_DIRECTION_LEFT) { angle += (float)diff * static_cast(M_PI * 2) / m_maxDuration; @@ -61,8 +61,8 @@ bool RotateMovementGenerator::Update(Unit& owner, const uint32& diff) angle -= (float)diff * static_cast(M_PI * 2) / m_maxDuration; while (angle < 0) angle += static_cast(M_PI * 2); } - owner.SetOrientation(angle); - owner.SendMovementFlagUpdate(); // this is a hack. we do not have anything correct to send in the beginning + owner->SetOrientation(angle); + owner->SendMovementFlagUpdate(); // this is a hack. we do not have anything correct to send in the beginning if (m_duration > diff) m_duration -= diff; @@ -72,24 +72,24 @@ bool RotateMovementGenerator::Update(Unit& owner, const uint32& diff) return true; } -void RotateMovementGenerator::Finalize(Unit &unit) +void RotateMovementGenerator::Finalize(Unit* unit) { - unit.ClearUnitState(UNIT_STATE_ROTATING); - if (unit.GetTypeId() == TYPEID_UNIT) - unit.ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0); + unit->ClearUnitState(UNIT_STATE_ROTATING); + if (unit->GetTypeId() == TYPEID_UNIT) + unit->ToCreature()->AI()->MovementInform(ROTATE_MOTION_TYPE, 0); } -void DistractMovementGenerator::Initialize(Unit& owner) +void DistractMovementGenerator::Initialize(Unit* owner) { - owner.AddUnitState(UNIT_STATE_DISTRACTED); + owner->AddUnitState(UNIT_STATE_DISTRACTED); } -void DistractMovementGenerator::Finalize(Unit& owner) +void DistractMovementGenerator::Finalize(Unit* owner) { - owner.ClearUnitState(UNIT_STATE_DISTRACTED); + owner->ClearUnitState(UNIT_STATE_DISTRACTED); } -bool DistractMovementGenerator::Update(Unit& /*owner*/, const uint32& time_diff) +bool DistractMovementGenerator::Update(Unit* /*owner*/, const uint32& time_diff) { if (time_diff > m_timer) return false; @@ -98,9 +98,9 @@ bool DistractMovementGenerator::Update(Unit& /*owner*/, const uint32& time_diff) return true; } -void AssistanceDistractMovementGenerator::Finalize(Unit &unit) +void AssistanceDistractMovementGenerator::Finalize(Unit* unit) { - unit.ClearUnitState(UNIT_STATE_DISTRACTED); - unit.ToCreature()->SetReactState(REACT_AGGRESSIVE); + unit->ClearUnitState(UNIT_STATE_DISTRACTED); + unit->ToCreature()->SetReactState(REACT_AGGRESSIVE); } diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h index 7acec82af98..14287d871c9 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h @@ -25,10 +25,10 @@ class IdleMovementGenerator : public MovementGenerator { public: - void Initialize(Unit &); - void Finalize(Unit &) { } - void Reset(Unit &); - bool Update(Unit &, const uint32&) { return true; } + void Initialize(Unit*); + void Finalize(Unit*) { } + void Reset(Unit*); + bool Update(Unit*, const uint32&) { return true; } MovementGeneratorType GetMovementGeneratorType() { return IDLE_MOTION_TYPE; } }; @@ -39,10 +39,10 @@ class RotateMovementGenerator : public MovementGenerator public: explicit RotateMovementGenerator(uint32 time, RotateDirection direction) : m_duration(time), m_maxDuration(time), m_direction(direction) {} - void Initialize(Unit& owner); - void Finalize(Unit& owner); - void Reset(Unit& owner) { Initialize(owner); } - bool Update(Unit& owner, const uint32& time_diff); + void Initialize(Unit*); + void Finalize(Unit*); + void Reset(Unit* owner) { Initialize(owner); } + bool Update(Unit*, const uint32&); MovementGeneratorType GetMovementGeneratorType() { return ROTATE_MOTION_TYPE; } private: @@ -55,10 +55,10 @@ class DistractMovementGenerator : public MovementGenerator public: explicit DistractMovementGenerator(uint32 timer) : m_timer(timer) {} - void Initialize(Unit& owner); - void Finalize(Unit& owner); - void Reset(Unit& owner) { Initialize(owner); } - bool Update(Unit& owner, const uint32& time_diff); + void Initialize(Unit*); + void Finalize(Unit*); + void Reset(Unit* owner) { Initialize(owner); } + bool Update(Unit*, const uint32&); MovementGeneratorType GetMovementGeneratorType() { return DISTRACT_MOTION_TYPE; } private: @@ -72,7 +72,7 @@ class AssistanceDistractMovementGenerator : public DistractMovementGenerator DistractMovementGenerator(timer) {} MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_DISTRACT_MOTION_TYPE; } - void Finalize(Unit& unit); + void Finalize(Unit*); }; #endif diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index cdb8a0a2a05..c8a7c8f8f8d 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -27,12 +27,12 @@ //----- Point Movement Generator template -void PointMovementGenerator::Initialize(T &unit) +void PointMovementGenerator::Initialize(T* unit) { - if (!unit.IsStopped()) - unit.StopMoving(); + if (!unit->IsStopped()) + unit->StopMoving(); - unit.AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); i_recalculateSpeed = false; Movement::MoveSplineInit init(unit); init.MoveTo(i_x, i_y, i_z, m_generatePath); @@ -42,20 +42,20 @@ void PointMovementGenerator::Initialize(T &unit) } template -bool PointMovementGenerator::Update(T &unit, const uint32 & /*diff*/) +bool PointMovementGenerator::Update(T* unit, const uint32& /*diff*/) { - if (!&unit) + if (!unit) return false; - if (unit.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) + if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) { - unit.ClearUnitState(UNIT_STATE_ROAMING_MOVE); + unit->ClearUnitState(UNIT_STATE_ROAMING_MOVE); return true; } - unit.AddUnitState(UNIT_STATE_ROAMING_MOVE); + unit->AddUnitState(UNIT_STATE_ROAMING_MOVE); - if (i_recalculateSpeed && !unit.movespline->Finalized()) + if (i_recalculateSpeed && !unit->movespline->Finalized()) { i_recalculateSpeed = false; Movement::MoveSplineInit init(unit); @@ -65,74 +65,74 @@ bool PointMovementGenerator::Update(T &unit, const uint32 & /*diff*/) init.Launch(); } - return !unit.movespline->Finalized(); + return !unit->movespline->Finalized(); } template -void PointMovementGenerator::Finalize(T &unit) +void PointMovementGenerator::Finalize(T* unit) { - if (unit.HasUnitState(UNIT_STATE_CHARGING)) - unit.ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); + if (unit->HasUnitState(UNIT_STATE_CHARGING)) + unit->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); - if (unit.movespline->Finalized()) + if (unit->movespline->Finalized()) MovementInform(unit); } template -void PointMovementGenerator::Reset(T &unit) +void PointMovementGenerator::Reset(T* unit) { - if (!unit.IsStopped()) - unit.StopMoving(); + if (!unit->IsStopped()) + unit->StopMoving(); - unit.AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); } template -void PointMovementGenerator::MovementInform(T & /*unit*/) +void PointMovementGenerator::MovementInform(T* /*unit*/) { } -template <> void PointMovementGenerator::MovementInform(Creature &unit) +template <> void PointMovementGenerator::MovementInform(Creature* unit) { - if (unit.AI()) - unit.AI()->MovementInform(POINT_MOTION_TYPE, id); + if (unit->AI()) + unit->AI()->MovementInform(POINT_MOTION_TYPE, id); } -template void PointMovementGenerator::Initialize(Player&); -template void PointMovementGenerator::Initialize(Creature&); -template void PointMovementGenerator::Finalize(Player&); -template void PointMovementGenerator::Finalize(Creature&); -template void PointMovementGenerator::Reset(Player&); -template void PointMovementGenerator::Reset(Creature&); -template bool PointMovementGenerator::Update(Player &, const uint32 &); -template bool PointMovementGenerator::Update(Creature&, const uint32 &); +template void PointMovementGenerator::Initialize(Player*); +template void PointMovementGenerator::Initialize(Creature*); +template void PointMovementGenerator::Finalize(Player*); +template void PointMovementGenerator::Finalize(Creature*); +template void PointMovementGenerator::Reset(Player*); +template void PointMovementGenerator::Reset(Creature*); +template bool PointMovementGenerator::Update(Player*, const uint32&); +template bool PointMovementGenerator::Update(Creature*, const uint32&); -void AssistanceMovementGenerator::Finalize(Unit &unit) +void AssistanceMovementGenerator::Finalize(Unit* unit) { - unit.ToCreature()->SetNoCallAssistance(false); - unit.ToCreature()->CallAssistance(); - if (unit.isAlive()) - unit.GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY)); + unit->ToCreature()->SetNoCallAssistance(false); + unit->ToCreature()->CallAssistance(); + if (unit->isAlive()) + unit->GetMotionMaster()->MoveSeekAssistanceDistract(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY)); } -bool EffectMovementGenerator::Update(Unit &unit, const uint32&) +bool EffectMovementGenerator::Update(Unit* unit, const uint32&) { - return !unit.movespline->Finalized(); + return !unit->movespline->Finalized(); } -void EffectMovementGenerator::Finalize(Unit &unit) +void EffectMovementGenerator::Finalize(Unit* unit) { - if (unit.GetTypeId() != TYPEID_UNIT) + if (unit->GetTypeId() != TYPEID_UNIT) return; - if (((Creature&)unit).AI()) - ((Creature&)unit).AI()->MovementInform(EFFECT_MOTION_TYPE, m_Id); + if (unit->ToCreature()->AI()) + unit->ToCreature()->AI()->MovementInform(EFFECT_MOTION_TYPE, m_Id); // Need restore previous movement since we have no proper states system - if (unit.isAlive() && !unit.HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_FLEEING)) + if (unit->isAlive() && !unit->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_FLEEING)) { - if (Unit* victim = unit.getVictim()) - unit.GetMotionMaster()->MoveChase(victim); + if (Unit* victim = unit->getVictim()) + unit->GetMotionMaster()->MoveChase(victim); else - unit.GetMotionMaster()->Initialize(); + unit->GetMotionMaster()->Initialize(); } } diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h index 541cbdbc3a7..4111690627e 100644 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h @@ -29,18 +29,18 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG PointMovementGenerator(uint32 _id, float _x, float _y, float _z, bool _generatePath, float _speed = 0.0f) : id(_id), i_x(_x), i_y(_y), i_z(_z), m_generatePath(_generatePath), speed(_speed) {} - void Initialize(T &); - void Finalize(T &); - void Reset(T &); - bool Update(T &, const uint32 &); + void Initialize(T*); + void Finalize(T*); + void Reset(T*); + bool Update(T*, const uint32 &); - void MovementInform(T &); + void MovementInform(T*); void unitSpeedChanged() { i_recalculateSpeed = true; } MovementGeneratorType GetMovementGeneratorType() { return POINT_MOTION_TYPE; } - bool GetDestination(float& x, float& y, float& z) const { x=i_x; y=i_y; z=i_z; return true; } + void GetDestination(float& x, float& y, float& z) const { x = i_x; y = i_y; z = i_z; } private: uint32 id; float i_x, i_y, i_z; @@ -56,7 +56,7 @@ class AssistanceMovementGenerator : public PointMovementGenerator PointMovementGenerator(0, _x, _y, _z, true) {} MovementGeneratorType GetMovementGeneratorType() { return ASSISTANCE_MOTION_TYPE; } - void Finalize(Unit &); + void Finalize(Unit*); }; // Does almost nothing - just doesn't allows previous movegen interrupt current effect. @@ -64,10 +64,10 @@ class EffectMovementGenerator : public MovementGenerator { public: explicit EffectMovementGenerator(uint32 Id) : m_Id(Id) {} - void Initialize(Unit &) {} - void Finalize(Unit &unit); - void Reset(Unit &) {} - bool Update(Unit &u, const uint32&); + void Initialize(Unit*) {} + void Finalize(Unit*); + void Reset(Unit*) {} + bool Update(Unit*, const uint32&); MovementGeneratorType GetMovementGeneratorType() { return EFFECT_MOTION_TYPE; } private: uint32 m_Id; diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 84cd9e88295..3e55b9679c6 100755 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -33,16 +33,16 @@ #endif template<> -void RandomMovementGenerator::_setRandomLocation(Creature& creature) +void RandomMovementGenerator::_setRandomLocation(Creature* creature) { float respX, respY, respZ, respO, destX, destY, destZ, travelDistZ; - creature.GetHomePosition(respX, respY, respZ, respO); - Map const* map = creature.GetBaseMap(); + creature->GetHomePosition(respX, respY, respZ, respO); + Map const* map = creature->GetBaseMap(); // For 2D/3D system selection //bool is_land_ok = creature.CanWalk(); // not used? //bool is_water_ok = creature.CanSwim(); // not used? - bool is_air_ok = creature.CanFly(); + bool is_air_ok = creature->CanFly(); const float angle = float(rand_norm()) * static_cast(M_PI*2.0f); const float range = float(rand_norm()) * wander_distance; @@ -77,17 +77,17 @@ void RandomMovementGenerator::_setRandomLocation(Creature& creature) // The fastest way to get an accurate result 90% of the time. // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long. - destZ = map->GetHeight(creature.GetPhaseMask(), destX, destY, respZ+travelDistZ-2.0f, false); + destZ = map->GetHeight(creature->GetPhaseMask(), destX, destY, respZ+travelDistZ-2.0f, false); if (fabs(destZ - respZ) > travelDistZ) // Map check { // Vmap Horizontal or above - destZ = map->GetHeight(creature.GetPhaseMask(), destX, destY, respZ - 2.0f, true); + destZ = map->GetHeight(creature->GetPhaseMask(), destX, destY, respZ - 2.0f, true); if (fabs(destZ - respZ) > travelDistZ) { // Vmap Higher - destZ = map->GetHeight(creature.GetPhaseMask(), destX, destY, respZ+travelDistZ-2.0f, true); + destZ = map->GetHeight(creature->GetPhaseMask(), destX, destY, respZ+travelDistZ-2.0f, true); // let's forget this bad coords where a z cannot be find and retry at next tick if (fabs(destZ - respZ) > travelDistZ) @@ -101,7 +101,7 @@ void RandomMovementGenerator::_setRandomLocation(Creature& creature) else i_nextMoveTime.Reset(urand(500, 10000)); - creature.AddUnitState(UNIT_STATE_ROAMING_MOVE); + creature->AddUnitState(UNIT_STATE_ROAMING_MOVE); Movement::MoveSplineInit init(creature); init.MoveTo(destX, destY, destZ); @@ -109,47 +109,47 @@ void RandomMovementGenerator::_setRandomLocation(Creature& creature) init.Launch(); //Call for creature group update - if (creature.GetFormation() && creature.GetFormation()->getLeader() == &creature) - creature.GetFormation()->LeaderMoveTo(destX, destY, destZ); + if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) + creature->GetFormation()->LeaderMoveTo(destX, destY, destZ); } template<> -void RandomMovementGenerator::Initialize(Creature &creature) +void RandomMovementGenerator::Initialize(Creature* creature) { - if (!creature.isAlive()) + if (!creature->isAlive()) return; if (!wander_distance) - wander_distance = creature.GetRespawnRadius(); + wander_distance = creature->GetRespawnRadius(); - creature.AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + creature->AddUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); _setRandomLocation(creature); } template<> -void RandomMovementGenerator::Reset(Creature &creature) +void RandomMovementGenerator::Reset(Creature* creature) { Initialize(creature); } template<> -void RandomMovementGenerator::Finalize(Creature &creature) +void RandomMovementGenerator::Finalize(Creature* creature) { - creature.ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); - creature.SetWalk(false); + creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + creature->SetWalk(false); } template<> -bool RandomMovementGenerator::Update(Creature &creature, const uint32 diff) +bool RandomMovementGenerator::Update(Creature* creature, const uint32 diff) { - if (creature.HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) + if (creature->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) { i_nextMoveTime.Reset(0); // Expire the timer - creature.ClearUnitState(UNIT_STATE_ROAMING_MOVE); + creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE); return true; } - if (creature.movespline->Finalized()) + if (creature->movespline->Finalized()) { i_nextMoveTime.Update(diff); if (i_nextMoveTime.Passed()) @@ -159,14 +159,14 @@ bool RandomMovementGenerator::Update(Creature &creature, const uint32 } template<> -bool RandomMovementGenerator::GetResetPosition(Creature &creature, float& x, float& y, float& z) +bool RandomMovementGenerator::GetResetPosition(Creature* creature, float& x, float& y, float& z) { float radius; - creature.GetRespawnPosition(x, y, z, NULL, &radius); + creature->GetRespawnPosition(x, y, z, NULL, &radius); // use current if in range - if (creature.IsWithinDist2d(x,y,radius)) - creature.GetPosition(x,y,z); + if (creature->IsWithinDist2d(x,y,radius)) + creature->GetPosition(x,y,z); return true; } diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h index 07ec3647052..ca370de6ac3 100755 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h @@ -27,12 +27,12 @@ class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovemen public: RandomMovementGenerator(float spawn_dist = 0.0f) : i_nextMoveTime(0), wander_distance(spawn_dist) {} - void _setRandomLocation(T &); - void Initialize(T &); - void Finalize(T &); - void Reset(T &); - bool Update(T &, const uint32); - bool GetResetPosition(T&, float& x, float& y, float& z); + void _setRandomLocation(T*); + void Initialize(T*); + void Finalize(T*); + void Reset(T*); + bool Update(T*, const uint32); + bool GetResetPosition(T*, float& x, float& y, float& z); MovementGeneratorType GetMovementGeneratorType() { return RANDOM_MOTION_TYPE; } private: TimeTrackerSmall i_nextMoveTime; diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 6d322a56a80..9784c19b4fd 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -27,12 +27,12 @@ #include "Player.h" template -void TargetedMovementGeneratorMedium::_setTargetLocation(T &owner) +void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner) { if (!i_target.isValid() || !i_target->IsInWorld()) return; - if (owner.HasUnitState(UNIT_STATE_NOT_MOVE)) + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE)) return; float x, y, z; @@ -49,26 +49,26 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T &owner) // else if (!i_offset) { - if (i_target->IsWithinMeleeRange(&owner)) + if (i_target->IsWithinMeleeRange(owner)) return; // to nearest random contact position - i_target->GetRandomContactPoint(&owner, x, y, z, 0, MELEE_RANGE - 0.5f); + i_target->GetRandomContactPoint(owner, x, y, z, 0, MELEE_RANGE - 0.5f); } else { - if (i_target->IsWithinDistInMap(&owner, i_offset + 1.0f)) + if (i_target->IsWithinDistInMap(owner, i_offset + 1.0f)) return; // to at i_offset distance from target and i_angle from target facing - i_target->GetClosePoint(x, y, z, owner.GetObjectSize(), i_offset, i_angle); + i_target->GetClosePoint(x, y, z, owner->GetObjectSize(), i_offset, i_angle); } if (!i_path) - i_path = new PathGenerator(&owner); + i_path = new PathGenerator(owner); // allow pets following their master to cheat while generating paths - bool forceDest = (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->isPet() - && owner.HasUnitState(UNIT_STATE_FOLLOW)); + bool forceDest = (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->isPet() + && owner->HasUnitState(UNIT_STATE_FOLLOW)); i_path->CalculatePath(x, y, z, forceDest); if (i_path->getPathType() & PATHFIND_NOPATH) return; @@ -76,7 +76,7 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T &owner) D::_addUnitStateMove(owner); i_targetReached = false; i_recalculateTravel = false; - owner.AddUnitState(UNIT_STATE_CHASE); + owner->AddUnitState(UNIT_STATE_CHASE); Movement::MoveSplineInit init(owner); init.MovebyPath(i_path->getPath()); @@ -111,25 +111,25 @@ void TargetedMovementGeneratorMedium } template -bool TargetedMovementGeneratorMedium::Update(T &owner, const uint32 & time_diff) +bool TargetedMovementGeneratorMedium::Update(T* owner, const uint32& time_diff) { if (!i_target.isValid() || !i_target->IsInWorld()) return false; - if (!&owner || !owner.isAlive()) + if (!owner || !owner->isAlive()) return true; - if (owner.HasUnitState(UNIT_STATE_NOT_MOVE)) + if (owner->HasUnitState(UNIT_STATE_NOT_MOVE)) { D::_clearUnitStateMove(owner); return true; } // prevent movement while casting spells with cast time or channel time - if (owner.HasUnitState(UNIT_STATE_CASTING)) + if (owner->HasUnitState(UNIT_STATE_CASTING)) { - if (!owner.IsStopped()) - owner.StopMoving(); + if (!owner->IsStopped()) + owner->StopMoving(); return true; } @@ -145,11 +145,11 @@ bool TargetedMovementGeneratorMedium::Update(T &owner, const uint32 & time_ { i_recheckDistance.Reset(100); //More distance let have better performance, less distance let have more sensitive reaction at target move. - float allowed_dist = owner.GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE); - G3D::Vector3 dest = owner.movespline->FinalDestination(); + float allowed_dist = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE); + G3D::Vector3 dest = owner->movespline->FinalDestination(); bool targetMoved = false; - if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->CanFly()) + if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->CanFly()) targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist); else targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist); @@ -158,11 +158,11 @@ bool TargetedMovementGeneratorMedium::Update(T &owner, const uint32 & time_ _setTargetLocation(owner); } - if (owner.movespline->Finalized()) + if (owner->movespline->Finalized()) { static_cast(this)->MovementInform(owner); - if (i_angle == 0.f && !owner.HasInArc(0.01f, i_target.getTarget())) - owner.SetInFront(i_target.getTarget()); + if (i_angle == 0.f && !owner->HasInArc(0.01f, i_target.getTarget())) + owner->SetInFront(i_target.getTarget()); if (!i_targetReached) { @@ -180,50 +180,50 @@ bool TargetedMovementGeneratorMedium::Update(T &owner, const uint32 & time_ //-----------------------------------------------// template -void ChaseMovementGenerator::_reachTarget(T &owner) +void ChaseMovementGenerator::_reachTarget(T* owner) { - if (owner.IsWithinMeleeRange(this->i_target.getTarget())) - owner.Attack(this->i_target.getTarget(),true); + if (owner->IsWithinMeleeRange(this->i_target.getTarget())) + owner->Attack(this->i_target.getTarget(),true); } template<> -void ChaseMovementGenerator::Initialize(Player &owner) +void ChaseMovementGenerator::Initialize(Player* owner) { - owner.AddUnitState(UNIT_STATE_CHASE|UNIT_STATE_CHASE_MOVE); + owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); _setTargetLocation(owner); } template<> -void ChaseMovementGenerator::Initialize(Creature &owner) +void ChaseMovementGenerator::Initialize(Creature* owner) { - owner.SetWalk(false); - owner.AddUnitState(UNIT_STATE_CHASE|UNIT_STATE_CHASE_MOVE); + owner->SetWalk(false); + owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); _setTargetLocation(owner); } template -void ChaseMovementGenerator::Finalize(T &owner) +void ChaseMovementGenerator::Finalize(T* owner) { - owner.ClearUnitState(UNIT_STATE_CHASE|UNIT_STATE_CHASE_MOVE); + owner->ClearUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); } template -void ChaseMovementGenerator::Reset(T &owner) +void ChaseMovementGenerator::Reset(T* owner) { Initialize(owner); } template -void ChaseMovementGenerator::MovementInform(T & /*unit*/) +void ChaseMovementGenerator::MovementInform(T* /*unit*/) { } template<> -void ChaseMovementGenerator::MovementInform(Creature &unit) +void ChaseMovementGenerator::MovementInform(Creature* unit) { // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle - if (unit.AI()) - unit.AI()->MovementInform(CHASE_MOTION_TYPE, i_target.getTarget()->GetGUIDLow()); + if (unit->AI()) + unit->AI()->MovementInform(CHASE_MOTION_TYPE, i_target.getTarget()->GetGUIDLow()); } //-----------------------------------------------// @@ -240,85 +240,85 @@ bool FollowMovementGenerator::EnableWalking() const } template<> -void FollowMovementGenerator::_updateSpeed(Player &/*u*/) +void FollowMovementGenerator::_updateSpeed(Player* /*u*/) { // nothing to do for Player } template<> -void FollowMovementGenerator::_updateSpeed(Creature &u) +void FollowMovementGenerator::_updateSpeed(Creature* u) { // pet only sync speed with owner - if (!((Creature&)u).isPet() || !i_target.isValid() || i_target->GetGUID() != u.GetOwnerGUID()) + if (!u->isPet() || !i_target.isValid() || i_target->GetGUID() != u->GetOwnerGUID()) return; - u.UpdateSpeed(MOVE_RUN,true); - u.UpdateSpeed(MOVE_WALK,true); - u.UpdateSpeed(MOVE_SWIM,true); + u->UpdateSpeed(MOVE_RUN,true); + u->UpdateSpeed(MOVE_WALK,true); + u->UpdateSpeed(MOVE_SWIM,true); } template<> -void FollowMovementGenerator::Initialize(Player &owner) +void FollowMovementGenerator::Initialize(Player* owner) { - owner.AddUnitState(UNIT_STATE_FOLLOW|UNIT_STATE_FOLLOW_MOVE); + owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); _updateSpeed(owner); _setTargetLocation(owner); } template<> -void FollowMovementGenerator::Initialize(Creature &owner) +void FollowMovementGenerator::Initialize(Creature* owner) { - owner.AddUnitState(UNIT_STATE_FOLLOW|UNIT_STATE_FOLLOW_MOVE); + owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); _updateSpeed(owner); _setTargetLocation(owner); } template -void FollowMovementGenerator::Finalize(T &owner) +void FollowMovementGenerator::Finalize(T* owner) { - owner.ClearUnitState(UNIT_STATE_FOLLOW|UNIT_STATE_FOLLOW_MOVE); + owner->ClearUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); _updateSpeed(owner); } template -void FollowMovementGenerator::Reset(T &owner) +void FollowMovementGenerator::Reset(T* owner) { Initialize(owner); } template -void FollowMovementGenerator::MovementInform(T & /*unit*/) +void FollowMovementGenerator::MovementInform(T* /*unit*/) { } template<> -void FollowMovementGenerator::MovementInform(Creature &unit) +void FollowMovementGenerator::MovementInform(Creature* unit) { // Pass back the GUIDLow of the target. If it is pet's owner then PetAI will handle - if (unit.AI()) - unit.AI()->MovementInform(FOLLOW_MOTION_TYPE, i_target.getTarget()->GetGUIDLow()); + if (unit->AI()) + unit->AI()->MovementInform(FOLLOW_MOTION_TYPE, i_target.getTarget()->GetGUIDLow()); } //-----------------------------------------------// -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player &); -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player &); -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature &); -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature &); -template bool TargetedMovementGeneratorMedium >::Update(Player &, const uint32 &); -template bool TargetedMovementGeneratorMedium >::Update(Player &, const uint32 &); -template bool TargetedMovementGeneratorMedium >::Update(Creature &, const uint32 &); -template bool TargetedMovementGeneratorMedium >::Update(Creature &, const uint32 &); - -template void ChaseMovementGenerator::_reachTarget(Player &); -template void ChaseMovementGenerator::_reachTarget(Creature &); -template void ChaseMovementGenerator::Finalize(Player &); -template void ChaseMovementGenerator::Finalize(Creature &); -template void ChaseMovementGenerator::Reset(Player &); -template void ChaseMovementGenerator::Reset(Creature &); -template void ChaseMovementGenerator::MovementInform(Player &unit); - -template void FollowMovementGenerator::Finalize(Player &); -template void FollowMovementGenerator::Finalize(Creature &); -template void FollowMovementGenerator::Reset(Player &); -template void FollowMovementGenerator::Reset(Creature &); -template void FollowMovementGenerator::MovementInform(Player &unit); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player*); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player*); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature*); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature*); +template bool TargetedMovementGeneratorMedium >::Update(Player*, const uint32&); +template bool TargetedMovementGeneratorMedium >::Update(Player*, const uint32&); +template bool TargetedMovementGeneratorMedium >::Update(Creature*, const uint32&); +template bool TargetedMovementGeneratorMedium >::Update(Creature*, const uint32&); + +template void ChaseMovementGenerator::_reachTarget(Player*); +template void ChaseMovementGenerator::_reachTarget(Creature*); +template void ChaseMovementGenerator::Finalize(Player*); +template void ChaseMovementGenerator::Finalize(Creature*); +template void ChaseMovementGenerator::Reset(Player*); +template void ChaseMovementGenerator::Reset(Creature*); +template void ChaseMovementGenerator::MovementInform(Player*); + +template void FollowMovementGenerator::Finalize(Player*); +template void FollowMovementGenerator::Finalize(Creature*); +template void FollowMovementGenerator::Reset(Player*); +template void FollowMovementGenerator::Reset(Creature*); +template void FollowMovementGenerator::MovementInform(Player*); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index db5e05c7b23..688d236c3f8 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -28,7 +28,7 @@ class TargetedMovementGeneratorBase { public: - TargetedMovementGeneratorBase(Unit &target) { i_target.link(&target, this); } + TargetedMovementGeneratorBase(Unit* target) { i_target.link(target, this); } void stopFollowing() { } protected: FollowerReference i_target; @@ -38,7 +38,7 @@ template class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, public TargetedMovementGeneratorBase { protected: - TargetedMovementGeneratorMedium(Unit &target, float offset, float angle) : + TargetedMovementGeneratorMedium(Unit* target, float offset, float angle) : TargetedMovementGeneratorBase(target), i_recheckDistance(0), i_path(NULL), i_offset(offset), i_angle(angle), i_recalculateTravel(false), i_targetReached(false) @@ -47,14 +47,14 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, ~TargetedMovementGeneratorMedium() { delete i_path; } public: - bool Update(T &, const uint32 &); + bool Update(T*, const uint32 &); Unit* GetTarget() const { return i_target.getTarget(); } - void unitSpeedChanged() { i_recalculateTravel=true; } + void unitSpeedChanged() { i_recalculateTravel = true; } void UpdateFinalDistance(float fDistance); bool IsReachable() const { return (i_path) ? (i_path->getPathType() & PATHFIND_NORMAL) : true; } protected: - void _setTargetLocation(T &); + void _setTargetLocation(T*); TimeTrackerSmall i_recheckDistance; float i_offset; @@ -68,50 +68,50 @@ template class ChaseMovementGenerator : public TargetedMovementGeneratorMedium > { public: - ChaseMovementGenerator(Unit &target) + ChaseMovementGenerator(Unit* target) : TargetedMovementGeneratorMedium >(target) {} - ChaseMovementGenerator(Unit &target, float offset, float angle) + ChaseMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGeneratorMedium >(target, offset, angle) {} ~ChaseMovementGenerator() {} MovementGeneratorType GetMovementGeneratorType() { return CHASE_MOTION_TYPE; } - void Initialize(T &); - void Finalize(T &); - void Reset(T &); - void MovementInform(T &); + void Initialize(T*); + void Finalize(T*); + void Reset(T*); + void MovementInform(T*); - static void _clearUnitStateMove(T &u) { u.ClearUnitState(UNIT_STATE_CHASE_MOVE); } - static void _addUnitStateMove(T &u) { u.AddUnitState(UNIT_STATE_CHASE_MOVE); } + static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_CHASE_MOVE); } + static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_CHASE_MOVE); } bool EnableWalking() const { return false;} - bool _lostTarget(T &u) const { return u.getVictim() != this->GetTarget(); } - void _reachTarget(T &); + bool _lostTarget(T* u) const { return u->getVictim() != GetTarget(); } + void _reachTarget(T*); }; template class FollowMovementGenerator : public TargetedMovementGeneratorMedium > { public: - FollowMovementGenerator(Unit &target) + FollowMovementGenerator(Unit* target) : TargetedMovementGeneratorMedium >(target){} - FollowMovementGenerator(Unit &target, float offset, float angle) + FollowMovementGenerator(Unit* target, float offset, float angle) : TargetedMovementGeneratorMedium >(target, offset, angle) {} ~FollowMovementGenerator() {} MovementGeneratorType GetMovementGeneratorType() { return FOLLOW_MOTION_TYPE; } - void Initialize(T &); - void Finalize(T &); - void Reset(T &); - void MovementInform(T &); + void Initialize(T*); + void Finalize(T*); + void Reset(T*); + void MovementInform(T*); - static void _clearUnitStateMove(T &u) { u.ClearUnitState(UNIT_STATE_FOLLOW_MOVE); } - static void _addUnitStateMove(T &u) { u.AddUnitState(UNIT_STATE_FOLLOW_MOVE); } + static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); } + static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_FOLLOW_MOVE); } bool EnableWalking() const; - bool _lostTarget(T &) const { return false; } - void _reachTarget(T &) {} + bool _lostTarget(T*) const { return false; } + void _reachTarget(T*) {} private: - void _updateSpeed(T &u); + void _updateSpeed(T* u); }; #endif diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 8c2db9ddbd6..c576d7389f3 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -31,64 +31,64 @@ #include "MoveSplineInit.h" #include "MoveSpline.h" -void WaypointMovementGenerator::LoadPath(Creature &creature) +void WaypointMovementGenerator::LoadPath(Creature* creature) { if (!path_id) - path_id = creature.GetWaypointPath(); + path_id = creature->GetWaypointPath(); i_path = sWaypointMgr->GetPath(path_id); if (!i_path) { // No movement found for entry - sLog->outError(LOG_FILTER_SQL, "WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u) doesn't have waypoint path id: %u", creature.GetName(), creature.GetEntry(), creature.GetGUIDLow(), path_id); + sLog->outError(LOG_FILTER_SQL, "WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u) doesn't have waypoint path id: %u", creature->GetName(), creature->GetEntry(), creature->GetGUIDLow(), path_id); return; } StartMoveNow(creature); } -void WaypointMovementGenerator::Initialize(Creature &creature) +void WaypointMovementGenerator::Initialize(Creature* creature) { LoadPath(creature); - creature.AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); } -void WaypointMovementGenerator::Finalize(Creature &creature) +void WaypointMovementGenerator::Finalize(Creature* creature) { - creature.ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); - creature.SetWalk(false); + creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + creature->SetWalk(false); } -void WaypointMovementGenerator::Reset(Creature &creature) +void WaypointMovementGenerator::Reset(Creature* creature) { - creature.AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); StartMoveNow(creature); } -void WaypointMovementGenerator::OnArrived(Creature& creature) +void WaypointMovementGenerator::OnArrived(Creature* creature) { if (!i_path || i_path->empty()) return; if (m_isArrivalDone) return; - creature.ClearUnitState(UNIT_STATE_ROAMING_MOVE); + creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE); m_isArrivalDone = true; if (i_path->at(i_currentNode)->event_id && urand(0, 99) < i_path->at(i_currentNode)->event_chance) { - sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Creature movement start script %u at point %u for "UI64FMTD".", i_path->at(i_currentNode)->event_id, i_currentNode, creature.GetGUID()); - creature.GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, &creature, NULL); + sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Creature movement start script %u at point %u for "UI64FMTD".", i_path->at(i_currentNode)->event_id, i_currentNode, creature->GetGUID()); + creature->GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, creature, NULL); } // Inform script MovementInform(creature); - creature.UpdateWaypointID(i_currentNode); + creature->UpdateWaypointID(i_currentNode); Stop(i_path->at(i_currentNode)->delay); } -bool WaypointMovementGenerator::StartMove(Creature &creature) +bool WaypointMovementGenerator::StartMove(Creature* creature) { if (!i_path || i_path->empty()) return false; @@ -99,8 +99,8 @@ bool WaypointMovementGenerator::StartMove(Creature &creature) { if ((i_currentNode == i_path->size() - 1) && !repeating) // If that's our last waypoint { - creature.SetHomePosition(i_path->at(i_currentNode)->x, i_path->at(i_currentNode)->y, i_path->at(i_currentNode)->z, creature.GetOrientation()); - creature.GetMotionMaster()->Initialize(); + creature->SetHomePosition(i_path->at(i_currentNode)->x, i_path->at(i_currentNode)->y, i_path->at(i_currentNode)->z, creature->GetOrientation()); + creature->GetMotionMaster()->Initialize(); return false; } @@ -111,7 +111,7 @@ bool WaypointMovementGenerator::StartMove(Creature &creature) m_isArrivalDone = false; - creature.AddUnitState(UNIT_STATE_ROAMING_MOVE); + creature->AddUnitState(UNIT_STATE_ROAMING_MOVE); Movement::MoveSplineInit init(creature); init.MoveTo(node->x, node->y, node->z); @@ -124,19 +124,19 @@ bool WaypointMovementGenerator::StartMove(Creature &creature) init.Launch(); //Call for creature group update - if (creature.GetFormation() && creature.GetFormation()->getLeader() == &creature) - creature.GetFormation()->LeaderMoveTo(node->x, node->y, node->z); + if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature) + creature->GetFormation()->LeaderMoveTo(node->x, node->y, node->z); return true; } -bool WaypointMovementGenerator::Update(Creature &creature, const uint32 &diff) +bool WaypointMovementGenerator::Update(Creature* creature, const uint32& diff) { // Waypoint movement can be switched on/off // This is quite handy for escort quests and other stuff - if (creature.HasUnitState(UNIT_STATE_NOT_MOVE)) + if (creature->HasUnitState(UNIT_STATE_NOT_MOVE)) { - creature.ClearUnitState(UNIT_STATE_ROAMING_MOVE); + creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE); return true; } // prevent a crash at empty waypoint path. @@ -150,9 +150,9 @@ bool WaypointMovementGenerator::Update(Creature &creature, const uint3 } else { - if (creature.IsStopped()) + if (creature->IsStopped()) Stop(STOP_TIME_FOR_PLAYER); - else if (creature.movespline->Finalized()) + else if (creature->movespline->Finalized()) { OnArrived(creature); return StartMove(creature); @@ -161,13 +161,13 @@ bool WaypointMovementGenerator::Update(Creature &creature, const uint3 return true; } -void WaypointMovementGenerator::MovementInform(Creature &creature) +void WaypointMovementGenerator::MovementInform(Creature* creature) { - if (creature.AI()) - creature.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode); + if (creature->AI()) + creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode); } -bool WaypointMovementGenerator::GetResetPosition(Creature&, float& x, float& y, float& z) +bool WaypointMovementGenerator::GetResetPosition(Creature*, float& x, float& y, float& z) { // prevent a crash at empty waypoint path. if (!i_path || i_path->empty()) @@ -196,37 +196,37 @@ uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const return i_path->size(); } -void FlightPathMovementGenerator::Initialize(Player &player) +void FlightPathMovementGenerator::Initialize(Player* player) { Reset(player); InitEndGridInfo(); } -void FlightPathMovementGenerator::Finalize(Player& player) +void FlightPathMovementGenerator::Finalize(Player* player) { // remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack) - player.ClearUnitState(UNIT_STATE_IN_FLIGHT); + player->ClearUnitState(UNIT_STATE_IN_FLIGHT); - player.Dismount(); - player.RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); + player->Dismount(); + player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); - if (player.m_taxi.empty()) + if (player->m_taxi.empty()) { - player.getHostileRefManager().setOnlineOfflineState(true); + player->getHostileRefManager().setOnlineOfflineState(true); // update z position to ground and orientation for landing point // this prevent cheating with landing point at lags // when client side flight end early in comparison server side - player.StopMoving(); + player->StopMoving(); } } #define PLAYER_FLIGHT_SPEED 32.0f -void FlightPathMovementGenerator::Reset(Player & player) +void FlightPathMovementGenerator::Reset(Player* player) { - player.getHostileRefManager().setOnlineOfflineState(false); - player.AddUnitState(UNIT_STATE_IN_FLIGHT); - player.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); + player->getHostileRefManager().setOnlineOfflineState(false); + player->AddUnitState(UNIT_STATE_IN_FLIGHT); + player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); Movement::MoveSplineInit init(player); uint32 end = GetPathAtMapEnd(); @@ -241,9 +241,9 @@ void FlightPathMovementGenerator::Reset(Player & player) init.Launch(); } -bool FlightPathMovementGenerator::Update(Player &player, const uint32& /*diff*/) +bool FlightPathMovementGenerator::Update(Player* player, const uint32& /*diff*/) { - uint32 pointId = (uint32)player.movespline->currentPathIdx(); + uint32 pointId = (uint32)player->movespline->currentPathIdx(); if (pointId > i_currentNode) { bool departureEvent = true; @@ -279,16 +279,16 @@ void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() } } -void FlightPathMovementGenerator::DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure) +void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry const& node, bool departure) { if (uint32 eventid = departure ? node.departureEventID : node.arrivalEventID) { - sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.index, node.path, player.GetName()); - player.GetMap()->ScriptsStart(sEventScripts, eventid, &player, &player); + sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.index, node.path, player->GetName()); + player->GetMap()->ScriptsStart(sEventScripts, eventid, player, player); } } -bool FlightPathMovementGenerator::GetResetPosition(Player&, float& x, float& y, float& z) +bool FlightPathMovementGenerator::GetResetPosition(Player*, float& x, float& y, float& z) { const TaxiPathNodeEntry& node = (*i_path)[i_currentNode]; x = node.x; y = node.y; z = node.z; diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index 0d8f047c83a..5230fe3b0e3 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -65,19 +65,19 @@ class WaypointMovementGenerator : public MovementGeneratorMedium< Crea WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) : i_nextMoveTime(0), m_isArrivalDone(false), path_id(_path_id), repeating(_repeating) {} ~WaypointMovementGenerator() { i_path = NULL; } - void Initialize(Creature &); - void Finalize(Creature &); - void Reset(Creature &); - bool Update(Creature &, const uint32 &diff); + void Initialize(Creature*); + void Finalize(Creature*); + void Reset(Creature*); + bool Update(Creature*, const uint32 &diff); - void MovementInform(Creature &); + void MovementInform(Creature*); MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; } // now path movement implmementation - void LoadPath(Creature &c); + void LoadPath(Creature*); - bool GetResetPosition(Creature&, float& x, float& y, float& z); + bool GetResetPosition(Creature*, float& x, float& y, float& z); private: @@ -91,10 +91,10 @@ class WaypointMovementGenerator : public MovementGeneratorMedium< Crea return i_nextMoveTime.Passed(); } - void OnArrived(Creature&); - bool StartMove(Creature&); + void OnArrived(Creature*); + bool StartMove(Creature*); - void StartMoveNow(Creature& creature) + void StartMoveNow(Creature* creature) { i_nextMoveTime.Reset(0); StartMove(creature); @@ -118,10 +118,10 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig i_path = &pathnodes; i_currentNode = startNode; } - void Initialize(Player &); - void Reset(Player &); - void Finalize(Player &); - bool Update(Player &, const uint32&); + void Initialize(Player*); + void Reset(Player*); + void Finalize(Player*); + bool Update(Player*, const uint32&); MovementGeneratorType GetMovementGeneratorType() { return FLIGHT_MOTION_TYPE; } TaxiPathNodeList const& GetPath() { return *i_path; } @@ -129,9 +129,9 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig bool HasArrived() const { return (i_currentNode >= i_path->size()); } void SetCurrentNodeAfterTeleport(); void SkipCurrentNode() { ++i_currentNode; } - void DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure); + void DoEventIfAny(Player* player, TaxiPathNodeEntry const& node, bool departure); - bool GetResetPosition(Player&, float& x, float& y, float& z); + bool GetResetPosition(Player*, float& x, float& y, float& z); void InitEndGridInfo(); void PreloadEndGrid(); diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index c5e314a8636..8167ff36de2 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -58,18 +58,18 @@ namespace Movement int32 MoveSplineInit::Launch() { - MoveSpline& move_spline = *unit.movespline; + MoveSpline& move_spline = *unit->movespline; bool transport = false; - Location real_position(unit.GetPositionX(), unit.GetPositionY(), unit.GetPositionZMinusOffset(), unit.GetOrientation()); + Location real_position(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZMinusOffset(), unit->GetOrientation()); // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes - if (unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit.GetTransGUID()) + if (unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID()) { transport = true; - real_position.x = unit.GetTransOffsetX(); - real_position.y = unit.GetTransOffsetY(); - real_position.z = unit.GetTransOffsetZ(); - real_position.orientation = unit.GetTransOffsetO(); + real_position.x = unit->GetTransOffsetX(); + real_position.y = unit->GetTransOffsetY(); + real_position.z = unit->GetTransOffsetZ(); + real_position.orientation = unit->GetTransOffsetO(); } // there is a big chance that current position is unknown if current state is not finalized, need compute it @@ -85,7 +85,7 @@ namespace Movement args.path[0] = real_position; args.initialOrientation = real_position.orientation; - uint32 moveFlags = unit.m_movementInfo.GetMovementFlags(); + uint32 moveFlags = unit->m_movementInfo.GetMovementFlags(); if (args.flags.walkmode) moveFlags |= MOVEMENTFLAG_WALKING; else @@ -94,7 +94,7 @@ namespace Movement moveFlags |= (MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD); if (!args.HasVelocity) - args.velocity = unit.GetSpeed(SelectSpeedType(moveFlags)); + args.velocity = unit->GetSpeed(SelectSpeedType(moveFlags)); if (!args.Validate()) return 0; @@ -102,33 +102,33 @@ namespace Movement if (moveFlags & MOVEMENTFLAG_ROOT) moveFlags &= ~MOVEMENTFLAG_MASK_MOVING; - unit.m_movementInfo.SetMovementFlags((MovementFlags)moveFlags); + unit->m_movementInfo.SetMovementFlags((MovementFlags)moveFlags); move_spline.Initialize(args); WorldPacket data(!transport ? SMSG_MONSTER_MOVE : SMSG_MONSTER_MOVE_TRANSPORT, 64); - data.append(unit.GetPackGUID()); + data.append(unit->GetPackGUID()); if (transport) { - data.appendPackGUID(unit.GetTransGUID()); - data << int8(unit.GetTransSeat()); + data.appendPackGUID(unit->GetTransGUID()); + data << int8(unit->GetTransSeat()); } PacketBuilder::WriteMonsterMove(move_spline, data); - unit.SendMessageToSet(&data,true); + unit->SendMessageToSet(&data,true); return move_spline.Duration(); } - MoveSplineInit::MoveSplineInit(Unit& m) : unit(m) + MoveSplineInit::MoveSplineInit(Unit* m) : unit(m) { // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes - args.TransformForTransport = unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit.GetTransGUID(); + args.TransformForTransport = unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit->GetTransGUID(); // mix existing state into new - args.flags.walkmode = unit.m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING); - args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY|MOVEMENTFLAG_DISABLE_GRAVITY)); + args.flags.walkmode = unit->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING); + args.flags.flying = unit->m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_DISABLE_GRAVITY)); } - void MoveSplineInit::SetFacing(const Unit * target) + void MoveSplineInit::SetFacing(const Unit* target) { args.flags.EnableFacingTarget(); args.facing.target = target->GetGUID(); @@ -138,9 +138,9 @@ namespace Movement { if (args.TransformForTransport) { - if (Unit* vehicle = unit.GetVehicleBase()) + if (Unit* vehicle = unit->GetVehicleBase()) angle -= vehicle->GetOrientation(); - else if (Transport* transport = unit.GetTransport()) + else if (Transport* transport = unit->GetTransport()) angle -= transport->GetOrientation(); } @@ -152,7 +152,7 @@ namespace Movement { if (generatePath) { - PathGenerator path(&unit); + PathGenerator path(unit); path.CalculatePath(dest.x, dest.y, dest.z, forceDestination); MovebyPath(path.getPath()); } @@ -169,13 +169,13 @@ namespace Movement { if (_transformForTransport) { - if (Unit* vehicle = _owner.GetVehicleBase()) + if (Unit* vehicle = _owner->GetVehicleBase()) { input.x -= vehicle->GetPositionX(); input.y -= vehicle->GetPositionY(); input.z -= vehicle->GetPositionZMinusOffset(); } - else if (Transport* transport = _owner.GetTransport()) + else if (Transport* transport = _owner->GetTransport()) { float unused = 0.0f; transport->CalculatePassengerOffset(input.x, input.y, input.z, unused); diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 759fc73d7fd..53adec2e633 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -38,12 +38,12 @@ namespace Movement class TransportPathTransform { public: - TransportPathTransform(Unit& owner, bool transformForTransport) + TransportPathTransform(Unit* owner, bool transformForTransport) : _owner(owner), _transformForTransport(transformForTransport) { } Vector3 operator()(Vector3 input); private: - Unit& _owner; + Unit* _owner; bool _transformForTransport; }; @@ -53,7 +53,7 @@ namespace Movement { public: - explicit MoveSplineInit(Unit& m); + explicit MoveSplineInit(Unit* m); /* Final pass of initialization that launches spline movement. */ @@ -76,7 +76,7 @@ namespace Movement */ void SetFacing(float angle); void SetFacing(Vector3 const& point); - void SetFacing(const Unit * target); + void SetFacing(const Unit* target); /* Initializes movement by path * @param path - array of points, shouldn't be empty @@ -138,7 +138,7 @@ namespace Movement protected: MoveSplineInitArgs args; - Unit& unit; + Unit* unit; }; inline void MoveSplineInit::SetFly() { args.flags.EnableFlying(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 7ee67060f97..c6b89d37878 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -342,7 +342,7 @@ class boss_algalon_the_observer : public CreatureScript DoCast(me, SPELL_RIDE_THE_LIGHTNING, true); me->GetMotionMaster()->MovePoint(POINT_ALGALON_LAND, AlgalonLandPos); me->SetHomePosition(AlgalonLandPos); - Movement::MoveSplineInit init(*me); + Movement::MoveSplineInit init(me); init.MoveTo(AlgalonLandPos.GetPositionX(), AlgalonLandPos.GetPositionY(), AlgalonLandPos.GetPositionZ()); init.SetOrientationFixed(true); init.Launch(); -- cgit v1.2.3 From a97cfbd2ebeaf8e39cef6802deb3139569505288 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 26 Aug 2012 18:14:58 -0500 Subject: Core/MMaps: Fixed infinite wait in the generator --- src/tools/mmaps_generator/MapBuilder.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index b04300994f9..8cdbdf61909 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -194,12 +194,13 @@ namespace MMAP buildMap(mapID); } } - // Wait for all threads to finish before closing down - ACE_Thread_Manager::instance()->wait(); // Free memory for (std::vector::iterator _th = _threads.begin(); _th != _threads.end(); ++_th) + { + _th->wait(); delete *_th; + } } /**************************************************************************/ -- cgit v1.2.3 From 02bbd1154eb3e119fb095850e60e3dc11ee937b1 Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 27 Aug 2012 15:21:54 -0500 Subject: Core/Mmaps: Fixed build --- src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h | 2 +- src/tools/mmaps_generator/MapBuilder.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 688d236c3f8..0ca688fb0df 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -84,7 +84,7 @@ class ChaseMovementGenerator : public TargetedMovementGeneratorMediumClearUnitState(UNIT_STATE_CHASE_MOVE); } static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_CHASE_MOVE); } bool EnableWalking() const { return false;} - bool _lostTarget(T* u) const { return u->getVictim() != GetTarget(); } + bool _lostTarget(T* u) const { return u->getVictim() != this->GetTarget(); } void _reachTarget(T*); }; diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 8cdbdf61909..03a77c01d27 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -198,7 +198,7 @@ namespace MMAP // Free memory for (std::vector::iterator _th = _threads.begin(); _th != _threads.end(); ++_th) { - _th->wait(); + (*_th)->wait(); delete *_th; } } -- cgit v1.2.3 From 8f9dad3d7637a18a5e3cc96dfe32826c810f17b3 Mon Sep 17 00:00:00 2001 From: thesensei Date: Tue, 28 Aug 2012 20:58:03 +0300 Subject: Core/Spells: Destabilize Azure Dragonshrine *Spell script support for spell 49370 --- .../2012_08_28_00_world_spell_script_name.sql | 4 +++ src/server/scripts/Spells/spell_quest.cpp | 41 ++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 sql/updates/world/2012_08_28_00_world_spell_script_name.sql (limited to 'src') diff --git a/sql/updates/world/2012_08_28_00_world_spell_script_name.sql b/sql/updates/world/2012_08_28_00_world_spell_script_name.sql new file mode 100644 index 00000000000..9cc18a4fa5a --- /dev/null +++ b/sql/updates/world/2012_08_28_00_world_spell_script_name.sql @@ -0,0 +1,4 @@ +-- Spell script name linking for Defending Wyrmrest Temple: Destabilize Azure Dragonshrine Effect +DELETE FROM `spell_script_names` WHERE `spell_id`=49370 ; +INSERT INTO `spell_script_names` VALUES +(49370,'spell_q12372_destabilize_azure_dragonshrine_dummy'); \ No newline at end of file diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 8b67a52d300..759dbfe802d 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -1276,6 +1276,46 @@ class spell_q12372_cast_from_gossip_trigger : public SpellScriptLoader } }; +// http://www.wowhead.com/quest=12372 Defending Wyrmrest Temple +// 49370 - Wyrmrest Defender: Destabilize Azure Dragonshrine Effect +enum eQuest12372Data +{ + NPC_WYRMREST_TEMPLE_CREDIT = 27698, +}; + +class spell_q12372_destabilize_azure_dragonshrine_dummy : public SpellScriptLoader +{ + public: + spell_q12372_destabilize_azure_dragonshrine_dummy() : SpellScriptLoader("spell_q12372_destabilize_azure_dragonshrine_dummy") { } + + class spell_q12372_destabilize_azure_dragonshrine_dummy_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12372_destabilize_azure_dragonshrine_dummy_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (GetHitCreature()) + { + if (Unit* caster = GetOriginalCaster()) + if (Vehicle* vehicle = caster->GetVehicleKit()) + if (Unit* passenger = vehicle->GetPassenger(0)) + if (Player* player = passenger->ToPlayer()) + player->KilledMonsterCredit(NPC_WYRMREST_TEMPLE_CREDIT, 0); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12372_destabilize_azure_dragonshrine_dummy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12372_destabilize_azure_dragonshrine_dummy_SpellScript(); + } +}; + void AddSC_quest_spell_scripts() { new spell_q55_sacred_cleansing(); @@ -1306,4 +1346,5 @@ void AddSC_quest_spell_scripts() new spell_q12066_bunny_kill_credit(); new spell_q12735_song_of_cleansing(); new spell_q12372_cast_from_gossip_trigger(); + new spell_q12372_destabilize_azure_dragonshrine_dummy(); } -- cgit v1.2.3 From d6221fc4f7a08fe09e7c8bb9226b0168db358450 Mon Sep 17 00:00:00 2001 From: Nay Date: Tue, 28 Aug 2012 19:31:15 +0100 Subject: Scripts: Fix code style after PR --- .../world/2012_08_28_00_world_spell_script_name.sql | 2 +- src/server/scripts/Spells/spell_quest.cpp | 20 +++++++++----------- 2 files changed, 10 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/sql/updates/world/2012_08_28_00_world_spell_script_name.sql b/sql/updates/world/2012_08_28_00_world_spell_script_name.sql index 9cc18a4fa5a..01cfeb35f1f 100644 --- a/sql/updates/world/2012_08_28_00_world_spell_script_name.sql +++ b/sql/updates/world/2012_08_28_00_world_spell_script_name.sql @@ -1,4 +1,4 @@ -- Spell script name linking for Defending Wyrmrest Temple: Destabilize Azure Dragonshrine Effect DELETE FROM `spell_script_names` WHERE `spell_id`=49370 ; INSERT INTO `spell_script_names` VALUES -(49370,'spell_q12372_destabilize_azure_dragonshrine_dummy'); \ No newline at end of file +(49370,'spell_q12372_destabilize_azure_dragonshrine_dummy'); diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 759dbfe802d..3cb2300cadf 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -1278,7 +1278,7 @@ class spell_q12372_cast_from_gossip_trigger : public SpellScriptLoader // http://www.wowhead.com/quest=12372 Defending Wyrmrest Temple // 49370 - Wyrmrest Defender: Destabilize Azure Dragonshrine Effect -enum eQuest12372Data +enum Quest12372Data { NPC_WYRMREST_TEMPLE_CREDIT = 27698, }; @@ -1294,16 +1294,14 @@ class spell_q12372_destabilize_azure_dragonshrine_dummy : public SpellScriptLoad void HandleDummy(SpellEffIndex /*effIndex*/) { - if (GetHitCreature()) - { - if (Unit* caster = GetOriginalCaster()) - if (Vehicle* vehicle = caster->GetVehicleKit()) - if (Unit* passenger = vehicle->GetPassenger(0)) - if (Player* player = passenger->ToPlayer()) - player->KilledMonsterCredit(NPC_WYRMREST_TEMPLE_CREDIT, 0); - } - } - + if (GetHitCreature()) + if (Unit* caster = GetOriginalCaster()) + if (Vehicle* vehicle = caster->GetVehicleKit()) + if (Unit* passenger = vehicle->GetPassenger(0)) + if (Player* player = passenger->ToPlayer()) + player->KilledMonsterCredit(NPC_WYRMREST_TEMPLE_CREDIT, 0); + } + void Register() { OnEffectHitTarget += SpellEffectFn(spell_q12372_destabilize_azure_dragonshrine_dummy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); -- cgit v1.2.3 From fa590d006e9026e95cd666223eee68fae8a33a68 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 28 Aug 2012 20:09:04 -0500 Subject: Core/MMaps: Made some cosmetic improvements to the mmaps generator --- src/tools/mmaps_generator/MapBuilder.cpp | 5 ++--- src/tools/mmaps_generator/PathGenerator.cpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 03a77c01d27..2a74233a1a7 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -179,7 +179,6 @@ namespace MMAP { if ((*_th)->Free) { - printf("Thread is free for map %03i\n", mapID); (*_th)->SetMapId(mapID); (*_th)->activate(); next = true; @@ -335,7 +334,7 @@ namespace MMAP buildNavMesh(mapID, navMesh); if (!navMesh) { - printf("Failed creating navmesh! \n"); + printf("[Map %i] Failed creating navmesh!\n", mapID); return; } @@ -363,7 +362,7 @@ namespace MMAP /**************************************************************************/ void MapBuilder::buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh) { - printf("Building map %03u, tile [%02u,%02u]\n", mapID, tileX, tileY); + printf("[Map %i] Building tile [%02u,%02u]\n", mapID, tileX, tileY); MeshData meshData; diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 4da90fd153a..026bf957ec4 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -292,6 +292,6 @@ int main(int argc, char** argv) builder.buildAllMaps(threads); if (!silent) - printf("Finished. MMAPS were built in %u ms!", GetMSTimeDiffToNow(start)); + printf("Finished. MMAPS were built in %u ms!\n", GetMSTimeDiffToNow(start)); return 1; } -- cgit v1.2.3 From 58d250ce83245dfebf089dc7e8d8f2aa05a7a2ed Mon Sep 17 00:00:00 2001 From: kaelima Date: Fri, 31 Aug 2012 11:58:45 +0200 Subject: Core/Mmaps: Use mmaps if enabled when re-generating point-movement path after speed changes. (often used by pets) --- src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index c8a7c8f8f8d..20f1c3a29e9 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -59,7 +59,7 @@ bool PointMovementGenerator::Update(T* unit, const uint32& /*diff*/) { i_recalculateSpeed = false; Movement::MoveSplineInit init(unit); - init.MoveTo(i_x, i_y, i_z); + init.MoveTo(i_x, i_y, i_z, m_generatePath); if (speed > 0.0f) // Default value for point motion type is 0.0, if 0.0 spline will use GetSpeed on unit init.SetVelocity(speed); init.Launch(); -- cgit v1.2.3 From a5d977c90eaf48f0961bc7dfdee12c603963abf5 Mon Sep 17 00:00:00 2001 From: kaelima Date: Fri, 31 Aug 2012 12:06:12 +0200 Subject: Core/Config: Disable petlos by default --- src/server/worldserver/worldserver.conf.dist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 1a237eac08a..e5b8f21da8e 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -305,10 +305,10 @@ vmap.ignoreSpellIds = "7720" # # vmap.petLOS # Description: Check line of sight for pets, to avoid them attacking through walls. -# Default: 1 - (Enabled, each pet attack will be checked for line of sight) +# Default: 1 - (Enabled, each pet attack will be checked for line of sight - not recommended if mmaps is enabled!) # 0 - (Disabled, somewhat less CPU usage) -vmap.petLOS = 1 +vmap.petLOS = 0 # # vmap.enableIndoorCheck -- cgit v1.2.3 From db7b750e0c33bf75ef6943a9da149cfbb8f6f2d1 Mon Sep 17 00:00:00 2001 From: Myran2 Date: Fri, 31 Aug 2012 01:26:21 +0100 Subject: Scripts/Commands: Create a new group of commands, .cheat, and add new and move old commands to it: Changes: - .explorecheat is now .cheat explore - .waterwalk is now .cheat waterwalk - .taxicheat is now .cheat taxi New commands: - .cheat god - .cheat casttime - .cheat cooldown - .cheat power (Descriptions available in the SQL file / in-game) Inspiration on ArcEmu commands Closes #7569 --- sql/updates/world/2012_8_29_00_world_command.sql | 14 ++ src/server/game/Entities/Player/Player.cpp | 2 + src/server/game/Entities/Player/Player.h | 17 ++ src/server/game/Scripting/ScriptLoader.cpp | 2 + src/server/game/Spells/Spell.cpp | 23 ++ src/server/scripts/Commands/CMakeLists.txt | 1 + src/server/scripts/Commands/cs_cheat.cpp | 281 +++++++++++++++++++++++ src/server/scripts/Commands/cs_misc.cpp | 118 ---------- 8 files changed, 340 insertions(+), 118 deletions(-) create mode 100644 sql/updates/world/2012_8_29_00_world_command.sql create mode 100644 src/server/scripts/Commands/cs_cheat.cpp (limited to 'src') diff --git a/sql/updates/world/2012_8_29_00_world_command.sql b/sql/updates/world/2012_8_29_00_world_command.sql new file mode 100644 index 00000000000..c0686d6d907 --- /dev/null +++ b/sql/updates/world/2012_8_29_00_world_command.sql @@ -0,0 +1,14 @@ +DELETE FROM `command` WHERE `name`='explorecheat'; +DELETE FROM `command` WHERE `name`='taxicheat'; +DELETE FROM `command` WHERE `name`='waterwalk'; + +DELETE FROM `command` WHERE `name`='cheat' OR `name` LIKE 'cheat%'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('cheat', 2, 'Syntax: .cheat $subcommand\r\nType .cheat to see the list of possible subcommands or .help cheat $subcommand to see info on subcommands'), +('cheat god', 2, 'Syntax: .cheat god [on/off]\r\nEnables or disables your character''s ability to take damage.'), +('cheat casttime', 2, 'Syntax: .cheat casttime [on/off]\r\nEnables or disables your character''s spell cast times.'), +('cheat cooldown', 2, 'Syntax: .cheat cooldown [on/off]\r\nEnables or disables your character''s spell cooldowns.'), +('cheat power', 2, 'Syntax: .cheat power [on/off]\r\nEnables or disables your character''s spell cost (e.g mana).'), +('cheat waterwalk', 2, 'Syntax: .cheat waterwalk on/off\r\nSet on/off waterwalk state for selected player or self if no player selected.'), +('cheat explore', 2, 'Syntax: .cheat explore #flag\r\nReveal or hide all maps for the selected player. If no player is selected, hide or reveal maps to you.\r\nUse a #flag of value 1 to reveal, use a #flag value of 0 to hide all maps.'), +('cheat taxi', 2, 'Syntax: .cheat taxi on/off\r\nTemporary grant access or remove to all taxi routes for the selected character.\r\n If no character is selected, hide or reveal all routes to you.Visited taxi nodes sill accessible after removing access.'); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 936788f484e..65f6588f80e 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -861,6 +861,8 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep m_SeasonalQuestChanged = false; SetPendingBind(0, 0); + + _activeCheats = CHEAT_NONE; } Player::~Player() diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1758b915ebf..71915f42784 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -896,6 +896,16 @@ enum PlayerRestState REST_STATE_RAF_LINKED = 0x06 }; +enum PlayerCommandStates +{ + CHEAT_NONE = 0x00, + CHEAT_GOD = 0x01, + CHEAT_CASTTIME = 0x02, + CHEAT_COOLDOWN = 0x04, + CHEAT_POWER = 0x08, + CHEAT_WATERWALK = 0x10 +}; + class PlayerTaxi { public: @@ -1148,6 +1158,11 @@ class Player : public Unit, public GridObject void InitStatsForLevel(bool reapplyMods = false); + // .cheat command related + bool GetCommandStatus(uint32 command) const { return _activeCheats & command; } + void SetCommandStatusOn(uint32 command) { _activeCheats |= command; } + void SetCommandStatusOff(uint32 command) { _activeCheats &= ~command; } + // Played Time Stuff time_t m_logintime; time_t m_Last_tick; @@ -2854,6 +2869,8 @@ class Player : public Unit, public GridObject InstanceTimeMap _instanceResetTimes; uint32 _pendingBindId; uint32 _pendingBindTimer; + + uint32 _activeCheats; }; void AddItemsSetItem(Player*player, Item* item); diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 9d983542fea..1848250ec8e 100755 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -50,6 +50,7 @@ void AddSC_ban_commandscript(); void AddSC_bf_commandscript(); void AddSC_cast_commandscript(); void AddSC_character_commandscript(); +void AddSC_cheat_commandscript(); void AddSC_debug_commandscript(); void AddSC_disable_commandscript(); void AddSC_event_commandscript(); @@ -666,6 +667,7 @@ void AddCommandScripts() AddSC_bf_commandscript(); AddSC_cast_commandscript(); AddSC_character_commandscript(); + AddSC_cheat_commandscript(); AddSC_debug_commandscript(); AddSC_disable_commandscript(); AddSC_event_commandscript(); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 19741ea7854..95345ed8b93 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3023,7 +3023,13 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered // calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail) m_casttime = m_spellInfo->CalcCastTime(m_caster, this); if (m_caster->GetTypeId() == TYPEID_PLAYER) + { m_caster->ToPlayer()->SetSpellModTakingSpell(this, false); + + // Set casttime to 0 if .cheat casttime is enabled. + if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_CASTTIME)) + m_casttime = 0; + } // don't allow channeled spells / spells with cast time to be casted while moving // (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in) @@ -3315,7 +3321,13 @@ void Spell::cast(bool skipCheck) } if (m_caster->GetTypeId() == TYPEID_PLAYER) + { m_caster->ToPlayer()->SetSpellModTakingSpell(this, false); + + //Clear spell cooldowns after every spell is cast if .cheat cooldown is enabled. + if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN)) + m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true); + } SetExecutedCurrently(false); } @@ -4358,6 +4370,13 @@ void Spell::TakePower() if (m_CastItem || m_triggeredByAuraSpell) return; + //Don't take power if the spell is cast while .cheat power is enabled. + if (m_caster->GetTypeId() == TYPEID_PLAYER) + { + if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_POWER)) + return; + } + Powers powerType = Powers(m_spellInfo->PowerType); bool hit = true; if (m_caster->GetTypeId() == TYPEID_PLAYER) @@ -7193,6 +7212,10 @@ void Spell::TriggerGlobalCooldown() if (!gcd) return; + if (m_caster->GetTypeId() == TYPEID_PLAYER) + if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN)) + return; + // Global cooldown can't leave range 1..1.5 secs // There are some spells (mostly not casted directly by player) that have < 1 sec and > 1.5 sec global cooldowns // but as tests show are not affected by any spell mods. diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt index d5ebeab3b8a..177b3a479f5 100644 --- a/src/server/scripts/Commands/CMakeLists.txt +++ b/src/server/scripts/Commands/CMakeLists.txt @@ -16,6 +16,7 @@ set(scripts_STAT_SRCS Commands/cs_bf.cpp Commands/cs_cast.cpp Commands/cs_character.cpp + Commands/cs_cheat.cpp Commands/cs_debug.cpp Commands/cs_disable.cpp Commands/cs_event.cpp diff --git a/src/server/scripts/Commands/cs_cheat.cpp b/src/server/scripts/Commands/cs_cheat.cpp new file mode 100644 index 00000000000..ade1b9fae02 --- /dev/null +++ b/src/server/scripts/Commands/cs_cheat.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2008-2012 TrinityCore + * + * 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 2 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 . + */ + +/* ScriptData +Name: cheat_commandscript +%Complete: 100 +Comment: All cheat related commands +Category: commandscripts +EndScriptData */ + +#include "ScriptMgr.h" +#include "ObjectMgr.h" +#include "Chat.h" + +class cheat_commandscript : public CommandScript +{ +public: + cheat_commandscript() : CommandScript("cheat_commandscript") { } + + ChatCommand* GetCommands() const + { + + static ChatCommand cheatCommandTable[] = + { + { "god", SEC_GAMEMASTER, false, &HandleGodModeCheatCommand, "", NULL }, + { "casttime", SEC_GAMEMASTER, false, &HandleCasttimeCheatCommand, "", NULL }, + { "cooldown", SEC_GAMEMASTER, false, &HandleCoolDownCheatCommand, "", NULL }, + { "power", SEC_GAMEMASTER, false, &HandlePowerCheatCommand, "", NULL }, + { "waterwalk", SEC_GAMEMASTER, false, &HandleWaterWalkCheatCommand, "", NULL }, + { "taxi", SEC_GAMEMASTER, false, &HandleTaxiCheatCommand, "", NULL }, + { "explore", SEC_GAMEMASTER, false, &HandleExploreCheatCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + + }; + + static ChatCommand commandTable[] = + { + { "cheat", SEC_GAMEMASTER, false, NULL, "", cheatCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + + static bool HandleGodModeCheatCommand(ChatHandler* handler, const char* args) + { + if (!handler->GetSession() && !handler->GetSession()->GetPlayer()) + return false; + + std::string argstr = (char*)args; + + if (!*args) + argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_GOD)) ? "off" : "on"; + + if (argstr == "off") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_GOD); + handler->SendSysMessage("Godmode is OFF. You can take damage."); + return true; + } + else if (argstr == "on") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_GOD); + handler->SendSysMessage("Godmode is ON. You won't take damage."); + return true; + } + + return false; + } + + static bool HandleCasttimeCheatCommand(ChatHandler* handler, const char* args) + { + if (!handler->GetSession() && !handler->GetSession()->GetPlayer()) + return false; + + std::string argstr = (char*)args; + + if (!*args) + argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_CASTTIME)) ? "off" : "on"; + + if (argstr == "off") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_CASTTIME); + handler->SendSysMessage("CastTime Cheat is OFF. Your spells will have a casttime."); + return true; + } + else if (argstr == "on") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_CASTTIME); + handler->SendSysMessage("CastTime Cheat is ON. Your spells won't have a casttime."); + return true; + } + + return false; + } + + static bool HandleCoolDownCheatCommand(ChatHandler* handler, const char* args) + { + if (!handler->GetSession() && !handler->GetSession()->GetPlayer()) + return false; + + std::string argstr = (char*)args; + + if (!*args) + argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_COOLDOWN)) ? "off" : "on"; + + if (argstr == "off") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_COOLDOWN); + handler->SendSysMessage("Cooldown Cheat is OFF. You are on the global cooldown."); + return true; + } + else if (argstr == "on") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_COOLDOWN); + handler->SendSysMessage("Cooldown Cheat is ON. You are not on the global cooldown."); + return true; + } + + return false; + } + + static bool HandlePowerCheatCommand(ChatHandler* handler, const char* args) + { + if (!handler->GetSession() && !handler->GetSession()->GetPlayer()) + return false; + + std::string argstr = (char*)args; + + if (!*args) + argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_POWER)) ? "off" : "on"; + + if (argstr == "off") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_POWER); + handler->SendSysMessage("Power Cheat is OFF. You need mana/rage/energy to use spells."); + return true; + } + else if (argstr == "on") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_POWER); + handler->SendSysMessage("Power Cheat is ON. You don't need mana/rage/energy to use spells."); + return true; + } + + return false; + } + + static bool HandleWaterWalkCheatCommand(ChatHandler* handler, const char* args) + { + if (!handler->GetSession() && !handler->GetSession()->GetPlayer()) + return false; + + std::string argstr = (char*)args; + + if (!*args) + { + argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_WATERWALK)) ? "off" : "on"; + if (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_WATERWALK)) + argstr = "off"; + else + argstr = "on"; + } + + if (argstr == "off") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOff(CHEAT_WATERWALK); + handler->GetSession()->GetPlayer()->SetMovement(MOVE_LAND_WALK); // OFF + handler->SendSysMessage("Waterwalking is OFF. You can't walk on water."); + return true; + } + else if (argstr == "on") + { + handler->GetSession()->GetPlayer()->SetCommandStatusOn(CHEAT_WATERWALK); + handler->GetSession()->GetPlayer()->SetMovement(MOVE_WATER_WALK); // ON + handler->SendSysMessage("Waterwalking is ON. You can walk on water."); + return true; + } + + return false; + } + + static bool HandleTaxiCheatCommand(ChatHandler* handler, const char* args) + { + if (!*args) + { + handler->SendSysMessage(LANG_USE_BOL); + handler->SetSentErrorMessage(true); + return false; + } + + std::string argstr = (char*)args; + + Player* chr = handler->getSelectedPlayer(); + + if (!chr) + chr = handler->GetSession()->GetPlayer(); + else if (handler->HasLowerSecurity(chr, 0)) // check online security + return false; + + if (argstr == "on") + { + chr->SetTaxiCheater(true); + handler->PSendSysMessage(LANG_YOU_GIVE_TAXIS, handler->GetNameLink(chr).c_str()); + if (handler->needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, handler->GetNameLink().c_str()); + return true; + } + + if (argstr == "off") + { + chr->SetTaxiCheater(false); + handler->PSendSysMessage(LANG_YOU_REMOVE_TAXIS, handler->GetNameLink(chr).c_str()); + if (handler->needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, handler->GetNameLink().c_str()); + + return true; + } + + handler->SendSysMessage(LANG_USE_BOL); + handler->SetSentErrorMessage(true); + return false; + } + + static bool HandleExploreCheatCommand(ChatHandler* handler, const char *args) + { + if (!*args) + return false; + + int flag = atoi((char*)args); + + Player* chr = handler->getSelectedPlayer(); + if (chr == NULL) + { + handler->SendSysMessage(LANG_NO_CHAR_SELECTED); + handler->SetSentErrorMessage(true); + return false; + } + + if (flag != 0) + { + handler->PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, handler->GetNameLink(chr).c_str()); + if (handler->needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL, handler->GetNameLink().c_str()); + } + else + { + handler->PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, handler->GetNameLink(chr).c_str()); + if (handler->needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING, handler->GetNameLink().c_str()); + } + + for (uint8 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i) + { + if (flag != 0) + handler->GetSession()->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i, 0xFFFFFFFF); + else + handler->GetSession()->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i, 0); + } + + return true; + } +}; + +void AddSC_cheat_commandscript() +{ + new cheat_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 1edaaf5bcbf..fa4b0ce3957 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -82,10 +82,8 @@ public: { "saveall", SEC_MODERATOR, true, &HandleSaveAllCommand, "", NULL }, { "kick", SEC_GAMEMASTER, true, &HandleKickPlayerCommand, "", NULL }, { "start", SEC_PLAYER, false, &HandleStartCommand, "", NULL }, - { "taxicheat", SEC_MODERATOR, false, &HandleTaxiCheatCommand, "", NULL }, { "linkgrave", SEC_ADMINISTRATOR, false, &HandleLinkGraveCommand, "", NULL }, { "neargrave", SEC_ADMINISTRATOR, false, &HandleNearGraveCommand, "", NULL }, - { "explorecheat", SEC_ADMINISTRATOR, false, &HandleExploreCheatCommand, "", NULL }, { "showarea", SEC_ADMINISTRATOR, false, &HandleShowAreaCommand, "", NULL }, { "hidearea", SEC_ADMINISTRATOR, false, &HandleHideAreaCommand, "", NULL }, { "additem", SEC_ADMINISTRATOR, false, &HandleAddItemCommand, "", NULL }, @@ -106,7 +104,6 @@ public: { "combatstop", SEC_GAMEMASTER, true, &HandleCombatStopCommand, "", NULL }, { "flusharenapoints", SEC_ADMINISTRATOR, false, &HandleFlushArenaPointsCommand, "", NULL }, { "repairitems", SEC_GAMEMASTER, true, &HandleRepairitemsCommand, "", NULL }, - { "waterwalk", SEC_GAMEMASTER, false, &HandleWaterwalkCommand, "", NULL }, { "freeze", SEC_MODERATOR, false, &HandleFreezeCommand, "", NULL }, { "unfreeze", SEC_MODERATOR, false, &HandleUnFreezeCommand, "", NULL }, { "listfreeze", SEC_MODERATOR, false, &HandleListFreezeCommand, "", NULL }, @@ -960,49 +957,6 @@ public: player->CastSpell(player, 7355, false); return true; } - // Enable on\off all taxi paths - static bool HandleTaxiCheatCommand(ChatHandler* handler, char const* args) - { - if (!*args) - { - handler->SendSysMessage(LANG_USE_BOL); - handler->SetSentErrorMessage(true); - return false; - } - - std::string argStr = (char*)args; - - Player* chr = handler->getSelectedPlayer(); - - if (!chr) - chr = handler->GetSession()->GetPlayer(); - else if (handler->HasLowerSecurity(chr, 0)) // check online security - return false; - - if (argStr == "on") - { - chr->SetTaxiCheater(true); - handler->PSendSysMessage(LANG_YOU_GIVE_TAXIS, handler->GetNameLink(chr).c_str()); - if (handler->needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, handler->GetNameLink().c_str()); - return true; - } - - if (argStr == "off") - { - chr->SetTaxiCheater(false); - handler->PSendSysMessage(LANG_YOU_REMOVE_TAXIS, handler->GetNameLink(chr).c_str()); - if (handler->needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, handler->GetNameLink().c_str()); - - return true; - } - - handler->SendSysMessage(LANG_USE_BOL); - handler->SetSentErrorMessage(true); - - return false; - } static bool HandleLinkGraveCommand(ChatHandler* handler, char const* args) { @@ -1123,45 +1077,6 @@ public: return true; } - static bool HandleExploreCheatCommand(ChatHandler* handler, char const* args) - { - if (!*args) - return false; - - int32 flag = int32(atoi((char*)args)); - - Player* playerTarget = handler->getSelectedPlayer(); - if (!playerTarget) - { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; - } - - if (flag != 0) - { - handler->PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, handler->GetNameLink(playerTarget).c_str()); - if (handler->needReportToTarget(playerTarget)) - ChatHandler(playerTarget).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL, handler->GetNameLink().c_str()); - } - else - { - handler->PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, handler->GetNameLink(playerTarget).c_str()); - if (handler->needReportToTarget(playerTarget)) - ChatHandler(playerTarget).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING, handler->GetNameLink().c_str()); - } - - for (uint8 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i) - { - if (flag != 0) - handler->GetSession()->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i, 0xFFFFFFFF); - else - handler->GetSession()->GetPlayer()->SetFlag(PLAYER_EXPLORED_ZONES_1+i, 0); - } - - return true; - } - static bool HandleShowAreaCommand(ChatHandler* handler, char const* args) { if (!*args) @@ -2194,39 +2109,6 @@ public: return true; } - static bool HandleWaterwalkCommand(ChatHandler* handler, char const* args) - { - if (!*args) - return false; - - Player* player = handler->getSelectedPlayer(); - if (!player) - { - handler->PSendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; - } - - // check online security - if (handler->HasLowerSecurity(player, 0)) - return false; - - if (strncmp(args, "on", 3) == 0) - player->SetMovement(MOVE_WATER_WALK); // ON - else if (strncmp(args, "off", 4) == 0) - player->SetMovement(MOVE_LAND_WALK); // OFF - else - { - handler->SendSysMessage(LANG_USE_BOL); - return false; - } - - handler->PSendSysMessage(LANG_YOU_SET_WATERWALK, args, handler->GetNameLink(player).c_str()); - if (handler->needReportToTarget(player)) - ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, handler->GetNameLink().c_str()); - return true; - } - // Send mail by command static bool HandleSendMailCommand(ChatHandler* handler, char const* args) { -- cgit v1.2.3 From 6fbe3a11ecc92a9a3acd4e2b05a784a57051f425 Mon Sep 17 00:00:00 2001 From: w1sht0l1v3 Date: Fri, 31 Aug 2012 04:15:04 +0300 Subject: DB/SAI: Taking on All Challengers & Defending Your Title --- sql/updates/world/2012_08_31_00_world_sai.sql | 50 ++++++++++++++ src/server/scripts/Northrend/storm_peaks.cpp | 98 --------------------------- 2 files changed, 50 insertions(+), 98 deletions(-) create mode 100644 sql/updates/world/2012_08_31_00_world_sai.sql (limited to 'src') diff --git a/sql/updates/world/2012_08_31_00_world_sai.sql b/sql/updates/world/2012_08_31_00_world_sai.sql new file mode 100644 index 00000000000..fd7e0d7810f --- /dev/null +++ b/sql/updates/world/2012_08_31_00_world_sai.sql @@ -0,0 +1,50 @@ +-- Defending Your Title (13423) +-- Taking on All Challengers (12971) + +SET @NPC_CHALLENGER := 30012; -- Victorious Challenger +SET @QUEST1 := 12971; +SET @QUEST2 := 13423; +SET @GOSSIP_MENUID := 9865; +SET @SPELL_SUNDER := 11971; -- Sunder Armor +SET @SPELL_REND := 11977; -- Rend + +UPDATE `creature_template` SET `faction_A`=2109,`faction_H`=2109,`unit_flags`=0x8000,`npcflag`=0x1,`gossip_menu_id`=@GOSSIP_MENUID,`AIName`='SmartAI',`ScriptName`='' WHERE `entry`=@NPC_CHALLENGER; + +DELETE FROM `creature_template_addon` WHERE `entry`=@NPC_CHALLENGER; +INSERT INTO `creature_template_addon` (`entry`,`mount`,`bytes1`,`bytes2`,`auras`) VALUES +(@NPC_CHALLENGER,0,0x0,0x1,''); + +DELETE FROM `creature_text` WHERE `entry`=@NPC_CHALLENGER; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@NPC_CHALLENGER,0,0,'You will not defeat me!',12,0,100,0,0,0,'Victorious Challenger'), +(@NPC_CHALLENGER,0,1,'You''re not worthy of Thorim!',12,0,100,0,0,0,'Victorious Challenger'), +(@NPC_CHALLENGER,0,2,'Good luck... You''ll need it!',12,0,100,0,0,0,'Victorious Challenger'), +(@NPC_CHALLENGER,0,3,'May the best win!',12,0,100,0,0,0,'Victorious Challenger'); + +DELETE FROM `gossip_menu` WHERE `entry`=@GOSSIP_MENUID; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(@GOSSIP_MENUID,13660); + +DELETE FROM `gossip_menu_option` WHERE `menu_id`=@GOSSIP_MENUID; +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(@GOSSIP_MENUID,0,0,'Let''s do this, sister.',1,1,0,0,0,0,''); + +DELETE FROM `creature_equip_template` WHERE `entry`=@NPC_CHALLENGER; +INSERT INTO `creature_equip_template` (`entry`,`itemEntry1`,`itemEntry2`,`itemEntry3`) VALUES +(@NPC_CHALLENGER,40542,39288,0); + +DELETE FROM `smart_scripts` WHERE (`source_type`=0 AND `entryorguid`=@NPC_CHALLENGER) OR (`source_type`=9 AND `entryorguid`=@NPC_CHALLENGER*100); +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@NPC_CHALLENGER,0,0,0,25,0,100,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Victorious Challenger - On Reset - Set Default Faction'), +(@NPC_CHALLENGER,0,1,2,62,0,100,0,@GOSSIP_MENUID,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Victorious Challenger - On Gossip - Close Gossip'), +(@NPC_CHALLENGER,0,2,0,61,0,100,0,0,0,0,0,80,@NPC_CHALLENGER*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Victorious Challenger - On Gossip - Run Timed Script'), +(@NPC_CHALLENGER,0,3,0,9,0,100,0,0,5,5000,10000,11,@SPELL_SUNDER,0,0,0,0,0,2,0,0,0,0,0,0,0,'Victorious Challenger - On Range - Cast Sunder Armor'), +(@NPC_CHALLENGER,0,4,0,0,0,100,0,10000,15000,15000,20000,11,@SPELL_REND,0,0,0,0,0,2,0,0,0,0,0,0,0,'Victorious Challenger - IC - Cast Rend'), +(@NPC_CHALLENGER*100,9,0,0,0,0,100,0,1000,1000,1000,1000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Victorious Challenger - Timed - Talk'), +(@NPC_CHALLENGER*100,9,1,0,0,0,100,0,3000,3000,3000,3000,2,14,0,0,0,0,0,1,0,0,0,0,0,0,0,'Victorious Challenger - Timed - Set Faction Hostile'), +(@NPC_CHALLENGER*100,9,2,0,0,0,100,0,0,0,0,0,49,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Victorious Challenger - Timed - Attack Invoker'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=@GOSSIP_MENUID; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,@GOSSIP_MENUID,0,0,0,9,0,@QUEST1,0,0,0,0,'','Show gossip option 0 if player has quest Taking on All Challengers'), +(15,@GOSSIP_MENUID,0,0,1,9,0,@QUEST2,0,0,0,0,'','Show gossip option 0 if player has quest Defending Your Title'); diff --git a/src/server/scripts/Northrend/storm_peaks.cpp b/src/server/scripts/Northrend/storm_peaks.cpp index 6bf342e4643..60c289dc8de 100644 --- a/src/server/scripts/Northrend/storm_peaks.cpp +++ b/src/server/scripts/Northrend/storm_peaks.cpp @@ -194,103 +194,6 @@ public: } }; -/*###### -## npc_victorious_challenger -######*/ - -#define GOSSIP_CHALLENGER "Let's do this, sister." - -enum eVictoriousChallenger -{ - QUEST_TAKING_ALL_CHALLENGERS = 12971, - QUEST_DEFENDING_YOUR_TITLE = 13423, - - SPELL_SUNDER_ARMOR = 11971, - SPELL_REND_VC = 11977 -}; - -class npc_victorious_challenger : public CreatureScript -{ -public: - npc_victorious_challenger() : CreatureScript("npc_victorious_challenger") { } - - struct npc_victorious_challengerAI : public ScriptedAI - { - npc_victorious_challengerAI(Creature* creature) : ScriptedAI(creature) {} - - uint32 SunderArmorTimer; - uint32 RendTimer; - - void Reset() - { - me->RestoreFaction(); - - SunderArmorTimer = 10000; - RendTimer = 15000; - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (RendTimer < diff) - { - DoCast(me->getVictim(), SPELL_REND_VC, true); - RendTimer = 15000; - }else RendTimer -= diff; - - if (SunderArmorTimer < diff) - { - DoCast(me->getVictim(), SPELL_SUNDER_ARMOR, true); - SunderArmorTimer = 10000; - }else SunderArmorTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void KilledUnit(Unit* /*victim*/) - { - me->RestoreFaction(); - } - - }; - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_TAKING_ALL_CHALLENGERS) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_DEFENDING_YOUR_TITLE) == QUEST_STATUS_INCOMPLETE) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CHALLENGER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - return true; - } - - return false; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - player->CLOSE_GOSSIP_MENU(); - creature->setFaction(14); - creature->AI()->AttackStart(player); - } - - return true; - } - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_victorious_challengerAI(creature); - } -}; - /*###### ## npc_loklira_crone ######*/ @@ -753,7 +656,6 @@ void AddSC_storm_peaks() new npc_agnetta_tyrsdottar(); new npc_frostborn_scout(); new npc_thorim(); - new npc_victorious_challenger(); new npc_loklira_crone(); new npc_injured_goblin(); new npc_roxi_ramrocket(); -- cgit v1.2.3 From a8d514914be2e88dbae5013a17013adabefcfe74 Mon Sep 17 00:00:00 2001 From: Trista Date: Fri, 31 Aug 2012 14:20:11 +0100 Subject: Core/Scripts: Improve Wyrmrest Defender gossip * Added conditions to only show default gossip, if not on quest 12372 * Else show other gossip text * Add second gossip text on gossip select * Remove close gossip - after a lot of videos turns out character close it by moving or clicking "goodbye" Ref #1861 Closes #7594 --- src/server/scripts/Northrend/dragonblight.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Northrend/dragonblight.cpp b/src/server/scripts/Northrend/dragonblight.cpp index b915f4c6304..1f1d24453ee 100644 --- a/src/server/scripts/Northrend/dragonblight.cpp +++ b/src/server/scripts/Northrend/dragonblight.cpp @@ -174,9 +174,12 @@ public: ## wyrmrest_defender ######*/ -enum Spells +enum WyrmDefenderEnum { - SPELL_CHARACTER_SCRIPT = 49213 + QUEST_DEFENDING_WYRMREST_TEMPLE = 12372, + GOSSIP_TEXTID_DEF1 = 12899, + GOSSIP_TEXTID_DEF2 = 12900, + SPELL_CHARACTER_SCRIPT = 49213 }; #define GOSSIP_ITEM_1 "We need to get into the fight. Are you ready?" @@ -187,19 +190,24 @@ class npc_wyrmrest_defender : public CreatureScript npc_wyrmrest_defender() : CreatureScript("npc_wyrmrest_defender") { } bool OnGossipHello(Player* player, Creature* creature) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); + { + if (player->GetQuestStatus(QUEST_DEFENDING_WYRMREST_TEMPLE) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DEF1, creature->GetGUID()); + } + else + player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); return true; } - bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) + bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) { player->PlayerTalkClass->ClearMenus(); if (action == GOSSIP_ACTION_INFO_DEF+1) { - player->CLOSE_GOSSIP_MENU(); + player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DEF2, creature->GetGUID()); // Makes player cast trigger spell for 49207 on self player->CastSpell(player, SPELL_CHARACTER_SCRIPT, true); } -- cgit v1.2.3 From d7eeebe0f3b9c1256bce900c39e0abcbf9641168 Mon Sep 17 00:00:00 2001 From: kaelima Date: Mon, 3 Sep 2012 20:30:30 +0200 Subject: Core/MMaps: Implement pathed charge effect --- src/server/game/Movement/MotionMaster.cpp | 14 +++++++++++- src/server/game/Movement/MotionMaster.h | 2 ++ .../MovementGenerators/PointMovementGenerator.cpp | 7 ++++-- .../MovementGenerators/PointMovementGenerator.h | 2 +- src/server/game/Movement/PathGenerator.cpp | 7 ++++++ src/server/game/Movement/PathGenerator.h | 13 ++++++----- src/server/game/Spells/Spell.cpp | 20 ++++++++++++++++- src/server/game/Spells/Spell.h | 2 ++ src/server/game/Spells/SpellEffects.cpp | 26 +++++++++++----------- 9 files changed, 69 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 2ad8028ca4f..d7bf433677c 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -340,7 +340,7 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa _owner->GetNearPoint(_owner, x, y, z, _owner->GetObjectSize(), dist, _owner->GetAngle(srcX, srcY) + M_PI); Movement::MoveSplineInit init(_owner); - init.MoveTo(x,y,z); + init.MoveTo(x, y, z); init.SetParabolic(max_height,0); init.SetOrientationFixed(true); init.SetVelocity(speedXY); @@ -423,6 +423,18 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id, } } +void MotionMaster::MoveCharge(PathGenerator path, float speed, uint32 id) +{ + Vector3 dest = path.getActualEndPosition(); + + MoveCharge(dest.x, dest.y, dest.z); + + Movement::MoveSplineInit init(_owner); + init.MovebyPath(path.getPath()); + init.SetVelocity(speed); + init.Launch(); +} + void MotionMaster::MoveSeekAssistance(float x, float y, float z) { if (_owner->GetTypeId() == TYPEID_PLAYER) diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 16accff2ab4..d59ec83e615 100755 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -26,6 +26,7 @@ class MovementGenerator; class Unit; +class PathGenerator; // Creature Entry ID used for waypoints show, visible only for GMs #define VISUAL_WAYPOINT 1 @@ -161,6 +162,7 @@ class MotionMaster //: private std::stack void MoveTakeoff(uint32 id, Position const& pos); void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, bool generatePath = false); + void MoveCharge(PathGenerator path, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE); void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ); void MoveJumpTo(float angle, float speedXY, float speedZ); void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = 0); diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index 20f1c3a29e9..c022de31869 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -33,7 +33,10 @@ void PointMovementGenerator::Initialize(T* unit) unit->StopMoving(); unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); - i_recalculateSpeed = false; + + if (id == EVENT_CHARGE) + return; + Movement::MoveSplineInit init(unit); init.MoveTo(i_x, i_y, i_z, m_generatePath); if (speed > 0.0f) @@ -55,7 +58,7 @@ bool PointMovementGenerator::Update(T* unit, const uint32& /*diff*/) unit->AddUnitState(UNIT_STATE_ROAMING_MOVE); - if (i_recalculateSpeed && !unit->movespline->Finalized()) + if (id != EVENT_CHARGE && i_recalculateSpeed && !unit->movespline->Finalized()) { i_recalculateSpeed = false; Movement::MoveSplineInit init(unit); diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h index 4111690627e..e01ced758a3 100644 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h @@ -27,7 +27,7 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG { public: PointMovementGenerator(uint32 _id, float _x, float _y, float _z, bool _generatePath, float _speed = 0.0f) : id(_id), - i_x(_x), i_y(_y), i_z(_z), m_generatePath(_generatePath), speed(_speed) {} + i_x(_x), i_y(_y), i_z(_z), m_generatePath(_generatePath), speed(_speed), i_recalculateSpeed(false) {} void Initialize(T*); void Finalize(T*); diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 4d7707020e1..a02eb0a9a84 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -456,6 +456,13 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin m_type = PATHFIND_NOPATH; return; } + else if (pointCount == m_pointPathLimit) + { + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d\n", pointCount, m_pointPathLimit); + BuildShortcut(); + m_type = PATHFIND_SHORT; + return; + } m_pathPoints.resize(pointCount); for (uint32 i = 0; i < pointCount; ++i) diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index a0d925cb11f..ac163f43be5 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -43,12 +43,13 @@ class Unit; enum PathType { - PATHFIND_BLANK = 0x0000, // path not built yet - PATHFIND_NORMAL = 0x0001, // normal path - PATHFIND_SHORTCUT = 0x0002, // travel through obstacles, terrain, air, etc (old behavior) - PATHFIND_INCOMPLETE = 0x0004, // we have partial path to follow - getting closer to target - PATHFIND_NOPATH = 0x0008, // no valid path at all or error in generating one - PATHFIND_NOT_USING_PATH = 0x0010 // used when we are either flying/swiming or on map w/o mmaps + PATHFIND_BLANK = 0x00, // path not built yet + PATHFIND_NORMAL = 0x01, // normal path + PATHFIND_SHORTCUT = 0x02, // travel through obstacles, terrain, air, etc (old behavior) + PATHFIND_INCOMPLETE = 0x04, // we have partial path to follow - getting closer to target + PATHFIND_NOPATH = 0x08, // no valid path at all or error in generating one + PATHFIND_NOT_USING_PATH = 0x10, // used when we are either flying/swiming or on map w/o mmaps + PATHFIND_SHORT = 0x20, // path is longer or equal to its limited path length }; class PathGenerator diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 79e6404f73e..6e056bf59f8 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -490,7 +490,7 @@ SpellValue::SpellValue(SpellInfo const* proto) Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, uint64 originalCasterGUID, bool skipCheck) : m_spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(info, caster)), m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster) -, m_spellValue(new SpellValue(m_spellInfo)) +, m_spellValue(new SpellValue(m_spellInfo)), m_preGeneratedPath(PathGenerator(m_caster)) { m_customError = SPELL_CUSTOM_ERROR_NONE; m_skipCheck = skipCheck; @@ -610,6 +610,7 @@ Spell::~Spell() if (m_caster && m_caster->GetTypeId() == TYPEID_PLAYER) ASSERT(m_caster->ToPlayer()->m_spellModTakingSpell != this); + delete m_spellValue; CheckEffectExecuteData(); @@ -5143,8 +5144,25 @@ SpellCastResult Spell::CheckCast(bool strict) if (strict && m_caster->IsScriptOverriden(m_spellInfo, 6953)) m_caster->RemoveMovementImpairingAuras(); } + if (m_caster->HasUnitState(UNIT_STATE_ROOT)) return SPELL_FAILED_ROOTED; + + Unit* target = m_targets.GetUnitTarget(); + + if (!target) + return SPELL_FAILED_DONT_REPORT; + + Position pos; + target->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); + target->GetFirstCollisionPosition(pos, CONTACT_DISTANCE, target->GetRelativeAngle(m_caster)); + + m_preGeneratedPath.setPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f); + m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize()); + + if (m_preGeneratedPath.getPathType() & PATHFIND_SHORT) + return SPELL_FAILED_OUT_OF_RANGE; + break; } case SPELL_EFFECT_SKINNING: diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 1376b0fbd40..22495b3f1f0 100755 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -23,6 +23,7 @@ #include "SharedDefines.h" #include "ObjectMgr.h" #include "SpellInfo.h" +#include "PathGenerator.h" class Unit; class Player; @@ -666,6 +667,7 @@ class Spell bool m_skipCheck; uint8 m_auraScaleMask; + PathGenerator m_preGeneratedPath; ByteBuffer * m_effectExecuteData[MAX_SPELL_EFFECTS]; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 3637bb18049..1aa2ca0176b 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -63,6 +63,7 @@ #include "GameObjectAI.h" #include "AccountMgr.h" #include "InstanceScript.h" +#include "PathGenerator.h" pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= { @@ -5133,25 +5134,24 @@ void Spell::EffectSkinning(SpellEffIndex /*effIndex*/) void Spell::EffectCharge(SpellEffIndex /*effIndex*/) { + if (!unitTarget) + return; + if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET) { - if (!unitTarget) - return; - - float angle = unitTarget->GetRelativeAngle(m_caster); - Position pos; - - unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); - unitTarget->GetFirstCollisionPosition(pos, unitTarget->GetObjectSize(), angle); - - m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ + unitTarget->GetObjectSize()); + if (m_preGeneratedPath.getPathType() & PATHFIND_NOPATH) + { + Position pos; + unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); + unitTarget->GetFirstCollisionPosition(pos, unitTarget->GetObjectSize(), unitTarget->GetRelativeAngle(m_caster)); + m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ); + } + else + m_caster->GetMotionMaster()->MoveCharge(m_preGeneratedPath); } if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET) { - if (!unitTarget) - return; - // not all charge effects used in negative spells if (!m_spellInfo->IsPositive() && m_caster->GetTypeId() == TYPEID_PLAYER) m_caster->Attack(unitTarget, true); -- cgit v1.2.3 From a9e672ab1d33a3502381d4b33f679a9d1f1f2087 Mon Sep 17 00:00:00 2001 From: kaelima Date: Mon, 3 Sep 2012 20:34:07 +0200 Subject: Core/MMaps: Prevent path generation when falling or exiting vehicle --- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Movement/MotionMaster.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ca8cb4763d7..d610c2e0fb9 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -17158,7 +17158,7 @@ void Unit::_ExitVehicle(Position const* exitPosition) } Movement::MoveSplineInit init(this); - init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); + init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), false); init.SetFacing(GetOrientation()); init.SetTransportExit(); init.Launch(); diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index d7bf433677c..bf938c3af6c 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -399,7 +399,7 @@ void MotionMaster::MoveFall(uint32 id/*=0*/) } Movement::MoveSplineInit init(_owner); - init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz); + init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz, false); init.SetFall(); init.Launch(); Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED); -- cgit v1.2.3 From 306e4c173c2a2c050af61f8eb511c67496621a60 Mon Sep 17 00:00:00 2001 From: Nay Date: Tue, 4 Sep 2012 19:58:39 +0100 Subject: Fix a merge failure --- .../game/Movement/MovementGenerators/FleeingMovementGenerator.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 029bc55ab58..acb1a57a9ba 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -47,11 +47,6 @@ void FleeingMovementGenerator::_setTargetLocation(T* owner) path.setPathLengthLimit(30.0f); path.CalculatePath(x, y, z); if (path.getPathType() & PATHFIND_NOPATH) - default: - angle = 0.0f; - distance = 0.0f; - break; - { i_nextCheckTime.Reset(urand(1000, 1500)); return; -- cgit v1.2.3 From 69602df83388e89dc473936f08992c48022a73f0 Mon Sep 17 00:00:00 2001 From: kaelima Date: Tue, 4 Sep 2012 23:33:11 +0200 Subject: Core/MMaps: Fix some uninitialized variable complaints in PathGenerator --- src/server/game/Movement/PathGenerator.cpp | 19 ++++++++++--------- src/tools/mmaps_generator/PathGenerator.cpp | 4 ++-- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index a02eb0a9a84..62ab0be4630 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -30,7 +30,7 @@ PathGenerator::PathGenerator(const Unit* owner) : m_polyLength(0), m_type(PATHFIND_BLANK), m_useStraightPath(false), m_forceDestination(false), m_pointPathLimit(MAX_POINT_PATH_LENGTH), - m_sourceUnit(owner), m_navMesh(NULL), m_navMeshQuery(NULL) + m_sourceUnit(owner), m_navMesh(NULL), m_navMeshQuery(NULL), m_endPosition(Vector3::zero()) { sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::PathGenerator for %u \n", m_sourceUnit->GetGUIDLow()); @@ -52,16 +52,16 @@ PathGenerator::~PathGenerator() bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest) { - if (!Trinity::IsValidMapCoord(destX, destY, destZ) || - !Trinity::IsValidMapCoord(m_sourceUnit->GetPositionX(), m_sourceUnit->GetPositionY(), m_sourceUnit->GetPositionZ())) + float x, y, z; + m_sourceUnit->GetPosition(x, y, z); + + if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z)) return false; Vector3 oldDest = getEndPosition(); Vector3 dest(destX, destY, destZ); setEndPosition(dest); - float x, y, z; - m_sourceUnit->GetPosition(x, y, z); Vector3 start(x, y, z); setStartPosition(start); @@ -84,7 +84,7 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo // check if destination moved - if not we can optimize something here // we are following old, precalculated path? float dist = m_sourceUnit->GetObjectSize(); - if (inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) + if (oldDest != Vector3::zero() && inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride @@ -192,7 +192,7 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos if (waterPath) { // Check both start and end points, if they're both in water, then we can *safely* let the creature move - for (int i = 0; i < m_pathPoints.size(); ++i) + for (uint32 i = 0; i < m_pathPoints.size(); ++i) { LiquidData data; m_sourceUnit->GetBaseMap()->getLiquidStatus(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z, MAP_ALL_LIQUIDS, &data); @@ -277,11 +277,12 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos // TODO: we can merge it with getPathPolyByPosition() loop bool startPolyFound = false; bool endPolyFound = false; - uint32 pathStartIndex, pathEndIndex; + uint32 pathStartIndex = 0; + uint32 pathEndIndex = 0; if (m_polyLength) { - for (pathStartIndex = 0; pathStartIndex < m_polyLength; ++pathStartIndex) + for (; pathStartIndex < m_polyLength; ++pathStartIndex) { // here to carch few bugs ASSERT(m_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 026bf957ec4..9707cb4160a 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -26,14 +26,14 @@ bool checkDirectories(bool debugOutput) { vector dirFiles; - if (getDirContents(dirFiles, "maps") == LISTFILE_DIRECTORY_NOT_FOUND || !dirFiles.size()) + if (getDirContents(dirFiles, "maps") == LISTFILE_DIRECTORY_NOT_FOUND || dirFiles.empty()) { printf("'maps' directory is empty or does not exist\n"); return false; } dirFiles.clear(); - if (getDirContents(dirFiles, "vmaps", "*.vmtree") == LISTFILE_DIRECTORY_NOT_FOUND || !dirFiles.size()) + if (getDirContents(dirFiles, "vmaps", "*.vmtree") == LISTFILE_DIRECTORY_NOT_FOUND || dirFiles.empty()) { printf("'vmaps' directory is empty or does not exist\n"); return false; -- cgit v1.2.3 From c2f446ded917efed58c8054693858b3c4b4c4a8f Mon Sep 17 00:00:00 2001 From: kaelima Date: Wed, 5 Sep 2012 17:07:47 +0200 Subject: Core/MMaps: Minor warning fix --- src/server/game/Movement/PathGenerator.cpp | 13 ++++++------- src/tools/mmaps_generator/MapBuilder.cpp | 10 +++++----- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 62ab0be4630..c9cfff08ede 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -591,8 +591,7 @@ bool PathGenerator::HaveTile(const Vector3 &p) const return (m_navMesh->getTileAt(tx, ty) != NULL); } -uint32 PathGenerator::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, - const dtPolyRef* visited, uint32 nvisited) +uint32 PathGenerator::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited) { int32 furthestPath = -1; int32 furthestVisited = -1; @@ -622,17 +621,17 @@ uint32 PathGenerator::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPat // Adjust beginning of the buffer to include the visited. uint32 req = nvisited - furthestVisited; - uint32 orig = uint32(furthestPath+1) < npath ? furthestPath+1 : npath; - uint32 size = npath-orig > 0 ? npath-orig : 0; - if (req+size > maxPath) + uint32 orig = uint32(furthestPath + 1) < npath ? furthestPath + 1 : npath; + uint32 size = npath > orig ? npath - orig : 0; + if (req + size > maxPath) size = maxPath-req; if (size) - memmove(path+req, path+orig, size*sizeof(dtPolyRef)); + memmove(path + req, path + orig, size * sizeof(dtPolyRef)); // Store visited for (uint32 i = 0; i < req; ++i) - path[i] = visited[(nvisited-1)-i]; + path[i] = visited[(nvisited - 1) - i]; return req+size; } diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 2a74233a1a7..69ffad94eb7 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -564,10 +564,10 @@ namespace MMAP Tile& tile = tiles[x + y * TILES_PER_MAP]; // Calculate the per tile bounding box. - tileCfg.bmin[0] = config.bmin[0] + (x*config.tileSize - config.borderSize)*config.cs; - tileCfg.bmin[2] = config.bmin[2] + (y*config.tileSize - config.borderSize)*config.cs; - tileCfg.bmax[0] = config.bmin[0] + ((x+1)*config.tileSize + config.borderSize)*config.cs; - tileCfg.bmax[2] = config.bmin[2] + ((y+1)*config.tileSize + config.borderSize)*config.cs; + tileCfg.bmin[0] = config.bmin[0] + float(x*config.tileSize - config.borderSize)*config.cs; + tileCfg.bmin[2] = config.bmin[2] + float(y*config.tileSize - config.borderSize)*config.cs; + tileCfg.bmax[0] = config.bmin[0] + float((x+1)*config.tileSize + config.borderSize)*config.cs; + tileCfg.bmax[2] = config.bmin[2] + float((y+1)*config.tileSize + config.borderSize)*config.cs; // build heightfield tile.solid = rcAllocHeightfield(); @@ -633,7 +633,7 @@ namespace MMAP } tile.dmesh = rcAllocPolyMeshDetail(); - if (!tile.dmesh || !rcBuildPolyMeshDetail(m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg .detailSampleMaxError, *tile.dmesh)) + if (!tile.dmesh || !rcBuildPolyMeshDetail(m_rcContext, *tile.pmesh, *tile.chf, tileCfg.detailSampleDist, tileCfg.detailSampleMaxError, *tile.dmesh)) { printf("%s Failed building polymesh detail! \n", tileString); continue; -- cgit v1.2.3 From 593f08609fa474c9aa881898e23e256e6e55c06e Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 5 Sep 2012 15:32:35 -0500 Subject: Core/Mmaps: Fixed a mistake in BuildPolyPath which could cause swimming creatures to bug in the navmesh generation. --- src/server/game/Movement/PathGenerator.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index c9cfff08ede..00aa8043312 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -194,10 +194,9 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos // Check both start and end points, if they're both in water, then we can *safely* let the creature move for (uint32 i = 0; i < m_pathPoints.size(); ++i) { - LiquidData data; - m_sourceUnit->GetBaseMap()->getLiquidStatus(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z, MAP_ALL_LIQUIDS, &data); + ZLiquidStatus status = m_sourceUnit->GetBaseMap()->getLiquidStatus(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z, MAP_ALL_LIQUIDS, NULL); // One of the points is not in the water, cancel movement. - if (data.type_flags == MAP_LIQUID_TYPE_NO_WATER) + if (status == LIQUID_MAP_NO_WATER) { waterPath = false; break; -- cgit v1.2.3 From ccdca7774023e7570f17cf15456384b316322420 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 5 Sep 2012 16:05:26 -0500 Subject: Core/Mmaps: Fixed unloading mmap tiles, the x and y were swapped. thanks to MaNGOS for original implementation, and thanks to @Chevron for noticing. --- src/server/collision/Management/MMapManager.cpp | 24 ++++++++++++------------ src/server/game/Maps/Map.cpp | 4 +--- 2 files changed, 13 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp index 0222f1a5995..8e6e2a3b6b4 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/server/collision/Management/MMapManager.cpp @@ -100,8 +100,8 @@ namespace MMAP // load this tile :: mmaps/MMMXXYY.mmtile uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1; char *fileName = new char[pathLen]; - // this change of y and x is needed because of mapbuilder.cpp (x and y are swapped there) so change it here so we dont need to re-extract. All swappes are done in other files. DONT CHANGE THIS! - snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, y, x); + + snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); FILE *file = fopen(fileName, "rb"); if (!file) @@ -118,7 +118,7 @@ namespace MMAP if (fileHeader.mmapMagic != MMAP_MAGIC) { - sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, y, x); + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y); return false; } @@ -135,7 +135,7 @@ namespace MMAP size_t result = fread(data, fileHeader.size, 1, file); if (!result) { - sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, y, x); + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y); fclose(file); return false; } @@ -150,12 +150,12 @@ namespace MMAP { mmap->mmapLoadedTiles.insert(std::pair(packedGridPos, tileRef)); ++loadedTiles; - sLog->outInfo(LOG_FILTER_MAPS, "MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, y, x, mapId, header->x, header->y); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, x, y, mapId, header->x, header->y); return true; } else { - sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, y, x); + sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y); dtFree(data); return false; } @@ -169,7 +169,7 @@ namespace MMAP if (loadedMMaps.find(mapId) == loadedMMaps.end()) { // file may not exist, therefore not loaded - sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, y, x); + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y); return false; } @@ -180,7 +180,7 @@ namespace MMAP if (mmap->mmapLoadedTiles.find(packedGridPos) == mmap->mmapLoadedTiles.end()) { // file may not exist, therefore not loaded - sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, y, x); + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y); return false; } @@ -192,14 +192,14 @@ namespace MMAP // this is technically a memory leak // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used // we cannot recover from this error - assert out - sLog->outError(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, y, x); + sLog->outError(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); ASSERT(false); } else { mmap->mmapLoadedTiles.erase(packedGridPos); --loadedTiles; - sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, y, x, mapId); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId); return true; } @@ -222,11 +222,11 @@ namespace MMAP uint32 x = (i->first >> 16); uint32 y = (i->first & 0x0000FFFF); if (DT_SUCCESS != mmap->navMesh->removeTile(i->second, NULL, NULL)) - sLog->outError(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, y, x); + sLog->outError(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); else { --loadedTiles; - sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, y, x, mapId); + sLog->outInfo(LOG_FILTER_MAPS, "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId); } } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index af139568ece..7e5a2ebb220 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -123,8 +123,7 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy) void Map::LoadMMap(int gx, int gy) { - // DONT CHANGE "gy" and "gx" - Its necessary ! - bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gy, gx); + bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gx, gy); if (mmapLoadResult) sLog->outInfo(LOG_FILTER_MAPS, "MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); @@ -1011,7 +1010,6 @@ bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll) GridMaps[gx][gy]->unloadData(); delete GridMaps[gx][gy]; } - // x and y are swapped VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gx, gy); MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId(), gx, gy); } -- cgit v1.2.3 From e7c0d8bef023a0b948602e2fc6b31fc68a120ac4 Mon Sep 17 00:00:00 2001 From: Venugh Date: Wed, 5 Sep 2012 23:47:02 +0200 Subject: Core/MMaps: Applied Trinity Codestyle to PathGenerator. --- src/server/game/Movement/MotionMaster.cpp | 4 +- .../ConfusedMovementGenerator.cpp | 6 +- .../FleeingMovementGenerator.cpp | 6 +- .../TargetedMovementGenerator.cpp | 4 +- src/server/game/Movement/PathGenerator.cpp | 307 ++++++++++----------- src/server/game/Movement/PathGenerator.h | 91 +++--- src/server/game/Movement/Spline/MoveSplineInit.cpp | 2 +- src/server/game/Spells/Spell.cpp | 4 +- src/server/game/Spells/SpellEffects.cpp | 2 +- 9 files changed, 211 insertions(+), 215 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index bf938c3af6c..34be779a8b7 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -425,12 +425,12 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id, void MotionMaster::MoveCharge(PathGenerator path, float speed, uint32 id) { - Vector3 dest = path.getActualEndPosition(); + Vector3 dest = path.GetActualEndPosition(); MoveCharge(dest.x, dest.y, dest.z); Movement::MoveSplineInit init(_owner); - init.MovebyPath(path.getPath()); + init.MovebyPath(path.GetPath()); init.SetVelocity(speed); init.Launch(); } diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index f1d1d8cf04a..32c6ec3858d 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -77,16 +77,16 @@ bool ConfusedMovementGenerator::Update(T* unit, const uint32& diff) unit->UpdateAllowedPositionZ(x, y, z); PathGenerator path(unit); - path.setPathLengthLimit(30.0f); + path.SetPathLengthLimit(30.0f); path.CalculatePath(x, y, z); - if (path.getPathType() & PATHFIND_NOPATH) + if (path.GetPathType() & PATHFIND_NOPATH) { i_nextMoveTime.Reset(urand(800, 1000)); return true; } Movement::MoveSplineInit init(unit); - init.MovebyPath(path.getPath()); + init.MovebyPath(path.GetPath()); init.SetWalk(true); init.Launch(); } diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index acb1a57a9ba..8f4d78b34b1 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -44,16 +44,16 @@ void FleeingMovementGenerator::_setTargetLocation(T* owner) owner->AddUnitState(UNIT_STATE_FLEEING_MOVE); PathGenerator path(owner); - path.setPathLengthLimit(30.0f); + path.SetPathLengthLimit(30.0f); path.CalculatePath(x, y, z); - if (path.getPathType() & PATHFIND_NOPATH) + if (path.GetPathType() & PATHFIND_NOPATH) { i_nextCheckTime.Reset(urand(1000, 1500)); return; } Movement::MoveSplineInit init(owner); - init.MovebyPath(path.getPath()); + init.MovebyPath(path.GetPath()); init.SetWalk(false); int32 traveltime = init.Launch(); i_nextCheckTime.Reset(traveltime + urand(800, 1500)); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 9784c19b4fd..4a8d15b8079 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -70,7 +70,7 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner) bool forceDest = (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->isPet() && owner->HasUnitState(UNIT_STATE_FOLLOW)); i_path->CalculatePath(x, y, z, forceDest); - if (i_path->getPathType() & PATHFIND_NOPATH) + if (i_path->GetPathType() & PATHFIND_NOPATH) return; D::_addUnitStateMove(owner); @@ -79,7 +79,7 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner) owner->AddUnitState(UNIT_STATE_CHASE); Movement::MoveSplineInit init(owner); - init.MovebyPath(i_path->getPath()); + init.MovebyPath(i_path->GetPath()); init.SetWalk(((D*)this)->EnableWalking()); init.Launch(); } diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 00aa8043312..165cc282e3a 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -28,69 +28,69 @@ ////////////////// PathGenerator ////////////////// PathGenerator::PathGenerator(const Unit* owner) : - m_polyLength(0), m_type(PATHFIND_BLANK), - m_useStraightPath(false), m_forceDestination(false), m_pointPathLimit(MAX_POINT_PATH_LENGTH), - m_sourceUnit(owner), m_navMesh(NULL), m_navMeshQuery(NULL), m_endPosition(Vector3::zero()) + _polyLength(0), _type(PATHFIND_BLANK), + _useStraightPath(false), _forceDestination(false), _pointPathLimit(MAX_POINT_PATH_LENGTH), + _sourceUnit(owner), _navMesh(NULL), _navMeshQuery(NULL), _endPosition(Vector3::zero()) { - sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::PathGenerator for %u \n", m_sourceUnit->GetGUIDLow()); + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow()); - uint32 mapId = m_sourceUnit->GetMapId(); + uint32 mapId = _sourceUnit->GetMapId(); if (MMAP::MMapFactory::IsPathfindingEnabled(mapId)) { MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); - m_navMesh = mmap->GetNavMesh(mapId); - m_navMeshQuery = mmap->GetNavMeshQuery(mapId, m_sourceUnit->GetInstanceId()); + _navMesh = mmap->GetNavMesh(mapId); + _navMeshQuery = mmap->GetNavMeshQuery(mapId, _sourceUnit->GetInstanceId()); } - createFilter(); + CreateFilter(); } PathGenerator::~PathGenerator() { - sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::~PathGenerator() for %u \n", m_sourceUnit->GetGUIDLow()); + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::~PathGenerator() for %u \n", _sourceUnit->GetGUIDLow()); } bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest) { float x, y, z; - m_sourceUnit->GetPosition(x, y, z); + _sourceUnit->GetPosition(x, y, z); if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z)) return false; - Vector3 oldDest = getEndPosition(); + Vector3 oldDest = GetEndPosition(); Vector3 dest(destX, destY, destZ); - setEndPosition(dest); + SetEndPosition(dest); Vector3 start(x, y, z); - setStartPosition(start); + SetStartPosition(start); - m_forceDestination = forceDest; + _forceDestination = forceDest; - sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::CalculatePath() for %u \n", m_sourceUnit->GetGUIDLow()); + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::CalculatePath() for %u \n", _sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) - if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || + if (!_navMesh || !_navMeshQuery || _sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || !HaveTile(start) || !HaveTile(dest)) { BuildShortcut(); - m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } - updateFilter(); + UpdateFilter(); // check if destination moved - if not we can optimize something here // we are following old, precalculated path? - float dist = m_sourceUnit->GetObjectSize(); - if (oldDest != Vector3::zero() && inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) + float dist = _sourceUnit->GetObjectSize(); + if (oldDest != Vector3::zero() && InRange(oldDest, dest, dist, dist) && _pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::CalculatePath:: precalculated path\n"); - m_pathPoints.erase(m_pathPoints.begin()); + _pathPoints.erase(_pathPoints.begin()); return false; } else @@ -101,7 +101,7 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo } } -dtPolyRef PathGenerator::getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance) const +dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* point, float* distance) const { if (!polyPath || !polyPathSize) return INVALID_POLYREF; @@ -113,7 +113,7 @@ dtPolyRef PathGenerator::getPathPolyByPosition(const dtPolyRef *polyPath, uint32 for (uint32 i = 0; i < polyPathSize; ++i) { float closestPoint[VERTEX_SIZE]; - if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint)) + if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint)) continue; float d = dtVdist2DSqr(point, closestPoint); @@ -134,12 +134,12 @@ dtPolyRef PathGenerator::getPathPolyByPosition(const dtPolyRef *polyPath, uint32 return (minDist2d < 3.0f) ? nearestPoly : INVALID_POLYREF; } -dtPolyRef PathGenerator::getPolyByLocation(const float* point, float *distance) const +dtPolyRef PathGenerator::GetPolyByLocation(float const* point, float* distance) const { // first we check the current path // if the current path doesn't contain the current poly, // we need to use the expensive navMesh.findNearestPoly - dtPolyRef polyRef = getPathPolyByPosition(m_pathPolyRefs, m_polyLength, point, distance); + dtPolyRef polyRef = GetPathPolyByPosition(_pathPolyRefs, _polyLength, point, distance); if (polyRef != INVALID_POLYREF) return polyRef; @@ -148,7 +148,7 @@ dtPolyRef PathGenerator::getPolyByLocation(const float* point, float *distance) // first try with low search box float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f}; - dtStatus result = m_navMeshQuery->findNearestPoly(point, extents, &m_filter, &polyRef, closestPoint); + dtStatus result = _navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint); if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) { *distance = dtVdist(closestPoint, point); @@ -158,7 +158,7 @@ dtPolyRef PathGenerator::getPolyByLocation(const float* point, float *distance) // still nothing .. // try with bigger search box extents[1] = 200.0f; - result = m_navMeshQuery->findNearestPoly(point, extents, &m_filter, &polyRef, closestPoint); + result = _navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint); if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) { *distance = dtVdist(closestPoint, point); @@ -168,7 +168,7 @@ dtPolyRef PathGenerator::getPolyByLocation(const float* point, float *distance) return INVALID_POLYREF; } -void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos) +void PathGenerator::BuildPolyPath(Vector3 const& startPos, Vector3 const& endPos) { // *** getting start/end poly logic *** @@ -176,8 +176,8 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x}; float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x}; - dtPolyRef startPoly = getPolyByLocation(startPoint, &distToStartPoly); - dtPolyRef endPoly = getPolyByLocation(endPoint, &distToEndPoly); + dtPolyRef startPoly = GetPolyByLocation(startPoint, &distToStartPoly); + dtPolyRef endPoly = GetPolyByLocation(endPoint, &distToEndPoly); // we have a hole in our mesh // make shortcut path and mark it as NOPATH ( with flying and swimming exception ) @@ -186,15 +186,15 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos { sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); BuildShortcut(); - bool path = m_sourceUnit->GetTypeId() == TYPEID_UNIT && m_sourceUnit->ToCreature()->CanFly(); + bool path = _sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->CanFly(); - bool waterPath = m_sourceUnit->GetTypeId() == TYPEID_UNIT && m_sourceUnit->ToCreature()->canSwim(); + bool waterPath = _sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->canSwim(); if (waterPath) { // Check both start and end points, if they're both in water, then we can *safely* let the creature move - for (uint32 i = 0; i < m_pathPoints.size(); ++i) + for (uint32 i = 0; i < _pathPoints.size(); ++i) { - ZLiquidStatus status = m_sourceUnit->GetBaseMap()->getLiquidStatus(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z, MAP_ALL_LIQUIDS, NULL); + ZLiquidStatus status = _sourceUnit->GetBaseMap()->getLiquidStatus(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, NULL); // One of the points is not in the water, cancel movement. if (status == LIQUID_MAP_NO_WATER) { @@ -204,7 +204,7 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos } } - m_type = (path || waterPath) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; + _type = (path || waterPath) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; return; } @@ -215,12 +215,12 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly); bool buildShotrcut = false; - if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) + if (_sourceUnit->GetTypeId() == TYPEID_UNIT) { - Creature* owner = (Creature*)m_sourceUnit; + Creature* owner = (Creature*)_sourceUnit; Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos; - if (m_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) + if (_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) { sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: underWater case\n"); if (owner->canSwim()) @@ -237,20 +237,20 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos if (buildShotrcut) { BuildShortcut(); - m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return; } else { float closestPoint[VERTEX_SIZE]; // we may want to use closestPointOnPolyBoundary instead - if (DT_SUCCESS == m_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) + if (DT_SUCCESS == _navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) { dtVcopy(endPoint, closestPoint); - setActualEndPosition(Vector3(endPoint[2],endPoint[0],endPoint[1])); + SetActualEndPosition(Vector3(endPoint[2], endPoint[0], endPoint[1])); } - m_type = PATHFIND_INCOMPLETE; + _type = PATHFIND_INCOMPLETE; } } @@ -264,11 +264,11 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos BuildShortcut(); - m_pathPolyRefs[0] = startPoly; - m_polyLength = 1; + _pathPolyRefs[0] = startPoly; + _polyLength = 1; - m_type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL; - sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: path type %d\n", m_type); + _type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL; + sLog->outDebug(LOG_FILTER_MAPS, "++ BuildPolyPath :: path type %d\n", _type); return; } @@ -279,22 +279,22 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos uint32 pathStartIndex = 0; uint32 pathEndIndex = 0; - if (m_polyLength) + if (_polyLength) { - for (; pathStartIndex < m_polyLength; ++pathStartIndex) + for (; pathStartIndex < _polyLength; ++pathStartIndex) { // here to carch few bugs - ASSERT(m_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); + ASSERT(_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); - if (m_pathPolyRefs[pathStartIndex] == startPoly) + if (_pathPolyRefs[pathStartIndex] == startPoly) { startPolyFound = true; break; } } - for (pathEndIndex = m_polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) - if (m_pathPolyRefs[pathEndIndex] == endPoly) + for (pathEndIndex = _polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) + if (_pathPolyRefs[pathEndIndex] == endPoly) { endPolyFound = true; break; @@ -309,8 +309,8 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos // our path is a simple subpath case, we have all the data we need // just "cut" it out - m_polyLength = pathEndIndex - pathStartIndex + 1; - memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, m_polyLength*sizeof(dtPolyRef)); + _polyLength = pathEndIndex - pathStartIndex + 1; + memmove(_pathPolyRefs, _pathPolyRefs + pathStartIndex, _polyLength * sizeof(dtPolyRef)); } else if (startPolyFound && !endPolyFound) { @@ -319,7 +319,7 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos // we are moving on the old path but target moved out // so we have atleast part of poly-path ready - m_polyLength -= pathStartIndex; + _polyLength -= pathStartIndex; // try to adjust the suffix of the path instead of recalculating entire length // at given interval the target cannot get too far from its last location @@ -328,37 +328,37 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos // take ~80% of the original length // TODO : play with the values here - uint32 prefixPolyLength = uint32(m_polyLength*0.8f + 0.5f); - memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, prefixPolyLength*sizeof(dtPolyRef)); + uint32 prefixPolyLength = uint32(_polyLength * 0.8f + 0.5f); + memmove(_pathPolyRefs, _pathPolyRefs+pathStartIndex, prefixPolyLength * sizeof(dtPolyRef)); - dtPolyRef suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; + dtPolyRef suffixStartPoly = _pathPolyRefs[prefixPolyLength-1]; // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data float suffixEndPoint[VERTEX_SIZE]; - if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) + if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) { // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that // try to recover by using prev polyref --prefixPolyLength; - suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; - if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) + suffixStartPoly = _pathPolyRefs[prefixPolyLength-1]; + if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) { // suffixStartPoly is still invalid, error state BuildShortcut(); - m_type = PATHFIND_NOPATH; + _type = PATHFIND_NOPATH; return; } } // generate suffix uint32 suffixPolyLength = 0; - dtStatus dtResult = m_navMeshQuery->findPath( + dtStatus dtResult = _navMeshQuery->findPath( suffixStartPoly, // start polygon endPoly, // end polygon suffixEndPoint, // start position endPoint, // end position - &m_filter, // polygon search filter - m_pathPolyRefs + prefixPolyLength - 1, // [out] path + &_filter, // polygon search filter + _pathPolyRefs + prefixPolyLength - 1, // [out] path (int*)&suffixPolyLength, MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path @@ -367,13 +367,13 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos // this is probably an error state, but we'll leave it // and hopefully recover on the next Update // we still need to copy our preffix - sLog->outError(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); + sLog->outError(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow()); } - sLog->outDebug(LOG_FILTER_MAPS, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength); + sLog->outDebug(LOG_FILTER_MAPS, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n", _polyLength, prefixPolyLength, suffixPolyLength); // new path = prefix + suffix - overlap - m_polyLength = prefixPolyLength + suffixPolyLength - 1; + _polyLength = prefixPolyLength + suffixPolyLength - 1; } else { @@ -384,33 +384,33 @@ void PathGenerator::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos // just generate new path // free and invalidate old path data - clear(); + Clear(); - dtStatus dtResult = m_navMeshQuery->findPath( + dtStatus dtResult = _navMeshQuery->findPath( startPoly, // start polygon endPoly, // end polygon startPoint, // start position endPoint, // end position - &m_filter, // polygon search filter - m_pathPolyRefs, // [out] path - (int*)&m_polyLength, + &_filter, // polygon search filter + _pathPolyRefs, // [out] path + (int*)&_polyLength, MAX_PATH_LENGTH); // max number of polygons in output path - if (!m_polyLength || dtResult != DT_SUCCESS) + if (!_polyLength || dtResult != DT_SUCCESS) { // only happens if we passed bad data to findPath(), or navmesh is messed up - sLog->outError(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); + sLog->outError(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow()); BuildShortcut(); - m_type = PATHFIND_NOPATH; + _type = PATHFIND_NOPATH; return; } } // by now we know what type of path we can get - if (m_pathPolyRefs[m_polyLength - 1] == endPoly && !(m_type & PATHFIND_INCOMPLETE)) - m_type = PATHFIND_NORMAL; + if (_pathPolyRefs[_polyLength - 1] == endPoly && !(_type & PATHFIND_INCOMPLETE)) + _type = PATHFIND_NORMAL; else - m_type = PATHFIND_INCOMPLETE; + _type = PATHFIND_INCOMPLETE; // generate the point-path out of our up-to-date poly-path BuildPointPath(startPoint, endPoint); @@ -421,29 +421,29 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; uint32 pointCount = 0; dtStatus dtResult = DT_FAILURE; - if (m_useStraightPath) + if (_useStraightPath) { - dtResult = m_navMeshQuery->findStraightPath( + dtResult = _navMeshQuery->findStraightPath( startPoint, // start position endPoint, // end position - m_pathPolyRefs, // current path - m_polyLength, // lenth of current path + _pathPolyRefs, // current path + _polyLength, // lenth of current path pathPoints, // [out] path corner points NULL, // [out] flags NULL, // [out] shortened path (int*)&pointCount, - m_pointPathLimit); // maximum number of points/polygons to use + _pointPathLimit); // maximum number of points/polygons to use } else { - dtResult = findSmoothPath( + dtResult = FindSmoothPath( startPoint, // start position endPoint, // end position - m_pathPolyRefs, // current path - m_polyLength, // length of current path + _pathPolyRefs, // current path + _polyLength, // length of current path pathPoints, // [out] path corner points (int*)&pointCount, - m_pointPathLimit); // maximum number of points + _pointPathLimit); // maximum number of points } if (pointCount < 2 || dtResult != DT_SUCCESS) @@ -453,81 +453,80 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin // TODO : check the exact cases sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount); BuildShortcut(); - m_type = PATHFIND_NOPATH; + _type = PATHFIND_NOPATH; return; } - else if (pointCount == m_pointPathLimit) + else if (pointCount == _pointPathLimit) { - sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d\n", pointCount, m_pointPathLimit); + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d\n", pointCount, _pointPathLimit); BuildShortcut(); - m_type = PATHFIND_SHORT; + _type = PATHFIND_SHORT; return; } - m_pathPoints.resize(pointCount); + _pathPoints.resize(pointCount); for (uint32 i = 0; i < pointCount; ++i) - m_pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); + _pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); NormalizePath(); // first point is always our current location - we need the next one - setActualEndPosition(m_pathPoints[pointCount-1]); + SetActualEndPosition(_pathPoints[pointCount-1]); // force the given destination, if needed - if(m_forceDestination && - (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f))) + if (_forceDestination && + (!(_type & PATHFIND_NORMAL) || !InRange(GetEndPosition(), GetActualEndPosition(), 1.0f, 1.0f))) { // we may want to keep partial subpath - if(dist3DSqr(getActualEndPosition(), getEndPosition()) < - 0.3f * dist3DSqr(getStartPosition(), getEndPosition())) + if (Dist3DSqr(GetActualEndPosition(), GetEndPosition()) < 0.3f * Dist3DSqr(GetStartPosition(), GetEndPosition())) { - setActualEndPosition(getEndPosition()); - m_pathPoints[m_pathPoints.size()-1] = getEndPosition(); + SetActualEndPosition(GetEndPosition()); + _pathPoints[_pathPoints.size()-1] = GetEndPosition(); } else { - setActualEndPosition(getEndPosition()); + SetActualEndPosition(GetEndPosition()); BuildShortcut(); } - m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } - sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); + sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath path type %d size %d poly-size %d\n", _type, pointCount, _polyLength); } void PathGenerator::NormalizePath() { - for (uint32 i = 0; i < m_pathPoints.size(); ++i) - m_sourceUnit->UpdateAllowedPositionZ(m_pathPoints[i].x, m_pathPoints[i].y, m_pathPoints[i].z); + for (uint32 i = 0; i < _pathPoints.size(); ++i) + _sourceUnit->UpdateAllowedPositionZ(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z); } void PathGenerator::BuildShortcut() { sLog->outDebug(LOG_FILTER_MAPS, "++ BuildShortcut :: making shortcut\n"); - clear(); + Clear(); // make two point path, our curr pos is the start, and dest is the end - m_pathPoints.resize(2); + _pathPoints.resize(2); // set start and a default next position - m_pathPoints[0] = getStartPosition(); - m_pathPoints[1] = getActualEndPosition(); + _pathPoints[0] = GetStartPosition(); + _pathPoints[1] = GetActualEndPosition(); NormalizePath(); - m_type = PATHFIND_SHORTCUT; + _type = PATHFIND_SHORTCUT; } -void PathGenerator::createFilter() +void PathGenerator::CreateFilter() { uint16 includeFlags = 0; uint16 excludeFlags = 0; - if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) + if (_sourceUnit->GetTypeId() == TYPEID_UNIT) { - Creature* creature = (Creature*)m_sourceUnit; + Creature* creature = (Creature*)_sourceUnit; if (creature->canWalk()) includeFlags |= NAV_GROUND; // walk @@ -535,37 +534,37 @@ void PathGenerator::createFilter() if (creature->canSwim()) includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim } - else if (m_sourceUnit->GetTypeId() == TYPEID_PLAYER) + else if (_sourceUnit->GetTypeId() == TYPEID_PLAYER) { // perfect support not possible, just stay 'safe' includeFlags |= (NAV_GROUND | NAV_WATER); } - m_filter.setIncludeFlags(includeFlags); - m_filter.setExcludeFlags(excludeFlags); + _filter.setIncludeFlags(includeFlags); + _filter.setExcludeFlags(excludeFlags); - updateFilter(); + UpdateFilter(); } -void PathGenerator::updateFilter() +void PathGenerator::UpdateFilter() { // allow creatures to cheat and use different movement types if they are moved // forcefully into terrain they can't normally move in - if (m_sourceUnit->IsInWater() || m_sourceUnit->IsUnderWater()) + if (_sourceUnit->IsInWater() || _sourceUnit->IsUnderWater()) { - uint16 includedFlags = m_filter.getIncludeFlags(); - includedFlags |= getNavTerrain(m_sourceUnit->GetPositionX(), - m_sourceUnit->GetPositionY(), - m_sourceUnit->GetPositionZ()); + uint16 includedFlags = _filter.getIncludeFlags(); + includedFlags |= GetNavTerrain(_sourceUnit->GetPositionX(), + _sourceUnit->GetPositionY(), + _sourceUnit->GetPositionZ()); - m_filter.setIncludeFlags(includedFlags); + _filter.setIncludeFlags(includedFlags); } } -NavTerrain PathGenerator::getNavTerrain(float x, float y, float z) +NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) { LiquidData data; - m_sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); + _sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); switch (data.type_flags) { @@ -581,16 +580,16 @@ NavTerrain PathGenerator::getNavTerrain(float x, float y, float z) } } -bool PathGenerator::HaveTile(const Vector3 &p) const +bool PathGenerator::HaveTile(Vector3 const& p) const { int tx, ty; float point[VERTEX_SIZE] = {p.y, p.z, p.x}; - m_navMesh->calcTileLoc(point, &tx, &ty); - return (m_navMesh->getTileAt(tx, ty) != NULL); + _navMesh->calcTileLoc(point, &tx, &ty); + return (_navMesh->getTileAt(tx, ty) != NULL); } -uint32 PathGenerator::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited) +uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited) { int32 furthestPath = -1; int32 furthestVisited = -1; @@ -635,8 +634,8 @@ uint32 PathGenerator::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPat return req+size; } -bool PathGenerator::getSteerTarget(const float* startPos, const float* endPos, - float minTargetDist, const dtPolyRef* path, uint32 pathSize, +bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos, + float minTargetDist, dtPolyRef const* path, uint32 pathSize, float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef) { // Find steer target. @@ -645,7 +644,7 @@ bool PathGenerator::getSteerTarget(const float* startPos, const float* endPos, unsigned char steerPathFlags[MAX_STEER_POINTS]; dtPolyRef steerPathPolys[MAX_STEER_POINTS]; uint32 nsteerPath = 0; - dtStatus dtResult = m_navMeshQuery->findStraightPath(startPos, endPos, path, pathSize, + dtStatus dtResult = _navMeshQuery->findStraightPath(startPos, endPos, path, pathSize, steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS); if (!nsteerPath || DT_SUCCESS != dtResult) return false; @@ -656,7 +655,7 @@ bool PathGenerator::getSteerTarget(const float* startPos, const float* endPos, { // Stop at Off-Mesh link or when point is further than slop away. if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || - !inRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f)) + !InRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f)) break; ns++; } @@ -672,8 +671,8 @@ bool PathGenerator::getSteerTarget(const float* startPos, const float* endPos, return true; } -dtStatus PathGenerator::findSmoothPath(const float* startPos, const float* endPos, - const dtPolyRef* polyPath, uint32 polyPathSize, +dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPos, + dtPolyRef const* polyPath, uint32 polyPathSize, float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize) { *smoothPathSize = 0; @@ -684,10 +683,10 @@ dtStatus PathGenerator::findSmoothPath(const float* startPos, const float* endPo uint32 npolys = polyPathSize; float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE]; - if (DT_SUCCESS != m_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos)) + if (DT_SUCCESS != _navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos)) return DT_FAILURE; - if (DT_SUCCESS != m_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos)) + if (DT_SUCCESS != _navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos)) return DT_FAILURE; dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); @@ -702,7 +701,7 @@ dtStatus PathGenerator::findSmoothPath(const float* startPos, const float* endPo unsigned char steerPosFlag; dtPolyRef steerPosRef = INVALID_POLYREF; - if (!getSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef)) + if (!GetSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef)) break; bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END); @@ -727,15 +726,15 @@ dtStatus PathGenerator::findSmoothPath(const float* startPos, const float* endPo dtPolyRef visited[MAX_VISIT_POLY]; uint32 nvisited = 0; - m_navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &m_filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY); - npolys = fixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited); + _navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &_filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY); + npolys = FixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited); - m_navMeshQuery->getPolyHeight(polys[0], result, &result[1]); + _navMeshQuery->getPolyHeight(polys[0], result, &result[1]); result[1] += 0.5f; dtVcopy(iterPos, result); // Handle end of path and off-mesh links when close enough. - if (endOfPath && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) + if (endOfPath && InRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) { // Reached end of path. dtVcopy(iterPos, targetPos); @@ -746,7 +745,7 @@ dtStatus PathGenerator::findSmoothPath(const float* startPos, const float* endPo } break; } - else if (offMeshConnection && inRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) + else if (offMeshConnection && InRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) { // Advance the path up to and over the off-mesh connection. dtPolyRef prevRef = INVALID_POLYREF; @@ -766,7 +765,7 @@ dtStatus PathGenerator::findSmoothPath(const float* startPos, const float* endPo // Handle the connection. float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE]; - if (DT_SUCCESS == m_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos)) + if (DT_SUCCESS == _navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos)) { if (nsmoothPath < maxSmoothPathSize) { @@ -775,7 +774,7 @@ dtStatus PathGenerator::findSmoothPath(const float* startPos, const float* endPo } // Move position at the other side of the off-mesh link. dtVcopy(iterPos, endPos); - m_navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]); + _navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]); iterPos[1] += 0.5f; } } @@ -794,21 +793,21 @@ dtStatus PathGenerator::findSmoothPath(const float* startPos, const float* endPo return nsmoothPath < MAX_POINT_PATH_LENGTH ? DT_SUCCESS : DT_FAILURE; } -bool PathGenerator::inRangeYZX(const float* v1, const float* v2, float r, float h) const +bool PathGenerator::InRangeYZX(const float* v1, const float* v2, float r, float h) const { const float dx = v2[0] - v1[0]; const float dy = v2[1] - v1[1]; // elevation const float dz = v2[2] - v1[2]; - return (dx*dx + dz*dz) < r*r && fabsf(dy) < h; + return (dx * dx + dz * dz) < r * r && fabsf(dy) < h; } -bool PathGenerator::inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const +bool PathGenerator::InRange(Vector3 const& p1, Vector3 const& p2, float r, float h) const { - Vector3 d = p1-p2; - return (d.x*d.x + d.y*d.y) < r*r && fabsf(d.z) < h; + Vector3 d = p1 - p2; + return (d.x * d.x + d.y * d.y) < r * r && fabsf(d.z) < h; } -float PathGenerator::dist3DSqr(const Vector3 &p1, const Vector3 &p2) const +float PathGenerator::Dist3DSqr(Vector3 const& p1, Vector3 const& p2) const { - return (p1-p2).squaredLength(); + return (p1 - p2).squaredLength(); } diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index ac163f43be5..a20f900b584 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -16,8 +16,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _PATH_INFO_H -#define _PATH_INFO_H +#ifndef _PATH_GENERATOR_H +#define _PATH_GENERATOR_H #include "SharedDefines.h" #include "DetourNavMesh.h" @@ -63,75 +63,72 @@ class PathGenerator bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false); // option setters - use optional - void SetUseStraightPath(bool useStraightPath) { m_useStraightPath = useStraightPath; }; - void setPathLengthLimit(float distance) { m_pointPathLimit = std::min(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }; + void SetUseStraightPath(bool useStraightPath) { _useStraightPath = useStraightPath; }; + void SetPathLengthLimit(float distance) { _pointPathLimit = std::min(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); }; // result getters - Vector3 getStartPosition() const { return m_startPosition; } - Vector3 getEndPosition() const { return m_endPosition; } - Vector3 getActualEndPosition() const { return m_actualEndPosition; } + Vector3 const& GetStartPosition() const { return _startPosition; } + Vector3 const& GetEndPosition() const { return _endPosition; } + Vector3 const& GetActualEndPosition() const { return _actualEndPosition; } - PointsArray& getPath() { return m_pathPoints; } - PathType getPathType() const { return m_type; } + PointsArray& GetPath() { return _pathPoints; } + PathType GetPathType() const { return _type; } private: - dtPolyRef m_pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references - uint32 m_polyLength; // number of polygons in the path + dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references + uint32 _polyLength; // number of polygons in the path - PointsArray m_pathPoints; // our actual (x,y,z) path to the target - PathType m_type; // tells what kind of path this is + PointsArray _pathPoints; // our actual (x,y,z) path to the target + PathType _type; // tells what kind of path this is - bool m_useStraightPath; // type of path will be generated - bool m_forceDestination; // when set, we will always arrive at given point - uint32 m_pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH) + bool _useStraightPath; // type of path will be generated + bool _forceDestination; // when set, we will always arrive at given point + uint32 _pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH) - Vector3 m_startPosition; // {x, y, z} of current location - Vector3 m_endPosition; // {x, y, z} of the destination - Vector3 m_actualEndPosition;// {x, y, z} of the closest possible point to given destination + Vector3 _startPosition; // {x, y, z} of current location + Vector3 _endPosition; // {x, y, z} of the destination + Vector3 _actualEndPosition;// {x, y, z} of the closest possible point to given destination - const Unit* const m_sourceUnit; // the unit that is moving - const dtNavMesh* m_navMesh; // the nav mesh - const dtNavMeshQuery* m_navMeshQuery; // the nav mesh query used to find the path + Unit const* const _sourceUnit; // the unit that is moving + dtNavMesh const* _navMesh; // the nav mesh + dtNavMeshQuery const* _navMeshQuery; // the nav mesh query used to find the path - dtQueryFilter m_filter; // use single filter for all movements, update it when needed + dtQueryFilter _filter; // use single filter for all movements, update it when needed - void setStartPosition(Vector3 point) { m_startPosition = point; } - void setEndPosition(Vector3 point) { m_actualEndPosition = point; m_endPosition = point; } - void setActualEndPosition(Vector3 point) { m_actualEndPosition = point; } - + void SetStartPosition(Vector3 Point) { _startPosition = Point; } + void SetEndPosition(Vector3 Point) { _actualEndPosition = Point; _endPosition = Point; } + void SetActualEndPosition(Vector3 Point) { _actualEndPosition = Point; } void NormalizePath(); - void clear() + void Clear() { - m_polyLength = 0; - m_pathPoints.clear(); + _polyLength = 0; + _pathPoints.clear(); } - bool inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const; - float dist3DSqr(const Vector3 &p1, const Vector3 &p2) const; - bool inRangeYZX(const float* v1, const float* v2, float r, float h) const; + bool InRange(Vector3 const& p1, Vector3 const& p2, float r, float h) const; + float Dist3DSqr(Vector3 const& p1, Vector3 const& p2) const; + bool InRangeYZX(float const* v1, float const* v2, float r, float h) const; - dtPolyRef getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance = NULL) const; - dtPolyRef getPolyByLocation(const float* point, float *distance) const; - bool HaveTile(const Vector3 &p) const; + dtPolyRef GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* Point, float* Distance = NULL) const; + dtPolyRef GetPolyByLocation(float const* Point, float* Distance) const; + bool HaveTile(Vector3 const& p) const; - void BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos); - void BuildPointPath(const float *startPoint, const float *endPoint); + void BuildPolyPath(Vector3 const& startPos, Vector3 const& endPos); + void BuildPointPath(float const* startPoint, float const* endPoint); void BuildShortcut(); - NavTerrain getNavTerrain(float x, float y, float z); - void createFilter(); - void updateFilter(); + NavTerrain GetNavTerrain(float x, float y, float z); + void CreateFilter(); + void UpdateFilter(); // smooth path aux functions - uint32 fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, - const dtPolyRef* visited, uint32 nvisited); - bool getSteerTarget(const float* startPos, const float* endPos, float minTargetDist, - const dtPolyRef* path, uint32 pathSize, float* steerPos, + uint32 FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited); + bool GetSteerTarget(float const* startPos, float const* endPos, float minTargetDist, dtPolyRef const* path, uint32 pathSize, float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef); - dtStatus findSmoothPath(const float* startPos, const float* endPos, - const dtPolyRef* polyPath, uint32 polyPathSize, + dtStatus FindSmoothPath(float const* startPos, float const* endPos, + dtPolyRef const* polyPath, uint32 polyPathSize, float* smoothPath, int* smoothPathSize, uint32 smoothPathMaxSize); }; diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index 8167ff36de2..2796e208e34 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -154,7 +154,7 @@ namespace Movement { PathGenerator path(unit); path.CalculatePath(dest.x, dest.y, dest.z, forceDestination); - MovebyPath(path.getPath()); + MovebyPath(path.GetPath()); } else { diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 081056c1c79..0cbae416271 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5157,10 +5157,10 @@ SpellCastResult Spell::CheckCast(bool strict) target->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); target->GetFirstCollisionPosition(pos, CONTACT_DISTANCE, target->GetRelativeAngle(m_caster)); - m_preGeneratedPath.setPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f); + m_preGeneratedPath.SetPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f); m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize()); - if (m_preGeneratedPath.getPathType() & PATHFIND_SHORT) + if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; break; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 1aa2ca0176b..d3b21395725 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -5139,7 +5139,7 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/) if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET) { - if (m_preGeneratedPath.getPathType() & PATHFIND_NOPATH) + if (m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH) { Position pos; unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); -- cgit v1.2.3 From c9eb42f2465e607c5e13425cc913b792a15e937e Mon Sep 17 00:00:00 2001 From: Venugh Date: Thu, 6 Sep 2012 00:36:24 +0200 Subject: Core/Commands: Implemented mmaps commands. --- sql/updates/world/2012_09_06_00_world_command.sql | 9 + src/server/game/Scripting/ScriptLoader.cpp | 2 + src/server/scripts/Commands/CMakeLists.txt | 1 + src/server/scripts/Commands/cs_mmaps.cpp | 293 ++++++++++++++++++++++ 4 files changed, 305 insertions(+) create mode 100644 sql/updates/world/2012_09_06_00_world_command.sql create mode 100644 src/server/scripts/Commands/cs_mmaps.cpp (limited to 'src') diff --git a/sql/updates/world/2012_09_06_00_world_command.sql b/sql/updates/world/2012_09_06_00_world_command.sql new file mode 100644 index 00000000000..e60c1644e05 --- /dev/null +++ b/sql/updates/world/2012_09_06_00_world_command.sql @@ -0,0 +1,9 @@ +DELETE FROM `command` WHERE `name`='mmap' OR `name` LIKE 'mmap%'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('mmap', 3, 'Syntax: Syntax: .mmaps $subcommand Type .mmaps to see the list of possible subcommands or .help mmaps $subcommand to see info on subcommands'), +('mmap path', 3, 'Syntax: .mmap path to calculate and show a path to current select unit'), +('mmap loc', 3, 'Syntax: .mmap loc to print on which tile one is'), +('mmap loadedtiles', 3, 'Syntax: .mmap loadedtiles to show which tiles are currently loaded'), +('mmap stats', 3, 'Syntax: .mmap stats to show information about current state of mmaps'), +('mmap testarea', 3, 'Syntax: .mmap testarea to calculate paths for all nearby npcs to player'); + diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index fc56106ab6f..6442a35f0c3 100755 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -75,6 +75,7 @@ void AddSC_tele_commandscript(); void AddSC_ticket_commandscript(); void AddSC_titles_commandscript(); void AddSC_wp_commandscript(); +void AddSC_mmaps_commandscript(); #ifdef SCRIPTS //world @@ -693,6 +694,7 @@ void AddCommandScripts() AddSC_ticket_commandscript(); AddSC_titles_commandscript(); AddSC_wp_commandscript(); + AddSC_mmaps_commandscript(); } void AddWorldScripts() diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt index 177b3a479f5..e799cf20633 100644 --- a/src/server/scripts/Commands/CMakeLists.txt +++ b/src/server/scripts/Commands/CMakeLists.txt @@ -41,6 +41,7 @@ set(scripts_STAT_SRCS Commands/cs_server.cpp Commands/cs_titles.cpp Commands/cs_wp.cpp + Commands/cs_mmaps.cpp # Commands/cs_pdump.cpp # Commands/cs_channel.cpp # Commands/cs_pet.cpp diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp new file mode 100644 index 00000000000..c1fc4d1a5e9 --- /dev/null +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2008-2012 TrinityCore + * + * 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 2 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 . + */ + +/** +* @file cs_mmaps.cpp +* @brief .mmap related commands +* +* This file contains the CommandScripts for all +* mmap sub-commands +*/ + +#include "ScriptMgr.h" +#include "Chat.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "PointMovementGenerator.h" +#include "PathGenerator.h" +#include "MMapFactory.h" +#include "Map.h" +#include "TargetedMovementGenerator.h" + +class mmaps_commandscript : public CommandScript +{ +public: + mmaps_commandscript() : CommandScript("mmaps_commandscript") { } + + ChatCommand* GetCommands() const + { + static ChatCommand mmapCommandTable[] = + { + { "path", SEC_ADMINISTRATOR, false, &HandleMmapPathCommand, "", NULL }, + { "loc", SEC_ADMINISTRATOR, false, &HandleMmapLocCommand, "", NULL }, + { "loadedtiles", SEC_ADMINISTRATOR, false, &HandleMmapLoadedTilesCommand, "", NULL }, + { "stats", SEC_ADMINISTRATOR, false, &HandleMmapStatsCommand, "", NULL }, + { "testarea", SEC_ADMINISTRATOR, false, &HandleMmapTestArea, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand commandTable[] = + { + { "mmap", SEC_ADMINISTRATOR, true, NULL, "", mmapCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + + static bool HandleMmapPathCommand(ChatHandler* handler, char const* args) + { + if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + handler->PSendSysMessage("mmap path:"); + + // units + Player* player = handler->GetSession()->GetPlayer(); + Unit* target = handler->getSelectedUnit(); + if (!player || !target) + { + handler->PSendSysMessage("Invalid target/source selection."); + return true; + } + + char* para = strtok((char*)args, " "); + + bool useStraightPath = false; + if (para && strcmp(para, "true") == 0) + useStraightPath = true; + + // unit locations + float x, y, z; + player->GetPosition(x, y, z); + + // path + PathGenerator path(target); + path.SetUseStraightPath(useStraightPath); + path.CalculatePath(x, y, z); + + PointsArray pointPath = path.GetPath(); + handler->PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName()); + handler->PSendSysMessage("Building %s", useStraightPath ? "StraightPath" : "SmoothPath"); + handler->PSendSysMessage("length %i type %u", pointPath.size(), path.GetPathType()); + + Vector3 start = path.GetStartPosition(); + Vector3 end = path.GetEndPosition(); + Vector3 actualEnd = path.GetActualEndPosition(); + + handler->PSendSysMessage("start (%.3f, %.3f, %.3f)", start.x, start.y, start.z); + handler->PSendSysMessage("end (%.3f, %.3f, %.3f)", end.x, end.y, end.z); + handler->PSendSysMessage("actual end (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); + + if (!player->isGameMaster()) + handler->PSendSysMessage("Enable GM mode to see the path points."); + + // this entry visible only to GM's with "gm on" + static const uint32 WAYPOINT_NPC_ENTRY = 1; + for (uint32 i = 0; i < pointPath.size(); ++i) + player->SummonCreature(WAYPOINT_NPC_ENTRY, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000); + + return true; + } + + static bool HandleMmapLocCommand(ChatHandler* handler, const char* args) + { + handler->PSendSysMessage("mmap tileloc:"); + + // grid tile location + Player* player = handler->GetSession()->GetPlayer(); + + int32 gx = 32 - player->GetPositionX() / SIZE_OF_GRIDS; + int32 gy = 32 - player->GetPositionY() / SIZE_OF_GRIDS; + + handler->PSendSysMessage("%03u%02i%02i.mmtile", player->GetMapId(), gy, gx); + handler->PSendSysMessage("gridloc [%i,%i]", gx, gy); + + // calculate navmesh tile location + dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(handler->GetSession()->GetPlayer()->GetMapId(), player->GetInstanceId()); + if (!navmesh || !navmeshquery) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + float const* min = navmesh->getParams()->orig; + float x, y, z; + player->GetPosition(x, y, z); + float location[VERTEX_SIZE] = {y, z, x}; + float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; + + int32 tilex = int32((y - min[0]) / SIZE_OF_GRIDS); + int32 tiley = int32((x - min[2]) / SIZE_OF_GRIDS); + + handler->PSendSysMessage("Calc [%02i,%02i]", tilex, tiley); + + // navmesh poly -> navmesh tile location + dtQueryFilter filter = dtQueryFilter(); + dtPolyRef polyRef = INVALID_POLYREF; + navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL); + + if (polyRef == INVALID_POLYREF) + handler->PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)"); + else + { + dtMeshTile const* tile; + dtPoly const* poly; + navmesh->getTileAndPolyByRef(polyRef, &tile, &poly); + if (tile) + handler->PSendSysMessage("Dt [%02i,%02i]", tile->header->x, tile->header->y); + else + handler->PSendSysMessage("Dt [??,??] (no tile loaded)"); + } + + return true; + } + + static bool HandleMmapLoadedTilesCommand(ChatHandler* handler, const char* args) + { + uint32 mapid = handler->GetSession()->GetPlayer()->GetMapId(); + dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, handler->GetSession()->GetPlayer()->GetInstanceId()); + if (!navmesh || !navmeshquery) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + handler->PSendSysMessage("mmap loadedtiles:"); + + for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) + { + dtMeshTile const* tile = navmesh->getTile(i); + if (!tile || !tile->header) + continue; + + handler->PSendSysMessage("[%02i,%02i]", tile->header->x, tile->header->y); + } + + return true; + } + + static bool HandleMmapStatsCommand(ChatHandler* handler, const char* args) + { + uint32 mapId = handler->GetSession()->GetPlayer()->GetMapId(); + handler->PSendSysMessage("mmap stats:"); + handler->PSendSysMessage(" global mmap pathfinding is %sabled", MMAP::MMapFactory::IsPathfindingEnabled(mapId) ? "en" : "dis"); + + MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager(); + handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); + + dtNavMesh const* navmesh = manager->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); + if (!navmesh) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + uint32 tileCount = 0; + uint32 nodeCount = 0; + uint32 polyCount = 0; + uint32 vertCount = 0; + uint32 triCount = 0; + uint32 triVertCount = 0; + uint32 dataSize = 0; + for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) + { + dtMeshTile const* tile = navmesh->getTile(i); + if (!tile || !tile->header) + continue; + + tileCount++; + nodeCount += tile->header->bvNodeCount; + polyCount += tile->header->polyCount; + vertCount += tile->header->vertCount; + triCount += tile->header->detailTriCount; + triVertCount += tile->header->detailVertCount; + dataSize += tile->dataSize; + } + + handler->PSendSysMessage("Navmesh stats:"); + handler->PSendSysMessage(" %u tiles loaded", tileCount); + handler->PSendSysMessage(" %u BVTree nodes", nodeCount); + handler->PSendSysMessage(" %u polygons (%u vertices)", polyCount, vertCount); + handler->PSendSysMessage(" %u triangles (%u vertices)", triCount, triVertCount); + handler->PSendSysMessage(" %.2f MB of data (not including pointers)", ((float)dataSize / sizeof(unsigned char)) / 1048576); + + return true; + } + + static bool HandleMmapTestArea(ChatHandler* handler, const char* args) + { + float radius = 40.0f; + WorldObject* object = handler->GetSession()->GetPlayer(); + + CellCoord pair(Trinity::ComputeCellCoord(object->GetPositionX(), object->GetPositionY()) ); + Cell cell(pair); + cell.SetNoCreate(); + + std::list creatureList; + + Trinity::AnyUnitInObjectRangeCheck go_check(object, radius); + Trinity::CreatureListSearcher go_search(object, creatureList, go_check); + TypeContainerVisitor, GridTypeMapContainer> go_visit(go_search); + + // Get Creatures + cell.Visit(pair, go_visit, *(object->GetMap()), *object, radius); + + if (!creatureList.empty()) + { + handler->PSendSysMessage("Found %i Creatures.", creatureList.size()); + + uint32 paths = 0; + uint32 uStartTime = getMSTime(); + + float gx, gy, gz; + object->GetPosition(gx, gy, gz); + for (std::list::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + { + PathGenerator path(*itr); + path.CalculatePath(gx, gy, gz); + ++paths; + } + + uint32 uPathLoadTime = getMSTimeDiff(uStartTime, getMSTime()); + handler->PSendSysMessage("Generated %i paths in %i ms", paths, uPathLoadTime); + } + else + handler->PSendSysMessage("No creatures in %f yard range.", radius); + + return true; + } +}; + +void AddSC_mmaps_commandscript() +{ + new mmaps_commandscript(); +} \ No newline at end of file -- cgit v1.2.3 From 5617921a55973018e1c5fd9c3307be875cf321b6 Mon Sep 17 00:00:00 2001 From: Aokromes Date: Thu, 6 Sep 2012 05:27:14 +0300 Subject: compile fix --- src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 0ca688fb0df..064e5bfa1a2 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -52,7 +52,7 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, void unitSpeedChanged() { i_recalculateTravel = true; } void UpdateFinalDistance(float fDistance); - bool IsReachable() const { return (i_path) ? (i_path->getPathType() & PATHFIND_NORMAL) : true; } + bool IsReachable() const { return (i_path) ? (i_path->GetPathType() & PATHFIND_NORMAL) : true; } protected: void _setTargetLocation(T*); -- cgit v1.2.3 From a2d533752c447a2bf4ef7b784e8abdbe3f6d6904 Mon Sep 17 00:00:00 2001 From: kaelima Date: Fri, 7 Sep 2012 04:21:11 +0200 Subject: Core/MMaps: Add several safety checks to confirm a valid path generation. - Address some issues in TargetMovementGenerator. Thanks Chevron --- src/server/collision/Management/MMapManager.cpp | 2 +- src/server/game/Entities/Object/Object.cpp | 2 +- .../ConfusedMovementGenerator.cpp | 4 +-- .../FleeingMovementGenerator.cpp | 4 +-- .../TargetedMovementGenerator.cpp | 41 +++++++++++----------- src/server/game/Movement/PathGenerator.cpp | 8 +++-- src/server/game/Movement/Spline/MoveSplineInit.cpp | 20 ++++++----- src/server/game/Spells/Spell.cpp | 5 +-- 8 files changed, 46 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp index 8e6e2a3b6b4..c7dea358d92 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/server/collision/Management/MMapManager.cpp @@ -295,4 +295,4 @@ namespace MMAP return mmap->navMeshQueries[instanceId]; } -} \ No newline at end of file +} diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index fe5d32b9b95..2205efa8724 100755 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2780,7 +2780,7 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle) desty = pos.m_positionY + dist * sin(angle); // Prevent invalid coordinates here, position is unchanged - if (!Trinity::IsValidMapCoord(destx, desty)) + if (!Trinity::IsValidMapCoord(destx, desty, pos.m_positionZ)) { sLog->outFatal(LOG_FILTER_GENERAL, "WorldObject::MovePosition invalid coordinates X: %f and Y: %f were passed!", destx, desty); return; diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index 32c6ec3858d..4c269a1024a 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -78,8 +78,8 @@ bool ConfusedMovementGenerator::Update(T* unit, const uint32& diff) PathGenerator path(unit); path.SetPathLengthLimit(30.0f); - path.CalculatePath(x, y, z); - if (path.GetPathType() & PATHFIND_NOPATH) + bool result = path.CalculatePath(x, y, z); + if (!result || path.GetPathType() & PATHFIND_NOPATH) { i_nextMoveTime.Reset(urand(800, 1000)); return true; diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 8f4d78b34b1..29466ab9670 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -45,8 +45,8 @@ void FleeingMovementGenerator::_setTargetLocation(T* owner) PathGenerator path(owner); path.SetPathLengthLimit(30.0f); - path.CalculatePath(x, y, z); - if (path.GetPathType() & PATHFIND_NOPATH) + bool result = path.CalculatePath(x, y, z); + if (!result || path.GetPathType() & PATHFIND_NOPATH) { i_nextCheckTime.Reset(urand(1000, 1500)); return; diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 4a8d15b8079..145251ec4aa 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -35,30 +35,28 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner) if (owner->HasUnitState(UNIT_STATE_NOT_MOVE)) return; + if (owner->GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor(owner->ToCreature())) + return; + float x, y, z; - //! Following block of code deleted by MrSmite in issue 4891 - //! Code kept for learning and diagnostical purposes -// -// if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset)) -// { -// if (!owner.movespline->Finalized()) -// return; -// -// owner.GetPosition(x, y, z); -// } -// else + if (!i_offset) { - if (i_target->IsWithinMeleeRange(owner)) - return; + float dist = 0.0f; + + if (owner->getVictim() && owner->getVictim()->GetGUID() == i_target->GetGUID()) + dist = owner->GetFloatValue(UNIT_FIELD_COMBATREACH) + i_target->GetFloatValue(UNIT_FIELD_COMBATREACH) - i_target->GetObjectSize() - owner->GetObjectSize() - 1.0f; + + if (dist < 0.5f) + dist = 0.5f; - // to nearest random contact position - i_target->GetRandomContactPoint(owner, x, y, z, 0, MELEE_RANGE - 0.5f); + if (owner->IsWithinLOSInMap(owner->getVictim())) + i_target->GetContactPoint(owner, x, y, z, dist); + else + i_target->GetPosition(x, y, z); } else { - if (i_target->IsWithinDistInMap(owner, i_offset + 1.0f)) - return; // to at i_offset distance from target and i_angle from target facing i_target->GetClosePoint(x, y, z, owner->GetObjectSize(), i_offset, i_angle); } @@ -69,8 +67,9 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner) // allow pets following their master to cheat while generating paths bool forceDest = (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->isPet() && owner->HasUnitState(UNIT_STATE_FOLLOW)); - i_path->CalculatePath(x, y, z, forceDest); - if (i_path->GetPathType() & PATHFIND_NOPATH) + + bool result = i_path->CalculatePath(x, y, z, forceDest); + if (!result || i_path->GetPathType() & PATHFIND_NOPATH) return; D::_addUnitStateMove(owner); @@ -117,7 +116,7 @@ bool TargetedMovementGeneratorMedium::Update(T* owner, const uint32& time_d return false; if (!owner || !owner->isAlive()) - return true; + return false; if (owner->HasUnitState(UNIT_STATE_NOT_MOVE)) { @@ -154,7 +153,7 @@ bool TargetedMovementGeneratorMedium::Update(T* owner, const uint32& time_d else targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist); - if (targetMoved) + if (targetMoved || !owner->IsWithinLOSInMap(owner->getVictim())) _setTargetLocation(owner); } diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 165cc282e3a..68dd8f4057d 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -58,8 +58,12 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z)) return false; + float newDestZ = _sourceUnit->GetBaseMap()->GetHeight(_sourceUnit->GetPhaseMask(), x, y, z, true, MAX_FALL_DISTANCE); + if (newDestZ >= INVALID_HEIGHT) + return false; + Vector3 oldDest = GetEndPosition(); - Vector3 dest(destX, destY, destZ); + Vector3 dest(destX, destY, newDestZ); SetEndPosition(dest); Vector3 start(x, y, z); @@ -124,7 +128,7 @@ dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 minDist3d = dtVdistSqr(point, closestPoint); } - if(minDist2d < 1.0f) // shortcut out - close enough for us + if (minDist2d < 1.0f) // shortcut out - close enough for us break; } diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index 2796e208e34..68201fcf275 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -153,16 +153,18 @@ namespace Movement if (generatePath) { PathGenerator path(unit); - path.CalculatePath(dest.x, dest.y, dest.z, forceDestination); - MovebyPath(path.GetPath()); - } - else - { - args.path_Idx_offset = 0; - args.path.resize(2); - TransportPathTransform transform(unit, args.TransformForTransport); - args.path[1] = transform(dest); + bool result = path.CalculatePath(dest.x, dest.y, dest.z, forceDestination); + if (result && path.GetPathType() & ~PATHFIND_NOPATH) + { + MovebyPath(path.GetPath()); + return; + } } + + args.path_Idx_offset = 0; + args.path.resize(2); + TransportPathTransform transform(unit, args.TransformForTransport); + args.path[1] = transform(dest); } Vector3 TransportPathTransform::operator()(Vector3 input) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index d9a3e6a4b3c..a701b9d143e 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5162,10 +5162,11 @@ SpellCastResult Spell::CheckCast(bool strict) target->GetFirstCollisionPosition(pos, CONTACT_DISTANCE, target->GetRelativeAngle(m_caster)); m_preGeneratedPath.SetPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f); - m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize()); - + bool result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize()); if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; + else if (!result) + return SPELL_FAILED_NOPATH; break; } -- cgit v1.2.3 From 2e80503283b8cb15f95dda6bd6a6da973e0b8501 Mon Sep 17 00:00:00 2001 From: kaelima Date: Fri, 7 Sep 2012 12:54:38 +0200 Subject: Typo --- src/server/game/Movement/PathGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 68dd8f4057d..6f505de25cd 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -59,7 +59,7 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo return false; float newDestZ = _sourceUnit->GetBaseMap()->GetHeight(_sourceUnit->GetPhaseMask(), x, y, z, true, MAX_FALL_DISTANCE); - if (newDestZ >= INVALID_HEIGHT) + if (newDestZ <= INVALID_HEIGHT) return false; Vector3 oldDest = GetEndPosition(); -- cgit v1.2.3 From 8966347a416b9e2fba43bc3ff7043d946cfe10c4 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 9 Sep 2012 15:14:02 -0500 Subject: Core/MMaps: Added a little workaround to prevent the crash. ref issue #7631 --- src/server/game/Movement/PathGenerator.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 6f505de25cd..9635399e71f 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -584,12 +584,19 @@ NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) } } -bool PathGenerator::HaveTile(Vector3 const& p) const +bool PathGenerator::HaveTile(const Vector3& p) const { - int tx, ty; + int tx = -1, ty = -1; float point[VERTEX_SIZE] = {p.y, p.z, p.x}; _navMesh->calcTileLoc(point, &tx, &ty); + + /// Workaround + /// For some reason, often the tx and ty variables wont get a valid value + /// Use this check to prevent getting negative tile coords and crashing on getTileAt + if (tx < 0 || ty < 0) + return false; + return (_navMesh->getTileAt(tx, ty) != NULL); } -- cgit v1.2.3 From f237a57f51c0473bda90bae7a06bd5b9c187754b Mon Sep 17 00:00:00 2001 From: kaelima Date: Mon, 10 Sep 2012 13:24:01 +0200 Subject: Fix compile. Closes #7718 --- src/server/game/Movement/Spline/MoveSplineInit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index 4f6865405ae..edef9cfed43 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -174,7 +174,7 @@ namespace Movement if (_transformForTransport) { float unused = 0.0f; - if (TransportBase* transport = _owner.GetDirectTransport()) + if (TransportBase* transport = _owner->GetDirectTransport()) transport->CalculatePassengerOffset(input.x, input.y, input.z, unused); } -- cgit v1.2.3 From 33994351fff5f7ebad7ae75a5dbadd70c6f26413 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 25 Sep 2012 12:22:02 -0500 Subject: Core/Configs: Removed vmap.petLOS option in the worldserver config, it was intended to somewhat fix the lack of pathfinding, its not needed anymore. Closes #7817 --- src/server/game/Handlers/PetHandler.cpp | 7 ------- src/server/game/World/World.cpp | 4 +--- src/server/game/World/World.h | 1 - src/server/worldserver/worldserver.conf.dist | 8 -------- 4 files changed, 1 insertion(+), 19 deletions(-) (limited to 'src') diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 3501b3bc068..f8cb0344a96 100755 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -194,13 +194,6 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid if (!owner->IsValidAttackTarget(TargetUnit)) return; - // Not let attack through obstructions - if (sWorld->getBoolConfig(CONFIG_PET_LOS)) - { - if (!pet->IsWithinLOSInMap(TargetUnit)) - return; - } - pet->ClearUnitState(UNIT_STATE_FOLLOW); // This is true if pet has no target or has target but targets differs. if (pet->getVictim() != TargetUnit || (pet->getVictim() == TargetUnit && !pet->GetCharmInfo()->IsCommandAttack())) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 72b81b671b0..e9d727e072a 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1133,7 +1133,6 @@ void World::LoadConfigSettings(bool reload) bool enableIndoor = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", true); bool enableLOS = ConfigMgr::GetBoolDefault("vmap.enableLOS", true); bool enableHeight = ConfigMgr::GetBoolDefault("vmap.enableHeight", true); - bool enablePetLOS = ConfigMgr::GetBoolDefault("vmap.petLOS", true); std::string ignoreSpellIds = ConfigMgr::GetStringDefault("vmap.ignoreSpellIds", ""); if (!enableHeight) @@ -1142,11 +1141,10 @@ void World::LoadConfigSettings(bool reload) VMAP::VMapFactory::createOrGetVMapManager()->setEnableLineOfSightCalc(enableLOS); VMAP::VMapFactory::createOrGetVMapManager()->setEnableHeightCalc(enableHeight); VMAP::VMapFactory::preventSpellsFromBeingTestedForLoS(ignoreSpellIds.c_str()); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "VMap support included. LineOfSight:%i, getHeight:%i, indoorCheck:%i PetLOS:%i", enableLOS, enableHeight, enableIndoor, enablePetLOS); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "VMap support included. LineOfSight:%i, getHeight:%i, indoorCheck:%i", enableLOS, enableHeight, enableIndoor); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "VMap data directory is: %svmaps", m_dataPath.c_str()); m_int_configs[CONFIG_MAX_WHO] = ConfigMgr::GetIntDefault("MaxWhoListReturns", 49); - m_bool_configs[CONFIG_PET_LOS] = ConfigMgr::GetBoolDefault("vmap.petLOS", true); m_bool_configs[CONFIG_START_ALL_SPELLS] = ConfigMgr::GetBoolDefault("PlayerStart.AllSpells", false); if (m_bool_configs[CONFIG_START_ALL_SPELLS]) sLog->outWarn(LOG_FILTER_SERVER_LOADING, "PlayerStart.AllSpells enabled - may not function as intended!"); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index f75745dac9b..e63ffa878ce 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -138,7 +138,6 @@ enum WorldBoolConfigs CONFIG_ARENA_LOG_EXTENDED_INFO, CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN, CONFIG_VMAP_INDOOR_CHECK, - CONFIG_PET_LOS, CONFIG_START_ALL_SPELLS, CONFIG_START_ALL_EXPLORED, CONFIG_START_ALL_REP, diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index e70ef00e94c..14d772aa79a 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -303,14 +303,6 @@ vmap.enableHeight = 1 vmap.ignoreSpellIds = "7720" -# -# vmap.petLOS -# Description: Check line of sight for pets, to avoid them attacking through walls. -# Default: 1 - (Enabled, each pet attack will be checked for line of sight - not recommended if mmaps is enabled!) -# 0 - (Disabled, somewhat less CPU usage) - -vmap.petLOS = 0 - # # vmap.enableIndoorCheck # Description: VMap based indoor check to remove outdoor-only auras (mounts etc.). -- cgit v1.2.3 From bb6ce2b2c9018873127a352a39737ed4df7f7d46 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 25 Sep 2012 12:37:25 -0500 Subject: Core/MMaps: Only unload the navMeshQuery when instances are unloaded, suggestion by @Vlad852 closes #7631 --- src/server/game/Maps/Map.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 50218c8ba83..ae192f16080 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -72,7 +72,6 @@ Map::~Map() sScriptMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size()); MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId); - MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId()); } bool Map::ExistMap(uint32 mapid, int gx, int gy) -- cgit v1.2.3 From 50f833a0086c9f7f80152b907c77acb19d352896 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 06:59:31 -0500 Subject: Tools: Added an experimental tool (still WIP) to replace the current mmaps generator --- cmake/options.cmake | 2 +- src/tools/CMakeLists.txt | 1 + src/tools/mesh_extractor/ADT.h | 26 ++ src/tools/mesh_extractor/CMakeLists.txt | 62 +++ src/tools/mesh_extractor/Cache.h | 44 +++ src/tools/mesh_extractor/Chunk.cpp | 31 ++ src/tools/mesh_extractor/Chunk.h | 20 + src/tools/mesh_extractor/ChunkedData.cpp | 63 ++++ src/tools/mesh_extractor/ChunkedData.h | 20 + src/tools/mesh_extractor/Constants.h | 33 ++ src/tools/mesh_extractor/ContinentBuilder.cpp | 11 + src/tools/mesh_extractor/ContinentBuilder.h | 15 + src/tools/mesh_extractor/DoodadHandler.cpp | 99 +++++ src/tools/mesh_extractor/DoodadHandler.h | 51 +++ src/tools/mesh_extractor/Geometry.cpp | 102 +++++ src/tools/mesh_extractor/Geometry.h | 21 ++ src/tools/mesh_extractor/LiquidHandler.cpp | 1 + src/tools/mesh_extractor/LiquidHandler.h | 17 + src/tools/mesh_extractor/MPQ.cpp | 117 ++++++ src/tools/mesh_extractor/MPQ.h | 88 +++++ src/tools/mesh_extractor/MPQManager.cpp | 58 +++ src/tools/mesh_extractor/MPQManager.h | 24 ++ src/tools/mesh_extractor/MapChunk.cpp | 77 ++++ src/tools/mesh_extractor/MapChunk.h | 25 ++ src/tools/mesh_extractor/MeshExtractor.cpp | 34 ++ src/tools/mesh_extractor/Model.cpp | 49 +++ src/tools/mesh_extractor/Model.h | 21 ++ src/tools/mesh_extractor/ObjectDataHandler.cpp | 21 ++ src/tools/mesh_extractor/ObjectDataHandler.h | 15 + src/tools/mesh_extractor/TileBuilder.cpp | 37 ++ src/tools/mesh_extractor/TileBuilder.h | 22 ++ src/tools/mesh_extractor/Utils.cpp | 163 ++++++++ src/tools/mesh_extractor/Utils.h | 497 +++++++++++++++++++++++++ src/tools/mesh_extractor/WDT.cpp | 55 +++ src/tools/mesh_extractor/WDT.h | 27 ++ src/tools/mesh_extractor/WorldModelGroup.cpp | 122 ++++++ src/tools/mesh_extractor/WorldModelGroup.h | 33 ++ src/tools/mesh_extractor/WorldModelHandler.cpp | 190 ++++++++++ src/tools/mesh_extractor/WorldModelHandler.h | 42 +++ src/tools/mesh_extractor/WorldModelRoot.cpp | 74 ++++ src/tools/mesh_extractor/WorldModelRoot.h | 26 ++ src/tools/mesh_extractor/readme | 6 + 42 files changed, 2441 insertions(+), 1 deletion(-) create mode 100644 src/tools/mesh_extractor/ADT.h create mode 100644 src/tools/mesh_extractor/CMakeLists.txt create mode 100644 src/tools/mesh_extractor/Cache.h create mode 100644 src/tools/mesh_extractor/Chunk.cpp create mode 100644 src/tools/mesh_extractor/Chunk.h create mode 100644 src/tools/mesh_extractor/ChunkedData.cpp create mode 100644 src/tools/mesh_extractor/ChunkedData.h create mode 100644 src/tools/mesh_extractor/Constants.h create mode 100644 src/tools/mesh_extractor/ContinentBuilder.cpp create mode 100644 src/tools/mesh_extractor/ContinentBuilder.h create mode 100644 src/tools/mesh_extractor/DoodadHandler.cpp create mode 100644 src/tools/mesh_extractor/DoodadHandler.h create mode 100644 src/tools/mesh_extractor/Geometry.cpp create mode 100644 src/tools/mesh_extractor/Geometry.h create mode 100644 src/tools/mesh_extractor/LiquidHandler.cpp create mode 100644 src/tools/mesh_extractor/LiquidHandler.h create mode 100644 src/tools/mesh_extractor/MPQ.cpp create mode 100644 src/tools/mesh_extractor/MPQ.h create mode 100644 src/tools/mesh_extractor/MPQManager.cpp create mode 100644 src/tools/mesh_extractor/MPQManager.h create mode 100644 src/tools/mesh_extractor/MapChunk.cpp create mode 100644 src/tools/mesh_extractor/MapChunk.h create mode 100644 src/tools/mesh_extractor/MeshExtractor.cpp create mode 100644 src/tools/mesh_extractor/Model.cpp create mode 100644 src/tools/mesh_extractor/Model.h create mode 100644 src/tools/mesh_extractor/ObjectDataHandler.cpp create mode 100644 src/tools/mesh_extractor/ObjectDataHandler.h create mode 100644 src/tools/mesh_extractor/TileBuilder.cpp create mode 100644 src/tools/mesh_extractor/TileBuilder.h create mode 100644 src/tools/mesh_extractor/Utils.cpp create mode 100644 src/tools/mesh_extractor/Utils.h create mode 100644 src/tools/mesh_extractor/WDT.cpp create mode 100644 src/tools/mesh_extractor/WDT.h create mode 100644 src/tools/mesh_extractor/WorldModelGroup.cpp create mode 100644 src/tools/mesh_extractor/WorldModelGroup.h create mode 100644 src/tools/mesh_extractor/WorldModelHandler.cpp create mode 100644 src/tools/mesh_extractor/WorldModelHandler.h create mode 100644 src/tools/mesh_extractor/WorldModelRoot.cpp create mode 100644 src/tools/mesh_extractor/WorldModelRoot.h create mode 100644 src/tools/mesh_extractor/readme (limited to 'src') diff --git a/cmake/options.cmake b/cmake/options.cmake index 11ebe6ddd12..5802ab86f43 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -10,7 +10,7 @@ option(SERVERS "Build worldserver and authserver" 1) option(SCRIPTS "Build core with scripts included" 1) -option(TOOLS "Build map/vmap extraction/assembler tools" 0) +option(TOOLS "Build map/vmap/mmap extraction/assembler tools" 0) option(USE_SCRIPTPCH "Use precompiled headers when compiling scripts" 1) option(USE_COREPCH "Use precompiled headers when compiling servers" 1) option(WITH_WARNINGS "Show all warnings during compile" 0) diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 2d378966aff..bbff6f85751 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -12,3 +12,4 @@ add_subdirectory(map_extractor) add_subdirectory(vmap4_assembler) add_subdirectory(vmap4_extractor) add_subdirectory(mmaps_generator) +add_subdirectory(mesh_extractor) diff --git a/src/tools/mesh_extractor/ADT.h b/src/tools/mesh_extractor/ADT.h new file mode 100644 index 00000000000..18b811a4e4c --- /dev/null +++ b/src/tools/mesh_extractor/ADT.h @@ -0,0 +1,26 @@ +#ifndef ADT_H +#define ADT_H +#include "ChunkedData.h" +#include "MapChunk.h" +#include "DoodadHandler.h" +#include "WorldModelHandler.h" + +class ADT +{ +public: + ADT(); + ~ADT() { delete[] MapChunks; delete ObjectData; delete Data; } + + ChunkedData* ObjectData; + ChunkedData* Data; + // This here is not a pointer, is an array of objects ( made this way to allow the dynamic allocation ) + MapChunk* MapChunks; + MHDR Header; + // Can we dispose of this? + bool HasObjectData; + + DoodadHandler* _DoodadHandler; + WorldModelHandler* _WorldModelHandler; + LiquidHandler* _LiquidHandler; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/CMakeLists.txt b/src/tools/mesh_extractor/CMakeLists.txt new file mode 100644 index 00000000000..3f5b5526dd4 --- /dev/null +++ b/src/tools/mesh_extractor/CMakeLists.txt @@ -0,0 +1,62 @@ +# Copyright (C) 2005-2009 MaNGOS project +# Copyright (C) 2008-2012 TrinityCore +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +file(GLOB_RECURSE sources *.cpp *.h) + +if( UNIX ) + include_directories ( + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/dep/libmpq + ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${CMAKE_CURRENT_SOURCE_DIR} + ) +elseif( WIN32 ) + include_directories ( + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/Database + ${CMAKE_SOURCE_DIR}/src/server/shared/Database/Implementation + ${CMAKE_SOURCE_DIR}/src/server/shared/Threading + ${CMAKE_SOURCE_DIR}/src/server/shared/Logging + ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/dep/libmpq + ${CMAKE_SOURCE_DIR}/dep/libmpq/win + ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${ACE_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ) +endif() + +add_executable(MeshExtractor + ${sources} +) + +target_link_libraries(MeshExtractor + mpq + Recast + Detour + ${BZIP2_LIBRARIES} + ${ZLIB_LIBRARIES} + ${ACE_LIBRARY} +) + +add_dependencies(MeshExtractor mpq Recast Detour) + +if( UNIX ) + install(TARGETS MeshExtractor DESTINATION bin) +elseif( WIN32 ) + install(TARGETS MeshExtractor DESTINATION "${CMAKE_INSTALL_PREFIX}") +endif() \ No newline at end of file diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h new file mode 100644 index 00000000000..186a7870af1 --- /dev/null +++ b/src/tools/mesh_extractor/Cache.h @@ -0,0 +1,44 @@ +#ifndef CACHE_H +#define CACHE_H +#include +#include "Common.h" + +class WorldModelRoot; +class Model; + +template +class GenericCache +{ +public: + GenericCache() {} + const int32 FlushLimit = 1000; + + void Insert(std::string key, T* val) + { + if (_items.size() > FlushLimit) + Clear(); + _items.insert(key, val); + } + + T* Get(std::string key) + { + UNORDERED_MAP::iterator itr = _items.find(key); + if (itr != _items.end()) + return itr->second; + return NULL; + } + + void Clear() { _items.clear(); } +private: + UNORDERED_MAP _items; +}; + +class CacheClass +{ + CacheClass() {} + GenericCache ModelCache; + GenericCache WorldModelCache; +}; + +extern CacheClass* Cache; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/Chunk.cpp b/src/tools/mesh_extractor/Chunk.cpp new file mode 100644 index 00000000000..b41fa7d07d4 --- /dev/null +++ b/src/tools/mesh_extractor/Chunk.cpp @@ -0,0 +1,31 @@ +#include "Chunk.h" +#include "Utils.h" + +int32 Chunk::FindSubChunkOffset(std::string name) +{ + // Reverse the name + name = std::string(name.rbegin(), name.rend()); + if (name.size() != 4) + return -1; + + FILE* stream = GetStream(); + uint32 matched = 0; + while (ftell(stream) < Utils::Size(stream)) + { + char b; + fread(&b, sizeof(char), 1, stream); + if (b == name[matched]) + ++matched; + else + matched = 0; + if (matched == 4) + return ftell(stream) - 4; + } + return -1; +} + +FILE* Chunk::GetStream() +{ + fseek(Stream, Offset, SEEK_SET); + return Stream; +} diff --git a/src/tools/mesh_extractor/Chunk.h b/src/tools/mesh_extractor/Chunk.h new file mode 100644 index 00000000000..2eea36f69b6 --- /dev/null +++ b/src/tools/mesh_extractor/Chunk.h @@ -0,0 +1,20 @@ +#ifndef CHUNK_H +#define CHUNK_H +#include "Common.h" +#include +class ChunkedData; + +class Chunk +{ +public: + Chunk(const char* name, uint32 length, uint32 offset, FILE* stream) : Name(name), Length(length), Offset(offset), Stream(stream) {} + + int32 FindSubChunkOffset(std::string name); + FILE* GetStream(); + std::string Name; + uint32 Length; + uint32 Offset; + FILE* Stream; +}; + +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/ChunkedData.cpp b/src/tools/mesh_extractor/ChunkedData.cpp new file mode 100644 index 00000000000..470b8b94f39 --- /dev/null +++ b/src/tools/mesh_extractor/ChunkedData.cpp @@ -0,0 +1,63 @@ +#include "ChunkedData.h" +#include "MPQManager.h" +#include "Utils.h" + +#include + +ChunkedData::ChunkedData( FILE* stream, uint32 maxLength, uint32 chunksHint /*= 300*/ ) : +Stream(stream) +{ + if (!Stream) + return; + Load(maxLength, chunksHint); +} + +ChunkedData::ChunkedData( std::string file, uint32 chunksHint /*= 300*/ ) +{ + Stream = MPQHandler->GetFile(file); + if (!Stream) + return; + Load(0, chunksHint); +} + +void ChunkedData::Load( uint32 maxLength, uint32 chunksHint ) +{ + if (!maxLength) + maxLength = Utils::Size(Stream); + Chunks.reserve(chunksHint); + uint32 baseOffset = ftell(Stream); + uint32 calcOffset = 0; + while ((calcOffset + baseOffset) < Utils::Size(Stream) && (calcOffset < maxLength)) + { + char nameBytes[5]; + uint32 read = fread(&nameBytes, sizeof(char), 4, Stream); + nameBytes[read] = '\0'; + std::string name = std::string(nameBytes); + // Utils::Reverse(nameBytes); + name = std::string(name.rbegin(), name.rend()); + uint32 length; + fread(&length, sizeof(uint32), 1, Stream); + calcOffset += 8; + Chunks.push_back(new Chunk(name.c_str(), length, calcOffset + baseOffset, Stream)); + calcOffset += length; + // save an extra seek at the end + if ((calcOffset + baseOffset) < Utils::Size(Stream) && calcOffset < maxLength) + fseek(Stream, length, SEEK_CUR); + } +} + +int ChunkedData::GetFirstIndex( std::string name ) +{ + for (int i = 0; i < Chunks.size(); ++i) + if (Chunks[i]->Name == name) + return i; + return -1; +} + +Chunk* ChunkedData::GetChunkByName( std::string name ) +{ + for (int i = 0; i < Chunks.size(); ++i) + if (Chunks[i]->Name == name) + return Chunks[i]; + return NULL; +} diff --git a/src/tools/mesh_extractor/ChunkedData.h b/src/tools/mesh_extractor/ChunkedData.h new file mode 100644 index 00000000000..6e102828222 --- /dev/null +++ b/src/tools/mesh_extractor/ChunkedData.h @@ -0,0 +1,20 @@ +#ifndef CHNK_H +#define CHNK_H + +#include +#include "Chunk.h" + +class ChunkedData +{ +public: + ChunkedData(FILE* stream, uint32 maxLength, uint32 chunksHint = 300); + ChunkedData(std::string file, uint32 chunksHint = 300); + + int GetFirstIndex(std::string name); + Chunk* GetChunkByName(std::string name); + + void Load(uint32 maxLength, uint32 chunksHint); + std::vector Chunks; + FILE* Stream; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/Constants.h b/src/tools/mesh_extractor/Constants.h new file mode 100644 index 00000000000..885761f1687 --- /dev/null +++ b/src/tools/mesh_extractor/Constants.h @@ -0,0 +1,33 @@ +#ifndef CONSTANTS_H +#define CONSTANTS_H + +#include "Common.h" + +class Constants +{ +public: + enum TriangleType + { + TRIANGLE_TYPE_UNKNOWN, + TRIANGLE_TYPE_TERRAIN, + TRIANGLE_TYPE_WATER, + TRIANGLE_TYPE_DOODAD, + TRIANGLE_TYPE_WMO + }; + + enum PolyArea + { + POLY_AREA_TERRAIN = 1, + POLY_AREA_WATER = 2, + POLY_AREA_ROAD = 3, + POLY_AREA_DANGER = 4, + }; + static const float TileSize; + static const float MaxXY; + static const float ChunkSize; + static const float UnitSize; + static const float Origin[]; + static const float PI; +}; + +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp new file mode 100644 index 00000000000..8af6f3a02e8 --- /dev/null +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -0,0 +1,11 @@ +#include "ContinentBuilder.h" +#include "WDT.h" +#include "Utils.h" + +void ContinentBuilder::Build() +{ + for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) + { + + } +} diff --git a/src/tools/mesh_extractor/ContinentBuilder.h b/src/tools/mesh_extractor/ContinentBuilder.h new file mode 100644 index 00000000000..7db141ddcf1 --- /dev/null +++ b/src/tools/mesh_extractor/ContinentBuilder.h @@ -0,0 +1,15 @@ +#ifndef CONT_BUILDER_H +#define CONT_BUILDER_H +#include +#include "WDT.h" + +class ContinentBuilder +{ +public: + ContinentBuilder(std::string continent, WDT* wdt) : Continent(continent), TileMap(wdt) {} + void Build(); +private: + std::string Continent; + WDT* TileMap; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/DoodadHandler.cpp b/src/tools/mesh_extractor/DoodadHandler.cpp new file mode 100644 index 00000000000..4a7707753c4 --- /dev/null +++ b/src/tools/mesh_extractor/DoodadHandler.cpp @@ -0,0 +1,99 @@ +#include "DoodadHandler.h" +#include "Chunk.h" +#include "Cache.h" +#include "Model.h" +#include "g3d/Matrix4.h" + +DoodadHandler::DoodadHandler( ADT* adt ) : ObjectDataHandler(adt), _definitions(NULL), _paths(NULL) +{ + if (!adt->HasObjectData) + return; + Chunk* mddf = adt->ObjectData->GetChunkByName("MDDF"); + if (mddf) + ReadDoodadDefinitions(mddf); + + Chunk* mmid = adt->ObjectData->GetChunkByName("MMID"); + Chunk* mmdx = adt->ObjectData->GetChunkByName("MMDX"); + if (mmid && mmdx) + ReadDoodadPaths(mmid, mmdx); +} + +void DoodadHandler::ProcessInternal( ChunkedData* subChunks ) +{ + if (!IsSane()) + return; + Chunk* doodadReferencesChunk = subChunks->GetChunkByName("MCRD"); + if (!doodadReferencesChunk) + return; + FILE* stream = doodadReferencesChunk->GetStream(); + uint32 refCount = doodadReferencesChunk->Length / 4; + for (int i = 0; i < refCount; i++) + { + int32 index; + fread(&index, sizeof(int32), 1, stream); + if (index < 0 || index >= _definitions->size()) + continue; + DoodadDefinition doodad = (*_definitions)[index]; + if (_drawn.find(doodad.UniqueId) != _drawn.end()) + continue; + _drawn.insert(doodad.UniqueId); + if (doodad.MmidIndex >= _paths->size()) + continue; + + std::string path = (*_paths)[doodad.MmidIndex]; + Model* model = Cache.ModelCache.Get(path); + if (!model) + { + model = new Model(path); + Cache.ModelCache.Insert(path, model); + } + if (!model->IsCollidable) + continue; + + Vertices.reserve(refCount * model->Vertices.size() * 0.2); + Triangles.reserve(refCount * model->Triangles.size() * 0.2); + + InsertModelGeometry(doodad, model); + } +} + +void DoodadHandler::ReadDoodadDefinitions( Chunk* chunk ) +{ + int32 count = chunk->Length / 36; + _definitions = new std::vector; + _definitions->reserve(count); + FILE* stream = chunk->GetStream(); + for (int i = 0; i < count; i++) + { + DoodadDefinition def; + def.Read(stream); + _definitions->push_back(def); + } +} + +void DoodadHandler::ReadDoodadPaths( Chunk* id, Chunk* data ) +{ + int paths = id->Length / 4; + _paths = new std::vector(); + _paths->reserve(paths); + for (int i = 0; i < paths; i++) + { + FILE* idStream = id->GetStream(); + fseek(idStream, i * 4, SEEK_CUR); + uint32 offset; + fread(&offset, sizeof(uint32), 1, idStream); + FILE* dataStream = data->GetStream(); + fseek(dataStream, offset + data->Offset, SEEK_SET); + _paths->push_back(Utils::ReadString(dataStream)); + } +} + +void DoodadHandler::InsertModelGeometry(DoodadDefinition def, Model* model) +{ + G3D::Matrix4 transformation = Utils::GetTransformation(def); + uint32 vertOffset = Vertices.size(); + for (std::vector::iterator itr = model->Vertices.begin(); itr != model->Vertices.end(); ++itr) + Vertices.push_back(Utils::VectorTransform(*itr, transformation)); + for (std::vector >::iterator itr = model->Triangles.begin(); itr != model->Triangles.end(); ++itr) + Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_DOODAD, itr->V0 + vertOffset, itr->V1 + vertOffset, itr->V2 + vertOffset)); +} \ No newline at end of file diff --git a/src/tools/mesh_extractor/DoodadHandler.h b/src/tools/mesh_extractor/DoodadHandler.h new file mode 100644 index 00000000000..c62584ca1f1 --- /dev/null +++ b/src/tools/mesh_extractor/DoodadHandler.h @@ -0,0 +1,51 @@ +#ifndef DOOADHNDL_H +#define DOOADHNDL_H +#include "ObjectDataHandler.h" +#include "Utils.h" +#include "Chunk.h" +#include "Model.h" +#include +#include + +class DoodadDefinition : IDefinition +{ +public: + uint32 MmidIndex; + uint32 UniqueId; + uint16 DecimalScale; + uint16 Flags; + + float Scale() { return DecimalScale / 1024.0f; } + + void Read(FILE* stream) + { + fread(&MmidIndex, sizeof(uint32), 1, stream); + fread(&UniqueId, sizeof(uint32), 1, stream); + Position = Vector3::Read(stream); + Rotation = Vector3::Read(stream); + fread(&DecimalScale, sizeof(uint16), 1, stream); + fread(&Flags, sizeof(uint16), 1, stream); + } +}; + +class DoodadHandler : public ObjectDataHandler +{ +public: + DoodadHandler(ADT* adt); + std::vector Vertices; + std::vector > Triangles; + bool IsSane() { return _definitions && _paths; } + + +protected: + void ProcessInternal(ChunkedData* chunk); + +private: + void ReadDoodadDefinitions(Chunk* chunk); + void ReadDoodadPaths(Chunk* id, Chunk* data); + void InsertModelGeometry(DoodadDefinition def, Model* model); + std::set _drawn; + std::vector* _definitions; + std::vector* _paths; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/Geometry.cpp b/src/tools/mesh_extractor/Geometry.cpp new file mode 100644 index 00000000000..8e417af4c73 --- /dev/null +++ b/src/tools/mesh_extractor/Geometry.cpp @@ -0,0 +1,102 @@ +#include "Geometry.h" +#include "Constants.h" + +Geometry::Geometry() : Transform(false) +{ + Vertices.reserve(10000); + Triangles.reserve(10000); +} + +void Geometry::CalculateBoundingBox( float*& min, float*& max ) +{ + min = new float[3]; + max = new float[3]; + + for (std::vector::iterator itr = Vertices.begin(); itr != Vertices.end(); ++itr) + { + if (itr->x > max[0]) + max[0] = itr->x; + if (itr->x < min[0]) + min[0] = itr->x; + + if (itr->y > max[1]) + max[1] = itr->y; + if (itr->y < min[1]) + min[1] = itr->y; + + if (itr->z > max[2]) + max[2] = itr->z; + if (itr->z < min[2]) + min[2] = itr->z; + } +} + +void Geometry::CalculateMinMaxHeight( float& min, float& max ) +{ + min = 0.0f; + max = 0.0f; + + for (std::vector::iterator itr = Vertices.begin(); itr != Vertices.end(); ++itr) + { + if (Transform) + { + if (itr->y < min) + min = itr->y; + if (itr->y > max) + max = itr->y; + } + else + { + if (itr->z < min) + min = itr->z; + if (itr->z > max) + max = itr->z; + } + } +} + +void Geometry::AddData( std::vector& verts, std::vector >& tris ) +{ + uint32 vertOffset = Vertices.size(); + for (std::vector::iterator itr = verts.begin(); itr != verts.end(); ++itr) + Vertices.push_back(Transform ? Utils::ToRecast(*itr) : *itr); + + for (std::vector >::iterator itr = tris.begin(); itr != tris.end(); ++itr) + Triangles.push_back(Triangle(itr->Type, itr->V0 + vertOffset, itr->V1 + vertOffset, itr->V2 + vertOffset)); +} + +void Geometry::GetRawData( float*& verts, int*& tris, uint8*& areas ) +{ + verts = new float[Vertices.size() * 3]; + for (int i = 0; i < Vertices.size(); ++i) + { + Vector3& vert = Vertices[i]; + verts[(i * 3) + 0] = vert.x; + verts[(i * 3) + 1] = vert.y; + verts[(i * 3) + 2] = vert.z; + } + + tris = new int[Triangles.size() * 3]; + for (int i = 0; i < Triangles.size(); ++i) + { + Triangle& tri = Triangles[i]; + tris[(i * 3) + 0] = (int)tri.V0; + tris[(i * 3) + 1] = (int)tri.V1; + tris[(i * 3) + 2] = (int)tri.V2; + } + + areas = new uint8[Triangles.size()]; + for (int i = 0; i < Triangles.size(); i++) + { + switch (Triangles[i].Type) + { + case Constants::TRIANGLE_TYPE_WATER: + areas[i] = Constants::POLY_AREA_WATER; + break; + default: + areas[i] = Constants::POLY_AREA_TERRAIN; + break; + } + } +} + diff --git a/src/tools/mesh_extractor/Geometry.h b/src/tools/mesh_extractor/Geometry.h new file mode 100644 index 00000000000..048d9fde578 --- /dev/null +++ b/src/tools/mesh_extractor/Geometry.h @@ -0,0 +1,21 @@ +#ifndef GEOMETRY_H +#define GEOMETRY_H +#include + +#include "Utils.h" + +class Geometry +{ +public: + Geometry(); + + void CalculateBoundingBox(float*& min, float*& max); + void CalculateMinMaxHeight(float& min, float& max); + void AddData(std::vector& verts, std::vector >& tris); + void GetRawData(float*& verts, int*& tris, uint8*& areas); + + std::vector Vertices; + std::vector > Triangles; + bool Transform; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/LiquidHandler.cpp b/src/tools/mesh_extractor/LiquidHandler.cpp new file mode 100644 index 00000000000..5924c693196 --- /dev/null +++ b/src/tools/mesh_extractor/LiquidHandler.cpp @@ -0,0 +1 @@ +#include "LiquidHandler.h" \ No newline at end of file diff --git a/src/tools/mesh_extractor/LiquidHandler.h b/src/tools/mesh_extractor/LiquidHandler.h new file mode 100644 index 00000000000..ba89be33e08 --- /dev/null +++ b/src/tools/mesh_extractor/LiquidHandler.h @@ -0,0 +1,17 @@ +#ifndef LIQUID_H +#define LIQUID_H +#include "ADT.h" +#include "Utils.h" +#include "Common.h" + +#include + +class LiquidHandler +{ +public: + ADT* Source; + std::vector Vertices; + std::vector > Triangles; + std::vector MCNKData; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/MPQ.cpp b/src/tools/mesh_extractor/MPQ.cpp new file mode 100644 index 00000000000..fbae56cd7a0 --- /dev/null +++ b/src/tools/mesh_extractor/MPQ.cpp @@ -0,0 +1,117 @@ +#include "MPQ.h" +#include "MPQManager.h" +#include +#include + +MPQArchive::MPQArchive(const char* filename) +{ + int result = libmpq__archive_open(&mpq_a, filename, -1); + printf("Opening %s\n", filename); + if (result) + { + switch (result) + { + case LIBMPQ_ERROR_OPEN : + printf("Error opening archive '%s': Does file really exist?\n", filename); + break; + case LIBMPQ_ERROR_FORMAT : /* bad file format */ + printf("Error opening archive '%s': Bad file format\n", filename); + break; + case LIBMPQ_ERROR_SEEK : /* seeking in file failed */ + printf("Error opening archive '%s': Seeking in file failed\n", filename); + break; + case LIBMPQ_ERROR_READ : /* Read error in archive */ + printf("Error opening archive '%s': Read error in archive\n", filename); + break; + case LIBMPQ_ERROR_MALLOC : /* maybe not enough memory? :) */ + printf("Error opening archive '%s': Maybe not enough memory\n", filename); + break; + default: + printf("Error opening archive '%s': Unknown error\n", filename); + break; + } + } +} + +void MPQArchive::close() +{ + libmpq__archive_close(mpq_a); +} + +MPQFile::MPQFile(const char* filename): +eof(false), buffer(0), pointer(0), size(0) +{ + for (std::deque::iterator i = MPQHandler->Archives.begin(); i != MPQHandler->Archives.end();++i) + { + mpq_archive* mpq_a = (*i)->mpq_a; + + uint32_t filenum; + if(libmpq__file_number(mpq_a, filename, &filenum)) + continue; + libmpq__off_t transferred; + libmpq__file_unpacked_size(mpq_a, filenum, &size); + + // HACK: in patch.mpq some files don't want to open and give 1 for filesize + if (size<=1) { + // printf("warning: file %s has size %d; cannot Read.\n", filename, size); + eof = true; + buffer = 0; + return; + } + buffer = new char[size]; + + //libmpq_file_getdata + libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); + /*libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);*/ + return; + + } + eof = true; + buffer = 0; +} + +size_t MPQFile::Read(void* dest, size_t bytes) +{ + if (eof) + return 0; + + size_t rpos = pointer + bytes; + if (rpos > size) { + bytes = size - pointer; + eof = true; + } + + memcpy(dest, &(buffer[pointer]), bytes); + + pointer = rpos; + + return bytes; +} + +void MPQFile::seek(int offset) +{ + pointer = offset; + eof = (pointer >= size); +} + +void MPQFile::seekRelative(int offset) +{ + pointer += offset; + eof = (pointer >= size); +} + +void MPQFile::close() +{ + if (buffer) + delete[] buffer; + buffer = 0; + eof = true; +} + +FILE* MPQFile::GetFileStream() +{ + FILE* file = tmpfile(); + fwrite(buffer, sizeof(char), size, file); + fseek(file, 0, SEEK_SET); + return file; +} diff --git a/src/tools/mesh_extractor/MPQ.h b/src/tools/mesh_extractor/MPQ.h new file mode 100644 index 00000000000..dd566bccff5 --- /dev/null +++ b/src/tools/mesh_extractor/MPQ.h @@ -0,0 +1,88 @@ +#ifndef MPQ_H +#define MPQ_H + +#include "libmpq/mpq.h" +#include "Common.h" +#include +#include +#include +#include +#include + +using namespace std; + +class MPQArchive +{ + +public: + mpq_archive_s *mpq_a; + + MPQArchive(const char* filename); + void close(); + + void GetFileListTo(vector& filelist) { + uint32_t filenum; + if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; + libmpq__off_t size, transferred; + libmpq__file_unpacked_size(mpq_a, filenum, &size); + + char *buffer = new char[size]; + + libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); + + char seps[] = "\n"; + char* token; + + token = strtok( buffer, seps ); + uint32 counter = 0; + while ((token != NULL) && (counter < size)) { + //cout << token << endl; + token[strlen(token) - 1] = 0; + string s = token; + filelist.push_back(s); + counter += strlen(token) + 2; + token = strtok(NULL, seps); + } + + delete[] buffer; + } +}; + +class MPQFile +{ + //MPQHANDLE handle; + bool eof; + char *buffer; + libmpq__off_t pointer,size; + + // disable copying + MPQFile(const MPQFile& /*f*/) {} + void operator=(const MPQFile& /*f*/) {} + +public: + MPQFile(const char* filename); // filenames are not case sensitive + ~MPQFile() { close(); } + size_t Read(void* dest, size_t bytes); + FILE* GetFileStream(); + size_t getSize() { return size; } + size_t getPos() { return pointer; } + char* getBuffer() { return buffer; } + char* getPointer() { return buffer + pointer; } + bool isEof() { return eof; } + void seek(int offset); + void seekRelative(int offset); + void close(); +}; + +inline void flipcc(char *fcc) +{ + char t; + t=fcc[0]; + fcc[0]=fcc[3]; + fcc[3]=t; + t=fcc[1]; + fcc[1]=fcc[2]; + fcc[2]=t; +} + +#endif diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp new file mode 100644 index 00000000000..429b09ffe02 --- /dev/null +++ b/src/tools/mesh_extractor/MPQManager.cpp @@ -0,0 +1,58 @@ +#include "MPQManager.h" +#include "MPQ.h" + +char* MPQManager::Files[] = { + "common.MPQ", + "common-2.MPQ", + "expansion.MPQ", + "lichking.MPQ", + "patch.MPQ", + "patch-2.MPQ", + "patch-3.MPQ" +}; + +void MPQManager::Initialize() +{ + LoadMPQs(); +} + +void MPQManager::LoadMaps() +{ + +} + +void MPQManager::LoadMPQs() +{ + // Load the locale MPQ files first + char filename[512]; + + /*sprintf(filename,"Data/%s/locale-%s.MPQ", langs[locale], langs[locale]);*/ + Archives.push_front(new MPQArchive("Data/enUS/locale-enUS.MPQ")); + + for(int i = 0; i < 3; ++i) + { + char ext[3] = ""; + if (i) + sprintf(ext, "-%i", i + 1); + + sprintf(filename, "Data/enUS/patch-enUS%s.MPQ", ext); + Archives.push_front(new MPQArchive(filename)); + } + + // Now load the common MPQ files + int count = sizeof(Files) / sizeof(char*); + for (int i = 0; i < count; ++i) + { + sprintf(filename, "Data/%s", Files[i]); + Archives.push_front(new MPQArchive(filename)); + } + printf("Loaded %u MPQ files succesfully", Archives.size()); +} + +FILE* MPQManager::GetFile( std::string path ) +{ + MPQFile file(path.c_str()); + if (file.isEof()) + return NULL; + return file.GetFileStream(); +} diff --git a/src/tools/mesh_extractor/MPQManager.h b/src/tools/mesh_extractor/MPQManager.h new file mode 100644 index 00000000000..e10066ae4a6 --- /dev/null +++ b/src/tools/mesh_extractor/MPQManager.h @@ -0,0 +1,24 @@ +#ifndef MPQ_MANAGER_H +#define MPQ_MANAGER_H + +#include "MPQ.h" + +class MPQManager +{ +public: + MPQManager() {} + ~MPQManager() {} + + void Initialize(); + void LoadMaps(); + FILE* GetFile(std::string path); + + std::deque Archives; + + static char* Files[]; +protected: + void LoadMPQs(); +}; + +extern MPQManager* MPQHandler; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/MapChunk.cpp b/src/tools/mesh_extractor/MapChunk.cpp new file mode 100644 index 00000000000..95f8c2e56c0 --- /dev/null +++ b/src/tools/mesh_extractor/MapChunk.cpp @@ -0,0 +1,77 @@ +#include "MapChunk.h" +#include "ADT.h" + +MapChunk::MapChunk( ADT* _adt, Chunk* chunk ) : adt(_adt), Source(chunk), Vertices(NULL) +{ + FILE* stream = chunk->GetStream(); + Header.Read(stream); + fseek(stream, chunk->Offset, SEEK_SET); + GenerateVertices(stream); +} + +void MapChunk::GenerateTriangles() +{ + Triangles.reserve(256); + for (int y = 0; y < 8; y++) + { + for (int x = 0; x < 8; x++) + { + if (HasHole(Header.Holes, x / 2, y / 2)) + continue; + + uint32 topLeft = (17 * y) + x; + uint32 topRight = (17 * y) + x + 1; + uint32 bottomLeft = (17 * (y + 1)) + x; + uint32 bottomRight = (17 * (y + 1)) + x + 1; + uint32 center = (17 * y) + 9 + x; + + uint8 triangleType = Constants::TRIANGLE_TYPE_TERRAIN; + if (ADT.LiquidHandler && ADT.LiquidHandler.MCNKData) + { + var data = ADT.LiquidHandler.MCNKData[Index]; + uint32 maxHeight = std::max( + std::max( + std::max(std::max(Vertices[topLeft].z, Vertices[topRight].z), Vertices[bottomLeft].z), + Vertices[bottomRight].z), Vertices[center].z); + if (data && data->IsWater(x, y, maxHeight)) + triangleType = Constants::TRIANGLE_TYPE_WATER; + } + + Triangles.push_back(new Triangle(triangleType, topRight, topLeft, center)); + Triangles.push_back(new Triangle(triangleType, topLeft, bottomLeft, center)); + Triangles.push_back(new Triangle(triangleType, bottomLeft, bottomRight, center)); + Triangles.push_back(new Triangle(triangleType, bottomRight, topRight, center)); + } + } +} + +MapChunk::~MapChunk() +{ + delete[] Vertices; +} + +void MapChunk::GenerateVertices( FILE* stream ) +{ + fseek(stream, Header.OffsetMCVT, SEEK_CUR); + int32 vertIndex = 0; + Vertices = new Vector3[125]; + + for (int j = 0; j < 17; j++) + { + int values = j % 2 ? 8 : 9; + for (int i = 0; i < values; i++) + { + float tmp; + fread(&tmp, sizeof(float), 1, stream); + Vector3 vert(Header.Position.x - (j * (Constants::UnitSize * 0.5f)), Header.Position.y - (i * Constants::UnitSize), Header.Position.z + tmp); + if (values == 8) + vert.y -= Constants::UnitSize * 0.5f; + Vertices[vertIndex++] = vert; + } + } +} + +bool MapChunk::HasHole( uint32 map, int x, int y ) +{ + return (map & 0x0000FFFF) & ((1 << x) << (y << 2)); +} diff --git a/src/tools/mesh_extractor/MapChunk.h b/src/tools/mesh_extractor/MapChunk.h new file mode 100644 index 00000000000..034429a81ec --- /dev/null +++ b/src/tools/mesh_extractor/MapChunk.h @@ -0,0 +1,25 @@ +#ifndef MAPCHUNK_H +#define MAPCHUNK_H +#include "Chunk.h" +#include "Utils.h" +#include "Constants.h" +#include +class ADT; + +class MapChunk +{ +public: + MapChunk(ADT* _adt, Chunk* chunk); + ~MapChunk(); + + void GenerateTriangles(); + void GenerateVertices(FILE* stream); + static bool HasHole(uint32 map, int x, int y); + ADT* adt; + Chunk* Source; + MapChunkHeader Header; + Vector3* Vertices; + std::vector > Triangles; + int32 Index; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp new file mode 100644 index 00000000000..0220627cbcc --- /dev/null +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -0,0 +1,34 @@ +#include "MPQManager.h" +#include "WDT.h" +#include "ContinentBuilder.h" +#include "Cache.h" + +MPQManager* MPQHandler; +CacheClass* Cache; + +void ExtractAllMaps() +{ + WDT wdt("World\\maps\\DalaranPrison\\DalaranPrison.wdt"); + if (!wdt.IsValid) + return; + printf("Model valid!"); + if (wdt.IsGlobalModel) + { + printf("Unsupported"); + return; + } + ContinentBuilder builder("DalaranPrison", &wdt); + builder.Build(); +} + +int main(int argc, char* argv[]) +{ + system("pause"); + Cache = new CacheClass(); + MPQHandler = new MPQManager(); + MPQHandler->Initialize(); + MPQHandler->LoadMaps(); + ExtractAllMaps(); + return 0; +} + diff --git a/src/tools/mesh_extractor/Model.cpp b/src/tools/mesh_extractor/Model.cpp new file mode 100644 index 00000000000..a1c67d23f28 --- /dev/null +++ b/src/tools/mesh_extractor/Model.cpp @@ -0,0 +1,49 @@ +#include "Model.h" +#include "MPQManager.h" +#include "Utils.h" + +Model::Model( std::string path ) +{ + Stream = MPQHandler->GetFile(Utils::FixModelPath(path)); + Header.Read(Stream); + if (Header.OffsetBoundingNormals > 0 && Header.OffsetBoundingVertices > 0 && + Header.OffsetBoundingTriangles > 0 && Header.BoundingRadius > 0.0f) + { + IsCollidable = true; + ReadVertices(Stream); + ReadBoundingNormals(Stream); + ReadBoundingTriangles(Stream); + } +} + +void Model::ReadVertices( FILE* stream ) +{ + fseek(stream, Header.OffsetBoundingVertices, SEEK_SET); + Vertices.reserve(Header.CountBoundingVertices); + for (int i = 0; i < Header.CountBoundingVertices; ++i) + Vertices[i] = Vector3::Read(stream); +} + +void Model::ReadBoundingTriangles( FILE* stream ) +{ + fseek(stream, Header.OffsetBoundingTriangles, SEEK_SET); + Triangles.reserve(Header.CountBoundingTriangles / 3); + for (int i = 0; i < Header.CountBoundingTriangles / 3; i++) + { + Triangle tri; + tri.Type = Constants::TRIANGLE_TYPE_DOODAD; + fread(&tri.V0, sizeof(uint16), 1, stream); + fread(&tri.V1, sizeof(uint16), 1, stream); + fread(&tri.V2, sizeof(uint16), 1, stream); + Triangles[i] = tri; + } +} + +void Model::ReadBoundingNormals( FILE* stream ) +{ + fseek(stream, Header.OffsetBoundingNormals, SEEK_SET); + Normals.reserve(Header.CountBoundingNormals); + for (int i = 0; i < Header.CountBoundingNormals; i++) + Normals[i] = Vector3::Read(stream); +} + diff --git a/src/tools/mesh_extractor/Model.h b/src/tools/mesh_extractor/Model.h new file mode 100644 index 00000000000..a5b8338461d --- /dev/null +++ b/src/tools/mesh_extractor/Model.h @@ -0,0 +1,21 @@ +#ifndef MODEL_H +#define MODEL_H +#include +#include "Utils.h" + +class Model +{ +public: + Model(std::string path); + + void ReadVertices(FILE* stream); + void ReadBoundingTriangles(FILE* stream); + void ReadBoundingNormals(FILE* stream); + ModelHeader Header; + std::vector Vertices; + std::vector Normals; + std::vector > Triangles; + bool IsCollidable; + FILE* Stream; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/ObjectDataHandler.cpp b/src/tools/mesh_extractor/ObjectDataHandler.cpp new file mode 100644 index 00000000000..3ed2ee49604 --- /dev/null +++ b/src/tools/mesh_extractor/ObjectDataHandler.cpp @@ -0,0 +1,21 @@ +#include "ObjectDataHandler.h" +#include "Chunk.h" +#include "ADT.h" +#include "ChunkedData.h" + +void ObjectDataHandler::ProcessMapChunk( MapChunk* chunk ) +{ + if (!Source->HasObjectData) + return; + // fuck it blizzard, why is this crap necessary? + int32 firstIndex = Source->ObjectData->GetFirstIndex("MCNK"); + if (firstIndex == -1) + return; + if (firstIndex + chunk->Index > Source->ObjectData->Chunks.size()) + return; + Chunk* ourChunk = Source->ObjectData->Chunks[firstIndex + chunk->Index]; + if (ourChunk->Length == 0) + return; + ChunkedData* subChunks = new ChunkedData(ourChunk->GetStream(), ourChunk->Length, 2); + ProcessInternal(subChunks); +} diff --git a/src/tools/mesh_extractor/ObjectDataHandler.h b/src/tools/mesh_extractor/ObjectDataHandler.h new file mode 100644 index 00000000000..834bf66bcfb --- /dev/null +++ b/src/tools/mesh_extractor/ObjectDataHandler.h @@ -0,0 +1,15 @@ +#ifndef ODATA_HNDL_H +#define ODATA_HNDL_H +#include "ADT.h" +#include "MapChunk.h" + +class ObjectDataHandler +{ +public: + ObjectDataHandler(ADT* _adt) : Source(_adt) {} + + void ProcessMapChunk(MapChunk* chunk); + virtual void ProcessInternal(ChunkedData* data) = 0; + ADT* Source; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp new file mode 100644 index 00000000000..070b9d70050 --- /dev/null +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -0,0 +1,37 @@ +#include "TileBuilder.h" +#include "Constants.h" + +TileBuilder::TileBuilder(std::string world, int x, int y) : _Geometry(NULL), World(world), X(x), Y(y), MapId(608) +{ + // Cell Size = TileSize / TileVoxelSize + // 1800 = TileVoxelSize + Config.cs = Constants::TileSize / 1800; + // Cell Height + Config.ch = 0.3f; + // Min Region Area = 6^2 + Config.minRegionArea = 36; + // Merge Region Area = 12^2 + Config.mergeRegionArea = 144; + Config.walkableSlopeAngle = 50.0f; + Config.detailSampleDist = 3.0f; + Config.detailSampleMaxError = 1.25f; + Config.walkableClimb = 1.0f / Config.ch; + Config.walkableHeight = 2.1f / Config.ch; + Config.walkableRadius = 0.6f / Config.cs; + Config.maxEdgeLen = Config.walkableRadius * 8; + Config.borderSize = Config.walkableRadius + 8; + Config.width = 1800; + Config.maxVertsPerPoly = 6; + Config.maxSimplificationError = 1.3f; +} + +void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax ) +{ + float origin[3] = Constants::Origin; + bmin = new float[3]; + bmax = new float[3]; + bmin[0] = origin[0] + (Constants::TileSize * X); + bmin[2] = origin[2] + (Constants::TileSize * Y); + bmax[0] = origin[0] + (Constants::TileSize * (X + 1)); + bmax[2] = origin[2] + (Constants::TileSize * (Y + 1)); +} \ No newline at end of file diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h new file mode 100644 index 00000000000..badb05295e5 --- /dev/null +++ b/src/tools/mesh_extractor/TileBuilder.h @@ -0,0 +1,22 @@ +#ifndef TILE_BUILD_H +#define TILE_BUILD_H +#include +#include "Recast.h" + +#include "Geometry.h" + +class TileBuilder +{ +public: + TileBuilder(std::string world, int x, int y); + void CalculateTileBounds(float*& bmin, float*& bmax); + uint8* Build(); + + std::string World; + int X; + int Y; + int MapId; + rcConfig Config; + Geometry* _Geometry; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp new file mode 100644 index 00000000000..03473eb0794 --- /dev/null +++ b/src/tools/mesh_extractor/Utils.cpp @@ -0,0 +1,163 @@ +#include "Utils.h" +#include "Constants.h" +#include +#include "g3d/Matrix4.h" + +const float Constants::TileSize = 533.0f + (1/3.0f); +const float Constants::MaxXY = 32.0f * Constants::TileSize; +const float Constants::ChunkSize = Constants::TileSize / 16.0f; +const float Constants::UnitSize = Constants::ChunkSize / 8.0f; +const float Constants::Origin[] = { -Constants::MaxXY, 0.0f, -Constants::MaxXY }; +const float Constants::PI = 3.1415926f; + +void Utils::Reverse(char word[]) +{ + int len = strlen(word); + for (int i = 0;i < len / 2; i++) + { + word[i] ^= word[len-i-1]; + word[len-i-1] ^= word[i]; + word[i] ^= word[len-i-1]; + } +} + +std::string Utils::ReadString( FILE* file ) +{ + std::string ret; + int i = 0; + while (true) + { + char b; + fread(&b, sizeof(char), 1, file); + if (b == 0) + break; + ret[i++] = b; + } + return ret; +} + +uint32 Utils::Size( FILE* file ) +{ + // store the old position + uint32 offset = ftell(file); + // Get file size + fseek(file, 0, SEEK_END); + uint32 size = ftell(file); + // reset back to the old position + fseek(file, offset, SEEK_SET); + return size; +} + +Vector3 Utils::ToRecast( Vector3 val ) +{ + return Vector3(-val.y, val.z, -val.x); +} + +std::string Utils::GetAdtPath( std::string world, int x, int y ) +{ + return "World\\Maps\\" + world + "\\" + world + "_" + Utils::ToString(x) + "_" + Utils::ToString(y) + ".adt"; +} + +std::string Utils::FixModelPath( std::string path ) +{ + std::string::size_type idx = path.rfind("."); + // Bizarre way of changing extension but... + if (idx != std::string::npos) + { + path[idx + 1] = "M"; + path[idx + 2] = "2"; + } + return path; +} + +G3D::Matrix4 Utils::RotationX(float angle) +{ + float _cos = cos(angle); + float _sin = sin(angle); + Matrix4 ret = G3D::Matrix4::identity(); + ret[2][2] = _cos; + ret[2][3] = _sin; + ret[3][2] = -_sin; + ret[3][3] = _cos; + return ret; +} + +G3D::Matrix4 Utils::GetTransformation( IDefinition def ) +{ + G3D::Matrix4 translation; + if (def.Position.x == 0.0f && def.Position.y == 0.0f && def.Position.z == 0.0f) + translation = G3D::Matrix4::identity(); + else + translation = G3D::Matrix4::translation(-(def.Position.z - Constants::MaxXY), + -(def.Position.x - Constants::MaxXY), def.Position.y); + + G3D::Matrix4 rotation = RotationX(ToRadians(def.Rotation.z)) * RotationY(ToRadians(def.Rotation.x)) * RotationZ(ToRadians(def.Rotation.y + 180)); + if (def.Scale() < 1.0f || def.Scale() > 1.0f) + return G3D::Matrix4::scale(def.Scale()) * rotation * translation; + return rotation * translation; +} + +G3D::Matrix4 Utils::RotationY( float angle ) +{ + float _cos = cos(angle); + float _sin = sin(angle); + Matrix4 ret = G3D::Matrix4::identity(); + ret[1][1] = _cos; + ret[1][3] = -_sin; + ret[3][1] = _sin; + ret[3][3] = _cos; + return ret; +} + +G3D::Matrix4 Utils::RotationZ( float angle ) +{ + float _cos = cos(angle); + float _sin = sin(angle); + Matrix4 ret = G3D::Matrix4::identity(); + ret[1][1] = _cos; + ret[1][2] = _sin; + ret[2][1] = -_sin; + ret[2][2] = _cos; + return ret; +} + +float Utils::ToRadians( float degrees ) +{ + return Constants::PI * degrees / 180.0f; +} + +Vector3 Utils::VectorTransform( Vector3 vec, G3D::Matrix matrix ) +{ + Vector3 ret; + ret.x = vec.x * matrix[1][1] + vec.y * matrix[2][1] + vec.z * matrix[3][1] + matrix[4][1]; + ret.y = vec.x * matrix[1][2] + vec.y * matrix[2][2] + vec.z * matrix[3][2] + matrix[4][2]; + ret.z = vec.x * matrix[1][3] + vec.y * matrix[2][3] + vec.z * matrix[3][3] + matrix[4][3]; + return ret; +} + +std::string Utils::GetPathBase( std::string path ) +{ + int lastIndex = path.find_last_of("."); + if (lastIndex != std::string::npos) + return path.substr(0, lastindex); + return path; +} + +Vector3 Vector3::Read( FILE* file ) +{ + Vector3 ret; + fread(&ret, sizeof(Vector3), 1, file); + return ret; +} + +Vector3 Utils::GetLiquidVert(G3D::Matrix4 transformation, Vector3 basePosition, float height, int x, int y) +{ + if (Utils::Distance(height, 0.0f) > 0.5f) + basePosition.z = 0.0f; + return Utils::VectorTransform(basePosition + Vector3(basePosition.x * Constants::UnitSize, basePosition.y * Constants::UnitSize, height), transformation); +} + +float Utils::Distance( float x, float y ) +{ + return sqrt(x*x + y*y); +} diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h new file mode 100644 index 00000000000..cda5f4c7cd8 --- /dev/null +++ b/src/tools/mesh_extractor/Utils.h @@ -0,0 +1,497 @@ +#ifndef UTILS_H +#define UTILS_H +#include +#include +#include + +#include "g3d/Matrix4.h" + +#include "Common.h" +#include "Constants.h" + +struct Vector3 +{ + Vector3() {} + Vector3(float X, float Y, float Z) : x(X), y(Y), z(Z) {} + float x; + float y; + float z; + Vector3 operator+(Vector3 right, Vector3 left) + { + return Vector3(right.x+left.x, right.y+left.y, right.z+left.z); + } + static Vector3 Read(FILE* file); +}; + +struct TilePos +{ + TilePos(int x, int y) : X(x), Y(y) {} + int X; + int Y; +}; + +template +struct Triangle +{ + Triangle(Constants::TriangleType type, T v0, T v1, T v2) : Type(type), V0(v0), V1(v1), V2(v2) {} + T V0; + T V1; + T V2; + Constants::TriangleType Type; +}; + +class MapChunkHeader +{ +public: + MapChunkHeader() {} + uint32 Flags; + uint32 IndexX; + uint32 IndexY; + uint32 Layers; + uint32 DoodadRefs; + uint32 OffsetMCVT; + uint32 OffsetMCNR; + uint32 OffsetMCLY; + uint32 OffsetMCRF; + uint32 OffsetMCAL; + uint32 SizeMCAL; + uint32 OffsetMCSH; + uint32 SizeMCSH; + uint32 AreaId; + uint32 MapObjectRefs; + uint32 Holes; + uint32* LowQualityTextureMap; + uint32 PredTex; + uint32 NumberEffectDoodad; + uint32 OffsetMCSE; + uint32 SoundEmitters; + uint32 OffsetMCLQ; + uint32 SizeMCLQ; + Vector3 Position; + uint32 OffsetMCCV; + + void Read(FILE* stream) + { + fread(&Flags, sizeof(uint32), 1, stream); + fread(&IndexX, sizeof(uint32), 1, stream); + fread(&IndexY, sizeof(uint32), 1, stream); + fread(&Layers, sizeof(uint32), 1, stream); + fread(&DoodadRefs, sizeof(uint32), 1, stream); + fread(&OffsetMCVT, sizeof(uint32), 1, stream); + fread(&OffsetMCNR, sizeof(uint32), 1, stream); + fread(&OffsetMCLY, sizeof(uint32), 1, stream); + fread(&OffsetMCRF, sizeof(uint32), 1, stream); + fread(&OffsetMCAL, sizeof(uint32), 1, stream); + fread(&SizeMCAL, sizeof(uint32), 1, stream); + fread(&OffsetMCSH, sizeof(uint32), 1, stream); + fread(&SizeMCSH, sizeof(uint32), 1, stream); + fread(&AreaId, sizeof(uint32), 1, stream); + fread(&MapObjectRefs, sizeof(uint32), 1, stream); + fread(&Holes, sizeof(uint32), 1, stream); + LowQualityTextureMap = new uint32[4]; + fread(LowQualityTextureMap, sizeof(uint32), 4, stream); + fread(&PredTex, sizeof(uint32), 1, stream); + fread(&NumberEffectDoodad, sizeof(uint32), 1, stream); + fread(&OffsetMCSE, sizeof(uint32), 1, stream); + fread(&SoundEmitters, sizeof(uint32), 1, stream); + fread(&OffsetMCLQ, sizeof(uint32), 1, stream); + fread(&SizeMCLQ, sizeof(uint32), 1, stream); + Position = Vector3::Read(stream); + fread(&OffsetMCCV, sizeof(uint32), 1, stream); + } +}; + +class MHDR +{ +public: + MHDR() {} + uint32 Flags; + uint32 OffsetMCIN; + uint32 OffsetMTEX; + uint32 OffsetMMDX; + uint32 OffsetMMID; + uint32 OffsetMWMO; + uint32 OffsetMWID; + uint32 OffsetMDDF; + uint32 OffsetMODF; + uint32 OffsetMFBO; + uint32 OffsetMH2O; + uint32 OffsetMTFX; + + void Read(FILE* stream) + { + fread(&Flags, sizeof(uint32), 1, stream); + fread(&OffsetMCIN, sizeof(uint32), 1, stream); + fread(&OffsetMTEX, sizeof(uint32), 1, stream); + fread(&OffsetMMDX, sizeof(uint32), 1, stream); + fread(&OffsetMMID, sizeof(uint32), 1, stream); + fread(&OffsetMWMO, sizeof(uint32), 1, stream); + fread(&OffsetMWID, sizeof(uint32), 1, stream); + fread(&OffsetMDDF, sizeof(uint32), 1, stream); + fread(&OffsetMODF, sizeof(uint32), 1, stream); + fread(&OffsetMFBO, sizeof(uint32), 1, stream); + fread(&OffsetMH2O, sizeof(uint32), 1, stream); + fread(&OffsetMTFX, sizeof(uint32), 1, stream); + } +}; + +class ModelHeader +{ +public: + char Magic[5]; + uint32 Version; + uint32 LengthModelName; + uint32 OffsetName; + uint32 ModelFlags; + uint32 CountGlobalSequences; + uint32 OffsetGlobalSequences; + uint32 CountAnimations; + uint32 OffsetAnimations; + uint32 CountAnimationLookup; + uint32 OffsetAnimationLookup; + uint32 CountBones; + uint32 OffsetBones; + uint32 CountKeyBoneLookup; + uint32 OffsetKeyBoneLookup; + uint32 CountVertices; + uint32 OffsetVertices; + uint32 CountViews; + uint32 CountColors; + uint32 OffsetColors; + uint32 CountTextures; + uint32 OffsetTextures; + uint32 CountTransparency; + uint32 OffsetTransparency; + uint32 CountUvAnimation; + uint32 OffsetUvAnimation; + uint32 CountTexReplace; + uint32 OffsetTexReplace; + uint32 CountRenderFlags; + uint32 OffsetRenderFlags; + uint32 CountBoneLookup; + uint32 OffsetBoneLookup; + uint32 CountTexLookup; + uint32 OffsetTexLookup; + uint32 CountTexUnits; + uint32 OffsetTexUnits; + uint32 CountTransLookup; + uint32 OffsetTransLookup; + uint32 CountUvAnimLookup; + uint32 OffsetUvAnimLookup; + Vector3 VertexBox[2]; + float VertexRadius; + Vector3 BoundingBox[2]; + float BoundingRadius; + uint32 CountBoundingTriangles; + uint32 OffsetBoundingTriangles; + uint32 CountBoundingVertices; + uint32 OffsetBoundingVertices; + uint32 CountBoundingNormals; + uint32 OffsetBoundingNormals; + + void Read(FILE* stream) + { + fread(&Magic, sizeof(char), 4, stream); + Magic[4] = '\0'; // null-terminate it. + fread(&Version, sizeof(uint32), 1, stream); + fread(&LengthModelName, sizeof(uint32), 1, stream); + fread(&OffsetName, sizeof(uint32), 1, stream); + fread(&ModelFlags, sizeof(uint32), 1, stream); + fread(&CountGlobalSequences, sizeof(uint32), 1, stream); + fread(&OffsetGlobalSequences, sizeof(uint32), 1, stream); + fread(&CountAnimations, sizeof(uint32), 1, stream); + fread(&OffsetAnimations, sizeof(uint32), 1, stream); + fread(&CountAnimationLookup, sizeof(uint32), 1, stream); + fread(&OffsetAnimationLookup, sizeof(uint32), 1, stream); + fread(&CountBones, sizeof(uint32), 1, stream); + fread(&OffsetBones, sizeof(uint32), 1, stream); + fread(&CountKeyBoneLookup, sizeof(uint32), 1, stream); + fread(&OffsetKeyBoneLookup, sizeof(uint32), 1, stream); + fread(&CountVertices, sizeof(uint32), 1, stream); + fread(&OffsetVertices, sizeof(uint32), 1, stream); + fread(&CountViews, sizeof(uint32), 1, stream); + fread(&CountColors, sizeof(uint32), 1, stream); + fread(&OffsetColors, sizeof(uint32), 1, stream); + fread(&CountTextures, sizeof(uint32), 1, stream); + fread(&OffsetTextures, sizeof(uint32), 1, stream); + fread(&CountTransparency, sizeof(uint32), 1, stream); + fread(&OffsetTransparency, sizeof(uint32), 1, stream); + fread(&CountUvAnimation, sizeof(uint32), 1, stream); + fread(&OffsetUvAnimation, sizeof(uint32), 1, stream); + fread(&CountTexReplace, sizeof(uint32), 1, stream); + fread(&OffsetTexReplace, sizeof(uint32), 1, stream); + fread(&CountRenderFlags, sizeof(uint32), 1, stream); + fread(&OffsetRenderFlags, sizeof(uint32), 1, stream); + fread(&CountBoneLookup, sizeof(uint32), 1, stream); + fread(&OffsetBoneLookup, sizeof(uint32), 1, stream); + fread(&CountTexLookup, sizeof(uint32), 1, stream); + fread(&OffsetTexLookup, sizeof(uint32), 1, stream); + fread(&CountTexUnits, sizeof(uint32), 1, stream); + fread(&OffsetTexUnits, sizeof(uint32), 1, stream); + fread(&CountTransLookup, sizeof(uint32), 1, stream); + fread(&OffsetTransLookup, sizeof(uint32), 1, stream); + fread(&CountUvAnimLookup, sizeof(uint32), 1, stream); + fread(&OffsetUvAnimLookup, sizeof(uint32), 1, stream); + fread(&CountColors, sizeof(uint32), 1, stream); + fread(&OffsetColors, sizeof(uint32), 1, stream); + fread(&CountTextures, sizeof(uint32), 1, stream); + fread(&OffsetTextures, sizeof(uint32), 1, stream); + fread(&CountTransparency, sizeof(uint32), 1, stream); + fread(&OffsetTransparency, sizeof(uint32), 1, stream); + fread(&CountUvAnimation, sizeof(uint32), 1, stream); + fread(&OffsetUvAnimation, sizeof(uint32), 1, stream); + fread(&CountTexReplace, sizeof(uint32), 1, stream); + fread(&OffsetTexReplace, sizeof(uint32), 1, stream); + VertexBox[0] = Vector3::Read(stream); + VertexBox[1] = Vector3::Read(stream); + fread(&VertexRadius, sizeof(float), 1, stream); + BoundingBox[0] = Vector3::Read(stream); + BoundingBox[1] = Vector3::Read(stream); + fread(&BoundingRadius, sizeof(float), 1, stream); + fread(&CountBoundingTriangles, sizeof(uint32), 1, stream); + fread(&OffsetBoundingTriangles, sizeof(uint32), 1, stream); + fread(&CountBoundingVertices, sizeof(uint32), 1, stream); + fread(&OffsetBoundingVertices, sizeof(uint32), 1, stream); + fread(&CountBoundingNormals, sizeof(uint32), 1, stream); + fread(&OffsetBoundingNormals, sizeof(uint32), 1, stream); + } +}; + +class WorldModelHeader +{ +public: + WorldModelHeader() {} + uint32 CountMaterials; + uint32 CountGroups; + uint32 CountPortals; + uint32 CountLights; + uint32 CountModels; + uint32 CountDoodads; + uint32 CountSets; + uint32 AmbientColorUnk; + uint32 WmoId; + Vector3 BoundingBox[2]; + uint32 LiquidTypeRelated; + + static WorldModelHeader Read(FILE* stream) + { + WorldModelHeader ret; + fread(&ret.CountMaterials, sizeof(uint32), 1, stream); + fread(&ret.CountGroups, sizeof(uint32), 1, stream); + fread(&ret.CountPortals, sizeof(uint32), 1, stream); + fread(&ret.CountLights, sizeof(uint32), 1, stream); + fread(&ret.CountModels, sizeof(uint32), 1, stream); + fread(&ret.CountDoodads, sizeof(uint32), 1, stream); + fread(&ret.CountSets, sizeof(uint32), 1, stream); + fread(&ret.AmbientColorUnk, sizeof(uint32), 1, stream); + fread(&ret.WmoId, sizeof(uint32), 1, stream); + ret.BoundingBox[0] = Vector3::Read(stream); + ret.BoundingBox[1] = Vector3::Read(stream); + fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream); + return ret; + } +}; + +class DoodadInstance +{ +public: + DoodadInstance() {} + uint32 FileOffset; + std::string File; + Vector3 Position; + float QuatW; + float QuatX; + float QuatY; + float QuatZ; + float Scale; + uint32 LightColor; + + static DoodadInstance Read(FILE* stream) + { + DoodadInstance ret; + fread(&ret.FileOffset, sizeof(uint32), 1, stream); + ret.Position = Vector3::Read(stream); + fread(&ret.QuatW, sizeof(float), 1, stream); + fread(&ret.QuatX, sizeof(float), 1, stream); + fread(&ret.QuatY, sizeof(float), 1, stream); + fread(&ret.QuatZ, sizeof(float), 1, stream); + fread(&ret.Scale, sizeof(float), 1, stream); + fread(&ret.LightColor, sizeof(uint32), 1, stream); + return ret; + } +}; + +class DoodadSet +{ +public: + DoodadSet() {} + std::string Name; + uint32 FirstInstanceIndex; + uint32 CountInstances; + uint32 UnknownZero; + + static DoodadSet Read(FILE* stream) + { + DoodadSet ret; + char name[21]; + fread(&name, sizeof(char), 20, stream); + name[20] = '\0'; + ret.Name = name; + fread(&ret.FirstInstanceIndex, sizeof(uint32), 1, stream); + fread(&ret.CountInstances, sizeof(uint32), 1, stream); + fread(&ret.UnknownZero, sizeof(uint32), 1, stream); + return ret; + } +} + +class LiquidHeader +{ +public: + LiquidHeader() {} + uint32 CountXVertices; + uint32 CountYVertices; + uint32 Width; + uint32 Height; + Vector3 BaseLocation; + uint16 MaterialId; + + static LiquidHeader Read(FILE* stream) + { + LiquidHeader ret; + fread(&ret.CountXVertices, sizeof(uint32), 1, stream); + fread(&ret.CountYVertices, sizeof(uint32), 1, stream); + fread(&ret.Width, sizeof(uint32), 1, stream); + fread(&ret.Height, sizeof(uint32), 1, stream); + ret.BaseLocation = Vector3::Read(stream); + fread(&ret.MaterialId, sizeof(uint16), 1, stream); + return ret; + } +}; + +class LiquidData +{ +public: + LiquidData() {} + float** HeightMap; + uint8** RenderFlags; + + bool ShouldRender(int x, int y) + { + return RenderFlags[x][y] != 0x0F; + } + + public static LiquidData Read(FILE* stream, LiquidHeader header) + { + LiquidData ret; + ret.HeightMap = new float*[header.CountXVertices]; + for (int i = 0; i < header.CountXVertices; ++i) + ret.HeightMap[i] = new float[header.CountYVertices]; + + ret.RenderFlags = new uint8*[header.Width]; + for (int i = 0; i < header.Width; ++i) + ret.RenderFlags[i] = new uint8[header.Height]; + + for (int y = 0; y < header.CountYVertices; y++) + { + for (int x = 0; x < header.CountXVertices; x++) + { + uint32 discard; + fread(&discard, sizeof(uint32), 1, stream); + float tmp; + fread(&tmp, sizeof(float), 1, stream); + ret.HeightMap[x][y] = tmp; + } + } + + for (int y = 0; y < header.Height; y++) + { + for (int x = 0; x < header.Width; x++) + { + uint8 tmp; + fread(&tmp, sizeof(uint8), 1, stream); + ret.RenderFlags[x][y] = tmp; + } + } + + return ret; + } +}; + +class H2ORenderMask +{ +public: + H2ORenderMask() {} + uint8 Mask[8]; + + bool ShouldRender(int x, int y) + { + return (Mask[y] >> x & 1) != 0; + } + + static H2ORenderMask Read(FILE* stream) + { + H2ORenderMask ret; + fread(&ret.Mask, sizeof(uint8), 8, stream); + return ret; + } +}; + +class MCNKLiquidData +{ +public: + MCNKLiquidData() {} + const float MaxStandableHeight = 1.5f; + + float** Heights; + H2ORenderMask* Mask; + + bool IsWater(int x, int y, float height) + { + if (!Heights || !Mask) + return false; + if (!Mask->ShouldRender(x, y)) + return false; + float diff = Heights[x][y] - height; + if (diff > MaxStandableHeight) + return true; + return false; + } +}; + +// Dummy class to act as an interface. +class IDefinition +{ +public: + Vector3 Position; + Vector3 Rotation; + virtual float Scale() = 0; +}; + +class Utils +{ +public: + static void Reverse(char word[]); + static std::string ReadString(FILE* file); + static uint32 Size(FILE* file); + static Vector3 ToRecast( Vector3 val ); + static std::string GetAdtPath(std::string world, int x, int y); + static std::string FixModelPath(std::string path); + static G3D::Matrix4 GetTransformation(IDefinition def); + /// They say its better to declare template functions in the header files. + template + static std::string ToString(T val) + { + std::stringstream ss; + ss << val; + return ss.str(); + } + static G3D::Matrix4 RotationX(float angle); + static G3D::Matrix4 RotationY(float angle); + static G3D::Matrix4 RotationZ(float angle); + static float ToRadians(float degrees); + static Vector3 VectorTransform(Vector3 vec, G3D::Matrix matrix); + static std::string GetPathBase(std::string path); + static Vector3 GetLiquidVert(G3D::Matrix4 transformation, Vector3 basePosition, float height, int x, int y); + static float Distance(float x, float y); +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/WDT.cpp b/src/tools/mesh_extractor/WDT.cpp new file mode 100644 index 00000000000..c06d8ac9677 --- /dev/null +++ b/src/tools/mesh_extractor/WDT.cpp @@ -0,0 +1,55 @@ +#include "WDT.h" +#include "Chunk.h" +#include "ChunkedData.h" +#include "Utils.h" +#include "WorldModelHandler.h" + +WDT::WDT(std::string file) : IsValid(false), IsGlobalModel(false) +{ + Data = new ChunkedData(file, 2); + ReadTileTable(); + ReadGlobalModel(); +} + +void WDT::ReadGlobalModel() +{ + Chunk* fileChunk = Data->GetChunkByName("MWMO"); + Chunk* defChunk = Data->GetChunkByName("MODF"); + if (!fileChunk || !defChunk) + return; + + IsGlobalModel = true; + ModelDefinition = WorldModelDefinition::Read(defChunk->GetStream()); + ModelFile = Utils::ReadString(fileChunk->GetStream()); +} + +void WDT::ReadTileTable() +{ + Chunk* chunk = Data->GetChunkByName("MAIN"); + if (!chunk) + return; + IsValid = true; + FILE* stream = chunk->GetStream(); + for (int y = 0; y < 64; ++y) + { + for (int x = 0; x < 64; ++x) + { + const uint32 hasTileFlag = 0x1; + uint32 flags; + uint32 discard; + fread(&flags, sizeof(uint32), 1, stream); + fread(&discard, sizeof(uint32), 1, stream); + if (flags & hasTileFlag) + TileTable.push_back(TilePos(x, y)); + + } + } +} + +bool WDT::HasTile( int x, int y ) +{ + for (std::vector::iterator itr = TileTable.begin(); itr != TileTable.end(); ++itr) + if (itr->X == x && itr->Y == y) + return true; + return false; +} diff --git a/src/tools/mesh_extractor/WDT.h b/src/tools/mesh_extractor/WDT.h new file mode 100644 index 00000000000..a12aa65218b --- /dev/null +++ b/src/tools/mesh_extractor/WDT.h @@ -0,0 +1,27 @@ +#ifndef WDT_H +#define WDT_H +#include +#include + +#include "ChunkedData.h" +#include "WorldModelHandler.h" +#include "Utils.h" + +class WDT +{ +public: + WDT(std::string file); + + ChunkedData* Data; + std::vector TileTable; + bool IsGlobalModel; + bool IsValid; + std::string ModelFile; + WorldModelDefinition ModelDefinition; + bool HasTile(int x, int y); +private: + void ReadGlobalModel(); + void ReadTileTable(); +}; + +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/WorldModelGroup.cpp b/src/tools/mesh_extractor/WorldModelGroup.cpp new file mode 100644 index 00000000000..308c7ff7b86 --- /dev/null +++ b/src/tools/mesh_extractor/WorldModelGroup.cpp @@ -0,0 +1,122 @@ +#include "WorldModelGroup.h" +#include "ChunkedData.h" +#include "Chunk.h" + +WorldModelGroup::WorldModelGroup( std::string path, int groupIndex ) : GroupIndex(groupIndex), IsBad(false) +{ + Data = new ChunkedData(path); + if (!Data->Stream) + { + IsBad = true; + return; + } + Chunk* mainChunk = Data->GetChunkByName("MOGP"); + int32 firstSub = mainChunk->FindSubChunkOffset("MOPY"); + if (firstSub == -1) + return; + FILE* stream = mainChunk->GetStream(); + fseek(stream, firstSub, SEEK_SET); + SubData = new ChunkedData(stream, mainChunk->Length - firstSub); + + ReadBoundingBox(); + ReadMaterials(); + ReadTriangles(); + ReadVertices(); + ReadNormals(); + ReadLiquid(); +} + +void WorldModelGroup::ReadNormals() +{ + Chunk* chunk = SubData->GetChunkByName("MONR"); + if (!chunk) + return; + + uint32 normalCount = chunk->Length / 12; + Assert(normalCount == Vertices.size(), "normalCount is different than the Vertices count"); + Normals.reserve(normalCount); + FILE* stream = chunk->GetStream(); + for (int i = 0; i < normalCount; i++) + Normals[i] = Vector3::Read(stream); +} + +void WorldModelGroup::ReadLiquid() +{ + Chunk* chunk = SubData->GetChunkByName("MLIQ"); + if (!chunk) + return; + + HasLiquidData = true; + FILE* stream = chunk->GetStream(); + LiquidDataHeader = LiquidHeader.Read(stream); + LiquidDataGeometry = LiquidData.Read(stream, LiquidDataHeader); +} + +void WorldModelGroup::ReadVertices() +{ + Chunk* chunk = SubData->GetChunkByName("MOVT"); + if (!chunk) + return; + + uint32 verticeCount = chunk.Length / 12; + Vertices.reserve(verticeCount); + FILE* stream = chunk->GetStream(); + for (int i = 0; i < verticeCount; i++) + Vertices.push_back(Vector3::Read(stream)); +} + +void WorldModelGroup::ReadTriangles() +{ + Chunk* chunk = SubData->GetChunkByName("MOVI"); + if (!chunk) + return; + + uint32 triangleCount = chunk.Length / 6; + Assert(triangleCount == TriangleFlags.size(), "triangleCount != TriangleFlags.size()"); + FILE* stream = chunk.GetStream(); + Triangles.reserve(triangleCount); + for (int i = 0; i < triangleCount; i++) + { + uint16 v0; + uint16 v1; + uint16 v2; + fread(&v0, sizeof(uint16), 1, stream); + fread(&v1, sizeof(uint16), 1, stream); + fread(&v2, sizeof(uint16), 1, stream); + Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_WMO, v0, v1, v2)); + } +} + +void WorldModelGroup::ReadMaterials() +{ + Chunk* chunk = SubData->GetChunkByName("MOPY"); + if (!chunk) + return; + + FILE* stream = chunk->GetStream(); + uint32 triangleCount = chunk.Length / 2; + TriangleFlags.reserve(triangleCount); + TriangleMaterials.reserve(triangleCount); + for (int i = 0; i < triangleCount; i++) + { + uint8 tmp; + fread(&tmp, sizeof(uint8), 1, stream); + TriangleFlags.push_back(tmp); + // Read again for material. + fread(&tmp, sizeof(uint8), 1, stream); + TriangleMaterials.push_back(tmp); + } +} + +void WorldModelGroup::ReadBoundingBox() +{ + Chunk* chunk = Data->GetChunkByName("MOGP"); + if (!chunk) + return; + + FILE* stream = chunk->GetStream(); + fseek(stream, 8, SEEK_CUR): + fread(&Flags, sizeof(uint32), 1, stream); + BoundingBox[0] = Vector3::Read(stream); + BoundingBox[1] = Vector3::Read(stream); +} diff --git a/src/tools/mesh_extractor/WorldModelGroup.h b/src/tools/mesh_extractor/WorldModelGroup.h new file mode 100644 index 00000000000..1dc754d0221 --- /dev/null +++ b/src/tools/mesh_extractor/WorldModelGroup.h @@ -0,0 +1,33 @@ +#ifndef WMOGROUP_H +#define WMOGROUP_H +#include "ChunkedData.h" +#include "Utils.h" + +class WorldModelGroup +{ +public: + WorldModelGroup(std::string path, int groupIndex); + ChunkedData* Data; + ChunkedData* SubData; + int GroupIndex; + Vector3 BoundingBox[2]; + uint32 Flags; + std::vector TriangleFlags; + std::vector TriangleMaterials; + std::vector > Triangles; + std::vector Vertices; + std::vector Normals; + + bool HasLiquidData; + bool IsBad; + LiquidHeader LiquidDataHeader; + LiquidData LiquidDataGeometry; +private: + void ReadNormals(); + void ReadLiquid(); + void ReadVertices(); + void ReadTriangles(); + void ReadMaterials(); + void ReadBoundingBox(); +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp new file mode 100644 index 00000000000..e895e2bfde8 --- /dev/null +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -0,0 +1,190 @@ +#include "WorldModelHandler.h" +#include "Chunk.h" +#include "Cache.h" +#include "Common.h" +#include "g3d/Matrix4.h" +#include + +WorldModelDefinition WorldModelDefinition::Read( FILE* file ) +{ + WorldModelDefinition ret; + fread(&ret.MwidIndex, sizeof(uint32), 1, file); + fread(&ret.UniqueId, sizeof(uint32), 1, file); + ret.Position = Vector3::Read(file); + ret.Rotation = Vector3::Read(file); + ret.UpperExtents = Vector3::Read(file); + ret.LowerExtents = Vector3::Read(file); + fread(&ret.Flags, sizeof(uint16), 1, file); + fread(&ret.DooadSet, sizeof(uint16), 1, file); + uint32 discard; + fread(&discard, sizeof(uint32), 1, file); + return ret; +} + + +WorldModelHandler::WorldModelHandler( ADT* adt ) : ObjectDataHandler(adt) +{ + if (!adt->HasObjectData) + return; + ReadModelPaths(); + ReadDefinitions(); +} + +void WorldModelHandler::ProcessInternal( ChunkedData* subChunks ) +{ + if (!IsSane()) + return; + Chunk* wmoReferencesChunk = subChunks->GetChunkByName("MCRW"); + if (!wmoReferencesChunk) + return; + FILE* stream = wmoReferencesChunk->GetStream(); + uint32 refCount = wmoReferencesChunk->Length / 4; + for (int i = 0; i < refCount; i++) + { + int32 index; + fread(&index, sizeof(int32), 1, stream); + + if (index < 0 || index >= _definitions->size()) + continue; + + WorldModelDefinition wmo = (*_definitions)[index]; + + if (_drawn.find(wmo.UniqueId) != _drawn.end()) + continue; + _drawn.insert(wmo.UniqueId); + + if (wmo.MwidIndex >= _paths->size()) + continue; + + std::string path = _paths[(int) wmo.MwidIndex]; + WorldModelRoot* model = Cache->WorldModelCache.Get(path); + if (!model) + { + model = new WorldModelRoot(path); + Cache->WorldModelCache.Insert(path, model); + } + + Vertices.reserve(1000); + Triangles.reserve(1000); + + InsertModelGeometry(Vertices, Triangles, wmo, model); + } +} + +void WorldModelHandler::InsertModelGeometry( std::vector verts, std::vector > tris, WorldModelDefinition& def, WorldModelRoot* root ) +{ + G3D::Matrix4 transformation = Utils::GetTransformation(); + for (std::vector::iterator group = root->Groups.begin(); group != root->Groups.end(); ++group) + { + uint32 vertOffset = verts.size(); + for (std::vector::iterator itr2 = group->Vertices.begin(); itr2 != group->Vertices.end(); ++itr2) + verts.push_back(Utils::VectorTransform(*itr2, transformation)); + + for (int i = 0; i < group->Triangles.size(); ++i) + { + // only include collidable tris + if ((group->TriangleFlags[i] & 0x04) != 0 && group->TriangleMaterials[i] != 0xFF) + continue; + Triangle tri = group->Triangles[i]; + tris.push_back(Triangle(Constants::TRIANGLE_TYPE_WMO, tri.V0 + vertOffset, tri.V1 + vertOffset, tri.V2 + vertOffset)); + } + } + + if (def.DoodadSet >= 0 && def.DoodadSet < root->DoodadSets.size()) + { + DoodadSet set = root->DoodadSets[def.DoodadSet]; + std::vector instances = new std::vector; + instances.reserve(set.CountInstances); + for (uint32 i = set.FirstInstanceIndex; i < (set.CountInstances + set.FirstInstanceIndex); i++) + { + if (i >= root->DoodadInstances.size()) + break; + instances.push_back(root->DoodadInstances[i]); + } + + for (std::vector::iterator instance = instances.begin(); instance != instances.end(); ++instance) + { + Model* model = Cache.ModelCache.Get(instance->File); + if (!model) + { + model = new Model(instance->File); + Cache.ModelCache.Insert(instance->File, model); + } + + if (!model.IsCollidable) + continue; + G3D::Matrix4 doodadTransformation = Utils::GetWmoDoodadTransformation(instance, def); + int vertOffset = verts.size(); + for (std::vector::iterator itr2 = model->Vertices.begin(); itr2 != model->Vertices.end(); ++itr2) + verts.push_back(Utils::VectorTransform(*itr2, doodadTransformation)); + for (std::vector >::iterator itr2 = model->Triangles.begin(); itr2 != model->Triangles.end(); ++itr2) + tris.push_back(Triangle(Constants::TRIANGLE_TYPE_WMO, itr2->V0 + vertOffset, itr2->V1 + vertOffset, itr2->V2 + vertOffset)); + } + + for (std::vector::iterator group = root->Groups.begin(); group != root->Groups.end(); ++group) + { + if (!group->HasLiquidData) + continue; + + for (int y = 0; y < group->LiquidDataHeader.Height; y++) + { + for (int x = 0; x < group->LiquidDataHeader.Width; x++) + { + if (!group->LiquidDataGeometry.ShouldRender(x, y)) + continue; + + uint32 vertOffset = verts.size(); + verts.push_back(Utils::GetLiquidVert(transformation, group->LiquidDataHeader.BaseLocation, + group->LiquidDataGeometry.HeightMap[x][y], x, y)); + verts.push_back(Utils::GetLiquidVert(transformation, group->LiquidDataHeader.BaseLocation, + group->LiquidDataGeometry.HeightMap[x + 1][y], x + 1, y)); + verts.push_back(Utils::GetLiquidVert(transformation, group->LiquidDataHeader.BaseLocation, + group->LiquidDataGeometry.HeightMap[x][y + 1], x, y + 1)); + verts.push_back(Utils::GetLiquidVert(transformation, group->LiquidDataHeader.BaseLocation, + group->LiquidDataGeometry.HeightMap[x + 1][y + 1], x + 1, y + 1)); + + tris.push_back(Triangle(Constants::TRIANGLE_TYPE_WATER, vertOffset, vertOffset + 2, vertOffset + 1)); + tris.push_back(new Triangle(Constants::TRIANGLE_TYPE_WATER, vertOffset + 2, vertOffset + 3, vertOffset + 1)); + + } + } + } + } +} + +void WorldModelHandler::ReadDefinitions() +{ + Chunk* chunk = Source->ObjectData->GetChunkByName("MODF"); + if (!chunk) + return; + + const int32 definitionSize = 64; + uint32 definitionCount = chunk.Length / definitionSize; + _definitions = new new std::vector; + _definitions->reserve(definitionCount); + FILE* stream = chunk->GetStream(); + for (int i = 0; i < definitionCount; i++) + _definitions->push_back(WorldModelDefinition::Read(stream)); +} + +void WorldModelHandler::ReadModelPaths() +{ + Chunk* mwid = Source->ObjectData->GetChunkByName("MWID"); + Chunk* mwmo = Source->ObjectData->GetChunkByName("MWMO"); + if (!mwid || !mwmo) + return; + + uint32 paths = mwid.Length / 4; + _paths = new std::vector; + _paths->reserve(paths); + for (int i = 0; i < paths; i++) + { + FILE* stream = mwid->GetStream(); + fseek(stream, i * 4, SEEK_CUR); + uint32 offset; + fread(&offset, sizeof(uint32), 1, stream); + FILE* dataStream = mwmo->GetStream(); + fseek(dataStream, offset + mwmo->Offset, SEEK_SET); + _paths->push_back(Utils::ReadString(dataStream)); + } +} diff --git a/src/tools/mesh_extractor/WorldModelHandler.h b/src/tools/mesh_extractor/WorldModelHandler.h new file mode 100644 index 00000000000..2236339de9d --- /dev/null +++ b/src/tools/mesh_extractor/WorldModelHandler.h @@ -0,0 +1,42 @@ +#ifndef WMODEL_HNDL_H +#define WMODEL_HNDL_H +#include "Common.h" +#include "Utils.h" +#include "ObjectDataHandler.h" +#include "ADT.h" + +#include +#include + +struct WorldModelDefinition : IDefinition +{ + WorldModelDefinition() {} + uint32 MwidIndex; + uint32 UniqueId; + Vector3 UpperExtents; + Vector3 LowerExtents; + uint16 Flags; + uint16 DoodadSet; + float Scale() { return 1.0f; } + static WorldModelDefinition Read(FILE* file); +}; + +class WorldModelHandler : public ObjectDataHandler +{ +public: + WorldModelHandler(ADT* adt); + + std::vector Vertices; + std::vector > Triangles; + bool IsSane() { return _definitions && _paths; } + void InsertModelGeometry(std::vector verts, std::vector > tris, WorldModelDefinition& def, WorldModelRoot* root); +protected: + void ProcessInternal(ChunkedData* data); +private: + void ReadDefinitions(); + void ReadModelPaths(); + std::set _drawn; + std::vector* _definitions; + std::vector* _paths; +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/WorldModelRoot.cpp b/src/tools/mesh_extractor/WorldModelRoot.cpp new file mode 100644 index 00000000000..9764e339242 --- /dev/null +++ b/src/tools/mesh_extractor/WorldModelRoot.cpp @@ -0,0 +1,74 @@ +#include "WorldModelRoot.h" +#include "ChunkedData.h" +#include "Utils.h" + +WorldModelRoot::WorldModelRoot( std::string path ) +{ + Data = new ChunkedData(path); + Path = path; + ReadHeader(); + ReadGroups(); + ReadDoodadInstances(); + ReadDoodadSets(); +} + +void WorldModelRoot::ReadGroups() +{ + std::string pathBase = Utils::GetPathBase(Path); + Groups.reserve(Header.CountGroups); + for (int i = 0; i < Header.CountGroups; i++) + { + char name[200]; + sprintf(name, "%s_%03u.wmo", pathBase.c_str(), i); + WorldModelGroup group(name, i); + if (!group.IsBad) + Groups.push_back(group); + } +} + +void WorldModelRoot::ReadDoodadSets() +{ + Chunk* chunk = Data->GetChunkByName("MODS"); + if (!chunk) + return; + + FILE* stream = chunk->GetStream(); + Assert(chunk.Length / 32 == Header.CountSets, "chunk.Length / 32 == Header.CountSets"); + DoodadSets.reserve(Header.CountSets); + for (int i = 0; i < Header.CountSets; i++) + DoodadSets.push_back(DoodadSet::Read(stream)); +} + +void WorldModelRoot::ReadDoodadInstances() +{ + Chunk* chunk = Data->GetChunkByName("MODD"); + Chunk* nameChunk = Data->GetChunkByName("MODN"); + if (!chunk || !nameChunk) + return; + + const uint32 instanceSize = 40; + uint32 countInstances = chunk->Length / instanceSize; + DoodadInstances.reserve(countInstances); + for (int i = 0; i < countInstances; i++) + { + FILE* stream = chunk->GetStream(); + fseek(stream, instanceSize * i, SEEK_CUR); + DoodadInstance instance = DoodadInstance::Read(stream); + FILE* nameStream = nameChunk->GetStream(); + if (instance.FileOffset >= nameChunk->Length) + continue; + fseek(nameStream, instance.FileOffset, SEEK_CUR); + instance.File = Utils::ReadString(nameStream); + DoodadInstances.push_back(instance); + } +} + +void WorldModelRoot::ReadHeader() +{ + Chunk* chunk = Data->GetChunkByName("MOHD"); + if (!chunk) + return; + + FILE* stream = chunk->GetStream(); + Header = WorldModelHeader::Read(stream); +} diff --git a/src/tools/mesh_extractor/WorldModelRoot.h b/src/tools/mesh_extractor/WorldModelRoot.h new file mode 100644 index 00000000000..c06ff3d5d2b --- /dev/null +++ b/src/tools/mesh_extractor/WorldModelRoot.h @@ -0,0 +1,26 @@ +#ifndef WMOROOT_H +#define WMOROOT_H +#include +#include + +#include "ChunkedData.h" +#include "Utils.h" +#include "WorldModelGroup.h" + +class WorldModelRoot +{ +public: + WorldModelRoot(std::string path); + std::string Path; + ChunkedData* Data; + WorldModelHeader Header; + std::vector DoodadInstances; + std::vector DoodadSets; + std::vector Groups; +private: + void ReadGroups(); + void ReadDoodadSets(); + void ReadDoodadInstances(); + void ReadHeader(); +}; +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/readme b/src/tools/mesh_extractor/readme new file mode 100644 index 00000000000..85cd7cfc975 --- /dev/null +++ b/src/tools/mesh_extractor/readme @@ -0,0 +1,6 @@ +Experimental mesh extractor. +Original work in C# by stschake +Thanks to: +Subv +~ +For helping in the porting to C++ \ No newline at end of file -- cgit v1.2.3 From ad0cd9f40acff1ff6d7571426b4acb1ea675d7a6 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 07:59:22 -0500 Subject: Tools: Made more updates to the MeshExtractor --- src/tools/mesh_extractor/ADT.h | 10 ++-- src/tools/mesh_extractor/LiquidHandler.cpp | 96 +++++++++++++++++++++++++++++- src/tools/mesh_extractor/LiquidHandler.h | 3 + src/tools/mesh_extractor/MapChunk.cpp | 8 +-- src/tools/mesh_extractor/MapChunk.h | 2 +- src/tools/mesh_extractor/Utils.cpp | 11 ++++ src/tools/mesh_extractor/Utils.h | 71 ++++++++++++++++++++-- 7 files changed, 186 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ADT.h b/src/tools/mesh_extractor/ADT.h index 18b811a4e4c..43984d0902c 100644 --- a/src/tools/mesh_extractor/ADT.h +++ b/src/tools/mesh_extractor/ADT.h @@ -4,17 +4,19 @@ #include "MapChunk.h" #include "DoodadHandler.h" #include "WorldModelHandler.h" +#include "LiquidHandler.h" class ADT { public: - ADT(); - ~ADT() { delete[] MapChunks; delete ObjectData; delete Data; } + ADT(std::string file); + ~ADT(); + + void Read(); ChunkedData* ObjectData; ChunkedData* Data; - // This here is not a pointer, is an array of objects ( made this way to allow the dynamic allocation ) - MapChunk* MapChunks; + std::vector MapChunks; MHDR Header; // Can we dispose of this? bool HasObjectData; diff --git a/src/tools/mesh_extractor/LiquidHandler.cpp b/src/tools/mesh_extractor/LiquidHandler.cpp index 5924c693196..3217bb2cbc6 100644 --- a/src/tools/mesh_extractor/LiquidHandler.cpp +++ b/src/tools/mesh_extractor/LiquidHandler.cpp @@ -1 +1,95 @@ -#include "LiquidHandler.h" \ No newline at end of file +#include "LiquidHandler.h" +#include "Utils.h" + +LiquidHandler::LiquidHandler( ADT* adt ) : Source(adt) +{ + HandleNewLiquid(); +} + +void LiquidHandler::HandleNewLiquid() +{ + Chunk* chunk = Source->Data->GetChunkByName("MH2O"); + if (!chunk) + return; + + Vertices.reserve(1000); + Triangles.reserve(1000); + + FILE* stream = chunk->GetStream(); + H2OHeader header[256]; + MCNKData.reserve(256); + for (int i = 0; i < 256; i++) + header[i] = H2OHeader::Read(stream); + + for (int i = 0; i < 256; i++) + { + H2OHeader h = header[i]; + if (h.LayerCount == 0) + continue; + fseek(stream, chunk->Offset + h.OffsetInformation, SEEK_SET); + H2OInformation information = H2OInformation::Read(stream); + + float** heights = new float*[9]; + for (int i = 0; i < 9; ++i) + heights[i] = new float[9]; + + H2ORenderMask renderMask; + if (information.LiquidType != 2) + { + fseek(stream, chunk->Offset + h.OffsetRender, SEEK_SET); + renderMask = H2ORenderMask::Read(stream); + if ((Utils::IsAllZero(renderMask.Mask, 8) || (information.Width == 8 && information.Height == 8)) && information.OffsetMask2) + { + fseek(stream, chunk->Offset + information.OffsetMask2, SEEK_SET); + uint32 size = ceil(information.Width * information.Height / 8.0f); + uint8* altMask = new uint8[size]; + fread(altMax, sizeof(uint8), size, stream); + + for (int mi = 0; mi < size; mi++) + renderMask.Mask[mi + information.OffsetY] |= altMask[mi]; + delete[] altMask; + } + fseek(stream, chunk->Offset + information.OffsetHeightmap, SEEK_SET); + + for (int y = information.OffsetY; y < (information.OffsetY + information.Height); y++) + for (int x = information.OffsetX; x < (information.OffsetX + information.Width); x++) + fread(&heights[x][y], sizeof(float), 1, stream); + } + else + { + // Fill with ocean data + for (uint32 i = 0; i < 8; ++i) + renderMask.Mask[i] = 0xFF; + + for (uint32 y = 0; y < 9; ++y) + for (uint32 x = 0; x < 9; ++x) + heights[x][y] = information.HeightLevel1; + } + + MCNKData.push_back(MCNKLiquidData(heights, renderMask)); + + for (int y = information.OffsetY; y < (information.OffsetY + information.Height); y++) + { + for (int x = information.OffsetX; x < (information.OffsetX + information.Width); x++) + { + if (!renderMask.ShouldRender(x, y)) + continue; + + MapChunk* mapChunk = Source->MapChunks[i]; + Vector3 location = mapChunk->Header.Position; + location.y = location.y - (x * Constants::UnitSize); + location.x = location.x - (y * Constants::UnitSize); + location.z = heights[x][y]; + + uint32 vertOffset = Vertices.size(); + Vertices.push_back(location); + Vertices.push_back(Vector3(location.x - Constants::UnitSize, location.y, location.z)); + Vertices.push_back(new Vector3(location.x, location.y - Constants::UnitSize, location.z)); + Vertices.push_back(new Vector3(location.x - Constants::UnitSize, location.y - Constants::UnitSize, location.z)); + + Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_WATER, vertOffset, vertOffset+2, vertOffset + 1)); + Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_WATER, vertOffset + 2, vertOffset + 3, vertOffset + 1)); + } + } + } +} diff --git a/src/tools/mesh_extractor/LiquidHandler.h b/src/tools/mesh_extractor/LiquidHandler.h index ba89be33e08..138b2da2ad9 100644 --- a/src/tools/mesh_extractor/LiquidHandler.h +++ b/src/tools/mesh_extractor/LiquidHandler.h @@ -9,9 +9,12 @@ class LiquidHandler { public: + LiquidHandler(ADT* adt); ADT* Source; std::vector Vertices; std::vector > Triangles; std::vector MCNKData; +private: + void HandleNewLiquid(); }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/MapChunk.cpp b/src/tools/mesh_extractor/MapChunk.cpp index 95f8c2e56c0..4cb5dc04d2d 100644 --- a/src/tools/mesh_extractor/MapChunk.cpp +++ b/src/tools/mesh_extractor/MapChunk.cpp @@ -1,7 +1,7 @@ #include "MapChunk.h" #include "ADT.h" -MapChunk::MapChunk( ADT* _adt, Chunk* chunk ) : adt(_adt), Source(chunk), Vertices(NULL) +MapChunk::MapChunk( ADT* _adt, Chunk* chunk ) : Adt(_adt), Source(chunk), Vertices(NULL) { FILE* stream = chunk->GetStream(); Header.Read(stream); @@ -26,14 +26,14 @@ void MapChunk::GenerateTriangles() uint32 center = (17 * y) + 9 + x; uint8 triangleType = Constants::TRIANGLE_TYPE_TERRAIN; - if (ADT.LiquidHandler && ADT.LiquidHandler.MCNKData) + if (Adt->_LiquidHandler && !Adt->_LiquidHandler->MCNKData.empty()) { - var data = ADT.LiquidHandler.MCNKData[Index]; + MCNKLiquidData& data = Adt->_LiquidHandler->MCNKData[Index]; uint32 maxHeight = std::max( std::max( std::max(std::max(Vertices[topLeft].z, Vertices[topRight].z), Vertices[bottomLeft].z), Vertices[bottomRight].z), Vertices[center].z); - if (data && data->IsWater(x, y, maxHeight)) + if (data.IsWater(x, y, maxHeight)) triangleType = Constants::TRIANGLE_TYPE_WATER; } diff --git a/src/tools/mesh_extractor/MapChunk.h b/src/tools/mesh_extractor/MapChunk.h index 034429a81ec..9d7b02bbfe5 100644 --- a/src/tools/mesh_extractor/MapChunk.h +++ b/src/tools/mesh_extractor/MapChunk.h @@ -15,7 +15,7 @@ public: void GenerateTriangles(); void GenerateVertices(FILE* stream); static bool HasHole(uint32 map, int x, int y); - ADT* adt; + ADT* Adt; Chunk* Source; MapChunkHeader Header; Vector3* Vertices; diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index 03473eb0794..0b92dab267f 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -161,3 +161,14 @@ float Utils::Distance( float x, float y ) { return sqrt(x*x + y*y); } + +std::string Utils::Replace( std::string str, const std::string& oldStr, const std::string& newStr ) +{ + size_t pos = 0; + while((pos = str.find(oldStr, pos)) != std::string::npos) + { + str.replace(pos, oldStr.length(), newStr); + pos += newStr.length(); + } + return str; +} diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index cda5f4c7cd8..aa73db173a7 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -16,9 +16,9 @@ struct Vector3 float x; float y; float z; - Vector3 operator+(Vector3 right, Vector3 left) + Vector3 operator +(Vector3 const& other) { - return Vector3(right.x+left.x, right.y+left.y, right.z+left.z); + return Vector3(x + other.x, y + other.y, z + other.z); } static Vector3 Read(FILE* file); }; @@ -380,7 +380,7 @@ public: return RenderFlags[x][y] != 0x0F; } - public static LiquidData Read(FILE* stream, LiquidHeader header) + static LiquidData Read(FILE* stream, LiquidHeader header) { LiquidData ret; ret.HeightMap = new float*[header.CountXVertices]; @@ -440,14 +440,15 @@ class MCNKLiquidData { public: MCNKLiquidData() {} + MCNKLiquidData(float** heights, H2ORenderMask mask) : Heights(heights), Mask(mask) {} const float MaxStandableHeight = 1.5f; float** Heights; - H2ORenderMask* Mask; + H2ORenderMask Mask; bool IsWater(int x, int y, float height) { - if (!Heights || !Mask) + if (!Heights) return false; if (!Mask->ShouldRender(x, y)) return false; @@ -458,6 +459,56 @@ public: } }; +class H2OHeader +{ +public: + H2OHeader() {} + uint32 OffsetInformation; + uint32 LayerCount; + uint32 OffsetRender; + + static H2OHeader Read(FILE* stream) + { + H2OHeader ret; + fread(&ret.OffsetInformation, sizeof(uint32), 1, stream); + fread(&ret.LayerCount, sizeof(uint32), 1, stream); + fread(&ret.OffsetRender, sizeof(uint32), 1, stream); + return ret; + } +}; + +class H2OInformation +{ +public: + H2OInformation() {} + uint16 LiquidType; + uint16 Flags; + float HeightLevel1; + float HeightLevel2; + uint8 OffsetX; + uint8 OffsetY; + uint8 Width; + uint8 Height; + uint32 OffsetMask2; + uint32 OffsetHeightmap; + + static H2OInformation Read(FILE* stream) + { + H2OInformation ret; + fread(&ret.LiquidType, sizeof(uint16), 1, stream); + fread(&ret.Flags, sizeof(uint16), 1, stream); + fread(&ret.HeightLevel1, sizeof(float), 1, stream); + fread(&ret.HeightLevel2, sizeof(float), 1, stream); + fread(&ret.OffsetX, sizeof(uint8), 1, stream); + fread(&ret.OffsetY, sizeof(uint8), 1, stream); + fread(&ret.Width, sizeof(uint8), 1, stream); + fread(&ret.Height, sizeof(uint8), 1, stream); + fread(&ret.OffsetMask2, sizeof(uint32), 1, stream); + fread(&ret.OffsetHeightmap, sizeof(uint32), 1, stream); + return ret; + } +}; + // Dummy class to act as an interface. class IDefinition { @@ -493,5 +544,15 @@ public: static std::string GetPathBase(std::string path); static Vector3 GetLiquidVert(G3D::Matrix4 transformation, Vector3 basePosition, float height, int x, int y); static float Distance(float x, float y); + template + static bool IsAllZero(T* arr, uint32 size) + { + for (uint32 i = 0; i < size; ++i) + if (arr[i]) + return false; + return true; + } + static std::string Utils::Replace( std::string str, const std::string& oldStr, const std::string& newStr ); + }; #endif \ No newline at end of file -- cgit v1.2.3 From 753f43718e59d4bf94b35e25a335e845e2277002 Mon Sep 17 00:00:00 2001 From: kaelima Date: Fri, 28 Sep 2012 15:04:47 +0200 Subject: Address a few compile errors. Correct spacing in HandleMmapPathCommand. --- src/server/scripts/Commands/cs_mmaps.cpp | 108 ++++++++++++------------- src/tools/mesh_extractor/Cache.h | 4 +- src/tools/mesh_extractor/DoodadHandler.cpp | 12 +-- src/tools/mesh_extractor/DoodadHandler.h | 2 +- src/tools/mesh_extractor/Geometry.cpp | 6 +- src/tools/mesh_extractor/TileBuilder.cpp | 2 +- src/tools/mesh_extractor/Utils.cpp | 10 +-- src/tools/mesh_extractor/Utils.h | 22 ++--- src/tools/mesh_extractor/WorldModelGroup.cpp | 14 ++-- src/tools/mesh_extractor/WorldModelHandler.cpp | 6 +- src/tools/mesh_extractor/WorldModelHandler.h | 6 +- src/tools/mesh_extractor/WorldModelRoot.cpp | 2 +- 12 files changed, 101 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index c1fc4d1a5e9..e4a0ebf7f24 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -60,60 +60,58 @@ public: static bool HandleMmapPathCommand(ChatHandler* handler, char const* args) { - if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) - { - handler->PSendSysMessage("NavMesh not loaded for current map."); - return true; - } - - handler->PSendSysMessage("mmap path:"); - - // units - Player* player = handler->GetSession()->GetPlayer(); - Unit* target = handler->getSelectedUnit(); - if (!player || !target) - { - handler->PSendSysMessage("Invalid target/source selection."); - return true; - } - - char* para = strtok((char*)args, " "); - - bool useStraightPath = false; - if (para && strcmp(para, "true") == 0) - useStraightPath = true; - - // unit locations - float x, y, z; - player->GetPosition(x, y, z); - - // path - PathGenerator path(target); - path.SetUseStraightPath(useStraightPath); - path.CalculatePath(x, y, z); - - PointsArray pointPath = path.GetPath(); - handler->PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName()); - handler->PSendSysMessage("Building %s", useStraightPath ? "StraightPath" : "SmoothPath"); - handler->PSendSysMessage("length %i type %u", pointPath.size(), path.GetPathType()); - - Vector3 start = path.GetStartPosition(); - Vector3 end = path.GetEndPosition(); - Vector3 actualEnd = path.GetActualEndPosition(); - - handler->PSendSysMessage("start (%.3f, %.3f, %.3f)", start.x, start.y, start.z); - handler->PSendSysMessage("end (%.3f, %.3f, %.3f)", end.x, end.y, end.z); - handler->PSendSysMessage("actual end (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); - - if (!player->isGameMaster()) - handler->PSendSysMessage("Enable GM mode to see the path points."); - - // this entry visible only to GM's with "gm on" - static const uint32 WAYPOINT_NPC_ENTRY = 1; - for (uint32 i = 0; i < pointPath.size(); ++i) - player->SummonCreature(WAYPOINT_NPC_ENTRY, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000); - - return true; + if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + handler->PSendSysMessage("mmap path:"); + + // units + Player* player = handler->GetSession()->GetPlayer(); + Unit* target = handler->getSelectedUnit(); + if (!player || !target) + { + handler->PSendSysMessage("Invalid target/source selection."); + return true; + } + + char* para = strtok((char*)args, " "); + + bool useStraightPath = false; + if (para && strcmp(para, "true") == 0) + useStraightPath = true; + + // unit locations + float x, y, z; + player->GetPosition(x, y, z); + + // path + PathGenerator path(target); + path.SetUseStraightPath(useStraightPath); + bool result = path.CalculatePath(x, y, z); + + PointsArray pointPath = path.GetPath(); + handler->PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName()); + handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : "SmoothPath"); + handler->PSendSysMessage("Result: %s - Length: %i - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); + + Vector3 start = path.GetStartPosition(); + Vector3 end = path.GetEndPosition(); + Vector3 actualEnd = path.GetActualEndPosition(); + + handler->PSendSysMessage("StartPosition (%.3f, %.3f, %.3f)", start.x, start.y, start.z); + handler->PSendSysMessage("EndPosition (%.3f, %.3f, %.3f)", end.x, end.y, end.z); + handler->PSendSysMessage("ActualEndPosition (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); + + if (!player->isGameMaster()) + handler->PSendSysMessage("Enable GM mode to see the path points."); + + for (uint32 i = 0; i < pointPath.size(); ++i) + player->SummonCreature(VISUAL_WAYPOINT, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000); + + return true; } static bool HandleMmapLocCommand(ChatHandler* handler, const char* args) @@ -290,4 +288,4 @@ public: void AddSC_mmaps_commandscript() { new mmaps_commandscript(); -} \ No newline at end of file +} diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h index 186a7870af1..bc2ea6a2883 100644 --- a/src/tools/mesh_extractor/Cache.h +++ b/src/tools/mesh_extractor/Cache.h @@ -11,7 +11,8 @@ class GenericCache { public: GenericCache() {} - const int32 FlushLimit = 1000; + + static const int32 FlushLimit = 1000; void Insert(std::string key, T* val) { @@ -35,6 +36,7 @@ private: class CacheClass { +public: CacheClass() {} GenericCache ModelCache; GenericCache WorldModelCache; diff --git a/src/tools/mesh_extractor/DoodadHandler.cpp b/src/tools/mesh_extractor/DoodadHandler.cpp index 4a7707753c4..71ca1974b81 100644 --- a/src/tools/mesh_extractor/DoodadHandler.cpp +++ b/src/tools/mesh_extractor/DoodadHandler.cpp @@ -27,7 +27,7 @@ void DoodadHandler::ProcessInternal( ChunkedData* subChunks ) return; FILE* stream = doodadReferencesChunk->GetStream(); uint32 refCount = doodadReferencesChunk->Length / 4; - for (int i = 0; i < refCount; i++) + for (uint32 i = 0; i < refCount; i++) { int32 index; fread(&index, sizeof(int32), 1, stream); @@ -41,11 +41,11 @@ void DoodadHandler::ProcessInternal( ChunkedData* subChunks ) continue; std::string path = (*_paths)[doodad.MmidIndex]; - Model* model = Cache.ModelCache.Get(path); + Model* model = Cache->ModelCache.Get(path); if (!model) { model = new Model(path); - Cache.ModelCache.Insert(path, model); + Cache->ModelCache.Insert(path, model); } if (!model->IsCollidable) continue; @@ -92,8 +92,10 @@ void DoodadHandler::InsertModelGeometry(DoodadDefinition def, Model* model) { G3D::Matrix4 transformation = Utils::GetTransformation(def); uint32 vertOffset = Vertices.size(); + for (std::vector::iterator itr = model->Vertices.begin(); itr != model->Vertices.end(); ++itr) Vertices.push_back(Utils::VectorTransform(*itr, transformation)); + for (std::vector >::iterator itr = model->Triangles.begin(); itr != model->Triangles.end(); ++itr) - Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_DOODAD, itr->V0 + vertOffset, itr->V1 + vertOffset, itr->V2 + vertOffset)); -} \ No newline at end of file + Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_DOODAD, itr->V0 + vertOffset, itr->V1 + vertOffset, itr->V2 + vertOffset)); +} diff --git a/src/tools/mesh_extractor/DoodadHandler.h b/src/tools/mesh_extractor/DoodadHandler.h index c62584ca1f1..d38ee723bef 100644 --- a/src/tools/mesh_extractor/DoodadHandler.h +++ b/src/tools/mesh_extractor/DoodadHandler.h @@ -15,7 +15,7 @@ public: uint16 DecimalScale; uint16 Flags; - float Scale() { return DecimalScale / 1024.0f; } + virtual float Scale() const { return DecimalScale / 1024.0f; } void Read(FILE* stream) { diff --git a/src/tools/mesh_extractor/Geometry.cpp b/src/tools/mesh_extractor/Geometry.cpp index 8e417af4c73..130258b6908 100644 --- a/src/tools/mesh_extractor/Geometry.cpp +++ b/src/tools/mesh_extractor/Geometry.cpp @@ -68,7 +68,7 @@ void Geometry::AddData( std::vector& verts, std::vector& tri = Triangles[i]; tris[(i * 3) + 0] = (int)tri.V0; @@ -86,7 +86,7 @@ void Geometry::GetRawData( float*& verts, int*& tris, uint8*& areas ) } areas = new uint8[Triangles.size()]; - for (int i = 0; i < Triangles.size(); i++) + for (uint32 i = 0; i < Triangles.size(); i++) { switch (Triangles[i].Type) { diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 070b9d70050..36e71730c34 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -34,4 +34,4 @@ void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax ) bmin[2] = origin[2] + (Constants::TileSize * Y); bmax[0] = origin[0] + (Constants::TileSize * (X + 1)); bmax[2] = origin[2] + (Constants::TileSize * (Y + 1)); -} \ No newline at end of file +} diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index 0b92dab267f..ef24a8017bd 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -74,7 +74,7 @@ G3D::Matrix4 Utils::RotationX(float angle) { float _cos = cos(angle); float _sin = sin(angle); - Matrix4 ret = G3D::Matrix4::identity(); + G3D::Matrix4 ret = G3D::Matrix4::identity(); ret[2][2] = _cos; ret[2][3] = _sin; ret[3][2] = -_sin; @@ -82,7 +82,7 @@ G3D::Matrix4 Utils::RotationX(float angle) return ret; } -G3D::Matrix4 Utils::GetTransformation( IDefinition def ) +G3D::Matrix4 Utils::GetTransformation(IDefinition def) { G3D::Matrix4 translation; if (def.Position.x == 0.0f && def.Position.y == 0.0f && def.Position.z == 0.0f) @@ -101,7 +101,7 @@ G3D::Matrix4 Utils::RotationY( float angle ) { float _cos = cos(angle); float _sin = sin(angle); - Matrix4 ret = G3D::Matrix4::identity(); + G3D::Matrix4 ret = G3D::Matrix4::identity(); ret[1][1] = _cos; ret[1][3] = -_sin; ret[3][1] = _sin; @@ -113,7 +113,7 @@ G3D::Matrix4 Utils::RotationZ( float angle ) { float _cos = cos(angle); float _sin = sin(angle); - Matrix4 ret = G3D::Matrix4::identity(); + G3D::Matrix4 ret = G3D::Matrix4::identity(); ret[1][1] = _cos; ret[1][2] = _sin; ret[2][1] = -_sin; @@ -126,7 +126,7 @@ float Utils::ToRadians( float degrees ) return Constants::PI * degrees / 180.0f; } -Vector3 Utils::VectorTransform( Vector3 vec, G3D::Matrix matrix ) +Vector3 Utils::VectorTransform( Vector3 vec, G3D::Matrix4 matrix ) { Vector3 ret; ret.x = vec.x * matrix[1][1] + vec.y * matrix[2][1] + vec.z * matrix[3][1] + matrix[4][1]; diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index aa73db173a7..ec333d80f8c 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -16,10 +16,12 @@ struct Vector3 float x; float y; float z; + Vector3 operator +(Vector3 const& other) { return Vector3(x + other.x, y + other.y, z + other.z); } + static Vector3 Read(FILE* file); }; @@ -342,7 +344,7 @@ public: fread(&ret.UnknownZero, sizeof(uint32), 1, stream); return ret; } -} +}; class LiquidHeader { @@ -384,16 +386,16 @@ public: { LiquidData ret; ret.HeightMap = new float*[header.CountXVertices]; - for (int i = 0; i < header.CountXVertices; ++i) + for (uint32 i = 0; i < header.CountXVertices; ++i) ret.HeightMap[i] = new float[header.CountYVertices]; ret.RenderFlags = new uint8*[header.Width]; - for (int i = 0; i < header.Width; ++i) + for (uint32 i = 0; i < header.Width; ++i) ret.RenderFlags[i] = new uint8[header.Height]; - for (int y = 0; y < header.CountYVertices; y++) + for (uint32 y = 0; y < header.CountYVertices; y++) { - for (int x = 0; x < header.CountXVertices; x++) + for (uint32 x = 0; x < header.CountXVertices; x++) { uint32 discard; fread(&discard, sizeof(uint32), 1, stream); @@ -403,9 +405,9 @@ public: } } - for (int y = 0; y < header.Height; y++) + for (uint32 y = 0; y < header.Height; y++) { - for (int x = 0; x < header.Width; x++) + for (uint32 x = 0; x < header.Width; x++) { uint8 tmp; fread(&tmp, sizeof(uint8), 1, stream); @@ -441,8 +443,8 @@ class MCNKLiquidData public: MCNKLiquidData() {} MCNKLiquidData(float** heights, H2ORenderMask mask) : Heights(heights), Mask(mask) {} - const float MaxStandableHeight = 1.5f; + static const float MaxStandableHeight = 1.5f; float** Heights; H2ORenderMask Mask; @@ -515,7 +517,7 @@ class IDefinition public: Vector3 Position; Vector3 Rotation; - virtual float Scale() = 0; + virtual float Scale() const = 0; }; class Utils @@ -540,7 +542,7 @@ public: static G3D::Matrix4 RotationY(float angle); static G3D::Matrix4 RotationZ(float angle); static float ToRadians(float degrees); - static Vector3 VectorTransform(Vector3 vec, G3D::Matrix matrix); + static Vector3 VectorTransform(Vector3 vec, G3D::Matrix4 matrix); static std::string GetPathBase(std::string path); static Vector3 GetLiquidVert(G3D::Matrix4 transformation, Vector3 basePosition, float height, int x, int y); static float Distance(float x, float y); diff --git a/src/tools/mesh_extractor/WorldModelGroup.cpp b/src/tools/mesh_extractor/WorldModelGroup.cpp index 308c7ff7b86..5039eb56381 100644 --- a/src/tools/mesh_extractor/WorldModelGroup.cpp +++ b/src/tools/mesh_extractor/WorldModelGroup.cpp @@ -33,7 +33,7 @@ void WorldModelGroup::ReadNormals() return; uint32 normalCount = chunk->Length / 12; - Assert(normalCount == Vertices.size(), "normalCount is different than the Vertices count"); + ASSERT(normalCount == Vertices.size(), "normalCount is different than the Vertices count"); Normals.reserve(normalCount); FILE* stream = chunk->GetStream(); for (int i = 0; i < normalCount; i++) @@ -58,7 +58,7 @@ void WorldModelGroup::ReadVertices() if (!chunk) return; - uint32 verticeCount = chunk.Length / 12; + uint32 verticeCount = chunk->Length / 12; Vertices.reserve(verticeCount); FILE* stream = chunk->GetStream(); for (int i = 0; i < verticeCount; i++) @@ -71,9 +71,9 @@ void WorldModelGroup::ReadTriangles() if (!chunk) return; - uint32 triangleCount = chunk.Length / 6; - Assert(triangleCount == TriangleFlags.size(), "triangleCount != TriangleFlags.size()"); - FILE* stream = chunk.GetStream(); + uint32 triangleCount = chunk->Length / 6; + ASSERT(triangleCount == TriangleFlags.size(), "triangleCount != TriangleFlags.size()"); + FILE* stream = chunk->GetStream(); Triangles.reserve(triangleCount); for (int i = 0; i < triangleCount; i++) { @@ -94,7 +94,7 @@ void WorldModelGroup::ReadMaterials() return; FILE* stream = chunk->GetStream(); - uint32 triangleCount = chunk.Length / 2; + uint32 triangleCount = chunk->Length / 2; TriangleFlags.reserve(triangleCount); TriangleMaterials.reserve(triangleCount); for (int i = 0; i < triangleCount; i++) @@ -115,7 +115,7 @@ void WorldModelGroup::ReadBoundingBox() return; FILE* stream = chunk->GetStream(); - fseek(stream, 8, SEEK_CUR): + fseek(stream, 8, SEEK_CUR); fread(&Flags, sizeof(uint32), 1, stream); BoundingBox[0] = Vector3::Read(stream); BoundingBox[1] = Vector3::Read(stream); diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index e895e2bfde8..cb8ac6d8e5d 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -159,8 +159,8 @@ void WorldModelHandler::ReadDefinitions() return; const int32 definitionSize = 64; - uint32 definitionCount = chunk.Length / definitionSize; - _definitions = new new std::vector; + uint32 definitionCount = chunk->Length / definitionSize; + _definitions = new std::vector; _definitions->reserve(definitionCount); FILE* stream = chunk->GetStream(); for (int i = 0; i < definitionCount; i++) @@ -174,7 +174,7 @@ void WorldModelHandler::ReadModelPaths() if (!mwid || !mwmo) return; - uint32 paths = mwid.Length / 4; + uint32 paths = mwid->Length / 4; _paths = new std::vector; _paths->reserve(paths); for (int i = 0; i < paths; i++) diff --git a/src/tools/mesh_extractor/WorldModelHandler.h b/src/tools/mesh_extractor/WorldModelHandler.h index 2236339de9d..81e6eab1c4b 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.h +++ b/src/tools/mesh_extractor/WorldModelHandler.h @@ -10,14 +10,18 @@ struct WorldModelDefinition : IDefinition { +public: WorldModelDefinition() {} + uint32 MwidIndex; uint32 UniqueId; Vector3 UpperExtents; Vector3 LowerExtents; uint16 Flags; uint16 DoodadSet; - float Scale() { return 1.0f; } + + virtual float Scale() const { return 1.0f; } + static WorldModelDefinition Read(FILE* file); }; diff --git a/src/tools/mesh_extractor/WorldModelRoot.cpp b/src/tools/mesh_extractor/WorldModelRoot.cpp index 9764e339242..18b3fd8586d 100644 --- a/src/tools/mesh_extractor/WorldModelRoot.cpp +++ b/src/tools/mesh_extractor/WorldModelRoot.cpp @@ -33,7 +33,7 @@ void WorldModelRoot::ReadDoodadSets() return; FILE* stream = chunk->GetStream(); - Assert(chunk.Length / 32 == Header.CountSets, "chunk.Length / 32 == Header.CountSets"); + ASSERT(chunk->Length / 32 == Header.CountSets, "chunk.Length / 32 == Header.CountSets"); DoodadSets.reserve(Header.CountSets); for (int i = 0; i < Header.CountSets; i++) DoodadSets.push_back(DoodadSet::Read(stream)); -- cgit v1.2.3 From e12f7ed3e89bc137ed8e893a6bbda8f3a5d9c63d Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 09:01:13 -0500 Subject: Tools: Fixed build in MeshExtractor (almost) --- dep/CMakeLists.txt | 2 +- src/server/CMakeLists.txt | 1 + src/tools/mesh_extractor/ADT.cpp | 53 ++++++++++++++++++++++++++ src/tools/mesh_extractor/ADT.h | 7 ++-- src/tools/mesh_extractor/CMakeLists.txt | 5 +++ src/tools/mesh_extractor/Cache.h | 2 +- src/tools/mesh_extractor/Constants.h | 1 + src/tools/mesh_extractor/DoodadHandler.cpp | 2 +- src/tools/mesh_extractor/DoodadHandler.h | 4 +- src/tools/mesh_extractor/LiquidHandler.cpp | 6 +-- src/tools/mesh_extractor/MapChunk.cpp | 11 +++--- src/tools/mesh_extractor/TileBuilder.cpp | 9 ++--- src/tools/mesh_extractor/Utils.cpp | 26 ++++++++----- src/tools/mesh_extractor/Utils.h | 13 ++++--- src/tools/mesh_extractor/WorldModelGroup.cpp | 8 ++-- src/tools/mesh_extractor/WorldModelHandler.cpp | 34 +++++++++-------- src/tools/mesh_extractor/WorldModelHandler.h | 10 ++--- src/tools/mesh_extractor/WorldModelRoot.cpp | 2 +- 18 files changed, 135 insertions(+), 61 deletions(-) create mode 100644 src/tools/mesh_extractor/ADT.cpp (limited to 'src') diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt index c01a1e3426a..f6db7ca22b7 100644 --- a/dep/CMakeLists.txt +++ b/dep/CMakeLists.txt @@ -22,7 +22,7 @@ endif() if(CMAKE_SYSTEM_NAME MATCHES "Windows") add_subdirectory(acelite) - if(SERVERS AND USE_MYSQL_SOURCES) + if(USE_MYSQL_SOURCES) add_subdirectory(mysqllite) endif() if(TOOLS) diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 2b6c553e10b..e038f36fd47 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -30,5 +30,6 @@ if( SERVERS ) else() if( TOOLS ) add_subdirectory(collision) + add_subdirectory(shared) endif() endif() diff --git a/src/tools/mesh_extractor/ADT.cpp b/src/tools/mesh_extractor/ADT.cpp new file mode 100644 index 00000000000..c564d7193cf --- /dev/null +++ b/src/tools/mesh_extractor/ADT.cpp @@ -0,0 +1,53 @@ +#include "ADT.h" +#include "DoodadHandler.h" +#include "LiquidHandler.h" +#include "WorldModelHandler.h" + +ADT::ADT( std::string file ) : ObjectData(NULL), Data(NULL), _DoodadHandler(NULL), _WorldModelHandler(NULL), _LiquidHandler(NULL), HasObjectData(false) +{ + Data = new ChunkedData(file); + ObjectData = new ChunkedData(Utils::Replace(file, ".adt", "_obj0.adt")); + if (ObjectData->Stream) + HasObjectData = true; + else + ObjectData = NULL; +} + +ADT::~ADT() +{ + delete ObjectData; + delete Data; + + for (std::vector::iterator itr = MapChunks.begin(); itr != MapChunks.end(); ++itr) + delete *itr; + + MapChunks.clear(); + delete _DoodadHandler; + delete _WorldModelHandler; + delete _LiquidHandler; +} + +void ADT::Read() +{ + Header.Read(Data->GetChunkByName("MHDR")->GetStream()); + MapChunks.reserve(16 * 16); + int mapChunkIndex = 0; + + for (std::vector::iterator itr = Data->Chunks.begin(); itr != Data->Chunks.end(); ++itr) + if ((*itr)->Name == "MCNK") + MapChunks.push_back(new MapChunk(this, *itr)); + + _LiquidHandler = new LiquidHandler(this); + + // do this separate from map chunk initialization to access liquid data + for (std::vector::iterator itr = MapChunks.begin(); itr != MapChunks.end(); ++itr) + (*itr)->GenerateTriangles(); + + _DoodadHandler = new DoodadHandler(this); + for (std::vector::iterator itr = MapChunks.begin(); itr != MapChunks.end(); ++itr) + _DoodadHandler->ProcessMapChunk(*itr); + + _WorldModelHandler = new WorldModelHandler(this); + for (std::vector::iterator itr = MapChunks.begin(); itr != MapChunks.end(); ++itr) + _WorldModelHandler->ProcessMapChunk(*itr); +} diff --git a/src/tools/mesh_extractor/ADT.h b/src/tools/mesh_extractor/ADT.h index 43984d0902c..096f491eed8 100644 --- a/src/tools/mesh_extractor/ADT.h +++ b/src/tools/mesh_extractor/ADT.h @@ -2,9 +2,10 @@ #define ADT_H #include "ChunkedData.h" #include "MapChunk.h" -#include "DoodadHandler.h" -#include "WorldModelHandler.h" -#include "LiquidHandler.h" + +class DoodadHandler; +class WorldModelHandler; +class LiquidHandler; class ADT { diff --git a/src/tools/mesh_extractor/CMakeLists.txt b/src/tools/mesh_extractor/CMakeLists.txt index 3f5b5526dd4..0469590a201 100644 --- a/src/tools/mesh_extractor/CMakeLists.txt +++ b/src/tools/mesh_extractor/CMakeLists.txt @@ -45,9 +45,14 @@ add_executable(MeshExtractor ) target_link_libraries(MeshExtractor + shared + g3dlib mpq Recast Detour + ${MYSQL_LIBRARY} + ${OPENSSL_LIBRARIES} + ${OPENSSL_EXTRA_LIBRARIES} ${BZIP2_LIBRARIES} ${ZLIB_LIBRARIES} ${ACE_LIBRARY} diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h index bc2ea6a2883..2693ce4e1e1 100644 --- a/src/tools/mesh_extractor/Cache.h +++ b/src/tools/mesh_extractor/Cache.h @@ -18,7 +18,7 @@ public: { if (_items.size() > FlushLimit) Clear(); - _items.insert(key, val); + _items[key] = val; } T* Get(std::string key) diff --git a/src/tools/mesh_extractor/Constants.h b/src/tools/mesh_extractor/Constants.h index 885761f1687..38fa0b2e35b 100644 --- a/src/tools/mesh_extractor/Constants.h +++ b/src/tools/mesh_extractor/Constants.h @@ -28,6 +28,7 @@ public: static const float UnitSize; static const float Origin[]; static const float PI; + static const float MaxStandableHeight; }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/DoodadHandler.cpp b/src/tools/mesh_extractor/DoodadHandler.cpp index 71ca1974b81..89fcaba5601 100644 --- a/src/tools/mesh_extractor/DoodadHandler.cpp +++ b/src/tools/mesh_extractor/DoodadHandler.cpp @@ -88,7 +88,7 @@ void DoodadHandler::ReadDoodadPaths( Chunk* id, Chunk* data ) } } -void DoodadHandler::InsertModelGeometry(DoodadDefinition def, Model* model) +void DoodadHandler::InsertModelGeometry(const DoodadDefinition def, Model* model) { G3D::Matrix4 transformation = Utils::GetTransformation(def); uint32 vertOffset = Vertices.size(); diff --git a/src/tools/mesh_extractor/DoodadHandler.h b/src/tools/mesh_extractor/DoodadHandler.h index d38ee723bef..c426504da32 100644 --- a/src/tools/mesh_extractor/DoodadHandler.h +++ b/src/tools/mesh_extractor/DoodadHandler.h @@ -7,7 +7,7 @@ #include #include -class DoodadDefinition : IDefinition +class DoodadDefinition : public IDefinition { public: uint32 MmidIndex; @@ -43,7 +43,7 @@ protected: private: void ReadDoodadDefinitions(Chunk* chunk); void ReadDoodadPaths(Chunk* id, Chunk* data); - void InsertModelGeometry(DoodadDefinition def, Model* model); + void InsertModelGeometry(const DoodadDefinition def, Model* model); std::set _drawn; std::vector* _definitions; std::vector* _paths; diff --git a/src/tools/mesh_extractor/LiquidHandler.cpp b/src/tools/mesh_extractor/LiquidHandler.cpp index 3217bb2cbc6..3d0876aeb74 100644 --- a/src/tools/mesh_extractor/LiquidHandler.cpp +++ b/src/tools/mesh_extractor/LiquidHandler.cpp @@ -43,7 +43,7 @@ void LiquidHandler::HandleNewLiquid() fseek(stream, chunk->Offset + information.OffsetMask2, SEEK_SET); uint32 size = ceil(information.Width * information.Height / 8.0f); uint8* altMask = new uint8[size]; - fread(altMax, sizeof(uint8), size, stream); + fread(altMask, sizeof(uint8), size, stream); for (int mi = 0; mi < size; mi++) renderMask.Mask[mi + information.OffsetY] |= altMask[mi]; @@ -84,8 +84,8 @@ void LiquidHandler::HandleNewLiquid() uint32 vertOffset = Vertices.size(); Vertices.push_back(location); Vertices.push_back(Vector3(location.x - Constants::UnitSize, location.y, location.z)); - Vertices.push_back(new Vector3(location.x, location.y - Constants::UnitSize, location.z)); - Vertices.push_back(new Vector3(location.x - Constants::UnitSize, location.y - Constants::UnitSize, location.z)); + Vertices.push_back(Vector3(location.x, location.y - Constants::UnitSize, location.z)); + Vertices.push_back(Vector3(location.x - Constants::UnitSize, location.y - Constants::UnitSize, location.z)); Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_WATER, vertOffset, vertOffset+2, vertOffset + 1)); Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_WATER, vertOffset + 2, vertOffset + 3, vertOffset + 1)); diff --git a/src/tools/mesh_extractor/MapChunk.cpp b/src/tools/mesh_extractor/MapChunk.cpp index 4cb5dc04d2d..0b02a2a4a14 100644 --- a/src/tools/mesh_extractor/MapChunk.cpp +++ b/src/tools/mesh_extractor/MapChunk.cpp @@ -1,5 +1,6 @@ #include "MapChunk.h" #include "ADT.h" +#include "LiquidHandler.h" MapChunk::MapChunk( ADT* _adt, Chunk* chunk ) : Adt(_adt), Source(chunk), Vertices(NULL) { @@ -25,7 +26,7 @@ void MapChunk::GenerateTriangles() uint32 bottomRight = (17 * (y + 1)) + x + 1; uint32 center = (17 * y) + 9 + x; - uint8 triangleType = Constants::TRIANGLE_TYPE_TERRAIN; + Constants::TriangleType triangleType = Constants::TRIANGLE_TYPE_TERRAIN; if (Adt->_LiquidHandler && !Adt->_LiquidHandler->MCNKData.empty()) { MCNKLiquidData& data = Adt->_LiquidHandler->MCNKData[Index]; @@ -37,10 +38,10 @@ void MapChunk::GenerateTriangles() triangleType = Constants::TRIANGLE_TYPE_WATER; } - Triangles.push_back(new Triangle(triangleType, topRight, topLeft, center)); - Triangles.push_back(new Triangle(triangleType, topLeft, bottomLeft, center)); - Triangles.push_back(new Triangle(triangleType, bottomLeft, bottomRight, center)); - Triangles.push_back(new Triangle(triangleType, bottomRight, topRight, center)); + Triangles.push_back(Triangle(triangleType, topRight, topLeft, center)); + Triangles.push_back(Triangle(triangleType, topLeft, bottomLeft, center)); + Triangles.push_back(Triangle(triangleType, bottomLeft, bottomRight, center)); + Triangles.push_back(Triangle(triangleType, bottomRight, topRight, center)); } } } diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 36e71730c34..190607493fa 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -27,11 +27,10 @@ TileBuilder::TileBuilder(std::string world, int x, int y) : _Geometry(NULL), Wor void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax ) { - float origin[3] = Constants::Origin; bmin = new float[3]; bmax = new float[3]; - bmin[0] = origin[0] + (Constants::TileSize * X); - bmin[2] = origin[2] + (Constants::TileSize * Y); - bmax[0] = origin[0] + (Constants::TileSize * (X + 1)); - bmax[2] = origin[2] + (Constants::TileSize * (Y + 1)); + bmin[0] = Constants::Origin[0] + (Constants::TileSize * X); + bmin[2] = Constants::Origin[2] + (Constants::TileSize * Y); + bmax[0] = Constants::Origin[0] + (Constants::TileSize * (X + 1)); + bmax[2] = Constants::Origin[2] + (Constants::TileSize * (Y + 1)); } diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index ef24a8017bd..c7c0cff0d42 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -1,7 +1,9 @@ #include "Utils.h" +#include "WorldModelHandler.h" #include "Constants.h" #include #include "g3d/Matrix4.h" +#include "g3d/Quat.h" const float Constants::TileSize = 533.0f + (1/3.0f); const float Constants::MaxXY = 32.0f * Constants::TileSize; @@ -9,6 +11,7 @@ const float Constants::ChunkSize = Constants::TileSize / 16.0f; const float Constants::UnitSize = Constants::ChunkSize / 8.0f; const float Constants::Origin[] = { -Constants::MaxXY, 0.0f, -Constants::MaxXY }; const float Constants::PI = 3.1415926f; +const float Constants::MaxStandableHeight = 1.5f; void Utils::Reverse(char word[]) { @@ -60,14 +63,7 @@ std::string Utils::GetAdtPath( std::string world, int x, int y ) std::string Utils::FixModelPath( std::string path ) { - std::string::size_type idx = path.rfind("."); - // Bizarre way of changing extension but... - if (idx != std::string::npos) - { - path[idx + 1] = "M"; - path[idx + 2] = "2"; - } - return path; + return Utils::GetPathBase(path) + ".M2"; } G3D::Matrix4 Utils::RotationX(float angle) @@ -139,7 +135,7 @@ std::string Utils::GetPathBase( std::string path ) { int lastIndex = path.find_last_of("."); if (lastIndex != std::string::npos) - return path.substr(0, lastindex); + return path.substr(0, lastIndex); return path; } @@ -172,3 +168,15 @@ std::string Utils::Replace( std::string str, const std::string& oldStr, const st } return str; } + +G3D::Matrix4 Utils::GetWmoDoodadTransformation( DoodadInstance inst, WorldModelDefinition root ) +{ + G3D::Matrix4 rootTransformation = Utils::GetTransformation(root); + G3D::Matrix4 translation = G3D::Matrix4::translation(inst.Position.x, inst.Position.y, inst.Position.z); + G3D::Matrix4 scale = G3D::Matrix4::scale(inst.Scale); + G3D::Matrix4 rotation = Utils::RotationY(Constants::PI); + G3D::Quat quat(-inst.QuatY, inst.QuatZ, -inst.QuatX, inst.QuatW); + G3D::Matrix4 quatRotation = quat.toRotationMatrix(); + + return scale * rotation * quatRotation ** translation * rootTransformation; +} diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index ec333d80f8c..ac14b9eca69 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -9,6 +9,9 @@ #include "Common.h" #include "Constants.h" +struct WorldModelDefinition; +class DoodadInstance; + struct Vector3 { Vector3() {} @@ -35,6 +38,7 @@ struct TilePos template struct Triangle { + Triangle() {} Triangle(Constants::TriangleType type, T v0, T v1, T v2) : Type(type), V0(v0), V1(v1), V2(v2) {} T V0; T V1; @@ -444,7 +448,6 @@ public: MCNKLiquidData() {} MCNKLiquidData(float** heights, H2ORenderMask mask) : Heights(heights), Mask(mask) {} - static const float MaxStandableHeight = 1.5f; float** Heights; H2ORenderMask Mask; @@ -452,10 +455,10 @@ public: { if (!Heights) return false; - if (!Mask->ShouldRender(x, y)) + if (!Mask.ShouldRender(x, y)) return false; float diff = Heights[x][y] - height; - if (diff > MaxStandableHeight) + if (diff > Constants::MaxStandableHeight) return true; return false; } @@ -517,7 +520,7 @@ class IDefinition public: Vector3 Position; Vector3 Rotation; - virtual float Scale() const = 0; + virtual float Scale() const { return 1.0f; }; }; class Utils @@ -555,6 +558,6 @@ public: return true; } static std::string Utils::Replace( std::string str, const std::string& oldStr, const std::string& newStr ); - + static G3D::Matrix4 GetWmoDoodadTransformation( DoodadInstance inst, WorldModelDefinition root ); }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/WorldModelGroup.cpp b/src/tools/mesh_extractor/WorldModelGroup.cpp index 5039eb56381..b4c963020c7 100644 --- a/src/tools/mesh_extractor/WorldModelGroup.cpp +++ b/src/tools/mesh_extractor/WorldModelGroup.cpp @@ -33,7 +33,7 @@ void WorldModelGroup::ReadNormals() return; uint32 normalCount = chunk->Length / 12; - ASSERT(normalCount == Vertices.size(), "normalCount is different than the Vertices count"); + ASSERT(normalCount == Vertices.size() && "normalCount is different than the Vertices count"); Normals.reserve(normalCount); FILE* stream = chunk->GetStream(); for (int i = 0; i < normalCount; i++) @@ -48,8 +48,8 @@ void WorldModelGroup::ReadLiquid() HasLiquidData = true; FILE* stream = chunk->GetStream(); - LiquidDataHeader = LiquidHeader.Read(stream); - LiquidDataGeometry = LiquidData.Read(stream, LiquidDataHeader); + LiquidDataHeader = LiquidHeader::Read(stream); + LiquidDataGeometry = LiquidData::Read(stream, LiquidDataHeader); } void WorldModelGroup::ReadVertices() @@ -72,7 +72,7 @@ void WorldModelGroup::ReadTriangles() return; uint32 triangleCount = chunk->Length / 6; - ASSERT(triangleCount == TriangleFlags.size(), "triangleCount != TriangleFlags.size()"); + ASSERT(triangleCount == TriangleFlags.size() && "triangleCount != TriangleFlags.size()"); FILE* stream = chunk->GetStream(); Triangles.reserve(triangleCount); for (int i = 0; i < triangleCount; i++) diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index cb8ac6d8e5d..e5a14d55c0c 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -1,6 +1,8 @@ #include "WorldModelHandler.h" +#include "WorldModelRoot.h" #include "Chunk.h" #include "Cache.h" +#include "Model.h" #include "Common.h" #include "g3d/Matrix4.h" #include @@ -15,7 +17,7 @@ WorldModelDefinition WorldModelDefinition::Read( FILE* file ) ret.UpperExtents = Vector3::Read(file); ret.LowerExtents = Vector3::Read(file); fread(&ret.Flags, sizeof(uint16), 1, file); - fread(&ret.DooadSet, sizeof(uint16), 1, file); + fread(&ret.DoodadSet, sizeof(uint16), 1, file); uint32 discard; fread(&discard, sizeof(uint32), 1, file); return ret; @@ -39,7 +41,7 @@ void WorldModelHandler::ProcessInternal( ChunkedData* subChunks ) return; FILE* stream = wmoReferencesChunk->GetStream(); uint32 refCount = wmoReferencesChunk->Length / 4; - for (int i = 0; i < refCount; i++) + for (uint32 i = 0; i < refCount; i++) { int32 index; fread(&index, sizeof(int32), 1, stream); @@ -56,7 +58,7 @@ void WorldModelHandler::ProcessInternal( ChunkedData* subChunks ) if (wmo.MwidIndex >= _paths->size()) continue; - std::string path = _paths[(int) wmo.MwidIndex]; + std::string path = (*_paths)[wmo.MwidIndex]; WorldModelRoot* model = Cache->WorldModelCache.Get(path); if (!model) { @@ -71,16 +73,16 @@ void WorldModelHandler::ProcessInternal( ChunkedData* subChunks ) } } -void WorldModelHandler::InsertModelGeometry( std::vector verts, std::vector > tris, WorldModelDefinition& def, WorldModelRoot* root ) +void WorldModelHandler::InsertModelGeometry( std::vector& verts, std::vector >& tris, WorldModelDefinition& def, WorldModelRoot* root ) { - G3D::Matrix4 transformation = Utils::GetTransformation(); + G3D::Matrix4 transformation = Utils::GetTransformation(def); for (std::vector::iterator group = root->Groups.begin(); group != root->Groups.end(); ++group) { uint32 vertOffset = verts.size(); for (std::vector::iterator itr2 = group->Vertices.begin(); itr2 != group->Vertices.end(); ++itr2) verts.push_back(Utils::VectorTransform(*itr2, transformation)); - for (int i = 0; i < group->Triangles.size(); ++i) + for (uint32 i = 0; i < group->Triangles.size(); ++i) { // only include collidable tris if ((group->TriangleFlags[i] & 0x04) != 0 && group->TriangleMaterials[i] != 0xFF) @@ -93,7 +95,7 @@ void WorldModelHandler::InsertModelGeometry( std::vector verts, std::ve if (def.DoodadSet >= 0 && def.DoodadSet < root->DoodadSets.size()) { DoodadSet set = root->DoodadSets[def.DoodadSet]; - std::vector instances = new std::vector; + std::vector instances; instances.reserve(set.CountInstances); for (uint32 i = set.FirstInstanceIndex; i < (set.CountInstances + set.FirstInstanceIndex); i++) { @@ -104,16 +106,16 @@ void WorldModelHandler::InsertModelGeometry( std::vector verts, std::ve for (std::vector::iterator instance = instances.begin(); instance != instances.end(); ++instance) { - Model* model = Cache.ModelCache.Get(instance->File); + Model* model = Cache->ModelCache.Get(instance->File); if (!model) { model = new Model(instance->File); - Cache.ModelCache.Insert(instance->File, model); + Cache->ModelCache.Insert(instance->File, model); } - if (!model.IsCollidable) + if (!model->IsCollidable) continue; - G3D::Matrix4 doodadTransformation = Utils::GetWmoDoodadTransformation(instance, def); + G3D::Matrix4 doodadTransformation = Utils::GetWmoDoodadTransformation(*instance, def); int vertOffset = verts.size(); for (std::vector::iterator itr2 = model->Vertices.begin(); itr2 != model->Vertices.end(); ++itr2) verts.push_back(Utils::VectorTransform(*itr2, doodadTransformation)); @@ -126,9 +128,9 @@ void WorldModelHandler::InsertModelGeometry( std::vector verts, std::ve if (!group->HasLiquidData) continue; - for (int y = 0; y < group->LiquidDataHeader.Height; y++) + for (uint32 y = 0; y < group->LiquidDataHeader.Height; y++) { - for (int x = 0; x < group->LiquidDataHeader.Width; x++) + for (uint32 x = 0; x < group->LiquidDataHeader.Width; x++) { if (!group->LiquidDataGeometry.ShouldRender(x, y)) continue; @@ -144,7 +146,7 @@ void WorldModelHandler::InsertModelGeometry( std::vector verts, std::ve group->LiquidDataGeometry.HeightMap[x + 1][y + 1], x + 1, y + 1)); tris.push_back(Triangle(Constants::TRIANGLE_TYPE_WATER, vertOffset, vertOffset + 2, vertOffset + 1)); - tris.push_back(new Triangle(Constants::TRIANGLE_TYPE_WATER, vertOffset + 2, vertOffset + 3, vertOffset + 1)); + tris.push_back(Triangle(Constants::TRIANGLE_TYPE_WATER, vertOffset + 2, vertOffset + 3, vertOffset + 1)); } } @@ -163,7 +165,7 @@ void WorldModelHandler::ReadDefinitions() _definitions = new std::vector; _definitions->reserve(definitionCount); FILE* stream = chunk->GetStream(); - for (int i = 0; i < definitionCount; i++) + for (uint32 i = 0; i < definitionCount; i++) _definitions->push_back(WorldModelDefinition::Read(stream)); } @@ -177,7 +179,7 @@ void WorldModelHandler::ReadModelPaths() uint32 paths = mwid->Length / 4; _paths = new std::vector; _paths->reserve(paths); - for (int i = 0; i < paths; i++) + for (uint32 i = 0; i < paths; i++) { FILE* stream = mwid->GetStream(); fseek(stream, i * 4, SEEK_CUR); diff --git a/src/tools/mesh_extractor/WorldModelHandler.h b/src/tools/mesh_extractor/WorldModelHandler.h index 81e6eab1c4b..daf0713ecd2 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.h +++ b/src/tools/mesh_extractor/WorldModelHandler.h @@ -2,13 +2,15 @@ #define WMODEL_HNDL_H #include "Common.h" #include "Utils.h" +#include "WorldModelRoot.h" #include "ObjectDataHandler.h" -#include "ADT.h" #include #include -struct WorldModelDefinition : IDefinition +class ADT; + +struct WorldModelDefinition : public IDefinition { public: WorldModelDefinition() {} @@ -20,8 +22,6 @@ public: uint16 Flags; uint16 DoodadSet; - virtual float Scale() const { return 1.0f; } - static WorldModelDefinition Read(FILE* file); }; @@ -33,7 +33,7 @@ public: std::vector Vertices; std::vector > Triangles; bool IsSane() { return _definitions && _paths; } - void InsertModelGeometry(std::vector verts, std::vector > tris, WorldModelDefinition& def, WorldModelRoot* root); + void InsertModelGeometry(std::vector& verts, std::vector >& tris, WorldModelDefinition& def, WorldModelRoot* root); protected: void ProcessInternal(ChunkedData* data); private: diff --git a/src/tools/mesh_extractor/WorldModelRoot.cpp b/src/tools/mesh_extractor/WorldModelRoot.cpp index 18b3fd8586d..3457a35f761 100644 --- a/src/tools/mesh_extractor/WorldModelRoot.cpp +++ b/src/tools/mesh_extractor/WorldModelRoot.cpp @@ -33,7 +33,7 @@ void WorldModelRoot::ReadDoodadSets() return; FILE* stream = chunk->GetStream(); - ASSERT(chunk->Length / 32 == Header.CountSets, "chunk.Length / 32 == Header.CountSets"); + ASSERT(chunk->Length / 32 == Header.CountSets && "chunk.Length / 32 == Header.CountSets"); DoodadSets.reserve(Header.CountSets); for (int i = 0; i < Header.CountSets; i++) DoodadSets.push_back(DoodadSet::Read(stream)); -- cgit v1.2.3 From 1c6a44e4c5516b5e81acf858733114e61d332e3f Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 09:30:23 -0500 Subject: Tools: Fixed build in MeshExtractor --- src/tools/mesh_extractor/CMakeLists.txt | 6 ++++++ src/tools/mesh_extractor/MeshExtractor.cpp | 4 ++++ 2 files changed, 10 insertions(+) (limited to 'src') diff --git a/src/tools/mesh_extractor/CMakeLists.txt b/src/tools/mesh_extractor/CMakeLists.txt index 0469590a201..09bd2982213 100644 --- a/src/tools/mesh_extractor/CMakeLists.txt +++ b/src/tools/mesh_extractor/CMakeLists.txt @@ -13,15 +13,19 @@ file(GLOB_RECURSE sources *.cpp *.h) if( UNIX ) include_directories ( + ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src/server/shared ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour ${CMAKE_SOURCE_DIR}/dep/libmpq ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${MYSQL_INCLUDE_DIR} + ${OPENSSL_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ) elseif( WIN32 ) include_directories ( + ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src/server/shared ${CMAKE_SOURCE_DIR}/src/server/shared/Database ${CMAKE_SOURCE_DIR}/src/server/shared/Database/Implementation @@ -36,6 +40,8 @@ elseif( WIN32 ) ${CMAKE_SOURCE_DIR}/dep/libmpq/win ${CMAKE_SOURCE_DIR}/dep/g3dlite/include ${ACE_INCLUDE_DIR} + ${MYSQL_INCLUDE_DIR} + ${OPENSSL_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ) endif() diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 0220627cbcc..0611c9c2d58 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -3,6 +3,10 @@ #include "ContinentBuilder.h" #include "Cache.h" +#include "Common.h" +#include "LoginDatabase.h" +LoginDatabaseWorkerPool LoginDatabase; + MPQManager* MPQHandler; CacheClass* Cache; -- cgit v1.2.3 From 3eda479e2970a72a8fcf7731d94b962ff9874e38 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 13:30:43 -0500 Subject: Tools: MeshExtractor is working now. Please note that this is not yet finished --- src/tools/mesh_extractor/Cache.h | 28 +++- src/tools/mesh_extractor/Constants.h | 7 + src/tools/mesh_extractor/ContinentBuilder.cpp | 29 +++- src/tools/mesh_extractor/Geometry.cpp | 21 +++ src/tools/mesh_extractor/Geometry.h | 2 + src/tools/mesh_extractor/MPQManager.cpp | 2 +- src/tools/mesh_extractor/MapChunk.cpp | 12 +- src/tools/mesh_extractor/MapChunk.h | 3 +- src/tools/mesh_extractor/MeshExtractor.cpp | 4 +- src/tools/mesh_extractor/TileBuilder.cpp | 201 ++++++++++++++++++++++++- src/tools/mesh_extractor/TileBuilder.h | 7 +- src/tools/mesh_extractor/Utils.h | 16 ++ src/tools/mesh_extractor/WorldModelHandler.cpp | 2 +- 13 files changed, 308 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h index 2693ce4e1e1..799878bdd3b 100644 --- a/src/tools/mesh_extractor/Cache.h +++ b/src/tools/mesh_extractor/Cache.h @@ -1,12 +1,14 @@ #ifndef CACHE_H #define CACHE_H #include +#include #include "Common.h" class WorldModelRoot; class Model; +class ADT; -template +template class GenericCache { public: @@ -14,32 +16,42 @@ public: static const int32 FlushLimit = 1000; - void Insert(std::string key, T* val) + void Insert(K key, T* val) { if (_items.size() > FlushLimit) Clear(); _items[key] = val; } - T* Get(std::string key) + T* Get(K key) { - UNORDERED_MAP::iterator itr = _items.find(key); + std::map::iterator itr = _items.find(key); if (itr != _items.end()) return itr->second; return NULL; } - void Clear() { _items.clear(); } + void Clear() + { + for (std::map::iterator itr = _items.begin(); itr != _items.end(); ++itr) + delete itr->second; + _items.clear(); + } private: - UNORDERED_MAP _items; + std::map _items; }; class CacheClass { public: CacheClass() {} - GenericCache ModelCache; - GenericCache WorldModelCache; + GenericCache ModelCache; + GenericCache WorldModelCache; + GenericCache, ADT> AdtCache; + void Clear() + { + AdtCache.Clear(); + } }; extern CacheClass* Cache; diff --git a/src/tools/mesh_extractor/Constants.h b/src/tools/mesh_extractor/Constants.h index 38fa0b2e35b..f44d5f16797 100644 --- a/src/tools/mesh_extractor/Constants.h +++ b/src/tools/mesh_extractor/Constants.h @@ -22,6 +22,13 @@ public: POLY_AREA_ROAD = 3, POLY_AREA_DANGER = 4, }; + + enum PolyFlag + { + POLY_FLAG_WALK = 1, + POLY_FLAG_SWIM = 2, + POLY_FLAG_FLIGHTMASTER = 4 + }; static const float TileSize; static const float MaxXY; static const float ChunkSize; diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index 8af6f3a02e8..f861dff1648 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -1,11 +1,38 @@ #include "ContinentBuilder.h" +#include "TileBuilder.h" #include "WDT.h" #include "Utils.h" +#include "DetourNavMesh.h" void ContinentBuilder::Build() { + FILE* mmap = fopen("608.mmap", "wb"); + dtNavMeshParams params; + params.maxPolys = 32768; + params.maxTiles = 4096; + params.orig[0] = -17066.666f; + params.orig[1] = 0.0f; + params.orig[2] = -17066.666f; + params.tileHeight = 533.33333f; + params.tileWidth = 533.33333f; + fwrite(¶ms, sizeof(dtNavMeshParams), 1, mmap); + fclose(mmap); for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) { - + TileBuilder builder(Continent, itr->X, itr->Y, TileMap); + char buff[100]; + sprintf(buff, "%03u%02u%02u.mmtile", builder.MapId, itr->X, itr->Y); + FILE* f = fopen(buff, "wb"); + uint8* nav = builder.Build(); + if (nav) + { + MmapTileHeader header; + header.size = builder.DataSize; + fwrite(&header, sizeof(MmapTileHeader), 1, f); + fwrite(nav, sizeof(uint8), builder.DataSize, f); + } + fclose(f); + dtFree(nav); + printf("[%02u,%02u] Tile Built!\n", itr->X, itr->Y); } } diff --git a/src/tools/mesh_extractor/Geometry.cpp b/src/tools/mesh_extractor/Geometry.cpp index 130258b6908..2fbe99e3211 100644 --- a/src/tools/mesh_extractor/Geometry.cpp +++ b/src/tools/mesh_extractor/Geometry.cpp @@ -1,5 +1,8 @@ #include "Geometry.h" #include "Constants.h" +#include "ADT.h" +#include "WorldModelHandler.h" +#include "DoodadHandler.h" Geometry::Geometry() : Transform(false) { @@ -100,3 +103,21 @@ void Geometry::GetRawData( float*& verts, int*& tris, uint8*& areas ) } } +void Geometry::AddAdt( ADT* adt ) +{ + for (std::vector::iterator itr = adt->MapChunks.begin(); itr != adt->MapChunks.end(); ++itr) + { + std::vector > tmp; + tmp.reserve((*itr)->Triangles.size()); + for (std::vector >::iterator itr2 = (*itr)->Triangles.begin(); itr2 != (*itr)->Triangles.end(); ++itr2) + tmp.push_back(Triangle(itr2->Type, itr2->V0, itr2->V1, itr2->V2)); + AddData((*itr)->Vertices, tmp); + } + + if (!adt->_DoodadHandler->Triangles.empty()) + AddData(adt->_DoodadHandler->Vertices, adt->_DoodadHandler->Triangles); + + if (!adt->_WorldModelHandler->Triangles.empty()) + AddData(adt->_WorldModelHandler->Vertices, adt->_WorldModelHandler->Triangles); +} + diff --git a/src/tools/mesh_extractor/Geometry.h b/src/tools/mesh_extractor/Geometry.h index 048d9fde578..9593c98044e 100644 --- a/src/tools/mesh_extractor/Geometry.h +++ b/src/tools/mesh_extractor/Geometry.h @@ -4,6 +4,7 @@ #include "Utils.h" +class ADT; class Geometry { public: @@ -12,6 +13,7 @@ public: void CalculateBoundingBox(float*& min, float*& max); void CalculateMinMaxHeight(float& min, float& max); void AddData(std::vector& verts, std::vector >& tris); + void AddAdt(ADT* adt); void GetRawData(float*& verts, int*& tris, uint8*& areas); std::vector Vertices; diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp index 429b09ffe02..35d4c91fc14 100644 --- a/src/tools/mesh_extractor/MPQManager.cpp +++ b/src/tools/mesh_extractor/MPQManager.cpp @@ -46,7 +46,7 @@ void MPQManager::LoadMPQs() sprintf(filename, "Data/%s", Files[i]); Archives.push_front(new MPQArchive(filename)); } - printf("Loaded %u MPQ files succesfully", Archives.size()); + printf("Loaded %u MPQ files succesfully\n", Archives.size()); } FILE* MPQManager::GetFile( std::string path ) diff --git a/src/tools/mesh_extractor/MapChunk.cpp b/src/tools/mesh_extractor/MapChunk.cpp index 0b02a2a4a14..61c106f9766 100644 --- a/src/tools/mesh_extractor/MapChunk.cpp +++ b/src/tools/mesh_extractor/MapChunk.cpp @@ -2,7 +2,7 @@ #include "ADT.h" #include "LiquidHandler.h" -MapChunk::MapChunk( ADT* _adt, Chunk* chunk ) : Adt(_adt), Source(chunk), Vertices(NULL) +MapChunk::MapChunk( ADT* _adt, Chunk* chunk ) : Adt(_adt), Source(chunk) { FILE* stream = chunk->GetStream(); Header.Read(stream); @@ -46,16 +46,10 @@ void MapChunk::GenerateTriangles() } } -MapChunk::~MapChunk() -{ - delete[] Vertices; -} - void MapChunk::GenerateVertices( FILE* stream ) { fseek(stream, Header.OffsetMCVT, SEEK_CUR); - int32 vertIndex = 0; - Vertices = new Vector3[125]; + Vertices.reserve(125); for (int j = 0; j < 17; j++) { @@ -67,7 +61,7 @@ void MapChunk::GenerateVertices( FILE* stream ) Vector3 vert(Header.Position.x - (j * (Constants::UnitSize * 0.5f)), Header.Position.y - (i * Constants::UnitSize), Header.Position.z + tmp); if (values == 8) vert.y -= Constants::UnitSize * 0.5f; - Vertices[vertIndex++] = vert; + Vertices.push_back(vert); } } } diff --git a/src/tools/mesh_extractor/MapChunk.h b/src/tools/mesh_extractor/MapChunk.h index 9d7b02bbfe5..61dcabac9b0 100644 --- a/src/tools/mesh_extractor/MapChunk.h +++ b/src/tools/mesh_extractor/MapChunk.h @@ -10,7 +10,6 @@ class MapChunk { public: MapChunk(ADT* _adt, Chunk* chunk); - ~MapChunk(); void GenerateTriangles(); void GenerateVertices(FILE* stream); @@ -18,7 +17,7 @@ public: ADT* Adt; Chunk* Source; MapChunkHeader Header; - Vector3* Vertices; + std::vector Vertices; std::vector > Triangles; int32 Index; }; diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 0611c9c2d58..38a120449bc 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -15,10 +15,10 @@ void ExtractAllMaps() WDT wdt("World\\maps\\DalaranPrison\\DalaranPrison.wdt"); if (!wdt.IsValid) return; - printf("Model valid!"); + printf("Model valid!\n"); if (wdt.IsGlobalModel) { - printf("Unsupported"); + printf("Unsupported\n"); return; } ContinentBuilder builder("DalaranPrison", &wdt); diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 190607493fa..4736274706d 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -1,7 +1,15 @@ #include "TileBuilder.h" +#include "Geometry.h" #include "Constants.h" +#include "Utils.h" +#include "Cache.h" +#include "ADT.h" +#include "WDT.h" +#include "Recast.h" +#include "RecastAlloc.h" +#include "DetourNavMeshBuilder.h" -TileBuilder::TileBuilder(std::string world, int x, int y) : _Geometry(NULL), World(world), X(x), Y(y), MapId(608) +TileBuilder::TileBuilder(std::string world, int x, int y, WDT* wdt) : _Geometry(NULL), World(world), X(x), Y(y), MapId(608), DataSize(0), Wdt(wdt) { // Cell Size = TileSize / TileVoxelSize // 1800 = TileVoxelSize @@ -23,6 +31,8 @@ TileBuilder::TileBuilder(std::string world, int x, int y) : _Geometry(NULL), Wor Config.width = 1800; Config.maxVertsPerPoly = 6; Config.maxSimplificationError = 1.3f; + + Context = new rcContext; } void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax ) @@ -34,3 +44,192 @@ void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax ) bmax[0] = Constants::Origin[0] + (Constants::TileSize * (X + 1)); bmax[2] = Constants::Origin[2] + (Constants::TileSize * (Y + 1)); } + +uint8* TileBuilder::Build() +{ + _Geometry = new Geometry(); + _Geometry->Transform = true; + ADT* adt = Cache->AdtCache.Get(std::make_pair(X, Y)); + if (!adt) + { + adt = new ADT(Utils::GetAdtPath(World, X, Y)); + adt->Read(); + Cache->AdtCache.Insert(std::make_pair(X, Y), adt); + } + _Geometry->AddAdt(adt); + + if (_Geometry->Vertices.empty() && _Geometry->Triangles.empty()) + return NULL; + + float* bbMin; + float* bbMax; + CalculateTileBounds(bbMin, bbMax); + _Geometry->CalculateMinMaxHeight(bbMin[1], bbMax[1]); + + // again, we load everything - wasteful but who cares + for (int ty = Y - 1; ty <= Y + 1; ty++) + { + for (int tx = X - 1; tx <= X + 1; tx++) + { + // don't load main tile again + if (tx == X && ty == Y) + continue; + + ADT* _adt = Cache->AdtCache.Get(std::make_pair(tx, ty)); + if (!_adt) + { + _adt = new ADT(Utils::GetAdtPath(World, tx, ty)); + // If this condition is met, it means that this wdt does not contain the ADT + if (!_adt->Data->Stream) + { + delete _adt; + continue; + } + _adt->Read(); + Cache->AdtCache.Insert(std::make_pair(tx, ty), _adt); + } + _Geometry->AddAdt(adt); + } + } + uint32 numVerts = _Geometry->Vertices.size(); + uint32 numTris = _Geometry->Triangles.size(); + float* vertices; + int* triangles; + uint8* areas; + _Geometry->GetRawData(vertices, triangles, areas); + _Geometry->Vertices.clear(); + _Geometry->Triangles.clear(); + + bbMin[0] -= Config.borderSize * Config.cs; + bbMin[2] -= Config.borderSize * Config.cs; + bbMax[0] += Config.borderSize * Config.cs; + bbMax[0] += Config.borderSize * Config.cs; + + rcHeightfield* hf = rcAllocHeightfield(); + int width = Config.width + (Config.borderSize * 2); + rcCreateHeightfield(Context, *hf, width, width, bbMin, bbMax, Config.cs, Config.ch); + rcClearUnwalkableTriangles(Context, Config.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas); + rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb); + + printf("[%02u,%02u] Triangles rasterized!\n", X, Y); + + // Once all geometry is rasterized, we do initial pass of filtering to + // remove unwanted overhangs caused by the conservative rasterization + // as well as filter spans where the character cannot possibly stand. + rcFilterLowHangingWalkableObstacles(Context, Config.walkableClimb, *hf); + rcFilterLedgeSpans(Context, Config.walkableHeight, Config.walkableClimb, *hf); + rcFilterWalkableLowHeightSpans(Context, Config.walkableHeight, *hf); + + printf("[%02u,%02u] Filtering done!\n", X, Y); + + // Compact the heightfield so that it is faster to handle from now on. + // This will result in more cache coherent data as well as the neighbours + // between walkable cells will be calculated. + rcCompactHeightfield* chf = rcAllocCompactHeightfield(); + rcBuildCompactHeightfield(Context, Config.walkableHeight, Config.walkableClimb, *hf, *chf); + + rcFreeHeightField(hf); + + printf("[%02u,%02u] Heightfield compressed!\n", X, Y); + + // Erode the walkable area by agent radius. + rcErodeWalkableArea(Context, Config.walkableRadius, *chf); + // Prepare for region partitioning, by calculating distance field along the walkable surface. + rcBuildDistanceField(Context, *chf); + // Partition the walkable surface into simple regions without holes. + rcBuildRegions(Context, *chf, Config.borderSize, Config.minRegionArea, Config.mergeRegionArea); + + printf("[%02u,%02u] Regions built!\n", X, Y); + + // Create contours. + rcContourSet* cset = rcAllocContourSet(); + rcBuildContours(Context, *chf, Config.maxSimplificationError, Config.maxEdgeLen, *cset); + + // Build polygon navmesh from the contours. + rcPolyMesh* pmesh = rcAllocPolyMesh(); + rcBuildPolyMesh(Context, *cset, Config.maxVertsPerPoly, *pmesh); + + printf("[%02u,%02u] Polymesh built!\n", X, Y); + + // Build detail mesh. + rcPolyMeshDetail* dmesh = rcAllocPolyMeshDetail(); + rcBuildPolyMeshDetail(Context, *pmesh, *chf, Config.detailSampleDist, Config.detailSampleMaxError, *dmesh); + + printf("[%02u,%02u] Polymesh detail built!\n", X, Y); + + rcFreeCompactHeightfield(chf); + rcFreeContourSet(cset); + + // Remove padding from the polymesh data. (Remove this odditity) + for (int i = 0; i < pmesh->nverts; ++i) + { + unsigned short* v = &pmesh->verts[i * 3]; + v[0] -= (unsigned short)Config.borderSize; + v[2] -= (unsigned short)Config.borderSize; + } + + // Set flags according to area types (e.g. Swim for Water) + for (int i = 0; i < pmesh->npolys; i++) + { + if (pmesh->areas[i] == Constants::POLY_AREA_ROAD || pmesh->areas[i] == Constants::POLY_AREA_TERRAIN) + pmesh->flags[i] = Constants::POLY_FLAG_WALK; + else if (pmesh->areas[i] == (int)Constants::POLY_AREA_WATER) + pmesh->flags[i] = Constants::POLY_FLAG_SWIM; + } + + // get original bounds + float* tilebMin; + float* tilebMax; + CalculateTileBounds(tilebMin, tilebMax); + tilebMin[1] = bbMin[1]; + tilebMax[1] = bbMax[1]; + + dtNavMeshCreateParams params; + // PolyMesh data + params.verts = pmesh->verts; + params.vertCount = pmesh->nverts; + params.polys = pmesh->polys; + params.polyAreas = pmesh->areas; + params.polyFlags = pmesh->flags; + params.polyCount = pmesh->npolys; + params.nvp = pmesh->nvp; + // PolyMeshDetail data + params.detailMeshes = dmesh->meshes; + params.detailVerts = dmesh->verts; + params.detailVertsCount = dmesh->nverts; + params.detailTris = dmesh->tris; + params.detailTriCount = dmesh->ntris; + // Copy bounding box + params.bmin[0] = tilebMin[0]; + params.bmin[1] = tilebMin[1]; + params.bmin[2] = tilebMin[2]; + params.bmax[0] = tilebMax[0]; + params.bmax[1] = tilebMax[1]; + params.bmax[2] = tilebMax[2]; + // General settings + params.ch = Config.ch; + params.cs = Config.cs; + params.walkableClimb = Config.walkableClimb; + params.walkableHeight = Config.walkableHeight; + params.walkableRadius = Config.walkableRadius; + params.tileX = X; + params.tileY = Y; + params.tileSize = Config.width; + int navDataSize; + uint8* navData; + printf("[%02u,%02u] Creating the navmesh!\n", X, Y); + bool result = dtCreateNavMeshData(¶ms, &navData, &navDataSize); + if (result) + { + printf("[%02u,%02u] NavMesh created, size %u!\n", X, Y, navDataSize); + DataSize = navDataSize; + rcFreePolyMesh(pmesh); + rcFreePolyMeshDetail(dmesh); + Cache->Clear(); + return navData; + } + + rcFreePolyMesh(pmesh); + rcFreePolyMeshDetail(dmesh); + return NULL; +} diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h index badb05295e5..7dff363cabe 100644 --- a/src/tools/mesh_extractor/TileBuilder.h +++ b/src/tools/mesh_extractor/TileBuilder.h @@ -5,10 +5,12 @@ #include "Geometry.h" +class WDT; + class TileBuilder { public: - TileBuilder(std::string world, int x, int y); + TileBuilder(std::string world, int x, int y, WDT* wdt); void CalculateTileBounds(float*& bmin, float*& bmax); uint8* Build(); @@ -17,6 +19,9 @@ public: int Y; int MapId; rcConfig Config; + rcContext* Context; Geometry* _Geometry; + uint32 DataSize; + WDT* Wdt; }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index ac14b9eca69..4cf20a4cf9d 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -5,6 +5,7 @@ #include #include "g3d/Matrix4.h" +#include "DetourNavMesh.h" #include "Common.h" #include "Constants.h" @@ -523,6 +524,21 @@ public: virtual float Scale() const { return 1.0f; }; }; +#define MMAP_MAGIC 0x4d4d4150 // 'MMAP' +#define MMAP_VERSION 3 + +struct MmapTileHeader +{ + uint32 mmapMagic; + uint32 dtVersion; + uint32 mmapVersion; + uint32 size; + bool usesLiquids : 1; + + MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION), + mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) {} +}; + class Utils { public: diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index e5a14d55c0c..1a772a36558 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -92,7 +92,7 @@ void WorldModelHandler::InsertModelGeometry( std::vector& verts, std::v } } - if (def.DoodadSet >= 0 && def.DoodadSet < root->DoodadSets.size()) + if (def.DoodadSet < root->DoodadSets.size()) { DoodadSet set = root->DoodadSets[def.DoodadSet]; std::vector instances; -- cgit v1.2.3 From 5725b068d22a22b3e77f8887b2a1736854d85027 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 14:28:50 -0500 Subject: Tools/MeshExtractor: Fixed an uninitialized variable error. --- src/tools/mesh_extractor/ContinentBuilder.cpp | 2 +- src/tools/mesh_extractor/DoodadHandler.cpp | 2 +- src/tools/mesh_extractor/DoodadHandler.h | 2 +- src/tools/mesh_extractor/TileBuilder.cpp | 20 ++++++++++++-------- src/tools/mesh_extractor/Utils.h | 2 +- 5 files changed, 16 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index f861dff1648..c63445b2287 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -29,7 +29,7 @@ void ContinentBuilder::Build() MmapTileHeader header; header.size = builder.DataSize; fwrite(&header, sizeof(MmapTileHeader), 1, f); - fwrite(nav, sizeof(uint8), builder.DataSize, f); + fwrite(nav, sizeof(unsigned char), builder.DataSize, f); } fclose(f); dtFree(nav); diff --git a/src/tools/mesh_extractor/DoodadHandler.cpp b/src/tools/mesh_extractor/DoodadHandler.cpp index 89fcaba5601..aa298cea698 100644 --- a/src/tools/mesh_extractor/DoodadHandler.cpp +++ b/src/tools/mesh_extractor/DoodadHandler.cpp @@ -88,7 +88,7 @@ void DoodadHandler::ReadDoodadPaths( Chunk* id, Chunk* data ) } } -void DoodadHandler::InsertModelGeometry(const DoodadDefinition def, Model* model) +void DoodadHandler::InsertModelGeometry(const DoodadDefinition& def, Model* model) { G3D::Matrix4 transformation = Utils::GetTransformation(def); uint32 vertOffset = Vertices.size(); diff --git a/src/tools/mesh_extractor/DoodadHandler.h b/src/tools/mesh_extractor/DoodadHandler.h index c426504da32..aa7e3cac20d 100644 --- a/src/tools/mesh_extractor/DoodadHandler.h +++ b/src/tools/mesh_extractor/DoodadHandler.h @@ -43,7 +43,7 @@ protected: private: void ReadDoodadDefinitions(Chunk* chunk); void ReadDoodadPaths(Chunk* id, Chunk* data); - void InsertModelGeometry(const DoodadDefinition def, Model* model); + void InsertModelGeometry(const DoodadDefinition& def, Model* model); std::set _drawn; std::vector* _definitions; std::vector* _paths; diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 4736274706d..445641fc009 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -111,7 +111,7 @@ uint8* TileBuilder::Build() rcClearUnwalkableTriangles(Context, Config.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas); rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb); - printf("[%02u,%02u] Triangles rasterized!\n", X, Y); + printf("[%02i,%02i] Triangles rasterized!\n", X, Y); // Once all geometry is rasterized, we do initial pass of filtering to // remove unwanted overhangs caused by the conservative rasterization @@ -120,7 +120,7 @@ uint8* TileBuilder::Build() rcFilterLedgeSpans(Context, Config.walkableHeight, Config.walkableClimb, *hf); rcFilterWalkableLowHeightSpans(Context, Config.walkableHeight, *hf); - printf("[%02u,%02u] Filtering done!\n", X, Y); + printf("[%02i,%02i] Filtering done!\n", X, Y); // Compact the heightfield so that it is faster to handle from now on. // This will result in more cache coherent data as well as the neighbours @@ -130,7 +130,7 @@ uint8* TileBuilder::Build() rcFreeHeightField(hf); - printf("[%02u,%02u] Heightfield compressed!\n", X, Y); + printf("[%02i,%02i] Heightfield compressed!\n", X, Y); // Erode the walkable area by agent radius. rcErodeWalkableArea(Context, Config.walkableRadius, *chf); @@ -139,7 +139,7 @@ uint8* TileBuilder::Build() // Partition the walkable surface into simple regions without holes. rcBuildRegions(Context, *chf, Config.borderSize, Config.minRegionArea, Config.mergeRegionArea); - printf("[%02u,%02u] Regions built!\n", X, Y); + printf("[%02i,%02i] Regions built!\n", X, Y); // Create contours. rcContourSet* cset = rcAllocContourSet(); @@ -149,13 +149,13 @@ uint8* TileBuilder::Build() rcPolyMesh* pmesh = rcAllocPolyMesh(); rcBuildPolyMesh(Context, *cset, Config.maxVertsPerPoly, *pmesh); - printf("[%02u,%02u] Polymesh built!\n", X, Y); + printf("[%02i,%02i] Polymesh built!\n", X, Y); // Build detail mesh. rcPolyMeshDetail* dmesh = rcAllocPolyMeshDetail(); rcBuildPolyMeshDetail(Context, *pmesh, *chf, Config.detailSampleDist, Config.detailSampleMaxError, *dmesh); - printf("[%02u,%02u] Polymesh detail built!\n", X, Y); + printf("[%02i,%02i] Polymesh detail built!\n", X, Y); rcFreeCompactHeightfield(chf); rcFreeContourSet(cset); @@ -215,13 +215,17 @@ uint8* TileBuilder::Build() params.tileX = X; params.tileY = Y; params.tileSize = Config.width; + + // Offmesh-connection settings + params.offMeshConCount = 0; // none for now + int navDataSize; uint8* navData; - printf("[%02u,%02u] Creating the navmesh!\n", X, Y); + printf("[%02i,%02i] Creating the navmesh!\n", X, Y); bool result = dtCreateNavMeshData(¶ms, &navData, &navDataSize); if (result) { - printf("[%02u,%02u] NavMesh created, size %u!\n", X, Y, navDataSize); + printf("[%02i,%02i] NavMesh created, size %i!\n", X, Y, navDataSize); DataSize = navDataSize; rcFreePolyMesh(pmesh); rcFreePolyMeshDetail(dmesh); diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index 4cf20a4cf9d..188d47a88ce 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -533,7 +533,7 @@ struct MmapTileHeader uint32 dtVersion; uint32 mmapVersion; uint32 size; - bool usesLiquids : 1; + bool usesLiquids; MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION), mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) {} -- cgit v1.2.3 From 886f71df72a751abf1b742e67e7707cb623fd854 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 16:21:35 -0500 Subject: Tools/MeshExtract: Fixed linux build, thanks Dev[Acho]. Added a DBC class It will now autodetect your locale and start extracting mmaps as soon as started. --- src/tools/mesh_extractor/ADT.cpp | 9 +++- src/tools/mesh_extractor/CMakeLists.txt | 7 +++ src/tools/mesh_extractor/Cache.h | 4 +- src/tools/mesh_extractor/ContinentBuilder.cpp | 19 ++++++-- src/tools/mesh_extractor/ContinentBuilder.h | 4 +- src/tools/mesh_extractor/DBC.cpp | 64 ++++++++++++++++++++++++++ src/tools/mesh_extractor/DBC.h | 51 ++++++++++++++++++++ src/tools/mesh_extractor/DoodadHandler.cpp | 2 +- src/tools/mesh_extractor/MPQManager.cpp | 59 ++++++++++++++---------- src/tools/mesh_extractor/MPQManager.h | 6 ++- src/tools/mesh_extractor/MeshExtractor.cpp | 13 ++++++ src/tools/mesh_extractor/TileBuilder.cpp | 7 ++- src/tools/mesh_extractor/TileBuilder.h | 2 +- src/tools/mesh_extractor/Utils.cpp | 4 +- src/tools/mesh_extractor/Utils.h | 4 +- src/tools/mesh_extractor/WorldModelHandler.cpp | 2 +- 16 files changed, 214 insertions(+), 43 deletions(-) create mode 100644 src/tools/mesh_extractor/DBC.cpp create mode 100644 src/tools/mesh_extractor/DBC.h (limited to 'src') diff --git a/src/tools/mesh_extractor/ADT.cpp b/src/tools/mesh_extractor/ADT.cpp index c564d7193cf..98bce8b2057 100644 --- a/src/tools/mesh_extractor/ADT.cpp +++ b/src/tools/mesh_extractor/ADT.cpp @@ -29,7 +29,14 @@ ADT::~ADT() void ADT::Read() { - Header.Read(Data->GetChunkByName("MHDR")->GetStream()); + Chunk* mhdr = Data->GetChunkByName("MHDR"); + if (!mhdr) + { + delete Data; + Data = NULL; + return; + } + Header.Read(mhdr->GetStream()); MapChunks.reserve(16 * 16); int mapChunkIndex = 0; diff --git a/src/tools/mesh_extractor/CMakeLists.txt b/src/tools/mesh_extractor/CMakeLists.txt index 09bd2982213..8ef48a90742 100644 --- a/src/tools/mesh_extractor/CMakeLists.txt +++ b/src/tools/mesh_extractor/CMakeLists.txt @@ -15,6 +15,13 @@ if( UNIX ) include_directories ( ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/Database + ${CMAKE_SOURCE_DIR}/src/server/shared/Database/Implementation + ${CMAKE_SOURCE_DIR}/src/server/shared/Threading + ${CMAKE_SOURCE_DIR}/src/server/shared/Logging + ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour ${CMAKE_SOURCE_DIR}/dep/libmpq diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h index 799878bdd3b..83b6ba6ca7a 100644 --- a/src/tools/mesh_extractor/Cache.h +++ b/src/tools/mesh_extractor/Cache.h @@ -25,7 +25,7 @@ public: T* Get(K key) { - std::map::iterator itr = _items.find(key); + typename std::map::iterator itr = _items.find(key); if (itr != _items.end()) return itr->second; return NULL; @@ -33,7 +33,7 @@ public: void Clear() { - for (std::map::iterator itr = _items.begin(); itr != _items.end(); ++itr) + for (typename std::map::iterator itr = _items.begin(); itr != _items.end(); ++itr) delete itr->second; _items.clear(); } diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index c63445b2287..7391ebb8767 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -6,7 +6,9 @@ void ContinentBuilder::Build() { - FILE* mmap = fopen("608.mmap", "wb"); + char buff[50]; + sprintf(buff, "%03u.mmap", MapId); + FILE* mmap = fopen(buff, "wb"); dtNavMeshParams params; params.maxPolys = 32768; params.maxTiles = 4096; @@ -19,19 +21,26 @@ void ContinentBuilder::Build() fclose(mmap); for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) { - TileBuilder builder(Continent, itr->X, itr->Y, TileMap); + TileBuilder builder(Continent, itr->X, itr->Y, TileMap, MapId); char buff[100]; - sprintf(buff, "%03u%02u%02u.mmtile", builder.MapId, itr->X, itr->Y); - FILE* f = fopen(buff, "wb"); + sprintf(buff, "%03u%02u%02u.mmtile", MapId, itr->X, itr->Y); + FILE* f = fopen(buff, "r"); + if (f) // Check if file already exists. + { + fclose(f); + continue; + } uint8* nav = builder.Build(); if (nav) { + fclose(f); + f = fopen(buff, "wb"); MmapTileHeader header; header.size = builder.DataSize; fwrite(&header, sizeof(MmapTileHeader), 1, f); fwrite(nav, sizeof(unsigned char), builder.DataSize, f); + fclose(f); } - fclose(f); dtFree(nav); printf("[%02u,%02u] Tile Built!\n", itr->X, itr->Y); } diff --git a/src/tools/mesh_extractor/ContinentBuilder.h b/src/tools/mesh_extractor/ContinentBuilder.h index 7db141ddcf1..92c97c5f7e0 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.h +++ b/src/tools/mesh_extractor/ContinentBuilder.h @@ -2,14 +2,16 @@ #define CONT_BUILDER_H #include #include "WDT.h" +#include "Common.h" class ContinentBuilder { public: - ContinentBuilder(std::string continent, WDT* wdt) : Continent(continent), TileMap(wdt) {} + ContinentBuilder(std::string continent, uint32 mapId, WDT* wdt) : MapId(mapId), Continent(continent), TileMap(wdt) {} void Build(); private: std::string Continent; WDT* TileMap; + uint32 MapId; }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/DBC.cpp b/src/tools/mesh_extractor/DBC.cpp new file mode 100644 index 00000000000..be04ce070ee --- /dev/null +++ b/src/tools/mesh_extractor/DBC.cpp @@ -0,0 +1,64 @@ +#include +#include "DBC.h" +#include "Common.h" + +DBC::DBC( FILE* stream ) : StringBlock(NULL), IsFaulty(true), StringBlockSize(0) +{ + char magic[5]; + fread(&magic, sizeof(char), 4, stream); + magic[4] = '\0'; + fread(&RecordCount, sizeof(uint32), 1, stream); + Records.reserve(RecordCount); + fread(&Fields, sizeof(uint32), 1, stream); + fread(&RecordSize, sizeof(uint32), 1, stream); + fread(&StringBlockSize, sizeof(uint32), 1, stream); + + for (int i = 0; i < RecordCount; i++) + { + Record* rec = new Record(this); + Records.push_back(rec); + int size = 0; + for (int f = 0; f < Fields; f++) + { + if (size + 4 > RecordSize) + { + IsFaulty = true; + break; + } + uint32 tmp; + fread(&tmp, sizeof(uint32), 1, stream); + rec->Values.push_back(tmp); + size += 4; + } + } + StringBlock = new uint8[StringBlockSize]; + fread(StringBlock, sizeof(uint8), StringBlockSize, stream); +} + +std::string DBC::GetStringByOffset( int offset ) +{ + int len = 0; + for (int i = offset; i < StringBlockSize; i++) + { + if (!StringBlock[i]) + { + len = (i - offset); + break; + } + } + char* d = new char[len+1]; + strcpy(d, (const char*)(StringBlock + offset)); + d[len] = '\0'; + std::string val = std::string(d); + delete d; + return val; +} + +Record* DBC::GetRecordById( int id ) +{ + // we assume Id is index 0 + for (std::vector::iterator itr = Records.begin(); itr != Records.end(); ++itr) + if ((*itr)->Values[0] == id) + return *itr; + return NULL; +} diff --git a/src/tools/mesh_extractor/DBC.h b/src/tools/mesh_extractor/DBC.h new file mode 100644 index 00000000000..6c86c1391dd --- /dev/null +++ b/src/tools/mesh_extractor/DBC.h @@ -0,0 +1,51 @@ +#ifndef DBC_H +#define DBC_H +#include +#include "Common.h" + +class Record; + +class DBC +{ +public: + DBC(FILE* stream); + + std::string GetStringByOffset(int offset); + + Record* GetRecordById(int id); + + std::string Name; + std::vector Records; + int RecordCount; + int Fields; + int RecordSize; + uint8* StringBlock; + uint32 StringBlockSize; + bool IsFaulty; +}; + +class Record +{ +public: + Record(DBC* dbc) : Source(dbc) {} + + DBC* Source; + std::vector Values; + + int operator[](int index) + { + return Values[index]; + } + + float GetFloat(int index) + { + return *(float*)(&Values[index]); + } + + std::string GetString(int index) + { + return Source->GetStringByOffset(Values[index]); + } +}; + +#endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/DoodadHandler.cpp b/src/tools/mesh_extractor/DoodadHandler.cpp index aa298cea698..28bb9da5f21 100644 --- a/src/tools/mesh_extractor/DoodadHandler.cpp +++ b/src/tools/mesh_extractor/DoodadHandler.cpp @@ -2,7 +2,7 @@ #include "Chunk.h" #include "Cache.h" #include "Model.h" -#include "g3d/Matrix4.h" +#include "G3D/Matrix4.h" DoodadHandler::DoodadHandler( ADT* adt ) : ObjectDataHandler(adt), _definitions(NULL), _paths(NULL) { diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp index 35d4c91fc14..24e7e827548 100644 --- a/src/tools/mesh_extractor/MPQManager.cpp +++ b/src/tools/mesh_extractor/MPQManager.cpp @@ -1,5 +1,7 @@ #include "MPQManager.h" #include "MPQ.h" +#include "DBC.h" +#include "Utils.h" char* MPQManager::Files[] = { "common.MPQ", @@ -11,42 +13,43 @@ char* MPQManager::Files[] = { "patch-3.MPQ" }; +char* MPQManager::Languages[] = { "esES", "enUS", "enGB", "esMX", "deDE" }; + void MPQManager::Initialize() { - LoadMPQs(); + InitializeDBC(); + uint32 size = sizeof(Files) / sizeof(char*); + for (uint32 i = 0; i < size; ++i) + { + MPQArchive* arc = new MPQArchive(std::string("Data/" + std::string(Files[i])).c_str()); + Archives.push_front(arc); + printf("Opened %s\n", Files[i]); + } } void MPQManager::LoadMaps() { - + DBC* file = GetDBC("Map"); + printf("NAME %s\n", file->GetRecordById(608)->GetString(1).c_str()); } -void MPQManager::LoadMPQs() +void MPQManager::InitializeDBC() { - // Load the locale MPQ files first - char filename[512]; - - /*sprintf(filename,"Data/%s/locale-%s.MPQ", langs[locale], langs[locale]);*/ - Archives.push_front(new MPQArchive("Data/enUS/locale-enUS.MPQ")); - - for(int i = 0; i < 3; ++i) + CurLocale = 0; + std::string fileName; + uint32 size = sizeof(Languages) / sizeof(char*); + for (uint32 i = 0; i < size; ++i) { - char ext[3] = ""; - if (i) - sprintf(ext, "-%i", i + 1); - - sprintf(filename, "Data/enUS/patch-enUS%s.MPQ", ext); - Archives.push_front(new MPQArchive(filename)); + fileName = "Data/" + std::string(Languages[i]) + "/locale-" + std::string(Languages[i]) + ".MPQ"; + FILE* file = fopen(fileName.c_str(), "rb"); + if (file) + { + CurLocale = i; + break; + } } - - // Now load the common MPQ files - int count = sizeof(Files) / sizeof(char*); - for (int i = 0; i < count; ++i) - { - sprintf(filename, "Data/%s", Files[i]); - Archives.push_front(new MPQArchive(filename)); - } - printf("Loaded %u MPQ files succesfully\n", Archives.size()); + Archives.push_front(new MPQArchive(fileName.c_str())); + printf("Using locale: %s\n", Languages[CurLocale]); } FILE* MPQManager::GetFile( std::string path ) @@ -56,3 +59,9 @@ FILE* MPQManager::GetFile( std::string path ) return NULL; return file.GetFileStream(); } + +DBC* MPQManager::GetDBC( std::string name ) +{ + std::string path = "DBFilesClient\\" + name + ".dbc"; + return new DBC(GetFile(path)); +} diff --git a/src/tools/mesh_extractor/MPQManager.h b/src/tools/mesh_extractor/MPQManager.h index e10066ae4a6..725e0168237 100644 --- a/src/tools/mesh_extractor/MPQManager.h +++ b/src/tools/mesh_extractor/MPQManager.h @@ -3,6 +3,7 @@ #include "MPQ.h" +class DBC; class MPQManager { public: @@ -12,12 +13,15 @@ public: void Initialize(); void LoadMaps(); FILE* GetFile(std::string path); + DBC* GetDBC(std::string name); std::deque Archives; + uint32 CurLocale; static char* Files[]; + static char* Languages[]; protected: - void LoadMPQs(); + void InitializeDBC(); }; extern MPQManager* MPQHandler; diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 38a120449bc..77b5a8e8c3d 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -2,6 +2,7 @@ #include "WDT.h" #include "ContinentBuilder.h" #include "Cache.h" +#include "DBC.h" #include "Common.h" #include "LoginDatabase.h" @@ -12,6 +13,17 @@ CacheClass* Cache; void ExtractAllMaps() { + DBC* dbc = MPQHandler->GetDBC("Map"); + for (std::vector::iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr) + { + std::string name = (*itr)->GetString(1); + WDT wdt("World\\maps\\" + name + "\\" + name + ".wdt"); + if (!wdt.IsValid || wdt.IsGlobalModel) + continue; + ContinentBuilder builder(name, (*itr)->Values[0], &wdt); + builder.Build(); + } + /* WDT wdt("World\\maps\\DalaranPrison\\DalaranPrison.wdt"); if (!wdt.IsValid) return; @@ -23,6 +35,7 @@ void ExtractAllMaps() } ContinentBuilder builder("DalaranPrison", &wdt); builder.Build(); + */ } int main(int argc, char* argv[]) diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 445641fc009..8bbfd5afb69 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -9,7 +9,7 @@ #include "RecastAlloc.h" #include "DetourNavMeshBuilder.h" -TileBuilder::TileBuilder(std::string world, int x, int y, WDT* wdt) : _Geometry(NULL), World(world), X(x), Y(y), MapId(608), DataSize(0), Wdt(wdt) +TileBuilder::TileBuilder(std::string world, int x, int y, WDT* wdt, uint32 mapId) : _Geometry(NULL), World(world), X(x), Y(y), MapId(mapId), DataSize(0), Wdt(wdt) { // Cell Size = TileSize / TileVoxelSize // 1800 = TileVoxelSize @@ -54,6 +54,11 @@ uint8* TileBuilder::Build() { adt = new ADT(Utils::GetAdtPath(World, X, Y)); adt->Read(); + if (!adt->Data) + { + delete adt; + return NULL; + } Cache->AdtCache.Insert(std::make_pair(X, Y), adt); } _Geometry->AddAdt(adt); diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h index 7dff363cabe..261675af7e2 100644 --- a/src/tools/mesh_extractor/TileBuilder.h +++ b/src/tools/mesh_extractor/TileBuilder.h @@ -10,7 +10,7 @@ class WDT; class TileBuilder { public: - TileBuilder(std::string world, int x, int y, WDT* wdt); + TileBuilder(std::string world, int x, int y, WDT* wdt, uint32 mapId); void CalculateTileBounds(float*& bmin, float*& bmax); uint8* Build(); diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index c7c0cff0d42..2f07bd20080 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -2,8 +2,8 @@ #include "WorldModelHandler.h" #include "Constants.h" #include -#include "g3d/Matrix4.h" -#include "g3d/Quat.h" +#include "G3D/Matrix4.h" +#include "G3D/Quat.h" const float Constants::TileSize = 533.0f + (1/3.0f); const float Constants::MaxXY = 32.0f * Constants::TileSize; diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index 188d47a88ce..c247169df73 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -4,7 +4,7 @@ #include #include -#include "g3d/Matrix4.h" +#include "G3D/Matrix4.h" #include "DetourNavMesh.h" #include "Common.h" @@ -573,7 +573,7 @@ public: return false; return true; } - static std::string Utils::Replace( std::string str, const std::string& oldStr, const std::string& newStr ); + static std::string Replace( std::string str, const std::string& oldStr, const std::string& newStr ); static G3D::Matrix4 GetWmoDoodadTransformation( DoodadInstance inst, WorldModelDefinition root ); }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index 1a772a36558..636b06f6f73 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -4,7 +4,7 @@ #include "Cache.h" #include "Model.h" #include "Common.h" -#include "g3d/Matrix4.h" +#include "G3D/Matrix4.h" #include WorldModelDefinition WorldModelDefinition::Read( FILE* file ) -- cgit v1.2.3 From eba6980b9a52f55859cb3bd93235e14866769514 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 16:26:43 -0500 Subject: Tools/MeshExtractor: Allow to extract only 1 map ( via command line ) --- src/tools/mesh_extractor/MeshExtractor.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 77b5a8e8c3d..a99cc4475a0 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -11,16 +11,20 @@ LoginDatabaseWorkerPool LoginDatabase; MPQManager* MPQHandler; CacheClass* Cache; -void ExtractAllMaps() +void ExtractAllMaps(uint32 onlyMap) { DBC* dbc = MPQHandler->GetDBC("Map"); for (std::vector::iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr) { + uint32 mapId = (*itr)->Values[0]; + if (onlyMap && mapId != onlyMap) + continue; std::string name = (*itr)->GetString(1); WDT wdt("World\\maps\\" + name + "\\" + name + ".wdt"); if (!wdt.IsValid || wdt.IsGlobalModel) continue; - ContinentBuilder builder(name, (*itr)->Values[0], &wdt); + printf("Building %s MapId %u\n", name, mapId); + ContinentBuilder builder(name, mapId, &wdt); builder.Build(); } /* @@ -45,7 +49,10 @@ int main(int argc, char* argv[]) MPQHandler = new MPQManager(); MPQHandler->Initialize(); MPQHandler->LoadMaps(); - ExtractAllMaps(); + uint32 onlyMap = 0; + if (argc == 2) + onlyMap = uint32(atoi(argv[1])); + ExtractAllMaps(onlyMap); return 0; } -- cgit v1.2.3 From 9b97a89ef8e1dd1694985d1fc8e88808da1550cd Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 17:09:44 -0500 Subject: Tools/MeshExtractor: Fixed a crash and some other mistakes. First glances of multithreading ( need to figure out a way around StormLib ) --- src/tools/mesh_extractor/ContinentBuilder.cpp | 88 +++++++++++++++++++++------ src/tools/mesh_extractor/MapChunk.cpp | 1 + src/tools/mesh_extractor/MeshExtractor.cpp | 2 +- src/tools/mesh_extractor/TileBuilder.cpp | 2 +- src/tools/mesh_extractor/TileBuilder.h | 3 +- 5 files changed, 73 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index 7391ebb8767..02a4d3626b7 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -3,32 +3,29 @@ #include "WDT.h" #include "Utils.h" #include "DetourNavMesh.h" +#include "ace/Task.h" -void ContinentBuilder::Build() +class BuilderThread : public ACE_Task { - char buff[50]; - sprintf(buff, "%03u.mmap", MapId); - FILE* mmap = fopen(buff, "wb"); - dtNavMeshParams params; - params.maxPolys = 32768; - params.maxTiles = 4096; - params.orig[0] = -17066.666f; - params.orig[1] = 0.0f; - params.orig[2] = -17066.666f; - params.tileHeight = 533.33333f; - params.tileWidth = 533.33333f; - fwrite(¶ms, sizeof(dtNavMeshParams), 1, mmap); - fclose(mmap); - for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) +private: + int X, Y, MapId; + std::string Continent; +public: + BuilderThread() : Free(true) {} + void SetData(int x, int y, int map, std::string cont) { X = x; Y = y; MapId = map; Continent = cont; } + + int svc() { - TileBuilder builder(Continent, itr->X, itr->Y, TileMap, MapId); + Free = false; + TileBuilder builder(Continent, X, Y, MapId); char buff[100]; - sprintf(buff, "%03u%02u%02u.mmtile", MapId, itr->X, itr->Y); + sprintf(buff, "%03u%02u%02u.mmtile", MapId, X, Y); FILE* f = fopen(buff, "r"); if (f) // Check if file already exists. { fclose(f); - continue; + Free = true; + return 0; } uint8* nav = builder.Build(); if (nav) @@ -42,6 +39,59 @@ void ContinentBuilder::Build() fclose(f); } dtFree(nav); - printf("[%02u,%02u] Tile Built!\n", itr->X, itr->Y); + printf("[%02u,%02u] Tile Built!\n", X, Y); + Free = true; + return 0; } + + bool Free; +}; + +void ContinentBuilder::Build() +{ + char buff[50]; + sprintf(buff, "%03u.mmap", MapId); + FILE* mmap = fopen(buff, "wb"); + dtNavMeshParams params; + params.maxPolys = 32768; + params.maxTiles = 4096; + params.orig[0] = -17066.666f; + params.orig[1] = 0.0f; + params.orig[2] = -17066.666f; + params.tileHeight = 533.33333f; + params.tileWidth = 533.33333f; + fwrite(¶ms, sizeof(dtNavMeshParams), 1, mmap); + fclose(mmap); + std::vector Threads; + /*for (uint32 i = 0; i < 1; ++i) + Threads.push_back(new BuilderThread());*/ + for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) + { + BuilderThread th; + th.SetData(itr->X, itr->Y, MapId, Continent); + th.svc(); + /*bool next = false; + while (!next) + { + for (std::vector::iterator _th = Threads.begin(); _th != Threads.end(); ++_th) + { + if ((*_th)->Free) + { + (*_th)->SetData(itr->X, itr->Y, MapId, Continent); + (*_th)->activate(); + next = true; + break; + } + } + // Wait for 20 seconds + ACE_OS::sleep(ACE_Time_Value (0, 20000)); + }*/ + } + + /*// Free memory + for (std::vector::iterator _th = Threads.begin(); _th != Threads.end(); ++_th) + { + (*_th)->wait(); + delete *_th; + }*/ } diff --git a/src/tools/mesh_extractor/MapChunk.cpp b/src/tools/mesh_extractor/MapChunk.cpp index 61c106f9766..debde08cda8 100644 --- a/src/tools/mesh_extractor/MapChunk.cpp +++ b/src/tools/mesh_extractor/MapChunk.cpp @@ -7,6 +7,7 @@ MapChunk::MapChunk( ADT* _adt, Chunk* chunk ) : Adt(_adt), Source(chunk) FILE* stream = chunk->GetStream(); Header.Read(stream); fseek(stream, chunk->Offset, SEEK_SET); + Index = Header.IndexX + Header.IndexY * 16; GenerateVertices(stream); } diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index a99cc4475a0..7ae6afadb84 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -23,7 +23,7 @@ void ExtractAllMaps(uint32 onlyMap) WDT wdt("World\\maps\\" + name + "\\" + name + ".wdt"); if (!wdt.IsValid || wdt.IsGlobalModel) continue; - printf("Building %s MapId %u\n", name, mapId); + printf("Building %s MapId %u\n", name.c_str(), mapId); ContinentBuilder builder(name, mapId, &wdt); builder.Build(); } diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 8bbfd5afb69..baf1fa0375c 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -9,7 +9,7 @@ #include "RecastAlloc.h" #include "DetourNavMeshBuilder.h" -TileBuilder::TileBuilder(std::string world, int x, int y, WDT* wdt, uint32 mapId) : _Geometry(NULL), World(world), X(x), Y(y), MapId(mapId), DataSize(0), Wdt(wdt) +TileBuilder::TileBuilder(std::string world, int x, int y, uint32 mapId) : _Geometry(NULL), World(world), X(x), Y(y), MapId(mapId), DataSize(0) { // Cell Size = TileSize / TileVoxelSize // 1800 = TileVoxelSize diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h index 261675af7e2..f91a732f70c 100644 --- a/src/tools/mesh_extractor/TileBuilder.h +++ b/src/tools/mesh_extractor/TileBuilder.h @@ -10,7 +10,7 @@ class WDT; class TileBuilder { public: - TileBuilder(std::string world, int x, int y, WDT* wdt, uint32 mapId); + TileBuilder(std::string world, int x, int y, uint32 mapId); void CalculateTileBounds(float*& bmin, float*& bmax); uint8* Build(); @@ -22,6 +22,5 @@ public: rcContext* Context; Geometry* _Geometry; uint32 DataSize; - WDT* Wdt; }; #endif \ No newline at end of file -- cgit v1.2.3 From 95db9605ce227403eb4ea7fa46c91f47eb51a3ac Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 17:28:20 -0500 Subject: Tools/MeshExtractor: Removed extra fclose --- src/tools/mesh_extractor/ContinentBuilder.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index 02a4d3626b7..29541da508c 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -30,7 +30,6 @@ public: uint8* nav = builder.Build(); if (nav) { - fclose(f); f = fopen(buff, "wb"); MmapTileHeader header; header.size = builder.DataSize; -- cgit v1.2.3 From 6b23d2f7710a7b1e39ec7d43c9a3b04345caa988 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 28 Sep 2012 19:08:01 -0500 Subject: Core/Build: Fixed build --- src/server/scripts/Commands/cs_mmaps.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index e4a0ebf7f24..be2d52b5925 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -32,6 +32,9 @@ #include "MMapFactory.h" #include "Map.h" #include "TargetedMovementGenerator.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" class mmaps_commandscript : public CommandScript { -- cgit v1.2.3 From 3bea28e62c00a5f73e4b58cd554db28666b1d54b Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 29 Sep 2012 06:24:35 -0500 Subject: Tools/MeshExtractor: Fixed a crash and bad data for liquids --- src/tools/mesh_extractor/ContinentBuilder.cpp | 1 + src/tools/mesh_extractor/LiquidHandler.cpp | 3 +++ src/tools/mesh_extractor/MapChunk.cpp | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index 29541da508c..9d3b18491f1 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -17,6 +17,7 @@ public: int svc() { Free = false; + printf("[%02i,%02i] Building tile", X, Y); TileBuilder builder(Continent, X, Y, MapId); char buff[100]; sprintf(buff, "%03u%02u%02u.mmtile", MapId, X, Y); diff --git a/src/tools/mesh_extractor/LiquidHandler.cpp b/src/tools/mesh_extractor/LiquidHandler.cpp index 3d0876aeb74..f6f8e5678c6 100644 --- a/src/tools/mesh_extractor/LiquidHandler.cpp +++ b/src/tools/mesh_extractor/LiquidHandler.cpp @@ -31,7 +31,10 @@ void LiquidHandler::HandleNewLiquid() float** heights = new float*[9]; for (int i = 0; i < 9; ++i) + { heights[i] = new float[9]; + memset(heights[i], 0, sizeof(float) * 9); + } H2ORenderMask renderMask; if (information.LiquidType != 2) diff --git a/src/tools/mesh_extractor/MapChunk.cpp b/src/tools/mesh_extractor/MapChunk.cpp index debde08cda8..67f4061035e 100644 --- a/src/tools/mesh_extractor/MapChunk.cpp +++ b/src/tools/mesh_extractor/MapChunk.cpp @@ -31,7 +31,7 @@ void MapChunk::GenerateTriangles() if (Adt->_LiquidHandler && !Adt->_LiquidHandler->MCNKData.empty()) { MCNKLiquidData& data = Adt->_LiquidHandler->MCNKData[Index]; - uint32 maxHeight = std::max( + float maxHeight = std::max( std::max( std::max(std::max(Vertices[topLeft].z, Vertices[topRight].z), Vertices[bottomLeft].z), Vertices[bottomRight].z), Vertices[center].z); -- cgit v1.2.3 From 1a7f0658b2a78a2c082b5f648548375b5d0f29e9 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 29 Sep 2012 12:49:14 -0500 Subject: Tools/MeshExtractor: * Fixed some crashes * Added multithreading support, default to 4 threads. * Added some command line arguments --- src/tools/mesh_extractor/ADT.cpp | 9 +--- src/tools/mesh_extractor/Cache.h | 3 ++ src/tools/mesh_extractor/ContinentBuilder.cpp | 19 ++++--- src/tools/mesh_extractor/ContinentBuilder.h | 3 +- src/tools/mesh_extractor/LiquidHandler.cpp | 4 ++ src/tools/mesh_extractor/MPQManager.cpp | 9 ++-- src/tools/mesh_extractor/MPQManager.h | 4 +- src/tools/mesh_extractor/MeshExtractor.cpp | 74 ++++++++++++++++++++------- src/tools/mesh_extractor/TileBuilder.cpp | 8 +-- 9 files changed, 82 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ADT.cpp b/src/tools/mesh_extractor/ADT.cpp index 98bce8b2057..c564d7193cf 100644 --- a/src/tools/mesh_extractor/ADT.cpp +++ b/src/tools/mesh_extractor/ADT.cpp @@ -29,14 +29,7 @@ ADT::~ADT() void ADT::Read() { - Chunk* mhdr = Data->GetChunkByName("MHDR"); - if (!mhdr) - { - delete Data; - Data = NULL; - return; - } - Header.Read(mhdr->GetStream()); + Header.Read(Data->GetChunkByName("MHDR")->GetStream()); MapChunks.reserve(16 * 16); int mapChunkIndex = 0; diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h index 83b6ba6ca7a..49e268ec507 100644 --- a/src/tools/mesh_extractor/Cache.h +++ b/src/tools/mesh_extractor/Cache.h @@ -3,6 +3,7 @@ #include #include #include "Common.h" +#include "ace/Synch.h" class WorldModelRoot; class Model; @@ -20,6 +21,7 @@ public: { if (_items.size() > FlushLimit) Clear(); + ACE_GUARD(ACE_Thread_Mutex, g, mutex); _items[key] = val; } @@ -39,6 +41,7 @@ public: } private: std::map _items; + ACE_Thread_Mutex mutex; }; class CacheClass diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index 9d3b18491f1..96f9085de8c 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -3,6 +3,7 @@ #include "WDT.h" #include "Utils.h" #include "DetourNavMesh.h" +#include "Cache.h" #include "ace/Task.h" class BuilderThread : public ACE_Task @@ -17,7 +18,7 @@ public: int svc() { Free = false; - printf("[%02i,%02i] Building tile", X, Y); + printf("[%02i,%02i] Building tile\n", X, Y); TileBuilder builder(Continent, X, Y, MapId); char buff[100]; sprintf(buff, "%03u%02u%02u.mmtile", MapId, X, Y); @@ -63,14 +64,11 @@ void ContinentBuilder::Build() fwrite(¶ms, sizeof(dtNavMeshParams), 1, mmap); fclose(mmap); std::vector Threads; - /*for (uint32 i = 0; i < 1; ++i) - Threads.push_back(new BuilderThread());*/ + for (uint32 i = 0; i < NumberOfThreads; ++i) + Threads.push_back(new BuilderThread()); for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) { - BuilderThread th; - th.SetData(itr->X, itr->Y, MapId, Continent); - th.svc(); - /*bool next = false; + bool next = false; while (!next) { for (std::vector::iterator _th = Threads.begin(); _th != Threads.end(); ++_th) @@ -85,13 +83,14 @@ void ContinentBuilder::Build() } // Wait for 20 seconds ACE_OS::sleep(ACE_Time_Value (0, 20000)); - }*/ + } } + Cache->Clear(); - /*// Free memory + // Free memory for (std::vector::iterator _th = Threads.begin(); _th != Threads.end(); ++_th) { (*_th)->wait(); delete *_th; - }*/ + } } diff --git a/src/tools/mesh_extractor/ContinentBuilder.h b/src/tools/mesh_extractor/ContinentBuilder.h index 92c97c5f7e0..d3da984595d 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.h +++ b/src/tools/mesh_extractor/ContinentBuilder.h @@ -7,11 +7,12 @@ class ContinentBuilder { public: - ContinentBuilder(std::string continent, uint32 mapId, WDT* wdt) : MapId(mapId), Continent(continent), TileMap(wdt) {} + ContinentBuilder(std::string continent, uint32 mapId, WDT* wdt, uint32 tn) : MapId(mapId), Continent(continent), TileMap(wdt), NumberOfThreads(tn) {} void Build(); private: std::string Continent; WDT* TileMap; uint32 MapId; + uint32 NumberOfThreads; }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/LiquidHandler.cpp b/src/tools/mesh_extractor/LiquidHandler.cpp index f6f8e5678c6..9a40e08b73a 100644 --- a/src/tools/mesh_extractor/LiquidHandler.cpp +++ b/src/tools/mesh_extractor/LiquidHandler.cpp @@ -25,7 +25,11 @@ void LiquidHandler::HandleNewLiquid() { H2OHeader h = header[i]; if (h.LayerCount == 0) + { + // Need to fill in missing data with dummies. + MCNKData.push_back(MCNKLiquidData(NULL, H2ORenderMask())); continue; + } fseek(stream, chunk->Offset + h.OffsetInformation, SEEK_SET); H2OInformation information = H2OInformation::Read(stream); diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp index 24e7e827548..5ea6198e76d 100644 --- a/src/tools/mesh_extractor/MPQManager.cpp +++ b/src/tools/mesh_extractor/MPQManager.cpp @@ -3,6 +3,8 @@ #include "DBC.h" #include "Utils.h" +#include "ace/Synch.h" + char* MPQManager::Files[] = { "common.MPQ", "common-2.MPQ", @@ -27,12 +29,6 @@ void MPQManager::Initialize() } } -void MPQManager::LoadMaps() -{ - DBC* file = GetDBC("Map"); - printf("NAME %s\n", file->GetRecordById(608)->GetString(1).c_str()); -} - void MPQManager::InitializeDBC() { CurLocale = 0; @@ -54,6 +50,7 @@ void MPQManager::InitializeDBC() FILE* MPQManager::GetFile( std::string path ) { + ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL); MPQFile file(path.c_str()); if (file.isEof()) return NULL; diff --git a/src/tools/mesh_extractor/MPQManager.h b/src/tools/mesh_extractor/MPQManager.h index 725e0168237..634c70cedeb 100644 --- a/src/tools/mesh_extractor/MPQManager.h +++ b/src/tools/mesh_extractor/MPQManager.h @@ -2,6 +2,7 @@ #define MPQ_MANAGER_H #include "MPQ.h" +#include "ace/Synch.h" class DBC; class MPQManager @@ -11,7 +12,6 @@ public: ~MPQManager() {} void Initialize(); - void LoadMaps(); FILE* GetFile(std::string path); DBC* GetDBC(std::string name); @@ -22,6 +22,8 @@ public: static char* Languages[]; protected: void InitializeDBC(); +private: + ACE_Thread_Mutex mutex; }; extern MPQManager* MPQHandler; diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 7ae6afadb84..2884b998ac8 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -4,42 +4,73 @@ #include "Cache.h" #include "DBC.h" +#include + #include "Common.h" #include "LoginDatabase.h" +#include "Util.h" LoginDatabaseWorkerPool LoginDatabase; MPQManager* MPQHandler; CacheClass* Cache; -void ExtractAllMaps(uint32 onlyMap) +void ExtractAllMaps(std::set& mapIds, uint32 threads) { DBC* dbc = MPQHandler->GetDBC("Map"); for (std::vector::iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr) { uint32 mapId = (*itr)->Values[0]; - if (onlyMap && mapId != onlyMap) + + // Skip this map if a list of specific maps was provided and this one is not contained in it. + if (!mapIds.empty() && mapIds.find(mapId) == mapIds.end()) continue; + std::string name = (*itr)->GetString(1); WDT wdt("World\\maps\\" + name + "\\" + name + ".wdt"); if (!wdt.IsValid || wdt.IsGlobalModel) continue; printf("Building %s MapId %u\n", name.c_str(), mapId); - ContinentBuilder builder(name, mapId, &wdt); + ContinentBuilder builder(name, mapId, &wdt, threads); builder.Build(); } - /* - WDT wdt("World\\maps\\DalaranPrison\\DalaranPrison.wdt"); - if (!wdt.IsValid) - return; - printf("Model valid!\n"); - if (wdt.IsGlobalModel) +} + +bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapList) +{ + char* param = NULL; + for (int i = 1; i < argc; ++i) { - printf("Unsupported\n"); - return; + if (strcmp(argv[i], "--threads") == 0) + { + param = argv[++i]; + if (!param) + return false; + + threads = atoi(param); + printf("Using %i threads\n", threads); + } + if (strcmp(argv[i], "--maps") == 0) + { + param = argv[++i]; + if (!param) + return false; + std::string maps = std::string(param); + Tokens tokens(maps, ','); + + for (Tokens::iterator itr = tokens.begin(); itr != tokens.end(); ++itr) + mapList.insert(atoi(*itr)); + + printf("Extracting only provided list of maps (%u).\n", mapList.size()); + } } - ContinentBuilder builder("DalaranPrison", &wdt); - builder.Build(); - */ + return true; +} + +void PrintUsage() +{ + printf("MeshExtractor help.\n"); + printf("* Use \"--threads \" to specify threads, default to 4\n"); + printf("* Use \"--maps a,b,c,d,e\" to extract only the maps specified ( do not use spaces )\n"); } int main(int argc, char* argv[]) @@ -48,11 +79,16 @@ int main(int argc, char* argv[]) Cache = new CacheClass(); MPQHandler = new MPQManager(); MPQHandler->Initialize(); - MPQHandler->LoadMaps(); - uint32 onlyMap = 0; - if (argc == 2) - onlyMap = uint32(atoi(argv[1])); - ExtractAllMaps(onlyMap); + uint32 threads = 4; + std::set mapIds; + + if (!HandleArgs(argc, argv, threads, mapIds)) + { + PrintUsage(); + return -1; + } + + ExtractAllMaps(mapIds, threads); return 0; } diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index baf1fa0375c..926d2591f1a 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -9,6 +9,8 @@ #include "RecastAlloc.h" #include "DetourNavMeshBuilder.h" +#include "ace/Synch.h" + TileBuilder::TileBuilder(std::string world, int x, int y, uint32 mapId) : _Geometry(NULL), World(world), X(x), Y(y), MapId(mapId), DataSize(0) { // Cell Size = TileSize / TileVoxelSize @@ -54,11 +56,6 @@ uint8* TileBuilder::Build() { adt = new ADT(Utils::GetAdtPath(World, X, Y)); adt->Read(); - if (!adt->Data) - { - delete adt; - return NULL; - } Cache->AdtCache.Insert(std::make_pair(X, Y), adt); } _Geometry->AddAdt(adt); @@ -234,7 +231,6 @@ uint8* TileBuilder::Build() DataSize = navDataSize; rcFreePolyMesh(pmesh); rcFreePolyMeshDetail(dmesh); - Cache->Clear(); return navData; } -- cgit v1.2.3 From 987436ceeac3c463a81d3b2cab05ff3c532dbbf8 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 29 Sep 2012 15:38:31 -0500 Subject: Tools/MeshExtractor: Get rid of some memory leaks --- src/tools/mesh_extractor/ChunkedData.cpp | 9 +++++++++ src/tools/mesh_extractor/ChunkedData.h | 1 + src/tools/mesh_extractor/DoodadHandler.cpp | 6 ++++++ src/tools/mesh_extractor/DoodadHandler.h | 2 ++ src/tools/mesh_extractor/LiquidHandler.h | 1 + src/tools/mesh_extractor/TileBuilder.cpp | 24 +++++++++++++++++++----- src/tools/mesh_extractor/TileBuilder.h | 2 ++ src/tools/mesh_extractor/WorldModelHandler.cpp | 8 +++++++- src/tools/mesh_extractor/WorldModelHandler.h | 1 + 9 files changed, 48 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ChunkedData.cpp b/src/tools/mesh_extractor/ChunkedData.cpp index 470b8b94f39..35b1bcd5af0 100644 --- a/src/tools/mesh_extractor/ChunkedData.cpp +++ b/src/tools/mesh_extractor/ChunkedData.cpp @@ -61,3 +61,12 @@ Chunk* ChunkedData::GetChunkByName( std::string name ) return Chunks[i]; return NULL; } + +ChunkedData::~ChunkedData() +{ + for (std::vector::iterator itr = Chunks.begin(); itr != Chunks.end(); ++itr) + delete *itr; + + Chunks.clear(); + fclose(Stream); +} diff --git a/src/tools/mesh_extractor/ChunkedData.h b/src/tools/mesh_extractor/ChunkedData.h index 6e102828222..d36d0868859 100644 --- a/src/tools/mesh_extractor/ChunkedData.h +++ b/src/tools/mesh_extractor/ChunkedData.h @@ -9,6 +9,7 @@ class ChunkedData public: ChunkedData(FILE* stream, uint32 maxLength, uint32 chunksHint = 300); ChunkedData(std::string file, uint32 chunksHint = 300); + ~ChunkedData(); int GetFirstIndex(std::string name); Chunk* GetChunkByName(std::string name); diff --git a/src/tools/mesh_extractor/DoodadHandler.cpp b/src/tools/mesh_extractor/DoodadHandler.cpp index 28bb9da5f21..6604aebe73a 100644 --- a/src/tools/mesh_extractor/DoodadHandler.cpp +++ b/src/tools/mesh_extractor/DoodadHandler.cpp @@ -99,3 +99,9 @@ void DoodadHandler::InsertModelGeometry(const DoodadDefinition& def, Model* mode for (std::vector >::iterator itr = model->Triangles.begin(); itr != model->Triangles.end(); ++itr) Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_DOODAD, itr->V0 + vertOffset, itr->V1 + vertOffset, itr->V2 + vertOffset)); } + +DoodadHandler::~DoodadHandler() +{ + delete _definitions; + delete _paths; +} diff --git a/src/tools/mesh_extractor/DoodadHandler.h b/src/tools/mesh_extractor/DoodadHandler.h index aa7e3cac20d..2e00696f7e5 100644 --- a/src/tools/mesh_extractor/DoodadHandler.h +++ b/src/tools/mesh_extractor/DoodadHandler.h @@ -32,6 +32,8 @@ class DoodadHandler : public ObjectDataHandler { public: DoodadHandler(ADT* adt); + ~DoodadHandler(); + std::vector Vertices; std::vector > Triangles; bool IsSane() { return _definitions && _paths; } diff --git a/src/tools/mesh_extractor/LiquidHandler.h b/src/tools/mesh_extractor/LiquidHandler.h index 138b2da2ad9..6e8d0081adb 100644 --- a/src/tools/mesh_extractor/LiquidHandler.h +++ b/src/tools/mesh_extractor/LiquidHandler.h @@ -10,6 +10,7 @@ class LiquidHandler { public: LiquidHandler(ADT* adt); + ADT* Source; std::vector Vertices; std::vector > Triangles; diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 926d2591f1a..5c2c4faab80 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -225,16 +225,30 @@ uint8* TileBuilder::Build() uint8* navData; printf("[%02i,%02i] Creating the navmesh!\n", X, Y); bool result = dtCreateNavMeshData(¶ms, &navData, &navDataSize); - if (result) + + // Free some memory + rcFreePolyMesh(pmesh); + rcFreePolyMeshDetail(dmesh); + delete tilebMax; + delete tilebMin; + delete areas; + delete triangles; + delete vertices; + delete bbMax; + delete bbMin; + + if (result) { printf("[%02i,%02i] NavMesh created, size %i!\n", X, Y, navDataSize); DataSize = navDataSize; - rcFreePolyMesh(pmesh); - rcFreePolyMeshDetail(dmesh); return navData; } - rcFreePolyMesh(pmesh); - rcFreePolyMeshDetail(dmesh); return NULL; } + +TileBuilder::~TileBuilder() +{ + delete Context; + delete _Geometry; +} diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h index f91a732f70c..e56b926e5a5 100644 --- a/src/tools/mesh_extractor/TileBuilder.h +++ b/src/tools/mesh_extractor/TileBuilder.h @@ -11,6 +11,8 @@ class TileBuilder { public: TileBuilder(std::string world, int x, int y, uint32 mapId); + ~TileBuilder(); + void CalculateTileBounds(float*& bmin, float*& bmax); uint8* Build(); diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index 636b06f6f73..edad6d1b6d8 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -24,7 +24,7 @@ WorldModelDefinition WorldModelDefinition::Read( FILE* file ) } -WorldModelHandler::WorldModelHandler( ADT* adt ) : ObjectDataHandler(adt) +WorldModelHandler::WorldModelHandler( ADT* adt ) : ObjectDataHandler(adt), _definitions(NULL), _paths(NULL) { if (!adt->HasObjectData) return; @@ -190,3 +190,9 @@ void WorldModelHandler::ReadModelPaths() _paths->push_back(Utils::ReadString(dataStream)); } } + +WorldModelHandler::~WorldModelHandler() +{ + delete _definitions; + delete _paths; +} diff --git a/src/tools/mesh_extractor/WorldModelHandler.h b/src/tools/mesh_extractor/WorldModelHandler.h index daf0713ecd2..df5e3764eb5 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.h +++ b/src/tools/mesh_extractor/WorldModelHandler.h @@ -29,6 +29,7 @@ class WorldModelHandler : public ObjectDataHandler { public: WorldModelHandler(ADT* adt); + ~WorldModelHandler(); std::vector Vertices; std::vector > Triangles; -- cgit v1.2.3 From 5c9e917e5e2a4c934aaa7d061624a46ff4269c8f Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 29 Sep 2012 16:19:33 -0500 Subject: Core/MMaps: Removed an incorrect call to GetHeight Tools/MeshExtractor: Fixed a crash caused by calling fclose in a NULL stream --- src/server/game/Movement/PathGenerator.cpp | 6 +----- src/tools/mesh_extractor/ChunkedData.cpp | 3 ++- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 9635399e71f..6e765b1ee27 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -58,12 +58,8 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z)) return false; - float newDestZ = _sourceUnit->GetBaseMap()->GetHeight(_sourceUnit->GetPhaseMask(), x, y, z, true, MAX_FALL_DISTANCE); - if (newDestZ <= INVALID_HEIGHT) - return false; - Vector3 oldDest = GetEndPosition(); - Vector3 dest(destX, destY, newDestZ); + Vector3 dest(destX, destY, destZ); SetEndPosition(dest); Vector3 start(x, y, z); diff --git a/src/tools/mesh_extractor/ChunkedData.cpp b/src/tools/mesh_extractor/ChunkedData.cpp index 35b1bcd5af0..4c59217ed33 100644 --- a/src/tools/mesh_extractor/ChunkedData.cpp +++ b/src/tools/mesh_extractor/ChunkedData.cpp @@ -68,5 +68,6 @@ ChunkedData::~ChunkedData() delete *itr; Chunks.clear(); - fclose(Stream); + if (Stream) + fclose(Stream); } -- cgit v1.2.3 From 14b304d4f726aeaf5f48fdac4cd9ce8aad66c5c9 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 30 Sep 2012 08:27:56 -0500 Subject: Tools/MeshExtractor: * Removed the cache of ADTs * Add the correct geometry for neighbor ADTs * Fixes more crashes * Calculate the correct bounds for the map tiles. --- src/tools/mesh_extractor/ADT.cpp | 1 + src/tools/mesh_extractor/Cache.h | 11 +++--- src/tools/mesh_extractor/ContinentBuilder.cpp | 57 +++++++++++++++++++++++---- src/tools/mesh_extractor/TileBuilder.cpp | 30 ++++++-------- 4 files changed, 68 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ADT.cpp b/src/tools/mesh_extractor/ADT.cpp index c564d7193cf..1684d0636f4 100644 --- a/src/tools/mesh_extractor/ADT.cpp +++ b/src/tools/mesh_extractor/ADT.cpp @@ -2,6 +2,7 @@ #include "DoodadHandler.h" #include "LiquidHandler.h" #include "WorldModelHandler.h" +#include "Cache.h" ADT::ADT( std::string file ) : ObjectData(NULL), Data(NULL), _DoodadHandler(NULL), _WorldModelHandler(NULL), _LiquidHandler(NULL), HasObjectData(false) { diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h index 49e268ec507..36bf4a7a693 100644 --- a/src/tools/mesh_extractor/Cache.h +++ b/src/tools/mesh_extractor/Cache.h @@ -7,7 +7,6 @@ class WorldModelRoot; class Model; -class ADT; template class GenericCache @@ -19,21 +18,23 @@ public: void Insert(K key, T* val) { + ACE_GUARD(ACE_Thread_Mutex, g, mutex); + if (_items.size() > FlushLimit) Clear(); - ACE_GUARD(ACE_Thread_Mutex, g, mutex); _items[key] = val; } T* Get(K key) { + ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL); typename std::map::iterator itr = _items.find(key); if (itr != _items.end()) return itr->second; return NULL; } - void Clear() + void Clear() { for (typename std::map::iterator itr = _items.begin(); itr != _items.end(); ++itr) delete itr->second; @@ -50,10 +51,10 @@ public: CacheClass() {} GenericCache ModelCache; GenericCache WorldModelCache; - GenericCache, ADT> AdtCache; + void Clear() { - AdtCache.Clear(); + } }; diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index 96f9085de8c..cdfe0ca050a 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -5,6 +5,7 @@ #include "DetourNavMesh.h" #include "Cache.h" #include "ace/Task.h" +#include "Recast.h" class BuilderThread : public ACE_Task { @@ -21,18 +22,24 @@ public: printf("[%02i,%02i] Building tile\n", X, Y); TileBuilder builder(Continent, X, Y, MapId); char buff[100]; - sprintf(buff, "%03u%02u%02u.mmtile", MapId, X, Y); + sprintf(buff, "mmaps/%03u%02u%02u.mmtile", MapId, X, Y); FILE* f = fopen(buff, "r"); if (f) // Check if file already exists. { + printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y); fclose(f); Free = true; - return 0; + return 1; } uint8* nav = builder.Build(); if (nav) { f = fopen(buff, "wb"); + if (!f) + { + printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff); + return -1; + } MmapTileHeader header; header.size = builder.DataSize; fwrite(&header, sizeof(MmapTileHeader), 1, f); @@ -48,17 +55,52 @@ public: bool Free; }; +void getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax) +{ + // this is for elevation + if (verts && vertCount) + rcCalcBounds(verts, vertCount, bmin, bmax); + else + { + bmin[1] = FLT_MIN; + bmax[1] = FLT_MAX; + } + + // this is for width and depth + bmax[0] = (32 - int(tileX)) * Constants::TileSize; + bmax[2] = (32 - int(tileY)) * Constants::TileSize; + bmin[0] = bmax[0] - Constants::TileSize; + bmin[2] = bmax[2] - Constants::TileSize; +} + void ContinentBuilder::Build() { char buff[50]; - sprintf(buff, "%03u.mmap", MapId); + sprintf(buff, "mmaps/%03u.mmap", MapId); FILE* mmap = fopen(buff, "wb"); + if (!mmap) + { + printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff); + return; + } + + int tileXMin = 64, tileYMin = 64, tileXMax = 0, tileYMax = 0; + for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) + { + tileXMax = std::max(itr->X, tileXMax); + tileXMin = std::min(itr->X, tileXMin); + + tileYMax = std::max(itr->Y, tileYMax); + tileYMin = std::min(itr->Y, tileYMin); + } + + float bmin[3], bmax[3]; + getTileBounds(tileXMax, tileYMax, NULL, 0, bmin, bmax); + dtNavMeshParams params; params.maxPolys = 32768; - params.maxTiles = 4096; - params.orig[0] = -17066.666f; - params.orig[1] = 0.0f; - params.orig[2] = -17066.666f; + params.maxTiles = TileMap->TileTable.size(); + rcVcopy(params.orig, bmin); params.tileHeight = 533.33333f; params.tileWidth = 533.33333f; fwrite(¶ms, sizeof(dtNavMeshParams), 1, mmap); @@ -66,6 +108,7 @@ void ContinentBuilder::Build() std::vector Threads; for (uint32 i = 0; i < NumberOfThreads; ++i) Threads.push_back(new BuilderThread()); + printf("Map %s ( %i ) has %i tiles. Building them with %i threads\n", Continent.c_str(), MapId, TileMap->TileTable.size(), NumberOfThreads); for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) { bool next = false; diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 5c2c4faab80..83137258710 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -51,14 +51,10 @@ uint8* TileBuilder::Build() { _Geometry = new Geometry(); _Geometry->Transform = true; - ADT* adt = Cache->AdtCache.Get(std::make_pair(X, Y)); - if (!adt) - { - adt = new ADT(Utils::GetAdtPath(World, X, Y)); - adt->Read(); - Cache->AdtCache.Insert(std::make_pair(X, Y), adt); - } + ADT* adt = new ADT(Utils::GetAdtPath(World, X, Y)); + adt->Read(); _Geometry->AddAdt(adt); + delete adt; if (_Geometry->Vertices.empty() && _Geometry->Triangles.empty()) return NULL; @@ -77,20 +73,16 @@ uint8* TileBuilder::Build() if (tx == X && ty == Y) continue; - ADT* _adt = Cache->AdtCache.Get(std::make_pair(tx, ty)); - if (!_adt) + ADT* _adt = new ADT(Utils::GetAdtPath(World, tx, ty)); + // If this condition is met, it means that this wdt does not contain the ADT + if (!_adt->Data->Stream) { - _adt = new ADT(Utils::GetAdtPath(World, tx, ty)); - // If this condition is met, it means that this wdt does not contain the ADT - if (!_adt->Data->Stream) - { - delete _adt; - continue; - } - _adt->Read(); - Cache->AdtCache.Insert(std::make_pair(tx, ty), _adt); + delete _adt; + continue; } - _Geometry->AddAdt(adt); + _adt->Read(); + _Geometry->AddAdt(_adt); + delete _adt; } } uint32 numVerts = _Geometry->Vertices.size(); -- cgit v1.2.3 From d63e1276d602b0172f2d32abe85ec718a7bc7912 Mon Sep 17 00:00:00 2001 From: Nay Date: Sun, 30 Sep 2012 15:38:03 +0100 Subject: Tools/MeshExtractor: tabs2spaces --- src/tools/mesh_extractor/ChunkedData.cpp | 12 +++++------ src/tools/mesh_extractor/ChunkedData.h | 2 +- src/tools/mesh_extractor/DoodadHandler.cpp | 4 ++-- src/tools/mesh_extractor/DoodadHandler.h | 2 +- src/tools/mesh_extractor/MeshExtractor.cpp | 2 +- src/tools/mesh_extractor/TileBuilder.cpp | 30 +++++++++++++------------- src/tools/mesh_extractor/TileBuilder.h | 2 +- src/tools/mesh_extractor/WorldModelHandler.cpp | 4 ++-- src/tools/mesh_extractor/WorldModelHandler.h | 2 +- 9 files changed, 30 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ChunkedData.cpp b/src/tools/mesh_extractor/ChunkedData.cpp index 4c59217ed33..725a6f45637 100644 --- a/src/tools/mesh_extractor/ChunkedData.cpp +++ b/src/tools/mesh_extractor/ChunkedData.cpp @@ -64,10 +64,10 @@ Chunk* ChunkedData::GetChunkByName( std::string name ) ChunkedData::~ChunkedData() { - for (std::vector::iterator itr = Chunks.begin(); itr != Chunks.end(); ++itr) - delete *itr; - - Chunks.clear(); - if (Stream) - fclose(Stream); + for (std::vector::iterator itr = Chunks.begin(); itr != Chunks.end(); ++itr) + delete *itr; + + Chunks.clear(); + if (Stream) + fclose(Stream); } diff --git a/src/tools/mesh_extractor/ChunkedData.h b/src/tools/mesh_extractor/ChunkedData.h index d36d0868859..e23648c845e 100644 --- a/src/tools/mesh_extractor/ChunkedData.h +++ b/src/tools/mesh_extractor/ChunkedData.h @@ -9,7 +9,7 @@ class ChunkedData public: ChunkedData(FILE* stream, uint32 maxLength, uint32 chunksHint = 300); ChunkedData(std::string file, uint32 chunksHint = 300); - ~ChunkedData(); + ~ChunkedData(); int GetFirstIndex(std::string name); Chunk* GetChunkByName(std::string name); diff --git a/src/tools/mesh_extractor/DoodadHandler.cpp b/src/tools/mesh_extractor/DoodadHandler.cpp index 6604aebe73a..363f07b4578 100644 --- a/src/tools/mesh_extractor/DoodadHandler.cpp +++ b/src/tools/mesh_extractor/DoodadHandler.cpp @@ -102,6 +102,6 @@ void DoodadHandler::InsertModelGeometry(const DoodadDefinition& def, Model* mode DoodadHandler::~DoodadHandler() { - delete _definitions; - delete _paths; + delete _definitions; + delete _paths; } diff --git a/src/tools/mesh_extractor/DoodadHandler.h b/src/tools/mesh_extractor/DoodadHandler.h index 2e00696f7e5..a212b032d1d 100644 --- a/src/tools/mesh_extractor/DoodadHandler.h +++ b/src/tools/mesh_extractor/DoodadHandler.h @@ -32,7 +32,7 @@ class DoodadHandler : public ObjectDataHandler { public: DoodadHandler(ADT* adt); - ~DoodadHandler(); + ~DoodadHandler(); std::vector Vertices; std::vector > Triangles; diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 2884b998ac8..3dde9ac36f5 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -89,6 +89,6 @@ int main(int argc, char* argv[]) } ExtractAllMaps(mapIds, threads); - return 0; + return 0; } diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 83137258710..e3694541be8 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -217,19 +217,19 @@ uint8* TileBuilder::Build() uint8* navData; printf("[%02i,%02i] Creating the navmesh!\n", X, Y); bool result = dtCreateNavMeshData(¶ms, &navData, &navDataSize); - - // Free some memory - rcFreePolyMesh(pmesh); - rcFreePolyMeshDetail(dmesh); - delete tilebMax; - delete tilebMin; - delete areas; - delete triangles; - delete vertices; - delete bbMax; - delete bbMin; - - if (result) + + // Free some memory + rcFreePolyMesh(pmesh); + rcFreePolyMeshDetail(dmesh); + delete tilebMax; + delete tilebMin; + delete areas; + delete triangles; + delete vertices; + delete bbMax; + delete bbMin; + + if (result) { printf("[%02i,%02i] NavMesh created, size %i!\n", X, Y, navDataSize); DataSize = navDataSize; @@ -241,6 +241,6 @@ uint8* TileBuilder::Build() TileBuilder::~TileBuilder() { - delete Context; - delete _Geometry; + delete Context; + delete _Geometry; } diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h index e56b926e5a5..2ec45811676 100644 --- a/src/tools/mesh_extractor/TileBuilder.h +++ b/src/tools/mesh_extractor/TileBuilder.h @@ -11,7 +11,7 @@ class TileBuilder { public: TileBuilder(std::string world, int x, int y, uint32 mapId); - ~TileBuilder(); + ~TileBuilder(); void CalculateTileBounds(float*& bmin, float*& bmax); uint8* Build(); diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index edad6d1b6d8..a0977c398c4 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -193,6 +193,6 @@ void WorldModelHandler::ReadModelPaths() WorldModelHandler::~WorldModelHandler() { - delete _definitions; - delete _paths; + delete _definitions; + delete _paths; } diff --git a/src/tools/mesh_extractor/WorldModelHandler.h b/src/tools/mesh_extractor/WorldModelHandler.h index df5e3764eb5..cccedfa60fb 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.h +++ b/src/tools/mesh_extractor/WorldModelHandler.h @@ -29,7 +29,7 @@ class WorldModelHandler : public ObjectDataHandler { public: WorldModelHandler(ADT* adt); - ~WorldModelHandler(); + ~WorldModelHandler(); std::vector Vertices; std::vector > Triangles; -- cgit v1.2.3 From 4c3266c7af5f5840a212d46bf068a793150b34fc Mon Sep 17 00:00:00 2001 From: Nay Date: Sun, 30 Sep 2012 15:52:10 +0100 Subject: Tools&Core: Whitespace cleanup No one likes whitespace, right? --- src/server/game/Maps/Map.cpp | 2 +- src/server/game/Movement/MotionMaster.cpp | 2 +- .../MovementGenerators/TargetedMovementGenerator.cpp | 2 +- src/server/game/Movement/PathGenerator.cpp | 4 ++-- src/server/scripts/Commands/cs_mmaps.cpp | 4 ++-- src/tools/map_extractor/System.cpp | 2 +- src/tools/mesh_extractor/ADT.cpp | 2 +- src/tools/mesh_extractor/ADT.h | 2 +- src/tools/mesh_extractor/Cache.h | 10 +++++----- src/tools/mesh_extractor/ChunkedData.cpp | 4 ++-- src/tools/mesh_extractor/Geometry.cpp | 4 ++-- src/tools/mesh_extractor/Geometry.h | 2 +- src/tools/mesh_extractor/LiquidHandler.cpp | 2 +- src/tools/mesh_extractor/MPQ.cpp | 10 +++++----- src/tools/mesh_extractor/MPQManager.cpp | 2 +- src/tools/mesh_extractor/MPQManager.h | 2 +- src/tools/mesh_extractor/MapChunk.h | 2 +- src/tools/mesh_extractor/MeshExtractor.cpp | 2 +- src/tools/mesh_extractor/ObjectDataHandler.h | 2 +- src/tools/mesh_extractor/TileBuilder.cpp | 14 +++++++------- src/tools/mesh_extractor/Utils.cpp | 2 +- src/tools/mesh_extractor/Utils.h | 4 ++-- src/tools/mesh_extractor/WDT.cpp | 2 +- src/tools/mesh_extractor/WorldModelHandler.cpp | 2 +- src/tools/mmaps_generator/MapBuilder.cpp | 10 +++++----- src/tools/mmaps_generator/TerrainBuilder.cpp | 2 +- 26 files changed, 49 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index ae192f16080..25ffc1d19f2 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -123,7 +123,7 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy) void Map::LoadMMap(int gx, int gy) { bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gx, gy); - + if (mmapLoadResult) sLog->outInfo(LOG_FILTER_MAPS, "MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); else diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 34be779a8b7..386a95fa838 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -428,7 +428,7 @@ void MotionMaster::MoveCharge(PathGenerator path, float speed, uint32 id) Vector3 dest = path.GetActualEndPosition(); MoveCharge(dest.x, dest.y, dest.z); - + Movement::MoveSplineInit init(_owner); init.MovebyPath(path.GetPath()); init.SetVelocity(speed); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index c275c33032f..7a6611ed2ca 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -124,7 +124,7 @@ bool TargetedMovementGeneratorMedium::Update(T* owner, const uint32& time_d D::_clearUnitStateMove(owner); return true; } - + // prevent movement while casting spells with cast time or channel time if (owner->HasUnitState(UNIT_STATE_CASTING)) { diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 6e765b1ee27..3495c4d1218 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -469,7 +469,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin _pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); NormalizePath(); - + // first point is always our current location - we need the next one SetActualEndPosition(_pathPoints[pointCount-1]); @@ -515,7 +515,7 @@ void PathGenerator::BuildShortcut() _pathPoints[1] = GetActualEndPosition(); NormalizePath(); - + _type = PATHFIND_SHORTCUT; } diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index be2d52b5925..c3f757614e2 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -152,7 +152,7 @@ public: // navmesh poly -> navmesh tile location dtQueryFilter filter = dtQueryFilter(); - dtPolyRef polyRef = INVALID_POLYREF; + dtPolyRef polyRef = INVALID_POLYREF; navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL); if (polyRef == INVALID_POLYREF) @@ -252,7 +252,7 @@ public: CellCoord pair(Trinity::ComputeCellCoord(object->GetPositionX(), object->GetPositionY()) ); Cell cell(pair); cell.SetNoCreate(); - + std::list creatureList; Trinity::AnyUnitInObjectRangeCheck go_check(object, radius); diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index 552bab30d50..2e117934679 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -852,7 +852,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, hasHoles = true; } } - + if (hasHoles) map.holesSize = sizeof(holes); else diff --git a/src/tools/mesh_extractor/ADT.cpp b/src/tools/mesh_extractor/ADT.cpp index 1684d0636f4..a6c080cf0b0 100644 --- a/src/tools/mesh_extractor/ADT.cpp +++ b/src/tools/mesh_extractor/ADT.cpp @@ -18,7 +18,7 @@ ADT::~ADT() { delete ObjectData; delete Data; - + for (std::vector::iterator itr = MapChunks.begin(); itr != MapChunks.end(); ++itr) delete *itr; diff --git a/src/tools/mesh_extractor/ADT.h b/src/tools/mesh_extractor/ADT.h index 096f491eed8..133596eb024 100644 --- a/src/tools/mesh_extractor/ADT.h +++ b/src/tools/mesh_extractor/ADT.h @@ -12,7 +12,7 @@ class ADT public: ADT(std::string file); ~ADT(); - + void Read(); ChunkedData* ObjectData; diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h index 36bf4a7a693..90e2c138376 100644 --- a/src/tools/mesh_extractor/Cache.h +++ b/src/tools/mesh_extractor/Cache.h @@ -15,7 +15,7 @@ public: GenericCache() {} static const int32 FlushLimit = 1000; - + void Insert(K key, T* val) { ACE_GUARD(ACE_Thread_Mutex, g, mutex); @@ -35,10 +35,10 @@ public: } void Clear() - { - for (typename std::map::iterator itr = _items.begin(); itr != _items.end(); ++itr) + { + for (typename std::map::iterator itr = _items.begin(); itr != _items.end(); ++itr) delete itr->second; - _items.clear(); + _items.clear(); } private: std::map _items; @@ -54,7 +54,7 @@ public: void Clear() { - + } }; diff --git a/src/tools/mesh_extractor/ChunkedData.cpp b/src/tools/mesh_extractor/ChunkedData.cpp index 725a6f45637..4431993e3d1 100644 --- a/src/tools/mesh_extractor/ChunkedData.cpp +++ b/src/tools/mesh_extractor/ChunkedData.cpp @@ -4,7 +4,7 @@ #include -ChunkedData::ChunkedData( FILE* stream, uint32 maxLength, uint32 chunksHint /*= 300*/ ) : +ChunkedData::ChunkedData( FILE* stream, uint32 maxLength, uint32 chunksHint /*= 300*/ ) : Stream(stream) { if (!Stream) @@ -66,7 +66,7 @@ ChunkedData::~ChunkedData() { for (std::vector::iterator itr = Chunks.begin(); itr != Chunks.end(); ++itr) delete *itr; - + Chunks.clear(); if (Stream) fclose(Stream); diff --git a/src/tools/mesh_extractor/Geometry.cpp b/src/tools/mesh_extractor/Geometry.cpp index 2fbe99e3211..2fc470e8e9f 100644 --- a/src/tools/mesh_extractor/Geometry.cpp +++ b/src/tools/mesh_extractor/Geometry.cpp @@ -63,7 +63,7 @@ void Geometry::AddData( std::vector& verts, std::vector::iterator itr = verts.begin(); itr != verts.end(); ++itr) Vertices.push_back(Transform ? Utils::ToRecast(*itr) : *itr); - + for (std::vector >::iterator itr = tris.begin(); itr != tris.end(); ++itr) Triangles.push_back(Triangle(itr->Type, itr->V0 + vertOffset, itr->V1 + vertOffset, itr->V2 + vertOffset)); } @@ -116,7 +116,7 @@ void Geometry::AddAdt( ADT* adt ) if (!adt->_DoodadHandler->Triangles.empty()) AddData(adt->_DoodadHandler->Vertices, adt->_DoodadHandler->Triangles); - + if (!adt->_WorldModelHandler->Triangles.empty()) AddData(adt->_WorldModelHandler->Vertices, adt->_WorldModelHandler->Triangles); } diff --git a/src/tools/mesh_extractor/Geometry.h b/src/tools/mesh_extractor/Geometry.h index 9593c98044e..e445234dd12 100644 --- a/src/tools/mesh_extractor/Geometry.h +++ b/src/tools/mesh_extractor/Geometry.h @@ -9,7 +9,7 @@ class Geometry { public: Geometry(); - + void CalculateBoundingBox(float*& min, float*& max); void CalculateMinMaxHeight(float& min, float& max); void AddData(std::vector& verts, std::vector >& tris); diff --git a/src/tools/mesh_extractor/LiquidHandler.cpp b/src/tools/mesh_extractor/LiquidHandler.cpp index 9a40e08b73a..5b998d75db9 100644 --- a/src/tools/mesh_extractor/LiquidHandler.cpp +++ b/src/tools/mesh_extractor/LiquidHandler.cpp @@ -20,7 +20,7 @@ void LiquidHandler::HandleNewLiquid() MCNKData.reserve(256); for (int i = 0; i < 256; i++) header[i] = H2OHeader::Read(stream); - + for (int i = 0; i < 256; i++) { H2OHeader h = header[i]; diff --git a/src/tools/mesh_extractor/MPQ.cpp b/src/tools/mesh_extractor/MPQ.cpp index fbae56cd7a0..699b0a5014c 100644 --- a/src/tools/mesh_extractor/MPQ.cpp +++ b/src/tools/mesh_extractor/MPQ.cpp @@ -7,9 +7,9 @@ MPQArchive::MPQArchive(const char* filename) { int result = libmpq__archive_open(&mpq_a, filename, -1); printf("Opening %s\n", filename); - if (result) + if (result) { - switch (result) + switch (result) { case LIBMPQ_ERROR_OPEN : printf("Error opening archive '%s': Does file really exist?\n", filename); @@ -46,7 +46,7 @@ eof(false), buffer(0), pointer(0), size(0) mpq_archive* mpq_a = (*i)->mpq_a; uint32_t filenum; - if(libmpq__file_number(mpq_a, filename, &filenum)) + if(libmpq__file_number(mpq_a, filename, &filenum)) continue; libmpq__off_t transferred; libmpq__file_unpacked_size(mpq_a, filenum, &size); @@ -72,7 +72,7 @@ eof(false), buffer(0), pointer(0), size(0) size_t MPQFile::Read(void* dest, size_t bytes) { - if (eof) + if (eof) return 0; size_t rpos = pointer + bytes; @@ -102,7 +102,7 @@ void MPQFile::seekRelative(int offset) void MPQFile::close() { - if (buffer) + if (buffer) delete[] buffer; buffer = 0; eof = true; diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp index 5ea6198e76d..608eef1547a 100644 --- a/src/tools/mesh_extractor/MPQManager.cpp +++ b/src/tools/mesh_extractor/MPQManager.cpp @@ -5,7 +5,7 @@ #include "ace/Synch.h" -char* MPQManager::Files[] = { +char* MPQManager::Files[] = { "common.MPQ", "common-2.MPQ", "expansion.MPQ", diff --git a/src/tools/mesh_extractor/MPQManager.h b/src/tools/mesh_extractor/MPQManager.h index 634c70cedeb..0050dc5218a 100644 --- a/src/tools/mesh_extractor/MPQManager.h +++ b/src/tools/mesh_extractor/MPQManager.h @@ -10,7 +10,7 @@ class MPQManager public: MPQManager() {} ~MPQManager() {} - + void Initialize(); FILE* GetFile(std::string path); DBC* GetDBC(std::string name); diff --git a/src/tools/mesh_extractor/MapChunk.h b/src/tools/mesh_extractor/MapChunk.h index 61dcabac9b0..e7d835ae0e3 100644 --- a/src/tools/mesh_extractor/MapChunk.h +++ b/src/tools/mesh_extractor/MapChunk.h @@ -10,7 +10,7 @@ class MapChunk { public: MapChunk(ADT* _adt, Chunk* chunk); - + void GenerateTriangles(); void GenerateVertices(FILE* stream); static bool HasHole(uint32 map, int x, int y); diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 3dde9ac36f5..423095b22ca 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -56,7 +56,7 @@ bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapLis return false; std::string maps = std::string(param); Tokens tokens(maps, ','); - + for (Tokens::iterator itr = tokens.begin(); itr != tokens.end(); ++itr) mapList.insert(atoi(*itr)); diff --git a/src/tools/mesh_extractor/ObjectDataHandler.h b/src/tools/mesh_extractor/ObjectDataHandler.h index 834bf66bcfb..75b4e45700c 100644 --- a/src/tools/mesh_extractor/ObjectDataHandler.h +++ b/src/tools/mesh_extractor/ObjectDataHandler.h @@ -7,7 +7,7 @@ class ObjectDataHandler { public: ObjectDataHandler(ADT* _adt) : Source(_adt) {} - + void ProcessMapChunk(MapChunk* chunk); virtual void ProcessInternal(ChunkedData* data) = 0; ADT* Source; diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index e3694541be8..0c775b9b8c9 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -15,7 +15,7 @@ TileBuilder::TileBuilder(std::string world, int x, int y, uint32 mapId) : _Geome { // Cell Size = TileSize / TileVoxelSize // 1800 = TileVoxelSize - Config.cs = Constants::TileSize / 1800; + Config.cs = Constants::TileSize / 1800; // Cell Height Config.ch = 0.3f; // Min Region Area = 6^2 @@ -72,7 +72,7 @@ uint8* TileBuilder::Build() // don't load main tile again if (tx == X && ty == Y) continue; - + ADT* _adt = new ADT(Utils::GetAdtPath(World, tx, ty)); // If this condition is met, it means that this wdt does not contain the ADT if (!_adt->Data->Stream) @@ -104,7 +104,7 @@ uint8* TileBuilder::Build() rcCreateHeightfield(Context, *hf, width, width, bbMin, bbMax, Config.cs, Config.ch); rcClearUnwalkableTriangles(Context, Config.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas); rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb); - + printf("[%02i,%02i] Triangles rasterized!\n", X, Y); // Once all geometry is rasterized, we do initial pass of filtering to @@ -113,7 +113,7 @@ uint8* TileBuilder::Build() rcFilterLowHangingWalkableObstacles(Context, Config.walkableClimb, *hf); rcFilterLedgeSpans(Context, Config.walkableHeight, Config.walkableClimb, *hf); rcFilterWalkableLowHeightSpans(Context, Config.walkableHeight, *hf); - + printf("[%02i,%02i] Filtering done!\n", X, Y); // Compact the heightfield so that it is faster to handle from now on. @@ -132,13 +132,13 @@ uint8* TileBuilder::Build() rcBuildDistanceField(Context, *chf); // Partition the walkable surface into simple regions without holes. rcBuildRegions(Context, *chf, Config.borderSize, Config.minRegionArea, Config.mergeRegionArea); - + printf("[%02i,%02i] Regions built!\n", X, Y); // Create contours. rcContourSet* cset = rcAllocContourSet(); rcBuildContours(Context, *chf, Config.maxSimplificationError, Config.maxEdgeLen, *cset); - + // Build polygon navmesh from the contours. rcPolyMesh* pmesh = rcAllocPolyMesh(); rcBuildPolyMesh(Context, *cset, Config.maxVertsPerPoly, *pmesh); @@ -217,7 +217,7 @@ uint8* TileBuilder::Build() uint8* navData; printf("[%02i,%02i] Creating the navmesh!\n", X, Y); bool result = dtCreateNavMeshData(¶ms, &navData, &navDataSize); - + // Free some memory rcFreePolyMesh(pmesh); rcFreePolyMeshDetail(dmesh); diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index 2f07bd20080..3db387bc81a 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -133,7 +133,7 @@ Vector3 Utils::VectorTransform( Vector3 vec, G3D::Matrix4 matrix ) std::string Utils::GetPathBase( std::string path ) { - int lastIndex = path.find_last_of("."); + int lastIndex = path.find_last_of("."); if (lastIndex != std::string::npos) return path.substr(0, lastIndex); return path; diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index c247169df73..c9d2746b7d8 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -551,8 +551,8 @@ public: static G3D::Matrix4 GetTransformation(IDefinition def); /// They say its better to declare template functions in the header files. template - static std::string ToString(T val) - { + static std::string ToString(T val) + { std::stringstream ss; ss << val; return ss.str(); diff --git a/src/tools/mesh_extractor/WDT.cpp b/src/tools/mesh_extractor/WDT.cpp index c06d8ac9677..f0c3091c04e 100644 --- a/src/tools/mesh_extractor/WDT.cpp +++ b/src/tools/mesh_extractor/WDT.cpp @@ -17,7 +17,7 @@ void WDT::ReadGlobalModel() Chunk* defChunk = Data->GetChunkByName("MODF"); if (!fileChunk || !defChunk) return; - + IsGlobalModel = true; ModelDefinition = WorldModelDefinition::Read(defChunk->GetStream()); ModelFile = Utils::ReadString(fileChunk->GetStream()); diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index a0977c398c4..b98a7aae826 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -103,7 +103,7 @@ void WorldModelHandler::InsertModelGeometry( std::vector& verts, std::v break; instances.push_back(root->DoodadInstances[i]); } - + for (std::vector::iterator instance = instances.begin(); instance != instances.end(); ++instance) { Model* model = Cache->ModelCache.Get(instance->File); diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 69ffad94eb7..754bced903c 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -161,7 +161,7 @@ namespace MMAP void MapBuilder::buildAllMaps(int threads) { std::vector _threads; - + for (int i = 0; i < threads; ++i) _threads.push_back(new BuilderThread(this)); @@ -241,7 +241,7 @@ namespace MMAP minX = 32 - bmax[0] / GRID_SIZE; minY = 32 - bmax[2] / GRID_SIZE; } - + void MapBuilder::buildMeshFromFile(char* name) { FILE* file = fopen(name, "rb"); @@ -253,7 +253,7 @@ namespace MMAP fread(&mapId, sizeof(int), 1, file); fread(&tileX, sizeof(int), 1, file); fread(&tileY, sizeof(int), 1, file); - + dtNavMesh* navMesh = NULL; buildNavMesh(mapId, navMesh); if (!navMesh) @@ -270,7 +270,7 @@ namespace MMAP float* verts = new float[verticesCount]; int* inds = new int[indicesCount]; - + fread(verts, sizeof(float), verticesCount, file); fread(inds, sizeof(int), indicesCount, file); @@ -648,7 +648,7 @@ namespace MMAP tile.chf = NULL; rcFreeContourSet(tile.cset); tile.cset = NULL; - + if (tile.pmesh) { pmmerge[nmerge] = tile.pmesh; diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index 7ee4dc7f46c..0159219c110 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -779,7 +779,7 @@ namespace MMAP continue; std::pair val; val.first = t[i]; - + index = val.first; val.second = count; -- cgit v1.2.3 From fa57ecddac2409307375a01c4214080c3ca1d44a Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 30 Sep 2012 15:47:39 -0500 Subject: Tools/MeshExtractor: * Added the option to output debug information on ADTs. * Tweaked rcConfig options and fixed some mistakes about it. * Generate 64 tiles per ADT, this should give us a more accurate mesh on large maps. * Speedup compilation time by moving function bodies from Utils.h to Utils.cpp --- src/tools/mesh_extractor/ADT.cpp | 1 - src/tools/mesh_extractor/ContinentBuilder.cpp | 17 +- src/tools/mesh_extractor/ContinentBuilder.h | 2 +- src/tools/mesh_extractor/MeshExtractor.cpp | 23 ++- src/tools/mesh_extractor/TileBuilder.cpp | 46 +++-- src/tools/mesh_extractor/TileBuilder.h | 2 +- src/tools/mesh_extractor/Utils.cpp | 250 ++++++++++++++++++++++++++ src/tools/mesh_extractor/Utils.h | 250 ++------------------------ 8 files changed, 319 insertions(+), 272 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ADT.cpp b/src/tools/mesh_extractor/ADT.cpp index a6c080cf0b0..8d7dce9ae11 100644 --- a/src/tools/mesh_extractor/ADT.cpp +++ b/src/tools/mesh_extractor/ADT.cpp @@ -2,7 +2,6 @@ #include "DoodadHandler.h" #include "LiquidHandler.h" #include "WorldModelHandler.h" -#include "Cache.h" ADT::ADT( std::string file ) : ObjectData(NULL), Data(NULL), _DoodadHandler(NULL), _WorldModelHandler(NULL), _LiquidHandler(NULL), HasObjectData(false) { diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index cdfe0ca050a..984f6170357 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -7,13 +7,14 @@ #include "ace/Task.h" #include "Recast.h" -class BuilderThread : public ACE_Task +class BuilderThread : public ACE_Task_Base { private: int X, Y, MapId; std::string Continent; + bool debug; public: - BuilderThread() : Free(true) {} + BuilderThread(bool deb) : Free(true), debug(deb) {} void SetData(int x, int y, int map, std::string cont) { X = x; Y = y; MapId = map; Continent = cont; } int svc() @@ -22,23 +23,23 @@ public: printf("[%02i,%02i] Building tile\n", X, Y); TileBuilder builder(Continent, X, Y, MapId); char buff[100]; - sprintf(buff, "mmaps/%03u%02u%02u.mmtile", MapId, X, Y); + sprintf(buff, "mmaps/%03u%02u%02u.mmtile", MapId, Y, X); FILE* f = fopen(buff, "r"); if (f) // Check if file already exists. { printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y); fclose(f); Free = true; - return 1; + return 0; } - uint8* nav = builder.Build(); + uint8* nav = builder.Build(debug); if (nav) { f = fopen(buff, "wb"); if (!f) { printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff); - return -1; + return 0; } MmapTileHeader header; header.size = builder.DataSize; @@ -73,7 +74,7 @@ void getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, floa bmin[2] = bmax[2] - Constants::TileSize; } -void ContinentBuilder::Build() +void ContinentBuilder::Build(bool debug) { char buff[50]; sprintf(buff, "mmaps/%03u.mmap", MapId); @@ -107,7 +108,7 @@ void ContinentBuilder::Build() fclose(mmap); std::vector Threads; for (uint32 i = 0; i < NumberOfThreads; ++i) - Threads.push_back(new BuilderThread()); + Threads.push_back(new BuilderThread(debug)); printf("Map %s ( %i ) has %i tiles. Building them with %i threads\n", Continent.c_str(), MapId, TileMap->TileTable.size(), NumberOfThreads); for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) { diff --git a/src/tools/mesh_extractor/ContinentBuilder.h b/src/tools/mesh_extractor/ContinentBuilder.h index d3da984595d..c923498fc5e 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.h +++ b/src/tools/mesh_extractor/ContinentBuilder.h @@ -8,7 +8,7 @@ class ContinentBuilder { public: ContinentBuilder(std::string continent, uint32 mapId, WDT* wdt, uint32 tn) : MapId(mapId), Continent(continent), TileMap(wdt), NumberOfThreads(tn) {} - void Build(); + void Build(bool debug); private: std::string Continent; WDT* TileMap; diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 423095b22ca..9d88fcdcdfc 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -14,7 +14,7 @@ LoginDatabaseWorkerPool LoginDatabase; MPQManager* MPQHandler; CacheClass* Cache; -void ExtractAllMaps(std::set& mapIds, uint32 threads) +void ExtractAllMaps(std::set& mapIds, uint32 threads, bool debug) { DBC* dbc = MPQHandler->GetDBC("Map"); for (std::vector::iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr) @@ -31,11 +31,11 @@ void ExtractAllMaps(std::set& mapIds, uint32 threads) continue; printf("Building %s MapId %u\n", name.c_str(), mapId); ContinentBuilder builder(name, mapId, &wdt, threads); - builder.Build(); + builder.Build(debug); } } -bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapList) +bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapList, bool& debugOutput) { char* param = NULL; for (int i = 1; i < argc; ++i) @@ -62,6 +62,14 @@ bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapLis printf("Extracting only provided list of maps (%u).\n", mapList.size()); } + if (strcmp(argv[i], "--debug") == 0) + { + param = argv[++i]; + if (!param) + return false; + debugOutput = atoi(param); + printf("Output will contain debug information (.obj files)\n"); + } } return true; } @@ -71,6 +79,7 @@ void PrintUsage() printf("MeshExtractor help.\n"); printf("* Use \"--threads \" to specify threads, default to 4\n"); printf("* Use \"--maps a,b,c,d,e\" to extract only the maps specified ( do not use spaces )\n"); + printf("* Use \"--debug 1\" to generate debug information of the tiles.\n"); } int main(int argc, char* argv[]) @@ -81,14 +90,14 @@ int main(int argc, char* argv[]) MPQHandler->Initialize(); uint32 threads = 4; std::set mapIds; + bool debug = false; - if (!HandleArgs(argc, argv, threads, mapIds)) + if (!HandleArgs(argc, argv, threads, mapIds, debug)) { PrintUsage(); return -1; } - ExtractAllMaps(mapIds, threads); + ExtractAllMaps(mapIds, threads, debug); return 0; -} - +} \ No newline at end of file diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 0c775b9b8c9..54b9e4865cd 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -17,20 +17,22 @@ TileBuilder::TileBuilder(std::string world, int x, int y, uint32 mapId) : _Geome // 1800 = TileVoxelSize Config.cs = Constants::TileSize / 1800; // Cell Height - Config.ch = 0.3f; - // Min Region Area = 6^2 - Config.minRegionArea = 36; - // Merge Region Area = 12^2 - Config.mergeRegionArea = 144; + Config.ch = 0.4f; + // Min Region Area = 20^2 + Config.minRegionArea = 20*20; + // Merge Region Area = 40^2 + Config.mergeRegionArea = 40*40; + Config.tileSize = Constants::TileSize / 4; Config.walkableSlopeAngle = 50.0f; Config.detailSampleDist = 3.0f; Config.detailSampleMaxError = 1.25f; Config.walkableClimb = 1.0f / Config.ch; - Config.walkableHeight = 2.1f / Config.ch; - Config.walkableRadius = 0.6f / Config.cs; + Config.walkableHeight = 1.652778f / Config.ch; + Config.walkableRadius = 0.2951389f / Config.cs; Config.maxEdgeLen = Config.walkableRadius * 8; - Config.borderSize = Config.walkableRadius + 8; - Config.width = 1800; + Config.borderSize = Config.walkableRadius + 4; + Config.width = 1800 + Config.borderSize * 2; + Config.height = 1800 + Config.borderSize * 2; Config.maxVertsPerPoly = 6; Config.maxSimplificationError = 1.3f; @@ -47,7 +49,7 @@ void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax ) bmax[2] = Constants::Origin[2] + (Constants::TileSize * (Y + 1)); } -uint8* TileBuilder::Build() +uint8* TileBuilder::Build(bool dbg) { _Geometry = new Geometry(); _Geometry->Transform = true; @@ -65,9 +67,9 @@ uint8* TileBuilder::Build() _Geometry->CalculateMinMaxHeight(bbMin[1], bbMax[1]); // again, we load everything - wasteful but who cares - for (int ty = Y - 1; ty <= Y + 1; ty++) + for (int ty = Y - 4; ty <= Y + 4; ty++) { - for (int tx = X - 1; tx <= X + 1; tx++) + for (int tx = X - 4; tx <= X + 4; tx++) { // don't load main tile again if (tx == X && ty == Y) @@ -85,6 +87,19 @@ uint8* TileBuilder::Build() delete _adt; } } + + if (dbg) + { + char buff[100]; + sprintf(buff, "mmaps/%s_%02u%02u.obj", World.c_str(), Y, X); + FILE* debug = fopen(buff, "wb"); + for (int i = 0; i < _Geometry->Vertices.size(); ++i) + fprintf(debug, "v %f %f %f\n", _Geometry->Vertices[i].x, _Geometry->Vertices[i].y, _Geometry->Vertices[i].z); + for (int i = 0; i < _Geometry->Triangles.size(); ++i) + fprintf(debug, "f %i %i %i\n", _Geometry->Triangles[i].V0 + 1, _Geometry->Triangles[i].V1 + 1, _Geometry->Triangles[i].V2 + 1); + fclose(debug); + } + uint32 numVerts = _Geometry->Vertices.size(); uint32 numTris = _Geometry->Triangles.size(); float* vertices; @@ -100,8 +115,7 @@ uint8* TileBuilder::Build() bbMax[0] += Config.borderSize * Config.cs; rcHeightfield* hf = rcAllocHeightfield(); - int width = Config.width + (Config.borderSize * 2); - rcCreateHeightfield(Context, *hf, width, width, bbMin, bbMax, Config.cs, Config.ch); + rcCreateHeightfield(Context, *hf, Config.width, Config.height, bbMin, bbMax, Config.cs, Config.ch); rcClearUnwalkableTriangles(Context, Config.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas); rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb); @@ -208,14 +222,14 @@ uint8* TileBuilder::Build() params.walkableRadius = Config.walkableRadius; params.tileX = X; params.tileY = Y; - params.tileSize = Config.width; + params.tileSize = 1800; // Offmesh-connection settings params.offMeshConCount = 0; // none for now int navDataSize; uint8* navData; - printf("[%02i,%02i] Creating the navmesh!\n", X, Y); + printf("[%02i,%02i] Creating the navmesh with %i vertices, %i polys, %i triangles!\n", X, Y, pmesh->nverts, pmesh->npolys, dmesh->ntris); bool result = dtCreateNavMeshData(¶ms, &navData, &navDataSize); // Free some memory diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h index 2ec45811676..72e275c75b7 100644 --- a/src/tools/mesh_extractor/TileBuilder.h +++ b/src/tools/mesh_extractor/TileBuilder.h @@ -14,7 +14,7 @@ public: ~TileBuilder(); void CalculateTileBounds(float*& bmin, float*& bmax); - uint8* Build(); + uint8* Build(bool dbg); std::string World; int X; diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index 3db387bc81a..6389e0aa66e 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -180,3 +180,253 @@ G3D::Matrix4 Utils::GetWmoDoodadTransformation( DoodadInstance inst, WorldModelD return scale * rotation * quatRotation ** translation * rootTransformation; } + +void MapChunkHeader::Read(FILE* stream) +{ + fread(&Flags, sizeof(uint32), 1, stream); + fread(&IndexX, sizeof(uint32), 1, stream); + fread(&IndexY, sizeof(uint32), 1, stream); + fread(&Layers, sizeof(uint32), 1, stream); + fread(&DoodadRefs, sizeof(uint32), 1, stream); + fread(&OffsetMCVT, sizeof(uint32), 1, stream); + fread(&OffsetMCNR, sizeof(uint32), 1, stream); + fread(&OffsetMCLY, sizeof(uint32), 1, stream); + fread(&OffsetMCRF, sizeof(uint32), 1, stream); + fread(&OffsetMCAL, sizeof(uint32), 1, stream); + fread(&SizeMCAL, sizeof(uint32), 1, stream); + fread(&OffsetMCSH, sizeof(uint32), 1, stream); + fread(&SizeMCSH, sizeof(uint32), 1, stream); + fread(&AreaId, sizeof(uint32), 1, stream); + fread(&MapObjectRefs, sizeof(uint32), 1, stream); + fread(&Holes, sizeof(uint32), 1, stream); + LowQualityTextureMap = new uint32[4]; + fread(LowQualityTextureMap, sizeof(uint32), 4, stream); + fread(&PredTex, sizeof(uint32), 1, stream); + fread(&NumberEffectDoodad, sizeof(uint32), 1, stream); + fread(&OffsetMCSE, sizeof(uint32), 1, stream); + fread(&SoundEmitters, sizeof(uint32), 1, stream); + fread(&OffsetMCLQ, sizeof(uint32), 1, stream); + fread(&SizeMCLQ, sizeof(uint32), 1, stream); + Position = Vector3::Read(stream); + fread(&OffsetMCCV, sizeof(uint32), 1, stream); +} + +void MHDR::Read(FILE* stream) +{ + fread(&Flags, sizeof(uint32), 1, stream); + fread(&OffsetMCIN, sizeof(uint32), 1, stream); + fread(&OffsetMTEX, sizeof(uint32), 1, stream); + fread(&OffsetMMDX, sizeof(uint32), 1, stream); + fread(&OffsetMMID, sizeof(uint32), 1, stream); + fread(&OffsetMWMO, sizeof(uint32), 1, stream); + fread(&OffsetMWID, sizeof(uint32), 1, stream); + fread(&OffsetMDDF, sizeof(uint32), 1, stream); + fread(&OffsetMODF, sizeof(uint32), 1, stream); + fread(&OffsetMFBO, sizeof(uint32), 1, stream); + fread(&OffsetMH2O, sizeof(uint32), 1, stream); + fread(&OffsetMTFX, sizeof(uint32), 1, stream); +} + +void ModelHeader::Read(FILE* stream) +{ + fread(&Magic, sizeof(char), 4, stream); + Magic[4] = '\0'; // null-terminate it. + fread(&Version, sizeof(uint32), 1, stream); + fread(&LengthModelName, sizeof(uint32), 1, stream); + fread(&OffsetName, sizeof(uint32), 1, stream); + fread(&ModelFlags, sizeof(uint32), 1, stream); + fread(&CountGlobalSequences, sizeof(uint32), 1, stream); + fread(&OffsetGlobalSequences, sizeof(uint32), 1, stream); + fread(&CountAnimations, sizeof(uint32), 1, stream); + fread(&OffsetAnimations, sizeof(uint32), 1, stream); + fread(&CountAnimationLookup, sizeof(uint32), 1, stream); + fread(&OffsetAnimationLookup, sizeof(uint32), 1, stream); + fread(&CountBones, sizeof(uint32), 1, stream); + fread(&OffsetBones, sizeof(uint32), 1, stream); + fread(&CountKeyBoneLookup, sizeof(uint32), 1, stream); + fread(&OffsetKeyBoneLookup, sizeof(uint32), 1, stream); + fread(&CountVertices, sizeof(uint32), 1, stream); + fread(&OffsetVertices, sizeof(uint32), 1, stream); + fread(&CountViews, sizeof(uint32), 1, stream); + fread(&CountColors, sizeof(uint32), 1, stream); + fread(&OffsetColors, sizeof(uint32), 1, stream); + fread(&CountTextures, sizeof(uint32), 1, stream); + fread(&OffsetTextures, sizeof(uint32), 1, stream); + fread(&CountTransparency, sizeof(uint32), 1, stream); + fread(&OffsetTransparency, sizeof(uint32), 1, stream); + fread(&CountUvAnimation, sizeof(uint32), 1, stream); + fread(&OffsetUvAnimation, sizeof(uint32), 1, stream); + fread(&CountTexReplace, sizeof(uint32), 1, stream); + fread(&OffsetTexReplace, sizeof(uint32), 1, stream); + fread(&CountRenderFlags, sizeof(uint32), 1, stream); + fread(&OffsetRenderFlags, sizeof(uint32), 1, stream); + fread(&CountBoneLookup, sizeof(uint32), 1, stream); + fread(&OffsetBoneLookup, sizeof(uint32), 1, stream); + fread(&CountTexLookup, sizeof(uint32), 1, stream); + fread(&OffsetTexLookup, sizeof(uint32), 1, stream); + fread(&CountTexUnits, sizeof(uint32), 1, stream); + fread(&OffsetTexUnits, sizeof(uint32), 1, stream); + fread(&CountTransLookup, sizeof(uint32), 1, stream); + fread(&OffsetTransLookup, sizeof(uint32), 1, stream); + fread(&CountUvAnimLookup, sizeof(uint32), 1, stream); + fread(&OffsetUvAnimLookup, sizeof(uint32), 1, stream); + fread(&CountColors, sizeof(uint32), 1, stream); + fread(&OffsetColors, sizeof(uint32), 1, stream); + fread(&CountTextures, sizeof(uint32), 1, stream); + fread(&OffsetTextures, sizeof(uint32), 1, stream); + fread(&CountTransparency, sizeof(uint32), 1, stream); + fread(&OffsetTransparency, sizeof(uint32), 1, stream); + fread(&CountUvAnimation, sizeof(uint32), 1, stream); + fread(&OffsetUvAnimation, sizeof(uint32), 1, stream); + fread(&CountTexReplace, sizeof(uint32), 1, stream); + fread(&OffsetTexReplace, sizeof(uint32), 1, stream); + VertexBox[0] = Vector3::Read(stream); + VertexBox[1] = Vector3::Read(stream); + fread(&VertexRadius, sizeof(float), 1, stream); + BoundingBox[0] = Vector3::Read(stream); + BoundingBox[1] = Vector3::Read(stream); + fread(&BoundingRadius, sizeof(float), 1, stream); + fread(&CountBoundingTriangles, sizeof(uint32), 1, stream); + fread(&OffsetBoundingTriangles, sizeof(uint32), 1, stream); + fread(&CountBoundingVertices, sizeof(uint32), 1, stream); + fread(&OffsetBoundingVertices, sizeof(uint32), 1, stream); + fread(&CountBoundingNormals, sizeof(uint32), 1, stream); + fread(&OffsetBoundingNormals, sizeof(uint32), 1, stream); +} + +WorldModelHeader WorldModelHeader::Read(FILE* stream) +{ + WorldModelHeader ret; + fread(&ret.CountMaterials, sizeof(uint32), 1, stream); + fread(&ret.CountGroups, sizeof(uint32), 1, stream); + fread(&ret.CountPortals, sizeof(uint32), 1, stream); + fread(&ret.CountLights, sizeof(uint32), 1, stream); + fread(&ret.CountModels, sizeof(uint32), 1, stream); + fread(&ret.CountDoodads, sizeof(uint32), 1, stream); + fread(&ret.CountSets, sizeof(uint32), 1, stream); + fread(&ret.AmbientColorUnk, sizeof(uint32), 1, stream); + fread(&ret.WmoId, sizeof(uint32), 1, stream); + ret.BoundingBox[0] = Vector3::Read(stream); + ret.BoundingBox[1] = Vector3::Read(stream); + fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream); + return ret; +} + +DoodadInstance DoodadInstance::Read(FILE* stream) +{ + DoodadInstance ret; + fread(&ret.FileOffset, sizeof(uint32), 1, stream); + ret.Position = Vector3::Read(stream); + fread(&ret.QuatW, sizeof(float), 1, stream); + fread(&ret.QuatX, sizeof(float), 1, stream); + fread(&ret.QuatY, sizeof(float), 1, stream); + fread(&ret.QuatZ, sizeof(float), 1, stream); + fread(&ret.Scale, sizeof(float), 1, stream); + fread(&ret.LightColor, sizeof(uint32), 1, stream); + return ret; +} + +DoodadSet DoodadSet::Read(FILE* stream) +{ + DoodadSet ret; + char name[21]; + fread(&name, sizeof(char), 20, stream); + name[20] = '\0'; + ret.Name = name; + fread(&ret.FirstInstanceIndex, sizeof(uint32), 1, stream); + fread(&ret.CountInstances, sizeof(uint32), 1, stream); + fread(&ret.UnknownZero, sizeof(uint32), 1, stream); + return ret; +} + +LiquidHeader LiquidHeader::Read(FILE* stream) +{ + LiquidHeader ret; + fread(&ret.CountXVertices, sizeof(uint32), 1, stream); + fread(&ret.CountYVertices, sizeof(uint32), 1, stream); + fread(&ret.Width, sizeof(uint32), 1, stream); + fread(&ret.Height, sizeof(uint32), 1, stream); + ret.BaseLocation = Vector3::Read(stream); + fread(&ret.MaterialId, sizeof(uint16), 1, stream); + return ret; +} + +LiquidData LiquidData::Read(FILE* stream, LiquidHeader& header) +{ + LiquidData ret; + ret.HeightMap = new float*[header.CountXVertices]; + for (uint32 i = 0; i < header.CountXVertices; ++i) + ret.HeightMap[i] = new float[header.CountYVertices]; + + ret.RenderFlags = new uint8*[header.Width]; + for (uint32 i = 0; i < header.Width; ++i) + ret.RenderFlags[i] = new uint8[header.Height]; + + for (uint32 y = 0; y < header.CountYVertices; y++) + { + for (uint32 x = 0; x < header.CountXVertices; x++) + { + uint32 discard; + fread(&discard, sizeof(uint32), 1, stream); + float tmp; + fread(&tmp, sizeof(float), 1, stream); + ret.HeightMap[x][y] = tmp; + } + } + + for (uint32 y = 0; y < header.Height; y++) + { + for (uint32 x = 0; x < header.Width; x++) + { + uint8 tmp; + fread(&tmp, sizeof(uint8), 1, stream); + ret.RenderFlags[x][y] = tmp; + } + } + + return ret; +} + +H2ORenderMask H2ORenderMask::Read(FILE* stream) +{ + H2ORenderMask ret; + fread(&ret.Mask, sizeof(uint8), 8, stream); + return ret; +} + +bool MCNKLiquidData::IsWater(int x, int y, float height) +{ + if (!Heights) + return false; + if (!Mask.ShouldRender(x, y)) + return false; + float diff = Heights[x][y] - height; + if (diff > Constants::MaxStandableHeight) + return true; + return false; +} + +H2OHeader H2OHeader::Read(FILE* stream) +{ + H2OHeader ret; + fread(&ret.OffsetInformation, sizeof(uint32), 1, stream); + fread(&ret.LayerCount, sizeof(uint32), 1, stream); + fread(&ret.OffsetRender, sizeof(uint32), 1, stream); + return ret; +} + +H2OInformation H2OInformation::Read(FILE* stream) +{ + H2OInformation ret; + fread(&ret.LiquidType, sizeof(uint16), 1, stream); + fread(&ret.Flags, sizeof(uint16), 1, stream); + fread(&ret.HeightLevel1, sizeof(float), 1, stream); + fread(&ret.HeightLevel2, sizeof(float), 1, stream); + fread(&ret.OffsetX, sizeof(uint8), 1, stream); + fread(&ret.OffsetY, sizeof(uint8), 1, stream); + fread(&ret.Width, sizeof(uint8), 1, stream); + fread(&ret.Height, sizeof(uint8), 1, stream); + fread(&ret.OffsetMask2, sizeof(uint32), 1, stream); + fread(&ret.OffsetHeightmap, sizeof(uint32), 1, stream); + return ret; +} diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index c9d2746b7d8..a45c3659240 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -77,35 +77,7 @@ public: Vector3 Position; uint32 OffsetMCCV; - void Read(FILE* stream) - { - fread(&Flags, sizeof(uint32), 1, stream); - fread(&IndexX, sizeof(uint32), 1, stream); - fread(&IndexY, sizeof(uint32), 1, stream); - fread(&Layers, sizeof(uint32), 1, stream); - fread(&DoodadRefs, sizeof(uint32), 1, stream); - fread(&OffsetMCVT, sizeof(uint32), 1, stream); - fread(&OffsetMCNR, sizeof(uint32), 1, stream); - fread(&OffsetMCLY, sizeof(uint32), 1, stream); - fread(&OffsetMCRF, sizeof(uint32), 1, stream); - fread(&OffsetMCAL, sizeof(uint32), 1, stream); - fread(&SizeMCAL, sizeof(uint32), 1, stream); - fread(&OffsetMCSH, sizeof(uint32), 1, stream); - fread(&SizeMCSH, sizeof(uint32), 1, stream); - fread(&AreaId, sizeof(uint32), 1, stream); - fread(&MapObjectRefs, sizeof(uint32), 1, stream); - fread(&Holes, sizeof(uint32), 1, stream); - LowQualityTextureMap = new uint32[4]; - fread(LowQualityTextureMap, sizeof(uint32), 4, stream); - fread(&PredTex, sizeof(uint32), 1, stream); - fread(&NumberEffectDoodad, sizeof(uint32), 1, stream); - fread(&OffsetMCSE, sizeof(uint32), 1, stream); - fread(&SoundEmitters, sizeof(uint32), 1, stream); - fread(&OffsetMCLQ, sizeof(uint32), 1, stream); - fread(&SizeMCLQ, sizeof(uint32), 1, stream); - Position = Vector3::Read(stream); - fread(&OffsetMCCV, sizeof(uint32), 1, stream); - } + void Read(FILE* stream); }; class MHDR @@ -125,21 +97,7 @@ public: uint32 OffsetMH2O; uint32 OffsetMTFX; - void Read(FILE* stream) - { - fread(&Flags, sizeof(uint32), 1, stream); - fread(&OffsetMCIN, sizeof(uint32), 1, stream); - fread(&OffsetMTEX, sizeof(uint32), 1, stream); - fread(&OffsetMMDX, sizeof(uint32), 1, stream); - fread(&OffsetMMID, sizeof(uint32), 1, stream); - fread(&OffsetMWMO, sizeof(uint32), 1, stream); - fread(&OffsetMWID, sizeof(uint32), 1, stream); - fread(&OffsetMDDF, sizeof(uint32), 1, stream); - fread(&OffsetMODF, sizeof(uint32), 1, stream); - fread(&OffsetMFBO, sizeof(uint32), 1, stream); - fread(&OffsetMH2O, sizeof(uint32), 1, stream); - fread(&OffsetMTFX, sizeof(uint32), 1, stream); - } + void Read(FILE* stream); }; class ModelHeader @@ -196,72 +154,7 @@ public: uint32 CountBoundingNormals; uint32 OffsetBoundingNormals; - void Read(FILE* stream) - { - fread(&Magic, sizeof(char), 4, stream); - Magic[4] = '\0'; // null-terminate it. - fread(&Version, sizeof(uint32), 1, stream); - fread(&LengthModelName, sizeof(uint32), 1, stream); - fread(&OffsetName, sizeof(uint32), 1, stream); - fread(&ModelFlags, sizeof(uint32), 1, stream); - fread(&CountGlobalSequences, sizeof(uint32), 1, stream); - fread(&OffsetGlobalSequences, sizeof(uint32), 1, stream); - fread(&CountAnimations, sizeof(uint32), 1, stream); - fread(&OffsetAnimations, sizeof(uint32), 1, stream); - fread(&CountAnimationLookup, sizeof(uint32), 1, stream); - fread(&OffsetAnimationLookup, sizeof(uint32), 1, stream); - fread(&CountBones, sizeof(uint32), 1, stream); - fread(&OffsetBones, sizeof(uint32), 1, stream); - fread(&CountKeyBoneLookup, sizeof(uint32), 1, stream); - fread(&OffsetKeyBoneLookup, sizeof(uint32), 1, stream); - fread(&CountVertices, sizeof(uint32), 1, stream); - fread(&OffsetVertices, sizeof(uint32), 1, stream); - fread(&CountViews, sizeof(uint32), 1, stream); - fread(&CountColors, sizeof(uint32), 1, stream); - fread(&OffsetColors, sizeof(uint32), 1, stream); - fread(&CountTextures, sizeof(uint32), 1, stream); - fread(&OffsetTextures, sizeof(uint32), 1, stream); - fread(&CountTransparency, sizeof(uint32), 1, stream); - fread(&OffsetTransparency, sizeof(uint32), 1, stream); - fread(&CountUvAnimation, sizeof(uint32), 1, stream); - fread(&OffsetUvAnimation, sizeof(uint32), 1, stream); - fread(&CountTexReplace, sizeof(uint32), 1, stream); - fread(&OffsetTexReplace, sizeof(uint32), 1, stream); - fread(&CountRenderFlags, sizeof(uint32), 1, stream); - fread(&OffsetRenderFlags, sizeof(uint32), 1, stream); - fread(&CountBoneLookup, sizeof(uint32), 1, stream); - fread(&OffsetBoneLookup, sizeof(uint32), 1, stream); - fread(&CountTexLookup, sizeof(uint32), 1, stream); - fread(&OffsetTexLookup, sizeof(uint32), 1, stream); - fread(&CountTexUnits, sizeof(uint32), 1, stream); - fread(&OffsetTexUnits, sizeof(uint32), 1, stream); - fread(&CountTransLookup, sizeof(uint32), 1, stream); - fread(&OffsetTransLookup, sizeof(uint32), 1, stream); - fread(&CountUvAnimLookup, sizeof(uint32), 1, stream); - fread(&OffsetUvAnimLookup, sizeof(uint32), 1, stream); - fread(&CountColors, sizeof(uint32), 1, stream); - fread(&OffsetColors, sizeof(uint32), 1, stream); - fread(&CountTextures, sizeof(uint32), 1, stream); - fread(&OffsetTextures, sizeof(uint32), 1, stream); - fread(&CountTransparency, sizeof(uint32), 1, stream); - fread(&OffsetTransparency, sizeof(uint32), 1, stream); - fread(&CountUvAnimation, sizeof(uint32), 1, stream); - fread(&OffsetUvAnimation, sizeof(uint32), 1, stream); - fread(&CountTexReplace, sizeof(uint32), 1, stream); - fread(&OffsetTexReplace, sizeof(uint32), 1, stream); - VertexBox[0] = Vector3::Read(stream); - VertexBox[1] = Vector3::Read(stream); - fread(&VertexRadius, sizeof(float), 1, stream); - BoundingBox[0] = Vector3::Read(stream); - BoundingBox[1] = Vector3::Read(stream); - fread(&BoundingRadius, sizeof(float), 1, stream); - fread(&CountBoundingTriangles, sizeof(uint32), 1, stream); - fread(&OffsetBoundingTriangles, sizeof(uint32), 1, stream); - fread(&CountBoundingVertices, sizeof(uint32), 1, stream); - fread(&OffsetBoundingVertices, sizeof(uint32), 1, stream); - fread(&CountBoundingNormals, sizeof(uint32), 1, stream); - fread(&OffsetBoundingNormals, sizeof(uint32), 1, stream); - } + void Read(FILE* stream); }; class WorldModelHeader @@ -280,23 +173,7 @@ public: Vector3 BoundingBox[2]; uint32 LiquidTypeRelated; - static WorldModelHeader Read(FILE* stream) - { - WorldModelHeader ret; - fread(&ret.CountMaterials, sizeof(uint32), 1, stream); - fread(&ret.CountGroups, sizeof(uint32), 1, stream); - fread(&ret.CountPortals, sizeof(uint32), 1, stream); - fread(&ret.CountLights, sizeof(uint32), 1, stream); - fread(&ret.CountModels, sizeof(uint32), 1, stream); - fread(&ret.CountDoodads, sizeof(uint32), 1, stream); - fread(&ret.CountSets, sizeof(uint32), 1, stream); - fread(&ret.AmbientColorUnk, sizeof(uint32), 1, stream); - fread(&ret.WmoId, sizeof(uint32), 1, stream); - ret.BoundingBox[0] = Vector3::Read(stream); - ret.BoundingBox[1] = Vector3::Read(stream); - fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream); - return ret; - } + static WorldModelHeader Read(FILE* stream); }; class DoodadInstance @@ -313,19 +190,7 @@ public: float Scale; uint32 LightColor; - static DoodadInstance Read(FILE* stream) - { - DoodadInstance ret; - fread(&ret.FileOffset, sizeof(uint32), 1, stream); - ret.Position = Vector3::Read(stream); - fread(&ret.QuatW, sizeof(float), 1, stream); - fread(&ret.QuatX, sizeof(float), 1, stream); - fread(&ret.QuatY, sizeof(float), 1, stream); - fread(&ret.QuatZ, sizeof(float), 1, stream); - fread(&ret.Scale, sizeof(float), 1, stream); - fread(&ret.LightColor, sizeof(uint32), 1, stream); - return ret; - } + static DoodadInstance Read(FILE* stream); }; class DoodadSet @@ -337,18 +202,7 @@ public: uint32 CountInstances; uint32 UnknownZero; - static DoodadSet Read(FILE* stream) - { - DoodadSet ret; - char name[21]; - fread(&name, sizeof(char), 20, stream); - name[20] = '\0'; - ret.Name = name; - fread(&ret.FirstInstanceIndex, sizeof(uint32), 1, stream); - fread(&ret.CountInstances, sizeof(uint32), 1, stream); - fread(&ret.UnknownZero, sizeof(uint32), 1, stream); - return ret; - } + static DoodadSet Read(FILE* stream); }; class LiquidHeader @@ -362,17 +216,7 @@ public: Vector3 BaseLocation; uint16 MaterialId; - static LiquidHeader Read(FILE* stream) - { - LiquidHeader ret; - fread(&ret.CountXVertices, sizeof(uint32), 1, stream); - fread(&ret.CountYVertices, sizeof(uint32), 1, stream); - fread(&ret.Width, sizeof(uint32), 1, stream); - fread(&ret.Height, sizeof(uint32), 1, stream); - ret.BaseLocation = Vector3::Read(stream); - fread(&ret.MaterialId, sizeof(uint16), 1, stream); - return ret; - } + static LiquidHeader Read(FILE* stream); }; class LiquidData @@ -387,41 +231,7 @@ public: return RenderFlags[x][y] != 0x0F; } - static LiquidData Read(FILE* stream, LiquidHeader header) - { - LiquidData ret; - ret.HeightMap = new float*[header.CountXVertices]; - for (uint32 i = 0; i < header.CountXVertices; ++i) - ret.HeightMap[i] = new float[header.CountYVertices]; - - ret.RenderFlags = new uint8*[header.Width]; - for (uint32 i = 0; i < header.Width; ++i) - ret.RenderFlags[i] = new uint8[header.Height]; - - for (uint32 y = 0; y < header.CountYVertices; y++) - { - for (uint32 x = 0; x < header.CountXVertices; x++) - { - uint32 discard; - fread(&discard, sizeof(uint32), 1, stream); - float tmp; - fread(&tmp, sizeof(float), 1, stream); - ret.HeightMap[x][y] = tmp; - } - } - - for (uint32 y = 0; y < header.Height; y++) - { - for (uint32 x = 0; x < header.Width; x++) - { - uint8 tmp; - fread(&tmp, sizeof(uint8), 1, stream); - ret.RenderFlags[x][y] = tmp; - } - } - - return ret; - } + static LiquidData Read(FILE* stream, LiquidHeader& header); }; class H2ORenderMask @@ -435,12 +245,7 @@ public: return (Mask[y] >> x & 1) != 0; } - static H2ORenderMask Read(FILE* stream) - { - H2ORenderMask ret; - fread(&ret.Mask, sizeof(uint8), 8, stream); - return ret; - } + static H2ORenderMask Read(FILE* stream); }; class MCNKLiquidData @@ -452,17 +257,7 @@ public: float** Heights; H2ORenderMask Mask; - bool IsWater(int x, int y, float height) - { - if (!Heights) - return false; - if (!Mask.ShouldRender(x, y)) - return false; - float diff = Heights[x][y] - height; - if (diff > Constants::MaxStandableHeight) - return true; - return false; - } + bool IsWater(int x, int y, float height); }; class H2OHeader @@ -473,14 +268,7 @@ public: uint32 LayerCount; uint32 OffsetRender; - static H2OHeader Read(FILE* stream) - { - H2OHeader ret; - fread(&ret.OffsetInformation, sizeof(uint32), 1, stream); - fread(&ret.LayerCount, sizeof(uint32), 1, stream); - fread(&ret.OffsetRender, sizeof(uint32), 1, stream); - return ret; - } + static H2OHeader Read(FILE* stream); }; class H2OInformation @@ -498,21 +286,7 @@ public: uint32 OffsetMask2; uint32 OffsetHeightmap; - static H2OInformation Read(FILE* stream) - { - H2OInformation ret; - fread(&ret.LiquidType, sizeof(uint16), 1, stream); - fread(&ret.Flags, sizeof(uint16), 1, stream); - fread(&ret.HeightLevel1, sizeof(float), 1, stream); - fread(&ret.HeightLevel2, sizeof(float), 1, stream); - fread(&ret.OffsetX, sizeof(uint8), 1, stream); - fread(&ret.OffsetY, sizeof(uint8), 1, stream); - fread(&ret.Width, sizeof(uint8), 1, stream); - fread(&ret.Height, sizeof(uint8), 1, stream); - fread(&ret.OffsetMask2, sizeof(uint32), 1, stream); - fread(&ret.OffsetHeightmap, sizeof(uint32), 1, stream); - return ret; - } + static H2OInformation Read(FILE* stream); }; // Dummy class to act as an interface. -- cgit v1.2.3 From e32ddea96a017c7d5ad22eca16764d74501b90f3 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 3 Oct 2012 18:02:18 -0500 Subject: Tools/MeshExtractor: * Added the capability of extracting DBCs. * Fixed most compile warnings * Some work on the navigation mesh generation process (still not ready) --- src/tools/mesh_extractor/ChunkedData.cpp | 4 +- src/tools/mesh_extractor/Constants.h | 11 +++ src/tools/mesh_extractor/ContinentBuilder.cpp | 16 +++-- src/tools/mesh_extractor/DoodadHandler.cpp | 2 +- src/tools/mesh_extractor/LiquidHandler.cpp | 8 +-- src/tools/mesh_extractor/MPQ.cpp | 1 + src/tools/mesh_extractor/MPQ.h | 2 + src/tools/mesh_extractor/MPQManager.cpp | 61 ++++++++++++++--- src/tools/mesh_extractor/MPQManager.h | 6 +- src/tools/mesh_extractor/MeshExtractor.cpp | 93 ++++++++++++++++++++++---- src/tools/mesh_extractor/TileBuilder.cpp | 75 ++++++++++++--------- src/tools/mesh_extractor/TileBuilder.h | 4 +- src/tools/mesh_extractor/Utils.cpp | 38 +++++++++++ src/tools/mesh_extractor/Utils.h | 2 + src/tools/mesh_extractor/WorldModelGroup.cpp | 8 +-- src/tools/mesh_extractor/WorldModelHandler.cpp | 2 +- src/tools/mesh_extractor/WorldModelRoot.cpp | 6 +- 17 files changed, 264 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/ChunkedData.cpp b/src/tools/mesh_extractor/ChunkedData.cpp index 4431993e3d1..4d609d8f6b2 100644 --- a/src/tools/mesh_extractor/ChunkedData.cpp +++ b/src/tools/mesh_extractor/ChunkedData.cpp @@ -48,7 +48,7 @@ void ChunkedData::Load( uint32 maxLength, uint32 chunksHint ) int ChunkedData::GetFirstIndex( std::string name ) { - for (int i = 0; i < Chunks.size(); ++i) + for (uint32 i = 0; i < Chunks.size(); ++i) if (Chunks[i]->Name == name) return i; return -1; @@ -56,7 +56,7 @@ int ChunkedData::GetFirstIndex( std::string name ) Chunk* ChunkedData::GetChunkByName( std::string name ) { - for (int i = 0; i < Chunks.size(); ++i) + for (uint32 i = 0; i < Chunks.size(); ++i) if (Chunks[i]->Name == name) return Chunks[i]; return NULL; diff --git a/src/tools/mesh_extractor/Constants.h b/src/tools/mesh_extractor/Constants.h index f44d5f16797..f3b71812155 100644 --- a/src/tools/mesh_extractor/Constants.h +++ b/src/tools/mesh_extractor/Constants.h @@ -29,6 +29,17 @@ public: POLY_FLAG_SWIM = 2, POLY_FLAG_FLIGHTMASTER = 4 }; + + enum ExtractFlags + { + EXTRACT_FLAG_DBC = 1, + EXTRACT_FLAG_MAPS = 2, + EXTRACT_FLAG_VMAPS = 4, + EXTRACT_FLAG_GOB_MODELS = 8, + EXTRACT_FLAG_MMAPS = 16, + EXTRACT_FLAG_ALLOWED = EXTRACT_FLAG_DBC | EXTRACT_FLAG_MAPS | EXTRACT_FLAG_VMAPS | EXTRACT_FLAG_GOB_MODELS | EXTRACT_FLAG_MMAPS + }; + static const float TileSize; static const float MaxXY; static const float ChunkSize; diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index 984f6170357..e4a1d2ca9f4 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -13,8 +13,9 @@ private: int X, Y, MapId; std::string Continent; bool debug; + dtNavMeshParams Params; public: - BuilderThread(bool deb) : Free(true), debug(deb) {} + BuilderThread(bool deb, dtNavMeshParams& params) : Free(true), debug(deb), Params(params) {} void SetData(int x, int y, int map, std::string cont) { X = x; Y = y; MapId = map; Continent = cont; } int svc() @@ -32,7 +33,7 @@ public: Free = true; return 0; } - uint8* nav = builder.Build(debug); + uint8* nav = builder.Build(debug, Params); if (nav) { f = fopen(buff, "wb"); @@ -101,14 +102,17 @@ void ContinentBuilder::Build(bool debug) dtNavMeshParams params; params.maxPolys = 32768; params.maxTiles = TileMap->TileTable.size(); - rcVcopy(params.orig, bmin); - params.tileHeight = 533.33333f; - params.tileWidth = 533.33333f; + // rcVcopy(params.orig, bmin); + params.orig[0] = Constants::Origin[0]; + params.orig[1] = 0; + params.orig[2] = Constants::Origin[2]; + params.tileHeight = Constants::TileSize; + params.tileWidth = Constants::TileSize; fwrite(¶ms, sizeof(dtNavMeshParams), 1, mmap); fclose(mmap); std::vector Threads; for (uint32 i = 0; i < NumberOfThreads; ++i) - Threads.push_back(new BuilderThread(debug)); + Threads.push_back(new BuilderThread(debug, params)); printf("Map %s ( %i ) has %i tiles. Building them with %i threads\n", Continent.c_str(), MapId, TileMap->TileTable.size(), NumberOfThreads); for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) { diff --git a/src/tools/mesh_extractor/DoodadHandler.cpp b/src/tools/mesh_extractor/DoodadHandler.cpp index 363f07b4578..4e8028b3dff 100644 --- a/src/tools/mesh_extractor/DoodadHandler.cpp +++ b/src/tools/mesh_extractor/DoodadHandler.cpp @@ -31,7 +31,7 @@ void DoodadHandler::ProcessInternal( ChunkedData* subChunks ) { int32 index; fread(&index, sizeof(int32), 1, stream); - if (index < 0 || index >= _definitions->size()) + if (index < 0 || uint32(index) >= _definitions->size()) continue; DoodadDefinition doodad = (*_definitions)[index]; if (_drawn.find(doodad.UniqueId) != _drawn.end()) diff --git a/src/tools/mesh_extractor/LiquidHandler.cpp b/src/tools/mesh_extractor/LiquidHandler.cpp index 5b998d75db9..7844130ab34 100644 --- a/src/tools/mesh_extractor/LiquidHandler.cpp +++ b/src/tools/mesh_extractor/LiquidHandler.cpp @@ -34,10 +34,10 @@ void LiquidHandler::HandleNewLiquid() H2OInformation information = H2OInformation::Read(stream); float** heights = new float*[9]; - for (int i = 0; i < 9; ++i) + for (int j = 0; j < 9; ++i) { - heights[i] = new float[9]; - memset(heights[i], 0, sizeof(float) * 9); + heights[j] = new float[9]; + memset(heights[j], 0, sizeof(float) * 9); } H2ORenderMask renderMask; @@ -52,7 +52,7 @@ void LiquidHandler::HandleNewLiquid() uint8* altMask = new uint8[size]; fread(altMask, sizeof(uint8), size, stream); - for (int mi = 0; mi < size; mi++) + for (uint32 mi = 0; mi < size; mi++) renderMask.Mask[mi + information.OffsetY] |= altMask[mi]; delete[] altMask; } diff --git a/src/tools/mesh_extractor/MPQ.cpp b/src/tools/mesh_extractor/MPQ.cpp index 699b0a5014c..b7be181594d 100644 --- a/src/tools/mesh_extractor/MPQ.cpp +++ b/src/tools/mesh_extractor/MPQ.cpp @@ -31,6 +31,7 @@ MPQArchive::MPQArchive(const char* filename) break; } } + GetFileListTo(Files); } void MPQArchive::close() diff --git a/src/tools/mesh_extractor/MPQ.h b/src/tools/mesh_extractor/MPQ.h index dd566bccff5..15fce452726 100644 --- a/src/tools/mesh_extractor/MPQ.h +++ b/src/tools/mesh_extractor/MPQ.h @@ -16,6 +16,8 @@ class MPQArchive public: mpq_archive_s *mpq_a; + + vector Files; MPQArchive(const char* filename); void close(); diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp index 608eef1547a..90491dfb945 100644 --- a/src/tools/mesh_extractor/MPQManager.cpp +++ b/src/tools/mesh_extractor/MPQManager.cpp @@ -15,7 +15,7 @@ char* MPQManager::Files[] = { "patch-3.MPQ" }; -char* MPQManager::Languages[] = { "esES", "enUS", "enGB", "esMX", "deDE" }; +char* MPQManager::Languages[] = { "enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; void MPQManager::Initialize() { @@ -31,21 +31,38 @@ void MPQManager::Initialize() void MPQManager::InitializeDBC() { - CurLocale = 0; + BaseLocale = -1; std::string fileName; uint32 size = sizeof(Languages) / sizeof(char*); + MPQArchive* _baseLocale = NULL; for (uint32 i = 0; i < size; ++i) { - fileName = "Data/" + std::string(Languages[i]) + "/locale-" + std::string(Languages[i]) + ".MPQ"; - FILE* file = fopen(fileName.c_str(), "rb"); + std::string _fileName = "Data/" + std::string(Languages[i]) + "/locale-" + std::string(Languages[i]) + ".MPQ"; + FILE* file = fopen(_fileName.c_str(), "rb"); if (file) { - CurLocale = i; - break; + if (BaseLocale == -1) + { + BaseLocale = i; + _baseLocale = new MPQArchive(_fileName.c_str()); + fileName = _fileName; + LocaleFiles[i] = _baseLocale; + } + else + LocaleFiles[i] = new MPQArchive(_fileName.c_str()); + + AvailableLocales.insert(i); + printf("Detected locale: %s\n", Languages[i]); } } - Archives.push_front(new MPQArchive(fileName.c_str())); - printf("Using locale: %s\n", Languages[CurLocale]); + Archives.push_front(_baseLocale); + if (BaseLocale == -1) + { + printf("No locale data detected\n"); + ASSERT(false); + } + else + printf("Using default locale: %s\n", Languages[BaseLocale]); } FILE* MPQManager::GetFile( std::string path ) @@ -62,3 +79,31 @@ DBC* MPQManager::GetDBC( std::string name ) std::string path = "DBFilesClient\\" + name + ".dbc"; return new DBC(GetFile(path)); } + +FILE* MPQManager::GetFileFrom( std::string path, MPQArchive* file ) +{ + ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL); + mpq_archive* mpq_a = file->mpq_a; + + uint32_t filenum; + if(libmpq__file_number(mpq_a, path.c_str(), &filenum)) + return NULL; + + libmpq__off_t transferred; + libmpq__off_t size = 0; + libmpq__file_unpacked_size(mpq_a, filenum, &size); + + // HACK: in patch.mpq some files don't want to open and give 1 for filesize + if (size <= 1) + return NULL; + + uint8* buffer = new uint8[size]; + + //libmpq_file_getdata + libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); + + // Pack the return into a FILE stream + FILE* ret = tmpfile(); + fwrite(buffer, sizeof(uint8), size, ret); + return ret; +} diff --git a/src/tools/mesh_extractor/MPQManager.h b/src/tools/mesh_extractor/MPQManager.h index 0050dc5218a..c23d7177825 100644 --- a/src/tools/mesh_extractor/MPQManager.h +++ b/src/tools/mesh_extractor/MPQManager.h @@ -13,10 +13,14 @@ public: void Initialize(); FILE* GetFile(std::string path); + FILE* GetFileFrom(std::string path, MPQArchive* file); DBC* GetDBC(std::string name); + std::vector GetAllFiles(std::string extension); std::deque Archives; - uint32 CurLocale; + int32 BaseLocale; + std::set AvailableLocales; + std::map LocaleFiles; static char* Files[]; static char* Languages[]; diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 9d88fcdcdfc..d6b701607ba 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -3,6 +3,7 @@ #include "ContinentBuilder.h" #include "Cache.h" #include "DBC.h" +#include "Constants.h" #include @@ -14,7 +15,7 @@ LoginDatabaseWorkerPool LoginDatabase; MPQManager* MPQHandler; CacheClass* Cache; -void ExtractAllMaps(std::set& mapIds, uint32 threads, bool debug) +void ExtractMMaps(std::set& mapIds, uint32 threads, bool debug) { DBC* dbc = MPQHandler->GetDBC("Map"); for (std::vector::iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr) @@ -35,9 +36,45 @@ void ExtractAllMaps(std::set& mapIds, uint32 threads, bool debug) } } -bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapList, bool& debugOutput) +void ExtractDBCs() +{ + printf("Extracting DBCs\n"); + // Create the filesystem structure + std::string baseDBCPath = "dbc/"; + Utils::CreateDir(baseDBCPath); + + // Populate list of DBC files + std::set DBCFiles; + for (std::vector::iterator itr = MPQHandler->LocaleFiles[MPQHandler->BaseLocale]->Files.begin(); itr != MPQHandler->LocaleFiles[MPQHandler->BaseLocale]->Files.end(); ++itr) + if (itr->rfind(".dbc") == itr->length() - strlen(".dbc")) + DBCFiles.insert(*itr); + + // Iterate over all available locales + for (std::set::iterator itr = MPQHandler->AvailableLocales.begin(); itr != MPQHandler->AvailableLocales.end(); ++itr) + { + printf("Extracting DBCs for locale %s\n", MPQManager::Languages[*itr]); + std::string path = baseDBCPath; + if (*itr != MPQHandler->BaseLocale) + { + path += std::string(MPQManager::Languages[*itr]) + "/"; + Utils::CreateDir(path); + } + + std::string component = "component.wow-" + std::string(MPQManager::Languages[*itr]) + ".txt"; + // Extract the component file + Utils::SaveToDisk(MPQHandler->GetFile(component), path + component); + // Extract the DBC files for the given locale + for (std::set::iterator itr2 = DBCFiles.begin(); itr2 != DBCFiles.end(); ++itr2) + Utils::SaveToDisk(MPQHandler->GetFileFrom(*itr2, MPQHandler->LocaleFiles[*itr]), path + (itr2->c_str() + strlen("DBFilesClient\\"))); + } + printf("DBC extraction finished!\n"); +} + +bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapList, bool& debugOutput, uint32& extractFlags) { char* param = NULL; + extractFlags = 0; + for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "--threads") == 0) @@ -49,7 +86,7 @@ bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapLis threads = atoi(param); printf("Using %i threads\n", threads); } - if (strcmp(argv[i], "--maps") == 0) + else if (strcmp(argv[i], "--maps") == 0) { param = argv[++i]; if (!param) @@ -62,13 +99,32 @@ bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapLis printf("Extracting only provided list of maps (%u).\n", mapList.size()); } - if (strcmp(argv[i], "--debug") == 0) + else if (strcmp(argv[i], "--debug") == 0) { param = argv[++i]; if (!param) return false; debugOutput = atoi(param); - printf("Output will contain debug information (.obj files)\n"); + if (debugOutput) + printf("Output will contain debug information (.obj files)\n"); + } + else if (strcmp(argv[i], "--extract") == 0) + { + param = argv[++i]; + if (!param) + return false; + + extractFlags = atoi(param); + + if (!(extractFlags & Constants::EXTRACT_FLAG_ALLOWED)) // Tried to use an invalid flag + return false; + + printf("Detected flags: \n"); + printf("* Extract DBCs: %s\n", (extractFlags & Constants::EXTRACT_FLAG_DBC) ? "Yes" : "No"); + printf("* Extract Maps: %s\n", (extractFlags & Constants::EXTRACT_FLAG_MAPS) ? "Yes" : "No"); + printf("* Extract VMaps: %s\n", (extractFlags & Constants::EXTRACT_FLAG_VMAPS) ? "Yes" : "No"); + printf("* Extract GameObject Models: %s\n", (extractFlags & Constants::EXTRACT_FLAG_GOB_MODELS) ? "Yes" : "No"); + printf("* Extract MMaps: %s\n", (extractFlags & Constants::EXTRACT_FLAG_MMAPS) ? "Yes" : "No"); } } return true; @@ -77,9 +133,17 @@ bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapLis void PrintUsage() { printf("MeshExtractor help.\n"); - printf("* Use \"--threads \" to specify threads, default to 4\n"); - printf("* Use \"--maps a,b,c,d,e\" to extract only the maps specified ( do not use spaces )\n"); - printf("* Use \"--debug 1\" to generate debug information of the tiles.\n"); + printf("* Use \"--threads \" to specify threads, default to 4 (Only available when extracting MMaps)\n"); + printf("* Use \"--maps a,b,c,d,e\" to extract only the maps specified (Do not use spaces)\n"); + printf("* Use \"--debug 1\" to generate debug information of the tiles (Only available when extracting MMaps)\n"); + printf("* Use \"--extract X\" to extract the data specified by the flag X (Note: You can combine the flags with the bitwise OR operator |). Available flags are: \n"); + { + printf("- %u to extract DBCs\n", Constants::EXTRACT_FLAG_DBC); + printf("- %u to extract Maps (Not yet implemented)\n", Constants::EXTRACT_FLAG_MAPS); + printf("- %u to extract VMaps (Not yet implemented)\n", Constants::EXTRACT_FLAG_VMAPS); + printf("- %u to extract GameObject models (Not yet implemented)\n", Constants::EXTRACT_FLAG_GOB_MODELS); + printf("- %u to extract MMaps (Not yet finished)\n", Constants::EXTRACT_FLAG_MMAPS); + } } int main(int argc, char* argv[]) @@ -88,16 +152,21 @@ int main(int argc, char* argv[]) Cache = new CacheClass(); MPQHandler = new MPQManager(); MPQHandler->Initialize(); - uint32 threads = 4; + uint32 threads = 4, extractFlags = 0; std::set mapIds; bool debug = false; - - if (!HandleArgs(argc, argv, threads, mapIds, debug)) + + if (!HandleArgs(argc, argv, threads, mapIds, debug, extractFlags)) { PrintUsage(); return -1; } - ExtractAllMaps(mapIds, threads, debug); + if (extractFlags & Constants::EXTRACT_FLAG_DBC) + ExtractDBCs(); + + if (extractFlags & Constants::EXTRACT_FLAG_MMAPS) + ExtractMMaps(mapIds, threads, debug); + return 0; } \ No newline at end of file diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 54b9e4865cd..5b3e181713e 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -26,9 +26,9 @@ TileBuilder::TileBuilder(std::string world, int x, int y, uint32 mapId) : _Geome Config.walkableSlopeAngle = 50.0f; Config.detailSampleDist = 3.0f; Config.detailSampleMaxError = 1.25f; - Config.walkableClimb = 1.0f / Config.ch; - Config.walkableHeight = 1.652778f / Config.ch; - Config.walkableRadius = 0.2951389f / Config.cs; + Config.walkableClimb = floorf(1.0f / Config.ch); + Config.walkableHeight = ceilf(1.652778f / Config.ch); + Config.walkableRadius = ceilf(0.2951389f / Config.cs); Config.maxEdgeLen = Config.walkableRadius * 8; Config.borderSize = Config.walkableRadius + 4; Config.width = 1800 + Config.borderSize * 2; @@ -39,17 +39,17 @@ TileBuilder::TileBuilder(std::string world, int x, int y, uint32 mapId) : _Geome Context = new rcContext; } -void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax ) +void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax, dtNavMeshParams& navMeshParams ) { bmin = new float[3]; bmax = new float[3]; - bmin[0] = Constants::Origin[0] + (Constants::TileSize * X); - bmin[2] = Constants::Origin[2] + (Constants::TileSize * Y); - bmax[0] = Constants::Origin[0] + (Constants::TileSize * (X + 1)); - bmax[2] = Constants::Origin[2] + (Constants::TileSize * (Y + 1)); + bmin[0] = Constants::Origin[0] /*navMeshParams.orig[0]*/ + (Constants::TileSize * X); + bmin[2] = Constants::Origin[2] /*navMeshParams.orig[2]*/ + (Constants::TileSize * Y); + bmax[0] = Constants::Origin[0] /*navMeshParams.orig[0]*/ + (Constants::TileSize * (X + 1)); + bmax[2] = Constants::Origin[2] /*navMeshParams.orig[2]*/ + (Constants::TileSize * (Y + 1)); } -uint8* TileBuilder::Build(bool dbg) +uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) { _Geometry = new Geometry(); _Geometry->Transform = true; @@ -61,15 +61,10 @@ uint8* TileBuilder::Build(bool dbg) if (_Geometry->Vertices.empty() && _Geometry->Triangles.empty()) return NULL; - float* bbMin; - float* bbMax; - CalculateTileBounds(bbMin, bbMax); - _Geometry->CalculateMinMaxHeight(bbMin[1], bbMax[1]); - // again, we load everything - wasteful but who cares - for (int ty = Y - 4; ty <= Y + 4; ty++) + for (int ty = Y - 2; ty <= Y + 2; ty++) { - for (int tx = X - 4; tx <= X + 4; tx++) + for (int tx = X - 2; tx <= X + 2; tx++) { // don't load main tile again if (tx == X && ty == Y) @@ -109,13 +104,23 @@ uint8* TileBuilder::Build(bool dbg) _Geometry->Vertices.clear(); _Geometry->Triangles.clear(); - bbMin[0] -= Config.borderSize * Config.cs; + float bbMin[3]; + float bbMax[3]; + // CalculateTileBounds(bbMin, bbMax, navMeshParams); + rcCalcBounds(vertices, numVerts, bbMin, bbMax); + // _Geometry->CalculateMinMaxHeight(bbMin[1], bbMax[1]); + + /*bbMin[0] -= Config.borderSize * Config.cs; bbMin[2] -= Config.borderSize * Config.cs; bbMax[0] += Config.borderSize * Config.cs; - bbMax[0] += Config.borderSize * Config.cs; + bbMax[0] += Config.borderSize * Config.cs;*/ + rcHeightfield* hf = rcAllocHeightfield(); - rcCreateHeightfield(Context, *hf, Config.width, Config.height, bbMin, bbMax, Config.cs, Config.ch); + int height, width; + rcCalcGridSize(bbMin, bbMax, Config.cs, &width, &height); + printf("Config values: Height: %i, Width: %i. Calculated values: Height: %i, Width: %i\n", Config.height, Config.width, height, width); + rcCreateHeightfield(Context, *hf, width, height, bbMin, bbMax, Config.cs, Config.ch); rcClearUnwalkableTriangles(Context, Config.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas); rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb); @@ -168,29 +173,31 @@ uint8* TileBuilder::Build(bool dbg) rcFreeCompactHeightfield(chf); rcFreeContourSet(cset); + /* + * Removed with RecastNavigation v292 // Remove padding from the polymesh data. (Remove this odditity) for (int i = 0; i < pmesh->nverts; ++i) { unsigned short* v = &pmesh->verts[i * 3]; v[0] -= (unsigned short)Config.borderSize; v[2] -= (unsigned short)Config.borderSize; - } + }*/ // Set flags according to area types (e.g. Swim for Water) for (int i = 0; i < pmesh->npolys; i++) { if (pmesh->areas[i] == Constants::POLY_AREA_ROAD || pmesh->areas[i] == Constants::POLY_AREA_TERRAIN) pmesh->flags[i] = Constants::POLY_FLAG_WALK; - else if (pmesh->areas[i] == (int)Constants::POLY_AREA_WATER) + else if (pmesh->areas[i] == Constants::POLY_AREA_WATER) pmesh->flags[i] = Constants::POLY_FLAG_SWIM; } // get original bounds - float* tilebMin; + /*float* tilebMin; float* tilebMax; - CalculateTileBounds(tilebMin, tilebMax); + CalculateTileBounds(tilebMin, tilebMax, navMeshParams); tilebMin[1] = bbMin[1]; - tilebMax[1] = bbMax[1]; + tilebMax[1] = bbMax[1];*/ dtNavMeshCreateParams params; // PolyMesh data @@ -208,12 +215,14 @@ uint8* TileBuilder::Build(bool dbg) params.detailTris = dmesh->tris; params.detailTriCount = dmesh->ntris; // Copy bounding box - params.bmin[0] = tilebMin[0]; + /*params.bmin[0] = tilebMin[0]; params.bmin[1] = tilebMin[1]; params.bmin[2] = tilebMin[2]; params.bmax[0] = tilebMax[0]; params.bmax[1] = tilebMax[1]; - params.bmax[2] = tilebMax[2]; + params.bmax[2] = tilebMax[2];*/ + rcVcopy(params.bmin, pmesh->bmin); + rcVcopy(params.bmax, pmesh->bmax); // General settings params.ch = Config.ch; params.cs = Config.cs; @@ -222,7 +231,11 @@ uint8* TileBuilder::Build(bool dbg) params.walkableRadius = Config.walkableRadius; params.tileX = X; params.tileY = Y; - params.tileSize = 1800; + int _x = (((pmesh->bmin[0] + pmesh->bmax[0]) / 2) - Constants::Origin[0]) / Constants::TileSize; + int _y = (((pmesh->bmin[2] + pmesh->bmax[2]) / 2) - Constants::Origin[2]) / Constants::TileSize; + printf("[%02i,%02i] Generated with TileX: %i and TileY: %i\nbmin[0] %f bmin[1] %f bmin[2] %f bmax[0] %f bmax[1] %f bmax[2] %f\n", X, Y, _x, _y, params.bmin[0], params.bmin[1], params.bmin[2], params.bmax[0], params.bmax[1], params.bmax[2]); + params.buildBvTree = true; + params.tileLayer = 0; // Offmesh-connection settings params.offMeshConCount = 0; // none for now @@ -235,13 +248,13 @@ uint8* TileBuilder::Build(bool dbg) // Free some memory rcFreePolyMesh(pmesh); rcFreePolyMeshDetail(dmesh); - delete tilebMax; - delete tilebMin; + //delete tilebMax; + //delete tilebMin; delete areas; delete triangles; delete vertices; - delete bbMax; - delete bbMin; + //delete bbMax; + //delete bbMin; if (result) { diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h index 72e275c75b7..17d6e48095a 100644 --- a/src/tools/mesh_extractor/TileBuilder.h +++ b/src/tools/mesh_extractor/TileBuilder.h @@ -13,8 +13,8 @@ public: TileBuilder(std::string world, int x, int y, uint32 mapId); ~TileBuilder(); - void CalculateTileBounds(float*& bmin, float*& bmax); - uint8* Build(bool dbg); + void CalculateTileBounds(float*& bmin, float*& bmax, dtNavMeshParams& navMeshParams); + uint8* Build(bool dbg, dtNavMeshParams& navMeshParams); std::string World; int X; diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index 6389e0aa66e..5b752885d17 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -5,6 +5,13 @@ #include "G3D/Matrix4.h" #include "G3D/Quat.h" +#ifdef _WIN32 + #include "direct.h" +#else + #include + #include +#endif + const float Constants::TileSize = 533.0f + (1/3.0f); const float Constants::MaxXY = 32.0f * Constants::TileSize; const float Constants::ChunkSize = Constants::TileSize / 16.0f; @@ -13,6 +20,15 @@ const float Constants::Origin[] = { -Constants::MaxXY, 0.0f, -Constants::MaxXY } const float Constants::PI = 3.1415926f; const float Constants::MaxStandableHeight = 1.5f; +void Utils::CreateDir( const std::string& Path ) +{ +#ifdef _WIN32 + _mkdir( Path.c_str()); +#else + mkdir( Path.c_str(), 0777 ); +#endif +} + void Utils::Reverse(char word[]) { int len = strlen(word); @@ -181,6 +197,28 @@ G3D::Matrix4 Utils::GetWmoDoodadTransformation( DoodadInstance inst, WorldModelD return scale * rotation * quatRotation ** translation * rootTransformation; } +void Utils::SaveToDisk( FILE* stream, std::string path ) +{ + FILE* disk = fopen(path.c_str(), "wb"); + if (!disk) + { + printf("Could not save file %s to disk, please verify that you have write permissions on that directory\n", path.c_str()); + return; + } + + uint32 size = Utils::Size(stream); + uint8* data = new uint8[size]; + // Read the data to an array + fread(data, 1, size, stream); + // And write it in the file + fwrite(data, 1, size, disk); + + // Close the filestream + fclose(disk); + // Free the used memory + delete data; +} + void MapChunkHeader::Read(FILE* stream) { fread(&Flags, sizeof(uint32), 1, stream); diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index a45c3659240..c19bc1bb29c 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -349,5 +349,7 @@ public: } static std::string Replace( std::string str, const std::string& oldStr, const std::string& newStr ); static G3D::Matrix4 GetWmoDoodadTransformation( DoodadInstance inst, WorldModelDefinition root ); + static void CreateDir( const std::string& Path ); + static void SaveToDisk(FILE* stream, std::string path); }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/WorldModelGroup.cpp b/src/tools/mesh_extractor/WorldModelGroup.cpp index b4c963020c7..bd0d106dabb 100644 --- a/src/tools/mesh_extractor/WorldModelGroup.cpp +++ b/src/tools/mesh_extractor/WorldModelGroup.cpp @@ -36,7 +36,7 @@ void WorldModelGroup::ReadNormals() ASSERT(normalCount == Vertices.size() && "normalCount is different than the Vertices count"); Normals.reserve(normalCount); FILE* stream = chunk->GetStream(); - for (int i = 0; i < normalCount; i++) + for (uint32 i = 0; i < normalCount; i++) Normals[i] = Vector3::Read(stream); } @@ -61,7 +61,7 @@ void WorldModelGroup::ReadVertices() uint32 verticeCount = chunk->Length / 12; Vertices.reserve(verticeCount); FILE* stream = chunk->GetStream(); - for (int i = 0; i < verticeCount; i++) + for (uint32 i = 0; i < verticeCount; i++) Vertices.push_back(Vector3::Read(stream)); } @@ -75,7 +75,7 @@ void WorldModelGroup::ReadTriangles() ASSERT(triangleCount == TriangleFlags.size() && "triangleCount != TriangleFlags.size()"); FILE* stream = chunk->GetStream(); Triangles.reserve(triangleCount); - for (int i = 0; i < triangleCount; i++) + for (uint32 i = 0; i < triangleCount; i++) { uint16 v0; uint16 v1; @@ -97,7 +97,7 @@ void WorldModelGroup::ReadMaterials() uint32 triangleCount = chunk->Length / 2; TriangleFlags.reserve(triangleCount); TriangleMaterials.reserve(triangleCount); - for (int i = 0; i < triangleCount; i++) + for (uint32 i = 0; i < triangleCount; i++) { uint8 tmp; fread(&tmp, sizeof(uint8), 1, stream); diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index b98a7aae826..7b60b9b2151 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -46,7 +46,7 @@ void WorldModelHandler::ProcessInternal( ChunkedData* subChunks ) int32 index; fread(&index, sizeof(int32), 1, stream); - if (index < 0 || index >= _definitions->size()) + if (index < 0 || uint32(index) >= _definitions->size()) continue; WorldModelDefinition wmo = (*_definitions)[index]; diff --git a/src/tools/mesh_extractor/WorldModelRoot.cpp b/src/tools/mesh_extractor/WorldModelRoot.cpp index 3457a35f761..c34a77e4531 100644 --- a/src/tools/mesh_extractor/WorldModelRoot.cpp +++ b/src/tools/mesh_extractor/WorldModelRoot.cpp @@ -16,7 +16,7 @@ void WorldModelRoot::ReadGroups() { std::string pathBase = Utils::GetPathBase(Path); Groups.reserve(Header.CountGroups); - for (int i = 0; i < Header.CountGroups; i++) + for (uint32 i = 0; i < Header.CountGroups; i++) { char name[200]; sprintf(name, "%s_%03u.wmo", pathBase.c_str(), i); @@ -35,7 +35,7 @@ void WorldModelRoot::ReadDoodadSets() FILE* stream = chunk->GetStream(); ASSERT(chunk->Length / 32 == Header.CountSets && "chunk.Length / 32 == Header.CountSets"); DoodadSets.reserve(Header.CountSets); - for (int i = 0; i < Header.CountSets; i++) + for (uint32 i = 0; i < Header.CountSets; i++) DoodadSets.push_back(DoodadSet::Read(stream)); } @@ -49,7 +49,7 @@ void WorldModelRoot::ReadDoodadInstances() const uint32 instanceSize = 40; uint32 countInstances = chunk->Length / instanceSize; DoodadInstances.reserve(countInstances); - for (int i = 0; i < countInstances; i++) + for (uint32 i = 0; i < countInstances; i++) { FILE* stream = chunk->GetStream(); fseek(stream, instanceSize * i, SEEK_CUR); -- cgit v1.2.3 From d2437407f4f7ad1af3baeb351626b41bd700065c Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 3 Oct 2012 21:09:05 -0500 Subject: Tools/MeshExtractor: * Fixed a bunch of errors * Allow to extract m2 and mdx models, WMOs are still not being extracted. --- src/tools/mesh_extractor/Chunk.cpp | 2 +- src/tools/mesh_extractor/Constants.h | 2 + src/tools/mesh_extractor/DBC.cpp | 2 +- src/tools/mesh_extractor/DBC.h | 5 +- src/tools/mesh_extractor/MeshExtractor.cpp | 123 ++++++++++++++++++++++++- src/tools/mesh_extractor/Model.cpp | 29 ++++-- src/tools/mesh_extractor/Model.h | 2 + src/tools/mesh_extractor/ObjectDataHandler.cpp | 2 +- src/tools/mesh_extractor/TileBuilder.cpp | 4 +- src/tools/mesh_extractor/Utils.cpp | 36 ++++++-- src/tools/mesh_extractor/Utils.h | 3 + src/tools/mesh_extractor/WorldModelGroup.cpp | 2 +- 12 files changed, 183 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/Chunk.cpp b/src/tools/mesh_extractor/Chunk.cpp index b41fa7d07d4..2f521f1badd 100644 --- a/src/tools/mesh_extractor/Chunk.cpp +++ b/src/tools/mesh_extractor/Chunk.cpp @@ -10,7 +10,7 @@ int32 Chunk::FindSubChunkOffset(std::string name) FILE* stream = GetStream(); uint32 matched = 0; - while (ftell(stream) < Utils::Size(stream)) + while (uint32(ftell(stream)) < Utils::Size(stream)) { char b; fread(&b, sizeof(char), 1, stream); diff --git a/src/tools/mesh_extractor/Constants.h b/src/tools/mesh_extractor/Constants.h index f3b71812155..89cd6da20a2 100644 --- a/src/tools/mesh_extractor/Constants.h +++ b/src/tools/mesh_extractor/Constants.h @@ -47,6 +47,8 @@ public: static const float Origin[]; static const float PI; static const float MaxStandableHeight; + static bool ToWoWCoords; + static const char* VMAPMagic; }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/DBC.cpp b/src/tools/mesh_extractor/DBC.cpp index be04ce070ee..c50e02014da 100644 --- a/src/tools/mesh_extractor/DBC.cpp +++ b/src/tools/mesh_extractor/DBC.cpp @@ -38,7 +38,7 @@ DBC::DBC( FILE* stream ) : StringBlock(NULL), IsFaulty(true), StringBlockSize(0) std::string DBC::GetStringByOffset( int offset ) { int len = 0; - for (int i = offset; i < StringBlockSize; i++) + for (uint32 i = offset; i < StringBlockSize; i++) { if (!StringBlock[i]) { diff --git a/src/tools/mesh_extractor/DBC.h b/src/tools/mesh_extractor/DBC.h index 6c86c1391dd..0c857bd40ed 100644 --- a/src/tools/mesh_extractor/DBC.h +++ b/src/tools/mesh_extractor/DBC.h @@ -37,9 +37,10 @@ public: return Values[index]; } - float GetFloat(int index) + template + T GetValue(int index) { - return *(float*)(&Values[index]); + return *(T*)(&Values[index]); } std::string GetString(int index) diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index d6b701607ba..8eb6ba5cb6e 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -4,6 +4,7 @@ #include "Cache.h" #include "DBC.h" #include "Constants.h" +#include "Model.h" #include @@ -70,6 +71,116 @@ void ExtractDBCs() printf("DBC extraction finished!\n"); } +void ExtractGameobjectModels() +{ + Constants::ToWoWCoords = true; + printf("Extracting GameObject models\n"); + + std::string baseBuildingsPath = "Buildings/"; + std::string baseVmapsPath = "vmaps/"; + Utils::CreateDir(baseVmapsPath); + Utils::CreateDir(baseBuildingsPath); + + FILE* modelList = fopen((baseVmapsPath + "GameObjectModels.list").c_str(), "wb"); + if (!modelList) + { + printf("Could not create file vmaps/GameObjectModels.list, please make sure that you have the write permissions in the folder\n"); + return; + } + + DBC* dbc = MPQHandler->GetDBC("GameObjectDisplayInfo"); + for (std::vector::iterator itr = dbc->Records.begin(); itr != dbc->Records.end(); ++itr) + { + std::string path = (*itr)->GetString(1); + std::string fileName = Utils::GetPlainName(path.c_str()); + std::string extension = Utils::GetExtension(fileName); + // Convert the extension to lowercase + std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); + if (extension == "mdx" || extension == "m2") + { + fileName = Utils::FixModelPath(fileName); + Model model(path); + + if (model.IsBad) + continue; + + FILE* output = fopen((baseBuildingsPath + fileName).c_str(), "wb"); + if (!output) + { + printf("Could not create file %s, please check that you have write permissions\n", (baseBuildingsPath + fileName).c_str()); + continue; + } + // Placeholder for 0 values + int Nop[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + fwrite(Constants::VMAPMagic, 8, 1, output); + uint32 numVerts = model.Header.CountBoundingVertices; + fwrite(&numVerts, sizeof(uint32), 1, output); + uint32 numGroups = 1; + fwrite(&numGroups, sizeof(uint32), 1, output); + fwrite(Nop, 4 * 3 , 1, output); // rootwmoid, flags, groupid + fwrite(Nop, sizeof(float), 3 * 2, output);//bbox, only needed for WMO currently + fwrite(Nop, 4, 1, output);// liquidflags + fwrite("GRP ", 4, 1, output); + + uint32 branches = 1; + uint32 wsize = sizeof(branches) + sizeof(uint32) * branches; + fwrite(&wsize, sizeof(uint32), 1, output); + fwrite(&branches, sizeof(branches), 1, output); + uint32 numTris = model.Header.CountBoundingTriangles; + fwrite(&numTris, sizeof(uint32), 1, output); + fwrite("INDX", 4, 1, output); + wsize = sizeof(uint32) + sizeof(unsigned short) * numTris; + fwrite(&wsize, sizeof(int), 1, output); + fwrite(&numTris, sizeof(uint32), 1, output); + uint16* indices = new uint16[numTris]; + + if (numTris > 0) + { + uint32 i = 0; + for (std::vector >::iterator itr2 = model.Triangles.begin(); itr2 != model.Triangles.end(); ++itr2, ++i) + { + indices[i * 3 + 0] = itr2->V0; + indices[i * 3 + 1] = itr2->V1; + indices[i * 3 + 2] = itr2->V2; + } + fwrite(indices, sizeof(uint16), numTris, output); + } + + + fwrite("VERT", 4, 1, output); + wsize = sizeof(int) + sizeof(float) * 3 * numVerts; + fwrite(&wsize, sizeof(int), 1, output); + fwrite(&numVerts, sizeof(int), 1, output); + float* vertices = new float[numVerts*3]; + + if (numVerts > 0) + { + uint32 i = 0; + for (std::vector::iterator itr2 = model.Vertices.begin(); itr2 != model.Vertices.end(); ++itr2, ++i) + { + vertices[i * 3 + 0] = itr2->x; + vertices[i * 3 + 1] = itr2->y; + vertices[i * 3 + 2] = itr2->z; + } + + fwrite(vertices, sizeof(float), numVerts * 3, output); + } + + fclose(output); + delete[] indices; + delete[] vertices; + } + else if (extension == "wmo") + { + //WorldModelRoot model(path); + } + } + + printf("GameObject models extraction finished!"); + Constants::ToWoWCoords = false; +} + bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapList, bool& debugOutput, uint32& extractFlags) { char* param = NULL; @@ -141,7 +252,7 @@ void PrintUsage() printf("- %u to extract DBCs\n", Constants::EXTRACT_FLAG_DBC); printf("- %u to extract Maps (Not yet implemented)\n", Constants::EXTRACT_FLAG_MAPS); printf("- %u to extract VMaps (Not yet implemented)\n", Constants::EXTRACT_FLAG_VMAPS); - printf("- %u to extract GameObject models (Not yet implemented)\n", Constants::EXTRACT_FLAG_GOB_MODELS); + printf("- %u to extract GameObject models (Not yet finished)\n", Constants::EXTRACT_FLAG_GOB_MODELS); printf("- %u to extract MMaps (Not yet finished)\n", Constants::EXTRACT_FLAG_MMAPS); } } @@ -149,9 +260,6 @@ void PrintUsage() int main(int argc, char* argv[]) { system("pause"); - Cache = new CacheClass(); - MPQHandler = new MPQManager(); - MPQHandler->Initialize(); uint32 threads = 4, extractFlags = 0; std::set mapIds; bool debug = false; @@ -162,11 +270,18 @@ int main(int argc, char* argv[]) return -1; } + Cache = new CacheClass(); + MPQHandler = new MPQManager(); + MPQHandler->Initialize(); + if (extractFlags & Constants::EXTRACT_FLAG_DBC) ExtractDBCs(); if (extractFlags & Constants::EXTRACT_FLAG_MMAPS) ExtractMMaps(mapIds, threads, debug); + + if (extractFlags & Constants::EXTRACT_FLAG_GOB_MODELS) + ExtractGameobjectModels(); return 0; } \ No newline at end of file diff --git a/src/tools/mesh_extractor/Model.cpp b/src/tools/mesh_extractor/Model.cpp index a1c67d23f28..10fde0ebc2d 100644 --- a/src/tools/mesh_extractor/Model.cpp +++ b/src/tools/mesh_extractor/Model.cpp @@ -2,9 +2,14 @@ #include "MPQManager.h" #include "Utils.h" -Model::Model( std::string path ) +Model::Model( std::string path ) : IsCollidable(false), IsBad(false) { Stream = MPQHandler->GetFile(Utils::FixModelPath(path)); + if (!Stream) + { + IsBad = true; + return; + } Header.Read(Stream); if (Header.OffsetBoundingNormals > 0 && Header.OffsetBoundingVertices > 0 && Header.OffsetBoundingTriangles > 0 && Header.BoundingRadius > 0.0f) @@ -16,26 +21,36 @@ Model::Model( std::string path ) } } +Model::~Model() +{ + if (Stream) + fclose(Stream); +} + void Model::ReadVertices( FILE* stream ) { fseek(stream, Header.OffsetBoundingVertices, SEEK_SET); Vertices.reserve(Header.CountBoundingVertices); - for (int i = 0; i < Header.CountBoundingVertices; ++i) - Vertices[i] = Vector3::Read(stream); + for (uint32 i = 0; i < Header.CountBoundingVertices; ++i) + { + Vertices.push_back(Vector3::Read(stream)); + if (Constants::ToWoWCoords) + Vertices[i] = Utils::ToWoWCoords(Vertices[i]); + } } void Model::ReadBoundingTriangles( FILE* stream ) { fseek(stream, Header.OffsetBoundingTriangles, SEEK_SET); Triangles.reserve(Header.CountBoundingTriangles / 3); - for (int i = 0; i < Header.CountBoundingTriangles / 3; i++) + for (uint32 i = 0; i < Header.CountBoundingTriangles / 3; i++) { Triangle tri; tri.Type = Constants::TRIANGLE_TYPE_DOODAD; fread(&tri.V0, sizeof(uint16), 1, stream); fread(&tri.V1, sizeof(uint16), 1, stream); fread(&tri.V2, sizeof(uint16), 1, stream); - Triangles[i] = tri; + Triangles.push_back(tri); } } @@ -43,7 +58,7 @@ void Model::ReadBoundingNormals( FILE* stream ) { fseek(stream, Header.OffsetBoundingNormals, SEEK_SET); Normals.reserve(Header.CountBoundingNormals); - for (int i = 0; i < Header.CountBoundingNormals; i++) - Normals[i] = Vector3::Read(stream); + for (uint32 i = 0; i < Header.CountBoundingNormals; i++) + Normals.push_back(Vector3::Read(stream)); } diff --git a/src/tools/mesh_extractor/Model.h b/src/tools/mesh_extractor/Model.h index a5b8338461d..ea9331e7c30 100644 --- a/src/tools/mesh_extractor/Model.h +++ b/src/tools/mesh_extractor/Model.h @@ -7,6 +7,7 @@ class Model { public: Model(std::string path); + ~Model(); void ReadVertices(FILE* stream); void ReadBoundingTriangles(FILE* stream); @@ -17,5 +18,6 @@ public: std::vector > Triangles; bool IsCollidable; FILE* Stream; + bool IsBad; }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/ObjectDataHandler.cpp b/src/tools/mesh_extractor/ObjectDataHandler.cpp index 3ed2ee49604..789efc6d62c 100644 --- a/src/tools/mesh_extractor/ObjectDataHandler.cpp +++ b/src/tools/mesh_extractor/ObjectDataHandler.cpp @@ -11,7 +11,7 @@ void ObjectDataHandler::ProcessMapChunk( MapChunk* chunk ) int32 firstIndex = Source->ObjectData->GetFirstIndex("MCNK"); if (firstIndex == -1) return; - if (firstIndex + chunk->Index > Source->ObjectData->Chunks.size()) + if (uint32(firstIndex + chunk->Index) > Source->ObjectData->Chunks.size()) return; Chunk* ourChunk = Source->ObjectData->Chunks[firstIndex + chunk->Index]; if (ourChunk->Length == 0) diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 5b3e181713e..12213b16373 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -88,9 +88,9 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) char buff[100]; sprintf(buff, "mmaps/%s_%02u%02u.obj", World.c_str(), Y, X); FILE* debug = fopen(buff, "wb"); - for (int i = 0; i < _Geometry->Vertices.size(); ++i) + for (uint32 i = 0; i < _Geometry->Vertices.size(); ++i) fprintf(debug, "v %f %f %f\n", _Geometry->Vertices[i].x, _Geometry->Vertices[i].y, _Geometry->Vertices[i].z); - for (int i = 0; i < _Geometry->Triangles.size(); ++i) + for (uint32 i = 0; i < _Geometry->Triangles.size(); ++i) fprintf(debug, "f %i %i %i\n", _Geometry->Triangles[i].V0 + 1, _Geometry->Triangles[i].V1 + 1, _Geometry->Triangles[i].V2 + 1); fclose(debug); } diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index 5b752885d17..5fccd319554 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -19,6 +19,8 @@ const float Constants::UnitSize = Constants::ChunkSize / 8.0f; const float Constants::Origin[] = { -Constants::MaxXY, 0.0f, -Constants::MaxXY }; const float Constants::PI = 3.1415926f; const float Constants::MaxStandableHeight = 1.5f; +const char* Constants::VMAPMagic = "VMAP042"; +bool Constants::ToWoWCoords = false; void Utils::CreateDir( const std::string& Path ) { @@ -219,6 +221,21 @@ void Utils::SaveToDisk( FILE* stream, std::string path ) delete data; } +Vector3 Utils::ToWoWCoords( Vector3 vec ) +{ + return Vector3(vec.x, -vec.z, vec.y); +} + +std::string Utils::GetExtension( std::string path ) +{ + std::string::size_type idx = path.rfind('.'); + std::string extension = ""; + + if(idx != std::string::npos) + extension = path.substr(idx+1); + return extension; +} + void MapChunkHeader::Read(FILE* stream) { fread(&Flags, sizeof(uint32), 1, stream); @@ -308,16 +325,6 @@ void ModelHeader::Read(FILE* stream) fread(&OffsetTransLookup, sizeof(uint32), 1, stream); fread(&CountUvAnimLookup, sizeof(uint32), 1, stream); fread(&OffsetUvAnimLookup, sizeof(uint32), 1, stream); - fread(&CountColors, sizeof(uint32), 1, stream); - fread(&OffsetColors, sizeof(uint32), 1, stream); - fread(&CountTextures, sizeof(uint32), 1, stream); - fread(&OffsetTextures, sizeof(uint32), 1, stream); - fread(&CountTransparency, sizeof(uint32), 1, stream); - fread(&OffsetTransparency, sizeof(uint32), 1, stream); - fread(&CountUvAnimation, sizeof(uint32), 1, stream); - fread(&OffsetUvAnimation, sizeof(uint32), 1, stream); - fread(&CountTexReplace, sizeof(uint32), 1, stream); - fread(&OffsetTexReplace, sizeof(uint32), 1, stream); VertexBox[0] = Vector3::Read(stream); VertexBox[1] = Vector3::Read(stream); fread(&VertexRadius, sizeof(float), 1, stream); @@ -468,3 +475,12 @@ H2OInformation H2OInformation::Read(FILE* stream) fread(&ret.OffsetHeightmap, sizeof(uint32), 1, stream); return ret; } + +char* Utils::GetPlainName(const char* FileName) +{ + char* temp; + + if((temp = (char*)strrchr(FileName, '\\')) != NULL) + FileName = temp + 1; + return (char*)FileName; +} \ No newline at end of file diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index c19bc1bb29c..47a6354d3b2 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -351,5 +351,8 @@ public: static G3D::Matrix4 GetWmoDoodadTransformation( DoodadInstance inst, WorldModelDefinition root ); static void CreateDir( const std::string& Path ); static void SaveToDisk(FILE* stream, std::string path); + static Vector3 ToWoWCoords( Vector3 vec ); + static std::string GetExtension( std::string path ); + static char* GetPlainName(const char* FileName); }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/WorldModelGroup.cpp b/src/tools/mesh_extractor/WorldModelGroup.cpp index bd0d106dabb..c7e6f0c525e 100644 --- a/src/tools/mesh_extractor/WorldModelGroup.cpp +++ b/src/tools/mesh_extractor/WorldModelGroup.cpp @@ -37,7 +37,7 @@ void WorldModelGroup::ReadNormals() Normals.reserve(normalCount); FILE* stream = chunk->GetStream(); for (uint32 i = 0; i < normalCount; i++) - Normals[i] = Vector3::Read(stream); + Normals.push_back(Vector3::Read(stream)); } void WorldModelGroup::ReadLiquid() -- cgit v1.2.3 From e31e251fda42f97844ad74892d364deb424a10b7 Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 4 Oct 2012 20:53:54 -0500 Subject: Tools/MeshExtractor: More progress on extracting GameObject models --- src/tools/mesh_extractor/MeshExtractor.cpp | 53 ++++++++++++++++++++++++++-- src/tools/mesh_extractor/Utils.cpp | 20 ++++++++++- src/tools/mesh_extractor/Utils.h | 19 ++++++++++ src/tools/mesh_extractor/WorldModelGroup.cpp | 27 ++++++++++---- src/tools/mesh_extractor/WorldModelGroup.h | 11 ++++-- 5 files changed, 117 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 8eb6ba5cb6e..117a398d5cf 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -170,13 +170,62 @@ void ExtractGameobjectModels() fclose(output); delete[] indices; delete[] vertices; + + uint32 displayId = (*itr)->Values[0]; + uint32 pathLength = fileName.size(); + fwrite(&displayId, sizeof(uint32), 1, modelList); + fwrite(&pathLength, sizeof(uint32), 1, modelList); + fwrite(fileName.c_str(), sizeof(char), pathLength, modelList); } else if (extension == "wmo") { - //WorldModelRoot model(path); + WorldModelRoot model(path); + + FILE* output = fopen((baseBuildingsPath + fileName).c_str(), "wb"); + if (!output) + { + printf("Could not create file %s, please check that you have write permissions\n", (baseBuildingsPath + fileName).c_str()); + continue; + } + + fwrite(Constants::VMAPMagic, 1, 8, output); + uint32 numVertices = 0; + fwrite(&numVertices, sizeof(uint32), 1, output); // will be filled later + fwrite(&model.Header.CountGroups, sizeof(uint32), 1, output); + fwrite(&model.Header.WmoId, sizeof(uint32), 1, output); + + uint32 i = 0; + for (std::vector::iterator itr2 = model.Groups.begin(); itr2 != model.Groups.end(); ++itr2) + { + fwrite(&itr2->Header.Flags, sizeof(uint32), 1, output); + fwrite(&itr2->Header.WmoId, sizeof(uint32), 1, output); + fwrite(&itr2->Header.BoundingBox[0], sizeof(uint32), 1, output); + fwrite(&itr2->Header.BoundingBox[1], sizeof(uint32), 1, output); + uint32 LiquidFlags = itr2->HasLiquidData ? 1 : 0; + fwrite(&LiquidFlags, sizeof(uint32), 1, output); + + fwrite("GRP ", sizeof(char), 4, output); + uint32 k = 0; + uint32 mobaBatch = itr2->MOBALength / 12; + uint32* MobaEx = new uint32[mobaBatch*4]; + + for(uint32 i = 8; i < itr2->MOBALength; i += 12) + MobaEx[k++] = itr2->MOBA[i]; + + int mobaSizeGrp = mobaBatch * 4 + 4; + fwrite(&mobaSizeGrp, 4, 1, output); + fwrite(&mobaBatch, 4, 1, output); + fwrite(MobaEx, 4, k, output); + delete[] MobaEx; + + // Note: still not finished + } + + fclose(output); } } + fclose(modelList); printf("GameObject models extraction finished!"); Constants::ToWoWCoords = false; } @@ -252,7 +301,7 @@ void PrintUsage() printf("- %u to extract DBCs\n", Constants::EXTRACT_FLAG_DBC); printf("- %u to extract Maps (Not yet implemented)\n", Constants::EXTRACT_FLAG_MAPS); printf("- %u to extract VMaps (Not yet implemented)\n", Constants::EXTRACT_FLAG_VMAPS); - printf("- %u to extract GameObject models (Not yet finished)\n", Constants::EXTRACT_FLAG_GOB_MODELS); + printf("- %u to extract GameObject models (Not yet finished, you need to run VMapAssembler on the extracted files)\n", Constants::EXTRACT_FLAG_GOB_MODELS); printf("- %u to extract MMaps (Not yet finished)\n", Constants::EXTRACT_FLAG_MMAPS); } } diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index 4414a02d681..b1b054e942e 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -483,4 +483,22 @@ char* Utils::GetPlainName(const char* FileName) if((temp = (char*)strrchr(FileName, '\\')) != NULL) FileName = temp + 1; return (char*)FileName; -} \ No newline at end of file +} + +WMOGroupHeader WMOGroupHeader::Read( FILE* stream ) +{ + WMOGroupHeader ret; + fread(&ret.OffsetGroupName, sizeof(uint32), 1, stream); + fread(&ret.OffsetDescriptiveName, sizeof(uint32), 1, stream); + fread(&ret.Flags, sizeof(uint32), 1, stream); + ret.BoundingBox[0] = Vector3::Read(stream); + ret.BoundingBox[1] = Vector3::Read(stream); + fread(&ret.OffsetPortals, sizeof(uint32), 1, stream); + fread(&ret.CountPortals, sizeof(uint32), 1, stream); + fread(&ret.CountBatches, sizeof(uint16), 4, stream); + fread(&ret.Fogs, sizeof(uint8), 4, stream); + fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream); + fread(&ret.WmoId, sizeof(uint32), 1, stream); + + return ret; +} diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index 47a6354d3b2..c5dd04fde06 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -289,6 +289,25 @@ public: static H2OInformation Read(FILE* stream); }; +class WMOGroupHeader +{ +public: + WMOGroupHeader() {} + + uint32 OffsetGroupName; + uint32 OffsetDescriptiveName; + uint32 Flags; + Vector3 BoundingBox[2]; + uint32 OffsetPortals; + uint32 CountPortals; + uint16 CountBatches[4]; + uint8 Fogs[4]; + uint32 LiquidTypeRelated; + uint32 WmoId; + + static WMOGroupHeader Read(FILE* stream); +}; + // Dummy class to act as an interface. class IDefinition { diff --git a/src/tools/mesh_extractor/WorldModelGroup.cpp b/src/tools/mesh_extractor/WorldModelGroup.cpp index c7e6f0c525e..35a5ba69782 100644 --- a/src/tools/mesh_extractor/WorldModelGroup.cpp +++ b/src/tools/mesh_extractor/WorldModelGroup.cpp @@ -1,8 +1,9 @@ #include "WorldModelGroup.h" #include "ChunkedData.h" #include "Chunk.h" +#include "Utils.h" -WorldModelGroup::WorldModelGroup( std::string path, int groupIndex ) : GroupIndex(groupIndex), IsBad(false) +WorldModelGroup::WorldModelGroup( std::string path, int groupIndex ) : GroupIndex(groupIndex), IsBad(false), MOBA(NULL) { Data = new ChunkedData(path); if (!Data->Stream) @@ -14,16 +15,20 @@ WorldModelGroup::WorldModelGroup( std::string path, int groupIndex ) : GroupInde int32 firstSub = mainChunk->FindSubChunkOffset("MOPY"); if (firstSub == -1) return; + + Name = Utils::GetPlainName(path.c_str()); + FILE* stream = mainChunk->GetStream(); fseek(stream, firstSub, SEEK_SET); SubData = new ChunkedData(stream, mainChunk->Length - firstSub); - ReadBoundingBox(); + ReadHeader(); ReadMaterials(); ReadTriangles(); ReadVertices(); ReadNormals(); ReadLiquid(); + ReadBatches(); } void WorldModelGroup::ReadNormals() @@ -108,15 +113,23 @@ void WorldModelGroup::ReadMaterials() } } -void WorldModelGroup::ReadBoundingBox() +void WorldModelGroup::ReadHeader() { Chunk* chunk = Data->GetChunkByName("MOGP"); if (!chunk) return; FILE* stream = chunk->GetStream(); - fseek(stream, 8, SEEK_CUR); - fread(&Flags, sizeof(uint32), 1, stream); - BoundingBox[0] = Vector3::Read(stream); - BoundingBox[1] = Vector3::Read(stream); + Header = WMOGroupHeader::Read(stream); +} + +void WorldModelGroup::ReadBatches() +{ + Chunk* chunk = Data->GetChunkByName("MOBA"); + if (!chunk) + return; + + MOBALength = chunk->Length / 2; + MOBA = new uint16[MOBALength]; + fread(MOBA, sizeof(uint16), MOBALength, chunk->GetStream()); } diff --git a/src/tools/mesh_extractor/WorldModelGroup.h b/src/tools/mesh_extractor/WorldModelGroup.h index 1dc754d0221..e4fe34cbc75 100644 --- a/src/tools/mesh_extractor/WorldModelGroup.h +++ b/src/tools/mesh_extractor/WorldModelGroup.h @@ -10,13 +10,17 @@ public: ChunkedData* Data; ChunkedData* SubData; int GroupIndex; - Vector3 BoundingBox[2]; - uint32 Flags; + std::string Name; + WMOGroupHeader Header; + std::vector TriangleFlags; std::vector TriangleMaterials; std::vector > Triangles; std::vector Vertices; std::vector Normals; + // @ToDo: Research. + uint16* MOBA; + uint32 MOBALength; bool HasLiquidData; bool IsBad; @@ -28,6 +32,7 @@ private: void ReadVertices(); void ReadTriangles(); void ReadMaterials(); - void ReadBoundingBox(); + void ReadHeader(); + void ReadBatches(); }; #endif \ No newline at end of file -- cgit v1.2.3 From 509c8d0baefa7d8e0edbca5c9f1bb2c0d81149a4 Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 4 Oct 2012 20:59:59 -0500 Subject: Tools/MeshExtractor: Fixed build --- src/tools/mesh_extractor/MeshExtractor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 117a398d5cf..accccf4460f 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -252,9 +252,9 @@ bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapLis if (!param) return false; std::string maps = std::string(param); - Tokens tokens(maps, ','); + Tokenizer tokens(maps, ','); - for (Tokens::iterator itr = tokens.begin(); itr != tokens.end(); ++itr) + for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) mapList.insert(atoi(*itr)); printf("Extracting only provided list of maps (%u).\n", mapList.size()); -- cgit v1.2.3 From 19d7f68592d653067c3b84c3d409e59b2724a85d Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 20 Oct 2012 07:17:11 -0500 Subject: Tools/MeshExtractor: Changed some things, lots of thanks to Faramir. --- src/tools/mesh_extractor/Constants.h | 17 +- src/tools/mesh_extractor/ContinentBuilder.cpp | 44 ++--- src/tools/mesh_extractor/ContinentBuilder.h | 10 +- src/tools/mesh_extractor/MeshExtractor.cpp | 82 +++++++++ src/tools/mesh_extractor/TileBuilder.cpp | 231 +++++++++++++++----------- src/tools/mesh_extractor/TileBuilder.h | 4 +- src/tools/mesh_extractor/Utils.cpp | 4 + 7 files changed, 265 insertions(+), 127 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/Constants.h b/src/tools/mesh_extractor/Constants.h index 89cd6da20a2..54fa073fbef 100644 --- a/src/tools/mesh_extractor/Constants.h +++ b/src/tools/mesh_extractor/Constants.h @@ -32,12 +32,13 @@ public: enum ExtractFlags { - EXTRACT_FLAG_DBC = 1, - EXTRACT_FLAG_MAPS = 2, - EXTRACT_FLAG_VMAPS = 4, - EXTRACT_FLAG_GOB_MODELS = 8, - EXTRACT_FLAG_MMAPS = 16, - EXTRACT_FLAG_ALLOWED = EXTRACT_FLAG_DBC | EXTRACT_FLAG_MAPS | EXTRACT_FLAG_VMAPS | EXTRACT_FLAG_GOB_MODELS | EXTRACT_FLAG_MMAPS + EXTRACT_FLAG_DBC = 0x01, + EXTRACT_FLAG_MAPS = 0x02, + EXTRACT_FLAG_VMAPS = 0x04, + EXTRACT_FLAG_GOB_MODELS = 0x08, + EXTRACT_FLAG_MMAPS = 0x10, + EXTRACT_FLAG_TEST = 0x20, + EXTRACT_FLAG_ALLOWED = EXTRACT_FLAG_DBC | EXTRACT_FLAG_MAPS | EXTRACT_FLAG_VMAPS | EXTRACT_FLAG_GOB_MODELS | EXTRACT_FLAG_MMAPS | EXTRACT_FLAG_TEST }; static const float TileSize; @@ -49,6 +50,10 @@ public: static const float MaxStandableHeight; static bool ToWoWCoords; static const char* VMAPMagic; + static const float BaseUnitDim; + static const int VertexPerMap; + static const int VertexPerTile; + static const int TilesPerMap; }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index e4a1d2ca9f4..013c0ff256a 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -14,15 +14,16 @@ private: std::string Continent; bool debug; dtNavMeshParams Params; + ContinentBuilder* cBuilder; public: - BuilderThread(bool deb, dtNavMeshParams& params) : Free(true), debug(deb), Params(params) {} + BuilderThread(ContinentBuilder* _cBuilder, bool deb, dtNavMeshParams& params) : Free(true), debug(deb), Params(params), cBuilder(_cBuilder) {} void SetData(int x, int y, int map, std::string cont) { X = x; Y = y; MapId = map; Continent = cont; } int svc() { Free = false; printf("[%02i,%02i] Building tile\n", X, Y); - TileBuilder builder(Continent, X, Y, MapId); + TileBuilder builder(cBuilder, Continent, X, Y, MapId); char buff[100]; sprintf(buff, "mmaps/%03u%02u%02u.mmtile", MapId, Y, X); FILE* f = fopen(buff, "r"); @@ -57,7 +58,7 @@ public: bool Free; }; -void getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax) +void ContinentBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax) { // this is for elevation if (verts && vertCount) @@ -75,18 +76,8 @@ void getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, floa bmin[2] = bmax[2] - Constants::TileSize; } -void ContinentBuilder::Build(bool debug) +void ContinentBuilder::CalculateTileBounds() { - char buff[50]; - sprintf(buff, "mmaps/%03u.mmap", MapId); - FILE* mmap = fopen(buff, "wb"); - if (!mmap) - { - printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff); - return; - } - - int tileXMin = 64, tileYMin = 64, tileXMax = 0, tileYMax = 0; for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) { tileXMax = std::max(itr->X, tileXMax); @@ -95,24 +86,33 @@ void ContinentBuilder::Build(bool debug) tileYMax = std::max(itr->Y, tileYMax); tileYMin = std::min(itr->Y, tileYMin); } - - float bmin[3], bmax[3]; getTileBounds(tileXMax, tileYMax, NULL, 0, bmin, bmax); +} + +void ContinentBuilder::Build(bool debug) +{ + char buff[50]; + sprintf(buff, "mmaps/%03u.mmap", MapId); + FILE* mmap = fopen(buff, "wb"); + if (!mmap) + { + printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff); + return; + } + CalculateTileBounds(); + dtNavMeshParams params; - params.maxPolys = 32768; + params.maxPolys = 1 << STATIC_POLY_BITS; params.maxTiles = TileMap->TileTable.size(); - // rcVcopy(params.orig, bmin); - params.orig[0] = Constants::Origin[0]; - params.orig[1] = 0; - params.orig[2] = Constants::Origin[2]; + rcVcopy(params.orig, bmin); params.tileHeight = Constants::TileSize; params.tileWidth = Constants::TileSize; fwrite(¶ms, sizeof(dtNavMeshParams), 1, mmap); fclose(mmap); std::vector Threads; for (uint32 i = 0; i < NumberOfThreads; ++i) - Threads.push_back(new BuilderThread(debug, params)); + Threads.push_back(new BuilderThread(this, debug, params)); printf("Map %s ( %i ) has %i tiles. Building them with %i threads\n", Continent.c_str(), MapId, TileMap->TileTable.size(), NumberOfThreads); for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) { diff --git a/src/tools/mesh_extractor/ContinentBuilder.h b/src/tools/mesh_extractor/ContinentBuilder.h index c923498fc5e..4c16fa0727e 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.h +++ b/src/tools/mesh_extractor/ContinentBuilder.h @@ -7,12 +7,20 @@ class ContinentBuilder { public: - ContinentBuilder(std::string continent, uint32 mapId, WDT* wdt, uint32 tn) : MapId(mapId), Continent(continent), TileMap(wdt), NumberOfThreads(tn) {} + ContinentBuilder(std::string continent, uint32 mapId, WDT* wdt, uint32 tn) : MapId(mapId), Continent(continent), TileMap(wdt), NumberOfThreads(tn), tileXMin(64), tileYMin(64), tileXMax(0), tileYMax(0) {} void Build(bool debug); + void getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax); + void CalculateTileBounds(); + float bmin[3]; + float bmax[3]; private: std::string Continent; WDT* TileMap; uint32 MapId; uint32 NumberOfThreads; + int tileXMin; + int tileYMin; + int tileXMax; + int tileYMax; }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index accccf4460f..7379ba87117 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -6,6 +6,10 @@ #include "Constants.h" #include "Model.h" +#include "Recast.h" +#include "DetourNavMesh.h" +#include "DetourNavMeshQuery.h" + #include #include "Common.h" @@ -306,6 +310,19 @@ void PrintUsage() } } +void LoadTile(dtNavMesh*& navMesh, const char* tile) +{ + FILE* f = fopen(tile, "rb"); + MmapTileHeader header; + fread(&header, sizeof(MmapTileHeader), 1, f); + uint8* nav = new uint8[header.size]; + fread(nav, header.size, 1, f); + + dtStatus res = navMesh->addTile(nav, header.size, DT_TILE_FREE_DATA, 0, NULL); + + fclose(f); +} + int main(int argc, char* argv[]) { system("pause"); @@ -331,6 +348,71 @@ int main(int argc, char* argv[]) if (extractFlags & Constants::EXTRACT_FLAG_GOB_MODELS) ExtractGameobjectModels(); + + if (extractFlags & Constants::EXTRACT_FLAG_TEST) + { + float start[] = { 0.0f, 0.0f, 0.0f }; + float end[] = { 0.0f, 0.0f, 0.0f }; + + // + float m_spos[3]; + m_spos[0] = -1.0f * start[1]; + m_spos[1] = start[2]; + m_spos[2] = -1.0f * start[0]; + + // + float m_epos[3]; + m_epos[0] = -1.0f * end[1]; + m_epos[1] = end[2]; + m_epos[2] = -1.0f * end[0]; + + // + dtQueryFilter m_filter; + m_filter.setIncludeFlags(0xffff) ; + m_filter.setExcludeFlags(0); + + // + float m_polyPickExt[3]; + m_polyPickExt[0] = 2; + m_polyPickExt[1] = 4; + m_polyPickExt[2] = 2; + + // + dtPolyRef m_startRef; + dtPolyRef m_endRef; + + FILE* mmap = fopen(".mmap", "rb"); + dtNavMeshParams params; + fread(¶ms, sizeof(dtNavMeshParams), 1, mmap); + fclose(mmap); + + dtNavMesh* navMesh = new dtNavMesh(); + dtNavMeshQuery* navMeshQuery = new dtNavMeshQuery(); + + navMesh->init(¶ms); + LoadTile(navMesh, ".mmtile"); + LoadTile(navMesh, ".mmtile"); + LoadTile(navMesh, ".mmtile"); + LoadTile(navMesh, ".mmtile"); + LoadTile(navMesh, ".mmtile"); + LoadTile(navMesh, ".mmtile"); + + navMeshQuery->init(navMesh, 2048); + + float nearestPt[3]; + + dtStatus status = navMeshQuery->findNearestPoly(m_spos, m_polyPickExt, &m_filter, &m_startRef, nearestPt); + status = navMeshQuery->findNearestPoly(m_epos, m_polyPickExt, &m_filter, &m_endRef, nearestPt); + + // + if ( !m_startRef || !m_endRef ) + { + std::cerr << "Could not find any nearby poly's (" << m_startRef << "," << m_endRef << ")" << std::endl; + return 0; + } + + printf("Found!"); + } return 0; } \ No newline at end of file diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 12213b16373..2a02bc50cd4 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -1,3 +1,4 @@ +#include "ContinentBuilder.h" #include "TileBuilder.h" #include "Geometry.h" #include "Constants.h" @@ -11,8 +12,10 @@ #include "ace/Synch.h" -TileBuilder::TileBuilder(std::string world, int x, int y, uint32 mapId) : _Geometry(NULL), World(world), X(x), Y(y), MapId(mapId), DataSize(0) +TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, int y, uint32 mapId) : _Geometry(NULL), World(world), X(x), Y(y), MapId(mapId), DataSize(0), cBuilder(_cBuilder) { + /* + Test, non-working values // Cell Size = TileSize / TileVoxelSize // 1800 = TileVoxelSize Config.cs = Constants::TileSize / 1800; @@ -35,6 +38,26 @@ TileBuilder::TileBuilder(std::string world, int x, int y, uint32 mapId) : _Geome Config.height = 1800 + Config.borderSize * 2; Config.maxVertsPerPoly = 6; Config.maxSimplificationError = 1.3f; + */ + + // All are in UNIT metrics! + memset(&Config, 0, sizeof(rcConfig)); + + Config.maxVertsPerPoly = DT_VERTS_PER_POLYGON; + Config.cs = Constants::BaseUnitDim; + Config.ch = Constants::BaseUnitDim; + Config.walkableSlopeAngle = 60.0f; + Config.tileSize = Constants::VertexPerTile; + Config.walkableRadius = 1; + Config.borderSize = Config.walkableRadius + 3; + Config.maxEdgeLen = Constants::VertexPerTile + 1; //anything bigger than tileSize + Config.walkableHeight = 3; + Config.walkableClimb = 2; // keep less than walkableHeight + Config.minRegionArea = rcSqr(60); + Config.mergeRegionArea = rcSqr(50); + Config.maxSimplificationError = 2.0f; // eliminates most jagged edges (tinny polygons) + Config.detailSampleDist = Config.cs * 64; + Config.detailSampleMaxError = Config.ch * 2; Context = new rcContext; } @@ -104,84 +127,101 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) _Geometry->Vertices.clear(); _Geometry->Triangles.clear(); - float bbMin[3]; - float bbMax[3]; - // CalculateTileBounds(bbMin, bbMax, navMeshParams); - rcCalcBounds(vertices, numVerts, bbMin, bbMax); - // _Geometry->CalculateMinMaxHeight(bbMin[1], bbMax[1]); - - /*bbMin[0] -= Config.borderSize * Config.cs; - bbMin[2] -= Config.borderSize * Config.cs; - bbMax[0] += Config.borderSize * Config.cs; - bbMax[0] += Config.borderSize * Config.cs;*/ - - - rcHeightfield* hf = rcAllocHeightfield(); - int height, width; - rcCalcGridSize(bbMin, bbMax, Config.cs, &width, &height); - printf("Config values: Height: %i, Width: %i. Calculated values: Height: %i, Width: %i\n", Config.height, Config.width, height, width); - rcCreateHeightfield(Context, *hf, width, height, bbMin, bbMax, Config.cs, Config.ch); - rcClearUnwalkableTriangles(Context, Config.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas); - rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb); - - printf("[%02i,%02i] Triangles rasterized!\n", X, Y); - - // Once all geometry is rasterized, we do initial pass of filtering to - // remove unwanted overhangs caused by the conservative rasterization - // as well as filter spans where the character cannot possibly stand. - rcFilterLowHangingWalkableObstacles(Context, Config.walkableClimb, *hf); - rcFilterLedgeSpans(Context, Config.walkableHeight, Config.walkableClimb, *hf); - rcFilterWalkableLowHeightSpans(Context, Config.walkableHeight, *hf); - - printf("[%02i,%02i] Filtering done!\n", X, Y); - - // Compact the heightfield so that it is faster to handle from now on. - // This will result in more cache coherent data as well as the neighbours - // between walkable cells will be calculated. - rcCompactHeightfield* chf = rcAllocCompactHeightfield(); - rcBuildCompactHeightfield(Context, Config.walkableHeight, Config.walkableClimb, *hf, *chf); - - rcFreeHeightField(hf); - - printf("[%02i,%02i] Heightfield compressed!\n", X, Y); - - // Erode the walkable area by agent radius. - rcErodeWalkableArea(Context, Config.walkableRadius, *chf); - // Prepare for region partitioning, by calculating distance field along the walkable surface. - rcBuildDistanceField(Context, *chf); - // Partition the walkable surface into simple regions without holes. - rcBuildRegions(Context, *chf, Config.borderSize, Config.minRegionArea, Config.mergeRegionArea); + + rcVcopy(Config.bmin, cBuilder->bmin); + rcVcopy(Config.bmax, cBuilder->bmax); + + // this sets the dimensions of the heightfield - should maybe happen before border padding + rcCalcGridSize(Config.bmin, Config.bmax, Config.cs, &Config.width, &Config.height); + + // Initialize per tile config. + rcConfig tileCfg = Config; + tileCfg.width = Config.tileSize + Config.borderSize * 2; + tileCfg.height = Config.tileSize + Config.borderSize * 2; - printf("[%02i,%02i] Regions built!\n", X, Y); + // merge per tile poly and detail meshes + rcPolyMesh** pmmerge = new rcPolyMesh*[Constants::TilesPerMap * Constants::TilesPerMap]; + rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[Constants::TilesPerMap * Constants::TilesPerMap]; - // Create contours. - rcContourSet* cset = rcAllocContourSet(); - rcBuildContours(Context, *chf, Config.maxSimplificationError, Config.maxEdgeLen, *cset); + int nmerge = 0; + for (int y = 0; y < Constants::TilesPerMap; ++y) + { + for (int x = 0; x < Constants::TilesPerMap; ++x) + { + // Calculate the per tile bounding box. + tileCfg.bmin[0] = Config.bmin[0] + float(x * Config.tileSize - Config.borderSize) * Config.cs; + tileCfg.bmin[2] = Config.bmin[2] + float(y * Config.tileSize - Config.borderSize) * Config.cs; + tileCfg.bmax[0] = Config.bmin[0] + float((x + 1) * Config.tileSize + Config.borderSize) * Config.cs; + tileCfg.bmax[2] = Config.bmin[2] + float((y + 1) * Config.tileSize + Config.borderSize) * Config.cs; + + + rcHeightfield* hf = rcAllocHeightfield(); + rcCreateHeightfield(Context, *hf, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch); + rcClearUnwalkableTriangles(Context, tileCfg.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas); + rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb); + + // Once all geometry is rasterized, we do initial pass of filtering to + // remove unwanted overhangs caused by the conservative rasterization + // as well as filter spans where the character cannot possibly stand. + rcFilterLowHangingWalkableObstacles(Context, Config.walkableClimb, *hf); + rcFilterLedgeSpans(Context, tileCfg.walkableHeight, tileCfg.walkableClimb, *hf); + rcFilterWalkableLowHeightSpans(Context, tileCfg.walkableHeight, *hf); + + // Compact the heightfield so that it is faster to handle from now on. + // This will result in more cache coherent data as well as the neighbours + // between walkable cells will be calculated. + rcCompactHeightfield* chf = rcAllocCompactHeightfield(); + rcBuildCompactHeightfield(Context, tileCfg.walkableHeight, tileCfg.walkableClimb, *hf, *chf); + + rcFreeHeightField(hf); + + // Erode the walkable area by agent radius. + rcErodeWalkableArea(Context, Config.walkableRadius, *chf); + // Prepare for region partitioning, by calculating distance field along the walkable surface. + rcBuildDistanceField(Context, *chf); + // Partition the walkable surface into simple regions without holes. + rcBuildRegions(Context, *chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea); + + // Create contours. + rcContourSet* cset = rcAllocContourSet(); + rcBuildContours(Context, *chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *cset); + + // Build polygon navmesh from the contours. + rcPolyMesh* pmesh = rcAllocPolyMesh(); + rcBuildPolyMesh(Context, *cset, tileCfg.maxVertsPerPoly, *pmesh); + + // Build detail mesh. + rcPolyMeshDetail* dmesh = rcAllocPolyMeshDetail(); + rcBuildPolyMeshDetail(Context, *pmesh, *chf, tileCfg.detailSampleDist, tileCfg.detailSampleMaxError, *dmesh); + + // Free memory + rcFreeCompactHeightfield(chf); + rcFreeContourSet(cset); + + pmmerge[nmerge] = pmesh; + dmmerge[nmerge] = dmesh; + ++nmerge; + } + } - // Build polygon navmesh from the contours. rcPolyMesh* pmesh = rcAllocPolyMesh(); - rcBuildPolyMesh(Context, *cset, Config.maxVertsPerPoly, *pmesh); - - printf("[%02i,%02i] Polymesh built!\n", X, Y); - - // Build detail mesh. + rcMergePolyMeshes(Context, pmmerge, nmerge, *pmesh); + rcPolyMeshDetail* dmesh = rcAllocPolyMeshDetail(); - rcBuildPolyMeshDetail(Context, *pmesh, *chf, Config.detailSampleDist, Config.detailSampleMaxError, *dmesh); - - printf("[%02i,%02i] Polymesh detail built!\n", X, Y); - - rcFreeCompactHeightfield(chf); - rcFreeContourSet(cset); - - /* - * Removed with RecastNavigation v292 + rcMergePolyMeshDetails(Context, dmmerge, nmerge, *dmesh); + + delete[] pmmerge; + delete[] dmmerge; + + printf("[%02i,%02i] Meshes merged!\n", X, Y); + // Remove padding from the polymesh data. (Remove this odditity) for (int i = 0; i < pmesh->nverts; ++i) { unsigned short* v = &pmesh->verts[i * 3]; v[0] -= (unsigned short)Config.borderSize; v[2] -= (unsigned short)Config.borderSize; - }*/ + } // Set flags according to area types (e.g. Swim for Water) for (int i = 0; i < pmesh->npolys; i++) @@ -192,14 +232,8 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) pmesh->flags[i] = Constants::POLY_FLAG_SWIM; } - // get original bounds - /*float* tilebMin; - float* tilebMax; - CalculateTileBounds(tilebMin, tilebMax, navMeshParams); - tilebMin[1] = bbMin[1]; - tilebMax[1] = bbMax[1];*/ - dtNavMeshCreateParams params; + memset(¶ms, 0, sizeof(params)); // PolyMesh data params.verts = pmesh->verts; params.vertCount = pmesh->nverts; @@ -214,32 +248,39 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) params.detailVertsCount = dmesh->nverts; params.detailTris = dmesh->tris; params.detailTriCount = dmesh->ntris; - // Copy bounding box - /*params.bmin[0] = tilebMin[0]; - params.bmin[1] = tilebMin[1]; - params.bmin[2] = tilebMin[2]; - params.bmax[0] = tilebMax[0]; - params.bmax[1] = tilebMax[1]; - params.bmax[2] = tilebMax[2];*/ rcVcopy(params.bmin, pmesh->bmin); rcVcopy(params.bmax, pmesh->bmax); // General settings params.ch = Config.ch; params.cs = Config.cs; - params.walkableClimb = Config.walkableClimb; - params.walkableHeight = Config.walkableHeight; - params.walkableRadius = Config.walkableRadius; - params.tileX = X; - params.tileY = Y; - int _x = (((pmesh->bmin[0] + pmesh->bmax[0]) / 2) - Constants::Origin[0]) / Constants::TileSize; - int _y = (((pmesh->bmin[2] + pmesh->bmax[2]) / 2) - Constants::Origin[2]) / Constants::TileSize; - printf("[%02i,%02i] Generated with TileX: %i and TileY: %i\nbmin[0] %f bmin[1] %f bmin[2] %f bmax[0] %f bmax[1] %f bmax[2] %f\n", X, Y, _x, _y, params.bmin[0], params.bmin[1], params.bmin[2], params.bmax[0], params.bmax[1], params.bmax[2]); - params.buildBvTree = true; - params.tileLayer = 0; - + params.walkableClimb = Constants::BaseUnitDim * Config.walkableClimb; + params.walkableHeight = Constants::BaseUnitDim * Config.walkableHeight; + params.walkableRadius = Constants::BaseUnitDim * Config.walkableRadius; + params.tileX = (((cBuilder->bmin[0] + cBuilder->bmax[0]) / 2) - navMeshParams.orig[0]) / Constants::TileSize; + params.tileY = (((cBuilder->bmin[2] + cBuilder->bmax[2]) / 2) - navMeshParams.orig[2]) / Constants::TileSize; + + rcVcopy(params.bmin, cBuilder->bmin); + rcVcopy(params.bmax, cBuilder->bmax); + // Offmesh-connection settings params.offMeshConCount = 0; // none for now + + params.tileSize = Constants::VertexPerMap; + if (!params.polyCount || !params.polys || Constants::TilesPerMap * Constants::TilesPerMap == params.polyCount) + { + // we have flat tiles with no actual geometry - don't build those, its useless + // keep in mind that we do output those into debug info + // drop tiles with only exact count - some tiles may have geometry while having less tiles + printf("[%02i,%02i] No polygons to build on tile, skipping.\n", X, Y); + rcFreePolyMesh(pmesh); + rcFreePolyMeshDetail(dmesh); + delete areas; + delete triangles; + delete vertices; + return NULL; + } + int navDataSize; uint8* navData; printf("[%02i,%02i] Creating the navmesh with %i vertices, %i polys, %i triangles!\n", X, Y, pmesh->nverts, pmesh->npolys, dmesh->ntris); @@ -248,13 +289,9 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) // Free some memory rcFreePolyMesh(pmesh); rcFreePolyMeshDetail(dmesh); - //delete tilebMax; - //delete tilebMin; delete areas; delete triangles; delete vertices; - //delete bbMax; - //delete bbMin; if (result) { diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h index 17d6e48095a..40c96f6ec42 100644 --- a/src/tools/mesh_extractor/TileBuilder.h +++ b/src/tools/mesh_extractor/TileBuilder.h @@ -5,12 +5,13 @@ #include "Geometry.h" +class ContinentBuilder; class WDT; class TileBuilder { public: - TileBuilder(std::string world, int x, int y, uint32 mapId); + TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, int y, uint32 mapId); ~TileBuilder(); void CalculateTileBounds(float*& bmin, float*& bmax, dtNavMeshParams& navMeshParams); @@ -24,5 +25,6 @@ public: rcContext* Context; Geometry* _Geometry; uint32 DataSize; + ContinentBuilder* cBuilder; }; #endif \ No newline at end of file diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index b1b054e942e..3639cb88acf 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -21,6 +21,10 @@ const float Constants::PI = 3.1415926f; const float Constants::MaxStandableHeight = 1.5f; const char* Constants::VMAPMagic = "VMAP041"; bool Constants::ToWoWCoords = false; +const float Constants::BaseUnitDim = 0.533333f; +const int Constants::VertexPerMap = (Constants::TileSize / Constants::BaseUnitDim) + 0.5f; +const int Constants::VertexPerTile = 40; +const int Constants::TilesPerMap = Constants::VertexPerMap / Constants::VertexPerTile; void Utils::CreateDir( const std::string& Path ) { -- cgit v1.2.3 From 677ee02b8ea32aad12bce60db7527c60ef76f164 Mon Sep 17 00:00:00 2001 From: kaelima Date: Wed, 7 Nov 2012 16:42:22 +0100 Subject: Core/Movement: MovementGenerator fixes. - vmap height search in FleeingMovementGenerator and ConfusedMovementGenerator (until we can search for a nearby position properly) Should solve #7704, needs testing - Removed some unused code in CalculatePath and TargetedMovementGenerator. Ty faramir118 - Allow players to charge through slime and lava liquids. Closes #7967 --- .../ConfusedMovementGenerator.cpp | 22 +++-- .../FleeingMovementGenerator.cpp | 26 ++++-- .../TargetedMovementGenerator.cpp | 100 ++++++++------------- .../MovementGenerators/TargetedMovementGenerator.h | 3 +- src/server/game/Movement/PathGenerator.cpp | 25 +----- src/server/game/Movement/Spline/MoveSplineInit.cpp | 2 +- 6 files changed, 79 insertions(+), 99 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index 4c269a1024a..4af5f7b4acb 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -70,18 +70,26 @@ bool ConfusedMovementGenerator::Update(T* unit, const uint32& diff) // start moving unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE); - float x = i_x + 10.0f*((float)rand_norm() - 0.5f); - float y = i_y + 10.0f*((float)rand_norm() - 0.5f); - float z = i_z; + float x = i_x + (4.0f * (float)rand_norm() - 2.0f); + float y = i_y + (4.0f * (float)rand_norm() - 2.0f); - unit->UpdateAllowedPositionZ(x, y, z); + Trinity::NormalizeMapCoord(x); + Trinity::NormalizeMapCoord(y); + + float z = unit->GetBaseMap()->GetHeight(unit->GetPhaseMask(), x, y, 10.0f, true); + + if (z <= INVALID_HEIGHT || fabs(i_z - z) > 10.0f || !unit->IsWithinLOS(x, y, z)) + { + i_nextMoveTime.Reset(100); + return true; + } PathGenerator path(unit); - path.SetPathLengthLimit(30.0f); + path.SetPathLengthLimit(20.0f); bool result = path.CalculatePath(x, y, z); - if (!result || path.GetPathType() & PATHFIND_NOPATH) + if (!result || (path.GetPathType() & PATHFIND_NOPATH)) { - i_nextMoveTime.Reset(urand(800, 1000)); + i_nextMoveTime.Reset(100); // short reset return true; } diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index b8764bd5042..5cdbdb24341 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -39,16 +39,19 @@ void FleeingMovementGenerator::_setTargetLocation(T* owner) float x, y, z; if (!_getPoint(owner, x, y, z)) + { + i_nextCheckTime.Reset(100); return; + } owner->AddUnitState(UNIT_STATE_FLEEING_MOVE); PathGenerator path(owner); - path.SetPathLengthLimit(30.0f); + path.SetPathLengthLimit(20.0f); bool result = path.CalculatePath(x, y, z); - if (!result || path.GetPathType() & PATHFIND_NOPATH) + if (!result || (path.GetPathType() & PATHFIND_NOPATH)) { - i_nextCheckTime.Reset(urand(1000, 1500)); + i_nextCheckTime.Reset(100); return; } @@ -86,7 +89,7 @@ bool FleeingMovementGenerator::_getPoint(T* owner, float &x, float &y, float dist = frand(0.4f, 1.3f)*(MIN_QUIET_DISTANCE - dist_from_caster); angle = angle_to_caster + frand(-static_cast(M_PI)/8, static_cast(M_PI)/8); } - else if(dist_from_caster > MAX_QUIET_DISTANCE) + else if (dist_from_caster > MAX_QUIET_DISTANCE) { dist = frand(0.4f, 1.0f)*(MAX_QUIET_DISTANCE - MIN_QUIET_DISTANCE); angle = -angle_to_caster + frand(-static_cast(M_PI)/4, static_cast(M_PI)/4); @@ -102,9 +105,17 @@ bool FleeingMovementGenerator::_getPoint(T* owner, float &x, float &y, float x = curr_x + dist * std::cos(angle); y = curr_y + dist * std::sin(angle); - z = curr_z; - owner->UpdateAllowedPositionZ(x, y, z); + Trinity::NormalizeMapCoord(x); + Trinity::NormalizeMapCoord(y); + + z = owner->GetBaseMap()->GetHeight(owner->GetPhaseMask(), x, y, 10.0f, true); + + if (z <= INVALID_HEIGHT) + return false; + + if (fabs(curr_z - z) > 10.0f || !owner->IsWithinLOS(x, y, z)) + return false; return true; } @@ -152,6 +163,7 @@ bool FleeingMovementGenerator::Update(T* owner, const uint32& time_diff) { if (!owner || !owner->isAlive()) return false; + if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) { owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE); @@ -159,7 +171,7 @@ bool FleeingMovementGenerator::Update(T* owner, const uint32& time_diff) } i_nextCheckTime.Update(time_diff); - if (i_nextCheckTime.Passed() && owner->movespline->Finalized()) + if (i_nextCheckTime.Passed()) _setTargetLocation(owner); return true; diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 7a6611ed2ca..dc6cc55b855 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -27,7 +27,7 @@ #include "Player.h" template -void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner) +void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner, bool updateDestination) { if (!i_target.isValid() || !i_target->IsInWorld()) return; @@ -40,37 +40,42 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner) float x, y, z; - if (!i_offset) + if (updateDestination || !i_path) { - float dist = 0.0f; - - if (owner->getVictim() && owner->getVictim()->GetGUID() == i_target->GetGUID()) - dist = owner->GetFloatValue(UNIT_FIELD_COMBATREACH) + i_target->GetFloatValue(UNIT_FIELD_COMBATREACH) - i_target->GetObjectSize() - owner->GetObjectSize() - 1.0f; - - if (dist < 0.5f) - dist = 0.5f; - - if (owner->IsWithinLOSInMap(owner->getVictim())) - i_target->GetContactPoint(owner, x, y, z, dist); + if (!i_offset) + { + // to nearest contact position + i_target->GetContactPoint(owner, x, y, z); + } else - i_target->GetPosition(x, y, z); + { + // to at i_offset distance from target and i_angle from target facing + i_target->GetClosePoint(x, y, z, owner->GetObjectSize(), i_offset, i_angle); + } } else { - // to at i_offset distance from target and i_angle from target facing - i_target->GetClosePoint(x, y, z, owner->GetObjectSize(), i_offset, i_angle); + // the destination has not changed, we just need to refresh the path (usually speed change) + G3D::Vector3 end = i_path->GetEndPosition(); + x = end.x; + y = end.y; + z = end.z; } if (!i_path) i_path = new PathGenerator(owner); - // allow pets following their master to cheat while generating paths + // allow pets to use shortcut if no path found when following their master bool forceDest = (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->isPet() && owner->HasUnitState(UNIT_STATE_FOLLOW)); bool result = i_path->CalculatePath(x, y, z, forceDest); - if (!result || i_path->GetPathType() & PATHFIND_NOPATH) + if (!result || (i_path->GetPathType() & PATHFIND_NOPATH)) + { + // Cant reach target + i_recalculateTravel = true; return; + } D::_addUnitStateMove(owner); i_targetReached = false; @@ -79,37 +84,14 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner) Movement::MoveSplineInit init(owner); init.MovebyPath(i_path->GetPath()); - init.SetFacing(i_target.getTarget()); + if (forceDest && updateDestination) + init.SetFacing(i_target.getTarget()->GetOrientation()); + else + init.SetFacing(i_target.getTarget()); init.SetWalk(((D*)this)->EnableWalking()); init.Launch(); } -template<> -void TargetedMovementGeneratorMedium >::UpdateFinalDistance(float /*fDistance*/) -{ - // nothing to do for Player -} - -template<> -void TargetedMovementGeneratorMedium >::UpdateFinalDistance(float /*fDistance*/) -{ - // nothing to do for Player -} - -template<> -void TargetedMovementGeneratorMedium >::UpdateFinalDistance(float fDistance) -{ - i_offset = fDistance; - i_recalculateTravel = true; -} - -template<> -void TargetedMovementGeneratorMedium >::UpdateFinalDistance(float fDistance) -{ - i_offset = fDistance; - i_recalculateTravel = true; -} - template bool TargetedMovementGeneratorMedium::Update(T* owner, const uint32& time_diff) { @@ -140,6 +122,7 @@ bool TargetedMovementGeneratorMedium::Update(T* owner, const uint32& time_d return true; } + bool targetMoved = false; i_recheckDistance.Update(time_diff); if (i_recheckDistance.Passed()) { @@ -148,16 +131,15 @@ bool TargetedMovementGeneratorMedium::Update(T* owner, const uint32& time_d float allowed_dist = owner->GetCombatReach() + sWorld->getRate(RATE_TARGET_POS_RECALCULATION_RANGE); G3D::Vector3 dest = owner->movespline->FinalDestination(); - bool targetMoved = false; if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->CanFly()) targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist); else targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist); - - if (targetMoved || !owner->IsWithinLOSInMap(owner->getVictim())) - _setTargetLocation(owner); } + if (i_recalculateTravel || targetMoved) + _setTargetLocation(owner, targetMoved); + if (owner->movespline->Finalized()) { static_cast(this)->MovementInform(owner); @@ -170,11 +152,7 @@ bool TargetedMovementGeneratorMedium::Update(T* owner, const uint32& time_d static_cast(this)->_reachTarget(owner); } } - else - { - if (i_recalculateTravel) - _setTargetLocation(owner); - } + return true; } @@ -190,7 +168,7 @@ template<> void ChaseMovementGenerator::Initialize(Player* owner) { owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); - _setTargetLocation(owner); + _setTargetLocation(owner, true); } template<> @@ -198,7 +176,7 @@ void ChaseMovementGenerator::Initialize(Creature* owner) { owner->SetWalk(false); owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); - _setTargetLocation(owner); + _setTargetLocation(owner, true); } template @@ -262,7 +240,7 @@ void FollowMovementGenerator::Initialize(Player* owner) { owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); _updateSpeed(owner); - _setTargetLocation(owner); + _setTargetLocation(owner, true); } template<> @@ -270,7 +248,7 @@ void FollowMovementGenerator::Initialize(Creature* owner) { owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); _updateSpeed(owner); - _setTargetLocation(owner); + _setTargetLocation(owner, true); } template @@ -300,10 +278,10 @@ void FollowMovementGenerator::MovementInform(Creature* unit) } //-----------------------------------------------// -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player*); -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player*); -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature*); -template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature*); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player*, bool); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player*, bool); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature*, bool); +template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature*, bool); template bool TargetedMovementGeneratorMedium >::Update(Player*, const uint32&); template bool TargetedMovementGeneratorMedium >::Update(Player*, const uint32&); template bool TargetedMovementGeneratorMedium >::Update(Creature*, const uint32&); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 064e5bfa1a2..f293d5976af 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -51,10 +51,9 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, Unit* GetTarget() const { return i_target.getTarget(); } void unitSpeedChanged() { i_recalculateTravel = true; } - void UpdateFinalDistance(float fDistance); bool IsReachable() const { return (i_path) ? (i_path->GetPathType() & PATHFIND_NORMAL) : true; } protected: - void _setTargetLocation(T*); + void _setTargetLocation(T* owner, bool updateDestination); TimeTrackerSmall i_recheckDistance; float i_offset; diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 3495c4d1218..71617f6a6ab 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -58,7 +58,6 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z)) return false; - Vector3 oldDest = GetEndPosition(); Vector3 dest(destX, destY, destZ); SetEndPosition(dest); @@ -81,24 +80,8 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo UpdateFilter(); - // check if destination moved - if not we can optimize something here - // we are following old, precalculated path? - float dist = _sourceUnit->GetObjectSize(); - if (oldDest != Vector3::zero() && InRange(oldDest, dest, dist, dist) && _pathPoints.size() > 2) - { - // our target is not moving - we just coming closer - // we are moving on precalculated path - enjoy the ride - sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::CalculatePath:: precalculated path\n"); - - _pathPoints.erase(_pathPoints.begin()); - return false; - } - else - { - // target moved, so we need to update the poly path - BuildPolyPath(start, dest); - return true; - } + BuildPolyPath(start, dest); + return true; } dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* point, float* distance) const @@ -534,10 +517,10 @@ void PathGenerator::CreateFilter() if (creature->canSwim()) includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim } - else if (_sourceUnit->GetTypeId() == TYPEID_PLAYER) + else // assume Player { // perfect support not possible, just stay 'safe' - includeFlags |= (NAV_GROUND | NAV_WATER); + includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA | NAV_SLIME); } _filter.setIncludeFlags(includeFlags); diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index 67b019b93f7..b6cd1391ca3 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -98,7 +98,7 @@ namespace Movement if (!args.HasVelocity) args.velocity = unit->GetSpeed(SelectSpeedType(moveFlags)); - if (!args.Validate(&unit)) + if (!args.Validate(unit)) return 0; if (moveFlags & MOVEMENTFLAG_ROOT) -- cgit v1.2.3 From 7249865a12e6483b925fae468bd899b73c190e39 Mon Sep 17 00:00:00 2001 From: rocky517 Date: Mon, 12 Nov 2012 14:43:51 +0200 Subject: Update src/server/scripts/Commands/cs_mmaps.cpp --- src/server/scripts/Commands/cs_mmaps.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index c3f757614e2..c17c01adc33 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -96,7 +96,7 @@ public: bool result = path.CalculatePath(x, y, z); PointsArray pointPath = path.GetPath(); - handler->PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName()); + handler->PSendSysMessage("%s's path to %s:", target->GetName().c_str(), player->GetName().c_str()); handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : "SmoothPath"); handler->PSendSysMessage("Result: %s - Length: %i - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); -- cgit v1.2.3 From 94cca94017d8652ce8efebed15894ea09dedf598 Mon Sep 17 00:00:00 2001 From: kaelima Date: Tue, 13 Nov 2012 15:44:42 +0100 Subject: Core/Movement: General improvements for confused/fleeing movement --- src/server/game/Movement/MotionMaster.cpp | 4 +- .../ConfusedMovementGenerator.cpp | 35 ++++++++------- .../FleeingMovementGenerator.cpp | 52 ++++++---------------- .../MovementGenerators/FleeingMovementGenerator.h | 2 +- 4 files changed, 35 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index b9cfbdf024f..48f17a0d0c6 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -651,9 +651,9 @@ void MotionMaster::DelayedDelete(_Ty curr) bool MotionMaster::GetDestination(float &x, float &y, float &z) { if (_owner->movespline->Finalized()) - return false; + return false; - const G3D::Vector3& dest = _owner->movespline->FinalDestination(); + G3D::Vector3 const& dest = _owner->movespline->FinalDestination(); x = dest.x; y = dest.y; z = dest.z; diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index 4af5f7b4acb..a8b4d68c802 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -33,16 +33,25 @@ template void ConfusedMovementGenerator::Initialize(T* unit) { + unit->AddUnitState(UNIT_STATE_CONFUSED); + unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); unit->GetPosition(i_x, i_y, i_z); + + if (!unit->isAlive() || unit->IsStopped()) + return; + unit->StopMoving(); - unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); - unit->AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); + unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE); } template void ConfusedMovementGenerator::Reset(T* unit) { i_nextMoveTime.Reset(0); + + if (!unit->isAlive() || unit->IsStopped()) + return; + unit->StopMoving(); unit->AddUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); } @@ -70,26 +79,18 @@ bool ConfusedMovementGenerator::Update(T* unit, const uint32& diff) // start moving unit->AddUnitState(UNIT_STATE_CONFUSED_MOVE); - float x = i_x + (4.0f * (float)rand_norm() - 2.0f); - float y = i_y + (4.0f * (float)rand_norm() - 2.0f); + float dest = 4.0f * (float)rand_norm() - 2.0f; - Trinity::NormalizeMapCoord(x); - Trinity::NormalizeMapCoord(y); - - float z = unit->GetBaseMap()->GetHeight(unit->GetPhaseMask(), x, y, 10.0f, true); - - if (z <= INVALID_HEIGHT || fabs(i_z - z) > 10.0f || !unit->IsWithinLOS(x, y, z)) - { - i_nextMoveTime.Reset(100); - return true; - } + Position pos; + pos.Relocate(i_x, i_y, i_z); + unit->MovePositionToFirstCollision(pos, dest, 0.0f); PathGenerator path(unit); - path.SetPathLengthLimit(20.0f); - bool result = path.CalculatePath(x, y, z); + path.SetPathLengthLimit(30.0f); + bool result = path.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ); if (!result || (path.GetPathType() & PATHFIND_NOPATH)) { - i_nextMoveTime.Reset(100); // short reset + i_nextMoveTime.Reset(100); return true; } diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 5cdbdb24341..578654ca162 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -37,17 +37,13 @@ void FleeingMovementGenerator::_setTargetLocation(T* owner) if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) return; - float x, y, z; - if (!_getPoint(owner, x, y, z)) - { - i_nextCheckTime.Reset(100); - return; - } - owner->AddUnitState(UNIT_STATE_FLEEING_MOVE); + float x, y, z; + _getPoint(owner, x, y, z); + PathGenerator path(owner); - path.SetPathLengthLimit(20.0f); + path.SetPathLengthLimit(30.0f); bool result = path.CalculatePath(x, y, z); if (!result || (path.GetPathType() & PATHFIND_NOPATH)) { @@ -63,11 +59,8 @@ void FleeingMovementGenerator::_setTargetLocation(T* owner) } template -bool FleeingMovementGenerator::_getPoint(T* owner, float &x, float &y, float &z) +void FleeingMovementGenerator::_getPoint(T* owner, float &x, float &y, float &z) { - if (!owner) - return false; - float dist_from_caster, angle_to_caster; if (Unit* fright = ObjectAccessor::GetUnit(*owner, i_frightGUID)) { @@ -100,24 +93,11 @@ bool FleeingMovementGenerator::_getPoint(T* owner, float &x, float &y, float angle = frand(0, 2*static_cast(M_PI)); } - float curr_x, curr_y, curr_z; - owner->GetPosition(curr_x, curr_y, curr_z); - - x = curr_x + dist * std::cos(angle); - y = curr_y + dist * std::sin(angle); - - Trinity::NormalizeMapCoord(x); - Trinity::NormalizeMapCoord(y); - - z = owner->GetBaseMap()->GetHeight(owner->GetPhaseMask(), x, y, 10.0f, true); - - if (z <= INVALID_HEIGHT) - return false; - - if (fabs(curr_z - z) > 10.0f || !owner->IsWithinLOS(x, y, z)) - return false; - - return true; + Position pos; + owner->GetFirstCollisionPosition(pos, dist, angle); + x = pos.m_positionX; + y = pos.m_positionY; + z = pos.m_positionZ; } template @@ -127,11 +107,7 @@ void FleeingMovementGenerator::Initialize(T* owner) return; owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); - owner->AddUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); - - if (owner->GetTypeId() == TYPEID_UNIT) - return; - + owner->AddUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE); _setTargetLocation(owner); } @@ -171,7 +147,7 @@ bool FleeingMovementGenerator::Update(T* owner, const uint32& time_diff) } i_nextCheckTime.Update(time_diff); - if (i_nextCheckTime.Passed()) + if (i_nextCheckTime.Passed() && owner->movespline->Finalized()) _setTargetLocation(owner); return true; @@ -179,8 +155,8 @@ bool FleeingMovementGenerator::Update(T* owner, const uint32& time_diff) template void FleeingMovementGenerator::Initialize(Player*); template void FleeingMovementGenerator::Initialize(Creature*); -template bool FleeingMovementGenerator::_getPoint(Player*, float&, float&, float&); -template bool FleeingMovementGenerator::_getPoint(Creature*, float&, float&, float&); +template void FleeingMovementGenerator::_getPoint(Player*, float&, float&, float&); +template void FleeingMovementGenerator::_getPoint(Creature*, float&, float&, float&); template void FleeingMovementGenerator::_setTargetLocation(Player*); template void FleeingMovementGenerator::_setTargetLocation(Creature*); template void FleeingMovementGenerator::Reset(Player*); diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h index 88dedd31af6..ed1fe85a314 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h @@ -36,7 +36,7 @@ class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovem private: void _setTargetLocation(T*); - bool _getPoint(T*, float &x, float &y, float &z); + void _getPoint(T*, float &x, float &y, float &z); uint64 i_frightGUID; TimeTracker i_nextCheckTime; -- cgit v1.2.3 From 0fa484793acb1f6b556569ebfc9ce472372d5d78 Mon Sep 17 00:00:00 2001 From: Nay Date: Fri, 23 Nov 2012 23:44:43 +0000 Subject: Fix a typo in previous merge --- .../game/Movement/MovementGenerators/TargetedMovementGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 554e38d7efd..45c7c7c9ab2 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -55,10 +55,10 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner, bool upd // We need to subtract GetObjectSize() because it gets added back further down the chain // and that makes pets too far away. Subtracting it allows pets to properly // be (GetCombatReach() + i_offset) away. - if (owner.isPet()) + if (owner->isPet()) size = i_target->GetCombatReach() - i_target->GetObjectSize(); else - size = owner.GetObjectSize(); + size = owner->GetObjectSize(); // to at i_offset distance from target and i_angle from target facing i_target->GetClosePoint(x, y, z, size, i_offset, i_angle); -- cgit v1.2.3 From 8f27dfda627903997b67cab9ebb4c5b365da201e Mon Sep 17 00:00:00 2001 From: Nay Date: Sat, 24 Nov 2012 23:48:30 +0000 Subject: Core/SAI: Add more details to an error log --- src/server/game/Conditions/ConditionMgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 2f3cb0fbaaf..5fe81bcf89c 100755 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -1410,7 +1410,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) if (cond->ConditionTarget >= cond->GetMaxAvailableConditionTargets()) { - sLog->outError(LOG_FILTER_SQL, "SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->SourceType, cond->SourceEntry); + sLog->outError(LOG_FILTER_SQL, "SourceType %u, SourceEntry %u, SourceGroup %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->SourceType, cond->SourceEntry, cond->SourceGroup); return false; } -- cgit v1.2.3 From a0239c2210a49a3b41a764d41d75098e8bb8ffeb Mon Sep 17 00:00:00 2001 From: kaelima Date: Sat, 22 Dec 2012 02:22:44 +0100 Subject: Fix last merge --- .../MovementGenerators/TargetedMovementGenerator.cpp | 14 +++++++++++++- src/server/game/Movement/Spline/MoveSpline.h | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 0cb46a11e2e..88eacccd0aa 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -49,16 +49,28 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner, bool upd } else { + float dist; float size; // Pets need special handling. // We need to subtract GetObjectSize() because it gets added back further down the chain // and that makes pets too far away. Subtracting it allows pets to properly // be (GetCombatReach() + i_offset) away. - if (owner->isPet()) + // Only applies when i_target is pet's owner otherwise pets and mobs end up + // doing a "dance" while fighting + if (owner->isPet() && i_target->GetTypeId() == TYPEID_PLAYER) + { + dist = i_target->GetCombatReach(); size = i_target->GetCombatReach() - i_target->GetObjectSize(); + } else + { + dist = i_offset + 1.0f; size = owner->GetObjectSize(); + } + + if (i_target->IsWithinDistInMap(owner, dist)) + return; // to at i_offset distance from target and i_angle from target facing i_target->GetClosePoint(x, y, z, size, i_offset, i_angle); diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h index edeff668e0c..938466cd475 100644 --- a/src/server/game/Movement/Spline/MoveSpline.h +++ b/src/server/game/Movement/Spline/MoveSpline.h @@ -78,11 +78,11 @@ namespace Movement UpdateResult _updateState(int32& ms_time_diff); int32 next_timestamp() const { return spline.length(point_Idx+1); } int32 segment_time_elapsed() const { return next_timestamp()-time_passed; } - int32 Duration() const { return spline.length(); } int32 timeElapsed() const { return Duration() - time_passed; } int32 timePassed() const { return time_passed; } public: + int32 Duration() const { return spline.length(); } const MySpline& _Spline() const { return spline; } int32 _currentSplineIdx() const { return point_Idx; } void _Finalize(); -- cgit v1.2.3 From 08f62d8313e05ed6eb1767eed07a7e31533e9bb6 Mon Sep 17 00:00:00 2001 From: joschiwald Date: Sun, 30 Dec 2012 21:09:21 +0100 Subject: Core/MMaps: use DisableMgr to disable pathfinding on a specific map --- sql/updates/world/2012_12_30_00_world_commands.sql | 4 +++ src/server/collision/Management/MMapFactory.cpp | 32 ++-------------------- src/server/collision/Management/MMapFactory.h | 1 - src/server/game/Conditions/DisableMgr.cpp | 31 ++++++++++++++++++++- src/server/game/Conditions/DisableMgr.h | 8 +++++- src/server/game/World/World.cpp | 1 - src/server/scripts/Commands/cs_disable.cpp | 32 ++++++++++++++++++++++ src/server/worldserver/worldserver.conf.dist | 7 ----- 8 files changed, 75 insertions(+), 41 deletions(-) create mode 100644 sql/updates/world/2012_12_30_00_world_commands.sql (limited to 'src') diff --git a/sql/updates/world/2012_12_30_00_world_commands.sql b/sql/updates/world/2012_12_30_00_world_commands.sql new file mode 100644 index 00000000000..fffd1a95cb5 --- /dev/null +++ b/sql/updates/world/2012_12_30_00_world_commands.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` LIKE 'disable add mmap' OR `name` LIKE 'disable remove mmap'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('disable add mmap', '3', 'Syntax: .disable add mmap $entry $flag $comment'), +('disable remove mmap', '3', 'Syntax: .disable remove mmap $entry'); diff --git a/src/server/collision/Management/MMapFactory.cpp b/src/server/collision/Management/MMapFactory.cpp index f4b2f3d47e4..0b292b56dca 100644 --- a/src/server/collision/Management/MMapFactory.cpp +++ b/src/server/collision/Management/MMapFactory.cpp @@ -19,7 +19,7 @@ #include "MMapFactory.h" #include "World.h" #include "Config.h" -#include +#include "DisableMgr.h" namespace MMAP { @@ -27,9 +27,6 @@ namespace MMAP // our global singleton copy MMapManager *g_MMapManager = NULL; - // stores list of mapids which do not use pathfinding - std::set* g_mmapDisabledIds = NULL; - MMapManager* MMapFactory::createOrGetMMapManager() { if (g_MMapManager == NULL) @@ -38,39 +35,14 @@ namespace MMAP return g_MMapManager; } - void MMapFactory::preventPathfindingOnMaps(const char* ignoreMapIds) - { - if (!g_mmapDisabledIds) - g_mmapDisabledIds = new std::set(); - - uint32 strLenght = strlen(ignoreMapIds)+1; - char* mapList = new char[strLenght]; - memcpy(mapList, ignoreMapIds, sizeof(char)*strLenght); - - char* idstr = strtok(mapList, ","); - while (idstr) - { - g_mmapDisabledIds->insert(uint32(atoi(idstr))); - idstr = strtok(NULL, ","); - } - - delete[] mapList; - } - bool MMapFactory::IsPathfindingEnabled(uint32 mapId) { return sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS) - && g_mmapDisabledIds->find(mapId) == g_mmapDisabledIds->end(); + && !DisableMgr::IsDisabledFor(DISABLE_TYPE_MMAP, mapId, NULL, MMAP_DISABLE_PATHFINDING); } void MMapFactory::clear() { - if (g_mmapDisabledIds) - { - delete g_mmapDisabledIds; - g_mmapDisabledIds = NULL; - } - if (g_MMapManager) { delete g_MMapManager; diff --git a/src/server/collision/Management/MMapFactory.h b/src/server/collision/Management/MMapFactory.h index ab047333a19..a006aedfa6d 100644 --- a/src/server/collision/Management/MMapFactory.h +++ b/src/server/collision/Management/MMapFactory.h @@ -42,7 +42,6 @@ namespace MMAP public: static MMapManager* createOrGetMMapManager(); static void clear(); - static void preventPathfindingOnMaps(const char* ignoreMapIds); static bool IsPathfindingEnabled(uint32 mapId); }; } diff --git a/src/server/game/Conditions/DisableMgr.cpp b/src/server/game/Conditions/DisableMgr.cpp index b544e966084..c9cef63907e 100644 --- a/src/server/game/Conditions/DisableMgr.cpp +++ b/src/server/game/Conditions/DisableMgr.cpp @@ -42,7 +42,7 @@ namespace DisableMap m_DisableMap; - uint8 MAX_DISABLE_TYPES = 7; + uint8 MAX_DISABLE_TYPES = 8; } void LoadDisables() @@ -222,6 +222,34 @@ void LoadDisables() } break; } + case DISABLE_TYPE_MMAP: + { + MapEntry const* mapEntry = sMapStore.LookupEntry(entry); + if (!mapEntry) + { + sLog->outError(LOG_FILTER_SQL, "Map entry %u from `disables` doesn't exist in dbc, skipped.", entry); + continue; + } + switch (mapEntry->map_type) + { + case MAP_COMMON: + sLog->outInfo(LOG_FILTER_GENERAL, "Pathfinding disabled for world map %u.", entry); + break; + case MAP_INSTANCE: + case MAP_RAID: + sLog->outInfo(LOG_FILTER_GENERAL, "Pathfinding disabled for instance map %u.", entry); + break; + case MAP_BATTLEGROUND: + sLog->outInfo(LOG_FILTER_GENERAL, "Pathfinding disabled for battleground map %u.", entry); + break; + case MAP_ARENA: + sLog->outInfo(LOG_FILTER_GENERAL, "Pathfinding disabled for arena map %u.", entry); + break; + default: + break; + } + break; + } default: break; } @@ -348,6 +376,7 @@ bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags case DISABLE_TYPE_BATTLEGROUND: case DISABLE_TYPE_OUTDOORPVP: case DISABLE_TYPE_ACHIEVEMENT_CRITERIA: + case DISABLE_TYPE_MMAP: return true; case DISABLE_TYPE_VMAP: return flags & itr->second.flags; diff --git a/src/server/game/Conditions/DisableMgr.h b/src/server/game/Conditions/DisableMgr.h index b1bb43315bd..379f0ac967b 100644 --- a/src/server/game/Conditions/DisableMgr.h +++ b/src/server/game/Conditions/DisableMgr.h @@ -31,7 +31,8 @@ enum DisableType DISABLE_TYPE_BATTLEGROUND = 3, DISABLE_TYPE_ACHIEVEMENT_CRITERIA = 4, DISABLE_TYPE_OUTDOORPVP = 5, - DISABLE_TYPE_VMAP = 6 + DISABLE_TYPE_VMAP = 6, + DISABLE_TYPE_MMAP = 7 }; enum SpellDisableTypes @@ -54,6 +55,11 @@ enum VmapDisableTypes VMAP_DISABLE_LIQUIDSTATUS = 0x8 }; +enum MMapDisableTypes +{ + MMAP_DISABLE_PATHFINDING = 0x0 +}; + namespace DisableMgr { void LoadDisables(); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 81261138957..d09bea8b9a6 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1134,7 +1134,6 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_ENABLE_MMAPS] = ConfigMgr::GetBoolDefault("mmap.enablePathFinding", true); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "WORLD: MMap data directory is: %smmaps", m_dataPath.c_str()); - MMAP::MMapFactory::preventPathfindingOnMaps(ConfigMgr::GetStringDefault("mmap.ignoreMapIds", "").c_str()); m_bool_configs[CONFIG_VMAP_INDOOR_CHECK] = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", 0); bool enableIndoor = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", true); diff --git a/src/server/scripts/Commands/cs_disable.cpp b/src/server/scripts/Commands/cs_disable.cpp index cf0b1f08e53..e17cd35b329 100644 --- a/src/server/scripts/Commands/cs_disable.cpp +++ b/src/server/scripts/Commands/cs_disable.cpp @@ -48,6 +48,7 @@ public: { "achievement_criteria", SEC_ADMINISTRATOR, true, &HandleRemoveDisableAchievementCriteriaCommand, "", NULL }, { "outdoorpvp", SEC_ADMINISTRATOR, true, &HandleRemoveDisableOutdoorPvPCommand, "", NULL }, { "vmap", SEC_ADMINISTRATOR, true, &HandleRemoveDisableVmapCommand, "", NULL }, + { "mmap", SEC_ADMINISTRATOR, true, &HandleRemoveDisableMMapCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand addDisableCommandTable[] = @@ -59,6 +60,7 @@ public: { "achievement_criteria", SEC_ADMINISTRATOR, true, &HandleAddDisableAchievementCriteriaCommand, "", NULL }, { "outdoorpvp", SEC_ADMINISTRATOR, true, &HandleAddDisableOutdoorPvPCommand, "", NULL }, { "vmap", SEC_ADMINISTRATOR, true, &HandleAddDisableVmapCommand, "", NULL }, + { "mmap", SEC_ADMINISTRATOR, true, &HandleAddDisableMMapCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand disableCommandTable[] = @@ -172,6 +174,17 @@ public: disableTypeStr = "vmap"; break; } + case DISABLE_TYPE_MMAP: + { + if (!sMapStore.LookupEntry(entry)) + { + handler->PSendSysMessage(LANG_COMMAND_NOMAPFOUND); + handler->SetSentErrorMessage(true); + return false; + } + disableTypeStr = "mmap"; + break; + } default: break; } @@ -256,6 +269,14 @@ public: return HandleAddDisables(handler, args, DISABLE_TYPE_VMAP); } + static bool HandleAddDisableMMapCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + return HandleAddDisables(handler, args, DISABLE_TYPE_MMAP); + } + static bool HandleRemoveDisables(ChatHandler* handler, char const* args, uint8 disableType) { char* entryStr = strtok((char*)args, " "); @@ -289,6 +310,9 @@ public: case DISABLE_TYPE_VMAP: disableTypeStr = "vmap"; break; + case DISABLE_TYPE_MMAP: + disableTypeStr = "mmap"; + break; } PreparedStatement* stmt = NULL; @@ -367,6 +391,14 @@ public: return HandleRemoveDisables(handler, args, DISABLE_TYPE_VMAP); } + + static bool HandleRemoveDisableMMapCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + return HandleRemoveDisables(handler, args, DISABLE_TYPE_MMAP); + } }; void AddSC_disable_commandscript() diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 426d4ab2d55..81b4dad8b06 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -276,13 +276,6 @@ PlayerSave.Stats.SaveOnlyOnLogout = 1 mmap.enablePathFinding = 1 -# -# mmap.ignoreMapIds -# Disable mmap pathfinding on the listed maps. -# List of map ids with delimiter ',' - -mmap.ignoreMapIds = "" - # # vmap.enableLOS # vmap.enableHeight -- cgit v1.2.3 From 234f0971200a0d75db61b163afc433270bce632b Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Tue, 1 Jan 2013 23:06:37 +0100 Subject: Core: Fix build --- src/server/game/Movement/FollowerRefManager.h | 1 - src/server/game/Movement/FollowerReference.cpp | 1 - src/server/game/Movement/FollowerReference.h | 1 - src/server/game/Movement/MotionMaster.h | 1 - src/server/game/Movement/MovementGenerator.h | 15 ++------ src/server/game/Movement/MovementGeneratorImpl.h | 1 - .../ConfusedMovementGenerator.cpp | 23 ++++++----- .../MovementGenerators/ConfusedMovementGenerator.h | 9 ++--- .../FleeingMovementGenerator.cpp | 25 ++++++------ .../MovementGenerators/FleeingMovementGenerator.h | 9 ++--- .../MovementGenerators/HomeMovementGenerator.cpp | 8 ++-- .../MovementGenerators/HomeMovementGenerator.h | 9 ++--- .../MovementGenerators/IdleMovementGenerator.cpp | 1 - .../MovementGenerators/IdleMovementGenerator.h | 1 - .../MovementGenerators/PointMovementGenerator.cpp | 24 ++++++------ .../MovementGenerators/PointMovementGenerator.h | 9 ++--- .../MovementGenerators/RandomMovementGenerator.cpp | 12 +++--- .../MovementGenerators/RandomMovementGenerator.h | 11 +++--- .../TargetedMovementGenerator.cpp | 44 +++++++++++----------- .../MovementGenerators/TargetedMovementGenerator.h | 14 +++---- .../WaypointMovementGenerator.cpp | 20 +++++----- .../MovementGenerators/WaypointMovementGenerator.h | 21 +++++------ src/server/game/Movement/Waypoints/Path.h | 1 - .../game/Movement/Waypoints/WaypointManager.h | 1 - 24 files changed, 119 insertions(+), 143 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/FollowerRefManager.h b/src/server/game/Movement/FollowerRefManager.h index 5066804d60f..48292efc016 100644 --- a/src/server/game/Movement/FollowerRefManager.h +++ b/src/server/game/Movement/FollowerRefManager.h @@ -29,4 +29,3 @@ class FollowerRefManager : public RefManagerstopFollowing(); } - diff --git a/src/server/game/Movement/FollowerReference.h b/src/server/game/Movement/FollowerReference.h index 6a1a3719cb8..647662eb066 100644 --- a/src/server/game/Movement/FollowerReference.h +++ b/src/server/game/Movement/FollowerReference.h @@ -32,4 +32,3 @@ class FollowerReference : public Reference void sourceObjectDestroyLink(); }; #endif - diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index b0676e02f51..f908b096455 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -201,4 +201,3 @@ class MotionMaster //: private std::stack uint8 _cleanFlag; }; #endif - diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h index 43d03160a41..b84899d9b12 100755 --- a/src/server/game/Movement/MovementGenerator.h +++ b/src/server/game/Movement/MovementGenerator.h @@ -55,32 +55,26 @@ class MovementGeneratorMedium : public MovementGenerator void Initialize(Unit* u) { //u->AssertIsType(); - (static_cast(this))->Initialize(static_cast(u)); + (static_cast(this))->DoInitialize(static_cast(u)); } void Finalize(Unit* u) { //u->AssertIsType(); - (static_cast(this))->Finalize(static_cast(u)); + (static_cast(this))->DoFinalize(static_cast(u)); } void Reset(Unit* u) { //u->AssertIsType(); - (static_cast(this))->Reset(static_cast(u)); + (static_cast(this))->DoReset(static_cast(u)); } bool Update(Unit* u, uint32 time_diff) { //u->AssertIsType(); - return (static_cast(this))->Update(static_cast(u), time_diff); + return (static_cast(this))->DoUpdate(static_cast(u), time_diff); } - public: - // will not link if not overridden in the generators - void Initialize(T* u); - void Finalize(T* u); - void Reset(T* u); - bool Update(T* u, const uint32& time_diff); }; struct SelectableMovement : public FactoryHolder @@ -100,4 +94,3 @@ typedef FactoryHolder MovementGenerato typedef FactoryHolder::FactoryHolderRegistry MovementGeneratorRegistry; typedef FactoryHolder::FactoryHolderRepository MovementGeneratorRepository; #endif - diff --git a/src/server/game/Movement/MovementGeneratorImpl.h b/src/server/game/Movement/MovementGeneratorImpl.h index 725b309e3f1..8d9c170bce8 100644 --- a/src/server/game/Movement/MovementGeneratorImpl.h +++ b/src/server/game/Movement/MovementGeneratorImpl.h @@ -28,4 +28,3 @@ MovementGeneratorFactory::Create(void * /*data*/) const return (new MOVEMENT_GEN()); } #endif - diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index 9ccb13c32ee..e1893d499ca 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -31,7 +31,7 @@ #endif template -void ConfusedMovementGenerator::Initialize(T* unit) +void ConfusedMovementGenerator::DoInitialize(T* unit) { unit->AddUnitState(UNIT_STATE_CONFUSED); unit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); @@ -45,7 +45,7 @@ void ConfusedMovementGenerator::Initialize(T* unit) } template -void ConfusedMovementGenerator::Reset(T* unit) +void ConfusedMovementGenerator::DoReset(T* unit) { i_nextMoveTime.Reset(0); @@ -57,7 +57,7 @@ void ConfusedMovementGenerator::Reset(T* unit) } template -bool ConfusedMovementGenerator::Update(T* unit, uint32 diff) +bool ConfusedMovementGenerator::DoUpdate(T* unit, uint32 diff) { if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) return true; @@ -105,7 +105,7 @@ bool ConfusedMovementGenerator::Update(T* unit, uint32 diff) } template<> -void ConfusedMovementGenerator::Finalize(Player* unit) +void ConfusedMovementGenerator::DoFinalize(Player* unit) { unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); unit->ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); @@ -113,7 +113,7 @@ void ConfusedMovementGenerator::Finalize(Player* unit) } template<> -void ConfusedMovementGenerator::Finalize(Creature* unit) +void ConfusedMovementGenerator::DoFinalize(Creature* unit) { unit->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED); unit->ClearUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_CONFUSED_MOVE); @@ -121,10 +121,9 @@ void ConfusedMovementGenerator::Finalize(Creature* unit) unit->SetTarget(unit->getVictim()->GetGUID()); } -template void ConfusedMovementGenerator::Initialize(Player*); -template void ConfusedMovementGenerator::Initialize(Creature*); -template void ConfusedMovementGenerator::Reset(Player*); -template void ConfusedMovementGenerator::Reset(Creature*); -template bool ConfusedMovementGenerator::Update(Player*, uint32 diff); -template bool ConfusedMovementGenerator::Update(Creature*, uint32 diff); - +template void ConfusedMovementGenerator::DoInitialize(Player*); +template void ConfusedMovementGenerator::DoInitialize(Creature*); +template void ConfusedMovementGenerator::DoReset(Player*); +template void ConfusedMovementGenerator::DoReset(Creature*); +template bool ConfusedMovementGenerator::DoUpdate(Player*, uint32 diff); +template bool ConfusedMovementGenerator::DoUpdate(Creature*, uint32 diff); diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h index 22d9bcc1a07..dd130961ed8 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.h @@ -28,10 +28,10 @@ class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMov public: explicit ConfusedMovementGenerator() : i_nextMoveTime(0) {} - void Initialize(T*); - void Finalize(T*); - void Reset(T*); - bool Update(T*, uint32); + void DoInitialize(T*); + void DoFinalize(T*); + void DoReset(T*); + bool DoUpdate(T*, uint32); MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; } private: @@ -39,4 +39,3 @@ class ConfusedMovementGenerator : public MovementGeneratorMedium< T, ConfusedMov float i_x, i_y, i_z; }; #endif - diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 7f9c7fac7e7..14215d22ad1 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -102,7 +102,7 @@ void FleeingMovementGenerator::_getPoint(T* owner, float &x, float &y, float } template -void FleeingMovementGenerator::Initialize(T* owner) +void FleeingMovementGenerator::DoInitialize(T* owner) { if (!owner) return; @@ -113,7 +113,7 @@ void FleeingMovementGenerator::Initialize(T* owner) } template<> -void FleeingMovementGenerator::Finalize(Player* owner) +void FleeingMovementGenerator::DoFinalize(Player* owner) { owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); owner->ClearUnitState(UNIT_STATE_FLEEING | UNIT_STATE_FLEEING_MOVE); @@ -121,7 +121,7 @@ void FleeingMovementGenerator::Finalize(Player* owner) } template<> -void FleeingMovementGenerator::Finalize(Creature* owner) +void FleeingMovementGenerator::DoFinalize(Creature* owner) { owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); owner->ClearUnitState(UNIT_STATE_FLEEING|UNIT_STATE_FLEEING_MOVE); @@ -130,13 +130,13 @@ void FleeingMovementGenerator::Finalize(Creature* owner) } template -void FleeingMovementGenerator::Reset(T* owner) +void FleeingMovementGenerator::DoReset(T* owner) { - Initialize(owner); + DoInitialize(owner); } template -bool FleeingMovementGenerator::Update(T* owner, uint32 time_diff) +bool FleeingMovementGenerator::DoUpdate(T* owner, uint32 time_diff) { if (!owner || !owner->isAlive()) return false; @@ -154,16 +154,16 @@ bool FleeingMovementGenerator::Update(T* owner, uint32 time_diff) return true; } -template void FleeingMovementGenerator::Initialize(Player*); -template void FleeingMovementGenerator::Initialize(Creature*); +template void FleeingMovementGenerator::DoInitialize(Player*); +template void FleeingMovementGenerator::DoInitialize(Creature*); template void FleeingMovementGenerator::_getPoint(Player*, float&, float&, float&); template void FleeingMovementGenerator::_getPoint(Creature*, float&, float&, float&); template void FleeingMovementGenerator::_setTargetLocation(Player*); template void FleeingMovementGenerator::_setTargetLocation(Creature*); -template void FleeingMovementGenerator::Reset(Player*); -template void FleeingMovementGenerator::Reset(Creature*); -template bool FleeingMovementGenerator::Update(Player*, uint32); -template bool FleeingMovementGenerator::Update(Creature*, uint32); +template void FleeingMovementGenerator::DoReset(Player*); +template void FleeingMovementGenerator::DoReset(Creature*); +template bool FleeingMovementGenerator::DoUpdate(Player*, uint32); +template bool FleeingMovementGenerator::DoUpdate(Creature*, uint32); void TimedFleeingMovementGenerator::Finalize(Unit* owner) { @@ -198,4 +198,3 @@ bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 time_diff) // This is done instead of casting Unit& to Creature& and call parent method, then we can use Unit directly return MovementGeneratorMedium< Creature, FleeingMovementGenerator >::Update(owner, time_diff); } - diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h index 05c3916ea8a..245c53513f3 100755 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.h @@ -27,10 +27,10 @@ class FleeingMovementGenerator : public MovementGeneratorMedium< T, FleeingMovem public: FleeingMovementGenerator(uint64 fright) : i_frightGUID(fright), i_nextCheckTime(0) {} - void Initialize(T*); - void Finalize(T*); - void Reset(T*); - bool Update(T*, uint32); + void DoInitialize(T*); + void DoFinalize(T*); + void DoReset(T*); + bool DoUpdate(T*, uint32); MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; } @@ -58,4 +58,3 @@ class TimedFleeingMovementGenerator : public FleeingMovementGenerator }; #endif - diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index 78c1f80005c..f52120b6999 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -23,12 +23,12 @@ #include "MoveSplineInit.h" #include "MoveSpline.h" -void HomeMovementGenerator::Initialize(Creature* owner) +void HomeMovementGenerator::DoInitialize(Creature* owner) { _setTargetLocation(owner); } -void HomeMovementGenerator::Finalize(Creature* owner) +void HomeMovementGenerator::DoFinalize(Creature* owner) { if (arrived) { @@ -39,7 +39,7 @@ void HomeMovementGenerator::Finalize(Creature* owner) } } -void HomeMovementGenerator::Reset(Creature*) +void HomeMovementGenerator::DoReset(Creature*) { } @@ -64,7 +64,7 @@ void HomeMovementGenerator::_setTargetLocation(Creature* owner) owner->ClearUnitState(UNIT_STATE_ALL_STATE & ~UNIT_STATE_EVADE); } -bool HomeMovementGenerator::Update(Creature* owner, const uint32 /*time_diff*/) +bool HomeMovementGenerator::DoUpdate(Creature* owner, const uint32 /*time_diff*/) { arrived = owner->movespline->Finalized(); return !arrived; diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h index dfbea60d353..5217f14f75a 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.h @@ -34,10 +34,10 @@ class HomeMovementGenerator : public MovementGeneratorMedium< Creature HomeMovementGenerator() : arrived(false) {} ~HomeMovementGenerator() {} - void Initialize(Creature*); - void Finalize(Creature*); - void Reset(Creature*); - bool Update(Creature*, const uint32); + void DoInitialize(Creature*); + void DoFinalize(Creature*); + void DoReset(Creature*); + bool DoUpdate(Creature*, const uint32); MovementGeneratorType GetMovementGeneratorType() { return HOME_MOTION_TYPE; } private: @@ -45,4 +45,3 @@ class HomeMovementGenerator : public MovementGeneratorMedium< Creature bool arrived; }; #endif - diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp index b33cddc6f6d..080ae1b5b89 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.cpp @@ -103,4 +103,3 @@ void AssistanceDistractMovementGenerator::Finalize(Unit* unit) unit->ClearUnitState(UNIT_STATE_DISTRACTED); unit->ToCreature()->SetReactState(REACT_AGGRESSIVE); } - diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h index 4a2a5e35d22..7be70990b22 100755 --- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h @@ -76,4 +76,3 @@ class AssistanceDistractMovementGenerator : public DistractMovementGenerator }; #endif - diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index 5d70b1aac3a..e7b61e30ea8 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -27,7 +27,7 @@ //----- Point Movement Generator template -void PointMovementGenerator::Initialize(T* unit) +void PointMovementGenerator::DoInitialize(T* unit) { if (!unit->IsStopped()) unit->StopMoving(); @@ -45,7 +45,7 @@ void PointMovementGenerator::Initialize(T* unit) } template -bool PointMovementGenerator::Update(T* unit, uint32 /*diff*/) +bool PointMovementGenerator::DoUpdate(T* unit, uint32 /*diff*/) { if (!unit) return false; @@ -72,7 +72,7 @@ bool PointMovementGenerator::Update(T* unit, uint32 /*diff*/) } template -void PointMovementGenerator::Finalize(T* unit) +void PointMovementGenerator::DoFinalize(T* unit) { if (unit->HasUnitState(UNIT_STATE_CHARGING)) unit->ClearUnitState(UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE); @@ -82,7 +82,7 @@ void PointMovementGenerator::Finalize(T* unit) } template -void PointMovementGenerator::Reset(T* unit) +void PointMovementGenerator::DoReset(T* unit) { if (!unit->IsStopped()) unit->StopMoving(); @@ -101,14 +101,14 @@ template <> void PointMovementGenerator::MovementInform(Creature* unit unit->AI()->MovementInform(POINT_MOTION_TYPE, id); } -template void PointMovementGenerator::Initialize(Player*); -template void PointMovementGenerator::Initialize(Creature*); -template void PointMovementGenerator::Finalize(Player*); -template void PointMovementGenerator::Finalize(Creature*); -template void PointMovementGenerator::Reset(Player*); -template void PointMovementGenerator::Reset(Creature*); -template bool PointMovementGenerator::Update(Player*, uint32); -template bool PointMovementGenerator::Update(Creature*, uint32); +template void PointMovementGenerator::DoInitialize(Player*); +template void PointMovementGenerator::DoInitialize(Creature*); +template void PointMovementGenerator::DoFinalize(Player*); +template void PointMovementGenerator::DoFinalize(Creature*); +template void PointMovementGenerator::DoReset(Player*); +template void PointMovementGenerator::DoReset(Creature*); +template bool PointMovementGenerator::DoUpdate(Player*, uint32); +template bool PointMovementGenerator::DoUpdate(Creature*, uint32); void AssistanceMovementGenerator::Finalize(Unit* unit) { diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h index c26ff94c3a4..592fc7bc517 100644 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h @@ -29,10 +29,10 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG PointMovementGenerator(uint32 _id, float _x, float _y, float _z, bool _generatePath, float _speed = 0.0f) : id(_id), i_x(_x), i_y(_y), i_z(_z), m_generatePath(_generatePath), speed(_speed), i_recalculateSpeed(false) {} - void Initialize(T*); - void Finalize(T*); - void Reset(T*); - bool Update(T*, uint32); + void DoInitialize(T*); + void DoFinalize(T*); + void DoReset(T*); + bool DoUpdate(T*, uint32); void MovementInform(T*); @@ -74,4 +74,3 @@ class EffectMovementGenerator : public MovementGenerator }; #endif - diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index a9d3c404a87..5b8bc6552d3 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -114,7 +114,7 @@ void RandomMovementGenerator::_setRandomLocation(Creature* creature) } template<> -void RandomMovementGenerator::Initialize(Creature* creature) +void RandomMovementGenerator::DoInitialize(Creature* creature) { if (!creature->isAlive()) return; @@ -127,20 +127,20 @@ void RandomMovementGenerator::Initialize(Creature* creature) } template<> -void RandomMovementGenerator::Reset(Creature* creature) +void RandomMovementGenerator::DoReset(Creature* creature) { - Initialize(creature); + DoInitialize(creature); } template<> -void RandomMovementGenerator::Finalize(Creature* creature) +void RandomMovementGenerator::DoFinalize(Creature* creature) { creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); creature->SetWalk(false); } template<> -bool RandomMovementGenerator::Update(Creature* creature, const uint32 diff) +bool RandomMovementGenerator::DoUpdate(Creature* creature, const uint32 diff) { if (creature->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED)) { @@ -159,7 +159,7 @@ bool RandomMovementGenerator::Update(Creature* creature, const uint32 } template<> -bool RandomMovementGenerator::GetResetPosition(Creature* creature, float& x, float& y, float& z) +bool RandomMovementGenerator::GetResetPos(Creature* creature, float& x, float& y, float& z) { float radius; creature->GetRespawnPosition(x, y, z, NULL, &radius); diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h index ca370de6ac3..80379dee632 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.h @@ -28,11 +28,11 @@ class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovemen RandomMovementGenerator(float spawn_dist = 0.0f) : i_nextMoveTime(0), wander_distance(spawn_dist) {} void _setRandomLocation(T*); - void Initialize(T*); - void Finalize(T*); - void Reset(T*); - bool Update(T*, const uint32); - bool GetResetPosition(T*, float& x, float& y, float& z); + void DoInitialize(T*); + void DoFinalize(T*); + void DoReset(T*); + bool DoUpdate(T*, const uint32); + bool GetResetPos(T*, float& x, float& y, float& z); MovementGeneratorType GetMovementGeneratorType() { return RANDOM_MOTION_TYPE; } private: TimeTrackerSmall i_nextMoveTime; @@ -41,4 +41,3 @@ class RandomMovementGenerator : public MovementGeneratorMedium< T, RandomMovemen float wander_distance; }; #endif - diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 88eacccd0aa..46db6b034c4 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -116,7 +116,7 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner, bool upd } template -bool TargetedMovementGeneratorMedium::Update(T* owner, uint32 time_diff) +bool TargetedMovementGeneratorMedium::DoUpdate(T* owner, uint32 time_diff) { if (!i_target.isValid() || !i_target->IsInWorld()) return false; @@ -188,14 +188,14 @@ void ChaseMovementGenerator::_reachTarget(T* owner) } template<> -void ChaseMovementGenerator::Initialize(Player* owner) +void ChaseMovementGenerator::DoInitialize(Player* owner) { owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); _setTargetLocation(owner, true); } template<> -void ChaseMovementGenerator::Initialize(Creature* owner) +void ChaseMovementGenerator::DoInitialize(Creature* owner) { owner->SetWalk(false); owner->AddUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); @@ -203,15 +203,15 @@ void ChaseMovementGenerator::Initialize(Creature* owner) } template -void ChaseMovementGenerator::Finalize(T* owner) +void ChaseMovementGenerator::DoFinalize(T* owner) { owner->ClearUnitState(UNIT_STATE_CHASE | UNIT_STATE_CHASE_MOVE); } template -void ChaseMovementGenerator::Reset(T* owner) +void ChaseMovementGenerator::DoReset(T* owner) { - Initialize(owner); + DoInitialize(owner); } template @@ -259,7 +259,7 @@ void FollowMovementGenerator::_updateSpeed(Creature* u) } template<> -void FollowMovementGenerator::Initialize(Player* owner) +void FollowMovementGenerator::DoInitialize(Player* owner) { owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); _updateSpeed(owner); @@ -267,7 +267,7 @@ void FollowMovementGenerator::Initialize(Player* owner) } template<> -void FollowMovementGenerator::Initialize(Creature* owner) +void FollowMovementGenerator::DoInitialize(Creature* owner) { owner->AddUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); _updateSpeed(owner); @@ -275,14 +275,14 @@ void FollowMovementGenerator::Initialize(Creature* owner) } template -void FollowMovementGenerator::Finalize(T* owner) +void FollowMovementGenerator::DoFinalize(T* owner) { owner->ClearUnitState(UNIT_STATE_FOLLOW | UNIT_STATE_FOLLOW_MOVE); _updateSpeed(owner); } template -void FollowMovementGenerator::Reset(T* owner) +void FollowMovementGenerator::DoReset(T* owner) { Initialize(owner); } @@ -305,21 +305,21 @@ template void TargetedMovementGeneratorMedium >::_setTargetLocation(Player*, bool); template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature*, bool); template void TargetedMovementGeneratorMedium >::_setTargetLocation(Creature*, bool); -template bool TargetedMovementGeneratorMedium >::Update(Player*, uint32); -template bool TargetedMovementGeneratorMedium >::Update(Player*, uint32); -template bool TargetedMovementGeneratorMedium >::Update(Creature*, uint32); -template bool TargetedMovementGeneratorMedium >::Update(Creature*, uint32); +template bool TargetedMovementGeneratorMedium >::DoUpdate(Player*, uint32); +template bool TargetedMovementGeneratorMedium >::DoUpdate(Player*, uint32); +template bool TargetedMovementGeneratorMedium >::DoUpdate(Creature*, uint32); +template bool TargetedMovementGeneratorMedium >::DoUpdate(Creature*, uint32); template void ChaseMovementGenerator::_reachTarget(Player*); template void ChaseMovementGenerator::_reachTarget(Creature*); -template void ChaseMovementGenerator::Finalize(Player*); -template void ChaseMovementGenerator::Finalize(Creature*); -template void ChaseMovementGenerator::Reset(Player*); -template void ChaseMovementGenerator::Reset(Creature*); +template void ChaseMovementGenerator::DoFinalize(Player*); +template void ChaseMovementGenerator::DoFinalize(Creature*); +template void ChaseMovementGenerator::DoReset(Player*); +template void ChaseMovementGenerator::DoReset(Creature*); template void ChaseMovementGenerator::MovementInform(Player*); -template void FollowMovementGenerator::Finalize(Player*); -template void FollowMovementGenerator::Finalize(Creature*); -template void FollowMovementGenerator::Reset(Player*); -template void FollowMovementGenerator::Reset(Creature*); +template void FollowMovementGenerator::DoFinalize(Player*); +template void FollowMovementGenerator::DoFinalize(Creature*); +template void FollowMovementGenerator::DoReset(Player*); +template void FollowMovementGenerator::DoReset(Creature*); template void FollowMovementGenerator::MovementInform(Player*); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 987baa91133..6b47821bbaa 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -47,7 +47,7 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, ~TargetedMovementGeneratorMedium() { delete i_path; } public: - bool Update(T*, uint32); + bool DoUpdate(T*, uint32); Unit* GetTarget() const { return i_target.getTarget(); } void unitSpeedChanged() { i_recalculateTravel = true; } @@ -75,9 +75,9 @@ class ChaseMovementGenerator : public TargetedMovementGeneratorMediumClearUnitState(UNIT_STATE_CHASE_MOVE); } @@ -99,9 +99,9 @@ class FollowMovementGenerator : public TargetedMovementGeneratorMediumClearUnitState(UNIT_STATE_FOLLOW_MOVE); } diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index d3b63ed6331..ffc4afebf2a 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -48,19 +48,19 @@ void WaypointMovementGenerator::LoadPath(Creature* creature) StartMoveNow(creature); } -void WaypointMovementGenerator::Initialize(Creature* creature) +void WaypointMovementGenerator::DoInitialize(Creature* creature) { LoadPath(creature); creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); } -void WaypointMovementGenerator::Finalize(Creature* creature) +void WaypointMovementGenerator::DoFinalize(Creature* creature) { creature->ClearUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); creature->SetWalk(false); } -void WaypointMovementGenerator::Reset(Creature* creature) +void WaypointMovementGenerator::DoReset(Creature* creature) { creature->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); StartMoveNow(creature); @@ -130,7 +130,7 @@ bool WaypointMovementGenerator::StartMove(Creature* creature) return true; } -bool WaypointMovementGenerator::Update(Creature* creature, uint32 diff) +bool WaypointMovementGenerator::DoUpdate(Creature* creature, uint32 diff) { // Waypoint movement can be switched on/off // This is quite handy for escort quests and other stuff @@ -167,7 +167,7 @@ void WaypointMovementGenerator::MovementInform(Creature* creature) creature->AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode); } -bool WaypointMovementGenerator::GetResetPosition(Creature*, float& x, float& y, float& z) +bool WaypointMovementGenerator::GetResetPos(Creature*, float& x, float& y, float& z) { // prevent a crash at empty waypoint path. if (!i_path || i_path->empty()) @@ -196,13 +196,13 @@ uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const return i_path->size(); } -void FlightPathMovementGenerator::Initialize(Player* player) +void FlightPathMovementGenerator::DoInitialize(Player* player) { Reset(player); InitEndGridInfo(); } -void FlightPathMovementGenerator::Finalize(Player* player) +void FlightPathMovementGenerator::DoFinalize(Player* player) { // remove flag to prevent send object build movement packets for flight state and crash (movement generator already not at top of stack) player->ClearUnitState(UNIT_STATE_IN_FLIGHT); @@ -222,7 +222,7 @@ void FlightPathMovementGenerator::Finalize(Player* player) #define PLAYER_FLIGHT_SPEED 32.0f -void FlightPathMovementGenerator::Reset(Player* player) +void FlightPathMovementGenerator::DoReset(Player* player) { player->getHostileRefManager().setOnlineOfflineState(false); player->AddUnitState(UNIT_STATE_IN_FLIGHT); @@ -241,7 +241,7 @@ void FlightPathMovementGenerator::Reset(Player* player) init.Launch(); } -bool FlightPathMovementGenerator::Update(Player* player, uint32 /*diff*/) +bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/) { uint32 pointId = (uint32)player->movespline->currentPathIdx(); if (pointId > i_currentNode) @@ -288,7 +288,7 @@ void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry } } -bool FlightPathMovementGenerator::GetResetPosition(Player*, float& x, float& y, float& z) +bool FlightPathMovementGenerator::GetResetPos(Player*, float& x, float& y, float& z) { const TaxiPathNodeEntry& node = (*i_path)[i_currentNode]; x = node.x; y = node.y; z = node.z; diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index bf3f6f4cae3..5f468ffc3a4 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -65,10 +65,10 @@ class WaypointMovementGenerator : public MovementGeneratorMedium< Crea WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) : i_nextMoveTime(0), m_isArrivalDone(false), path_id(_path_id), repeating(_repeating) {} ~WaypointMovementGenerator() { i_path = NULL; } - void Initialize(Creature*); - void Finalize(Creature*); - void Reset(Creature*); - bool Update(Creature*, uint32 diff); + void DoInitialize(Creature*); + void DoFinalize(Creature*); + void DoReset(Creature*); + bool DoUpdate(Creature*, uint32 diff); void MovementInform(Creature*); @@ -77,7 +77,7 @@ class WaypointMovementGenerator : public MovementGeneratorMedium< Crea // now path movement implmementation void LoadPath(Creature*); - bool GetResetPosition(Creature*, float& x, float& y, float& z); + bool GetResetPos(Creature*, float& x, float& y, float& z); private: @@ -118,10 +118,10 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig i_path = &pathnodes; i_currentNode = startNode; } - void Initialize(Player*); - void Reset(Player*); - void Finalize(Player*); - bool Update(Player*, uint32); + void DoInitialize(Player*); + void DoReset(Player*); + void DoFinalize(Player*); + bool DoUpdate(Player*, uint32); MovementGeneratorType GetMovementGeneratorType() { return FLIGHT_MOTION_TYPE; } TaxiPathNodeList const& GetPath() { return *i_path; } @@ -131,7 +131,7 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig void SkipCurrentNode() { ++i_currentNode; } void DoEventIfAny(Player* player, TaxiPathNodeEntry const& node, bool departure); - bool GetResetPosition(Player*, float& x, float& y, float& z); + bool GetResetPos(Player*, float& x, float& y, float& z); void InitEndGridInfo(); void PreloadEndGrid(); @@ -143,4 +143,3 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig uint32 _preloadTargetNode; //! node index where preloading starts }; #endif - diff --git a/src/server/game/Movement/Waypoints/Path.h b/src/server/game/Movement/Waypoints/Path.h index 038958593fb..f86b62c8be8 100644 --- a/src/server/game/Movement/Waypoints/Path.h +++ b/src/server/game/Movement/Waypoints/Path.h @@ -98,4 +98,3 @@ class Path typedef Path SimplePath; #endif - diff --git a/src/server/game/Movement/Waypoints/WaypointManager.h b/src/server/game/Movement/Waypoints/WaypointManager.h index df20c513c90..3417b44ef09 100644 --- a/src/server/game/Movement/Waypoints/WaypointManager.h +++ b/src/server/game/Movement/Waypoints/WaypointManager.h @@ -68,4 +68,3 @@ class WaypointMgr #define sWaypointMgr ACE_Singleton::instance() #endif - -- cgit v1.2.3 From 05efdaf39349f057eabf58252532dff76511e7ef Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Wed, 2 Jan 2013 13:58:36 +0100 Subject: Core: Fix non pch build --- src/server/shared/Memory.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/server/shared/Memory.h b/src/server/shared/Memory.h index ac697f7a1af..25533638915 100644 --- a/src/server/shared/Memory.h +++ b/src/server/shared/Memory.h @@ -3,6 +3,8 @@ #ifndef _MEMORY_H #define _MEMORY_H +#include "DetourAlloc.h" + // memory management inline void* dtCustomAlloc(int size, dtAllocHint /*hint*/) { -- cgit v1.2.3 From 20ab789fe76b2b4e6c7dce006024aaba1b2a548b Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Tue, 8 Jan 2013 16:26:45 +0100 Subject: Core: Fix build with Debian 7.0 Closes #8882 --- .../game/Movement/MovementGenerators/TargetedMovementGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 9d60fa11a2f..d03edeb9bab 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -284,7 +284,7 @@ void FollowMovementGenerator::DoFinalize(T* owner) template void FollowMovementGenerator::DoReset(T* owner) { - Initialize(owner); + DoInitialize(owner); } template -- cgit v1.2.3 From 5f15600e7a26170f0aacc77e9417df61db45a992 Mon Sep 17 00:00:00 2001 From: Spp Date: Wed, 9 Jan 2013 13:13:39 +0100 Subject: Core/Build: Fix linking and sooo many compile warnings --- src/server/collision/Management/MMapManager.cpp | 14 +- src/server/collision/Models/ModelInstance.h | 2 +- src/tools/map_extractor/adt.cpp | 21 +- src/tools/map_extractor/loadlib.cpp | 4 +- src/tools/map_extractor/loadlib/loadlib.h | 6 + src/tools/map_extractor/wdt.cpp | 12 +- src/tools/mesh_extractor/ADT.cpp | 4 +- src/tools/mesh_extractor/CMakeLists.txt | 3 +- src/tools/mesh_extractor/Cache.h | 4 +- src/tools/mesh_extractor/Chunk.cpp | 10 +- src/tools/mesh_extractor/ChunkedData.cpp | 3 +- src/tools/mesh_extractor/ContinentBuilder.cpp | 4 +- src/tools/mesh_extractor/ContinentBuilder.h | 8 +- src/tools/mesh_extractor/DBC.cpp | 22 +- src/tools/mesh_extractor/DoodadHandler.cpp | 6 +- src/tools/mesh_extractor/DoodadHandler.h | 14 +- src/tools/mesh_extractor/LiquidHandler.cpp | 10 +- src/tools/mesh_extractor/MapChunk.cpp | 3 +- src/tools/mesh_extractor/MeshExtractor.cpp | 36 ++- src/tools/mesh_extractor/Model.cpp | 9 +- src/tools/mesh_extractor/TileBuilder.cpp | 5 +- src/tools/mesh_extractor/Utils.cpp | 354 ++++++++++++++---------- src/tools/mesh_extractor/Utils.h | 4 +- src/tools/mesh_extractor/WDT.cpp | 11 +- src/tools/mesh_extractor/WorldModelGroup.cpp | 22 +- src/tools/mesh_extractor/WorldModelHandler.cpp | 20 +- src/tools/mmaps_generator/CMakeLists.txt | 2 +- src/tools/mmaps_generator/IntermediateValues.h | 2 +- src/tools/mmaps_generator/MapBuilder.cpp | 45 +-- src/tools/mmaps_generator/PathCommon.h | 2 +- src/tools/mmaps_generator/TerrainBuilder.cpp | 92 +++--- src/tools/mmaps_generator/TerrainBuilder.h | 1 - src/tools/mmaps_generator/VMapExtensions.cpp | 2 +- src/tools/vmap4_extractor/adtfile.cpp | 3 +- src/tools/vmap4_extractor/model.cpp | 4 +- src/tools/vmap4_extractor/vmapexport.cpp | 3 +- src/tools/vmap4_extractor/wmo.cpp | 4 +- 37 files changed, 468 insertions(+), 303 deletions(-) (limited to 'src') diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp index c7dea358d92..1b6cf5c0260 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/server/collision/Management/MMapManager.cpp @@ -52,8 +52,14 @@ namespace MMAP } dtNavMeshParams params; - fread(¶ms, sizeof(dtNavMeshParams), 1, file); + int count = fread(¶ms, sizeof(dtNavMeshParams), 1, file); fclose(file); + if (count != 1) + { + sLog->outDebug(LOG_FILTER_MAPS, "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName); + delete [] fileName; + return false; + } dtNavMesh* mesh = dtAllocNavMesh(); ASSERT(mesh); @@ -82,7 +88,7 @@ namespace MMAP return uint32(x << 16 | y); } - bool MMapManager::loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y) + bool MMapManager::loadMap(const std::string& /*basePath*/, uint32 mapId, int32 x, int32 y) { // make sure the mmap is loaded and ready to load tiles if (!loadMapData(mapId)) @@ -114,9 +120,7 @@ namespace MMAP // read header MmapTileHeader fileHeader; - fread(&fileHeader, sizeof(MmapTileHeader), 1, file); - - if (fileHeader.mmapMagic != MMAP_MAGIC) + if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC) { sLog->outError(LOG_FILTER_MAPS, "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y); return false; diff --git a/src/server/collision/Models/ModelInstance.h b/src/server/collision/Models/ModelInstance.h index 6d1b7c68bd5..f26089bb46c 100644 --- a/src/server/collision/Models/ModelInstance.h +++ b/src/server/collision/Models/ModelInstance.h @@ -75,7 +75,7 @@ namespace VMAP float iInvScale; WorldModel* iModel; public: - WorldModel* const getWorldModel(); + WorldModel* getWorldModel(); }; } // namespace VMAP diff --git a/src/tools/map_extractor/adt.cpp b/src/tools/map_extractor/adt.cpp index fde70681113..505813c4bd0 100644 --- a/src/tools/map_extractor/adt.cpp +++ b/src/tools/map_extractor/adt.cpp @@ -6,6 +6,13 @@ int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; +u_map_fcc MHDRMagic = { {'M','H','D','R'} }; +u_map_fcc MCINMagic = { {'M','C','I','N'} }; +u_map_fcc MH20Magic = { {'M','H','2','0'} }; +u_map_fcc MCNKMagic = { {'M','C','N','K'} }; +u_map_fcc MCVTMagic = { {'M','C','V','T'} }; +u_map_fcc MCLQMagic = { {'M','C','L','Q'} }; + bool isHole(int holes, int i, int j) { int testi = i / 2; @@ -53,7 +60,7 @@ bool ADT_file::prepareLoadedData() bool adt_MHDR::prepareLoadedData() { - if (fcc != 'MHDR') + if (fcc != MHDRMagic.fcc) return false; if (size!=sizeof(adt_MHDR)-8) @@ -72,7 +79,7 @@ bool adt_MHDR::prepareLoadedData() bool adt_MCIN::prepareLoadedData() { - if (fcc != 'MCIN') + if (fcc != MCINMagic.fcc) return false; // Check cells data @@ -86,7 +93,7 @@ bool adt_MCIN::prepareLoadedData() bool adt_MH2O::prepareLoadedData() { - if (fcc != 'MH2O') + if (fcc != MH20Magic.fcc) return false; // Check liquid data @@ -98,7 +105,7 @@ bool adt_MH2O::prepareLoadedData() bool adt_MCNK::prepareLoadedData() { - if (fcc != 'MCNK') + if (fcc != MCNKMagic.fcc) return false; // Check height map @@ -113,7 +120,7 @@ bool adt_MCNK::prepareLoadedData() bool adt_MCVT::prepareLoadedData() { - if (fcc != 'MCVT') + if (fcc != MCVTMagic.fcc) return false; if (size != sizeof(adt_MCVT)-8) @@ -124,8 +131,8 @@ bool adt_MCVT::prepareLoadedData() bool adt_MCLQ::prepareLoadedData() { - if (fcc != 'MCLQ') + if (fcc != MCLQMagic.fcc) return false; return true; -} \ No newline at end of file +} diff --git a/src/tools/map_extractor/loadlib.cpp b/src/tools/map_extractor/loadlib.cpp index 465eb04083f..d1ea40110de 100644 --- a/src/tools/map_extractor/loadlib.cpp +++ b/src/tools/map_extractor/loadlib.cpp @@ -6,6 +6,8 @@ class MPQFile; +u_map_fcc MverMagic = { {'M','V','E','R'} }; + FileLoader::FileLoader() { data = 0; @@ -49,7 +51,7 @@ bool FileLoader::prepareLoadedData() { // Check version version = (file_MVER *) data; - if (version->fcc != 'MVER') + if (version->fcc != MverMagic.fcc) return false; if (version->ver != FILE_FORMAT_VERSION) return false; diff --git a/src/tools/map_extractor/loadlib/loadlib.h b/src/tools/map_extractor/loadlib/loadlib.h index bf6c0706d46..f32f46c63b9 100644 --- a/src/tools/map_extractor/loadlib/loadlib.h +++ b/src/tools/map_extractor/loadlib/loadlib.h @@ -29,6 +29,12 @@ typedef uint8_t uint8; #define FILE_FORMAT_VERSION 18 +union u_map_fcc +{ + char fcc_txt[4]; + uint32 fcc; +}; + // // File version chunk // diff --git a/src/tools/map_extractor/wdt.cpp b/src/tools/map_extractor/wdt.cpp index dedefbb64e5..90a07eafab3 100644 --- a/src/tools/map_extractor/wdt.cpp +++ b/src/tools/map_extractor/wdt.cpp @@ -2,23 +2,27 @@ #include "wdt.h" +u_map_fcc MWMOMagic = { {'M', 'W', 'M', 'O'} }; +u_map_fcc MPHDMagic = { {'M', 'P', 'H', 'D'} }; +u_map_fcc MAINMagic = { {'M', 'A', 'I', 'N'} }; + bool wdt_MWMO::prepareLoadedData() { - if (fcc != 'MWMO') + if (fcc != MWMOMagic.fcc) return false; return true; } bool wdt_MPHD::prepareLoadedData() { - if (fcc != 'MPHD') + if (fcc != MPHDMagic.fcc) return false; return true; } bool wdt_MAIN::prepareLoadedData() { - if (fcc != 'MAIN') + if (fcc != MAINMagic.fcc) return false; return true; } @@ -59,4 +63,4 @@ bool WDT_file::prepareLoadedData() if (!wmo->prepareLoadedData()) return false; return true; -} \ No newline at end of file +} diff --git a/src/tools/mesh_extractor/ADT.cpp b/src/tools/mesh_extractor/ADT.cpp index 8d7dce9ae11..c2ac19d5be0 100644 --- a/src/tools/mesh_extractor/ADT.cpp +++ b/src/tools/mesh_extractor/ADT.cpp @@ -3,7 +3,8 @@ #include "LiquidHandler.h" #include "WorldModelHandler.h" -ADT::ADT( std::string file ) : ObjectData(NULL), Data(NULL), _DoodadHandler(NULL), _WorldModelHandler(NULL), _LiquidHandler(NULL), HasObjectData(false) +ADT::ADT( std::string file ) : ObjectData(NULL), Data(NULL), HasObjectData(false), + _DoodadHandler(NULL), _WorldModelHandler(NULL), _LiquidHandler(NULL) { Data = new ChunkedData(file); ObjectData = new ChunkedData(Utils::Replace(file, ".adt", "_obj0.adt")); @@ -31,7 +32,6 @@ void ADT::Read() { Header.Read(Data->GetChunkByName("MHDR")->GetStream()); MapChunks.reserve(16 * 16); - int mapChunkIndex = 0; for (std::vector::iterator itr = Data->Chunks.begin(); itr != Data->Chunks.end(); ++itr) if ((*itr)->Name == "MCNK") diff --git a/src/tools/mesh_extractor/CMakeLists.txt b/src/tools/mesh_extractor/CMakeLists.txt index 8ef48a90742..29c571d9301 100644 --- a/src/tools/mesh_extractor/CMakeLists.txt +++ b/src/tools/mesh_extractor/CMakeLists.txt @@ -26,6 +26,7 @@ if( UNIX ) ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour ${CMAKE_SOURCE_DIR}/dep/libmpq ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${ACE_INCLUDE_DIR} ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} @@ -77,4 +78,4 @@ if( UNIX ) install(TARGETS MeshExtractor DESTINATION bin) elseif( WIN32 ) install(TARGETS MeshExtractor DESTINATION "${CMAKE_INSTALL_PREFIX}") -endif() \ No newline at end of file +endif() diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h index 90e2c138376..34293b14b54 100644 --- a/src/tools/mesh_extractor/Cache.h +++ b/src/tools/mesh_extractor/Cache.h @@ -14,7 +14,7 @@ class GenericCache public: GenericCache() {} - static const int32 FlushLimit = 1000; + static const uint32 FlushLimit = 1000; void Insert(K key, T* val) { @@ -59,4 +59,4 @@ public: }; extern CacheClass* Cache; -#endif \ No newline at end of file +#endif diff --git a/src/tools/mesh_extractor/Chunk.cpp b/src/tools/mesh_extractor/Chunk.cpp index 2f521f1badd..9f2898a46e0 100644 --- a/src/tools/mesh_extractor/Chunk.cpp +++ b/src/tools/mesh_extractor/Chunk.cpp @@ -12,12 +12,12 @@ int32 Chunk::FindSubChunkOffset(std::string name) uint32 matched = 0; while (uint32(ftell(stream)) < Utils::Size(stream)) { - char b; - fread(&b, sizeof(char), 1, stream); - if (b == name[matched]) - ++matched; - else + char b = 0; + if (fread(&b, sizeof(char), 1, stream) != 1 || b != name[matched]) matched = 0; + else + ++matched; + if (matched == 4) return ftell(stream) - 4; } diff --git a/src/tools/mesh_extractor/ChunkedData.cpp b/src/tools/mesh_extractor/ChunkedData.cpp index 4d609d8f6b2..e0db12a6be7 100644 --- a/src/tools/mesh_extractor/ChunkedData.cpp +++ b/src/tools/mesh_extractor/ChunkedData.cpp @@ -36,7 +36,8 @@ void ChunkedData::Load( uint32 maxLength, uint32 chunksHint ) // Utils::Reverse(nameBytes); name = std::string(name.rbegin(), name.rend()); uint32 length; - fread(&length, sizeof(uint32), 1, Stream); + if (fread(&length, sizeof(uint32), 1, Stream) != 1) + continue; calcOffset += 8; Chunks.push_back(new Chunk(name.c_str(), length, calcOffset + baseOffset, Stream)); calcOffset += length; diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index 013c0ff256a..9b5c9f9c77b 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -16,7 +16,7 @@ private: dtNavMeshParams Params; ContinentBuilder* cBuilder; public: - BuilderThread(ContinentBuilder* _cBuilder, bool deb, dtNavMeshParams& params) : Free(true), debug(deb), Params(params), cBuilder(_cBuilder) {} + BuilderThread(ContinentBuilder* _cBuilder, bool deb, dtNavMeshParams& params) : debug(deb), Params(params), cBuilder(_cBuilder), Free(true) {} void SetData(int x, int y, int map, std::string cont) { X = x; Y = y; MapId = map; Continent = cont; } int svc() @@ -113,7 +113,7 @@ void ContinentBuilder::Build(bool debug) std::vector Threads; for (uint32 i = 0; i < NumberOfThreads; ++i) Threads.push_back(new BuilderThread(this, debug, params)); - printf("Map %s ( %i ) has %i tiles. Building them with %i threads\n", Continent.c_str(), MapId, TileMap->TileTable.size(), NumberOfThreads); + printf("Map %s ( %i ) has %u tiles. Building them with %i threads\n", Continent.c_str(), MapId, uint32(TileMap->TileTable.size()), NumberOfThreads); for (std::vector::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr) { bool next = false; diff --git a/src/tools/mesh_extractor/ContinentBuilder.h b/src/tools/mesh_extractor/ContinentBuilder.h index 4c16fa0727e..3d7b879879e 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.h +++ b/src/tools/mesh_extractor/ContinentBuilder.h @@ -7,7 +7,11 @@ class ContinentBuilder { public: - ContinentBuilder(std::string continent, uint32 mapId, WDT* wdt, uint32 tn) : MapId(mapId), Continent(continent), TileMap(wdt), NumberOfThreads(tn), tileXMin(64), tileYMin(64), tileXMax(0), tileYMax(0) {} + ContinentBuilder(std::string continent, uint32 mapId, WDT* wdt, uint32 tn) : + Continent(continent), TileMap(wdt), MapId(mapId), + NumberOfThreads(tn), tileXMin(64), tileYMin(64), tileXMax(0), tileYMax(0) + {} + void Build(bool debug); void getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax); void CalculateTileBounds(); @@ -23,4 +27,4 @@ private: int tileXMax; int tileYMax; }; -#endif \ No newline at end of file +#endif diff --git a/src/tools/mesh_extractor/DBC.cpp b/src/tools/mesh_extractor/DBC.cpp index c50e02014da..5c54d975487 100644 --- a/src/tools/mesh_extractor/DBC.cpp +++ b/src/tools/mesh_extractor/DBC.cpp @@ -2,16 +2,19 @@ #include "DBC.h" #include "Common.h" -DBC::DBC( FILE* stream ) : StringBlock(NULL), IsFaulty(true), StringBlockSize(0) +DBC::DBC( FILE* stream ) : StringBlock(NULL), StringBlockSize(0), IsFaulty(true) { char magic[5]; - fread(&magic, sizeof(char), 4, stream); + uint count = 0; + count += fread(&magic, sizeof(char), 4, stream); magic[4] = '\0'; - fread(&RecordCount, sizeof(uint32), 1, stream); + count += fread(&RecordCount, sizeof(uint32), 1, stream); Records.reserve(RecordCount); - fread(&Fields, sizeof(uint32), 1, stream); - fread(&RecordSize, sizeof(uint32), 1, stream); - fread(&StringBlockSize, sizeof(uint32), 1, stream); + count += fread(&Fields, sizeof(uint32), 1, stream); + count += fread(&RecordSize, sizeof(uint32), 1, stream); + count += fread(&StringBlockSize, sizeof(uint32), 1, stream); + if (count != 8) + printf("DBC::DBC: Failed to read some data expected 8, read %u\n", count); for (int i = 0; i < RecordCount; i++) { @@ -26,13 +29,16 @@ DBC::DBC( FILE* stream ) : StringBlock(NULL), IsFaulty(true), StringBlockSize(0) break; } uint32 tmp; - fread(&tmp, sizeof(uint32), 1, stream); + if (fread(&tmp, sizeof(uint32), 1, stream) != 1) + printf("DBC::DBC: Failed to read some data expected 1, read 0\n"); rec->Values.push_back(tmp); size += 4; } } StringBlock = new uint8[StringBlockSize]; - fread(StringBlock, sizeof(uint8), StringBlockSize, stream); + count = fread(StringBlock, sizeof(uint8), StringBlockSize, stream); + if (count != StringBlockSize) + printf("DBC::DBC: Failed to read some data expected %u, read %u\n", StringBlockSize, count); } std::string DBC::GetStringByOffset( int offset ) diff --git a/src/tools/mesh_extractor/DoodadHandler.cpp b/src/tools/mesh_extractor/DoodadHandler.cpp index 4e8028b3dff..56c2a7986f8 100644 --- a/src/tools/mesh_extractor/DoodadHandler.cpp +++ b/src/tools/mesh_extractor/DoodadHandler.cpp @@ -30,7 +30,8 @@ void DoodadHandler::ProcessInternal( ChunkedData* subChunks ) for (uint32 i = 0; i < refCount; i++) { int32 index; - fread(&index, sizeof(int32), 1, stream); + if (int count = fread(&index, sizeof(int32), 1, stream) != 1) + printf("DoodadHandler::ProcessInternal: Failed to read some data expected 1, read %d\n", count); if (index < 0 || uint32(index) >= _definitions->size()) continue; DoodadDefinition doodad = (*_definitions)[index]; @@ -81,7 +82,8 @@ void DoodadHandler::ReadDoodadPaths( Chunk* id, Chunk* data ) FILE* idStream = id->GetStream(); fseek(idStream, i * 4, SEEK_CUR); uint32 offset; - fread(&offset, sizeof(uint32), 1, idStream); + if (fread(&offset, sizeof(uint32), 1, idStream) != 1) + printf("DoodadHandler::ReadDoodadPaths: Failed to read some data expected 1, read 0\n"); FILE* dataStream = data->GetStream(); fseek(dataStream, offset + data->Offset, SEEK_SET); _paths->push_back(Utils::ReadString(dataStream)); diff --git a/src/tools/mesh_extractor/DoodadHandler.h b/src/tools/mesh_extractor/DoodadHandler.h index a212b032d1d..981834ec7ac 100644 --- a/src/tools/mesh_extractor/DoodadHandler.h +++ b/src/tools/mesh_extractor/DoodadHandler.h @@ -19,12 +19,16 @@ public: void Read(FILE* stream) { - fread(&MmidIndex, sizeof(uint32), 1, stream); - fread(&UniqueId, sizeof(uint32), 1, stream); + int count = 0; + + count += fread(&MmidIndex, sizeof(uint32), 1, stream); + count += fread(&UniqueId, sizeof(uint32), 1, stream); Position = Vector3::Read(stream); Rotation = Vector3::Read(stream); - fread(&DecimalScale, sizeof(uint16), 1, stream); - fread(&Flags, sizeof(uint16), 1, stream); + count += fread(&DecimalScale, sizeof(uint16), 1, stream); + count += fread(&Flags, sizeof(uint16), 1, stream); + if (count != 4) + printf("DoodadDefinition::Read: Failed to read some data expected 4, read %d\n", count); } }; @@ -50,4 +54,4 @@ private: std::vector* _definitions; std::vector* _paths; }; -#endif \ No newline at end of file +#endif diff --git a/src/tools/mesh_extractor/LiquidHandler.cpp b/src/tools/mesh_extractor/LiquidHandler.cpp index 7844130ab34..285ea1a5b74 100644 --- a/src/tools/mesh_extractor/LiquidHandler.cpp +++ b/src/tools/mesh_extractor/LiquidHandler.cpp @@ -50,17 +50,17 @@ void LiquidHandler::HandleNewLiquid() fseek(stream, chunk->Offset + information.OffsetMask2, SEEK_SET); uint32 size = ceil(information.Width * information.Height / 8.0f); uint8* altMask = new uint8[size]; - fread(altMask, sizeof(uint8), size, stream); - - for (uint32 mi = 0; mi < size; mi++) - renderMask.Mask[mi + information.OffsetY] |= altMask[mi]; + if (fread(altMask, sizeof(uint8), size, stream) == size) + for (uint32 mi = 0; mi < size; mi++) + renderMask.Mask[mi + information.OffsetY] |= altMask[mi]; delete[] altMask; } fseek(stream, chunk->Offset + information.OffsetHeightmap, SEEK_SET); for (int y = information.OffsetY; y < (information.OffsetY + information.Height); y++) for (int x = information.OffsetX; x < (information.OffsetX + information.Width); x++) - fread(&heights[x][y], sizeof(float), 1, stream); + if (fread(&heights[x][y], sizeof(float), 1, stream) != 1) + return; } else { diff --git a/src/tools/mesh_extractor/MapChunk.cpp b/src/tools/mesh_extractor/MapChunk.cpp index 67f4061035e..8fe40773d43 100644 --- a/src/tools/mesh_extractor/MapChunk.cpp +++ b/src/tools/mesh_extractor/MapChunk.cpp @@ -58,7 +58,8 @@ void MapChunk::GenerateVertices( FILE* stream ) for (int i = 0; i < values; i++) { float tmp; - fread(&tmp, sizeof(float), 1, stream); + if (fread(&tmp, sizeof(float), 1, stream) != 1) + printf("MapChunk::GenerateVertices: Failed to read some data expected 1, read 0\n"); Vector3 vert(Header.Position.x - (j * (Constants::UnitSize * 0.5f)), Header.Position.y - (i * Constants::UnitSize), Header.Position.z + tmp); if (values == 8) vert.y -= Constants::UnitSize * 0.5f; diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index 7379ba87117..b164ff5861d 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -59,7 +59,7 @@ void ExtractDBCs() { printf("Extracting DBCs for locale %s\n", MPQManager::Languages[*itr]); std::string path = baseDBCPath; - if (*itr != MPQHandler->BaseLocale) + if (*itr != uint32(MPQHandler->BaseLocale)) { path += std::string(MPQManager::Languages[*itr]) + "/"; Utils::CreateDir(path); @@ -198,7 +198,6 @@ void ExtractGameobjectModels() fwrite(&model.Header.CountGroups, sizeof(uint32), 1, output); fwrite(&model.Header.WmoId, sizeof(uint32), 1, output); - uint32 i = 0; for (std::vector::iterator itr2 = model.Groups.begin(); itr2 != model.Groups.end(); ++itr2) { fwrite(&itr2->Header.Flags, sizeof(uint32), 1, output); @@ -261,7 +260,7 @@ bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapLis for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) mapList.insert(atoi(*itr)); - printf("Extracting only provided list of maps (%u).\n", mapList.size()); + printf("Extracting only provided list of maps (%u).\n", uint32(mapList.size())); } else if (strcmp(argv[i], "--debug") == 0) { @@ -314,18 +313,27 @@ void LoadTile(dtNavMesh*& navMesh, const char* tile) { FILE* f = fopen(tile, "rb"); MmapTileHeader header; - fread(&header, sizeof(MmapTileHeader), 1, f); + + if (fread(&header, sizeof(MmapTileHeader), 1, f) != 1) + return; + uint8* nav = new uint8[header.size]; - fread(nav, header.size, 1, f); + if (fread(nav, header.size, 1, f) != 1) + return; - dtStatus res = navMesh->addTile(nav, header.size, DT_TILE_FREE_DATA, 0, NULL); + navMesh->addTile(nav, header.size, DT_TILE_FREE_DATA, 0, NULL); fclose(f); } int main(int argc, char* argv[]) { - system("pause"); + if (!system("pause")) + { + printf("main: Error in system call to pause\n"); + return -1; + } + uint32 threads = 4, extractFlags = 0; std::set mapIds; bool debug = false; @@ -383,8 +391,13 @@ int main(int argc, char* argv[]) FILE* mmap = fopen(".mmap", "rb"); dtNavMeshParams params; - fread(¶ms, sizeof(dtNavMeshParams), 1, mmap); + int count = fread(¶ms, sizeof(dtNavMeshParams), 1, mmap); fclose(mmap); + if (count != 1) + { + printf("main: Error reading from .mmap\n"); + return 0; + } dtNavMesh* navMesh = new dtNavMesh(); dtNavMeshQuery* navMeshQuery = new dtNavMeshQuery(); @@ -401,10 +414,9 @@ int main(int argc, char* argv[]) float nearestPt[3]; - dtStatus status = navMeshQuery->findNearestPoly(m_spos, m_polyPickExt, &m_filter, &m_startRef, nearestPt); - status = navMeshQuery->findNearestPoly(m_epos, m_polyPickExt, &m_filter, &m_endRef, nearestPt); + navMeshQuery->findNearestPoly(m_spos, m_polyPickExt, &m_filter, &m_startRef, nearestPt); + navMeshQuery->findNearestPoly(m_epos, m_polyPickExt, &m_filter, &m_endRef, nearestPt); - // if ( !m_startRef || !m_endRef ) { std::cerr << "Could not find any nearby poly's (" << m_startRef << "," << m_endRef << ")" << std::endl; @@ -415,4 +427,4 @@ int main(int argc, char* argv[]) } return 0; -} \ No newline at end of file +} diff --git a/src/tools/mesh_extractor/Model.cpp b/src/tools/mesh_extractor/Model.cpp index 10fde0ebc2d..77b1adbeaa0 100644 --- a/src/tools/mesh_extractor/Model.cpp +++ b/src/tools/mesh_extractor/Model.cpp @@ -47,9 +47,12 @@ void Model::ReadBoundingTriangles( FILE* stream ) { Triangle tri; tri.Type = Constants::TRIANGLE_TYPE_DOODAD; - fread(&tri.V0, sizeof(uint16), 1, stream); - fread(&tri.V1, sizeof(uint16), 1, stream); - fread(&tri.V2, sizeof(uint16), 1, stream); + int count = 0; + count += fread(&tri.V0, sizeof(uint16), 1, stream); + count += fread(&tri.V1, sizeof(uint16), 1, stream); + count += fread(&tri.V2, sizeof(uint16), 1, stream); + if (count != 3) + printf("Model::ReadBoundingTriangles: Error reading data, expected 3, read %d\n", count); Triangles.push_back(tri); } } diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 2a02bc50cd4..4a14cbbd51d 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -12,7 +12,8 @@ #include "ace/Synch.h" -TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, int y, uint32 mapId) : _Geometry(NULL), World(world), X(x), Y(y), MapId(mapId), DataSize(0), cBuilder(_cBuilder) +TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, int y, uint32 mapId) : + World(world), X(x), Y(y), MapId(mapId), _Geometry(NULL), DataSize(0), cBuilder(_cBuilder) { /* Test, non-working values @@ -62,7 +63,7 @@ TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, Context = new rcContext; } -void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax, dtNavMeshParams& navMeshParams ) +void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax, dtNavMeshParams& /*navMeshParams*/ ) { bmin = new float[3]; bmax = new float[3]; diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index 3639cb88acf..119ac94f94f 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -53,8 +53,7 @@ std::string Utils::ReadString( FILE* file ) while (true) { char b; - fread(&b, sizeof(char), 1, file); - if (b == 0) + if (fread(&b, sizeof(char), 1, file) != 1 || b == 0) break; ret[i++] = b; } @@ -155,7 +154,7 @@ Vector3 Utils::VectorTransform( Vector3 vec, G3D::Matrix4 matrix ) std::string Utils::GetPathBase( std::string path ) { - int lastIndex = path.find_last_of("."); + size_t lastIndex = path.find_last_of("."); if (lastIndex != std::string::npos) return path.substr(0, lastIndex); return path; @@ -164,11 +163,12 @@ std::string Utils::GetPathBase( std::string path ) Vector3 Vector3::Read( FILE* file ) { Vector3 ret; - fread(&ret, sizeof(Vector3), 1, file); + if (fread(&ret, sizeof(Vector3), 1, file) != 1) + printf("Vector3::Read: Failed to read some data expected 1, read 0\n"); return ret; } -Vector3 Utils::GetLiquidVert(G3D::Matrix4 transformation, Vector3 basePosition, float height, int x, int y) +Vector3 Utils::GetLiquidVert(G3D::Matrix4 transformation, Vector3 basePosition, float height, int /*x*/, int /*y*/) { if (Utils::Distance(height, 0.0f) > 0.5f) basePosition.z = 0.0f; @@ -208,14 +208,18 @@ void Utils::SaveToDisk( FILE* stream, std::string path ) FILE* disk = fopen(path.c_str(), "wb"); if (!disk) { - printf("Could not save file %s to disk, please verify that you have write permissions on that directory\n", path.c_str()); + printf("SaveToDisk: Could not save file %s to disk, please verify that you have write permissions on that directory\n", path.c_str()); return; } uint32 size = Utils::Size(stream); uint8* data = new uint8[size]; // Read the data to an array - fread(data, 1, size, stream); + if (fread(data, 1, size, stream) != 1) + { + printf("SaveToDisk: Error reading from Stream while trying to save file %s to disck.\n", path.c_str()); + return; + } // And write it in the file fwrite(data, 1, size, disk); @@ -242,136 +246,164 @@ std::string Utils::GetExtension( std::string path ) void MapChunkHeader::Read(FILE* stream) { - fread(&Flags, sizeof(uint32), 1, stream); - fread(&IndexX, sizeof(uint32), 1, stream); - fread(&IndexY, sizeof(uint32), 1, stream); - fread(&Layers, sizeof(uint32), 1, stream); - fread(&DoodadRefs, sizeof(uint32), 1, stream); - fread(&OffsetMCVT, sizeof(uint32), 1, stream); - fread(&OffsetMCNR, sizeof(uint32), 1, stream); - fread(&OffsetMCLY, sizeof(uint32), 1, stream); - fread(&OffsetMCRF, sizeof(uint32), 1, stream); - fread(&OffsetMCAL, sizeof(uint32), 1, stream); - fread(&SizeMCAL, sizeof(uint32), 1, stream); - fread(&OffsetMCSH, sizeof(uint32), 1, stream); - fread(&SizeMCSH, sizeof(uint32), 1, stream); - fread(&AreaId, sizeof(uint32), 1, stream); - fread(&MapObjectRefs, sizeof(uint32), 1, stream); - fread(&Holes, sizeof(uint32), 1, stream); + int count = 0; + + count += fread(&Flags, sizeof(uint32), 1, stream); + count += fread(&IndexX, sizeof(uint32), 1, stream); + count += fread(&IndexY, sizeof(uint32), 1, stream); + count += fread(&Layers, sizeof(uint32), 1, stream); + count += fread(&DoodadRefs, sizeof(uint32), 1, stream); + count += fread(&OffsetMCVT, sizeof(uint32), 1, stream); + count += fread(&OffsetMCNR, sizeof(uint32), 1, stream); + count += fread(&OffsetMCLY, sizeof(uint32), 1, stream); + count += fread(&OffsetMCRF, sizeof(uint32), 1, stream); + count += fread(&OffsetMCAL, sizeof(uint32), 1, stream); + count += fread(&SizeMCAL, sizeof(uint32), 1, stream); + count += fread(&OffsetMCSH, sizeof(uint32), 1, stream); + count += fread(&SizeMCSH, sizeof(uint32), 1, stream); + count += fread(&AreaId, sizeof(uint32), 1, stream); + count += fread(&MapObjectRefs, sizeof(uint32), 1, stream); + count += fread(&Holes, sizeof(uint32), 1, stream); LowQualityTextureMap = new uint32[4]; - fread(LowQualityTextureMap, sizeof(uint32), 4, stream); - fread(&PredTex, sizeof(uint32), 1, stream); - fread(&NumberEffectDoodad, sizeof(uint32), 1, stream); - fread(&OffsetMCSE, sizeof(uint32), 1, stream); - fread(&SoundEmitters, sizeof(uint32), 1, stream); - fread(&OffsetMCLQ, sizeof(uint32), 1, stream); - fread(&SizeMCLQ, sizeof(uint32), 1, stream); + count += fread(LowQualityTextureMap, sizeof(uint32), 4, stream); + count += fread(&PredTex, sizeof(uint32), 1, stream); + count += fread(&NumberEffectDoodad, sizeof(uint32), 1, stream); + count += fread(&OffsetMCSE, sizeof(uint32), 1, stream); + count += fread(&SoundEmitters, sizeof(uint32), 1, stream); + count += fread(&OffsetMCLQ, sizeof(uint32), 1, stream); + count += fread(&SizeMCLQ, sizeof(uint32), 1, stream); Position = Vector3::Read(stream); - fread(&OffsetMCCV, sizeof(uint32), 1, stream); + count += fread(&OffsetMCCV, sizeof(uint32), 1, stream); + + if (count != 27) + printf("MapChunkHeader::Read: Failed to read some data expected 27, read %d\n", count); } void MHDR::Read(FILE* stream) { - fread(&Flags, sizeof(uint32), 1, stream); - fread(&OffsetMCIN, sizeof(uint32), 1, stream); - fread(&OffsetMTEX, sizeof(uint32), 1, stream); - fread(&OffsetMMDX, sizeof(uint32), 1, stream); - fread(&OffsetMMID, sizeof(uint32), 1, stream); - fread(&OffsetMWMO, sizeof(uint32), 1, stream); - fread(&OffsetMWID, sizeof(uint32), 1, stream); - fread(&OffsetMDDF, sizeof(uint32), 1, stream); - fread(&OffsetMODF, sizeof(uint32), 1, stream); - fread(&OffsetMFBO, sizeof(uint32), 1, stream); - fread(&OffsetMH2O, sizeof(uint32), 1, stream); - fread(&OffsetMTFX, sizeof(uint32), 1, stream); + int count = 0; + + count += fread(&Flags, sizeof(uint32), 1, stream); + count += fread(&OffsetMCIN, sizeof(uint32), 1, stream); + count += fread(&OffsetMTEX, sizeof(uint32), 1, stream); + count += fread(&OffsetMMDX, sizeof(uint32), 1, stream); + count += fread(&OffsetMMID, sizeof(uint32), 1, stream); + count += fread(&OffsetMWMO, sizeof(uint32), 1, stream); + count += fread(&OffsetMWID, sizeof(uint32), 1, stream); + count += fread(&OffsetMDDF, sizeof(uint32), 1, stream); + count += fread(&OffsetMODF, sizeof(uint32), 1, stream); + count += fread(&OffsetMFBO, sizeof(uint32), 1, stream); + count += fread(&OffsetMH2O, sizeof(uint32), 1, stream); + count += fread(&OffsetMTFX, sizeof(uint32), 1, stream); + + if (count != 12) + printf("MHDR::Read: Failed to read some data expected 12, read %d\n", count); } void ModelHeader::Read(FILE* stream) { - fread(&Magic, sizeof(char), 4, stream); + int count = 0; + + count += fread(&Magic, sizeof(char), 4, stream); Magic[4] = '\0'; // null-terminate it. - fread(&Version, sizeof(uint32), 1, stream); - fread(&LengthModelName, sizeof(uint32), 1, stream); - fread(&OffsetName, sizeof(uint32), 1, stream); - fread(&ModelFlags, sizeof(uint32), 1, stream); - fread(&CountGlobalSequences, sizeof(uint32), 1, stream); - fread(&OffsetGlobalSequences, sizeof(uint32), 1, stream); - fread(&CountAnimations, sizeof(uint32), 1, stream); - fread(&OffsetAnimations, sizeof(uint32), 1, stream); - fread(&CountAnimationLookup, sizeof(uint32), 1, stream); - fread(&OffsetAnimationLookup, sizeof(uint32), 1, stream); - fread(&CountBones, sizeof(uint32), 1, stream); - fread(&OffsetBones, sizeof(uint32), 1, stream); - fread(&CountKeyBoneLookup, sizeof(uint32), 1, stream); - fread(&OffsetKeyBoneLookup, sizeof(uint32), 1, stream); - fread(&CountVertices, sizeof(uint32), 1, stream); - fread(&OffsetVertices, sizeof(uint32), 1, stream); - fread(&CountViews, sizeof(uint32), 1, stream); - fread(&CountColors, sizeof(uint32), 1, stream); - fread(&OffsetColors, sizeof(uint32), 1, stream); - fread(&CountTextures, sizeof(uint32), 1, stream); - fread(&OffsetTextures, sizeof(uint32), 1, stream); - fread(&CountTransparency, sizeof(uint32), 1, stream); - fread(&OffsetTransparency, sizeof(uint32), 1, stream); - fread(&CountUvAnimation, sizeof(uint32), 1, stream); - fread(&OffsetUvAnimation, sizeof(uint32), 1, stream); - fread(&CountTexReplace, sizeof(uint32), 1, stream); - fread(&OffsetTexReplace, sizeof(uint32), 1, stream); - fread(&CountRenderFlags, sizeof(uint32), 1, stream); - fread(&OffsetRenderFlags, sizeof(uint32), 1, stream); - fread(&CountBoneLookup, sizeof(uint32), 1, stream); - fread(&OffsetBoneLookup, sizeof(uint32), 1, stream); - fread(&CountTexLookup, sizeof(uint32), 1, stream); - fread(&OffsetTexLookup, sizeof(uint32), 1, stream); - fread(&CountTexUnits, sizeof(uint32), 1, stream); - fread(&OffsetTexUnits, sizeof(uint32), 1, stream); - fread(&CountTransLookup, sizeof(uint32), 1, stream); - fread(&OffsetTransLookup, sizeof(uint32), 1, stream); - fread(&CountUvAnimLookup, sizeof(uint32), 1, stream); - fread(&OffsetUvAnimLookup, sizeof(uint32), 1, stream); + count += fread(&Version, sizeof(uint32), 1, stream); + count += fread(&LengthModelName, sizeof(uint32), 1, stream); + count += fread(&OffsetName, sizeof(uint32), 1, stream); + count += fread(&ModelFlags, sizeof(uint32), 1, stream); + count += fread(&CountGlobalSequences, sizeof(uint32), 1, stream); + count += fread(&OffsetGlobalSequences, sizeof(uint32), 1, stream); + count += fread(&CountAnimations, sizeof(uint32), 1, stream); + count += fread(&OffsetAnimations, sizeof(uint32), 1, stream); + count += fread(&CountAnimationLookup, sizeof(uint32), 1, stream); + count += fread(&OffsetAnimationLookup, sizeof(uint32), 1, stream); + count += fread(&CountBones, sizeof(uint32), 1, stream); + count += fread(&OffsetBones, sizeof(uint32), 1, stream); + count += fread(&CountKeyBoneLookup, sizeof(uint32), 1, stream); + count += fread(&OffsetKeyBoneLookup, sizeof(uint32), 1, stream); + count += fread(&CountVertices, sizeof(uint32), 1, stream); + count += fread(&OffsetVertices, sizeof(uint32), 1, stream); + count += fread(&CountViews, sizeof(uint32), 1, stream); + count += fread(&CountColors, sizeof(uint32), 1, stream); + count += fread(&OffsetColors, sizeof(uint32), 1, stream); + count += fread(&CountTextures, sizeof(uint32), 1, stream); + count += fread(&OffsetTextures, sizeof(uint32), 1, stream); + count += fread(&CountTransparency, sizeof(uint32), 1, stream); + count += fread(&OffsetTransparency, sizeof(uint32), 1, stream); + count += fread(&CountUvAnimation, sizeof(uint32), 1, stream); + count += fread(&OffsetUvAnimation, sizeof(uint32), 1, stream); + count += fread(&CountTexReplace, sizeof(uint32), 1, stream); + count += fread(&OffsetTexReplace, sizeof(uint32), 1, stream); + count += fread(&CountRenderFlags, sizeof(uint32), 1, stream); + count += fread(&OffsetRenderFlags, sizeof(uint32), 1, stream); + count += fread(&CountBoneLookup, sizeof(uint32), 1, stream); + count += fread(&OffsetBoneLookup, sizeof(uint32), 1, stream); + count += fread(&CountTexLookup, sizeof(uint32), 1, stream); + count += fread(&OffsetTexLookup, sizeof(uint32), 1, stream); + count += fread(&CountTexUnits, sizeof(uint32), 1, stream); + count += fread(&OffsetTexUnits, sizeof(uint32), 1, stream); + count += fread(&CountTransLookup, sizeof(uint32), 1, stream); + count += fread(&OffsetTransLookup, sizeof(uint32), 1, stream); + count += fread(&CountUvAnimLookup, sizeof(uint32), 1, stream); + count += fread(&OffsetUvAnimLookup, sizeof(uint32), 1, stream); VertexBox[0] = Vector3::Read(stream); VertexBox[1] = Vector3::Read(stream); - fread(&VertexRadius, sizeof(float), 1, stream); + count += fread(&VertexRadius, sizeof(float), 1, stream); BoundingBox[0] = Vector3::Read(stream); BoundingBox[1] = Vector3::Read(stream); - fread(&BoundingRadius, sizeof(float), 1, stream); - fread(&CountBoundingTriangles, sizeof(uint32), 1, stream); - fread(&OffsetBoundingTriangles, sizeof(uint32), 1, stream); - fread(&CountBoundingVertices, sizeof(uint32), 1, stream); - fread(&OffsetBoundingVertices, sizeof(uint32), 1, stream); - fread(&CountBoundingNormals, sizeof(uint32), 1, stream); - fread(&OffsetBoundingNormals, sizeof(uint32), 1, stream); + count += fread(&BoundingRadius, sizeof(float), 1, stream); + count += fread(&CountBoundingTriangles, sizeof(uint32), 1, stream); + count += fread(&OffsetBoundingTriangles, sizeof(uint32), 1, stream); + count += fread(&CountBoundingVertices, sizeof(uint32), 1, stream); + count += fread(&OffsetBoundingVertices, sizeof(uint32), 1, stream); + count += fread(&CountBoundingNormals, sizeof(uint32), 1, stream); + count += fread(&OffsetBoundingNormals, sizeof(uint32), 1, stream); + + if (count != 51) + printf("ModelHeader::Read: Failed to read some data expected 51, read %d\n", count); + } WorldModelHeader WorldModelHeader::Read(FILE* stream) { WorldModelHeader ret; - fread(&ret.CountMaterials, sizeof(uint32), 1, stream); - fread(&ret.CountGroups, sizeof(uint32), 1, stream); - fread(&ret.CountPortals, sizeof(uint32), 1, stream); - fread(&ret.CountLights, sizeof(uint32), 1, stream); - fread(&ret.CountModels, sizeof(uint32), 1, stream); - fread(&ret.CountDoodads, sizeof(uint32), 1, stream); - fread(&ret.CountSets, sizeof(uint32), 1, stream); - fread(&ret.AmbientColorUnk, sizeof(uint32), 1, stream); - fread(&ret.WmoId, sizeof(uint32), 1, stream); + int count = 0; + + count += fread(&ret.CountMaterials, sizeof(uint32), 1, stream); + count += fread(&ret.CountGroups, sizeof(uint32), 1, stream); + count += fread(&ret.CountPortals, sizeof(uint32), 1, stream); + count += fread(&ret.CountLights, sizeof(uint32), 1, stream); + count += fread(&ret.CountModels, sizeof(uint32), 1, stream); + count += fread(&ret.CountDoodads, sizeof(uint32), 1, stream); + count += fread(&ret.CountSets, sizeof(uint32), 1, stream); + count += fread(&ret.AmbientColorUnk, sizeof(uint32), 1, stream); + count += fread(&ret.WmoId, sizeof(uint32), 1, stream); ret.BoundingBox[0] = Vector3::Read(stream); ret.BoundingBox[1] = Vector3::Read(stream); - fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream); + count += fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream); + + if (count != 10) + printf("WorldModelHeader::Read: Failed to read some data expected 10, read %d\n", count); + return ret; } DoodadInstance DoodadInstance::Read(FILE* stream) { DoodadInstance ret; - fread(&ret.FileOffset, sizeof(uint32), 1, stream); + int count = 0; + + count += fread(&ret.FileOffset, sizeof(uint32), 1, stream); ret.Position = Vector3::Read(stream); - fread(&ret.QuatW, sizeof(float), 1, stream); - fread(&ret.QuatX, sizeof(float), 1, stream); - fread(&ret.QuatY, sizeof(float), 1, stream); - fread(&ret.QuatZ, sizeof(float), 1, stream); - fread(&ret.Scale, sizeof(float), 1, stream); - fread(&ret.LightColor, sizeof(uint32), 1, stream); + count += fread(&ret.QuatW, sizeof(float), 1, stream); + count += fread(&ret.QuatX, sizeof(float), 1, stream); + count += fread(&ret.QuatY, sizeof(float), 1, stream); + count += fread(&ret.QuatZ, sizeof(float), 1, stream); + count += fread(&ret.Scale, sizeof(float), 1, stream); + count += fread(&ret.LightColor, sizeof(uint32), 1, stream); + + if (count != 7) + printf("DoodadInstance::Read: Failed to read some data expected 7, read %d\n", count); + return ret; } @@ -379,24 +411,35 @@ DoodadSet DoodadSet::Read(FILE* stream) { DoodadSet ret; char name[21]; - fread(&name, sizeof(char), 20, stream); + int count = 0; + + count += fread(&name, sizeof(char), 20, stream); name[20] = '\0'; ret.Name = name; - fread(&ret.FirstInstanceIndex, sizeof(uint32), 1, stream); - fread(&ret.CountInstances, sizeof(uint32), 1, stream); - fread(&ret.UnknownZero, sizeof(uint32), 1, stream); + count += fread(&ret.FirstInstanceIndex, sizeof(uint32), 1, stream); + count += fread(&ret.CountInstances, sizeof(uint32), 1, stream); + count += fread(&ret.UnknownZero, sizeof(uint32), 1, stream); + + if (count != 23) + printf("DoodadSet::Read: Failed to read some data expected 23, read %d\n", count); + return ret; } LiquidHeader LiquidHeader::Read(FILE* stream) { LiquidHeader ret; - fread(&ret.CountXVertices, sizeof(uint32), 1, stream); - fread(&ret.CountYVertices, sizeof(uint32), 1, stream); - fread(&ret.Width, sizeof(uint32), 1, stream); - fread(&ret.Height, sizeof(uint32), 1, stream); + int count = 0; + count += fread(&ret.CountXVertices, sizeof(uint32), 1, stream); + count += fread(&ret.CountYVertices, sizeof(uint32), 1, stream); + count += fread(&ret.Width, sizeof(uint32), 1, stream); + count += fread(&ret.Height, sizeof(uint32), 1, stream); ret.BaseLocation = Vector3::Read(stream); - fread(&ret.MaterialId, sizeof(uint16), 1, stream); + count += fread(&ret.MaterialId, sizeof(uint16), 1, stream); + + if (count != 5) + printf("LiquidHeader::Read: Failed to read some data expected 5, read %d\n", count); + return ret; } @@ -416,10 +459,12 @@ LiquidData LiquidData::Read(FILE* stream, LiquidHeader& header) for (uint32 x = 0; x < header.CountXVertices; x++) { uint32 discard; - fread(&discard, sizeof(uint32), 1, stream); float tmp; - fread(&tmp, sizeof(float), 1, stream); - ret.HeightMap[x][y] = tmp; + if (fread(&discard, sizeof(uint32), 1, stream) == 1 && + fread(&tmp, sizeof(float), 1, stream) == 1) + { + ret.HeightMap[x][y] = tmp; + } } } @@ -427,9 +472,9 @@ LiquidData LiquidData::Read(FILE* stream, LiquidHeader& header) { for (uint32 x = 0; x < header.Width; x++) { - uint8 tmp; - fread(&tmp, sizeof(uint8), 1, stream); - ret.RenderFlags[x][y] = tmp; + uint8 tmp = 0; + if (fread(&tmp, sizeof(uint8), 1, stream) == 1) + ret.RenderFlags[x][y] = tmp; } } @@ -439,7 +484,8 @@ LiquidData LiquidData::Read(FILE* stream, LiquidHeader& header) H2ORenderMask H2ORenderMask::Read(FILE* stream) { H2ORenderMask ret; - fread(&ret.Mask, sizeof(uint8), 8, stream); + if (int count = fread(&ret.Mask, sizeof(uint8), 8, stream) != 8) + printf("H2OHeader::Read: Failed to read some data expected 8, read %d\n", count); return ret; } @@ -458,25 +504,35 @@ bool MCNKLiquidData::IsWater(int x, int y, float height) H2OHeader H2OHeader::Read(FILE* stream) { H2OHeader ret; - fread(&ret.OffsetInformation, sizeof(uint32), 1, stream); - fread(&ret.LayerCount, sizeof(uint32), 1, stream); - fread(&ret.OffsetRender, sizeof(uint32), 1, stream); + int count = 0; + count += fread(&ret.OffsetInformation, sizeof(uint32), 1, stream); + count += fread(&ret.LayerCount, sizeof(uint32), 1, stream); + count += fread(&ret.OffsetRender, sizeof(uint32), 1, stream); + + if (count != 3) + printf("H2OHeader::Read: Failed to read some data expected 3, read %d\n", count); + return ret; } H2OInformation H2OInformation::Read(FILE* stream) { H2OInformation ret; - fread(&ret.LiquidType, sizeof(uint16), 1, stream); - fread(&ret.Flags, sizeof(uint16), 1, stream); - fread(&ret.HeightLevel1, sizeof(float), 1, stream); - fread(&ret.HeightLevel2, sizeof(float), 1, stream); - fread(&ret.OffsetX, sizeof(uint8), 1, stream); - fread(&ret.OffsetY, sizeof(uint8), 1, stream); - fread(&ret.Width, sizeof(uint8), 1, stream); - fread(&ret.Height, sizeof(uint8), 1, stream); - fread(&ret.OffsetMask2, sizeof(uint32), 1, stream); - fread(&ret.OffsetHeightmap, sizeof(uint32), 1, stream); + int count = 0; + count += fread(&ret.LiquidType, sizeof(uint16), 1, stream); + count += fread(&ret.Flags, sizeof(uint16), 1, stream); + count += fread(&ret.HeightLevel1, sizeof(float), 1, stream); + count += fread(&ret.HeightLevel2, sizeof(float), 1, stream); + count += fread(&ret.OffsetX, sizeof(uint8), 1, stream); + count += fread(&ret.OffsetY, sizeof(uint8), 1, stream); + count += fread(&ret.Width, sizeof(uint8), 1, stream); + count += fread(&ret.Height, sizeof(uint8), 1, stream); + count += fread(&ret.OffsetMask2, sizeof(uint32), 1, stream); + count += fread(&ret.OffsetHeightmap, sizeof(uint32), 1, stream); + + if (count != 10) + printf("H2OInformation::Read: Failed to read some data expected 10, read %d\n", count); + return ret; } @@ -492,17 +548,21 @@ char* Utils::GetPlainName(const char* FileName) WMOGroupHeader WMOGroupHeader::Read( FILE* stream ) { WMOGroupHeader ret; - fread(&ret.OffsetGroupName, sizeof(uint32), 1, stream); - fread(&ret.OffsetDescriptiveName, sizeof(uint32), 1, stream); - fread(&ret.Flags, sizeof(uint32), 1, stream); + int count = 0; + count += fread(&ret.OffsetGroupName, sizeof(uint32), 1, stream); + count += fread(&ret.OffsetDescriptiveName, sizeof(uint32), 1, stream); + count += fread(&ret.Flags, sizeof(uint32), 1, stream); ret.BoundingBox[0] = Vector3::Read(stream); ret.BoundingBox[1] = Vector3::Read(stream); - fread(&ret.OffsetPortals, sizeof(uint32), 1, stream); - fread(&ret.CountPortals, sizeof(uint32), 1, stream); - fread(&ret.CountBatches, sizeof(uint16), 4, stream); - fread(&ret.Fogs, sizeof(uint8), 4, stream); - fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream); - fread(&ret.WmoId, sizeof(uint32), 1, stream); - + count += fread(&ret.OffsetPortals, sizeof(uint32), 1, stream); + count += fread(&ret.CountPortals, sizeof(uint32), 1, stream); + count += fread(&ret.CountBatches, sizeof(uint16), 4, stream); + count += fread(&ret.Fogs, sizeof(uint8), 4, stream); + count += fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream); + count += fread(&ret.WmoId, sizeof(uint32), 1, stream); + + if (count != 15) + printf("WMOGroupHeader::Read: Failed to read some data expected 15, read %d\n", count); + return ret; } diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index c5dd04fde06..e7380ed8142 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -40,7 +40,7 @@ template struct Triangle { Triangle() {} - Triangle(Constants::TriangleType type, T v0, T v1, T v2) : Type(type), V0(v0), V1(v1), V2(v2) {} + Triangle(Constants::TriangleType type, T v0, T v1, T v2) : V0(v0), V1(v1), V2(v2), Type(type) {} T V0; T V1; T V2; @@ -374,4 +374,4 @@ public: static std::string GetExtension( std::string path ); static char* GetPlainName(const char* FileName); }; -#endif \ No newline at end of file +#endif diff --git a/src/tools/mesh_extractor/WDT.cpp b/src/tools/mesh_extractor/WDT.cpp index f0c3091c04e..70d140e79ed 100644 --- a/src/tools/mesh_extractor/WDT.cpp +++ b/src/tools/mesh_extractor/WDT.cpp @@ -4,7 +4,7 @@ #include "Utils.h" #include "WorldModelHandler.h" -WDT::WDT(std::string file) : IsValid(false), IsGlobalModel(false) +WDT::WDT(std::string file) : IsGlobalModel(false), IsValid(false) { Data = new ChunkedData(file, 2); ReadTileTable(); @@ -37,8 +37,13 @@ void WDT::ReadTileTable() const uint32 hasTileFlag = 0x1; uint32 flags; uint32 discard; - fread(&flags, sizeof(uint32), 1, stream); - fread(&discard, sizeof(uint32), 1, stream); + int count = 0; + count += fread(&flags, sizeof(uint32), 1, stream); + count += fread(&discard, sizeof(uint32), 1, stream); + + if (count != 2) + printf("WDT::ReadTileTable: Failed to read some data expected 2, read %d\n", count); + if (flags & hasTileFlag) TileTable.push_back(TilePos(x, y)); diff --git a/src/tools/mesh_extractor/WorldModelGroup.cpp b/src/tools/mesh_extractor/WorldModelGroup.cpp index 35a5ba69782..5eeef824b1a 100644 --- a/src/tools/mesh_extractor/WorldModelGroup.cpp +++ b/src/tools/mesh_extractor/WorldModelGroup.cpp @@ -3,7 +3,7 @@ #include "Chunk.h" #include "Utils.h" -WorldModelGroup::WorldModelGroup( std::string path, int groupIndex ) : GroupIndex(groupIndex), IsBad(false), MOBA(NULL) +WorldModelGroup::WorldModelGroup( std::string path, int groupIndex ) : GroupIndex(groupIndex), MOBA(NULL), IsBad(false) { Data = new ChunkedData(path); if (!Data->Stream) @@ -85,9 +85,13 @@ void WorldModelGroup::ReadTriangles() uint16 v0; uint16 v1; uint16 v2; - fread(&v0, sizeof(uint16), 1, stream); - fread(&v1, sizeof(uint16), 1, stream); - fread(&v2, sizeof(uint16), 1, stream); + int count = 0; + count += fread(&v0, sizeof(uint16), 1, stream); + count += fread(&v1, sizeof(uint16), 1, stream); + count += fread(&v2, sizeof(uint16), 1, stream); + if (count != 3) + printf("WorldModelGroup::ReadMaterials: Error reading data, expected 3, read %d\n", count); + Triangles.push_back(Triangle(Constants::TRIANGLE_TYPE_WMO, v0, v1, v2)); } } @@ -105,10 +109,12 @@ void WorldModelGroup::ReadMaterials() for (uint32 i = 0; i < triangleCount; i++) { uint8 tmp; - fread(&tmp, sizeof(uint8), 1, stream); + if (fread(&tmp, sizeof(uint8), 1, stream) != 1) + printf("WorldModelGroup::ReadMaterials: Error reading data, expected 1, read 0\n"); TriangleFlags.push_back(tmp); // Read again for material. - fread(&tmp, sizeof(uint8), 1, stream); + if (fread(&tmp, sizeof(uint8), 1, stream) != 1) + printf("WorldModelGroup::ReadMaterials: Error reading data, expected 1, read 0\n"); TriangleMaterials.push_back(tmp); } } @@ -131,5 +137,7 @@ void WorldModelGroup::ReadBatches() MOBALength = chunk->Length / 2; MOBA = new uint16[MOBALength]; - fread(MOBA, sizeof(uint16), MOBALength, chunk->GetStream()); + int count = fread(MOBA, sizeof(uint16), MOBALength, chunk->GetStream()); + if (count != MOBALength) + printf("WorldModelGroup::ReadBatches: Error reading data, expected %d, read %d\n", MOBALength, count); } diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index 7b60b9b2151..6ce41807492 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -10,16 +10,20 @@ WorldModelDefinition WorldModelDefinition::Read( FILE* file ) { WorldModelDefinition ret; - fread(&ret.MwidIndex, sizeof(uint32), 1, file); - fread(&ret.UniqueId, sizeof(uint32), 1, file); + int count = 0; + count += fread(&ret.MwidIndex, sizeof(uint32), 1, file); + count += fread(&ret.UniqueId, sizeof(uint32), 1, file); ret.Position = Vector3::Read(file); ret.Rotation = Vector3::Read(file); ret.UpperExtents = Vector3::Read(file); ret.LowerExtents = Vector3::Read(file); - fread(&ret.Flags, sizeof(uint16), 1, file); - fread(&ret.DoodadSet, sizeof(uint16), 1, file); + count += fread(&ret.Flags, sizeof(uint16), 1, file); + count += fread(&ret.DoodadSet, sizeof(uint16), 1, file); uint32 discard; - fread(&discard, sizeof(uint32), 1, file); + count += fread(&discard, sizeof(uint32), 1, file); + + if (count != 5) + printf("WorldModelDefinition::Read: Error reading data, expected 5, read %d\n", count); return ret; } @@ -44,7 +48,8 @@ void WorldModelHandler::ProcessInternal( ChunkedData* subChunks ) for (uint32 i = 0; i < refCount; i++) { int32 index; - fread(&index, sizeof(int32), 1, stream); + if (fread(&index, sizeof(int32), 1, stream) != 1) + printf("WorldModelDefinition::Read: Error reading data, expected 1, read 0\n"); if (index < 0 || uint32(index) >= _definitions->size()) continue; @@ -184,7 +189,8 @@ void WorldModelHandler::ReadModelPaths() FILE* stream = mwid->GetStream(); fseek(stream, i * 4, SEEK_CUR); uint32 offset; - fread(&offset, sizeof(uint32), 1, stream); + if (fread(&offset, sizeof(uint32), 1, stream) != 1) + printf("WorldModelDefinition::Read: Error reading data, expected 1, read 0\n"); FILE* dataStream = mwmo->GetStream(); fseek(dataStream, offset + mwmo->Offset, SEEK_SET); _paths->push_back(Utils::ReadString(dataStream)); diff --git a/src/tools/mmaps_generator/CMakeLists.txt b/src/tools/mmaps_generator/CMakeLists.txt index 46bf9d00d43..229a2cd808f 100644 --- a/src/tools/mmaps_generator/CMakeLists.txt +++ b/src/tools/mmaps_generator/CMakeLists.txt @@ -22,13 +22,13 @@ include_directories( ${CMAKE_SOURCE_DIR}/dep/libmpq ${CMAKE_SOURCE_DIR}/dep/zlib ${CMAKE_SOURCE_DIR}/dep/bzip2 - ${CMAKE_SOURCE_DIR}/dep/acelite ${CMAKE_SOURCE_DIR}/dep/g3dlite/include ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour ${CMAKE_SOURCE_DIR}/src/server/shared ${CMAKE_SOURCE_DIR}/src/server/shared/Database ${CMAKE_SOURCE_DIR}/src/server/shared/Database/Implementation + ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging ${CMAKE_SOURCE_DIR}/src/server/shared/Threading ${CMAKE_SOURCE_DIR}/src/server/shared/Logging ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities diff --git a/src/tools/mmaps_generator/IntermediateValues.h b/src/tools/mmaps_generator/IntermediateValues.h index a267a0f6412..98042e1b917 100644 --- a/src/tools/mmaps_generator/IntermediateValues.h +++ b/src/tools/mmaps_generator/IntermediateValues.h @@ -35,7 +35,7 @@ namespace MMAP rcPolyMesh* polyMesh; rcPolyMeshDetail* polyMeshDetail; - IntermediateValues() : compactHeightfield(NULL), heightfield(NULL), + IntermediateValues() : heightfield(NULL), compactHeightfield(NULL), contours(NULL), polyMesh(NULL), polyMeshDetail(NULL) {} ~IntermediateValues(); diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 754bced903c..689ccdc906d 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -29,7 +29,7 @@ // These make the linker happy. LoginDatabaseWorkerPool LoginDatabase; -uint32 GetLiquidFlags(uint32 liquidType) +uint32 GetLiquidFlags(uint32 /*liquidType*/) { return 0; } @@ -37,7 +37,7 @@ uint32 GetLiquidFlags(uint32 liquidType) #include "DisableMgr.h" namespace DisableMgr { - bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags) + bool IsDisabledFor(DisableType /*type*/, uint32 /*entry*/, Unit const* /*unit*/, uint8 /*flags*/) { return 0; } @@ -50,15 +50,15 @@ namespace MMAP MapBuilder::MapBuilder(float maxWalkableAngle, bool skipLiquid, bool skipContinents, bool skipJunkMaps, bool skipBattlegrounds, bool debugOutput, bool bigBaseUnit, const char* offMeshFilePath) : - m_terrainBuilder(NULL), + m_terrainBuilder (NULL), m_debugOutput (debugOutput), + m_offMeshFilePath (offMeshFilePath), m_skipContinents (skipContinents), m_skipJunkMaps (skipJunkMaps), m_skipBattlegrounds (skipBattlegrounds), m_maxWalkableAngle (maxWalkableAngle), m_bigBaseUnit (bigBaseUnit), - m_rcContext (NULL), - m_offMeshFilePath (offMeshFilePath) + m_rcContext (NULL) { m_terrainBuilder = new TerrainBuilder(skipLiquid); @@ -250,9 +250,12 @@ namespace MMAP printf("Building mesh from file\n"); int tileX, tileY, mapId; - fread(&mapId, sizeof(int), 1, file); - fread(&tileX, sizeof(int), 1, file); - fread(&tileY, sizeof(int), 1, file); + if (fread(&mapId, sizeof(int), 1, file) != 1) + return; + if (fread(&tileX, sizeof(int), 1, file) != 1) + return; + if (fread(&tileY, sizeof(int), 1, file) != 1) + return; dtNavMesh* navMesh = NULL; buildNavMesh(mapId, navMesh); @@ -263,23 +266,26 @@ namespace MMAP return; } - - int verticesCount, indicesCount; - fread(&verticesCount, sizeof(int), 1, file); - fread(&indicesCount, sizeof(int), 1, file); + uint verticesCount, indicesCount; + if (fread(&verticesCount, sizeof(uint), 1, file) != 1) + return; + if (fread(&indicesCount, sizeof(uint), 1, file) != 1) + return; float* verts = new float[verticesCount]; int* inds = new int[indicesCount]; - fread(verts, sizeof(float), verticesCount, file); - fread(inds, sizeof(int), indicesCount, file); + if (fread(verts, sizeof(float), verticesCount, file) != verticesCount) + return; + if (fread(inds, sizeof(int), indicesCount, file) != indicesCount) + return; MeshData data; - for (int i = 0; i < verticesCount; ++i) + for (uint i = 0; i < verticesCount; ++i) data.solidVerts.append(verts[i]); - for (int i = 0; i < indicesCount; ++i) + for (uint i = 0; i < indicesCount; ++i) data.solidTris.append(inds[i]); TerrainBuilder::cleanVertices(data.solidVerts, data.solidTris); @@ -310,7 +316,7 @@ namespace MMAP /**************************************************************************/ void MapBuilder::buildMap(uint32 mapID) { - printf("[Thread %i] Building map %03u:\n", ACE_Thread::self(), mapID); + printf("[Thread %u] Building map %03u:\n", uint32(ACE_Thread::self()), mapID); set* tiles = getTileList(mapID); @@ -409,7 +415,6 @@ namespace MMAP //if (tileBits < 1) tileBits = 1; // need at least one bit! //int polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits; - int tileBits = STATIC_TILE_BITS; int polyBits = STATIC_POLY_BITS; int maxTiles = tiles->size(); @@ -955,8 +960,10 @@ namespace MMAP return false; MmapTileHeader header; - fread(&header, sizeof(MmapTileHeader), 1, file); + int count = fread(&header, sizeof(MmapTileHeader), 1, file); fclose(file); + if (count != 1) + return false; if (header.mmapMagic != MMAP_MAGIC || header.dtVersion != DT_NAVMESH_VERSION) return false; diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h index fd02ec02d50..966c12ec19e 100644 --- a/src/tools/mmaps_generator/PathCommon.h +++ b/src/tools/mmaps_generator/PathCommon.h @@ -75,7 +75,7 @@ namespace MMAP LISTFILE_OK = 1 }; - inline ListFilesResult getDirContents(vector &fileList, string dirpath = ".", string filter = "*", bool includeSubDirs = false) + inline ListFilesResult getDirContents(vector &fileList, string dirpath = ".", string filter = "*") { #ifdef WIN32 HANDLE hFind; diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index 0159219c110..22946df478a 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -27,6 +27,9 @@ namespace MMAP { + + char const* MAP_VERSION_MAGIC = "v1.3"; + TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ } TerrainBuilder::~TerrainBuilder() { } @@ -86,9 +89,8 @@ namespace MMAP return false; map_fileheader fheader; - fread(&fheader, sizeof(map_fileheader), 1, mapFile); - - if (fheader.versionMagic != *((uint32 const*)(MAP_VERSION_MAGIC))) + if (fread(&fheader, sizeof(map_fileheader), 1, mapFile) != 1 || + fheader.versionMagic != *((uint32 const*)(MAP_VERSION_MAGIC))) { fclose(mapFile); printf("%s is the wrong version, please extract new .map files\n", mapFileName); @@ -97,10 +99,14 @@ namespace MMAP map_heightHeader hheader; fseek(mapFile, fheader.heightMapOffset, SEEK_SET); - fread(&hheader, sizeof(map_heightHeader), 1, mapFile); - bool haveTerrain = !(hheader.flags & MAP_HEIGHT_NO_HEIGHT); - bool haveLiquid = fheader.liquidMapOffset && !m_skipLiquid; + bool haveTerrain = false; + bool haveLiquid = false; + if (fread(&hheader, sizeof(map_heightHeader), 1, mapFile) == 1) + { + haveTerrain = !(hheader.flags & MAP_HEIGHT_NO_HEIGHT); + haveLiquid = fheader.liquidMapOffset && !m_skipLiquid; + } // no data in this map file if (!haveTerrain && !haveLiquid) @@ -120,42 +126,53 @@ namespace MMAP // terrain data if (haveTerrain) { - int i; float heightMultiplier; float V9[V9_SIZE_SQ], V8[V8_SIZE_SQ]; + int expected = V9_SIZE_SQ + V8_SIZE_SQ; if (hheader.flags & MAP_HEIGHT_AS_INT8) { uint8 v9[V9_SIZE_SQ]; uint8 v8[V8_SIZE_SQ]; - fread(v9, sizeof(uint8), V9_SIZE_SQ, mapFile); - fread(v8, sizeof(uint8), V8_SIZE_SQ, mapFile); + int count = 0; + count += fread(v9, sizeof(uint8), V9_SIZE_SQ, mapFile); + count += fread(v8, sizeof(uint8), V8_SIZE_SQ, mapFile); + if (count != expected) + printf("TerrainBuilder::loadMap: Failed to read some data expected %d, read %d\n", expected, count); + heightMultiplier = (hheader.gridMaxHeight - hheader.gridHeight) / 255; - for (i = 0; i < V9_SIZE_SQ; ++i) + for (int i = 0; i < V9_SIZE_SQ; ++i) V9[i] = (float)v9[i]*heightMultiplier + hheader.gridHeight; - for (i = 0; i < V8_SIZE_SQ; ++i) + for (int i = 0; i < V8_SIZE_SQ; ++i) V8[i] = (float)v8[i]*heightMultiplier + hheader.gridHeight; } else if (hheader.flags & MAP_HEIGHT_AS_INT16) { uint16 v9[V9_SIZE_SQ]; uint16 v8[V8_SIZE_SQ]; - fread(v9, sizeof(uint16), V9_SIZE_SQ, mapFile); - fread(v8, sizeof(uint16), V8_SIZE_SQ, mapFile); + int count = 0; + count += fread(v9, sizeof(uint16), V9_SIZE_SQ, mapFile); + count += fread(v8, sizeof(uint16), V8_SIZE_SQ, mapFile); + if (count != expected) + printf("TerrainBuilder::loadMap: Failed to read some data expected %d, read %d\n", expected, count); + heightMultiplier = (hheader.gridMaxHeight - hheader.gridHeight) / 65535; - for (i = 0; i < V9_SIZE_SQ; ++i) + for (int i = 0; i < V9_SIZE_SQ; ++i) V9[i] = (float)v9[i]*heightMultiplier + hheader.gridHeight; - for (i = 0; i < V8_SIZE_SQ; ++i) + for (int i = 0; i < V8_SIZE_SQ; ++i) V8[i] = (float)v8[i]*heightMultiplier + hheader.gridHeight; } else { - fread (V9, sizeof(float), V9_SIZE_SQ, mapFile); - fread(V8, sizeof(float), V8_SIZE_SQ, mapFile); + int count = 0; + count += fread(V9, sizeof(float), V9_SIZE_SQ, mapFile); + count += fread(V8, sizeof(float), V8_SIZE_SQ, mapFile); + if (count != expected) + printf("TerrainBuilder::loadMap: Failed to read some data expected %d, read %d\n", expected, count); } // hole data @@ -163,7 +180,8 @@ namespace MMAP { memset(holes, 0, fheader.holesSize); fseek(mapFile, fheader.holesOffset, SEEK_SET); - fread(holes, fheader.holesSize, 1, mapFile); + if (fread(holes, fheader.holesSize, 1, mapFile) != 1) + printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n"); } int count = meshData.solidVerts.size() / 3; @@ -172,7 +190,7 @@ namespace MMAP float coord[3]; - for (i = 0; i < V9_SIZE_SQ; ++i) + for (int i = 0; i < V9_SIZE_SQ; ++i) { getHeightCoord(i, GRID_V9, xoffset, yoffset, coord, V9); meshData.solidVerts.append(coord[0]); @@ -180,7 +198,7 @@ namespace MMAP meshData.solidVerts.append(coord[1]); } - for (i = 0; i < V8_SIZE_SQ; ++i) + for (int i = 0; i < V8_SIZE_SQ; ++i) { getHeightCoord(i, GRID_V8, xoffset, yoffset, coord, V8); meshData.solidVerts.append(coord[0]); @@ -188,10 +206,10 @@ namespace MMAP meshData.solidVerts.append(coord[1]); } - int j, indices[3], loopStart, loopEnd, loopInc; + int indices[3], loopStart = 0, loopEnd = 0, loopInc = 0; getLoopVars(portion, loopStart, loopEnd, loopInc); - for (i = loopStart; i < loopEnd; i+=loopInc) - for (j = TOP; j <= BOTTOM; j+=1) + for (int i = loopStart; i < loopEnd; i+=loopInc) + for (int j = TOP; j <= BOTTOM; j+=1) { getHeightTriangle(i, Spot(j), indices); ttriangles.append(indices[2] + count); @@ -205,19 +223,25 @@ namespace MMAP { map_liquidHeader lheader; fseek(mapFile, fheader.liquidMapOffset, SEEK_SET); - fread(&lheader, sizeof(map_liquidHeader), 1, mapFile); + if (fread(&lheader, sizeof(map_liquidHeader), 1, mapFile) != 1) + printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n"); + float* liquid_map = NULL; if (!(lheader.flags & MAP_LIQUID_NO_TYPE)) - fread(liquid_type, sizeof(liquid_type), 1, mapFile); + if (fread(liquid_type, sizeof(liquid_type), 1, mapFile) != 1) + printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n"); if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT)) { - liquid_map = new float [lheader.width*lheader.height]; - fread(liquid_map, sizeof(float), lheader.width*lheader.height, mapFile); + uint toRead = lheader.width*lheader.height; + liquid_map = new float [toRead]; + if (fread(liquid_map, sizeof(float), toRead, mapFile) != toRead) + printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n"); } + // FIXME: "the address of ‘liquid_type’ will always evaluate as ‘true’" if (liquid_type && liquid_map) { int count = meshData.liquidVerts.size() / 3; @@ -263,9 +287,8 @@ namespace MMAP delete [] liquid_map; - int indices[3], loopStart, loopEnd, loopInc, triInc; + int indices[3], loopStart = 0, loopEnd = 0, loopInc = 0, triInc = BOTTOM-TOP; getLoopVars(portion, loopStart, loopEnd, loopInc); - triInc = BOTTOM-TOP; // generate triangles for (int i = loopStart; i < loopEnd; i+=loopInc) @@ -283,7 +306,7 @@ namespace MMAP // now that we have gathered the data, we can figure out which parts to keep: // liquid above ground, ground above liquid - int loopStart, loopEnd, loopInc, tTriCount = 4; + int loopStart = 0, loopEnd = 0, loopInc = 0, tTriCount = 4; bool useTerrain, useLiquid; float* lverts = meshData.liquidVerts.getCArray(); @@ -313,6 +336,7 @@ namespace MMAP useTerrain = true; useLiquid = true; uint8 liquidType = MAP_LIQUID_TYPE_NO_WATER; + // FIXME: "warning: the address of ‘liquid_type’ will always evaluate as ‘true’" // if there is no liquid, don't use liquid if (!liquid_type || !meshData.liquidVerts.size() || !ltriangles.size()) @@ -825,13 +849,13 @@ namespace MMAP while(fgets(buf, 512, fp)) { float p0[3], p1[3]; - int mid, tx, ty; + uint32 mid, tx, ty; float size; - if (10 != sscanf(buf, "%d %d,%d (%f %f %f) (%f %f %f) %f", &mid, &tx, &ty, - &p0[0], &p0[1], &p0[2], &p1[0], &p1[1], &p1[2], &size)) + if (sscanf(buf, "%d %d,%d (%f %f %f) (%f %f %f) %f", &mid, &tx, &ty, + &p0[0], &p0[1], &p0[2], &p1[0], &p1[1], &p1[2], &size) != 10) continue; - if (mapID == mid, tileX == tx, tileY == ty) + if (mapID == mid && tileX == tx && tileY == ty) { meshData.offMeshConnections.append(p0[1]); meshData.offMeshConnections.append(p0[2]); diff --git a/src/tools/mmaps_generator/TerrainBuilder.h b/src/tools/mmaps_generator/TerrainBuilder.h index 6d478753279..7a24146946b 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.h +++ b/src/tools/mmaps_generator/TerrainBuilder.h @@ -62,7 +62,6 @@ namespace MMAP // see following files: // contrib/extractor/system.cpp // src/game/Map.cpp - static char const* MAP_VERSION_MAGIC = "v1.3"; struct MeshData { diff --git a/src/tools/mmaps_generator/VMapExtensions.cpp b/src/tools/mmaps_generator/VMapExtensions.cpp index 4f203e11c21..2b525fbf353 100644 --- a/src/tools/mmaps_generator/VMapExtensions.cpp +++ b/src/tools/mmaps_generator/VMapExtensions.cpp @@ -57,7 +57,7 @@ namespace VMAP } // declared in src/shared/vmap/ModelInstance.h - WorldModel* const ModelInstance::getWorldModel() + WorldModel* ModelInstance::getWorldModel() { return iModel; } diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index a605118eead..56e62d474d1 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -69,8 +69,7 @@ void fixname2(char* name, size_t len) char* GetExtension(char* FileName) { - char* szTemp; - if (szTemp = strrchr(FileName, '.')) + if (char* szTemp = strrchr(FileName, '.')) return szTemp; return NULL; } diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index c642f73ccae..b950db023fe 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -152,10 +152,10 @@ ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID fseek(input, 8, SEEK_SET); // get the correct no of vertices int nVertices; - fread(&nVertices, sizeof (int), 1, input); + int count = fread(&nVertices, sizeof (int), 1, input); fclose(input); - if(nVertices == 0) + if (count != 1 || nVertices == 0) return; uint16 adtId = 0;// not used for models diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 186f9c8606e..89e4b850dac 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -461,8 +461,7 @@ int main(int argc, char ** argv) printf("Your output directory seems to be polluted, please use an empty directory!\n"); printf(""); char garbage[2]; - scanf("%c", garbage); - return 1; + return scanf("%c", garbage); } } diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 0bc749b9bd5..7c9f23c5a95 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -521,10 +521,10 @@ WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint fseek(input, 8, SEEK_SET); // get the correct no of vertices int nVertices; - fread(&nVertices, sizeof (int), 1, input); + int count = fread(&nVertices, sizeof (int), 1, input); fclose(input); - if(nVertices == 0) + if (count != 1 || nVertices == 0) return; float x,z; -- cgit v1.2.3 From cbf9324f61984727163150ed09a72288da45e3a4 Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Wed, 9 Jan 2013 21:01:39 +0100 Subject: Core: Fix build --- src/tools/mesh_extractor/DBC.cpp | 2 +- src/tools/mmaps_generator/MapBuilder.cpp | 10 +++++----- src/tools/mmaps_generator/PathCommon.h | 2 +- src/tools/mmaps_generator/TerrainBuilder.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/DBC.cpp b/src/tools/mesh_extractor/DBC.cpp index 5c54d975487..3c846363d06 100644 --- a/src/tools/mesh_extractor/DBC.cpp +++ b/src/tools/mesh_extractor/DBC.cpp @@ -5,7 +5,7 @@ DBC::DBC( FILE* stream ) : StringBlock(NULL), StringBlockSize(0), IsFaulty(true) { char magic[5]; - uint count = 0; + uint32 count = 0; count += fread(&magic, sizeof(char), 4, stream); magic[4] = '\0'; count += fread(&RecordCount, sizeof(uint32), 1, stream); diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 689ccdc906d..29591a406df 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -266,10 +266,10 @@ namespace MMAP return; } - uint verticesCount, indicesCount; - if (fread(&verticesCount, sizeof(uint), 1, file) != 1) + uint32 verticesCount, indicesCount; + if (fread(&verticesCount, sizeof(uint32), 1, file) != 1) return; - if (fread(&indicesCount, sizeof(uint), 1, file) != 1) + if (fread(&indicesCount, sizeof(uint32), 1, file) != 1) return; float* verts = new float[verticesCount]; @@ -282,10 +282,10 @@ namespace MMAP MeshData data; - for (uint i = 0; i < verticesCount; ++i) + for (uint32 i = 0; i < verticesCount; ++i) data.solidVerts.append(verts[i]); - for (uint i = 0; i < indicesCount; ++i) + for (uint32 i = 0; i < indicesCount; ++i) data.solidTris.append(inds[i]); TerrainBuilder::cleanVertices(data.solidVerts, data.solidTris); diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h index 966c12ec19e..8fad880212b 100644 --- a/src/tools/mmaps_generator/PathCommon.h +++ b/src/tools/mmaps_generator/PathCommon.h @@ -90,7 +90,7 @@ namespace MMAP return LISTFILE_DIRECTORY_NOT_FOUND; do { - if (includeSubDirs || (findFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) + if (findFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0) fileList.push_back(string(findFileInfo.cFileName)); } while (FindNextFile(hFind, &findFileInfo)); diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index 22946df478a..97e504d5160 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -235,7 +235,7 @@ namespace MMAP if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT)) { - uint toRead = lheader.width*lheader.height; + uint8 toRead = lheader.width*lheader.height; liquid_map = new float [toRead]; if (fread(liquid_map, sizeof(float), toRead, mapFile) != toRead) printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n"); -- cgit v1.2.3 From 7210ffe34d2052c1aee642ac3af40425c8ba137e Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Wed, 9 Jan 2013 21:14:12 +0100 Subject: Core: Fix warnings --- src/server/scripts/Commands/cs_mmaps.cpp | 10 +++++----- src/tools/mmaps_generator/PathCommon.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index c17c01adc33..09e777e4047 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -117,7 +117,7 @@ public: return true; } - static bool HandleMmapLocCommand(ChatHandler* handler, const char* args) + static bool HandleMmapLocCommand(ChatHandler* handler, char const* /*args*/) { handler->PSendSysMessage("mmap tileloc:"); @@ -171,7 +171,7 @@ public: return true; } - static bool HandleMmapLoadedTilesCommand(ChatHandler* handler, const char* args) + static bool HandleMmapLoadedTilesCommand(ChatHandler* handler, char const* /*args*/) { uint32 mapid = handler->GetSession()->GetPlayer()->GetMapId(); dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid); @@ -196,7 +196,7 @@ public: return true; } - static bool HandleMmapStatsCommand(ChatHandler* handler, const char* args) + static bool HandleMmapStatsCommand(ChatHandler* handler, char const* /*args*/) { uint32 mapId = handler->GetSession()->GetPlayer()->GetMapId(); handler->PSendSysMessage("mmap stats:"); @@ -244,12 +244,12 @@ public: return true; } - static bool HandleMmapTestArea(ChatHandler* handler, const char* args) + static bool HandleMmapTestArea(ChatHandler* handler, char const* /*args*/) { float radius = 40.0f; WorldObject* object = handler->GetSession()->GetPlayer(); - CellCoord pair(Trinity::ComputeCellCoord(object->GetPositionX(), object->GetPositionY()) ); + CellCoord pair(Trinity::ComputeCellCoord(object->GetPositionX(), object->GetPositionY())); Cell cell(pair); cell.SetNoCreate(); diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h index 8fad880212b..820ff34d425 100644 --- a/src/tools/mmaps_generator/PathCommon.h +++ b/src/tools/mmaps_generator/PathCommon.h @@ -90,7 +90,7 @@ namespace MMAP return LISTFILE_DIRECTORY_NOT_FOUND; do { - if (findFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0) + if ((findFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) fileList.push_back(string(findFileInfo.cFileName)); } while (FindNextFile(hFind, &findFileInfo)); -- cgit v1.2.3 From 1154c62b65af70e7801bb280aa90a98581d0c1ec Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Thu, 10 Jan 2013 12:40:26 +0100 Subject: Core/Tools: Fix logic fail for mmaps generator (thx armano2) --- src/tools/mmaps_generator/TerrainBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index 97e504d5160..d3c3772532d 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -235,7 +235,7 @@ namespace MMAP if (!(lheader.flags & MAP_LIQUID_NO_HEIGHT)) { - uint8 toRead = lheader.width*lheader.height; + uint32 toRead = lheader.width * lheader.height; liquid_map = new float [toRead]; if (fread(liquid_map, sizeof(float), toRead, mapFile) != toRead) printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n"); -- cgit v1.2.3 From dfbf318a4feb48d412391d7da1df9381310858ab Mon Sep 17 00:00:00 2001 From: Spp Date: Thu, 10 Jan 2013 15:29:08 +0100 Subject: Typo fix --- src/tools/map_extractor/adt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tools/map_extractor/adt.cpp b/src/tools/map_extractor/adt.cpp index 505813c4bd0..eeb69134fab 100644 --- a/src/tools/map_extractor/adt.cpp +++ b/src/tools/map_extractor/adt.cpp @@ -8,7 +8,7 @@ int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; u_map_fcc MHDRMagic = { {'M','H','D','R'} }; u_map_fcc MCINMagic = { {'M','C','I','N'} }; -u_map_fcc MH20Magic = { {'M','H','2','0'} }; +u_map_fcc MH2OMagic = { {'M','H','2','O'} }; u_map_fcc MCNKMagic = { {'M','C','N','K'} }; u_map_fcc MCVTMagic = { {'M','C','V','T'} }; u_map_fcc MCLQMagic = { {'M','C','L','Q'} }; @@ -93,7 +93,7 @@ bool adt_MCIN::prepareLoadedData() bool adt_MH2O::prepareLoadedData() { - if (fcc != MH20Magic.fcc) + if (fcc != MH2OMagic.fcc) return false; // Check liquid data -- cgit v1.2.3 From e783349803e64d0fd1879a97dcb4749435a87f05 Mon Sep 17 00:00:00 2001 From: Spp Date: Sat, 12 Jan 2013 02:15:10 +0100 Subject: Use correct initialization of some vars --- src/tools/map_extractor/adt.cpp | 12 ++++++------ src/tools/map_extractor/loadlib.cpp | 2 +- src/tools/map_extractor/wdt.cpp | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/tools/map_extractor/adt.cpp b/src/tools/map_extractor/adt.cpp index eeb69134fab..a93ead838fe 100644 --- a/src/tools/map_extractor/adt.cpp +++ b/src/tools/map_extractor/adt.cpp @@ -6,12 +6,12 @@ int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; -u_map_fcc MHDRMagic = { {'M','H','D','R'} }; -u_map_fcc MCINMagic = { {'M','C','I','N'} }; -u_map_fcc MH2OMagic = { {'M','H','2','O'} }; -u_map_fcc MCNKMagic = { {'M','C','N','K'} }; -u_map_fcc MCVTMagic = { {'M','C','V','T'} }; -u_map_fcc MCLQMagic = { {'M','C','L','Q'} }; +u_map_fcc MHDRMagic = { {'R','D','H','M'} }; +u_map_fcc MCINMagic = { {'N','I','C','M'} }; +u_map_fcc MH2OMagic = { {'0','2','H','M'} }; +u_map_fcc MCNKMagic = { {'K','N','C','M'} }; +u_map_fcc MCVTMagic = { {'T','V','C','M'} }; +u_map_fcc MCLQMagic = { {'Q','L','C','M'} }; bool isHole(int holes, int i, int j) { diff --git a/src/tools/map_extractor/loadlib.cpp b/src/tools/map_extractor/loadlib.cpp index d1ea40110de..5dcb479a11c 100644 --- a/src/tools/map_extractor/loadlib.cpp +++ b/src/tools/map_extractor/loadlib.cpp @@ -6,7 +6,7 @@ class MPQFile; -u_map_fcc MverMagic = { {'M','V','E','R'} }; +u_map_fcc MverMagic = { {'R','E','V','M'} }; FileLoader::FileLoader() { diff --git a/src/tools/map_extractor/wdt.cpp b/src/tools/map_extractor/wdt.cpp index 90a07eafab3..ff255145583 100644 --- a/src/tools/map_extractor/wdt.cpp +++ b/src/tools/map_extractor/wdt.cpp @@ -2,9 +2,9 @@ #include "wdt.h" -u_map_fcc MWMOMagic = { {'M', 'W', 'M', 'O'} }; -u_map_fcc MPHDMagic = { {'M', 'P', 'H', 'D'} }; -u_map_fcc MAINMagic = { {'M', 'A', 'I', 'N'} }; +u_map_fcc MWMOMagic = { {'O', 'M', 'W', 'M'} }; +u_map_fcc MPHDMagic = { {'D', 'H', 'P', 'M'} }; +u_map_fcc MAINMagic = { {'N', 'I', 'A', 'M'} }; bool wdt_MWMO::prepareLoadedData() { -- cgit v1.2.3 From 32e08bcd122fce70ae33eed3f0ec44d35a60eff2 Mon Sep 17 00:00:00 2001 From: Nay Date: Sun, 13 Jan 2013 02:11:21 +0000 Subject: Tools/Extractor: Fix yet another typo in ADT. Fixes extracting. Closes #8900 --- src/tools/map_extractor/adt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/map_extractor/adt.cpp b/src/tools/map_extractor/adt.cpp index a93ead838fe..30524dbd640 100644 --- a/src/tools/map_extractor/adt.cpp +++ b/src/tools/map_extractor/adt.cpp @@ -8,7 +8,7 @@ int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; u_map_fcc MHDRMagic = { {'R','D','H','M'} }; u_map_fcc MCINMagic = { {'N','I','C','M'} }; -u_map_fcc MH2OMagic = { {'0','2','H','M'} }; +u_map_fcc MH2OMagic = { {'O','2','H','M'} }; u_map_fcc MCNKMagic = { {'K','N','C','M'} }; u_map_fcc MCVTMagic = { {'T','V','C','M'} }; u_map_fcc MCLQMagic = { {'Q','L','C','M'} }; -- cgit v1.2.3 From 65cd79dc779e1900cb82e862ffab9ef3a20771ac Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Mon, 14 Jan 2013 17:42:06 +0100 Subject: Core/Misc: Update headers to 2013 --- src/server/collision/Management/MMapFactory.cpp | 2 +- src/server/collision/Management/MMapFactory.h | 2 +- src/server/collision/Management/MMapManager.cpp | 2 +- src/server/collision/Management/MMapManager.h | 2 +- src/server/scripts/Commands/cs_mmaps.cpp | 2 +- src/tools/mesh_extractor/CMakeLists.txt | 2 +- src/tools/mmaps_generator/IntermediateValues.cpp | 2 +- src/tools/mmaps_generator/IntermediateValues.h | 2 +- src/tools/mmaps_generator/MapBuilder.cpp | 2 +- src/tools/mmaps_generator/MapBuilder.h | 2 +- src/tools/mmaps_generator/PathCommon.h | 2 +- src/tools/mmaps_generator/TerrainBuilder.cpp | 2 +- src/tools/mmaps_generator/TerrainBuilder.h | 2 +- src/tools/mmaps_generator/VMapExtensions.cpp | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/server/collision/Management/MMapFactory.cpp b/src/server/collision/Management/MMapFactory.cpp index 0b292b56dca..7adf7fbfa66 100644 --- a/src/server/collision/Management/MMapFactory.cpp +++ b/src/server/collision/Management/MMapFactory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2010 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/server/collision/Management/MMapFactory.h b/src/server/collision/Management/MMapFactory.h index a006aedfa6d..00f19a194d3 100644 --- a/src/server/collision/Management/MMapFactory.h +++ b/src/server/collision/Management/MMapFactory.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2010 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp index 1b6cf5c0260..e3ed8f3310a 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/server/collision/Management/MMapManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2010 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h index 23b7d5fc6f8..56b1b856d65 100644 --- a/src/server/collision/Management/MMapManager.h +++ b/src/server/collision/Management/MMapManager.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2010 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 09e777e4047..4649e13e1c4 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2012 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * * 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 diff --git a/src/tools/mesh_extractor/CMakeLists.txt b/src/tools/mesh_extractor/CMakeLists.txt index 29c571d9301..b8bd9f54331 100644 --- a/src/tools/mesh_extractor/CMakeLists.txt +++ b/src/tools/mesh_extractor/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (C) 2005-2009 MaNGOS project -# Copyright (C) 2008-2012 TrinityCore +# Copyright (C) 2008-2013 TrinityCore # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without diff --git a/src/tools/mmaps_generator/IntermediateValues.cpp b/src/tools/mmaps_generator/IntermediateValues.cpp index b473d6472a0..6fad96887a2 100644 --- a/src/tools/mmaps_generator/IntermediateValues.cpp +++ b/src/tools/mmaps_generator/IntermediateValues.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/tools/mmaps_generator/IntermediateValues.h b/src/tools/mmaps_generator/IntermediateValues.h index 98042e1b917..89a5c3ae4c2 100644 --- a/src/tools/mmaps_generator/IntermediateValues.h +++ b/src/tools/mmaps_generator/IntermediateValues.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 29591a406df..9e6acd71a72 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index 61a71ff6d5b..c083e0b680a 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h index 820ff34d425..413f2b8735d 100644 --- a/src/tools/mmaps_generator/PathCommon.h +++ b/src/tools/mmaps_generator/PathCommon.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index d3c3772532d..f7cf76e9718 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/tools/mmaps_generator/TerrainBuilder.h b/src/tools/mmaps_generator/TerrainBuilder.h index 7a24146946b..6ad4284f416 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.h +++ b/src/tools/mmaps_generator/TerrainBuilder.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/tools/mmaps_generator/VMapExtensions.cpp b/src/tools/mmaps_generator/VMapExtensions.cpp index 2b525fbf353..37b7d94af55 100644 --- a/src/tools/mmaps_generator/VMapExtensions.cpp +++ b/src/tools/mmaps_generator/VMapExtensions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2011 TrinityCore + * Copyright (C) 2008-2013 TrinityCore * Copyright (C) 2005-2011 MaNGOS * * This program is free software; you can redistribute it and/or modify it -- cgit v1.2.3 From 98f502f32f092fe1bcb9e19c32c189d2ea552d19 Mon Sep 17 00:00:00 2001 From: MrSmite Date: Mon, 14 Jan 2013 21:42:23 -0500 Subject: Fix passive pets not using spells when commanded to attack Closes #8941 --- src/server/game/AI/CoreAI/PetAI.cpp | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index a8d2a2248ad..2792f68004f 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -432,29 +432,23 @@ void PetAI::HandleReturnMovement() if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning()) { // Return to previous position where stay was clicked - if (!me->GetCharmInfo()->IsCommandAttack()) - { - float x, y, z; + float x, y, z; - me->GetCharmInfo()->GetStayPosition(x, y, z); - ClearCharmInfoFlags(); - me->GetCharmInfo()->SetIsReturning(true); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(me->GetGUIDLow(), x, y, z); - } + me->GetCharmInfo()->GetStayPosition(x, y, z); + ClearCharmInfoFlags(); + me->GetCharmInfo()->SetIsReturning(true); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(me->GetGUIDLow(), x, y, z); } } else // COMMAND_FOLLOW { if (!me->GetCharmInfo()->IsFollowing() && !me->GetCharmInfo()->IsReturning()) { - if (!me->GetCharmInfo()->IsCommandAttack()) - { - ClearCharmInfoFlags(); - me->GetCharmInfo()->SetIsReturning(true); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveFollow(me->GetCharmerOrOwner(), PET_FOLLOW_DIST, me->GetFollowAngle()); - } + ClearCharmInfoFlags(); + me->GetCharmInfo()->SetIsReturning(true); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveFollow(me->GetCharmerOrOwner(), PET_FOLLOW_DIST, me->GetFollowAngle()); } } } @@ -473,12 +467,13 @@ void PetAI::DoAttack(Unit* target, bool chase) if (me->HasReactState(REACT_AGGRESSIVE) && !me->GetCharmInfo()->IsCommandAttack()) me->SendPetAIReaction(me->GetGUID()); - if (chase) { - ClearCharmInfoFlags(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(target); + bool oldCmdAttack = me->GetCharmInfo()->IsCommandAttack(); // This needs to be reset after other flags are cleared + ClearCharmInfoFlags(); + me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(target); } else // (Stay && ((Aggressive || Defensive) && In Melee Range))) { -- cgit v1.2.3 From 6191642e5902fe8e670c8172a1a918d48a84683f Mon Sep 17 00:00:00 2001 From: Naios Date: Thu, 17 Jan 2013 14:04:20 +0100 Subject: Core/SmartScripts: Check Conditions also for timed Events * some cleanup work in SmartScripts.cpp Core/SmartScripts: Some Corrections to last commit --- src/server/game/AI/SmartScripts/SmartScript.cpp | 64 +++++++++++-------------- src/server/game/AI/SmartScripts/SmartScript.h | 1 + 2 files changed, 29 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 84c9dffabd2..86d86739bc9 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2011,6 +2011,17 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } } +void SmartScript::ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob) +{ + ConditionList const conds = sConditionMgr->GetConditionsForSmartEvent(e.entryOrGuid, e.event_id, e.source_type); + ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject()); + + if (sConditionMgr->IsObjectMeetToConditions(info, conds)) + ProcessAction(e, unit, var0, var1, bvar, spell, gob); + + RecalcTimer(e, min, max); +} + void SmartScript::InstallTemplate(SmartScriptHolder const& e) { if (!GetBaseObject()) @@ -2409,20 +2420,17 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui break; //called from Update tick case SMART_EVENT_UPDATE: - RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); - ProcessAction(e); + ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); break; case SMART_EVENT_UPDATE_OOC: if (me && me->isInCombat()) return; - RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); - ProcessAction(e); + ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); break; case SMART_EVENT_UPDATE_IC: if (!me || !me->isInCombat()) return; - RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); - ProcessAction(e); + ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); break; case SMART_EVENT_HEALT_PCT: { @@ -2431,8 +2439,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui uint32 perc = (uint32)me->GetHealthPct(); if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) return; - RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); - ProcessAction(e); + ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); break; } case SMART_EVENT_TARGET_HEALTH_PCT: @@ -2442,8 +2449,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui uint32 perc = (uint32)me->getVictim()->GetHealthPct(); if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) return; - RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); - ProcessAction(e, me->getVictim()); + ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->getVictim()); break; } case SMART_EVENT_MANA_PCT: @@ -2453,8 +2459,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui uint32 perc = uint32(100.0f * me->GetPower(POWER_MANA) / me->GetMaxPower(POWER_MANA)); if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) return; - RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); - ProcessAction(e); + ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); break; } case SMART_EVENT_TARGET_MANA_PCT: @@ -2464,8 +2469,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui uint32 perc = uint32(100.0f * me->getVictim()->GetPower(POWER_MANA) / me->getVictim()->GetMaxPower(POWER_MANA)); if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) return; - RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); - ProcessAction(e, me->getVictim()); + ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->getVictim()); break; } case SMART_EVENT_RANGE: @@ -2474,18 +2478,15 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui return; if (me->IsInRange(me->getVictim(), (float)e.event.minMaxRepeat.min, (float)e.event.minMaxRepeat.max)) - { - ProcessAction(e, me->getVictim()); - RecalcTimer(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); - } + ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->getVictim()); break; } case SMART_EVENT_TARGET_CASTING: { if (!me || !me->isInCombat() || !me->getVictim() || !me->getVictim()->IsNonMeleeSpellCasted(false, false, true)) return; - ProcessAction(e, me->getVictim()); - RecalcTimer(e, e.event.minMax.repeatMin, e.event.minMax.repeatMax); + + ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->getVictim()); } case SMART_EVENT_FRIENDLY_HEALTH: { @@ -2495,8 +2496,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui Unit* target = DoSelectLowestHpFriendly((float)e.event.friendlyHealt.radius, e.event.friendlyHealt.hpDeficit); if (!target) return; - ProcessAction(e, target); - RecalcTimer(e, e.event.friendlyHealt.repeatMin, e.event.friendlyHealt.repeatMax); + ProcessTimedAction(e, e.event.friendlyHealt.repeatMin, e.event.friendlyHealt.repeatMax, target); break; } case SMART_EVENT_FRIENDLY_IS_CC: @@ -2508,8 +2508,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui DoFindFriendlyCC(pList, (float)e.event.friendlyCC.radius); if (pList.empty()) return; - ProcessAction(e, *(pList.begin())); - RecalcTimer(e, e.event.friendlyCC.repeatMin, e.event.friendlyCC.repeatMax); + ProcessTimedAction(e, e.event.friendlyCC.repeatMin, e.event.friendlyCC.repeatMax, *pList.begin()); break; } case SMART_EVENT_FRIENDLY_MISSING_BUFF: @@ -2519,8 +2518,8 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (pList.empty()) return; - ProcessAction(e, *(pList.begin())); - RecalcTimer(e, e.event.missingBuff.repeatMin, e.event.missingBuff.repeatMax); + + ProcessTimedAction(e, e.event.missingBuff.repeatMin, e.event.missingBuff.repeatMax, *pList.begin()); break; } case SMART_EVENT_HAS_AURA: @@ -2529,10 +2528,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui return; uint32 count = me->GetAuraCount(e.event.aura.spell); if ((!e.event.aura.count && !count) || (e.event.aura.count && count >= e.event.aura.count)) - { - ProcessAction(e); - RecalcTimer(e, e.event.aura.repeatMin, e.event.aura.repeatMax); - } + ProcessTimedAction(e, e.event.aura.repeatMin, e.event.aura.repeatMax); break; } case SMART_EVENT_TARGET_BUFFED: @@ -2542,8 +2538,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui uint32 count = me->getVictim()->GetAuraCount(e.event.aura.spell); if (count < e.event.aura.count) return; - ProcessAction(e); - RecalcTimer(e, e.event.aura.repeatMin, e.event.aura.repeatMax); + ProcessTimedAction(e, e.event.aura.repeatMin, e.event.aura.repeatMax); break; } //no params @@ -2578,10 +2573,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (Unit* victim = me->getVictim()) { if (!victim->HasInArc(static_cast(M_PI), me)) - { - ProcessAction(e, victim); - RecalcTimer(e, e.event.behindTarget.cooldownMin, e.event.behindTarget.cooldownMax); - } + ProcessTimedAction(e, e.event.behindTarget.cooldownMin, e.event.behindTarget.cooldownMax, victim); } break; } diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index d0d0221493f..28b328a2947 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -45,6 +45,7 @@ class SmartScript void UpdateTimer(SmartScriptHolder& e, uint32 const diff); void InitTimer(SmartScriptHolder& e); void ProcessAction(SmartScriptHolder& e, Unit* unit = NULL, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = NULL, GameObject* gob = NULL); + void ProcessTimedAction(SmartScriptHolder& e, uint32 const& min, uint32 const& max, Unit* unit = NULL, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, const SpellInfo* spell = NULL, GameObject* gob = NULL); ObjectList* GetTargets(SmartScriptHolder const& e, Unit* invoker = NULL); ObjectList* GetWorldObjectsInDist(float dist); void InstallTemplate(SmartScriptHolder const& e); -- cgit v1.2.3 From ed44eea699379b4da814b85c22c0f87682cccc0c Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Sat, 19 Jan 2013 20:28:29 +0100 Subject: Core: Fix warnings --- .../scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp | 4 ++-- .../scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp index 58e130ce644..19660cec4af 100644 --- a/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp @@ -66,8 +66,8 @@ enum eMisc Position const PosMove[2] = { - { 299.4884f, 92.76137f, 105.6335f }, - { 314.8673f, 90.30210f, 101.6459f } + { 299.4884f, 92.76137f, 105.6335f, 0.0f }, + { 314.8673f, 90.30210f, 101.6459f, 0.0f } }; class boss_kirtonos_the_herald : public CreatureScript diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index 7f8108e5e71..6039e01b901 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -359,7 +359,7 @@ class boss_halion : public CreatureScript if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_TWILIGHT_HALION))) if (twilightHalion->isAlive()) twilightHalion->Kill(twilightHalion); - + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_HALION_CONTROLLER))) if (controller->isAlive()) controller->Kill(controller); -- cgit v1.2.3 From e524539d90f7c1b3393754641729fa844119b881 Mon Sep 17 00:00:00 2001 From: Gacko Date: Sat, 19 Jan 2013 19:17:31 +0100 Subject: Core/CS: More npcflag info in .npc info --- .../world/2013_01_19_06_world_trinity_string.sql | 28 ++++++++++++++ src/server/game/Miscellaneous/Language.h | 27 ++++++++++++- src/server/scripts/Commands/cs_npc.cpp | 44 +++++++++++++++++++--- 3 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 sql/updates/world/2013_01_19_06_world_trinity_string.sql (limited to 'src') diff --git a/sql/updates/world/2013_01_19_06_world_trinity_string.sql b/sql/updates/world/2013_01_19_06_world_trinity_string.sql new file mode 100644 index 00000000000..322d43a7720 --- /dev/null +++ b/sql/updates/world/2013_01_19_06_world_trinity_string.sql @@ -0,0 +1,28 @@ +DELETE FROM `trinity_string` WHERE `entry` BETWEEN 820 AND 842; +INSERT INTO `trinity_string`(`entry`,`content_default`) VALUES +(820,'* has gossip (%u)'), +(821,'* is quest giver (%u)'), +(822,'* is class trainer (%u)'), +(823,'* is profession trainer(%u)'), +(824,'* is ammo vendor (%u)'), +(825,'* is food vendor(%u)'), +(826,'* is poison vendor (%u)'), +(827,'* is reagent vendor (%u)'), +(828,'* can repair (%u)'), +(829,'* is flight master (%u)'), +(830,'* is spirit healer (%u)'), +(831,'* is spirit guide (%u)'), +(832,'* is innkeeper (%u)'), +(833,'* is banker (%u)'), +(834,'* is petitioner (%u)'), +(835,'* is tabard designer (%u)'), +(836,'* is battle master (%u)'), +(837,'* is auctioneer (%u)'), +(838,'* is stable master (%u)'), +(839,'* is guild banker (%u)'), +(840,'* has spell click (%u)'), +(841,'* is mailbox (%u)'), +(842,'* is player vehicle (%u)'); + +UPDATE `trinity_string` SET `content_default`='* is vendor (%u)' WHERE `entry`=545; +UPDATE `trinity_string` SET `content_default`='* is trainer (%u)' WHERE `entry`=546; diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 292833c3955..35b0a6f8569 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -742,7 +742,32 @@ enum TrinityStrings LANG_COMMAND_CREATURESTORAGE_NOTFOUND = 818, LANG_CHANNEL_CITY = 819, - // Room for in-game strings 820-999 not used + + LANG_NPCINFO_GOSSIP = 820, + LANG_NPCINFO_QUESTGIVER = 821, + LANG_NPCINFO_TRAINER_CLASS = 822, + LANG_NPCINFO_TRAINER_PROFESSION = 823, + LANG_NPCINFO_VENDOR_AMMO = 824, + LANG_NPCINFO_VENDOR_FOOD = 825, + LANG_NPCINFO_VENDOR_POISON = 826, + LANG_NPCINFO_VENDOR_REAGENT = 827, + LANG_NPCINFO_REPAIR = 828, + LANG_NPCINFO_FLIGHTMASTER = 829, + LANG_NPCINFO_SPIRITHEALER = 830, + LANG_NPCINFO_SPIRITGUIDE = 831, + LANG_NPCINFO_INNKEEPER = 832, + LANG_NPCINFO_BANKER = 833, + LANG_NPCINFO_PETITIONER = 834, + LANG_NPCINFO_TABARDDESIGNER = 835, + LANG_NPCINFO_BATTLEMASTER = 836, + LANG_NPCINFO_AUCTIONEER = 837, + LANG_NPCINFO_STABLEMASTER = 838, + LANG_NPCINFO_GUILD_BANKER = 839, + LANG_NPCINFO_SPELLCLICK = 840, + LANG_NPCINFO_MAILBOX = 841, + LANG_NPCINFO_PLAYER_VEHICLE = 842, + + // Room for in-game strings 843-999 not used // Level 4 (CLI only commands) LANG_COMMAND_EXIT = 1000, diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 8679e288282..7ccd5ed1177 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -33,6 +33,42 @@ EndScriptData */ #include "Player.h" #include "Pet.h" +struct NpcFlagText +{ + uint32 flag; + int32 text; +}; + +#define NPCFLAG_COUNT 24 + +const NpcFlagText npcFlagTexts[NPCFLAG_COUNT] = +{ + { UNIT_NPC_FLAG_AUCTIONEER, LANG_NPCINFO_AUCTIONEER }, + { UNIT_NPC_FLAG_BANKER, LANG_NPCINFO_BANKER }, + { UNIT_NPC_FLAG_BATTLEMASTER, LANG_NPCINFO_BATTLEMASTER }, + { UNIT_NPC_FLAG_FLIGHTMASTER, LANG_NPCINFO_FLIGHTMASTER }, + { UNIT_NPC_FLAG_GOSSIP, LANG_NPCINFO_GOSSIP }, + { UNIT_NPC_FLAG_GUILD_BANKER, LANG_NPCINFO_GUILD_BANKER }, + { UNIT_NPC_FLAG_INNKEEPER, LANG_NPCINFO_INNKEEPER }, + { UNIT_NPC_FLAG_PETITIONER, LANG_NPCINFO_PETITIONER }, + { UNIT_NPC_FLAG_PLAYER_VEHICLE, LANG_NPCINFO_PLAYER_VEHICLE }, + { UNIT_NPC_FLAG_QUESTGIVER, LANG_NPCINFO_QUESTGIVER }, + { UNIT_NPC_FLAG_REPAIR, LANG_NPCINFO_REPAIR }, + { UNIT_NPC_FLAG_SPELLCLICK, LANG_NPCINFO_SPELLCLICK }, + { UNIT_NPC_FLAG_SPIRITGUIDE, LANG_NPCINFO_SPIRITGUIDE }, + { UNIT_NPC_FLAG_SPIRITHEALER, LANG_NPCINFO_SPIRITHEALER }, + { UNIT_NPC_FLAG_STABLEMASTER, LANG_NPCINFO_STABLEMASTER }, + { UNIT_NPC_FLAG_TABARDDESIGNER, LANG_NPCINFO_TABARDDESIGNER }, + { UNIT_NPC_FLAG_TRAINER, LANG_NPCINFO_TRAINER }, + { UNIT_NPC_FLAG_TRAINER_CLASS, LANG_NPCINFO_TRAINER_CLASS }, + { UNIT_NPC_FLAG_TRAINER_PROFESSION, LANG_NPCINFO_TRAINER_PROFESSION }, + { UNIT_NPC_FLAG_VENDOR, LANG_NPCINFO_VENDOR }, + { UNIT_NPC_FLAG_VENDOR_AMMO, LANG_NPCINFO_VENDOR_AMMO }, + { UNIT_NPC_FLAG_VENDOR_FOOD, LANG_NPCINFO_VENDOR_FOOD }, + { UNIT_NPC_FLAG_VENDOR_POISON, LANG_NPCINFO_VENDOR_POISON }, + { UNIT_NPC_FLAG_VENDOR_REAGENT, LANG_NPCINFO_VENDOR_REAGENT } +}; + class npc_commandscript : public CommandScript { public: @@ -619,11 +655,9 @@ public: handler->PSendSysMessage(LANG_NPCINFO_POSITION, float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); handler->PSendSysMessage(LANG_NPCINFO_AIINFO, target->GetAIName().c_str(), target->GetScriptName().c_str()); - if (npcflags & UNIT_NPC_FLAG_VENDOR) - handler->SendSysMessage(LANG_NPCINFO_VENDOR); - - if (npcflags & UNIT_NPC_FLAG_TRAINER) - handler->SendSysMessage(LANG_NPCINFO_TRAINER); + for (uint8 i = 0; i < NPCFLAG_COUNT; i++) + if (npcflags & npcFlagTexts[i].flag) + handler->PSendSysMessage(npcFlagTexts[i].text, npcFlagTexts[i].flag); return true; } -- cgit v1.2.3 From c38d95ac33e44ea30908b5d8e8707848094dd5f0 Mon Sep 17 00:00:00 2001 From: joschiwald Date: Sun, 20 Jan 2013 04:30:17 +0100 Subject: Core/Spells: convert some spells to SpellScripts --- .../2013_01_20_03_world_spell_script_names.sql | 81 ++++++ src/server/game/Spells/Auras/SpellAuraEffects.cpp | 284 +-------------------- src/server/game/Spells/Spell.cpp | 5 - src/server/game/Spells/SpellEffects.cpp | 191 +------------- src/server/scripts/Spells/spell_dk.cpp | 107 ++++++++ src/server/scripts/Spells/spell_druid.cpp | 205 +++++++++++++++ src/server/scripts/Spells/spell_generic.cpp | 155 +++++++++++ src/server/scripts/Spells/spell_holiday.cpp | 87 +++++-- src/server/scripts/Spells/spell_item.cpp | 225 ++++++++++++++++ src/server/scripts/Spells/spell_mage.cpp | 178 ++++++++----- src/server/scripts/Spells/spell_paladin.cpp | 111 ++++++++ src/server/scripts/Spells/spell_priest.cpp | 148 ++++++++--- src/server/scripts/Spells/spell_rogue.cpp | 53 ++++ src/server/scripts/Spells/spell_shaman.cpp | 31 +++ src/server/scripts/Spells/spell_warlock.cpp | 38 +++ src/server/scripts/Spells/spell_warrior.cpp | 141 ++++++++++ 16 files changed, 1447 insertions(+), 593 deletions(-) create mode 100644 sql/updates/world/2013_01_20_03_world_spell_script_names.sql (limited to 'src') diff --git a/sql/updates/world/2013_01_20_03_world_spell_script_names.sql b/sql/updates/world/2013_01_20_03_world_spell_script_names.sql new file mode 100644 index 00000000000..0cd28de0472 --- /dev/null +++ b/sql/updates/world/2013_01_20_03_world_spell_script_names.sql @@ -0,0 +1,81 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` IN ( +48792, -- spell_dk_icebound_fortitude +59754, -- spell_dk_rune_tap_party +55233, -- spell_dk_vampiric_blood +-1850, -- spell_dru_dash +48391, -- spell_dru_owlkin_frenzy +29166, -- spell_dru_innervate +34246, -- spell_dru_idol_lifebloom +60779, -- spell_dru_idol_lifebloom +-1079, -- spell_dru_rip +-61391,-- spell_dru_typhoon +63845, -- spell_gen_create_lance +28702, -- spell_gen_netherbloom +28720, -- spell_gen_nightmare_vine +26400, -- spell_item_arcane_shroud +8342, -- spell_item_goblin_jumper_cables +22999, -- spell_item_goblin_jumper_cables_xl +54732, -- spell_item_gnomish_army_knife +17512, -- spell_item_piccolo_of_the_flaming_fire +48129, -- spell_item_scroll_of_recall +60320, -- spell_item_scroll_of_recall +60321, -- spell_item_scroll_of_recall +28862, -- spell_item_the_eye_of_diminution +-543, -- spell_mage_fire_frost_ward +-6143, -- spell_mage_fire_frost_ward +-11426,-- spell_mage_ice_barrier +-1463, -- spell_mage_mana_shield +1038, -- spell_pal_hand_of_salvation +58597, -- spell_pal_sacred_shield +-7001, -- spell_pri_lightwell_renew +-17, -- spell_pri_power_word_shield +-1943, -- spell_rog_rupture +-51490,-- spell_sha_thunderstorm +-7235, -- spell_warl_shadow_ward +5246, -- spell_warr_intimidating_shout +-772, -- spell_warr_rend +64380, -- spell_warr_shattering_throw +65941, -- spell_warr_shattering_throw +50725, -- spell_warr_vigilance_trigger +26275 -- spell_winter_veil_px_238_winter_wondervolt +); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(48792, 'spell_dk_icebound_fortitude'), +(59754, 'spell_dk_rune_tap_party'), +(55233, 'spell_dk_vampiric_blood'), +(-1850, 'spell_dru_dash'), +(48391, 'spell_dru_owlkin_frenzy'), +(29166, 'spell_dru_innervate'), +(34246, 'spell_dru_idol_lifebloom'), +(60779, 'spell_dru_idol_lifebloom'), +(-1079, 'spell_dru_rip'), +(-61391,'spell_dru_typhoon'), +(63845, 'spell_gen_create_lance'), +(28702, 'spell_gen_netherbloom'), +(28720, 'spell_gen_nightmare_vine'), +(26400, 'spell_item_arcane_shroud'), +(8342, 'spell_item_goblin_jumper_cables'), +(22999, 'spell_item_goblin_jumper_cables_xl'), +(54732, 'spell_item_gnomish_army_knife'), +(17512, 'spell_item_piccolo_of_the_flaming_fire'), +(48129, 'spell_item_scroll_of_recall'), +(60320, 'spell_item_scroll_of_recall'), +(60321, 'spell_item_scroll_of_recall'), +(28862, 'spell_item_the_eye_of_diminution'), +(-543, 'spell_mage_fire_frost_ward'), +(-6143, 'spell_mage_fire_frost_ward'), +(-11426,'spell_mage_ice_barrier'), +(-1463, 'spell_mage_mana_shield'), +(1038, 'spell_pal_hand_of_salvation'), +(58597, 'spell_pal_sacred_shield'), +(-7001, 'spell_pri_lightwell_renew'), +(-17, 'spell_pri_power_word_shield'), +(-1943, 'spell_rog_rupture'), +(-51490,'spell_sha_thunderstorm'), +(-7235, 'spell_warl_shadow_ward'), +(5246, 'spell_warr_intimidating_shout'), +(-772, 'spell_warr_rend'), +(64380, 'spell_warr_shattering_throw'), +(65941, 'spell_warr_shattering_throw'), +(50725, 'spell_warr_vigilance_trigger'), +(26275, 'spell_winter_veil_px_238_winter_wondervolt'); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 3b5c6131c5a..05da36d2ccc 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -483,112 +483,8 @@ int32 AuraEffect::CalculateAmount(Unit* caster) } break; case SPELL_AURA_SCHOOL_ABSORB: - m_canBeRecalculated = false; - if (!caster) - break; - switch (GetSpellInfo()->SpellFamilyName) - { - case SPELLFAMILY_MAGE: - // Ice Barrier - if (GetSpellInfo()->SpellFamilyFlags[1] & 0x1 && GetSpellInfo()->SpellFamilyFlags[2] & 0x8) - { - // +80.68% from sp bonus - DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8068f; - // Glyph of Ice Barrier: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :) - // Glyph of Ice Barrier is only applied at the spell damage bonus because it was already applied to the base value in CalculateSpellDamage - DoneActualBenefit = caster->ApplyEffectModifiers(GetSpellInfo(), m_effIndex, DoneActualBenefit); - } - // Fire Ward - else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x8 && GetSpellInfo()->SpellFamilyFlags[2] & 0x8) - { - // +80.68% from sp bonus - DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8068f; - } - // Frost Ward - else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x100 && GetSpellInfo()->SpellFamilyFlags[2] & 0x8) - { - // +80.68% from sp bonus - DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8068f; - } - break; - case SPELLFAMILY_WARLOCK: - // Shadow Ward - if (m_spellInfo->SpellFamilyFlags[2] & 0x40) - { - // +80.68% from sp bonus - DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8068f; - } - break; - case SPELLFAMILY_PRIEST: - // Power Word: Shield - if (GetSpellInfo()->SpellFamilyFlags[0] & 0x1 && GetSpellInfo()->SpellFamilyFlags[2] & 0x400) - { - // +80.68% from sp bonus - float bonus = 0.8068f; - - // Borrowed Time - if (AuraEffect const* pAurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 2899, 1)) - bonus += CalculatePct(1.0f, pAurEff->GetAmount()); - - DoneActualBenefit += caster->SpellBaseHealingBonusDone(m_spellInfo->GetSchoolMask()) * bonus; - // Improved PW: Shield: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :) - // Improved PW: Shield is only applied at the spell healing bonus because it was already applied to the base value in CalculateSpellDamage - DoneActualBenefit = caster->ApplyEffectModifiers(GetSpellInfo(), m_effIndex, DoneActualBenefit); - DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellInfo()); - - amount += int32(DoneActualBenefit); - - // Twin Disciplines - if (AuraEffect const* pAurEff = caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_PRIEST, 0x400000, 0, 0, caster->GetGUID())) - AddPct(amount, pAurEff->GetAmount()); - - // Focused Power - // Reuse variable, not sure if this code below can be moved before Twin Disciplines - DoneActualBenefit = float(amount); - DoneActualBenefit *= caster->GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_DONE_PERCENT); - amount = int32(DoneActualBenefit); - - return amount; - } - break; - case SPELLFAMILY_PALADIN: - // Sacred Shield - if (m_spellInfo->SpellFamilyFlags[1] & 0x80000) - { - //+75.00% from sp bonus - float bonus = 0.75f; - - DoneActualBenefit += caster->SpellBaseHealingBonusDone(m_spellInfo->GetSchoolMask()) * bonus; - // Divine Guardian is only applied at the spell healing bonus because it was already applied to the base value in CalculateSpellDamage - DoneActualBenefit = caster->ApplyEffectModifiers(GetSpellInfo(), m_effIndex, DoneActualBenefit); - DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellInfo()); - - amount += (int32)DoneActualBenefit; - - // Arena - Dampening - AuraEffect const* pAurEff = caster->GetAuraEffect(74410, 0); - if (!pAurEff) - pAurEff = caster->GetAuraEffect(74411, 0); // Battleground - Dampening - if (pAurEff) - AddPct(amount, pAurEff->GetAmount()); - - return amount; - } - break; - default: - break; - } - break; case SPELL_AURA_MANA_SHIELD: m_canBeRecalculated = false; - if (!caster) - break; - // Mana Shield - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_MAGE && GetSpellInfo()->SpellFamilyFlags[0] & 0x8000 && m_spellInfo->SpellFamilyFlags[2] & 0x8) - { - // +80.53% from +spd bonus - DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8053f; - } break; case SPELL_AURA_DUMMY: if (!caster) @@ -600,161 +496,9 @@ int32 AuraEffect::CalculateAmount(Unit* caster) amount = GetBase()->GetUnitOwner()->SpellHealingBonusTaken(caster, GetSpellInfo(), amount, SPELL_DIRECT_DAMAGE); } break; - case SPELL_AURA_PERIODIC_DAMAGE: - if (!caster) - break; - // Rupture - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellInfo->SpellFamilyFlags[0] & 0x100000) - { - m_canBeRecalculated = false; - if (caster->GetTypeId() != TYPEID_PLAYER) - break; - //1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs - //2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs - //3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs - //4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs - //5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs - float AP_per_combo[6] = {0.0f, 0.015f, 0.024f, 0.03f, 0.03428571f, 0.0375f}; - uint8 cp = caster->ToPlayer()->GetComboPoints(); - if (cp > 5) cp = 5; - amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]); - } - // Rip - else if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[0] & 0x00800000 && GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE) - { - m_canBeRecalculated = false; - // 0.01*$AP*cp - if (caster->GetTypeId() != TYPEID_PLAYER) - break; - - uint8 cp = caster->ToPlayer()->GetComboPoints(); - - // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs - if (AuraEffect const* aurEff = caster->GetAuraEffect(34241, EFFECT_0)) - amount += cp * aurEff->GetAmount(); - // Idol of Worship. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs - else if (AuraEffect const* aurEff = caster->GetAuraEffect(60774, EFFECT_0)) - amount += cp * aurEff->GetAmount(); - - amount += uint32(CalculatePct(caster->GetTotalAttackPowerValue(BASE_ATTACK), cp)); - } - // Rend - else if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARRIOR && GetSpellInfo()->SpellFamilyFlags[0] & 0x20) - { - m_canBeRecalculated = false; - // $0.2 * (($MWB + $mwb) / 2 + $AP / 14 * $MWS) bonus per tick - float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 mws = caster->GetAttackTime(BASE_ATTACK); - float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); - float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); - float mwb = ((mwb_min + mwb_max) / 2 + ap * mws / 14000) * 0.2f; - amount += int32(caster->ApplyEffectModifiers(m_spellInfo, m_effIndex, mwb)); - // "If used while your target is above 75% health, Rend does 35% more damage." - // as for 3.1.3 only ranks above 9 (wrong tooltip?) - if (m_spellInfo->GetRank() >= 9) - { - if (GetBase()->GetUnitOwner()->HasAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, m_spellInfo, caster)) - AddPct(amount, m_spellInfo->Effects[EFFECT_2].CalcValue(caster)); - } - } - break; - case SPELL_AURA_PERIODIC_ENERGIZE: - switch (m_spellInfo->Id) - { - case 29166: // Innervate - ApplyPct(amount, float(GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA)) / GetTotalTicks()); - break; - case 48391: // Owlkin Frenzy - ApplyPct(amount, GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA)); - break; - default: - break; - } - break; - case SPELL_AURA_PERIODIC_HEAL: - if (!caster) - break; - // Lightwell Renew - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_PRIEST && m_spellInfo->SpellFamilyFlags[2] & 0x4000) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - // Bonus from Glyph of Lightwell - if (AuraEffect* modHealing = caster->GetAuraEffect(55673, 0)) - AddPct(amount, modHealing->GetAmount()); - } - break; - case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: - if (!caster) - break; - // Icebound Fortitude - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00100000) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - { - int32 value = (-1 * amount) - 10; - uint32 defva = uint32(caster->ToPlayer()->GetSkillValue(SKILL_DEFENSE) + caster->ToPlayer()->GetRatingBonusValue(CR_DEFENSE_SKILL)); - - if (defva > 400) - value += int32((defva - 400) * 0.15); - - // Glyph of Icebound Fortitude - if (AuraEffect const* aurEff = caster->GetAuraEffect(58625, 0)) - { - int32 valMax = aurEff->GetAmount(); - if (value < valMax) - value = valMax; - } - amount = -value; - } - } - // Hand of Salvation - else if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_PALADIN && GetSpellInfo()->SpellFamilyFlags[0] & 0x00000100) - { - //Glyph of Salvation - if (caster->GetGUID() == GetBase()->GetUnitOwner()->GetGUID()) - if (AuraEffect const* aurEff = caster->GetAuraEffect(63225, 0)) - amount = -aurEff->GetAmount(); - } - break; - case SPELL_AURA_MOD_THREAT: - { - uint8 level_diff = 0; - float multiplier = 0.0f; - switch (GetId()) - { - // Arcane Shroud - case 26400: - level_diff = GetBase()->GetUnitOwner()->getLevel() - 60; - multiplier = 2; - break; - // The Eye of Diminution - case 28862: - level_diff = GetBase()->GetUnitOwner()->getLevel() - 60; - multiplier = 1; - break; - } - if (level_diff > 0) - amount += int32(multiplier * level_diff); - break; - } - case SPELL_AURA_MOD_INCREASE_HEALTH: - // Vampiric Blood - if (GetId() == 55233) - amount = GetBase()->GetUnitOwner()->CountPctFromMaxHealth(amount); - break; - case SPELL_AURA_MOD_INCREASE_SPEED: - // Dash - do not set speed if not in cat form - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_DRUID && GetSpellInfo()->SpellFamilyFlags[2] & 0x00000008) - amount = GetBase()->GetUnitOwner()->GetShapeshiftForm() == FORM_CAT ? amount : 0; - break; default: break; } - if (DoneActualBenefit != 0.0f) - { - DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellInfo()); - amount += (int32)DoneActualBenefit; - } GetBase()->CallScriptEffectCalcAmountHandlers(const_cast(this), amount, m_canBeRecalculated); amount *= GetBase()->GetStackAmount(); @@ -848,32 +592,6 @@ void AuraEffect::CalculateSpellMod() { switch (GetAuraType()) { - case SPELL_AURA_DUMMY: - switch (GetSpellInfo()->SpellFamilyName) - { - case SPELLFAMILY_DRUID: - switch (GetId()) - { - case 34246: // Idol of the Emerald Queen - case 60779: // Idol of Lush Moss - { - if (!m_spellmod) - { - m_spellmod = new SpellModifier(GetBase()); - m_spellmod->op = SPELLMOD_DOT; - m_spellmod->type = SPELLMOD_FLAT; - m_spellmod->spellId = GetId(); - m_spellmod->mask[1] = 0x0010; - } - m_spellmod->value = GetAmount()/7; - } - break; - } - break; - default: - break; - } - break; case SPELL_AURA_ADD_FLAT_MODIFIER: case SPELL_AURA_ADD_PCT_MODIFIER: if (!m_spellmod) @@ -882,7 +600,7 @@ void AuraEffect::CalculateSpellMod() m_spellmod->op = SpellModOp(GetMiscValue()); ASSERT(m_spellmod->op < MAX_SPELLMOD); - m_spellmod->type = SpellModType(GetAuraType()); // SpellModType value == spell aura types + m_spellmod->type = SpellModType(GetAuraType()); // SpellModType value == spell aura types m_spellmod->spellId = GetId(); m_spellmod->mask = GetSpellInfo()->Effects[GetEffIndex()].SpellClassMask; m_spellmod->charges = GetBase()->GetCharges(); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 9bb3eaa31f1..054f6a109db 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1345,11 +1345,6 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge } } - // todo: move to scripts, but we must call it before resize list by MaxAffectedTargets - // Intimidating Shout - if (m_spellInfo->Id == 5246 && effIndex != EFFECT_0) - unitTargets.remove(m_targets.GetUnitTarget()); - // Other special target selection goes here if (uint32 maxTargets = m_spellValue->MaxAffectedTargets) { diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 1dddb08be0b..4fdf6654cba 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -883,12 +883,6 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) m_caster->CastSpell(unitTarget, spell->Id, true); return; } - // Righteous Defense - case 31980: - { - m_caster->CastSpell(unitTarget, 31790, true); - return; - } // Cloak of Shadows case 35729: { @@ -1139,32 +1133,8 @@ void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/) return; // Pre effects - uint8 uiMaxSafeLevel = 0; switch (m_spellInfo->Id) { - case 48129: // Scroll of Recall - uiMaxSafeLevel = 40; - case 60320: // Scroll of Recall II - if (!uiMaxSafeLevel) - uiMaxSafeLevel = 70; - case 60321: // Scroll of Recal III - if (!uiMaxSafeLevel) - uiMaxSafeLevel = 80; - - if (unitTarget->getLevel() > uiMaxSafeLevel) - { - unitTarget->AddAura(60444, unitTarget); //Apply Lost! Aura - - // ALLIANCE from 60323 to 60330 - HORDE from 60328 to 60335 - uint32 spellId = 60323; - if (m_caster->ToPlayer()->GetTeam() == HORDE) - spellId += 5; - - spellId += urand(0, 7); - m_caster->CastSpell(m_caster, spellId, true); - return; - } - break; case 66550: // teleports outside (Isle of Conquest) if (Player* target = unitTarget->ToPlayer()) { @@ -1188,7 +1158,7 @@ void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/) // If not exist data for dest location - return if (!m_targets.HasDst()) { - sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id); + sLog->outError(LOG_FILTER_SPELLS_AURAS, "Spell::EffectTeleportUnits - does not have destination for spellId %u.", m_spellInfo->Id); return; } @@ -1585,10 +1555,6 @@ void Spell::EffectHealPct(SpellEffIndex /*effIndex*/) if (!m_originalCaster) return; - // Rune Tap - Party - if (m_spellInfo->Id == 59754 && unitTarget == m_caster) - return; - uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, unitTarget->CountPctFromMaxHealth(damage), HEAL); heal = unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL); @@ -3732,23 +3698,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) return; unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].CalcValue()); break; - // PX-238 Winter Wondervolt TRAP - case 26275: - { - uint32 spells[4] = { 26272, 26157, 26273, 26274 }; - - // check presence - for (uint8 j = 0; j < 4; ++j) - if (unitTarget->HasAuraEffect(spells[j], 0)) - return; - - // select spell - uint32 iTmpSpellId = spells[urand(0, 3)]; - - // cast - unitTarget->CastSpell(unitTarget, iTmpSpellId, true); - return; - } // Bending Shinbone case 8856: { @@ -3794,14 +3743,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) m_caster->CastSpell(unitTarget, 22682, true); return; } - // Piccolo of the Flaming Fire - case 17512: - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); - return; - } // Decimate case 28374: case 54426: @@ -3944,17 +3885,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) m_caster->MonsterTextEmote(buf, 0); break; } - // Vigilance - case 50725: - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - // Remove Taunt cooldown - unitTarget->ToPlayer()->RemoveSpellCooldown(355, true); - - return; - } // Death Knight Initiate Visual case 51519: { @@ -4113,17 +4043,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) } return; } - case 63845: // Create Lance - { - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - - if (m_caster->ToPlayer()->GetTeam() == ALLIANCE) - m_caster->CastSpell(m_caster, 63914, true); - else - m_caster->CastSpell(m_caster, 63919, true); - return; - } case 59317: // Teleporting { @@ -4317,46 +4236,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) return; } } - case SPELLFAMILY_POTION: - { - switch (m_spellInfo->Id) - { - // Netherbloom - case 28702: - { - if (!unitTarget) - return; - // 25% chance of casting a random buff - if (roll_chance_i(75)) - return; - - // triggered spells are 28703 to 28707 - // Note: some sources say, that there was the possibility of - // receiving a debuff. However, this seems to be removed by a patch. - const uint32 spellid = 28703; - - // don't overwrite an existing aura - for (uint8 i = 0; i < 5; ++i) - if (unitTarget->HasAura(spellid + i)) - return; - unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true); - break; - } - - // Nightmare Vine - case 28720: - { - if (!unitTarget) - return; - // 25% chance of casting Nightmare Pollen - if (roll_chance_i(75)) - return; - unitTarget->CastSpell(unitTarget, 28721, true); - break; - } - } - break; - } case SPELLFAMILY_DEATHKNIGHT: { // Pestilence @@ -4377,19 +4256,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) } break; } - case SPELLFAMILY_WARRIOR: - { - // Shattering Throw - if (m_spellInfo->SpellFamilyFlags[1] & 0x00400000) - { - if (!unitTarget) - return; - // remove shields, will still display immune to damage part - unitTarget->RemoveAurasWithMechanic(1<GetTypeId() != TYPEID_PLAYER) + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - if (unitTarget->isAlive()) + if (unitTarget->isAlive() || !unitTarget->IsInWorld()) return; - if (!unitTarget->IsInWorld()) - return; - - switch (m_spellInfo->Id) - { - // Defibrillate (Goblin Jumper Cables) have 33% chance on success - case 8342: - if (roll_chance_i(67)) - { - m_caster->CastSpell(m_caster, 8338, true, m_CastItem); - return; - } - break; - // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success - case 22999: - if (roll_chance_i(50)) - { - m_caster->CastSpell(m_caster, 23055, true, m_CastItem); - return; - } - break; - // Defibrillate (Gnomish Army Knife) have 67% chance on success_list - case 54732: - if (roll_chance_i(33)) - { - return; - } - break; - default: - break; - } Player* target = unitTarget->ToPlayer(); @@ -5151,26 +4984,10 @@ void Spell::EffectKnockBack(SpellEffIndex effIndex) if (creatureTarget->isWorldBoss() || creatureTarget->IsDungeonBoss()) return; - // Spells with SPELL_EFFECT_KNOCK_BACK(like Thunderstorm) can't knoback target if target has ROOT/STUN + // Spells with SPELL_EFFECT_KNOCK_BACK (like Thunderstorm) can't knockback target if target has ROOT/STUN if (unitTarget->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) return; - // Typhoon - if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[1] & 0x01000000) - { - // Glyph of Typhoon - if (m_caster->HasAura(62135)) - return; - } - - // Thunderstorm - if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[1] & 0x00002000) - { - // Glyph of Thunderstorm - if (m_caster->HasAura(62132)) - return; - } - // Instantly interrupt non melee spells being casted if (unitTarget->IsNonMeleeSpellCasted(true)) unitTarget->InterruptNonMeleeSpells(true); diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 060db02d53c..62a0599dab1 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -37,6 +37,7 @@ enum DeathKnightSpells SPELL_DK_DEATH_COIL_HEAL = 47633, SPELL_DK_DEATH_STRIKE_HEAL = 45470, SPELL_DK_GHOUL_EXPLODE = 47496, + SPELL_DK_GLYPH_OF_ICEBOUND_FORTITUDE = 58625, SPELL_DK_RUNIC_POWER_ENERGIZE = 49088, SPELL_DK_SCOURGE_STRIKE_TRIGGERED = 70890, SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1 = 49189, @@ -584,6 +585,55 @@ class spell_dk_ghoul_explode : public SpellScriptLoader } }; +// 48792 - Icebound Fortitude +class spell_dk_icebound_fortitude : public SpellScriptLoader +{ + public: + spell_dk_icebound_fortitude() : SpellScriptLoader("spell_dk_icebound_fortitude") { } + + class spell_dk_icebound_fortitude_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_icebound_fortitude_AuraScript); + + bool Load() + { + Unit* caster = GetCaster(); + return caster && caster->GetTypeId() == TYPEID_PLAYER; + } + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + { + int32 value = amount; + uint32 defValue = uint32(caster->ToPlayer()->GetSkillValue(SKILL_DEFENSE) + caster->ToPlayer()->GetRatingBonusValue(CR_DEFENSE_SKILL)); + + if (defValue > 400) + value -= int32((defValue - 400) * 0.15); + + // Glyph of Icebound Fortitude + if (AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_DK_GLYPH_OF_ICEBOUND_FORTITUDE, EFFECT_0)) + { + int32 valMax = -aurEff->GetAmount(); + if (value > valMax) + value = valMax; + } + amount = value; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_icebound_fortitude_AuraScript::CalculateAmount, EFFECT_2, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_icebound_fortitude_AuraScript(); + } +}; + // 50365, 50371 - Improved Blood Presence class spell_dk_improved_blood_presence : public SpellScriptLoader { @@ -677,6 +727,33 @@ class spell_dk_improved_unholy_presence : public SpellScriptLoader } }; +// 59754 Rune Tap - Party +class spell_dk_rune_tap_party : public SpellScriptLoader +{ + public: + spell_dk_rune_tap_party() : SpellScriptLoader("spell_dk_rune_tap_party") { } + + class spell_dk_rune_tap_party_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dk_rune_tap_party_SpellScript); + + void CheckTargets(std::list& targets) + { + targets.remove(GetCaster()); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_rune_tap_party_SpellScript::CheckTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_PARTY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_dk_rune_tap_party_SpellScript(); + } +}; + // 55090 - Scourge Strike (55265, 55270, 55271) class spell_dk_scourge_strike : public SpellScriptLoader { @@ -784,6 +861,33 @@ class spell_dk_spell_deflection : public SpellScriptLoader } }; +// 55233 - Vampiric Blood +class spell_dk_vampiric_blood : public SpellScriptLoader +{ + public: + spell_dk_vampiric_blood() : SpellScriptLoader("spell_dk_vampiric_blood") { } + + class spell_dk_vampiric_blood_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_vampiric_blood_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + amount = GetUnitOwner()->CountPctFromMaxHealth(amount); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_vampiric_blood_AuraScript::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_INCREASE_HEALTH); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_vampiric_blood_AuraScript(); + } +}; + // 52284 - Will of the Necropolis class spell_dk_will_of_the_necropolis : public SpellScriptLoader { @@ -861,9 +965,12 @@ void AddSC_deathknight_spell_scripts() new spell_dk_death_pact(); new spell_dk_death_strike(); new spell_dk_ghoul_explode(); + new spell_dk_icebound_fortitude(); new spell_dk_improved_blood_presence(); new spell_dk_improved_unholy_presence(); + new spell_dk_rune_tap_party(); new spell_dk_scourge_strike(); new spell_dk_spell_deflection(); + new spell_dk_vampiric_blood(); new spell_dk_will_of_the_necropolis(); } diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 6dd453597de..e2b918e1c7f 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -30,6 +30,9 @@ enum DruidSpells { SPELL_DRUID_ENRAGE_MOD_DAMAGE = 51185, + SPELL_DRUID_GLYPH_OF_TYPHOON = 62135, + SPELL_DRUID_IDOL_OF_FERAL_SHADOWS = 34241, + SPELL_DRUID_IDOL_OF_WORSHIP = 60774, SPELL_DRUID_INCREASED_MOONFIRE_DURATION = 38414, SPELL_DRUID_KING_OF_THE_JUNGLE = 48492, SPELL_DRUID_LIFEBLOOM_ENERGIZE = 64372, @@ -41,6 +44,35 @@ enum DruidSpells SPELL_DRUID_ITEM_T8_BALANCE_RELIC = 64950, }; +// -1850 - Dash +class spell_dru_dash : public SpellScriptLoader +{ + public: + spell_dru_dash() : SpellScriptLoader("spell_dru_dash") { } + + class spell_dru_dash_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_dash_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + // do not set speed if not in cat form + if (GetUnitOwner()->GetShapeshiftForm() != FORM_CAT) + amount = 0; + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_dash_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_INCREASE_SPEED); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_dash_AuraScript(); + } +}; + // -5229 - Enrage class spell_dru_enrage : public SpellScriptLoader { @@ -121,6 +153,69 @@ class spell_dru_glyph_of_starfire : public SpellScriptLoader } }; +// 34246 - Idol of the Emerald Queen +// 60779 - Idol of Lush Moss +class spell_dru_idol_lifebloom : public SpellScriptLoader +{ + public: + spell_dru_idol_lifebloom() : SpellScriptLoader("spell_dru_idol_lifebloom") { } + + class spell_dru_idol_lifebloom_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_idol_lifebloom_AuraScript); + + void HandleEffectCalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod) + { + if (!spellMod) + { + spellMod = new SpellModifier(GetAura()); + spellMod->op = SPELLMOD_DOT; + spellMod->type = SPELLMOD_FLAT; + spellMod->spellId = GetId(); + spellMod->mask = GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask; + } + spellMod->value = aurEff->GetAmount() / 7; + } + + void Register() + { + DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_dru_idol_lifebloom_AuraScript::HandleEffectCalcSpellMod, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_idol_lifebloom_AuraScript(); + } +}; + +// 29166 - Innervate +class spell_dru_innervate : public SpellScriptLoader +{ + public: + spell_dru_innervate() : SpellScriptLoader("spell_dru_innervate") { } + + class spell_dru_innervate_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_innervate_AuraScript); + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + amount = CalculatePct(int32(GetUnitOwner()->GetCreatePowers(POWER_MANA) / aurEff->GetTotalTicks()), amount); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_innervate_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_ENERGIZE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_innervate_AuraScript(); + } +}; + // -5570 - Insect Swarm class spell_dru_insect_swarm : public SpellScriptLoader { @@ -276,6 +371,33 @@ class spell_dru_moonkin_form_passive : public SpellScriptLoader } }; +// 48391 - Owlkin Frenzy +class spell_dru_owlkin_frenzy : public SpellScriptLoader +{ + public: + spell_dru_owlkin_frenzy() : SpellScriptLoader("spell_dru_owlkin_frenzy") { } + + class spell_dru_owlkin_frenzy_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_owlkin_frenzy_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + amount = CalculatePct(GetUnitOwner()->GetCreatePowers(POWER_MANA), amount); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_owlkin_frenzy_AuraScript::CalculateAmount, EFFECT_2, SPELL_AURA_PERIODIC_ENERGIZE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_owlkin_frenzy_AuraScript(); + } +}; + // -16972 - Predatory Strikes class spell_dru_predatory_strikes : public SpellScriptLoader { @@ -349,6 +471,54 @@ class spell_dru_primal_tenacity : public SpellScriptLoader } }; +// -1079 - Rip +class spell_dru_rip : public SpellScriptLoader +{ + public: + spell_dru_rip() : SpellScriptLoader("spell_dru_rip") { } + + class spell_dru_rip_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_rip_AuraScript); + + bool Load() + { + Unit* caster = GetCaster(); + return caster && caster->GetTypeId() == TYPEID_PLAYER; + } + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + + if (Unit* caster = GetCaster()) + { + // 0.01 * $AP * cp + uint8 cp = caster->ToPlayer()->GetComboPoints(); + + // Idol of Feral Shadows. Can't be handled as SpellMod due its dependency from CPs + if (AuraEffect const* idol = caster->GetAuraEffect(SPELL_DRUID_IDOL_OF_FERAL_SHADOWS, EFFECT_0)) + amount += cp * idol->GetAmount(); + // Idol of Worship. Can't be handled as SpellMod due its dependency from CPs + else if (AuraEffect const* idol = caster->GetAuraEffect(SPELL_DRUID_IDOL_OF_WORSHIP, EFFECT_0)) + amount += cp * idol->GetAmount(); + + amount += int32(CalculatePct(caster->GetTotalAttackPowerValue(BASE_ATTACK), cp)); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dru_rip_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_rip_AuraScript(); + } +}; + // 62606 - Savage Defense class spell_dru_savage_defense : public SpellScriptLoader { @@ -658,6 +828,35 @@ class spell_dru_tiger_s_fury : public SpellScriptLoader } }; +// -61391 - Typhoon +class spell_dru_typhoon : public SpellScriptLoader +{ + public: + spell_dru_typhoon() : SpellScriptLoader("spell_dru_typhoon") { } + + class spell_dru_typhoon_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dru_typhoon_SpellScript); + + void HandleKnockBack(SpellEffIndex effIndex) + { + // Glyph of Typhoon + if (GetCaster()->HasAura(SPELL_DRUID_GLYPH_OF_TYPHOON)) + PreventHitDefaultEffect(effIndex); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_dru_typhoon_SpellScript::HandleKnockBack, EFFECT_0, SPELL_EFFECT_KNOCK_BACK); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_dru_typhoon_SpellScript(); + } +}; + // 70691 - Item T10 Restoration 4P Bonus class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader { @@ -715,13 +914,18 @@ class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader void AddSC_druid_spell_scripts() { + new spell_dru_dash(); new spell_dru_enrage(); new spell_dru_glyph_of_starfire(); + new spell_dru_idol_lifebloom(); + new spell_dru_innervate(); new spell_dru_insect_swarm(); new spell_dru_lifebloom(); new spell_dru_moonkin_form_passive(); + new spell_dru_owlkin_frenzy(); new spell_dru_predatory_strikes(); new spell_dru_primal_tenacity(); + new spell_dru_rip(); new spell_dru_savage_defense(); new spell_dru_savage_roar(); new spell_dru_starfall_aoe(); @@ -729,5 +933,6 @@ void AddSC_druid_spell_scripts() new spell_dru_survival_instincts(); new spell_dru_swift_flight_passive(); new spell_dru_tiger_s_fury(); + new spell_dru_typhoon(); new spell_dru_t10_restoration_4p_bonus(); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index b5f4312bae5..6004ec6cf89 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -226,6 +226,158 @@ class spell_gen_cannibalize : public SpellScriptLoader } }; +// 63845 - Create Lance +enum CreateLanceSpells +{ + SPELL_CREATE_LANCE_ALLIANCE = 63914, + SPELL_CREATE_LANCE_HORDE = 63919 +}; + +class spell_gen_create_lance : public SpellScriptLoader +{ + public: + spell_gen_create_lance() : SpellScriptLoader("spell_gen_create_lance") { } + + class spell_gen_create_lance_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_create_lance_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_CREATE_LANCE_ALLIANCE) || !sSpellMgr->GetSpellInfo(SPELL_CREATE_LANCE_HORDE)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + if (Player* target = GetHitPlayer()) + { + if (target->GetTeam() == ALLIANCE) + GetCaster()->CastSpell(target, SPELL_CREATE_LANCE_ALLIANCE, true); + else + GetCaster()->CastSpell(target, SPELL_CREATE_LANCE_HORDE, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gen_create_lance_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_create_lance_SpellScript(); + } +}; + +// 28702 - Netherbloom +enum Netherbloom +{ + SPELL_NETHERBLOOM_POLLEN_1 = 28703 +}; + +class spell_gen_netherbloom : public SpellScriptLoader +{ + public: + spell_gen_netherbloom() : SpellScriptLoader("spell_gen_netherbloom") { } + + class spell_gen_netherbloom_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_netherbloom_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + for (uint8 i = 0; i < 5; ++i) + if (!sSpellMgr->GetSpellInfo(SPELL_NETHERBLOOM_POLLEN_1 + i)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + if (Unit* target = GetHitUnit()) + { + // 25% chance of casting a random buff + if (roll_chance_i(75)) + return; + + // triggered spells are 28703 to 28707 + // Note: some sources say, that there was the possibility of + // receiving a debuff. However, this seems to be removed by a patch. + + // don't overwrite an existing aura + for (uint8 i = 0; i < 5; ++i) + if (target->HasAura(SPELL_NETHERBLOOM_POLLEN_1 + i)) + return; + + target->CastSpell(target, SPELL_NETHERBLOOM_POLLEN_1 + urand(0, 4), true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gen_netherbloom_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_netherbloom_SpellScript(); + } +}; + +// 28720 - Nightmare Vine +enum NightmareVine +{ + SPELL_NIGHTMARE_POLLEN = 28721 +}; + +class spell_gen_nightmare_vine : public SpellScriptLoader +{ + public: + spell_gen_nightmare_vine() : SpellScriptLoader("spell_gen_nightmare_vine") { } + + class spell_gen_nightmare_vine_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_nightmare_vine_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_NIGHTMARE_POLLEN)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + if (Unit* target = GetHitUnit()) + { + // 25% chance of casting Nightmare Pollen + if (roll_chance_i(25)) + target->CastSpell(target, SPELL_NIGHTMARE_POLLEN, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gen_nightmare_vine_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_nightmare_vine_SpellScript(); + } +}; + // 45472 Parachute enum ParachuteSpells { @@ -3195,6 +3347,9 @@ void AddSC_generic_spell_scripts() new spell_gen_av_drekthar_presence(); new spell_gen_burn_brutallus(); new spell_gen_cannibalize(); + new spell_gen_create_lance(); + new spell_gen_netherbloom(); + new spell_gen_nightmare_vine(); new spell_gen_parachute(); new spell_gen_pet_summoned(); new spell_gen_remove_flight_auras(); diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp index d883b4d7da7..dbfc2b44501 100644 --- a/src/server/scripts/Spells/spell_holiday.cpp +++ b/src/server/scripts/Spells/spell_holiday.cpp @@ -303,27 +303,10 @@ class spell_winter_veil_mistletoe : public SpellScriptLoader void HandleScript(SpellEffIndex /*effIndex*/) { - Unit* caster = GetCaster(); - if (Player* target = GetHitPlayer()) { - uint32 spellId = 0; - switch (urand(0, 2)) - { - case 0: - spellId = SPELL_CREATE_MISTLETOE; - break; - case 1: - spellId = SPELL_CREATE_HOLLY; - break; - case 2: - spellId = SPELL_CREATE_SNOWFLAKES; - break; - default: - return; - } - - caster->CastSpell(target, spellId, true); + uint32 spellId = RAND(SPELL_CREATE_HOLLY, SPELL_CREATE_MISTLETOE, SPELL_CREATE_SNOWFLAKES); + GetCaster()->CastSpell(target, spellId, true); } } @@ -339,6 +322,71 @@ class spell_winter_veil_mistletoe : public SpellScriptLoader } }; +// 26275 - PX-238 Winter Wondervolt TRAP +enum PX238WinterWondervolt +{ + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_1 = 26157, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_2 = 26272, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_3 = 26273, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_4 = 26274 +}; + +class spell_winter_veil_px_238_winter_wondervolt : public SpellScriptLoader +{ + public: + spell_winter_veil_px_238_winter_wondervolt() : SpellScriptLoader("spell_winter_veil_px_238_winter_wondervolt") { } + + class spell_winter_veil_px_238_winter_wondervolt_SpellScript : public SpellScript + { + PrepareSpellScript(spell_winter_veil_px_238_winter_wondervolt_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_1) || + !sSpellMgr->GetSpellInfo(SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_2) || + !sSpellMgr->GetSpellInfo(SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_3) || + !sSpellMgr->GetSpellInfo(SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_4)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + uint32 const spells[4] = + { + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_1, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_2, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_3, + SPELL_PX_238_WINTER_WONDERVOLT_TRANSFORM_4 + }; + + if (Unit* target = GetHitUnit()) + { + for (uint8 i = 0; i < 4; ++i) + if (target->HasAura(spells[i])) + return; + + GetCaster()->CastSpell(target, spells[urand(0, 3)], true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_winter_veil_px_238_winter_wondervolt_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + + private: + + }; + + SpellScript* GetSpellScript() const + { + return new spell_winter_veil_px_238_winter_wondervolt_SpellScript(); + } +}; + void AddSC_holiday_spell_scripts() { // Love is in the Air @@ -349,4 +397,5 @@ void AddSC_holiday_spell_scripts() new spell_hallow_end_tricky_treat(); // Winter Veil new spell_winter_veil_mistletoe(); + new spell_winter_veil_px_238_winter_wondervolt(); } diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index b4e06cb6b48..c38d05bc02a 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -73,6 +73,93 @@ class spell_item_trigger_spell : public SpellScriptLoader } }; +// 26400 - Arcane Shroud +class spell_item_arcane_shroud : public SpellScriptLoader +{ + public: + spell_item_arcane_shroud() : SpellScriptLoader("spell_item_arcane_shroud") { } + + class spell_item_arcane_shroud_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_arcane_shroud_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + int32 diff = GetUnitOwner()->getLevel() - 60; + if (diff > 0) + amount += 2 * diff; + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_item_arcane_shroud_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_THREAT); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_arcane_shroud_AuraScript(); + } +}; + +// 8342 - Defibrillate (Goblin Jumper Cables) have 33% chance on success +// 22999 - Defibrillate (Goblin Jumper Cables XL) have 50% chance on success +// 54732 - Defibrillate (Gnomish Army Knife) have 67% chance on success +enum Defibrillate +{ + SPELL_GOBLIN_JUMPER_CABLES_FAIL = 8338, + SPELL_GOBLIN_JUMPER_CABLES_XL_FAIL = 23055 +}; + +class spell_item_defibrillate : public SpellScriptLoader +{ + public: + spell_item_defibrillate(char const* name, uint8 chance, uint32 failSpell = 0) : SpellScriptLoader(name), _chance(chance), _failSpell(failSpell) { } + + class spell_item_defibrillate_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_defibrillate_SpellScript); + + public: + spell_item_defibrillate_SpellScript(uint8 chance, uint32 failSpell) : SpellScript(), _chance(chance), _failSpell(failSpell) { } + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (_failSpell && !sSpellMgr->GetSpellInfo(_failSpell)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + if (roll_chance_i(_chance)) + { + PreventHitDefaultEffect(effIndex); + if (_failSpell) + GetCaster()->CastSpell(GetCaster(), _failSpell, true, GetCastItem()); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_item_defibrillate_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_RESURRECT); + } + + private: + uint8 _chance; + uint32 _failSpell; + }; + + SpellScript* GetSpellScript() const + { + return new spell_item_defibrillate_SpellScript(_chance, _failSpell); + } + + private: + uint8 _chance; + uint32 _failSpell; +}; + // http://www.wowhead.com/item=6522 Deviate Fish // 8063 Deviate Fish enum DeviateFishSpells @@ -464,6 +551,35 @@ class spell_item_noggenfogger_elixir : public SpellScriptLoader } }; +// 17512 - Piccolo of the Flaming Fire +class spell_item_piccolo_of_the_flaming_fire : public SpellScriptLoader +{ + public: + spell_item_piccolo_of_the_flaming_fire() : SpellScriptLoader("spell_item_piccolo_of_the_flaming_fire") { } + + class spell_item_piccolo_of_the_flaming_fire_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_piccolo_of_the_flaming_fire_SpellScript); + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (Player* target = GetHitPlayer()) + target->HandleEmoteCommand(EMOTE_STATE_DANCE); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_item_piccolo_of_the_flaming_fire_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_item_piccolo_of_the_flaming_fire_SpellScript(); + } +}; + // http://www.wowhead.com/item=6657 Savory Deviate Delight // 8213 Savory Deviate Delight enum SavoryDeviateDelight @@ -522,6 +638,79 @@ class spell_item_savory_deviate_delight : public SpellScriptLoader } }; +// 48129 - Scroll of Recall +// 60320 - Scroll of Recall II +// 60321 - Scroll of Recall III +enum ScrollOfRecall +{ + SPELL_SCROLL_OF_RECALL_I = 48129, + SPELL_SCROLL_OF_RECALL_II = 60320, + SPELL_SCROLL_OF_RECALL_III = 60321, + SPELL_LOST = 60444, + SPELL_SCROLL_OF_RECALL_FAIL_ALLIANCE_1 = 60323, + SPELL_SCROLL_OF_RECALL_FAIL_HORDE_1 = 60328, +}; + +class spell_item_scroll_of_recall : public SpellScriptLoader +{ + public: + spell_item_scroll_of_recall() : SpellScriptLoader("spell_item_scroll_of_recall") { } + + class spell_item_scroll_of_recall_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_scroll_of_recall_SpellScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void HandleScript(SpellEffIndex effIndex) + { + Unit* caster = GetCaster(); + uint8 maxSafeLevel = 0; + switch (GetSpellInfo()->Id) + { + case SPELL_SCROLL_OF_RECALL_I: // Scroll of Recall + maxSafeLevel = 40; + break; + case SPELL_SCROLL_OF_RECALL_II: // Scroll of Recall II + maxSafeLevel = 70; + break; + case SPELL_SCROLL_OF_RECALL_III: // Scroll of Recal III + maxSafeLevel = 80; + break; + default: + break; + } + + if (caster->getLevel() > maxSafeLevel) + { + caster->CastSpell(caster, SPELL_LOST, true); + + // ALLIANCE from 60323 to 60330 - HORDE from 60328 to 60335 + uint32 spellId = SPELL_SCROLL_OF_RECALL_FAIL_ALLIANCE_1; + if (GetCaster()->ToPlayer()->GetTeam() == HORDE) + spellId = SPELL_SCROLL_OF_RECALL_FAIL_HORDE_1; + + GetCaster()->CastSpell(GetCaster(), spellId + urand(0, 7), true); + + PreventHitDefaultEffect(effIndex); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_item_scroll_of_recall_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_TELEPORT_UNITS); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_item_scroll_of_recall_SpellScript(); + } +}; + // http://www.wowhead.com/item=7734 Six Demon Bag // 14537 Six Demon Bag enum SixDemonBagSpells @@ -593,6 +782,35 @@ class spell_item_six_demon_bag : public SpellScriptLoader } }; +// 28862 - The Eye of Diminution +class spell_item_the_eye_of_diminution : public SpellScriptLoader +{ + public: + spell_item_the_eye_of_diminution() : SpellScriptLoader("spell_item_the_eye_of_diminution") { } + + class spell_item_the_eye_of_diminution_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_the_eye_of_diminution_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + int32 diff = GetUnitOwner()->getLevel() - 60; + if (diff > 0) + amount += diff; + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_item_the_eye_of_diminution_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_THREAT); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_the_eye_of_diminution_AuraScript(); + } +}; + // http://www.wowhead.com/item=44012 Underbelly Elixir // 59640 Underbelly Elixir enum UnderbellyElixirSpells @@ -2030,6 +2248,10 @@ void AddSC_item_spell_scripts() // 23075 Mithril Mechanical Dragonling new spell_item_trigger_spell("spell_item_mithril_mechanical_dragonling", SPELL_MITHRIL_MECHANICAL_DRAGONLING); + new spell_item_arcane_shroud(); + new spell_item_defibrillate("spell_item_goblin_jumper_cables", 67, SPELL_GOBLIN_JUMPER_CABLES_FAIL); + new spell_item_defibrillate("spell_item_goblin_jumper_cables_xl", 50, SPELL_GOBLIN_JUMPER_CABLES_XL_FAIL); + new spell_item_defibrillate("spell_item_gnomish_army_knife", 33); new spell_item_deviate_fish(); new spell_item_flask_of_the_north(); new spell_item_gnomish_death_ray(); @@ -2037,8 +2259,11 @@ void AddSC_item_spell_scripts() new spell_item_mingos_fortune_generator(); new spell_item_net_o_matic(); new spell_item_noggenfogger_elixir(); + new spell_item_piccolo_of_the_flaming_fire(); new spell_item_savory_deviate_delight(); + new spell_item_scroll_of_recall(); new spell_item_six_demon_bag(); + new spell_item_the_eye_of_diminution(); new spell_item_underbelly_elixir(); new spell_item_shadowmourne(); new spell_item_red_rider_air_rifle(); diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index 61f0579190f..a673759a49e 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -29,7 +29,7 @@ enum MageSpells { SPELL_MAGE_COLD_SNAP = 11958, - SPELL_MAGE_FROST_WARDING_R1 = 28332, + SPELL_MAGE_FROST_WARDING_R1 = 11189, SPELL_MAGE_FROST_WARDING_TRIGGERED = 57776, SPELL_MAGE_INCANTERS_ABSORBTION_R1 = 44394, SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED = 44413, @@ -45,6 +45,31 @@ enum MageSpells SPELL_MAGE_GLYPH_OF_BLAST_WAVE = 62126, }; +// Incanter's Absorbtion +class spell_mage_incanters_absorbtion_base_AuraScript : public AuraScript +{ + public: + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_INCANTERS_ABSORBTION_R1)) + return false; + return true; + } + + void Trigger(AuraEffect* aurEff, DamageInfo& /*dmgInfo*/, uint32& absorbAmount) + { + Unit* target = GetTarget(); + + if (AuraEffect* talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_MAGE_INCANTERS_ABSORBTION_R1, EFFECT_0)) + { + int32 bp = CalculatePct(absorbAmount, talentAurEff->GetAmount()); + target->CastCustomSpell(target, SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff); + } + } +}; + // -11113 - Blast Wave class spell_mage_blast_wave : public SpellScriptLoader { @@ -127,29 +152,47 @@ class spell_mage_cold_snap : public SpellScriptLoader } }; -// -543, -6143 - Frost Warding -class spell_mage_frost_warding_trigger : public SpellScriptLoader +// -543 - Fire Ward +// -6143 - Frost Ward +class spell_mage_fire_frost_ward : public SpellScriptLoader { public: - spell_mage_frost_warding_trigger() : SpellScriptLoader("spell_mage_frost_warding_trigger") { } + spell_mage_fire_frost_ward() : SpellScriptLoader("spell_mage_fire_frost_ward") { } - class spell_mage_frost_warding_trigger_AuraScript : public AuraScript + class spell_mage_fire_frost_ward_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript { - PrepareAuraScript(spell_mage_frost_warding_trigger_AuraScript); + PrepareAuraScript(spell_mage_fire_frost_ward_AuraScript); bool Validate(SpellInfo const* /*spellInfo*/) { - if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_FROST_WARDING_TRIGGERED) || !sSpellMgr->GetSpellInfo(SPELL_MAGE_FROST_WARDING_R1)) + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_FROST_WARDING_TRIGGERED)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_FROST_WARDING_R1)) return false; return true; } - void Absorb(AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount) + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + if (Unit* caster = GetCaster()) + { + // +80.68% from sp bonus + float bonus = 0.8068f; + + bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()); + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + } + } + + void Absorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) { Unit* target = GetTarget(); if (AuraEffect* talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_MAGE_FROST_WARDING_R1, EFFECT_0)) { - int32 chance = talentAurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); + int32 chance = talentAurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); // SPELL_EFFECT_DUMMY with NO_TARGET if (roll_chance_i(chance)) { @@ -164,79 +207,58 @@ class spell_mage_frost_warding_trigger : public SpellScriptLoader void Register() { - OnEffectAbsorb += AuraEffectAbsorbFn(spell_mage_frost_warding_trigger_AuraScript::Absorb, EFFECT_0); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mage_fire_frost_ward_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + OnEffectAbsorb += AuraEffectAbsorbFn(spell_mage_fire_frost_ward_AuraScript::Absorb, EFFECT_0); + AfterEffectAbsorb += AuraEffectAbsorbFn(spell_mage_fire_frost_ward_AuraScript::Trigger, EFFECT_0); } }; AuraScript* GetAuraScript() const { - return new spell_mage_frost_warding_trigger_AuraScript(); + return new spell_mage_fire_frost_ward_AuraScript(); } }; -class spell_mage_incanters_absorbtion_base_AuraScript : public AuraScript +// -11426 - Ice Barrier +class spell_mage_ice_barrier : public SpellScriptLoader { public: + spell_mage_ice_barrier() : SpellScriptLoader("spell_mage_ice_barrier") { } - bool Validate(SpellInfo const* /*spellInfo*/) - { - return sSpellMgr->GetSpellInfo(SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED) - && sSpellMgr->GetSpellInfo(SPELL_MAGE_INCANTERS_ABSORBTION_R1); - } - - void Trigger(AuraEffect* aurEff, DamageInfo & /*dmgInfo*/, uint32 & absorbAmount) + class spell_mage_ice_barrier_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript { - Unit* target = GetTarget(); + PrepareAuraScript(spell_mage_ice_barrier_AuraScript); - if (AuraEffect* talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_MAGE_INCANTERS_ABSORBTION_R1, EFFECT_0)) + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) { - int32 bp = CalculatePct(absorbAmount, talentAurEff->GetAmount()); - target->CastCustomSpell(target, SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff); - } - } -}; - -// -543, -6143, -11426 - Incanter's Absorption -class spell_mage_incanters_absorbtion_absorb : public SpellScriptLoader -{ - public: - spell_mage_incanters_absorbtion_absorb() : SpellScriptLoader("spell_mage_incanters_absorbtion_absorb") { } + canBeRecalculated = false; + if (Unit* caster = GetCaster()) + { + // +80.68% from sp bonus + float bonus = 0.8068f; - class spell_mage_incanters_absorbtion_absorb_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript - { - PrepareAuraScript(spell_mage_incanters_absorbtion_absorb_AuraScript); + bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()); - void Register() - { - AfterEffectAbsorb += AuraEffectAbsorbFn(spell_mage_incanters_absorbtion_absorb_AuraScript::Trigger, EFFECT_0); - } - }; + // Glyph of Ice Barrier: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :) + // Glyph of Ice Barrier is only applied at the spell damage bonus because it was already applied to the base value in CalculateSpellDamage + bonus = caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), bonus); - AuraScript* GetAuraScript() const - { - return new spell_mage_incanters_absorbtion_absorb_AuraScript(); - } -}; + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); -// -1463 - Incanter's Absorption -class spell_mage_incanters_absorbtion_manashield : public SpellScriptLoader -{ - public: - spell_mage_incanters_absorbtion_manashield() : SpellScriptLoader("spell_mage_incanters_absorbtion_manashield") { } - - class spell_mage_incanters_absorbtion_manashield_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript - { - PrepareAuraScript(spell_mage_incanters_absorbtion_manashield_AuraScript); + amount += int32(bonus); + } + } void Register() { - AfterEffectManaShield += AuraEffectManaShieldFn(spell_mage_incanters_absorbtion_manashield_AuraScript::Trigger, EFFECT_0); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mage_ice_barrier_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + AfterEffectAbsorb += AuraEffectAbsorbFn(spell_mage_ice_barrier_AuraScript::Trigger, EFFECT_0); } }; AuraScript* GetAuraScript() const { - return new spell_mage_incanters_absorbtion_manashield_AuraScript(); + return new spell_mage_ice_barrier_AuraScript(); } }; @@ -279,6 +301,44 @@ class spell_mage_living_bomb : public SpellScriptLoader } }; +// -1463 - Mana Shield +class spell_mage_mana_shield : public SpellScriptLoader +{ + public: + spell_mage_mana_shield() : SpellScriptLoader("spell_mage_mana_shield") { } + + class spell_mage_mana_shield_AuraScript : public spell_mage_incanters_absorbtion_base_AuraScript + { + PrepareAuraScript(spell_mage_mana_shield_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + if (Unit* caster = GetCaster()) + { + // +80.53% from sp bonus + float bonus = 0.8053f; + + bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()); + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mage_mana_shield_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MANA_SHIELD); + AfterEffectManaShield += AuraEffectManaShieldFn(spell_mage_mana_shield_AuraScript::Trigger, EFFECT_0); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_mage_mana_shield_AuraScript(); + } +}; + enum SilvermoonPolymorph { NPC_AUROSALIA = 18744, @@ -378,10 +438,10 @@ void AddSC_mage_spell_scripts() { new spell_mage_blast_wave(); new spell_mage_cold_snap(); - new spell_mage_frost_warding_trigger(); - new spell_mage_incanters_absorbtion_absorb(); - new spell_mage_incanters_absorbtion_manashield(); + new spell_mage_fire_frost_ward(); + new spell_mage_ice_barrier(); new spell_mage_living_bomb(); + new spell_mage_mana_shield(); new spell_mage_polymorph_cast_visual(); new spell_mage_summon_water_elemental(); } diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index d3fc86302e1..2f22de97d77 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -51,6 +51,13 @@ enum PaladinSpells SPELL_PALADIN_HAND_OF_SACRIFICE = 6940, SPELL_PALADIN_DIVINE_SACRIFICE = 64205, + + SPELL_PALADIN_GLYPH_OF_SALVATION = 63225, + + SPELL_PALADIN_RIGHTEOUS_DEFENSE_TAUNT = 31790, + + SPELL_GENERIC_ARENA_DAMPENING = 74410, + SPELL_GENERIC_BATTLEGROUND_DAMPENING = 74411 }; // 31850 - Ardent Defender @@ -490,6 +497,39 @@ class spell_pal_hand_of_sacrifice : public SpellScriptLoader } }; +// 1038 - Hand of Salvation +class spell_pal_hand_of_salvation : public SpellScriptLoader +{ + public: + spell_pal_hand_of_salvation() : SpellScriptLoader("spell_pal_hand_of_salvation") { } + + class spell_pal_hand_of_salvation_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_hand_of_salvation_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + { + // Glyph of Salvation + if (caster->GetGUID() == GetUnitOwner()->GetGUID()) + if (AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_PALADIN_GLYPH_OF_SALVATION, EFFECT_0)) + amount -= aurEff->GetAmount(); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pal_hand_of_salvation_AuraScript::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pal_hand_of_salvation_AuraScript(); + } +}; + // -20473 - Holy Shock class spell_pal_holy_shock : public SpellScriptLoader { @@ -656,6 +696,13 @@ class spell_pal_righteous_defense : public SpellScriptLoader { PrepareSpellScript(spell_pal_righteous_defense_SpellScript); + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_RIGHTEOUS_DEFENSE_TAUNT)) + return false; + return true; + } + SpellCastResult CheckCast() { Unit* caster = GetCaster(); @@ -673,9 +720,27 @@ class spell_pal_righteous_defense : public SpellScriptLoader return SPELL_CAST_OK; } + void HandleTriggerSpellLaunch(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + } + + void HandleTriggerSpellHit(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (Unit* target = GetHitUnit()) + GetCaster()->CastSpell(target, SPELL_PALADIN_RIGHTEOUS_DEFENSE_TAUNT, true); + } + void Register() { OnCheckCast += SpellCheckCastFn(spell_pal_righteous_defense_SpellScript::CheckCast); + //! WORKAROUND + //! target select will be executed in hitphase of effect 0 + //! so we must handle trigger spell also in hit phase (default execution in launch phase) + //! see issue #3718 + OnEffectLaunchTarget += SpellEffectFn(spell_pal_righteous_defense_SpellScript::HandleTriggerSpellLaunch, EFFECT_1, SPELL_EFFECT_TRIGGER_SPELL); + OnEffectHitTarget += SpellEffectFn(spell_pal_righteous_defense_SpellScript::HandleTriggerSpellHit, EFFECT_1, SPELL_EFFECT_TRIGGER_SPELL); } }; @@ -685,6 +750,50 @@ class spell_pal_righteous_defense : public SpellScriptLoader } }; +// 58597 - Sacred Shield +class spell_pal_sacred_shield : public SpellScriptLoader +{ + public: + spell_pal_sacred_shield() : SpellScriptLoader("spell_pal_sacred_shield") { } + + class spell_pal_sacred_shield_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_sacred_shield_AuraScript); + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + { + // +75.00% from sp bonus + float bonus = CalculatePct(caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()), 75.0f); + + // Divine Guardian is only applied at the spell healing bonus because it was already applied to the base value in CalculateSpellDamage + bonus = caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), bonus); + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + + // Arena - Dampening + if (AuraEffect const* dampening = caster->GetAuraEffect(SPELL_GENERIC_ARENA_DAMPENING, EFFECT_0)) + AddPct(amount, dampening->GetAmount()); + // Battleground - Dampening + else if (AuraEffect const* dampening = caster->GetAuraEffect(SPELL_GENERIC_BATTLEGROUND_DAMPENING, EFFECT_0)) + AddPct(amount, dampening->GetAmount()); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pal_sacred_shield_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pal_sacred_shield_AuraScript(); + } +}; + void AddSC_paladin_spell_scripts() { new spell_pal_ardent_defender(); @@ -696,8 +805,10 @@ void AddSC_paladin_spell_scripts() new spell_pal_exorcism_and_holy_wrath_damage(); new spell_pal_guarded_by_the_light(); new spell_pal_hand_of_sacrifice(); + new spell_pal_hand_of_salvation(); new spell_pal_holy_shock(); new spell_pal_judgement_of_command(); new spell_pal_lay_on_hands(); new spell_pal_righteous_defense(); + new spell_pal_sacred_shield(); } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 1c416a0d28a..23a39819aa2 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -30,6 +30,7 @@ enum PriestSpells { SPELL_PRIEST_EMPOWERED_RENEW = 63544, + SPELL_PRIEST_GLYPHE_OF_LIGHTWELL = 55673, SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL = 48153, SPELL_PRIEST_PENANCE_R1 = 47540, SPELL_PRIEST_PENANCE_R1_DAMAGE = 47758, @@ -43,6 +44,7 @@ enum PriestSpells enum PriestSpellIcons { + PRIEST_ICON_ID_BORROWED_TIME = 2899, PRIEST_ICON_ID_EMPOWERED_RENEW_TALENT = 3021, PRIEST_ICON_ID_PAIN_AND_SUFFERING = 2874, }; @@ -104,6 +106,38 @@ class spell_pri_guardian_spirit : public SpellScriptLoader } }; +// -7001 - Lightwell Renew +class spell_pri_lightwell_renew : public SpellScriptLoader +{ + public: + spell_pri_lightwell_renew() : SpellScriptLoader("spell_pri_lightwell_renew") { } + + class spell_pri_lightwell_renew_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_lightwell_renew_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + { + // Bonus from Glyph of Lightwell + if (AuraEffect* modHealing = caster->GetAuraEffect(SPELL_PRIEST_GLYPHE_OF_LIGHTWELL, EFFECT_0)) + AddPct(amount, modHealing->GetAmount()); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pri_lightwell_renew_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pri_lightwell_renew_AuraScript(); + } +}; + // -8129 - Mana Burn class spell_pri_mana_burn : public SpellScriptLoader { @@ -260,81 +294,114 @@ class spell_pri_penance : public SpellScriptLoader } }; -// 33110 - Prayer of Mending Heal -class spell_pri_prayer_of_mending_heal : public SpellScriptLoader +// -17 - Power Word: Shield +class spell_pri_power_word_shield : public SpellScriptLoader { public: - spell_pri_prayer_of_mending_heal() : SpellScriptLoader("spell_pri_prayer_of_mending_heal") { } + spell_pri_power_word_shield() : SpellScriptLoader("spell_pri_power_word_shield") { } - class spell_pri_prayer_of_mending_heal_SpellScript : public SpellScript + class spell_pri_power_word_shield_AuraScript : public AuraScript { - PrepareSpellScript(spell_pri_prayer_of_mending_heal_SpellScript); + PrepareAuraScript(spell_pri_power_word_shield_AuraScript); - void HandleHeal(SpellEffIndex /*effIndex*/) + bool Validate(SpellInfo const* /*spellInfo*/) { - if (Unit* caster = GetOriginalCaster()) + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_REFLECTIVE_SHIELD_R1)) + return false; + return true; + } + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + if (Unit* caster = GetCaster()) { - if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_PRIEST_T9_HEALING_2P, EFFECT_0)) + // +80.68% from sp bonus + float bonus = 0.8068f; + + // Borrowed Time + if (AuraEffect const* borrowedTime = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, PRIEST_ICON_ID_BORROWED_TIME, EFFECT_1)) + bonus += CalculatePct(1.0f, borrowedTime->GetAmount()); + + bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()); + + // Improved PW: Shield: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :) + // Improved PW: Shield is only applied at the spell healing bonus because it was already applied to the base value in CalculateSpellDamage + bonus = caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), bonus); + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + + // Twin Disciplines + if (AuraEffect const* twinDisciplines = caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_PRIEST, 0x400000, 0, 0, GetCasterGUID())) + AddPct(amount, twinDisciplines->GetAmount()); + + // Focused Power + amount *= caster->GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALING_DONE_PERCENT); + } + } + + void ReflectDamage(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) + { + Unit* target = GetTarget(); + if (dmgInfo.GetAttacker() == target) + return; + + if (Unit* caster = GetCaster()) + if (AuraEffect* talentAurEff = caster->GetAuraEffectOfRankedSpell(SPELL_PRIEST_REFLECTIVE_SHIELD_R1, EFFECT_0)) { - int32 heal = GetHitHeal(); - AddPct(heal, aurEff->GetAmount()); - SetHitHeal(heal); + int32 bp = CalculatePct(absorbAmount, talentAurEff->GetAmount()); + target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff); } - } } void Register() { - OnEffectHitTarget += SpellEffectFn(spell_pri_prayer_of_mending_heal_SpellScript::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pri_power_word_shield_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + AfterEffectAbsorb += AuraEffectAbsorbFn(spell_pri_power_word_shield_AuraScript::ReflectDamage, EFFECT_0); } }; - SpellScript* GetSpellScript() const + AuraScript* GetAuraScript() const { - return new spell_pri_prayer_of_mending_heal_SpellScript(); + return new spell_pri_power_word_shield_AuraScript(); } }; -// -17 - Reflective Shield -class spell_pri_reflective_shield_trigger : public SpellScriptLoader +// 33110 - Prayer of Mending Heal +class spell_pri_prayer_of_mending_heal : public SpellScriptLoader { public: - spell_pri_reflective_shield_trigger() : SpellScriptLoader("spell_pri_reflective_shield_trigger") { } + spell_pri_prayer_of_mending_heal() : SpellScriptLoader("spell_pri_prayer_of_mending_heal") { } - class spell_pri_reflective_shield_trigger_AuraScript : public AuraScript + class spell_pri_prayer_of_mending_heal_SpellScript : public SpellScript { - PrepareAuraScript(spell_pri_reflective_shield_trigger_AuraScript); - - bool Validate(SpellInfo const* /*spellInfo*/) - { - if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED) || !sSpellMgr->GetSpellInfo(SPELL_PRIEST_REFLECTIVE_SHIELD_R1)) - return false; - return true; - } + PrepareSpellScript(spell_pri_prayer_of_mending_heal_SpellScript); - void Trigger(AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount) + void HandleHeal(SpellEffIndex /*effIndex*/) { - Unit* target = GetTarget(); - if (dmgInfo.GetAttacker() == target) - return; - - if (GetCaster()) - if (AuraEffect* talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_PRIEST_REFLECTIVE_SHIELD_R1, EFFECT_0)) + if (Unit* caster = GetOriginalCaster()) + { + if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_PRIEST_T9_HEALING_2P, EFFECT_0)) { - int32 bp = CalculatePct(absorbAmount, talentAurEff->GetAmount()); - target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED, &bp, NULL, NULL, true, NULL, aurEff); + int32 heal = GetHitHeal(); + AddPct(heal, aurEff->GetAmount()); + SetHitHeal(heal); } + } } void Register() { - AfterEffectAbsorb += AuraEffectAbsorbFn(spell_pri_reflective_shield_trigger_AuraScript::Trigger, EFFECT_0); + OnEffectHitTarget += SpellEffectFn(spell_pri_prayer_of_mending_heal_SpellScript::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL); } }; - AuraScript* GetAuraScript() const + SpellScript* GetSpellScript() const { - return new spell_pri_reflective_shield_trigger_AuraScript(); + return new spell_pri_prayer_of_mending_heal_SpellScript(); } }; @@ -458,12 +525,13 @@ class spell_pri_vampiric_touch : public SpellScriptLoader void AddSC_priest_spell_scripts() { new spell_pri_guardian_spirit(); + new spell_pri_lightwell_renew(); new spell_pri_mana_burn(); new spell_pri_mind_sear(); new spell_pri_pain_and_suffering_proc(); new spell_pri_penance(); + new spell_pri_power_word_shield(); new spell_pri_prayer_of_mending_heal(); - new spell_pri_reflective_shield_trigger(); new spell_pri_renew(); new spell_pri_shadow_word_death(); new spell_pri_vampiric_touch(); diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index 70b677f5aaa..156158b4e36 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -347,6 +347,58 @@ class spell_rog_prey_on_the_weak : public SpellScriptLoader } }; +// -1943 - Rupture +class spell_rog_rupture : public SpellScriptLoader +{ + public: + spell_rog_rupture() : SpellScriptLoader("spell_rog_rupture") { } + + class spell_rog_rupture_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_rupture_AuraScript); + + bool Load() + { + Unit* caster = GetCaster(); + return caster && caster->GetTypeId() == TYPEID_PLAYER; + } + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + if (Unit* caster = GetCaster()) + { + canBeRecalculated = false; + + float const attackpowerPerCombo[6] = + { + 0.0f, + 0.015f, // 1 point: ${($m1 + $b1*1 + 0.015 * $AP) * 4} damage over 8 secs + 0.024f, // 2 points: ${($m1 + $b1*2 + 0.024 * $AP) * 5} damage over 10 secs + 0.03f, // 3 points: ${($m1 + $b1*3 + 0.03 * $AP) * 6} damage over 12 secs + 0.03428571f, // 4 points: ${($m1 + $b1*4 + 0.03428571 * $AP) * 7} damage over 14 secs + 0.0375f // 5 points: ${($m1 + $b1*5 + 0.0375 * $AP) * 8} damage over 16 secs + }; + + uint8 cp = caster->ToPlayer()->GetComboPoints(); + if (cp > 5) + cp = 5; + + amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * attackpowerPerCombo[cp]); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_rog_rupture_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_rog_rupture_AuraScript(); + } +}; + // 5938 - Shiv class spell_rog_shiv : public SpellScriptLoader { @@ -395,5 +447,6 @@ void AddSC_rogue_spell_scripts() new spell_rog_nerves_of_steel(); new spell_rog_preparation(); new spell_rog_prey_on_the_weak(); + new spell_rog_rupture(); new spell_rog_shiv(); } diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index 0d249953421..2994761be6f 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -38,6 +38,7 @@ enum ShamanSpells SPELL_SHAMAN_FIRE_NOVA_TRIGGERED_R1 = 8349, SPELL_SHAMAN_GLYPH_OF_HEALING_STREAM_TOTEM = 55456, SPELL_SHAMAN_GLYPH_OF_MANA_TIDE = 55441, + SPELL_SHAMAN_GLYPH_OF_THUNDERSTORM = 62132, SPELL_SHAMAN_LAVA_FLOWS_R1 = 51480, SPELL_SHAMAN_LAVA_FLOWS_TRIGGERED_R1 = 64694, SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE = 52032, @@ -743,6 +744,35 @@ class spell_sha_sentry_totem : public SpellScriptLoader } }; +// -51490 - Thunderstorm +class spell_sha_thunderstorm : public SpellScriptLoader +{ + public: + spell_sha_thunderstorm() : SpellScriptLoader("spell_sha_thunderstorm") { } + + class spell_sha_thunderstorm_SpellScript : public SpellScript + { + PrepareSpellScript(spell_sha_thunderstorm_SpellScript); + + void HandleKnockBack(SpellEffIndex effIndex) + { + // Glyph of Thunderstorm + if (GetCaster()->HasAura(SPELL_SHAMAN_GLYPH_OF_THUNDERSTORM)) + PreventHitDefaultEffect(effIndex); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_sha_thunderstorm_SpellScript::HandleKnockBack, EFFECT_2, SPELL_EFFECT_KNOCK_BACK); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_sha_thunderstorm_SpellScript(); + } +}; + void AddSC_shaman_spell_scripts() { new spell_sha_ancestral_awakening_proc(); @@ -760,4 +790,5 @@ void AddSC_shaman_spell_scripts() new spell_sha_mana_spring_totem(); new spell_sha_mana_tide_totem(); new spell_sha_sentry_totem(); + new spell_sha_thunderstorm(); } diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 89c69733daf..68ad1315dce 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -649,6 +649,43 @@ class spell_warl_seed_of_corruption : public SpellScriptLoader } }; +// -7235 - Shadow Ward +class spell_warl_shadow_ward : public SpellScriptLoader +{ + public: + spell_warl_shadow_ward() : SpellScriptLoader("spell_warl_shadow_ward") { } + + class spell_warl_shadow_ward_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_shadow_ward_AuraScript); + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + canBeRecalculated = false; + if (Unit* caster = GetCaster()) + { + // +80.68% from sp bonus + float bonus = 0.8068f; + + bonus *= caster->SpellBaseHealingBonusDone(GetSpellInfo()->GetSchoolMask()); + bonus *= caster->CalculateLevelPenalty(GetSpellInfo()); + + amount += int32(bonus); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_shadow_ward_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_shadow_ward_AuraScript(); + } +}; + // 29858 - Soulshatter class spell_warl_soulshatter : public SpellScriptLoader { @@ -742,6 +779,7 @@ void AddSC_warlock_spell_scripts() new spell_warl_life_tap(); new spell_warl_ritual_of_doom_effect(); new spell_warl_seed_of_corruption(); + new spell_warl_shadow_ward(); new spell_warl_soulshatter(); new spell_warl_unstable_affliction(); } diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index f84265b89de..822d4b17992 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -41,6 +41,7 @@ enum WarriorSpells SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT = 64976, SPELL_WARRIOR_LAST_STAND_TRIGGERED = 12976, SPELL_WARRIOR_SLAM = 50783, + SPELL_WARRIOR_TAUNT = 355, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_1 = 46859, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_2 = 46860, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_1 = 64849, @@ -333,6 +334,34 @@ class spell_warr_improved_spell_reflection : public SpellScriptLoader } }; +// 5246 - Intimidating Shout +class spell_warr_intimidating_shout : public SpellScriptLoader +{ + public: + spell_warr_intimidating_shout() : SpellScriptLoader("spell_warr_intimidating_shout") { } + + class spell_warr_intimidating_shout_SpellScript : public SpellScript + { + PrepareSpellScript(spell_warr_intimidating_shout_SpellScript); + + void FilterTargets(std::list& unitList) + { + unitList.remove(GetExplTargetWorldObject()); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_intimidating_shout_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_intimidating_shout_SpellScript::FilterTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_warr_intimidating_shout_SpellScript(); + } +}; + // 12975 - Last Stand class spell_warr_last_stand : public SpellScriptLoader { @@ -409,6 +438,83 @@ class spell_warr_overpower : public SpellScriptLoader } }; +// -772 - Rend +class spell_warr_rend : public SpellScriptLoader +{ + public: + spell_warr_rend() : SpellScriptLoader("spell_warr_rend") { } + + class spell_warr_rend_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warr_rend_AuraScript); + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) + { + if (Unit* caster = GetCaster()) + { + canBeRecalculated = false; + + // $0.2 * (($MWB + $mwb) / 2 + $AP / 14 * $MWS) bonus per tick + float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 mws = caster->GetAttackTime(BASE_ATTACK); + float mwbMin = caster->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); + float mwbMax = caster->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); + float mwb = ((mwbMin + mwbMax) / 2 + ap * mws / 14000) * 0.2f; + amount += int32(caster->ApplyEffectModifiers(GetSpellInfo(), aurEff->GetEffIndex(), mwb)); + + // "If used while your target is above 75% health, Rend does 35% more damage." + // as for 3.1.3 only ranks above 9 (wrong tooltip?) + if (GetSpellInfo()->GetRank() >= 9) + { + if (GetUnitOwner()->HasAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetSpellInfo(), caster)) + AddPct(amount, GetSpellInfo()->Effects[EFFECT_2].CalcValue(caster)); + } + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warr_rend_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warr_rend_AuraScript(); + } +}; + +// 64380, 65941 - Shattering Throw +class spell_warr_shattering_throw : public SpellScriptLoader +{ + public: + spell_warr_shattering_throw() : SpellScriptLoader("spell_warr_shattering_throw") { } + + class spell_warr_shattering_throw_SpellScript : public SpellScript + { + PrepareSpellScript(spell_warr_shattering_throw_SpellScript); + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + // remove shields, will still display immune to damage part + if (Unit* target = GetHitUnit()) + target->RemoveAurasWithMechanic(1 << MECHANIC_IMMUNE_SHIELD, AURA_REMOVE_BY_ENEMY_SPELL); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_warr_shattering_throw_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_warr_shattering_throw_SpellScript(); + } +}; + // -1464 - Slam class spell_warr_slam : public SpellScriptLoader { @@ -493,6 +599,37 @@ class spell_warr_vigilance : public SpellScriptLoader } }; +// 50725 Vigilance +class spell_warr_vigilance_trigger : public SpellScriptLoader +{ + public: + spell_warr_vigilance_trigger() : SpellScriptLoader("spell_warr_vigilance_trigger") { } + + class spell_warr_vigilance_trigger_SpellScript : public SpellScript + { + PrepareSpellScript(spell_warr_vigilance_trigger_SpellScript); + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + // Remove Taunt cooldown + if (Player* target = GetHitPlayer()) + target->RemoveSpellCooldown(SPELL_WARRIOR_TAUNT, true); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_warr_vigilance_trigger_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_warr_vigilance_trigger_SpellScript(); + } +}; + void AddSC_warrior_spell_scripts() { new spell_warr_bloodthirst(); @@ -502,8 +639,12 @@ void AddSC_warrior_spell_scripts() new spell_warr_deep_wounds(); new spell_warr_execute(); new spell_warr_improved_spell_reflection(); + new spell_warr_intimidating_shout(); new spell_warr_last_stand(); new spell_warr_overpower(); + new spell_warr_rend(); + new spell_warr_shattering_throw(); new spell_warr_slam(); new spell_warr_vigilance(); + new spell_warr_vigilance_trigger(); } -- cgit v1.2.3 From bbcc78e2c187b99396f1311401a26b3e24d33332 Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Sun, 20 Jan 2013 17:55:48 +0100 Subject: Core: Fix warnings --- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index e440b2a0fbd..d029d2884c9 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -449,8 +449,6 @@ int32 AuraEffect::CalculateAmount(Unit* caster) } } - float DoneActualBenefit = 0.0f; - // custom amount calculations go here switch (GetAuraType()) { -- cgit v1.2.3 From 1eab850cab9c71c0e8086af538aded557c526914 Mon Sep 17 00:00:00 2001 From: kaelima Date: Sun, 20 Jan 2013 19:44:38 +0100 Subject: Core/BG: Set bgteam in PLAYER_BYTES_3 >> 24. Creds to vlad852 closes #8969 --- src/server/game/Battlegrounds/Battleground.cpp | 13 +++---------- src/server/game/Entities/Player/Player.h | 6 +++++- src/server/game/Handlers/BattleGroundHandler.cpp | 6 ++++-- 3 files changed, 12 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index e717a10fcd7..264c2c333aa 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -523,7 +523,7 @@ inline void Battleground::_ProcessJoin(uint32 diff) WorldPacket status; BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(m_TypeID, GetArenaType()); uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId); - sBattlegroundMgr->BuildBattlegroundStatusPacket(&status, this, queueSlot, STATUS_IN_PROGRESS, 0, GetStartTime(), GetArenaType(), GetPlayerTeam(itr->first)); + sBattlegroundMgr->BuildBattlegroundStatusPacket(&status, this, queueSlot, STATUS_IN_PROGRESS, 0, GetStartTime(), GetArenaType(), player->GetBGTeam()); player->GetSession()->SendPacket(&status); player->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); @@ -919,7 +919,7 @@ void Battleground::EndBattleground(uint32 winner) player->GetSession()->SendPacket(&pvpLogData); WorldPacket data; - sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType(), GetPlayerTeam(player->GetGUID())); + sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType(), player->GetBGTeam()); player->GetSession()->SendPacket(&data); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); } @@ -1147,13 +1147,6 @@ void Battleground::AddPlayer(Player* player) sBattlegroundMgr->BuildPlayerJoinedBattlegroundPacket(&data, player); SendPacketToTeam(team, &data, player, false); - // BG Status packet - WorldPacket status; - BattlegroundQueueTypeId bgQueueTypeId = sBattlegroundMgr->BGQueueTypeId(m_TypeID, GetArenaType()); - uint32 queueSlot = player->GetBattlegroundQueueIndex(bgQueueTypeId); - sBattlegroundMgr->BuildBattlegroundStatusPacket(&status, this, queueSlot, STATUS_IN_PROGRESS, 0, GetStartTime(), GetArenaType(), team); - player->GetSession()->SendPacket(&status); - player->RemoveAurasByType(SPELL_AURA_MOUNTED); // add arena specific auras @@ -1846,7 +1839,7 @@ void Battleground::PlayerAddedToBGCheckIfBGIsRunning(Player* player) sBattlegroundMgr->BuildPvpLogDataPacket(&data, this); player->GetSession()->SendPacket(&data); - sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), GetPlayerTeam(player->GetGUID())); + sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, GetEndTime(), GetStartTime(), GetArenaType(), player->GetBGTeam()); player->GetSession()->SendPacket(&data); } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 52e81d6d0cd..6d9d63b8fda 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2219,7 +2219,11 @@ class Player : public Unit, public GridObject WorldLocation const& GetBattlegroundEntryPoint() const { return m_bgData.joinPos; } void SetBattlegroundEntryPoint(); - void SetBGTeam(uint32 team) { m_bgData.bgTeam = team; } + void SetBGTeam(uint32 team) + { + m_bgData.bgTeam = team; + SetByteValue(PLAYER_BYTES_3, 3, uint8(team == ALLIANCE ? TEAM_ALLIANCE : TEAM_HORDE)); + } uint32 GetBGTeam() const { return m_bgData.bgTeam ? m_bgData.bgTeam : GetTeam(); } void LeaveBattleground(bool teleportToEntryPoint = true); diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index 99056960893..e70f127d600 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -453,8 +453,9 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) _player->CleanupAfterTaxiFlight(); } - sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), bg->GetPlayerTeam(_player->GetGUID())); + sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), ginfo.Team); _player->GetSession()->SendPacket(&data); + // remove battleground queue status from BGmgr bgQueue.RemovePlayer(_player->GetGUID(), false); // this is still needed here if battleground "jumping" shouldn't add deserter debuff @@ -466,6 +467,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) _player->SetBattlegroundId(bg->GetInstanceID(), bgTypeId); // set the destination team _player->SetBGTeam(ginfo.Team); + // bg->HandleBeforeTeleportToBattleground(_player); sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); // add only in HandleMoveWorldPortAck() @@ -541,7 +543,7 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recvData*/) { // this line is checked, i only don't know if GetStartTime is changing itself after bg end! // send status in Battleground - sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType, bg->GetPlayerTeam(_player->GetGUID())); + sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, i, STATUS_IN_PROGRESS, bg->GetEndTime(), bg->GetStartTime(), arenaType, _player->GetBGTeam()); SendPacket(&data); continue; } -- cgit v1.2.3 From 4372d24a7cc9dab325a9352bedf053a7580ac7b4 Mon Sep 17 00:00:00 2001 From: kaelima Date: Sun, 20 Jan 2013 20:06:30 +0100 Subject: Core/Movement: Prevent calling _updateSpeed for pets during a maptransfer Closes #8998 --- .../Movement/MovementGenerators/TargetedMovementGenerator.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 1958774380e..20c9c6cb608 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -273,15 +273,16 @@ void FollowMovementGenerator::_updateSpeed(Player &/*u*/) } template<> -void FollowMovementGenerator::_updateSpeed(Creature &u) +void FollowMovementGenerator::_updateSpeed(Creature& owner) { // pet only sync speed with owner - if (!((Creature&)u).isPet() || !i_target.isValid() || i_target->GetGUID() != u.GetOwnerGUID()) + /// Make sure we are not in the process of a map change + if (!owner.isPet() || !owner.IsInWorld() || !i_target.isValid() || i_target->GetGUID() != owner.GetOwnerGUID()) return; - u.UpdateSpeed(MOVE_RUN, true); - u.UpdateSpeed(MOVE_WALK, true); - u.UpdateSpeed(MOVE_SWIM, true); + owner.UpdateSpeed(MOVE_RUN, true); + owner.UpdateSpeed(MOVE_WALK, true); + owner.UpdateSpeed(MOVE_SWIM, true); } template<> -- cgit v1.2.3 From b153e68cfdd79adaeaff99cda1c0bfdbf22f2cd6 Mon Sep 17 00:00:00 2001 From: Mislav Blažević Date: Sun, 20 Jan 2013 16:36:55 +0100 Subject: Too small buffer fail --- src/server/game/DataStores/DBCStores.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 3fdff8e11d6..ad1c2d8e0b1 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -237,9 +237,10 @@ inline void LoadDBC(uint32& availableDbcLocales, StoreProblemList& errors, DBCSt // sort problematic dbc to (1) non compatible and (2) non-existed if (FILE* f = fopen(dbcFilename.c_str(), "rb")) { - char buf[100]; - snprintf(buf, 100, " exists, and has %u field(s) (expected " SIZEFMTD "). Extracted file might be from wrong client version or a database-update has been forgotten.", storage.GetFieldCount(), strlen(storage.GetFormat())); - errors.push_back(dbcFilename + buf); + std::ostringstream stream; + stream << dbcFilename << " exists, and has " << storage.GetFieldCount() << " field(s) (expected " << strlen(storage.GetFormat()) << "). Extracted file might be from wrong client version or a database-update has been forgotten."; + std::string buf = stream.str(); + errors.push_back(buf); fclose(f); } else -- cgit v1.2.3 From 4d7b2c4929c7efc5ce5c82f7a884d383094cc087 Mon Sep 17 00:00:00 2001 From: kaelima Date: Sun, 20 Jan 2013 21:30:11 +0100 Subject: Corrections to 1eab850cab9c71c0e8086af538aded557c526914 --- src/server/game/Entities/Player/Player.h | 2 +- .../game/Movement/MovementGenerators/TargetedMovementGenerator.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 6d9d63b8fda..a1e6591413f 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2222,7 +2222,7 @@ class Player : public Unit, public GridObject void SetBGTeam(uint32 team) { m_bgData.bgTeam = team; - SetByteValue(PLAYER_BYTES_3, 3, uint8(team == ALLIANCE ? TEAM_ALLIANCE : TEAM_HORDE)); + SetByteValue(PLAYER_BYTES_3, 3, uint8(team == ALLIANCE ? 1 : 0)); } uint32 GetBGTeam() const { return m_bgData.bgTeam ? m_bgData.bgTeam : GetTeam(); } diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 20c9c6cb608..7a1cf552731 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -276,7 +276,7 @@ template<> void FollowMovementGenerator::_updateSpeed(Creature& owner) { // pet only sync speed with owner - /// Make sure we are not in the process of a map change + /// Make sure we are not in the process of a map change (IsInWorld) if (!owner.isPet() || !owner.IsInWorld() || !i_target.isValid() || i_target->GetGUID() != owner.GetOwnerGUID()) return; -- cgit v1.2.3 From b7dbc8d746ed583ff5b4b529ce4441aa3c1149ba Mon Sep 17 00:00:00 2001 From: Malcrom Date: Sun, 20 Jan 2013 18:04:06 -0330 Subject: Scripting/Zulgrub: Updated Boss Arlokk Script. --- .../world/2013_01_20_09_world_spell_dbc.sql | 18 + .../EasternKingdoms/ZulGurub/boss_arlokk.cpp | 396 ++++++++++++++++----- .../EasternKingdoms/ZulGurub/instance_zulgurub.cpp | 77 ++-- .../scripts/EasternKingdoms/ZulGurub/zulgurub.h | 22 +- 4 files changed, 396 insertions(+), 117 deletions(-) create mode 100644 sql/updates/world/2013_01_20_09_world_spell_dbc.sql (limited to 'src') diff --git a/sql/updates/world/2013_01_20_09_world_spell_dbc.sql b/sql/updates/world/2013_01_20_09_world_spell_dbc.sql new file mode 100644 index 00000000000..bdd57e940b5 --- /dev/null +++ b/sql/updates/world/2013_01_20_09_world_spell_dbc.sql @@ -0,0 +1,18 @@ +-- Add missing spells to spell_dbc +DELETE FROM `spell_dbc` WHERE `Id` IN (24211,24246,24235,7939); +INSERT INTO `spell_dbc` (`Id`,`SchoolMask`,`Dispel`,`Mechanic`,`Attributes`,`AttributesEx`,`AttributesEx2`,`AttributesEx3`,`AttributesEx4`,`Stances`,`StancesNot`,`Targets`,`CastingTimeIndex`,`AuraInterruptFlags`,`ProcFlags`,`ProcChance`,`ProcCharges`,`MaxLevel`,`BaseLevel`,`SpellLevel`,`DurationIndex`,`RangeIndex`,`StackAmount`,`EquippedItemClass`,`EquippedItemSubClassMask`,`EquippedItemInventoryTypeMask`,`Effect1`,`Effect2`,`Effect3`,`EffectDieSides1`,`EffectDieSides2`,`EffectDieSides3`,`EffectRealPointsPerLevel1`,`EffectRealPointsPerLevel2`,`EffectRealPointsPerLevel3`,`EffectBasePoints1`,`EffectBasePoints2`,`EffectBasePoints3`,`EffectMechanic1`,`EffectMechanic2`,`EffectMechanic3`,`EffectImplicitTargetA1`,`EffectImplicitTargetA2`,`EffectImplicitTargetA3`,`EffectImplicitTargetB1`,`EffectImplicitTargetB2`,`EffectImplicitTargetB3`,`EffectRadiusIndex1`,`EffectRadiusIndex2`,`EffectRadiusIndex3`,`EffectApplyAuraName1`,`EffectApplyAuraName2`,`EffectApplyAuraName3`,`EffectAmplitude1`,`EffectAmplitude2`,`EffectAmplitude3`,`EffectMultipleValue1`,`EffectMultipleValue2`,`EffectMultipleValue3`,`EffectMiscValue1`,`EffectMiscValue2`,`EffectMiscValue3`,`EffectTriggerSpell1`,`EffectTriggerSpell2`,`EffectTriggerSpell3`,`Comment`,`MaxTargetLevel`,`SpellFamilyName`,`SpellFamilyFlags1`,`SpellFamilyFlags2`,`MaxAffectedTargets`,`DmgClass`,`PreventionType`,`DmgMultiplier1`,`DmgMultiplier2`,`DmgMultiplier3`,`EffectMiscValueB1`) VALUES +(24211,0,0,0,256,0,4,0,0,0,0,0,1,0,0,101,0,0,0,0,0,0,0,-1,0,0,63,0,0,1,0,0,0,0,0,4999,0,0,0,0,0,22,0,0,0,0,0,7,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'Mark of Arlokk',0,0,0,0,0,0,0,1,0,0,0), +(24246,0,0,0,256,0,0,0,0,0,0,0,1,0,0,101,0,0,0,0,6,0,0,-1,0,0,28,0,0,1,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,15101,0,0,0,0,0,'Summon Zulian Prowler',0,0,0,0,0,0,0,1,0,0,64), +(24235,0,0,0,272,268435456,0,0,0,0,0,0,1,0,0,101,0,0,0,0,1,0,0,-1,0,0,6,0,0,0,0,0,0,0,0,9999,0,0,0,0,0,1,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'Super Invis',0,0,0,0,0,0,0,1,1,1,0), +(7939,0,5,0,402915728,268435456,0,0,0,0,0,0,1,6147,0,101,0,0,1,1,21,1,0,-1,-1,0,6,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 'Sneak Rank 1',0,0,0,0,0,0,0,-1,1,1,0); + +-- Add script name to Zulian Prowler +UPDATE `creature_template` SET `AIName` = '', `ScriptName`='npc_zulian_prowler' WHERE `entry`=15101; + +-- Remove SmartAI +DELETE FROM smart_scripts WHERE entryorguid = 15101; + +-- Add condition for Mark of Arlokk +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=24211; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13,1,24211,0,0,0,31,3,15101,0,0,0,0, '', 'Mark of Arlokk - Targets Zulian Prowler'); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 51aab7c20d0..9d6aaf71665 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -17,10 +16,12 @@ */ /* ScriptData -SDName: Boss_Arlokk -SD%Complete: 95 -SDComment: Wrong cleave and red aura is missing. -SDCategory: Zul'Gurub +TCName: Boss_Arlokk +TC%Complete: 95 +TCComment: Wrong cleave and red aura is missing not yet added. +TCComment: Prowlers moving through wall hopefully mmaps will fix. +TCComment: Can't test LOS until mmaps. +TCCategory: Zul'Gurub EndScriptData */ #include "ScriptMgr.h" @@ -30,47 +31,58 @@ EndScriptData */ enum Says { SAY_AGGRO = 0, - SAY_FEAST_PANTHER = 1, + SAY_FEAST_PROWLER = 1, SAY_DEATH = 2 }; enum Spells { - SPELL_SHADOW_WORD_PAIN = 23952, - SPELL_GOUGE = 24698, - SPELL_MARK = 24210, - SPELL_CLEAVE = 26350, // Perhaps not right. Not a red aura... - SPELL_PANTHER_TRANSFORM = 24190 + SPELL_SHADOW_WORD_PAIN = 24212, // corrected + SPELL_GOUGE = 12540, // corrected + SPELL_MARK_OF_ARLOKK = 24210, // This is correct triggers 24211 Added to Spell_dbc + SPELL_RAVAGE = 24213, // corrected + SPELL_CLEAVE = 25174, // Searching for right spell + SPELL_PANTHER_TRANSFORM = 24190, // Transform to panther now used + SPELL_SUMMON_PROWLER = 24246, // Added to Spell_dbc + SPELL_VANISH_VISUAL = 24222, // Added + SPELL_VANISH = 24223, // Added + SPELL_SUPER_INVIS = 24235 // Added }; enum Events { - EVENT_SHADOW_WORD_PAIN = 0, - EVENT_GOUGE = 1, - EVENT_MARK = 2, - EVENT_CLEAVE = 3, - EVENT_VANISH = 4, - EVENT_VISIBLE = 5, - EVENT_SUMMON = 6 + EVENT_SHADOW_WORD_PAIN = 1, + EVENT_GOUGE = 2, + EVENT_MARK_OF_ARLOKK = 3, + EVENT_RAVAGE = 4, + EVENT_TRANSFORM = 5, + EVENT_VANISH = 6, + EVENT_VANISH_2 = 7, + EVENT_TRANSFORM_BACK = 8, + EVENT_VISIBLE = 9, + EVENT_SUMMON_PROWLERS = 10 }; enum Phases { - PHASE_ONE = 1, - PHASE_TWO = 2 + PHASE_ALL = 0, + PHASE_ONE = 1, + PHASE_TWO = 2 }; -enum ModelIds +enum Weapon { - MODEL_ID_NORMAL = 15218, - MODEL_ID_PANTHER = 15215, - MODEL_ID_BLANK = 11686 + WEAPON_DAGGER = 10616 }; -Position const PosSummonProwlers[2] = +enum Misc { - { -11532.7998f, -1649.6734f, 41.4800f, 0.0f }, - { -11532.9970f, -1606.4840f, 41.2979f, 0.0f } + MAX_PROWLERS_PER_SIDE = 15 +}; + +Position const PosMoveOnSpawn[1] = +{ + { -11561.9f, -1627.868f, 41.29941f } }; class boss_arlokk : public CreatureScript @@ -83,52 +95,88 @@ class boss_arlokk : public CreatureScript void Reset() { - summonCount = 0; - markedTargetGUID = 0; - me->SetDisplayId(MODEL_ID_NORMAL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summonCountA = 0; + summonCountB = 0; + me->RemoveAllAuras(); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER)); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER)); + if (instance) + { + if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) + gate->SetGoState(GO_STATE_READY); + me->SetWalk(false); + me->GetMotionMaster()->MovePoint(0, PosMoveOnSpawn[0].m_positionX,PosMoveOnSpawn[0].m_positionY,PosMoveOnSpawn[0].m_positionZ); + } } void JustDied(Unit* /*killer*/) { - _JustDied(); Talk(SAY_DEATH); - me->SetDisplayId(MODEL_ID_NORMAL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAllAuras(); + if (instance) + { + if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) + gate->SetGoState(GO_STATE_ACTIVE); + instance->SetBossState(DATA_ARLOKK, DONE); + } } void EnterCombat(Unit* /*who*/) { _EnterCombat(); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_MARK, 35000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON, 5000); - events.ScheduleEvent(EVENT_VANISH, 60000); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(7000, 9000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); + if (instance) + events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); + events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(9000, 11000), 0, PHASE_ALL); + events.ScheduleEvent(EVENT_TRANSFORM, urand(15000, 20000), 0, PHASE_ONE); Talk(SAY_AGGRO); - } - void JustReachedHome() - { - instance->SetBossState(DATA_ARLOKK, NOT_STARTED); - me->DespawnOrUnsummon(); + // Sets up list of Panther spawners to cast on + std::list triggerList; + GetCreatureListWithEntryInGrid(triggerList, me, NPC_PANTHER_TRIGGER, 100.0f); + if (!triggerList.empty()) + { + uint8 sideA = 0; + uint8 sideB = 0; + for (std::list::const_iterator itr = triggerList.begin(); itr != triggerList.end(); ++itr) + { + if (Creature* trigger = *itr) + { + if (trigger->GetPositionY() < -1625.0f) + { + triggersSideAGUID[sideA] = trigger->GetGUID(); + ++sideA; + } + else + { + triggersSideBGUID[sideB] = trigger->GetGUID(); + ++sideB; + } + } + } + } } - void DoSummonPhanters() + void EnterEvadeMode() { - if (summonCount > 30) - return; - - if (markedTargetGUID) - Talk(SAY_FEAST_PANTHER, markedTargetGUID); - me->SummonCreature(NPC_ZULIAN_PROWLER, PosSummonProwlers[0], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - me->SummonCreature(NPC_ZULIAN_PROWLER, PosSummonProwlers[1], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + if (instance) + { + if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) + object->SetGoState(GO_STATE_ACTIVE); + if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_GONG_OF_BETHEKK))) + object->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + instance->SetBossState(DATA_ARLOKK, NOT_STARTED); + } + me->DespawnOrUnsummon(4000); } - void JustSummoned(Creature* summoned) + void SetData(uint32 uiId, uint32 uiValue) { - if (Unit* markedTarget = Unit::GetUnit(*me, markedTargetGUID)) - summoned->AI()->AttackStart(markedTarget); - ++summonCount; + if (uiId == 1) + --summonCountA; + if (uiId == 2) + --summonCountB; } void UpdateAI(uint32 const diff) @@ -147,47 +195,99 @@ class boss_arlokk : public CreatureScript { case EVENT_SHADOW_WORD_PAIN: DoCastVictim(SPELL_SHADOW_WORD_PAIN, true); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 15000, 0, PHASE_ONE); - break; - case EVENT_MARK: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_MARK); - events.ScheduleEvent(EVENT_MARK, 15000, 0, PHASE_ONE); - break; - case EVENT_CLEAVE: - DoCastVictim(SPELL_SHADOW_WORD_PAIN, true); - events.ScheduleEvent(EVENT_CLEAVE, 16000, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(5000, 7000), 0, PHASE_ONE); break; case EVENT_GOUGE: - DoCastVictim(SPELL_SHADOW_WORD_PAIN, true); - events.ScheduleEvent(EVENT_GOUGE, urand(17000, 27000), 0, PHASE_TWO); + DoCastVictim(SPELL_GOUGE, true); break; - case EVENT_SUMMON: - DoSummonPhanters(); - events.ScheduleEvent(EVENT_SUMMON, 5000); + case EVENT_SUMMON_PROWLERS: + if (summonCountA < MAX_PROWLERS_PER_SIDE) + if (Unit* trigger = me->GetUnit(*me, triggersSideAGUID[urand(0, 4)])) + { + trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER); + ++summonCountA; + } + if (summonCountB < MAX_PROWLERS_PER_SIDE) + if (Unit* trigger = me->GetUnit(*me, triggersSideBGUID[urand(0, 4)])) + { + trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER); + ++summonCountB; + } + events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); break; - case EVENT_VANISH: - me->SetDisplayId(MODEL_ID_BLANK); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->AttackStop(); - DoResetThreat(); - events.ScheduleEvent(EVENT_VISIBLE, 6000); + case EVENT_MARK_OF_ARLOKK: + { + Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, urand(1,3), 0.0f, false, -SPELL_MARK_OF_ARLOKK); + if (!target) + target = me->getVictim(); + if (target) + { + DoCast(target, SPELL_MARK_OF_ARLOKK, true); + Talk(SAY_FEAST_PROWLER, target->GetGUID()); + } break; - case EVENT_VISIBLE: + events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(120000, 130000)); + } + case EVENT_TRANSFORM: { - me->SetDisplayId(MODEL_ID_PANTHER); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_PANTHER_TRANSFORM); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP)); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(EQUIP_UNEQUIP)); const CreatureTemplate* cinfo = me->GetCreatureTemplate(); me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35))); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35))); me->UpdateDamagePhysical(BASE_ATTACK); + me->AttackStop(); + DoResetThreat(); + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_VANISH_VISUAL); + DoCast(me, SPELL_VANISH); + events.ScheduleEvent(EVENT_VANISH, 1000, 0, PHASE_ONE); + break; + } + case EVENT_VANISH: + DoCast(me, SPELL_SUPER_INVIS); + me->SetWalk(false); + if (instance) + me->GetMotionMaster()->MovePoint(0, frand(-11551.0f, -11508.0f), frand(-1638.0f, -1617.0f), me->GetPositionZ()); + events.ScheduleEvent(EVENT_VANISH_2, 9000, 0, PHASE_ONE); + break; + case EVENT_VANISH_2: + DoCast(me, SPELL_VANISH); + DoCast(me, SPELL_SUPER_INVIS); + events.ScheduleEvent(EVENT_VISIBLE, urand(7000, 10000), 0, PHASE_ONE); + break; + case EVENT_VISIBLE: + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) AttackStart(target); - events.ScheduleEvent(EVENT_VANISH, 39000); - events.ScheduleEvent(EVENT_CLEAVE, 0, PHASE_TWO); - events.ScheduleEvent(EVENT_GOUGE, 14000, 0, PHASE_TWO); + me->RemoveAura(SPELL_SUPER_INVIS); + me->RemoveAura(SPELL_VANISH); + events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); + events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO); events.SetPhase(PHASE_TWO); break; + case EVENT_RAVAGE: + DoCastVictim(SPELL_RAVAGE, true); + events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); + break; + case EVENT_TRANSFORM_BACK: + { + me->RemoveAura(SPELL_PANTHER_TRANSFORM); + DoCast(me, SPELL_VANISH_VISUAL); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER)); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER)); + const CreatureTemplate* cinfo = me->GetCreatureTemplate(); + me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg)); + me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg)); + me->UpdateDamagePhysical(BASE_ATTACK); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE); + events.SetPhase(PHASE_ONE); + break; } default: break; @@ -198,8 +298,10 @@ class boss_arlokk : public CreatureScript } private: - uint32 summonCount; - uint64 markedTargetGUID; + uint8 summonCountA; + uint8 summonCountB; + uint64 triggersSideAGUID[5]; + uint64 triggersSideBGUID[5]; }; CreatureAI* GetAI(Creature* creature) const @@ -208,6 +310,123 @@ class boss_arlokk : public CreatureScript } }; +/*###### +## npc_zulian_prowler +######*/ + +enum ZulianProwlerSpells +{ + SPELL_SNEAK_RANK_1_1 = 22766, + SPELL_SNEAK_RANK_1_2 = 7939, + SPELL_MARK_OF_ARLOKK_TRIGGER = 24211 +}; + +enum ZulianProwlerEvents +{ + EVENT_ATTACK = 1 +}; + +Position const PosProwlerCenter[1] = +{ + { -11556.7f, -1631.344f, 41.2994f } +}; + +class npc_zulian_prowler : public CreatureScript +{ + public: npc_zulian_prowler() : CreatureScript("npc_zulian_prowler") {} + + struct npc_zulian_prowlerAI : public ScriptedAI + { + npc_zulian_prowlerAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { } + + void Reset() + { + if (me->GetPositionY() < -1625.0f) + sideData = 1; + else + sideData = 2; + + DoCast(me, SPELL_SNEAK_RANK_1_1); + DoCast(me, SPELL_SNEAK_RANK_1_2); + // me->SetReactState(REACT_PASSIVE); + + if (instance) + if (Unit* arlokk = me->GetUnit(*me, instance->GetData64(NPC_ARLOKK))) + me->GetMotionMaster()->MovePoint(0, arlokk->GetPositionX(), arlokk->GetPositionY(), arlokk->GetPositionZ()); + events.ScheduleEvent(EVENT_ATTACK, 6000); + } + + void EnterCombat(Unit* /*who*/) + { + me->GetMotionMaster()->Clear(false); + me->RemoveAura(SPELL_SNEAK_RANK_1_1); + me->RemoveAura(SPELL_SNEAK_RANK_1_2); + } + + void SpellHit(Unit* caster, SpellInfo const* spell) + { + if (spell->Id == SPELL_MARK_OF_ARLOKK_TRIGGER) // Should only hit if line of sight + { + me->Attack(caster, true); + } + } + + void JustDied(Unit* /*killer*/) + { + + if (instance) + if (Unit* arlokk = me->GetUnit(*me, instance->GetData64(NPC_ARLOKK))) + if (arlokk->isAlive()) + arlokk->GetAI()->SetData(sideData, 0); + me->DespawnOrUnsummon(4000); + } + + void UpdateAI(const uint32 diff) + { + + if (UpdateVictim()) + { + DoMeleeAttackIfReady(); + return; + } + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ATTACK: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0.0f, 100, false)) + me->Attack(target, true); + break; + default: + break; + } + } + } + + private: + int32 sideData; + EventMap events; + InstanceScript* instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return GetZulGurubAI(creature); + } +}; + +/*###### +## go_gong_of_bethekk +######*/ + +Position const PosSummonArlokk[1] = +{ + { -11507.22f, -1628.062f, 41.38264f, 3.159046f } +}; + class go_gong_of_bethekk : public GameObjectScript { public: go_gong_of_bethekk() : GameObjectScript("go_gong_of_bethekk") {} @@ -216,12 +435,11 @@ class go_gong_of_bethekk : public GameObjectScript { if (InstanceScript* instance = go->GetInstanceScript()) { - if (instance->GetBossState(DATA_ARLOKK) == DONE || instance->GetBossState(DATA_ARLOKK) == IN_PROGRESS) - return true; + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + go->SendCustomAnim(0); + go->SummonCreature(NPC_ARLOKK, PosSummonArlokk[0], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 600000); instance->SetBossState(DATA_ARLOKK, IN_PROGRESS); - return true; } - return true; } }; @@ -229,6 +447,6 @@ class go_gong_of_bethekk : public GameObjectScript void AddSC_boss_arlokk() { new boss_arlokk(); + new npc_zulian_prowler(); new go_gong_of_bethekk(); } - diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp index 19a2ba39578..d922e2db3f3 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp @@ -40,11 +40,14 @@ class instance_zulgurub : public InstanceMapScript void Initialize() { - ZealotLorkhanGUID = 0; - ZealotZathGUID = 0; - HighPriestTekalGUID = 0; - JindoTheHexxerGUID = 0; - VilebranchSpeakerGUID = 0; + zealotLorkhanGUID = 0; + zealotZathGUID = 0; + highPriestTekalGUID = 0; + jindoTheHexxerGUID = 0; + vilebranchSpeakerGUID = 0; + arlokkGUID = 0; + go_ForcefieldGUID = 0; + go_GongOfBethekkGUID = 0; } bool IsEncounterInProgress() const @@ -58,23 +61,41 @@ class instance_zulgurub : public InstanceMapScript switch (creature->GetEntry()) { case NPC_ZEALOT_LORKHAN: - ZealotLorkhanGUID = creature->GetGUID(); + zealotLorkhanGUID = creature->GetGUID(); break; case NPC_ZEALOT_ZATH: - ZealotZathGUID = creature->GetGUID(); + zealotZathGUID = creature->GetGUID(); break; case NPC_HIGH_PRIEST_THEKAL: - HighPriestTekalGUID = creature->GetGUID(); + highPriestTekalGUID = creature->GetGUID(); break; case NPC_JINDO_THE_HEXXER: - JindoTheHexxerGUID = creature->GetGUID(); + jindoTheHexxerGUID = creature->GetGUID(); break; case NPC_VILEBRANCH_SPEAKER: - VilebranchSpeakerGUID = creature->GetGUID(); + vilebranchSpeakerGUID = creature->GetGUID(); break; - case NPC_MANDOKIR: - if (GetBossState(DATA_MANDOKIR) == DONE) - creature->DespawnOrUnsummon(); + case NPC_ARLOKK: + arlokkGUID = creature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* go) + { + switch (go->GetEntry()) + { + case GO_FORCEFIELD: + go_ForcefieldGUID = go->GetGUID(); + break; + case GO_GONG_OF_BETHEKK: + go_GongOfBethekkGUID = go->GetGUID(); + if (GetBossState(DATA_ARLOKK) == DONE) + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + else + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; + default: break; } } @@ -84,16 +105,25 @@ class instance_zulgurub : public InstanceMapScript switch (uiData) { case DATA_LORKHAN: - return ZealotLorkhanGUID; + return zealotLorkhanGUID; break; case DATA_ZATH: - return ZealotZathGUID; + return zealotZathGUID; break; case DATA_THEKAL: - return HighPriestTekalGUID; + return highPriestTekalGUID; break; case DATA_JINDO: - return JindoTheHexxerGUID; + return jindoTheHexxerGUID; + break; + case NPC_ARLOKK: + return arlokkGUID; + break; + case GO_FORCEFIELD: + return go_ForcefieldGUID; + break; + case GO_GONG_OF_BETHEKK: + return go_GongOfBethekkGUID; break; } return 0; @@ -145,11 +175,14 @@ class instance_zulgurub : public InstanceMapScript //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too. //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too. - uint64 ZealotLorkhanGUID; - uint64 ZealotZathGUID; - uint64 HighPriestTekalGUID; - uint64 JindoTheHexxerGUID; - uint64 VilebranchSpeakerGUID; + uint64 zealotLorkhanGUID; + uint64 zealotZathGUID; + uint64 highPriestTekalGUID; + uint64 jindoTheHexxerGUID; + uint64 vilebranchSpeakerGUID; + uint64 arlokkGUID; + uint64 go_ForcefieldGUID; + uint64 go_GongOfBethekkGUID; }; InstanceScript* GetInstanceScript(InstanceMap* map) const diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h index 34680447cd7..77767153a96 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h +++ b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h @@ -36,23 +36,33 @@ enum DataTypes DATA_EDGE_OF_MADNESS = 9, // Optional Event Edge of Madness - one of: Gri'lek, Renataki, Hazza'rah, or Wushoolay DATA_LORKHAN = 10, // Zealot Lor'Khan add to High priest Thekal! DATA_ZATH = 11, // Zealot Zath add to High priest Thekal! - DATA_OHGAN = 12 // Bloodlord Mandokir's raptor mount + DATA_OHGAN = 12, // Bloodlord Mandokir's raptor mount + TYPE_EDGE_OF_MADNESS = 13 // Boss storage }; enum CreatureIds { + NPC_ARLOKK = 14515, // Arlokk Event + NPC_PANTHER_TRIGGER = 15091, // Arlokk Event + NPC_ZULIAN_PROWLER = 15101, // Arlokk Event NPC_ZEALOT_LORKHAN = 11347, NPC_ZEALOT_ZATH = 11348, NPC_HIGH_PRIEST_THEKAL = 14509, NPC_JINDO_THE_HEXXER = 11380, NPC_NIGHTMARE_ILLUSION = 15163, - NPC_ZULIAN_PROWLER = 15101, - NPC_VILEBRANCH_SPEAKER = 11391, NPC_SHADE_OF_JINDO = 14986, NPC_SACRIFICED_TROLL = 14826, - NPC_OHGAN = 14988, - NPC_CHAINED_SPIRT = 15117, - NPC_MANDOKIR = 11382 + NPC_MANDOKIR = 11382, // Mandokir Event + NPC_OHGAN = 14988, // Mandokir Event + NPC_VILEBRANCH_SPEAKER = 11391, // Mandokir Event + NPC_CHAINED_SPIRT = 15117 // Mandokir Event + +}; + +enum GameobjectIds +{ + GO_FORCEFIELD = 180497, // Arlokk Event + GO_GONG_OF_BETHEKK = 180526 // Arlokk Event }; template -- cgit v1.2.3 From 33b768569635fc4a2477ed63e6a1673f5ada6660 Mon Sep 17 00:00:00 2001 From: Malcrom Date: Sun, 20 Jan 2013 18:20:46 -0330 Subject: Scripting/ZulGrub: Fix last commit --- .../EasternKingdoms/ZulGurub/boss_arlokk.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 9d6aaf71665..3682b265cbc 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -26,6 +26,7 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellInfo.h" #include "zulgurub.h" enum Says @@ -37,16 +38,16 @@ enum Says enum Spells { - SPELL_SHADOW_WORD_PAIN = 24212, // corrected - SPELL_GOUGE = 12540, // corrected - SPELL_MARK_OF_ARLOKK = 24210, // This is correct triggers 24211 Added to Spell_dbc - SPELL_RAVAGE = 24213, // corrected + SPELL_SHADOW_WORD_PAIN = 24212, // Corrected + SPELL_GOUGE = 12540, // Corrected + SPELL_MARK_OF_ARLOKK = 24210, // triggered spell 24211 Added to spell_dbc + SPELL_RAVAGE = 24213, // Corrected SPELL_CLEAVE = 25174, // Searching for right spell SPELL_PANTHER_TRANSFORM = 24190, // Transform to panther now used SPELL_SUMMON_PROWLER = 24246, // Added to Spell_dbc SPELL_VANISH_VISUAL = 24222, // Added SPELL_VANISH = 24223, // Added - SPELL_SUPER_INVIS = 24235 // Added + SPELL_SUPER_INVIS = 24235 // Added to Spell_dbc }; enum Events @@ -105,7 +106,7 @@ class boss_arlokk : public CreatureScript if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) gate->SetGoState(GO_STATE_READY); me->SetWalk(false); - me->GetMotionMaster()->MovePoint(0, PosMoveOnSpawn[0].m_positionX,PosMoveOnSpawn[0].m_positionY,PosMoveOnSpawn[0].m_positionZ); + me->GetMotionMaster()->MovePoint(0, PosMoveOnSpawn[0]); } } @@ -171,7 +172,7 @@ class boss_arlokk : public CreatureScript me->DespawnOrUnsummon(4000); } - void SetData(uint32 uiId, uint32 uiValue) + void SetData(uint32 uiId, uint32 /*uiValue*/) { if (uiId == 1) --summonCountA; @@ -317,8 +318,8 @@ class boss_arlokk : public CreatureScript enum ZulianProwlerSpells { SPELL_SNEAK_RANK_1_1 = 22766, - SPELL_SNEAK_RANK_1_2 = 7939, - SPELL_MARK_OF_ARLOKK_TRIGGER = 24211 + SPELL_SNEAK_RANK_1_2 = 7939, // Added to Spell_dbc + SPELL_MARK_OF_ARLOKK_TRIGGER = 24211 // Added to Spell_dbc }; enum ZulianProwlerEvents @@ -348,7 +349,6 @@ class npc_zulian_prowler : public CreatureScript DoCast(me, SPELL_SNEAK_RANK_1_1); DoCast(me, SPELL_SNEAK_RANK_1_2); - // me->SetReactState(REACT_PASSIVE); if (instance) if (Unit* arlokk = me->GetUnit(*me, instance->GetData64(NPC_ARLOKK))) @@ -438,7 +438,6 @@ class go_gong_of_bethekk : public GameObjectScript go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); go->SendCustomAnim(0); go->SummonCreature(NPC_ARLOKK, PosSummonArlokk[0], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 600000); - instance->SetBossState(DATA_ARLOKK, IN_PROGRESS); } return true; } -- cgit v1.2.3 From dd7391660b9c897fdb4584ab03227bde2478ecee Mon Sep 17 00:00:00 2001 From: jackpoz Date: Mon, 21 Jan 2013 01:55:56 +0000 Subject: Core/Collision: Fix BIH::intersectRay crash Assure that BIHWrap::remove(const T& obj) actually removes every reference of obj from BIHWrap. Also add sanity checks to MDLCallback () functions to avoid array overruns. Closes #5218 Signed-off-by: Nay --- .../collision/BoundingIntervalHierarchyWrapper.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/collision/BoundingIntervalHierarchyWrapper.h b/src/server/collision/BoundingIntervalHierarchyWrapper.h index 8a99078caab..315f3004306 100644 --- a/src/server/collision/BoundingIntervalHierarchyWrapper.h +++ b/src/server/collision/BoundingIntervalHierarchyWrapper.h @@ -33,11 +33,14 @@ class BIHWrap { const T* const* objects; RayCallback& _callback; + uint32 objects_size; - MDLCallback(RayCallback& callback, const T* const* objects_array ) : objects(objects_array), _callback(callback) {} + MDLCallback(RayCallback& callback, const T* const* objects_array, uint32 objects_size ) : objects(objects_array), _callback(callback), objects_size(objects_size) {} bool operator() (const Ray& ray, uint32 Idx, float& MaxDist, bool /*stopAtFirst*/) { + if (Idx >= objects_size) + return false; if (const T* obj = objects[Idx]) return _callback(ray, *obj, MaxDist/*, stopAtFirst*/); return false; @@ -45,6 +48,8 @@ class BIHWrap void operator() (const Vector3& p, uint32 Idx) { + if (Idx >= objects_size) + return false; if (const T* obj = objects[Idx]) _callback(p, *obj); } @@ -87,21 +92,24 @@ public: m_objects.fastClear(); m_obj2Idx.getKeys(m_objects); m_objects_to_push.getMembers(m_objects); + //assert that m_obj2Idx has all the keys m_tree.build(m_objects, BoundsFunc::getBounds2); } template - void intersectRay(const Ray& ray, RayCallback& intersectCallback, float& maxDist) const + void intersectRay(const Ray& ray, RayCallback& intersectCallback, float& maxDist) { - MDLCallback temp_cb(intersectCallback, m_objects.getCArray()); + balance(); + MDLCallback temp_cb(intersectCallback, m_objects.getCArray(), m_objects.size()); m_tree.intersectRay(ray, temp_cb, maxDist, true); } template - void intersectPoint(const Vector3& point, IsectCallback& intersectCallback) const + void intersectPoint(const Vector3& point, IsectCallback& intersectCallback) { - MDLCallback callback(intersectCallback, m_objects.getCArray()); + balance(); + MDLCallback callback(intersectCallback, m_objects.getCArray(), m_objects.size()); m_tree.intersectPoint(point, callback); } }; -- cgit v1.2.3 From c6c23d67b8692936fe9e7d5920bfb997df516323 Mon Sep 17 00:00:00 2001 From: Nay Date: Mon, 21 Jan 2013 02:10:01 +0000 Subject: Scripts/ZG: Fix some code style issues and logic errors --- .../world/2013_01_20_09_world_spell_dbc.sql | 2 +- src/server/game/Miscellaneous/Language.h | 4 +- .../EasternKingdoms/ZulGurub/boss_arlokk.cpp | 146 +++++++++++---------- .../EasternKingdoms/ZulGurub/boss_gahzranka.cpp | 1 - .../EasternKingdoms/ZulGurub/boss_hazzarah.cpp | 1 - .../EasternKingdoms/ZulGurub/instance_zulgurub.cpp | 64 ++++----- 6 files changed, 110 insertions(+), 108 deletions(-) (limited to 'src') diff --git a/sql/updates/world/2013_01_20_09_world_spell_dbc.sql b/sql/updates/world/2013_01_20_09_world_spell_dbc.sql index bdd57e940b5..d8f466173f3 100644 --- a/sql/updates/world/2013_01_20_09_world_spell_dbc.sql +++ b/sql/updates/world/2013_01_20_09_world_spell_dbc.sql @@ -10,7 +10,7 @@ INSERT INTO `spell_dbc` (`Id`,`SchoolMask`,`Dispel`,`Mechanic`,`Attributes`,`Att UPDATE `creature_template` SET `AIName` = '', `ScriptName`='npc_zulian_prowler' WHERE `entry`=15101; -- Remove SmartAI -DELETE FROM smart_scripts WHERE entryorguid = 15101; +DELETE FROM `smart_scripts` WHERE `entryorguid`=15101; -- Add condition for Mark of Arlokk DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=24211; diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 35b0a6f8569..039e8b816b3 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -742,7 +742,7 @@ enum TrinityStrings LANG_COMMAND_CREATURESTORAGE_NOTFOUND = 818, LANG_CHANNEL_CITY = 819, - + LANG_NPCINFO_GOSSIP = 820, LANG_NPCINFO_QUESTGIVER = 821, LANG_NPCINFO_TRAINER_CLASS = 822, @@ -766,7 +766,7 @@ enum TrinityStrings LANG_NPCINFO_SPELLCLICK = 840, LANG_NPCINFO_MAILBOX = 841, LANG_NPCINFO_PLAYER_VEHICLE = 842, - + // Room for in-game strings 843-999 not used // Level 4 (CLI only commands) diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 3682b265cbc..4b4186c7684 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -96,14 +96,14 @@ class boss_arlokk : public CreatureScript void Reset() { - summonCountA = 0; - summonCountB = 0; + _summonCountA = 0; + _summonCountB = 0; me->RemoveAllAuras(); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER)); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER)); - if (instance) + if (_instance) { - if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) + if (GameObject* gate = me->GetMap()->GetGameObject(_instance->GetData64(GO_FORCEFIELD))) gate->SetGoState(GO_STATE_READY); me->SetWalk(false); me->GetMotionMaster()->MovePoint(0, PosMoveOnSpawn[0]); @@ -114,23 +114,23 @@ class boss_arlokk : public CreatureScript { Talk(SAY_DEATH); me->RemoveAllAuras(); - if (instance) + if (_instance) { - if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) + if (GameObject* gate = me->GetMap()->GetGameObject(_instance->GetData64(GO_FORCEFIELD))) gate->SetGoState(GO_STATE_ACTIVE); - instance->SetBossState(DATA_ARLOKK, DONE); + _instance->SetBossState(DATA_ARLOKK, DONE); } } void EnterCombat(Unit* /*who*/) { _EnterCombat(); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(7000, 9000), 0, PHASE_ONE); - events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); - if (instance) - events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); - events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(9000, 11000), 0, PHASE_ALL); - events.ScheduleEvent(EVENT_TRANSFORM, urand(15000, 20000), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(7000, 9000), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); + if (_instance) + _events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); + _events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(9000, 11000), 0, PHASE_ALL); + _events.ScheduleEvent(EVENT_TRANSFORM, urand(15000, 20000), 0, PHASE_ONE); Talk(SAY_AGGRO); // Sets up list of Panther spawners to cast on @@ -146,12 +146,12 @@ class boss_arlokk : public CreatureScript { if (trigger->GetPositionY() < -1625.0f) { - triggersSideAGUID[sideA] = trigger->GetGUID(); + _triggersSideAGUID[sideA] = trigger->GetGUID(); ++sideA; } else { - triggersSideBGUID[sideB] = trigger->GetGUID(); + _triggersSideBGUID[sideB] = trigger->GetGUID(); ++sideB; } } @@ -161,23 +161,23 @@ class boss_arlokk : public CreatureScript void EnterEvadeMode() { - if (instance) + if (_instance) { - if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) + if (GameObject* object = me->GetMap()->GetGameObject(_instance->GetData64(GO_FORCEFIELD))) object->SetGoState(GO_STATE_ACTIVE); - if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_GONG_OF_BETHEKK))) + if (GameObject* object = me->GetMap()->GetGameObject(_instance->GetData64(GO_GONG_OF_BETHEKK))) object->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - instance->SetBossState(DATA_ARLOKK, NOT_STARTED); + _instance->SetBossState(DATA_ARLOKK, NOT_STARTED); } me->DespawnOrUnsummon(4000); } - void SetData(uint32 uiId, uint32 /*uiValue*/) + void SetData(uint32 id, uint32 /*value*/) { - if (uiId == 1) - --summonCountA; - if (uiId == 2) - --summonCountB; + if (id == 1) + --_summonCountA; + else if (id == 2) + --_summonCountB; } void UpdateAI(uint32 const diff) @@ -185,36 +185,40 @@ class boss_arlokk : public CreatureScript if (!UpdateVictim()) return; - events.Update(diff); + _events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_SHADOW_WORD_PAIN: DoCastVictim(SPELL_SHADOW_WORD_PAIN, true); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(5000, 7000), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(5000, 7000), 0, PHASE_ONE); break; case EVENT_GOUGE: DoCastVictim(SPELL_GOUGE, true); break; case EVENT_SUMMON_PROWLERS: - if (summonCountA < MAX_PROWLERS_PER_SIDE) - if (Unit* trigger = me->GetUnit(*me, triggersSideAGUID[urand(0, 4)])) + if (_summonCountA < MAX_PROWLERS_PER_SIDE) + { + if (Unit* trigger = me->GetUnit(*me, _triggersSideAGUID[urand(0, 4)])) { trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER); - ++summonCountA; + ++_summonCountA; } - if (summonCountB < MAX_PROWLERS_PER_SIDE) - if (Unit* trigger = me->GetUnit(*me, triggersSideBGUID[urand(0, 4)])) + } + if (_summonCountB < MAX_PROWLERS_PER_SIDE) + { + if (Unit* trigger = me->GetUnit(*me, _triggersSideBGUID[urand(0, 4)])) { trigger->CastSpell(trigger, SPELL_SUMMON_PROWLER); - ++summonCountB; + ++_summonCountB; } - events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); + } + _events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); break; case EVENT_MARK_OF_ARLOKK: { @@ -226,8 +230,8 @@ class boss_arlokk : public CreatureScript DoCast(target, SPELL_MARK_OF_ARLOKK, true); Talk(SAY_FEAST_PROWLER, target->GetGUID()); } + _events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(120000, 130000)); break; - events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(120000, 130000)); } case EVENT_TRANSFORM: { @@ -244,20 +248,20 @@ class boss_arlokk : public CreatureScript me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); DoCast(me, SPELL_VANISH_VISUAL); DoCast(me, SPELL_VANISH); - events.ScheduleEvent(EVENT_VANISH, 1000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_VANISH, 1000, 0, PHASE_ONE); break; } case EVENT_VANISH: DoCast(me, SPELL_SUPER_INVIS); me->SetWalk(false); - if (instance) + if (_instance) me->GetMotionMaster()->MovePoint(0, frand(-11551.0f, -11508.0f), frand(-1638.0f, -1617.0f), me->GetPositionZ()); - events.ScheduleEvent(EVENT_VANISH_2, 9000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_VANISH_2, 9000, 0, PHASE_ONE); break; case EVENT_VANISH_2: DoCast(me, SPELL_VANISH); DoCast(me, SPELL_SUPER_INVIS); - events.ScheduleEvent(EVENT_VISIBLE, urand(7000, 10000), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_VISIBLE, urand(7000, 10000), 0, PHASE_ONE); break; case EVENT_VISIBLE: me->SetReactState(REACT_AGGRESSIVE); @@ -266,13 +270,13 @@ class boss_arlokk : public CreatureScript AttackStart(target); me->RemoveAura(SPELL_SUPER_INVIS); me->RemoveAura(SPELL_VANISH); - events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); - events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO); - events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); + _events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO); + _events.SetPhase(PHASE_TWO); break; case EVENT_RAVAGE: DoCastVictim(SPELL_RAVAGE, true); - events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); + _events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); break; case EVENT_TRANSFORM_BACK: { @@ -284,10 +288,10 @@ class boss_arlokk : public CreatureScript me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg)); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg)); me->UpdateDamagePhysical(BASE_ATTACK); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE); - events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); - events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE); - events.SetPhase(PHASE_ONE); + _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE); + _events.SetPhase(PHASE_ONE); break; } default: @@ -299,10 +303,10 @@ class boss_arlokk : public CreatureScript } private: - uint8 summonCountA; - uint8 summonCountB; - uint64 triggersSideAGUID[5]; - uint64 triggersSideBGUID[5]; + uint8 _summonCountA; + uint8 _summonCountB; + uint64 _triggersSideAGUID[5]; + uint64 _triggersSideBGUID[5]; }; CreatureAI* GetAI(Creature* creature) const @@ -338,22 +342,22 @@ class npc_zulian_prowler : public CreatureScript struct npc_zulian_prowlerAI : public ScriptedAI { - npc_zulian_prowlerAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { } + npc_zulian_prowlerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } void Reset() { if (me->GetPositionY() < -1625.0f) - sideData = 1; + _sideData = 1; else - sideData = 2; + _sideData = 2; DoCast(me, SPELL_SNEAK_RANK_1_1); DoCast(me, SPELL_SNEAK_RANK_1_2); - if (instance) - if (Unit* arlokk = me->GetUnit(*me, instance->GetData64(NPC_ARLOKK))) + if (_instance) + if (Unit* arlokk = me->GetUnit(*me, _instance->GetData64(NPC_ARLOKK))) me->GetMotionMaster()->MovePoint(0, arlokk->GetPositionX(), arlokk->GetPositionY(), arlokk->GetPositionZ()); - events.ScheduleEvent(EVENT_ATTACK, 6000); + _events.ScheduleEvent(EVENT_ATTACK, 6000); } void EnterCombat(Unit* /*who*/) @@ -366,33 +370,33 @@ class npc_zulian_prowler : public CreatureScript void SpellHit(Unit* caster, SpellInfo const* spell) { if (spell->Id == SPELL_MARK_OF_ARLOKK_TRIGGER) // Should only hit if line of sight - { me->Attack(caster, true); - } } void JustDied(Unit* /*killer*/) { - - if (instance) - if (Unit* arlokk = me->GetUnit(*me, instance->GetData64(NPC_ARLOKK))) - if (arlokk->isAlive()) - arlokk->GetAI()->SetData(sideData, 0); + if (_instance) + { + if (Unit* arlokk = me->GetUnit(*me, instance->GetData64(NPC_ARLOKK))) + { + if (arlokk->isAlive()) + arlokk->GetAI()->SetData(_sideData, 0); + } + } me->DespawnOrUnsummon(4000); } void UpdateAI(const uint32 diff) { - if (UpdateVictim()) { DoMeleeAttackIfReady(); return; } - events.Update(diff); + _events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { @@ -407,9 +411,9 @@ class npc_zulian_prowler : public CreatureScript } private: - int32 sideData; - EventMap events; - InstanceScript* instance; + int32 _sideData; + EventMap _events; + InstanceScript* _instance; }; CreatureAI* GetAI(Creature* creature) const @@ -433,7 +437,7 @@ class go_gong_of_bethekk : public GameObjectScript bool OnGossipHello(Player* /*player*/, GameObject* go) { - if (InstanceScript* instance = go->GetInstanceScript()) + if (go->GetInstanceScript()) { go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); go->SendCustomAnim(0); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp index 70399b6934c..f3f12bc35c5 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp @@ -112,4 +112,3 @@ void AddSC_boss_gahzranka() { new boss_gahzranka(); } - diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp index 15228815d69..809403bb325 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_hazzarah.cpp @@ -121,4 +121,3 @@ void AddSC_boss_hazzarah() { new boss_hazzarah(); } - diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp index d922e2db3f3..01c5ef998f5 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/instance_zulgurub.cpp @@ -40,14 +40,14 @@ class instance_zulgurub : public InstanceMapScript void Initialize() { - zealotLorkhanGUID = 0; - zealotZathGUID = 0; - highPriestTekalGUID = 0; - jindoTheHexxerGUID = 0; - vilebranchSpeakerGUID = 0; - arlokkGUID = 0; - go_ForcefieldGUID = 0; - go_GongOfBethekkGUID = 0; + _zealotLorkhanGUID = 0; + _zealotZathGUID = 0; + _highPriestTekalGUID = 0; + _jindoTheHexxerGUID = 0; + _vilebranchSpeakerGUID = 0; + _arlokkGUID = 0; + _goForcefieldGUID = 0; + _goGongOfBethekkGUID = 0; } bool IsEncounterInProgress() const @@ -61,22 +61,22 @@ class instance_zulgurub : public InstanceMapScript switch (creature->GetEntry()) { case NPC_ZEALOT_LORKHAN: - zealotLorkhanGUID = creature->GetGUID(); + _zealotLorkhanGUID = creature->GetGUID(); break; case NPC_ZEALOT_ZATH: - zealotZathGUID = creature->GetGUID(); + _zealotZathGUID = creature->GetGUID(); break; case NPC_HIGH_PRIEST_THEKAL: - highPriestTekalGUID = creature->GetGUID(); + _highPriestTekalGUID = creature->GetGUID(); break; case NPC_JINDO_THE_HEXXER: - jindoTheHexxerGUID = creature->GetGUID(); + _jindoTheHexxerGUID = creature->GetGUID(); break; case NPC_VILEBRANCH_SPEAKER: - vilebranchSpeakerGUID = creature->GetGUID(); + _vilebranchSpeakerGUID = creature->GetGUID(); break; case NPC_ARLOKK: - arlokkGUID = creature->GetGUID(); + _arlokkGUID = creature->GetGUID(); break; } } @@ -86,13 +86,13 @@ class instance_zulgurub : public InstanceMapScript switch (go->GetEntry()) { case GO_FORCEFIELD: - go_ForcefieldGUID = go->GetGUID(); + _goForcefieldGUID = go->GetGUID(); break; case GO_GONG_OF_BETHEKK: - go_GongOfBethekkGUID = go->GetGUID(); + _goGongOfBethekkGUID = go->GetGUID(); if (GetBossState(DATA_ARLOKK) == DONE) go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - else + else go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); break; default: @@ -105,25 +105,25 @@ class instance_zulgurub : public InstanceMapScript switch (uiData) { case DATA_LORKHAN: - return zealotLorkhanGUID; + return _zealotLorkhanGUID; break; case DATA_ZATH: - return zealotZathGUID; + return _zealotZathGUID; break; case DATA_THEKAL: - return highPriestTekalGUID; + return _highPriestTekalGUID; break; case DATA_JINDO: - return jindoTheHexxerGUID; + return _jindoTheHexxerGUID; break; case NPC_ARLOKK: - return arlokkGUID; + return _arlokkGUID; break; case GO_FORCEFIELD: - return go_ForcefieldGUID; + return _goForcefieldGUID; break; case GO_GONG_OF_BETHEKK: - return go_GongOfBethekkGUID; + return _goGongOfBethekkGUID; break; } return 0; @@ -175,14 +175,14 @@ class instance_zulgurub : public InstanceMapScript //If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too. //Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for healfunction too. - uint64 zealotLorkhanGUID; - uint64 zealotZathGUID; - uint64 highPriestTekalGUID; - uint64 jindoTheHexxerGUID; - uint64 vilebranchSpeakerGUID; - uint64 arlokkGUID; - uint64 go_ForcefieldGUID; - uint64 go_GongOfBethekkGUID; + uint64 _zealotLorkhanGUID; + uint64 _zealotZathGUID; + uint64 _highPriestTekalGUID; + uint64 _jindoTheHexxerGUID; + uint64 _vilebranchSpeakerGUID; + uint64 _arlokkGUID; + uint64 _goForcefieldGUID; + uint64 _goGongOfBethekkGUID; }; InstanceScript* GetInstanceScript(InstanceMap* map) const -- cgit v1.2.3 From 236355265598955861cc9ecd46315737270ac893 Mon Sep 17 00:00:00 2001 From: Nay Date: Mon, 21 Jan 2013 02:24:25 +0000 Subject: Scripts/ZG: Fix a warning and a compile error introduced in previous commit Personal opinion: BossAI should not have a public field named "instance" --- .../EasternKingdoms/ZulGurub/boss_arlokk.cpp | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 4b4186c7684..3c549150a78 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -83,7 +83,7 @@ enum Misc Position const PosMoveOnSpawn[1] = { - { -11561.9f, -1627.868f, 41.29941f } + { -11561.9f, -1627.868f, 41.29941f, 0.0f } }; class boss_arlokk : public CreatureScript @@ -101,9 +101,9 @@ class boss_arlokk : public CreatureScript me->RemoveAllAuras(); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER)); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER)); - if (_instance) + if (instance) { - if (GameObject* gate = me->GetMap()->GetGameObject(_instance->GetData64(GO_FORCEFIELD))) + if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) gate->SetGoState(GO_STATE_READY); me->SetWalk(false); me->GetMotionMaster()->MovePoint(0, PosMoveOnSpawn[0]); @@ -114,11 +114,11 @@ class boss_arlokk : public CreatureScript { Talk(SAY_DEATH); me->RemoveAllAuras(); - if (_instance) + if (instance) { - if (GameObject* gate = me->GetMap()->GetGameObject(_instance->GetData64(GO_FORCEFIELD))) + if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) gate->SetGoState(GO_STATE_ACTIVE); - _instance->SetBossState(DATA_ARLOKK, DONE); + instance->SetBossState(DATA_ARLOKK, DONE); } } @@ -127,7 +127,7 @@ class boss_arlokk : public CreatureScript _EnterCombat(); _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(7000, 9000), 0, PHASE_ONE); _events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); - if (_instance) + if (instance) _events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); _events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(9000, 11000), 0, PHASE_ALL); _events.ScheduleEvent(EVENT_TRANSFORM, urand(15000, 20000), 0, PHASE_ONE); @@ -161,13 +161,13 @@ class boss_arlokk : public CreatureScript void EnterEvadeMode() { - if (_instance) + if (instance) { - if (GameObject* object = me->GetMap()->GetGameObject(_instance->GetData64(GO_FORCEFIELD))) + if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_FORCEFIELD))) object->SetGoState(GO_STATE_ACTIVE); - if (GameObject* object = me->GetMap()->GetGameObject(_instance->GetData64(GO_GONG_OF_BETHEKK))) + if (GameObject* object = me->GetMap()->GetGameObject(instance->GetData64(GO_GONG_OF_BETHEKK))) object->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - _instance->SetBossState(DATA_ARLOKK, NOT_STARTED); + instance->SetBossState(DATA_ARLOKK, NOT_STARTED); } me->DespawnOrUnsummon(4000); } @@ -254,7 +254,7 @@ class boss_arlokk : public CreatureScript case EVENT_VANISH: DoCast(me, SPELL_SUPER_INVIS); me->SetWalk(false); - if (_instance) + if (instance) me->GetMotionMaster()->MovePoint(0, frand(-11551.0f, -11508.0f), frand(-1638.0f, -1617.0f), me->GetPositionZ()); _events.ScheduleEvent(EVENT_VANISH_2, 9000, 0, PHASE_ONE); break; -- cgit v1.2.3 From 3523d84a9146b2aecd6895adb2a84f60a76c5f21 Mon Sep 17 00:00:00 2001 From: Nay Date: Mon, 21 Jan 2013 02:34:43 +0000 Subject: Shooting myself in 3... 2... --- .../EasternKingdoms/ZulGurub/boss_arlokk.cpp | 42 +++++++++++----------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 3c549150a78..2a8c663a5ed 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -125,12 +125,12 @@ class boss_arlokk : public CreatureScript void EnterCombat(Unit* /*who*/) { _EnterCombat(); - _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(7000, 9000), 0, PHASE_ONE); - _events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(7000, 9000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); if (instance) - _events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); - _events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(9000, 11000), 0, PHASE_ALL); - _events.ScheduleEvent(EVENT_TRANSFORM, urand(15000, 20000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); + events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(9000, 11000), 0, PHASE_ALL); + events.ScheduleEvent(EVENT_TRANSFORM, urand(15000, 20000), 0, PHASE_ONE); Talk(SAY_AGGRO); // Sets up list of Panther spawners to cast on @@ -185,18 +185,18 @@ class boss_arlokk : public CreatureScript if (!UpdateVictim()) return; - _events.Update(diff); + events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) return; - while (uint32 eventId = _events.ExecuteEvent()) + while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_SHADOW_WORD_PAIN: DoCastVictim(SPELL_SHADOW_WORD_PAIN, true); - _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(5000, 7000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(5000, 7000), 0, PHASE_ONE); break; case EVENT_GOUGE: DoCastVictim(SPELL_GOUGE, true); @@ -218,7 +218,7 @@ class boss_arlokk : public CreatureScript ++_summonCountB; } } - _events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); + events.ScheduleEvent(EVENT_SUMMON_PROWLERS, 6000, 0, PHASE_ALL); break; case EVENT_MARK_OF_ARLOKK: { @@ -230,7 +230,7 @@ class boss_arlokk : public CreatureScript DoCast(target, SPELL_MARK_OF_ARLOKK, true); Talk(SAY_FEAST_PROWLER, target->GetGUID()); } - _events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(120000, 130000)); + events.ScheduleEvent(EVENT_MARK_OF_ARLOKK, urand(120000, 130000)); break; } case EVENT_TRANSFORM: @@ -248,7 +248,7 @@ class boss_arlokk : public CreatureScript me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); DoCast(me, SPELL_VANISH_VISUAL); DoCast(me, SPELL_VANISH); - _events.ScheduleEvent(EVENT_VANISH, 1000, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_VANISH, 1000, 0, PHASE_ONE); break; } case EVENT_VANISH: @@ -256,12 +256,12 @@ class boss_arlokk : public CreatureScript me->SetWalk(false); if (instance) me->GetMotionMaster()->MovePoint(0, frand(-11551.0f, -11508.0f), frand(-1638.0f, -1617.0f), me->GetPositionZ()); - _events.ScheduleEvent(EVENT_VANISH_2, 9000, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_VANISH_2, 9000, 0, PHASE_ONE); break; case EVENT_VANISH_2: DoCast(me, SPELL_VANISH); DoCast(me, SPELL_SUPER_INVIS); - _events.ScheduleEvent(EVENT_VISIBLE, urand(7000, 10000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_VISIBLE, urand(7000, 10000), 0, PHASE_ONE); break; case EVENT_VISIBLE: me->SetReactState(REACT_AGGRESSIVE); @@ -270,13 +270,13 @@ class boss_arlokk : public CreatureScript AttackStart(target); me->RemoveAura(SPELL_SUPER_INVIS); me->RemoveAura(SPELL_VANISH); - _events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); - _events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO); - _events.SetPhase(PHASE_TWO); + events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); + events.ScheduleEvent(EVENT_TRANSFORM_BACK, urand(15000, 18000), 0, PHASE_TWO); + events.SetPhase(PHASE_TWO); break; case EVENT_RAVAGE: DoCastVictim(SPELL_RAVAGE, true); - _events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); + events.ScheduleEvent(EVENT_RAVAGE, urand(10000, 14000), 0, PHASE_TWO); break; case EVENT_TRANSFORM_BACK: { @@ -288,10 +288,10 @@ class boss_arlokk : public CreatureScript me->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg)); me->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg)); me->UpdateDamagePhysical(BASE_ATTACK); - _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE); - _events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); - _events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE); - _events.SetPhase(PHASE_ONE); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(4000, 7000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_GOUGE, urand(12000, 15000), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_TRANSFORM, urand(16000, 20000), 0, PHASE_ONE); + events.SetPhase(PHASE_ONE); break; } default: -- cgit v1.2.3 From 321b425f366330768f4bb84f8f4f785c53f3d1ff Mon Sep 17 00:00:00 2001 From: Aokromes Date: Mon, 21 Jan 2013 02:47:51 +0000 Subject: Update COPYING Signed-off-by: Nay --- COPYING | 40 +++++++++++----------- .../EasternKingdoms/ZulGurub/boss_arlokk.cpp | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/COPYING b/COPYING index cdfdede6e8c..d159169d105 100644 --- a/COPYING +++ b/COPYING @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to +the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not @@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - - GNU GENERAL PUBLIC LICENSE + + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions: License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in @@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - + 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is @@ -225,7 +225,7 @@ impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License @@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -303,16 +303,16 @@ the "copyright" line and a pointer to where the full notice is found. 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, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) year name of author + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. @@ -335,5 +335,5 @@ necessary. Here is a sample; alter the names: This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General +library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 2a8c663a5ed..e4e8235a172 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -377,7 +377,7 @@ class npc_zulian_prowler : public CreatureScript { if (_instance) { - if (Unit* arlokk = me->GetUnit(*me, instance->GetData64(NPC_ARLOKK))) + if (Unit* arlokk = me->GetUnit(*me, _instance->GetData64(NPC_ARLOKK))) { if (arlokk->isAlive()) arlokk->GetAI()->SetData(_sideData, 0); -- cgit v1.2.3 From 367e1f7b2b2b2754ea9225af0e8f90cb5b315871 Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Mon, 21 Jan 2013 10:11:46 +0100 Subject: Core: Fix warnings --- src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index e4e8235a172..c2806c395f4 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -333,7 +333,7 @@ enum ZulianProwlerEvents Position const PosProwlerCenter[1] = { - { -11556.7f, -1631.344f, 41.2994f } + { -11556.7f, -1631.344f, 41.2994f, 0.0f } }; class npc_zulian_prowler : public CreatureScript -- cgit v1.2.3 From 3cb80f206eb75ab7d1b09662885fd13f8cf46071 Mon Sep 17 00:00:00 2001 From: Nay Date: Mon, 21 Jan 2013 20:45:09 +0000 Subject: Core/Config: Set mmaps disabled by default --- src/server/game/World/World.cpp | 2 +- src/server/worldserver/worldserver.conf.dist | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index da00034108c..8f42be71f44 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1132,7 +1132,7 @@ void World::LoadConfigSettings(bool reload) sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Using DataDir %s", m_dataPath.c_str()); } - m_bool_configs[CONFIG_ENABLE_MMAPS] = ConfigMgr::GetBoolDefault("mmap.enablePathFinding", true); + m_bool_configs[CONFIG_ENABLE_MMAPS] = ConfigMgr::GetBoolDefault("mmap.enablePathFinding", false); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "WORLD: MMap data directory is: %smmaps", m_dataPath.c_str()); m_bool_configs[CONFIG_VMAP_INDOOR_CHECK] = ConfigMgr::GetBoolDefault("vmap.enableIndoorCheck", 0); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index b3e6b636b32..51c083a3dbe 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -270,11 +270,11 @@ PlayerSave.Stats.SaveOnlyOnLogout = 1 # # mmap.enablePathFinding -# Description: Enable/Disable pathfinding using mmaps -# Default: 1 - (Enabled) -# 0 - (Disabled) +# Description: Enable/Disable pathfinding using mmaps - experimental +# Default: 0 - (Disabled) +# 1 - (Enabled) -mmap.enablePathFinding = 1 +mmap.enablePathFinding = 0 # # vmap.enableLOS -- cgit v1.2.3 From 0cdadcdd781b768d9869f6b06e6abb572fbfdefc Mon Sep 17 00:00:00 2001 From: Mislav Blažević Date: Tue, 22 Jan 2013 09:36:54 +0100 Subject: Expand ~ to home directory on unix --- src/server/game/World/World.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index d232920418d..264119ee99c 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1118,6 +1118,15 @@ void World::LoadConfigSettings(bool reload) if (dataPath.at(dataPath.length()-1) != '/' && dataPath.at(dataPath.length()-1) != '\\') dataPath.push_back('/'); +#if PLATFORM == PLATFORM_UNIX || PLATFORM == PLATFORM_APPLE + if (dataPath[0] == '~') + { + const char* home = getenv("HOME"); + if (home) + dataPath.replace(0, 1, home); + } +#endif + if (reload) { if (dataPath != m_dataPath) -- cgit v1.2.3 From a65caa6da2d6090ca23018706029f3a96a035b55 Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 22 Jan 2013 13:13:41 +0100 Subject: Core/Movement: Fixed one (probably many remain) merge error --- .../game/Movement/MovementGenerators/TargetedMovementGenerator.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 3a8841848d1..abb4ac9964b 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -107,10 +107,6 @@ void TargetedMovementGeneratorMedium::_setTargetLocation(T* owner, bool upd Movement::MoveSplineInit init(owner); init.MovebyPath(i_path->GetPath()); - if (forceDest && updateDestination) - init.SetFacing(i_target.getTarget()->GetOrientation()); - else - init.SetFacing(i_target.getTarget()); init.SetWalk(((D*)this)->EnableWalking()); // Using the same condition for facing target as the one that is used for SetInFront on movement end // - applies to ChaseMovementGenerator mostly -- cgit v1.2.3 From fcd258a8a97098c4392c216f9bd6f99424b5b4b9 Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 22 Jan 2013 15:40:12 +0100 Subject: Tools/MeshExtractor: Removed shared and MySQL dependencies. --- src/tools/mesh_extractor/CMakeLists.txt | 65 ++++++++------------------ src/tools/mesh_extractor/Cache.h | 5 +- src/tools/mesh_extractor/Chunk.h | 2 +- src/tools/mesh_extractor/Constants.h | 2 - src/tools/mesh_extractor/ContinentBuilder.h | 4 +- src/tools/mesh_extractor/DBC.cpp | 2 +- src/tools/mesh_extractor/DBC.h | 3 +- src/tools/mesh_extractor/LiquidHandler.h | 2 +- src/tools/mesh_extractor/MPQ.h | 14 +++--- src/tools/mesh_extractor/MPQManager.cpp | 3 +- src/tools/mesh_extractor/MPQManager.h | 4 +- src/tools/mesh_extractor/MeshExtractor.cpp | 28 ++++++----- src/tools/mesh_extractor/TileBuilder.cpp | 30 ++++++------ src/tools/mesh_extractor/Utils.h | 6 ++- src/tools/mesh_extractor/WorldModelHandler.cpp | 2 +- src/tools/mesh_extractor/WorldModelHandler.h | 2 +- 16 files changed, 74 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/CMakeLists.txt b/src/tools/mesh_extractor/CMakeLists.txt index b8bd9f54331..1b5d1564b71 100644 --- a/src/tools/mesh_extractor/CMakeLists.txt +++ b/src/tools/mesh_extractor/CMakeLists.txt @@ -11,69 +11,42 @@ file(GLOB_RECURSE sources *.cpp *.h) -if( UNIX ) - include_directories ( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/Database/Implementation - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/libmpq - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${ACE_INCLUDE_DIR} - ${MYSQL_INCLUDE_DIR} - ${OPENSSL_INCLUDE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ) -elseif( WIN32 ) - include_directories ( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/Database/Implementation - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/libmpq +add_definitions(-DNO_CORE_FUNCS) + +set(include_Base + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/dep/libmpq + ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${ACE_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +if( WIN32 ) + set(include_Base + ${include_Base} ${CMAKE_SOURCE_DIR}/dep/libmpq/win - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${ACE_INCLUDE_DIR} - ${MYSQL_INCLUDE_DIR} - ${OPENSSL_INCLUDE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ) + ) endif() +include_directories(${include_Base}) + add_executable(MeshExtractor ${sources} ) target_link_libraries(MeshExtractor - shared g3dlib mpq Recast Detour - ${MYSQL_LIBRARY} - ${OPENSSL_LIBRARIES} - ${OPENSSL_EXTRA_LIBRARIES} ${BZIP2_LIBRARIES} ${ZLIB_LIBRARIES} ${ACE_LIBRARY} ) -add_dependencies(MeshExtractor mpq Recast Detour) - if( UNIX ) install(TARGETS MeshExtractor DESTINATION bin) elseif( WIN32 ) diff --git a/src/tools/mesh_extractor/Cache.h b/src/tools/mesh_extractor/Cache.h index 34293b14b54..60e3d8434cf 100644 --- a/src/tools/mesh_extractor/Cache.h +++ b/src/tools/mesh_extractor/Cache.h @@ -2,8 +2,9 @@ #define CACHE_H #include #include -#include "Common.h" -#include "ace/Synch.h" +#include "Define.h" +#include +#include class WorldModelRoot; class Model; diff --git a/src/tools/mesh_extractor/Chunk.h b/src/tools/mesh_extractor/Chunk.h index 2eea36f69b6..f3681a9f576 100644 --- a/src/tools/mesh_extractor/Chunk.h +++ b/src/tools/mesh_extractor/Chunk.h @@ -1,6 +1,6 @@ #ifndef CHUNK_H #define CHUNK_H -#include "Common.h" +#include "Define.h" #include class ChunkedData; diff --git a/src/tools/mesh_extractor/Constants.h b/src/tools/mesh_extractor/Constants.h index 54fa073fbef..02e2d25559f 100644 --- a/src/tools/mesh_extractor/Constants.h +++ b/src/tools/mesh_extractor/Constants.h @@ -1,8 +1,6 @@ #ifndef CONSTANTS_H #define CONSTANTS_H -#include "Common.h" - class Constants { public: diff --git a/src/tools/mesh_extractor/ContinentBuilder.h b/src/tools/mesh_extractor/ContinentBuilder.h index 3d7b879879e..b36ca125b9e 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.h +++ b/src/tools/mesh_extractor/ContinentBuilder.h @@ -2,7 +2,7 @@ #define CONT_BUILDER_H #include #include "WDT.h" -#include "Common.h" +#include "Define.h" class ContinentBuilder { @@ -22,7 +22,7 @@ private: WDT* TileMap; uint32 MapId; uint32 NumberOfThreads; - int tileXMin; + int tileXMin; int tileYMin; int tileXMax; int tileYMax; diff --git a/src/tools/mesh_extractor/DBC.cpp b/src/tools/mesh_extractor/DBC.cpp index 3c846363d06..9a55ff6d7ed 100644 --- a/src/tools/mesh_extractor/DBC.cpp +++ b/src/tools/mesh_extractor/DBC.cpp @@ -1,6 +1,6 @@ #include #include "DBC.h" -#include "Common.h" +#include "Define.h" DBC::DBC( FILE* stream ) : StringBlock(NULL), StringBlockSize(0), IsFaulty(true) { diff --git a/src/tools/mesh_extractor/DBC.h b/src/tools/mesh_extractor/DBC.h index 0c857bd40ed..5ed57754e73 100644 --- a/src/tools/mesh_extractor/DBC.h +++ b/src/tools/mesh_extractor/DBC.h @@ -1,7 +1,8 @@ #ifndef DBC_H #define DBC_H #include -#include "Common.h" +#include +#include "Define.h" class Record; diff --git a/src/tools/mesh_extractor/LiquidHandler.h b/src/tools/mesh_extractor/LiquidHandler.h index 6e8d0081adb..41e128ba20b 100644 --- a/src/tools/mesh_extractor/LiquidHandler.h +++ b/src/tools/mesh_extractor/LiquidHandler.h @@ -2,7 +2,7 @@ #define LIQUID_H #include "ADT.h" #include "Utils.h" -#include "Common.h" +#include "Define.h" #include diff --git a/src/tools/mesh_extractor/MPQ.h b/src/tools/mesh_extractor/MPQ.h index 15fce452726..2f8b082f526 100644 --- a/src/tools/mesh_extractor/MPQ.h +++ b/src/tools/mesh_extractor/MPQ.h @@ -2,27 +2,25 @@ #define MPQ_H #include "libmpq/mpq.h" -#include "Common.h" -#include +#include "Define.h" +#include #include #include #include #include -using namespace std; - class MPQArchive { public: mpq_archive_s *mpq_a; - - vector Files; + + std::vector Files; MPQArchive(const char* filename); void close(); - void GetFileListTo(vector& filelist) { + void GetFileListTo(std::vector& filelist) { uint32_t filenum; if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; libmpq__off_t size, transferred; @@ -40,7 +38,7 @@ public: while ((token != NULL) && (counter < size)) { //cout << token << endl; token[strlen(token) - 1] = 0; - string s = token; + std::string s = token; filelist.push_back(s); counter += strlen(token) + 2; token = strtok(NULL, seps); diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp index 90491dfb945..0fe07cd8b85 100644 --- a/src/tools/mesh_extractor/MPQManager.cpp +++ b/src/tools/mesh_extractor/MPQManager.cpp @@ -2,8 +2,7 @@ #include "MPQ.h" #include "DBC.h" #include "Utils.h" - -#include "ace/Synch.h" +#include char* MPQManager::Files[] = { "common.MPQ", diff --git a/src/tools/mesh_extractor/MPQManager.h b/src/tools/mesh_extractor/MPQManager.h index c23d7177825..788be7f5974 100644 --- a/src/tools/mesh_extractor/MPQManager.h +++ b/src/tools/mesh_extractor/MPQManager.h @@ -2,7 +2,9 @@ #define MPQ_MANAGER_H #include "MPQ.h" -#include "ace/Synch.h" +#include +#include +#include class DBC; class MPQManager diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp index b164ff5861d..e06f44c7125 100644 --- a/src/tools/mesh_extractor/MeshExtractor.cpp +++ b/src/tools/mesh_extractor/MeshExtractor.cpp @@ -12,11 +12,6 @@ #include -#include "Common.h" -#include "LoginDatabase.h" -#include "Util.h" -LoginDatabaseWorkerPool LoginDatabase; - MPQManager* MPQHandler; CacheClass* Cache; @@ -64,7 +59,7 @@ void ExtractDBCs() path += std::string(MPQManager::Languages[*itr]) + "/"; Utils::CreateDir(path); } - + std::string component = "component.wow-" + std::string(MPQManager::Languages[*itr]) + ".txt"; // Extract the component file Utils::SaveToDisk(MPQHandler->GetFile(component), path + component); @@ -104,7 +99,7 @@ void ExtractGameobjectModels() { fileName = Utils::FixModelPath(fileName); Model model(path); - + if (model.IsBad) continue; @@ -151,7 +146,7 @@ void ExtractGameobjectModels() fwrite(indices, sizeof(uint16), numTris, output); } - + fwrite("VERT", 4, 1, output); wsize = sizeof(int) + sizeof(float) * 3 * numVerts; fwrite(&wsize, sizeof(int), 1, output); @@ -170,7 +165,7 @@ void ExtractGameobjectModels() fwrite(vertices, sizeof(float), numVerts * 3, output); } - + fclose(output); delete[] indices; delete[] vertices; @@ -254,11 +249,14 @@ bool HandleArgs(int argc, char** argv, uint32& threads, std::set& mapLis param = argv[++i]; if (!param) return false; - std::string maps = std::string(param); - Tokenizer tokens(maps, ','); - for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) - mapList.insert(atoi(*itr)); + char* copy = strdup(param); + char* token = strtok(copy, ","); + while (token) + { + mapList.insert(atoi(token)); + token = strtok(NULL, ","); + } printf("Extracting only provided list of maps (%u).\n", uint32(mapList.size())); } @@ -337,7 +335,7 @@ int main(int argc, char* argv[]) uint32 threads = 4, extractFlags = 0; std::set mapIds; bool debug = false; - + if (!HandleArgs(argc, argv, threads, mapIds, debug, extractFlags)) { PrintUsage(); @@ -425,6 +423,6 @@ int main(int argc, char* argv[]) printf("Found!"); } - + return 0; } diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp index 4a14cbbd51d..9bb9b11619f 100644 --- a/src/tools/mesh_extractor/TileBuilder.cpp +++ b/src/tools/mesh_extractor/TileBuilder.cpp @@ -10,7 +10,7 @@ #include "RecastAlloc.h" #include "DetourNavMeshBuilder.h" -#include "ace/Synch.h" +#include TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, int y, uint32 mapId) : World(world), X(x), Y(y), MapId(mapId), _Geometry(NULL), DataSize(0), cBuilder(_cBuilder) @@ -118,7 +118,7 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) fprintf(debug, "f %i %i %i\n", _Geometry->Triangles[i].V0 + 1, _Geometry->Triangles[i].V1 + 1, _Geometry->Triangles[i].V2 + 1); fclose(debug); } - + uint32 numVerts = _Geometry->Vertices.size(); uint32 numTris = _Geometry->Triangles.size(); float* vertices; @@ -128,13 +128,13 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) _Geometry->Vertices.clear(); _Geometry->Triangles.clear(); - + rcVcopy(Config.bmin, cBuilder->bmin); rcVcopy(Config.bmax, cBuilder->bmax); - + // this sets the dimensions of the heightfield - should maybe happen before border padding rcCalcGridSize(Config.bmin, Config.bmax, Config.cs, &Config.width, &Config.height); - + // Initialize per tile config. rcConfig tileCfg = Config; tileCfg.width = Config.tileSize + Config.borderSize * 2; @@ -154,8 +154,8 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) tileCfg.bmin[2] = Config.bmin[2] + float(y * Config.tileSize - Config.borderSize) * Config.cs; tileCfg.bmax[0] = Config.bmin[0] + float((x + 1) * Config.tileSize + Config.borderSize) * Config.cs; tileCfg.bmax[2] = Config.bmin[2] + float((y + 1) * Config.tileSize + Config.borderSize) * Config.cs; - - + + rcHeightfield* hf = rcAllocHeightfield(); rcCreateHeightfield(Context, *hf, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch); rcClearUnwalkableTriangles(Context, tileCfg.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas); @@ -198,7 +198,7 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) // Free memory rcFreeCompactHeightfield(chf); rcFreeContourSet(cset); - + pmmerge[nmerge] = pmesh; dmmerge[nmerge] = dmesh; ++nmerge; @@ -207,15 +207,15 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) rcPolyMesh* pmesh = rcAllocPolyMesh(); rcMergePolyMeshes(Context, pmmerge, nmerge, *pmesh); - + rcPolyMeshDetail* dmesh = rcAllocPolyMeshDetail(); rcMergePolyMeshDetails(Context, dmmerge, nmerge, *dmesh); - + delete[] pmmerge; delete[] dmmerge; - + printf("[%02i,%02i] Meshes merged!\n", X, Y); - + // Remove padding from the polymesh data. (Remove this odditity) for (int i = 0; i < pmesh->nverts; ++i) { @@ -262,10 +262,10 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) rcVcopy(params.bmin, cBuilder->bmin); rcVcopy(params.bmax, cBuilder->bmax); - + // Offmesh-connection settings params.offMeshConCount = 0; // none for now - + params.tileSize = Constants::VertexPerMap; if (!params.polyCount || !params.polys || Constants::TilesPerMap * Constants::TilesPerMap == params.polyCount) @@ -281,7 +281,7 @@ uint8* TileBuilder::Build(bool dbg, dtNavMeshParams& navMeshParams) delete vertices; return NULL; } - + int navDataSize; uint8* navData; printf("[%02i,%02i] Creating the navmesh with %i vertices, %i polys, %i triangles!\n", X, Y, pmesh->nverts, pmesh->npolys, dmesh->ntris); diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index e7380ed8142..41ea33e6157 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -7,12 +7,16 @@ #include "G3D/Matrix4.h" #include "DetourNavMesh.h" -#include "Common.h" +#include "Define.h" #include "Constants.h" +#include + struct WorldModelDefinition; class DoodadInstance; +#define ASSERT(assertion) { if (!(assertion)) { ACE_Stack_Trace st; fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n", __FILE__, __LINE__, __FUNCTION__, #assertion, st.c_str()); *((volatile int*)NULL) = 0; } } + struct Vector3 { Vector3() {} diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp index 6ce41807492..ecfff4e97d4 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.cpp +++ b/src/tools/mesh_extractor/WorldModelHandler.cpp @@ -3,7 +3,7 @@ #include "Chunk.h" #include "Cache.h" #include "Model.h" -#include "Common.h" +#include "Define.h" #include "G3D/Matrix4.h" #include diff --git a/src/tools/mesh_extractor/WorldModelHandler.h b/src/tools/mesh_extractor/WorldModelHandler.h index cccedfa60fb..29715ded696 100644 --- a/src/tools/mesh_extractor/WorldModelHandler.h +++ b/src/tools/mesh_extractor/WorldModelHandler.h @@ -1,6 +1,6 @@ #ifndef WMODEL_HNDL_H #define WMODEL_HNDL_H -#include "Common.h" +#include "Define.h" #include "Utils.h" #include "WorldModelRoot.h" #include "ObjectDataHandler.h" -- cgit v1.2.3 From 259a29c0935e566dd63d8c03360c5cd19b4ffe52 Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 22 Jan 2013 18:40:32 +0100 Subject: Tools/Extractors: Mmap extractors no longer depend on shared and MySQL libraries --- cmake/showoptions.cmake | 1 + src/server/collision/Management/VMapManager2.cpp | 12 ++-- src/server/collision/Maps/MapTree.cpp | 21 ++---- src/server/collision/Models/GameObjectModel.cpp | 13 ++-- src/server/collision/VMapDefinitions.h | 12 ++++ src/server/shared/Debugging/Errors.h | 2 +- src/tools/map_extractor/CMakeLists.txt | 19 +++-- src/tools/map_extractor/mpq_libmpq.cpp | 2 +- src/tools/map_extractor/mpq_libmpq04.h | 3 - src/tools/mesh_extractor/CMakeLists.txt | 8 +-- src/tools/mesh_extractor/MPQ.cpp | 2 +- src/tools/mmaps_generator/CMakeLists.txt | 45 +++++------- src/tools/mmaps_generator/IntermediateValues.cpp | 2 +- src/tools/mmaps_generator/MapBuilder.cpp | 55 +++++++------- src/tools/mmaps_generator/MapBuilder.h | 10 +-- src/tools/mmaps_generator/PathCommon.h | 43 +++++++++-- src/tools/mmaps_generator/PathGenerator.cpp | 3 +- src/tools/mmaps_generator/TerrainBuilder.cpp | 92 +++++++++++++++++++----- src/tools/mmaps_generator/TerrainBuilder.h | 11 +-- src/tools/mmaps_generator/VMapExtensions.cpp | 6 +- src/tools/vmap4_assembler/CMakeLists.txt | 2 - src/tools/vmap4_extractor/CMakeLists.txt | 25 +++---- src/tools/vmap4_extractor/mpq_libmpq.cpp | 2 +- src/tools/vmap4_extractor/mpq_libmpq04.h | 3 - src/tools/vmap4_extractor/wdtfile.cpp | 2 +- 25 files changed, 220 insertions(+), 176 deletions(-) (limited to 'src') diff --git a/cmake/showoptions.cmake b/cmake/showoptions.cmake index 47ad7b0889b..d3415e4e204 100644 --- a/cmake/showoptions.cmake +++ b/cmake/showoptions.cmake @@ -34,6 +34,7 @@ endif() if( TOOLS ) message("* Build map/vmap tools : Yes") + add_definitions(-DNO_CORE_FUNCS) else() message("* Build map/vmap tools : No (default)") endif() diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp index 5e3741ca753..8a1bd346957 100644 --- a/src/server/collision/Management/VMapManager2.cpp +++ b/src/server/collision/Management/VMapManager2.cpp @@ -24,13 +24,13 @@ #include "MapTree.h" #include "ModelInstance.h" #include "WorldModel.h" -#include "VMapDefinitions.h" -#include "Log.h" #include #include #include #include "DisableMgr.h" #include "DBCStores.h" +#include "Log.h" +#include "VMapDefinitions.h" using G3D::Vector3; @@ -257,11 +257,11 @@ namespace VMAP WorldModel* worldmodel = new WorldModel(); if (!worldmodel->readFile(basepath + filename + ".vmo")) { - sLog->outError(LOG_FILTER_GENERAL, "VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str()); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str()); delete worldmodel; return NULL; } - sLog->outDebug(LOG_FILTER_MAPS, "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str()); + VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str()); model = iLoadedModelFiles.insert(std::pair(filename, ManagedModel())).first; model->second.setModel(worldmodel); } @@ -277,12 +277,12 @@ namespace VMAP ModelFileMap::iterator model = iLoadedModelFiles.find(filename); if (model == iLoadedModelFiles.end()) { - sLog->outError(LOG_FILTER_GENERAL, "VMapManager2: trying to unload non-loaded file '%s'", filename.c_str()); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "VMapManager2: trying to unload non-loaded file '%s'", filename.c_str()); return; } if (model->second.decRefCount() == 0) { - sLog->outDebug(LOG_FILTER_MAPS, "VMapManager2: unloading file '%s'", filename.c_str()); + VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "VMapManager2: unloading file '%s'", filename.c_str()); delete model->second.getModel(); iLoadedModelFiles.erase(model); } diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp index 5f4e2b6aa8b..e3cd158709c 100644 --- a/src/server/collision/Maps/MapTree.cpp +++ b/src/server/collision/Maps/MapTree.cpp @@ -27,12 +27,6 @@ #include #include -#ifndef NO_CORE_FUNCS - #include "Errors.h" -#else - #define ASSERT(x) -#endif - using G3D::Vector3; namespace VMAP @@ -277,7 +271,7 @@ namespace VMAP bool StaticMapTree::InitMap(const std::string &fname, VMapManager2* vm) { - sLog->outDebug(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); + VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); bool success = true; std::string fullname = iBasePath + fname; FILE* rf = fopen(fullname.c_str(), "rb"); @@ -310,7 +304,7 @@ namespace VMAP if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) { WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); - sLog->outDebug(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); + VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); if (model) { // assume that global model always is the first and only tree value (could be improved...) @@ -320,7 +314,7 @@ namespace VMAP else { success = false; - sLog->outError(LOG_FILTER_GENERAL, "StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); } } @@ -356,7 +350,7 @@ namespace VMAP } if (!iTreeValues) { - sLog->outError(LOG_FILTER_GENERAL, "StaticMapTree::LoadMapTile() : tree has not been initialized [%u, %u]", tileX, tileY); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::LoadMapTile() : tree has not been initialized [%u, %u]", tileX, tileY); return false; } bool result = true; @@ -382,7 +376,7 @@ namespace VMAP // acquire model instance WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); if (!model) - sLog->outError(LOG_FILTER_GENERAL, "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY); // update tree uint32 referencedVal; @@ -432,7 +426,7 @@ namespace VMAP loadedTileMap::iterator tile = iLoadedTiles.find(tileID); if (tile == iLoadedTiles.end()) { - sLog->outError(LOG_FILTER_GENERAL, "StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:%u X:%u Y:%u", iMapID, tileX, tileY); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:%u X:%u Y:%u", iMapID, tileX, tileY); return; } if (tile->second) // file associated with tile @@ -466,7 +460,7 @@ namespace VMAP else { if (!iLoadedSpawns.count(referencedNode)) - sLog->outError(LOG_FILTER_GENERAL, "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); else if (--iLoadedSpawns[referencedNode] == 0) { iTreeValues[referencedNode].setUnloaded(); @@ -480,5 +474,4 @@ namespace VMAP } iLoadedTiles.erase(tile); } - } diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/server/collision/Models/GameObjectModel.cpp index 0ecf02648f9..54283389387 100644 --- a/src/server/collision/Models/GameObjectModel.cpp +++ b/src/server/collision/Models/GameObjectModel.cpp @@ -34,8 +34,6 @@ using G3D::Vector3; using G3D::Ray; using G3D::AABox; -#ifndef NO_CORE_FUNCS - struct GameobjectModelData { GameobjectModelData(const std::string& name_, const AABox& box) : @@ -54,7 +52,7 @@ void LoadGameObjectModelList() FILE* model_list_file = fopen((sWorld->GetDataPath() + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb"); if (!model_list_file) { - sLog->outError(LOG_FILTER_GENERAL, "Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS); return; } @@ -73,7 +71,7 @@ void LoadGameObjectModelList() || fread(&v1, sizeof(Vector3), 1, model_list_file) != 1 || fread(&v2, sizeof(Vector3), 1, model_list_file) != 1) { - sLog->outError(LOG_FILTER_GENERAL, "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS); break; } @@ -84,8 +82,7 @@ void LoadGameObjectModelList() } fclose(model_list_file); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u GameObject models in %u ms", uint32(model_list.size()), GetMSTimeDiffToNow(oldMSTime)); - + VMAP_INFO_LOG(LOG_FILTER_SERVER_LOADING, ">> Loaded %u GameObject models in %u ms", uint32(model_list.size()), GetMSTimeDiffToNow(oldMSTime)); } GameObjectModel::~GameObjectModel() @@ -104,7 +101,7 @@ bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayIn // ignore models with no bounds if (mdl_box == G3D::AABox::zero()) { - sLog->outError(LOG_FILTER_GENERAL, "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str()); + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str()); return false; } @@ -184,5 +181,3 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto } return hit; } - -#endif diff --git a/src/server/collision/VMapDefinitions.h b/src/server/collision/VMapDefinitions.h index 609d00cd00f..56084389ad6 100644 --- a/src/server/collision/VMapDefinitions.h +++ b/src/server/collision/VMapDefinitions.h @@ -31,4 +31,16 @@ namespace VMAP // defined in TileAssembler.cpp currently... bool readChunk(FILE* rf, char *dest, const char *compare, uint32 len); } + +// Set of helper macros for extractors (VMAP and MMAP) +#ifndef NO_CORE_FUNCS +#define VMAP_ERROR_LOG(FILTER, ...) sLog->outError(FILTER, __VA_ARGS__) +#define VMAP_DEBUG_LOG(FILTER, ...) sLog->outDebug(FILTER, __VA_ARGS__) +#define VMAP_INFO_LOG(FILTER, ...) sLog->outInfo(FILTER, __VA_ARGS__) +#else +#define VMAP_ERROR_LOG(FILTER, ...) printf(__VA_ARGS__) +#define VMAP_DEBUG_LOG(FILTER, ...) printf(__VA_ARGS__) +#define VMAP_INFO_LOG(FILTER, ...) printf(__VA_ARGS__) +#endif + #endif diff --git a/src/server/shared/Debugging/Errors.h b/src/server/shared/Debugging/Errors.h index 3d10740f149..10e94634e9a 100644 --- a/src/server/shared/Debugging/Errors.h +++ b/src/server/shared/Debugging/Errors.h @@ -24,7 +24,7 @@ #include #include -#define WPAssert(assertion) { if (!(assertion)) { ACE_Stack_Trace st; sLog->outError(LOG_FILTER_GENERAL, "\n%s:%i in %s ASSERTION FAILED:\n %s\n%s\n", __FILE__, __LINE__, __FUNCTION__, #assertion, st.c_str()); *((volatile int*)NULL) = 0; } } +#define WPAssert(assertion) { if (!(assertion)) { ACE_Stack_Trace st; fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n%s\n", __FILE__, __LINE__, __FUNCTION__, #assertion, st.c_str()); *((volatile int*)NULL) = 0; } } #define WPError(assertion, errmsg) { if (!(assertion)) { sLog->outError(LOG_FILTER_GENERAL, "%\n%s:%i in %s ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg); *((volatile int*)NULL) = 0; } } #define WPWarning(assertion, errmsg) { if (!(assertion)) { sLog->outError(LOG_FILTER_GENERAL, "\n%s:%i in %s WARNING:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg); } } #define WPFatal(assertion, errmsg) { if (!(assertion)) { sLog->outError(LOG_FILTER_GENERAL, "\n%s:%i in %s FATAL ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg); ACE_OS::sleep(10); *((volatile int*)NULL) = 0; } } diff --git a/src/tools/map_extractor/CMakeLists.txt b/src/tools/map_extractor/CMakeLists.txt index 9fb8d5713d7..ea073456680 100644 --- a/src/tools/map_extractor/CMakeLists.txt +++ b/src/tools/map_extractor/CMakeLists.txt @@ -11,23 +11,22 @@ file(GLOB_RECURSE sources *.cpp *.h) -if( UNIX ) - include_directories ( +set(include_Dirs ${CMAKE_SOURCE_DIR}/src/server/shared ${CMAKE_SOURCE_DIR}/dep/libmpq ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/loadlib - ) -elseif( WIN32 ) - include_directories ( - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/dep/libmpq +) + +if( WIN32 ) + set(include_Dirs + ${include_Dirs} ${CMAKE_SOURCE_DIR}/dep/libmpq/win - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/loadlib ) endif() +include_directories(${include_Dirs}) + add_executable(mapextractor ${sources} ) @@ -38,8 +37,6 @@ target_link_libraries(mapextractor ${ZLIB_LIBRARIES} ) -add_dependencies(mapextractor mpq) - if( UNIX ) install(TARGETS mapextractor DESTINATION bin) elseif( WIN32 ) diff --git a/src/tools/map_extractor/mpq_libmpq.cpp b/src/tools/map_extractor/mpq_libmpq.cpp index 81aa8cc2894..1c1a12e7b85 100644 --- a/src/tools/map_extractor/mpq_libmpq.cpp +++ b/src/tools/map_extractor/mpq_libmpq.cpp @@ -79,7 +79,7 @@ size_t MPQFile::read(void* dest, size_t bytes) if (eof) return 0; size_t rpos = pointer + bytes; - if (rpos > size) { + if (rpos > size_t(size)) { bytes = size - pointer; eof = true; } diff --git a/src/tools/map_extractor/mpq_libmpq04.h b/src/tools/map_extractor/mpq_libmpq04.h index 89f715e9e87..9f0163067c4 100644 --- a/src/tools/map_extractor/mpq_libmpq04.h +++ b/src/tools/map_extractor/mpq_libmpq04.h @@ -1,6 +1,3 @@ -#define _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_WARNINGS - #ifndef MPQ_H #define MPQ_H diff --git a/src/tools/mesh_extractor/CMakeLists.txt b/src/tools/mesh_extractor/CMakeLists.txt index 1b5d1564b71..9ed8472051d 100644 --- a/src/tools/mesh_extractor/CMakeLists.txt +++ b/src/tools/mesh_extractor/CMakeLists.txt @@ -9,9 +9,7 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -file(GLOB_RECURSE sources *.cpp *.h) - -add_definitions(-DNO_CORE_FUNCS) +file(GLOB_RECURSE meshExtract_Sources *.cpp *.h) set(include_Base ${CMAKE_BINARY_DIR} @@ -33,9 +31,7 @@ endif() include_directories(${include_Base}) -add_executable(MeshExtractor - ${sources} -) +add_executable(MeshExtractor ${meshExtract_Sources}) target_link_libraries(MeshExtractor g3dlib diff --git a/src/tools/mesh_extractor/MPQ.cpp b/src/tools/mesh_extractor/MPQ.cpp index b7be181594d..18a9eb0f0e3 100644 --- a/src/tools/mesh_extractor/MPQ.cpp +++ b/src/tools/mesh_extractor/MPQ.cpp @@ -77,7 +77,7 @@ size_t MPQFile::Read(void* dest, size_t bytes) return 0; size_t rpos = pointer + bytes; - if (rpos > size) { + if (rpos > size_t(size)) { bytes = size - pointer; eof = true; } diff --git a/src/tools/mmaps_generator/CMakeLists.txt b/src/tools/mmaps_generator/CMakeLists.txt index 229a2cd808f..99492abf8ee 100644 --- a/src/tools/mmaps_generator/CMakeLists.txt +++ b/src/tools/mmaps_generator/CMakeLists.txt @@ -8,17 +8,11 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -file(GLOB_RECURSE sources *.cpp *.h) +file(GLOB_RECURSE mmap_gen_sources *.cpp *.h) -# definitions -add_definitions(-DNO_CORE_FUNCS) -add_definitions(-DDEBUG) -add_definitions(-DNO_vsnprintf) - -include_directories( +set(mmap_gen_Includes ${CMAKE_BINARY_DIR} ${ACE_INCLUDE_DIR} - ${MYSQL_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/dep/libmpq ${CMAKE_SOURCE_DIR}/dep/zlib ${CMAKE_SOURCE_DIR}/dep/bzip2 @@ -26,20 +20,6 @@ include_directories( ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/Database/Implementation - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/game/Maps - ${CMAKE_SOURCE_DIR}/src/server/game/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints - ${CMAKE_SOURCE_DIR}/src/server/game/Grids - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells - ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous ${CMAKE_SOURCE_DIR}/src/server/game/Conditions ${CMAKE_SOURCE_DIR}/src/server/collision ${CMAKE_SOURCE_DIR}/src/server/collision/Management @@ -47,18 +27,25 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/collision/Models ) -add_executable(mmaps_generator ${sources}) +if( WIN32 ) + set(mmap_gen_Includes + ${mmap_gen_Includes} + ${CMAKE_SOURCE_DIR}/dep/libmpq/win + ) +endif() + +include_directories(${mmap_gen_Includes}) + +add_executable(mmaps_generator ${mmap_gen_sources}) target_link_libraries(mmaps_generator - ${MYSQL_LIBRARY} + collision + g3dlib + Recast + Detour ${ACE_LIBRARY} ${BZIP2_LIBRARIES} ${ZLIB_LIBRARIES} - Recast - Detour - collision - g3dlib - shared ) if( UNIX ) diff --git a/src/tools/mmaps_generator/IntermediateValues.cpp b/src/tools/mmaps_generator/IntermediateValues.cpp index 6fad96887a2..a490273ad80 100644 --- a/src/tools/mmaps_generator/IntermediateValues.cpp +++ b/src/tools/mmaps_generator/IntermediateValues.cpp @@ -37,7 +37,7 @@ namespace MMAP printf("%sWriting debug output... \r", tileString); - string name("meshes/%03u%02i%02i."); + std::string name("meshes/%03u%02i%02i."); #define DEBUG_WRITE(fileExtension,data) \ do { \ diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 9e6acd71a72..a62011ddfff 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -21,29 +21,34 @@ #include "MapTree.h" #include "ModelInstance.h" -#include "LoginDatabase.h" #include "DetourNavMeshBuilder.h" #include "DetourNavMesh.h" #include "DetourCommon.h" -// These make the linker happy. -LoginDatabaseWorkerPool LoginDatabase; -uint32 GetLiquidFlags(uint32 /*liquidType*/) -{ - return 0; -} - #include "DisableMgr.h" +#include + +uint32 GetLiquidFlags(uint32 /*liquidType*/) { return 0; } namespace DisableMgr { - bool IsDisabledFor(DisableType /*type*/, uint32 /*entry*/, Unit const* /*unit*/, uint8 /*flags*/) - { - return 0; - } + bool IsDisabledFor(DisableType /*type*/, uint32 /*entry*/, Unit const* /*unit*/, uint8 /*flags*/ /*= 0*/) { return false; } } -using namespace VMAP; +#define MMAP_MAGIC 0x4d4d4150 // 'MMAP' +#define MMAP_VERSION 3 + +struct MmapTileHeader +{ + uint32 mmapMagic; + uint32 dtVersion; + uint32 mmapVersion; + uint32 size; + bool usesLiquids : 1; + + MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION), + mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) {} +}; namespace MMAP { @@ -83,7 +88,7 @@ namespace MMAP /**************************************************************************/ void MapBuilder::discoverTiles() { - vector files; + std::vector files; uint32 mapID, tileX, tileY, tileID, count = 0; char filter[12]; @@ -94,7 +99,7 @@ namespace MMAP mapID = uint32(atoi(files[i].substr(0,3).c_str())); if (m_tiles.find(mapID) == m_tiles.end()) { - m_tiles.insert(pair*>(mapID, new set)); + m_tiles.insert(std::pair*>(mapID, new std::set)); count++; } } @@ -104,7 +109,7 @@ namespace MMAP for (uint32 i = 0; i < files.size(); ++i) { mapID = uint32(atoi(files[i].substr(0,3).c_str())); - m_tiles.insert(pair*>(mapID, new set)); + m_tiles.insert(std::pair*>(mapID, new std::set)); count++; } printf("found %u.\n", count); @@ -113,7 +118,7 @@ namespace MMAP printf("Discovering tiles... "); for (TileList::iterator itr = m_tiles.begin(); itr != m_tiles.end(); ++itr) { - set* tiles = (*itr).second; + std::set* tiles = (*itr).second; mapID = (*itr).first; sprintf(filter, "%03u*.vmtile", mapID); @@ -146,14 +151,14 @@ namespace MMAP } /**************************************************************************/ - set* MapBuilder::getTileList(uint32 mapID) + std::set* MapBuilder::getTileList(uint32 mapID) { TileList::iterator itr = m_tiles.find(mapID); if (itr != m_tiles.end()) return (*itr).second; - set* tiles = new set(); - m_tiles.insert(pair*>(mapID, tiles)); + std::set* tiles = new std::set(); + m_tiles.insert(std::pair*>(mapID, tiles)); return tiles; } @@ -318,7 +323,7 @@ namespace MMAP { printf("[Thread %u] Building map %03u:\n", uint32(ACE_Thread::self()), mapID); - set* tiles = getTileList(mapID); + std::set* tiles = getTileList(mapID); // make sure we process maps which don't have tiles if (!tiles->size()) @@ -346,7 +351,7 @@ namespace MMAP // now start building mmtiles for each tile printf("[Map %i] We have %u tiles. \n", mapID, (unsigned int)tiles->size()); - for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) + for (std::set::iterator it = tiles->begin(); it != tiles->end(); ++it) { uint32 tileX, tileY; @@ -407,7 +412,7 @@ namespace MMAP /**************************************************************************/ void MapBuilder::buildNavMesh(uint32 mapID, dtNavMesh* &navMesh) { - set* tiles = getTileList(mapID); + std::set* tiles = getTileList(mapID); // old code for non-statically assigned bitmask sizes: ///*** calculate number of bits needed to store tiles & polys ***/ @@ -423,9 +428,9 @@ namespace MMAP /*** calculate bounds of map ***/ uint32 tileXMin = 64, tileYMin = 64, tileXMax = 0, tileYMax = 0, tileX, tileY; - for (set::iterator it = tiles->begin(); it != tiles->end(); ++it) + for (std::set::iterator it = tiles->begin(); it != tiles->end(); ++it) { - StaticMapTree::unpackTileID((*it), tileX, tileY); + StaticMapTree::unpackTileID(*it, tileX, tileY); if (tileX > tileXMax) tileXMax = tileX; diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index c083e0b680a..ea9636b3cc3 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -26,22 +26,18 @@ #include "TerrainBuilder.h" #include "IntermediateValues.h" -#include "IVMapManager.h" -#include "WorldModel.h" - #include "Recast.h" #include "DetourNavMesh.h" -#include "ace/Task.h" +#include -using namespace std; using namespace VMAP; // G3D namespace typedefs conflicts with ACE typedefs namespace MMAP { - typedef map*> TileList; + typedef std::map*> TileList; struct Tile { Tile() : chf(NULL), solid(NULL), cset(NULL), pmesh(NULL), dmesh(NULL) {} @@ -87,7 +83,7 @@ namespace MMAP private: // detect maps and tiles void discoverTiles(); - set* getTileList(uint32 mapID); + std::set* getTileList(uint32 mapID); void buildNavMesh(uint32 mapID, dtNavMesh* &navMesh); diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h index 413f2b8735d..3e06ff58410 100644 --- a/src/tools/mmaps_generator/PathCommon.h +++ b/src/tools/mmaps_generator/PathCommon.h @@ -21,6 +21,7 @@ #include #include +#include #include "Define.h" @@ -33,7 +34,19 @@ #include #endif -using namespace std; +enum NavTerrain +{ + NAV_EMPTY = 0x00, + NAV_GROUND = 0x01, + NAV_MAGMA = 0x02, + NAV_SLIME = 0x04, + NAV_WATER = 0x08, + NAV_UNUSED1 = 0x10, + NAV_UNUSED2 = 0x20, + NAV_UNUSED3 = 0x40, + NAV_UNUSED4 = 0x80 + // we only have 8 bits +}; namespace MMAP { @@ -75,12 +88,12 @@ namespace MMAP LISTFILE_OK = 1 }; - inline ListFilesResult getDirContents(vector &fileList, string dirpath = ".", string filter = "*") + inline ListFilesResult getDirContents(std::vector &fileList, std::string dirpath = ".", std::string filter = "*") { #ifdef WIN32 HANDLE hFind; WIN32_FIND_DATA findFileInfo; - string directory; + std::string directory; directory = dirpath + "/" + filter; @@ -91,7 +104,7 @@ namespace MMAP do { if ((findFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) - fileList.push_back(string(findFileInfo.cFileName)); + fileList.push_back(std::string(findFileInfo.cFileName)); } while (FindNextFile(hFind, &findFileInfo)); @@ -109,7 +122,7 @@ namespace MMAP if ((dp = readdir(dirp)) != NULL) { if (matchWildcardFilter(filter.c_str(), dp->d_name)) - fileList.push_back(string(dp->d_name)); + fileList.push_back(std::string(dp->d_name)); } else break; @@ -123,6 +136,26 @@ namespace MMAP return LISTFILE_OK; } + + inline uint32 getMSTime() + { + static const ACE_Time_Value ApplicationStartTime = ACE_OS::gettimeofday(); + return (ACE_OS::gettimeofday() - ApplicationStartTime).msec(); + } + + inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime) + { + // getMSTime() have limited data range and this is case when it overflow in this tick + if (oldMSTime > newMSTime) + return (0xFFFFFFFF - oldMSTime) + newMSTime; + else + return newMSTime - oldMSTime; + } + + inline uint32 GetMSTimeDiffToNow(uint32 oldMSTime) + { + return getMSTimeDiff(oldMSTime, getMSTime()); + } } #endif diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 9707cb4160a..01059099f98 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -18,13 +18,12 @@ #include "PathCommon.h" #include "MapBuilder.h" -#include "Timer.h" using namespace MMAP; bool checkDirectories(bool debugOutput) { - vector dirFiles; + std::vector dirFiles; if (getDirContents(dirFiles, "maps") == LISTFILE_DIRECTORY_NOT_FOUND || dirFiles.empty()) { diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index f7cf76e9718..c3d6541dfa3 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -24,6 +24,60 @@ #include "VMapManager2.h" #include "MapTree.h" #include "ModelInstance.h" +#include + +// ****************************************** +// Map file format defines +// ****************************************** +struct map_fileheader +{ + uint32 mapMagic; + uint32 versionMagic; + uint32 buildMagic; + uint32 areaMapOffset; + uint32 areaMapSize; + uint32 heightMapOffset; + uint32 heightMapSize; + uint32 liquidMapOffset; + uint32 liquidMapSize; + uint32 holesOffset; + uint32 holesSize; +}; + +#define MAP_HEIGHT_NO_HEIGHT 0x0001 +#define MAP_HEIGHT_AS_INT16 0x0002 +#define MAP_HEIGHT_AS_INT8 0x0004 + +struct map_heightHeader +{ + uint32 fourcc; + uint32 flags; + float gridHeight; + float gridMaxHeight; +}; + +#define MAP_LIQUID_NO_TYPE 0x0001 +#define MAP_LIQUID_NO_HEIGHT 0x0002 + +struct map_liquidHeader +{ + uint32 fourcc; + uint16 flags; + uint16 liquidType; + uint8 offsetX; + uint8 offsetY; + uint8 width; + uint8 height; + float liquidLevel; +}; + +#define MAP_LIQUID_TYPE_NO_WATER 0x00 +#define MAP_LIQUID_TYPE_WATER 0x01 +#define MAP_LIQUID_TYPE_OCEAN 0x02 +#define MAP_LIQUID_TYPE_MAGMA 0x04 +#define MAP_LIQUID_TYPE_SLIME 0x08 +#define MAP_LIQUID_TYPE_DARK_WATER 0x10 +#define MAP_LIQUID_TYPE_WMO_WATER 0x20 namespace MMAP { @@ -139,7 +193,7 @@ namespace MMAP count += fread(v8, sizeof(uint8), V8_SIZE_SQ, mapFile); if (count != expected) printf("TerrainBuilder::loadMap: Failed to read some data expected %d, read %d\n", expected, count); - + heightMultiplier = (hheader.gridMaxHeight - hheader.gridHeight) / 255; for (int i = 0; i < V9_SIZE_SQ; ++i) @@ -612,11 +666,11 @@ namespace MMAP // now we have a model to add to the meshdata retval = true; - vector groupModels; + std::vector groupModels; worldModel->getGroupModels(groupModels); // all M2s need to have triangle indices reversed - bool isM2 = instance.name.find(".m2") != instance.name.npos || instance.name.find(".M2") != instance.name.npos; + bool isM2 = instance.name.find(".m2") != std::string::npos || instance.name.find(".M2") != std::string::npos; // transform data float scale = instance.iScale; @@ -625,14 +679,14 @@ namespace MMAP position.x -= 32*GRID_SIZE; position.y -= 32*GRID_SIZE; - for (vector::iterator it = groupModels.begin(); it != groupModels.end(); ++it) + for (std::vector::iterator it = groupModels.begin(); it != groupModels.end(); ++it) { - vector tempVertices; - vector transformedVertices; - vector tempTriangles; + std::vector tempVertices; + std::vector transformedVertices; + std::vector tempTriangles; WmoLiquid* liquid = NULL; - (*it).getMeshData(tempVertices, tempTriangles, liquid); + it->getMeshData(tempVertices, tempTriangles, liquid); // first handle collision mesh transform(tempVertices, transformedVertices, scale, rotation, position); @@ -645,8 +699,8 @@ namespace MMAP // now handle liquid data if (liquid) { - vector liqVerts; - vector liqTris; + std::vector liqVerts; + std::vector liqTris; uint32 tilesX, tilesY, vertsX, vertsY; Vector3 corner; liquid->getPosInfo(tilesX, tilesY, corner); @@ -732,9 +786,9 @@ namespace MMAP } /**************************************************************************/ - void TerrainBuilder::transform(vector &source, vector &transformedVertices, float scale, G3D::Matrix3 &rotation, Vector3 &position) + void TerrainBuilder::transform(std::vector &source, std::vector &transformedVertices, float scale, G3D::Matrix3 &rotation, Vector3 &position) { - for (vector::iterator it = source.begin(); it != source.end(); ++it) + for (std::vector::iterator it = source.begin(); it != source.end(); ++it) { // apply tranform, then mirror along the horizontal axes Vector3 v((*it) * rotation * scale + position); @@ -745,9 +799,9 @@ namespace MMAP } /**************************************************************************/ - void TerrainBuilder::copyVertices(vector &source, G3D::Array &dest) + void TerrainBuilder::copyVertices(std::vector &source, G3D::Array &dest) { - for (vector::iterator it = source.begin(); it != source.end(); ++it) + for (std::vector::iterator it = source.begin(); it != source.end(); ++it) { dest.push_back((*it).y); dest.push_back((*it).z); @@ -756,11 +810,11 @@ namespace MMAP } /**************************************************************************/ - void TerrainBuilder::copyIndices(vector &source, G3D::Array &dest, int offset, bool flip) + void TerrainBuilder::copyIndices(std::vector &source, G3D::Array &dest, int offset, bool flip) { if (flip) { - for (vector::iterator it = source.begin(); it != source.end(); ++it) + for (std::vector::iterator it = source.begin(); it != source.end(); ++it) { dest.push_back((*it).idx2+offset); dest.push_back((*it).idx1+offset); @@ -769,7 +823,7 @@ namespace MMAP } else { - for (vector::iterator it = source.begin(); it != source.end(); ++it) + for (std::vector::iterator it = source.begin(); it != source.end(); ++it) { dest.push_back((*it).idx0+offset); dest.push_back((*it).idx1+offset); @@ -789,7 +843,7 @@ namespace MMAP /**************************************************************************/ void TerrainBuilder::cleanVertices(G3D::Array &verts, G3D::Array &tris) { - map vertMap; + std::map vertMap; int* t = tris.getCArray(); float* v = verts.getCArray(); @@ -819,7 +873,7 @@ namespace MMAP // update triangles to use new indices for (int i = 0; i < tris.size(); ++i) { - map::iterator it; + std::map::iterator it; if ((it = vertMap.find(t[i])) == vertMap.end()) continue; diff --git a/src/tools/mmaps_generator/TerrainBuilder.h b/src/tools/mmaps_generator/TerrainBuilder.h index 6ad4284f416..069a5a94c84 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.h +++ b/src/tools/mmaps_generator/TerrainBuilder.h @@ -20,17 +20,12 @@ #define _MMAP_TERRAIN_BUILDER_H #include "PathCommon.h" -#include "Map.h" -#include "SharedDefines.h" - #include "WorldModel.h" #include "G3D/Array.h" #include "G3D/Vector3.h" #include "G3D/Matrix3.h" -using namespace Trinity; - namespace MMAP { enum Spot @@ -93,10 +88,10 @@ namespace MMAP bool usesLiquids() { return !m_skipLiquid; } // vert and triangle methods - static void transform(vector &original, vector &transformed, + static void transform(std::vector &original, std::vector &transformed, float scale, G3D::Matrix3 &rotation, G3D::Vector3 &position); - static void copyVertices(vector &source, G3D::Array &dest); - static void copyIndices(vector &source, G3D::Array &dest, int offest, bool flip); + static void copyVertices(std::vector &source, G3D::Array &dest); + static void copyIndices(std::vector &source, G3D::Array &dest, int offest, bool flip); static void copyIndices(G3D::Array &src, G3D::Array &dest, int offset); static void cleanVertices(G3D::Array &verts, G3D::Array &tris); private: diff --git a/src/tools/mmaps_generator/VMapExtensions.cpp b/src/tools/mmaps_generator/VMapExtensions.cpp index 37b7d94af55..972f222bba6 100644 --- a/src/tools/mmaps_generator/VMapExtensions.cpp +++ b/src/tools/mmaps_generator/VMapExtensions.cpp @@ -22,8 +22,6 @@ #include "WorldModel.h" #include "ModelInstance.h" -using namespace std; - namespace VMAP { // Need direct access to encapsulated VMAP data, so we add functions for MMAP generator @@ -43,13 +41,13 @@ namespace VMAP } // declared in src/shared/vmap/WorldModel.h - void WorldModel::getGroupModels(vector &groupModels) + void WorldModel::getGroupModels(std::vector &groupModels) { groupModels = this->groupModels; } // declared in src/shared/vmap/WorldModel.h - void GroupModel::getMeshData(vector &vertices, vector &triangles, WmoLiquid* &liquid) + void GroupModel::getMeshData(std::vector &vertices, std::vector &triangles, WmoLiquid* &liquid) { vertices = this->vertices; triangles = this->triangles; diff --git a/src/tools/vmap4_assembler/CMakeLists.txt b/src/tools/vmap4_assembler/CMakeLists.txt index 55b6514d091..8d455eae6ee 100644 --- a/src/tools/vmap4_assembler/CMakeLists.txt +++ b/src/tools/vmap4_assembler/CMakeLists.txt @@ -20,9 +20,7 @@ include_directories( ${ZLIB_INCLUDE_DIR} ) -add_definitions(-DNO_CORE_FUNCS) add_executable(vmap4assembler VMapAssembler.cpp) -add_dependencies(vmap4assembler mpq) if(CMAKE_SYSTEM_NAME MATCHES "Darwin") set_target_properties(vmap4assembler PROPERTIES LINK_FLAGS "-framework Carbon") diff --git a/src/tools/vmap4_extractor/CMakeLists.txt b/src/tools/vmap4_extractor/CMakeLists.txt index 19798e46475..023f5447f85 100644 --- a/src/tools/vmap4_extractor/CMakeLists.txt +++ b/src/tools/vmap4_extractor/CMakeLists.txt @@ -11,26 +11,19 @@ file(GLOB_RECURSE sources *.cpp *.h) -# uncomment next line to disable debug mode -add_definitions("-DIOMAP_DEBUG") - -# build setup currently only supports libmpq 0.4.x -add_definitions("-DUSE_LIBMPQ04") -add_definitions("-Wall") -add_definitions("-ggdb") -add_definitions("-O3") - -if( UNIX ) - include_directories( - ${CMAKE_SOURCE_DIR}/dep/libmpq - ) -elseif( WIN32 ) - include_directories( +set(include_Dirs ${CMAKE_SOURCE_DIR}/dep/libmpq +) + +if( WIN32 ) + set(include_Dirs + ${include_Dirs} ${CMAKE_SOURCE_DIR}/dep/libmpq/win ) endif() +include_directories(${include_Dirs}) + add_executable(vmap4extractor ${sources}) target_link_libraries(vmap4extractor @@ -39,8 +32,6 @@ target_link_libraries(vmap4extractor ${ZLIB_LIBRARIES} ) -add_dependencies(vmap4extractor mpq) - if( UNIX ) install(TARGETS vmap4extractor DESTINATION bin) elseif( WIN32 ) diff --git a/src/tools/vmap4_extractor/mpq_libmpq.cpp b/src/tools/vmap4_extractor/mpq_libmpq.cpp index 528b9679a58..ffa097d9a22 100644 --- a/src/tools/vmap4_extractor/mpq_libmpq.cpp +++ b/src/tools/vmap4_extractor/mpq_libmpq.cpp @@ -79,7 +79,7 @@ size_t MPQFile::read(void* dest, size_t bytes) if (eof) return 0; size_t rpos = pointer + bytes; - if (rpos > size) { + if (rpos > size_t(size)) { bytes = size - pointer; eof = true; } diff --git a/src/tools/vmap4_extractor/mpq_libmpq04.h b/src/tools/vmap4_extractor/mpq_libmpq04.h index 89f715e9e87..9f0163067c4 100644 --- a/src/tools/vmap4_extractor/mpq_libmpq04.h +++ b/src/tools/vmap4_extractor/mpq_libmpq04.h @@ -1,6 +1,3 @@ -#define _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_WARNINGS - #ifndef MPQ_H #define MPQ_H diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp index 7420edfee2e..d9216fd77eb 100644 --- a/src/tools/vmap4_extractor/wdtfile.cpp +++ b/src/tools/vmap4_extractor/wdtfile.cpp @@ -35,7 +35,7 @@ WDTFile::WDTFile(char* file_name, char* file_name1) : WDT(file_name), gWmoInstan filename.append(file_name1,strlen(file_name1)); } -bool WDTFile::init(char */*map_id*/, unsigned int mapID) +bool WDTFile::init(char* /*map_id*/, unsigned int mapID) { if (WDT.isEof()) { -- cgit v1.2.3 From 10d4d2e5b74ef682f5db5364dd52547ec39f4510 Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 22 Jan 2013 18:45:09 +0100 Subject: Core/Objects: Changed how update fields marked for sending are stored serverside to use our UpdateMask class --- src/server/game/Entities/Object/Object.cpp | 49 ++++++++++++++---------------- src/server/game/Entities/Object/Object.h | 5 ++- 2 files changed, 24 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 6f4f3cf9d3d..f20d452dc96 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -75,7 +75,6 @@ Object::Object() : m_PackGUID(sizeof(uint64)+1) m_objectType = TYPEMASK_OBJECT; m_uint32Values = NULL; - _changedFields = NULL; m_valuesCount = 0; _fieldNotifyFlags = UF_FLAG_DYNAMIC; @@ -119,8 +118,6 @@ Object::~Object() } delete [] m_uint32Values; - delete [] _changedFields; - } void Object::_InitValues() @@ -128,8 +125,7 @@ void Object::_InitValues() m_uint32Values = new uint32[m_valuesCount]; memset(m_uint32Values, 0, m_valuesCount*sizeof(uint32)); - _changedFields = new bool[m_valuesCount]; - memset(_changedFields, 0, m_valuesCount*sizeof(bool)); + _changesMask.SetCount(m_valuesCount); m_objectUpdated = false; } @@ -757,7 +753,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* void Object::ClearUpdateMask(bool remove) { - memset(_changedFields, 0, m_valuesCount*sizeof(bool)); + _changesMask.Clear(); if (m_objectUpdated) { @@ -854,13 +850,12 @@ void Object::_LoadIntoDataField(std::string const& data, uint32 startOffset, uin for (uint32 index = 0; index < count; ++index) { m_uint32Values[startOffset + index] = atol(tokens[index]); - _changedFields[startOffset + index] = true; + _changesMask.SetBit(startOffset + index); } } void Object::_SetUpdateBits(UpdateMask* updateMask, Player* target) const { - bool* indexes = _changedFields; uint32* flags = NULL; bool isSelf = target == this; bool isOwner = false; @@ -870,8 +865,8 @@ void Object::_SetUpdateBits(UpdateMask* updateMask, Player* target) const GetUpdateFieldData(target, flags, isOwner, isItemOwner, hasSpecialInfo, isPartyMember); - for (uint16 index = 0; index < m_valuesCount; ++index, ++indexes) - if (_fieldNotifyFlags & flags[index] || (flags[index] & UF_FLAG_SPECIAL_INFO && hasSpecialInfo) || (*indexes && IsUpdateFieldVisible(flags[index], isSelf, isOwner, isItemOwner, isPartyMember))) + for (uint16 index = 0; index < m_valuesCount; ++index) + if (_fieldNotifyFlags & flags[index] || (flags[index] & UF_FLAG_SPECIAL_INFO && hasSpecialInfo) || (_changesMask.GetBit(index) && IsUpdateFieldVisible(flags[index], isSelf, isOwner, isItemOwner, isPartyMember))) updateMask->SetBit(index); } @@ -899,7 +894,7 @@ void Object::SetInt32Value(uint16 index, int32 value) if (m_int32Values[index] != value) { m_int32Values[index] = value; - _changedFields[index] = true; + _changesMask.SetBit(index); if (m_inWorld && !m_objectUpdated) { @@ -916,7 +911,7 @@ void Object::SetUInt32Value(uint16 index, uint32 value) if (m_uint32Values[index] != value) { m_uint32Values[index] = value; - _changedFields[index] = true; + _changesMask.SetBit(index); if (m_inWorld && !m_objectUpdated) { @@ -931,7 +926,7 @@ void Object::UpdateUInt32Value(uint16 index, uint32 value) ASSERT(index < m_valuesCount || PrintIndexError(index, true)); m_uint32Values[index] = value; - _changedFields[index] = true; + _changesMask.SetBit(index); } void Object::SetUInt64Value(uint16 index, uint64 value) @@ -941,8 +936,8 @@ void Object::SetUInt64Value(uint16 index, uint64 value) { m_uint32Values[index] = PAIR64_LOPART(value); m_uint32Values[index + 1] = PAIR64_HIPART(value); - _changedFields[index] = true; - _changedFields[index + 1] = true; + _changesMask.SetBit(index); + _changesMask.SetBit(index + 1); if (m_inWorld && !m_objectUpdated) { @@ -959,8 +954,8 @@ bool Object::AddUInt64Value(uint16 index, uint64 value) { m_uint32Values[index] = PAIR64_LOPART(value); m_uint32Values[index + 1] = PAIR64_HIPART(value); - _changedFields[index] = true; - _changedFields[index + 1] = true; + _changesMask.SetBit(index); + _changesMask.SetBit(index + 1); if (m_inWorld && !m_objectUpdated) { @@ -981,8 +976,8 @@ bool Object::RemoveUInt64Value(uint16 index, uint64 value) { m_uint32Values[index] = 0; m_uint32Values[index + 1] = 0; - _changedFields[index] = true; - _changedFields[index + 1] = true; + _changesMask.SetBit(index); + _changesMask.SetBit(index + 1); if (m_inWorld && !m_objectUpdated) { @@ -1003,7 +998,7 @@ void Object::SetFloatValue(uint16 index, float value) if (m_floatValues[index] != value) { m_floatValues[index] = value; - _changedFields[index] = true; + _changesMask.SetBit(index); if (m_inWorld && !m_objectUpdated) { @@ -1027,7 +1022,7 @@ void Object::SetByteValue(uint16 index, uint8 offset, uint8 value) { m_uint32Values[index] &= ~uint32(uint32(0xFF) << (offset * 8)); m_uint32Values[index] |= uint32(uint32(value) << (offset * 8)); - _changedFields[index] = true; + _changesMask.SetBit(index); if (m_inWorld && !m_objectUpdated) { @@ -1051,7 +1046,7 @@ void Object::SetUInt16Value(uint16 index, uint8 offset, uint16 value) { m_uint32Values[index] &= ~uint32(uint32(0xFFFF) << (offset * 16)); m_uint32Values[index] |= uint32(uint32(value) << (offset * 16)); - _changedFields[index] = true; + _changesMask.SetBit(index); if (m_inWorld && !m_objectUpdated) { @@ -1118,7 +1113,7 @@ void Object::SetFlag(uint16 index, uint32 newFlag) if (oldval != newval) { m_uint32Values[index] = newval; - _changedFields[index] = true; + _changesMask.SetBit(index); if (m_inWorld && !m_objectUpdated) { @@ -1139,7 +1134,7 @@ void Object::RemoveFlag(uint16 index, uint32 oldFlag) if (oldval != newval) { m_uint32Values[index] = newval; - _changedFields[index] = true; + _changesMask.SetBit(index); if (m_inWorld && !m_objectUpdated) { @@ -1162,7 +1157,7 @@ void Object::SetByteFlag(uint16 index, uint8 offset, uint8 newFlag) if (!(uint8(m_uint32Values[index] >> (offset * 8)) & newFlag)) { m_uint32Values[index] |= uint32(uint32(newFlag) << (offset * 8)); - _changedFields[index] = true; + _changesMask.SetBit(index); if (m_inWorld && !m_objectUpdated) { @@ -1185,7 +1180,7 @@ void Object::RemoveByteFlag(uint16 index, uint8 offset, uint8 oldFlag) if (uint8(m_uint32Values[index] >> (offset * 8)) & oldFlag) { m_uint32Values[index] &= ~uint32(uint32(oldFlag) << (offset * 8)); - _changedFields[index] = true; + _changesMask.SetBit(index); if (m_inWorld && !m_objectUpdated) { @@ -1968,7 +1963,7 @@ void WorldObject::SendPlaySound(uint32 Sound, bool OnlySelf) void Object::ForceValuesUpdateAtIndex(uint32 i) { - _changedFields[i] = true; + _changesMask.SetBit(i); if (m_inWorld && !m_objectUpdated) { sObjectAccessor->AddUpdateObject(this); diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index a9afd074c67..641f9afb154 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -20,7 +20,7 @@ #define _OBJECT_H #include "Common.h" -#include "UpdateFields.h" +#include "UpdateMask.h" #include "UpdateData.h" #include "GridReference.h" #include "ObjectDefines.h" @@ -107,7 +107,6 @@ class ByteBuffer; class WorldSession; class Creature; class Player; -class UpdateMask; class InstanceScript; class GameObject; class TempSummon; @@ -348,7 +347,7 @@ class Object float *m_floatValues; }; - bool* _changedFields; + UpdateMask _changesMask; uint16 m_valuesCount; -- cgit v1.2.3 From 5b9159e165ea4bca3ab32317b180d9d543f99dbf Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 22 Jan 2013 19:07:40 +0100 Subject: Tools: Build fix --- src/tools/mesh_extractor/MPQManager.cpp | 2 +- src/tools/mesh_extractor/Utils.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp index 0fe07cd8b85..5ae8558d749 100644 --- a/src/tools/mesh_extractor/MPQManager.cpp +++ b/src/tools/mesh_extractor/MPQManager.cpp @@ -14,7 +14,7 @@ char* MPQManager::Files[] = { "patch-3.MPQ" }; -char* MPQManager::Languages[] = { "enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; +char const* MPQManager::Languages[] = { "enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; void MPQManager::Initialize() { diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index 41ea33e6157..64fb1bb35ba 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -15,7 +15,7 @@ struct WorldModelDefinition; class DoodadInstance; -#define ASSERT(assertion) { if (!(assertion)) { ACE_Stack_Trace st; fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n", __FILE__, __LINE__, __FUNCTION__, #assertion, st.c_str()); *((volatile int*)NULL) = 0; } } +#define ASSERT(assertion) { if (!(assertion)) { ACE_Stack_Trace st; fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n%s\n", __FILE__, __LINE__, __FUNCTION__, #assertion, st.c_str()); *((volatile int*)NULL) = 0; } } struct Vector3 { -- cgit v1.2.3 From 7a74f68c0d974de5a1f885904fefa45db934da3d Mon Sep 17 00:00:00 2001 From: Nay Date: Tue, 22 Jan 2013 18:14:32 +0000 Subject: Tools/MapExtractor: Fix displaying of a few counts in Windows %zu works fine on GCC/Linux, but fails in MSVC/Windows --- src/tools/map_extractor/System.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index 2e117934679..bf88a92c32a 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -222,7 +222,7 @@ uint32 ReadMapDBC() map_ids[x].id = dbc.getRecord(x).getUInt(0); strcpy(map_ids[x].name, dbc.getRecord(x).getString(1)); } - printf("Done! (%zu maps loaded)\n", map_count); + printf("Done! (%u maps loaded)\n", (uint32)map_count); return map_count; } @@ -247,7 +247,7 @@ void ReadAreaTableDBC() maxAreaId = dbc.getMaxId(); - printf("Done! (%zu areas loaded)\n", area_count); + printf("Done! (%u areas loaded)\n", (uint32)area_count); } void ReadLiquidTypeTableDBC() @@ -268,7 +268,7 @@ void ReadLiquidTypeTableDBC() for(uint32 x = 0; x < liqTypeCount; ++x) LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); - printf("Done! (%zu LiqTypes loaded)\n", liqTypeCount); + printf("Done! (%u LiqTypes loaded)\n", (uint32)liqTypeCount); } // -- cgit v1.2.3 From 69baba23cc81bef23278549c93576afc3195ece5 Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 22 Jan 2013 19:30:52 +0100 Subject: Tools: Build fix, for real this time --- src/server/collision/Maps/MapTree.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp index e3cd158709c..eb4b4555cb4 100644 --- a/src/server/collision/Maps/MapTree.cpp +++ b/src/server/collision/Maps/MapTree.cpp @@ -21,6 +21,7 @@ #include "VMapManager2.h" #include "VMapDefinitions.h" #include "Log.h" +#include "Errors.h" #include #include -- cgit v1.2.3 From bd893b4516292de4d2b1244acbecb0f301977e3f Mon Sep 17 00:00:00 2001 From: Nay Date: Tue, 22 Jan 2013 18:41:26 +0000 Subject: Tools/MeshExtractor: Fix warnings --- src/tools/mesh_extractor/MPQManager.cpp | 2 +- src/tools/mesh_extractor/MPQManager.h | 4 ++-- src/tools/mesh_extractor/WorldModelGroup.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp index 5ae8558d749..91b9c121c89 100644 --- a/src/tools/mesh_extractor/MPQManager.cpp +++ b/src/tools/mesh_extractor/MPQManager.cpp @@ -4,7 +4,7 @@ #include "Utils.h" #include -char* MPQManager::Files[] = { +char const* MPQManager::Files[] = { "common.MPQ", "common-2.MPQ", "expansion.MPQ", diff --git a/src/tools/mesh_extractor/MPQManager.h b/src/tools/mesh_extractor/MPQManager.h index 788be7f5974..2f49ad258a5 100644 --- a/src/tools/mesh_extractor/MPQManager.h +++ b/src/tools/mesh_extractor/MPQManager.h @@ -24,8 +24,8 @@ public: std::set AvailableLocales; std::map LocaleFiles; - static char* Files[]; - static char* Languages[]; + static char const* Files[]; + static char const* Languages[]; protected: void InitializeDBC(); private: diff --git a/src/tools/mesh_extractor/WorldModelGroup.cpp b/src/tools/mesh_extractor/WorldModelGroup.cpp index 5eeef824b1a..21e1c1e63e1 100644 --- a/src/tools/mesh_extractor/WorldModelGroup.cpp +++ b/src/tools/mesh_extractor/WorldModelGroup.cpp @@ -137,7 +137,7 @@ void WorldModelGroup::ReadBatches() MOBALength = chunk->Length / 2; MOBA = new uint16[MOBALength]; - int count = fread(MOBA, sizeof(uint16), MOBALength, chunk->GetStream()); + uint32 count = (uint32)fread(MOBA, sizeof(uint16), MOBALength, chunk->GetStream()); if (count != MOBALength) - printf("WorldModelGroup::ReadBatches: Error reading data, expected %d, read %d\n", MOBALength, count); + printf("WorldModelGroup::ReadBatches: Error reading data, expected %u, read %u\n", MOBALength, count); } -- cgit v1.2.3 From 7a76de93f83984a05bc38e321ca2f710cfd221d4 Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Tue, 22 Jan 2013 20:24:00 +0100 Subject: Update more copyright note for 2013. --- dep/recastnavigation/Detour/CMakeLists.txt | 2 +- dep/recastnavigation/Recast/CMakeLists.txt | 2 +- src/tools/mmaps_generator/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/dep/recastnavigation/Detour/CMakeLists.txt b/dep/recastnavigation/Detour/CMakeLists.txt index c09e0e35d42..303a003dee2 100644 --- a/dep/recastnavigation/Detour/CMakeLists.txt +++ b/dep/recastnavigation/Detour/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2008-2010 Trinity +# Copyright (C) 2008-2013 TrinityCore # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without diff --git a/dep/recastnavigation/Recast/CMakeLists.txt b/dep/recastnavigation/Recast/CMakeLists.txt index 7ced79c10b7..726aff72c0c 100644 --- a/dep/recastnavigation/Recast/CMakeLists.txt +++ b/dep/recastnavigation/Recast/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2008-2010 Trinity +# Copyright (C) 2008-2013 TrinityCore # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without diff --git a/src/tools/mmaps_generator/CMakeLists.txt b/src/tools/mmaps_generator/CMakeLists.txt index 99492abf8ee..b168691c994 100644 --- a/src/tools/mmaps_generator/CMakeLists.txt +++ b/src/tools/mmaps_generator/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2008-2011 Trinity +# Copyright (C) 2008-2013 TrinityCore # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without -- cgit v1.2.3 From 6fc17c6b1e0dadc3429ffa67b753ac492ddbd7a1 Mon Sep 17 00:00:00 2001 From: Nay Date: Tue, 22 Jan 2013 19:34:04 +0000 Subject: Core: Fix compile warnings --- src/server/game/Miscellaneous/SharedDefines.h | 2 +- .../game/Movement/MovementGenerators/PointMovementGenerator.h | 2 +- .../game/Movement/MovementGenerators/TargetedMovementGenerator.h | 6 +++--- src/server/game/Movement/PathGenerator.cpp | 2 +- src/server/scripts/Commands/cs_mmaps.cpp | 4 ++-- src/tools/mmaps_generator/TerrainBuilder.cpp | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index e5c4377d085..3d8ad37c92d 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -3534,7 +3534,7 @@ enum PartyResult ERR_PARTY_LFG_TELEPORT_IN_COMBAT = 30 }; -#define MMAP_MAGIC 0x4d4d4150 // 'MMAP' +const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP' #define MMAP_VERSION 3 struct MmapTileHeader diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h index 89f643283d6..421736ca4ec 100644 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h @@ -27,7 +27,7 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG { public: PointMovementGenerator(uint32 _id, float _x, float _y, float _z, bool _generatePath, float _speed = 0.0f) : id(_id), - i_x(_x), i_y(_y), i_z(_z), m_generatePath(_generatePath), speed(_speed), i_recalculateSpeed(false) {} + i_x(_x), i_y(_y), i_z(_z), speed(_speed), m_generatePath(_generatePath), i_recalculateSpeed(false) {} void DoInitialize(T*); void DoFinalize(T*); diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 4f8cf658fde..3edeb348d54 100755 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -39,8 +39,8 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, { protected: TargetedMovementGeneratorMedium(Unit* target, float offset, float angle) : - TargetedMovementGeneratorBase(target), i_recheckDistance(0), i_path(NULL), - i_offset(offset), i_angle(angle), + TargetedMovementGeneratorBase(target), i_path(NULL), + i_recheckDistance(0), i_offset(offset), i_angle(angle), i_recalculateTravel(false), i_targetReached(false) { } @@ -55,12 +55,12 @@ class TargetedMovementGeneratorMedium : public MovementGeneratorMedium< T, D >, protected: void _setTargetLocation(T* owner, bool updateDestination); + PathGenerator* i_path; TimeTrackerSmall i_recheckDistance; float i_offset; float i_angle; bool i_recalculateTravel : 1; bool i_targetReached : 1; - PathGenerator* i_path; }; template diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 71617f6a6ab..dbda4aa2411 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -30,7 +30,7 @@ PathGenerator::PathGenerator(const Unit* owner) : _polyLength(0), _type(PATHFIND_BLANK), _useStraightPath(false), _forceDestination(false), _pointPathLimit(MAX_POINT_PATH_LENGTH), - _sourceUnit(owner), _navMesh(NULL), _navMeshQuery(NULL), _endPosition(Vector3::zero()) + _endPosition(Vector3::zero()), _sourceUnit(owner), _navMesh(NULL), _navMeshQuery(NULL) { sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow()); diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 4649e13e1c4..c4605e30991 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -98,7 +98,7 @@ public: PointsArray pointPath = path.GetPath(); handler->PSendSysMessage("%s's path to %s:", target->GetName().c_str(), player->GetName().c_str()); handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : "SmoothPath"); - handler->PSendSysMessage("Result: %s - Length: %i - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); + handler->PSendSysMessage("Result: %s - Length: "SIZEFMTD" - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); Vector3 start = path.GetStartPosition(); Vector3 end = path.GetEndPosition(); @@ -264,7 +264,7 @@ public: if (!creatureList.empty()) { - handler->PSendSysMessage("Found %i Creatures.", creatureList.size()); + handler->PSendSysMessage("Found "SIZEFTMD" Creatures.", creatureList.size()); uint32 paths = 0; uint32 uStartTime = getMSTime(); diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index c3d6541dfa3..6f26a43fa05 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -296,7 +296,7 @@ namespace MMAP } // FIXME: "the address of ‘liquid_type’ will always evaluate as ‘true’" - if (liquid_type && liquid_map) + if (liquid_map) { int count = meshData.liquidVerts.size() / 3; float xoffset = (float(tileX)-32)*GRID_SIZE; @@ -393,7 +393,7 @@ namespace MMAP // FIXME: "warning: the address of ‘liquid_type’ will always evaluate as ‘true’" // if there is no liquid, don't use liquid - if (!liquid_type || !meshData.liquidVerts.size() || !ltriangles.size()) + if (!meshData.liquidVerts.size() || !ltriangles.size()) useLiquid = false; else { -- cgit v1.2.3 From 98e01fdb3f8278502a461e481323e62ed4523148 Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Tue, 22 Jan 2013 21:00:08 +0100 Subject: Core: Fix build --- src/server/scripts/Commands/cs_mmaps.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index c4605e30991..97861133983 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -264,7 +264,7 @@ public: if (!creatureList.empty()) { - handler->PSendSysMessage("Found "SIZEFTMD" Creatures.", creatureList.size()); + handler->PSendSysMessage("Found "SIZEFMTD" Creatures.", creatureList.size()); uint32 paths = 0; uint32 uStartTime = getMSTime(); -- cgit v1.2.3 From 4f3c6b139031116fe5074e9340bc53139a98ab57 Mon Sep 17 00:00:00 2001 From: Nay Date: Tue, 22 Jan 2013 20:47:52 +0000 Subject: Core: Yet another warning fix @Kaelima: could you verify MoveCharge? --- src/server/game/Movement/MotionMaster.cpp | 2 +- src/tools/mmaps_generator/TerrainBuilder.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index f792aa959fb..c9ca7772186 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -428,7 +428,7 @@ void MotionMaster::MoveCharge(PathGenerator path, float speed, uint32 id) { Vector3 dest = path.GetActualEndPosition(); - MoveCharge(dest.x, dest.y, dest.z); + MoveCharge(dest.x, dest.y, dest.z, speed, id); Movement::MoveSplineInit init(_owner); init.MovebyPath(path.GetPath()); diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index 6f26a43fa05..a42cd2b9bc6 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -295,7 +295,6 @@ namespace MMAP printf("TerrainBuilder::loadMap: Failed to read some data expected 1, read 0\n"); } - // FIXME: "the address of ‘liquid_type’ will always evaluate as ‘true’" if (liquid_map) { int count = meshData.liquidVerts.size() / 3; @@ -369,7 +368,7 @@ namespace MMAP float* tverts = meshData.solidVerts.getCArray(); int* ttris = ttriangles.getCArray(); - if (ltriangles.size() + ttriangles.size() == 0) + if ((ltriangles.size() + ttriangles.size()) == 0) return false; // make a copy of liquid vertices -- cgit v1.2.3 From af50ce6223ded9aa91a087556f2332b9c1f13df8 Mon Sep 17 00:00:00 2001 From: joschiwald Date: Tue, 22 Jan 2013 00:20:16 +0100 Subject: Core/Spell: convert more spells to SpellScripts --- .../2013_01_23_00_world_spell_script_names.sql | 77 +++ src/server/game/Combat/ThreatManager.cpp | 19 +- src/server/game/Entities/Unit/Unit.cpp | 647 +-------------------- src/server/game/Entities/Unit/Unit.h | 42 +- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 28 - src/server/game/Spells/Auras/SpellAuras.cpp | 11 - src/server/game/Spells/SpellEffects.cpp | 2 +- .../IcecrownCitadel/boss_blood_queen_lana_thel.cpp | 38 ++ .../IcecrownCitadel/boss_the_lich_king.cpp | 37 ++ src/server/scripts/Spells/spell_dk.cpp | 54 ++ src/server/scripts/Spells/spell_druid.cpp | 75 +++ src/server/scripts/Spells/spell_generic.cpp | 180 ++++++ src/server/scripts/Spells/spell_hunter.cpp | 78 ++- src/server/scripts/Spells/spell_item.cpp | 351 ++++++++--- src/server/scripts/Spells/spell_mage.cpp | 197 +++++++ src/server/scripts/Spells/spell_paladin.cpp | 109 +++- src/server/scripts/Spells/spell_priest.cpp | 173 +++++- src/server/scripts/Spells/spell_rogue.cpp | 152 +++++ src/server/scripts/Spells/spell_shaman.cpp | 65 +++ src/server/scripts/Spells/spell_warlock.cpp | 97 +++ src/server/scripts/Spells/spell_warrior.cpp | 164 +++++- 21 files changed, 1795 insertions(+), 801 deletions(-) create mode 100644 sql/updates/world/2013_01_23_00_world_spell_script_names.sql (limited to 'src') diff --git a/sql/updates/world/2013_01_23_00_world_spell_script_names.sql b/sql/updates/world/2013_01_23_00_world_spell_script_names.sql new file mode 100644 index 00000000000..dd8b35ae420 --- /dev/null +++ b/sql/updates/world/2013_01_23_00_world_spell_script_names.sql @@ -0,0 +1,77 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` IN ( +70871, -- spell_blood_queen_essence_of_the_blood_queen +69383, -- spell_the_lich_king_dark_hunger +50453, -- spell_dk_blood_gorged +-48496, -- spell_dru_living_seed +48504, -- spell_dru_living_seed_proc +28764, -- spell_gen_adaptive_warding +27539, -- spell_gen_obsidian_armor +34074, -- spell_hun_ascpect_of_the_viper +64411, -- spell_item_blessing_of_ancient_kings +71875, -- spell_item_necrotic_touch +71877, -- spell_item_necrotic_touch +71169, -- spell_item_shadows_fate +71903, -- spell_item_shadowmourne +71905, -- spell_item_shadowmourne_soul_fragment +-44449, -- spell_mage_burnout +54646, -- spell_mage_focus_magic +-11119, -- spell_mage_ignite +-29074, -- spell_mage_master_of_elements +-9799, -- spell_pal_eye_for_an_eye +20154, -- spell_pal_seal_of_righteousness +21084 -- spell_pal_seal_of_righteousness +-47509, -- spell_pri_divine_aegis +55680, -- spell_pri_glyph_of_prayer_of_healing +28305, -- spell_pri_mana_leech +13877, -- spell_rog_blade_flurry +33735, -- spell_rog_blade_flurry +51211, -- spell_rog_blade_flurry +65956, -- spell_rog_blade_flurry +57934, -- spell_rog_tricks_of_the_trade +59628, -- spell_rog_tricks_of_the_trade_proc +-974, -- spell_sha_earth_shield +-47230, -- spell_warl_fel_synergy +63108, -- spell_warl_siphon_life +-58872, -- spell_warr_damage_shield +12328, -- spell_warr_sweeping_strikes +18765, -- spell_warr_sweeping_strikes +35429 -- spell_warr_sweeping_strikes +); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(70871, 'spell_blood_queen_essence_of_the_blood_queen'), +(69383, 'spell_the_lich_king_dark_hunger'), +(50453, 'spell_dk_blood_gorged'), +(-48496, 'spell_dru_living_seed'), +(48504, 'spell_dru_living_seed_proc'), +(28764, 'spell_gen_adaptive_warding'), +(27539, 'spell_gen_obsidian_armor'), +(34074, 'spell_hun_ascpect_of_the_viper'), +(64411, 'spell_item_blessing_of_ancient_kings'), +(71875, 'spell_item_necrotic_touch'), +(71877, 'spell_item_necrotic_touch'), +(71169, 'spell_item_shadows_fate'), +(71903, 'spell_item_shadowmourne'), +(71905, 'spell_item_shadowmourne_soul_fragment'), +(-44449, 'spell_mage_burnout'), +(54646, 'spell_mage_focus_magic'), +(-11119, 'spell_mage_ignite'), +(-29074, 'spell_mage_master_of_elements'), +(-9799, 'spell_pal_eye_for_an_eye'), +(20154, 'spell_pal_seal_of_righteousness'), +(21084, 'spell_pal_seal_of_righteousness'), +(-47509, 'spell_pri_divine_aegis'), +(55680, 'spell_pri_glyph_of_prayer_of_healing'), +(28305, 'spell_pri_mana_leech'), +(13877, 'spell_rog_blade_flurry'), +(33735, 'spell_rog_blade_flurry'), +(51211, 'spell_rog_blade_flurry'), +(65956, 'spell_rog_blade_flurry'), +(57934, 'spell_rog_tricks_of_the_trade'), +(59628, 'spell_rog_tricks_of_the_trade_proc'), +(-974, 'spell_sha_earth_shield'), +(-47230, 'spell_warl_fel_synergy'), +(63108, 'spell_warl_siphon_life'), +(-58872, 'spell_warr_damage_shield'), +(12328, 'spell_warr_sweeping_strikes'), +(18765, 'spell_warr_sweeping_strikes'), +(35429, 'spell_warr_sweeping_strikes'); diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp index 6d291ca301f..249c1696348 100644 --- a/src/server/game/Combat/ThreatManager.cpp +++ b/src/server/game/Combat/ThreatManager.cpp @@ -416,20 +416,17 @@ void ThreatManager::addThreat(Unit* victim, float threat, SpellSchoolMask school void ThreatManager::doAddThreat(Unit* victim, float threat) { - uint32 reducedThreadPercent = victim->GetReducedThreatPercent(); + uint32 redirectThreadPct = victim->GetRedirectThreatPercent(); // must check > 0.0f, otherwise dead loop - if (threat > 0.0f && reducedThreadPercent) + if (threat > 0.0f && redirectThreadPct) { - Unit* redirectTarget = victim->GetMisdirectionTarget(); - if (redirectTarget) - if (Aura* glyphAura = redirectTarget->GetAura(63326)) // Glyph of Vigilance - reducedThreadPercent += glyphAura->GetSpellInfo()->Effects[0].CalcValue(); - - float reducedThreat = threat * reducedThreadPercent / 100.0f; - threat -= reducedThreat; - if (redirectTarget) - _addThreat(redirectTarget, reducedThreat); + if (Unit* redirectTarget = victim->GetRedirectThreatTarget()) + { + float redirectThreat = CalculatePct(threat, redirectThreadPct); + threat -= redirectThreat; + _addThreat(redirectTarget, redirectThreat); + } } _addThreat(victim, threat); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 49b86cff864..e7136a5c26f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -256,8 +256,8 @@ Unit::Unit(bool isWorldObject): WorldObject(isWorldObject) m_speed_rate[i] = 1.0f; m_charmInfo = NULL; - m_reducedThreatPercent = 0; - m_misdirectionTargetGUID = 0; + + _redirectThreadInfo = RedirectThreatInfo(); // remove aurastates allowing special moves for (uint8 i = 0; i < MAX_REACTIVE; ++i) @@ -4984,127 +4984,6 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType SendAttackStateUpdate(&dmgInfo); } -bool Unit::HandleHasteAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown) -{ - SpellInfo const* hasteSpell = triggeredByAura->GetSpellInfo(); - - Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; - - uint32 triggered_spell_id = 0; - Unit* target = victim; - int32 basepoints0 = 0; - - switch (hasteSpell->SpellFamilyName) - { - case SPELLFAMILY_ROGUE: - { - switch (hasteSpell->Id) - { - // Blade Flurry - case 13877: - case 33735: - { - target = SelectNearbyTarget(victim); - if (!target) - return false; - basepoints0 = damage; - triggered_spell_id = 22482; - break; - } - } - break; - } - } - - // processed charge only counting case - if (!triggered_spell_id) - return true; - - SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id); - - if (!triggerEntry) - { - sLog->outError(LOG_FILTER_UNITS, "Unit::HandleHasteAuraProc: Spell %u has non-existing triggered spell %u", hasteSpell->Id, triggered_spell_id); - return false; - } - - if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(triggered_spell_id)) - return false; - - if (basepoints0) - CastCustomSpell(target, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); - else - CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura); - - if (cooldown && GetTypeId() == TYPEID_PLAYER) - ToPlayer()->AddSpellCooldown(triggered_spell_id, 0, time(NULL) + cooldown); - - return true; -} - -bool Unit::HandleSpellCritChanceAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown) -{ - SpellInfo const* triggeredByAuraSpell = triggeredByAura->GetSpellInfo(); - - Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; - - uint32 triggered_spell_id = 0; - Unit* target = victim; - int32 basepoints0 = 0; - - switch (triggeredByAuraSpell->SpellFamilyName) - { - case SPELLFAMILY_MAGE: - { - switch (triggeredByAuraSpell->Id) - { - // Focus Magic - case 54646: - { - Unit* caster = triggeredByAura->GetCaster(); - if (!caster) - return false; - - triggered_spell_id = 54648; - target = caster; - break; - } - } - } - } - - // processed charge only counting case - if (!triggered_spell_id) - return true; - - SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id); - - if (!triggerEntry) - { - sLog->outError(LOG_FILTER_UNITS, "Unit::HandleHasteAuraProc: Spell %u has non-existing triggered spell %u", triggeredByAuraSpell->Id, triggered_spell_id); - return false; - } - - // default case - if (!target || (target != this && !target->isAlive())) - return false; - - if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(triggered_spell_id)) - return false; - - if (basepoints0) - CastCustomSpell(target, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); - else - CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura); - - if (cooldown && GetTypeId() == TYPEID_PLAYER) - ToPlayer()->AddSpellCooldown(triggered_spell_id, 0, time(NULL) + cooldown); - - return true; -} - //victim may be NULL bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown) { @@ -5128,38 +5007,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere { switch (dummySpell->Id) { - // Bloodworms Health Leech - case 50453: - { - if (Unit* owner = GetOwner()) - { - basepoints0 = int32(damage * 1.50f); - target = owner; - triggered_spell_id = 50454; - break; - } - return false; - } - // Eye for an Eye - case 9799: - case 25988: - { - // return damage % to attacker but < 50% own total health - basepoints0 = int32(std::min(CalculatePct(damage, triggerAmount), CountPctFromMaxHealth(50))); - triggered_spell_id = 25997; - break; - } - // Sweeping Strikes - case 18765: - case 35429: - { - target = SelectNearbyTarget(victim); - if (!target) - return false; - - triggered_spell_id = 26654; - break; - } // Unstable Power case 24658: { @@ -5176,67 +5023,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere RemoveAuraFromStack(24662); return true; } - // Adaptive Warding (Frostfire Regalia set) - case 28764: - { - if (!procSpell) - return false; - - // find Mage Armor - if (!GetAuraEffect(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT, SPELLFAMILY_MAGE, 0x10000000, 0, 0)) - return false; - - switch (GetFirstSchoolInMask(procSpell->GetSchoolMask())) - { - case SPELL_SCHOOL_NORMAL: - case SPELL_SCHOOL_HOLY: - return false; // ignored - case SPELL_SCHOOL_FIRE: triggered_spell_id = 28765; break; - case SPELL_SCHOOL_NATURE: triggered_spell_id = 28768; break; - case SPELL_SCHOOL_FROST: triggered_spell_id = 28766; break; - case SPELL_SCHOOL_SHADOW: triggered_spell_id = 28769; break; - case SPELL_SCHOOL_ARCANE: triggered_spell_id = 28770; break; - default: - return false; - } - - target = this; - break; - } - // Obsidian Armor (Justice Bearer`s Pauldrons shoulder) - case 27539: - { - if (!procSpell) - return false; - - switch (GetFirstSchoolInMask(procSpell->GetSchoolMask())) - { - case SPELL_SCHOOL_NORMAL: - return false; // ignore - case SPELL_SCHOOL_HOLY: triggered_spell_id = 27536; break; - case SPELL_SCHOOL_FIRE: triggered_spell_id = 27533; break; - case SPELL_SCHOOL_NATURE: triggered_spell_id = 27538; break; - case SPELL_SCHOOL_FROST: triggered_spell_id = 27534; break; - case SPELL_SCHOOL_SHADOW: triggered_spell_id = 27535; break; - case SPELL_SCHOOL_ARCANE: triggered_spell_id = 27540; break; - default: - return false; - } - - target = this; - break; - } - // Mana Leech (Passive) (Priest Pet Aura) - case 28305: - { - // Cast on owner - target = GetOwner(); - if (!target) - return false; - - triggered_spell_id = 34650; - break; - } // Mark of Malice case 33493: { @@ -5427,14 +5213,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } return false; } - // Living Seed - case 48504: - { - triggered_spell_id = 48503; - basepoints0 = triggerAmount; - target = this; - break; - } // Kill command case 58914: { @@ -5594,50 +5372,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } break; } - case 71875: // Item - Black Bruise: Necrotic Touch Proc - case 71877: - { - basepoints0 = CalculatePct(int32(damage), triggerAmount); - triggered_spell_id = 71879; - break; - } - // Item - Shadowmourne Legendary - case 71903: - { - if (!victim || !victim->isAlive() || HasAura(73422)) // cant collect shards while under effect of Chaos Bane buff - return false; - - CastSpell(this, 71905, true, NULL, triggeredByAura); - - // this can't be handled in AuraScript because we need to know victim - Aura const* dummy = GetAura(71905); - if (!dummy || dummy->GetStackAmount() < 10) - return false; - - RemoveAurasDueToSpell(71905); - triggered_spell_id = 71904; - target = victim; - break; - } - // Shadow's Fate (Shadowmourne questline) - case 71169: - { - Unit* caster = triggeredByAura->GetCaster(); - if (caster && caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->GetQuestStatus(24547) == QUEST_STATUS_INCOMPLETE) - { - CastSpell(caster, 71203, true); - return true; - } - else - return false; - } - // Essence of the Blood Queen - case 70871: - { - basepoints0 = CalculatePct(int32(damage), triggerAmount); - CastCustomSpell(70872, SPELLVALUE_BASE_POINT0, basepoints0, this); - return true; - } case 65032: // Boom aura (321 Boombot) { if (victim->GetEntry() != 33343) // Scrapbot @@ -5650,13 +5384,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere instance->DoCastSpellOnPlayers(65037); // Achievement criteria marker break; } - // Dark Hunger (The Lich King encounter) - case 69383: - { - basepoints0 = CalculatePct(int32(damage), 50); - triggered_spell_id = 69384; - break; - } } break; } @@ -5674,22 +5401,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 29442; break; } - // Master of Elements - if (dummySpell->SpellIconID == 1920) - { - if (!procSpell) - return false; - - // mana cost save - int32 cost = int32(procSpell->ManaCost + CalculatePct(GetCreateMana(), procSpell->ManaCostPercentage)); - basepoints0 = CalculatePct(cost, triggerAmount); - if (basepoints0 <= 0) - return false; - - target = this; - triggered_spell_id = 29077; - break; - } // Arcane Potency if (dummySpell->SpellIconID == 2120) { @@ -5707,7 +5418,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } break; } - // Hot Streak if (dummySpell->SpellIconID == 2999) { @@ -5730,20 +5440,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere counter->SetAmount(25); return true; } - // Burnout - if (dummySpell->SpellIconID == 2998) - { - if (!procSpell) - return false; - - int32 cost = int32(procSpell->ManaCost + CalculatePct(GetCreateMana(), procSpell->ManaCostPercentage)); - basepoints0 = CalculatePct(cost, triggerAmount); - if (basepoints0 <= 0) - return false; - triggered_spell_id = 44450; - target = this; - break; - } // Incanter's Regalia set (add trigger chance to Mana Shield) if (dummySpell->SpellFamilyFlags[0] & 0x8000) { @@ -5773,29 +5469,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere RemoveAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); return true; } - // Ignite - case 11119: - case 11120: - case 12846: - case 12847: - case 12848: - { - switch (dummySpell->Id) - { - case 11119: basepoints0 = int32(0.04f * damage); break; - case 11120: basepoints0 = int32(0.08f * damage); break; - case 12846: basepoints0 = int32(0.12f * damage); break; - case 12847: basepoints0 = int32(0.16f * damage); break; - case 12848: basepoints0 = int32(0.20f * damage); break; - default: - sLog->outError(LOG_FILTER_UNITS, "Unit::HandleDummyAuraProc: non handled spell id: %u (IG)", dummySpell->Id); - return false; - } - - triggered_spell_id = 12654; - basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE); - break; - } // Glyph of Ice Block case 56372: { @@ -5815,25 +5488,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } break; } - // Blessing of Ancient Kings (Val'anyr, Hammer of Ancient Kings) - case 64411: - { - if (!victim) - return false; - basepoints0 = int32(CalculatePct(damage, 15)); - if (AuraEffect* aurEff = victim->GetAuraEffect(64413, 0, GetGUID())) - { - // The shield can grow to a maximum size of 20, 000 damage absorbtion - aurEff->SetAmount(std::min(aurEff->GetAmount() + basepoints0, 20000)); - - // Refresh and return to prevent replacing the aura - aurEff->GetBase()->RefreshDuration(); - return true; - } - target = victim; - triggered_spell_id = 64413; - break; - } case 47020: // Enter vehicle XT-002 (Scrapbot) { if (GetTypeId() != TYPEID_UNIT) @@ -5854,16 +5508,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere { switch (dummySpell->Id) { - // Sweeping Strikes - case 12328: - { - target = SelectNearbyTarget(victim); - if (!target) - return false; - - triggered_spell_id = 26654; - break; - } // Victorious case 32216: { @@ -5913,14 +5557,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere target = this; break; } - // Damage Shield - if (dummySpell->SpellIconID == 3214) - { - triggered_spell_id = 59653; - // % of amount blocked - basepoints0 = CalculatePct(int32(GetShieldBlockValue()), triggerAmount); - break; - } // Glyph of Blocking if (dummySpell->Id == 58375) { @@ -5991,31 +5627,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggeredByAura->SetAmount(triggeredByAura->GetAmount() - damage); return true; } - // Fel Synergy - if (dummySpell->SpellIconID == 3222) - { - target = GetGuardianPet(); - if (!target) - return false; - basepoints0 = CalculatePct(int32(damage), triggerAmount); - triggered_spell_id = 54181; - break; - } switch (dummySpell->Id) { - // Siphon Life - case 63108: - { - if (!damage) - break; - // Glyph of Siphon Life - if (HasAura(56216)) - triggerAmount += triggerAmount / 4; - triggered_spell_id = 63106; - target = this; - basepoints0 = CalculatePct(int32(damage), triggerAmount); - break; - } // Glyph of Shadowflame case 63310: { @@ -6126,24 +5739,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere victim->CastSpell(victim, 57669, true, castItem, triggeredByAura); return true; // no hidden cooldown } - // Divine Aegis - if (dummySpell->SpellIconID == 2820) - { - if (!target) - return false; - - // Multiple effects stack, so let's try to find this aura. - int32 bonus = 0; - if (AuraEffect const* aurEff = target->GetAuraEffect(47753, 0)) - bonus = aurEff->GetAmount(); - - basepoints0 = CalculatePct(int32(damage), triggerAmount) + bonus; - if (basepoints0 > target->getLevel() * 125) - basepoints0 = target->getLevel() * 125; - - triggered_spell_id = 47753; - break; - } // Body and Soul if (dummySpell->SpellIconID == 2218) { @@ -6184,31 +5779,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere target = this; break; } - // Glyph of Prayer of Healing - case 55680: - { - triggered_spell_id = 56161; - - SpellInfo const* GoPoH = sSpellMgr->GetSpellInfo(triggered_spell_id); - if (!GoPoH) - return false; - - int EffIndex = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++) - { - if (GoPoH->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA) - { - EffIndex = i; - break; - } - } - int32 tickcount = GoPoH->GetMaxDuration() / GoPoH->Effects[EffIndex].Amplitude; - if (!tickcount) - return false; - - basepoints0 = CalculatePct(int32(damage), triggerAmount) / tickcount; - break; - } // Improved Shadowform case 47570: case 47569: @@ -6481,13 +6051,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = isWrathSpell ? 48518 : 48517; break; } - // Living Seed - else if (dummySpell->SpellIconID == 2860) - { - triggered_spell_id = 48504; - basepoints0 = CalculatePct(int32(damage), triggerAmount); - break; - } break; } case SPELLFAMILY_ROGUE: @@ -6508,16 +6071,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 32747; break; } - case 57934: // Tricks of the Trade - { - Unit* redirectTarget = GetMisdirectionTarget(); - RemoveAura(57934); - if (!redirectTarget) - break; - CastSpell(this, 59628, true); - CastSpell(redirectTarget, 57933, true); - break; - } } switch (dummySpell->SpellIconID) @@ -6636,14 +6189,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere switch (dummySpell->Id) { - case 34477: // Misdirection - { - if (!GetMisdirectionTarget()) - return false; - triggered_spell_id = 35079; // 4 sec buff on self - target = this; - break; - } case 57870: // Glyph of Mend Pet { victim->CastSpell(victim, 57894, true, NULL, NULL, GetGUID()); @@ -6654,18 +6199,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } case SPELLFAMILY_PALADIN: { - // Seal of Righteousness - melee proc dummy (addition ${$MWS*(0.022*$AP+0.044*$SPH)} damage) - if (dummySpell->SpellFamilyFlags[0] & 0x8000000) - { - if (effIndex != 0) - return false; - triggered_spell_id = 25742; - float ap = GetTotalAttackPowerValue(BASE_ATTACK); - int32 holy = SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_HOLY) + - victim->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_HOLY); - basepoints0 = (int32)GetAttackTime(BASE_ATTACK) * int32(ap * 0.022f + 0.044f * holy) / 1000; - break; - } // Light's Beacon - Beacon of Light if (dummySpell->Id == 53651) { @@ -6832,20 +6365,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } break; } - case 25899: // Greater Blessing of Sanctuary - case 20911: // Blessing of Sanctuary - { - target = this; - switch (target->getPowerType()) - { - case POWER_MANA: - triggered_spell_id = 57319; - break; - default: - return false; - } - break; - } // Seal of Vengeance (damage calc on apply aura) case 31801: { @@ -7348,20 +6867,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere target = this; break; } - // Earth Shield - if (dummySpell->SpellFamilyFlags[1] & 0x00000400) - { - // 3.0.8: Now correctly uses the Shaman's own spell critical strike chance to determine the chance of a critical heal. - originalCaster = triggeredByAura->GetCasterGUID(); - target = this; - basepoints0 = triggerAmount; - - // Glyph of Earth Shield - if (AuraEffect* aur = GetAuraEffect(63279, 0)) - AddPct(basepoints0, aur->GetAmount()); - triggered_spell_id = 379; - break; - } // Flametongue Weapon (Passive) if (dummySpell->SpellFamilyFlags[0] & 0x200000) { @@ -7813,114 +7318,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere return true; } -bool Unit::HandleObsModEnergyAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown) -{ - SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo(); - //uint32 effIndex = triggeredByAura->GetEffIndex(); - //int32 triggerAmount = triggeredByAura->GetAmount(); - - Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; - - uint32 triggered_spell_id = 0; - Unit* target = victim; - int32 basepoints0 = 0; - - switch (dummySpell->SpellFamilyName) - { - case SPELLFAMILY_HUNTER: - { - // Aspect of the Viper - if (dummySpell->SpellFamilyFlags[1] & 0x40000) - { - uint32 maxmana = GetMaxPower(POWER_MANA); - basepoints0 = CalculatePct(maxmana, GetAttackTime(RANGED_ATTACK) / 1000.0f); - target = this; - triggered_spell_id = 34075; - break; - } - break; - } - } - // processed charge only counting case - if (!triggered_spell_id) - return true; - - SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id); - - // Try handle unknown trigger spells - if (!triggerEntry) - { - sLog->outError(LOG_FILTER_UNITS, "Unit::HandleObsModEnergyAuraProc: Spell %u has non-existing triggered spell %u", dummySpell->Id, triggered_spell_id); - return false; - } - - if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(triggered_spell_id)) - return false; - if (basepoints0) - CastCustomSpell(target, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); - else - CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura); - - if (cooldown && GetTypeId() == TYPEID_PLAYER) - ToPlayer()->AddSpellCooldown(triggered_spell_id, 0, time(NULL) + cooldown); - return true; -} -bool Unit::HandleModDamagePctTakenAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown) -{ - SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo(); - //uint32 effIndex = triggeredByAura->GetEffIndex(); - //int32 triggerAmount = triggeredByAura->GetAmount(); - - Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; - - uint32 triggered_spell_id = 0; - Unit* target = victim; - int32 basepoints0 = 0; - - switch (dummySpell->SpellFamilyName) - { - case SPELLFAMILY_PALADIN: - { - // Blessing of Sanctuary - if (dummySpell->SpellFamilyFlags[0] & 0x10000000) - { - switch (getPowerType()) - { - case POWER_MANA: triggered_spell_id = 57319; break; - default: - return false; - } - } - break; - } - } - // processed charge only counting case - if (!triggered_spell_id) - return true; - - SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id); - - if (!triggerEntry) - { - sLog->outError(LOG_FILTER_UNITS, "Unit::HandleModDamagePctTakenAuraProc: Spell %u has non-existing triggered spell %u", dummySpell->Id, triggered_spell_id); - return false; - } - - if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(triggered_spell_id)) - return false; - - if (basepoints0) - CastCustomSpell(target, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); - else - CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura); - - if (cooldown && GetTypeId() == TYPEID_PLAYER) - ToPlayer()->AddSpellCooldown(triggered_spell_id, 0, time(NULL) + cooldown); - - return true; -} // Used in case when access to whole aura is needed // All procs should be handled like this... @@ -8303,12 +7700,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg RemoveAuraFromStack(auraSpellInfo->Id); return false; } - if (auraSpellInfo->Id == 50720) - { - target = triggeredByAura->GetCaster(); - if (!target) - return false; - } break; case SPELLFAMILY_WARLOCK: { @@ -14536,7 +13927,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u SpellInfo const* spellInfo = i->aura->GetSpellInfo(); uint32 Id = i->aura->GetId(); - AuraApplication const* aurApp = i->aura->GetApplicationOfTarget(GetGUID()); + AuraApplication* aurApp = i->aura->GetApplicationOfTarget(GetGUID()); bool prepare = i->aura->CallScriptPrepareProcHandlers(aurApp, eventInfo); @@ -14589,17 +13980,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u case SPELL_AURA_PROC_TRIGGER_DAMAGE: { // target has to be valid - if (!target) + if (!eventInfo.GetProcTarget()) break; - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", triggeredByAura->GetAmount(), spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); - SpellNonMeleeDamage damageInfo(this, target, spellInfo->Id, spellInfo->SchoolMask); - uint32 newDamage = SpellDamageBonusDone(target, spellInfo, triggeredByAura->GetAmount(), SPELL_DIRECT_DAMAGE); - newDamage = target->SpellDamageBonusTaken(this, spellInfo, newDamage, SPELL_DIRECT_DAMAGE); - CalculateSpellDamageTaken(&damageInfo, newDamage, spellInfo); - DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb); - SendSpellNonMeleeDamageLog(&damageInfo); - DealSpellDamage(&damageInfo, true); + triggeredByAura->HandleProcTriggerDamageAuraProc(aurApp, eventInfo); // this function is part of the new proc system takeCharges = true; break; } @@ -14612,22 +13996,12 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u break; } case SPELL_AURA_OBS_MOD_POWER: - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); - if (HandleObsModEnergyAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) - takeCharges = true; - break; + case SPELL_AURA_MOD_SPELL_CRIT_CHANCE: case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); - if (HandleModDamagePctTakenAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) - takeCharges = true; - break; case SPELL_AURA_MOD_MELEE_HASTE: - { - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); - if (HandleHasteAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) - takeCharges = true; + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, isVictim ? "a victim's" : "an attacker's", triggeredByAura->GetId()); + takeCharges = true; break; - } case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: { sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); @@ -14699,11 +14073,6 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u if (triggeredByAura->GetCasterGUID() == target->GetGUID()) takeCharges = true; break; - case SPELL_AURA_MOD_SPELL_CRIT_CHANCE: - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: casting spell id %u (triggered by %s spell crit chance aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); - if (procSpell && HandleSpellCritChanceAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) - takeCharges = true; - break; // CC Auras which use their amount amount to drop // Are there any more auras which need this? case SPELL_AURA_MOD_CONFUSE: diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 4bcc9c4b823..9b353d4cc02 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -965,6 +965,28 @@ struct SpellPeriodicAuraLogInfo uint32 createProcExtendMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCondition); +struct RedirectThreatInfo +{ + RedirectThreatInfo() : _targetGUID(0), _threatPct(0) { } + uint64 _targetGUID; + uint32 _threatPct; + + uint64 GetTargetGUID() { return _targetGUID; } + uint32 GetThreatPct() { return _threatPct; } + + void Set(uint64 guid, uint32 pct) + { + _targetGUID = guid; + _threatPct = pct; + } + + void ModifyThreatPct(int32 amount) + { + amount += _threatPct; + _threatPct = uint32(std::max(0, amount)); + } +}; + #define MAX_DECLINED_NAME_CASES 5 struct DeclinedName @@ -2153,13 +2175,12 @@ class Unit : public WorldObject uint32 GetModelForForm(ShapeshiftForm form) const; uint32 GetModelForTotem(PlayerTotemType totemType); - void SetReducedThreatPercent(uint32 pct, uint64 guid) - { - m_reducedThreatPercent = pct; - m_misdirectionTargetGUID = guid; - } - uint32 GetReducedThreatPercent() { return m_reducedThreatPercent; } - Unit* GetMisdirectionTarget() { return m_misdirectionTargetGUID ? GetUnit(*this, m_misdirectionTargetGUID) : NULL; } + // Redirect Threat + void SetRedirectThreat(uint64 guid, uint32 pct) { _redirectThreadInfo.Set(guid, pct); } + void ResetRedirectThreat() { SetRedirectThreat(0, 0); } + void ModifyRedirectThreat(int32 amount) { _redirectThreadInfo.ModifyThreatPct(amount); } + uint32 GetRedirectThreatPercent() { return _redirectThreadInfo.GetThreatPct(); } + Unit* GetRedirectThreatTarget() { return _redirectThreadInfo.GetTargetGUID() ? GetUnit(*this, _redirectThreadInfo.GetTargetGUID()) : NULL; } bool IsAIEnabled, NeedChangeAI; bool CreateVehicleKit(uint32 id, uint32 creatureEntry); @@ -2305,10 +2326,6 @@ class Unit : public WorldObject private: bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const* & spellProcEvent); bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); - bool HandleHasteAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); - bool HandleSpellCritChanceAuraProc(Unit* victim, uint32 damage, AuraEffect* triggredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); - bool HandleObsModEnergyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); - bool HandleModDamagePctTakenAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool * handled); bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown); @@ -2341,8 +2358,7 @@ class Unit : public WorldObject ComboPointHolderSet m_ComboPointHolders; - uint32 m_reducedThreatPercent; - uint64 m_misdirectionTargetGUID; + RedirectThreatInfo _redirectThreadInfo; bool m_cleanupDone; // lock made to not add stuff after cleanup before delete bool m_duringRemoveFromWorld; // lock made to not add stuff after begining removing from world diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index d029d2884c9..9230c46db15 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -484,16 +484,6 @@ int32 AuraEffect::CalculateAmount(Unit* caster) case SPELL_AURA_MANA_SHIELD: m_canBeRecalculated = false; break; - case SPELL_AURA_DUMMY: - if (!caster) - break; - // Earth Shield - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[1] & 0x400) - { - amount = caster->SpellHealingBonusDone(GetBase()->GetUnitOwner(), GetSpellInfo(), amount, SPELL_DIRECT_DAMAGE); - amount = GetBase()->GetUnitOwner()->SpellHealingBonusTaken(caster, GetSpellInfo(), amount, SPELL_DIRECT_DAMAGE); - } - break; default: break; } @@ -4694,10 +4684,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool if (Aura* newAura = target->AddAura(71564, target)) newAura->SetStackAmount(newAura->GetSpellInfo()->StackAmount); break; - case 59628: // Tricks of the Trade - if (caster && caster->GetMisdirectionTarget()) - target->SetReducedThreatPercent(100, caster->GetMisdirectionTarget()->GetGUID()); - break; } } // AT REMOVE @@ -4793,20 +4779,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool if (GetId() == 61777) target->CastSpell(target, GetAmount(), true); break; - case SPELLFAMILY_ROGUE: - // Tricks of the trade - switch (GetId()) - { - case 59628: //Tricks of the trade buff on rogue (6sec duration) - target->SetReducedThreatPercent(0, 0); - break; - case 57934: //Tricks of the trade buff on rogue (30sec duration) - if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE || !caster->GetMisdirectionTarget()) - target->SetReducedThreatPercent(0, 0); - else - target->SetReducedThreatPercent(0, caster->GetMisdirectionTarget()->GetGUID()); - break; - } default: break; } diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index a41d25eae09..795908ce4b5 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1537,17 +1537,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b // mods at aura apply or remove switch (GetSpellInfo()->SpellFamilyName) { - case SPELLFAMILY_GENERIC: - switch (GetId()) - { - case 50720: // Vigilance - if (apply) - target->CastSpell(caster, 59665, true, 0, 0, caster->GetGUID()); - else - target->SetReducedThreatPercent(0, 0); - break; - } - break; case SPELLFAMILY_DRUID: // Enrage if ((GetSpellInfo()->SpellFamilyFlags[0] & 0x80000) && GetSpellInfo()->SpellIconID == 961) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 4fdf6654cba..bee770df748 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -5791,7 +5791,7 @@ void Spell::EffectRedirectThreat(SpellEffIndex /*effIndex*/) return; if (unitTarget) - m_caster->SetReducedThreatPercent((uint32)damage, unitTarget->GetGUID()); + m_caster->SetRedirectThreat(unitTarget->GetGUID(), uint32(damage)); } void Spell::EffectGameObjectDamage(SpellEffIndex /*effIndex*/) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index c8caa3976e4..5643d0ab732 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -46,6 +46,7 @@ enum Spells SPELL_FRENZIED_BLOODTHIRST_VISUAL = 71949, SPELL_VAMPIRIC_BITE = 71726, SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR = 70879, + SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL = 70872, SPELL_FRENZIED_BLOODTHIRST = 70877, SPELL_UNCONTROLLABLE_FRENZY = 70923, SPELL_PRESENCE_OF_THE_DARKFALLEN = 71952, @@ -698,6 +699,42 @@ class spell_blood_queen_bloodbolt : public SpellScriptLoader } }; +// 70871 - Essence of the Blood Queen +class spell_blood_queen_essence_of_the_blood_queen : public SpellScriptLoader +{ + public: + spell_blood_queen_essence_of_the_blood_queen() : SpellScriptLoader("spell_blood_queen_essence_of_the_blood_queen") { } + + class spell_blood_queen_essence_of_the_blood_queen_AuraScript : public AuraScript + { + PrepareAuraScript(spell_blood_queen_essence_of_the_blood_queen_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL)) + return false; + return true; + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 heal = CalculatePct(int32(eventInfo.GetDamageInfo()->GetDamage()), aurEff->GetAmount()); + GetTarget()->CastCustomSpell(SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL, SPELLVALUE_BASE_POINT0, heal, GetTarget()); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_blood_queen_essence_of_the_blood_queen_AuraScript::OnProc, EFFECT_1, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_blood_queen_essence_of_the_blood_queen_AuraScript(); + } +}; + class spell_blood_queen_pact_of_the_darkfallen : public SpellScriptLoader { public: @@ -849,6 +886,7 @@ void AddSC_boss_blood_queen_lana_thel() new spell_blood_queen_vampiric_bite(); new spell_blood_queen_frenzied_bloodthirst(); new spell_blood_queen_bloodbolt(); + new spell_blood_queen_essence_of_the_blood_queen(); new spell_blood_queen_pact_of_the_darkfallen(); new spell_blood_queen_pact_of_the_darkfallen_dmg(); new spell_blood_queen_pact_of_the_darkfallen_dmg_target(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 452d09cf65f..3bd313fa148 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -145,6 +145,7 @@ enum Spells SPELL_RESTORE_SOUL = 72595, SPELL_RESTORE_SOULS = 73650, // Heroic SPELL_DARK_HUNGER = 69383, // Passive proc healing + SPELL_DARK_HUNGER_HEAL = 69384, SPELL_DESTROY_SOUL = 74086, // Used when Terenas Menethil dies SPELL_SOUL_RIP = 69397, // Deals increasing damage SPELL_SOUL_RIP_DAMAGE = 69398, @@ -3008,6 +3009,41 @@ class spell_the_lich_king_restore_soul : public SpellScriptLoader } }; +class spell_the_lich_king_dark_hunger : public SpellScriptLoader +{ + public: + spell_the_lich_king_dark_hunger() : SpellScriptLoader("spell_the_lich_king_dark_hunger") { } + + class spell_the_lich_king_dark_hunger_AuraScript : public AuraScript + { + PrepareAuraScript(spell_the_lich_king_dark_hunger_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DARK_HUNGER_HEAL)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 heal = int32(eventInfo.GetDamageInfo()->GetDamage() / 2); + GetTarget()->CastCustomSpell(SPELL_DARK_HUNGER_HEAL, SPELLVALUE_BASE_POINT0, heal, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_the_lich_king_dark_hunger_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_the_lich_king_dark_hunger_AuraScript(); + } +}; + class spell_the_lich_king_in_frostmourne_room : public SpellScriptLoader { public: @@ -3253,6 +3289,7 @@ void AddSC_boss_the_lich_king() new spell_the_lich_king_lights_favor(); new spell_the_lich_king_soul_rip(); new spell_the_lich_king_restore_soul(); + new spell_the_lich_king_dark_hunger(); new spell_the_lich_king_in_frostmourne_room(); new spell_the_lich_king_summon_spirit_bomb(); new spell_the_lich_king_trigger_vile_spirit(); diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 62a0599dab1..73c34d42538 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -31,6 +31,7 @@ enum DeathKnightSpells SPELL_DK_ANTI_MAGIC_SHELL_TALENT = 51052, SPELL_DK_BLACK_ICE_R1 = 49140, SPELL_DK_BLOOD_BOIL_TRIGGERED = 65658, + SPELL_DK_BLOOD_GORGED_HEAL = 50454, SPELL_DK_CORPSE_EXPLOSION_TRIGGERED = 43999, SPELL_DK_CORPSE_EXPLOSION_VISUAL = 51270, SPELL_DK_DEATH_COIL_DAMAGE = 47632, @@ -252,6 +253,58 @@ class spell_dk_blood_boil : public SpellScriptLoader } }; +// 50453 - Bloodworms Health Leech +class spell_dk_blood_gorged : public SpellScriptLoader +{ + public: + spell_dk_blood_gorged() : SpellScriptLoader("spell_dk_blood_gorged") { } + + class spell_dk_blood_gorged_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_blood_gorged_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_BLOOD_GORGED_HEAL)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _procTarget = GetTarget()->GetOwner(); + return _procTarget; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 bp = int32(eventInfo.GetDamageInfo()->GetDamage() * 1.5f); + GetTarget()->CastCustomSpell(SPELL_DK_BLOOD_GORGED_HEAL, SPELLVALUE_BASE_POINT0, bp, _procTarget, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_dk_blood_gorged_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dk_blood_gorged_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_blood_gorged_AuraScript(); + } +}; + // 49158 - Corpse Explosion (51325, 51326, 51327, 51328) class spell_dk_corpse_explosion : public SpellScriptLoader { @@ -958,6 +1011,7 @@ void AddSC_deathknight_spell_scripts() new spell_dk_anti_magic_shell_self(); new spell_dk_anti_magic_zone(); new spell_dk_blood_boil(); + new spell_dk_blood_gorged(); new spell_dk_corpse_explosion(); new spell_dk_death_coil(); new spell_dk_death_gate(); diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index e2b918e1c7f..160f14ff670 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -37,6 +37,8 @@ enum DruidSpells SPELL_DRUID_KING_OF_THE_JUNGLE = 48492, SPELL_DRUID_LIFEBLOOM_ENERGIZE = 64372, SPELL_DRUID_LIFEBLOOM_FINAL_HEAL = 33778, + SPELL_DRUID_LIVING_SEED_HEAL = 48503, + SPELL_DRUID_LIVING_SEED_PROC = 48504, SPELL_DRUID_NATURES_SPLENDOR = 57865, SPELL_DRUID_SURVIVAL_INSTINCTS = 50322, SPELL_DRUID_SAVAGE_ROAR = 62071, @@ -327,6 +329,77 @@ class spell_dru_lifebloom : public SpellScriptLoader } }; +// -48496 - Living Seed +class spell_dru_living_seed : public SpellScriptLoader +{ + public: + spell_dru_living_seed() : SpellScriptLoader("spell_dru_living_seed") { } + + class spell_dru_living_seed_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_living_seed_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_LIVING_SEED_PROC)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 amount = CalculatePct(eventInfo.GetHealInfo()->GetHeal(), aurEff->GetAmount()); + GetTarget()->CastCustomSpell(SPELL_DRUID_LIVING_SEED_PROC, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_dru_living_seed_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_living_seed_AuraScript(); + } +}; + +// 48504 - Living Seed (Proc) +class spell_dru_living_seed_proc : public SpellScriptLoader +{ + public: + spell_dru_living_seed_proc() : SpellScriptLoader("spell_dru_living_seed_proc") { } + + class spell_dru_living_seed_proc_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_living_seed_proc_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_LIVING_SEED_HEAL)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastCustomSpell(SPELL_DRUID_LIVING_SEED_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_dru_living_seed_proc_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_living_seed_proc_AuraScript(); + } +}; + // 69366 - Moonkin Form passive class spell_dru_moonkin_form_passive : public SpellScriptLoader { @@ -921,6 +994,8 @@ void AddSC_druid_spell_scripts() new spell_dru_innervate(); new spell_dru_insect_swarm(); new spell_dru_lifebloom(); + new spell_dru_living_seed(); + new spell_dru_living_seed_proc(); new spell_dru_moonkin_form_passive(); new spell_dru_owlkin_frenzy(); new spell_dru_predatory_strikes(); diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 6004ec6cf89..05fad623114 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -72,6 +72,97 @@ class spell_gen_absorb0_hitlimit1 : public SpellScriptLoader } }; +// 28764 - Adaptive Warding (Frostfire Regalia Set) +enum AdaptiveWarding +{ + SPELL_GEN_ADAPTIVE_WARDING_FIRE = 28765, + SPELL_GEN_ADAPTIVE_WARDING_NATURE = 28768, + SPELL_GEN_ADAPTIVE_WARDING_FROST = 28766, + SPELL_GEN_ADAPTIVE_WARDING_SHADOW = 28769, + SPELL_GEN_ADAPTIVE_WARDING_ARCANE = 28770 +}; + +class spell_gen_adaptive_warding : public SpellScriptLoader +{ + public: + spell_gen_adaptive_warding() : SpellScriptLoader("spell_gen_adaptive_warding") { } + + class spell_gen_adaptive_warding_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_adaptive_warding_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_GEN_ADAPTIVE_WARDING_FIRE) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_ADAPTIVE_WARDING_NATURE) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_ADAPTIVE_WARDING_FROST) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_ADAPTIVE_WARDING_SHADOW) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_ADAPTIVE_WARDING_ARCANE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetDamageInfo()->GetSpellInfo()) // eventInfo.GetSpellInfo() + return false; + + // find Mage Armor + if (!GetTarget()->GetAuraEffect(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT, SPELLFAMILY_MAGE, 0x10000000, 0x0, 0x0)) + return false; + + switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask())) + { + case SPELL_SCHOOL_NORMAL: + case SPELL_SCHOOL_HOLY: + return false; + default: + break; + } + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + uint32 spellId = 0; + switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask())) + { + case SPELL_SCHOOL_FIRE: + spellId = SPELL_GEN_ADAPTIVE_WARDING_FIRE; + break; + case SPELL_SCHOOL_NATURE: + spellId = SPELL_GEN_ADAPTIVE_WARDING_NATURE; + break; + case SPELL_SCHOOL_FROST: + spellId = SPELL_GEN_ADAPTIVE_WARDING_FROST; + break; + case SPELL_SCHOOL_SHADOW: + spellId = SPELL_GEN_ADAPTIVE_WARDING_SHADOW; + break; + case SPELL_SCHOOL_ARCANE: + spellId = SPELL_GEN_ADAPTIVE_WARDING_ARCANE; + break; + default: + return; + } + GetTarget()->CastSpell(GetTarget(), spellId, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_gen_adaptive_warding_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_gen_adaptive_warding_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_adaptive_warding_AuraScript(); + } +}; + // 41337 Aura of Anger class spell_gen_aura_of_anger : public SpellScriptLoader { @@ -378,6 +469,93 @@ class spell_gen_nightmare_vine : public SpellScriptLoader } }; +// 27539 - Obsidian Armor +enum ObsidianArmor +{ + SPELL_GEN_OBSIDIAN_ARMOR_HOLY = 27536, + SPELL_GEN_OBSIDIAN_ARMOR_FIRE = 27533, + SPELL_GEN_OBSIDIAN_ARMOR_NATURE = 27538, + SPELL_GEN_OBSIDIAN_ARMOR_FROST = 27534, + SPELL_GEN_OBSIDIAN_ARMOR_SHADOW = 27535, + SPELL_GEN_OBSIDIAN_ARMOR_ARCANE = 27540 +}; + +class spell_gen_obsidian_armor : public SpellScriptLoader +{ + public: + spell_gen_obsidian_armor() : SpellScriptLoader("spell_gen_obsidian_armor") { } + + class spell_gen_obsidian_armor_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_obsidian_armor_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_HOLY) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_FIRE) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_NATURE) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_FROST) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_SHADOW) || + !sSpellMgr->GetSpellInfo(SPELL_GEN_OBSIDIAN_ARMOR_ARCANE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetDamageInfo()->GetSpellInfo()) // eventInfo.GetSpellInfo() + return false; + + if (GetFirstSchoolInMask(eventInfo.GetSchoolMask()) == SPELL_SCHOOL_NORMAL) + return false; + + return true; + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + uint32 spellId = 0; + switch (GetFirstSchoolInMask(eventInfo.GetSchoolMask())) + { + case SPELL_SCHOOL_HOLY: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_HOLY; + break; + case SPELL_SCHOOL_FIRE: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_FIRE; + break; + case SPELL_SCHOOL_NATURE: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_NATURE; + break; + case SPELL_SCHOOL_FROST: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_FROST; + break; + case SPELL_SCHOOL_SHADOW: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_SHADOW; + break; + case SPELL_SCHOOL_ARCANE: + spellId = SPELL_GEN_OBSIDIAN_ARMOR_ARCANE; + break; + default: + return; + } + GetTarget()->CastSpell(GetTarget(), spellId, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_gen_obsidian_armor_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_gen_obsidian_armor_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_obsidian_armor_AuraScript(); + } +}; + // 45472 Parachute enum ParachuteSpells { @@ -3343,6 +3521,7 @@ class spell_gen_replenishment : public SpellScriptLoader void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); + new spell_gen_adaptive_warding(); new spell_gen_aura_of_anger(); new spell_gen_av_drekthar_presence(); new spell_gen_burn_brutallus(); @@ -3350,6 +3529,7 @@ void AddSC_generic_spell_scripts() new spell_gen_create_lance(); new spell_gen_netherbloom(); new spell_gen_nightmare_vine(); + new spell_gen_obsidian_armor(); new spell_gen_parachute(); new spell_gen_pet_summoned(); new spell_gen_remove_flight_auras(); diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index a9b21807899..877248cf1a8 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -33,12 +33,15 @@ enum HunterSpells { SPELL_HUNTER_ASPECT_OF_THE_BEAST_PET = 61669, + SPELL_HUNTER_ASPECT_OF_THE_VIPER_ENERGIZE = 34075, SPELL_HUNTER_BESTIAL_WRATH = 19574, SPELL_HUNTER_CHIMERA_SHOT_SERPENT = 53353, SPELL_HUNTER_CHIMERA_SHOT_VIPER = 53358, SPELL_HUNTER_CHIMERA_SHOT_SCORPID = 53359, + SPELL_HUNTER_GLYPHE_OF_ASPECT_OF_THE_VIPER = 56851, SPELL_HUNTER_INVIGORATION_TRIGGERED = 53398, SPELL_HUNTER_MASTERS_CALL_TRIGGERED = 62305, + SPELL_HUNTER_MISDIRECTION_PROC = 35079, SPELL_HUNTER_PET_LAST_STAND_TRIGGERED = 53479, SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX = 55709, SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_TRIGGERED = 54114, @@ -99,6 +102,50 @@ class spell_hun_aspect_of_the_beast : public SpellScriptLoader } }; +// 34074 - Aspect of the Viper +class spell_hun_ascpect_of_the_viper : public SpellScriptLoader +{ + public: + spell_hun_ascpect_of_the_viper() : SpellScriptLoader("spell_hun_ascpect_of_the_viper") { } + + class spell_hun_ascpect_of_the_viper_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_ascpect_of_the_viper_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_ASPECT_OF_THE_VIPER_ENERGIZE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_GLYPHE_OF_ASPECT_OF_THE_VIPER)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + + uint32 maxMana = GetTarget()->GetMaxPower(POWER_MANA); + int32 mana = CalculatePct(maxMana, GetTarget()->GetAttackTime(RANGED_ATTACK) / 1000.0f); + + if (AuraEffect const* glyphe = GetTarget()->GetAuraEffect(SPELL_HUNTER_GLYPHE_OF_ASPECT_OF_THE_VIPER, EFFECT_0)) + AddPct(mana, glyphe->GetAmount()); + + GetTarget()->CastCustomSpell(SPELL_HUNTER_ASPECT_OF_THE_VIPER_ENERGIZE, SPELLVALUE_BASE_POINT0, mana, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_hun_ascpect_of_the_viper_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_OBS_MOD_POWER); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_ascpect_of_the_viper_AuraScript(); + } +}; + // 53209 - Chimera Shot class spell_hun_chimera_shot : public SpellScriptLoader { @@ -358,16 +405,35 @@ class spell_hun_misdirection : public SpellScriptLoader { PrepareAuraScript(spell_hun_misdirection_AuraScript); + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_MISDIRECTION_PROC)) + return false; + return true; + } + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (Unit* caster = GetCaster()) - if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEFAULT) - caster->SetReducedThreatPercent(0, 0); + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEFAULT) + GetTarget()->ResetRedirectThreat(); + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + return GetTarget()->GetRedirectThreatTarget(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(GetTarget(), SPELL_HUNTER_MISDIRECTION_PROC, true, NULL, aurEff); } void Register() { AfterEffectRemove += AuraEffectRemoveFn(spell_hun_misdirection_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + DoCheckProc += AuraCheckProcFn(spell_hun_misdirection_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_hun_misdirection_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_DUMMY); } }; @@ -377,7 +443,7 @@ class spell_hun_misdirection : public SpellScriptLoader } }; -// 35079 - Misdirection proc +// 35079 - Misdirection (Proc) class spell_hun_misdirection_proc : public SpellScriptLoader { public: @@ -389,8 +455,7 @@ class spell_hun_misdirection_proc : public SpellScriptLoader void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (GetCaster()) - GetCaster()->SetReducedThreatPercent(0, 0); + GetTarget()->ResetRedirectThreat(); } void Register() @@ -740,6 +805,7 @@ class spell_hun_target_only_pet_and_owner : public SpellScriptLoader void AddSC_hunter_spell_scripts() { new spell_hun_aspect_of_the_beast(); + new spell_hun_ascpect_of_the_viper(); new spell_hun_chimera_shot(); new spell_hun_disengage(); new spell_hun_invigoration(); diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index c38d05bc02a..b8e17f4ecca 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -102,6 +102,63 @@ class spell_item_arcane_shroud : public SpellScriptLoader } }; +// 64411 - Blessing of Ancient Kings (Val'anyr, Hammer of Ancient Kings) +enum BlessingOfAncientKings +{ + SPELL_PROTECTION_OF_ANCIENT_KINGS = 64413 +}; + +class spell_item_blessing_of_ancient_kings : public SpellScriptLoader +{ + public: + spell_item_blessing_of_ancient_kings() : SpellScriptLoader("spell_item_blessing_of_ancient_kings") { } + + class spell_item_blessing_of_ancient_kings_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_blessing_of_ancient_kings_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PROTECTION_OF_ANCIENT_KINGS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetProcTarget(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 absorb = int32(CalculatePct(eventInfo.GetHealInfo()->GetHeal(), 15.0f)); + if (AuraEffect* protEff = eventInfo.GetProcTarget()->GetAuraEffect(SPELL_PROTECTION_OF_ANCIENT_KINGS, 0, eventInfo.GetActor()->GetGUID())) + { + // The shield can grow to a maximum size of 20,000 damage absorbtion + protEff->SetAmount(std::min(protEff->GetAmount() + absorb, 20000)); + + // Refresh and return to prevent replacing the aura + aurEff->GetBase()->RefreshDuration(); + } + else + GetTarget()->CastCustomSpell(SPELL_PROTECTION_OF_ANCIENT_KINGS, SPELLVALUE_BASE_POINT0, absorb, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_item_blessing_of_ancient_kings_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_item_blessing_of_ancient_kings_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_blessing_of_ancient_kings_AuraScript(); + } +}; + // 8342 - Defibrillate (Goblin Jumper Cables) have 33% chance on success // 22999 - Defibrillate (Goblin Jumper Cables XL) have 50% chance on success // 54732 - Defibrillate (Gnomish Army Knife) have 67% chance on success @@ -444,6 +501,47 @@ class spell_item_mingos_fortune_generator : public SpellScriptLoader } }; +// 71875, 71877 - Item - Black Bruise: Necrotic Touch Proc +enum NecroticTouch +{ + SPELL_ITEM_NECROTIC_TOUCH_PROC = 71879 +}; + +class spell_item_necrotic_touch : public SpellScriptLoader +{ + public: + spell_item_necrotic_touch() : SpellScriptLoader("spell_item_necrotic_touch") { } + + class spell_item_necrotic_touch_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_necrotic_touch_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ITEM_NECROTIC_TOUCH_PROC)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 bp = CalculatePct(int32(eventInfo.GetDamageInfo()->GetDamage()), aurEff->GetAmount()); + GetTarget()->CastCustomSpell(SPELL_ITEM_NECROTIC_TOUCH_PROC, SPELLVALUE_BASE_POINT0, bp, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_item_necrotic_touch_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_necrotic_touch_AuraScript(); + } +}; + // http://www.wowhead.com/item=10720 Gnomish Net-o-Matic Projector // 13120 Net-o-Matic enum NetOMaticSpells @@ -711,6 +809,189 @@ class spell_item_scroll_of_recall : public SpellScriptLoader } }; +// 71169 - Shadow's Fate (Shadowmourne questline) +enum ShadowsFate +{ + SPELL_SOUL_FEAST = 71203, + QUEST_A_FEAST_OF_SOULS = 24547 +}; + +class spell_item_shadows_fate : public SpellScriptLoader +{ + public: + spell_item_shadows_fate() : SpellScriptLoader("spell_item_shadows_fate") { } + + class spell_item_shadows_fate_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_shadows_fate_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SOUL_FEAST)) + return false; + if (!sObjectMgr->GetQuestTemplate(QUEST_A_FEAST_OF_SOULS)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _procTarget = GetCaster(); + return _procTarget && _procTarget->GetTypeId() == TYPEID_PLAYER && _procTarget->ToPlayer()->GetQuestStatus(QUEST_A_FEAST_OF_SOULS) == QUEST_STATUS_INCOMPLETE; + } + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(_procTarget, SPELL_SOUL_FEAST, true); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_item_shadows_fate_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_item_shadows_fate_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_shadows_fate_AuraScript(); + } +}; + +enum Shadowmourne +{ + SPELL_SHADOWMOURNE_CHAOS_BANE_DAMAGE = 71904, + SPELL_SHADOWMOURNE_SOUL_FRAGMENT = 71905, + SPELL_SHADOWMOURNE_VISUAL_LOW = 72521, + SPELL_SHADOWMOURNE_VISUAL_HIGH = 72523, + SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF = 73422, +}; + +// 71903 - Item - Shadowmourne Legendary +class spell_item_shadowmourne : public SpellScriptLoader +{ + public: + spell_item_shadowmourne() : SpellScriptLoader("spell_item_shadowmourne") { } + + class spell_item_shadowmourne_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_shadowmourne_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_CHAOS_BANE_DAMAGE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_SOUL_FRAGMENT)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (GetTarget()->HasAura(SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF)) // cant collect shards while under effect of Chaos Bane buff + return false; + return eventInfo.GetProcTarget() && eventInfo.GetProcTarget()->isAlive(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + GetTarget()->CastSpell(GetTarget(), SPELL_SHADOWMOURNE_SOUL_FRAGMENT, true, NULL, aurEff); + + // this can't be handled in AuraScript of SoulFragments because we need to know victim + if (Aura* soulFragments = GetTarget()->GetAura(SPELL_SHADOWMOURNE_SOUL_FRAGMENT)) + { + if (soulFragments->GetStackAmount() >= 10) + { + GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_SHADOWMOURNE_CHAOS_BANE_DAMAGE, true, NULL, aurEff); + soulFragments->Remove(); + } + } + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_item_shadowmourne_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_item_shadowmourne_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_shadowmourne_AuraScript(); + } +}; + +// 71905 - Soul Fragment +class spell_item_shadowmourne_soul_fragment : public SpellScriptLoader +{ + public: + spell_item_shadowmourne_soul_fragment() : SpellScriptLoader("spell_item_shadowmourne_soul_fragment") { } + + class spell_item_shadowmourne_soul_fragment_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_shadowmourne_soul_fragment_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_VISUAL_LOW) || !sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_VISUAL_HIGH) || !sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF)) + return false; + return true; + } + + void OnStackChange(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + switch (GetStackAmount()) + { + case 1: + target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_LOW, true); + break; + case 6: + target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW); + target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_HIGH, true); + break; + case 10: + target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH); + target->CastSpell(target, SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF, true); + break; + default: + break; + } + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW); + target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_item_shadowmourne_soul_fragment_AuraScript::OnStackChange, EFFECT_0, SPELL_AURA_MOD_STAT, AuraEffectHandleModes(AURA_EFFECT_HANDLE_REAL | AURA_EFFECT_HANDLE_REAPPLY)); + AfterEffectRemove += AuraEffectRemoveFn(spell_item_shadowmourne_soul_fragment_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_item_shadowmourne_soul_fragment_AuraScript(); + } +}; + // http://www.wowhead.com/item=7734 Six Demon Bag // 14537 Six Demon Bag enum SixDemonBagSpells @@ -864,70 +1145,6 @@ class spell_item_underbelly_elixir : public SpellScriptLoader } }; -enum eShadowmourneVisuals -{ - SPELL_SHADOWMOURNE_VISUAL_LOW = 72521, - SPELL_SHADOWMOURNE_VISUAL_HIGH = 72523, - SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF = 73422, -}; - -class spell_item_shadowmourne : public SpellScriptLoader -{ -public: - spell_item_shadowmourne() : SpellScriptLoader("spell_item_shadowmourne") { } - - class spell_item_shadowmourne_AuraScript : public AuraScript - { - PrepareAuraScript(spell_item_shadowmourne_AuraScript); - - bool Validate(SpellInfo const* /*spellEntry*/) - { - if (!sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_VISUAL_LOW) || !sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_VISUAL_HIGH) || !sSpellMgr->GetSpellInfo(SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF)) - return false; - return true; - } - - void OnStackChange(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* target = GetTarget(); - switch (GetStackAmount()) - { - case 1: - target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_LOW, true); - break; - case 6: - target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW); - target->CastSpell(target, SPELL_SHADOWMOURNE_VISUAL_HIGH, true); - break; - case 10: - target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH); - target->CastSpell(target, SPELL_SHADOWMOURNE_CHAOS_BANE_BUFF, true); - break; - default: - break; - } - } - - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - Unit* target = GetTarget(); - target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_LOW); - target->RemoveAurasDueToSpell(SPELL_SHADOWMOURNE_VISUAL_HIGH); - } - - void Register() - { - AfterEffectApply += AuraEffectApplyFn(spell_item_shadowmourne_AuraScript::OnStackChange, EFFECT_0, SPELL_AURA_MOD_STAT, AuraEffectHandleModes(AURA_EFFECT_HANDLE_REAL | AURA_EFFECT_HANDLE_REAPPLY)); - AfterEffectRemove += AuraEffectRemoveFn(spell_item_shadowmourne_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const - { - return new spell_item_shadowmourne_AuraScript(); - } -}; - enum AirRifleSpells { SPELL_AIR_RIFLE_HOLD_VISUAL = 65582, @@ -2249,6 +2466,7 @@ void AddSC_item_spell_scripts() new spell_item_trigger_spell("spell_item_mithril_mechanical_dragonling", SPELL_MITHRIL_MECHANICAL_DRAGONLING); new spell_item_arcane_shroud(); + new spell_item_blessing_of_ancient_kings(); new spell_item_defibrillate("spell_item_goblin_jumper_cables", 67, SPELL_GOBLIN_JUMPER_CABLES_FAIL); new spell_item_defibrillate("spell_item_goblin_jumper_cables_xl", 50, SPELL_GOBLIN_JUMPER_CABLES_XL_FAIL); new spell_item_defibrillate("spell_item_gnomish_army_knife", 33); @@ -2257,15 +2475,18 @@ void AddSC_item_spell_scripts() new spell_item_gnomish_death_ray(); new spell_item_make_a_wish(); new spell_item_mingos_fortune_generator(); + new spell_item_necrotic_touch(); new spell_item_net_o_matic(); new spell_item_noggenfogger_elixir(); new spell_item_piccolo_of_the_flaming_fire(); new spell_item_savory_deviate_delight(); new spell_item_scroll_of_recall(); + new spell_item_shadows_fate(); + new spell_item_shadowmourne(); + new spell_item_shadowmourne_soul_fragment(); new spell_item_six_demon_bag(); new spell_item_the_eye_of_diminution(); new spell_item_underbelly_elixir(); - new spell_item_shadowmourne(); new spell_item_red_rider_air_rifle(); new spell_item_create_heart_candy(); diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index a673759a49e..ca835c61a3a 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -28,11 +28,15 @@ enum MageSpells { + SPELL_MAGE_BURNOUT = 29077, SPELL_MAGE_COLD_SNAP = 11958, + SPELL_MAGE_FOCUS_MAGIC_PROC = 54648, SPELL_MAGE_FROST_WARDING_R1 = 11189, SPELL_MAGE_FROST_WARDING_TRIGGERED = 57776, SPELL_MAGE_INCANTERS_ABSORBTION_R1 = 44394, SPELL_MAGE_INCANTERS_ABSORBTION_TRIGGERED = 44413, + SPELL_MAGE_IGNITE = 12654, + SPELL_MAGE_MASTER_OF_ELEMENTS_ENERGIZE = 29077, SPELL_MAGE_SQUIRREL_FORM = 32813, SPELL_MAGE_GIRAFFE_FORM = 32816, SPELL_MAGE_SERPENT_FORM = 32817, @@ -105,6 +109,51 @@ class spell_mage_blast_wave : public SpellScriptLoader } }; +// -44449 - Burnout +class spell_mage_burnout : public SpellScriptLoader +{ + public: + spell_mage_burnout() : SpellScriptLoader("spell_mage_burnout") { } + + class spell_mage_burnout_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mage_burnout_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_BURNOUT)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetDamageInfo()->GetSpellInfo(); // eventInfo.GetSpellInfo() + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 mana = int32(eventInfo.GetDamageInfo()->GetSpellInfo()->CalcPowerCost(GetTarget(), eventInfo.GetDamageInfo()->GetSchoolMask())); + mana = CalculatePct(mana, aurEff->GetAmount()); + + GetTarget()->CastCustomSpell(SPELL_MAGE_BURNOUT, SPELLVALUE_BASE_POINT0, mana, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_mage_burnout_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_mage_burnout_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_mage_burnout_AuraScript(); + } +}; + // 11958 - Cold Snap class spell_mage_cold_snap : public SpellScriptLoader { @@ -219,6 +268,57 @@ class spell_mage_fire_frost_ward : public SpellScriptLoader } }; +// 54646 - Focus Magic +class spell_mage_focus_magic : public SpellScriptLoader +{ + public: + spell_mage_focus_magic() : SpellScriptLoader("spell_mage_focus_magic") { } + + class spell_mage_focus_magic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mage_focus_magic_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_FOCUS_MAGIC_PROC)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _procTarget = GetCaster(); + return _procTarget && _procTarget->isAlive(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(_procTarget, SPELL_MAGE_FOCUS_MAGIC_PROC, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_mage_focus_magic_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_mage_focus_magic_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_mage_focus_magic_AuraScript(); + } +}; + // -11426 - Ice Barrier class spell_mage_ice_barrier : public SpellScriptLoader { @@ -262,6 +362,53 @@ class spell_mage_ice_barrier : public SpellScriptLoader } }; +// -11119 - Ignite +class spell_mage_ignite : public SpellScriptLoader +{ + public: + spell_mage_ignite() : SpellScriptLoader("spell_mage_ignite") { } + + class spell_mage_ignite_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mage_ignite_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_IGNITE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetProcTarget(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + SpellInfo const* igniteDot = sSpellMgr->GetSpellInfo(SPELL_MAGE_IGNITE); + int32 pct = 8 * GetSpellInfo()->GetRank(); + + int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), pct) / igniteDot->GetMaxTicks()); + amount += eventInfo.GetProcTarget()->GetRemainingPeriodicAmount(eventInfo.GetActor()->GetGUID(), SPELL_MAGE_IGNITE, SPELL_AURA_PERIODIC_DAMAGE); + GetTarget()->CastCustomSpell(SPELL_MAGE_IGNITE, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_mage_ignite_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_mage_ignite_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_mage_ignite_AuraScript(); + } +}; + // -44457 - Living Bomb class spell_mage_living_bomb : public SpellScriptLoader { @@ -339,6 +486,52 @@ class spell_mage_mana_shield : public SpellScriptLoader } }; +// -29074 - Master of Elements +class spell_mage_master_of_elements : public SpellScriptLoader +{ + public: + spell_mage_master_of_elements() : SpellScriptLoader("spell_mage_master_of_elements") { } + + class spell_mage_master_of_elements_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mage_master_of_elements_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_MASTER_OF_ELEMENTS_ENERGIZE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetDamageInfo()->GetSpellInfo(); // eventInfo.GetSpellInfo() + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 mana = int32(eventInfo.GetDamageInfo()->GetSpellInfo()->CalcPowerCost(GetTarget(), eventInfo.GetDamageInfo()->GetSchoolMask())); + mana = CalculatePct(mana, aurEff->GetAmount()); + + if (mana > 0) + GetTarget()->CastCustomSpell(SPELL_MAGE_MASTER_OF_ELEMENTS_ENERGIZE, SPELLVALUE_BASE_POINT0, mana, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_mage_master_of_elements_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_mage_master_of_elements_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_mage_master_of_elements_AuraScript(); + } +}; + enum SilvermoonPolymorph { NPC_AUROSALIA = 18744, @@ -437,11 +630,15 @@ class spell_mage_summon_water_elemental : public SpellScriptLoader void AddSC_mage_spell_scripts() { new spell_mage_blast_wave(); + new spell_mage_burnout(); new spell_mage_cold_snap(); new spell_mage_fire_frost_ward(); + new spell_mage_focus_magic(); new spell_mage_ice_barrier(); + new spell_mage_ignite(); new spell_mage_living_bomb(); new spell_mage_mana_shield(); + new spell_mage_master_of_elements(); new spell_mage_polymorph_cast_visual(); new spell_mage_summon_water_elemental(); } diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index 2f22de97d77..6be2453affb 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -31,6 +31,7 @@ enum PaladinSpells { SPELL_PALADIN_DIVINE_PLEA = 54428, SPELL_PALADIN_BLESSING_OF_SANCTUARY_BUFF = 67480, + SPELL_PALADIN_BLESSING_OF_SANCTUARY_ENERGIZE = 57319, SPELL_PALADIN_HOLY_SHOCK_R1 = 20473, SPELL_PALADIN_HOLY_SHOCK_R1_DAMAGE = 25912, @@ -45,6 +46,8 @@ enum PaladinSpells SPELL_PALADIN_DIVINE_STORM_DUMMY = 54171, SPELL_PALADIN_DIVINE_STORM_HEAL = 54172, + SPELL_PALADIN_EYE_FOR_AN_EYE_DAMAGE = 25997, + SPELL_PALADIN_FORBEARANCE = 25771, SPELL_PALADIN_AVENGING_WRATH_MARKER = 61987, SPELL_PALADIN_IMMUNE_SHIELD_MARKER = 61988, @@ -56,6 +59,8 @@ enum PaladinSpells SPELL_PALADIN_RIGHTEOUS_DEFENSE_TAUNT = 31790, + SPELL_PALADIN_SEAL_OF_RIGHTEOUSNESS = 25742, + SPELL_GENERIC_ARENA_DAMPENING = 74410, SPELL_GENERIC_BATTLEGROUND_DAMPENING = 74411 }; @@ -192,8 +197,8 @@ class spell_pal_blessing_of_faith : public SpellScriptLoader } }; -// 20911 Blessing of Sanctuary -// 25899 Greater Blessing of Sanctuary +// 20911 - Blessing of Sanctuary +// 25899 - Greater Blessing of Sanctuary class spell_pal_blessing_of_sanctuary : public SpellScriptLoader { public: @@ -207,6 +212,8 @@ class spell_pal_blessing_of_sanctuary : public SpellScriptLoader { if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_BLESSING_OF_SANCTUARY_BUFF)) return false; + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_BLESSING_OF_SANCTUARY_ENERGIZE)) + return false; return true; } @@ -223,10 +230,23 @@ class spell_pal_blessing_of_sanctuary : public SpellScriptLoader target->RemoveAura(SPELL_PALADIN_BLESSING_OF_SANCTUARY_BUFF, GetCasterGUID()); } + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + return GetTarget()->getPowerType() == POWER_MANA; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(GetTarget(), SPELL_PALADIN_BLESSING_OF_SANCTUARY_ENERGIZE, true, NULL, aurEff); + } + void Register() { AfterEffectApply += AuraEffectApplyFn(spell_pal_blessing_of_sanctuary_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); AfterEffectRemove += AuraEffectRemoveFn(spell_pal_blessing_of_sanctuary_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + DoCheckProc += AuraCheckProcFn(spell_pal_blessing_of_sanctuary_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_pal_blessing_of_sanctuary_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); } }; @@ -417,6 +437,43 @@ class spell_pal_exorcism_and_holy_wrath_damage : public SpellScriptLoader } }; +// -9799 - Eye for an Eye +class spell_pal_eye_for_an_eye : public SpellScriptLoader +{ + public: + spell_pal_eye_for_an_eye() : SpellScriptLoader("spell_pal_eye_for_an_eye") { } + + class spell_pal_eye_for_an_eye_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_eye_for_an_eye_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_EYE_FOR_AN_EYE_DAMAGE)) + return false; + return true; + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + // return damage % to attacker but < 50% own total health + int32 damage = int32(std::min(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()), GetTarget()->GetMaxHealth() / 2)); + GetTarget()->CastCustomSpell(SPELL_PALADIN_EYE_FOR_AN_EYE_DAMAGE, SPELLVALUE_BASE_POINT0, damage, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_pal_eye_for_an_eye_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pal_eye_for_an_eye_AuraScript(); + } +}; + // 63521 - Guarded by The Light class spell_pal_guarded_by_the_light : public SpellScriptLoader { @@ -794,6 +851,52 @@ class spell_pal_sacred_shield : public SpellScriptLoader } }; +// 20154, 21084 - Seal of Righteousness - melee proc dummy (addition ${$MWS*(0.022*$AP+0.044*$SPH)} damage) +class spell_pal_seal_of_righteousness : public SpellScriptLoader +{ + public: + spell_pal_seal_of_righteousness() : SpellScriptLoader("spell_pal_seal_of_righteousness") { } + + class spell_pal_seal_of_righteousness_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_seal_of_righteousness_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_SEAL_OF_RIGHTEOUSNESS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetProcTarget(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + float ap = GetTarget()->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = GetTarget()->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_HOLY); + holy += eventInfo.GetProcTarget()->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_HOLY); + int32 bp = int32((ap * 0.022f + 0.044f * holy) * GetTarget()->GetAttackTime(BASE_ATTACK) / 1000); + GetTarget()->CastCustomSpell(SPELL_PALADIN_SEAL_OF_RIGHTEOUSNESS, SPELLVALUE_BASE_POINT0, bp, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_pal_seal_of_righteousness_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_pal_seal_of_righteousness_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pal_seal_of_righteousness_AuraScript(); + } +}; + void AddSC_paladin_spell_scripts() { new spell_pal_ardent_defender(); @@ -803,6 +906,7 @@ void AddSC_paladin_spell_scripts() new spell_pal_divine_storm(); new spell_pal_divine_storm_dummy(); new spell_pal_exorcism_and_holy_wrath_damage(); + new spell_pal_eye_for_an_eye(); new spell_pal_guarded_by_the_light(); new spell_pal_hand_of_sacrifice(); new spell_pal_hand_of_salvation(); @@ -811,4 +915,5 @@ void AddSC_paladin_spell_scripts() new spell_pal_lay_on_hands(); new spell_pal_righteous_defense(); new spell_pal_sacred_shield(); + new spell_pal_seal_of_righteousness(); } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 23a39819aa2..e19110d0f62 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -29,24 +29,115 @@ enum PriestSpells { - SPELL_PRIEST_EMPOWERED_RENEW = 63544, - SPELL_PRIEST_GLYPHE_OF_LIGHTWELL = 55673, - SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL = 48153, - SPELL_PRIEST_PENANCE_R1 = 47540, - SPELL_PRIEST_PENANCE_R1_DAMAGE = 47758, - SPELL_PRIEST_PENANCE_R1_HEAL = 47757, - SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED = 33619, - SPELL_PRIEST_REFLECTIVE_SHIELD_R1 = 33201, - SPELL_PRIEST_SHADOW_WORD_DEATH = 32409, - SPELL_PRIEST_T9_HEALING_2P = 67201, - SPELL_PRIEST_VAMPIRIC_TOUCH_DISPEL = 64085, + SPELL_PRIEST_DIVINE_AEGIS = 47753, + SPELL_PRIEST_EMPOWERED_RENEW = 63544, + SPELL_PRIEST_GLYPHE_OF_LIGHTWELL = 55673, + SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL = 56161, + SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL = 48153, + SPELL_PRIEST_MANA_LEECH_PROC = 34650, + SPELL_PRIEST_PENANCE_R1 = 47540, + SPELL_PRIEST_PENANCE_R1_DAMAGE = 47758, + SPELL_PRIEST_PENANCE_R1_HEAL = 47757, + SPELL_PRIEST_REFLECTIVE_SHIELD_TRIGGERED = 33619, + SPELL_PRIEST_REFLECTIVE_SHIELD_R1 = 33201, + SPELL_PRIEST_SHADOW_WORD_DEATH = 32409, + SPELL_PRIEST_T9_HEALING_2P = 67201, + SPELL_PRIEST_VAMPIRIC_TOUCH_DISPEL = 64085, }; enum PriestSpellIcons { - PRIEST_ICON_ID_BORROWED_TIME = 2899, - PRIEST_ICON_ID_EMPOWERED_RENEW_TALENT = 3021, - PRIEST_ICON_ID_PAIN_AND_SUFFERING = 2874, + PRIEST_ICON_ID_BORROWED_TIME = 2899, + PRIEST_ICON_ID_EMPOWERED_RENEW_TALENT = 3021, + PRIEST_ICON_ID_PAIN_AND_SUFFERING = 2874, +}; + +// -47509 - Divine Aegis +class spell_pri_divine_aegis : public SpellScriptLoader +{ + public: + spell_pri_divine_aegis() : SpellScriptLoader("spell_pri_divine_aegis") { } + + class spell_pri_divine_aegis_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_divine_aegis_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_DIVINE_AEGIS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetProcTarget(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 absorb = CalculatePct(int32(eventInfo.GetHealInfo()->GetHeal()), aurEff->GetAmount()); + + // Multiple effects stack, so let's try to find this aura. + if (AuraEffect const* aegis = eventInfo.GetProcTarget()->GetAuraEffect(SPELL_PRIEST_DIVINE_AEGIS, EFFECT_0)) + absorb += aegis->GetAmount(); + + absorb = std::min(absorb, eventInfo.GetProcTarget()->getLevel() * 125); + + GetTarget()->CastCustomSpell(SPELL_PRIEST_DIVINE_AEGIS, SPELLVALUE_BASE_POINT0, absorb, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_pri_divine_aegis_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_pri_divine_aegis_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pri_divine_aegis_AuraScript(); + } +}; + +// 55680 - Glyph of Prayer of Healing +class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader +{ + public: + spell_pri_glyph_of_prayer_of_healing() : SpellScriptLoader("spell_pri_glyph_of_prayer_of_healing") { } + + class spell_pri_glyph_of_prayer_of_healing_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_glyph_of_prayer_of_healing_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL); + int32 heal = int32(CalculatePct(int32(eventInfo.GetHealInfo()->GetHeal()), aurEff->GetAmount()) / triggeredSpellInfo->GetMaxTicks()); + GetTarget()->CastCustomSpell(SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL, SPELLVALUE_BASE_POINT0, heal, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_pri_glyph_of_prayer_of_healing_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pri_glyph_of_prayer_of_healing_AuraScript(); + } }; // -47788 - Guardian Spirit @@ -166,6 +257,57 @@ class spell_pri_mana_burn : public SpellScriptLoader } }; +// 28305 - Mana Leech (Passive) (Priest Pet Aura) +class spell_pri_mana_leech : public SpellScriptLoader +{ + public: + spell_pri_mana_leech() : SpellScriptLoader("spell_pri_mana_leech") { } + + class spell_pri_mana_leech_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_mana_leech_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_MANA_LEECH_PROC)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _procTarget = GetTarget()->GetOwner(); + return _procTarget; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(_procTarget, SPELL_PRIEST_MANA_LEECH_PROC, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_pri_mana_leech_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_pri_mana_leech_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_pri_mana_leech_AuraScript(); + } +}; + // -49821 - Mind Sear class spell_pri_mind_sear : public SpellScriptLoader { @@ -524,9 +666,12 @@ class spell_pri_vampiric_touch : public SpellScriptLoader void AddSC_priest_spell_scripts() { + new spell_pri_divine_aegis(); + new spell_pri_glyph_of_prayer_of_healing(); new spell_pri_guardian_spirit(); new spell_pri_lightwell_renew(); new spell_pri_mana_burn(); + new spell_pri_mana_leech(); new spell_pri_mind_sear(); new spell_pri_pain_and_suffering_proc(); new spell_pri_penance(); diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index 156158b4e36..f6391c80d63 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -28,10 +28,68 @@ enum RogueSpells { + SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK = 22482, SPELL_ROGUE_CHEAT_DEATH_COOLDOWN = 31231, SPELL_ROGUE_GLYPH_OF_PREPARATION = 56819, SPELL_ROGUE_PREY_ON_THE_WEAK = 58670, SPELL_ROGUE_SHIV_TRIGGERED = 5940, + SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST = 57933, + SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC = 59628, +}; + +// 13877, 33735, (check 51211, 65956) - Blade Flurry +class spell_rog_blade_flurry : public SpellScriptLoader +{ + public: + spell_rog_blade_flurry() : SpellScriptLoader("spell_rog_blade_flurry") { } + + class spell_rog_blade_flurry_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_blade_flurry_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + _procTarget = eventInfo.GetActor()->SelectNearbyTarget(eventInfo.GetProcTarget()); + return _procTarget; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + if (eventInfo.GetDamageInfo()) + { + int32 damage = eventInfo.GetDamageInfo()->GetDamage(); + GetTarget()->CastCustomSpell(SPELL_ROGUE_BLADE_FLURRY_EXTRA_ATTACK, SPELLVALUE_BASE_POINT0, damage, _procTarget, true, NULL, aurEff); + } + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_rog_blade_flurry_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_rog_blade_flurry_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_MOD_MELEE_HASTE); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_rog_blade_flurry_AuraScript(); + } }; // -31228 - Cheat Death @@ -440,8 +498,100 @@ class spell_rog_shiv : public SpellScriptLoader } }; +// 57934 - Tricks of the Trade +class spell_rog_tricks_of_the_trade : public SpellScriptLoader +{ + public: + spell_rog_tricks_of_the_trade() : SpellScriptLoader("spell_rog_tricks_of_the_trade") { } + + class spell_rog_tricks_of_the_trade_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_tricks_of_the_trade_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC)) + return false; + return true; + } + + bool Load() + { + _redirectTarget = NULL; + return true; + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEFAULT) + GetTarget()->ResetRedirectThreat(); + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _redirectTarget = GetTarget()->GetRedirectThreatTarget(); + return _redirectTarget; + } + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + + Unit* target = GetTarget(); + target->CastSpell(_redirectTarget, SPELL_ROGUE_TRICKS_OF_THE_TRADE_DMG_BOOST, true); + target->CastSpell(target, SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC, true); + Remove(AURA_REMOVE_BY_DEFAULT); // maybe handle by proc charges + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_rog_tricks_of_the_trade_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + DoCheckProc += AuraCheckProcFn(spell_rog_tricks_of_the_trade_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_rog_tricks_of_the_trade_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_DUMMY); + } + + private: + Unit* _redirectTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_rog_tricks_of_the_trade_AuraScript(); + } +}; + +// 59628 - Tricks of the Trade (Proc) +class spell_rog_tricks_of_the_trade_proc : public SpellScriptLoader +{ + public: + spell_rog_tricks_of_the_trade_proc() : SpellScriptLoader("spell_rog_tricks_of_the_trade_proc") { } + + class spell_rog_tricks_of_the_trade_proc_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_tricks_of_the_trade_proc_AuraScript); + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->ResetRedirectThreat(); + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_rog_tricks_of_the_trade_proc_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_rog_tricks_of_the_trade_proc_AuraScript(); + } +}; + void AddSC_rogue_spell_scripts() { + new spell_rog_blade_flurry(); new spell_rog_cheat_death(); new spell_rog_deadly_poison(); new spell_rog_nerves_of_steel(); @@ -449,4 +599,6 @@ void AddSC_rogue_spell_scripts() new spell_rog_prey_on_the_weak(); new spell_rog_rupture(); new spell_rog_shiv(); + new spell_rog_tricks_of_the_trade(); + new spell_rog_tricks_of_the_trade_proc(); } diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index 2994761be6f..b69295150c2 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -33,9 +33,11 @@ enum ShamanSpells SPELL_SHAMAN_ANCESTRAL_AWAKENING_PROC = 52752, SPELL_SHAMAN_BIND_SIGHT = 6277, SPELL_SHAMAN_CLEANSING_TOTEM_EFFECT = 52025, + SPELL_SHAMAN_EARTH_SHIELD_HEAL = 379, SPELL_SHAMAN_EXHAUSTION = 57723, SPELL_SHAMAN_FIRE_NOVA_R1 = 1535, SPELL_SHAMAN_FIRE_NOVA_TRIGGERED_R1 = 8349, + SPELL_SHAMAN_GLYPH_OF_EARTH_SHIELD = 63279, SPELL_SHAMAN_GLYPH_OF_HEALING_STREAM_TOTEM = 55456, SPELL_SHAMAN_GLYPH_OF_MANA_TIDE = 55441, SPELL_SHAMAN_GLYPH_OF_THUNDERSTORM = 62132, @@ -266,6 +268,68 @@ class spell_sha_cleansing_totem_pulse : public SpellScriptLoader } }; +// -974 - Earth Shield +class spell_sha_earth_shield : public SpellScriptLoader +{ + public: + spell_sha_earth_shield() : SpellScriptLoader("spell_sha_earth_shield") { } + + class spell_sha_earth_shield_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_earth_shield_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_EARTH_SHIELD_HEAL)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_GLYPH_OF_EARTH_SHIELD)) + return false; + return true; + } + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool & /*canBeRecalculated*/) + { + if (Unit* caster = GetCaster()) + { + amount = caster->SpellHealingBonusDone(GetUnitOwner(), GetSpellInfo(), amount, HEAL); + amount = GetUnitOwner()->SpellHealingBonusTaken(caster, GetSpellInfo(), amount, HEAL); + + // Glyph of Earth Shield + //! WORKAROUND + //! this glyphe is a proc + if (AuraEffect* glyphe = caster->GetAuraEffect(SPELL_SHAMAN_GLYPH_OF_EARTH_SHIELD, EFFECT_0)) + AddPct(amount, glyphe->GetAmount()); + } + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + + //! HACK due to currenct proc system implementation + if (Player* player = GetTarget()->ToPlayer()) + if (player->HasSpellCooldown(SPELL_SHAMAN_EARTH_SHIELD_HEAL)) + return; + + GetTarget()->CastCustomSpell(SPELL_SHAMAN_EARTH_SHIELD_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), GetTarget(), true, NULL, aurEff, GetCasterGUID()); + + if (Player* player = GetTarget()->ToPlayer()) + player->AddSpellCooldown(SPELL_SHAMAN_EARTH_SHIELD_HEAL, 0, time(NULL) + 3); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_sha_earth_shield_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_DUMMY); + OnEffectProc += AuraEffectProcFn(spell_sha_earth_shield_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_sha_earth_shield_AuraScript(); + } +}; + // 6474 - Earthbind Totem - Fix Talent: Earthen Power class spell_sha_earthbind_totem : public SpellScriptLoader { @@ -780,6 +844,7 @@ void AddSC_shaman_spell_scripts() new spell_sha_bloodlust(); new spell_sha_chain_heal(); new spell_sha_cleansing_totem_pulse(); + new spell_sha_earth_shield(); new spell_sha_earthbind_totem(); new spell_sha_earthen_power(); new spell_sha_fire_nova(); diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 68ad1315dce..78bfcbab6a0 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -37,6 +37,8 @@ enum WarlockSpells SPELL_WARLOCK_DEMONIC_EMPOWERMENT_FELGUARD = 54508, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_FELHUNTER = 54509, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_IMP = 54444, + SPELL_WARLOCK_FEL_SYNERGY_HEAL = 54181, + SPELL_WARLOCK_GLYPHE_OF_SIPHON_LIFE = 63106, SPELL_WARLOCK_IMPROVED_HEALTHSTONE_R1 = 18692, SPELL_WARLOCK_IMPROVED_HEALTHSTONE_R2 = 18693, SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_R1 = 18703, @@ -48,6 +50,7 @@ enum WarlockSpells SPELL_WARLOCK_LIFE_TAP_ENERGIZE = 31818, SPELL_WARLOCK_LIFE_TAP_ENERGIZE_2 = 32553, SPELL_WARLOCK_SOULSHATTER = 32835, + SPELL_WARLOCK_SIPHON_LIFE_HEAL = 63106, SPELL_WARLOCK_UNSTABLE_AFFLICTION_DISPEL = 31117 }; @@ -418,6 +421,49 @@ class spell_warl_everlasting_affliction : public SpellScriptLoader } }; +// -47230 - Fel Synergy +class spell_warl_fel_synergy : public SpellScriptLoader +{ + public: + spell_warl_fel_synergy() : SpellScriptLoader("spell_warl_fel_synergy") { } + + class spell_warl_fel_synergy_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_fel_synergy_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_FEL_SYNERGY_HEAL)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return GetTarget()->GetGuardianPet() && eventInfo.GetDamageInfo()->GetDamage(); + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 heal = CalculatePct(int32(eventInfo.GetDamageInfo()->GetDamage()), aurEff->GetAmount()); + GetTarget()->CastCustomSpell(SPELL_WARLOCK_FEL_SYNERGY_HEAL, SPELLVALUE_BASE_POINT0, heal, (Unit*)NULL, true, NULL, aurEff); // TARGET_UNIT_PET + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_warl_fel_synergy_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warl_fel_synergy_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_fel_synergy_AuraScript(); + } +}; + // -48181 - Haunt class spell_warl_haunt : public SpellScriptLoader { @@ -686,6 +732,55 @@ class spell_warl_shadow_ward : public SpellScriptLoader } }; +// 63108 - Siphon Life +class spell_warl_siphon_life : public SpellScriptLoader +{ + public: + spell_warl_siphon_life() : SpellScriptLoader("spell_warl_siphon_life") { } + + class spell_warl_siphon_life_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_siphon_life_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_SIPHON_LIFE_HEAL)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_GLYPHE_OF_SIPHON_LIFE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetDamageInfo()->GetDamage(); + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount())); + // Glyph of Siphon Life + if (AuraEffect const* glyphe = GetTarget()->GetAuraEffect(SPELL_WARLOCK_GLYPHE_OF_SIPHON_LIFE, EFFECT_0)) + AddPct(amount, glyphe->GetAmount()); + + GetTarget()->CastCustomSpell(SPELL_WARLOCK_SIPHON_LIFE_HEAL, SPELLVALUE_BASE_POINT0, amount, GetTarget(), true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_warl_siphon_life_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warl_siphon_life_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_siphon_life_AuraScript(); + } +}; + // 29858 - Soulshatter class spell_warl_soulshatter : public SpellScriptLoader { @@ -774,12 +869,14 @@ void AddSC_warlock_spell_scripts() new spell_warl_demonic_circle_teleport(); new spell_warl_demonic_empowerment(); new spell_warl_everlasting_affliction(); + new spell_warl_fel_synergy(); new spell_warl_haunt(); new spell_warl_health_funnel(); new spell_warl_life_tap(); new spell_warl_ritual_of_doom_effect(); new spell_warl_seed_of_corruption(); new spell_warl_shadow_ward(); + new spell_warl_siphon_life(); new spell_warl_soulshatter(); new spell_warl_unstable_affliction(); } diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index 822d4b17992..7136f046873 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -31,21 +31,26 @@ enum WarriorSpells SPELL_WARRIOR_BLOODTHIRST = 23885, SPELL_WARRIOR_BLOODTHIRST_DAMAGE = 23881, SPELL_WARRIOR_CHARGE = 34846, + SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE = 59653, SPELL_WARRIOR_DEEP_WOUNDS_RANK_1 = 12162, SPELL_WARRIOR_DEEP_WOUNDS_RANK_2 = 12850, SPELL_WARRIOR_DEEP_WOUNDS_RANK_3 = 12868, SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC = 12721, SPELL_WARRIOR_EXECUTE = 20647, SPELL_WARRIOR_GLYPH_OF_EXECUTION = 58367, + SPELL_WARRIOR_GLYPH_OF_VIGILANCE = 63326, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_BUFF = 65156, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT = 64976, SPELL_WARRIOR_LAST_STAND_TRIGGERED = 12976, SPELL_WARRIOR_SLAM = 50783, + SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK = 26654, SPELL_WARRIOR_TAUNT = 355, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_1 = 46859, SPELL_WARRIOR_UNRELENTING_ASSAULT_RANK_2 = 46860, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_1 = 64849, SPELL_WARRIOR_UNRELENTING_ASSAULT_TRIGGER_2 = 64850, + SPELL_WARRIOR_VIGILANCE_PROC = 50725, + SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT = 59665, SPELL_PALADIN_BLESSING_OF_SANCTUARY = 20911, SPELL_PALADIN_GREATER_BLESSING_OF_SANCTUARY = 25899, @@ -195,6 +200,44 @@ class spell_warr_concussion_blow : public SpellScriptLoader } }; +// -58872 - Damage Shield +class spell_warr_damage_shield : public SpellScriptLoader +{ + public: + spell_warr_damage_shield() : SpellScriptLoader("spell_warr_damage_shield") { } + + class spell_warr_damage_shield_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warr_damage_shield_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE)) + return false; + return true; + } + + void OnProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + // % of amount blocked + int32 damage = CalculatePct(int32(GetTarget()->GetShieldBlockValue()), aurEff->GetAmount()); + GetTarget()->CastCustomSpell(SPELL_WARRIOR_DAMAGE_SHIELD_DAMAGE, SPELLVALUE_BASE_POINT0, damage, eventInfo.GetProcTarget(), true, NULL, aurEff); + } + + void Register() + { + OnEffectProc += AuraEffectProcFn(spell_warr_damage_shield_AuraScript::OnProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warr_damage_shield_AuraScript(); + } +}; + // -12162 - Deep Wounds class spell_warr_deep_wounds : public SpellScriptLoader { @@ -551,6 +594,57 @@ class spell_warr_slam : public SpellScriptLoader } }; +// 12328, 18765, 35429 - Sweeping Strikes +class spell_warr_sweeping_strikes : public SpellScriptLoader +{ + public: + spell_warr_sweeping_strikes() : SpellScriptLoader("spell_warr_sweeping_strikes") { } + + class spell_warr_sweeping_strikes_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warr_sweeping_strikes_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK)) + return false; + return true; + } + + bool Load() + { + _procTarget = NULL; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + _procTarget = eventInfo.GetActor()->SelectNearbyTarget(eventInfo.GetProcTarget()); + return _procTarget; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_SWEEPING_STRIKES_EXTRA_ATTACK, true, NULL, aurEff); + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_warr_sweeping_strikes_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warr_sweeping_strikes_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + + private: + Unit* _procTarget; + }; + + AuraScript* GetAuraScript() const + { + return new spell_warr_sweeping_strikes_AuraScript(); + } +}; + // 50720 - Vigilance class spell_warr_vigilance : public SpellScriptLoader { @@ -563,34 +657,80 @@ class spell_warr_vigilance : public SpellScriptLoader bool Validate(SpellInfo const* /*spellInfo*/) { + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_GLYPH_OF_VIGILANCE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_VIGILANCE_PROC)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT)) + return false; if (!sSpellMgr->GetSpellInfo(SPELL_GEN_DAMAGE_REDUCTION_AURA)) return false; return true; } - void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + bool Load() { - if (Unit* target = GetTarget()) - target->CastSpell(target, SPELL_GEN_DAMAGE_REDUCTION_AURA, true); + _procTarget = NULL; + return true; + } + + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->CastSpell(target, SPELL_GEN_DAMAGE_REDUCTION_AURA, true); + + if (Unit* caster = GetCaster()) + target->CastSpell(caster, SPELL_WARRIOR_VIGILANCE_REDIRECT_THREAT, true); } - void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + void HandleAfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (Unit* target = GetTarget()) + //! WORKAROUND + //! this glyph is a proc + if (Unit* caster = GetCaster()) { - if (target->HasAura(SPELL_GEN_DAMAGE_REDUCTION_AURA) && !(target->HasAura(SPELL_PALADIN_BLESSING_OF_SANCTUARY) || - target->HasAura(SPELL_PALADIN_GREATER_BLESSING_OF_SANCTUARY) || - target->HasAura(SPELL_PRIEST_RENEWED_HOPE))) - target->RemoveAurasDueToSpell(SPELL_GEN_DAMAGE_REDUCTION_AURA); + if (AuraEffect const* glyph = caster->GetAuraEffect(SPELL_WARRIOR_GLYPH_OF_VIGILANCE, EFFECT_0)) + GetTarget()->ModifyRedirectThreat(glyph->GetAmount()); } } + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + if (target->HasAura(SPELL_GEN_DAMAGE_REDUCTION_AURA) && + !(target->HasAura(SPELL_PALADIN_BLESSING_OF_SANCTUARY) || + target->HasAura(SPELL_PALADIN_GREATER_BLESSING_OF_SANCTUARY) || + target->HasAura(SPELL_PRIEST_RENEWED_HOPE))) + { + target->RemoveAurasDueToSpell(SPELL_GEN_DAMAGE_REDUCTION_AURA); + } + + target->ResetRedirectThreat(); + } + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + _procTarget = GetCaster(); + return _procTarget; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_VIGILANCE_PROC, true, NULL, aurEff); + } + void Register() { - OnEffectApply += AuraEffectApplyFn(spell_warr_vigilance_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - OnEffectRemove += AuraEffectRemoveFn(spell_warr_vigilance_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectApply += AuraEffectApplyFn(spell_warr_vigilance_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_warr_vigilance_AuraScript::HandleAfterApply, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectRemove += AuraEffectRemoveFn(spell_warr_vigilance_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + DoCheckProc += AuraCheckProcFn(spell_warr_vigilance_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warr_vigilance_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); } + private: + Unit* _procTarget; }; AuraScript* GetAuraScript() const @@ -636,6 +776,7 @@ void AddSC_warrior_spell_scripts() new spell_warr_bloodthirst_heal(); new spell_warr_charge(); new spell_warr_concussion_blow(); + new spell_warr_damage_shield(); new spell_warr_deep_wounds(); new spell_warr_execute(); new spell_warr_improved_spell_reflection(); @@ -645,6 +786,7 @@ void AddSC_warrior_spell_scripts() new spell_warr_rend(); new spell_warr_shattering_throw(); new spell_warr_slam(); + new spell_warr_sweeping_strikes(); new spell_warr_vigilance(); new spell_warr_vigilance_trigger(); } -- cgit v1.2.3 From 39c2d892f3e696526b2373fb6990f3a93c2bd9ec Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Wed, 23 Jan 2013 17:48:17 +0100 Subject: Core/Log: Allow configuring a maximum file size for a log file. If the file size is about to be exceeded, the core will create a new file titled _.log and start outputting there. --- src/server/shared/Logging/Appender.h | 6 ++++++ src/server/shared/Logging/AppenderFile.cpp | 20 ++++++++++++++++++-- src/server/shared/Logging/AppenderFile.h | 4 +++- src/server/shared/Logging/Log.cpp | 9 ++++++++- src/server/worldserver/worldserver.conf.dist | 9 ++++++++- 5 files changed, 43 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/shared/Logging/Appender.h b/src/server/shared/Logging/Appender.h index a8854a8abc6..08628948b90 100644 --- a/src/server/shared/Logging/Appender.h +++ b/src/server/shared/Logging/Appender.h @@ -123,6 +123,12 @@ struct LogMessage std::string prefix; std::string param1; time_t mtime; + + ///@ Returns size of the log message content in bytes + uint32 Size() const + { + return prefix.size() + text.size(); + } }; class Appender diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp index 8189237bb4e..c2f1e0c919d 100644 --- a/src/server/shared/Logging/AppenderFile.cpp +++ b/src/server/shared/Logging/AppenderFile.cpp @@ -18,11 +18,12 @@ #include "AppenderFile.h" #include "Common.h" -AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* _filename, const char* _logDir, const char* _mode, AppenderFlags _flags) +AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* _filename, const char* _logDir, const char* _mode, AppenderFlags _flags, uint64 fileSize) : Appender(id, name, APPENDER_FILE, level, _flags) , filename(_filename) , logDir(_logDir) , mode(_mode) + , _fileSize(fileSize) { dynamicName = std::string::npos != filename.find("%s"); backup = _flags & APPENDER_FLAGS_MAKE_FILE_BACKUP; @@ -46,12 +47,25 @@ void AppenderFile::_write(LogMessage const& message) char namebuf[TRINITY_PATH_MAX]; snprintf(namebuf, TRINITY_PATH_MAX, filename.c_str(), message.param1.c_str()); logfile = OpenFile(namebuf, mode, backup); + _fileSize = ftell(logfile); } if (logfile) { + if (!dynamicName && _fileSize + message.Size() > _maxFileSize) + { + /** @ We assume all log files have a .log extension. + If file "gol.log" is at its max capacity, this will spawn a new file, "gol_.log". If that one reaches capacity, it'll spawn "gol__.log", etc. + */ + filename.replace(filename.end() - 3, filename.end(), "_.log"); + logfile = OpenFile(filename.c_str(), mode, backup); + _write(message); + return; + } + fprintf(logfile, "%s%s", message.prefix.c_str(), message.text.c_str()); fflush(logfile); + _fileSize += message.Size(); if (dynamicName) { @@ -71,5 +85,7 @@ FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mod rename(filename.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore } - return fopen((logDir + filename).c_str(), mode.c_str()); + FILE* ret = fopen((logDir + filename).c_str(), mode.c_str()); + _fileSize = ftell(ret); + return ret; } diff --git a/src/server/shared/Logging/AppenderFile.h b/src/server/shared/Logging/AppenderFile.h index a3fe285cc7d..4f3055bd6be 100644 --- a/src/server/shared/Logging/AppenderFile.h +++ b/src/server/shared/Logging/AppenderFile.h @@ -23,7 +23,7 @@ class AppenderFile: public Appender { public: - AppenderFile(uint8 _id, std::string const& _name, LogLevel level, const char* filename, const char* logDir, const char* mode, AppenderFlags flags); + AppenderFile(uint8 _id, std::string const& _name, LogLevel level, const char* filename, const char* logDir, const char* mode, AppenderFlags flags, uint64 maxSize); ~AppenderFile(); FILE* OpenFile(std::string const& _name, std::string const& _mode, bool _backup); @@ -35,6 +35,8 @@ class AppenderFile: public Appender std::string mode; bool dynamicName; bool backup; + uint64 _maxFileSize; + uint64 _fileSize; }; #endif diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index 96c72b5eb74..73b75a2a853 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -145,8 +145,15 @@ void Log::CreateAppenderFromConfig(const char* name) filename += m_logsTimestamp; } + uint64 maxFileSize = 0; + if (++iter != tokens.end()) + { + char const* c = *iter; + maxFileSize = atoi(c); + } + uint8 id = NextAppenderId(); - appenders[id] = new AppenderFile(id, name, level, filename.c_str(), m_logsDir.c_str(), mode.c_str(), flags); + appenders[id] = new AppenderFile(id, name, level, filename.c_str(), m_logsDir.c_str(), mode.c_str(), flags, maxFileSize); //fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type FILE, Mask %u, File %s, Mode %s\n", name, id, level, filename.c_str(), mode.c_str()); // DEBUG - RemoveMe break; } diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 51c083a3dbe..31d180df751 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -2661,7 +2661,7 @@ PlayerDump.DisallowOverwrite = 1 # Appender config values: Given a appender "name" # Appender.name # Description: Defines 'where to log' -# Format: Type,LogLevel,Flags,optional1,optional2 +# Format: Type,LogLevel,Flags,optional1,optional2,optional3 # # Type # 0 - (None) @@ -2712,6 +2712,13 @@ PlayerDump.DisallowOverwrite = 1 # a - (Append) # w - (Overwrite) # +# MaxFileSize: Maximum file size of the log file before creating a new log file +# (read as optional3 if Type = File) +# Size is measured in bytes expressed in a 64-bit unsigned integer. +# Maximum value is 4294967295 (4 gb). Leave blank for no limit. +# NOTE: Does not work with dynamic filenames. +# Example: 536870912 (512 mb) +# Appender.Console=1,3,0 Appender.Server=2,2,0,Server.log,w -- cgit v1.2.3 From 70490c8238d21ff56be48d6b8444344451f8f255 Mon Sep 17 00:00:00 2001 From: w1sht0l1v3 Date: Wed, 23 Jan 2013 20:58:01 +0200 Subject: Script/Commands: Add command to join an existing group/party. --- sql/updates/world/2013_01_23_01_world_misc.sql | 10 +++++ src/server/game/Miscellaneous/Language.h | 4 ++ src/server/scripts/Commands/cs_misc.cpp | 56 ++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 sql/updates/world/2013_01_23_01_world_misc.sql (limited to 'src') diff --git a/sql/updates/world/2013_01_23_01_world_misc.sql b/sql/updates/world/2013_01_23_01_world_misc.sql new file mode 100644 index 00000000000..25042e241dd --- /dev/null +++ b/sql/updates/world/2013_01_23_01_world_misc.sql @@ -0,0 +1,10 @@ +DELETE FROM `trinity_string` WHERE `entry` BETWEEN 1145 AND 1148; +INSERT INTO `trinity_string` (`entry`,`content_default`,`content_loc1`,`content_loc2`,`content_loc3`,`content_loc4`,`content_loc5`,`content_loc6`,`content_loc7`,`content_loc8`) VALUES +(1145,'%s is already in a group!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1146,'%s joined %s''s group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1147,'%s is not in a group!',NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1148,'Group is full!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + +DELETE FROM `command` WHERE `name`='group join'; +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('group join',3,'Syntax: .group join $AnyCharacterNameFromGroup [$CharacterName] \r\nAdds to group of player $AnyCharacterNameFromGroup player $CharacterName (or selected).'); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 039e8b816b3..093622467f8 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -847,6 +847,10 @@ enum TrinityStrings LANG_MOVEGENS_EFFECT = 1142, LANG_MOVEFLAGS_GET = 1143, LANG_MOVEFLAGS_SET = 1144, + LANG_GROUP_ALREADY_IN_GROUP = 1145, + LANG_GROUP_PLAYER_JOINED = 1146, + LANG_GROUP_NOT_IN_GROUP = 1147, + LANG_GROUP_FULL = 1148, // Room for more level 3 1144-1199 not used // Debug commands diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 54fe41a8a4d..e2b5ac9487d 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -46,6 +46,7 @@ public: { "leader", SEC_ADMINISTRATOR, false, &HandleGroupLeaderCommand, "", NULL }, { "disband", SEC_ADMINISTRATOR, false, &HandleGroupDisbandCommand, "", NULL }, { "remove", SEC_ADMINISTRATOR, false, &HandleGroupRemoveCommand, "", NULL }, + { "join", SEC_ADMINISTRATOR, false, &HandleGroupJoinCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand petCommandTable[] = @@ -2725,6 +2726,61 @@ public: return true; } + static bool HandleGroupJoinCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Player* playerSource = NULL; + Player* playerTarget = NULL; + Group* groupSource = NULL; + Group* groupTarget = NULL; + uint64 guidSource = 0; + uint64 guidTarget = 0; + char* nameplgrStr = strtok((char*)args, " "); + char* nameplStr = strtok(NULL, " "); + + if (handler->GetPlayerGroupAndGUIDByName(nameplgrStr, playerSource, groupSource, guidSource, true)) + { + if (groupSource) + { + if (handler->GetPlayerGroupAndGUIDByName(nameplStr, playerTarget, groupTarget, guidTarget, true)) + { + if (!groupTarget && playerTarget->GetGroup() != groupSource) + { + if (!groupSource->IsFull()) + { + groupSource->AddMember(playerTarget); + groupSource->BroadcastGroupUpdate(); + handler->PSendSysMessage(LANG_GROUP_PLAYER_JOINED, playerTarget->GetName().c_str(), playerSource->GetName().c_str()); + return true; + } + else + { + // group is full + handler->PSendSysMessage(LANG_GROUP_FULL); + return true; + } + } + else + { + // group is full or target player already in a group + handler->PSendSysMessage(LANG_GROUP_ALREADY_IN_GROUP, playerTarget->GetName().c_str()); + return true; + } + } + } + else + { + // specified source player is not in a group + handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, playerSource->GetName().c_str()); + return true; + } + } + + return true; + } + static bool HandlePlayAllCommand(ChatHandler* handler, char const* args) { if (!*args) -- cgit v1.2.3 From d291c78ca0889d569c114d1a638fac466a1fe7a6 Mon Sep 17 00:00:00 2001 From: WishToDie Date: Wed, 23 Jan 2013 21:08:33 +0200 Subject: Typo fix. --- src/server/game/Miscellaneous/Language.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 093622467f8..1aeb16e9c7e 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -851,7 +851,7 @@ enum TrinityStrings LANG_GROUP_PLAYER_JOINED = 1146, LANG_GROUP_NOT_IN_GROUP = 1147, LANG_GROUP_FULL = 1148, - // Room for more level 3 1144-1199 not used + // Room for more level 3 1149-1199 not used // Debug commands LANG_CINEMATIC_NOT_EXIST = 1200, -- cgit v1.2.3 From f4de181db00bf323793e2121aac496588c3b9b33 Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Wed, 23 Jan 2013 20:29:40 +0100 Subject: SQL: Rename SQL merged in PR --- dep/SFMT/SFMT.h | 2 +- dep/SFMT/randomc.h | 2 +- .../2013_01_23_00_world_spell_script_names.sql | 77 ---------------------- .../2013_01_23_02_world_spell_script_names.sql | 77 ++++++++++++++++++++++ src/tools/mesh_extractor/Chunk.cpp | 2 +- src/tools/mesh_extractor/ContinentBuilder.cpp | 2 +- src/tools/mesh_extractor/DoodadHandler.h | 2 +- src/tools/mesh_extractor/Utils.cpp | 12 ++-- 8 files changed, 88 insertions(+), 88 deletions(-) delete mode 100644 sql/updates/world/2013_01_23_00_world_spell_script_names.sql create mode 100644 sql/updates/world/2013_01_23_02_world_spell_script_names.sql (limited to 'src') diff --git a/dep/SFMT/SFMT.h b/dep/SFMT/SFMT.h index 08966e1831c..4004ae1db6e 100644 --- a/dep/SFMT/SFMT.h +++ b/dep/SFMT/SFMT.h @@ -7,7 +7,7 @@ * in effect in addition to the GNU General Public License. * Copyright (c) 2006, 2007 by Mutsuo Saito, Makoto Matsumoto and Hiroshima University. * Copyright (c) 2008 by Agner Fog. - * Copyright (c) 2012 Trinity Core + * Copyright (c) 2008-2013 Trinity Core * * BSD License: * Redistribution and use in source and binary forms, with or without diff --git a/dep/SFMT/randomc.h b/dep/SFMT/randomc.h index ee5ad9aa43b..eed2c81a205 100644 --- a/dep/SFMT/randomc.h +++ b/dep/SFMT/randomc.h @@ -7,7 +7,7 @@ * in effect in addition to the GNU General Public License. * Copyright (c) 2006, 2007 by Mutsuo Saito, Makoto Matsumoto and Hiroshima University. * Copyright (c) 2008 by Agner Fog. - * Copyright (c) 2012 Trinity Core + * Copyright (c) 2008-2013 Trinity Core * * BSD License: * Redistribution and use in source and binary forms, with or without diff --git a/sql/updates/world/2013_01_23_00_world_spell_script_names.sql b/sql/updates/world/2013_01_23_00_world_spell_script_names.sql deleted file mode 100644 index dd8b35ae420..00000000000 --- a/sql/updates/world/2013_01_23_00_world_spell_script_names.sql +++ /dev/null @@ -1,77 +0,0 @@ -DELETE FROM `spell_script_names` WHERE `spell_id` IN ( -70871, -- spell_blood_queen_essence_of_the_blood_queen -69383, -- spell_the_lich_king_dark_hunger -50453, -- spell_dk_blood_gorged --48496, -- spell_dru_living_seed -48504, -- spell_dru_living_seed_proc -28764, -- spell_gen_adaptive_warding -27539, -- spell_gen_obsidian_armor -34074, -- spell_hun_ascpect_of_the_viper -64411, -- spell_item_blessing_of_ancient_kings -71875, -- spell_item_necrotic_touch -71877, -- spell_item_necrotic_touch -71169, -- spell_item_shadows_fate -71903, -- spell_item_shadowmourne -71905, -- spell_item_shadowmourne_soul_fragment --44449, -- spell_mage_burnout -54646, -- spell_mage_focus_magic --11119, -- spell_mage_ignite --29074, -- spell_mage_master_of_elements --9799, -- spell_pal_eye_for_an_eye -20154, -- spell_pal_seal_of_righteousness -21084 -- spell_pal_seal_of_righteousness --47509, -- spell_pri_divine_aegis -55680, -- spell_pri_glyph_of_prayer_of_healing -28305, -- spell_pri_mana_leech -13877, -- spell_rog_blade_flurry -33735, -- spell_rog_blade_flurry -51211, -- spell_rog_blade_flurry -65956, -- spell_rog_blade_flurry -57934, -- spell_rog_tricks_of_the_trade -59628, -- spell_rog_tricks_of_the_trade_proc --974, -- spell_sha_earth_shield --47230, -- spell_warl_fel_synergy -63108, -- spell_warl_siphon_life --58872, -- spell_warr_damage_shield -12328, -- spell_warr_sweeping_strikes -18765, -- spell_warr_sweeping_strikes -35429 -- spell_warr_sweeping_strikes -); -INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES -(70871, 'spell_blood_queen_essence_of_the_blood_queen'), -(69383, 'spell_the_lich_king_dark_hunger'), -(50453, 'spell_dk_blood_gorged'), -(-48496, 'spell_dru_living_seed'), -(48504, 'spell_dru_living_seed_proc'), -(28764, 'spell_gen_adaptive_warding'), -(27539, 'spell_gen_obsidian_armor'), -(34074, 'spell_hun_ascpect_of_the_viper'), -(64411, 'spell_item_blessing_of_ancient_kings'), -(71875, 'spell_item_necrotic_touch'), -(71877, 'spell_item_necrotic_touch'), -(71169, 'spell_item_shadows_fate'), -(71903, 'spell_item_shadowmourne'), -(71905, 'spell_item_shadowmourne_soul_fragment'), -(-44449, 'spell_mage_burnout'), -(54646, 'spell_mage_focus_magic'), -(-11119, 'spell_mage_ignite'), -(-29074, 'spell_mage_master_of_elements'), -(-9799, 'spell_pal_eye_for_an_eye'), -(20154, 'spell_pal_seal_of_righteousness'), -(21084, 'spell_pal_seal_of_righteousness'), -(-47509, 'spell_pri_divine_aegis'), -(55680, 'spell_pri_glyph_of_prayer_of_healing'), -(28305, 'spell_pri_mana_leech'), -(13877, 'spell_rog_blade_flurry'), -(33735, 'spell_rog_blade_flurry'), -(51211, 'spell_rog_blade_flurry'), -(65956, 'spell_rog_blade_flurry'), -(57934, 'spell_rog_tricks_of_the_trade'), -(59628, 'spell_rog_tricks_of_the_trade_proc'), -(-974, 'spell_sha_earth_shield'), -(-47230, 'spell_warl_fel_synergy'), -(63108, 'spell_warl_siphon_life'), -(-58872, 'spell_warr_damage_shield'), -(12328, 'spell_warr_sweeping_strikes'), -(18765, 'spell_warr_sweeping_strikes'), -(35429, 'spell_warr_sweeping_strikes'); diff --git a/sql/updates/world/2013_01_23_02_world_spell_script_names.sql b/sql/updates/world/2013_01_23_02_world_spell_script_names.sql new file mode 100644 index 00000000000..dd8b35ae420 --- /dev/null +++ b/sql/updates/world/2013_01_23_02_world_spell_script_names.sql @@ -0,0 +1,77 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` IN ( +70871, -- spell_blood_queen_essence_of_the_blood_queen +69383, -- spell_the_lich_king_dark_hunger +50453, -- spell_dk_blood_gorged +-48496, -- spell_dru_living_seed +48504, -- spell_dru_living_seed_proc +28764, -- spell_gen_adaptive_warding +27539, -- spell_gen_obsidian_armor +34074, -- spell_hun_ascpect_of_the_viper +64411, -- spell_item_blessing_of_ancient_kings +71875, -- spell_item_necrotic_touch +71877, -- spell_item_necrotic_touch +71169, -- spell_item_shadows_fate +71903, -- spell_item_shadowmourne +71905, -- spell_item_shadowmourne_soul_fragment +-44449, -- spell_mage_burnout +54646, -- spell_mage_focus_magic +-11119, -- spell_mage_ignite +-29074, -- spell_mage_master_of_elements +-9799, -- spell_pal_eye_for_an_eye +20154, -- spell_pal_seal_of_righteousness +21084 -- spell_pal_seal_of_righteousness +-47509, -- spell_pri_divine_aegis +55680, -- spell_pri_glyph_of_prayer_of_healing +28305, -- spell_pri_mana_leech +13877, -- spell_rog_blade_flurry +33735, -- spell_rog_blade_flurry +51211, -- spell_rog_blade_flurry +65956, -- spell_rog_blade_flurry +57934, -- spell_rog_tricks_of_the_trade +59628, -- spell_rog_tricks_of_the_trade_proc +-974, -- spell_sha_earth_shield +-47230, -- spell_warl_fel_synergy +63108, -- spell_warl_siphon_life +-58872, -- spell_warr_damage_shield +12328, -- spell_warr_sweeping_strikes +18765, -- spell_warr_sweeping_strikes +35429 -- spell_warr_sweeping_strikes +); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(70871, 'spell_blood_queen_essence_of_the_blood_queen'), +(69383, 'spell_the_lich_king_dark_hunger'), +(50453, 'spell_dk_blood_gorged'), +(-48496, 'spell_dru_living_seed'), +(48504, 'spell_dru_living_seed_proc'), +(28764, 'spell_gen_adaptive_warding'), +(27539, 'spell_gen_obsidian_armor'), +(34074, 'spell_hun_ascpect_of_the_viper'), +(64411, 'spell_item_blessing_of_ancient_kings'), +(71875, 'spell_item_necrotic_touch'), +(71877, 'spell_item_necrotic_touch'), +(71169, 'spell_item_shadows_fate'), +(71903, 'spell_item_shadowmourne'), +(71905, 'spell_item_shadowmourne_soul_fragment'), +(-44449, 'spell_mage_burnout'), +(54646, 'spell_mage_focus_magic'), +(-11119, 'spell_mage_ignite'), +(-29074, 'spell_mage_master_of_elements'), +(-9799, 'spell_pal_eye_for_an_eye'), +(20154, 'spell_pal_seal_of_righteousness'), +(21084, 'spell_pal_seal_of_righteousness'), +(-47509, 'spell_pri_divine_aegis'), +(55680, 'spell_pri_glyph_of_prayer_of_healing'), +(28305, 'spell_pri_mana_leech'), +(13877, 'spell_rog_blade_flurry'), +(33735, 'spell_rog_blade_flurry'), +(51211, 'spell_rog_blade_flurry'), +(65956, 'spell_rog_blade_flurry'), +(57934, 'spell_rog_tricks_of_the_trade'), +(59628, 'spell_rog_tricks_of_the_trade_proc'), +(-974, 'spell_sha_earth_shield'), +(-47230, 'spell_warl_fel_synergy'), +(63108, 'spell_warl_siphon_life'), +(-58872, 'spell_warr_damage_shield'), +(12328, 'spell_warr_sweeping_strikes'), +(18765, 'spell_warr_sweeping_strikes'), +(35429, 'spell_warr_sweeping_strikes'); diff --git a/src/tools/mesh_extractor/Chunk.cpp b/src/tools/mesh_extractor/Chunk.cpp index 9f2898a46e0..4605ae0f0dd 100644 --- a/src/tools/mesh_extractor/Chunk.cpp +++ b/src/tools/mesh_extractor/Chunk.cpp @@ -17,7 +17,7 @@ int32 Chunk::FindSubChunkOffset(std::string name) matched = 0; else ++matched; - + if (matched == 4) return ftell(stream) - 4; } diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp index 9b5c9f9c77b..d6125bdd8e2 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.cpp +++ b/src/tools/mesh_extractor/ContinentBuilder.cpp @@ -101,7 +101,7 @@ void ContinentBuilder::Build(bool debug) } CalculateTileBounds(); - + dtNavMeshParams params; params.maxPolys = 1 << STATIC_POLY_BITS; params.maxTiles = TileMap->TileTable.size(); diff --git a/src/tools/mesh_extractor/DoodadHandler.h b/src/tools/mesh_extractor/DoodadHandler.h index 981834ec7ac..96aecbcce27 100644 --- a/src/tools/mesh_extractor/DoodadHandler.h +++ b/src/tools/mesh_extractor/DoodadHandler.h @@ -20,7 +20,7 @@ public: void Read(FILE* stream) { int count = 0; - + count += fread(&MmidIndex, sizeof(uint32), 1, stream); count += fread(&UniqueId, sizeof(uint32), 1, stream); Position = Vector3::Read(stream); diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp index 119ac94f94f..acb1ed38e27 100644 --- a/src/tools/mesh_extractor/Utils.cpp +++ b/src/tools/mesh_extractor/Utils.cpp @@ -218,7 +218,7 @@ void Utils::SaveToDisk( FILE* stream, std::string path ) if (fread(data, 1, size, stream) != 1) { printf("SaveToDisk: Error reading from Stream while trying to save file %s to disck.\n", path.c_str()); - return; + return; } // And write it in the file fwrite(data, 1, size, disk); @@ -274,7 +274,7 @@ void MapChunkHeader::Read(FILE* stream) count += fread(&SizeMCLQ, sizeof(uint32), 1, stream); Position = Vector3::Read(stream); count += fread(&OffsetMCCV, sizeof(uint32), 1, stream); - + if (count != 27) printf("MapChunkHeader::Read: Failed to read some data expected 27, read %d\n", count); } @@ -295,7 +295,7 @@ void MHDR::Read(FILE* stream) count += fread(&OffsetMFBO, sizeof(uint32), 1, stream); count += fread(&OffsetMH2O, sizeof(uint32), 1, stream); count += fread(&OffsetMTFX, sizeof(uint32), 1, stream); - + if (count != 12) printf("MHDR::Read: Failed to read some data expected 12, read %d\n", count); } @@ -357,7 +357,7 @@ void ModelHeader::Read(FILE* stream) count += fread(&OffsetBoundingVertices, sizeof(uint32), 1, stream); count += fread(&CountBoundingNormals, sizeof(uint32), 1, stream); count += fread(&OffsetBoundingNormals, sizeof(uint32), 1, stream); - + if (count != 51) printf("ModelHeader::Read: Failed to read some data expected 51, read %d\n", count); @@ -380,7 +380,7 @@ WorldModelHeader WorldModelHeader::Read(FILE* stream) ret.BoundingBox[0] = Vector3::Read(stream); ret.BoundingBox[1] = Vector3::Read(stream); count += fread(&ret.LiquidTypeRelated, sizeof(uint32), 1, stream); - + if (count != 10) printf("WorldModelHeader::Read: Failed to read some data expected 10, read %d\n", count); @@ -400,7 +400,7 @@ DoodadInstance DoodadInstance::Read(FILE* stream) count += fread(&ret.QuatZ, sizeof(float), 1, stream); count += fread(&ret.Scale, sizeof(float), 1, stream); count += fread(&ret.LightColor, sizeof(uint32), 1, stream); - + if (count != 7) printf("DoodadInstance::Read: Failed to read some data expected 7, read %d\n", count); -- cgit v1.2.3 From 1c0239ea9873f1fbbaf6cf80bb3caf2d350a656a Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Wed, 23 Jan 2013 22:56:56 +0100 Subject: Core/DBLayer: Drop support for MySQL versions <5.1 Both server and client libraries must be up to date in order to run TC. --- src/server/shared/Database/DatabaseWorkerPool.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h index 34b7c5083e3..3df9436a4c4 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -31,6 +31,9 @@ #include "QueryHolder.h" #include "AdhocStatement.h" +#define MIN_MYSQL_SERVER_VERSION 51000u +#define MIN_MYSQL_CLIENT_VERSION 51000u + class PingOperation : public SQLOperation { //! Operation for idle delaythreads @@ -53,6 +56,9 @@ class DatabaseWorkerPool _connections.resize(IDX_SIZE); WPFatal (mysql_thread_safe(), "Used MySQL library isn't thread-safe."); + WPFatal (mysql_get_server_version() >= MIN_MYSQL_SERVER_VERSION && + mysql_get_client_version() >= MIN_MYSQL_CLIENT_VERSION, + "TrinityCore does not support MySQL versions below 5.1"); } ~DatabaseWorkerPool() -- cgit v1.2.3 From 6c5fbc492c7353dcf41c6becc669baa7e2d0205d Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 23 Jan 2013 23:14:18 +0100 Subject: Scripts/Icecrown Citadel: Fixed Essence of the Blood Queen interrupting player spell casts Closes #8665 --- .../scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index 5643d0ab732..ab0c44aa6d0 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -720,7 +720,7 @@ class spell_blood_queen_essence_of_the_blood_queen : public SpellScriptLoader { PreventDefaultAction(); int32 heal = CalculatePct(int32(eventInfo.GetDamageInfo()->GetDamage()), aurEff->GetAmount()); - GetTarget()->CastCustomSpell(SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL, SPELLVALUE_BASE_POINT0, heal, GetTarget()); + GetTarget()->CastCustomSpell(SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL, SPELLVALUE_BASE_POINT0, heal, GetTarget(), TRIGGERED_FULL_MASK, NULL, aurEff); } void Register() -- cgit v1.2.3 From 5d75ac29b49b4238844f84aedcbbe62c43c8180d Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 23 Jan 2013 23:25:42 +0100 Subject: Tools: Remove a bit of spam when mmaps_generator loads vmaps --- src/server/collision/VMapDefinitions.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/collision/VMapDefinitions.h b/src/server/collision/VMapDefinitions.h index 56084389ad6..bb0766dc8ff 100644 --- a/src/server/collision/VMapDefinitions.h +++ b/src/server/collision/VMapDefinitions.h @@ -38,9 +38,9 @@ namespace VMAP #define VMAP_DEBUG_LOG(FILTER, ...) sLog->outDebug(FILTER, __VA_ARGS__) #define VMAP_INFO_LOG(FILTER, ...) sLog->outInfo(FILTER, __VA_ARGS__) #else -#define VMAP_ERROR_LOG(FILTER, ...) printf(__VA_ARGS__) -#define VMAP_DEBUG_LOG(FILTER, ...) printf(__VA_ARGS__) -#define VMAP_INFO_LOG(FILTER, ...) printf(__VA_ARGS__) +#define VMAP_ERROR_LOG(FILTER, ...) (void)sizeof(FILTER) +#define VMAP_DEBUG_LOG(FILTER, ...) (void)sizeof(FILTER) +#define VMAP_INFO_LOG(FILTER, ...) (void)sizeof(FILTER) #endif #endif -- cgit v1.2.3 From fd967ba4c64a71221397523440f2a3da0a9ec5f3 Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Thu, 24 Jan 2013 01:20:25 +0100 Subject: Tools/mmaps_generator: Multithreading optimisations. Should save some time generating mmaps. --- src/server/shared/Database/DatabaseWorkerPool.h | 5 +-- src/tools/mmaps_generator/MapBuilder.cpp | 31 ++++---------- src/tools/mmaps_generator/MapBuilder.h | 55 ++++++++++++++++++++----- 3 files changed, 56 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h index 3df9436a4c4..edbc41be8f7 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -56,9 +56,7 @@ class DatabaseWorkerPool _connections.resize(IDX_SIZE); WPFatal (mysql_thread_safe(), "Used MySQL library isn't thread-safe."); - WPFatal (mysql_get_server_version() >= MIN_MYSQL_SERVER_VERSION && - mysql_get_client_version() >= MIN_MYSQL_CLIENT_VERSION, - "TrinityCore does not support MySQL versions below 5.1"); + WPFatal (mysql_get_client_version() >= MIN_MYSQL_CLIENT_VERSION, "TrinityCore does not support MySQL versions below 5.1"); } ~DatabaseWorkerPool() @@ -79,6 +77,7 @@ class DatabaseWorkerPool { T* t = new T(_queue, _connectionInfo); res &= t->Open(); + WPFatal (mysql_get_server_version(t->GetHandle()) >= MIN_MYSQL_SERVER_VERSION, "TrinityCore does not support MySQL versions below 5.1"); _connections[IDX_ASYNC][i] = t; ++_connectionCount[IDX_ASYNC]; } diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index a62011ddfff..4707feb5857 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -166,45 +166,32 @@ namespace MMAP void MapBuilder::buildAllMaps(int threads) { std::vector _threads; - - for (int i = 0; i < threads; ++i) - _threads.push_back(new BuilderThread(this)); + + BuilderThreadPool* pool = new BuilderThreadPool(); for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { uint32 mapID = it->first; if (!shouldSkipMap(mapID)) { - if (threads > 1) - { - bool next = false; - while (!next) - { - for (std::vector::iterator _th = _threads.begin(); _th != _threads.end(); ++_th) - { - if ((*_th)->Free) - { - (*_th)->SetMapId(mapID); - (*_th)->activate(); - next = true; - break; - } - } - // Wait for 20 seconds - ACE_OS::sleep(ACE_Time_Value (0, 20000)); - } - } + if (threads > 0) + pool->Enqueue(new BuildAMapPlz(mapID)); else buildMap(mapID); } } + for (int i = 0; i < threads; ++i) + _threads.push_back(new BuilderThread(this, pool->Queue())); + // Free memory for (std::vector::iterator _th = _threads.begin(); _th != _threads.end(); ++_th) { (*_th)->wait(); delete *_th; } + + delete pool; } /**************************************************************************/ diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index ea9636b3cc3..ea805fd9235 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -30,6 +30,8 @@ #include "DetourNavMesh.h" #include +#include +#include using namespace VMAP; @@ -123,27 +125,60 @@ namespace MMAP // build performance - not really used for now rcContext* m_rcContext; }; + + class BuildAMapPlz : public ACE_Method_Request + { + public: + BuildAMapPlz(uint32 mapId) : _mapId(mapId) {} + + virtual int call() + { + /// @ Actually a creative way of unabstracting the class and returning a member variable + return (int)_mapId; + } + + private: + uint32 _mapId; + }; class BuilderThread : public ACE_Task { private: MapBuilder* _builder; - uint32 _mapId; - public: - BuilderThread(MapBuilder* builder) : _builder(builder), Free(true) {} - - void SetMapId(uint32 mapId) { _mapId = mapId; } + ACE_Activation_Queue* _queue; + public: + BuilderThread(MapBuilder* builder, ACE_Activation_Queue* queue) : _builder(builder), _queue(queue) { activate(); } + int svc() { - Free = false; - if (_builder) - _builder->buildMap(_mapId); - Free = true; + BuildAMapPlz* request = NULL; + while (request = (BuildAMapPlz*)_queue->dequeue()) + { + _builder->buildMap(request->call()); + delete request; + request = NULL; + } return 0; } - bool Free; + }; + + class BuilderThreadPool + { + public: + BuilderThreadPool() : _queue(new ACE_Activation_Queue()) {} + ~BuilderThreadPool() { _queue->queue()->close(); delete _queue; } + + void Enqueue(BuildAMapPlz* request) + { + _queue->enqueue(request); + } + + ACE_Activation_Queue* Queue() { return _queue; } + + private: + ACE_Activation_Queue* _queue; }; } -- cgit v1.2.3 From 54027803bdcdefb48007e791f02202a23bf10076 Mon Sep 17 00:00:00 2001 From: Mislav Blažević Date: Wed, 23 Jan 2013 21:11:08 +0100 Subject: Fix error when swapping unique equipped weapon on dual wield Also fix rings and trinkets --- src/server/game/Entities/Player/Player.cpp | 34 +++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 14878b078bd..208b24ea105 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -10735,7 +10735,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des { if (no_space_count) *no_space_count = count; - return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED :EQUIP_ERR_ITEM_NOT_FOUND; + return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND; } if (pItem) @@ -11490,8 +11490,36 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool if (!swap && GetItemByPos(INVENTORY_SLOT_BAG_0, eslot)) return EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE; - // if swap ignore item (equipped also) - InventoryResult res2 = CanEquipUniqueItem(pItem, swap ? eslot : uint8(NULL_SLOT)); + // if we are swapping 2 equiped items, CanEquipUniqueItem check + // should ignore the item we are trying to swap, and not the + // destination item. CanEquipUniqueItem should ignore destination + // item only when we are swapping weapon from bag + uint8 ignore; + switch (eslot) + { + case EQUIPMENT_SLOT_MAINHAND: + ignore = EQUIPMENT_SLOT_OFFHAND; + break; + case EQUIPMENT_SLOT_OFFHAND: + ignore = EQUIPMENT_SLOT_MAINHAND; + break; + case EQUIPMENT_SLOT_FINGER1: + ignore = EQUIPMENT_SLOT_FINGER2; + break; + case EQUIPMENT_SLOT_FINGER2: + ignore = EQUIPMENT_SLOT_FINGER1; + break; + case EQUIPMENT_SLOT_TRINKET1: + ignore = EQUIPMENT_SLOT_TRINKET2; + break; + case EQUIPMENT_SLOT_TRINKET2: + ignore = EQUIPMENT_SLOT_TRINKET1; + break; + } + if (pItem != GetItemByPos(INVENTORY_SLOT_BAG_0, ignore)) + ignore = eslot; + + InventoryResult res2 = CanEquipUniqueItem(pItem, swap ? ignore : uint8(NULL_SLOT)); if (res2 != EQUIP_ERR_OK) return res2; -- cgit v1.2.3 From 3034db92963bb068ee05da7a97d325d6dd4080f1 Mon Sep 17 00:00:00 2001 From: Mislav Blažević Date: Thu, 24 Jan 2013 11:02:08 +0100 Subject: Core/DBLayer: Fixed required version definitions --- src/server/shared/Database/DatabaseWorkerPool.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h index edbc41be8f7..9f93e99ab26 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -31,8 +31,8 @@ #include "QueryHolder.h" #include "AdhocStatement.h" -#define MIN_MYSQL_SERVER_VERSION 51000u -#define MIN_MYSQL_CLIENT_VERSION 51000u +#define MIN_MYSQL_SERVER_VERSION 50100u +#define MIN_MYSQL_CLIENT_VERSION 50100u class PingOperation : public SQLOperation { -- cgit v1.2.3 From 23b6a6a7cd27987bff8a5786cfd8dc45349f52ed Mon Sep 17 00:00:00 2001 From: Spp Date: Thu, 24 Jan 2013 12:44:58 +0100 Subject: Core/Log: Rotate logs when maximum size is exceeded, backup name will be "filename".datetime - This is an addition to 39c2d89 --- src/server/authserver/authserver.conf.dist | 11 +++- src/server/shared/Logging/AppenderFile.cpp | 83 +++++++++++++++--------------- src/server/shared/Logging/AppenderFile.h | 5 +- 3 files changed, 54 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist index 67d22c49da1..dda19c3b849 100644 --- a/src/server/authserver/authserver.conf.dist +++ b/src/server/authserver/authserver.conf.dist @@ -154,7 +154,7 @@ LoginDatabase.WorkerThreads = 1 # Appender config values: Given a appender "name" # Appender.name # Description: Defines 'where to log' -# Format: Type,LogLevel,Flags,optional1,optional2 +# Format: Type,LogLevel,Flags,optional1,optional2,optional3 # # Type # 0 - (None) @@ -205,6 +205,13 @@ LoginDatabase.WorkerThreads = 1 # a - (Append) # w - (Overwrite) # +# MaxFileSize: Maximum file size of the log file before creating a new log file +# (read as optional3 if Type = File) +# Size is measured in bytes expressed in a 64-bit unsigned integer. +# Maximum value is 4294967295 (4 gb). Leave blank for no limit. +# NOTE: Does not work with dynamic filenames. +# Example: 536870912 (512 mb) +# Appender.Console=1,2,0 Appender.Auth=2,2,0,Auth.log,w @@ -250,4 +257,4 @@ Logger.Root=0,3,Console Auth Loggers=Root # -################################################################################################### \ No newline at end of file +################################################################################################### diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp index c2f1e0c919d..1ed6350f813 100644 --- a/src/server/shared/Logging/AppenderFile.cpp +++ b/src/server/shared/Logging/AppenderFile.cpp @@ -18,74 +18,75 @@ #include "AppenderFile.h" #include "Common.h" -AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* _filename, const char* _logDir, const char* _mode, AppenderFlags _flags, uint64 fileSize) - : Appender(id, name, APPENDER_FILE, level, _flags) - , filename(_filename) - , logDir(_logDir) - , mode(_mode) - , _fileSize(fileSize) +AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* _filename, const char* _logDir, const char* _mode, AppenderFlags _flags, uint64 fileSize): + Appender(id, name, APPENDER_FILE, level, _flags), + filename(_filename), + logDir(_logDir), + mode(_mode), + maxFileSize(fileSize), + fileSize(0) { dynamicName = std::string::npos != filename.find("%s"); backup = _flags & APPENDER_FLAGS_MAKE_FILE_BACKUP; - logfile = !dynamicName ? OpenFile(_filename, _mode, backup) : NULL; + logfile = !dynamicName ? OpenFile(_filename, _mode, mode == "w" && backup) : NULL; } AppenderFile::~AppenderFile() { - if (logfile) - { - fclose(logfile); - logfile = NULL; - } + CloseFile(); } void AppenderFile::_write(LogMessage const& message) { + bool exceedMaxSize = maxFileSize > 0 && (fileSize + message.Size()) > maxFileSize; + if (dynamicName) { char namebuf[TRINITY_PATH_MAX]; snprintf(namebuf, TRINITY_PATH_MAX, filename.c_str(), message.param1.c_str()); - logfile = OpenFile(namebuf, mode, backup); - _fileSize = ftell(logfile); + logfile = OpenFile(namebuf, mode, backup || exceedMaxSize); } + else if (exceedMaxSize) + logfile = OpenFile(filename, "w", true); - if (logfile) - { - if (!dynamicName && _fileSize + message.Size() > _maxFileSize) - { - /** @ We assume all log files have a .log extension. - If file "gol.log" is at its max capacity, this will spawn a new file, "gol_.log". If that one reaches capacity, it'll spawn "gol__.log", etc. - */ - filename.replace(filename.end() - 3, filename.end(), "_.log"); - logfile = OpenFile(filename.c_str(), mode, backup); - _write(message); - return; - } + if (!logfile) + return; - fprintf(logfile, "%s%s", message.prefix.c_str(), message.text.c_str()); - fflush(logfile); - _fileSize += message.Size(); + fprintf(logfile, "%s%s", message.prefix.c_str(), message.text.c_str()); + fflush(logfile); + fileSize += message.Size(); - if (dynamicName) - { - fclose(logfile); - logfile = NULL; - } - } + if (dynamicName) + CloseFile(); } FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mode, bool backup) { - if (mode == "w" && backup) + std::string fullName(logDir + filename); + if (backup) { - std::string newName(filename); + CloseFile(); + std::string newName(fullName); newName.push_back('.'); newName.append(LogMessage::getTimeStr(time(NULL))); - rename(filename.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore + rename(fullName.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore } - FILE* ret = fopen((logDir + filename).c_str(), mode.c_str()); - _fileSize = ftell(ret); - return ret; + if (FILE* ret = fopen(fullName.c_str(), mode.c_str())) + { + fileSize = ftell(ret); + return ret; + } + + return NULL; +} + +void AppenderFile::CloseFile() +{ + if (logfile) + { + fclose(logfile); + logfile = NULL; + } } diff --git a/src/server/shared/Logging/AppenderFile.h b/src/server/shared/Logging/AppenderFile.h index 4f3055bd6be..c15974799e1 100644 --- a/src/server/shared/Logging/AppenderFile.h +++ b/src/server/shared/Logging/AppenderFile.h @@ -28,6 +28,7 @@ class AppenderFile: public Appender FILE* OpenFile(std::string const& _name, std::string const& _mode, bool _backup); private: + void CloseFile(); void _write(LogMessage const& message); FILE* logfile; std::string filename; @@ -35,8 +36,8 @@ class AppenderFile: public Appender std::string mode; bool dynamicName; bool backup; - uint64 _maxFileSize; - uint64 _fileSize; + uint64 maxFileSize; + uint64 fileSize; }; #endif -- cgit v1.2.3 From 389a4899f4032863955989386a02a6399411ebb3 Mon Sep 17 00:00:00 2001 From: springfieldking Date: Thu, 24 Jan 2013 22:26:11 +0800 Subject: Update src/server/shared/Logging/Log.cpp Fix crash when the last iter plus and change value --- src/server/shared/Logging/Log.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index 73b75a2a853..48512852dc4 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -146,7 +146,7 @@ void Log::CreateAppenderFromConfig(const char* name) } uint64 maxFileSize = 0; - if (++iter != tokens.end()) + if ( (iter != tokens.end()) && (++iter != tokens.end()) ) { char const* c = *iter; maxFileSize = atoi(c); -- cgit v1.2.3 From 08866f377edae3c32d57195e2d9acabbd85fdd32 Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 24 Jan 2013 16:40:35 +0100 Subject: Tools/mmap_generator: Fixed a deadlock at exit --- src/tools/mmaps_generator/MapBuilder.cpp | 8 ++++---- src/tools/mmaps_generator/MapBuilder.h | 20 +++++++++++--------- src/tools/mmaps_generator/PathGenerator.cpp | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 4707feb5857..4a016f267b4 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -166,8 +166,8 @@ namespace MMAP void MapBuilder::buildAllMaps(int threads) { std::vector _threads; - - BuilderThreadPool* pool = new BuilderThreadPool(); + + BuilderThreadPool* pool = threads > 0 ? new BuilderThreadPool() : NULL; for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { @@ -175,13 +175,13 @@ namespace MMAP if (!shouldSkipMap(mapID)) { if (threads > 0) - pool->Enqueue(new BuildAMapPlz(mapID)); + pool->Enqueue(new MapBuildRequest(mapID)); else buildMap(mapID); } } - for (int i = 0; i < threads; ++i) + for (int i = 0; i < threads; ++i) _threads.push_back(new BuilderThread(this, pool->Queue())); // Free memory diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index ea805fd9235..3ffaea0ab66 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -125,11 +125,11 @@ namespace MMAP // build performance - not really used for now rcContext* m_rcContext; }; - - class BuildAMapPlz : public ACE_Method_Request + + class MapBuildRequest : public ACE_Method_Request { public: - BuildAMapPlz(uint32 mapId) : _mapId(mapId) {} + MapBuildRequest(uint32 mapId) : _mapId(mapId) {} virtual int call() { @@ -141,7 +141,7 @@ namespace MMAP uint32 _mapId; }; - class BuilderThread : public ACE_Task + class BuilderThread : public ACE_Task_Base { private: MapBuilder* _builder; @@ -149,19 +149,21 @@ namespace MMAP public: BuilderThread(MapBuilder* builder, ACE_Activation_Queue* queue) : _builder(builder), _queue(queue) { activate(); } - + int svc() { - BuildAMapPlz* request = NULL; - while (request = (BuildAMapPlz*)_queue->dequeue()) + /// @ Set a timeout for dequeue attempts (only used when the queue is empty) as it will never get populated after thread starts + ACE_Time_Value timeout(5); + ACE_Method_Request* request = NULL; + while ((request = _queue->dequeue(&timeout)) != NULL) { _builder->buildMap(request->call()); delete request; request = NULL; } + return 0; } - }; class BuilderThreadPool @@ -170,7 +172,7 @@ namespace MMAP BuilderThreadPool() : _queue(new ACE_Activation_Queue()) {} ~BuilderThreadPool() { _queue->queue()->close(); delete _queue; } - void Enqueue(BuildAMapPlz* request) + void Enqueue(MapBuildRequest* request) { _queue->enqueue(request); } diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 01059099f98..47d35b517d5 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -292,5 +292,5 @@ int main(int argc, char** argv) if (!silent) printf("Finished. MMAPS were built in %u ms!\n", GetMSTimeDiffToNow(start)); - return 1; + return 0; } -- cgit v1.2.3 From cc605e060509d1255dfb2659200efa3c6f03fdf2 Mon Sep 17 00:00:00 2001 From: Spp Date: Thu, 17 Jan 2013 17:35:47 +0100 Subject: Core/Misc: Minor cosmetic changes here and there --- src/server/game/Entities/Player/Player.cpp | 2 +- src/server/game/Entities/Player/Player.h | 2 +- src/server/game/Groups/Group.cpp | 2 +- src/server/game/Handlers/BattleGroundHandler.cpp | 4 ++-- src/server/game/Handlers/MiscHandler.cpp | 2 +- src/server/game/Server/WorldSocket.cpp | 2 +- src/server/game/World/World.cpp | 29 +++++++++--------------- 7 files changed, 18 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c232a7a936c..fbc40db790e 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -21759,7 +21759,7 @@ void Player::LeaveBattleground(bool teleportToEntryPoint) } } -bool Player::CanJoinToBattleground() const +bool Player::CanJoinToBattleground(Battleground const* /*bg*/) const { // check Deserter debuff if (HasAura(26013)) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index a1e6591413f..a69f8c44715 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2227,7 +2227,7 @@ class Player : public Unit, public GridObject uint32 GetBGTeam() const { return m_bgData.bgTeam ? m_bgData.bgTeam : GetTeam(); } void LeaveBattleground(bool teleportToEntryPoint = true); - bool CanJoinToBattleground() const; + bool CanJoinToBattleground(Battleground const* bg) const; bool CanReportAfkDueToLimit(); void ReportedAfkBy(Player* reporter); void ClearAfkReports() { m_bgData.bgAfkReporter.clear(); } diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 734a1bfbaad..711e07ef941 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1818,7 +1818,7 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const* if (bgOrTemplate->GetTypeID() == BATTLEGROUND_RB && member->InBattlegroundQueue()) return ERR_IN_NON_RANDOM_BG; // check for deserter debuff in case not arena queue - if (bgOrTemplate->GetTypeID() != BATTLEGROUND_AA && !member->CanJoinToBattleground()) + if (bgOrTemplate->GetTypeID() != BATTLEGROUND_AA && !member->CanJoinToBattleground(bgOrTemplate)) return ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS; // check if member can join any more battleground queues if (!member->HasFreeBattlegroundQueueId()) diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index e70f127d600..0213df31630 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -138,7 +138,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData) } // check Deserter debuff - if (!_player->CanJoinToBattleground()) + if (!_player->CanJoinToBattleground(bg)) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); @@ -413,7 +413,7 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) if (action == 1 && ginfo.ArenaType == 0) { //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue - if (!_player->CanJoinToBattleground()) + if (!_player->CanJoinToBattleground(bg)) { //send bg command result to show nice message WorldPacket data2; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index c16a33ad97c..1aadd7f319d 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1342,7 +1342,7 @@ void WorldSession::HandleComplainOpcode(WorldPacket& recvData) recvData >> unk1; // probably language recvData >> unk2; // message type? recvData >> unk3; // probably channel id - recvData >> unk4; // unk random value + recvData >> unk4; // time recvData >> description; // spam description string (messagetype, channel name, player name, message) break; } diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index b9955fac523..c80d25be139 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -1033,4 +1033,4 @@ void WorldSocket::SendAuthResponseError(uint8 code) WorldPacket packet(SMSG_AUTH_RESPONSE, 1); packet << uint8(code); SendPacket(packet); -} \ No newline at end of file +} diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 67444475849..26a7986bcb8 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -225,7 +225,7 @@ void World::AddSession(WorldSession* s) void World::AddSession_(WorldSession* s) { - ASSERT (s); + ASSERT(s); //NOTE - Still there is race condition in WorldSession* being used in the Sockets @@ -260,7 +260,7 @@ void World::AddSession_(WorldSession* s) uint32 Sessions = GetActiveAndQueuedSessionCount(); uint32 pLimit = GetPlayerAmountLimit(); - uint32 QueueSize = GetQueuedSessionCount(); //number of players in the queue + uint32 QueueSize = GetQueuedSessionCount(); //number of players in the queue //so we don't count the user trying to //login as a session and queue the socket that we are using @@ -269,7 +269,7 @@ void World::AddSession_(WorldSession* s) if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(s->GetSecurity()) && !HasRecentlyDisconnected(s)) { - AddQueuedPlayer (s); + AddQueuedPlayer(s); UpdateMaxSessionCounters(); sLog->outInfo(LOG_FILTER_GENERAL, "PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId(), ++QueueSize); return; @@ -775,7 +775,7 @@ void World::LoadConfigSettings(bool reload) if (int32(m_int_configs[CONFIG_START_PLAYER_MONEY]) < 0) { sLog->outError(LOG_FILTER_SERVER_LOADING, "StartPlayerMoney (%i) must be in range 0..%u. Set to %u.", m_int_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, 0); - m_int_configs[CONFIG_START_PLAYER_MONEY] = 0; + m_int_configs[CONFIG_START_PLAYER_MONEY] = 0; } else if (m_int_configs[CONFIG_START_PLAYER_MONEY] > MAX_MONEY_AMOUNT) { @@ -1292,12 +1292,7 @@ void World::SetInitialWorldSettings() //No SQL injection as values are treated as integers // not send custom type REALM_FFA_PVP to realm list - uint32 server_type; - if (IsFFAPvPRealm()) - server_type = REALM_TYPE_PVP; - else - server_type = getIntConfig(CONFIG_GAME_TYPE); - + uint32 server_type = IsFFAPvPRealm() ? uint32(REALM_TYPE_PVP) : getIntConfig(CONFIG_GAME_TYPE); uint32 realm_zone = getIntConfig(CONFIG_REALM_ZONE); LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID); // One-time query @@ -1398,8 +1393,8 @@ void World::SetInitialWorldSettings() sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Item Random Enchantments Table..."); LoadRandomEnchantmentsTable(); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Disables"); - DisableMgr::LoadDisables(); // must be before loading quests and items + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Disables"); // must be before loading quests and items + DisableMgr::LoadDisables(); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Items..."); // must be after LoadRandomEnchantmentsTable and LoadPageTexts sObjectMgr->LoadItemTemplates(); @@ -1579,9 +1574,11 @@ void World::SetInitialWorldSettings() ///- Load dynamic data tables from the database sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Item Auctions..."); sAuctionMgr->LoadAuctionItems(); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Auctions..."); sAuctionMgr->LoadAuctions(); + sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Guilds..."); sGuildMgr->LoadGuilds(); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading ArenaTeams..."); @@ -1843,7 +1840,6 @@ void World::DetectDBCLang() m_defaultDbcLocale = LocaleConstant(default_locale); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Using %s DBC Locale as default. All available DBC locales: %s", localeNames[m_defaultDbcLocale], availableLocalsStr.empty() ? "" : availableLocalsStr.c_str()); - } void World::RecordTimeDiff(const char *text, ...) @@ -1883,7 +1879,6 @@ void World::LoadAutobroadcasts() if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 autobroadcasts definitions. DB table `autobroadcast` is empty!"); - return; } @@ -1891,7 +1886,6 @@ void World::LoadAutobroadcasts() do { - Field* fields = result->Fetch(); std::string message = fields[0].GetString(); @@ -1900,8 +1894,7 @@ void World::LoadAutobroadcasts() ++count; } while (result->NextRow()); - sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u autobroadcasts definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); - + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u autobroadcast definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } /// Update the World ! @@ -2951,8 +2944,8 @@ void World::LoadDBVersion() if (result) { Field* fields = result->Fetch(); - m_DBVersion = fields[0].GetString(); + m_DBVersion = fields[0].GetString(); // will be overwrite by config values if different and non-0 m_int_configs[CONFIG_CLIENTCACHE_VERSION] = fields[1].GetUInt32(); } -- cgit v1.2.3 From 53a3373a985e4c266ed0197e9e537d3de1ffab33 Mon Sep 17 00:00:00 2001 From: Spp Date: Thu, 24 Jan 2013 16:56:32 +0100 Subject: Core/Logging: Fix all possible crashes when using bad Appender config settings --- src/server/shared/Logging/Log.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index 48512852dc4..f5ef6dfcc5b 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -89,8 +89,9 @@ void Log::CreateAppenderFromConfig(const char* name) options = ConfigMgr::GetStringDefault(options.c_str(), ""); Tokenizer tokens(options, ','); Tokenizer::const_iterator iter = tokens.begin(); + uint8 size = tokens.size(); - if (tokens.size() < 2) + if (size < 2) { fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong configuration for appender %s. Config line: %s\n", name, options.c_str()); return; @@ -98,16 +99,15 @@ void Log::CreateAppenderFromConfig(const char* name) AppenderFlags flags = APPENDER_FLAGS_NONE; AppenderType type = AppenderType(atoi(*iter)); - ++iter; - LogLevel level = LogLevel(atoi(*iter)); + LogLevel level = LogLevel(atoi(*(++iter))); if (level > LOG_LEVEL_FATAL) { fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong Log Level %d for appender %s\n", level, name); return; } - if (++iter != tokens.end()) - flags = AppenderFlags(atoi(*iter)); + if (size > 2) + flags = AppenderFlags(atoi(*(++iter))); switch (type) { @@ -115,7 +115,7 @@ void Log::CreateAppenderFromConfig(const char* name) { AppenderConsole* appender = new AppenderConsole(NextAppenderId(), name, level, flags); appenders[appender->getId()] = appender; - if (++iter != tokens.end()) + if (iter != tokens.end()) appender->InitColors(*iter); //fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type CONSOLE, Mask %u\n", appender->getName().c_str(), appender->getId(), appender->getLogLevel()); // DEBUG - RemoveMe break; @@ -125,16 +125,16 @@ void Log::CreateAppenderFromConfig(const char* name) std::string filename; std::string mode = "a"; - if (++iter == tokens.end()) + if (size < 4) { fprintf(stderr, "Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name); return; } - filename = *iter; + filename = *(++iter); - if (++iter != tokens.end()) - mode = *iter; + if (size > 4) + mode = *(++iter); if (flags & APPENDER_FLAGS_USE_TIMESTAMP) { @@ -146,11 +146,8 @@ void Log::CreateAppenderFromConfig(const char* name) } uint64 maxFileSize = 0; - if ( (iter != tokens.end()) && (++iter != tokens.end()) ) - { - char const* c = *iter; - maxFileSize = atoi(c); - } + if (size > 5) + maxFileSize = atoi(*(++iter)); uint8 id = NextAppenderId(); appenders[id] = new AppenderFile(id, name, level, filename.c_str(), m_logsDir.c_str(), mode.c_str(), flags, maxFileSize); -- cgit v1.2.3 From bf0c976f76d3ae2078f503748888f1eaf5586b2b Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 24 Jan 2013 17:23:34 +0100 Subject: Core/Players: Fixed uninitialized variable for item swaps --- src/server/game/Entities/Player/Player.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index fbc40db790e..66162142fdc 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -11491,7 +11491,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool // should ignore the item we are trying to swap, and not the // destination item. CanEquipUniqueItem should ignore destination // item only when we are swapping weapon from bag - uint8 ignore; + uint8 ignore = uint8(NULL_SLOT); switch (eslot) { case EQUIPMENT_SLOT_MAINHAND: @@ -11513,7 +11513,8 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool ignore = EQUIPMENT_SLOT_TRINKET1; break; } - if (pItem != GetItemByPos(INVENTORY_SLOT_BAG_0, ignore)) + + if (ignore == uint8(NULL_SLOT) || pItem != GetItemByPos(INVENTORY_SLOT_BAG_0, ignore)) ignore = eslot; InventoryResult res2 = CanEquipUniqueItem(pItem, swap ? ignore : uint8(NULL_SLOT)); -- cgit v1.2.3 From 0d3cc3ae3acdf3e92af4b027b822666b20352774 Mon Sep 17 00:00:00 2001 From: Spp Date: Thu, 24 Jan 2013 21:50:58 +0100 Subject: Core/Log: Fix console colors (missing change from 53a3373) Closes #9051 --- src/server/shared/Logging/Log.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index f5ef6dfcc5b..920ce4ce570 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -115,8 +115,8 @@ void Log::CreateAppenderFromConfig(const char* name) { AppenderConsole* appender = new AppenderConsole(NextAppenderId(), name, level, flags); appenders[appender->getId()] = appender; - if (iter != tokens.end()) - appender->InitColors(*iter); + if (size > 3) + appender->InitColors(*(++iter)); //fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type CONSOLE, Mask %u\n", appender->getName().c_str(), appender->getId(), appender->getLogLevel()); // DEBUG - RemoveMe break; } -- cgit v1.2.3 From 1c7ade5e54454d285c843e633f69b911a1d81fb9 Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 24 Jan 2013 22:46:45 +0100 Subject: Scripts/Icecrown Citadel: Fixed Deathbringer Saurfang's Blood Power scaling on first attempt. Closes #3283 --- .../IcecrownCitadel/boss_deathbringer_saurfang.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 23e4fc19dd2..d688205938a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -415,6 +415,13 @@ class boss_deathbringer_saurfang : public CreatureScript } } + void SpellHit(Unit* caster, SpellInfo const* spell) + { + if (spell->Id == SPELL_BLOOD_LINK_POWER) + if (Aura* bloodPower = me->GetAura(SPELL_BLOOD_POWER)) + bloodPower->RecalculateAmountOfEffects(); + } + void UpdateAI(uint32 const diff) { if (!UpdateVictim() && !(events.GetPhaseMask() & PHASE_INTRO_MASK)) @@ -1004,8 +1011,6 @@ class spell_deathbringer_blood_link : public SpellScriptLoader void HandleDummy(SpellEffIndex /*effIndex*/) { GetHitUnit()->CastCustomSpell(SPELL_BLOOD_LINK_POWER, SPELLVALUE_BASE_POINT0, GetEffectValue(), GetHitUnit(), true); - if (Aura* bloodPower = GetHitUnit()->GetAura(SPELL_BLOOD_POWER)) - bloodPower->RecalculateAmountOfEffects(); PreventHitDefaultEffect(EFFECT_0); } @@ -1093,13 +1098,6 @@ class spell_deathbringer_blood_power : public SpellScriptLoader DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_deathbringer_blood_power_AuraScript::RecalculateHook, EFFECT_0, SPELL_AURA_MOD_SCALE); DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_deathbringer_blood_power_AuraScript::RecalculateHook, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); } - - bool Load() - { - if (GetUnitOwner()->getPowerType() != POWER_ENERGY) - return false; - return true; - } }; SpellScript* GetSpellScript() const -- cgit v1.2.3 From 705d0c88657e04ee0b4610e2f40ba9378228d670 Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 24 Jan 2013 22:51:42 +0100 Subject: Scripts/Icecrown Citadel: Fixed possible crash with Bone Spike Graveyard Closes #7171 --- .../Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index e751ec2bd7b..4763896cf72 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -53,7 +53,7 @@ enum Spells SPELL_COLDFLAME_SUMMON = 69147, }; -uint32 const boneSpikeSummonId[3] = {69062, 72669, 72670}; +uint32 const BoneSpikeSummonId[3] = {69062, 72669, 72670}; enum Events { @@ -515,6 +515,20 @@ class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader { PrepareSpellScript(spell_marrowgar_bone_spike_graveyard_SpellScript); + bool Validate(SpellInfo const* /*spell*/) + { + for (uint32 i = 0; i < 3; ++i) + if (!sSpellMgr->GetSpellInfo(BoneSpikeSummonId[i])) + return false; + + return true; + } + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT && GetCaster()->IsAIEnabled; + } + SpellCastResult CheckCast() { return GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1, 0.0f, true, -SPELL_IMPALED) ? SPELL_CAST_OK : SPELL_FAILED_NO_VALID_TARGETS; @@ -536,7 +550,7 @@ class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader break; didHit = true; - target->CastCustomSpell(boneSpikeSummonId[i], SPELLVALUE_BASE_POINT0, 0, target, true); + target->CastCustomSpell(BoneSpikeSummonId[i], SPELLVALUE_BASE_POINT0, 0, target, true); } if (didHit) -- cgit v1.2.3 From c36aa6e7af667580d9a8e4da9971ce8a33e9352b Mon Sep 17 00:00:00 2001 From: thomas33 Date: Fri, 25 Jan 2013 12:25:06 +0100 Subject: fix typo --- src/server/game/Globals/ObjectMgr.cpp | 2 +- src/server/shared/Database/Implementation/WorldDatabase.cpp | 2 +- src/server/shared/Database/Implementation/WorldDatabase.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 30257797470..891bc9b253a 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -4730,7 +4730,7 @@ void ObjectMgr::LoadWaypointScripts() for (ScriptMapMap::const_iterator itr = sWaypointScripts.begin(); itr != sWaypointScripts.end(); ++itr) actionSet.insert(itr->first); - PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WOLRD_SEL_WAYPOINT_DATA_ACTION); + PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_ACTION); PreparedQueryResult result = WorldDatabase.Query(stmt); if (result) diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp index 399a4eeb031..b807736f47b 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp @@ -60,7 +60,7 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_UPD_WAYPOINT_DATA_ALL_WPGUID, "UPDATE waypoint_data SET wpguid = 0", CONNECTION_ASYNC); PrepareStatement(WORLD_SEL_WAYPOINT_DATA_BY_POS, "SELECT id, point FROM waypoint_data WHERE (abs(position_x - ?) <= ?) and (abs(position_y - ?) <= ?) and (abs(position_z - ?) <= ?)", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_WAYPOINT_DATA_WPGUID_BY_ID, "SELECT wpguid FROM waypoint_data WHERE id = ? and wpguid <> 0", CONNECTION_SYNCH); - PrepareStatement(WOLRD_SEL_WAYPOINT_DATA_ACTION, "SELECT DISTINCT action FROM waypoint_data", CONNECTION_SYNCH); + PrepareStatement(WORLD_SEL_WAYPOINT_DATA_ACTION, "SELECT DISTINCT action FROM waypoint_data", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPTS_MAX_ID, "SELECT MAX(guid) FROM waypoint_scripts", CONNECTION_SYNCH); PrepareStatement(WORLD_INS_CREATURE_ADDON, "INSERT INTO creature_addon(guid, path_id) VALUES (?, ?)", CONNECTION_ASYNC); PrepareStatement(WORLD_UPD_CREATURE_ADDON_PATH, "UPDATE creature_addon SET path_id = ? WHERE guid = ?", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/Implementation/WorldDatabase.h b/src/server/shared/Database/Implementation/WorldDatabase.h index 30cc45c535a..032baf29dd9 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.h +++ b/src/server/shared/Database/Implementation/WorldDatabase.h @@ -80,7 +80,7 @@ enum WorldDatabaseStatements WORLD_SEL_WAYPOINT_DATA_MAX_POINT, WORLD_SEL_WAYPOINT_DATA_BY_POS, WORLD_SEL_WAYPOINT_DATA_WPGUID_BY_ID, - WOLRD_SEL_WAYPOINT_DATA_ACTION, + WORLD_SEL_WAYPOINT_DATA_ACTION, WORLD_SEL_WAYPOINT_SCRIPTS_MAX_ID, WORLD_UPD_CREATURE_ADDON_PATH, WORLD_INS_CREATURE_ADDON, -- cgit v1.2.3 From 61495d18a3423d5b7f44425f902342d4a3a3892c Mon Sep 17 00:00:00 2001 From: Machiavelli Date: Fri, 25 Jan 2013 21:40:21 +0100 Subject: Core/Log: Fix crash due to uninitialized variable --- src/server/shared/Logging/AppenderFile.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp index 1ed6350f813..25141815de6 100644 --- a/src/server/shared/Logging/AppenderFile.cpp +++ b/src/server/shared/Logging/AppenderFile.cpp @@ -24,7 +24,8 @@ AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, co logDir(_logDir), mode(_mode), maxFileSize(fileSize), - fileSize(0) + fileSize(0), + logfile(NULL) { dynamicName = std::string::npos != filename.find("%s"); backup = _flags & APPENDER_FLAGS_MAKE_FILE_BACKUP; -- cgit v1.2.3 From 6acfa490659875af8ea546aa223d07b3c9ad21cc Mon Sep 17 00:00:00 2001 From: w1sht0l1v3 Date: Sat, 26 Jan 2013 00:41:46 +0200 Subject: Script/Commands: Implement command to list the members of a group/party. --- sql/updates/world/2013_01_26_00_world_misc.sql | 8 +++ src/server/game/Miscellaneous/Language.h | 4 +- src/server/scripts/Commands/cs_misc.cpp | 75 ++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 sql/updates/world/2013_01_26_00_world_misc.sql (limited to 'src') diff --git a/sql/updates/world/2013_01_26_00_world_misc.sql b/sql/updates/world/2013_01_26_00_world_misc.sql new file mode 100644 index 00000000000..429d900d765 --- /dev/null +++ b/sql/updates/world/2013_01_26_00_world_misc.sql @@ -0,0 +1,8 @@ +DELETE FROM `trinity_string` WHERE `entry` IN (1149,1150); +INSERT INTO `trinity_string` (`entry`,`content_default`,`content_loc1`,`content_loc2`,`content_loc3`,`content_loc4`,`content_loc5`,`content_loc6`,`content_loc7`,`content_loc8`) VALUES +(1149,'Group type: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1150,'Name: %s (%s), GUID: %u, Flags: %s, Roles: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); + +DELETE FROM `command` WHERE `name`='group list'; +INSERT INTO `command` (`name`,`security`,`help`) VALUES +('group list',3,'Syntax: .group list [$CharacterName] \r\nLists all the members of the group/party the player is in.'); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 1aeb16e9c7e..8b416339bc7 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -851,7 +851,9 @@ enum TrinityStrings LANG_GROUP_PLAYER_JOINED = 1146, LANG_GROUP_NOT_IN_GROUP = 1147, LANG_GROUP_FULL = 1148, - // Room for more level 3 1149-1199 not used + LANG_GROUP_TYPE = 1149, + LANG_GROUP_PLAYER_NAME_GUID = 1150, + // Room for more level 3 1151-1199 not used // Debug commands LANG_CINEMATIC_NOT_EXIST = 1200, diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index e2b5ac9487d..3721f221178 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -33,6 +33,8 @@ #include "ace/INET_Addr.h" #include "Player.h" #include "Pet.h" +#include "LFG.h" +#include "GroupMGR.h" class misc_commandscript : public CommandScript { @@ -47,6 +49,7 @@ public: { "disband", SEC_ADMINISTRATOR, false, &HandleGroupDisbandCommand, "", NULL }, { "remove", SEC_ADMINISTRATOR, false, &HandleGroupRemoveCommand, "", NULL }, { "join", SEC_ADMINISTRATOR, false, &HandleGroupJoinCommand, "", NULL }, + { "list", SEC_ADMINISTRATOR, false, &HandleGroupListCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand petCommandTable[] = @@ -2781,6 +2784,78 @@ public: return true; } + static bool HandleGroupListCommand(ChatHandler* handler, char const* args) + { + Player* playerTarget; + uint64 guidTarget; + std::string nameTarget; + + uint32 parseGUID = MAKE_NEW_GUID(atol((char*)args), 0, HIGHGUID_PLAYER); + + if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget)) + { + playerTarget = sObjectMgr->GetPlayerByLowGUID(parseGUID); + guidTarget = parseGUID; + } + else if (!handler->extractPlayerTarget((char*)args, &playerTarget, &guidTarget, &nameTarget)) + return false; + + Group* groupTarget = NULL; + if (playerTarget) + groupTarget = playerTarget->GetGroup(); + + if (!groupTarget) + { + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER); + stmt->setUInt32(0, guidTarget); + PreparedQueryResult resultGroup = CharacterDatabase.Query(stmt); + if (resultGroup) + groupTarget = sGroupMgr->GetGroupByDbStoreId((*resultGroup)[0].GetUInt32()); + } + + if (groupTarget) + { + handler->PSendSysMessage(LANG_GROUP_TYPE, (groupTarget->isRaidGroup() ? "raid" : "party")); + Group::MemberSlotList const& members = groupTarget->GetMemberSlots(); + Group::MemberSlotList::const_iterator itr; + for (itr = members.begin(); itr != members.end(); ++itr) + { + std::ostringstream flags, roles; + if ((*itr).flags & MEMBER_FLAG_ASSISTANT) + flags << "Assistant "; + if ((*itr).flags & MEMBER_FLAG_MAINTANK) + flags << "MainTank "; + if ((*itr).flags & MEMBER_FLAG_MAINASSIST) + flags << "MainAssist "; + + if ((*itr).roles & PLAYER_ROLE_LEADER) + roles << "Leader "; + if ((*itr).roles & PLAYER_ROLE_TANK) + roles << "Tank "; + if ((*itr).roles & PLAYER_ROLE_HEALER) + roles << "Healer "; + if ((*itr).roles & PLAYER_ROLE_DAMAGE) + roles << "Damage "; + + Player* p = ObjectAccessor::FindPlayer((*itr).guid); + const char* onlineState = (p && p->IsInWorld()) ? "online" : "offline"; + + std::string flagsStr = (flags.str().empty()) ? "None" : flags.str(); + std::string rolesStr = (roles.str().empty()) ? "None" : roles.str(); + + handler->PSendSysMessage(LANG_GROUP_PLAYER_NAME_GUID, (*itr).name.c_str(), onlineState, GUID_LOPART((*itr).guid), flagsStr.c_str(), rolesStr.c_str()); + } + return true; + } + else + { + handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, nameTarget.c_str()); + return true; + } + + return true; + } + static bool HandlePlayAllCommand(ChatHandler* handler, char const* args) { if (!*args) -- cgit v1.2.3 From 1348e4e44d4a762abc338adbfc58bb22648fa4a9 Mon Sep 17 00:00:00 2001 From: WishToDie Date: Sat, 26 Jan 2013 00:57:10 +0200 Subject: Fix Typo. --- src/server/scripts/Commands/cs_misc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 3721f221178..3196e81a951 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -34,7 +34,7 @@ #include "Player.h" #include "Pet.h" #include "LFG.h" -#include "GroupMGR.h" +#include "GroupMgr.h" class misc_commandscript : public CommandScript { -- cgit v1.2.3 From a45f7fd878ba9060c3b4a38f353ac0de4b22c388 Mon Sep 17 00:00:00 2001 From: MrSmite Date: Sat, 19 Jan 2013 02:14:20 -0500 Subject: Adds CONF option to show quest levels in dialogs. Example: [13] Westfall Stew Default = 0 (off). Make sure to set UI.ShowQuestLevelsInDialogs to 1 to turn it on NOTES: * DO NOT supply the quest level when using commands such as .lookup quest, it is not actually part of the title (even though it will be printed in the result) * Also adds the level in the quest tracker and quest log * If locale is used, the level is added after the proper title is looked up * LUA Mods that offer this feature do not work properly with TC, most will not put the level in all dialogs. Users who have such mods should disable the mod's feature or they may see the quest level listed twice. Example: [13][13] Westfall Stew --- src/server/game/Entities/Creature/GossipDef.cpp | 35 +++++++++++++++++++++++++ src/server/game/Entities/Creature/GossipDef.h | 2 ++ src/server/game/World/World.cpp | 1 + src/server/game/World/World.h | 1 + src/server/worldserver/worldserver.conf.dist | 8 ++++++ 5 files changed, 47 insertions(+) (limited to 'src') diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index f5877a3b927..a26e84a5311 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -142,6 +142,9 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, uint64 objectGUID) const data << uint32(_questMenu.GetMenuItemCount()); // max count 0x20 + // Store this instead of checking the Singleton every loop iteration + bool questLevelInTitle = sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS); + for (uint8 i = 0; i < _questMenu.GetMenuItemCount(); ++i) { QuestMenuItem const& item = _questMenu.GetItem(i); @@ -160,6 +163,9 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, uint64 objectGUID) const if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(questID)) ObjectMgr::GetLocaleString(localeData->Title, locale, title); + if (questLevelInTitle) + AddQuestLevelToTitle(title, quest->GetQuestLevel()); + data << title; // max 0x200 } @@ -252,6 +258,10 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote eEmote, const std::string& Title size_t count_pos = data.wpos(); data << uint8 (_questMenu.GetMenuItemCount()); uint32 count = 0; + + // Store this instead of checking the Singleton every loop iteration + bool questLevelInTitle = sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS); + for (; count < _questMenu.GetMenuItemCount(); ++count) { QuestMenuItem const& qmi = _questMenu.GetItem(count); @@ -267,6 +277,9 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote eEmote, const std::string& Title if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(questID)) ObjectMgr::GetLocaleString(localeData->Title, locale, title); + if (questLevelInTitle) + AddQuestLevelToTitle(title, quest->GetQuestLevel()); + data << uint32(questID); data << uint32(qmi.QuestIcon); data << int32(quest->GetQuestLevel()); @@ -310,6 +323,9 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID, } } + if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) + AddQuestLevelToTitle(questTitle, quest->GetQuestLevel()); + WorldPacket data(SMSG_QUESTGIVER_QUEST_DETAILS, 100); // guess size data << uint64(npcGUID); data << uint64(0); // wotlk, something todo with quest sharing? @@ -499,6 +515,9 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const data << float(quest->GetPointY()); data << uint32(quest->GetPointOpt()); + if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) + AddQuestLevelToTitle(questTitle, quest->GetQuestLevel()); + data << questTitle; data << questObjectives; data << questDetails; @@ -545,6 +564,9 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, b } } + if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) + AddQuestLevelToTitle(questTitle, quest->GetQuestLevel()); + WorldPacket data(SMSG_QUESTGIVER_OFFER_REWARD, 50); // guess size data << uint64(npcGUID); data << uint32(quest->GetQuestId()); @@ -645,6 +667,9 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, uint64 npcGUID, return; } + if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) + AddQuestLevelToTitle(questTitle, quest->GetQuestLevel()); + WorldPacket data(SMSG_QUESTGIVER_REQUEST_ITEMS, 50); // guess size data << uint64(npcGUID); data << uint32(quest->GetQuestId()); @@ -694,3 +719,13 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, uint64 npcGUID, _session->SendPacket(&data); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), quest->GetQuestId()); } + +static void PlayerMenu::AddQuestLevelToTitle(std::string &title, int32 level) +{ + // Adds the quest level to the front of the quest title + // example: [13] Westfall Stew + + std::stringstream questTitlePretty; + questTitlePretty << "[" << level << "] " << title; + title = questTitlePretty.str(); +} diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h index 6c5f465bbf0..f13f19bba55 100644 --- a/src/server/game/Entities/Creature/GossipDef.h +++ b/src/server/game/Entities/Creature/GossipDef.h @@ -277,6 +277,8 @@ class PlayerMenu void SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, bool enableNext) const; void SendQuestGiverRequestItems(Quest const* quest, uint64 npcGUID, bool canComplete, bool closeOnCancel) const; + static void AddQuestLevelToTitle(std::string &title, int32 level); + private: GossipMenu _gossipMenu; QuestMenu _questMenu; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 26a7986bcb8..c43cbbd417e 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1224,6 +1224,7 @@ void World::LoadConfigSettings(bool reload) // misc m_bool_configs[CONFIG_PDUMP_NO_PATHS] = ConfigMgr::GetBoolDefault("PlayerDump.DisallowPaths", true); m_bool_configs[CONFIG_PDUMP_NO_OVERWRITE] = ConfigMgr::GetBoolDefault("PlayerDump.DisallowOverwrite", true); + m_bool_configs[CONFIG_UI_QUESTLEVELS_IN_DIALOGS] = ConfigMgr::GetBoolDefault("UI.ShowQuestLevelsInDialogs", false); // call ScriptMgr if we're reloading the configuration m_bool_configs[CONFIG_WINTERGRASP_ENABLE] = ConfigMgr::GetBoolDefault("Wintergrasp.Enable", false); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 4a7629cb3af..95c10329690 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -165,6 +165,7 @@ enum WorldBoolConfigs CONFIG_WARDEN_ENABLED, CONFIG_ENABLE_MMAPS, CONFIG_WINTERGRASP_ENABLE, + CONFIG_UI_QUESTLEVELS_IN_DIALOGS, // Should we add quest levels to the title in the NPC dialogs? BOOL_CONFIG_VALUE_COUNT }; diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 31d180df751..641fe1ebb62 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -2651,6 +2651,14 @@ PlayerDump.DisallowPaths = 1 PlayerDump.DisallowOverwrite = 1 +# +# UI.ShowQuestLevelsInDialogs +# Description: Show quest levels next to quest titles in UI dialogs +# Example: [13] Westfall Stew +# Default: 0 (do not show) + +UI.ShowQuestLevelsInDialogs = 0 + # ################################################################################################### -- cgit v1.2.3 From f0800d392655f9d55a8e16e64984fb1630f7c4fe Mon Sep 17 00:00:00 2001 From: w1sht0l1v3 Date: Sat, 26 Jan 2013 19:19:55 +0200 Subject: Scripts/ShadowmoonValley: Fixup script for Lord Illidan Stormrage quest to be doable. Notice: this whole script needs a proper rewrite(contains wrong Illidan npc id,bad dialogues,etc). --- .../scripts/Outland/zone_shadowmoon_valley.cpp | 75 +++++++++++++++------- 1 file changed, 52 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index 0a016f0923c..a1bfc0a090a 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -661,6 +661,7 @@ class npc_karynaku : public CreatureScript /*#### # npc_overlord_morghor +# this whole script is wrong and needs a rewrite.even the illidan npc used is the wrong one.npc id 23467 may be the correct one ####*/ enum eOverlordData { @@ -766,7 +767,7 @@ public: Player* player = Unit::GetPlayer(*me, PlayerGUID); Creature* Illi = Creature::GetCreature(*me, IllidanGUID); - if (!player || !Illi) + if (!player) { EnterEvadeMode(); return 0; @@ -794,14 +795,21 @@ public: return 2000; break; case 5: - Illi->SetVisible(true); - Illi->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (Illi) + { + Illi->SetVisible(true); + Illi->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Illi->SetDisplayId(21526); + } return 350; break; case 6: - Illi->CastSpell(Illi, SPELL_ONE, true); - Illi->SetTarget(me->GetGUID()); - me->SetTarget(IllidanGUID); + if (Illi) + { + Illi->CastSpell(Illi, SPELL_ONE, true); + Illi->SetTarget(me->GetGUID()); + me->SetTarget(IllidanGUID); + } return 2000; break; case 7: @@ -810,10 +818,15 @@ public: break; case 8: me->SetUInt32Value(UNIT_FIELD_BYTES_1, 8); - return 9000; + return 2500; + break; + case 9: + // missing text "Lord Illidan, this is the Dragonmaw that I, and others, have told you about. He will lead us to victory!" + return 5000; break; case 10: - Illi->AI()->Talk(LORD_ILLIDAN_SAY_1); + if (Illi) + Illi->AI()->Talk(LORD_ILLIDAN_SAY_1); return 5000; break; case 11: @@ -821,42 +834,53 @@ public: return 6000; break; case 12: - Illi->AI()->Talk(LORD_ILLIDAN_SAY_2); + if (Illi) + Illi->AI()->Talk(LORD_ILLIDAN_SAY_2); return 5500; break; case 13: - Illi->AI()->Talk(LORD_ILLIDAN_SAY_3); + if (Illi) + Illi->AI()->Talk(LORD_ILLIDAN_SAY_3); return 4000; break; case 14: - Illi->SetTarget(PlayerGUID); + if (Illi) + Illi->SetTarget(PlayerGUID); return 1500; break; case 15: - Illi->AI()->Talk(LORD_ILLIDAN_SAY_4); + if (Illi) + Illi->AI()->Talk(LORD_ILLIDAN_SAY_4); return 1500; break; case 16: - Illi->CastSpell(player, SPELL_TWO, true); + if (Illi) + Illi->CastSpell(player, SPELL_TWO, true); player->RemoveAurasDueToSpell(SPELL_THREE); player->RemoveAurasDueToSpell(SPELL_FOUR); return 5000; break; case 17: - Illi->AI()->Talk(LORD_ILLIDAN_SAY_5); + if (Illi) + Illi->AI()->Talk(LORD_ILLIDAN_SAY_5); return 5000; break; case 18: - Illi->AI()->Talk(LORD_ILLIDAN_SAY_6); + if (Illi) + Illi->AI()->Talk(LORD_ILLIDAN_SAY_6); return 5000; break; case 19: - Illi->AI()->Talk(LORD_ILLIDAN_SAY_7); + if (Illi) + Illi->AI()->Talk(LORD_ILLIDAN_SAY_7); return 5000; break; case 20: - Illi->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - Illi->SetDisableGravity(true); + if (Illi) + { + Illi->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + Illi->SetDisableGravity(true); + } return 500; break; case 21: @@ -864,8 +888,11 @@ public: return 500; break; case 22: - Illi->SetVisible(false); - Illi->setDeathState(JUST_DIED); + if (Illi) + { + Illi->SetVisible(false); + Illi->setDeathState(JUST_DIED); + } return 1000; break; case 23: @@ -886,7 +913,7 @@ public: break; case 27: { - Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50); + Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50.0f); if (Yarzill) Yarzill->SetTarget(PlayerGUID); return 500; @@ -921,9 +948,11 @@ public: } break; case 32: - me->GetMotionMaster()->MovePoint(0, -5085.77f, 577.231f, 86.6719f); return 5000; + me->GetMotionMaster()->MovePoint(0, -5085.77f, 577.231f, 86.6719f); + return 5000; break; case 33: + me->SetTarget(0); Reset(); return 100; break; @@ -940,7 +969,7 @@ public: if (ConversationTimer <= diff) { - if (Event && IllidanGUID && PlayerGUID) + if (Event && PlayerGUID) ConversationTimer = NextStep(++Step); } else ConversationTimer -= diff; } -- cgit v1.2.3 From 18f5de77c3efb73a781e40a81d3a1438bc1f1b11 Mon Sep 17 00:00:00 2001 From: Nay Date: Sat, 26 Jan 2013 17:48:47 +0000 Subject: Core/GossipDef: Fix a build error from 9812afe08be *slaps MrSmite* --- src/server/game/Entities/Creature/GossipDef.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index a26e84a5311..a2305a8a56d 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -720,7 +720,7 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, uint64 npcGUID, sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), quest->GetQuestId()); } -static void PlayerMenu::AddQuestLevelToTitle(std::string &title, int32 level) +void PlayerMenu::AddQuestLevelToTitle(std::string &title, int32 level) { // Adds the quest level to the front of the quest title // example: [13] Westfall Stew -- cgit v1.2.3 From 480c8471566c36081ea5602380408363dde307c1 Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Sat, 26 Jan 2013 19:48:54 +0100 Subject: Core: Some cosmetic changes --- src/server/game/Entities/Player/Player.cpp | 2 +- src/server/game/Scripting/ScriptLoader.cpp | 4 ++-- src/server/scripts/Spells/spell_hunter.cpp | 8 ++++---- src/server/scripts/Spells/spell_priest.cpp | 12 ++++++------ src/server/scripts/Spells/spell_shaman.cpp | 6 +++--- src/server/scripts/Spells/spell_warlock.cpp | 8 ++++---- 6 files changed, 20 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 66162142fdc..82a1164b423 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -14291,7 +14291,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool VendorItemData const* vendorItems = creature->GetVendorItems(); if (!vendorItems || vendorItems->Empty()) { - sLog->outError(LOG_FILTER_SQL, "Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.", creature->GetGUIDLow(), creature->GetEntry()); + sLog->outError(LOG_FILTER_SQL, "Creature (GUID: %u, Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.", creature->GetGUIDLow(), creature->GetEntry()); canTalk = false; } break; diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 3da9ac8fade..efd45188d42 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -66,6 +66,7 @@ void AddSC_list_commandscript(); void AddSC_lookup_commandscript(); void AddSC_message_commandscript(); void AddSC_misc_commandscript(); +void AddSC_mmaps_commandscript(); void AddSC_modify_commandscript(); void AddSC_npc_commandscript(); void AddSC_quest_commandscript(); @@ -76,7 +77,6 @@ void AddSC_tele_commandscript(); void AddSC_ticket_commandscript(); void AddSC_titles_commandscript(); void AddSC_wp_commandscript(); -void AddSC_mmaps_commandscript(); #ifdef SCRIPTS //world @@ -696,6 +696,7 @@ void AddCommandScripts() AddSC_list_commandscript(); AddSC_message_commandscript(); AddSC_misc_commandscript(); + AddSC_mmaps_commandscript(); AddSC_modify_commandscript(); AddSC_npc_commandscript(); AddSC_quest_commandscript(); @@ -706,7 +707,6 @@ void AddCommandScripts() AddSC_ticket_commandscript(); AddSC_titles_commandscript(); AddSC_wp_commandscript(); - AddSC_mmaps_commandscript(); } void AddWorldScripts() diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 877248cf1a8..891a7daaa1f 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -38,7 +38,7 @@ enum HunterSpells SPELL_HUNTER_CHIMERA_SHOT_SERPENT = 53353, SPELL_HUNTER_CHIMERA_SHOT_VIPER = 53358, SPELL_HUNTER_CHIMERA_SHOT_SCORPID = 53359, - SPELL_HUNTER_GLYPHE_OF_ASPECT_OF_THE_VIPER = 56851, + SPELL_HUNTER_GLYPH_OF_ASPECT_OF_THE_VIPER = 56851, SPELL_HUNTER_INVIGORATION_TRIGGERED = 53398, SPELL_HUNTER_MASTERS_CALL_TRIGGERED = 62305, SPELL_HUNTER_MISDIRECTION_PROC = 35079, @@ -116,7 +116,7 @@ class spell_hun_ascpect_of_the_viper : public SpellScriptLoader { if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_ASPECT_OF_THE_VIPER_ENERGIZE)) return false; - if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_GLYPHE_OF_ASPECT_OF_THE_VIPER)) + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_GLYPH_OF_ASPECT_OF_THE_VIPER)) return false; return true; } @@ -128,8 +128,8 @@ class spell_hun_ascpect_of_the_viper : public SpellScriptLoader uint32 maxMana = GetTarget()->GetMaxPower(POWER_MANA); int32 mana = CalculatePct(maxMana, GetTarget()->GetAttackTime(RANGED_ATTACK) / 1000.0f); - if (AuraEffect const* glyphe = GetTarget()->GetAuraEffect(SPELL_HUNTER_GLYPHE_OF_ASPECT_OF_THE_VIPER, EFFECT_0)) - AddPct(mana, glyphe->GetAmount()); + if (AuraEffect const* glyph = GetTarget()->GetAuraEffect(SPELL_HUNTER_GLYPH_OF_ASPECT_OF_THE_VIPER, EFFECT_0)) + AddPct(mana, glyph->GetAmount()); GetTarget()->CastCustomSpell(SPELL_HUNTER_ASPECT_OF_THE_VIPER_ENERGIZE, SPELLVALUE_BASE_POINT0, mana, GetTarget(), true, NULL, aurEff); } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index e19110d0f62..4e86a895484 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -31,8 +31,8 @@ enum PriestSpells { SPELL_PRIEST_DIVINE_AEGIS = 47753, SPELL_PRIEST_EMPOWERED_RENEW = 63544, - SPELL_PRIEST_GLYPHE_OF_LIGHTWELL = 55673, - SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL = 56161, + SPELL_PRIEST_GLYPH_OF_LIGHTWELL = 55673, + SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL = 56161, SPELL_PRIEST_GUARDIAN_SPIRIT_HEAL = 48153, SPELL_PRIEST_MANA_LEECH_PROC = 34650, SPELL_PRIEST_PENANCE_R1 = 47540, @@ -114,7 +114,7 @@ class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader bool Validate(SpellInfo const* /*spellInfo*/) { - if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL)) + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL)) return false; return true; } @@ -123,9 +123,9 @@ class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader { PreventDefaultAction(); - SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL); + SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL); int32 heal = int32(CalculatePct(int32(eventInfo.GetHealInfo()->GetHeal()), aurEff->GetAmount()) / triggeredSpellInfo->GetMaxTicks()); - GetTarget()->CastCustomSpell(SPELL_PRIEST_GLYPHE_OF_PRAYER_OF_HEALING_HEAL, SPELLVALUE_BASE_POINT0, heal, eventInfo.GetProcTarget(), true, NULL, aurEff); + GetTarget()->CastCustomSpell(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL, SPELLVALUE_BASE_POINT0, heal, eventInfo.GetProcTarget(), true, NULL, aurEff); } void Register() @@ -212,7 +212,7 @@ class spell_pri_lightwell_renew : public SpellScriptLoader if (Unit* caster = GetCaster()) { // Bonus from Glyph of Lightwell - if (AuraEffect* modHealing = caster->GetAuraEffect(SPELL_PRIEST_GLYPHE_OF_LIGHTWELL, EFFECT_0)) + if (AuraEffect* modHealing = caster->GetAuraEffect(SPELL_PRIEST_GLYPH_OF_LIGHTWELL, EFFECT_0)) AddPct(amount, modHealing->GetAmount()); } } diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index b69295150c2..f970807bb94 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -296,9 +296,9 @@ class spell_sha_earth_shield : public SpellScriptLoader // Glyph of Earth Shield //! WORKAROUND - //! this glyphe is a proc - if (AuraEffect* glyphe = caster->GetAuraEffect(SPELL_SHAMAN_GLYPH_OF_EARTH_SHIELD, EFFECT_0)) - AddPct(amount, glyphe->GetAmount()); + //! this glyph is a proc + if (AuraEffect* glyph = caster->GetAuraEffect(SPELL_SHAMAN_GLYPH_OF_EARTH_SHIELD, EFFECT_0)) + AddPct(amount, glyph->GetAmount()); } } diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 78bfcbab6a0..a9a4b2d749a 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -38,7 +38,7 @@ enum WarlockSpells SPELL_WARLOCK_DEMONIC_EMPOWERMENT_FELHUNTER = 54509, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_IMP = 54444, SPELL_WARLOCK_FEL_SYNERGY_HEAL = 54181, - SPELL_WARLOCK_GLYPHE_OF_SIPHON_LIFE = 63106, + SPELL_WARLOCK_GLYPH_OF_SIPHON_LIFE = 63106, SPELL_WARLOCK_IMPROVED_HEALTHSTONE_R1 = 18692, SPELL_WARLOCK_IMPROVED_HEALTHSTONE_R2 = 18693, SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_R1 = 18703, @@ -746,7 +746,7 @@ class spell_warl_siphon_life : public SpellScriptLoader { if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_SIPHON_LIFE_HEAL)) return false; - if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_GLYPHE_OF_SIPHON_LIFE)) + if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_GLYPH_OF_SIPHON_LIFE)) return false; return true; } @@ -762,8 +762,8 @@ class spell_warl_siphon_life : public SpellScriptLoader int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount())); // Glyph of Siphon Life - if (AuraEffect const* glyphe = GetTarget()->GetAuraEffect(SPELL_WARLOCK_GLYPHE_OF_SIPHON_LIFE, EFFECT_0)) - AddPct(amount, glyphe->GetAmount()); + if (AuraEffect const* glyph = GetTarget()->GetAuraEffect(SPELL_WARLOCK_GLYPH_OF_SIPHON_LIFE, EFFECT_0)) + AddPct(amount, glyph->GetAmount()); GetTarget()->CastCustomSpell(SPELL_WARLOCK_SIPHON_LIFE_HEAL, SPELLVALUE_BASE_POINT0, amount, GetTarget(), true, NULL, aurEff); } -- cgit v1.2.3 From ceed5ea42f046b0b91e41f877bc53b6436e04a69 Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Sat, 26 Jan 2013 19:57:11 +0100 Subject: Scripts/Icecrown Citadel: Fix warning --- .../scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index d688205938a..af727348719 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -415,7 +415,7 @@ class boss_deathbringer_saurfang : public CreatureScript } } - void SpellHit(Unit* caster, SpellInfo const* spell) + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) { if (spell->Id == SPELL_BLOOD_LINK_POWER) if (Aura* bloodPower = me->GetAura(SPELL_BLOOD_POWER)) -- cgit v1.2.3 From 1b551cc157a3324e0523abca55138fd7af10b2ca Mon Sep 17 00:00:00 2001 From: Nay Date: Sat, 26 Jan 2013 21:31:48 +0000 Subject: Scripts/Commands: Add guild info to .pinfo Original patch by @secharles, modified Closes #8946 --- .../world/2013_01_26_05_world_misc_pinfo.sql | 5 +++++ src/server/game/Miscellaneous/Language.h | 1 + src/server/scripts/Commands/cs_misc.cpp | 23 ++++++++++++++++++++++ .../Database/Implementation/CharacterDatabase.cpp | 1 + .../Database/Implementation/CharacterDatabase.h | 1 + 5 files changed, 31 insertions(+) create mode 100644 sql/updates/world/2013_01_26_05_world_misc_pinfo.sql (limited to 'src') diff --git a/sql/updates/world/2013_01_26_05_world_misc_pinfo.sql b/sql/updates/world/2013_01_26_05_world_misc_pinfo.sql new file mode 100644 index 00000000000..2c0a28066d4 --- /dev/null +++ b/sql/updates/world/2013_01_26_05_world_misc_pinfo.sql @@ -0,0 +1,5 @@ +DELETE FROM `trinity_string` WHERE `entry`=749; +INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES +(749, 'Guild: %s (%u) Rank: %s Note: %s OffNote: %s'); + +UPDATE `command` SET `help`='Syntax: .pinfo [$player_name/#GUID]\r\n\r\nOutput account information and guild information for selected player or player find by $player_name or #GUID.' WHERE `name`='pinfo'; diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 8b416339bc7..e13cc86747c 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -522,6 +522,7 @@ enum TrinityStrings LANG_PINFO_BAN = 453, LANG_PINFO_MAP_ONLINE = 714, LANG_PINFO_MAP_OFFLINE = 716, + LANG_PINFO_GUILD_INFO = 749, LANG_YOU_SET_EXPLORE_ALL = 551, LANG_YOU_SET_EXPLORE_NOTHING = 552, diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 3196e81a951..367591080d2 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1734,6 +1734,29 @@ public: else handler->PSendSysMessage(LANG_PINFO_MAP_OFFLINE, map->name[locale], areaName.c_str()); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER_EXTENDED); + stmt->setUInt32(0, GUID_LOPART(targetGuid)); + + result = CharacterDatabase.Query(stmt); + if (result) + { + uint32 guildId = 0; + std::string guildName = ""; + std::string guildRank = ""; + std::string note = ""; + std::string officeNote = ""; + + Field* fields = result->Fetch(); + guildId = fields[0].GetUInt32(); + guildName = fields[1].GetString(); + //rankId = fields[2].GetUInt8(); + guildRank = fields[3].GetString(); + note = fields[4].GetString(); + officeNote = fields[5].GetString(); + + handler->PSendSysMessage(LANG_PINFO_GUILD_INFO, guildName.c_str(), guildId, guildRank.c_str(), note.c_str(), officeNote.c_str()); + } + return true; } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 1c2410b8b53..b3d818c7565 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -101,6 +101,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHARACTER_SPELLCOOLDOWNS, "SELECT spell, item, time FROM character_spell_cooldown WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_DECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_GUILD_MEMBER, "SELECT guildid, rank FROM guild_member WHERE guid = ?", CONNECTION_BOTH); + PrepareStatement(CHAR_SEL_GUILD_MEMBER_EXTENDED, "SELECT g.guildid, g.name, gm.rank, gr.rname, gm.pnote, gm.offnote FROM guild g JOIN guild_member gm ON g.guildid = gm.guildid JOIN guild_rank gr ON g.guildid = gr.guildid WHERE gm.guid = ?", CONNECTION_BOTH); PrepareStatement(CHAR_SEL_CHARACTER_ACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_CRITERIAPROGRESS, "SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_EQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, ignore_mask, item0, item1, item2, item3, item4, item5, item6, item7, item8, " diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index e4728e19934..7c064a98e17 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -105,6 +105,7 @@ enum CharacterDatabaseStatements CHAR_SEL_CHARACTER_SPELLCOOLDOWNS, CHAR_SEL_CHARACTER_DECLINEDNAMES, CHAR_SEL_GUILD_MEMBER, + CHAR_SEL_GUILD_MEMBER_EXTENDED, CHAR_SEL_CHARACTER_ARENAINFO, CHAR_SEL_CHARACTER_ACHIEVEMENTS, CHAR_SEL_CHARACTER_CRITERIAPROGRESS, -- cgit v1.2.3 From e1d12de2b14534e35916e58afbe4e7016f0b6ff7 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 27 Jan 2013 11:56:56 +0100 Subject: Core/Battlegrounds: Fixed arena scoreboards not showing all players. --- src/server/game/Battlegrounds/BattlegroundMgr.cpp | 25 +++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 24e69a151b5..6133bd60258 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -589,6 +589,27 @@ Battleground* BattlegroundMgr::CreateNewBattleground(BattlegroundTypeId original bg->SetRated(isRated); bg->SetRandom(isRandom); + // Set up correct min/max player counts for scoreboards + if (bg->isArena()) + { + uint32 maxPlayersPerTeam = 0; + switch (arenaType) + { + case ARENA_TYPE_2v2: + maxPlayersPerTeam = 2; + break; + case ARENA_TYPE_3v3: + maxPlayersPerTeam = 3; + break; + case ARENA_TYPE_5v5: + maxPlayersPerTeam = 5; + break; + } + + bg->SetMaxPlayersPerTeam(maxPlayersPerTeam); + bg->SetMaxPlayers(maxPlayersPerTeam * 2); + } + return bg; } @@ -649,8 +670,8 @@ bool BattlegroundMgr::CreateBattleground(CreateBattlegroundData& data) bg->SetArenaorBGType(data.IsArena); bg->SetMinPlayersPerTeam(data.MinPlayersPerTeam); bg->SetMaxPlayersPerTeam(data.MaxPlayersPerTeam); - bg->SetMinPlayers(data.MinPlayersPerTeam* 2); - bg->SetMaxPlayers(data.MaxPlayersPerTeam* 2); + bg->SetMinPlayers(data.MinPlayersPerTeam * 2); + bg->SetMaxPlayers(data.MaxPlayersPerTeam * 2); bg->SetName(data.BattlegroundName); bg->SetTeamStartLoc(ALLIANCE, data.Team1StartLocX, data.Team1StartLocY, data.Team1StartLocZ, data.Team1StartLocO); bg->SetTeamStartLoc(HORDE, data.Team2StartLocX, data.Team2StartLocY, data.Team2StartLocZ, data.Team2StartLocO); -- cgit v1.2.3 From 6e80357f8e8b4e820bab8bd05fb8457c3cb46d11 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 27 Jan 2013 17:33:01 +0100 Subject: Core/Authserver: Added possibility to allow realm connections both from "world" and local networks. --- sql/base/auth_database.sql | 2 ++ sql/updates/auth/2013_01_27_00_auth_realmlist.sql | 3 ++ src/server/authserver/Realms/RealmList.cpp | 42 ++++++++++++---------- src/server/authserver/Realms/RealmList.h | 6 ++-- src/server/authserver/Server/AuthSocket.cpp | 30 +++++++++++++++- src/server/authserver/Server/AuthSocket.h | 5 +++ .../Database/Implementation/LoginDatabase.cpp | 2 +- src/server/shared/Utilities/Util.cpp | 16 ++++++++- src/server/shared/Utilities/Util.h | 8 +++++ 9 files changed, 91 insertions(+), 23 deletions(-) create mode 100644 sql/updates/auth/2013_01_27_00_auth_realmlist.sql (limited to 'src') diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index a052a74c837..5050906b008 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -193,6 +193,8 @@ CREATE TABLE `realmlist` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL DEFAULT '', `address` varchar(255) NOT NULL DEFAULT '127.0.0.1', + `localAddress` varchar(255) NOT NULL DEFAULT '127.0.0.1', + `localSubnetMask` varchar(255) NOT NULL DEFAULT '255.255.255.0', `port` smallint(5) unsigned NOT NULL DEFAULT '8085', `icon` tinyint(3) unsigned NOT NULL DEFAULT '0', `flag` tinyint(3) unsigned NOT NULL DEFAULT '2', diff --git a/sql/updates/auth/2013_01_27_00_auth_realmlist.sql b/sql/updates/auth/2013_01_27_00_auth_realmlist.sql new file mode 100644 index 00000000000..0c3b18448e6 --- /dev/null +++ b/sql/updates/auth/2013_01_27_00_auth_realmlist.sql @@ -0,0 +1,3 @@ +ALTER TABLE `realmlist` + ADD `localAddress` varchar(255) NOT NULL DEFAULT '127.0.0.1' AFTER `address`, + ADD `localSubnetMask` varchar(255) NOT NULL DEFAULT '255.255.255.0' AFTER `localAddress`; diff --git a/src/server/authserver/Realms/RealmList.cpp b/src/server/authserver/Realms/RealmList.cpp index 72873e40ce5..b4becc96451 100644 --- a/src/server/authserver/Realms/RealmList.cpp +++ b/src/server/authserver/Realms/RealmList.cpp @@ -31,12 +31,12 @@ void RealmList::Initialize(uint32 updateInterval) UpdateRealms(true); } -void RealmList::UpdateRealm(uint32 ID, const std::string& name, ACE_INET_Addr const& address, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build) +void RealmList::UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build) { // Create new if not exist or update existed Realm& realm = m_realms[name]; - realm.m_ID = ID; + realm.m_ID = id; realm.name = name; realm.icon = icon; realm.flag = flag; @@ -45,7 +45,9 @@ void RealmList::UpdateRealm(uint32 ID, const std::string& name, ACE_INET_Addr co realm.populationLevel = popu; // Append port to IP address. - address.addr_to_string(realm.address, ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16); + realm.ExternalAddress = address; + realm.LocalAddress = localAddr; + realm.LocalSubnetMask = localSubmask; realm.gamebuild = build; } @@ -77,23 +79,27 @@ void RealmList::UpdateRealms(bool init) do { Field* fields = result->Fetch(); - uint32 realmId = fields[0].GetUInt32(); - std::string name = fields[1].GetString(); - std::string address = fields[2].GetString(); - uint16 port = fields[3].GetUInt16(); - uint8 icon = fields[4].GetUInt8(); - RealmFlags flag = RealmFlags(fields[5].GetUInt8()); - uint8 timezone = fields[6].GetUInt8(); - uint8 allowedSecurityLevel = fields[7].GetUInt8(); - float pop = fields[8].GetFloat(); - uint32 build = fields[9].GetUInt32(); - - ACE_INET_Addr addr(port, address.c_str(), AF_INET); - - UpdateRealm(realmId, name, addr, icon, flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build); + uint32 realmId = fields[0].GetUInt32(); + std::string name = fields[1].GetString(); + std::string externalAddress = fields[2].GetString(); + std::string localAddress = fields[3].GetString(); + std::string localSubmask = fields[4].GetString(); + uint16 port = fields[5].GetUInt16(); + uint8 icon = fields[6].GetUInt8(); + RealmFlags flag = RealmFlags(fields[7].GetUInt8()); + uint8 timezone = fields[8].GetUInt8(); + uint8 allowedSecurityLevel = fields[9].GetUInt8(); + float pop = fields[10].GetFloat(); + uint32 build = fields[11].GetUInt32(); + + ACE_INET_Addr externalAddr(port, externalAddress.c_str(), AF_INET); + ACE_INET_Addr localAddr(port, localAddress.c_str(), AF_INET); + ACE_INET_Addr submask(0, localSubmask.c_str(), AF_INET); + + UpdateRealm(realmId, name, externalAddr, localAddr, submask, icon, flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build); if (init) - sLog->outInfo(LOG_FILTER_AUTHSERVER, "Added realm \"%s\" at %s.", name.c_str(), m_realms[name].address); + sLog->outInfo(LOG_FILTER_AUTHSERVER, "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.get_host_addr(), port); } while (result->NextRow()); } diff --git a/src/server/authserver/Realms/RealmList.h b/src/server/authserver/Realms/RealmList.h index 1949c34df9a..68e6524c334 100644 --- a/src/server/authserver/Realms/RealmList.h +++ b/src/server/authserver/Realms/RealmList.h @@ -40,7 +40,9 @@ enum RealmFlags // Storage object for a realm struct Realm { - char address[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16]; + ACE_INET_Addr ExternalAddress; + ACE_INET_Addr LocalAddress; + ACE_INET_Addr LocalSubnetMask; std::string name; uint8 icon; RealmFlags flag; @@ -72,7 +74,7 @@ public: private: void UpdateRealms(bool init=false); - void UpdateRealm(uint32 ID, const std::string& name, ACE_INET_Addr const& address, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build); + void UpdateRealm(uint32 id, const std::string& name, ACE_INET_Addr const& address, ACE_INET_Addr const& localAddr, ACE_INET_Addr const& localSubmask, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float popu, uint32 build); RealmMap m_realms; uint32 m_UpdateInterval; diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp index 8ab4ab8a1a2..b0bce520d4f 100644 --- a/src/server/authserver/Server/AuthSocket.cpp +++ b/src/server/authserver/Server/AuthSocket.cpp @@ -818,6 +818,28 @@ bool AuthSocket::_HandleReconnectProof() } } +ACE_INET_Addr const& AuthSocket::GetAddressForClient(Realm const& realm, ACE_INET_Addr const& clientAddr) +{ + // Attempt to send best address for client + if (clientAddr.is_loopback()) + { + // Try guessing if realm is also connected locally + if (realm.LocalAddress.is_loopback() || realm.ExternalAddress.is_loopback()) + return clientAddr; + + // Assume that user connecting from the machine that authserver is located on + // has all realms available in his local network + return realm.LocalAddress; + } + + // Check if connecting client is in the same network + if (IsIPAddrInNetwork(realm.LocalAddress, clientAddr, realm.LocalSubnetMask)) + return realm.LocalAddress; + + // Return external IP + return realm.ExternalAddress; +} + // Realm List command handler bool AuthSocket::_HandleRealmList() { @@ -845,6 +867,9 @@ bool AuthSocket::_HandleRealmList() // Update realm list if need sRealmList->UpdateIfNeed(); + ACE_INET_Addr clientAddr; + socket().peer().get_remote_addr(clientAddr); + // Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm) ByteBuffer pkt; @@ -876,6 +901,9 @@ bool AuthSocket::_HandleRealmList() name = ss.str(); } + // We don't need the port number from which client connects with but the realm's port + clientAddr.set_port_number(i->second.ExternalAddress.get_port_number()); + uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; uint8 AmountOfCharacters = 0; @@ -891,7 +919,7 @@ bool AuthSocket::_HandleRealmList() pkt << lock; // if 1, then realm locked pkt << uint8(flag); // RealmFlags pkt << name; - pkt << i->second.address; + pkt << GetAddressString(GetAddressForClient(i->second, clientAddr)); pkt << i->second.populationLevel; pkt << AmountOfCharacters; pkt << i->second.timezone; // realm category diff --git a/src/server/authserver/Server/AuthSocket.h b/src/server/authserver/Server/AuthSocket.h index 87fd092381e..6c13f85a022 100644 --- a/src/server/authserver/Server/AuthSocket.h +++ b/src/server/authserver/Server/AuthSocket.h @@ -23,6 +23,9 @@ #include "BigNumber.h" #include "RealmSocket.h" +class ACE_INET_Addr; +struct Realm; + // Handle login commands class AuthSocket: public RealmSocket::Session { @@ -36,6 +39,8 @@ public: virtual void OnAccept(void); virtual void OnClose(void); + static ACE_INET_Addr const& GetAddressForClient(Realm const& realm, ACE_INET_Addr const& clientAddr); + bool _HandleLogonChallenge(); bool _HandleLogonProof(); bool _HandleReconnectChallenge(); diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp index 70d509af6fe..3fc6649bd4d 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.cpp +++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp @@ -22,7 +22,7 @@ void LoginDatabaseConnection::DoPrepareStatements() if (!m_reconnecting) m_stmts.resize(MAX_LOGINDATABASE_STATEMENTS); - PrepareStatement(LOGIN_SEL_REALMLIST, "SELECT id, name, address, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE flag <> 3 ORDER BY name", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_REALMLIST, "SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE flag <> 3 ORDER BY name", CONNECTION_SYNCH); PrepareStatement(LOGIN_DEL_EXPIRED_IP_BANS, "DELETE FROM ip_banned WHERE unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS, "UPDATE account_banned SET active = 0 WHERE active = 1 AND unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_IP_BANNED, "SELECT * FROM ip_banned WHERE ip = ?", CONNECTION_SYNCH); diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp index 0d9314c48a3..1bba3c2db09 100644 --- a/src/server/shared/Utilities/Util.cpp +++ b/src/server/shared/Utilities/Util.cpp @@ -22,7 +22,6 @@ #include "SFMT.h" #include "Errors.h" // for ASSERT #include -#include typedef ACE_TSS SFMTRandTSS; static SFMTRandTSS sfmtRand; @@ -239,6 +238,21 @@ bool IsIPAddress(char const* ipaddress) return inet_addr(ipaddress) != INADDR_NONE; } +std::string GetAddressString(ACE_INET_Addr const& addr) +{ + char buf[ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16]; + addr.addr_to_string(buf, ACE_MAX_FULLY_QUALIFIED_NAME_LEN + 16); + return buf; +} + +bool IsIPAddrInNetwork(ACE_INET_Addr const& net, ACE_INET_Addr const& addr, ACE_INET_Addr const& subnetMask) +{ + uint32 mask = subnetMask.get_ip_address(); + if ((net.get_ip_address() & mask) == (addr.get_ip_address() & mask)) + return true; + return false; +} + /// create PID file uint32 CreatePIDFile(const std::string& filename) { diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h index e7218d7ba72..a379bfd32fc 100644 --- a/src/server/shared/Utilities/Util.h +++ b/src/server/shared/Utilities/Util.h @@ -25,6 +25,7 @@ #include #include #include +#include // Searcher for map of structs template struct Finder @@ -343,6 +344,13 @@ void utf8printf(FILE* out, const char *str, ...); void vutf8printf(FILE* out, const char *str, va_list* ap); bool IsIPAddress(char const* ipaddress); + +/// Checks if address belongs to the a network with specified submask +bool IsIPAddrInNetwork(ACE_INET_Addr const& net, ACE_INET_Addr const& addr, ACE_INET_Addr const& subnetMask); + +/// Transforms ACE_INET_Addr address into string format "dotted_ip:port" +std::string GetAddressString(ACE_INET_Addr const& addr); + uint32 CreatePIDFile(const std::string& filename); std::string ByteArrayToHexStr(uint8 const* bytes, uint32 length, bool reverse = false); -- cgit v1.2.3